./PaxHeaders/rsyslog-8.2608.00000644000000000000000000000013215241076640012624 xustar0030 mtime=1787067808.776993051 30 atime=1787067808.782993163 30 ctime=1787067808.776993051 rsyslog-8.2608.0/0000775000175000017500000000000015241076640012210 5ustar00rgerrgerrsyslog-8.2608.0/PaxHeaders/README0000644000000000000000000000013215053526213013421 xustar0030 mtime=1756277899.484426395 30 atime=1782715518.781788721 30 ctime=1787067790.720656589 rsyslog-8.2608.0/README0000666000175000017500000000007715053526213013073 0ustar00rgerrgersee README.md -- this file here is just required for autotools rsyslog-8.2608.0/PaxHeaders/m40000644000000000000000000000013215241076616013012 xustar0030 mtime=1787067790.692656067 30 atime=1787067808.782993163 30 ctime=1787067790.692656067 rsyslog-8.2608.0/m4/0000775000175000017500000000000015241076616012533 5ustar00rgerrgerrsyslog-8.2608.0/m4/PaxHeaders/lt~obsolete.m40000644000000000000000000000013115241076154015677 xustar0030 mtime=1787067500.547246568 29 atime=1787067500.56824696 30 ctime=1787067790.692656067 rsyslog-8.2608.0/m4/lt~obsolete.m40000644000175000017500000001400715241076154015344 0ustar00rgerrger# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 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])]) rsyslog-8.2608.0/m4/PaxHeaders/ltsugar.m40000644000000000000000000000013215241076154015007 xustar0030 mtime=1787067500.485245412 30 atime=1787067500.503245747 30 ctime=1787067790.688655993 rsyslog-8.2608.0/m4/ltsugar.m40000644000175000017500000001045315241076154014454 0ustar00rgerrger# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 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 ]) rsyslog-8.2608.0/m4/PaxHeaders/atomic_operations_64bit.m40000644000000000000000000000013115241075234020052 xustar0029 mtime=1787067036.58557792 30 atime=1787067036.730580635 30 ctime=1787067790.678655806 rsyslog-8.2608.0/m4/atomic_operations_64bit.m40000664000175000017500000000324315241075234017521 0ustar00rgerrger# rsyslog # # atomic_operations.m4 - autoconf macro to check if compiler supports atomic # operations # # rgerhards, 2008-09-18, added based on # http://svn.apache.org/repos/asf/apr/apr/trunk/configure.in # # AC_DEFUN([RS_ATOMIC_OPERATIONS_64BIT], [AC_CACHE_CHECK([whether the compiler provides atomic builtins for 64 bit data types], [ap_cv_atomic_builtins_64], [AC_TRY_RUN([ int main() { unsigned long long val = 1010, tmp, *mem = &val; void *ptr = &val, *expected_ptr, *new_ptr; if (__atomic_fetch_add(&val, 1010, __ATOMIC_SEQ_CST) != 1010 || val != 2020) return 1; tmp = val; if (__atomic_fetch_sub(mem, 1010, __ATOMIC_SEQ_CST) != tmp || val != 1010) return 1; if (__atomic_sub_fetch(&val, 1010, __ATOMIC_SEQ_CST) != 0 || val != 0) return 1; tmp = 3030; { unsigned long long expected = 0; if (!__atomic_compare_exchange_n(mem, &expected, tmp, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) || val != tmp) return 1; } __atomic_store_n(&val, 4040, __ATOMIC_RELEASE); if (__atomic_load_n(&val, __ATOMIC_ACQUIRE) != 4040) return 1; expected_ptr = &val; new_ptr = &tmp; if (!__atomic_compare_exchange_n(&ptr, &expected_ptr, new_ptr, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return 1; __atomic_thread_fence(__ATOMIC_SEQ_CST); if (ptr != &tmp) return 1; return 0; }], [ap_cv_atomic_builtins_64=yes], [ap_cv_atomic_builtins_64=no], [ap_cv_atomic_builtins_64=no])]) if test "$ap_cv_atomic_builtins_64" = "yes"; then AC_DEFINE(HAVE_ATOMIC_BUILTINS64, 1, [Define if compiler provides 64 bit atomic builtins]) fi ]) rsyslog-8.2608.0/m4/PaxHeaders/ac_check_define.m40000644000000000000000000000013215035412264016355 xustar0030 mtime=1752569012.356063431 30 atime=1787067430.965948303 30 ctime=1787067790.674655732 rsyslog-8.2608.0/m4/ac_check_define.m40000666000175000017500000000215515035412264016026 0ustar00rgerrgerAC_DEFUN([AC_CHECK_DEFINED],[ AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$1])dnl AC_CACHE_CHECK([for $1 defined], ac_var, AC_TRY_COMPILE(,[ #ifdef $1 int ok; #else choke me #endif ],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no))) AS_IF([test AS_VAR_GET(ac_var) != "no"], [$2], [$3])dnl AS_VAR_POPDEF([ac_var])dnl ]) AC_DEFUN([AX_CHECK_DEFINED],[ AS_VAR_PUSHDEF([ac_var],[ac_cv_defined_$2])dnl AC_CACHE_CHECK([for $2 defined], ac_var, AC_TRY_COMPILE($1,[ #ifdef $2 int ok; #else choke me #endif ],AS_VAR_SET(ac_var, yes),AS_VAR_SET(ac_var, no))) AS_IF([test AS_VAR_GET(ac_var) != "no"], [$3], [$4])dnl AS_VAR_POPDEF([ac_var])dnl ]) AC_DEFUN([AX_CHECK_FUNC], [AS_VAR_PUSHDEF([ac_var], [ac_cv_func_$2])dnl AC_CACHE_CHECK([for $2], ac_var, dnl AC_LANG_FUNC_LINK_TRY [AC_LINK_IFELSE([AC_LANG_PROGRAM([$1 #undef $2 char $2 ();],[ char (*f) () = $2; return f != $2; ])], [AS_VAR_SET(ac_var, yes)], [AS_VAR_SET(ac_var, no)])]) AS_IF([test AS_VAR_GET(ac_var) = yes], [$3], [$4])dnl AS_VAR_POPDEF([ac_var])dnl ])# AC_CHECK_FUNC rsyslog-8.2608.0/m4/PaxHeaders/atomic_operations.m40000644000000000000000000000013115241075234017042 xustar0029 mtime=1787067036.58557792 30 atime=1787067036.729580616 30 ctime=1787067790.676655769 rsyslog-8.2608.0/m4/atomic_operations.m40000664000175000017500000000457615241075234016523 0ustar00rgerrger# rsyslog # # atomic_operations.m4 - autoconf macro to check if compiler supports atomic # operations # # rgerhards, 2008-09-18, added based on # http://svn.apache.org/repos/asf/apr/apr/trunk/configure.in # # AC_DEFUN([RS_ATOMIC_OPERATIONS], [AC_CACHE_CHECK([whether the compiler provides atomic builtins], [ap_cv_atomic_builtins], [AC_TRY_RUN([ #include #include int main() { unsigned long val = 1010, tmp, *mem = &val; time_t tval = 1010, ttmp, *tmem = &tval; void *ptr = &val, *expected_ptr, *new_ptr; if (__atomic_fetch_add(&val, 1010, __ATOMIC_SEQ_CST) != 1010 || val != 2020) return 1; tmp = val; if (__atomic_fetch_sub(mem, 1010, __ATOMIC_SEQ_CST) != tmp || val != 1010) return 1; if (__atomic_sub_fetch(&val, 1010, __ATOMIC_SEQ_CST) != 0 || val != 0) return 1; tmp = 3030; { unsigned long expected = 0; if (!__atomic_compare_exchange_n(mem, &expected, tmp, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) || val != tmp) return 1; } __atomic_store_n(&val, 4040, __ATOMIC_RELEASE); if (__atomic_load_n(&val, __ATOMIC_ACQUIRE) != 4040) return 1; expected_ptr = &val; new_ptr = &tmp; if (!__atomic_compare_exchange_n(&ptr, &expected_ptr, new_ptr, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) return 1; if (__atomic_fetch_add(&tval, 1010, __ATOMIC_SEQ_CST) != 1010 || tval != 2020) return 1; ttmp = tval; if (__atomic_fetch_sub(tmem, 1010, __ATOMIC_SEQ_CST) != ttmp || tval != 1010) return 1; if (__atomic_sub_fetch(&tval, 1010, __ATOMIC_SEQ_CST) != 0 || tval != 0) return 1; ttmp = 3030; { time_t expected = 0; if (!__atomic_compare_exchange_n(tmem, &expected, ttmp, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) || tval != ttmp) return 1; } __atomic_store_n(&tval, 4040, __ATOMIC_RELEASE); if (__atomic_load_n(&tval, __ATOMIC_ACQUIRE) != 4040) return 1; __atomic_thread_fence(__ATOMIC_SEQ_CST); if (ptr != &tmp) return 1; if (tmem != &tval) return 1; return 0; }], [ap_cv_atomic_builtins=yes], [ap_cv_atomic_builtins=no], [ap_cv_atomic_builtins=no])]) if test "$ap_cv_atomic_builtins" = "yes"; then AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1, [Define if compiler provides atomic builtins]) fi ]) rsyslog-8.2608.0/m4/PaxHeaders/libtool.m40000644000000000000000000000013115241076154014771 xustar0029 mtime=1787067500.39724377 30 atime=1787067500.425244292 30 ctime=1787067790.683655899 rsyslog-8.2608.0/m4/libtool.m40000644000175000017500000113165215241076154014445 0ustar00rgerrger# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2019, 2021-2022 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) 2014 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 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 this program. If not, see . ]) # serial 59 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.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK 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_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _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_DECL_FILECMD])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 m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that 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 set != "${COLLECT_NAMES+set}"; 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 and # ICC, which need '.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\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) 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\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) 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 0 = "$lt_write_fail" && 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 yes = "$silent" && 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 that 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 # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _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 set != "${COLLECT_NAMES+set}"; 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) 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' 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 0 = "$_lt_result"; 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 $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR $AR_FLAGS 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 0 = "$_lt_result" && $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*) case $MACOSX_DEPLOYMENT_TARGET,$host in 10.[[012]],*|,*powerpc*-darwin[[5-8]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; *) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; 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 no = "$lt_cv_ld_force_load"; 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 yes = "$lt_cv_ld_force_load"; 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*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; 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 yes != "$lt_cv_apple_cc_single_mod"; 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 set = "${lt_cv_aix_libpath+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 that will find a shell with a builtin # printf (that 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], [m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--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 yes = "$GCC"; 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 where 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 no = "$enable_libtool_lock" || 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 what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `$FILECMD 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* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; 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" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; 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 yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-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} _LT_DECL([], [AR], [1], [The archiver]) # Use ARFLAGS variable as AR's operation code to sync the variable naming with # Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have # higher priority because thats what people were doing historically (setting # ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS # variable obsoleted/removed. test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} lt_ar_flags=$AR_FLAGS _LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)]) # Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override # by AR_FLAGS because that was never working and AR_FLAGS is about to die. _LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}], [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 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; 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 bitrig* | 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" ## exclude from sc_useless_quotes_in_assignment # 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 yes = "[$]$2"; 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 yes = "[$]$2"; 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; ;; bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # 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" && \ test undefined != "$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 17 != "$i" # 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 yes = "$cross_compiling"; 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 -fvisibility=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 yes != "$enable_dlopen"; 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 ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) 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 no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && 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 yes = "$lt_cv_dlopen_self"; 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 no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; 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 no = "$hard_links"; 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 where 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 yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # 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 no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; 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 relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; 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 -z "$STRIP"; then AC_MSG_RESULT([no]) else if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else case $host_os in darwin*) # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) ;; freebsd*) if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then old_striplib="$STRIP --strip-debug" striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _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 m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; 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` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac 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" elif test -n "$lt_multi_os_dir"; then 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 AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) 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 ia64 = "$host_cpu"; 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 # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # 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' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # 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' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac 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%'\''`; $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* | *,icl*) # Native MSVC or ICC 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 and ICC 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* | midnightbsd*) # 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$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' 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 ;; 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=no 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 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; 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 yes = "$lt_cv_prog_gnu_ld"; 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 ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # 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 dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | 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 # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) 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="/lib /usr/lib $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' ;; netbsdelf*-gnu) version_type=linux 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='NetBSD ld.elf_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* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi 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 shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec 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' ;; 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 yes = "$with_gnu_ld"; 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=sco 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 yes = "$with_gnu_ld"; 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 no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _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], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that 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 that 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 no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; 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 yes = "$with_gnu_ld"; 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 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [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 # that 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='$FILECMD -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. if ( 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* | midnightbsd*) 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=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=$FILECMD 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 | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) 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=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; 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 ;; os2*) 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 # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) 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 no != "$lt_cv_path_NM"; 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 -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) 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 one 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 yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # 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 yes = "$GCC"; 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 ia64 = "$host_cpu"; 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 if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # 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"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$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"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/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, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++ or ICC, # 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};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,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 $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && 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 can'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* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$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 yes = "$pipe_works"; 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_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _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_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _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 yes = "$GXX"; 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 ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; 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']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; 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 ia64 = "$host_cpu"; 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* | midnightbsd*) # 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 ia64 != "$host_cpu"; 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 | 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* | netbsdelf*-gnu) ;; *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 yes = "$GCC"; 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 ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; 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']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; 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 ia64 = "$host_cpu"; 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 ;; 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' case $cc_basename in 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' ;; esac ;; 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']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; 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 | 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' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _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' ;; tcc*) # Fabrice Bellard et al's Tiny 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)='-static' ;; 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 that 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 GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. 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) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl* | icl*) _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 ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _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++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=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 yes = "$with_gnu_ld"; 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 yes = "$lt_use_gnu_ld_interface"; 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 | $SED -e 's/([[^)]]\+)\s\+//' 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 ia64 != "$host_cpu"; 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, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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 ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; 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 linux-dietlibc = "$host_os"; 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 no = "$tmp_diet" 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' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-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 yes = "$supports_anon_versioning"; 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 tcc*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; 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 yes = "$supports_anon_versioning"; 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* | netbsdelf*-gnu) 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 cannot *** 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 no = "$_LT_TAGVAR(ld_shlibs, $1)"; 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 yes = "$GCC" && 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 ia64 = "$host_cpu"; 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 GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. 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) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | 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 # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; 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,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; 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 yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' 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,yes = "$with_aix_soname,$aix_use_runtimelinking"; 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 -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; 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 yes = "$with_gnu_ld"; 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 _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' 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++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl* | icl*) # Native MSVC or ICC _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,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $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 and ICC 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* | midnightbsd*) _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 yes = "$GCC"; 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 "x$output_objdir/$soname" = "x$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 "x$output_objdir/$soname" = "x$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 yes,no = "$GCC,$with_gnu_ld"; 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 no = "$with_gnu_ld"; 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 yes,no = "$GCC,$with_gnu_ld"; 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 no = "$with_gnu_ld"; 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 yes = "$GCC"; 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 yes = "$lt_cv_irix_exported_symbol"; 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 _LT_TAGVAR(link_all_deplibs, $1)=no 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 ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; esac ;; netbsd* | netbsdelf*-gnu) 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* | bitrig*) 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__`"; 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 _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' 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 shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' ;; osf3*) if test yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 yes = "$GCC"; 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 sequent = "$host_vendor"; 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 yes = "$GCC"; 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 CANNOT 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 yes = "$GCC"; 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 sni = "$host_vendor"; 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 no = "$_LT_TAGVAR(ld_shlibs, $1)" && 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 yes,yes = "$GCC,$enable_shared"; 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 what 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || 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 no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); 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 yes != "$_lt_caught_CXX_error"; 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 yes = "$GXX"; 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 yes = "$GXX"; 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 yes = "$with_gnu_ld"; 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 ia64 = "$host_cpu"; 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 # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive 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 if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; 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,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; 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 yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; 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 yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' 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,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # 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 -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; 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 yes = "$with_gnu_ld"; 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 _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' 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* | ,icl* | no,icl*) # Native MSVC or ICC # 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,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $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, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); 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) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(file_list_spec, $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* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; 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 "x$output_objdir/$soname" = "x$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 yes = "$GXX"; 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 "x$output_objdir/$soname" = "x$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 no = "$with_gnu_ld"; 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 yes = "$GXX"; then if test no = "$with_gnu_ld"; 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 yes = "$GXX"; then if test no = "$with_gnu_ld"; 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 | 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 yes = "$supports_anon_versioning"; 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 ;; openbsd* | bitrig*) 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__`"; 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 yes,no = "$GXX,$with_gnu_ld"; 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 yes,no = "$GXX,$with_gnu_ld"; 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 $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 $wl-h $wl$soname -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 $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 $wl-h $wl$soname -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 CANNOT 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 no = "$_LT_TAGVAR(ld_shlibs, $1)" && 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 yes != "$_lt_caught_CXX_error" 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 @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@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 x-L = "$p" || test x-R = "$p"; 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 no = "$pre_test_object_deps_done"; 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 no = "$pre_test_object_deps_done"; 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)= ;; 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 no = "$F77"; 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 yes != "$_lt_disable_F77"; 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || 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 yes != "$_lt_disable_F77" 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 no = "$FC"; 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 yes != "$_lt_disable_FC"; 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 no = "$can_build_shared" && 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 yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac 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 yes = "$enable_shared" || 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 yes != "$_lt_disable_FC" 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 set = "${GCJFLAGS+set}" || 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_FILECMD # ---------------- # Check for a file(cmd) program that can be used to detect file type and magic m4_defun([_LT_DECL_FILECMD], [AC_CHECK_TOOL([FILECMD], [file], [:]) _LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types]) ])# _LD_DECL_FILECMD # _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 10 -lt "$lt_ac_count" && 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], [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_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what 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 rsyslog-8.2608.0/m4/PaxHeaders/ltversion.m40000644000000000000000000000013115241076154015352 xustar0030 mtime=1787067500.514245953 30 atime=1787067500.535246344 29 ctime=1787067790.69065603 rsyslog-8.2608.0/m4/ltversion.m40000644000175000017500000000131215241076154015012 0ustar00rgerrger# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2019, 2021-2022 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 4245 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.7]) m4_define([LT_PACKAGE_REVISION], [2.4.7]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.7' macro_revision='2.4.7' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) rsyslog-8.2608.0/m4/PaxHeaders/ltoptions.m40000644000000000000000000000013215241076154015361 xustar0030 mtime=1787067500.450244759 30 atime=1787067500.470245132 30 ctime=1787067790.685655937 rsyslog-8.2608.0/m4/ltoptions.m40000644000175000017500000003427515241076154015036 0ustar00rgerrger# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 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 8 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_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _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_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _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=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])]) rsyslog-8.2608.0/PaxHeaders/test-driver0000644000000000000000000000013215241076163014737 xustar0030 mtime=1787067507.846382732 30 atime=1787067507.846382732 30 ctime=1787067803.538895444 rsyslog-8.2608.0/test-driver0000755000175000017500000001141715241076163014410 0ustar00rgerrger#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2018-03-07.03; # UTC # Copyright (C) 2011-2021 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. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <"$log_file" "$@" >>"$log_file" 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>"$log_file" # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: rsyslog-8.2608.0/PaxHeaders/platform0000644000000000000000000000013215241076616014316 xustar0030 mtime=1787067790.743657018 30 atime=1787067808.782993163 30 ctime=1787067790.743657018 rsyslog-8.2608.0/platform/0000775000175000017500000000000015241076616014037 5ustar00rgerrgerrsyslog-8.2608.0/platform/PaxHeaders/README0000644000000000000000000000013215131231047015240 xustar0030 mtime=1768239655.668211993 30 atime=1782715518.784788772 30 ctime=1787067790.744657036 rsyslog-8.2608.0/platform/README0000666000175000017500000000064015131231047014706 0ustar00rgerrgerThis subdirectory contains platform-specific files. They are maintained based on a best effort basis, and are not necessarily the same like the specific platform ships them. Some files are changed in the way the rsyslog projects would recommend them; some may even be outdated. Use this with care. If in doubt, please have a look at the official distro repos. They obviously have the gold standard for each distro. rsyslog-8.2608.0/platform/PaxHeaders/freebsd0000644000000000000000000000013215241076616015730 xustar0030 mtime=1787067790.746657073 30 atime=1787067808.782993163 30 ctime=1787067790.746657073 rsyslog-8.2608.0/platform/freebsd/0000775000175000017500000000000015241076616015451 5ustar00rgerrgerrsyslog-8.2608.0/platform/freebsd/PaxHeaders/rsyslogd0000644000000000000000000000013115216464436017600 xustar0029 mtime=1782212894.00126578 30 atime=1782212894.220269321 30 ctime=1787067790.747657092 rsyslog-8.2608.0/platform/freebsd/rsyslogd0000775000175000017500000000406315216464436017253 0ustar00rgerrger#!/bin/sh # Sample startup script for rsyslogd on FreeBSD. # It worked on my machine, but this does not necessarily # mean it works on all machines - it's not thouroughly # tested. Please note that it may also work on other # BSD variants, too. # # As of this writing, there was an issue with the mysql client # library on startup. If compiled with MySQL support, rsyslogd # would not necessarily start correctly but could eventually # die with a "mysql client libary not found" (or similar) # message. I do not know its cause neither the cure. If you # have one, let me know. # # ATTENTION: you need also to change the /etc/rc.config file # and disable stock syslogd and then enable rsyslogd! # # rgerhards 2005-08-09 # # PROVIDE: rsyslogd # REQUIRE: mountcritremote cleanvar # BEFORE: SERVERS . /etc/rc.subr name="rsyslogd" rcvar=$(set_rcvar) pidfile="/var/run/rsyslogd.pid" command="/usr/sbin/${name}" required_files="/etc/rsyslog.conf" start_precmd="rsyslogd_precmd" extra_commands="reload" _sockfile="/var/run/rsyslogd.sockets" evalargs="rc_flags=\"\`set_socketlist\` \$rc_flags\"" altlog_proglist="named" rsyslogd_precmd() { # Transitional symlink for old binaries # if [ ! -L /dev/log ]; then ln -sf /var/run/log /dev/log fi rm -f /var/run/log # Create default list of syslog sockets to watch # ( umask 022 ; > $_sockfile ) # If running named(8) or ntpd(8) chrooted, added appropriate # syslog socket to list of sockets to watch. # for _l in $altlog_proglist; do eval _ldir=\$${_l}_chrootdir if checkyesno "$(set_rcvar $_l)" && [ -n "$_ldir" ]; then echo "${_ldir}/var/run/log" >> $_sockfile fi done # If other sockets have been provided, change run_rc_command()'s # internal copy of $rsyslogd_flags to force use of specific # rsyslogd sockets. # if [ -s $_sockfile ]; then echo "/var/run/log" >> $_sockfile eval $evalargs fi return 0 } set_socketlist() { _socketargs= for _s in $(cat $_sockfile | tr '\n' ' ') ; do _socketargs="-l $_s $_socketargs" done echo $_socketargs } load_rc_config $name run_rc_command "$1" rsyslog-8.2608.0/platform/PaxHeaders/slackware0000644000000000000000000000013215241076616016272 xustar0030 mtime=1787067790.749657129 30 atime=1787067808.783993182 30 ctime=1787067790.749657129 rsyslog-8.2608.0/platform/slackware/0000775000175000017500000000000015241076616016013 5ustar00rgerrgerrsyslog-8.2608.0/platform/slackware/PaxHeaders/rc.rsyslogd0000644000000000000000000000013215035412264020535 xustar0030 mtime=1752569012.365000895 30 atime=1782715518.783788755 30 ctime=1787067790.749657129 rsyslog-8.2608.0/platform/slackware/rc.rsyslogd0000777000175000017500000000305215035412264020206 0ustar00rgerrger#!/bin/sh # Start/stop/restart the system logging daemons. # # Written for Slackware Linux by Patrick J. Volkerding . # Modded for rsyslogd by Chris Elvidge Sept 2005 # create_xconsole() { if [ ! -e /dev/xconsole ]; then mknod -m 640 /dev/xconsole p else chmod 0640 /dev/xconsole fi chown 0:0 /dev/xconsole } rsyslogd_start() { if [ -x /usr/sbin/rsyslogd -a -x /usr/sbin/klogd ]; then echo "Starting rsyslogd / klogd daemons: " # this one listens on the "usual" socket /dev/log echo "/usr/sbin/rsyslogd -i $pidfile1" /usr/sbin/rsyslogd -i "$pidfile1" # this one listens only to the UDP port sleep 1 echo "/usr/sbin/rsyslogd -o -r0 -f $confile2 -i $pidfile2" /usr/sbin/rsyslogd -o -r0 -f "$confile2" -i "$pidfile2" sleep 1 # prevent syslogd/klogd race condition on SMP kernels echo "/usr/sbin/klogd -c 3 -x" # '-c 3' = display level 'error' or higher messages on console # '-x' = turn off broken EIP translation /usr/sbin/klogd -c 3 -x fi } rsyslogd_stop() { killall rsyslogd 2> /dev/null killall klogd 2> /dev/null /usr/bin/rm pidfile1 2> /dev/null /usr/bin/rm pidfile2 2> /dev/null } rsyslogd_restart() { rsyslogd_stop sleep 1 rsyslogd_start } confile1=/etc/rsyslog.conf pidfile1=/var/run/rsyslogd.pid confile2=/etc/rsyslog.udp.conf pidfile2=/var/run/rsyslogd.udp.pid case "$1" in 'start') create_xconsole rsyslogd_start ;; 'stop') rsyslogd_stop ;; 'restart') rsyslogd_restart ;; *) echo "usage $0 start|stop|restart" esac rsyslog-8.2608.0/platform/PaxHeaders/redhat0000644000000000000000000000013215241076616015565 xustar0030 mtime=1787067790.751657167 30 atime=1787067808.783993182 30 ctime=1787067790.751657167 rsyslog-8.2608.0/platform/redhat/0000775000175000017500000000000015241076616015306 5ustar00rgerrgerrsyslog-8.2608.0/platform/redhat/PaxHeaders/rsyslog.conf0000644000000000000000000000013215035412264020205 xustar0030 mtime=1752569012.365000895 30 atime=1782213078.278287093 30 ctime=1787067790.752657185 rsyslog-8.2608.0/platform/redhat/rsyslog.conf0000666000175000017500000000657115035412264017664 0ustar00rgerrger# rsyslog configuration file (for Red Hat-based systems) # note that most of this config file uses old-style format, # because it is well-known AND quite suitable for simple cases # like we have with the default config. For more advanced # things, RainerScript configuration is suggested. # # For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html # or latest version online at https://www.rsyslog.com/doc/rsyslog_conf.html # If you experience problems, see https://www.rsyslog.com/doc/troubleshoot.html #### MODULES #### module(load="imuxsock") # provides support for local system logging (e.g. via logger command) module(load="imklog") # provides kernel logging support (previously done by rklogd) #module(load"immark") # provides --MARK-- message capability # Provides UDP syslog reception # for parameters see https://www.rsyslog.com/doc/imudp.html #module(load="imudp") # needs to be done just once #input(type="imudp" port="514") # Provides TCP syslog reception # for parameters see https://www.rsyslog.com/doc/imtcp.html #module(load="imtcp") # needs to be done just once #input(type="imtcp" port="514") #### GLOBAL DIRECTIVES #### # Use default timestamp format $ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat # File syncing capability is disabled by default. This feature is usually not required, # not useful and an extreme performance hit #$ActionFileEnableSync on # Include all config files in /etc/rsyslog.d/ $IncludeConfig /etc/rsyslog.d/*.conf #### RULES #### # Log all kernel messages to the console. # Logging much else clutters up the screen. #kern.* /dev/console # Log anything (except mail) of level info or higher. # Don't log private authentication messages! *.info;mail.none;authpriv.none;cron.none /var/log/messages # The authpriv file has restricted access. authpriv.* /var/log/secure # Log all the mail messages in one place. mail.* /var/log/maillog # Log cron stuff cron.* /var/log/cron # Everybody gets emergency messages *.emerg :omusrmsg:* # Save news errors of level crit and higher in a special file. uucp,news.crit /var/log/spooler # Save boot messages also to boot.log local7.* /var/log/boot.log # ### begin forwarding rule ### # The statement between the begin ... end define a SINGLE forwarding # rule. They belong together, do NOT split them. If you create multiple # forwarding rules, duplicate the whole block! # Remote Logging (we use TCP for reliable delivery) # # An on-disk queue is created for this action. If the remote host is # down, messages are spooled to disk and sent when it is up again. #$WorkDirectory /var/lib/rsyslog # where to place spool files #$ActionQueueFileName fwdRule1 # unique name prefix for spool files #$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible) #$ActionQueueSaveOnShutdown on # save messages to disk on shutdown #$ActionQueueType LinkedList # run asynchronously #$ActionResumeRetryCount -1 # infinite retries if host is down # remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional #*.* @@remote-host:514 # ### end of the forwarding rule ### rsyslog-8.2608.0/PaxHeaders/COPYING.ASL200000644000000000000000000000013115035412264014353 xustar0029 mtime=1752569012.32130663 30 atime=1782715518.781788721 30 ctime=1787067790.760657334 rsyslog-8.2608.0/COPYING.ASL200000666000175000017500000002166115035412264014030 0ustar00rgerrgerApache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 1. You must give any other recipients of the Work or Derivative Works a copy of this License; and 2. You must cause any modified files to carry prominent notices stating that You changed the files; and 3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. rsyslog-8.2608.0/PaxHeaders/missing0000644000000000000000000000013215241076160014135 xustar0030 mtime=1787067504.277316152 30 atime=1787067527.425747961 30 ctime=1787067790.736656887 rsyslog-8.2608.0/missing0000755000175000017500000001533615241076160013612 0ustar00rgerrger#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2018-03-07.03; # UTC # Copyright (C) 1996-2021 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=https://www.perl.org/ flex_URL=https://github.com/westes/flex gnu_software_URL=https://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 'autom4te' 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 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: rsyslog-8.2608.0/PaxHeaders/devtools0000644000000000000000000000013215241076640014326 xustar0030 mtime=1787067808.465987256 30 atime=1787067808.783993182 30 ctime=1787067808.465987256 rsyslog-8.2608.0/devtools/0000775000175000017500000000000015241076640014047 5ustar00rgerrgerrsyslog-8.2608.0/devtools/PaxHeaders/release0000644000000000000000000000013215241076616015751 xustar0030 mtime=1787067790.780657707 30 atime=1787067808.783993182 30 ctime=1787067790.780657707 rsyslog-8.2608.0/devtools/release/0000775000175000017500000000000015241076616015472 5ustar00rgerrgerrsyslog-8.2608.0/devtools/release/PaxHeaders/validate-rpm-baseline-patches.py0000644000000000000000000000013215241075234024165 xustar0030 mtime=1787067036.574577714 30 atime=1787067036.676579624 30 ctime=1787067790.780657707 rsyslog-8.2608.0/devtools/release/validate-rpm-baseline-patches.py0000664000175000017500000001263515241075234023640 0ustar00rgerrger#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 # Copyright 2026 Rainer Gerhards and Others # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Verify and remove reviewed downstream RPM baseline patches. Daily-stable packages replace a distribution's source archive with current upstream. Every downstream patch must therefore be explicitly reviewed, content-pinned, and removed before the RPM spec is reused. """ import hashlib import json import pathlib import re import sys def fail(message): raise SystemExit(message) def main(): if len(sys.argv) != 4: fail("usage: validate-rpm-baseline-patches.py ") spec_path = pathlib.Path(sys.argv[1]) policy_path = pathlib.Path(sys.argv[2]) distro = sys.argv[3] spec = spec_path.read_text(encoding="utf-8") policy = json.loads(policy_path.read_text(encoding="utf-8")) if "allowed_patch_skips" in policy: fail(f"{distro} policy must use integrated_baseline_patches") reviewed = policy.get("integrated_baseline_patches", []) if not isinstance(reviewed, list): fail("integrated_baseline_patches must be a list") reviewed_hashes = {} for entry in reviewed: if not isinstance(entry, dict): fail("integrated baseline patch entry must be an object") name = entry.get("name", "").strip() digest = entry.get("sha256", "").lower() reason = entry.get("reason", "").strip() if not name or not re.fullmatch(r"[A-Za-z0-9._+-]+", name): fail("integrated baseline patch has an invalid name") if not re.fullmatch(r"[0-9a-f]{64}", digest): fail(f"integrated baseline patch {name} has an invalid SHA-256") if not reason: fail(f"integrated baseline patch {name} has no reason") if name in reviewed_hashes: fail(f"integrated baseline patch {name} is listed more than once") reviewed_hashes[name] = digest declarations = re.findall(r"(?m)^Patch(\d*):\s*(\S+)\s*$", spec) numbers = [number for number, _ in declarations] names = [name for _, name in declarations] normalized_numbers = [int(number or "0") for number in numbers] duplicate_numbers = sorted( str(number) for number in set(normalized_numbers) if normalized_numbers.count(number) > 1 ) duplicate_names = sorted(name for name in set(names) if names.count(name) > 1) if duplicate_numbers or duplicate_names: details = [] if duplicate_numbers: details.append("numbers: " + ", ".join(duplicate_numbers)) if duplicate_names: details.append("names: " + ", ".join(duplicate_names)) fail(f"duplicate {distro} baseline patch declaration (" + "; ".join(details) + ")") baseline_names = set(names) unreviewed = sorted(baseline_names - set(reviewed_hashes)) missing = sorted(set(reviewed_hashes) - baseline_names) if unreviewed: fail( f"{distro} baseline gained unreviewed patches; review them before packaging main: " + ", ".join(unreviewed) ) if missing: fail( f"reviewed baseline patches are absent from {distro} baseline: " + ", ".join(missing) ) sources_dir = spec_path.parent.parent / "SOURCES" patch_paths = [] for number, name in declarations: patch_path = sources_dir / name if not patch_path.is_file(): fail(f"reviewed baseline patch is missing: {name}") digest = hashlib.sha256(patch_path.read_bytes()).hexdigest() if digest != reviewed_hashes[name]: fail(f"reviewed baseline patch changed: {name}") patch_paths.append(patch_path) spec, declaration_count = re.subn( rf"(?m)^Patch{re.escape(number)}:\s*{re.escape(name)}\s*\n", "", spec ) if number: application_pattern = ( rf"(?m)^%patch(?:{re.escape(number)}(?=\s|$)|" rf"\s+-P\s*{re.escape(number)}|\s+-P{re.escape(number)}|" rf"\s+{re.escape(number)})(?:\s+[^\n]*)?\s*\n" ) else: application_pattern = ( r"(?m)^%patch(?:0(?=\s|$)|\s+-P\s*0(?=\s|$)|" r"\s+-P0(?=\s|$)|\s+0(?=\s|$)|" r"(?!\s+(?:-P\s*[1-9]\d*|-P[1-9]\d*|[1-9]\d*)(?:\s|$)))" r"(?:\s+[^\n]*)?\s*\n" ) spec, application_count = re.subn(application_pattern, "", spec) if declaration_count != 1: fail(f"could not remove exactly one declaration for {name}") if application_count == 0 and not re.search(r"(?m)^%autosetup(?:\s|$)", spec): fail(f"could not find an application for {name}") if application_count > 1: fail(f"could not remove exactly one application for {name}") spec_path.write_text(spec, encoding="utf-8") for patch_path in patch_paths: patch_path.unlink() if __name__ == "__main__": main() rsyslog-8.2608.0/devtools/PaxHeaders/prep-mysql-db.sh0000644000000000000000000000013215035412264017430 xustar0030 mtime=1752569012.332230196 30 atime=1782715518.894790642 30 ctime=1787067808.463987219 rsyslog-8.2608.0/devtools/prep-mysql-db.sh0000777000175000017500000000040115035412264017074 0ustar00rgerrger#!/bin/bash # this script prepares a mysql instance for use by the rsyslog testbench mysql -u root -e "CREATE USER 'rsyslog'@'localhost' IDENTIFIED BY 'testbench';" mysql -u root -e "GRANT ALL PRIVILEGES ON *.* TO 'rsyslog'@'localhost'; FLUSH PRIVILEGES;" rsyslog-8.2608.0/devtools/PaxHeaders/prepare_clickhouse.sh0000644000000000000000000000013215035412264020603 xustar0030 mtime=1752569012.332230196 30 atime=1782715518.893790625 30 ctime=1787067808.466987275 rsyslog-8.2608.0/devtools/prepare_clickhouse.sh0000777000175000017500000000120615035412264020253 0ustar00rgerrger#!/bin/bash # this script prepares a clickhouse instance for use by the rsyslog testbench clickhouse-client --query="CREATE DATABASE rsyslog" echo clickouse create database RETURN STATE: $? # At the moment only the database is created for preperation. # Every test creates a table for itself and drops it afterwards. # This could look something like this: #clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.test ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id" #clickhouse-client --query="DROP TABLE rsyslog.test" rsyslog-8.2608.0/PaxHeaders/COPYING.LESSER0000644000000000000000000000013115035412264014567 xustar0029 mtime=1752569012.32130663 30 atime=1782715518.781788721 30 ctime=1787067790.709656384 rsyslog-8.2608.0/COPYING.LESSER0000666000175000017500000001672715035412264014253 0ustar00rgerrger GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. rsyslog-8.2608.0/PaxHeaders/Makefile.am0000644000000000000000000000013115241075234014575 xustar0030 mtime=1787067036.568577601 30 atime=1787067036.712580298 29 ctime=1787067790.66865562 rsyslog-8.2608.0/Makefile.am0000664000175000017500000003203015241075234014240 0ustar00rgerrgersbin_PROGRAMS = pkglib_LTLIBRARIES = pkgconfigdir = $(libdir)/pkgconfig EXTRA_DIST = \ README.md \ platform/README \ platform/freebsd/rsyslogd \ platform/slackware/rc.rsyslogd \ platform/redhat/rsyslog.conf \ contrib/README \ CONTRIBUTING.md \ COPYING \ COPYING.LESSER \ COPYING.ASL20 \ contrib/gnutls/ca.pem \ contrib/gnutls/cert.pem \ contrib/gnutls/key.pem \ scripts/generate_distro_component_map.py \ devtools/release/validate-rpm-baseline-patches.py SUBDIRS = doc compat grammar runtime . plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting # external plugin driver is always enabled (core component) SUBDIRS += plugins/mmexternal if ENABLE_RSYSLOGD SUBDIRS += tools endif if ENABLE_IMKLOG SUBDIRS += plugins/imklog endif if ENABLE_IMKMSG SUBDIRS += contrib/imkmsg endif if ENABLE_IMPSTATS SUBDIRS += plugins/impstats endif if ENABLE_IMSOLARIS SUBDIRS += plugins/imsolaris endif if ENABLE_GSSAPI SUBDIRS += plugins/omgssapi plugins/imgssapi endif if ENABLE_RELP SUBDIRS += plugins/omrelp plugins/imrelp endif if ENABLE_MYSQL SUBDIRS += plugins/ommysql endif if ENABLE_OMLIBDBI SUBDIRS += plugins/omlibdbi endif if ENABLE_PGSQL SUBDIRS += plugins/ompgsql endif if ENABLE_SNMP SUBDIRS += plugins/omsnmp endif if ENABLE_OMSTDOUT SUBDIRS += plugins/omstdout endif if ENABLE_OMSENDERTRACK SUBDIRS += plugins/omsendertrack endif if ENABLE_PMCISCONAMES SUBDIRS += contrib/pmcisconames endif if ENABLE_PMCISCOIOS SUBDIRS += plugins/pmciscoios endif if ENABLE_PMNULL SUBDIRS += plugins/pmnull endif if ENABLE_PMNORMALIZE SUBDIRS += plugins/pmnormalize endif if ENABLE_PMAIXFORWARDEDFROM SUBDIRS += contrib/pmaixforwardedfrom endif if ENABLE_PMSNARE SUBDIRS += contrib/pmsnare endif if ENABLE_PMPANNGFW SUBDIRS += contrib/pmpanngfw endif if ENABLE_PMLASTMSG SUBDIRS += plugins/pmlastmsg endif if ENABLE_OMRULESET SUBDIRS += plugins/omruleset endif if ENABLE_OMUDPSPOOF SUBDIRS += plugins/omudpspoof endif if ENABLE_OMMONGODB SUBDIRS += plugins/ommongodb endif if ENABLE_OMHIREDIS SUBDIRS += contrib/omhiredis endif if ENABLE_OMCZMQ SUBDIRS += contrib/omczmq endif if ENABLE_OMRABBITMQ SUBDIRS += contrib/omrabbitmq endif if ENABLE_IMCZMQ SUBDIRS += contrib/imczmq endif if ENABLE_OMUXSOCK SUBDIRS += plugins/omuxsock endif if ENABLE_OMHDFS SUBDIRS += plugins/omhdfs endif if ENABLE_OMOTEL SUBDIRS += plugins/omotel endif if ENABLE_OMJOURNAL SUBDIRS += plugins/omjournal endif if ENABLE_IMJOURNAL SUBDIRS += plugins/imjournal endif if ENABLE_ELASTICSEARCH SUBDIRS += plugins/omelasticsearch endif if ENABLE_CLICKHOUSE SUBDIRS += plugins/omclickhouse endif if ENABLE_OMHTTP SUBDIRS += contrib/omhttp endif if ENABLE_SNMP SUBDIRS += plugins/omsnmp endif if ENABLE_MMSNMPTRAPD SUBDIRS += plugins/mmsnmptrapd endif if ENABLE_IMFILE SUBDIRS += plugins/imfile endif if ENABLE_IMFIFO SUBDIRS += plugins/imfifo endif if ENABLE_IMDOCKER SUBDIRS += contrib/imdocker endif if ENABLE_IMKUBERNETES SUBDIRS += contrib/imkubernetes endif if ENABLE_IMPTCP SUBDIRS += plugins/imptcp endif if ENABLE_IMDIAG SUBDIRS += plugins/imdiag endif if ENABLE_IMBEATS SUBDIRS += plugins/imbeats endif if ENABLE_MAIL SUBDIRS += plugins/ommail endif if ENABLE_FMHTTP SUBDIRS += plugins/fmhttp endif if ENABLE_FMHASH SUBDIRS += contrib/fmhash endif if ENABLE_FMUNFLATTEN SUBDIRS += contrib/fmunflatten endif if ENABLE_FMPCRE SUBDIRS += plugins/fmpcre endif if ENABLE_FFAUP SUBDIRS += contrib/ffaup endif if ENABLE_OMKAFKA SUBDIRS += plugins/omkafka endif if ENABLE_IMKAFKA SUBDIRS += plugins/imkafka endif if ENABLE_OMAZUREEVENTHUBS SUBDIRS += plugins/omazureeventhubs endif if ENABLE_OMAZUREDCE SUBDIRS += plugins/omazuredce endif if ENABLE_OMAWSLOGSHLC SUBDIRS += plugins/omawslogshlc endif if ENABLE_IMDTLS SUBDIRS += plugins/imdtls endif if ENABLE_OMDTLS SUBDIRS += plugins/omdtls endif if ENABLE_OMPROG SUBDIRS += plugins/omprog endif if ENABLE_RFC3195 SUBDIRS += plugins/im3195 endif if ENABLE_MMNORMALIZE SUBDIRS += plugins/mmnormalize endif if ENABLE_MMLEEFPARSE SUBDIRS += plugins/mmleefparse endif if ENABLE_MMJSONPARSE SUBDIRS += plugins/mmjsonparse endif if ENABLE_MMJSONTRANSFORM SUBDIRS += plugins/mmjsontransform endif if ENABLE_MMGROK SUBDIRS += contrib/mmgrok endif if ENABLE_MMAUDIT SUBDIRS += plugins/mmaudit endif if ENABLE_MMANON SUBDIRS += plugins/mmanon endif if ENABLE_MMRM1STSPACE SUBDIRS += plugins/mmrm1stspace endif if ENABLE_MMUTF8FIX SUBDIRS += plugins/mmutf8fix endif if ENABLE_MMCOUNT SUBDIRS += contrib/mmcount endif if ENABLE_MMSEQUENCE SUBDIRS += contrib/mmsequence endif if ENABLE_MMDBLOOKUP SUBDIRS += plugins/mmdblookup endif if ENABLE_MMDARWIN SUBDIRS += contrib/mmdarwin endif if ENABLE_MMFIELDS SUBDIRS += plugins/mmfields endif if ENABLE_MMPSTRUCDATA SUBDIRS += plugins/mmpstrucdata endif if ENABLE_MMAITAG SUBDIRS += plugins/mmaitag endif if ENABLE_MMRFC5424ADDHMAC SUBDIRS += contrib/mmrfc5424addhmac endif if ENABLE_MMSNAREPARSE SUBDIRS += plugins/mmsnareparse endif # omhttpfs if ENABLE_OMHTTPFS SUBDIRS += contrib/omhttpfs endif # omamqp1 if ENABLE_OMAMQP1 SUBDIRS += contrib/omamqp1 endif # imbatchreport if ENABLE_IMBATCHREPORT SUBDIRS += contrib/imbatchreport endif # omtcl if ENABLE_OMTCL SUBDIRS += contrib/omtcl endif # mmkubernetes if ENABLE_MMKUBERNETES SUBDIRS += contrib/mmkubernetes endif # impcap if ENABLE_IMPCAP SUBDIRS += contrib/impcap endif # imtuxedoulog if ENABLE_IMTUXEDOULOG SUBDIRS += contrib/imtuxedoulog endif # improg if ENABLE_IMPROG SUBDIRS += contrib/improg endif # imhttp if ENABLE_IMHTTP SUBDIRS += contrib/imhttp endif # mmtaghostname if ENABLE_MMTAGHOSTNAME SUBDIRS += contrib/mmtaghostname endif # imdb2diag if ENABLE_PMDB2DIAG SUBDIRS += contrib/pmdb2diag endif # imhiredis if ENABLE_IMHIREDIS SUBDIRS += contrib/imhiredis endif # tests are added as last element, because tests may need different # modules that need to be generated first SUBDIRS += tests DISTCHECK_CONFIGURE_FLAGS= # make sure "make distcheck" tries to build all modules. This means that # a developer must always have an environment where every supporting library # is available. If that is not the case, the respective configure option may # temporarily be removed below. The intent behind forcing everthing to compile # in a make distcheck is so that we detect code that accidently was not updated # when some global update happened. DISTCHECK_CONFIGURE_FLAGS+= \ --enable-silent-rules \ --enable-rsyslogd \ --enable-omstdout \ --enable-omsendertrack \ --enable-imdiag \ --enable-testbench \ --enable-valgrind if HAVE_LIBYAML else DISTCHECK_CONFIGURE_FLAGS+= --disable-libyaml endif # HAVE_LIBYAML # currently not supported in make distcheck: # --enable-pgsql-tests # --enable-extended-tests --> should probably never be enabled due to runtime if ENABLE_DEFAULT_TESTS DISTCHECK_CONFIGURE_FLAGS+= \ --enable-diagtools \ --enable-impstats \ --enable-imptcp \ --enable-klog \ --enable-mail \ --enable-mmanon \ --enable-mmaudit \ --enable-mmcount \ --enable-mmexternal \ --enable-mmfields \ --enable-mmjsonparse \ --enable-mmpstrucdata \ --enable-mmrm1stspace \ --enable-mmsequence \ --enable-mmutf8fix \ --enable-omruleset \ --enable-omuxsock \ --enable-pmaixforwardedfrom \ --enable-pmciscoios \ --enable-pmcisconames \ --enable-pmlastmsg \ --enable-pmnull \ --enable-pmsnare \ --enable-usertools else DISTCHECK_CONFIGURE_FLAGS+= \ --disable-default-tests endif # if ENABLE_DEFAULT_TESTS if ENABLE_IMPROG DISTCHECK_CONFIGURE_FLAGS+= --enable-improg endif if ENABLE_IMHTTP DISTCHECK_CONFIGURE_FLAGS+= --enable-imhttp endif if ENABLE_OMPROG DISTCHECK_CONFIGURE_FLAGS+= --enable-omprog endif if ENABLE_GSSAPI DISTCHECK_CONFIGURE_FLAGS+= --enable-gssapi-krb5 endif if ENABLE_PMNORMALIZE DISTCHECK_CONFIGURE_FLAGS+= --enable-pmnormalize endif if ENABLE_MMDBLOOKUP DISTCHECK_CONFIGURE_FLAGS+= --enable-mmdblookup endif if ENABLE_MMDARWIN DISTCHECK_CONFIGURE_FLAGS+= --enable-mmdarwin endif if ENABLE_MMNORMALIZE DISTCHECK_CONFIGURE_FLAGS+= --enable-mmnormalize endif if ENABLE_OMMONGODB DISTCHECK_CONFIGURE_FLAGS+= --enable-ommongodb endif if ENABLE_OMHIREDIS DISTCHECK_CONFIGURE_FLAGS+= --enable-omhiredis endif if ENABLE_MMSNMPTRAPD DISTCHECK_CONFIGURE_FLAGS+= --enable-mmsnmptrapd endif if ENABLE_OMLIBDBI DISTCHECK_CONFIGURE_FLAGS+= --enable-libdbi endif if ENABLE_LIBGCRYPT DISTCHECK_CONFIGURE_FLAGS+= --enable-libgcrypt endif if ENABLE_OMHTTP DISTCHECK_CONFIGURE_FLAGS+= --enable-omhttp endif if ENABLE_OMHTTPFS DISTCHECK_CONFIGURE_FLAGS+= --enable-omhttpfs endif if ENABLE_OMTCL DISTCHECK_CONFIGURE_FLAGS+= --enable-omtcl endif if ENABLE_SNMP DISTCHECK_CONFIGURE_FLAGS+= --enable-snmp endif if ENABLE_SNMP_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-snmp-tests endif if ENABLE_FMHTTP DISTCHECK_CONFIGURE_FLAGS+= --enable-fmhttp endif if ENABLE_OMUDPSPOOF DISTCHECK_CONFIGURE_FLAGS+= --enable-omudpspoof endif if ENABLE_PGSQL DISTCHECK_CONFIGURE_FLAGS+= --enable-pgsql endif if ENABLE_GNUTLS DISTCHECK_CONFIGURE_FLAGS+= --enable-gnutls endif if ENABLE_GNUTLS_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-gnutls-tests else DISTCHECK_CONFIGURE_FLAGS+= --disable-gnutls-tests endif if ENABLE_OPENSSL DISTCHECK_CONFIGURE_FLAGS+= --enable-openssl endif if ENABLE_WOLFSSL DISTCHECK_CONFIGURE_FLAGS+= --enable-wolfssl endif if ENABLE_MYSQL DISTCHECK_CONFIGURE_FLAGS+= --enable-mysql endif if ENABLE_MYSQL_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-mysql-tests endif if ENABLE_ELASTICSEARCH DISTCHECK_CONFIGURE_FLAGS+= --enable-elasticsearch endif if ENABLE_ELASTICSEARCH_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-elasticsearch-tests endif if ENABLE_CLICKHOUSE DISTCHECK_CONFIGURE_FLAGS+= --enable-clickhouse endif if ENABLE_CLICKHOUSE_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-clickhouse-tests endif if ENABLE_MMGROK DISTCHECK_CONFIGURE_FLAGS+= --enable-mmgrok endif if ENABLE_RELP DISTCHECK_CONFIGURE_FLAGS+= --enable-relp --enable-omrelp-default-port=13515 endif if ENABLE_IMKAFKA DISTCHECK_CONFIGURE_FLAGS+= --enable-imkafka endif if ENABLE_OMKAFKA DISTCHECK_CONFIGURE_FLAGS+= --enable-omkafka endif if ENABLE_KAFKA_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-kafka-tests endif if ENABLE_OMAZUREEVENTHUBS DISTCHECK_CONFIGURE_FLAGS+= --enable-omazureeventhubs endif if ENABLE_OMAZUREDCE DISTCHECK_CONFIGURE_FLAGS+= --enable-omazuredce endif if ENABLE_OMAWSLOGSHLC DISTCHECK_CONFIGURE_FLAGS+= --enable-omawslogshlc endif if ENABLE_IMDTLS DISTCHECK_CONFIGURE_FLAGS+= --enable-imdtls endif if ENABLE_OMDTLS DISTCHECK_CONFIGURE_FLAGS+= --enable-omdtls endif if ENABLE_IMJOURNAL DISTCHECK_CONFIGURE_FLAGS+= --enable-imjournal endif if ENABLE_OMJOURNAL DISTCHECK_CONFIGURE_FLAGS+= --enable-omjournal endif if ENABLE_JOURNAL_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-journal-tests endif if ENABLE_IMCZMQ DISTCHECK_CONFIGURE_FLAGS+= --enable-imczmq endif if ENABLE_OMCZMQ DISTCHECK_CONFIGURE_FLAGS+= --enable-omczmq endif if ENABLE_MMTAGHOSTNAME DISTCHECK_CONFIGURE_FLAGS+= --enable-mmtaghostname endif if ENABLE_IMTUXEDOULOG DISTCHECK_CONFIGURE_FLAGS+= --enable-imtuxedolog endif if ENABLE_PMDB2DIAG DISTCHECK_CONFIGURE_FLAGS+= --enable-pmdb2diag endif if ENABLE_IMBATCHREPORT DISTCHECK_CONFIGURE_FLAGS+= --enable-imbatchreport endif if ENABLE_IMFILE DISTCHECK_CONFIGURE_FLAGS+= --enable-imfile endif if ENABLE_IMFIFO DISTCHECK_CONFIGURE_FLAGS+= --enable-imfifo endif if ENABLE_IMFILE_TESTS DISTCHECK_CONFIGURE_FLAGS+= --enable-imfile-tests else DISTCHECK_CONFIGURE_FLAGS+= --disable-imfile-tests endif if ENABLE_IMPCAP DISTCHECK_CONFIGURE_FLAGS+= --enable-impcap endif if ENABLE_IMDOCKER DISTCHECK_CONFIGURE_FLAGS+= --enable-imdocker endif if ENABLE_OMRABBITMQ DISTCHECK_CONFIGURE_FLAGS+= --enable-omrabbitmq endif if ENABLE_MMKUBERNETES DISTCHECK_CONFIGURE_FLAGS+= --enable-mmkubernetes endif if ENABLE_OMAMQP1 DISTCHECK_CONFIGURE_FLAGS+= --enable-omamqp1 endif if ENABLE_DISTCHECK_WORKAROUND DISTCHECK_CONFIGURE_FLAGS+= --disable-testbench else DISTCHECK_CONFIGURE_FLAGS+= --enable-testbench endif if ENABLE_IMHIREDIS DISTCHECK_CONFIGURE_FLAGS+= --enable-imhiredis endif dist-hook: $(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version ACLOCAL_AMFLAGS = -I m4 COVERAGE_INFO = $(top_builddir)/coverage.info COVERAGE_DIR = coverage LCOV_FLAGS = --capture \ --config-file "$(top_srcdir)/lcovrc" \ --directory "$(abs_top_builddir)" \ --ignore-errors mismatch \ --output-file $(COVERAGE_INFO) GENHTML_FLAGS = --legend \ --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" \ --output-directory $(top_builddir)/$(COVERAGE_DIR) check-coverage: reset-coverage-stats if ENABLE_COVERAGE $(MAKE) check || true $(MAKE) coverage reset-coverage-stats: $(LCOV) --zerocounters --directory "$(abs_top_builddir)" coverage: clean-coverage-local distclean-coverage-local @echo "Aggregating coverage files and generating HTML summary..." $(LCOV) $(LCOV_FLAGS) > /dev/null $(GENHTML) $(GENHTML_FLAGS) $(COVERAGE_INFO) > /dev/null @echo "Coverage HTML page result file://$(abs_builddir)/$(COVERAGE_DIR)/index.html" else @echo "Code coverage not enabled; to enable:" @echo @echo " ./configure --enable-coverage" endif clean-local: clean-coverage-local clean-coverage-local: rm -f $(COVERAGE_INFO) distclean-local: distclean-coverage-local distclean-coverage-local: rm -rf $(COVERAGE_DIR) rsyslog-8.2608.0/PaxHeaders/config.guess0000644000000000000000000000013215241076160015056 xustar0030 mtime=1787067504.267315966 30 atime=1787067507.962384896 30 ctime=1787067790.725656682 rsyslog-8.2608.0/config.guess0000755000175000017500000014051215241076160014526 0ustar00rgerrger#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale timestamp='2022-01-09' # 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; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . # The "shellcheck disable" line above the timestamp inhibits complaints # about features and limitations of the classic Bourne shell that were # superseded or lifted in POSIX. However, this script identifies a wide # variety of pre-POSIX systems that do not have POSIX shells at all, and # even some reasonably current systems (Solaris 10 as case-in-point) still # have a pre-POSIX /bin/sh. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -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-2022 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 # Just in case it came from the environment. GUESS= # 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. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039,SC3028 { 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" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD=$driver 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 } # 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 ; 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/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; 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". UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ echo unknown)` case $UNAME_MACHINE_ARCH in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-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) and ABI. case $UNAME_MACHINE_ARCH in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) 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 # Determine ABI tags. case $UNAME_MACHINE_ARCH in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; 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/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. GUESS=$machine-${os}${release}${abi-} ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE ;; *:SecBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE ;; *:MidnightBSD:*:*) GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE ;; *:ekkoBSD:*:*) GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE ;; *:SolidBSD:*:*) GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE ;; *:OS108:*:*) GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE ;; macppc:MirBSD:*:*) GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE ;; *:MirBSD:*:*) GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE ;; *:Sortix:*:*) GUESS=$UNAME_MACHINE-unknown-sortix ;; *:Twizzler:*:*) GUESS=$UNAME_MACHINE-unknown-twizzler ;; *:Redox:*:*) GUESS=$UNAME_MACHINE-unknown-redox ;; mips:OSF1:*.*) GUESS=mips-dec-osf1 ;; alpha:OSF1:*:*) # Reset EXIT trap before exiting to avoid spurious non-zero exit code. trap '' 0 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. OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` GUESS=$UNAME_MACHINE-dec-osf$OSF_REL ;; Amiga*:UNIX_System_V:4.0:*) GUESS=m68k-unknown-sysv4 ;; *:[Aa]miga[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-amigaos ;; *:[Mm]orph[Oo][Ss]:*:*) GUESS=$UNAME_MACHINE-unknown-morphos ;; *:OS/390:*:*) GUESS=i370-ibm-openedition ;; *:z/VM:*:*) GUESS=s390-ibm-zvmoe ;; *:OS400:*:*) GUESS=powerpc-ibm-os400 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) GUESS=arm-acorn-riscix$UNAME_RELEASE ;; arm*:riscos:*:*|arm*:RISCOS:*:*) GUESS=arm-unknown-riscos ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) GUESS=hppa1.1-hitachi-hiuxmpp ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. case `(/bin/universe) 2>/dev/null` in att) GUESS=pyramid-pyramid-sysv3 ;; *) GUESS=pyramid-pyramid-bsd ;; esac ;; NILE*:*:*:dcosx) GUESS=pyramid-pyramid-svr4 ;; DRS?6000:unix:4.0:6*) GUESS=sparc-icl-nx6 ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) GUESS=sparc-icl-nx7 ;; esac ;; s390x:SunOS:*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL ;; sun4H:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-hal-solaris2$SUN_REL ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris2$SUN_REL ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) GUESS=i386-pc-auroraux$UNAME_RELEASE ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) 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 test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=$SUN_ARCH-pc-solaris2$SUN_REL ;; 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. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=sparc-sun-solaris3$SUN_REL ;; 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'. SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` GUESS=sparc-sun-sunos$SUN_REL ;; sun3*:SunOS:*:*) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; 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) GUESS=m68k-sun-sunos$UNAME_RELEASE ;; sun4) GUESS=sparc-sun-sunos$UNAME_RELEASE ;; esac ;; aushp:SunOS:*:*) GUESS=sparc-auspex-sunos$UNAME_RELEASE ;; # 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:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) GUESS=m68k-atari-mint$UNAME_RELEASE ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) GUESS=m68k-milan-mint$UNAME_RELEASE ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) GUESS=m68k-hades-mint$UNAME_RELEASE ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) GUESS=m68k-unknown-mint$UNAME_RELEASE ;; m68k:machten:*:*) GUESS=m68k-apple-machten$UNAME_RELEASE ;; powerpc:machten:*:*) GUESS=powerpc-apple-machten$UNAME_RELEASE ;; RISC*:Mach:*:*) GUESS=mips-dec-mach_bsd4.3 ;; RISC*:ULTRIX:*:*) GUESS=mips-dec-ultrix$UNAME_RELEASE ;; VAX*:ULTRIX*:*:*) GUESS=vax-dec-ultrix$UNAME_RELEASE ;; 2020:CLIX:*:* | 2430:CLIX:*:*) GUESS=clipper-intergraph-clix$UNAME_RELEASE ;; mips:*:*:UMIPS | mips:*:*:RISCos) 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; } GUESS=mips-mips-riscos$UNAME_RELEASE ;; Motorola:PowerMAX_OS:*:*) GUESS=powerpc-motorola-powermax ;; Motorola:*:4.3:PL8-*) GUESS=powerpc-harris-powermax ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) GUESS=powerpc-harris-powermax ;; Night_Hawk:Power_UNIX:*:*) GUESS=powerpc-harris-powerunix ;; m88k:CX/UX:7*:*) GUESS=m88k-harris-cxux7 ;; m88k:*:4*:R4*) GUESS=m88k-motorola-sysv4 ;; m88k:*:3*:R3*) GUESS=m88k-motorola-sysv3 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then GUESS=m88k-dg-dgux$UNAME_RELEASE else GUESS=m88k-dg-dguxbcs$UNAME_RELEASE fi else GUESS=i586-dg-dgux$UNAME_RELEASE fi ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) GUESS=m88k-dolphin-sysv3 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 GUESS=m88k-motorola-sysv3 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) GUESS=m88k-tektronix-sysv3 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) GUESS=m68k-tektronix-bsd ;; *:IRIX*:*:*) IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` GUESS=mips-sgi-irix$IRIX_REL ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) GUESS=i386-ibm-aix ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then 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 GUESS=$SYSTEM_NAME else GUESS=rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then GUESS=rs6000-ibm-aix3.2.4 else GUESS=rs6000-ibm-aix3.2 fi ;; *: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 test -x /usr/bin/lslpp ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=$UNAME_VERSION.$UNAME_RELEASE fi GUESS=$IBM_ARCH-ibm-aix$IBM_REV ;; *:AIX:*:*) GUESS=rs6000-ibm-aix ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) GUESS=romp-ibm-bsd4.4 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) GUESS=rs6000-bull-bosx ;; DPX/2?00:B.O.S.:*:*) GUESS=m68k-bull-sysv3 ;; 9000/[34]??:4.3bsd:1.*:*) GUESS=m68k-hp-bsd ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) GUESS=m68k-hp-bsd4.4 ;; 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 test -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 test "$HP_ARCH" = ""; then 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 test "$HP_ARCH" = hppa2.0w then 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 GUESS=$HP_ARCH-hp-hpux$HPUX_REV ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` GUESS=ia64-hp-hpux$HPUX_REV ;; 3050*:HI-UX:*:*) 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; } GUESS=unknown-hitachi-hiuxwe2 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) GUESS=hppa1.1-hp-bsd ;; 9000/8??:4.3bsd:*:*) GUESS=hppa1.0-hp-bsd ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) GUESS=hppa1.0-hp-mpeix ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) GUESS=hppa1.1-hp-osf ;; hp8??:OSF1:*:*) GUESS=hppa1.0-hp-osf ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then GUESS=$UNAME_MACHINE-unknown-osf1mk else GUESS=$UNAME_MACHINE-unknown-osf1 fi ;; parisc*:Lites*:*:*) GUESS=hppa1.1-hp-lites ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) GUESS=c1-convex-bsd ;; 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*:*) GUESS=c34-convex-bsd ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) GUESS=c38-convex-bsd ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) GUESS=c4-convex-bsd ;; CRAY*Y-MP:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=ymp-cray-unicos$CRAY_REL ;; 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:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=t90-cray-unicos$CRAY_REL ;; CRAY*T3E:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=alphaev5-cray-unicosmk$CRAY_REL ;; CRAY*SV1:*:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=sv1-cray-unicos$CRAY_REL ;; *:UNICOS/mp:*:*) CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` GUESS=craynv-cray-unicosmp$CRAY_REL ;; 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/ /_/'` GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; 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/ /_/'` GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE ;; sparc*:BSD/OS:*:*) GUESS=sparc-unknown-bsdi$UNAME_RELEASE ;; *:BSD/OS:*:*) GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=`uname -p` set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi else FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf fi ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL ;; i*:CYGWIN*:*) GUESS=$UNAME_MACHINE-pc-cygwin ;; *:MINGW64*:*) GUESS=$UNAME_MACHINE-pc-mingw64 ;; *:MINGW*:*) GUESS=$UNAME_MACHINE-pc-mingw32 ;; *:MSYS*:*) GUESS=$UNAME_MACHINE-pc-msys ;; i*:PW*:*) GUESS=$UNAME_MACHINE-pc-pw32 ;; *:SerenityOS:*:*) GUESS=$UNAME_MACHINE-pc-serenity ;; *:Interix*:*) case $UNAME_MACHINE in x86) GUESS=i586-pc-interix$UNAME_RELEASE ;; authenticamd | genuineintel | EM64T) GUESS=x86_64-unknown-interix$UNAME_RELEASE ;; IA64) GUESS=ia64-unknown-interix$UNAME_RELEASE ;; esac ;; i*:UWIN*:*) GUESS=$UNAME_MACHINE-pc-uwin ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) GUESS=x86_64-pc-cygwin ;; prep*:SunOS:5.*:*) SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` GUESS=powerpcle-unknown-solaris2$SUN_REL ;; *:GNU:*:*) # the GNU system GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL ;; *:GNU/*:*:*) # other systems with GNU libc and userland GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC ;; *:Minix:*:*) GUESS=$UNAME_MACHINE-unknown-minix ;; aarch64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` 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 GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then GUESS=$UNAME_MACHINE-unknown-linux-$LIBC else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi else GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf fi fi ;; avr32*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; cris:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; crisv32:Linux:*:*) GUESS=$UNAME_MACHINE-axis-linux-$LIBC ;; e2k:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; frv:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; hexagon:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; i*86:Linux:*:*) GUESS=$UNAME_MACHINE-pc-linux-$LIBC ;; ia64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; k1om:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m32r*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; m68*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` eval "$cc_set_vars" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; openrisc*:Linux:*:*) GUESS=or1k-unknown-linux-$LIBC ;; or32:Linux:*:* | or1k*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; padre:Linux:*:*) GUESS=sparc-unknown-linux-$LIBC ;; parisc64:Linux:*:* | hppa64:Linux:*:*) GUESS=hppa64-unknown-linux-$LIBC ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; *) GUESS=hppa-unknown-linux-$LIBC ;; esac ;; ppc64:Linux:*:*) GUESS=powerpc64-unknown-linux-$LIBC ;; ppc:Linux:*:*) GUESS=powerpc-unknown-linux-$LIBC ;; ppc64le:Linux:*:*) GUESS=powerpc64le-unknown-linux-$LIBC ;; ppcle:Linux:*:*) GUESS=powerpcle-unknown-linux-$LIBC ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; s390:Linux:*:* | s390x:Linux:*:*) GUESS=$UNAME_MACHINE-ibm-linux-$LIBC ;; sh64*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sh*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; sparc:Linux:*:* | sparc64:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; tile*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; vax:Linux:*:*) GUESS=$UNAME_MACHINE-dec-linux-$LIBC ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI=${LIBC}x32 fi fi GUESS=$UNAME_MACHINE-pc-linux-$LIBCABI ;; xtensa*:Linux:*:*) GUESS=$UNAME_MACHINE-unknown-linux-$LIBC ;; 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. GUESS=i386-sequent-sysv4 ;; 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. GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. GUESS=$UNAME_MACHINE-pc-os2-emx ;; i*86:XTS-300:*:STOP) GUESS=$UNAME_MACHINE-unknown-stop ;; i*86:atheos:*:*) GUESS=$UNAME_MACHINE-unknown-atheos ;; i*86:syllable:*:*) GUESS=$UNAME_MACHINE-pc-syllable ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) GUESS=i386-unknown-lynxos$UNAME_RELEASE ;; i*86:*DOS:*:*) GUESS=$UNAME_MACHINE-pc-msdosdjgpp ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL fi ;; 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 GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} ;; 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 GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL else GUESS=$UNAME_MACHINE-pc-sysv32 fi ;; 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 configure will decide that # this is a cross-build. GUESS=i586-pc-msdosdjgpp ;; Intel:Mach:3*:*) GUESS=i386-pc-mach3 ;; paragon:*:*:*) GUESS=i860-intel-osf1 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 fi ;; mini*:CTIX:SYS*5:*) # "miniframe" GUESS=m68010-convergent-sysv ;; mc68k:UNIX:SYSTEM5:3.51m) GUESS=m68k-convergent-sysv ;; M680?0:D-NIX:5.3:*) GUESS=m68k-diab-dnix ;; 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*:*) GUESS=m68k-unknown-lynxos$UNAME_RELEASE ;; mc68030:UNIX_System_V:4.*:*) GUESS=m68k-atari-sysv4 ;; TSUNAMI:LynxOS:2.*:*) GUESS=sparc-unknown-lynxos$UNAME_RELEASE ;; rs6000:LynxOS:2.*:*) GUESS=rs6000-unknown-lynxos$UNAME_RELEASE ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) GUESS=powerpc-unknown-lynxos$UNAME_RELEASE ;; SM[BE]S:UNIX_SV:*:*) GUESS=mips-dde-sysv$UNAME_RELEASE ;; RM*:ReliantUNIX-*:*:*) GUESS=mips-sni-sysv4 ;; RM*:SINIX-*:*:*) GUESS=mips-sni-sysv4 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` GUESS=$UNAME_MACHINE-sni-sysv4 else GUESS=ns32k-sni-sysv fi ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says GUESS=i586-unisys-sysv4 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm GUESS=hppa1.1-stratus-sysv4 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. GUESS=i860-stratus-sysv4 ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. GUESS=$UNAME_MACHINE-stratus-vos ;; *:VOS:*:*) # From Paul.Green@stratus.com. GUESS=hppa1.1-stratus-vos ;; mc68*:A/UX:*:*) GUESS=m68k-apple-aux$UNAME_RELEASE ;; news*:NEWS-OS:6*:*) GUESS=mips-sony-newsos6 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then GUESS=mips-nec-sysv$UNAME_RELEASE else GUESS=mips-unknown-sysv$UNAME_RELEASE fi ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. GUESS=powerpc-be-beos ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. GUESS=powerpc-apple-beos ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. GUESS=i586-pc-beos ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; x86_64:Haiku:*:*) GUESS=x86_64-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE ;; SX-5:SUPER-UX:*:*) GUESS=sx5-nec-superux$UNAME_RELEASE ;; SX-6:SUPER-UX:*:*) GUESS=sx6-nec-superux$UNAME_RELEASE ;; SX-7:SUPER-UX:*:*) GUESS=sx7-nec-superux$UNAME_RELEASE ;; SX-8:SUPER-UX:*:*) GUESS=sx8-nec-superux$UNAME_RELEASE ;; SX-8R:SUPER-UX:*:*) GUESS=sx8r-nec-superux$UNAME_RELEASE ;; SX-ACE:SUPER-UX:*:*) GUESS=sxace-nec-superux$UNAME_RELEASE ;; Power*:Rhapsody:*:*) GUESS=powerpc-apple-rhapsody$UNAME_RELEASE ;; *:Rhapsody:*:*) GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE ;; arm64:Darwin:*:*) GUESS=aarch64-apple-darwin$UNAME_RELEASE ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$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 # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE ;; *:QNX:*:4*) GUESS=i386-pc-qnx ;; NEO-*:NONSTOP_KERNEL:*:*) GUESS=neo-tandem-nsk$UNAME_RELEASE ;; NSE-*:NONSTOP_KERNEL:*:*) GUESS=nse-tandem-nsk$UNAME_RELEASE ;; NSR-*:NONSTOP_KERNEL:*:*) GUESS=nsr-tandem-nsk$UNAME_RELEASE ;; NSV-*:NONSTOP_KERNEL:*:*) GUESS=nsv-tandem-nsk$UNAME_RELEASE ;; NSX-*:NONSTOP_KERNEL:*:*) GUESS=nsx-tandem-nsk$UNAME_RELEASE ;; *:NonStop-UX:*:*) GUESS=mips-compaq-nonstopux ;; BS2000:POSIX*:*:*) GUESS=bs2000-siemens-sysv ;; DS/*:UNIX_System_V:*:*) GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE ;; *: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 elif test "x${cputype-}" != x; then UNAME_MACHINE=$cputype fi GUESS=$UNAME_MACHINE-unknown-plan9 ;; *:TOPS-10:*:*) GUESS=pdp10-unknown-tops10 ;; *:TENEX:*:*) GUESS=pdp10-unknown-tenex ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) GUESS=pdp10-dec-tops20 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) GUESS=pdp10-xkl-tops20 ;; *:TOPS-20:*:*) GUESS=pdp10-unknown-tops20 ;; *:ITS:*:*) GUESS=pdp10-unknown-its ;; SEI:*:*:SEIUX) GUESS=mips-sei-seiux$UNAME_RELEASE ;; *:DragonFly:*:*) DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case $UNAME_MACHINE in A*) GUESS=alpha-dec-vms ;; I*) GUESS=ia64-dec-vms ;; V*) GUESS=vax-dec-vms ;; esac ;; *:XENIX:*:SysV) GUESS=i386-pc-xenix ;; i*86:skyos:*:*) SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL ;; i*86:rdos:*:*) GUESS=$UNAME_MACHINE-pc-rdos ;; i*86:Fiwix:*:*) GUESS=$UNAME_MACHINE-pc-fiwix ;; *:AROS:*:*) GUESS=$UNAME_MACHINE-unknown-aros ;; x86_64:VMkernel:*:*) GUESS=$UNAME_MACHINE-unknown-esx ;; amd64:Isilon\ OneFS:*:*) GUESS=x86_64-unknown-onefs ;; *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; esac # Do we have a guess based on uname results? if test "x$GUESS" != x; then echo "$GUESS" exit fi # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #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 (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 #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #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; } echo "$0: unable to guess system type" >&2 case $UNAME_MACHINE:$UNAME_SYSTEM in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&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 fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: rsyslog-8.2608.0/PaxHeaders/tools0000644000000000000000000000013215241076623013630 xustar0030 mtime=1787067795.323742367 30 atime=1787067808.783993182 30 ctime=1787067795.323742367 rsyslog-8.2608.0/tools/0000775000175000017500000000000015241076623013351 5ustar00rgerrgerrsyslog-8.2608.0/tools/PaxHeaders/recover_qi.pl0000644000000000000000000000013115035412264016373 xustar0029 mtime=1752569012.42259788 30 atime=1782715518.789788857 30 ctime=1787067795.319742292 rsyslog-8.2608.0/tools/recover_qi.pl0000777000175000017500000001372215035412264016052 0ustar00rgerrger#!/usr/bin/perl -w # recover rsyslog disk queue index (.qi) from queue files (.nnnnnnnn). # # See: # runtime/queue.c: qqueuePersist() # runtime/queue.c: qqueueTryLoadPersistedInfo() # # kaiwang.chen@gmail.com 2012-03-14 # use strict; use Getopt::Long; my %opt = (); GetOptions(\%opt,"spool|w=s","basename|f=s","digits|d=i","help!"); if ($opt{help}) { print "Usage: \t$0 -w WorkDirectory -f QueueFileName -d 8 > QueueFileName.qi "; exit; } # runtime/queue.c: qConstructDisk() my $iMaxFiles = 10000000; # 0+"1".( "0"x($opt{digits} - 1)); # get the list of queue files, spool directory excluded my $re = qr/^\Q$opt{basename}\E\.\d{$opt{digits}}$/; opendir(DIR, $opt{spool}) or die "can’t open spool: $!"; my @qf = grep { /$re/ && -f "$opt{spool}/$_" } readdir(DIR); closedir DIR; # ensure order and continuity @qf = sort @qf; my ($head) = ($qf[0] =~ /(\d+)$/); my ($tail) = ($qf[-1] =~ /(\d+)$/); $head += 0; $tail += 0; if ($tail-$head+1 != @qf || $tail > $iMaxFiles) { die "broken queue: missing file(s) or wrong tail\n"; } # collect some counters about the queue, assuming all are unprocessed entries. my $sizeOnDisk = 0; my $iQueueSize = 0; chdir($opt{spool}) or die "can't chdir to spool: $!"; print STDERR "traversing ". @qf ." files, please wait...\n"; for (@qf) { open FH, "<", $_ or die "can't read queue file $_\n"; $sizeOnDisk += (stat FH)[7]; while () { $iQueueSize++ if /^new("qqueue",1); $qqueue->property("iQueueSize", "INT", $iQueueSize); $qqueue->property("tVars.disk.sizeOnDisk", "INT64", $sizeOnDisk); $qqueue->property("tVars.disk.bytesRead", "INT64", 0); # runtime/stream.h: strmType_t my $STREAMTYPE_FILE_CIRCULAR = 1; # runtime/stream.h: strmMode_t my $STREAMMODE_READ = 1; my $STREAMMODE_WRITE_APPEND = 4; # runtime/stream.c: strmSerialize() # write to end my $strm_Write = Rsyslog::Obj->new("strm",1); $strm_Write->property( "iCurrFNum", "INT", $tail); $strm_Write->property( "pszFName", "PSZ", $opt{basename}); $strm_Write->property( "iMaxFiles", "INT", $iMaxFiles); $strm_Write->property( "bDeleteOnClose", "INT", 0); $strm_Write->property( "sType", "INT", $STREAMTYPE_FILE_CIRCULAR); $strm_Write->property("tOperationsMode", "INT", $STREAMMODE_WRITE_APPEND); $strm_Write->property( "tOpenMode", "INT", 0600); $strm_Write->property( "iCurrOffs","INT64", $iCurrOffs_Write); # read from head my $strm_ReadDel = Rsyslog::Obj->new("strm",1); $strm_ReadDel->property( "iCurrFNum", "INT", $head); $strm_ReadDel->property( "pszFName", "PSZ", $opt{basename}); $strm_ReadDel->property( "iMaxFiles", "INT", $iMaxFiles); $strm_ReadDel->property( "bDeleteOnClose", "INT", 1); $strm_ReadDel->property( "sType", "INT", $STREAMTYPE_FILE_CIRCULAR); $strm_ReadDel->property("tOperationsMode", "INT", $STREAMMODE_READ); $strm_ReadDel->property( "tOpenMode", "INT", 0600); $strm_ReadDel->property( "iCurrOffs","INT64", 0); # .qi print $qqueue->serialize(); print $strm_Write->serialize(); print $strm_ReadDel->serialize(); exit; #----------------------------------------------------------------------------- package Rsyslog::Serializable; # runtime/obj.c sub COOKIE_OBJLINE { '<' } sub COOKIE_PROPLINE { '+' } sub COOKIE_ENDLINE { '>' } sub COOKIE_BLANKLINE { '.' } # VARTYPE(short_ptype) sub VARTYPE { my ($t) = @_; # runtime/obj-types.h: propType_t my $ptype = "PROPTYPE_".$t; # runtime/var.h: varType_t my %vm = ( VARTYPE_NONE => 0, VARTYPE_STR => 1, VARTYPE_NUMBER => 2, VARTYPE_SYSLOGTIME => 3, ); # runtime/obj.c: SerializeProp() my %p2v = ( #PROPTYPE_NONE => "", PROPTYPE_PSZ => "VARTYPE_STR", PROPTYPE_SHORT => "VARTYPE_NUMBER", PROPTYPE_INT => "VARTYPE_NUMBER", PROPTYPE_LONG => "VARTYPE_NUMBER", PROPTYPE_INT64 => "VARTYPE_NUMBER", PROPTYPE_CSTR => "VARTYPE_STR", #PROPTYPE_SYSLOGTIME => "VARTYPE_SYSLOGTIME", ); my $vtype = $p2v{$ptype}; unless ($vtype) { die "property type $t is not supported!\n"; } return $vm{$vtype}; } sub serialize { my $self = shift; # runtime/obj.c: objSerializeHeader() my $x = COOKIE_OBJLINE(); $x .= join(":", $self->type(), $self->cver(), $self->id(), $self->version()); $x .= ":\n"; for ( values %{$self->{props}} ) { # runtime/obj.c: SerializeProp() $x .= COOKIE_PROPLINE(); $x .= join(":", $_->{name}, VARTYPE($_->{type}), length($_->{value}), $_->{value}); $x .= ":\n"; } # runtime/obj.c: EndSerialize() $x .= COOKIE_ENDLINE() . "End\n"; $x .= COOKIE_BLANKLINE() . "\n"; } # constructor: new(id,version) sub new { my ($class, $id, $version) = @_; $class = ref $class if ref $class; bless { id => $id, version => $version, props => {}, }, $class; } sub id { my $self = shift; if (@_) { my $x = $self->{id}; $self->{id} = shift; return $x; } return $self->{id}; } sub version { my $self = shift; if (@_) { my $x = $self->{version}; $self->{version} = shift; return $x; } return $self->{version}; } # property(name, type, value) sub property { my $self = shift; my $name = shift; if (@_) { my $x = $self->{props}{$name}; $self->{props}{$name}{name} = $name; $self->{props}{$name}{type} = shift; $self->{props}{$name}{value} = shift; return $x; } return $self->{props}{$name}; } 1; package Rsyslog::OPB; use base qw(Rsyslog::Serializable); sub type { 'OPB' } sub cver { 1 } sub new { shift->SUPER::new(@_) } 1; package Rsyslog::Obj; use base qw(Rsyslog::Serializable); sub type { 'Obj' } sub cver { 1 } sub new { shift->SUPER::new(@_) } 1; rsyslog-8.2608.0/tools/PaxHeaders/smtradfwd.h0000644000000000000000000000013215141401300016030 xustar0030 mtime=1770390208.970869795 30 atime=1787067618.337443364 30 ctime=1787067795.287741696 rsyslog-8.2608.0/tools/smtradfwd.h0000664000175000017500000000226615141401300015502 0ustar00rgerrger/* smtradfwd.h * * File begun on 2010-06-04 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SMTRADFWD_H_INCLUDED #define SMTRADFWD_H_INCLUDED 1 /* prototypes */ rsRetVal modInitsmtradfwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef SMTRADFWD_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/smfwd.c0000644000000000000000000000013215132411300015151 xustar0030 mtime=1768559296.305886257 30 atime=1787067622.110513714 30 ctime=1787067795.280741565 rsyslog-8.2608.0/tools/smfwd.c0000666000175000017500000001012715132411300014620 0ustar00rgerrger/* smfwd.c * This is a strgen module for the traditional (network) forwarding format. * * Format generated: * "<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%" * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2010-06-01 by RGerhards * * Copyright 2010-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "unicode-helper.h" MODULE_TYPE_STRGEN MODULE_TYPE_NOKEEP; STRGEN_NAME("RSYSLOG_ForwardFormat") /* internal structures */ DEF_SMOD_STATIC_DATA; /* config data */ /* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings * needed (including their length) and then calculating the actual space required. So when we * finally copy, we know exactly what we need. So we do at most one alloc. */ BEGINstrgen register int iBuf; const char *pPRI; size_t lenPRI; uchar *pTimeStamp; size_t lenTimeStamp; uchar *pHOSTNAME; size_t lenHOSTNAME; uchar *pTAG; int lenTAG; uchar *pMSG; size_t lenMSG; size_t lenTotal; CODESTARTstrgen; /* first obtain all strings and their length (if not fixed) */ pPRI = getPRI(pMsg); lenPRI = strlen(pPRI); pTimeStamp = (uchar *)getTimeReported(pMsg, tplFmtRFC3339Date); lenTimeStamp = ustrlen(pTimeStamp); pHOSTNAME = (uchar *)getHOSTNAME(pMsg); lenHOSTNAME = getHOSTNAMELen(pMsg); getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX); if (lenTAG > 32) lenTAG = 32; /* for forwarding, a max of 32 chars is permitted (RFC!) */ pMSG = getMSG(pMsg); lenMSG = getMSGLen(pMsg); /* calculate len, constants for spaces and similar fixed strings */ lenTotal = 1 + lenPRI + 1 + lenTimeStamp + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 1; if (pMSG[0] != ' ') ++lenTotal; /* then we need to introduce one additional space */ /* now make sure buffer is large enough */ if (lenTotal >= iparam->lenBuf) CHKiRet(ExtendBuf(iparam, lenTotal)); /* and concatenate the resulting string */ iparam->param[0] = '<'; memcpy(iparam->param + 1, pPRI, lenPRI); iBuf = lenPRI + 1; iparam->param[iBuf++] = '>'; memcpy(iparam->param + iBuf, pTimeStamp, lenTimeStamp); iBuf += lenTimeStamp; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME); iBuf += lenHOSTNAME; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pTAG, lenTAG); iBuf += lenTAG; if (pMSG[0] != ' ') iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pMSG, lenMSG); iBuf += lenMSG; /* string terminator */ iparam->param[iBuf] = '\0'; iparam->lenStr = lenTotal - 1; /* do not count \0! */ finalize_it: ENDstrgen BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_SMOD_QUERIES; ENDqueryEtryPt BEGINmodInit(smfwd) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf( "rsyslog standard (network) forward format strgen init called, compiled with version" " %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/omdiscard.h0000644000000000000000000000013215141401300016002 xustar0030 mtime=1770390208.969869851 30 atime=1787067618.304442748 30 ctime=1787067795.260741193 rsyslog-8.2608.0/tools/omdiscard.h0000664000175000017500000000240715141401300015451 0ustar00rgerrger/* omdiscard.h * These are the definitions for the built-in discard output module. * * File begun on 2007-07-24 by RGerhards * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OMDISCARD_H_INCLUDED #define OMDISCARD_H_INCLUDED 1 /* prototypes */ rsRetVal modInitDiscard(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef OMDISCARD_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/smtradfile.c0000644000000000000000000000013215132411300016163 xustar0030 mtime=1768559296.305886257 30 atime=1787067622.101513546 30 ctime=1787067795.271741398 rsyslog-8.2608.0/tools/smtradfile.c0000666000175000017500000000740215132411300015634 0ustar00rgerrger/* smtradfile.c * This is a strgen module for the traditional file format. * * Format generated: * "%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2010-06-01 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "unicode-helper.h" MODULE_TYPE_STRGEN MODULE_TYPE_NOKEEP; STRGEN_NAME("RSYSLOG_TraditionalFileFormat") /* internal structures */ DEF_SMOD_STATIC_DATA; /* config data */ /* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings * needed (including their length) and then calculating the actual space required. So when we * finally copy, we know exactly what we need. So we do at most one alloc. */ BEGINstrgen register int iBuf; uchar *pTimeStamp; uchar *pHOSTNAME; size_t lenHOSTNAME; uchar *pTAG; int lenTAG; uchar *pMSG; size_t lenMSG; size_t lenTotal; CODESTARTstrgen; /* first obtain all strings and their length (if not fixed) */ pTimeStamp = (uchar *)getTimeReported(pMsg, tplFmtRFC3164Date); pHOSTNAME = (uchar *)getHOSTNAME(pMsg); lenHOSTNAME = getHOSTNAMELen(pMsg); getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX); pMSG = getMSG(pMsg); lenMSG = getMSGLen(pMsg); /* calculate len, constants for spaces and similar fixed strings */ lenTotal = CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 2; if (pMSG[0] != ' ') ++lenTotal; /* then we need to introduce one additional space */ /* now make sure buffer is large enough */ if (lenTotal >= iparam->lenBuf) CHKiRet(ExtendBuf(iparam, lenTotal)); /* and concatenate the resulting string */ memcpy(iparam->param, pTimeStamp, CONST_LEN_TIMESTAMP_3164); iparam->param[CONST_LEN_TIMESTAMP_3164] = ' '; memcpy(iparam->param + CONST_LEN_TIMESTAMP_3164 + 1, pHOSTNAME, lenHOSTNAME); iBuf = CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pTAG, lenTAG); iBuf += lenTAG; if (pMSG[0] != ' ') iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pMSG, lenMSG); iBuf += lenMSG; /* trailer */ iparam->param[iBuf++] = '\n'; iparam->param[iBuf] = '\0'; iparam->lenStr = lenTotal - 1; /* do not count \0! */ finalize_it: ENDstrgen BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_SMOD_QUERIES; ENDqueryEtryPt BEGINmodInit(smtradfile) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf("traditional file format strgen init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/fuzz_rsyslog_message.c0000644000000000000000000000013215241075234020332 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.697580017 30 ctime=1787067795.294741826 rsyslog-8.2608.0/tools/fuzz_rsyslog_message.c0000664000175000017500000000457715241075234020013 0ustar00rgerrger/* * Exercise the real PRI, RFC 3164, and RFC 5424 parser implementations with * arbitrary byte strings. Each parser receives an independent message so one * parser's field mutations cannot mask failures in the other. */ #include "config.h" #include #include #include #include #include #include #include "rsyslog.h" #include "msg.h" #include "parser.h" #include "pmrfc3164.h" #include "pmrfc5424.h" #include "rsconf.h" DEFobjCurrIf(obj); static void fuzzAbortOnError(const rsRetVal ret) { if (ret != RS_RET_OK) abort(); } static void fuzzCleanup(void) { pmrfc5424FuzzExit(); pmrfc3164FuzzExit(); fuzzAbortOnError(rsrtExit()); } static void fuzzOneParser(const uint8_t *data, const size_t size, rsRetVal (*parseFn)(smsg_t *)) { smsg_t *msg = NULL; rsRetVal ret; fuzzAbortOnError(msgConstruct(&msg)); MsgSetRawMsg(msg, (const char *)data, size); msg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; fuzzAbortOnError(parserParsePRI(msg)); ret = parseFn(msg); if (ret == RS_RET_OK) { if (msg->offAfterPRI < 0 || msg->offAfterPRI > msg->iLenRawMsg || msg->offMSG < 0 || msg->offMSG > msg->iLenRawMsg) { abort(); } } fuzzAbortOnError(msgDestruct(&msg)); } int LLVMFuzzerInitialize(int *argc, char ***argv); int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); int LLVMFuzzerInitialize(int *argc __attribute__((unused)), char ***argv) { const char *errObj = "rsyslog runtime"; const char *slash; static char modulePath[PATH_MAX]; int len; slash = strrchr((*argv)[0], '/'); if (slash == NULL) { len = snprintf(modulePath, sizeof(modulePath), "runtime/.libs"); } else { len = snprintf(modulePath, sizeof(modulePath), "%.*s/../runtime/.libs", (int)(slash - (*argv)[0]), (*argv)[0]); } if (len < 0 || (size_t)len >= sizeof(modulePath) || setenv("RSYSLOG_MODDIR", modulePath, 1) != 0) abort(); fuzzAbortOnError(rsrtInit(&errObj, &obj)); fuzzAbortOnError(pmrfc3164FuzzInit()); fuzzAbortOnError(pmrfc5424FuzzInit()); if (atexit(fuzzCleanup) != 0) abort(); return 0; } int LLVMFuzzerTestOneInput(const uint8_t *data, const size_t size) { if (size > INT_MAX) return 0; fuzzOneParser(data, size, pmrfc3164FuzzParse); fuzzOneParser(data, size, pmrfc5424FuzzParse); return 0; } rsyslog-8.2608.0/tools/PaxHeaders/omfwd.c0000644000000000000000000000013215241075234015162 xustar0030 mtime=1787067036.651579156 30 atime=1787067036.803582002 30 ctime=1787067795.243740876 rsyslog-8.2608.0/tools/omfwd.c0000664000175000017500000035654715241075234014652 0ustar00rgerrger/* omfwd.c * This is the implementation of the build-in forwarding output module. * * NOTE: read comments in module-template.h to understand how this file * works! * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_LIBZSTD #include #endif #include #include #include #include #ifndef MAXDNAME #define MAXDNAME 1025 #endif #include "rsyslog.h" #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "net.h" #include "netstrms.h" #include "netstrm.h" #include "omfwd.h" #include "template.h" #include "msg.h" #include "action.h" #include "tcpclt.h" #include "cfsysline.h" #include "module-template.h" #include "glbl.h" #include "rsconf.h" #include "errmsg.h" #include "unicode-helper.h" #include "parserif.h" #include "ratelimit.h" #include "statsobj.h" #include "datetime.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omfwd") /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(netstrms) DEFobjCurrIf(netstrm) DEFobjCurrIf(tcpclt) DEFobjCurrIf(statsobj) DEFobjCurrIf(datetime) /* some local constants (just) for better readybility */ #define IS_FLUSH 1 #define NO_FLUSH 0 typedef struct _targetStats { statsobj_t *stats; intctr_t sentBytes; intctr_t sentMsgs; intctr_t numConnects; DEF_ATOMIC_HELPER_MUT64(mut_sentBytes); DEF_ATOMIC_HELPER_MUT64(mut_sentMsgs); DEF_ATOMIC_HELPER_MUT64(mut_numConnects); } targetStats_t; typedef struct _instanceData { uchar *tplName; /* name of assigned template */ action_t *pAction; uchar *pszStrmDrvr; uchar *pszStrmDrvrAuthMode; uchar *pszStrmDrvrPermitExpiredCerts; uchar *pszStrmDrvrRemoteSNI; /* Optional TLS SNI to use for the remote server (instead of its hostname) */ permittedPeers_t *pPermPeers; int iStrmDrvrMode; sbool bStrmDrvrModeSet; int iStrmDrvrExtendedCertCheck; /* verify also purpose OID in certificate extended field */ int iStrmDrvrSANPreference; /* ignore CN when any SAN set */ int iStrmTlsVerifyDepth; /**< Verify Depth for certificate chains */ const uchar *pszStrmDrvrCAFile; const uchar *pszStrmDrvrCRLFile; const uchar *pszStrmDrvrCAExtraFiles; const uchar *pszStrmDrvrKeyFile; const uchar *pszStrmDrvrCertFile; int nTargets; int nActiveTargets; /* how many targets have been active the last time? */ DEF_ATOMIC_HELPER_MUT(mut_nActiveTargets); char **target_name; char *targetSrv; int nPorts; char **ports; char *address; char *device; int compressionLevel; /* 0 - no compression, else level for zlib */ #define COMPRESS_DRIVER_ZLIB 0 #define COMPRESS_DRIVER_ZSTD 1 uint8_t compressionDriver; int protocol; char *networkNamespace; int originalNamespace; int iRebindInterval; /* rebind interval */ sbool bKeepAlive; int iKeepAliveIntvl; int iKeepAliveProbes; int iKeepAliveTime; int tcp_user_timeout_ms; int iConErrSkip; /* skipping excessive connection errors */ uchar *gnutlsPriorityString; int ipfreebind; #define FORW_UDP 0 #define FORW_TCP 1 /* following fields for UDP-based delivery */ int bSendToAll; int iUDPSendDelay; int UDPSendBuf; /* following fields for TCP-based delivery */ TCPFRAMINGMODE tcp_framing; uchar tcp_framingDelimiter; int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */ int bExtendedConnCheck; /* do extended connection checking? */ #define COMPRESS_NEVER 0 #define COMPRESS_SINGLE_MSG 1 /* old, single-message compression */ /* all other settings are for stream-compression */ #define COMPRESS_STREAM_ALWAYS 2 uint8_t compressionMode; sbool strmCompFlushOnTxEnd; /* flush stream compression on transaction end? */ unsigned poolResumeInterval; int ratelimitInterval; int ratelimitBurst; uchar *pszRatelimitName; ratelimit_t *ratelimiter; targetStats_t *target_stats; } instanceData; typedef struct targetData { instanceData *pData; struct wrkrInstanceData *pWrkrData; /* forward def of struct */ netstrms_t *pNS; /* netstream subsystem */ netstrm_t *pNetstrm; /* our output netstream */ char *target_name; char *port; struct addrinfo *f_addr; int *pSockArray; /* sockets to use for UDP */ int bIsConnected; /* are we connected to remote host? 0 - no, 1 - yes, UDP means addr resolved */ int nXmit; /* number of transmissions since last (re-)bind */ tcpclt_t *pTCPClt; /* our tcpclt object */ sbool bInDestruct; /* guard against recursive teardown on send failure */ sbool bzInitDone; /* did we do an init of zstrm already? */ z_stream zstrm; /* zip stream to use for tcp compression */ #ifdef ENABLE_LIBZSTD ZSTD_CCtx *zstdCctx; #endif /* we know int is sufficient, as we have the fixed buffer size above! so no need for size_t */ int maxLenSndBuf; /* max usable length of sendbuf - primarily for testing */ int offsSndBuf; /* next free spot in send buffer */ time_t ttResume; targetStats_t *pTargetStats; /* sndBuf buffer size is intensionally fixed -- see no good reason to make configurable */ #define SNDBUF_FIXED_BUFFER_SIZE (16 * 1024) uchar sndBuf[SNDBUF_FIXED_BUFFER_SIZE]; } targetData_t; typedef struct wrkrInstanceData { instanceData *pData; targetData_t *target; int nXmit; /* number of transmissions since last (re-)bind */ unsigned actualTarget; unsigned wrkrID; /* an internal monotonically increasing id for correlating worker messages */ } wrkrInstanceData_t; static unsigned wrkrID = 0; /* config data */ typedef struct configSettings_s { uchar *pszTplName; /* name of the default template to use */ uchar *pszStrmDrvr; /* name of the stream driver to use */ int iStrmDrvrMode; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */ sbool bStrmDrvrModeSet; /* stream driver mode was explicitly configured */ int bResendLastOnRecon; /* should the last message be re-sent on a successful reconnect? */ uchar *pszStrmDrvrAuthMode; /* authentication mode to use */ uchar *pszStrmDrvrPermitExpiredCerts; /* control how to handly expired certificates */ uchar *pszStrmDrvrRemoteSNI; /* Optional TLS SNI to use for the remote server (instead of its hostname) */ int iTCPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */ int iUDPRebindInterval; /* support for automatic re-binding (load balancers!). 0 - no rebind */ int bKeepAlive; int iKeepAliveIntvl; int iKeepAliveProbes; int iKeepAliveTime; int iConErrSkip; uchar *gnutlsPriorityString; permittedPeers_t *pPermPeers; } configSettings_t; static configSettings_t cs; /* tables for interfacing with the v6 config system */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"iobuffer.maxsize", eCmdHdlrNonNegInt, 0}, {"template", eCmdHdlrGetWord, 0}, {"streamdriver.cafile", eCmdHdlrString, 0}, {"streamdriver.crlfile", eCmdHdlrString, 0}, {"streamdriver.caextrafiles", eCmdHdlrString, 0}, {"streamdriver.keyfile", eCmdHdlrString, 0}, {"streamdriver.certfile", eCmdHdlrString, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"target", eCmdHdlrArray, 0}, {"targetsrv", eCmdHdlrGetWord, 0}, {"address", eCmdHdlrGetWord, 0}, {"device", eCmdHdlrGetWord, 0}, {"port", eCmdHdlrArray, 0}, {"protocol", eCmdHdlrGetWord, 0}, {"networknamespace", eCmdHdlrGetWord, 0}, {"tcp_framing", eCmdHdlrGetWord, 0}, {"tcp_framedelimiter", eCmdHdlrInt, 0}, {"ziplevel", eCmdHdlrInt, 0}, {"compression.mode", eCmdHdlrGetWord, 0}, {"compression.driver", eCmdHdlrGetWord, 0}, {"compression.stream.flushontxend", eCmdHdlrBinary, 0}, {"ipfreebind", eCmdHdlrInt, 0}, {"maxerrormessages", eCmdHdlrInt, CNFPARAM_DEPRECATED}, {"rebindinterval", eCmdHdlrInt, 0}, {"keepalive", eCmdHdlrBinary, 0}, {"keepalive.probes", eCmdHdlrNonNegInt, 0}, {"keepalive.time", eCmdHdlrNonNegInt, 0}, {"keepalive.interval", eCmdHdlrNonNegInt, 0}, {"tcp_user_timeout", eCmdHdlrNonNegInt, 0}, {"conerrskip", eCmdHdlrNonNegInt, 0}, {"gnutlsprioritystring", eCmdHdlrString, 0}, {"streamdriver", eCmdHdlrGetWord, 0}, {"streamdriver.name", eCmdHdlrGetWord, 0}, /* alias for streamdriver */ {"streamdrivermode", eCmdHdlrInt, 0}, {"streamdriver.mode", eCmdHdlrInt, 0}, /* alias for streamdrivermode */ {"streamdriverauthmode", eCmdHdlrGetWord, 0}, {"streamdriver.authmode", eCmdHdlrGetWord, 0}, /* alias for streamdriverauthmode */ {"streamdriverpermittedpeers", eCmdHdlrGetWord, 0}, {"streamdriver.permitexpiredcerts", eCmdHdlrGetWord, 0}, {"streamdriverremotesni", eCmdHdlrString, 0}, {"streamdriver.remotesni", eCmdHdlrString, 0}, {"streamdriver.CheckExtendedKeyPurpose", eCmdHdlrBinary, 0}, {"streamdriver.PrioritizeSAN", eCmdHdlrBinary, 0}, {"streamdriver.TlsVerifyDepth", eCmdHdlrPositiveInt, 0}, {"streamdriver.cafile", eCmdHdlrString, 0}, {"streamdriver.crlfile", eCmdHdlrString, 0}, {"streamdriver.caextrafiles", eCmdHdlrString, 0}, {"streamdriver.keyfile", eCmdHdlrString, 0}, {"streamdriver.certfile", eCmdHdlrString, 0}, {"resendlastmsgonreconnect", eCmdHdlrBinary, 0}, {"extendedconnectioncheck", eCmdHdlrBinary, 0}, {"udp.sendtoall", eCmdHdlrBinary, 0}, {"udp.senddelay", eCmdHdlrInt, 0}, {"udp.sendbuf", eCmdHdlrSize, 0}, {"template", eCmdHdlrGetWord, 0}, {"pool.resumeinterval", eCmdHdlrPositiveInt, 0}, {"ratelimit.interval", eCmdHdlrInt, 0}, {"ratelimit.burst", eCmdHdlrInt, 0}, {"ratelimit.name", eCmdHdlrString, 0}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ uchar *tplName; /* default template */ uchar *pszStrmDrvrCAFile; /* module default CA file or URI */ uchar *pszStrmDrvrCRLFile; /* module default CRL file or URI */ uchar *pszStrmDrvrCAExtraFiles; /* module default extra CA files or URIs */ uchar *pszStrmDrvrKeyFile; /* module default private key file or URI */ uchar *pszStrmDrvrCertFile; /* module default certificate file or URI */ int maxLenSndBuf; /* default max usable length of sendbuf - primarily for testing */ }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ static rsRetVal initTCP(wrkrInstanceData_t *pWrkrData); BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars; cs.pszTplName = NULL; /* name of the default template to use */ cs.pszStrmDrvr = NULL; /* name of the stream driver to use */ cs.iStrmDrvrMode = 0; /* mode for stream driver, driver-dependent (0 mostly means plain tcp) */ cs.bStrmDrvrModeSet = 0; cs.bResendLastOnRecon = 0; /* should the last message be re-sent on a successful reconnect? */ cs.pszStrmDrvrAuthMode = NULL; /* authentication mode to use */ cs.pszStrmDrvrRemoteSNI = NULL; /* Remote TLS SNI to use instead of hostname */ cs.iUDPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */ cs.iTCPRebindInterval = 0; /* support for automatic re-binding (load balancers!). 0 - no rebind */ cs.pPermPeers = NULL; ENDinitConfVars static rsRetVal doTryResume(targetData_t *); static rsRetVal doCompressionFinish(targetData_t *); static rsRetVal TCPSendBuf(targetData_t *, uchar *, unsigned, sbool); /* this function gets the default template. It coordinates action between * old-style and new-style configuration parts. */ static uchar *getDfltTpl(void) { if (loadModConf != NULL && loadModConf->tplName != NULL) return loadModConf->tplName; else if (cs.pszTplName == NULL) return (uchar *)"RSYSLOG_TraditionalForwardFormat"; else return cs.pszTplName; } /** * @brief Check whether the effective netstream driver selects the OpenSSL * driver. * @param drvr Effective netstream driver name, or NULL. * @return Non-zero when the effective driver is ``ossl``. */ static int isOsslNetstrmDrvr(const uchar *const drvr) { return drvr != NULL && !strcasecmp((const char *)drvr, "ossl"); } /** * @brief Check whether a TLS object reference uses a strict PKCS#11 URI. * @param ref TLS object reference string, or NULL. * @return Non-zero when the reference begins with ``pkcs11:``. */ static int isPkcs11UriRef(const uchar *const ref) { return ref != NULL && !strncasecmp((const char *)ref, "pkcs11:", sizeof("pkcs11:") - 1); } /** * @brief Copy a module-scope TLS object default into an action instance. * * The destination is updated only when the action instance did not already set * the corresponding parameter. This preserves the precedence order of action * setting over module default over global netstream default. */ static rsRetVal ATTR_NONNULL(1) copyModuleTlsDefaultIfUnset(uchar **const ppDst, const uchar *const pSrc) { DEFiRet; if (*ppDst == NULL && pSrc != NULL) { CHKmalloc(*ppDst = ustrdup(pSrc)); } finalize_it: RETiRet; } /** * @brief Apply builtin:omfwd module TLS defaults to an action instance. * * This fills in any unset CA, CRL, key, and certificate references from the * current omfwd module configuration, leaving explicitly configured action * values untouched. Global netstream defaults remain the final fallback in the * driver when both action and module settings are absent. * * Module defaults are applied only when the effective stream driver supports * the corresponding setting. Ordinary filesystem-backed TLS defaults remain * available to every TLS-capable driver, but strict ``pkcs11:`` URI defaults * are inherited only by ``ossl`` actions. This preserves mixed deployments * where ``builtin:omfwd`` provides shared TLS defaults for encrypted * forwarding actions, while other omfwd actions in the same configuration * still use plain TCP or another TLS driver that cannot resolve PKCS#11 * objects. Explicit action parameters remain untouched so unsupported * action-level settings still fail in the selected driver instead of being * silently ignored. */ static rsRetVal ATTR_NONNULL() applyModuleTlsDefaults(instanceData *const pData, const modConfData_t *const pModConf) { DEFiRet; const uchar *const effectiveDrvr = glblGetEffectiveNetstrmDrvr(pModConf->pConf, pData->pszStrmDrvr); const int tlsCapable = glblIsTlsCapableNetstrmDrvr(effectiveDrvr); const int osslDriver = isOsslNetstrmDrvr(effectiveDrvr); if (tlsCapable) { if (!isPkcs11UriRef(pModConf->pszStrmDrvrCAFile) || osslDriver) { CHKiRet(copyModuleTlsDefaultIfUnset((uchar **)&pData->pszStrmDrvrCAFile, pModConf->pszStrmDrvrCAFile)); } if (!isPkcs11UriRef(pModConf->pszStrmDrvrCRLFile)) { CHKiRet(copyModuleTlsDefaultIfUnset((uchar **)&pData->pszStrmDrvrCRLFile, pModConf->pszStrmDrvrCRLFile)); } if (!isPkcs11UriRef(pModConf->pszStrmDrvrKeyFile) || osslDriver) { CHKiRet(copyModuleTlsDefaultIfUnset((uchar **)&pData->pszStrmDrvrKeyFile, pModConf->pszStrmDrvrKeyFile)); } if (!isPkcs11UriRef(pModConf->pszStrmDrvrCertFile) || osslDriver) { CHKiRet(copyModuleTlsDefaultIfUnset((uchar **)&pData->pszStrmDrvrCertFile, pModConf->pszStrmDrvrCertFile)); } } if (osslDriver) { CHKiRet( copyModuleTlsDefaultIfUnset((uchar **)&pData->pszStrmDrvrCAExtraFiles, pModConf->pszStrmDrvrCAExtraFiles)); } finalize_it: RETiRet; } /* set the default template to be used * This is a module-global parameter, and as such needs special handling. It needs to * be coordinated with values set via the v2 config system (rsyslog v6+). What we do * is we do not permit this directive after the v2 config system has been used to set * the parameter. */ static rsRetVal setLegacyDfltTpl(void __attribute__((unused)) * pVal, uchar *newVal) { DEFiRet; if (loadModConf != NULL && loadModConf->tplName != NULL) { free(newVal); LogError(0, RS_RET_ERR, "omfwd default template already set via module " "global parameter - can no longer be changed"); ABORT_FINALIZE(RS_RET_ERR); } free(cs.pszTplName); cs.pszTplName = newVal; finalize_it: RETiRet; } typedef struct srvRecord_s { char host[MAXDNAME]; uint16_t port; uint16_t priority; uint16_t weight; } srvRecord_t; static void freeConfiguredPorts(instanceData *const pData) { if (pData->ports != NULL) { for (int j = 0; j < pData->nPorts; ++j) { free(pData->ports[j]); } free(pData->ports); } pData->ports = NULL; pData->nPorts = 0; } #ifdef HAVE_RESOLV_NS_INITPARSE static int compareSrvPriority(const void *lhs, const void *rhs) { const srvRecord_t *const left = (const srvRecord_t *)lhs; const srvRecord_t *const right = (const srvRecord_t *)rhs; if (left->priority == right->priority) return 0; return (left->priority < right->priority) ? -1 : 1; } static rsRetVal buildSrvTargets(instanceData *const pData, const srvRecord_t *const ordered, const unsigned recCount) { unsigned allocated = 0; DEFiRet; pData->nTargets = (int)recCount; pData->nPorts = (int)recCount; CHKmalloc(pData->target_name = (char **)calloc(recCount, sizeof(char *))); CHKmalloc(pData->ports = (char **)calloc(recCount, sizeof(char *))); for (unsigned i = 0; i < recCount; ++i) { char portBuf[16]; if (snprintf(portBuf, sizeof(portBuf), "%u", (unsigned)ordered[i].port) >= (int)sizeof(portBuf)) { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: SRV-discovered port for %s exceeds buffer length", ordered[i].host); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } pData->target_name[i] = strdup(ordered[i].host); if (pData->target_name[i] == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pData->ports[i] = strdup(portBuf); if (pData->ports[i] == NULL) { free(pData->target_name[i]); pData->target_name[i] = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } ++allocated; } finalize_it: if (iRet != RS_RET_OK) { if (pData->target_name != NULL) { for (unsigned j = 0; j < allocated; ++j) { free(pData->target_name[j]); } free(pData->target_name); pData->target_name = NULL; } if (pData->ports != NULL) { for (unsigned j = 0; j < allocated; ++j) { free(pData->ports[j]); } free(pData->ports); pData->ports = NULL; } pData->nTargets = 0; pData->nPorts = 0; } RETiRet; } static const char *resolverErrorString(const int err) { switch (err) { case HOST_NOT_FOUND: return "host not found"; case TRY_AGAIN: return "temporary resolver failure"; case NO_RECOVERY: return "unrecoverable resolver failure"; case NO_DATA: return "no data"; #if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_ADDRESS != NO_DATA)) case NO_ADDRESS: return "no address"; #endif default: return "unknown resolver error"; } } static rsRetVal initResolverState(res_state *const pres) { DEFiRet; #ifdef HAVE_RESOLV_RES_N_API CHKmalloc(*pres = (res_state)calloc(1, sizeof(struct __res_state))); if (res_ninit(*pres) != 0) { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: failed to init resolver state: %s", strerror(errno)); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } #else if (res_init() != 0) { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: failed to init resolver state: %s", strerror(errno)); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } *pres = &_res; #endif finalize_it: RETiRet; } static int queryResolverState(res_state const res, const char *const srvName, unsigned char *const answer, const size_t answerSize) { #ifdef HAVE_RESOLV_RES_N_API return res_nquery(res, srvName, ns_c_in, ns_t_srv, answer, answerSize); #else (void)res; return res_query(srvName, ns_c_in, ns_t_srv, answer, answerSize); #endif } static void closeResolverState(res_state const res) { if (res == NULL) { return; } #ifdef HAVE_RESOLV_RES_N_API res_nclose(res); free(res); #else /* Old resolver APIs use global state; musl's implementation is stateless. */ (void)res; #endif } static rsRetVal applyResolverOverrides(res_state res) { const char *const dnsServerEnv = getenv("RSYSLOG_DNS_SERVER"); const char *const dnsPortEnv = getenv("RSYSLOG_DNS_PORT"); const char *dnsServer = dnsServerEnv; uint16_t dnsPort = 53; const sbool hasDnsPort = (dnsPortEnv != NULL && *dnsPortEnv != '\0'); DEFiRet; if (dnsServer == NULL && dnsPortEnv == NULL) { return RS_RET_OK; } if (hasDnsPort) { char *endptr = NULL; const unsigned long port = strtoul(dnsPortEnv, &endptr, 10); if (dnsPortEnv == endptr || *endptr != '\0' || port == 0 || port > 65535) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: RSYSLOG_DNS_PORT must be an integer from 1 to 65535 (got '%s')", dnsPortEnv); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } dnsPort = (uint16_t)port; } if (dnsServer != NULL && *dnsServer == '\0') { LogError(0, RS_RET_PARAM_ERROR, "omfwd: RSYSLOG_DNS_SERVER must be set to an IPv4 address, not an empty string"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (dnsServer == NULL) { if (hasDnsPort) { if (res->nscount == 0) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: RSYSLOG_DNS_PORT set but resolver has no configured nameservers"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } for (int idx = 0; idx < res->nscount; ++idx) { res->nsaddr_list[idx].sin_port = htons(dnsPort); } } return RS_RET_OK; } struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(dnsPort); if (inet_pton(AF_INET, dnsServer, &addr.sin_addr) != 1) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: RSYSLOG_DNS_SERVER must be an IPv4 address (got '%s')", dnsServer); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } res->nsaddr_list[0] = addr; res->nscount = 1; finalize_it: RETiRet; } #endif static rsRetVal resolveSrvTargets(instanceData *const pData) { #ifndef HAVE_RESOLV_NS_INITPARSE (void)pData; LogError(0, RS_RET_NOT_IMPLEMENTED, "omfwd: DNS SRV lookup is not available (resolver support missing)"); return RS_RET_NOT_IMPLEMENTED; #else unsigned char answer[4096]; srvRecord_t *records = NULL; srvRecord_t *ordered = NULL; res_state res = NULL; unsigned recCount = 0; unsigned recCap = 0; DEFiRet; const char *const proto = (pData->protocol == FORW_TCP) ? "tcp" : "udp"; char srvName[2 * MAXDNAME]; if (snprintf(srvName, sizeof(srvName), "_syslog._%s.%s", proto, pData->targetSrv) >= (int)sizeof(srvName)) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: targetSrv value '%s' is too long", pData->targetSrv); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKiRet(initResolverState(&res)); CHKiRet(applyResolverOverrides(res)); const int ansLen = queryResolverState(res, srvName, answer, sizeof(answer)); if (ansLen < 0) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: failed to resolve SRV records for '%s': %s", srvName, resolverErrorString(res->res_h_errno)); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } ns_msg handle; if (ns_initparse(answer, ansLen, &handle) != 0) { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: failed to parse SRV response for '%s'", srvName); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } const int ancount = ns_msg_count(handle, ns_s_an); for (int i = 0; i < ancount; ++i) { ns_rr rr; if (ns_parserr(&handle, ns_s_an, i, &rr) != 0) continue; if (ns_rr_type(rr) != ns_t_srv || ns_rr_rdlen(rr) < 6) continue; char targetName[MAXDNAME]; if (ns_name_uncompress(ns_msg_base(handle), ns_msg_end(handle), ns_rr_rdata(rr) + 6, targetName, sizeof(targetName)) < 0) { continue; } srvRecord_t record; memset(&record, 0, sizeof(record)); record.priority = ns_get16(ns_rr_rdata(rr)); record.weight = ns_get16(ns_rr_rdata(rr) + 2); record.port = ns_get16(ns_rr_rdata(rr) + 4); size_t hostLen = strlen(targetName); if (hostLen > 0 && targetName[hostLen - 1] == '.') { targetName[hostLen - 1] = '\0'; --hostLen; } if (hostLen >= sizeof(record.host)) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: SRV target name '%s' exceeds supported length", targetName); continue; } memcpy(record.host, targetName, hostLen + 1); if (recCount == recCap) { const unsigned nextCap = (recCap == 0) ? 4 : (recCap * 2); srvRecord_t *const tmp = (srvRecord_t *)realloc(records, nextCap * sizeof(srvRecord_t)); if (tmp == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } records = tmp; recCap = nextCap; } records[recCount++] = record; } if (recCount == 0) { LogError(0, RS_RET_NOT_FOUND, "omfwd: no usable SRV records found for '%s'", srvName); ABORT_FINALIZE(RS_RET_NOT_FOUND); } qsort(records, recCount, sizeof(srvRecord_t), compareSrvPriority); CHKmalloc(ordered = (srvRecord_t *)calloc(recCount, sizeof(srvRecord_t))); unsigned outIdx = 0; for (unsigned idx = 0; idx < recCount;) { const uint16_t priority = records[idx].priority; unsigned grpStart = idx; while (idx < recCount && records[idx].priority == priority) { ++idx; } const unsigned grpCount = idx - grpStart; /*!\brief Allocate per-priority usage bitmap during SRV ordering. * This runs once during config parsing, so the transient allocation is acceptable. */ unsigned char *used = NULL; CHKmalloc(used = (unsigned char *)calloc(grpCount, sizeof(unsigned char))); unsigned remaining = grpCount; uint32_t totalWeight = 0; for (unsigned j = 0; j < grpCount; ++j) { totalWeight += records[grpStart + j].weight; } if (grpCount > 1) { seedRandomNumber(); } while (remaining > 0) { unsigned selected = 0; if (totalWeight == 0) { const unsigned pick = (unsigned)((unsigned long)randomNumber() % remaining); unsigned seen = 0; for (unsigned j = 0; j < grpCount; ++j) { if (used[j]) continue; if (seen == pick) { selected = j; break; } ++seen; } } else { const uint32_t pick = (uint32_t)((unsigned long)randomNumber() % totalWeight); uint32_t running = 0; for (unsigned j = 0; j < grpCount; ++j) { if (used[j]) continue; running += records[grpStart + j].weight; if (pick < running) { selected = j; break; } } } ordered[outIdx++] = records[grpStart + selected]; used[selected] = 1; if (totalWeight > 0) { const uint32_t pickedWeight = records[grpStart + selected].weight; totalWeight = (pickedWeight >= totalWeight) ? 0 : (totalWeight - pickedWeight); } --remaining; } free(used); } CHKiRet(buildSrvTargets(pData, ordered, outIdx)); finalize_it: free(records); free(ordered); closeResolverState(res); RETiRet; #endif } static void DestructTargetData(targetData_t *const pTarget, const sbool bIsRebind) { if (pTarget->bInDestruct) { return; } pTarget->bInDestruct = RSTRUE; if (pTarget->bIsConnected && pTarget->offsSndBuf != 0) { rsRetVal localRet = TCPSendBuf(pTarget, pTarget->sndBuf, pTarget->offsSndBuf, IS_FLUSH); if (localRet == RS_RET_OK || localRet == RS_RET_DEFER_COMMIT || localRet == RS_RET_PREVIOUS_COMMITTED) { pTarget->offsSndBuf = 0; } } doCompressionFinish(pTarget); if (pTarget->pNetstrm != NULL) { netstrm.Destruct(&pTarget->pNetstrm); } if (pTarget->pNS != NULL) { netstrms.Destruct(&pTarget->pNS); } if (pTarget->pSockArray != NULL) { net.closeUDPListenSockets(pTarget->pSockArray); pTarget->pSockArray = NULL; } if (pTarget->f_addr != NULL) { freeaddrinfo(pTarget->f_addr); pTarget->f_addr = NULL; } if (bIsRebind) { pTarget->ttResume = 0; } else { /* set resume time for interal retries */ datetime.GetTime(&pTarget->ttResume); pTarget->ttResume += pTarget->pData->poolResumeInterval; } pTarget->bIsConnected = 0; pTarget->bInDestruct = RSFALSE; DBGPRINTF("omfwd: DestructTargetData: %p %s:%s, connected %d, ttResume %lld\n", pTarget, pTarget->target_name, pTarget->port, pTarget->bIsConnected, (long long)pTarget->ttResume); } /* destruct the helper objects * This, for example, is needed after something went wrong. * This function is void because it "can not" fail. * rgerhards, 2008-06-04 * Note that we DO NOT discard the current buffer contents * (if any). This permits us to save data between sessions. In * the worst case, some duplication occurs, but we do not * loose data. */ static void DestructInstanceData(wrkrInstanceData_t *pWrkrData, const sbool bIsRebind) { LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: Destructing target pool of %d targets (DestructInstanceData)", pWrkrData->pData->nTargets); for (int j = 0; j < pWrkrData->pData->nTargets; ++j) { DestructTargetData(&(pWrkrData->target[j]), bIsRebind); } } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; pModConf->tplName = NULL; pModConf->pszStrmDrvrCAFile = NULL; pModConf->pszStrmDrvrCRLFile = NULL; pModConf->pszStrmDrvrCAExtraFiles = NULL; pModConf->pszStrmDrvrKeyFile = NULL; pModConf->pszStrmDrvrCertFile = NULL; pModConf->maxLenSndBuf = -1; ENDbeginCnfLoad BEGINsetModCnf int i; CODESTARTsetModCnf; const struct cnfparamvals *const __restrict__ pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for omfwd:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "template")) { CHKmalloc(loadModConf->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (cs.pszTplName != NULL) { LogError(0, RS_RET_DUP_PARAM, "omfwd: warning: default template " "was already set via legacy directive - may lead to inconsistent " "results."); } } else if (!strcmp(modpblk.descr[i].name, "iobuffer.maxsize")) { const int newLen = (int)pvals[i].val.d.n; if (newLen > SNDBUF_FIXED_BUFFER_SIZE) { LogMsg(0, RS_RET_PARAM_ERROR, LOG_WARNING, "omfwd: module parameter \"iobuffer.maxsize\" specified larger " "than actual buffer size (%d bytes) - ignored", SNDBUF_FIXED_BUFFER_SIZE); } else { if (newLen > 0) { loadModConf->maxLenSndBuf = newLen; } } } else if (!strcmp(modpblk.descr[i].name, "streamdriver.cafile")) { free(loadModConf->pszStrmDrvrCAFile); CHKmalloc(loadModConf->pszStrmDrvrCAFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "streamdriver.crlfile")) { free(loadModConf->pszStrmDrvrCRLFile); CHKmalloc(loadModConf->pszStrmDrvrCRLFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "streamdriver.caextrafiles")) { free(loadModConf->pszStrmDrvrCAExtraFiles); CHKmalloc(loadModConf->pszStrmDrvrCAExtraFiles = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "streamdriver.keyfile")) { free(loadModConf->pszStrmDrvrKeyFile); CHKmalloc(loadModConf->pszStrmDrvrKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "streamdriver.certfile")) { free(loadModConf->pszStrmDrvrCertFile); CHKmalloc(loadModConf->pszStrmDrvrCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_ERR, "omfwd: internal error, non-handled param '%s' in beginCnfLoad", modpblk.descr[i].name); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; /* done loading */ /* free legacy config vars */ free(cs.pszTplName); cs.pszTplName = NULL; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(pModConf->tplName); free(pModConf->pszStrmDrvrCAFile); free(pModConf->pszStrmDrvrCRLFile); free(pModConf->pszStrmDrvrCAExtraFiles); free(pModConf->pszStrmDrvrKeyFile); free(pModConf->pszStrmDrvrCertFile); ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; /* We always have at least one target and port */ pData->nTargets = 1; pData->nActiveTargets = 0; INIT_ATOMIC_HELPER_MUT(pData->mut_nActiveTargets); pData->nPorts = 1; pData->target_name = NULL; if (cs.pszStrmDrvr != NULL) CHKmalloc(pData->pszStrmDrvr = (uchar *)strdup((char *)cs.pszStrmDrvr)); pData->bStrmDrvrModeSet = cs.bStrmDrvrModeSet; if (cs.pszStrmDrvrAuthMode != NULL) CHKmalloc(pData->pszStrmDrvrAuthMode = (uchar *)strdup((char *)cs.pszStrmDrvrAuthMode)); if (cs.pszStrmDrvrRemoteSNI != NULL) CHKmalloc(pData->pszStrmDrvrRemoteSNI = (uchar *)strdup((char *)cs.pszStrmDrvrRemoteSNI)); finalize_it: ENDcreateInstance /* Among others, all worker-specific targets are initialized here. */ BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; time_t ttNow; datetime.GetTime(&ttNow); ttNow--; /* make sure it is expired */ assert(pData->nTargets > 0); pWrkrData->actualTarget = 0; pWrkrData->wrkrID = wrkrID++; CHKmalloc(pWrkrData->target = (targetData_t *)calloc(pData->nTargets, sizeof(targetData_t))); for (int i = 0; i < pData->nTargets; ++i) { pWrkrData->target[i].pData = pWrkrData->pData; pWrkrData->target[i].pWrkrData = pWrkrData; pWrkrData->target[i].target_name = pData->target_name[i]; pWrkrData->target[i].pTargetStats = &(pData->target_stats[i]); /* if insufficient ports are configured, we use ports[0] for the * missing ports. */ pWrkrData->target[i].port = pData->ports[(i < pData->nPorts) ? i : 0]; pWrkrData->target[i].maxLenSndBuf = (runModConf->maxLenSndBuf == -1) ? SNDBUF_FIXED_BUFFER_SIZE : runModConf->maxLenSndBuf; pWrkrData->target[i].bInDestruct = RSFALSE; pWrkrData->target[i].offsSndBuf = 0; pWrkrData->target[i].ttResume = ttNow; } iRet = initTCP(pWrkrData); LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: worker with id %u initialized", pWrkrData->wrkrID); finalize_it: ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINsetActionInfo CODESTARTsetActionInfo; pData->pAction = pAction; ENDsetActionInfo /** * @brief Release all action-instance resources owned by an omfwd action. * * This includes transport-related configuration strings, dynamically * allocated target metadata, TLS object paths or URIs, and the optional * action-level template name used when building the output message stream. */ BEGINfreeInstance CODESTARTfreeInstance; free(pData->tplName); free(pData->pszStrmDrvr); free(pData->pszStrmDrvrAuthMode); free(pData->pszStrmDrvrPermitExpiredCerts); free(pData->pszStrmDrvrRemoteSNI); free(pData->gnutlsPriorityString); free(pData->targetSrv); free(pData->networkNamespace); if (pData->ports != NULL) { /* could happen in error case (very unlikely) */ for (int j = 0; j < pData->nPorts; ++j) { free(pData->ports[j]); } free(pData->ports); } if (pData->target_stats != NULL) { for (int j = 0; j < pData->nTargets; ++j) { free(pData->target_name[j]); if (pData->target_stats[j].stats != NULL) statsobj.Destruct(&(pData->target_stats[j].stats)); } free(pData->target_stats); } free(pData->target_name); free(pData->address); free(pData->device); free((void *)pData->pszStrmDrvrCAFile); free((void *)pData->pszStrmDrvrCRLFile); free((void *)pData->pszStrmDrvrCAExtraFiles); free((void *)pData->pszStrmDrvrKeyFile); free((void *)pData->pszStrmDrvrCertFile); free(pData->pszRatelimitName); net.DestructPermittedPeers(&pData->pPermPeers); if (pData->ratelimiter != NULL) { ratelimitDestruct(pData->ratelimiter); pData->ratelimiter = NULL; } DESTROY_ATOMIC_HELPER_MUT(pData->mut_nActiveTargets); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u/%" PRIuPTR "] Destructing worker instance", pWrkrData->wrkrID, (uintptr_t)pthread_self()); DestructInstanceData(pWrkrData, 0); if (pWrkrData->pData->protocol == FORW_TCP) { for (int i = 0; i < pWrkrData->pData->nTargets; ++i) { tcpclt.Destruct(&pWrkrData->target[i].pTCPClt); } } free(pWrkrData->target); /* note: this frees all target memory,calloc()ed array! */ ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; dbgprintf("omfwd\n"); ENDdbgPrintInstInfo /* Send a message via UDP * rgehards, 2007-12-20 */ #define UDP_MAX_MSGSIZE 65507 /* limit per RFC definition */ static rsRetVal UDPSend(wrkrInstanceData_t *__restrict__ const pWrkrData, uchar *__restrict__ const msg, size_t len) { DEFiRet; struct addrinfo *r; int i; ssize_t lsent = 0; sbool bSendSuccess; sbool reInit = RSFALSE; int lasterrno = ENOENT; int lasterr_sock = -1; targetData_t *const pTarget = &(pWrkrData->target[0]); targetStats_t *const pTargetStats = &(pWrkrData->pData->target_stats[0]); if (pWrkrData->pData->iRebindInterval && (pTarget->nXmit++ % pWrkrData->pData->iRebindInterval == 0)) { dbgprintf("omfwd dropping UDP 'connection' (as configured)\n"); pTarget->nXmit = 1; /* else we have an addtl wrap at 2^31-1 */ DestructTargetData(pTarget, 1); } if (pWrkrData->target[0].pSockArray == NULL) { CHKiRet(doTryResume(pTarget)); /* for UDP, we have only a single target! */ } if (pTarget->pSockArray == NULL) { FINALIZE; } if (len > UDP_MAX_MSGSIZE) { LogError(0, RS_RET_UDP_MSGSIZE_TOO_LARGE, "omfwd/udp: message is %u " "bytes long, but UDP can send at most %d bytes (by RFC limit) " "- truncating message", (unsigned)len, UDP_MAX_MSGSIZE); len = UDP_MAX_MSGSIZE; } /* we need to track if we have success sending to the remote * peer. Success is indicated by at least one sendto() call * succeeding. We track this be bSendSuccess. We can not simply * rely on lsent, as a call might initially work, but a later * call fails. Then, lsent has the error status, even though * the sendto() succeeded. -- rgerhards, 2007-06-22 */ bSendSuccess = RSFALSE; for (r = pTarget->f_addr; r; r = r->ai_next) { int runSockArrayLoop = 1; for (i = 0; runSockArrayLoop && (i < *pTarget->pSockArray); i++) { int try_send = 1; size_t lenThisTry = len; while (try_send) { int sendErrno; lsent = sendto(pTarget->pSockArray[i + 1], msg, lenThisTry, 0, r->ai_addr, r->ai_addrlen); sendErrno = errno; if (lsent == (ssize_t)lenThisTry) { bSendSuccess = RSTRUE; ATOMIC_ADD_uint64(&pTargetStats->sentBytes, &pTargetStats->mut_sentBytes, lenThisTry); try_send = 0; runSockArrayLoop = 0; } else if (sendErrno == EMSGSIZE) { const size_t newlen = (lenThisTry > 1024) ? lenThisTry - 1024 : 512; LogError(0, RS_RET_UDP_MSGSIZE_TOO_LARGE, "omfwd/udp: send failed due to message being too " "large for this system. Message size was %u bytes. " "Truncating to %u bytes and retrying.", (unsigned)lenThisTry, (unsigned)newlen); lenThisTry = newlen; } else { reInit = RSTRUE; lasterrno = sendErrno; lasterr_sock = pTarget->pSockArray[i + 1]; LogError(lasterrno, RS_RET_ERR_UDPSEND, "omfwd/udp: socket %d: sendto() error", lasterr_sock); try_send = 0; } } } if (lsent == (ssize_t)len && !pWrkrData->pData->bSendToAll) break; } /* one or more send failures; close sockets and re-init */ if (reInit == RSTRUE) { DestructTargetData(pTarget, 0); } /* finished looping */ if (bSendSuccess == RSTRUE) { if (pWrkrData->pData->iUDPSendDelay > 0) { srSleep(pWrkrData->pData->iUDPSendDelay / 1000000, pWrkrData->pData->iUDPSendDelay % 1000000); } } else { LogError(lasterrno, RS_RET_ERR_UDPSEND, "omfwd: socket %d: error %d sending via udp", lasterr_sock, lasterrno); iRet = RS_RET_SUSPENDED; } finalize_it: RETiRet; } /* set the permitted peers -- rgerhards, 2008-05-19 */ static rsRetVal setPermittedPeer(void __attribute__((unused)) * pVal, uchar *pszID) { DEFiRet; CHKiRet(net.AddPermittedPeer(&cs.pPermPeers, pszID)); free(pszID); /* no longer needed, but we must free it as of interface def */ finalize_it: RETiRet; } /* CODE FOR SENDING TCP MESSAGES */ /* This is a common function so that we can emit consistent error * messages whenever we have trouble with a connection, e.g. when * sending or checking if it's broken. */ static void emitConnectionErrorMsg(const targetData_t *const pTarget, const rsRetVal iRet) { wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; if (iRet == RS_RET_IO_ERROR || iRet == RS_RET_PEER_CLOSED_CONN) { static unsigned int conErrCnt = 0; const int skipFactor = pWrkrData->pData->iConErrSkip; const char *actualErrMsg; if (iRet == RS_RET_PEER_CLOSED_CONN) { actualErrMsg = "remote server closed connection. "; } else { actualErrMsg = "we had a generic or IO error with the remote server. " "The actual error message should already have been provided. "; } if (skipFactor <= 1) { /* All the connection errors are printed. */ LogError(0, iRet, "omfwd: [wrkr %u/%" PRIuPTR "] %s Server is %s:%s. " "This can be caused by the remote server or an interim system like a load " "balancer or firewall. Rsyslog will re-open the connection if configured " "to do so.", pTarget->pWrkrData->wrkrID, (uintptr_t)pthread_self(), actualErrMsg, pTarget->target_name, pTarget->port); } else if ((conErrCnt++ % skipFactor) == 0) { /* Every N'th error message is printed where N is a skipFactor. */ LogError(0, iRet, "omfwd: [wrkr %u] %s Server is %s:%s. " "This can be caused by the remote server or an interim system like a load " "balancer or firewall. Rsyslog will re-open the connection if configured " "to do so. Note that the next %d connection error messages will be " "skipped.", pTarget->pWrkrData->wrkrID, actualErrMsg, pTarget->target_name, pTarget->port, skipFactor - 1); } } else { LogError(0, iRet, "omfwd: TCPSendBuf error %d, destruct TCP Connection to %s:%s", iRet, pTarget->target_name, pTarget->port); } } /* hack to check connections for plain tcp syslog - see ptcp driver for details */ static rsRetVal CheckConnection(targetData_t *const pTarget) { DEFiRet; if ((pTarget->pData->protocol == FORW_TCP) && (pTarget->pData->bExtendedConnCheck)) { CHKiRet(netstrm.CheckConnection(pTarget->pNetstrm)); } finalize_it: if (iRet != RS_RET_OK) { emitConnectionErrorMsg(pTarget, iRet); if (!pTarget->bInDestruct) { DestructTargetData(pTarget, 0); } iRet = RS_RET_SUSPENDED; } RETiRet; } static rsRetVal TCPSendBufUncompressed(targetData_t *const pTarget, uchar *const buf, const unsigned len) { DEFiRet; unsigned alreadySent; ssize_t lenSend; alreadySent = 0; if (pTarget->pData->bExtendedConnCheck) { CHKiRet(netstrm.CheckConnection(pTarget->pNetstrm)); /* hack for plain tcp syslog - see ptcp driver for details */ } while (alreadySent != len) { lenSend = len - alreadySent; iRet = netstrm.Send(pTarget->pNetstrm, buf + alreadySent, &lenSend); if (iRet == RS_RET_RETRY) ABORT_FINALIZE(iRet); CHKiRet(iRet); DBGPRINTF("omfwd: TCP sent %zd bytes, requested %u\n", lenSend, len - alreadySent); alreadySent += lenSend; } ATOMIC_ADD_uint64(&pTarget->pTargetStats->sentBytes, &pTarget->pTargetStats->mut_sentBytes, len); finalize_it: if (iRet != RS_RET_OK) { if (iRet == RS_RET_RETRY) { DBGPRINTF("omfwd: TCP send deferred for retry\n"); } else { emitConnectionErrorMsg(pTarget, iRet); if (!pTarget->bInDestruct) { DestructTargetData(pTarget, 0); } iRet = RS_RET_SUSPENDED; } } RETiRet; } static rsRetVal TCPSendBufCompressedZlib(targetData_t *pTarget, uchar *const buf, unsigned len, sbool bIsFlush) { wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; int zRet; /* zlib return state */ unsigned outavail; uchar zipBuf[32 * 1024]; int op; DEFiRet; if (!pTarget->bzInitDone) { /* allocate deflate state */ pTarget->zstrm.zalloc = Z_NULL; pTarget->zstrm.zfree = Z_NULL; pTarget->zstrm.opaque = Z_NULL; /* see note in file header for the params we use with deflateInit2() */ zRet = deflateInit(&pTarget->zstrm, pWrkrData->pData->compressionLevel); if (zRet != Z_OK) { DBGPRINTF("error %d returned from zlib/deflateInit()\n", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pTarget->bzInitDone = RSTRUE; } /* now doing the compression */ pTarget->zstrm.next_in = (Bytef *)buf; pTarget->zstrm.avail_in = len; if (pWrkrData->pData->strmCompFlushOnTxEnd && bIsFlush) op = Z_SYNC_FLUSH; else op = Z_NO_FLUSH; /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("omfwd: in deflate() loop, avail_in %d, total_in %ld, isFlush %d\n", pTarget->zstrm.avail_in, pTarget->zstrm.total_in, bIsFlush); pTarget->zstrm.avail_out = sizeof(zipBuf); pTarget->zstrm.next_out = zipBuf; zRet = deflate(&pTarget->zstrm, op); /* no bad return value */ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pTarget->zstrm.avail_out); outavail = sizeof(zipBuf) - pTarget->zstrm.avail_out; if (outavail != 0) { CHKiRet(TCPSendBufUncompressed(pTarget, zipBuf, outavail)); } } while (pTarget->zstrm.avail_out == 0); finalize_it: RETiRet; } static rsRetVal TCPSendBufCompressedZstd(targetData_t *pTarget, uchar *const buf, unsigned len, sbool bIsFlush) { #ifdef ENABLE_LIBZSTD wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; uchar zipBuf[32 * 1024]; DEFiRet; if (!pTarget->bzInitDone) { pTarget->zstdCctx = ZSTD_createCCtx(); if (pTarget->zstdCctx == NULL) { LogError(0, RS_RET_ZLIB_ERR, "omfwd: error creating zstd compression context"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } size_t zRet = ZSTD_CCtx_setParameter(pTarget->zstdCctx, ZSTD_c_compressionLevel, pWrkrData->pData->compressionLevel); if (ZSTD_isError(zRet)) { LogError(0, RS_RET_ZLIB_ERR, "omfwd: error setting zstd compression level: %s", ZSTD_getErrorName(zRet)); ZSTD_freeCCtx(pTarget->zstdCctx); pTarget->zstdCctx = NULL; ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pTarget->bzInitDone = RSTRUE; } ZSTD_inBuffer input = {buf, len, 0}; const ZSTD_EndDirective op = (pWrkrData->pData->strmCompFlushOnTxEnd && bIsFlush) ? ZSTD_e_flush : ZSTD_e_continue; size_t remaining; do { ZSTD_outBuffer output = {zipBuf, sizeof(zipBuf), 0}; remaining = ZSTD_compressStream2(pTarget->zstdCctx, &output, &input, op); if (ZSTD_isError(remaining)) { LogError(0, RS_RET_ZLIB_ERR, "omfwd: error returned from ZSTD_compressStream2(): %s", ZSTD_getErrorName(remaining)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (output.pos != 0) { CHKiRet(TCPSendBufUncompressed(pTarget, zipBuf, output.pos)); } } while (input.pos != input.size || (op == ZSTD_e_flush && remaining != 0)); finalize_it: RETiRet; #else (void)pTarget; (void)buf; (void)len; (void)bIsFlush; LogError(0, RS_RET_PARAM_ERROR, "omfwd: zstd stream compression requested but rsyslog was built without libzstd"); return RS_RET_PARAM_ERROR; #endif } static rsRetVal TCPSendBufCompressed(targetData_t *pTarget, uchar *const buf, unsigned len, sbool bIsFlush) { wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; if (pWrkrData->pData->compressionDriver == COMPRESS_DRIVER_ZSTD) return TCPSendBufCompressedZstd(pTarget, buf, len, bIsFlush); else return TCPSendBufCompressedZlib(pTarget, buf, len, bIsFlush); } static rsRetVal TCPSendBuf(targetData_t *pTarget, uchar *buf, unsigned len, sbool bIsFlush) { wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; DEFiRet; if (pWrkrData->pData->compressionMode >= COMPRESS_STREAM_ALWAYS) iRet = TCPSendBufCompressed(pTarget, buf, len, bIsFlush); else iRet = TCPSendBufUncompressed(pTarget, buf, len); RETiRet; } /* finish zlib buffer, to be called before closing the ZIP file (if running in stream mode). */ static rsRetVal doZlibFinish(targetData_t *pTarget) { int zRet; /* zlib return state */ DEFiRet; unsigned outavail; uchar zipBuf[32 * 1024]; if (!pTarget->bzInitDone) goto done; // TODO: can we get this into a single common function? pTarget->zstrm.avail_in = 0; /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld\n", pTarget->zstrm.avail_in, pTarget->zstrm.total_in); pTarget->zstrm.avail_out = sizeof(zipBuf); pTarget->zstrm.next_out = zipBuf; zRet = deflate(&pTarget->zstrm, Z_FINISH); /* no bad return value */ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pTarget->zstrm.avail_out); outavail = sizeof(zipBuf) - pTarget->zstrm.avail_out; if (outavail != 0) { CHKiRet(TCPSendBufUncompressed(pTarget, zipBuf, outavail)); } } while (pTarget->zstrm.avail_out == 0); finalize_it: zRet = deflateEnd(&pTarget->zstrm); if (zRet != Z_OK) { DBGPRINTF("error %d returned from zlib/deflateEnd()\n", zRet); } pTarget->bzInitDone = 0; done: RETiRet; } static rsRetVal doZstdFinish(targetData_t *pTarget) { #ifdef ENABLE_LIBZSTD DEFiRet; uchar zipBuf[32 * 1024]; if (!pTarget->bzInitDone) goto done; ZSTD_inBuffer input = {zipBuf, 0, 0}; size_t remaining; do { ZSTD_outBuffer output = {zipBuf, sizeof(zipBuf), 0}; remaining = ZSTD_compressStream2(pTarget->zstdCctx, &output, &input, ZSTD_e_end); if (ZSTD_isError(remaining)) { LogError(0, RS_RET_ZLIB_ERR, "omfwd: error finishing zstd stream: %s", ZSTD_getErrorName(remaining)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (output.pos != 0) { CHKiRet(TCPSendBufUncompressed(pTarget, zipBuf, output.pos)); } } while (remaining != 0); finalize_it: if (pTarget->zstdCctx != NULL) { const size_t zRet = ZSTD_freeCCtx(pTarget->zstdCctx); if (ZSTD_isError(zRet)) { LogError(0, RS_RET_ZLIB_ERR, "omfwd: error from ZSTD_freeCCtx(): %s", ZSTD_getErrorName(zRet)); } pTarget->zstdCctx = NULL; } pTarget->bzInitDone = 0; done: RETiRet; #else (void)pTarget; return RS_RET_OK; #endif } static rsRetVal doCompressionFinish(targetData_t *pTarget) { if (pTarget->pData->compressionDriver == COMPRESS_DRIVER_ZSTD) return doZstdFinish(pTarget); else return doZlibFinish(pTarget); } /* Add frame to send buffer (or send, if requried) */ static rsRetVal TCPSendFrame(void *pvData, char *msg, const size_t len) { DEFiRet; targetData_t *pTarget = (targetData_t *)pvData; DBGPRINTF("omfwd: add %zu bytes to send buffer (curr offs %u, max len %d) msg: %*s\n", len, pTarget->offsSndBuf, pTarget->maxLenSndBuf, (int)len, msg); if (pTarget->offsSndBuf != 0 && (pTarget->offsSndBuf + len) >= (size_t)pTarget->maxLenSndBuf) { /* no buffer space left, need to commit previous records. With the * current API, there unfortunately is no way to signal this * state transition to the upper layer. */ DBGPRINTF( "omfwd: we need to do a tcp send due to buffer " "out of space. If the transaction fails, this will " "lead to duplication of messages"); CHKiRet(TCPSendBuf(pTarget, pTarget->sndBuf, pTarget->offsSndBuf, NO_FLUSH)); pTarget->offsSndBuf = 0; } /* check if the message is too large to fit into buffer */ if (len > sizeof(pTarget->sndBuf)) { CHKiRet(TCPSendBuf(pTarget, (uchar *)msg, len, NO_FLUSH)); ABORT_FINALIZE(RS_RET_OK); /* committed everything so far */ } /* we now know the buffer has enough free space */ memcpy(pTarget->sndBuf + pTarget->offsSndBuf, msg, len); pTarget->offsSndBuf += len; iRet = RS_RET_DEFER_COMMIT; finalize_it: RETiRet; } /* initializes a TCP session to a single Target */ static rsRetVal TCPSendInitTarget(targetData_t *const pTarget) { DEFiRet; wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; instanceData *pData = pWrkrData->pData; // TODO-RG: check error case - we need to make sure that we handle the situation correctly // when SOME calls fails - else we may get into big trouble during de-init if (pTarget->pNetstrm == NULL) { dbgprintf("TCPSendInitTarget CREATE %s:%s, conn %d\n", pTarget->target_name, pTarget->port, pTarget->bIsConnected); CHKiRet(netstrms.Construct(&pTarget->pNS)); /* the stream driver must be set before the object is finalized! */ CHKiRet(netstrms.SetDrvrName(pTarget->pNS, pData->pszStrmDrvr)); CHKiRet(netstrms.ConstructFinalize(pTarget->pNS)); /* now create the actual stream and connect to the server */ CHKiRet(netstrms.CreateStrm(pTarget->pNS, &pTarget->pNetstrm)); CHKiRet(netstrm.ConstructFinalize(pTarget->pNetstrm)); CHKiRet(netstrm.SetDrvrMode(pTarget->pNetstrm, pData->iStrmDrvrMode)); CHKiRet(netstrm.SetDrvrCheckExtendedKeyUsage(pTarget->pNetstrm, pData->iStrmDrvrExtendedCertCheck)); CHKiRet(netstrm.SetDrvrPrioritizeSAN(pTarget->pNetstrm, pData->iStrmDrvrSANPreference)); CHKiRet(netstrm.SetDrvrTlsVerifyDepth(pTarget->pNetstrm, pData->iStrmTlsVerifyDepth)); /* now set optional params, but only if they were actually configured */ if (pData->pszStrmDrvrAuthMode != NULL) { CHKiRet(netstrm.SetDrvrAuthMode(pTarget->pNetstrm, pData->pszStrmDrvrAuthMode)); } /* Call SetDrvrPermitExpiredCerts required * when param is NULL default handling for ExpiredCerts is set! */ CHKiRet(netstrm.SetDrvrPermitExpiredCerts(pTarget->pNetstrm, pData->pszStrmDrvrPermitExpiredCerts)); CHKiRet(netstrm.SetDrvrTlsCAFile(pTarget->pNetstrm, pData->pszStrmDrvrCAFile)); CHKiRet(netstrm.SetDrvrTlsCRLFile(pTarget->pNetstrm, pData->pszStrmDrvrCRLFile)); CHKiRet(netstrm.SetDrvrTlsCAExtraFiles(pTarget->pNetstrm, pData->pszStrmDrvrCAExtraFiles)); CHKiRet(netstrm.SetDrvrTlsKeyFile(pTarget->pNetstrm, pData->pszStrmDrvrKeyFile)); CHKiRet(netstrm.SetDrvrTlsCertFile(pTarget->pNetstrm, pData->pszStrmDrvrCertFile)); if (pData->pszStrmDrvrRemoteSNI != NULL) { CHKiRet(netstrm.SetDrvrRemoteSNI(pTarget->pNetstrm, pData->pszStrmDrvrRemoteSNI)); } if (pData->pPermPeers != NULL) { CHKiRet(netstrm.SetDrvrPermPeers(pTarget->pNetstrm, pData->pPermPeers)); } /* params set, now connect */ if (pData->gnutlsPriorityString != NULL) { CHKiRet(netstrm.SetGnutlsPriorityString(pTarget->pNetstrm, pData->gnutlsPriorityString)); } CHKiRet(netstrm.SetTcpUserTimeout(pTarget->pNetstrm, pData->tcp_user_timeout_ms)); CHKiRet(netstrm.Connect(pTarget->pNetstrm, glbl.GetDefPFFamily(runModConf->pConf), (uchar *)pTarget->port, (uchar *)pTarget->target_name, pData->device)); ATOMIC_INC_uint64(&pTarget->pTargetStats->numConnects, &pTarget->pTargetStats->mut_numConnects); /* set keep-alive if enabled */ if (pData->bKeepAlive) { CHKiRet(netstrm.SetKeepAliveProbes(pTarget->pNetstrm, pData->iKeepAliveProbes)); CHKiRet(netstrm.SetKeepAliveIntvl(pTarget->pNetstrm, pData->iKeepAliveIntvl)); CHKiRet(netstrm.SetKeepAliveTime(pTarget->pNetstrm, pData->iKeepAliveTime)); CHKiRet(netstrm.EnableKeepAlive(pTarget->pNetstrm)); } LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u] TCPSendInitTarget established connection to %s:%s", pTarget->pWrkrData->wrkrID, pTarget->target_name, pTarget->port); } finalize_it: if (iRet != RS_RET_OK) { dbgprintf("TCPSendInitTarget FAILED with %d.\n", iRet); DestructTargetData(pTarget, 0); } RETiRet; } /* Callback to initialize the provided target. * rgerhards, 2007-12-28 */ static rsRetVal TCPSendInit(void *pvData) { return TCPSendInitTarget((targetData_t *)pvData); } /* This callback function is called immediately before a send retry is attempted. * It shall clean up whatever makes sense. * side-note: TCPSendInit() is called afterwards by the generic tcp client code. */ static rsRetVal TCPSendPrepRetry(void *pvData) { DestructTargetData((targetData_t *)pvData, 0); /* Even if the destruct fails, it does not help to provide this info to * the upper layer. Also, DestructTargetData() does currently not * provide a return status. */ return RS_RET_OK; } /* change to network namespace pData->networkNamespace and keep the file * descriptor to the original namespace. */ static rsRetVal changeToNs(instanceData *const pData __attribute__((unused))) { DEFiRet; #ifdef HAVE_SETNS if (pData->networkNamespace) { CHKiRet(net.netns_save(&pData->originalNamespace)); CHKiRet(net.netns_switch(pData->networkNamespace)); } finalize_it: #else /* #ifdef HAVE_SETNS */ dbgprintf("omfwd: OS does not support network namespaces\n"); #endif /* #ifdef HAVE_SETNS */ RETiRet; } /* return to the original network namespace. This should be called after * changeToNs(). */ static rsRetVal returnToOriginalNs(instanceData *const pData __attribute__((unused))) { DEFiRet; #ifdef HAVE_SETNS /* only in case a network namespace is given and a file descriptor to * the original namespace exists */ if (pData->networkNamespace && pData->originalNamespace >= 0) { CHKiRet(net.netns_restore(&pData->originalNamespace)); dbgprintf("omfwd: returned to original network namespace\n"); } finalize_it: #endif /* #ifdef HAVE_SETNS */ RETiRet; } /* count the actual number of active targets. */ static void countActiveTargets(const wrkrInstanceData_t *const pWrkrData) { int activeTargets = 0; for (int j = 0; j < pWrkrData->pData->nTargets; ++j) { if (pWrkrData->target[j].bIsConnected) { activeTargets++; } } /* nActiveTargets is a scheduling snapshot; ordering comes from the CAS update, not from readers. */ int oldVal, newVal; do { oldVal = ATOMIC_LOAD_32BIT_RELAXED(&pWrkrData->pData->nActiveTargets, &pWrkrData->pData->mut_nActiveTargets); if (oldVal == activeTargets) { break; /* no change, so no log message either */ } newVal = activeTargets; } while (!ATOMIC_CAS(&pWrkrData->pData->nActiveTargets, oldVal, newVal, &pWrkrData->pData->mut_nActiveTargets)); if (oldVal != activeTargets) { LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u] number of active targets changed from %d to %d", pWrkrData->wrkrID, oldVal, activeTargets); } } /* check if the action as while is working (one target is OK) or suspended. * Try to resume initially not working targets along the way. */ static rsRetVal poolTryResume(wrkrInstanceData_t *const pWrkrData) { DEFiRet; int oneTargetOK = 0; for (int j = 0; j < pWrkrData->pData->nTargets; ++j) { if (pWrkrData->target[j].bIsConnected) { if (CheckConnection(&(pWrkrData->target[j])) == RS_RET_OK) { oneTargetOK = 1; } } else { DBGPRINTF("omfwd: poolTryResume, calling tryResume, target %d\n", j); iRet = doTryResume(&(pWrkrData->target[j])); DBGPRINTF("omfwd: poolTryResume, done tryResume, target %d, iRet %d\n", j, iRet); if (iRet == RS_RET_OK) { oneTargetOK = 1; } } } if (oneTargetOK) { iRet = RS_RET_OK; } DBGPRINTF("poolTryResume: oneTargetOK %d, iRet %d\n", oneTargetOK, iRet); RETiRet; } /* try to resume connection if it is not ready * When done, we set the time of earliest resumption. This is to handle * suspend and resume within the target connection pool. * rgerhards, 2007-08-02 */ static rsRetVal doTryResume(targetData_t *pTarget) { wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; instanceData *const pData = pWrkrData->pData; ; int iErr; struct addrinfo *res = NULL; struct addrinfo hints; int bBindRequired = 0; int bNeedReturnNs = 0; const char *address; DEFiRet; const int nActiveTargets = ATOMIC_LOAD_32BIT_RELAXED(&pTarget->pData->nActiveTargets, &pTarget->pData->mut_nActiveTargets); DBGPRINTF("doTryResume: isConnected: %d, ttResume %lld, LastActiveTargets: %d\n", pTarget->bIsConnected, (long long)pTarget->ttResume, nActiveTargets); if (pTarget->bIsConnected) FINALIZE; /* we look at the resume counter only if we have active targets at all - otherwise * rsyslog core handles the retry timing. */ if (pTarget->ttResume > 0 && nActiveTargets > 0) { time_t ttNow; datetime.GetTime(&ttNow); if (ttNow < pTarget->ttResume) { DBGPRINTF("omfwd: doTryResume: %s not yet time to retry, time %lld, ttResume %lld\n", pTarget->target_name, (long long)ttNow, (long long)pTarget->ttResume); ABORT_FINALIZE(RS_RET_SUSPENDED); } } /* The remote address is not yet known and needs to be obtained */ if (pData->protocol == FORW_UDP) { memset(&hints, 0, sizeof(hints)); /* port must be numeric, because config file syntax requires this */ hints.ai_flags = AI_NUMERICSERV; hints.ai_family = glbl.GetDefPFFamily(runModConf->pConf); hints.ai_socktype = SOCK_DGRAM; if ((iErr = (getaddrinfo(pTarget->target_name, pTarget->port, &hints, &res))) != 0) { LogError(0, RS_RET_SUSPENDED, "omfwd: could not get addrinfo for hostname '%s':'%s': %s", pTarget->target_name, pTarget->port, gai_strerror(iErr)); ABORT_FINALIZE(RS_RET_SUSPENDED); } address = pTarget->target_name; if (pData->address) { struct addrinfo *addr; /* The AF of the bind addr must match that of target */ hints.ai_family = res->ai_family; hints.ai_flags |= AI_PASSIVE; iErr = getaddrinfo(pData->address, pTarget->port, &hints, &addr); if (iErr != 0) { LogError(0, RS_RET_SUSPENDED, "omfwd: cannot use bind address '%s' for host '%s': %s", pData->address, pTarget->target_name, gai_strerror(iErr)); ABORT_FINALIZE(RS_RET_SUSPENDED); } freeaddrinfo(addr); bBindRequired = 1; address = pData->address; } DBGPRINTF("%s found, resuming.\n", pTarget->target_name); pTarget->f_addr = res; res = NULL; if (pTarget->pSockArray == NULL) { CHKiRet(changeToNs(pData)); bNeedReturnNs = 1; pTarget->pSockArray = net.create_udp_socket((uchar *)address, NULL, bBindRequired, 0, pData->UDPSendBuf, pData->ipfreebind, pData->device); CHKiRet(returnToOriginalNs(pData)); bNeedReturnNs = 0; } if (pTarget->pSockArray != NULL) { pTarget->bIsConnected = 1; } } else { CHKiRet(changeToNs(pData)); bNeedReturnNs = 1; CHKiRet(TCPSendInitTarget((void *)pTarget)); CHKiRet(returnToOriginalNs(pData)); bNeedReturnNs = 0; pTarget->bIsConnected = 1; } finalize_it: if (res != NULL) { freeaddrinfo(res); } if (iRet != RS_RET_OK) { if (bNeedReturnNs) { returnToOriginalNs(pData); } if (pTarget->f_addr != NULL) { freeaddrinfo(pTarget->f_addr); pTarget->f_addr = NULL; } iRet = RS_RET_SUSPENDED; } RETiRet; } BEGINtryResume CODESTARTtryResume; iRet = poolTryResume(pWrkrData); countActiveTargets(pWrkrData); const int nActiveTargets = ATOMIC_LOAD_32BIT_RELAXED(&pWrkrData->pData->nActiveTargets, &pWrkrData->pData->mut_nActiveTargets); LogMsg(0, RS_RET_DEBUG, LOG_DEBUG, "omfwd: [wrkr %u/%" PRIuPTR "] tryResume was called by rsyslog core: " "active targets: %d, overall return state %d", pWrkrData->wrkrID, (uintptr_t)pthread_self(), nActiveTargets, iRet); ENDtryResume BEGINbeginTransaction CODESTARTbeginTransaction; dbgprintf("omfwd: beginTransaction\n"); /* note: we need to try resume so that we are at least at the start * of the transaction aware of target states. It is not useful to * start a transaction when we know it will most probably fail. */ iRet = poolTryResume(pWrkrData); if (iRet == RS_RET_SUSPENDED) { LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "omfwd: [wrkr %d/%" PRIuPTR "] no working target servers in " "pool available, suspending action (state: beginTx)", pWrkrData->wrkrID, (uintptr_t)pthread_self()); } ENDbeginTransaction static rsRetVal processMsg(targetData_t *__restrict__ const pTarget, actWrkrIParams_t *__restrict__ const iparam) { wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)pTarget->pWrkrData; uchar *psz; /* temporary buffering */ register unsigned l; int iMaxLine; Bytef *out = NULL; /* for compression */ instanceData *__restrict__ const pData = pWrkrData->pData; DEFiRet; iMaxLine = glbl.GetMaxLine(runModConf->pConf); psz = iparam->param; l = iparam->lenStr; if ((int)l > iMaxLine) l = iMaxLine; /* Check if we should compress and, if so, do it. We also * check if the message is large enough to justify compression. * The smaller the message, the less likely is a gain in compression. * To save CPU cycles, we do not try to compress very small messages. * What "very small" means needs to be configured. Currently, it is * hard-coded but this may be changed to a config parameter. * rgerhards, 2006-11-30 */ if (pData->compressionMode == COMPRESS_SINGLE_MSG && (l > CONF_MIN_SIZE_FOR_COMPRESS)) { uLongf destLen = iMaxLine + iMaxLine / 100 + 12; /* recommended value from zlib doc */ uLong srcLen = l; int ret; CHKmalloc(out = (Bytef *)malloc(destLen)); out[0] = 'z'; out[1] = '\0'; ret = compress2((Bytef *)out + 1, &destLen, (Bytef *)psz, srcLen, pData->compressionLevel); dbgprintf("Compressing message, length was %d now %d, return state %d.\n", l, (int)destLen, ret); if (ret != Z_OK) { /* if we fail, we complain, but only in debug mode * Otherwise, we are silent. In any case, we ignore the * failed compression and just sent the uncompressed * data, which is still valid. So this is probably the * best course of action. * rgerhards, 2006-11-30 */ dbgprintf("Compression failed, sending uncompressed message\n"); } else if (destLen + 1 < l) { /* only use compression if there is a gain in using it! */ dbgprintf("there is gain in compression, so we do it\n"); psz = out; l = destLen + 1; /* take care for the "z" at message start! */ } ++destLen; } if (pData->protocol == FORW_UDP) { /* forward via UDP */ CHKiRet(UDPSend(pWrkrData, psz, l)); // TODO-RG: always add "actualTarget"! } else { /* forward via TCP */ iRet = tcpclt.Send(pTarget->pTCPClt, pTarget, (char *)psz, l); if (iRet == RS_RET_RETRY) { DBGPRINTF("omfwd: TCP send deferred for retry to %s:%s\n", pTarget->target_name, pTarget->port); } else if (iRet != RS_RET_OK && iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED) { /* error! */ LogError(0, iRet, "omfwd: error forwarding via tcp to %s:%s, suspending target", pTarget->target_name, pTarget->port); DestructTargetData(pTarget, 0); iRet = RS_RET_SUSPENDED; } } finalize_it: if (iRet == RS_RET_OK || iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) { ATOMIC_INC_uint64(&pTarget->pTargetStats->sentMsgs, &pTarget->pTargetStats->mut_sentMsgs); } free(out); /* is NULL if it was never used... */ RETiRet; } BEGINcommitTransaction unsigned i; char namebuf[264]; /* 256 for FQDN, 5 for port and 3 for transport => 264 */ sbool bFlushRetry = 0; CODESTARTcommitTransaction; /* if needed, rebind first. This ensure we can deliver to the rebound addresses. * Note that rebind requires reconnect (TCP) or socket recreation (UDP) to * the new targets. DestructInstanceData() drops the transport state and * poolTryResume() creates the next connection. The per-worker tcpclt * objects stay valid across rebinds and must not be reallocated here. */ if (pWrkrData->pData->iRebindInterval && (pWrkrData->nXmit++ >= pWrkrData->pData->iRebindInterval)) { dbgprintf("REBIND (sent %d, interval %d) - omfwd dropping target connection (as configured)\n", pWrkrData->nXmit, pWrkrData->pData->iRebindInterval); pWrkrData->nXmit = 0; /* else we have an addtl wrap at 2^31-1 */ DestructInstanceData(pWrkrData, 1); LogMsg(0, RS_RET_PARAM_ERROR, LOG_WARNING, "omfwd: dropped connections due to configured rebind interval"); } CHKiRet(poolTryResume(pWrkrData)); countActiveTargets(pWrkrData); DBGPRINTF("pool %s:%s/%s\n", pWrkrData->pData->target_name[0], pWrkrData->pData->ports[0], pWrkrData->pData->protocol == FORW_UDP ? "udp" : "tcp"); /* we use a rate-limiter based on the first pool members name. This looks * good enough. As an alternative, we may consider creating a special pool * name. But we leave this for when need actually arises. */ if (pWrkrData->pData->ratelimiter) { snprintf(namebuf, sizeof namebuf, "%s:[%s]:%s", pWrkrData->pData->protocol == FORW_UDP ? "udp" : "tcp", pWrkrData->pData->target_name[0], pWrkrData->pData->ports[0]); } for (i = 0; i < nParams; ++i) { /* If rate limiting is enabled, check whether this message has to be discarded */ if (pWrkrData->pData->ratelimiter) { iRet = ratelimitMsgCount(pWrkrData->pData->ratelimiter, 0, namebuf); if (iRet == RS_RET_DISCARDMSG) { iRet = RS_RET_OK; continue; } else if (iRet != RS_RET_OK) { LogError(0, RS_RET_ERR, "omfwd: action '%s' error during rate limit: %d.\n", actionGetName(pWrkrData->pData->pAction), iRet); } } int trynbr = 0; int dotry = 1; while (dotry && trynbr < pWrkrData->pData->nTargets) { /* In the future we may consider if we would like to have targets on a per-worker or global basis. We now use worker because otherwise we have thread interdependence, which hurts performance. But this can lead to uneven distribution of messages when multiple workers run. */ const unsigned actualTarget = (pWrkrData->actualTarget++) % pWrkrData->pData->nTargets; targetData_t *pTarget = &(pWrkrData->target[actualTarget]); DBGPRINTF("load balancer: trying actualTarget %u [%u]: try %d, isConnected %d, wrkr %p\n", actualTarget, (pWrkrData->actualTarget - 1), trynbr, pTarget->bIsConnected, pWrkrData); if (pTarget->bIsConnected) { DBGPRINTF("RGER: sending to actualTarget %d: try %d\n", actualTarget, trynbr); iRet = processMsg(pTarget, &actParam(pParams, 1, i, 0)); if (iRet == RS_RET_OK || iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) { dotry = 0; } } trynbr++; } if (dotry == 1) { LogMsg(0, RS_RET_SUSPENDED, LOG_INFO, "omfwd: [wrkr %u] found no working target server when trying to send " "messages (main loop)", pWrkrData->wrkrID); ABORT_FINALIZE(RS_RET_SUSPENDED); } pWrkrData->nXmit++; } for (int j = 0; j < pWrkrData->pData->nTargets; ++j) { if (pWrkrData->target[j].bIsConnected && pWrkrData->target[j].offsSndBuf != 0) { iRet = TCPSendBuf(&(pWrkrData->target[j]), pWrkrData->target[j].sndBuf, pWrkrData->target[j].offsSndBuf, IS_FLUSH); if (iRet == RS_RET_OK || iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) { pWrkrData->target[j].offsSndBuf = 0; } else if (iRet == RS_RET_RETRY) { DBGPRINTF("omfwd: TCP buffer flush deferred for retry to %s:%s\n", pWrkrData->target[j].target_name, pWrkrData->target[j].port); bFlushRetry = 1; iRet = RS_RET_OK; } else { LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "omfwd: [wrkr %u] target %s:%s became unavailable during buffer flush. " "Remaining messages will be sent when it is online again.", pWrkrData->wrkrID, pWrkrData->target[j].target_name, pWrkrData->target[j].port); DestructTargetData(&(pWrkrData->target[j]), 0); /* Note: do not return RS_RET_SUSPENDED here. We only return SUSPENDED * when no pool member is left active (see block below after pool stats). * For multi-target pools, other active targets may continue to work * and the remaining buffered data for this target will be flushed once * it resumes on a subsequent transaction. */ iRet = RS_RET_OK; } } } finalize_it: /* * Return semantics for commitTransaction: * - Only return RS_RET_SUSPENDED when no pool member is left active. * We determine this by calling countActiveTargets() and inspecting * the atomic nActiveTargets value. When it is zero, the whole pool * is unavailable and the action engine must enter retry logic. * - Also return RS_RET_SUSPENDED when a connected target reports * RS_RET_RETRY while flushing its pending TCP buffer. The target remains * connected, but the action engine still needs to schedule another commit * attempt for the retained buffered data. * - If at least one target remains active and no flush retry is pending, * we keep returning OK here so that the action is not suspended at pool * level. Any buffered frames for failed targets remain in that target's * send buffer and will be flushed once doTryResume() re-establishes the * connection on a subsequent transaction. */ /* do pool stats */ countActiveTargets(pWrkrData); const int nActiveTargets = ATOMIC_LOAD_32BIT_RELAXED(&pWrkrData->pData->nActiveTargets, &pWrkrData->pData->mut_nActiveTargets); if (bFlushRetry || nActiveTargets == 0) { /* * All pool members are currently unavailable, or a connected target * needs a retry to finish flushing retained TCP data. Return * RS_RET_SUSPENDED so the action engine schedules retry handling. */ iRet = RS_RET_SUSPENDED; } if (iRet == RS_RET_SUSPENDED) { LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "omfwd: [wrkr %d/%" PRIuPTR "] no working target servers in pool available, suspending action", pWrkrData->wrkrID, (uintptr_t)pthread_self()); } ENDcommitTransaction /* This function loads TCP support, if not already loaded. It will be called * during config processing. To server ressources, TCP support will only * be loaded if it actually is used. -- rgerhard, 2008-04-17 */ static rsRetVal loadTCPSupport(void) { DEFiRet; CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(tcpclt, LM_TCPCLT_FILENAME)); finalize_it: RETiRet; } /* initialize TCP structures (if necessary) after the instance has been * created. */ static rsRetVal initTCP(wrkrInstanceData_t *pWrkrData) { instanceData *pData; DEFiRet; pData = pWrkrData->pData; if (pData->protocol == FORW_TCP) { for (int i = 0; i < pData->nTargets; ++i) { /* create our tcpclt */ CHKiRet(tcpclt.Construct(&pWrkrData->target[i].pTCPClt)); CHKiRet(tcpclt.SetResendLastOnRecon(pWrkrData->target[i].pTCPClt, pData->bResendLastOnRecon)); CHKiRet(tcpclt.SetFraming(pWrkrData->target[i].pTCPClt, pData->tcp_framing)); CHKiRet(tcpclt.SetFramingDelimiter(pWrkrData->target[i].pTCPClt, pData->tcp_framingDelimiter)); /* and set callbacks */ CHKiRet(tcpclt.SetSendInit(pWrkrData->target[i].pTCPClt, TCPSendInit)); CHKiRet(tcpclt.SetSendFrame(pWrkrData->target[i].pTCPClt, TCPSendFrame)); CHKiRet(tcpclt.SetSendPrepRetry(pWrkrData->target[i].pTCPClt, TCPSendPrepRetry)); } } finalize_it: RETiRet; } static void setInstParamDefaults(instanceData *pData) { pData->tplName = NULL; pData->pAction = NULL; pData->targetSrv = NULL; pData->protocol = FORW_UDP; pData->networkNamespace = NULL; pData->originalNamespace = -1; pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING; pData->tcp_framingDelimiter = '\n'; pData->pszStrmDrvr = NULL; pData->pszStrmDrvrAuthMode = NULL; pData->pszStrmDrvrPermitExpiredCerts = NULL; pData->pszStrmDrvrRemoteSNI = NULL; pData->iStrmDrvrMode = 0; pData->bStrmDrvrModeSet = 0; pData->iStrmDrvrExtendedCertCheck = 0; pData->iStrmDrvrSANPreference = 0; pData->iStrmTlsVerifyDepth = 0; pData->pszStrmDrvrCAFile = NULL; pData->pszStrmDrvrCRLFile = NULL; pData->pszStrmDrvrCAExtraFiles = NULL; pData->pszStrmDrvrKeyFile = NULL; pData->pszStrmDrvrCertFile = NULL; pData->iRebindInterval = 0; pData->bKeepAlive = 0; pData->iKeepAliveProbes = 0; pData->iKeepAliveIntvl = 0; pData->iKeepAliveTime = 0; pData->tcp_user_timeout_ms = 0; pData->iConErrSkip = 0; pData->gnutlsPriorityString = NULL; pData->bResendLastOnRecon = 0; pData->bExtendedConnCheck = 1; /* traditionally enabled! */ pData->bSendToAll = -1; /* unspecified */ pData->iUDPSendDelay = 0; pData->UDPSendBuf = 0; pData->pPermPeers = NULL; pData->compressionLevel = 9; pData->compressionDriver = COMPRESS_DRIVER_ZLIB; pData->strmCompFlushOnTxEnd = 1; pData->compressionMode = COMPRESS_NEVER; pData->ipfreebind = IPFREEBIND_ENABLED_WITH_LOG; pData->poolResumeInterval = 30; pData->ratelimiter = NULL; pData->ratelimitInterval = -1; pData->ratelimitBurst = -1; pData->pszRatelimitName = NULL; } /* support statistics gathering - note: counter names are the same as for * previous non-pool based code. This permits easy migration in our opinion. */ static rsRetVal setupInstStatsCtrs(instanceData *const pData) { uchar ctrName[512]; DEFiRet; if (pData->target_name == NULL) { /* This is primarily introduced to keep the static analyzer happy. We * do not understand how this situation could actually happen. */ LogError(0, RS_RET_INTERNAL_ERROR, "internal error: target_name is NULL in setupInstStatsCtrs() -" "statistics countes are disable. Report this error to the " "rsyslog project please."); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } CHKmalloc(pData->target_stats = (targetStats_t *)calloc(pData->nTargets, sizeof(targetStats_t))); for (int i = 0; i < pData->nTargets; ++i) { /* if insufficient ports are configured, we use ports[0] for the * missing ports. */ snprintf((char *)ctrName, sizeof(ctrName), "%s-%s-%s", (pData->protocol == FORW_TCP) ? "TCP" : "UDP", pData->target_name[i], pData->ports[(i < pData->nPorts) ? i : 0]); ctrName[sizeof(ctrName) - 1] = '\0'; /* be on the save side */ CHKiRet(statsobj.Construct(&(pData->target_stats[i].stats))); CHKiRet(statsobj.SetName(pData->target_stats[i].stats, ctrName)); CHKiRet(statsobj.SetOrigin(pData->target_stats[i].stats, (uchar *)"omfwd")); pData->target_stats[i].sentBytes = 0; INIT_ATOMIC_HELPER_MUT64(pData->target_stats[i].mut_sentBytes); CHKiRet(statsobj.AddCounter(pData->target_stats[i].stats, UCHAR_CONSTANT("bytes.sent"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->target_stats[i].sentBytes))); pData->target_stats[i].sentMsgs = 0; INIT_ATOMIC_HELPER_MUT64(pData->target_stats[i].mut_sentMsgs); CHKiRet(statsobj.AddCounter(pData->target_stats[i].stats, UCHAR_CONSTANT("messages.sent"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->target_stats[i].sentMsgs))); pData->target_stats[i].numConnects = 0; INIT_ATOMIC_HELPER_MUT64(pData->target_stats[i].mut_numConnects); CHKiRet(statsobj.AddCounter(pData->target_stats[i].stats, UCHAR_CONSTANT("num.connects"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->target_stats[i].numConnects))); CHKiRet(statsobj.ConstructFinalize(pData->target_stats[i].stats)); } finalize_it: RETiRet; } /** Warn in secure warn mode when omfwd is configured without TLS transport protection. */ static void warnIfNonTlsForwardingConfigured(const instanceData *const pData) { if (pData->protocol == FORW_UDP) { glblWarnIfInsecureDefault(loadModConf->pConf, "omfwd action uses protocol=\"udp\" (without TLS); " "see https://docs.rsyslog.com/doc/faq/tls_mode0_disables_tls.html"); } else if (pData->protocol == FORW_TCP && pData->iStrmDrvrMode == 0) { const uchar *const effectiveDrvr = glblGetEffectiveNetstrmDrvr(loadModConf->pConf, pData->pszStrmDrvr); const int tlsHintsConfigured = (pData->pszStrmDrvrAuthMode != NULL) || glblIsTlsCapableNetstrmDrvr(effectiveDrvr); if (tlsHintsConfigured) { glblWarnIfInsecureDefault(loadModConf->pConf, "omfwd has TLS-related settings but streamdriver.mode=\"0\"; mode 0 uses plain " "TCP so TLS is not active " "(see https://docs.rsyslog.com/doc/faq/tls_mode0_disables_tls.html)"); } else { glblWarnIfInsecureDefault( loadModConf->pConf, "omfwd action uses protocol=\"tcp\" with streamdriver.mode=\"0\" " "(plain TCP without TLS); see https://docs.rsyslog.com/doc/faq/tls_mode0_disables_tls.html"); } } if (pData->protocol == FORW_TCP && pData->iStrmDrvrMode != 0 && pData->pszStrmDrvrAuthMode != NULL && strcasecmp((const char *)pData->pszStrmDrvrAuthMode, "anon") == 0) { glblWarnIfInsecureDefault( loadModConf->pConf, "omfwd uses streamdriver.authmode=\"anon\"; server identity is not authenticated, so MITM is possible " "(see https://docs.rsyslog.com/doc/faq/tls_anon_auth_mitm.html)"); } } static rsRetVal applySecureDefaultsToForwarding(instanceData *const pData) { DEFiRet; if (pData->protocol == FORW_TCP) { const uchar *const effectiveDrvr = glblGetEffectiveNetstrmDrvr(loadModConf->pConf, pData->pszStrmDrvr); if (glblIsTlsCapableNetstrmDrvr(effectiveDrvr) && pData->iStrmDrvrMode == 0 && loadModConf->pConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_STRICT) { if (pData->bStrmDrvrModeSet) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: compatibility.defaults.secure=\"strict\" rejects explicit " "streamdriver.mode=\"0\" with TLS-capable stream driver \"%s\"; use " "streamdriver.mode=\"1\" to enable TLS or select ptcp/plain TCP intentionally", (const char *)effectiveDrvr); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->iStrmDrvrMode = 1; } } finalize_it: RETiRet; } static rsRetVal setLegacyStrmDrvrMode(void __attribute__((unused)) * pVal, int mode) { cs.iStrmDrvrMode = mode; cs.bStrmDrvrModeSet = 1; return RS_RET_OK; } static rsRetVal validateTargetSrvTlsAuth(const instanceData *const pData) { DEFiRet; if (pData->targetSrv == NULL || pData->protocol != FORW_TCP || pData->iStrmDrvrMode == 0) { FINALIZE; } if (pData->pPermPeers != NULL) { FINALIZE; } if (pData->pszStrmDrvrAuthMode == NULL || !strcasecmp((const char *)pData->pszStrmDrvrAuthMode, "x509/name")) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: targetSrv with TLS requires streamdriverpermittedpeers when using streamdriverauthmode " "\"x509/name\" or the default auth mode (explicitly set permitted peers or use static target)"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } finalize_it: RETiRet; } BEGINnewActInst struct cnfparamvals *pvals; uchar *tplToUse; char *cstr; int i; rsRetVal localRet; int complevel = -1; CODESTARTnewActInst; DBGPRINTF("newActInst (omfwd)\n"); pvals = nvlstGetParams(lst, &actpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("action param blk in omfwd:\n"); cnfparamsPrint(&actpblk, pvals); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); pData->nPorts = 0; /* we need this to detect missing port param */ for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "target")) { const int nTargets = pvals[i].val.d.ar->nmemb; /* keep static analyzer happy */ pData->nTargets = nTargets; CHKmalloc(pData->target_name = (char **)calloc(pData->nTargets, sizeof(char *))); for (int j = 0; j < nTargets; ++j) { CHKmalloc(pData->target_name[j] = (char *)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL)); } } else if (!strcmp(actpblk.descr[i].name, "targetsrv")) { CHKmalloc(pData->targetSrv = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "address")) { CHKmalloc(pData->address = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "device")) { CHKmalloc(pData->device = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "port")) { pData->nPorts = pvals[i].val.d.ar->nmemb; CHKmalloc(pData->ports = (char **)calloc(pData->nPorts, sizeof(char *))); for (int j = 0; j < pData->nPorts; ++j) { CHKmalloc(pData->ports[j] = (char *)es_str2cstr(pvals[i].val.d.ar->arr[j], NULL)); } } else if (!strcmp(actpblk.descr[i].name, "protocol")) { if (!es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"udp", 3)) { pData->protocol = FORW_UDP; } else if (!es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"tcp", 3)) { localRet = loadTCPSupport(); if (localRet != RS_RET_OK) { LogError(0, localRet, "could not activate network stream modules for TCP " "(internal error %d) - are modules missing?", localRet); ABORT_FINALIZE(localRet); } pData->protocol = FORW_TCP; } else { uchar *str; CHKmalloc(str = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_INVLD_PROTOCOL, "omfwd: invalid protocol \"%s\"", str); free(str); ABORT_FINALIZE(RS_RET_INVLD_PROTOCOL); } } else if (!strcmp(actpblk.descr[i].name, "networknamespace")) { CHKmalloc(pData->networkNamespace = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "tcp_framing")) { if (!es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"traditional", 11)) { pData->tcp_framing = TCP_FRAMING_OCTET_STUFFING; } else if (!es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"octet-counted", 13)) { pData->tcp_framing = TCP_FRAMING_OCTET_COUNTING; } else { uchar *str; CHKmalloc(str = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_CNF_INVLD_FRAMING, "omfwd: invalid framing \"%s\"", str); free(str); ABORT_FINALIZE(RS_RET_CNF_INVLD_FRAMING); } } else if (!strcmp(actpblk.descr[i].name, "rebindinterval")) { pData->iRebindInterval = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "keepalive")) { pData->bKeepAlive = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "keepalive.probes")) { pData->iKeepAliveProbes = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "keepalive.interval")) { pData->iKeepAliveIntvl = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "keepalive.time")) { pData->iKeepAliveTime = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "tcp_user_timeout")) { pData->tcp_user_timeout_ms = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "conerrskip")) { pData->iConErrSkip = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "gnutlsprioritystring")) { CHKmalloc(pData->gnutlsPriorityString = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver") || !strcmp(actpblk.descr[i].name, "streamdriver.name")) { CHKmalloc(pData->pszStrmDrvr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdrivermode") || !strcmp(actpblk.descr[i].name, "streamdriver.mode")) { pData->iStrmDrvrMode = pvals[i].val.d.n; pData->bStrmDrvrModeSet = 1; } else if (!strcmp(actpblk.descr[i].name, "streamdriver.CheckExtendedKeyPurpose")) { pData->iStrmDrvrExtendedCertCheck = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "streamdriver.PrioritizeSAN")) { pData->iStrmDrvrSANPreference = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "streamdriver.TlsVerifyDepth")) { if (pvals[i].val.d.n >= 2) { pData->iStrmTlsVerifyDepth = pvals[i].val.d.n; } else { parser_errmsg("streamdriver.TlsVerifyDepth must be 2 or higher but is %d", (int)pvals[i].val.d.n); } } else if (!strcmp(actpblk.descr[i].name, "streamdriverauthmode") || !strcmp(actpblk.descr[i].name, "streamdriver.authmode")) { CHKmalloc(pData->pszStrmDrvrAuthMode = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.permitexpiredcerts")) { uchar *val; CHKmalloc(val = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"off", 3) && es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"on", 2) && es_strcasebufcmp(pvals[i].val.d.estr, (uchar *)"warn", 4)) { parser_errmsg( "streamdriver.permitExpiredCerts must be 'warn', 'off' or 'on' " "but is '%s' - ignoring parameter, using 'off' instead.", val); free(val); } else { pData->pszStrmDrvrPermitExpiredCerts = val; } } else if (!strcmp(actpblk.descr[i].name, "streamdriverremotesni") || !strcmp(actpblk.descr[i].name, "streamdriver.remotesni")) { CHKmalloc(pData->pszStrmDrvrRemoteSNI = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.cafile")) { CHKmalloc(pData->pszStrmDrvrCAFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.crlfile")) { CHKmalloc(pData->pszStrmDrvrCRLFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.caextrafiles")) { CHKmalloc(pData->pszStrmDrvrCAExtraFiles = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.keyfile")) { CHKmalloc(pData->pszStrmDrvrKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriver.certfile")) { CHKmalloc(pData->pszStrmDrvrCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "streamdriverpermittedpeers")) { uchar *start, *str; uchar *p; int lenStr; CHKmalloc(str = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); start = str; lenStr = ustrlen(start); /* we need length after '\0' has been dropped... */ while (lenStr > 0) { p = start; while (*p && *p != ',' && lenStr--) p++; if (*p == ',') { *p = '\0'; } if (*start == '\0') { DBGPRINTF("omfwd: ignoring empty permitted peer\n"); } else { dbgprintf("omfwd: adding permitted peer: '%s'\n", start); CHKiRet(net.AddPermittedPeer(&(pData->pPermPeers), start)); } start = p + 1; if (lenStr) --lenStr; } free(str); } else if (!strcmp(actpblk.descr[i].name, "ziplevel")) { complevel = pvals[i].val.d.n; if (complevel >= 0 && complevel <= 10) { pData->compressionLevel = complevel; pData->compressionMode = COMPRESS_SINGLE_MSG; } else { LogError(0, NO_ERRCODE, "Invalid ziplevel %d specified in " "forwarding action - NOT turning on compression.", complevel); } } else if (!strcmp(actpblk.descr[i].name, "tcp_framedelimiter")) { if (pvals[i].val.d.n > 255) { parser_errmsg("tcp_frameDelimiter must be below 255 but is %d", (int)pvals[i].val.d.n); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->tcp_framingDelimiter = (uchar)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "resendlastmsgonreconnect")) { pData->bResendLastOnRecon = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "extendedconnectioncheck")) { pData->bExtendedConnCheck = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "udp.sendtoall")) { pData->bSendToAll = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "udp.senddelay")) { pData->iUDPSendDelay = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "udp.sendbuf")) { pData->UDPSendBuf = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "compression.stream.flushontxend")) { pData->strmCompFlushOnTxEnd = (sbool)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "compression.driver")) { CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcasecmp(cstr, "zlib")) { pData->compressionDriver = COMPRESS_DRIVER_ZLIB; } else if (!strcasecmp(cstr, "zstd")) { #ifdef ENABLE_LIBZSTD pData->compressionDriver = COMPRESS_DRIVER_ZSTD; #else LogError(0, RS_RET_PARAM_ERROR, "omfwd: compression.driver=\"zstd\" requires rsyslog to be built with libzstd support"); free(cstr); ABORT_FINALIZE(RS_RET_PARAM_ERROR); #endif } else { LogError(0, RS_RET_PARAM_ERROR, "omfwd: invalid value for 'compression.driver' " "parameter (given is '%s')", cstr); free(cstr); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } free(cstr); } else if (!strcmp(actpblk.descr[i].name, "compression.mode")) { CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcasecmp(cstr, "stream:always")) { pData->compressionMode = COMPRESS_STREAM_ALWAYS; } else if (!strcasecmp(cstr, "none")) { pData->compressionMode = COMPRESS_NEVER; } else if (!strcasecmp(cstr, "single")) { pData->compressionMode = COMPRESS_SINGLE_MSG; } else { LogError(0, RS_RET_PARAM_ERROR, "omfwd: invalid value for 'compression.mode' " "parameter (given is '%s')", cstr); free(cstr); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } free(cstr); } else if (!strcmp(actpblk.descr[i].name, "ipfreebind")) { pData->ipfreebind = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "pool.resumeinterval")) { pData->poolResumeInterval = (unsigned int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.burst")) { pData->ratelimitBurst = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.interval")) { pData->ratelimitInterval = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.name")) { CHKmalloc(pData->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { LogError(0, RS_RET_INTERNAL_ERROR, "omfwd: program error, non-handled parameter '%s'", actpblk.descr[i].name); } } if (pData->pszRatelimitName != NULL) { if (pData->ratelimitInterval != -1 || pData->ratelimitBurst != -1) { LogError(0, RS_RET_INVALID_PARAMS, "omfwd: ratelimit.name is mutually exclusive with " "ratelimit.interval and ratelimit.burst - using ratelimit.name"); } pData->ratelimitInterval = 0; pData->ratelimitBurst = 0; } else { if (pData->ratelimitInterval == -1) pData->ratelimitInterval = 0; if (pData->ratelimitBurst == -1) pData->ratelimitBurst = 200; } if (pData->targetSrv != NULL && pData->target_name != NULL) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: target and targetSrv are mutually exclusive"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (pData->targetSrv == NULL && pData->target_name == NULL) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: either target or targetSrv must be specified"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKiRet(applyModuleTlsDefaults(pData, loadModConf)); CHKiRet(applySecureDefaultsToForwarding(pData)); if (pData->targetSrv != NULL) { if (pData->ports != NULL) { parser_warnmsg("omfwd: targetSrv was set, ignoring explicit port list"); freeConfiguredPorts(pData); } CHKiRet(validateTargetSrvTlsAuth(pData)); CHKiRet(resolveSrvTargets(pData)); } if (pData->protocol == FORW_UDP && pData->nTargets > 1) { parser_warnmsg( "you have defined %d targets. Multiple targets are ONLY " "supported in TCP mode ignoring all but the first target in UDP mode", pData->nTargets); } /* check if no port is set. If so, we use the IANA-assigned port of 514 */ if (pData->nPorts == 0) { pData->nPorts = 1; CHKmalloc(pData->ports = (char **)calloc(pData->nPorts, sizeof(char *))); CHKmalloc(pData->ports[0] = strdup("514")); } if (pData->nPorts > pData->nTargets) { parser_warnmsg( "defined %d ports, but only %d targets - ignoring " "extra ports", pData->nPorts, pData->nTargets); } if (pData->nPorts < pData->nTargets) { parser_warnmsg( "defined %d ports, but %d targets - using port %s " "as default for the additional targets", pData->nPorts, pData->nTargets, pData->ports[0]); } if (complevel != -1) { pData->compressionLevel = complevel; if (pData->compressionMode == COMPRESS_NEVER) { /* to keep compatible with pre-7.3.11, only setting the * compresion level means old-style single-message mode. */ pData->compressionMode = COMPRESS_SINGLE_MSG; } } if (pData->compressionDriver == COMPRESS_DRIVER_ZSTD && pData->compressionMode != COMPRESS_STREAM_ALWAYS) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: compression.driver=\"zstd\" is supported only with " "compression.mode=\"stream:always\""); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (pData->compressionDriver == COMPRESS_DRIVER_ZSTD && pData->compressionMode == COMPRESS_STREAM_ALWAYS && pData->compressionLevel == 0) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: compression.driver=\"zstd\" with compression.mode=\"stream:always\" requires non-zero " "zipLevel because libzstd treats level 0 as its default compression level"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CODE_STD_STRING_REQUESTnewActInst(1); tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName); CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS)); if (pData->bSendToAll == -1) { pData->bSendToAll = send_to_all; } else { if (pData->protocol == FORW_TCP) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: parameter udp.sendToAll " "cannot be used with tcp transport -- ignored"); } } if (pData->address && (pData->protocol == FORW_TCP)) { LogError(0, RS_RET_PARAM_ERROR, "omfwd: parameter \"address\" not supported for tcp -- ignored"); } warnIfNonTlsForwardingConfigured(pData); if (pData->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfig(&pData->ratelimiter, loadModConf->pConf, (char *)pData->pszRatelimitName, "omfwd", NULL)); ratelimitSetNoTimeCache(pData->ratelimiter); } else if (pData->ratelimitInterval > 0) { CHKiRet(ratelimitNew(&pData->ratelimiter, "omfwd", NULL)); ratelimitSetLinuxLike(pData->ratelimiter, (unsigned)pData->ratelimitInterval, (unsigned)pData->ratelimitBurst); ratelimitSetNoTimeCache(pData->ratelimiter); } setupInstStatsCtrs(pData); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINparseSelectorAct uchar *q; int i; rsRetVal localRet; struct addrinfo; TCPFRAMINGMODE tcp_framing = TCP_FRAMING_OCTET_STUFFING; CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) if (*p != '@') ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); CHKiRet(createInstance(&pData)); pData->tcp_framingDelimiter = '\n'; ++p; /* eat '@' */ if (*p == '@') { /* indicator for TCP! */ localRet = loadTCPSupport(); if (localRet != RS_RET_OK) { LogError(0, localRet, "could not activate network stream modules for TCP " "(internal error %d) - are modules missing?", localRet); ABORT_FINALIZE(localRet); } pData->protocol = FORW_TCP; ++p; /* eat this '@', too */ } else { pData->protocol = FORW_UDP; } /* we are now after the protocol indicator. Now check if we should * use compression. We begin to use a new option format for this: * @(option,option)host:port * The first option defined is "z[0..9]" where the digit indicates * the compression level. If it is not given, 9 (best compression) is * assumed. An example action statement might be: * @@(z5,o)127.0.0.1:1400 * Which means send via TCP with medium (5) compresion (z) to the local * host on port 1400. The '0' option means that octet-couting (as in * IETF I-D syslog-transport-tls) is to be used for framing (this option * applies to TCP-based syslog only and is ignored when specified with UDP). * That is not yet implemented. * rgerhards, 2006-12-07 * In order to support IPv6 addresses, we must introduce an extension to * the hostname. If it is in square brackets, whatever is in them is treated as * the hostname - without any exceptions ;) -- rgerhards, 2008-08-05 */ if (*p == '(') { /* at this position, it *must* be an option indicator */ do { ++p; /* eat '(' or ',' (depending on when called) */ /* check options */ if (*p == 'z') { /* compression */ ++p; /* eat */ if (isdigit((int)*p)) { int iLevel; iLevel = *p - '0'; ++p; /* eat */ pData->compressionLevel = iLevel; pData->compressionMode = COMPRESS_SINGLE_MSG; } else { LogError(0, NO_ERRCODE, "Invalid compression level '%c' specified in " "forwarding action - NOT turning on compression.", *p); } } else if (*p == 'o') { /* octet-couting based TCP framing? */ ++p; /* eat */ /* no further options settable */ tcp_framing = TCP_FRAMING_OCTET_COUNTING; } else { /* invalid option! Just skip it... */ LogError(0, NO_ERRCODE, "Invalid option %c in forwarding action - ignoring.", *p); ++p; /* eat invalid option */ } /* the option processing is done. We now do a generic skip * to either the next option or the end of the option * block. */ while (*p && *p != ')' && *p != ',') ++p; /* just skip it */ } while (*p && *p == ','); /* Attention: do.. while() */ if (*p == ')') ++p; /* eat terminator, on to next */ else /* we probably have end of string - leave it for the rest * of the code to handle it (but warn the user) */ LogError(0, NO_ERRCODE, "Option block not terminated in forwarding action."); } /* extract the host first (we do a trick - we replace the ';' or ':' with a '\0') * now skip to port and then template name. rgerhards 2005-07-06 */ if (*p == '[') { /* everything is hostname upto ']' */ ++p; /* skip '[' */ for (q = p; *p && *p != ']'; ++p) /* JUST SKIP */ ; if (*p == ']') { *p = '\0'; /* trick to obtain hostname (later)! */ ++p; /* eat it */ } } else { /* traditional view of hostname */ for (q = p; *p && *p != ';' && *p != ':' && *p != '#'; ++p) /* JUST SKIP */ ; } pData->tcp_framing = tcp_framing; pData->ports = NULL; pData->networkNamespace = NULL; CHKmalloc(pData->target_name = (char **)malloc(sizeof(char *) * pData->nTargets)); CHKmalloc(pData->ports = (char **)calloc(pData->nTargets, sizeof(char *))); if (*p == ':') { /* process port */ uchar *tmp; *p = '\0'; /* trick to obtain hostname (later)! */ tmp = ++p; for (i = 0; *p && isdigit((int)*p); ++p, ++i) /* SKIP AND COUNT */ ; pData->ports[0] = malloc(i + 1); if (pData->ports[0] == NULL) { LogError(0, NO_ERRCODE, "Could not get memory to store syslog forwarding port, " "using default port, results may not be what you intend"); /* we leave f_forw.port set to NULL, this is then handled below */ } else { memcpy(pData->ports[0], tmp, i); *(pData->ports[0] + i) = '\0'; } } /* check if no port is set. If so, we use the IANA-assigned port of 514 */ if (pData->ports[0] == NULL) { CHKmalloc(pData->ports[0] = strdup("514")); } /* now skip to template */ while (*p && *p != ';' && *p != '#' && !isspace((int)*p)) ++p; /*JUST SKIP*/ if (*p == ';' || *p == '#' || isspace(*p)) { uchar cTmp = *p; *p = '\0'; /* trick to obtain hostname (later)! */ CHKmalloc(pData->target_name[0] = strdup((char *)q)); *p = cTmp; } else { CHKmalloc(pData->target_name[0] = strdup((char *)q)); } /* We have a port at ports[0], so we must tell the module it is allocated. * Otherwise, the port would not be freed. */ pData->nPorts = 1; /* copy over config data as needed */ pData->iRebindInterval = (pData->protocol == FORW_TCP) ? cs.iTCPRebindInterval : cs.iUDPRebindInterval; pData->bKeepAlive = cs.bKeepAlive; pData->iKeepAliveProbes = cs.iKeepAliveProbes; pData->iKeepAliveIntvl = cs.iKeepAliveIntvl; pData->iKeepAliveTime = cs.iKeepAliveTime; pData->iConErrSkip = cs.iConErrSkip; /* process template */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); if (pData->protocol == FORW_TCP) { pData->bResendLastOnRecon = cs.bResendLastOnRecon; pData->iStrmDrvrMode = cs.iStrmDrvrMode; pData->bStrmDrvrModeSet = cs.bStrmDrvrModeSet; if (cs.pszStrmDrvrRemoteSNI != NULL) { CHKmalloc(pData->pszStrmDrvrRemoteSNI = (uchar *)strdup((char *)cs.pszStrmDrvrRemoteSNI)); } if (cs.pPermPeers != NULL) { pData->pPermPeers = cs.pPermPeers; cs.pPermPeers = NULL; } } CHKiRet(applyModuleTlsDefaults(pData, loadModConf)); CHKiRet(applySecureDefaultsToForwarding(pData)); warnIfNonTlsForwardingConfigured(pData); CODE_STD_FINALIZERparseSelectorAct if (iRet == RS_RET_OK) { setupInstStatsCtrs(pData); } ENDparseSelectorAct /* a common function to free our configuration variables - used both on exit * and on $ResetConfig processing. -- rgerhards, 2008-05-16 */ static void freeConfigVars(void) { free(cs.pszStrmDrvr); cs.pszStrmDrvr = NULL; free(cs.pszStrmDrvrAuthMode); cs.pszStrmDrvrAuthMode = NULL; free(cs.pszStrmDrvrRemoteSNI); cs.pszStrmDrvrRemoteSNI = NULL; free(cs.pPermPeers); cs.pPermPeers = NULL; } BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(netstrms, LM_NETSTRMS_FILENAME); objRelease(tcpclt, LM_TCPCLT_FILENAME); objRelease(statsobj, CORE_COMPONENT); freeConfigVars(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMODTX_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_SetActionInfo_IF_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt /* Reset config variables for this module to default values. * rgerhards, 2008-03-28 */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { freeConfigVars(); /* we now must reset all non-string values */ cs.iStrmDrvrMode = 0; cs.bStrmDrvrModeSet = 0; cs.bResendLastOnRecon = 0; cs.iUDPRebindInterval = 0; cs.iTCPRebindInterval = 0; cs.bKeepAlive = 0; cs.iKeepAliveProbes = 0; cs.iKeepAliveIntvl = 0; cs.iKeepAliveTime = 0; cs.iConErrSkip = 0; return RS_RET_OK; } BEGINmodInitNoPredecl(Fwd) CODESTARTmodInit; INITLegCnfVars; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet( regCfSysLineHdlr((uchar *)"actionforwarddefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl, NULL, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionsendtcprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iTCPRebindInterval, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionsendudprebindinterval", 0, eCmdHdlrInt, NULL, &cs.iUDPRebindInterval, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive", 0, eCmdHdlrBinary, NULL, &cs.bKeepAlive, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_probes", 0, eCmdHdlrInt, NULL, &cs.iKeepAliveProbes, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_intvl", 0, eCmdHdlrInt, NULL, &cs.iKeepAliveIntvl, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendtcpkeepalive_time", 0, eCmdHdlrInt, NULL, &cs.iKeepAliveTime, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriver", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdrivermode", 0, eCmdHdlrInt, setLegacyStrmDrvrMode, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverauthmode", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvrAuthMode, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverremotesni", 0, eCmdHdlrGetWord, NULL, &cs.pszStrmDrvrRemoteSNI, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendstreamdriverpermittedpeer", 0, eCmdHdlrGetWord, setPermittedPeer, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionsendresendlastmsgonreconnect", 0, eCmdHdlrBinary, NULL, &cs.bResendLastOnRecon, NULL)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/rsyslog-segqueue.rst0000644000000000000000000000013215241075234017757 xustar0030 mtime=1787067036.651579156 30 atime=1787067036.697580017 30 ctime=1787067795.321742329 rsyslog-8.2608.0/tools/rsyslog-segqueue.rst0000664000175000017500000001113315241075234017422 0ustar00rgerrger================= rsyslog-segqueue ================= ------------------------------------------- Maintain segmentedDisk queue stores offline ------------------------------------------- :Manual section: 1 SYNOPSIS ======== :: rsyslog-segqueue status QUEUE-DIR [--json] rsyslog-segqueue check QUEUE-DIR [--json] rsyslog-segqueue export QUEUE-DIR [--output FILE|-] [--scope live|all] [--salvage] rsyslog-segqueue repair QUEUE-DIR --mode state-slot|rebuild|salvage [--apply --offline] [--json] rsyslog-segqueue tui [QUEUE-DIR] DESCRIPTION =========== ``rsyslog-segqueue`` inspects, exports, and repairs the version 2 store used by ``queue.type="segmentedDisk"``. It does not operate on classic ``.qi`` disk queues. The queue directory is normally ``/.segq``. Status, check, and export are read-only. They detect a store that changes during repair preparation, but cannot provide a coherent snapshot while rsyslog is writing the queue. Stop rsyslog before applying any repair. COMMANDS ======== status ------ Read state slots and segment metadata. The report includes the selected state generation, queue UUID, commit frontier, live/recovery/delete ranges, physical size, and immediately visible inconsistencies. Payloads are not scanned. check ----- Scan the complete store. Checks cover state-slot checksums and invariants, segment headers and footers, topology, record framing and sequence numbers, payload checksums, and the versioned TLV message codec. Every error includes a stable code and location. export ------ Write one JSON object per valid record. The default ``--scope live`` begins at the durable commit frontier. ``--scope all`` also includes physical records that state identifies as already committed or pending deletion. Export refuses a corrupt store by default. ``--salvage`` exports independently valid records, reports omissions, and exits with status 2. Valid UTF-8 is written as a JSON string. Other byte strings are represented as an object with ``encoding`` set to ``base64`` and a lossless ``data`` value. For an unparsed message whose stored message offset is rsyslog's ``0xffffffff`` sentinel, ``msg`` contains the complete raw message and ``msg_offset_unset`` is true. repair ------ Repair is a no-write plan unless both ``--apply`` and ``--offline`` are given. The modes are: ``state-slot`` Recreate one invalid state slot from the surviving valid slot and preserve its commit frontier. ``rebuild`` Require clean, unambiguous segment data and construct a normalized store in which every recovered record is pending. ``salvage`` Resynchronize after corrupt framing, retain every record whose framing, payload checksum, and codec validate, and construct a normalized store. Rebuild and salvage may replay records that had already been processed because an unusable state file cannot prove the old commit frontier. This deliberate duplicate-over-loss policy is always shown in the repair plan. Applied repairs retain the original state file or queue directory under a UTC-timestamped ``backup`` name. Rebuild and salvage validate a same-filesystem staging store before atomically renaming the original. Backups are never deleted automatically. tui --- Open a dependency-free guided terminal menu. It invokes the same commands and requires the exact queue path to be typed before applying a repair. OPTIONS ------- ``--json`` Emit a machine-readable status, check, or repair report. ``--output FILE|-`` Write JSON Lines to FILE. ``-`` selects standard output and is the default. ``--scope live|all`` Select logically live records or all physical records. The default is ``live``. ``--salvage`` Permit a partial JSONL export from a corrupt store. ``--apply`` Apply a repair plan. This also requires ``--offline``. ``--offline`` Acknowledge that rsyslog is stopped and will not access the queue during the repair. EXIT STATUS =========== 0 The command completed successfully and no integrity errors were found. 1 Invocation, filesystem, or internal processing failed. 2 Integrity errors were found, or a salvage export completed with omissions. EXAMPLES ======== :: rsyslog-segqueue status /var/spool/rsyslog/mainq.segq rsyslog-segqueue check --json /var/spool/rsyslog/mainq.segq rsyslog-segqueue export /var/spool/rsyslog/mainq.segq --output backlog.jsonl rsyslog-segqueue repair /var/spool/rsyslog/mainq.segq --mode salvage rsyslog-segqueue repair /var/spool/rsyslog/mainq.segq --mode salvage --apply --offline SEE ALSO ======== ``rsyslogd(8)``, ``rsyslog.conf(5)`` rsyslog-8.2608.0/tools/PaxHeaders/Makefile.am0000644000000000000000000000013215241075234015736 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.803582002 30 ctime=1787067795.220740447 rsyslog-8.2608.0/tools/Makefile.am0000664000175000017500000000763015241075234015410 0ustar00rgerrgersbin_PROGRAMS = CLEANFILES = man5_MANS = rsyslog.conf.5 man8_MANS = rsyslogd.8 man1_MANS = sbin_PROGRAMS += rsyslogd rsyslogd_SOURCES = \ syslogd.c \ rsyslogd.c \ syslogd.h \ omshell.c \ omshell.h \ omusrmsg.c \ omusrmsg.h \ omfwd.c \ omfwd.h \ omfile.c \ omfile.h \ ompipe.c \ ompipe.h \ omdiscard.c \ omdiscard.h \ pmrfc5424.c \ pmrfc5424.h \ pmrfc3164.c \ pmrfc3164.h \ smtradfile.c \ smtradfile.h \ smfile.c \ smfile.h \ smfwd.c \ smfwd.h \ smtradfwd.c \ smtradfwd.h \ iminternal.c \ iminternal.h \ \ ../runtime/dirty.h rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) if ENABLE_LIBZSTD rsyslogd_CPPFLAGS += $(ZSTD_CFLAGS) rsyslogd_LDADD_ZSTD = $(ZSTD_LIBS) else rsyslogd_LDADD_ZSTD = endif if ENABLE_LIBLOGGING_STDLOG rsyslogd_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) endif rsyslogd_CPPFLAGS += -DSD_EXPORT_SYMBOLS # note: it looks like librsyslog.la must be explicitely given on LDDADD, # otherwise dependencies are not properly calculated (resulting in a # potentially incomplete build, a problem we had several times...) rsyslogd_LDADD = ../grammar/libgrammar.la ../runtime/librsyslog.la ../compat/compat.la $(ZLIB_LIBS) $(rsyslogd_LDADD_ZSTD) $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBUUID_LIBS) $(HASH_XXHASH_LIBS) $(LIBRESOLV_LIBS) $(LIBYAML_LIBS) # Note: do NOT indent the if chain - it will not work! if OS_LINUX rsyslogd_LDFLAGS = -export-dynamic \ #-Wl,--whole-archive,$(top_builddir)/runtime/.libs/librsyslog.a,--no-whole-archive exports_list_file = else if OS_APPLE rsyslogd_LDFLAGS = -export-dynamic \ -Wl,$(top_builddir)/runtime/.libs/librsyslog.a exports_list_file = else if OS_AIX rsyslogd_LDFLAGS = -brtl -bexpall -f"aix_exports_list" -lsrc exports_list_file = aix_exports_list else # e.g. FreeBSD rsyslogd_LDFLAGS = -export-dynamic exports_list_file = endif # if OS_AIX endif # if OS_APPLE endif # if OS_LINUX EXTRA_DIST = $(man5_MANS) $(man8_MANS) \ rscryutil.rst \ recover_qi.pl \ rsyslog-segqueue.rst if ENABLE_FUZZING noinst_PROGRAMS = fuzz_rsyslog_message fuzz_rsyslog_message_SOURCES = $(rsyslogd_SOURCES) fuzz_rsyslog_message.c fuzz_rsyslog_message_CPPFLAGS = $(rsyslogd_CPPFLAGS) -DRSYSLOG_FUZZ_TARGET -Dmain=rsyslogd_main fuzz_rsyslog_message_LDADD = $(rsyslogd_LDADD) fuzz_rsyslog_message_LDFLAGS = $(rsyslogd_LDFLAGS) $(LIB_FUZZING_ENGINE) endif EXTRA_rsyslogd_DEPENDENCIES = $(exports_list_file) if ENABLE_LIBLOGGING_STDLOG rsyslogd_LDADD += $(LIBLOGGING_STDLOG_LIBS) endif if ENABLE_DIAGTOOLS sbin_PROGRAMS += rsyslog_diag_hostname msggen rsyslog_diag_hostname_SOURCES = gethostn.c msggen_SOURCES = msggen.c endif if ENABLE_USERTOOLS bin_PROGRAMS = if ENABLE_SEGQUEUE_TOOL dist_bin_SCRIPTS = rsyslog-segqueue rsyslog-segqueue.1: rsyslog-segqueue.rst $(AM_V_GEN) $(RST2MAN) rsyslog-segqueue.rst $@ if ENABLE_GENERATE_MAN_PAGES man1_MANS += rsyslog-segqueue.1 CLEANFILES += rsyslog-segqueue.1 EXTRA_DIST += rsyslog-segqueue.1 endif endif if ENABLE_OMMONGODB bin_PROGRAMS += logctl logctl_SOURCES = logctl.c logctl_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS) logctl_LDADD = $(LIBMONGOC_LIBS) endif if ENABLE_RSCRYUTIL bin_PROGRAMS += rscryutil rscryutil = rscryutil.c rscryutil_CPPFLAGS = -I../runtime $(RSRT_CFLAGS) rscryutil_LDADD = if ENABLE_LIBGCRYPT rscryutil_CPPFLAGS += $(LIBGCRYPT_CFLAGS) rscryutil_LDADD += ../runtime/libgcry.la $(LIBGCRYPT_LIBS) endif if ENABLE_OPENSSL_CRYPTO_PROVIDER rscryutil_CPPFLAGS += $(OPENSSL_CFLAGS) rscryutil_LDADD += ../runtime/libossl.la $(OPENSSL_LIBS) endif rscryutil_LDFLAGS = \ -Wl,--whole-archive,--no-whole-archive if ENABLE_GENERATE_MAN_PAGES RSTMANFILE = rscryutil.rst rscryutil.1: $(RSTMANFILE) $(AM_V_GEN) $(RST2MAN) $(RSTMANFILE) $@ man1_MANS += rscryutil.1 CLEANFILES += rscryutil.1 EXTRA_DIST+= rscryutil.1 endif endif endif aix_exports_list: echo "$(top_builddir)/runtime/.libs/librsyslog_la-*.o" > $@ echo "$(top_builddir)/.libs/librsyslog_la-*.o" >> $@ echo "$(top_builddir)/grammar/.libs/libgrammar_la-*.o" >> $@ rsyslog-8.2608.0/tools/PaxHeaders/rsyslog-segqueue.10000644000000000000000000000013215241076346017314 xustar0030 mtime=1787067622.275516791 30 atime=1787067622.274516772 30 ctime=1787067795.324742385 rsyslog-8.2608.0/tools/rsyslog-segqueue.10000664000175000017500000001277015241076346016767 0ustar00rgerrger.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "RSYSLOG-SEGQUEUE" 1 "" "" .SH NAME rsyslog-segqueue \- Maintain segmentedDisk queue stores offline .SH SYNOPSIS .INDENT 0.0 .INDENT 3.5 .sp .EX rsyslog\-segqueue status QUEUE\-DIR [\-\-json] rsyslog\-segqueue check QUEUE\-DIR [\-\-json] rsyslog\-segqueue export QUEUE\-DIR [\-\-output FILE|\-] [\-\-scope live|all] [\-\-salvage] rsyslog\-segqueue repair QUEUE\-DIR \-\-mode state\-slot|rebuild|salvage [\-\-apply \-\-offline] [\-\-json] rsyslog\-segqueue tui [QUEUE\-DIR] .EE .UNINDENT .UNINDENT .SH DESCRIPTION .sp \fBrsyslog\-segqueue\fP inspects, exports, and repairs the version 2 store used by \fBqueue.type=\(dqsegmentedDisk\(dq\fP\&. It does not operate on classic \fB\&.qi\fP disk queues. The queue directory is normally \fB/.segq\fP\&. .sp Status, check, and export are read\-only. They detect a store that changes during repair preparation, but cannot provide a coherent snapshot while rsyslog is writing the queue. Stop rsyslog before applying any repair. .SH COMMANDS .SS status .sp Read state slots and segment metadata. The report includes the selected state generation, queue UUID, commit frontier, live/recovery/delete ranges, physical size, and immediately visible inconsistencies. Payloads are not scanned. .SS check .sp Scan the complete store. Checks cover state\-slot checksums and invariants, segment headers and footers, topology, record framing and sequence numbers, payload checksums, and the versioned TLV message codec. Every error includes a stable code and location. .SS export .sp Write one JSON object per valid record. The default \fB\-\-scope live\fP begins at the durable commit frontier. \fB\-\-scope all\fP also includes physical records that state identifies as already committed or pending deletion. .sp Export refuses a corrupt store by default. \fB\-\-salvage\fP exports independently valid records, reports omissions, and exits with status 2. Valid UTF\-8 is written as a JSON string. Other byte strings are represented as an object with \fBencoding\fP set to \fBbase64\fP and a lossless \fBdata\fP value. For an unparsed message whose stored message offset is rsyslog\(aqs \fB0xffffffff\fP sentinel, \fBmsg\fP contains the complete raw message and \fBmsg_offset_unset\fP is true. .SS repair .sp Repair is a no\-write plan unless both \fB\-\-apply\fP and \fB\-\-offline\fP are given. The modes are: .INDENT 0.0 .TP .B \fBstate\-slot\fP Recreate one invalid state slot from the surviving valid slot and preserve its commit frontier. .TP .B \fBrebuild\fP Require clean, unambiguous segment data and construct a normalized store in which every recovered record is pending. .TP .B \fBsalvage\fP Resynchronize after corrupt framing, retain every record whose framing, payload checksum, and codec validate, and construct a normalized store. .UNINDENT .sp Rebuild and salvage may replay records that had already been processed because an unusable state file cannot prove the old commit frontier. This deliberate duplicate\-over\-loss policy is always shown in the repair plan. .sp Applied repairs retain the original state file or queue directory under a UTC\-timestamped \fBbackup\fP name. Rebuild and salvage validate a same\-filesystem staging store before atomically renaming the original. Backups are never deleted automatically. .SS tui .sp Open a dependency\-free guided terminal menu. It invokes the same commands and requires the exact queue path to be typed before applying a repair. .SS OPTIONS .INDENT 0.0 .TP .B \fB\-\-json\fP Emit a machine\-readable status, check, or repair report. .TP .B \fB\-\-output FILE|\-\fP Write JSON Lines to FILE. \fB\-\fP selects standard output and is the default. .TP .B \fB\-\-scope live|all\fP Select logically live records or all physical records. The default is \fBlive\fP\&. .TP .B \fB\-\-salvage\fP Permit a partial JSONL export from a corrupt store. .TP .B \fB\-\-apply\fP Apply a repair plan. This also requires \fB\-\-offline\fP\&. .TP .B \fB\-\-offline\fP Acknowledge that rsyslog is stopped and will not access the queue during the repair. .UNINDENT .SH EXIT STATUS .INDENT 0.0 .TP .B 0 The command completed successfully and no integrity errors were found. .TP .B 1 Invocation, filesystem, or internal processing failed. .TP .B 2 Integrity errors were found, or a salvage export completed with omissions. .UNINDENT .SH EXAMPLES .INDENT 0.0 .INDENT 3.5 .sp .EX rsyslog\-segqueue status /var/spool/rsyslog/mainq.segq rsyslog\-segqueue check \-\-json /var/spool/rsyslog/mainq.segq rsyslog\-segqueue export /var/spool/rsyslog/mainq.segq \-\-output backlog.jsonl rsyslog\-segqueue repair /var/spool/rsyslog/mainq.segq \-\-mode salvage rsyslog\-segqueue repair /var/spool/rsyslog/mainq.segq \-\-mode salvage \-\-apply \-\-offline .EE .UNINDENT .UNINDENT .SH SEE ALSO .sp \fBrsyslogd(8)\fP, \fBrsyslog.conf(5)\fP .\" Generated by docutils manpage writer. . rsyslog-8.2608.0/tools/PaxHeaders/omdiscard.c0000644000000000000000000000013215145046113016010 xustar0030 mtime=1771326539.071014811 30 atime=1787067622.101513546 30 ctime=1787067795.258741155 rsyslog-8.2608.0/tools/omdiscard.c0000664000175000017500000000750515145046113015463 0ustar00rgerrger/* omdiscard.c * This is the implementation of the built-in discard output module. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2007-07-24 by RGerhards * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include "syslogd.h" #include "syslogd-types.h" #include "omdiscard.h" #include "module-template.h" #include "errmsg.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; /* internal structures */ DEF_OMOD_STATIC_DATA; typedef struct _instanceData { EMPTY_STRUCT } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; /* we do not need a createInstance()! BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance */ BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; /* do nothing */ ENDdbgPrintInstInfo BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; /* we are not compatible with repeated msg reduction feature, so do not allow it */ ENDisCompatibleWithFeature BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINdoAction_NoStrings CODESTARTdoAction; (void)pMsgData; /* Suppress compiler warning on unused var */ dbgprintf("\n"); iRet = RS_RET_DISCARDMSG; ENDdoAction BEGINfreeInstance CODESTARTfreeInstance; /* we do not have instance data, so we do not need to * do anything here. -- rgerhards, 2007-07-25 */ ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINparseSelectorAct CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(0) pData = NULL; /* this action does not have any instance data */ p = *pp; if (*p == '~') { dbgprintf("discard\n"); LogMsg(0, RS_RET_DEPRECATED, LOG_WARNING, "warning: ~ action is deprecated, consider " "using the 'stop' statement instead"); } else { iRet = RS_RET_CONFLINE_UNPROCESSED; } /* we do not use the macro * CODE_STD_FINALIZERparseSelectorAct * here as this causes a Coverity ID "false positive" (CID 185431). * We don't see an issue with using the copy&pasted code as it is unlikly * to change for this (outdated) module. */ finalize_it: ATTR_UNUSED; /* semi-colon needed according to gcc doc! */ if (iRet == RS_RET_OK || iRet == RS_RET_OK_WARN || iRet == RS_RET_SUSPENDED) { *ppModData = pData; *pp = p; } else { /* cleanup, we failed */ if (*ppOMSR != NULL) { OMSRdestruct(*ppOMSR); *ppOMSR = NULL; } } /* END modified macro text */ ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; ENDqueryEtryPt BEGINmodInitNoPredecl(Discard) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* * vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/smtradfile.h0000644000000000000000000000013215141401300016167 xustar0030 mtime=1770390208.970869795 30 atime=1787067618.326443159 30 ctime=1787067795.273741435 rsyslog-8.2608.0/tools/smtradfile.h0000664000175000017500000000241515141401300015635 0ustar00rgerrger/* smtradfile.h * These are the definitions for the traditional file format stringen module. * * File begun on 2010-06-01 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SMTRADFILE_H_INCLUDED #define SMTRADFILE_H_INCLUDED 1 /* prototypes */ rsRetVal modInitsmtradfile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef SMTRADFILE_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/smfile.c0000644000000000000000000000013115132411300015307 xustar0030 mtime=1768559296.305886257 29 atime=1787067622.09151336 30 ctime=1787067795.276741491 rsyslog-8.2608.0/tools/smfile.c0000666000175000017500000000766715132411300014776 0ustar00rgerrger/* smfile.c * This is a strgen module for the traditional file format. * * Format generated: * "%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" * Note that this is the same as smtradfile.c, except that we do have a RFC3339 timestamp. However, * we have copied over the code from there, it is too simple to go through all the hassle * of having a single code base. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2010-06-01 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "unicode-helper.h" MODULE_TYPE_STRGEN MODULE_TYPE_NOKEEP; STRGEN_NAME("RSYSLOG_FileFormat") /* internal structures */ DEF_SMOD_STATIC_DATA; /* config data */ /* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings * needed (including their length) and then calculating the actual space required. So when we * finally copy, we know exactly what we need. So we do at most one alloc. */ BEGINstrgen register int iBuf; uchar *pTimeStamp; size_t lenTimeStamp; uchar *pHOSTNAME; size_t lenHOSTNAME; uchar *pTAG; int lenTAG; uchar *pMSG; size_t lenMSG; size_t lenTotal; CODESTARTstrgen; /* first obtain all strings and their length (if not fixed) */ pTimeStamp = (uchar *)getTimeReported(pMsg, tplFmtRFC3339Date); lenTimeStamp = ustrlen(pTimeStamp); pHOSTNAME = (uchar *)getHOSTNAME(pMsg); lenHOSTNAME = getHOSTNAMELen(pMsg); getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX); pMSG = getMSG(pMsg); lenMSG = getMSGLen(pMsg); /* calculate len, constants for spaces and similar fixed strings */ lenTotal = lenTimeStamp + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 2; if (pMSG[0] != ' ') ++lenTotal; /* then we need to introduce one additional space */ /* now make sure buffer is large enough */ if (lenTotal >= iparam->lenBuf) CHKiRet(ExtendBuf(iparam, lenTotal)); /* and concatenate the resulting string */ memcpy(iparam->param, pTimeStamp, lenTimeStamp); iBuf = lenTimeStamp; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME); iBuf += lenHOSTNAME; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pTAG, lenTAG); iBuf += lenTAG; if (pMSG[0] != ' ') iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pMSG, lenMSG); iBuf += lenMSG; /* trailer */ iparam->param[iBuf++] = '\n'; iparam->param[iBuf] = '\0'; iparam->lenStr = lenTotal - 1; /* do not count \0! */ finalize_it: ENDstrgen BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_SMOD_QUERIES; ENDqueryEtryPt BEGINmodInit(smfile) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf("rsyslog standard file format strgen init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/pmrfc5424.h0000644000000000000000000000013215241075234015501 xustar0030 mtime=1787067036.651579156 30 atime=1787067036.805582039 30 ctime=1787067795.264741267 rsyslog-8.2608.0/tools/pmrfc5424.h0000664000175000017500000000263415241075234015152 0ustar00rgerrger/* pmrfc5424.h * These are the definitions for the RFCC5424 parser module. * * File begun on 2009-11-03 by RGerhards * * Copyright 2009-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PMRFC54254_H_INCLUDED #define PMRFC54254_H_INCLUDED 1 /* prototypes */ rsRetVal modInitpmrfc5424(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #ifdef ENABLE_FUZZING rsRetVal pmrfc5424FuzzInit(void); void pmrfc5424FuzzExit(void); rsRetVal pmrfc5424FuzzParse(smsg_t *pMsg); #endif #endif /* #ifndef PMRFC54254_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/syslogd.c0000644000000000000000000000013215132411300015515 xustar0030 mtime=1768559296.306886273 30 atime=1787067622.083513211 30 ctime=1787067795.227740578 rsyslog-8.2608.0/tools/syslogd.c0000666000175000017500000000736015132411300015171 0ustar00rgerrger/** * main rsyslog file with GPLv3 content. * * *********************** NOTE ************************ * * Do no longer patch this file. If there is hard * * * need to, talk to Rainer as to how we can make any * * * patch be licensed under ASL 2.0. * * * THIS FILE WILL GO AWAY. The new main file is * * * rsyslogd.c. * * ***************************************************** * * Please visit the rsyslog project at * https://www.rsyslog.com * to learn more about it and discuss any questions you may have. * * rsyslog had initially been forked from the sysklogd project. * I would like to express my thanks to the developers of the sysklogd * package - without it, I would have had a much harder start... * * Please note that while rsyslog started from the sysklogd code base, * it nowadays has almost nothing left in common with it. Allmost all * parts of the code have been rewritten. * * This Project was intiated and is maintained by * Rainer Gerhards . * * rsyslog - An Enhanced syslogd Replacement. * Copyright 2003-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef OS_SOLARIS #include #include #include #include #else #include #endif #include #include #include #include #include #ifdef HAVE_SYS_TIMESPEC_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #include #ifdef HAVE_PATHS_H #include #endif #include "srUtils.h" #include "stringbuf.h" #include "syslogd-types.h" #include "template.h" #include "outchannel.h" #include "syslogd.h" #include "msg.h" #include "iminternal.h" #include "threads.h" #include "parser.h" #include "unicode-helper.h" #include "dnscache.h" #include "ratelimit.h" #ifndef HAVE_SETSID /* stems back to sysklogd in whole */ void untty(void) { int i; pid_t pid; if (!Debug) { /* Peng Haitao contribution */ pid = getpid(); if (setpgid(pid, pid) < 0) { perror("setpgid"); exit(1); } /* end Peng Haitao contribution */ i = open(_PATH_TTY, O_RDWR | O_CLOEXEC); if (i >= 0) { #if !defined(__hpux) (void)ioctl(i, (int)TIOCNOTTY, NULL); #else /* TODO: we need to implement something for HP UX! -- rgerhards, 2008-03-04 */ /* actually, HP UX should have setsid, so the code directly above should * trigger. So the actual question is why it doesn't do that... */ #endif close(i); } } } #endif rsyslog-8.2608.0/tools/PaxHeaders/ompipe.h0000644000000000000000000000013215141401300015326 xustar0030 mtime=1770390208.969869851 30 atime=1787067618.293442543 30 ctime=1787067795.255741099 rsyslog-8.2608.0/tools/ompipe.h0000664000175000017500000000227515141401300015000 0ustar00rgerrger/* ompipe.h * These are the definitions for the build-in pipe output module. * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This pipe is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OMPIPE_H_INCLUDED #define OMPIPE_H_INCLUDED 1 /* prototypes */ rsRetVal modInitPipe(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef OMPIPE_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/rsyslog.conf.50000644000000000000000000000013215132733117016416 xustar0030 mtime=1768666703.972621223 30 atime=1782715518.785788789 30 ctime=1787067795.311742143 rsyslog-8.2608.0/tools/rsyslog.conf.50000666000175000017500000007402615132733117016075 0ustar00rgerrger.\" rsyslog.conf - rsyslogd(8) configuration file .\" Copyright 2003-2008 Rainer Gerhards and Adiscon GmbH. .\" .\" This file is part of the rsyslog package, an enhanced system log daemon. .\" .\" 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 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, write to the Free Software .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. .\" .TH RSYSLOG.CONF 5 "18 February 2025" "Version 8.2502.0" "Linux System Administration" .SH NAME rsyslog.conf \- rsyslogd(8) configuration file .SH DESCRIPTION The .I rsyslog.conf file is the main configuration file for the .BR rsyslogd (8) which logs system messages on *nix systems. This file specifies rules for logging. For special features see the .BR rsyslogd (8) manpage. Rsyslog.conf is backward-compatible with sysklogd's syslog.conf file. So if you migrate from sysklogd you can rename it and it should work. .B Note that this version of rsyslog ships with extensive documentation in HTML format. This is provided in the ./doc subdirectory and probably in a separate package if you installed rsyslog via a packaging system. To use rsyslog's advanced features, you .B need to look at the HTML documentation, because the man pages only cover basic aspects of operation. .SH MODULES Rsyslog has a modular design. Consequently, there is a growing number of modules. See the HTML documentation for their full description. .TP .I omsnmp SNMP trap output module .TP .I omgssapi Output module for GSS-enabled syslog .TP .I ommysql Output module for MySQL .TP .I omrelp Output module for the reliable RELP protocol (prevents message loss). For details, see below at imrelp and the HTML documentation. It can be used like this: .IP *.* :omrelp:server:port .IP *.* :omrelp:192.168.0.1:2514 # actual sample .TP .I ompgsql Output module for PostgreSQL .TP .I omlibdbi Generic database output module (Firebird/Interbase, MS SQL, Sybase, SQLite, Ingres, Oracle, mSQL) .TP .I imfile Input module for text files .TP .I imudp Input plugin for UDP syslog. Replaces the deprecated -r option. Can be used like this: .IP $ModLoad imudp .IP $UDPServerRun 514 .TP .I imtcp Input plugin for plain TCP syslog. Replaces the deprecated -t option. Can be used like this: .IP $ModLoad imtcp .IP $InputTCPServerRun 514 .TP .TP .I imrelp Input plugin for the RELP protocol. RELP can be used instead of UDP or plain TCP syslog to provide reliable delivery of syslog messages. Please note that plain TCP syslog does NOT provide truly reliable delivery, with it messages may be lost when there is a connection problem or the server shuts down. RELP prevents message loss in those cases. It can be used like this: .IP $ModLoad imrelp .IP $InputRELPServerRun 2514 .TP .I imgssapi Input plugin for plain TCP and GSS-enable syslog .TP .I immark Support for mark messages .TP .I imklog Kernel logging. To include kernel log messages, you need to do .IP $ModLoad imklog Please note that the klogd daemon is no longer necessary and consequently no longer provided by the rsyslog package. .TP .I imuxsock Unix sockets, including the system log socket. You need to specify .IP $ModLoad imuxsock in order to receive log messages from local system processes. This config directive should only left out if you know exactly what you are doing. .SH BASIC STRUCTURE Lines starting with a hash mark ('#') and empty lines are ignored. Rsyslog.conf should contain following sections (sorted by recommended order in file): .TP Global directives Global directives set some global properties of whole rsyslog daemon, for example size of main message queue ($MainMessageQueueSize), loading external modules ($ModLoad) and so on. All global directives need to be specified on a line by their own and must start with a dollar-sign. The complete list of global directives can be found in HTML documentation in doc directory or online on web pages. .TP Templates Templates allow you to specify format of the logged message. They are also used for dynamic file name generation. They have to be defined before they are used in rules. For more info about templates see TEMPLATES section of this manpage. .TP Output channels Output channels provide an umbrella for any type of output that the user might want. They have to be defined before they are used in rules. For more info about output channels see OUTPUT CHANNELS section of this manpage. .TP Rules (selector + action) Every rule line consists of two fields, a selector field and an action field. These two fields are separated by one or more spaces or tabs. The selector field specifies a pattern of facilities and priorities belonging to the specified action. .SH SELECTORS The selector field itself again consists of two parts, a facility and a priority, separated by a period ('.'). Both parts are case insensitive and can also be specified as decimal numbers, but don't do that, you have been warned. Both facilities and priorities are described in syslog(3). The names mentioned below correspond to the similar LOG_-values in /usr/include/syslog.h. The facility is one of the following keywords: auth, authpriv, cron, daemon, kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and local0 through local7. The keyword security should not be used anymore and mark is only for internal use and therefore should not be used in applications. Anyway, you may want to specify and redirect these messages here. The facility specifies the subsystem that produced the message, i.e. all mail programs log with the mail facility (LOG_MAIL) if they log using syslog. The priority is one of the following keywords, in ascending order: debug, info, notice, warning, warn (same as warning), err, error (same as err), crit, alert, emerg, panic (same as emerg). The keywords error, warn and panic are deprecated and should not be used anymore. The priority defines the severity of the message. The behavior of the original BSD syslogd is that all messages of the specified priority and higher are logged according to the given action. Rsyslogd behaves the same, but has some extensions. In addition to the above mentioned names the rsyslogd(8) understands the following extensions: An asterisk ('*') stands for all facilities or all priorities, depending on where it is used (before or after the period). The keyword none stands for no priority of the given facility. You can specify multiple facilities with the same priority pattern in one statement using the comma (',') operator. You may specify as much facilities as you want. Remember that only the facility part from such a statement is taken, a priority part would be skipped. Multiple selectors may be specified for a single action using the semicolon (';') separator. Remember that each selector in the selector field is capable to overwrite the preceding ones. Using this behavior you can exclude some priorities from the pattern. Rsyslogd has a syntax extension to the original BSD source, that makes its use more intuitively. You may precede every priority with an equals sign ('=') to specify only this single priority and not any of the above. You may also (both is valid, too) precede the priority with an exclamation mark ('!') to ignore all that priorities, either exact this one or this and any higher priority. If you use both extensions then the exclamation mark must occur before the equals sign, just use it intuitively. However, please note that there are some restrictions over the traditional BSD syslog behaviour. These restrictions stem back to sysklogd, exist probably since at least the 1990's and as such have always been in rsyslog. Namely, in BSD syslogd you can craft a selector like this: *.debug;local6.err The intent is to log all facilities at debug or higher, except for local6, which should only log at err or higher. Unfortunately, local6.err will permit error severity and higher, but will not exclude lower severity messages from facility local6. As an alternative, you can explicitly exclude all severities that you do not want to match. For the above case, this selector is equivalent to the BSD syslog selector: *.debug;local6.!=info;local6.!=notice;local6.!=warn An easier approach is probably to do if ... then based matching in script. .SH ACTIONS The action field of a rule describes what to do with the message. In general, message content is written to a kind of "logfile". But also other actions might be done, like writing to a database table or forwarding to another host. .SS Regular file Typically messages are logged to real files. The file has to be specified with full pathname, beginning with a slash ('/'). .B Example: .RS *.* /var/log/traditionalfile.log;RSYSLOG_TraditionalFileFormat # log to a file in the traditional format .RE Note: if you would like to use high-precision timestamps in your log files, just remove the ";RSYSLOG_TraditionalFormat". That will select the default template, which, if not changed, uses RFC 3339 timestamps. .B Example: .RS *.* /var/log/file.log # log to a file with RFC3339 timestamps .RE By default, files are not synced after each write. To enable syncing of log files globally, use either the "$ActionFileEnableSync" directive or the "sync" parameter to omfile. Enabling this option degrades performance and it is advised not to enable syncing unless you know what you are doing. To selectively disable syncing for certain files, you may prefix the file path with a minus sign ("-"). .SS Named pipes This version of rsyslogd(8) has support for logging output to named pipes (fifos). A fifo or named pipe can be used as a destination for log messages by prepending a pipe symbol ('|') to the name of the file. This is handy for debugging. Note that the fifo must be created with the mkfifo(1) command before rsyslogd(8) is started. .SS Terminal and console If the file you specified is a tty, special tty-handling is done, same with /dev/console. .SS Remote machine There are three ways to forward message: the traditional UDP transport, which is extremely lossy but standard, the plain TCP based transport which loses messages only during certain situations but is widely available and the RELP transport which does not lose messages but is currently available only as part of rsyslogd 3.15.0 and above. To forward messages to another host via UDP, prepend the hostname with the at sign ("@"). To forward it via plain tcp, prepend two at signs ("@@"). To forward via RELP, prepend the string ":omrelp:" in front of the hostname. .B Example: .RS *.* @192.168.0.1 .RE .sp In the example above, messages are forwarded via UDP to the machine 192.168.0.1, the destination port defaults to 514. Due to the nature of UDP, you will probably lose some messages in transit. If you expect high traffic volume, you can expect to lose a quite noticeable number of messages (the higher the traffic, the more likely and severe is message loss). Sockets for forwarded messages can be bound to a specific device using the "device" option for the omfwd module. .B Example: .RS action(type="omfwd" Target="192.168.0.1" Device="eth0" Port="514" Protocol="udp") .RE .sp In the example above, messages are forwarded via UDP to the machine 192.168.0.1 at port 514 over the device eth0. TCP can be used by setting Protocol to "tcp" in the above example. For Linux with VRF support, the device option is used to specify the VRF to send messages. .B If you would like to prevent message loss, use RELP: .RS *.* :omrelp:192.168.0.1:2514 .RE .sp Note that a port number was given as there is no standard port for relp. Keep in mind that you need to load the correct input and output plugins (see "Modules" above). Please note that rsyslogd offers a variety of options in regarding to remote forwarding. For full details, please see the HTML documentation. .SS List of users Usually critical messages are also directed to ``root'' on that machine. You can specify a list of users that shall get the message by simply writing ":omusrmsg:" followed by the login name. You may specify more than one user by separating them with commas (','). If they're logged in they get the message (for example: ":omusrmsg:root,user1,user2"). .SS Everyone logged on Emergency messages often go to all users currently online to notify them that something strange is happening with the system. To specify this wall(1)-feature use an ":omusrmsg:*". .SS Database table This allows logging of the message to a database table. By default, a MonitorWare-compatible schema is required for this to work. You can create that schema with the createDB.SQL file that came with the rsyslog package. You can also use any other schema of your liking - you just need to define a proper template and assign this template to the action. See the HTML documentation for further details on database logging. .SS Discard If the discard action is carried out, the received message is immediately discarded. Discard can be highly effective if you want to filter out some annoying messages that otherwise would fill your log files. To do that, place the discard actions early in your log files. This often plays well with property-based filters, giving you great freedom in specifying what you do not want. Discard is just the single 'stop' command with no further parameters. .sp .B Example: .RS *.* stop # discards everything. .RE .SS Output channel Binds an output channel definition (see there for details) to this action. Output channel actions must start with a $-sign, e.g. if you would like to bind your output channel definition "mychannel" to the action, use "$mychannel". Output channels support template definitions like all all other actions. .SS Shell execute This executes a program in a subshell. The program is passed the template-generated message as the only command line parameter. Rsyslog waits until the program terminates and only then continues to run. .B Example: .RS ^program-to-execute;template .RE The program-to-execute can be any valid executable. It receives the template string as a single parameter (argv[1]). .SH FILTER CONDITIONS Rsyslog offers three different types "filter conditions": .sp 0 * "traditional" severity and facility based selectors .sp 0 * property-based filters .sp 0 * expression-based filters .RE .SS Selectors .B Selectors are the traditional way of filtering syslog messages. They have been kept in rsyslog with their original syntax, because it is well-known, highly effective and also needed for compatibility with stock syslogd configuration files. If you just need to filter based on priority and facility, you should do this with selector lines. They are not second-class citizens in rsyslog and offer the best performance for this job. .SS Property-Based Filters Property-based filters are unique to rsyslogd. They allow one to filter on any property, like HOSTNAME, syslogtag and msg. A property-based filter must start with a colon in column 0. This tells rsyslogd that it is the new filter type. The colon must be followed by the property name, a comma, the name of the compare operation to carry out, another comma and then the value to compare against. This value must be quoted. There can be spaces and tabs between the commas. Property names and compare operations are case-sensitive, so "msg" works, while "MSG" is an invalid property name. In brief, the syntax is as follows: .sp .RS :property, [!]compare-operation, "value" .RE The following compare-operations are currently supported: .sp .RS .B contains .RS Checks if the string provided in value is contained in the property .RE .sp .B isequal .RS Compares the "value" string provided and the property contents. These two values must be exactly equal to match. .RE .sp .B startswith .RS Checks if the value is found exactly at the beginning of the property value .RE .sp .B regex .RS Compares the property against the provided regular expression. .RE .SS Expression-Based Filters See the HTML documentation for this feature. .SH TEMPLATES Every output in rsyslog uses templates - this holds true for files, user messages and so on. Templates compatible with the stock syslogd formats are hardcoded into rsyslogd. If no template is specified, we use one of these hardcoded templates. Search for "template_" in syslogd.c and you will find the hardcoded ones. A template consists of a template directive, a name, the actual template text and optional options. A sample is: .RS .B $template MyTemplateName,"\\\\7Text %property% some more text\\\\n", .RE The "$template" is the template directive. It tells rsyslog that this line contains a template. The backslash is an escape character. For example, \\7 rings the bell (this is an ASCII value), \\n is a new line. The set in rsyslog is a bit restricted currently. All text in the template is used literally, except for things within percent signs. These are properties and allow you access to the contents of the syslog message. Properties are accessed via the property replacer and it can for example pick a substring or do date-specific formatting. More on this is the PROPERTY REPLACER section of this manpage. To escape: .sp 0 % = \\% .sp 0 \\ = \\\\ --> '\\' is used to escape (as in C) .sp 0 $template TraditionalFormat,"%timegenerated% %HOSTNAME% %syslogtag%%msg%\\n" Properties can be accessed by the property replacer (see there for details). .B Please note that templates can also by used to generate selector lines with dynamic file names. For example, if you would like to split syslog messages from different hosts to different files (one per host), you can define the following template: .RS .B $template DynFile,"/var/log/system-%HOSTNAME%.log" .RE This template can then be used when defining an output selector line. It will result in something like "/var/log/system-localhost.log" .SS Template options The part is optional. It carries options influencing the template as whole. See details below. Be sure NOT to mistake template options with property options - the later ones are processed by the property replacer and apply to a SINGLE property, only (and not the whole template). Template options are case-insensitive. Currently defined are: .RS .TP sql format the string suitable for a SQL statement in MySQL format. This will replace single quotes ("'") and the backslash character by their backslash-escaped counterpart ("\'" and "\\") inside each field. Please note that in MySQL configuration, the NO_BACKSLASH_ESCAPES mode must be turned off for this format to work (this is the default). .TP stdsql format the string suitable for a SQL statement that is to be sent to a standards-compliant sql server. This will replace single quotes ("'") by two single quotes ("''") inside each field. You must use stdsql together with MySQL if in MySQL configuration the NO_BACKSLASH_ESCAPES is turned on. .RE Either the .B sql or .B stdsql option .B MUST be specified when a template is used for writing to a database, otherwise injection might occur. Please note that due to the unfortunate fact that several vendors have violated the sql standard and introduced their own escape methods, it is impossible to have a single option doing all the work. So you yourself must make sure you are using the right format. .B If you choose the wrong one, you are still vulnerable to sql injection. Please note that the database writer *checks* that the sql option is present in the template. If it is not present, the write database action is disabled. This is to guard you against accidental forgetting it and then becoming vulnerable to SQL injection. The sql option can also be useful with files - especially if you want to import them into a database on another machine for performance reasons. However, do NOT use it if you do not have a real need for it - among others, it takes some toll on the processing time. Not much, but on a really busy system you might notice it ;) The default template for the write to database action has the sql option set. .SS Template examples Please note that the samples are split across multiple lines. A template MUST NOT actually be split across multiple lines. A template that resembles traditional syslogd file output: .sp .RS $template TraditionalFormat,"%timegenerated% %HOSTNAME% .sp 0 %syslogtag%%msg:::drop-last-lf%\\n" .RE A template that tells you a little more about the message: .sp .RS $template precise,"%syslogpriority%,%syslogfacility%,%timegenerated%,%HOSTNAME%, .sp 0 %syslogtag%,%msg%\\n" .RE A template for RFC 3164 format: .sp .RS $template RFC3164fmt,"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%" .RE A template for the format traditionally used for user messages: .sp .RS $template usermsg," XXXX%syslogtag%%msg%\\n\\r" .RE And a template with the traditional wall-message format: .sp .RS $template wallmsg,"\\r\\n\\7Message from syslogd@%HOSTNAME% at %timegenerated%" .RE .B A template that can be used for writing to a database (please note the SQL template option) .sp .RS .ad l $template MySQLInsert,"insert iut, message, receivedat values ('%iut%', '%msg:::UPPERCASE%', '%timegenerated:::date-mysql%') into systemevents\\r\\n", SQL NOTE 1: This template is embedded into core application under name .B StdDBFmt , so you don't need to define it. .sp NOTE 2: You have to have MySQL module installed to use this template. .ad .RE .SH OUTPUT CHANNELS Output Channels are a new concept first introduced in rsyslog 0.9.0. As of this writing, it is most likely that they will be replaced by something different in the future. So if you use them, be prepared to change you configuration file syntax when you upgrade to a later release. Output channels are defined via an $outchannel directive. It's syntax is as follows: .sp .RS .B $outchannel name,file-name,max-size,action-on-max-size .RE name is the name of the output channel (not the file), file-name is the file name to be written to, max-size the maximum allowed size and action-on-max-size a command to be issued when the max size is reached. This command always has exactly one parameter. The binary is that part of action-on-max-size before the first space, its parameter is everything behind that space. Keep in mind that $outchannel just defines a channel with "name". It does not activate it. To do so, you must use a selector line (see below). That selector line includes the channel name plus ":omfile:$" in front of it. A sample might be: .sp .RS *.* :omfile:$mychannel .RE .SH PROPERTY REPLACER The property replacer is a core component in rsyslogd's output system. A syslog message has a number of well-defined properties (see below). Each of this properties can be accessed and manipulated by the property replacer. With it, it is easy to use only part of a property value or manipulate the value, e.g. by converting all characters to lower case. .SS Accessing Properties Syslog message properties are used inside templates. They are accessed by putting them between percent signs. Properties can be modified by the property replacer. The full syntax is as follows: .sp .RS .B %propname:fromChar:toChar:options% .RE propname is the name of the property to access. .B It is case-sensitive. .SS Available Properties .TP .B msg the MSG part of the message (aka "the message" ;)) .TP .B rawmsg the message exactly as it was received from the socket. Should be useful for debugging. .TP .B HOSTNAME hostname from the message .TP .B FROMHOST hostname of the system the message was received from (in a relay chain, this is the system immediately in front of us and not necessarily the original sender) .TP .B syslogtag TAG from the message .TP .B programname the "static" part of the tag, as defined by BSD syslogd. For example, when TAG is "named[12345]", programname is "named". .TP .B PRI PRI part of the message - undecoded (single value) .TP .B PRI-text the PRI part of the message in a textual form (e.g. "syslog.info") .TP .B IUT the monitorware InfoUnitType - used when talking to a MonitorWare backend (also for phpLogCon) .TP .B syslogfacility the facility from the message - in numerical form .TP .B syslogfacility-text the facility from the message - in text form .TP .B syslogseverity severity from the message - in numerical form .TP .B syslogseverity-text severity from the message - in text form .TP .B timegenerated timestamp when the message was RECEIVED. Always in high resolution .TP .B timereported timestamp from the message. Resolution depends on what was provided in the message (in most cases, only seconds) .TP .B TIMESTAMP alias for timereported .TP .B PROTOCOL-VERSION The contents of the PROTOCOL-VERSION field from IETF draft draft-ietf-syslog-protocol .TP .B STRUCTURED-DATA The contents of the STRUCTURED-DATA field from IETF draft draft-ietf-syslog-protocol .TP .B APP-NAME The contents of the APP-NAME field from IETF draft draft-ietf-syslog-protocol .TP .B PROCID The contents of the PROCID field from IETF draft draft-ietf-syslog-protocol .TP .B MSGID The contents of the MSGID field from IETF draft draft-ietf-syslog-protocol .TP .B $NOW The current date stamp in the format YYYY-MM-DD .TP .B $YEAR The current year (4-digit) .TP .B $MONTH The current month (2-digit) .TP .B $DAY The current day of the month (2-digit) .TP .B $HOUR The current hour in military (24 hour) time (2-digit) .TP .B $MINUTE The current minute (2-digit) .P Properties starting with a $-sign are so-called system properties. These do NOT stem from the message but are rather internally-generated. .SS Character Positions FromChar and toChar are used to build substrings. They specify the offset within the string that should be copied. Offset counting starts at 1, so if you need to obtain the first 2 characters of the message text, you can use this syntax: "%msg:1:2%". If you do not wish to specify from and to, but you want to specify options, you still need to include the colons. For example, if you would like to convert the full message text to lower case, use "%msg:::lowercase%". If you would like to extract from a position until the end of the string, you can place a dollar-sign ("$") in toChar (e.g. %msg:10:$%, which will extract from position 10 to the end of the string). There is also support for .B regular expressions. To use them, you need to place a "R" into FromChar. This tells rsyslog that a regular expression instead of position-based extraction is desired. The actual regular expression .B must then be provided in toChar. The regular expression must be followed by the string "--end". It denotes the end of the regular expression and will not become part of it. If you are using regular expressions, the property replacer will return the part of the property text that matches the regular expression. An example for a property replacer sequence with a regular expression is: "%msg:R:.*Sev:. \\(.*\\) \\[.*--end%" Also, extraction can be done based on so-called "fields". To do so, place a "F" into FromChar. A field in its current definition is anything that is delimited by a delimiter character. The delimiter by default is TAB (US-ASCII value 9). However, if can be changed to any other US-ASCII character by specifying a comma and the decimal US-ASCII value of the delimiter immediately after the "F". For example, to use comma (",") as a delimiter, use this field specifier: "F,44". If your syslog data is delimited, this is a quicker way to extract than via regular expressions (actually, a *much* quicker way). Field counting starts at 1. Field zero is accepted, but will always lead to a "field not found" error. The same happens if a field number higher than the number of fields in the property is requested. The field number must be placed in the "ToChar" parameter. An example where the 3rd field (delimited by TAB) from the msg property is extracted is as follows: "%msg:F:3%". The same example with semicolon as delimiter is "%msg:F,59:3%". Please note that the special characters "F" and "R" are case-sensitive. Only upper case works, lower case will return an error. There are no white spaces permitted inside the sequence (that will lead to error messages and will NOT provide the intended result). .SS Property Options Property options are case-insensitive. Currently, the following options are defined: .TP uppercase convert property to lowercase only .TP lowercase convert property text to uppercase only .TP drop-last-lf The last LF in the message (if any), is dropped. Especially useful for PIX. .TP date-mysql format as mysql date .TP date-rfc3164 format as RFC 3164 date .TP date-rfc3339 format as RFC 3339 date .TP escape-cc replace control characters (ASCII value 127 and values less then 32) with an escape sequence. The sequence is "#" where charval is the 3-digit decimal value of the control character. For example, a tabulator would be replaced by "#009". .TP space-cc replace control characters by spaces .TP drop-cc drop control characters - the resulting string will neither contain control characters, escape sequences nor any other replacement character like space. .SH QUEUED OPERATIONS Rsyslogd supports queued operations to handle offline outputs (like remote syslogd's or database servers being down). When running in queued mode, rsyslogd buffers messages to memory and optionally to disk (on an as-needed basis). Queues survive rsyslogd restarts. It is highly suggested to use remote forwarding and database writing in queued mode, only. To learn more about queued operations, see the HTML documentation. .SH FILES .PD 0 .TP .I /etc/rsyslog.conf Configuration file for .B rsyslogd .SH SEE ALSO .BR rsyslogd (8), .BR logger (1), .BR syslog (3) The complete documentation can be found in the doc folder of the rsyslog distribution or online at .RS .B https://www.rsyslog.com/doc/ .RE Please note that the man page reflects only a subset of the configuration options. Be sure to read the HTML documentation for all features and details. This is especially vital if you plan to set up a more-then-extremely-simple system. .SH AUTHORS .B rsyslogd is taken from sysklogd sources, which have been heavily modified by Rainer Gerhards (rgerhards@adiscon.com) and others. rsyslog-8.2608.0/tools/PaxHeaders/pmrfc3164.h0000644000000000000000000000013015241075234015476 xustar0030 mtime=1787067036.651579156 29 atime=1787067036.80458202 29 ctime=1787067795.26974136 rsyslog-8.2608.0/tools/pmrfc3164.h0000664000175000017500000000262315241075234015147 0ustar00rgerrger/* pmrfc3164.h * These are the definitions for the RFC3164 parser module. * * File begun on 2009-11-04 by RGerhards * * Copyright 2009 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef PMRFC3164_H_INCLUDED #define PMRFC3164_H_INCLUDED 1 /* prototypes */ rsRetVal modInitpmrfc3164(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #ifdef ENABLE_FUZZING rsRetVal pmrfc3164FuzzInit(void); void pmrfc3164FuzzExit(void); rsRetVal pmrfc3164FuzzParse(smsg_t *pMsg); #endif #endif /* #ifndef PMRFC3164_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/rscryutil.rst0000644000000000000000000000013215132733117016474 xustar0030 mtime=1768666703.972621223 30 atime=1782715518.784788772 30 ctime=1787067795.316742236 rsyslog-8.2608.0/tools/rscryutil.rst0000666000175000017500000001355615132733117016154 0ustar00rgerrger========= rscryutil ========= -------------------------- Manage Encrypted Log Files -------------------------- :Author: Rainer Gerhards :Date: 2013-04-15 :Manual section: 1 SYNOPSIS ======== :: rscryutil [OPTIONS] [FILE] ... DESCRIPTION =========== This tool performs various operations on encrypted log files. Most importantly, it provides the ability to decrypt them. OPTIONS ======= -d, --decrypt Select decryption mode. This is the default mode. -W, --write-keyfile Utility function to write a key to a keyfile. The key can be obtained via any method. -l, --lib Select the crypto library to be used. Either "ossl" or "gcry". Defaults to "gcry" or whatever is currently available. -v, --verbose Select verbose mode. -f, --force Forces operations that otherwise would fail. -k, --keyfile Reads the key from . File _must_ contain the key, only, no headers or other meta information. Keyfiles can be generated via the *--write-keyfile* option. -p, --key-program In this mode, the key is provided by a so-called "key program". This program is executed and must return the key to (as well as some meta information) via stdout. The core idea of key programs is that using this interface the user can implement as complex (and secure) method to obtain keys as desired, all without the need to make modifications to rsyslog. -K, --key TESTING AID, NOT FOR PRODUCTION USE. This uses the KEY specified on the command line. This is the actual key, and as such this mode is highly insecure. However, it can be useful for initial testing steps. This option may be removed in the future. -a, --algo Sets the encryption algorightm (cipher) to be used. Refer to the list of supported algorithms below for the "gcry" library. The default algorithm for "gcry" is "AES128". For the "ossl" library, both the algorithm and mode are specified using this option, with "AES-128-CBC" as the default. -m, --mode Sets the ciphermode to be used. See below for supported modes. The default is "CBC". In case of "ossl" library, this options is ignored. -r, --generate-random-key Generates a random key of length . This option is meant to be used together with *--write-keyfile* (and it is hard to envision any other valid use for it). OPERATION MODES =============== The operation mode specifies what exactly the tool does with the provided files. The default operation mode is "dump", but this may change in the future. Thus, it is recommended to always set the operations mode explicitely. If multiple operations mode are set on the command line, results are unpredictable. decrypt ------- The provided log files are decrypted. Note that the *.encinfo* side files must exist and be accessible in order for decryption to to work. write-keyfile ------------- In this mode no log files are processed; thus it is an error to specify any on the command line. The specified keyfile is written. The key itself is obtained via the usual key commands. If *--keyfile* is used, that file is effectively copied. For security reasons, existing key files are _not_ overwritten. To permit this, specify the *--force* option. When doing so, keep in mind that lost keys cannot be recovered and data encrypted with them may also be considered lost. Keyfiles are always created with 0400 permission, that is read access for only the user. An exception is when an existing file is overwritten via the *--force* option, in which case the former permissions still apply. EXIT CODES ========== The command returns an exit code of 0 if everything went fine, and some other code in case of failures. SUPPORTED ALGORITHMS ==================== In case of "ossl", see "ALGORITHM FETCHING" in crypto(7) for further information. In case of "gcry" we basically support what libgcrypt supports and that is: 3DES CAST5 BLOWFISH AES128 AES192 AES256 TWOFISH TWOFISH128 ARCFOUR DES SERPENT128 SERPENT192 SERPENT256 RFC2268_40 SEED CAMELLIA128 CAMELLIA192 CAMELLIA256 SUPPORTED CIPHER MODES ====================== In case of "gcry", we basically support what libgcrypt supports. This is: ECB CFB CBC STREAM OFB CTR AESWRAP EXAMPLES ======== **rscryutil logfile** Decrypts "logfile" and sends data to stdout. **rscryutil -k keyfile -l ossl -a AES-256-CBC encryptedfile** Decrypts encryptedfile using ossl library with AES256 algorithm and CBC mode **rscryutil -k keyfile -l gcry -a AES256 -m CBC encryptedfile** Decrypts encryptedfile using gcry library with AES256 algorithm and CBC mode **rscryutil --generate-random-key 16 --keyfile /some/secured/path/keyfile** Generates random key and stores it in the specified keyfile. LOG SIGNATURES ============== Encrypted log files can be used together with signing. To verify such a file, it must be decrypted first, and the verification tool **rsgtutil(1)** must be run on the decrypted file. SECURITY CONSIDERATIONS ======================= Specifying keys directly on the command line (*--key* option) is very insecure and should not be done, except for testing purposes with test keys. Even then it is recommended to use keyfiles, which are also easy to handle during testing. Keep in mind that command history is usally be kept by bash and can also easily be monitored. Local keyfiles are also a security risk. At a minimum, they should be used with very restrictive file permissions. For this reason, the *rscryutil* tool creates them with read permissions for the user, only, no matter what umask is set to. When selecting cipher algorithms and modes, care needs to be taken. The defaults should be reasonable safe to use, but this tends to change over time. Keep up with the most current crypto recommendations. SEE ALSO ======== **rsgtutil(1)**, **rsyslogd(8)** COPYRIGHT ========= This page is part of the *rsyslog* project, and is available under LGPLv2. rsyslog-8.2608.0/tools/PaxHeaders/omusrmsg.c0000644000000000000000000000013215220503174015716 xustar0030 mtime=1782744700.141046417 30 atime=1787067622.107513658 30 ctime=1787067795.239740801 rsyslog-8.2608.0/tools/omusrmsg.c0000664000175000017500000005047015220503174015370 0ustar00rgerrger/** * @file omusrmsg.c * @brief Implementation of the built-in user message output module. * * This module provides message delivery to logged-in users. Depending on * configuration it can either send messages to specific user terminals or * broadcast them using a "wall" style interface. * * NOTE: read comments in module-template.h to understand how this file works! * * File begun on 2007-07-20 by Rainer Gerhards (extracted from syslogd.c, * which at the time of the fork from sysklogd was under BSD license). * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef HAVE_UTMPX_H #include #define STRUCTUTMP struct utmpx #define UTNAME ut_user #define setutent setutxent #define getutent getutxent #define endutent endutxent #ifndef UT_LINESIZE /* __UT_LINESIZE for glibc; _UTX_LINESIZE common on Solaris */ #ifdef __UT_LINESIZE #define UT_LINESIZE __UT_LINESIZE #elif defined(_UTX_LINESIZE) #define UT_LINESIZE _UTX_LINESIZE #else /* method of last resort */ #define UT_LINESIZE 32 #endif #endif #elif defined(HAVE_UTMP_H) #include #define STRUCTUTMP struct utmp #define UTNAME ut_name #endif #include #include #include #include #if HAVE_FCNTL_H #include #else #include #endif #ifdef HAVE_PATHS_H #include #endif #ifndef _PATH_UTMP #define _PATH_UTMP "/var/run/utmp" #endif #ifdef HAVE_LIBSYSTEMD #include #include #include #endif #include "rsyslog.h" #include "srUtils.h" #include "stringbuf.h" #include "syslogd-types.h" #include "conf.h" #include "omusrmsg.h" #include "module-template.h" #include "errmsg.h" #include "ratelimit.h" /* portability: */ #ifndef _PATH_DEV #define _PATH_DEV "/dev/" #endif #ifdef UT_NAMESIZE #define UNAMESZ UT_NAMESIZE /* length of a login name */ #else #define UNAMESZ 32 /* length of a login name, 32 seems current (2018) good bet */ #endif #define MAXUNAMES 20 /* maximum number of user names */ #ifdef OS_SOLARIS #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omusrmsg") /* internal structures */ DEF_OMOD_STATIC_DATA; typedef struct _instanceData { int bIsWall; /* 1- is wall, 0 - individual users */ char uname[MAXUNAMES][UNAMESZ + 1]; uchar *tplName; int ratelimitInterval; int ratelimitBurst; uchar *pszRatelimitName; ratelimit_t *ratelimiter; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; struct modConfData_s { rsconf_t *pConf; }; static modConfData_t *loadModConf = NULL; static modConfData_t *runModConf = NULL; typedef struct configSettings_s { EMPTY_STRUCT } configSettings_t; static configSettings_t __attribute__((unused)) cs; /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = {{"users", eCmdHdlrString, CNFPARAM_REQUIRED}, {"template", eCmdHdlrGetWord, 0}, {"ratelimit.interval", eCmdHdlrInt, 0}, {"ratelimit.burst", eCmdHdlrInt, 0}, {"ratelimit.name", eCmdHdlrString, 0}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars; ENDinitConfVars BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; free(pData->tplName); free(pData->pszRatelimitName); if (pData->ratelimiter != NULL) { ratelimitDestruct(pData->ratelimiter); pData->ratelimiter = NULL; } ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINdbgPrintInstInfo register int i; CODESTARTdbgPrintInstInfo; for (i = 0; i < MAXUNAMES && *pData->uname[i]; i++) dbgprintf("%s, ", pData->uname[i]); ENDdbgPrintInstInfo /** * BSD setutent/getutent() replacement routines * The following routines emulate setutent() and getutent() under * BSD because they are not available there. We only emulate what we actually * need! rgerhards 2005-03-18 */ #ifdef OS_BSD /* Since version 900007, FreeBSD has a POSIX compliant */ #if defined(__FreeBSD__) && (__FreeBSD_version >= 900007) #ifndef setutent #define setutent() setutxent() #endif #ifndef getutent #define getutent() getutxent() #endif #ifndef endutent #define endutent() endutxent() #endif #else static FILE *BSD_uf = NULL; void setutent(void) { assert(BSD_uf == NULL); if ((BSD_uf = fopen(_PATH_UTMP, "r")) == NULL) { LogError(errno, NO_ERRCODE, "error opening utmp %s", _PATH_UTMP); return; } } STRUCTUTMP *getutent(void) { static STRUCTUTMP st_utmp; if (fread((char *)&st_utmp, sizeof(st_utmp), 1, BSD_uf) != 1) return NULL; return (&st_utmp); } void endutent(void) { fclose(BSD_uf); BSD_uf = NULL; } #endif /* if defined(__FreeBSD__) */ #endif /* #ifdef OS_BSD */ /** * Send a message to a specific terminal device. * * The function builds the full device path from the supplied tty name * and writes the message using non-blocking I/O so that a blocked * terminal does not stall the caller. * * @param tty terminal name (e.g. "pts/0") * @param pMsg message text to send */ static void sendwallmsg(const char *tty, uchar *pMsg) { uchar szErr[512]; int errnoSave; char p[sizeof(_PATH_DEV) + UT_LINESIZE]; int ttyf; struct stat statb; int wrRet; /* compute the device name */ RS_COPY_LITERAL(p, _PATH_DEV); size_t base_len = strlen(p); size_t avail = sizeof(p) - base_len - 1; size_t ttylen = strnlen(tty, avail); memcpy(p + base_len, tty, ttylen); p[base_len + ttylen] = '\0'; /* we must be careful when writing to the terminal. A terminal may block * (for example, a user has pressed -s). In that case, we can not * wait indefinitely. So we need to use non-blocking I/O. In case we would * block, we simply do not send the message, because that's the best we can * do. -- rgerhards, 2008-07-04 */ /* open the terminal */ if ((ttyf = open(p, O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) { if (fstat(ttyf, &statb) == 0 && (statb.st_mode & S_IWRITE)) { wrRet = write(ttyf, pMsg, strlen((char *)pMsg)); if (Debug && wrRet == -1) { /* we record the state to the debug log */ errnoSave = errno; rs_strerror_r(errno, (char *)szErr, sizeof(szErr)); dbgprintf("write to terminal '%s' failed with [%d]:%s\n", p, errnoSave, szErr); } } close(ttyf); } } /** * Write a message to the world at large. * * The message can either be broadcast to all logged-in users or sent only * to the set configured in @a pData. The implementation avoids forking a * helper process and instead performs delivery on the caller's thread. * * @param[in] pMsg message text to deliver * @param[in] pData per-action configuration * * @return rsRetVal */ static rsRetVal wallmsg(uchar *pMsg, instanceData *pData) { register int i; STRUCTUTMP ut; STRUCTUTMP *uptr; DEFiRet; assert(pMsg != NULL); #ifdef HAVE_LIBSYSTEMD if (sd_booted() > 0) { register int j; int sdRet; char **sessions_list = NULL; int sessions = sd_get_sessions(&sessions_list); for (j = 0; j < sessions; j++) { uchar szErr[512]; char *tty; const char *user = NULL; uid_t uid; struct passwd *pws; sdRet = sd_session_get_uid(sessions_list[j], &uid); if (sdRet >= 0) { pws = getpwuid(uid); if (pws == NULL) { LogError(0, NO_ERRCODE, "failed to get passwd for userid '%d'\n", uid); free(sessions_list[j]); continue; } user = pws->pw_name; /* DO NOT FREE, OS/LIB internal memory! */ if (user == NULL) { LogError(0, NO_ERRCODE, "failed to get username for userid '%d'\n", uid); free(sessions_list[j]); continue; } } else { /* we record the state to the debug log */ rs_strerror_r(-sdRet, (char *)szErr, sizeof(szErr)); LogError(0, NO_ERRCODE, "get userid for session '%s' failed with [%d]:%s\n", sessions_list[j], -sdRet, szErr); free(sessions_list[j]); continue; /* try next session */ } /* should we send the message to this user? */ if (pData->bIsWall == 0) { for (i = 0; i < MAXUNAMES; i++) { if (!pData->uname[i][0]) { i = MAXUNAMES; break; } if (strncmp(pData->uname[i], user, UNAMESZ) == 0) break; } if (i == MAXUNAMES) { /* user not found? */ free(sessions_list[j]); continue; /* on to next user! */ } } if ((sdRet = sd_session_get_tty(sessions_list[j], &tty)) < 0) { /* we record the state to the debug log */ rs_strerror_r(-sdRet, (char *)szErr, sizeof(szErr)); LogError(0, NO_ERRCODE, "get tty for session '%s' failed with [%d]:%s\n", sessions_list[j], -sdRet, szErr); free(sessions_list[j]); continue; /* try next session */ } sendwallmsg(tty, pMsg); free(tty); free(sessions_list[j]); } free(sessions_list); } else { #endif /* open the user login file */ setutent(); /* scan the user login file */ while ((uptr = getutent())) { memcpy(&ut, uptr, sizeof(ut)); /* is this slot used? */ if (ut.UTNAME[0] == '\0') continue; #ifndef OS_BSD if (ut.ut_type != USER_PROCESS) continue; #endif if (!(memcmp(ut.UTNAME, "LOGIN", 6))) /* paranoia */ continue; /* should we send the message to this user? */ if (pData->bIsWall == 0) { for (i = 0; i < MAXUNAMES; i++) { if (!pData->uname[i][0]) { i = MAXUNAMES; break; } if (strncmp(pData->uname[i], ut.UTNAME, UNAMESZ) == 0) break; } if (i == MAXUNAMES) /* user not found? */ continue; /* on to next user! */ } sendwallmsg(ut.ut_line, pMsg); } /* close the user login file */ endutent(); #ifdef HAVE_LIBSYSTEMD } #endif RETiRet; } BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINdoAction CODESTARTdoAction; dbgprintf("\n"); if (pWrkrData->pData->ratelimiter == NULL || ratelimitMsgCount(pWrkrData->pData->ratelimiter, 0, "omusrmsg") != RS_RET_DISCARDMSG) { iRet = wallmsg(ppString[0], pWrkrData->pData); } ENDdoAction static void /** * Parse a comma separated list of usernames. * * The user list is copied into the instance data. Whitespace is skipped * and overly long names are reported via the error log. If more than * MAXUNAMES users are specified, excess entries are ignored. * * @param[in] pData Instance configuration to populate * @param[in] usrs comma separated list of users */ populateUsers(instanceData *pData, es_str_t *usrs) { int i; int iDst; es_size_t iUsr; es_size_t len; uchar *c; len = es_strlen(usrs); c = es_getBufAddr(usrs); pData->bIsWall = 0; /* write to individual users */ iUsr = 0; for (i = 0; i < MAXUNAMES && iUsr < len; ++i) { for (iDst = 0; iDst < UNAMESZ && iUsr < len && c[iUsr] != ','; ++iDst, ++iUsr) { pData->uname[i][iDst] = c[iUsr]; } pData->uname[i][iDst] = '\0'; DBGPRINTF("omusrmsg: send to user '%s'\n", pData->uname[i]); if (iUsr < len && c[iUsr] != ',') { LogError(0, RS_RET_ERR, "user name '%s...' too long - " "ignored", pData->uname[i]); --i; ++iUsr; while (iUsr < len && c[iUsr] != ',') ++iUsr; /* skip to next name */ } else if (iDst == 0) { LogError(0, RS_RET_ERR, "no user name given - " "ignored"); --i; ++iUsr; while (iUsr < len && c[iUsr] != ',') ++iUsr; /* skip to next name */ } if (iUsr < len) { ++iUsr; /* skip "," */ while (iUsr < len && isspace(c[iUsr])) ++iUsr; /* skip whitespace */ } } if (i == MAXUNAMES && iUsr != len) { LogError(0, RS_RET_ERR, "omusrmsg supports only up to %d " "user names in a single action - all others have been ignored", MAXUNAMES); } } static inline void setInstParamDefaults(instanceData *pData) { pData->bIsWall = 0; pData->tplName = NULL; pData->ratelimiter = NULL; pData->ratelimitInterval = -1; pData->ratelimitBurst = -1; pData->pszRatelimitName = NULL; } BEGINnewActInst struct cnfparamvals *pvals; int i; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); CODE_STD_STRING_REQUESTnewActInst(1); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "users")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"*", 1)) { pData->bIsWall = 1; } else { populateUsers(pData, pvals[i].val.d.estr); } } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "ratelimit.interval")) { pData->ratelimitInterval = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.burst")) { pData->ratelimitBurst = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.name")) { CHKmalloc(pData->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { dbgprintf( "omusrmsg: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } if (pData->pszRatelimitName != NULL) { if (pData->ratelimitInterval != -1 || pData->ratelimitBurst != -1) { LogError(0, RS_RET_INVALID_PARAMS, "omusrmsg: ratelimit.name is mutually exclusive with " "ratelimit.interval and ratelimit.burst - using ratelimit.name"); } pData->ratelimitInterval = 0; pData->ratelimitBurst = 0; } else { if (pData->ratelimitInterval == -1) pData->ratelimitInterval = 0; if (pData->ratelimitBurst == -1) pData->ratelimitBurst = 200; } if (pData->tplName == NULL) { CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)strdup(pData->bIsWall ? " WallFmt" : " StdUsrMsgFmt"), OMSR_NO_RQD_TPL_OPTS)); } else { CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)strdup((char *)pData->tplName), OMSR_NO_RQD_TPL_OPTS)); } if (pData->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfig(&pData->ratelimiter, loadModConf->pConf, (char *)pData->pszRatelimitName, "omusrmsg", NULL)); ratelimitSetNoTimeCache(pData->ratelimiter); } else if (pData->ratelimitInterval > 0) { CHKiRet(ratelimitNew(&pData->ratelimiter, "omusrmsg", NULL)); ratelimitSetLinuxLike(pData->ratelimiter, (unsigned)pData->ratelimitInterval, (unsigned)pData->ratelimitBurst); ratelimitSetNoTimeCache(pData->ratelimiter); } if (pData->ratelimiter != NULL) { ratelimitSetThreadSafe(pData->ratelimiter); } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINparseSelectorAct es_str_t *usrs; int bHadWarning; CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) bHadWarning = 0; if (!strncmp((char *)p, ":omusrmsg:", sizeof(":omusrmsg:") - 1)) { p += sizeof(":omusrmsg:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ } else { if (!*p || !((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_' || *p == '.' || *p == '*')) { ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); } else { LogMsg(0, RS_RET_OUTDATED_STMT, LOG_WARNING, "action '%s' treated as ':omusrmsg:%s' - please " "use ':omusrmsg:%s' syntax instead, '%s' will " "not be supported in the future", p, p, p, p); bHadWarning = 1; } } CHKiRet(createInstance(&pData)); if (*p == '*') { /* wall */ dbgprintf("write-all"); ++p; /* eat '*' */ pData->bIsWall = 1; /* write to all users */ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar *)" WallFmt")); } else { /* everything else is currently treated as a user name */ usrs = es_newStr(128); while (*p && *p != ';') { es_addChar(&usrs, *p); ++p; } populateUsers(pData, usrs); es_deleteStr(usrs); if ((iRet = cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar *)" StdUsrMsgFmt")) != RS_RET_OK) goto finalize_it; } if (iRet == RS_RET_OK && bHadWarning) iRet = RS_RET_OK_WARN; CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInitNoPredecl(UsrMsg) CODESTARTmodInit; INITLegCnfVars; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr; ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/rsyslog-segqueue0000644000000000000000000000013215241075234017150 xustar0030 mtime=1787067036.651579156 30 atime=1787067036.805582039 30 ctime=1787067795.222740485 rsyslog-8.2608.0/tools/rsyslog-segqueue0000775000175000017500000017765515241075234016644 0ustar00rgerrger#!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 """Inspect, export, and repair rsyslog segmentedDisk queue stores.""" import argparse import base64 import datetime import errno import json import os import re import shutil import stat import struct import sys import tempfile SEG_MAGIC = b"RSSEGH02" REC_MAGIC = b"RSRECD02" FOOT_MAGIC = b"RSSEAL02" STATE_MAGIC = b"RSSEGST2" STORE_VERSION = 2 CODEC_VERSION = 1 SEG_HEADER_LEN = 52 RECORD_HEADER_LEN = 32 FOOTER_LEN = 48 STATE_SLOT_LEN = 256 STATE_FILE_LEN = 2 * STATE_SLOT_LEN MAX_RECORD_SIZE = 128 * 1024 * 1024 STATE_FLAG_RECOVERY = 1 STATE_FLAG_DEMATERIALIZING = 2 KNOWN_STATE_FLAGS = STATE_FLAG_RECOVERY | STATE_FLAG_DEMATERIALIZING SEGMENT_RE = re.compile(r"^segment-([0-9]{20})\.(seg|recover|open)$") UINT64_MASK = (1 << 64) - 1 UINT32_UNSET = (1 << 32) - 1 TLV_U8 = 1 TLV_U16 = 2 TLV_U32 = 3 TLV_U64 = 4 TLV_BYTES = 5 TLV_TIME = 6 TLV_CRITICAL = 1 FIELD_NAMES = { 1: "protocol_version", 2: "severity", 3: "facility", 4: "flags", 5: "timegenerated_unix", 6: "timereceived", 7: "timereported", 8: "tag", 9: "rawmsg", 10: "hostname", 11: "inputname", 12: "fromhost", 13: "fromhost_ip", 14: "fromhost_port", 15: "structured_data", 16: "json", 17: "localvars", 18: "app_name", 19: "procid", 20: "msgid", 21: "uuid", 22: "ruleset", 23: "msg_offset", 24: "after_pri_offset", 25: "parse_success", } FIELD_TYPES = { 1: (TLV_U16, 2), 2: (TLV_U16, 2), 3: (TLV_U16, 2), 4: (TLV_U32, 4), 5: (TLV_U64, 8), 6: (TLV_TIME, 20), 7: (TLV_TIME, 20), 8: (TLV_BYTES, None), 9: (TLV_BYTES, None), 10: (TLV_BYTES, None), 11: (TLV_BYTES, None), 12: (TLV_BYTES, None), 13: (TLV_BYTES, None), 14: (TLV_BYTES, None), 15: (TLV_BYTES, None), 16: (TLV_BYTES, None), 17: (TLV_BYTES, None), 18: (TLV_BYTES, None), 19: (TLV_BYTES, None), 20: (TLV_BYTES, None), 21: (TLV_BYTES, None), 22: (TLV_BYTES, None), 23: (TLV_U32, 4), 24: (TLV_U32, 4), 25: (TLV_U8, 1), } TEXT_FIELDS = { 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 22, } class QueueToolError(Exception): """Operational or invocation error with a user-facing explanation.""" def crc32c(data): crc = 0xFFFFFFFF for byte in data: crc ^= byte for _ in range(8): crc = (crc >> 1) ^ (0x82F63B78 if crc & 1 else 0) return (~crc) & 0xFFFFFFFF def unpack_u16(data, offset): return struct.unpack_from(">H", data, offset)[0] def unpack_u32(data, offset): return struct.unpack_from(">I", data, offset)[0] def unpack_u64(data, offset): return struct.unpack_from(">Q", data, offset)[0] def unpack_i64(data, offset): return struct.unpack_from(">q", data, offset)[0] def pack_u16(value): return struct.pack(">H", value) def pack_u32(value): return struct.pack(">I", value) def pack_u64(value): return struct.pack(">Q", value & UINT64_MASK) def generation_newer(candidate, reference): if candidate == reference: return False return ((candidate - reference) & UINT64_MASK) < (1 << 63) def uuid_text(value): if value is None or len(value) != 16: return None raw = value.hex() return "{}-{}-{}-{}-{}".format(raw[:8], raw[8:12], raw[12:16], raw[16:20], raw[20:]) def add_issue(report, severity, code, message, path=None, segment=None, offset=None, repair=None): issue = {"severity": severity, "code": code, "message": message} if path is not None: issue["path"] = str(path) if segment is not None: issue["segment"] = segment if offset is not None: issue["offset"] = offset if repair is not None: issue["suggested_repair"] = repair report["issues"].append(issue) if severity == "error": report["error_count"] += 1 else: report["warning_count"] += 1 def safe_lstat_regular(path, description): try: info = os.lstat(path) except OSError as error: raise QueueToolError("cannot inspect {} '{}': {}".format(description, path, error)) if not stat.S_ISREG(info.st_mode): raise QueueToolError("{} '{}' is not a regular file".format(description, path)) return info def preserve_path_ownership(path, uid, gid): try: os.chown(path, uid, gid) except PermissionError as error: current = os.lstat(path) if (current.st_uid, current.st_gid) != (uid, gid): raise QueueToolError("cannot preserve ownership of '{}': {}".format(path, error)) def preserve_fd_ownership(descriptor, path, uid, gid): try: os.fchown(descriptor, uid, gid) except PermissionError as error: current = os.fstat(descriptor) if (current.st_uid, current.st_gid) != (uid, gid): raise QueueToolError("cannot preserve ownership of '{}': {}".format(path, error)) def read_regular(path, description, exact_size=None): info = safe_lstat_regular(path, description) if exact_size is not None and info.st_size != exact_size: raise QueueToolError( "{} '{}' has size {}, expected {}".format(description, path, info.st_size, exact_size) ) flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0) try: descriptor = os.open(path, flags) except OSError as error: raise QueueToolError("cannot open {} '{}': {}".format(description, path, error)) try: chunks = [] remaining = info.st_size while remaining: chunk = os.read(descriptor, min(remaining, 1024 * 1024)) if not chunk: raise QueueToolError("short read from {} '{}'".format(description, path)) chunks.append(chunk) remaining -= len(chunk) return b"".join(chunks), info finally: os.close(descriptor) def file_signature(path): info = os.lstat(path) return (info.st_dev, info.st_ino, info.st_mode, info.st_size, info.st_mtime_ns) def state_slot_valid(slot): return ( len(slot) == STATE_SLOT_LEN and slot[:8] == STATE_MAGIC and unpack_u16(slot, 8) == STORE_VERSION and unpack_u16(slot, 10) == CODEC_VERSION and unpack_u32(slot, STATE_SLOT_LEN - 4) == crc32c(slot[: STATE_SLOT_LEN - 4]) ) def decode_state(slot): return { "uuid_bytes": slot[12:28], "uuid": uuid_text(slot[12:28]), "generation": unpack_u64(slot, 28), "flags": unpack_u32(slot, 36), "committed_segment": unpack_u64(slot, 40), "committed_offset": unpack_i64(slot, 48), "committed_record_sequence": unpack_u64(slot, 56), "first_live_segment": unpack_u64(slot, 64), "last_data_segment": unpack_u64(slot, 72), "active_segment": unpack_u64(slot, 80), "recovery_first": unpack_u64(slot, 88), "recovery_last": unpack_u64(slot, 96), "next_segment": unpack_u64(slot, 104), "known_queue_size": unpack_u64(slot, 112), "bytes": unpack_i64(slot, 120), "segments": unpack_u64(slot, 128), "writer_segment": unpack_u64(slot, 136), "writer_end": unpack_i64(slot, 144), "writer_sequence": unpack_u64(slot, 152), "writer_count": unpack_u64(slot, 160), "delete_first": unpack_u64(slot, 168), "delete_last": unpack_u64(slot, 176), "delete_bytes": unpack_i64(slot, 184), "delete_segments": unpack_u64(slot, 192), } def encode_state(state, generation): data = bytearray(STATE_SLOT_LEN) data[:8] = STATE_MAGIC data[8:10] = pack_u16(STORE_VERSION) data[10:12] = pack_u16(CODEC_VERSION) data[12:28] = state["uuid_bytes"] data[28:36] = pack_u64(generation) fields = ( (36, "flags", 4), (40, "committed_segment", 8), (48, "committed_offset", 8), (56, "committed_record_sequence", 8), (64, "first_live_segment", 8), (72, "last_data_segment", 8), (80, "active_segment", 8), (88, "recovery_first", 8), (96, "recovery_last", 8), (104, "next_segment", 8), (112, "known_queue_size", 8), (120, "bytes", 8), (128, "segments", 8), (136, "writer_segment", 8), (144, "writer_end", 8), (152, "writer_sequence", 8), (160, "writer_count", 8), (168, "delete_first", 8), (176, "delete_last", 8), (184, "delete_bytes", 8), (192, "delete_segments", 8), ) for offset, name, width in fields: value = state.get(name, 0) data[offset: offset + width] = pack_u32(value) if width == 4 else pack_u64(value) data[-4:] = pack_u32(crc32c(data[:-4])) return bytes(data) def validate_state_image(report, state, path): if state["flags"] & ~KNOWN_STATE_FLAGS: add_issue(report, "error", "state.unknown_flags", "state contains unknown flags", path=path) if bool(state["delete_first"]) != bool(state["delete_last"]): add_issue(report, "error", "state.delete_range_partial", "pending-delete range has one zero endpoint", path=path) if state["delete_first"] and state["delete_first"] > state["delete_last"]: add_issue(report, "error", "state.delete_range_reverse", "pending-delete range is reversed", path=path) if bool(state["recovery_first"]) != bool(state["recovery_last"]): add_issue(report, "error", "state.recovery_range_partial", "recovery range has one zero endpoint", path=path) if state["recovery_first"] and state["recovery_first"] > state["recovery_last"]: add_issue(report, "error", "state.recovery_range_reverse", "recovery range is reversed", path=path) if state["committed_segment"] and state["committed_offset"] < SEG_HEADER_LEN: add_issue(report, "error", "state.commit_offset_small", "commit offset precedes the segment payload", path=path) for name in ("bytes", "writer_end", "delete_bytes"): if state[name] < 0: add_issue( report, "error", "state.{}_negative".format(name), "state {} is negative".format(name), path=path, ) if state["next_segment"] == 0: add_issue(report, "error", "state.next_segment_zero", "next segment id is zero", path=path) def inspect_state(queue_dir, report): state_path = os.path.join(queue_dir, "state") result = {"present": False, "size": 0, "slots": [], "selected": None, "selected_slot": None} try: info = os.lstat(state_path) except FileNotFoundError: return result except OSError as error: add_issue(report, "error", "state.stat_failed", str(error), path=state_path) return result result["present"] = True result["size"] = info.st_size if not stat.S_ISREG(info.st_mode): add_issue(report, "error", "state.not_regular", "state is not a regular file", path=state_path) return result if info.st_size != STATE_FILE_LEN: add_issue( report, "error", "state.wrong_size", "state is {} bytes; expected {}".format(info.st_size, STATE_FILE_LEN), path=state_path, repair="rebuild", ) return result try: data, _ = read_regular(state_path, "state file", STATE_FILE_LEN) except QueueToolError as error: add_issue(report, "error", "state.read_failed", str(error), path=state_path) return result for index in range(2): raw = data[index * STATE_SLOT_LEN: (index + 1) * STATE_SLOT_LEN] valid = state_slot_valid(raw) item = {"index": index, "valid": valid, "raw": raw} if valid: item["image"] = decode_state(raw) result["slots"].append(item) valid_slots = [slot for slot in result["slots"] if slot["valid"]] if not valid_slots: add_issue( report, "error", "state.no_valid_slot", "neither state slot is valid", path=state_path, repair="rebuild", ) return result if len(valid_slots) == 1: add_issue( report, "warning", "state.single_valid_slot", "only state slot {} is valid".format(valid_slots[0]["index"]), path=state_path, repair="state-slot", ) selected = valid_slots[0] else: first, second = valid_slots if first["image"]["uuid_bytes"] != second["image"]["uuid_bytes"]: add_issue(report, "error", "state.uuid_mismatch", "valid state slots have different UUIDs", path=state_path) return result generation0 = first["image"]["generation"] generation1 = second["image"]["generation"] if generation0 == generation1: # Match segdiskStateSelect(): equal generations deterministically use slot 0. selected = first elif generation_newer(generation1, generation0): selected = second elif generation_newer(generation0, generation1): selected = first else: add_issue(report, "error", "state.generation_ambiguous", "state generations are incomparable", path=state_path) return result older = first if selected is second else second distance = (selected["image"]["generation"] - older["image"]["generation"]) & UINT64_MASK if distance != 1: add_issue( report, "warning", "state.generation_gap", "valid state slots differ by {} generations".format(distance), path=state_path, ) result["selected"] = selected["image"] result["selected_slot"] = selected["index"] validate_state_image(report, result["selected"], state_path) return result def inventory_segments(queue_dir, report): segments = [] by_id = {} try: entries = list(os.scandir(queue_dir)) except OSError as error: raise QueueToolError("cannot enumerate queue directory '{}': {}".format(queue_dir, error)) for entry in sorted(entries, key=lambda item: item.name): if entry.name == "state" or entry.name.startswith("state.backup-"): continue match = SEGMENT_RE.match(entry.name) if not match: add_issue( report, "warning", "directory.foreign_entry", "unrecognized entry in queue directory", path=entry.path, ) continue try: info = entry.stat(follow_symlinks=False) except OSError as error: add_issue(report, "error", "segment.stat_failed", str(error), path=entry.path) continue if not stat.S_ISREG(info.st_mode): add_issue(report, "error", "segment.not_regular", "segment is not a regular file", path=entry.path) continue segment_id = int(match.group(1)) item = { "id": segment_id, "suffix": match.group(2), "path": entry.path, "size": info.st_size, "signature": (info.st_dev, info.st_ino, info.st_mode, info.st_size, info.st_mtime_ns), } segments.append(item) by_id.setdefault(segment_id, []).append(item) for segment_id, items in by_id.items(): if len(items) > 1: add_issue( report, "error", "segment.duplicate_id", "segment id {} has multiple representations: {}".format( segment_id, ", ".join(item["suffix"] for item in items) ), segment=segment_id, repair="salvage", ) return segments def inspect_segment_metadata(item, report, expected_uuid=None): path = item["path"] try: descriptor = os.open( path, os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0) ) except OSError as error: add_issue(report, "error", "segment.open_failed", str(error), path=path, segment=item["id"]) return None try: header = os.pread(descriptor, SEG_HEADER_LEN, 0) if len(header) != SEG_HEADER_LEN: add_issue( report, "error", "segment.header_short", "segment is shorter than its header", path=path, segment=item["id"], repair="salvage", ) return None checks = ( (header[:8] == SEG_MAGIC, "segment.header_magic", "invalid segment magic"), (unpack_u16(header, 8) == STORE_VERSION, "segment.store_version", "unsupported store version"), (unpack_u16(header, 10) == CODEC_VERSION, "segment.codec_version", "unsupported codec version"), (unpack_u64(header, 28) == item["id"], "segment.id_mismatch", "header id does not match filename"), (unpack_u32(header, 44) == SEG_HEADER_LEN, "segment.header_length", "invalid header length"), ( unpack_u32(header, 48) == crc32c(header[:48]), "segment.header_crc", "segment header checksum mismatch", ), ) valid = True for condition, code, message in checks: if not condition: valid = False add_issue( report, "error", code, message, path=path, segment=item["id"], offset=0, repair="salvage", ) segment_uuid = header[12:28] if expected_uuid is not None and segment_uuid != expected_uuid: valid = False add_issue( report, "error", "segment.uuid_mismatch", "segment UUID does not match selected state", path=path, segment=item["id"], repair="salvage", ) metadata = { "uuid_bytes": segment_uuid, "uuid": uuid_text(segment_uuid), "first_sequence": unpack_u64(header, 36), "data_end": item["size"], "sealed": item["suffix"] == "seg", "footer": None, "header_valid": valid, } if metadata["sealed"]: if item["size"] < SEG_HEADER_LEN + FOOTER_LEN: add_issue( report, "error", "segment.footer_missing", "sealed segment is too short for a footer", path=path, segment=item["id"], repair="salvage", ) metadata["header_valid"] = False return metadata footer = os.pread(descriptor, FOOTER_LEN, item["size"] - FOOTER_LEN) footer_valid = ( len(footer) == FOOTER_LEN and footer[:8] == FOOT_MAGIC and unpack_u64(footer, 8) == item["id"] and unpack_u32(footer, 44) == crc32c(footer[:44]) ) if not footer_valid: add_issue( report, "error", "segment.footer_invalid", "sealed segment footer is invalid", path=path, segment=item["id"], offset=item["size"] - FOOTER_LEN, repair="salvage", ) else: metadata["footer"] = { "first_sequence": unpack_u64(footer, 16), "last_sequence": unpack_u64(footer, 24), "record_count": unpack_u64(footer, 32), "rolling_crc": unpack_u32(footer, 40), } metadata["data_end"] -= FOOTER_LEN return metadata finally: os.close(descriptor) def find_next_magic(descriptor, start, end): position = start overlap = b"" chunk_size = 1024 * 1024 while position < end: chunk = os.pread(descriptor, min(chunk_size, end - position), position) if not chunk: return None data = overlap + chunk found = data.find(REC_MAGIC) if found >= 0: return position - len(overlap) + found overlap = data[-(len(REC_MAGIC) - 1):] position += len(chunk) return None def decode_time(value): result = { "time_type": value[0], "month": value[1], "day": value[2], "weekday": value[3], "hour": value[4], "minute": value[5], "second": value[6], "fraction_precision": value[7], "offset_minute": value[8], "offset_hour": value[9], "offset_mode": chr(value[10]) if 32 <= value[10] <= 126 else value[10], "in_utc": bool(value[11]), "year": unpack_u16(value, 12), "fraction": unpack_u32(value, 14), } try: base = datetime.datetime( result["year"], result["month"], result["day"], result["hour"], result["minute"], min(result["second"], 59), ) fraction = str(result["fraction"]).zfill(result["fraction_precision"]) suffix = "Z" if result["in_utc"] else "{}{:02d}:{:02d}".format( "-" if result["offset_mode"] == "-" else "+", result["offset_hour"], result["offset_minute"] ) result["rfc3339"] = base.strftime("%Y-%m-%dT%H:%M:%S") if result["fraction_precision"]: result["rfc3339"] += "." + fraction result["rfc3339"] += suffix except (ValueError, OverflowError): result["rfc3339"] = None return result def decode_codec(payload): position = 0 seen = set() values = {} unknown_optional = [] while position < len(payload): if len(payload) - position < 8: raise ValueError("truncated TLV header at payload offset {}".format(position)) field, field_type, flags, length = struct.unpack_from(">HBBI", payload, position) position += 8 if length > MAX_RECORD_SIZE or length > len(payload) - position: raise ValueError("invalid TLV length for field {}".format(field)) value = payload[position: position + length] position += length if 1 <= field <= 31: if field in seen: raise ValueError("duplicate TLV field {}".format(field)) seen.add(field) expected = FIELD_TYPES.get(field) if expected is None: if flags & TLV_CRITICAL: raise ValueError("unknown critical TLV field {}".format(field)) unknown_optional.append( { "field": field, "type": field_type, "flags": flags, "value": { "encoding": "base64", "data": base64.b64encode(value).decode("ascii"), }, } ) continue expected_type, expected_length = expected if field_type != expected_type or (expected_length is not None and length != expected_length): raise ValueError("invalid type or length for TLV field {}".format(field)) if field_type == TLV_U8: decoded = value[0] elif field_type == TLV_U16: decoded = unpack_u16(value, 0) elif field_type == TLV_U32: decoded = unpack_u32(value, 0) elif field_type == TLV_U64: decoded = unpack_u64(value, 0) if field == 5 and decoded & (1 << 63): decoded -= 1 << 64 elif field_type == TLV_TIME: decoded = decode_time(value) else: decoded = value if field in (16, 17): try: decoded = json.loads(value.decode("utf-8")) except (UnicodeDecodeError, ValueError) as error: raise ValueError("invalid JSON in TLV field {}: {}".format(field, error)) values[field] = decoded if 9 not in values or 23 not in values: raise ValueError("codec is missing rawmsg or msg_offset") raw = values[9] if values[23] != UINT32_UNSET and values[23] > len(raw): raise ValueError("msg_offset exceeds rawmsg length") if 24 in values and values[24] != UINT32_UNSET and values[24] > len(raw): raise ValueError("after_pri_offset exceeds rawmsg length") if unknown_optional: values["unknown_optional_tlvs"] = unknown_optional return values def json_bytes(value): try: return value.decode("utf-8") except UnicodeDecodeError: return {"encoding": "base64", "data": base64.b64encode(value).decode("ascii")} def message_json(values): output = {} for field, value in values.items(): if field == "unknown_optional_tlvs": output[field] = value continue name = FIELD_NAMES[field] if field in TEXT_FIELDS: output[name] = json_bytes(value) else: output[name] = value raw = values[9] if values[23] == UINT32_UNSET: output["msg"] = json_bytes(raw) output["msg_offset_unset"] = True else: output["msg"] = json_bytes(raw[values[23]:]) if 24 in values: if values[24] == UINT32_UNSET: output["rawmsg_after_pri"] = None output["after_pri_offset_unset"] = True else: output["rawmsg_after_pri"] = json_bytes(raw[values[24]:]) if 25 in values: output["parse_success"] = bool(values[25]) return output def scan_segment(item, metadata, report, callback=None, salvage=True): if metadata is None: return {"record_count": 0, "valid_records": 0, "invalid_records": 0, "rolling_crc": 0, "boundaries": []} path = item["path"] descriptor = os.open(path, os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)) position = SEG_HEADER_LEN record_count = 0 valid_records = 0 invalid_records = 0 rolling_crc = 0 boundaries = [SEG_HEADER_LEN] expected_sequence = metadata["first_sequence"] if metadata["header_valid"] else 1 try: while position < metadata["data_end"]: if metadata["data_end"] - position < RECORD_HEADER_LEN: add_issue( report, "error", "record.trailing_bytes", "{} trailing bytes do not form a record".format(metadata["data_end"] - position), path=path, segment=item["id"], offset=position, repair="salvage", ) break header = os.pread(descriptor, RECORD_HEADER_LEN, position) header_valid = ( len(header) == RECORD_HEADER_LEN and header[:8] == REC_MAGIC and unpack_u16(header, 8) == STORE_VERSION and unpack_u32(header, 24) == crc32c(header[:24]) ) length = unpack_u32(header, 12) if len(header) == RECORD_HEADER_LEN else MAX_RECORD_SIZE + 1 if header_valid and ( length > MAX_RECORD_SIZE or position + RECORD_HEADER_LEN + length > metadata["data_end"] ): header_valid = False if not header_valid: next_position = find_next_magic(descriptor, position + 1, metadata["data_end"]) corrupt_end = next_position if next_position is not None else metadata["data_end"] add_issue( report, "error", "record.framing", "invalid record framing across {} bytes".format(corrupt_end - position), path=path, segment=item["id"], offset=position, repair="salvage", ) invalid_records += 1 if not salvage or next_position is None: break position = next_position continue sequence = unpack_u64(header, 16) payload = os.pread(descriptor, length, position + RECORD_HEADER_LEN) payload_valid = len(payload) == length and unpack_u32(header, 28) == crc32c(payload) codec_values = None codec_error = None if payload_valid: try: codec_values = decode_codec(payload) except ValueError as error: codec_error = str(error) if sequence != expected_sequence: add_issue( report, "error", "record.sequence", "record sequence {} does not match expected {}".format(sequence, expected_sequence), path=path, segment=item["id"], offset=position, repair="salvage", ) expected_sequence = sequence + 1 record_count += 1 rolling_crc ^= crc32c(header) ^ unpack_u32(header, 28) end = position + RECORD_HEADER_LEN + length boundaries.append(end) if not payload_valid: invalid_records += 1 add_issue( report, "error", "record.payload_crc", "record payload checksum mismatch", path=path, segment=item["id"], offset=position, repair="salvage", ) elif codec_error is not None: invalid_records += 1 add_issue( report, "error", "record.codec", codec_error, path=path, segment=item["id"], offset=position, repair="salvage", ) else: valid_records += 1 if callback is not None: callback( { "segment_id": item["id"], "offset": position, "end_offset": end, "sequence": sequence, "payload": payload, "codec": codec_values, "path": path, } ) position = end footer = metadata.get("footer") if footer is not None: if footer["first_sequence"] != metadata["first_sequence"]: add_issue(report, "error", "footer.first_sequence", "footer first sequence disagrees with header", path=path) if footer["record_count"] != record_count: add_issue( report, "error", "footer.record_count", "footer count {} differs from scanned count {}".format(footer["record_count"], record_count), path=path, segment=item["id"], repair="salvage", ) if record_count and footer["last_sequence"] != expected_sequence - 1: add_issue(report, "error", "footer.last_sequence", "footer last sequence disagrees with records", path=path) if footer["rolling_crc"] != rolling_crc: add_issue( report, "error", "footer.rolling_crc", "footer rolling checksum differs from scanned records", path=path, segment=item["id"], repair="salvage", ) return { "record_count": record_count, "valid_records": valid_records, "invalid_records": invalid_records, "rolling_crc": rolling_crc, "boundaries": boundaries, } finally: os.close(descriptor) def new_report(queue_dir, mode): return { "tool": "rsyslog-segqueue", "mode": mode, "queue_directory": queue_dir, "format": {"store_version": STORE_VERSION, "codec_version": CODEC_VERSION}, "issues": [], "error_count": 0, "warning_count": 0, } def inspect_store(queue_dir, full=False): queue_dir = os.path.abspath(queue_dir) report = new_report(queue_dir, "check" if full else "status") try: directory_info = os.lstat(queue_dir) except OSError as error: raise QueueToolError("cannot inspect queue directory '{}': {}".format(queue_dir, error)) if not stat.S_ISDIR(directory_info.st_mode): raise QueueToolError("queue path '{}' is not a directory".format(queue_dir)) if stat.S_ISLNK(directory_info.st_mode): raise QueueToolError("queue directory may not be a symbolic link") state = inspect_state(queue_dir, report) selected = state["selected"] segments = inventory_segments(queue_dir, report) expected_uuid = selected["uuid_bytes"] if selected is not None else None uuids = set() total_bytes = 0 total_records = 0 total_valid_records = 0 metadata_by_path = {} scans_by_path = {} for item in segments: total_bytes += item["size"] metadata = inspect_segment_metadata(item, report, expected_uuid) metadata_by_path[item["path"]] = metadata if metadata is not None: uuids.add(metadata["uuid_bytes"]) if full and metadata is not None: scan = scan_segment(item, metadata, report) scans_by_path[item["path"]] = scan total_records += scan["record_count"] total_valid_records += scan["valid_records"] ids = sorted(set(item["id"] for item in segments)) if ids: missing_count = 0 missing_preview = [] for previous, current in zip(ids, ids[1:]): gap = current - previous - 1 if gap <= 0: continue missing_count += gap for segment_id in range(previous + 1, min(current, previous + 1 + (8 - len(missing_preview)))): missing_preview.append(segment_id) if missing_count: preview = ", ".join(str(segment_id) for segment_id in missing_preview) if missing_count > len(missing_preview): preview += ", ..." add_issue( report, "error", "segment.id_gap", "missing segment id(s): {}".format(preview), path=queue_dir, repair="salvage", ) if len(uuids) > 1: add_issue( report, "error", "store.mixed_uuid", "segments from multiple queue UUIDs are present", path=queue_dir, ) if not state["present"] and segments: add_issue( report, "error", "state.missing", "state is missing while segments remain", path=os.path.join(queue_dir, "state"), repair="rebuild", ) if selected is not None: if selected["segments"] != len(segments): add_issue( report, "warning", "state.segment_count", "state counts {} segments but {} files exist".format(selected["segments"], len(segments)), repair="rebuild", ) if selected["bytes"] != total_bytes: add_issue( report, "warning", "state.byte_count", "state counts {} bytes but {} bytes exist".format(selected["bytes"], total_bytes), repair="rebuild", ) if ids and selected["next_segment"] <= max(ids): add_issue(report, "error", "state.next_segment_used", "next segment id is not above existing ids", repair="rebuild") if selected["first_live_segment"] and ids and selected["first_live_segment"] not in ids: add_issue( report, "error", "state.first_live_missing", "first live segment is missing", segment=selected["first_live_segment"], repair="rebuild", ) if selected["last_data_segment"] and ids and selected["last_data_segment"] not in ids: add_issue( report, "error", "state.last_data_missing", "last data segment is missing", segment=selected["last_data_segment"], repair="rebuild", ) if full and selected["committed_segment"]: candidates = [item for item in segments if item["id"] == selected["committed_segment"]] if not candidates: add_issue( report, "error", "state.committed_segment_missing", "committed segment is missing", segment=selected["committed_segment"], repair="rebuild", ) elif len(candidates) == 1: scan = scans_by_path.get(candidates[0]["path"]) if scan is not None and selected["committed_offset"] not in scan["boundaries"]: add_issue( report, "error", "state.commit_not_boundary", "commit offset is not a record boundary", segment=selected["committed_segment"], offset=selected["committed_offset"], repair="rebuild", ) report["state"] = state_for_json(state) report["summary"] = { "segment_files": len(segments), "segment_ids": ids, "physical_bytes": total_bytes, "record_count": total_records if full else None, "valid_record_count": total_valid_records if full else None, "queue_uuid": ( selected["uuid"] if selected is not None else (uuid_text(next(iter(uuids))) if len(uuids) == 1 else None) ), } report["_internal"] = { "state": state, "segments": segments, "metadata": metadata_by_path, "scans": scans_by_path, "directory_signature": ( directory_info.st_dev, directory_info.st_ino, directory_info.st_mode, directory_info.st_mtime_ns, ), } return report def state_for_json(state): result = { "present": state["present"], "size": state["size"], "selected_slot": state["selected_slot"], "slots": [], "selected": None, } for slot in state["slots"]: item = {"index": slot["index"], "valid": slot["valid"]} if slot["valid"]: item["generation"] = slot["image"]["generation"] item["uuid"] = slot["image"]["uuid"] result["slots"].append(item) if state["selected"] is not None: result["selected"] = {key: value for key, value in state["selected"].items() if key != "uuid_bytes"} return result def public_report(report): return {key: value for key, value in report.items() if key != "_internal"} def print_human_report(report): summary = report["summary"] state = report["state"] print("Queue: {}".format(report["queue_directory"])) print("Format: store v{}, codec v{}".format(STORE_VERSION, CODEC_VERSION)) print("UUID: {}".format(summary["queue_uuid"] or "unknown")) print("State: {}".format("present" if state["present"] else "missing")) if state["selected"] is not None: selected = state["selected"] print("Selected slot/generation: {}/{}".format(state["selected_slot"], selected["generation"])) print( "Commit frontier: segment {}, offset {}, sequence {}".format( selected["committed_segment"], selected["committed_offset"], selected["committed_record_sequence"], ) ) print( "Live/recovery/delete: {}-{} / {}-{} / {}-{}".format( selected["first_live_segment"], selected["last_data_segment"], selected["recovery_first"], selected["recovery_last"], selected["delete_first"], selected["delete_last"], ) ) print("Segments: {} files, {} bytes".format(summary["segment_files"], summary["physical_bytes"])) if summary["record_count"] is not None: print( "Records: {} framed, {} valid".format(summary["record_count"], summary["valid_record_count"]) ) print("Result: {} error(s), {} warning(s)".format(report["error_count"], report["warning_count"])) for issue in report["issues"]: location = issue.get("path", "") if "segment" in issue: location += " segment={}".format(issue["segment"]) if "offset" in issue: location += " offset={}".format(issue["offset"]) print("{} {}: {}{}".format(issue["severity"].upper(), issue["code"], issue["message"], " [" + location.strip() + "]" if location else "")) def record_is_live(record, selected): if selected is None or selected["committed_segment"] == 0: return True if record["segment_id"] > selected["committed_segment"]: return True if record["segment_id"] < selected["committed_segment"]: return False return record["offset"] >= selected["committed_offset"] def write_json_line(stream, record): item = { "queue": { "segment_id": record["segment_id"], "offset": record["offset"], "end_offset": record["end_offset"], "record_sequence": record["sequence"], }, "message": message_json(record["codec"]), } stream.write(json.dumps(item, ensure_ascii=False, separators=(",", ":"), sort_keys=True)) stream.write("\n") def export_records(args): report = inspect_store(args.queue_dir, full=True) selected = report["_internal"]["state"]["selected"] if args.scope == "live" and selected is None: raise QueueToolError("live export requires a valid state slot; use --scope all for forensic export") if report["error_count"] and not args.salvage: print_human_report(report) return 2 output_path = args.output temporary = None if output_path == "-": stream = sys.stdout else: output_path = os.path.abspath(output_path) parent = os.path.dirname(output_path) or "." descriptor, temporary = tempfile.mkstemp(prefix=".rsyslog-segqueue-export-", dir=parent, text=True) stream = os.fdopen(descriptor, "w", encoding="utf-8", newline="\n") count = 0 def emit(record): nonlocal count if args.scope == "all" or record_is_live(record, selected): write_json_line(stream, record) count += 1 try: export_report = new_report(report["queue_directory"], "export") for item in report["_internal"]["segments"]: metadata = report["_internal"]["metadata"].get(item["path"]) scan_segment(item, metadata, export_report, callback=emit) if stream is not sys.stdout: stream.flush() os.fsync(stream.fileno()) stream.close() os.replace(temporary, output_path) temporary = None print( "exported {} record(s){}".format(count, " with integrity errors" if report["error_count"] else ""), file=sys.stderr, ) finally: if stream is not sys.stdout and not stream.closed: stream.close() if temporary is not None: try: os.unlink(temporary) except FileNotFoundError: pass return 2 if report["error_count"] else 0 def timestamp_tag(): return datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ") def fsync_directory(path): descriptor = os.open(path, os.O_RDONLY | getattr(os, "O_DIRECTORY", 0) | getattr(os, "O_CLOEXEC", 0)) try: os.fsync(descriptor) finally: os.close(descriptor) def atomic_write(path, data, source_info=None): parent = os.path.dirname(path) descriptor, temporary = tempfile.mkstemp(prefix=".rsyslog-segqueue-state-", dir=parent) try: os.write(descriptor, data) os.fsync(descriptor) if source_info is not None: os.fchmod(descriptor, stat.S_IMODE(source_info.st_mode)) try: os.fchown(descriptor, source_info.st_uid, source_info.st_gid) except PermissionError: current = os.fstat(descriptor) if (current.st_uid, current.st_gid) != (source_info.st_uid, source_info.st_gid): raise os.close(descriptor) descriptor = -1 os.replace(temporary, path) fsync_directory(parent) finally: if descriptor >= 0: os.close(descriptor) try: os.unlink(temporary) except FileNotFoundError: pass def make_replay_state(uuid_bytes, segment_count, byte_count, record_count): first = 1 if segment_count else 0 last = segment_count if segment_count else 0 return { "uuid_bytes": uuid_bytes, "flags": STATE_FLAG_RECOVERY if segment_count else 0, "committed_segment": first, "committed_offset": SEG_HEADER_LEN, "committed_record_sequence": 0, "first_live_segment": first, "last_data_segment": last, "active_segment": 0, "recovery_first": first, "recovery_last": last, "next_segment": segment_count + 1, "known_queue_size": record_count, "bytes": byte_count, "segments": segment_count, "writer_segment": 0, "writer_end": SEG_HEADER_LEN, "writer_sequence": 0, "writer_count": 0, "delete_first": 0, "delete_last": 0, "delete_bytes": 0, "delete_segments": 0, } def write_segment_header(stream, uuid_bytes, segment_id): header = bytearray(SEG_HEADER_LEN) header[:8] = SEG_MAGIC header[8:10] = pack_u16(STORE_VERSION) header[10:12] = pack_u16(CODEC_VERSION) header[12:28] = uuid_bytes header[28:36] = pack_u64(segment_id) header[36:44] = pack_u64(1) header[44:48] = pack_u32(SEG_HEADER_LEN) header[48:52] = pack_u32(crc32c(header[:48])) stream.write(header) def write_clean_record(stream, payload, sequence): header = bytearray(RECORD_HEADER_LEN) header[:8] = REC_MAGIC header[8:10] = pack_u16(STORE_VERSION) header[12:16] = pack_u32(len(payload)) header[16:24] = pack_u64(sequence) header[24:28] = pack_u32(crc32c(header[:24])) payload_crc = crc32c(payload) header[28:32] = pack_u32(payload_crc) stream.write(header) stream.write(payload) return crc32c(header) ^ payload_crc def write_footer(stream, segment_id, record_count, rolling_crc): footer = bytearray(FOOTER_LEN) footer[:8] = FOOT_MAGIC footer[8:16] = pack_u64(segment_id) footer[16:24] = pack_u64(1) footer[24:32] = pack_u64(record_count) footer[32:40] = pack_u64(record_count) footer[40:44] = pack_u32(rolling_crc) footer[44:48] = pack_u32(crc32c(footer[:44])) stream.write(footer) def choose_repair_uuid(report): uuids = { metadata["uuid_bytes"] for metadata in report["_internal"]["metadata"].values() if metadata is not None and metadata["header_valid"] } if len(uuids) > 1: raise QueueToolError("repair refuses a store containing multiple queue UUIDs") selected = report["_internal"]["state"]["selected"] if selected is not None: if uuids and selected["uuid_bytes"] not in uuids: raise QueueToolError("selected state UUID does not match the recoverable segments") return selected["uuid_bytes"] if len(uuids) == 1: return next(iter(uuids)) if not report["_internal"]["segments"]: value = bytearray(os.urandom(16)) value[6] = (value[6] & 0x0F) | 0x40 value[8] = (value[8] & 0x3F) | 0x80 return bytes(value) raise QueueToolError("repair requires exactly one unambiguous queue UUID") def build_repaired_store(report, mode, stage): uuid_bytes = choose_repair_uuid(report) os.mkdir(stage, 0o700) source_info = os.lstat(report["queue_directory"]) preserve_path_ownership(stage, source_info.st_uid, source_info.st_gid) os.chmod(stage, stat.S_IMODE(source_info.st_mode)) records_written = 0 segments_written = 0 bytes_written = 0 skipped = 0 repair_report = new_report(report["queue_directory"], "repair-build") for source_item in report["_internal"]["segments"]: metadata = report["_internal"]["metadata"].get(source_item["path"]) if metadata is not None and metadata["uuid_bytes"] != uuid_bytes: raise QueueToolError( "repair refuses segment {!r} because its UUID differs from the selected store UUID".format( source_item["path"] ) ) target_stream = None target_path = None target_sequence = 0 target_rolling_crc = 0 def collect(record): nonlocal target_stream, target_path, target_sequence, target_rolling_crc if target_stream is None: target_id = segments_written + 1 name = "segment-{:020d}.seg".format(target_id) target_path = os.path.join(stage, name) flags = ( os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0) ) descriptor = os.open(target_path, flags, 0o600) target_info = os.lstat(source_item["path"]) preserve_fd_ownership( descriptor, target_path, target_info.st_uid, target_info.st_gid ) os.fchmod(descriptor, stat.S_IMODE(target_info.st_mode)) target_stream = os.fdopen(descriptor, "wb") write_segment_header(target_stream, uuid_bytes, target_id) target_sequence += 1 target_rolling_crc ^= write_clean_record(target_stream, record["payload"], target_sequence) try: before_errors = repair_report["error_count"] scan = scan_segment(source_item, metadata, repair_report, callback=collect) skipped += scan["invalid_records"] if mode == "rebuild" and repair_report["error_count"] != before_errors: raise QueueToolError("rebuild requires clean segments; use salvage for damaged records") if target_stream is None: continue segments_written += 1 records_written += target_sequence write_footer(target_stream, segments_written, target_sequence, target_rolling_crc) target_stream.flush() os.fsync(target_stream.fileno()) target_stream.close() target_stream = None bytes_written += os.path.getsize(target_path) finally: if target_stream is not None: target_stream.close() state = make_replay_state(uuid_bytes, segments_written, bytes_written, records_written) state_data = encode_state(state, 0) + encode_state(state, 1) state_path = os.path.join(stage, "state") descriptor = os.open(state_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_CLOEXEC", 0), 0o600) source_state_path = os.path.join(report["queue_directory"], "state") try: state_info = safe_lstat_regular(source_state_path, "state file") state_mode = stat.S_IMODE(state_info.st_mode) except QueueToolError: state_info = ( os.lstat(report["_internal"]["segments"][0]["path"]) if report["_internal"]["segments"] else source_info ) state_mode = 0o600 preserve_fd_ownership(descriptor, state_path, state_info.st_uid, state_info.st_gid) os.fchmod(descriptor, state_mode) with os.fdopen(descriptor, "wb") as stream: stream.write(state_data) stream.flush() os.fsync(stream.fileno()) fsync_directory(stage) staged_report = inspect_store(stage, full=True) if staged_report["error_count"]: raise QueueToolError("the staged repaired store did not pass validation") return { "uuid": uuid_text(uuid_bytes), "segments_written": segments_written, "records_written": records_written, "skipped_corrupt_regions_or_records": skipped, "bytes_written": bytes_written + STATE_FILE_LEN, } def store_signature(report): signatures = {report["queue_directory"]: file_signature(report["queue_directory"])} state_path = os.path.join(report["queue_directory"], "state") if os.path.exists(state_path): signatures[state_path] = file_signature(state_path) for item in report["_internal"]["segments"]: signatures[item["path"]] = file_signature(item["path"]) return signatures def verify_store_unchanged(signatures): for path, signature in signatures.items(): try: current = file_signature(path) except OSError as error: raise QueueToolError("queue changed during repair planning: {}".format(error)) if current != signature: raise QueueToolError("queue changed during repair planning: '{}'".format(path)) def repair_state_slot(report, apply): state = report["_internal"]["state"] valid = [slot for slot in state["slots"] if slot["valid"]] if len(valid) != 1: raise QueueToolError("state-slot repair requires exactly one valid state slot") semantic_errors = [ issue for issue in report["issues"] if issue["severity"] == "error" and issue["code"].startswith("state.") ] if semantic_errors: raise QueueToolError("state-slot repair refuses a semantically invalid surviving state slot") source = valid[0] target_index = 1 - source["index"] generation = (source["image"]["generation"] + 1) & UINT64_MASK new_slot = encode_state(source["image"], generation) state_path = os.path.join(report["queue_directory"], "state") data, info = read_regular(state_path, "state file", STATE_FILE_LEN) expected_source = source["raw"] actual_source = data[source["index"] * STATE_SLOT_LEN: (source["index"] + 1) * STATE_SLOT_LEN] if actual_source != expected_source: raise QueueToolError("state changed during repair planning") repaired = bytearray(data) repaired[target_index * STATE_SLOT_LEN: (target_index + 1) * STATE_SLOT_LEN] = new_slot plan = { "mode": "state-slot", "apply": apply, "target_slot": target_index, "new_generation": generation, "preserves_commit_frontier": True, } if not apply: return plan backup = state_path + ".backup-" + timestamp_tag() if os.path.exists(backup): raise QueueToolError("backup already exists: '{}'".format(backup)) shutil.copy2(state_path, backup, follow_symlinks=False) atomic_write(state_path, bytes(repaired), info) plan["backup"] = backup verified = inspect_store(report["queue_directory"], full=False) if verified["_internal"]["state"]["selected"] is None: raise QueueToolError("state-slot repair verification failed; backup remains at '{}'".format(backup)) return plan def repair_rebuild(report, mode, apply): if mode == "rebuild" and report["error_count"]: non_state = [issue for issue in report["issues"] if not issue["code"].startswith("state.")] if non_state: raise QueueToolError("rebuild requires clean segment data; use salvage for corruption") if not apply: uuid_bytes = choose_repair_uuid(report) scans = report["_internal"]["scans"].values() projected = { "uuid": uuid_text(uuid_bytes), "segments_written": sum(1 for scan in scans if scan["valid_records"]), "records_written": sum(scan["valid_records"] for scan in scans), "skipped_corrupt_regions_or_records": sum(scan["invalid_records"] for scan in scans), } return { "mode": mode, "apply": False, "replays_all_recovered_records": True, "possible_duplicates": True, "projected_result": projected, } signatures = store_signature(report) parent = os.path.dirname(report["queue_directory"]) base = os.path.basename(report["queue_directory"]) stage = tempfile.mkdtemp(prefix=".{}-stage-".format(base), dir=parent) os.rmdir(stage) try: result = build_repaired_store(report, mode, stage) plan = { "mode": mode, "apply": apply, "replays_all_recovered_records": True, "possible_duplicates": True, "staged_result": result, } verify_store_unchanged(signatures) backup = report["queue_directory"] + ".backup-" + timestamp_tag() if os.path.exists(backup): raise QueueToolError("backup already exists: '{}'".format(backup)) os.rename(report["queue_directory"], backup) try: os.rename(stage, report["queue_directory"]) stage = None fsync_directory(parent) except Exception: os.rename(backup, report["queue_directory"]) fsync_directory(parent) raise plan["backup"] = backup verified = inspect_store(report["queue_directory"], full=True) if verified["error_count"]: raise QueueToolError( "installed repaired store failed validation; original backup remains at '{}'".format(backup)) return plan finally: if stage is not None and os.path.isdir(stage): shutil.rmtree(stage) def run_repair(queue_dir, mode, apply, offline): if mode not in ("state-slot", "rebuild", "salvage"): raise QueueToolError("unknown repair mode '{}'".format(mode)) if apply and not offline: raise QueueToolError("--apply requires --offline to acknowledge that rsyslog is stopped") report = inspect_store(queue_dir, full=True) if mode == "state-slot": plan = repair_state_slot(report, apply) else: plan = repair_rebuild(report, mode, apply) return {"queue_directory": report["queue_directory"], "repair": plan} def print_repair(result, as_json=False): if as_json: print(json.dumps(result, indent=2, sort_keys=True)) return repair = result["repair"] print("Queue: {}".format(result["queue_directory"])) print("Repair mode: {}".format(repair["mode"])) print("Action: {}".format("applied" if repair["apply"] else "plan only; no files changed")) result_name = "staged_result" if "staged_result" in repair else "projected_result" if result_name in repair: staged = repair[result_name] print( "Recovered: {} records in {} segments; skipped {} corrupt region(s) or record(s)".format( staged["records_written"], staged["segments_written"], staged["skipped_corrupt_regions_or_records"], ) ) print("All recovered records will replay; duplicates are possible.") if "backup" in repair: print("Backup: {}".format(repair["backup"])) def guided_tui(queue_dir=None): print("rsyslog segmentedDisk queue maintenance") if queue_dir is None: queue_dir = input("Queue .segq directory: ").strip() while True: print("\n1) Status\n2) Check\n3) Export JSONL\n4) Repair\n5) Quit") choice = input("Selection: ").strip() if choice == "1" or choice == "2": report = inspect_store(queue_dir, full=choice == "2") print_human_report(report) elif choice == "3": output = input("Output file ('-' for stdout): ").strip() or "-" scope = input("Scope [live/all] (live): ").strip() or "live" if scope not in ("live", "all"): print("Scope must be 'live' or 'all'.", file=sys.stderr) continue salvage = input("Salvage valid records despite corruption? [y/N]: ").strip().lower() == "y" export_args = argparse.Namespace(queue_dir=queue_dir, output=output, scope=scope, salvage=salvage) export_records(export_args) elif choice == "4": mode = input("Repair mode [state-slot/rebuild/salvage]: ").strip() result = run_repair(queue_dir, mode, False, False) print_repair(result) confirmation = input("Type the exact queue path to apply, or press Enter to cancel: ").strip() if confirmation: expected = os.path.abspath(queue_dir) if os.path.abspath(confirmation) != expected: print("Confirmation did not match; repair cancelled.", file=sys.stderr) else: print_repair(run_repair(queue_dir, mode, True, True)) elif choice == "5": return 0 else: print("Unknown selection.", file=sys.stderr) def build_parser(): parser = argparse.ArgumentParser( prog="rsyslog-segqueue", description="Maintain rsyslog segmentedDisk queue stores while rsyslog is stopped." ) parser.add_argument("--version", action="version", version="%(prog)s format-v2") subparsers = parser.add_subparsers(dest="command") for name in ("status", "check"): subparser = subparsers.add_parser(name, help="{} a segmentedDisk store".format(name)) subparser.add_argument("queue_dir") subparser.add_argument("--json", action="store_true", help="emit a machine-readable report") export_parser = subparsers.add_parser("export", help="export queue records as JSON Lines") export_parser.add_argument("queue_dir") export_parser.add_argument("--output", default="-", help="output path, or '-' for stdout") export_parser.add_argument("--scope", choices=("live", "all"), default="live") export_parser.add_argument("--salvage", action="store_true", help="export valid records despite corruption") repair_parser = subparsers.add_parser("repair", help="plan or apply an offline repair") repair_parser.add_argument("queue_dir") repair_parser.add_argument("--mode", choices=("state-slot", "rebuild", "salvage"), required=True) repair_parser.add_argument("--apply", action="store_true", help="apply the otherwise read-only repair plan") repair_parser.add_argument("--offline", action="store_true", help="acknowledge that rsyslog is stopped") repair_parser.add_argument("--json", action="store_true", help="emit a machine-readable plan or result") tui_parser = subparsers.add_parser("tui", help="open the guided terminal interface") tui_parser.add_argument("queue_dir", nargs="?") return parser def main(argv=None): parser = build_parser() args = parser.parse_args(argv) if args.command is None: parser.print_help(sys.stderr) return 1 try: if args.command in ("status", "check"): report = inspect_store(args.queue_dir, full=args.command == "check") if args.json: print(json.dumps(public_report(report), indent=2, sort_keys=True)) else: print_human_report(report) return 2 if report["error_count"] else 0 if args.command == "export": return export_records(args) if args.command == "repair": result = run_repair(args.queue_dir, args.mode, args.apply, args.offline) print_repair(result, args.json) return 0 if args.command == "tui": return guided_tui(args.queue_dir) except (QueueToolError, OSError) as error: print("rsyslog-segqueue: error: {}".format(error), file=sys.stderr) return 1 return 1 if __name__ == "__main__": sys.exit(main()) rsyslog-8.2608.0/tools/PaxHeaders/rsyslogd.80000644000000000000000000000013215216464436015651 xustar0030 mtime=1782212894.096267316 30 atime=1782715518.782788738 30 ctime=1787067795.314742199 rsyslog-8.2608.0/tools/rsyslogd.80000664000175000017500000002473315216464436015326 0ustar00rgerrger.\" Copyright 2004-2014 Rainer Gerhards and Adiscon for the rsyslog modifications .\" May be distributed under the GNU General Public License .\" .TH RSYSLOGD 8 "18 February 2025" "Version 8.2502.0" "Linux System Administration" .SH NAME rsyslogd \- reliable and extended syslogd .SH SYNOPSIS .B rsyslogd .RB [ " \-d " ] .RB [ " \-D " ] .RB [ " \-f " .I config file ] .RB [ " \-i " .I pid file ] .RB [ " \-n " ] .RB [ " \-N " .I level ] .RB [ " \-o " .I fullconf ] .RB [ " \-C " ] .RB [ " \-v " ] .LP .SH DESCRIPTION .B Rsyslogd is a system utility providing support for message logging. Support of both internet and unix domain sockets enables this utility to support both local and remote logging. .B Note that this version of rsyslog ships with extensive documentation in HTML format. This is provided in the ./doc subdirectory and probably in a separate package if you installed rsyslog via a packaging system. To use rsyslog's advanced features, you .B need to look at the HTML documentation, because the man pages only covers basic aspects of operation. .B For details and configuration examples, see the rsyslog.conf (5) .B man page and the online documentation at https://www.rsyslog.com/doc/ .BR Rsyslogd (8) is derived from the sysklogd package which in turn is derived from the stock BSD sources. .B Rsyslogd provides a kind of logging that many modern programs use. Every logged message contains at least a time and a hostname field, normally a program name field, too, but that depends on how trusty the logging program is. The rsyslog package supports free definition of output formats via templates. It also supports precise timestamps and writing directly to databases. If the database option is used, tools like phpLogCon can be used to view the log data. While the .B rsyslogd sources have been heavily modified a couple of notes are in order. First of all there has been a systematic attempt to ensure that rsyslogd follows its default, standard BSD behavior. Of course, some configuration file changes are necessary in order to support the template system. However, rsyslogd should be able to use a standard syslog.conf and act like the original syslogd. However, an original syslogd will not work correctly with a rsyslog-enhanced configuration file. At best, it will generate funny looking file names. The second important concept to note is that this version of rsyslogd interacts transparently with the version of syslog found in the standard libraries. If a binary linked to the standard shared libraries fails to function correctly we would like an example of the anomalous behavior. The main configuration file .I /etc/rsyslog.conf or an alternative file, given with the .B "\-f" option, is read at startup. Any lines that begin with the hash mark (``#'') and empty lines are ignored. If an error occurs during parsing the error element is ignored. It is tried to parse the rest of the line. .LP .SH OPTIONS .TP .B "\-D" Runs the Bison config parser in debug mode. This may help when hard to find syntax errors are reported. Please note that the output generated is deeply technical and originally targeted towards developers. .TP .B "\-d" Turns on debug mode. See the DEBUGGING section for more information. .TP .BI "\-f " "config file" Specify an alternative configuration file instead of .IR /etc/rsyslog.conf "," which is the default. .TP .BI "\-i " "pid file" Specify an alternative pid file instead of the default one. This option must be used if multiple instances of rsyslogd should run on a single machine. To disable writing a pid file, use the reserved name "NONE" (all upper case!), so "-iNONE". .TP .B "\-n" Avoid auto-backgrounding. This is needed especially if the .B rsyslogd is started and controlled by .BR init (8). .TP .B "\-N " "level" Do a config check. Do NOT run in regular mode, just check configuration file correctness. This option is meant to verify a config file. To do so, run rsyslogd interactively in foreground, specifying -f and -N level. The level argument modifies behaviour. Currently, 0 is the same as not specifying the -N option at all (so this makes limited sense) and 1 actually activates the code. Later, higher levels will mean more verbosity (this is a forward-compatibility option). .TP .B "\-o " "fullconf" Generates a consolidated config file .I fullconf that contains all of rsyslog's configuration in a single file. Include files are exploded into that file in exactly the way rsyslog sees them. This option is useful for troubleshooting, especially if problems with the order of action processing is suspected. It may also be used to check for "unexepectedly" included config content. .TP .BI "\-C" This prevents rsyslogd from changing to the root directory. This is almost never a good idea in production use. This option was introduced in support of the internal testbed. .TP .B "\-v" Print version and exit. .LP .SH SIGNALS .B Rsyslogd reacts to a set of signals. You may easily send a signal to .B rsyslogd using the following: .IP .nf kill -SIGNAL $(cat /var/run/rsyslogd.pid) .fi .PP Note that -SIGNAL must be replaced with the actual signal you are trying to send, e.g. with HUP. So it then becomes: .IP .nf kill -HUP $(cat /var/run/rsyslogd.pid) .fi .PP .TP .B HUP This lets .B rsyslogd perform close all open files. .TP .B TERM ", " QUIT .B Rsyslogd will die. .TP .B INT .B Rsyslogd will die. This signal is only processed if .B rsyslogd was started with the .B "\-d" debug option, if the .B shutdown.enable.ctlc global config parameter is set, or if running as PID 1 (e.g. in a container). .TP .B USR1 Switch debugging on/off. This option can only be used if .B rsyslogd is started with the .B "\-d" debug option. .TP .B CHLD Wait for children if some were born, because of wall'ing messages. .LP .SH SECURITY THREATS There is the potential for the rsyslogd daemon to be used as a conduit for a denial of service attack. A rogue program(mer) could very easily flood the rsyslogd daemon with syslog messages resulting in the log files consuming all the remaining space on the filesystem. Activating logging over the inet domain sockets will of course expose a system to risks outside of programs or individuals on the local machine. There are a number of methods of protecting a machine: .IP 1. Implement kernel firewalling to limit which hosts or networks have access to the 514/UDP socket. .IP 2. Logging can be directed to an isolated or non-root filesystem which, if filled, will not impair the machine. .IP 3. The ext2 filesystem can be used which can be configured to limit a certain percentage of a filesystem to usage by root only. \fBNOTE\fP that this will require rsyslogd to be run as a non-root process. \fBALSO NOTE\fP that this will prevent usage of remote logging on the default port since rsyslogd will be unable to bind to the 514/UDP socket. .IP 4. Disabling inet domain sockets will limit risk to the local machine. .SS Message replay and spoofing If remote logging is enabled, messages can easily be spoofed and replayed. As the messages are transmitted in clear-text, an attacker might use the information obtained from the packets for malicious things. Also, an attacker might replay recorded messages or spoof a sender's IP address, which could lead to a wrong perception of system activity. These can be prevented by using GSS-API authentication and encryption. Be sure to think about syslog network security before enabling it. .LP .SH DEBUGGING When debugging is turned on using the .B "\-d" option, .B rsyslogd produces debugging information according to the .B RSYSLOG_DEBUG environment variable and the signals received. When run in foreground, the information is written to stdout. An additional output file can be specified using the .B RSYSLOG_DEBUGLOG environment variable. .SH FILES .PD 0 .TP .I /etc/rsyslog.conf Configuration file for .BR rsyslogd . See .BR rsyslog.conf (5) for exact information. .TP .I /dev/log The Unix domain socket to from where local syslog messages are read. .TP .I /var/run/rsyslogd.pid The file containing the process id of .BR rsyslogd . .TP .I prefix/lib/rsyslog Default directory for .B rsyslogd modules. The .I prefix is specified during compilation (e.g. /usr/local). .SH ENVIRONMENT .TP .B RSYSLOG_DEBUG Controls runtime debug support. It contains an option string with the following options possible (all are case insensitive): .RS .IP Debug Turns on debugging and prevents forking. This is processed earlier in the startup than command line options (i.e. -d) and as such enables earlier debugging output. Mutually exclusive with DebugOnDemand. .IP DebugOnDemand Enables debugging but turns off debug output. The output can be toggled by sending SIGUSR1. Mutually exclusive with Debug. .IP LogFuncFlow Print out the logical flow of functions (entering and exiting them) .IP FileTrace Specifies which files to trace LogFuncFlow. If not set (the default), a LogFuncFlow trace is provided for all files. Set to limit it to the files specified.FileTrace may be specified multiple times, one file each (e.g. export RSYSLOG_DEBUG="LogFuncFlow FileTrace=vm.c FileTrace=expr.c" .IP PrintFuncDB Print the content of the debug function database whenever debug information is printed (e.g. abort case)! .IP PrintAllDebugInfoOnExit Print all debug information immediately before rsyslogd exits (currently not implemented!) .IP PrintMutexAction Print mutex action as it happens. Useful for finding deadlocks and such. .IP NoLogTimeStamp Do not prefix log lines with a timestamp (default is to do that). .IP NoStdOut Do not emit debug messages to stdout. If RSYSLOG_DEBUGLOG is not set, this means no messages will be displayed at all. .IP Help Display a very short list of commands - hopefully a life saver if you can't access the documentation... .RE .TP .B RSYSLOG_DEBUGLOG If set, writes (almost) all debug message to the specified log file in addition to stdout. .TP .B RSYSLOG_MODDIR Provides the default directory in which loadable modules reside. .PD .SH BUGS Please review the file BUGS for up-to-date information on known bugs and annoyances. .SH Further Information Please visit .BR https://www.rsyslog.com/doc/ for additional information, tutorials and a support forum. .SH SEE ALSO .BR rsyslog.conf (5), .BR logger (1), .BR syslog (2), .BR syslog (3), .BR services (5), .BR savelog (8) .LP .SH COLLABORATORS .B rsyslogd is derived from sysklogd sources, which in turn was taken from the BSD sources. Special thanks to Greg Wettstein (greg@wind.enjellic.com) and Martin Schulze (joey@linux.de) for the fine sysklogd package. .PD 0 .TP Rainer Gerhards .TP Adiscon GmbH .TP Grossrinderfeld, Germany .TP rgerhards@adiscon.com .PD rsyslog-8.2608.0/tools/PaxHeaders/smtradfwd.c0000644000000000000000000000013215132411300016024 xustar0030 mtime=1768559296.305886257 30 atime=1787067622.112513751 30 ctime=1787067795.285741659 rsyslog-8.2608.0/tools/smtradfwd.c0000666000175000017500000001004215132411300015467 0ustar00rgerrger/* smtradfwd.c * This is a strgen module for the traditional forwarding format. * * Format generated: * "<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%" * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2010-06-01 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "unicode-helper.h" MODULE_TYPE_STRGEN MODULE_TYPE_NOKEEP; STRGEN_NAME("RSYSLOG_TraditionalForwardFormat") /* internal structures */ DEF_SMOD_STATIC_DATA; /* config data */ /* This strgen tries to minimize the amount of reallocs be first obtaining pointers to all strings * needed (including their length) and then calculating the actual space required. So when we * finally copy, we know exactly what we need. So we do at most one alloc. */ BEGINstrgen register int iBuf; const char *pPRI; size_t lenPRI; uchar *pTimeStamp; uchar *pHOSTNAME; size_t lenHOSTNAME; uchar *pTAG; int lenTAG; uchar *pMSG; size_t lenMSG; size_t lenTotal; CODESTARTstrgen; /* first obtain all strings and their length (if not fixed) */ pPRI = getPRI(pMsg); lenPRI = strlen(pPRI); pTimeStamp = (uchar *)getTimeReported(pMsg, tplFmtRFC3164Date); pHOSTNAME = (uchar *)getHOSTNAME(pMsg); lenHOSTNAME = getHOSTNAMELen(pMsg); getTAG(pMsg, &pTAG, &lenTAG, LOCK_MUTEX); if (lenTAG > 32) lenTAG = 32; /* for forwarding, a max of 32 chars is permitted (RFC!) */ pMSG = getMSG(pMsg); lenMSG = getMSGLen(pMsg); /* calculate len, constants for spaces and similar fixed strings */ lenTotal = 1 + lenPRI + 1 + CONST_LEN_TIMESTAMP_3164 + 1 + lenHOSTNAME + 1 + lenTAG + lenMSG + 1; if (pMSG[0] != ' ') ++lenTotal; /* then we need to introduce one additional space */ /* now make sure buffer is large enough */ if (lenTotal >= iparam->lenBuf) CHKiRet(ExtendBuf(iparam, lenTotal)); /* and concatenate the resulting string */ iparam->param[0] = '<'; memcpy(iparam->param + 1, pPRI, lenPRI); iBuf = lenPRI + 1; iparam->param[iBuf++] = '>'; memcpy(iparam->param + iBuf, pTimeStamp, CONST_LEN_TIMESTAMP_3164); iBuf += CONST_LEN_TIMESTAMP_3164; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pHOSTNAME, lenHOSTNAME); iBuf += lenHOSTNAME; iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pTAG, lenTAG); iBuf += lenTAG; if (pMSG[0] != ' ') iparam->param[iBuf++] = ' '; memcpy(iparam->param + iBuf, pMSG, lenMSG); iBuf += lenMSG; /* string terminator */ iparam->param[iBuf] = '\0'; iparam->lenStr = lenTotal - 1; /* do not count \0! */ finalize_it: ENDstrgen BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_SMOD_QUERIES; ENDqueryEtryPt BEGINmodInit(smtradfwd) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf( "rsyslog traditional (network) forward format strgen init called, compiled with " "version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/gethostn.c0000644000000000000000000000013115132411300015663 xustar0029 mtime=1768559296.30288621 30 atime=1782715518.783788755 30 ctime=1787067795.307742069 rsyslog-8.2608.0/tools/gethostn.c0000666000175000017500000000270215132411300015333 0ustar00rgerrger/* gethostn - a small diagnostic utility to show what the * gethostname() API returns. Of course, this tool duplicates * functionality already found in other tools. But the point is * that the API shall be called by a program that is compiled like * rsyslogd and does exactly what rsyslog does. * * Copyright 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include int main(int __attribute__((unused)) argc, char __attribute__((unused)) * argv[]) { char hostname[4096]; /* this should always be sufficient ;) */ int err; err = gethostname(hostname, sizeof(hostname)); if (err) { perror("gethostname failed"); exit(1); } printf("hostname of this system is '%s'.\n", hostname); return 0; } rsyslog-8.2608.0/tools/PaxHeaders/omshell.h0000644000000000000000000000013215141401300015500 xustar0030 mtime=1770390208.969869851 30 atime=1787067618.271442133 30 ctime=1787067795.236740745 rsyslog-8.2608.0/tools/omshell.h0000664000175000017500000000240015141401300015140 0ustar00rgerrger/* omshell.c * These are the definitions for the build-in shell output module. * * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) * * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ACTSHELL_H_INCLUDED #define ACTSHELL_H_INCLUDED 1 /* prototypes */ rsRetVal modInitShell(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef ACTSHELL_H_INCLUDED */ /* * vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/smfwd.h0000644000000000000000000000013215141401300015155 xustar0030 mtime=1770390208.970869795 30 atime=1787067618.330443233 30 ctime=1787067795.283741621 rsyslog-8.2608.0/tools/smfwd.h0000664000175000017500000000222215141401300014617 0ustar00rgerrger/* smfwd.h * * File begun on 2010-06-04 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SMFWD_H_INCLUDED #define SMFWD_H_INCLUDED 1 /* prototypes */ rsRetVal modInitsmfwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef SMFWD_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/omusrmsg.h0000644000000000000000000000013215141401300015711 xustar0030 mtime=1770390208.970869795 30 atime=1787067618.276442227 30 ctime=1787067795.241740839 rsyslog-8.2608.0/tools/omusrmsg.h0000664000175000017500000000364015141401300015360 0ustar00rgerrger/** * @file omusrmsg.h * @brief Interface for the built-in user message output module. * * This header exposes the initialization routine for the `omusrmsg` * module. The module implements delivery of log messages directly to * logged-in users (either individually or via "wall" style broadcast). * * File begun on 2007-07-13 by Rainer Gerhards. * * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OMUSRMSG_H_INCLUDED #define OMUSRMSG_H_INCLUDED 1 /* prototypes */ /** * Initialize the omusrmsg module. * * @param[in] iIFVersRequested interface version requested by the core * @param[out] ipIFVersProvided the interface version actually provided * @param[out] pQueryEtryPt receives module entry points * @param[in] pHostQueryEtryPt callback used to query host entry points * @param[in] pModInfo pointer to the module information block * * @return rsRetVal standard return code */ rsRetVal modInitUsrMsg(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *pModInfo); #endif /* #ifndef OMUSRMSG_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/iminternal.c0000644000000000000000000000013115132411300016172 xustar0029 mtime=1768559296.30288621 30 atime=1787067622.126514013 30 ctime=1787067795.290741752 rsyslog-8.2608.0/tools/iminternal.c0000666000175000017500000001202415132411300015640 0ustar00rgerrger/* iminternal.c * This file set implements the internal messages input module for rsyslog. * Note: we currently do not have an input module spec, but * we will have one in the future. This module needs then to be * adapted. * * File begun on 2007-08-03 by RGerhards * * Copyright 2007-2022 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include "syslogd.h" #include "linkedlist.h" #include "iminternal.h" #include "unicode-helper.h" static linkedList_t llMsgs; static pthread_mutex_t mutList = PTHREAD_MUTEX_INITIALIZER; /* destructs an iminternal object */ static rsRetVal iminternalDestruct(iminternal_t *pThis) { DEFiRet; if (pThis->pMsg != NULL) msgDestruct(&pThis->pMsg); free(pThis); RETiRet; } /* Construct an iminternal object */ static rsRetVal iminternalConstruct(iminternal_t **ppThis) { DEFiRet; if ((*ppThis = (iminternal_t *)calloc(1, sizeof(iminternal_t))) == NULL) { iRet = RS_RET_OUT_OF_MEMORY; } RETiRet; } /* add a message to the linked list * Note: the pMsg reference counter is not incremented. Consequently, * the caller must NOT decrement it. The caller actually hands over * full ownership of the pMsg object. */ rsRetVal iminternalAddMsg(smsg_t *pMsg) { DEFiRet; iminternal_t *pThis = NULL; struct timespec to; int r; int is_locked = 0; /* we guard against deadlock, so we can guarantee rsyslog will never * block due to internal messages. The 1 second timeout should be * sufficient under all circumstances. */ to.tv_sec = time(NULL) + 1; to.tv_nsec = 0; #if !defined(__APPLE__) r = pthread_mutex_timedlock(&mutList, &to); #else r = pthread_mutex_trylock(&mutList); // must check #endif if (r != 0) { dbgprintf("iminternalAddMsg: timedlock for mutex failed with %d, msg %s\n", r, getMSG(pMsg)); /* the message is lost, nothing we can do against this! */ msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_ERR); } is_locked = 1; CHKiRet(iminternalConstruct(&pThis)); pThis->pMsg = pMsg; CHKiRet(llAppend(&llMsgs, NULL, (void *)pThis)); if (PREFER_FETCH_32BIT(bHaveMainQueue)) { DBGPRINTF("signaling new internal message via SIGTTOU: '%s'\n", pThis->pMsg->pszRawMsg); kill(glblGetOurPid(), SIGTTOU); } finalize_it: if (is_locked) { pthread_mutex_unlock(&mutList); } if (iRet != RS_RET_OK) { dbgprintf("iminternalAddMsg() error %d - can not otherwise report this error, message lost\n", iRet); if (pThis != NULL) iminternalDestruct(pThis); } RETiRet; } /* pull the first error message from the linked list, remove it * from the list and return it to the caller. The caller is * responsible for freeing the message! */ rsRetVal iminternalRemoveMsg(smsg_t **ppMsg) { DEFiRet; iminternal_t *pThis; linkedListCookie_t llCookie = NULL; pthread_mutex_lock(&mutList); CHKiRet(llGetNextElt(&llMsgs, &llCookie, (void *)&pThis)); if (!strcmp((char *)pThis->pMsg->pszHOSTNAME, "[localhost]")) { /* early (pre-conf) startup message detected, need to set real hostname now */ MsgSetHOSTNAME(pThis->pMsg, glblGetLocalHostName(), ustrlen(glblGetLocalHostName())); } *ppMsg = pThis->pMsg; pThis->pMsg = NULL; /* we do no longer own it - important for destructor */ if (llDestroyRootElt(&llMsgs) != RS_RET_OK) { dbgprintf( "Root element of iminternal linked list could not be destroyed - there is " "nothing we can do against it, we ignore it for now. Things may go wild " "from here on. This is most probably a program logic error.\n"); } finalize_it: pthread_mutex_unlock(&mutList); RETiRet; } /* initialize the iminternal subsystem * must be called once at the start of the program */ rsRetVal modInitIminternal(void) { DEFiRet; iRet = llInit(&llMsgs, (rsRetVal(*)(void *))iminternalDestruct, NULL, NULL); RETiRet; } /* de-initialize the iminternal subsystem * must be called once at the end of the program * Note: the error list must have been pulled first. We do * NOT care if there are any errors left - we simply destroy * them. */ rsRetVal modExitIminternal(void) { DEFiRet; iRet = llDestroy(&llMsgs); RETiRet; } rsyslog-8.2608.0/tools/PaxHeaders/logctl.c0000644000000000000000000000013215132733117015332 xustar0030 mtime=1768666703.971621208 30 atime=1787067622.085513248 30 ctime=1787067795.297741882 rsyslog-8.2608.0/tools/logctl.c0000666000175000017500000003116115132733117015002 0ustar00rgerrger/** * logctl - a tool to access lumberjack logs in MongoDB * ... and potentially other sources in the future. * * Copyright 2012-2022 Ulrike Gerhards and Adiscon GmbH. * * Copyright 2017 Hugo Soszynski and aDvens * * long short * level l read records with level x * severity s read records with severity x * ret r number of records to return * skip k number of records to skip * sys y read records of system x * msg m read records with message containing x * datef f read records starting on time received x * dateu u read records until time received x * * examples: * * logctl -f 15/05/2012-12:00:00 -u 15/05/2012-12:37:00 * logctl -s 50 --ret 10 * logctl -m "closed" * logctl -l "INFO" * logctl -s 3 * logctl -y "ubuntu" * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #define _XOPEN_SOURCE 700 /* Need to define POSIX version to use strptime() */ #include #include #include #include #include #include #include #include "rsyslog.h" /* we need this to avoid issues with older versions of libbson */ PRAGMA_DIAGNOSTIC_PUSH; PRAGMA_IGNORE_Wpragmas; PRAGMA_IGNORE_Wunknown_warning_option; PRAGMA_IGNORE_Wunknown_attribute; PRAGMA_IGNORE_Wexpansion_to_defined; PRAGMA_IGNORE_Wstrict_prototypes; PRAGMA_IGNORE_Wold_style_definition; #ifdef HAVE_LIBMONGOC1 #include #include #else #include #include #endif PRAGMA_DIAGNOSTIC_POP; #define N 80 static struct option long_options[] = {{"level", required_argument, NULL, 'l'}, {"severity", required_argument, NULL, 's'}, {"ret", required_argument, NULL, 'r'}, {"skip", required_argument, NULL, 'k'}, {"sys", required_argument, NULL, 'y'}, {"msg", required_argument, NULL, 'm'}, {"datef", required_argument, NULL, 'f'}, {"dateu", required_argument, NULL, 'u'}, {NULL, 0, NULL, 0}}; struct queryopt { int32_t e_sever; int32_t e_ret; int32_t e_skip; char* e_date; char* e_level; char* e_msg; char* e_sys; char* e_dateu; int bsever; int blevel; int bskip; int bret; int bsys; int bmsg; int bdate; int bdatef; int bdateu; }; struct ofields { const char* msg; const char* syslog_tag; const char* prog; char* date; int64_t date_r; }; struct query_doc { bson_t* query; }; struct select_doc { bson_t* select; }; struct db_connect { mongoc_client_t* conn; }; struct db_collection { mongoc_collection_t* collection; }; struct db_cursor { mongoc_cursor_t* cursor; }; struct results { const bson_t* result; }; static void formater(struct ofields* fields) { char str[N]; time_t rtime; struct tm now; rtime = (time_t)(fields->date_r / 1000); strftime(str, N, "%b %d %H:%M:%S", gmtime_r(&rtime, &now)); printf("%s %s %s %s\n", str, fields->prog, fields->syslog_tag, fields->msg); } static struct ofields* get_data(struct results* res) { struct ofields* fields; const char* msg; const char* prog; const char* syslog_tag; int64_t date_r; bson_iter_t c; fields = malloc(sizeof(struct ofields)); bson_iter_init_find(&c, res->result, "msg"); if (!(msg = bson_iter_utf8(&c, NULL))) { perror("bson_cursor_get_string()"); exit(1); } bson_iter_init_find(&c, res->result, "sys"); if (!(prog = bson_iter_utf8(&c, NULL))) { perror("bson_cursor_get_string()"); exit(1); } bson_iter_init_find(&c, res->result, "syslog_tag"); if (!(syslog_tag = bson_iter_utf8(&c, NULL))) { perror("bson_cursor_get_string()"); exit(1); } bson_iter_init_find(&c, res->result, "time_rcvd"); if (!(date_r = bson_iter_date_time(&c))) { perror("bson_cursor_get_utc_datetime()"); exit(1); } fields->msg = msg; fields->prog = prog; fields->syslog_tag = syslog_tag; fields->date_r = date_r; return fields; } static void getoptions(int argc, char* argv[], struct queryopt* opt) { int iarg; while ((iarg = getopt_long(argc, argv, "l:s:r:k:y:f:u:m:", long_options, NULL)) != -1) { /* check to see if a single character or long option came through */ switch (iarg) { /* short option 's' */ case 's': opt->bsever = 1; opt->e_sever = atoi(optarg); break; /* short option 'r' */ case 'r': opt->bret = 1; opt->e_ret = atoi(optarg); break; /* short option 'f' : date from */ case 'f': opt->bdate = 1; opt->bdatef = 1; opt->e_date = optarg; break; /* short option 'u': date until */ case 'u': opt->bdate = 1; opt->bdateu = 1; opt->e_dateu = optarg; break; /* short option 'k' */ case 'k': opt->bskip = 1; opt->e_skip = atoi(optarg); break; /* short option 'l' */ case 'l': opt->blevel = 1; opt->e_level = optarg; break; /* short option 'm' */ case 'm': opt->bmsg = 1; opt->e_msg = optarg; break; /* short option 'y' */ case 'y': opt->bsys = 1; opt->e_sys = optarg; break; default: break; } /* end switch iarg */ } /* end while */ } /* end void getoptions */ static struct select_doc* create_select(void) /* BSON object indicating the fields to return */ { struct select_doc* s_doc; s_doc = malloc(sizeof(struct select_doc)); s_doc->select = bson_new(); bson_append_utf8(s_doc->select, "syslog_tag", 10, "s", 1); bson_append_utf8(s_doc->select, "msg", 3, "ERROR", 5); bson_append_utf8(s_doc->select, "sys", 3, "sys", 3); bson_append_date_time(s_doc->select, "time_rcvd", 9, 1ll); return s_doc; } static struct query_doc* create_query(struct queryopt* opt) { struct query_doc* qu_doc; bson_t *query_what, *order_what, *msg_what, *date_what; struct tm tm; time_t t; int64_t ts; qu_doc = malloc(sizeof(struct query_doc)); qu_doc->query = bson_new(); query_what = bson_new(); bson_init(query_what); bson_append_document_begin(qu_doc->query, "$query", 6, query_what); if (opt->bsever == 1) { bson_append_int32(query_what, "syslog_sever", 12, opt->e_sever); } if (opt->blevel == 1) { bson_append_utf8(query_what, "level", 5, opt->e_level, -1); } if (opt->bmsg == 1) { msg_what = bson_new(); bson_init(msg_what); bson_append_document_begin(query_what, "msg", 3, msg_what); bson_append_utf8(msg_what, "$regex", 6, opt->e_msg, -1); bson_append_utf8(msg_what, "$options", 8, "i", 1); bson_append_document_end(query_what, msg_what); } if (opt->bdate == 1) { date_what = bson_new(); bson_init(date_what); bson_append_document_begin(query_what, "time_rcvd", 9, date_what); if (opt->bdatef == 1) { tm.tm_isdst = -1; strptime(opt->e_date, "%d/%m/%Y-%H:%M:%S", &tm); tm.tm_hour = tm.tm_hour + 1; t = mktime(&tm); ts = 1000 * (int64_t)t; bson_append_date_time(date_what, "$gt", 3, ts); } if (opt->bdateu == 1) { tm.tm_isdst = -1; strptime(opt->e_dateu, "%d/%m/%Y-%H:%M:%S", &tm); tm.tm_hour = tm.tm_hour + 1; t = mktime(&tm); ts = 1000 * (int64_t)t; bson_append_date_time(date_what, "$lt", 3, ts); } bson_append_document_end(query_what, date_what); } if (opt->bsys == 1) { bson_append_utf8(query_what, "sys", 3, opt->e_sys, -1); } bson_append_document_end(qu_doc->query, query_what); order_what = bson_new(); bson_init(order_what); bson_append_document_begin(qu_doc->query, "$orderby", 8, order_what); bson_append_date_time(order_what, "time_rcvd", 9, 1ll); bson_append_document_end(qu_doc->query, order_what); bson_free(order_what); return qu_doc; } static struct db_connect* create_conn(void) { struct db_connect* db_conn; db_conn = malloc(sizeof(struct db_connect)); db_conn->conn = mongoc_client_new("mongodb://localhost:27017"); if (!db_conn->conn) { perror("mongo_sync_connect()"); exit(1); } return db_conn; } static void close_conn(struct db_connect* db_conn) { mongoc_client_destroy(db_conn->conn); free(db_conn); } static void free_cursor(struct db_cursor* db_c) { mongoc_cursor_destroy(db_c->cursor); free(db_c); } static struct db_cursor* launch_query(struct queryopt* opt, __attribute__((unused)) struct select_doc* s_doc, struct query_doc* qu_doc, struct db_collection* db_coll) { struct db_cursor* out; #if MONGOC_CHECK_VERSION(1, 5, 0) /* Declaration before code (ISO C90) */ const bson_t* opts = BCON_NEW("skip", BCON_INT32(opt->e_skip), "limit", BCON_INT32(opt->e_ret)); #endif /* MONGOC_CHECK_VERSION (1, 5, 0) */ out = malloc(sizeof(struct db_cursor)); if (!out) { perror("mongo_sync_cmd_query()"); printf("malloc failed\n"); exit(1); } #if MONGOC_CHECK_VERSION(1, 5, 0) out->cursor = mongoc_collection_find_with_opts(db_coll->collection, qu_doc->query, opts, NULL); #else /* !MONGOC_CHECK_VERSION (1, 5, 0) */ out->cursor = mongoc_collection_find(db_coll->collection, MONGOC_QUERY_NONE, (uint32_t)opt->e_skip, (uint32_t)opt->e_ret, 0, qu_doc->query, s_doc->select, NULL); #endif /* MONGOC_CHECK_VERSION (1, 5, 0) */ if (!out->cursor) { perror("mongo_sync_cmd_query()"); printf("no records found\n"); exit(1); } return out; } static int cursor_next(struct db_cursor* db_c, struct results* res) { if (mongoc_cursor_next(db_c->cursor, &res->result)) return true; return false; } static struct db_collection* get_collection(struct db_connect* db_conn) { struct db_collection* coll; coll = malloc(sizeof(struct db_collection)); coll->collection = mongoc_client_get_collection(db_conn->conn, "syslog", "log"); return coll; } static void release_collection(struct db_collection* db_coll) { mongoc_collection_destroy(db_coll->collection); free(db_coll); } int main(int argc, char* argv[]) { struct queryopt opt; struct ofields* fields; struct select_doc* s_doc; struct query_doc* qu_doc; struct db_connect* db_conn; struct db_cursor* db_c; struct db_collection* db_coll; struct results* res; memset(&opt, 0, sizeof(struct queryopt)); mongoc_init(); /* Initialisation of mongo-c-driver */ getoptions(argc, argv, &opt); qu_doc = create_query(&opt); /* create query */ s_doc = create_select(); db_conn = create_conn(); /* create connection */ db_coll = get_collection(db_conn); /* Get the collection to perform query on */ db_c = launch_query(&opt, s_doc, qu_doc, db_coll); /* launch the query and get the related cursor */ res = malloc(sizeof(struct results)); while (cursor_next(db_c, res)) /* Move cursor & get pointed data */ { fields = get_data(res); formater(fields); /* format output */ free(fields); } free(res); free_cursor(db_c); release_collection(db_coll); close_conn(db_conn); free(s_doc); free(qu_doc); mongoc_cleanup(); /* Cleanup of mongo-c-driver */ return (0); } rsyslog-8.2608.0/tools/PaxHeaders/ompipe.c0000644000000000000000000000013115216464436015346 xustar0030 mtime=1782212894.094267283 29 atime=1787067622.10651364 30 ctime=1787067795.253741062 rsyslog-8.2608.0/tools/ompipe.c0000664000175000017500000003136115216464436015017 0ustar00rgerrger/* ompipe.c * This is the implementation of the build-in pipe output module. * Note that this module stems back to the "old" (4.4.2 and below) * omfile. There were some issues with the new omfile code and pipes * (namely in regard to xconsole), so we took out the pipe code and moved * that to a separate module. That a) immediately solves the issue for a * less common use case and probably makes it much easier to enhance * file and pipe support (now independently) in the future (we always * needed to think about pipes in omfile so far, what we now no longer * need to, hopefully resulting in reduction of complexity). * * NOTE: read comments in module-template.h to understand how this pipe * works! * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "syslogd.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "ompipe.h" #include "omfile.h" /* for dirty trick: access to $ActionFileDefaultTemplate value */ #include "cfsysline.h" #include "module-template.h" #include "conf.h" #include "errmsg.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("ompipe") /* internal structures */ DEF_OMOD_STATIC_DATA; typedef struct _instanceData { uchar *pipe; /* pipe or template name (display only) */ uchar *tplName; /* format template to use */ short fd; /* pipe descriptor for (current) pipe */ pthread_mutex_t mutWrite; /* guard against multiple instances writing to same pipe */ sbool bHadError; /* did we already have/report an error on this pipe? */ sbool bTryResumeReopen; /* should we attempt to reopen the pipe on action resume? */ } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; typedef struct configSettings_s { EMPTY_STRUCT } configSettings_t; static configSettings_t __attribute__((unused)) cs; /* tables for interfacing with the v6 config system */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"template", eCmdHdlrGetWord, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"pipe", eCmdHdlrString, CNFPARAM_REQUIRED}, {"template", eCmdHdlrGetWord, 0}, {"tryResumeReopen", eCmdHdlrBinary, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ uchar *tplName; /* default template */ }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ /* this function gets the default template */ static uchar *getDfltTpl(void) { if (loadModConf != NULL && loadModConf->tplName != NULL) return loadModConf->tplName; else return (uchar *)"RSYSLOG_FileFormat"; } BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars; ENDinitConfVars BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; dbgprintf("pipe %s", pData->pipe); if (pData->fd == -1) dbgprintf(" (unused)"); ENDdbgPrintInstInfo /* This is now shared code for all types of files. It simply prepares * pipe access, which, among others, means the the pipe wil be opened * and any directories in between will be created (based on config, of * course). -- rgerhards, 2008-10-22 * changed to iRet interface - 2009-03-19 */ static rsRetVal preparePipe(instanceData *pData) { DEFiRet; pData->fd = open((char *)pData->pipe, O_RDWR | O_NONBLOCK | O_CLOEXEC); if (pData->fd < 0) { pData->fd = -1; if (!pData->bHadError) { LogError(errno, RS_RET_NO_FILE_ACCESS, "Could not open output pipe '%s':", pData->pipe); pData->bHadError = 1; } DBGPRINTF("Error opening log pipe: %s\n", pData->pipe); } RETiRet; } /* rgerhards 2004-11-11: write to a pipe output. This * will be called for all outputs using pipe semantics, * for example also for pipes. */ static rsRetVal writePipe(uchar **ppString, instanceData *pData) { int iLenWritten; DEFiRet; assert(pData != NULL); if (pData->fd == -1) { rsRetVal iRetLocal; iRetLocal = preparePipe(pData); if ((iRetLocal != RS_RET_OK) || (pData->fd == -1)) ABORT_FINALIZE(RS_RET_SUSPENDED); /* whatever the failure was, we need to retry */ } /* create the message based on format specified */ iLenWritten = write(pData->fd, ppString[0], strlen((char *)ppString[0])); if (iLenWritten < 0) { const int e = errno; /* If a named pipe is full, we suspend this action for a while */ if (e == EAGAIN) ABORT_FINALIZE(RS_RET_SUSPENDED); close(pData->fd); pData->fd = -1; /* tell that fd is no longer open! */ iRet = RS_RET_SUSPENDED; LogError(e, NO_ERRCODE, "write error on pipe %s", pData->pipe); } finalize_it: RETiRet; } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; pModConf->tplName = NULL; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for ompipe:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "template")) { CHKmalloc(loadModConf->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (pszFileDfltTplName != NULL) { LogError(0, RS_RET_DUP_PARAM, "ompipe: warning: default template " "was already set via legacy directive - may lead to inconsistent " "results."); } } else { dbgprintf( "ompipe: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; /* done loading */ /* free legacy config vars */ free(pszFileDfltTplName); pszFileDfltTplName = NULL; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(pModConf->tplName); ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; pData->pipe = NULL; pData->fd = -1; pData->bHadError = 0; pData->bTryResumeReopen = 0; pthread_mutex_init(&pData->mutWrite, NULL); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINfreeInstance CODESTARTfreeInstance; pthread_mutex_destroy(&pData->mutWrite); free(pData->pipe); if (pData->fd != -1) close(pData->fd); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINtryResume instanceData *__restrict__ const pData = pWrkrData->pData; fd_set wrds; struct timeval tv; int ready; CODESTARTtryResume; if (pData->fd == -1) { rsRetVal iRetLocal; iRetLocal = preparePipe(pData); if ((iRetLocal != RS_RET_OK) || (pData->fd == -1)) ABORT_FINALIZE(RS_RET_SUSPENDED); } else { /* we can reach this if the pipe is full, so we need * to check if we can write again. /dev/xconsole is the * ugly example of why this is necessary. */ FD_ZERO(&wrds); FD_SET(pData->fd, &wrds); tv.tv_sec = 0; tv.tv_usec = 0; ready = select(pData->fd + 1, NULL, &wrds, NULL, &tv); DBGPRINTF("ompipe: tryResume: ready to write fd %d: %d\n", pData->fd, ready); if (ready != 1) { if (pData->bTryResumeReopen && pData->fd != -1) { close(pData->fd); pData->fd = -1; } ABORT_FINALIZE(RS_RET_SUSPENDED); } } finalize_it: ENDtryResume BEGINdoAction instanceData *pData; CODESTARTdoAction; pData = pWrkrData->pData; DBGPRINTF("ompipe: writing to %s\n", pData->pipe); /* this module is single-threaded by nature */ pthread_mutex_lock(&pData->mutWrite); iRet = writePipe(ppString, pData); pthread_mutex_unlock(&pData->mutWrite); ENDdoAction static inline void setInstParamDefaults(instanceData *pData) { pData->tplName = NULL; } BEGINnewActInst struct cnfparamvals *pvals; int i; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); CODE_STD_STRING_REQUESTnewActInst(1); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "pipe")) { CHKmalloc(pData->pipe = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "tryResumeReopen")) { pData->bTryResumeReopen = (int)pvals[i].val.d.n; } else { dbgprintf( "ompipe: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)strdup((pData->tplName == NULL) ? "RSYSLOG_FileFormat" : (char *)pData->tplName), OMSR_NO_RQD_TPL_OPTS)); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINparseSelectorAct CODESTARTparseSelectorAct; /* yes, the if below is redundant, but I need it now. Will go away as * the code further changes. -- rgerhards, 2007-07-25 */ if (*p == '|') { if ((iRet = createInstance(&pData)) != RS_RET_OK) { return iRet; /* this can not use RET_iRet! */ } } else { /* this is not clean, but we need it for the time being * TODO: remove when cleaning up modularization */ return RS_RET_CONFLINE_UNPROCESSED; } CODE_STD_STRING_REQUESTparseSelectorAct(1) CHKmalloc(pData->pipe = malloc(512)); ++p; CHKiRet(cflineParseFileName(p, (uchar *)pData->pipe, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINdoHUP CODESTARTdoHUP; pthread_mutex_lock(&pData->mutWrite); if (pData->fd != -1) { close(pData->fd); pData->fd = -1; } pthread_mutex_unlock(&pData->mutWrite); ENDdoHUP BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_doHUP CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInitNoPredecl(Pipe) CODESTARTmodInit; INITLegCnfVars; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/smfile.h0000644000000000000000000000013215141401300015314 xustar0030 mtime=1770390208.970869795 30 atime=1787067618.311442879 30 ctime=1787067795.278741528 rsyslog-8.2608.0/tools/smfile.h0000664000175000017500000000235115141401300014761 0ustar00rgerrger/* smfile.h * These are the definitions for the traditional file format stringen module. * * File begun on 2010-06-04 by RGerhards * * Copyright 2010-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SMFILE_H_INCLUDED #define SMFILE_H_INCLUDED 1 /* prototypes */ rsRetVal modInitsmfile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef SMFILE_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/pmrfc3164.c0000644000000000000000000000013115241075234015472 xustar0030 mtime=1787067036.651579156 29 atime=1787067036.80458202 30 ctime=1787067795.267741323 rsyslog-8.2608.0/tools/pmrfc3164.c0000664000175000017500000005660515241075234015153 0ustar00rgerrger/* pmrfc3164.c * This is a parser module for RFC3164(legacy syslog)-formatted messages. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2009-11-04 by RGerhards * * Copyright 2007-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" #include "ruleset.h" #include "rsconf.h" #include "atomic.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.rfc3164") MODULE_CNFNAME("pmrfc3164") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl); DEFobjCurrIf(parser); DEFobjCurrIf(datetime); DEFobjCurrIf(ruleset); /* parser instance parameters */ static struct cnfparamdescr parserpdescr[] = { {"detect.yearaftertimestamp", eCmdHdlrBinary, 0}, {"permit.squarebracketsinhostname", eCmdHdlrBinary, 0}, {"permit.slashesinhostname", eCmdHdlrBinary, 0}, {"permit.atsignsinhostname", eCmdHdlrBinary, 0}, {"force.tagendingbycolon", eCmdHdlrBinary, 0}, {"remove.msgfirstspace", eCmdHdlrBinary, 0}, {"detect.headerless", eCmdHdlrBinary, 0}, {"headerless.hostname", eCmdHdlrString, 0}, {"headerless.tag", eCmdHdlrString, 0}, {"headerless.ruleset", eCmdHdlrString, 0}, {"headerless.errorfile", eCmdHdlrString, 0}, {"headerless.drop", eCmdHdlrBinary, 0}, }; static struct cnfparamblk parserpblk = {CNFPARAMBLK_VERSION, sizeof(parserpdescr) / sizeof(struct cnfparamdescr), parserpdescr}; struct instanceConf_s { int bDetectYearAfterTimestamp; int bPermitSquareBracketsInHostname; int bPermitSlashesInHostname; int bPermitAtSignsInHostname; int bForceTagEndingByColon; int bRemoveMsgFirstSpace; int bHdrLessMode; /**< is headerless mode activated? 0 - no, other - yes */ uchar* pszHeaderlessHostname; /** < HOSTNAME to use for headerless messages */ uchar* pszHeaderlessTag; /** < TAG to use for headerless messages */ uchar* pszHeaderlessRulesetName; /** < name of Ruleset to use for headerless messages */ ruleset_t* pHeaderlessRuleset; /**< Ruleset to use for headerless messages */ DEF_ATOMIC_HELPER_MUT(mutHeaderlessRuleset); /**< mutex for atomic operations on pHeaderlessRuleset */ uchar* pszHeaderlessErrFile; /**< name of error file for headerless messages */ FILE* fpHeaderlessErr; /**< file pointer for error file (headerless) */ pthread_mutex_t mutErrFile; int bDropHeaderless; int bParseHOSTNAMEandTAG; }; BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature /* create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal createInstance(instanceConf_t** pinst) { instanceConf_t* inst; DEFiRet; CHKmalloc(inst = malloc(sizeof(instanceConf_t))); inst->bDetectYearAfterTimestamp = 0; inst->bPermitSquareBracketsInHostname = 0; inst->bPermitSlashesInHostname = 0; inst->bPermitAtSignsInHostname = 0; inst->bForceTagEndingByColon = 0; inst->bRemoveMsgFirstSpace = 0; inst->bHdrLessMode = 0; inst->pszHeaderlessHostname = NULL; inst->pszHeaderlessTag = NULL; inst->pszHeaderlessRulesetName = NULL; inst->pHeaderlessRuleset = NULL; INIT_ATOMIC_HELPER_MUT(inst->mutHeaderlessRuleset); inst->pszHeaderlessErrFile = NULL; inst->fpHeaderlessErr = NULL; pthread_mutex_init(&inst->mutErrFile, NULL); inst->bDropHeaderless = 0; inst->bParseHOSTNAMEandTAG = 1; *pinst = inst; finalize_it: RETiRet; } BEGINnewParserInst struct cnfparamvals* pvals = NULL; int i; CODESTARTnewParserInst; DBGPRINTF("newParserInst (pmrfc3164)\n"); inst = NULL; CHKiRet(createInstance(&inst)); if (lst == NULL) FINALIZE; /* just set defaults, no param block! */ if ((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("parser param blk in pmrfc3164:\n"); cnfparamsPrint(&parserpblk, pvals); } for (i = 0; i < parserpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(parserpblk.descr[i].name, "detect.yearaftertimestamp")) { inst->bDetectYearAfterTimestamp = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "permit.squarebracketsinhostname")) { inst->bPermitSquareBracketsInHostname = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "permit.slashesinhostname")) { inst->bPermitSlashesInHostname = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "permit.atsignsinhostname")) { inst->bPermitAtSignsInHostname = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "force.tagendingbycolon")) { inst->bForceTagEndingByColon = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "remove.msgfirstspace")) { inst->bRemoveMsgFirstSpace = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "detect.headerless")) { inst->bHdrLessMode = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "headerless.hostname")) { CHKmalloc(inst->pszHeaderlessHostname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(parserpblk.descr[i].name, "headerless.tag")) { CHKmalloc(inst->pszHeaderlessTag = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(parserpblk.descr[i].name, "headerless.ruleset")) { CHKmalloc(inst->pszHeaderlessRulesetName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(parserpblk.descr[i].name, "headerless.errorfile")) { CHKmalloc(inst->pszHeaderlessErrFile = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(parserpblk.descr[i].name, "headerless.drop")) { inst->bDropHeaderless = (int)pvals[i].val.d.n; } else { dbgprintf( "pmrfc3164: program error, non-handled " "param '%s'\n", parserpblk.descr[i].name); } } finalize_it: CODE_STD_FINALIZERnewParserInst if (lst != NULL) cnfparamvalsDestruct(pvals, &parserpblk); if (iRet != RS_RET_OK) free(inst); ENDnewParserInst BEGINfreeParserInst CODESTARTfreeParserInst; free(pInst->pszHeaderlessHostname); free(pInst->pszHeaderlessTag); free(pInst->pszHeaderlessRulesetName); free(pInst->pszHeaderlessErrFile); if (pInst->fpHeaderlessErr != NULL) fclose(pInst->fpHeaderlessErr); pthread_mutex_destroy(&pInst->mutErrFile); DESTROY_ATOMIC_HELPER_MUT(pInst->mutHeaderlessRuleset); dbgprintf("pmrfc3164: free parser instance %p\n", pInst); ENDfreeParserInst BEGINcheckParserInst CODESTARTcheckParserInst; pInst->bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); if (pInst->pszHeaderlessRulesetName != NULL) { ruleset_t* myRuleset = NULL; rsRetVal localRet = ruleset.GetRuleset(loadConf, &myRuleset, pInst->pszHeaderlessRulesetName); if (localRet == RS_RET_OK && myRuleset != NULL) { pInst->pHeaderlessRuleset = myRuleset; } else { LogError(0, localRet, "pmrfc3164: ruleset '%s' not found, cannot route headerless messages, " "not assigning any ruleset to these messages.", pInst->pszHeaderlessRulesetName); } } ENDcheckParserInst BEGINdoHUPParser CODESTARTdoHUPParser; instanceConf_t* pInst = (instanceConf_t*)pData; /* Close and reopen error file on HUP signal to support log rotation */ if (pInst->pszHeaderlessErrFile != NULL) { pthread_mutex_lock(&pInst->mutErrFile); if (pInst->fpHeaderlessErr != NULL) { fclose(pInst->fpHeaderlessErr); pInst->fpHeaderlessErr = NULL; DBGPRINTF("pmrfc3164: closed error file %s on HUP\n", pInst->pszHeaderlessErrFile); } /* File will be reopened on next write attempt in handleHeaderlessMessage() */ pthread_mutex_unlock(&pInst->mutErrFile); } ENDdoHUPParser /** Handle a headerless message by setting defaults and marking the object */ static ATTR_NONNULL() rsRetVal handleHeaderlessMessage(smsg_t* pMsg, instanceConf_t* const pInst, uchar* p2parse) { DEFiRet; uchar* hostname = pInst->pszHeaderlessHostname ? pInst->pszHeaderlessHostname : getRcvFrom(pMsg); if (hostname == NULL) hostname = (uchar*)"unknown"; MsgSetHOSTNAME(pMsg, hostname, strlen((char*)hostname)); uchar* tag = pInst->pszHeaderlessTag ? pInst->pszHeaderlessTag : (uchar*)"headerless"; MsgSetTAG(pMsg, tag, strlen((char*)tag)); MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg); if (pInst->pHeaderlessRuleset != NULL) MsgSetRuleset(pMsg, pInst->pHeaderlessRuleset); if (pInst->pszHeaderlessErrFile != NULL) { pthread_mutex_lock(&pInst->mutErrFile); if (pInst->fpHeaderlessErr == NULL) { pInst->fpHeaderlessErr = fopen((char*)pInst->pszHeaderlessErrFile, "a"); if (pInst->fpHeaderlessErr == NULL) { LogError(errno, RS_RET_ERR, "pmrfc3164: cannot open error file %s", pInst->pszHeaderlessErrFile); } } if (pInst->fpHeaderlessErr != NULL) { /* Write the raw message followed by a newline */ if (fwrite(pMsg->pszRawMsg, 1, pMsg->iLenRawMsg, pInst->fpHeaderlessErr) != (size_t)pMsg->iLenRawMsg || fputc('\n', pInst->fpHeaderlessErr) == EOF) { LogError(errno, RS_RET_IO_ERROR, "pmrfc3164: error writing to error file %s", pInst->pszHeaderlessErrFile); fclose(pInst->fpHeaderlessErr); pInst->fpHeaderlessErr = NULL; } } pthread_mutex_unlock(&pInst->mutErrFile); } DBGPRINTF("pmrfc3164: headerless message handled with hostname='%s', tag='%s'\n", hostname, tag); if (pInst->bDropHeaderless) ABORT_FINALIZE(RS_RET_DISCARDMSG); finalize_it: RETiRet; } /* parse a legacy-formatted syslog message. * We apply heuristics during header detection. These are not 100% failure * prove, but the best compromise we came up within 20+ years of adapting * the heuristics. */ BEGINparse2 uchar* p2parse; int lenMsg; int i; /* general index for parsing */ uchar bufParseTAG[CONF_TAG_MAXSIZE]; uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE]; CODESTARTparse; assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; DBGPRINTF("Message will now be parsed by the legacy syslog parser (offAfterPRI=%d, lenMsg=%d.\n", pMsg->offAfterPRI, lenMsg); /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ setProtocolVersion(pMsg, MSG_LEGACY_PROTOCOL); if (pMsg->iFacility == (LOG_INVLD >> 3)) { DBGPRINTF("facility LOG_INVLD, do not parse\n"); FINALIZE; } /* now check if we have a completely headerless message. This is always the * case if it starts with spaces or tabs followed '{' or '['. * Note that this is from the grown heuristics and not controlled by the * headerless options. // TODO: make transparent in conf? */ i = 0; while (i < lenMsg && (p2parse[i] == ' ' || p2parse[i] == '\t')) { ++i; } if (i < lenMsg && (p2parse[i] == '{' || p2parse[i] == '[')) { DBGPRINTF("msg seems to be headerless, treating it as such\n"); FINALIZE; } /* Check to see if msg contains a timestamp. We start by assuming * that the message timestamp is the time of reception (which we * generated ourselfs and then try to actually find one inside the * message. There we go from high-to low precison and are done * when we find a matching one. -- rgerhards, 2008-09-16 */ int bFoundTimestamp = 0; /**< indicates if we found a timestamp or not */ if (datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { bFoundTimestamp = 1; /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */; } else if (datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) { if (pMsg->dfltTZ[0] != '\0') applyDfltTZ(&pMsg->tTIMESTAMP, pMsg->dfltTZ); bFoundTimestamp = 1; /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; } else if (*p2parse == ' ' && lenMsg > 1) { /* try to see if it is slightly malformed - HP procurve seems to do that sometimes */ ++p2parse; /* move over space */ --lenMsg; if (datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg, NO_PARSE3164_TZSTRING, pInst->bDetectYearAfterTimestamp) == RS_RET_OK) { /* indeed, we got it! */ bFoundTimestamp = 1; /* we are done - parse pointer is moved by ParseTIMESTAMP3164 */; } else { /* parse pointer needs to be restored, as we moved it off-by-one * for this try. */ --p2parse; ++lenMsg; } } if (pInst->bHdrLessMode != 0 && bFoundTimestamp == 0) { /* we do not have a valid timestamp in any of the formats we support * This is a strong indication that the message is headerless. So let's * process it according to headerless rules. */ DBGPRINTF("msg seems to be headerless (no PRI, no timestamp), treating it as such\n"); CHKiRet(handleHeaderlessMessage(pMsg, pInst, p2parse)); } if (pMsg->msgFlags & IGNDATE) { /* we need to ignore the msg data, so simply copy over reception date */ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime)); } /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we * do this only when the user has not forbidden this. I now introduce some * code that allows a user to configure rsyslogd to treat the rest of the * message as MSG part completely. In this case, the hostname will be the * machine that we received the message from and the tag will be empty. This * is meant to be an interim solution, but for now it is in the code. */ if (pInst->bParseHOSTNAMEandTAG && !(pMsg->msgFlags & INTERNAL_MSG)) { /* parse HOSTNAME - but only if this is network-received! * rger, 2005-11-14: we still have a problem with BSD messages. These messages * do NOT include a host name. In most cases, this leads to the TAG to be treated * as hostname and the first word of the message as the TAG. Clearly, this is not * of advantage ;) I think I have now found a way to handle this situation: there * are certain characters which are frequently used in TAG (e.g. ':'), which are * *invalid* in host names. So while parsing the hostname, I check for these characters. * If I find them, I set a simple flag but continue. After parsing, I check the flag. * If it was set, then we most probably do not have a hostname but a TAG. Thus, I change * the fields. I think this logic shall work with any type of syslog message. * rgerhards, 2009-06-23: and I now have extended this logic to every character * that is not a valid hostname. * A "hostname" can validly include "[]" at the beginning and end. This sometimes * happens with IP address (e.g. "[192.168.0.1]"). This must be turned on via * an option as it may interfere with non-hostnames in some message formats. * rgerhards, 2015-04-20 */ if (lenMsg > 0 && pMsg->msgFlags & PARSE_HOSTNAME) { i = 0; int bHadSBracket = 0; if (pInst->bPermitSquareBracketsInHostname) { assert(i < lenMsg); if (p2parse[i] == '[') { bHadSBracket = 1; bufParseHOSTNAME[0] = '['; ++i; } } while (i < lenMsg && (isalnum(p2parse[i]) || p2parse[i] == '.' || p2parse[i] == '_' || p2parse[i] == '-' || (p2parse[i] == ']' && bHadSBracket) || (p2parse[i] == '@' && pInst->bPermitAtSignsInHostname) || (p2parse[i] == '/' && pInst->bPermitSlashesInHostname)) && i < (CONF_HOSTNAME_MAXSIZE - 1)) { bufParseHOSTNAME[i] = p2parse[i]; ++i; if (p2parse[i] == ']') break; /* must be closing bracket */ } if (i == lenMsg) { /* we have a message that is empty immediately after the hostname, * but the hostname thus is valid! -- rgerhards, 2010-02-22 */ p2parse += i; lenMsg -= i; bufParseHOSTNAME[i] = '\0'; MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, i); } else { int isHostName = 0; if (i > 0) { if (bHadSBracket) { if (p2parse[i] == ']') { bufParseHOSTNAME[i] = ']'; ++i; isHostName = 1; } } else { if (isalnum(p2parse[i - 1])) { isHostName = 1; } } if (p2parse[i] != ' ') isHostName = 0; } if (isHostName) { /* we got a hostname! */ p2parse += i + 1; /* "eat" it (including SP delimiter) */ lenMsg -= i + 1; bufParseHOSTNAME[i] = '\0'; MsgSetHOSTNAME(pMsg, bufParseHOSTNAME, i); } } } /* now parse TAG - that should be present in message from all sources. * This code is somewhat not compliant with RFC 3164. As of 3164, * the TAG field is ended by any non-alphanumeric character. In * practice, however, the TAG often contains dashes and other things, * which would end the TAG. So it is not desirable. As such, we only * accept colon and SP to be terminators. Even there is a slight difference: * a colon is PART of the TAG, while a SP is NOT part of the tag * (it is CONTENT). Starting 2008-04-04, we have removed the 32 character * size limit (from RFC3164) on the tag. This had bad effects on existing * environments, as sysklogd didn't obey it either (probably another bug * in RFC3164...). We now receive the full size, but will modify the * outputs so that only 32 characters max are used by default. */ uchar* const pTagStart = p2parse; i = 0; while (lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE - 2) { bufParseTAG[i++] = *p2parse++; --lenMsg; } if (lenMsg > 0 && *p2parse == ':') { ++p2parse; --lenMsg; bufParseTAG[i++] = ':'; } else if (pInst->bForceTagEndingByColon) { /* Tag need to be ended by a colon or it's not a tag but the * begin of the message */ size_t rewind = i; if (pTagStart > pMsg->pszRawMsg && pTagStart[-1] == ' ') { ++rewind; } p2parse -= rewind; lenMsg += rewind; i = 0; /* Default TAG is dash (without ':') */ bufParseTAG[i++] = '-'; } /* no TAG can only be detected if the message immediately ends, in which case an empty TAG * is considered OK. So we do not need to check for empty TAG. -- rgerhards, 2009-06-23 */ bufParseTAG[i] = '\0'; /* terminate string */ MsgSetTAG(pMsg, bufParseTAG, i); } else { /* we enter this code area when the user has instructed rsyslog NOT * to parse HOSTNAME and TAG - rgerhards, 2006-03-13 */ if (!(pMsg->msgFlags & INTERNAL_MSG)) { DBGPRINTF("HOSTNAME and TAG not parsed by user configuration.\n"); } } finalize_it: if (pInst->bRemoveMsgFirstSpace && *p2parse == ' ') { /* Bypass first space found in MSG part */ p2parse++; lenMsg--; } MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg); ENDparse2 #ifdef ENABLE_FUZZING static instanceConf_t* fuzzParserInstance; rsRetVal pmrfc3164FuzzInit(void); void pmrfc3164FuzzExit(void); rsRetVal pmrfc3164FuzzParse(smsg_t* pMsg); rsRetVal pmrfc3164FuzzInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(createInstance(&fuzzParserInstance)); finalize_it: RETiRet; } void pmrfc3164FuzzExit(void) { if (fuzzParserInstance != NULL) { freeParserInst(fuzzParserInstance); fuzzParserInstance = NULL; } objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); } rsRetVal pmrfc3164FuzzParse(smsg_t* pMsg) { if (fuzzParserInstance == NULL) return RS_RET_ERR; return parse2(fuzzParserInstance, pMsg); } #endif BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD2_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; CODEqueryEtryPt_doHUPParser; ENDqueryEtryPt BEGINmodInit(pmrfc3164) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); DBGPRINTF("rfc3164 parser init called\n"); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/omshell.c0000644000000000000000000000013215145046113015506 xustar0030 mtime=1771326539.072014827 30 atime=1787067622.080513155 30 ctime=1787067795.234740708 rsyslog-8.2608.0/tools/omshell.c0000664000175000017500000001027615145046113015160 0ustar00rgerrger/* omshell.c * This is the implementation of the build-in shell output module. * * ************* DO NOT EXTEND THIS MODULE ************** * This is pure legacy, omprog has much better and more * secure functionality than this module. It is NOT * recommended to base new work on it! * 2012-01-19 rgerhards * ****************************************************** * * NOTE: read comments in module-template.h to understand how this file * works! * * shell support was initially written by bkalkbrenner 2005-09-20 * * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c) * This file is under development and has not yet arrived at being fully * self-contained and a real object. So far, it is mostly an excerpt * of the "old" message code without any modifications. However, it * helps to have things at the right place one we go to the meat of it. * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "omshell.h" #include "module-template.h" #include "errmsg.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; /* internal structures */ DEF_OMOD_STATIC_DATA; typedef struct _instanceData { uchar progName[MAXFNAME]; /* program to execute */ } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; printf("%s", pData->progName); ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINdoAction CODESTARTdoAction; dbgprintf("\n"); if (execProg((uchar *)pWrkrData->pData->progName, 1, (uchar *)ppString[0], NULL) == 0) LogError(0, NO_ERRCODE, "Executing program '%s' failed", (char *)pWrkrData->pData->progName); ENDdoAction BEGINparseSelectorAct CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) /* yes, the if below is redundant, but I need it now. Will go away as * the code further changes. -- rgerhards, 2007-07-25 */ if (*p == '^') { if ((iRet = createInstance(&pData)) != RS_RET_OK) goto finalize_it; } switch (*p) { case '^': /* bkalkbrenner 2005-09-20: execute shell command */ dbgprintf("exec\n"); ++p; iRet = cflineParseFileName(p, (uchar *)pData->progName, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, (uchar *)"RSYSLOG_TraditionalFileFormat"); break; default: iRet = RS_RET_CONFLINE_UNPROCESSED; break; } CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; ENDqueryEtryPt BEGINmodInitNoPredecl(Shell) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr ENDmodInit /* * vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/omfile.c0000644000000000000000000000013215241075234015321 xustar0030 mtime=1787067036.650579137 30 atime=1787067036.803582002 30 ctime=1787067795.248740969 rsyslog-8.2608.0/tools/omfile.c0000664000175000017500000026226115241075234014776 0ustar00rgerrger/* omfile.c * This is the implementation of the build-in file output module. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c, which * at the time of the fork from sysklogd was under BSD license) * * A large re-write of this file was done in June, 2009. The focus was * to introduce many more features (like zipped writing), clean up the code * and make it more reliable. In short, that rewrite tries to provide a new * solid basis for the next three to five years to come. During it, bugs * may have been introduced ;) -- rgerhards, 2009-06-04 * * Note that as of 2010-02-28 this module does no longer handle * pipes. These have been moved to ompipe, to reduced the entanglement * between the two different functionalities. -- rgerhards * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ATOMIC_BUILTINS #include #endif #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "action.h" #include "outchannel.h" #include "omfile.h" #include "cfsysline.h" #include "module-template.h" #include "errmsg.h" #include "stream.h" #include "unicode-helper.h" #include "atomic.h" #include "statsobj.h" #include "sigprov.h" #include "cryprov.h" #include "parserif.h" #include "janitor.h" #include "rsconf.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omfile") /* forward definitions */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal); static rsRetVal normalizeDynaFileCacheSize(int *const pNewVal); typedef struct pathComponent_s { const char *ptr; size_t len; } pathComponent_t; /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(strm) DEFobjCurrIf(statsobj) /** * @brief Global counter/clock for file access timestamping. * * This counter is used as a "Lamport logical clock" for the LRU mechanism * of the dynamic file cache. It provides a monotonically increasing sequence * number to track the access order of files, rather than actual time. * It is highly unlikely to wrap within the lifetime of a process. */ #ifdef HAVE_ATOMIC_BUILTINS64 static uint64 clockFileAccess = 0; #else static unsigned clockFileAccess = 0; #endif /** * @brief Mutex for protecting clockFileAccess in non-atomic builtins environments. */ #ifndef HAVE_ATOMIC_BUILTINS static pthread_mutex_t mutClock; #endif /** * @brief Retrieves and increments the global file access clock. * * This function provides a monotonically increasing counter used for the LRU * mechanism in the dynamic file cache. It is thread-safe. * * @return The incremented value of the file access clock. */ static uint64 getClockFileAccess(void) { #ifdef HAVE_ATOMIC_BUILTINS64 return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock); #else return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock); #endif } /** * @brief Structure for a dynamic file name cache entry. * * This structure holds information about a dynamically opened file, * including its name, the associated stream, signature provider data, * and access timestamp for LRU management. */ struct s_dynaFileCacheEntry { uchar *pName; /**< name currently open, if dynamic name */ strm_t *pStrm; /**< our output stream */ void *sigprovFileData; /**< opaque data ptr for provider use */ uint64 clkTickAccessed; /**< for LRU - based on clockFileAccess */ short nInactive; /**< number of minutes not writen - for close timeout */ }; typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; #define IOBUF_DFLT_SIZE 4096 /**< default size for io buffers */ #define FLUSH_INTRVL_DFLT 1 /**< default buffer flush interval (in seconds) */ #define USE_ASYNCWRITER_DFLT 0 /**< default buffer use async writer */ #define FLUSHONTX_DFLT 1 /**< default for flush on TX end */ #define ADDLF_SIGBUF_STACKLEN 1024 /**< stack buffer size for addLF signing helper */ /** * @brief Instance data for the omfile module. * * This structure holds the configuration and runtime state for each * file output action. */ typedef struct _instanceData { pthread_mutex_t mutWrite; /**< guard against multiple instances writing to single file */ uchar *fname; /**< file or template name (display only) */ uchar *tplName; /**< name of assigned template */ uchar *dynaFileBasePath; /**< normalized constant base path for dynafile templates */ sbool bPermitDynaFilePathEscape; /**< permit dynafile paths outside the derived base */ sbool bRestrictDynaFileTplType; /**< reject template types without an inspectable fixed prefix */ strm_t *pStrm; /**< our output stream */ short nInactive; /**< number of minutes not writen (STATIC files only) */ char bDynamicName; /**< 0 - static name, 1 - dynamic name (with properties) */ int isDevNull; /**< do we "write" to /dev/null? - if so, do nothing */ int fCreateMode; /**< file creation mode for open() */ int fDirCreateMode; /**< creation mode for mkdir() */ int bCreateDirs; /**< auto-create directories? */ int bSyncFile; /**< should the file by sync()'ed? 1- yes, 0- no */ uint8_t iNumTpls; /**< number of tpls we use */ uid_t fileUID; /**< IDs for creation */ uid_t dirUID; gid_t fileGID; gid_t dirGID; int bFailOnChown; /**< fail creation if chown fails? */ uchar *sigprovName; /**< signature provider */ uchar *sigprovNameFull; /**< full internal signature provider name */ sigprov_if_t sigprov; /**< ptr to signature provider interface */ void *sigprovData; /**< opaque data ptr for provider use */ void *sigprovFileData; /**< opaque data ptr for file instance */ sbool useSigprov; /**< quicker than checkig ptr (1 vs 8 bytes!) */ uchar *cryprovName; /**< crypto provider */ uchar *cryprovNameFull; /**< full internal crypto provider name */ void *cryprovData; /**< opaque data ptr for provider use */ cryprov_if_t cryprov; /**< ptr to crypto provider interface */ sbool useCryprov; /**< quicker than checkig ptr (1 vs 8 bytes!) */ int iCurrElt; /**< currently active cache element (-1 = none) */ int iCurrCacheSize; /**< currently cache size (1-based) */ int iDynaFileCacheSize; /**< size of file handle cache */ /** * The cache is implemented as an array. An empty element is indicated * by a NULL pointer. Memory is allocated as needed. The following * pointer points to the overall structure. */ dynaFileCacheEntry **dynCache; off_t iSizeLimit; /**< file size limit, 0 = no limit */ uchar *pszSizeLimitCmd; /**< command to carry out when size limit is reached */ sbool bSizeLimitCmdPassFileName; /**< pass current file name to size limit command? */ int iZipLevel; /**< zip mode to use for this selector */ int iIOBufSize; /**< size of associated io buffer */ int iFlushInterval; /**< how fast flush buffer on inactivity? */ short iCloseTimeout; /**< after how many *minutes* shall the file be closed if inactive? */ sbool bFlushOnTXEnd; /**< flush write buffers when transaction has ended? */ sbool bUseAsyncWriter; /**< use async stream writer? */ sbool bVeryRobustZip; sbool bAddLF; /**< append LF to records that are missing it? */ int bFollowSymlinks; /**< allow final output path component to be a symlink? */ sbool bFollowSymlinksExplicit; /**< was symlink policy configured explicitly? */ statsobj_t *stats; /**< dynafile, primarily cache stats */ STATSCOUNTER_DEF(ctrRequests, mutCtrRequests); STATSCOUNTER_DEF(ctrLevel0, mutCtrLevel0); STATSCOUNTER_DEF(ctrEvict, mutCtrEvict); STATSCOUNTER_DEF(ctrMiss, mutCtrMiss); STATSCOUNTER_DEF(ctrMax, mutCtrMax); STATSCOUNTER_DEF(ctrCloseTimeouts, mutCtrCloseTimeouts); char janitorID[128]; /**< holds ID for janitor calls */ } instanceData; /** * @brief Worker instance data for the omfile module. * * This structure holds a pointer to the main instance data for use * by worker threads. */ typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; static int pathIsMeaningfulBase(const uchar *const path) { return path != NULL && path[0] != '\0' && ustrcmp(path, (uchar *)"."); } static int pathStartsWithParentRef(const uchar *const path) { return path[0] == '.' && path[1] == '.' && (path[2] == '\0' || path[2] == '/'); } /** * @brief Normalize a path syntactically without touching the filesystem. * * omfile may create missing directories and files, so realpath(3) cannot be * used here. This helper removes duplicate separators and "." components, and * resolves standalone ".." path components lexically. Relative paths that still * escape above their starting point keep leading ".." components so callers can * reject them. * * @param path Path string to normalize. * @param ppNorm Receives a newly allocated normalized path on success. * @return RS_RET_OK on success, RS_RET_OUT_OF_MEMORY on allocation failure. */ static rsRetVal normalizePathLexically(const uchar *const path, uchar **const ppNorm) { pathComponent_t *components = NULL; uchar *norm = NULL; const char *pszPath; const char *p; const char *start; uchar *dst; size_t lenPath; size_t maxComponents; size_t nComponents = 0; size_t lenComponent; size_t lenNorm; size_t i; int isAbsolute; DEFiRet; assert(path != NULL); assert(ppNorm != NULL); pszPath = (const char *)path; lenPath = strlen(pszPath); maxComponents = lenPath / 2 + 2; isAbsolute = pszPath[0] == '/'; CHKmalloc(components = calloc(maxComponents, sizeof(pathComponent_t))); p = pszPath; while (*p != '\0') { while (*p == '/') { ++p; } start = p; while (*p != '\0' && *p != '/') { ++p; } lenComponent = (size_t)(p - start); if (lenComponent == 0 || (lenComponent == 1 && start[0] == '.')) { continue; } if (lenComponent == 2 && start[0] == '.' && start[1] == '.') { if (nComponents > 0 && !(components[nComponents - 1].len == 2 && components[nComponents - 1].ptr[0] == '.' && components[nComponents - 1].ptr[1] == '.')) { --nComponents; } else if (!isAbsolute) { components[nComponents].ptr = start; components[nComponents].len = lenComponent; ++nComponents; } continue; } components[nComponents].ptr = start; components[nComponents].len = lenComponent; ++nComponents; } if (nComponents == 0) { CHKmalloc(norm = (uchar *)strdup(isAbsolute ? "/" : ".")); FINALIZE; } lenNorm = isAbsolute ? 1 : 0; for (i = 0; i < nComponents; ++i) { lenNorm += components[i].len; if (i > 0) { ++lenNorm; } } CHKmalloc(norm = malloc(lenNorm + 1)); dst = norm; if (isAbsolute) { *dst++ = '/'; } for (i = 0; i < nComponents; ++i) { if (i > 0) { *dst++ = '/'; } memcpy(dst, components[i].ptr, components[i].len); dst += components[i].len; } *dst = '\0'; finalize_it: free(components); if (iRet == RS_RET_OK) { *ppNorm = norm; } else { free(norm); } RETiRet; } static int normalizedPathIsBelowBase(const uchar *const normPath, const uchar *const normBase) { const size_t lenBase = ustrlen(normBase); if (!ustrcmp(normBase, (uchar *)"/")) { return normPath[0] == '/'; } if (!ustrcmp(normPath, normBase)) { return 1; } return !strncmp((const char *)normPath, (const char *)normBase, lenBase) && normPath[lenBase] == '/'; } /** * @brief Validate a rendered dynamic file name before it can be opened. * * If the dynafile template had a meaningful static directory prefix, the * rendered path must normalize to that directory or a child of it. For templates * where no useful base can be derived, absolute paths and leading parent * traversal are rejected as a fallback. Installations that intentionally rely * on those legacy forms can opt in with dangerousPermitPathEscape. * * @param pData omfile action instance data. * @param newFileName Rendered dynafile path. * @return RS_RET_OK if the path is acceptable, RS_RET_DISCARDMSG if it is blocked. */ static rsRetVal validateDynaFilePath(instanceData *const pData, const uchar *const newFileName) { uchar *normPath = NULL; DEFiRet; assert(pData != NULL); assert(newFileName != NULL); CHKiRet(normalizePathLexically(newFileName, &normPath)); if (pathIsMeaningfulBase(pData->dynaFileBasePath)) { if (!normalizedPathIsBelowBase(normPath, pData->dynaFileBasePath)) { LogError(0, RS_RET_ERR, "omfile: dynafile path traversal blocked: '%s' resolves outside base '%s'", newFileName, pData->dynaFileBasePath); ABORT_FINALIZE(RS_RET_DISCARDMSG); } } else if (normPath[0] == '/' || pathStartsWithParentRef(normPath)) { LogError(0, RS_RET_ERR, "omfile: dynafile path traversal blocked: '%s'", newFileName); ABORT_FINALIZE(RS_RET_DISCARDMSG); } finalize_it: free(normPath); RETiRet; } /** * @brief Derive the immutable base directory from a dynafile template. * * The trusted part of a dynafile template is the contiguous run of constant * template entries before the first property field. The last slash in that * trusted prefix defines the directory base that rendered file names may not * escape. For example, `/var/log/%HOSTNAME%/%APP-NAME%.log` derives `/var/log`. * * Templates backed by string generators or subtree output are intentionally not * inspected; in those cases runtime validation falls back to rejecting absolute * paths and leading parent traversal. * * @param pData omfile action instance data to receive the normalized base. * @param pTpl Resolved dynafile template. * @return RS_RET_OK on success, RS_RET_OUT_OF_MEMORY on allocation failure. */ static rsRetVal deriveDynaFileBasePath(instanceData *const pData, const struct template *const pTpl) { const struct templateEntry *entry; uchar *prefix = NULL; uchar *base = NULL; uchar *normBase = NULL; uchar *lastSlash; size_t prefixLen = 0; size_t baseLen; uchar *dst; DEFiRet; assert(pData != NULL); free(pData->dynaFileBasePath); pData->dynaFileBasePath = NULL; if (pTpl == NULL || pTpl->pStrgen != NULL || pTpl->bHaveSubtree) { FINALIZE; } /* Only constants before the first field are trusted as admin-authored path. */ for (entry = pTpl->pEntryRoot; entry != NULL && entry->eEntryType == CONSTANT; entry = entry->pNext) { prefixLen += (size_t)entry->data.constant.iLenConstant; } if (prefixLen == 0) { FINALIZE; } CHKmalloc(prefix = malloc(prefixLen + 1)); dst = prefix; for (entry = pTpl->pEntryRoot; entry != NULL && entry->eEntryType == CONSTANT; entry = entry->pNext) { memcpy(dst, entry->data.constant.pConstant, (size_t)entry->data.constant.iLenConstant); dst += entry->data.constant.iLenConstant; } *dst = '\0'; /* The base is the deepest complete directory in the trusted prefix. */ lastSlash = (uchar *)strrchr((const char *)prefix, '/'); if (lastSlash == NULL) { FINALIZE; } baseLen = (size_t)(lastSlash - prefix); if (baseLen == 0) { baseLen = 1; } CHKmalloc(base = malloc(baseLen + 1)); memcpy(base, prefix, baseLen); base[baseLen] = '\0'; CHKiRet(normalizePathLexically(base, &normBase)); if (pathIsMeaningfulBase(normBase)) { pData->dynaFileBasePath = normBase; normBase = NULL; } finalize_it: free(prefix); free(base); free(normBase); RETiRet; } /** * @brief Reject dynafile templates whose fixed prefix cannot be inspected. * * Dynafile path hardening depends on inspecting the static template entries * before the first message-derived field. Rsyslog string and list templates * both use the template entry list and can be checked this way. Subtree and * plugin/string-generator templates bypass that representation, so omfile * cannot derive a trusted base directory from their configured form. * * @param pData omfile action instance data. * @param pTpl Resolved dynafile template. * @return RS_RET_OK if the template type is accepted, RS_RET_ERR otherwise. */ static rsRetVal checkDynaFileTemplateType(instanceData *const pData, const struct template *const pTpl) { DEFiRet; assert(pData != NULL); if (pData->bRestrictDynaFileTplType && (pTpl == NULL || pTpl->pStrgen != NULL || pTpl->bHaveSubtree)) { LogError(0, RS_RET_ERR, "omfile: dynafile template '%s' uses a template type that cannot be " "safely inspected for path traversal; use type=\"string\" or " "type=\"list\", or set module parameter " "dynafile.restrictTemplateType=\"off\" to use the legacy " "template subject to the fallback path guards", pData->fname); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: RETiRet; } static void warnDynaFilePathEscapeEnabled(const char *const scope) { parser_warnmsg( "omfile: %s dynafile.dangerousPermitPathEscape permits dynafile " "paths to escape the configured base directory. This is dangerous " "with untrusted message properties and can overwrite any file " "permitted by OS permissions.", scope); } /** * @brief Module-global configuration settings. * * This structure holds the configuration settings that apply globally * to the omfile module. */ typedef struct configSettings_s { int iDynaFileCacheSize; /**< max cache for dynamic files */ int fCreateMode; /**< mode to use when creating files */ int fDirCreateMode; /**< mode to use when creating files */ int bFailOnChown; /**< fail if chown fails? */ uid_t fileUID; /**< UID to be used for newly created files */ uid_t fileGID; /**< GID to be used for newly created files */ uid_t dirUID; /**< UID to be used for newly created directories */ uid_t dirGID; /**< GID to be used for newly created directories */ int bCreateDirs; /**< auto-create directories for dynaFiles: 0 - no, 1 - yes */ int bEnableSync; /**< enable syncing of files (no dash in front of pathname in conf): 0 - no, 1 - yes */ int iZipLevel; /**< zip compression mode (0..9 as usual) */ sbool bFlushOnTXEnd; /**< flush write buffers when transaction has ended? */ int64 iIOBufSize; /**< size of an io buffer */ int iFlushInterval; /**< how often flush the output buffer on inactivity? */ int bUseAsyncWriter; /**< should we enable asynchronous writing? */ sbool bAddLF; /**< append LF to records that are missing it? */ EMPTY_STRUCT } configSettings_t; static configSettings_t cs; uchar *pszFileDfltTplName; /**< name of the default template to use */ /** * @brief Module configuration data for the v6 config system. */ struct modConfData_s { rsconf_t *pConf; /**< our overall config object */ uchar *tplName; /**< default template */ int fCreateMode; /**< default mode to use when creating files */ int fDirCreateMode; /**< default mode to use when creating files */ uid_t fileUID; /**< default IDs for creation */ uid_t dirUID; gid_t fileGID; gid_t dirGID; int bDynafileDoNotSuspend; int bFollowSymlinks; sbool bFollowSymlinksExplicit; sbool bPermitDynaFilePathEscape; sbool bRestrictDynaFileTplType; strm_compressionDriver_t compressionDriver; int compressionDriver_workers; sbool bAddLF; /**< default setting for addLF action parameter */ }; static modConfData_t *loadModConf = NULL; /**< modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /**< modConf ptr to use for the current exec process */ /* tables for interfacing with the v6 config system */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"template", eCmdHdlrGetWord, 0}, {"addlf", eCmdHdlrBinary, 0}, {"compression.driver", eCmdHdlrGetWord, 0}, {"compression.zstd.workers", eCmdHdlrPositiveInt, 0}, {"dircreatemode", eCmdHdlrFileCreateMode, 0}, {"filecreatemode", eCmdHdlrFileCreateMode, 0}, {"dirowner", eCmdHdlrUID, 0}, {"dirownernum", eCmdHdlrInt, 0}, {"dirgroup", eCmdHdlrGID, 0}, {"dirgroupnum", eCmdHdlrInt, 0}, {"fileowner", eCmdHdlrUID, 0}, {"fileownernum", eCmdHdlrInt, 0}, {"filegroup", eCmdHdlrGID, 0}, {"dynafile.donotsuspend", eCmdHdlrBinary, 0}, {"followsymlinks", eCmdHdlrBinary, 0}, {"dynafile.dangerouspermitpathescape", eCmdHdlrBinary, 0}, {"dynafile.restricttemplatetype", eCmdHdlrBinary, 0}, {"filegroupnum", eCmdHdlrInt, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = {{"dynafilecachesize", eCmdHdlrInt, 0}, /* legacy: dynafilecachesize */ {"ziplevel", eCmdHdlrInt, 0}, /* legacy: omfileziplevel */ {"flushinterval", eCmdHdlrInt, 0}, /* legacy: omfileflushinterval */ {"asyncwriting", eCmdHdlrBinary, 0}, /* legacy: omfileasyncwriting */ {"veryrobustzip", eCmdHdlrBinary, 0}, {"flushontxend", eCmdHdlrBinary, 0}, /* legacy: omfileflushontxend */ {"iobuffersize", eCmdHdlrSize, 0}, /* legacy: omfileiobuffersize */ {"dirowner", eCmdHdlrUID, 0}, /* legacy: dirowner */ {"dirownernum", eCmdHdlrInt, 0}, /* legacy: dirownernum */ {"dirgroup", eCmdHdlrGID, 0}, /* legacy: dirgroup */ {"dirgroupnum", eCmdHdlrInt, 0}, /* legacy: dirgroupnum */ {"fileowner", eCmdHdlrUID, 0}, /* legacy: fileowner */ {"fileownernum", eCmdHdlrInt, 0}, /* legacy: fileownernum */ {"filegroup", eCmdHdlrGID, 0}, /* legacy: filegroup */ {"filegroupnum", eCmdHdlrInt, 0}, /* legacy: filegroupnum */ {"dircreatemode", eCmdHdlrFileCreateMode, 0}, /* legacy: dircreatemode */ {"filecreatemode", eCmdHdlrFileCreateMode, 0}, /* legacy: filecreatemode */ {"failonchownfailure", eCmdHdlrBinary, 0}, /* legacy: failonchownfailure */ {"createdirs", eCmdHdlrBinary, 0}, /* legacy: createdirs */ {"sync", eCmdHdlrBinary, 0}, /* legacy: actionfileenablesync */ {"file", eCmdHdlrString, 0}, /* either "file" or ... */ {"dynafile", eCmdHdlrString, 0}, /* "dynafile" MUST be present */ {"followsymlinks", eCmdHdlrBinary, 0}, {"sig.provider", eCmdHdlrGetWord, 0}, {"cry.provider", eCmdHdlrGetWord, 0}, {"closetimeout", eCmdHdlrPositiveInt, 0}, {"rotation.sizelimit", eCmdHdlrSize, 0}, {"rotation.sizelimitcommand", eCmdHdlrString, 0}, {"rotation.sizelimitcommandpassfilename", eCmdHdlrBinary, 0}, {"template", eCmdHdlrGetWord, 0}, {"dynafile.dangerouspermitpathescape", eCmdHdlrBinary, 0}, {"addlf", eCmdHdlrBinary, 0}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; /** * @brief Gets the default template name to be used. * * This function coordinates the default template name between old-style * and new-style configuration parts. * * @return A pointer to the default template name string. */ static uchar *getDfltTpl(void) { if (loadModConf != NULL && loadModConf->tplName != NULL) return loadModConf->tplName; else if (pszFileDfltTplName == NULL) return (uchar *)"RSYSLOG_FileFormat"; else return pszFileDfltTplName; } BEGINinitConfVars /* (re)set config variables to default values */ CODESTARTinitConfVars; pszFileDfltTplName = NULL; /* make sure this can be free'ed! */ iRet = resetConfigVariables(NULL, NULL); /* params are dummies */ ENDinitConfVars BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; if (pData->bDynamicName) { dbgprintf("[dynamic]\n"); } else { /* regular file */ dbgprintf("%s%s\n", pData->fname, (pData->pStrm == NULL) ? " (closed)" : ""); } dbgprintf("\ttemplate='%s'\n", pData->fname); dbgprintf("\tuse async writer=%d\n", pData->bUseAsyncWriter); dbgprintf("\tflush on TX end=%d\n", pData->bFlushOnTXEnd); dbgprintf("\tflush interval=%d\n", pData->iFlushInterval); dbgprintf("\tappend LF=%d\n", pData->bAddLF); dbgprintf("\tfile cache size=%d\n", pData->iDynaFileCacheSize); dbgprintf("\tcreate directories: %s\n", pData->bCreateDirs ? "on" : "off"); dbgprintf("\tvery robust zip: %s\n", pData->bCreateDirs ? "on" : "off"); dbgprintf("\tfile owner %d, group %d\n", (int)pData->fileUID, (int)pData->fileGID); dbgprintf("\tdirectory owner %d, group %d\n", (int)pData->dirUID, (int)pData->dirGID); dbgprintf("\tdir create mode 0%3.3o, file create mode 0%3.3o\n", pData->fDirCreateMode, pData->fCreateMode); dbgprintf("\tfail if owner/group can not be set: %s\n", pData->bFailOnChown ? "yes" : "no"); ENDdbgPrintInstInfo /** * @brief Sets the default template to be used for output files (legacy method). * * This is a module-global parameter and needs special handling to coordinate * with values set via the v2 config system (rsyslog v6+). This directive is * not permitted after the v2 config system has been used to set the parameter. * * @param pVal Unused pointer, kept for compatibility with command handler signature. * @param newVal The new default template name. Ownership is transferred to this function. * @return RS_RET_OK on success, RS_RET_ERR if already set by new config system. */ static rsRetVal setLegacyDfltTpl(void __attribute__((unused)) * pVal, uchar *newVal) { DEFiRet; if (loadModConf != NULL && loadModConf->tplName != NULL) { free(newVal); parser_errmsg( "omfile: default template already set via module " "global parameter - can no longer be changed"); ABORT_FINALIZE(RS_RET_ERR); } free(pszFileDfltTplName); pszFileDfltTplName = newVal; finalize_it: RETiRet; } /** * @brief Sets the dynamic file cache size. * * Performs limit checking to ensure the new value is valid and logs warnings * for unusually large values. * * @param pVal Unused pointer, kept for compatibility with command handler signature. * @param iNewVal The new size for the dynamic file cache. * @return RS_RET_OK on success, RS_RET_VAL_OUT_OF_RANGE if the value was invalid * (the value will be adjusted to a valid range in this case). */ static rsRetVal setDynaFileCacheSize(void __attribute__((unused)) * pVal, int iNewVal) { DEFiRet; iRet = normalizeDynaFileCacheSize(&iNewVal); cs.iDynaFileCacheSize = iNewVal; DBGPRINTF("DynaFileCacheSize changed to %d.\n", iNewVal); RETiRet; } static rsRetVal normalizeDynaFileCacheSize(int *const pNewVal) { DEFiRet; assert(pNewVal != NULL); if (*pNewVal < 1) { errno = 0; parser_errmsg("DynaFileCacheSize must be greater 0 (%d given), changed to 1.", *pNewVal); iRet = RS_RET_VAL_OUT_OF_RANGE; *pNewVal = 1; } else if (*pNewVal > 25000) { errno = 0; parser_warnmsg( "DynaFileCacheSize is larger than 25,000 (%d given) - this looks very " "large. Is it intended?", *pNewVal); } RETiRet; } /** * @brief Parses an output channel name and associates it with the action. * * This is a helper function to `cfline()`. It parses an output channel name * from the configuration line, looks up the channel, and extracts its * associated file template and size limit settings, storing them in the * provided `instanceData` structure. * * @param pData Pointer to the instance data structure to populate. * @param p Pointer to the current position in the configuration line. * @param pOMSR Pointer to the OMOD String Request structure. * @param iEntry Index for the OMOD String Request. * @param iTplOpts Template options. * @return RS_RET_OK on success, or an error code if the output channel * is not found or has no valid file name template. */ static rsRetVal cflineParseOutchannel( instanceData *pData, uchar *p, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts) { DEFiRet; size_t i; struct outchannel *pOch; char szBuf[128]; /* should be more than sufficient */ ++p; /* skip '$' */ i = 0; /* get outchannel name */ while (*p && *p != ';' && *p != ' ' && i < (sizeof(szBuf) - 1)) { szBuf[i++] = *p++; } szBuf[i] = '\0'; /* got the name, now look up the channel... */ pOch = ochFind(szBuf, i); if (pOch == NULL) { parser_errmsg("outchannel '%s' not found - ignoring action line", szBuf); ABORT_FINALIZE(RS_RET_NOT_FOUND); } /* check if there is a file name in the outchannel... */ if (pOch->pszFileTemplate == NULL) { parser_errmsg("outchannel '%s' has no file name template - ignoring action line", szBuf); ABORT_FINALIZE(RS_RET_ERR); } /* OK, we finally got a correct template. So let's use it... */ pData->fname = ustrdup(pOch->pszFileTemplate); pData->iSizeLimit = pOch->uSizeLimit; if (pOch->cmdOnSizeLimit != NULL) pData->pszSizeLimitCmd = ustrdup(pOch->cmdOnSizeLimit); /* legacy outchannel: preserve historic behavior (no filename argument) */ pData->bSizeLimitCmdPassFileName = 0; iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, getDfltTpl()); finalize_it: RETiRet; } /** * @brief Deletes an entry from the dynamic file name cache. * * This function closes the associated file stream, frees memory for the * file name, and optionally frees the cache entry structure itself. * * @param pData Pointer to the instance data containing the dynamic file cache. * @param iEntry The index of the entry to be deleted in the cache array. * @param bFreeEntry If 1, the cache entry structure itself is free()ed; * if 0, only its contents are freed (e.g., if it's being * reused for a new entry). * @return RS_RET_OK on success. */ static rsRetVal dynaFileDelCacheEntry(instanceData *__restrict__ const pData, const int iEntry, const int bFreeEntry) { dynaFileCacheEntry **pCache = pData->dynCache; DEFiRet; assert(pCache != NULL); if (pCache[iEntry] == NULL) FINALIZE; DBGPRINTF("Removing entry %d for file '%s' from dynaCache.\n", iEntry, pCache[iEntry]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[iEntry]->pName); if (pCache[iEntry]->pName != NULL) { free(pCache[iEntry]->pName); pCache[iEntry]->pName = NULL; } if (pCache[iEntry]->pStrm != NULL) { if (iEntry == pData->iCurrElt) { pData->iCurrElt = -1; pData->pStrm = NULL; } strm.Destruct(&pCache[iEntry]->pStrm); if (pData->useSigprov) { pData->sigprov.OnFileClose(pCache[iEntry]->sigprovFileData); pCache[iEntry]->sigprovFileData = NULL; } } if (bFreeEntry) { free(pCache[iEntry]); pCache[iEntry] = NULL; } finalize_it: RETiRet; } /** * @brief Frees all dynamic file name cache entries and closes relevant files. * * This function is typically called during module shutdown or HUP processing * to release all resources held by the dynamic file cache. * * @param pData Pointer to the instance data containing the dynamic file cache. */ static void dynaFileFreeCacheEntries(instanceData *__restrict__ const pData) { register int i; assert(pData != NULL); for (i = 0; i < pData->iCurrCacheSize; ++i) { dynaFileDelCacheEntry(pData, i, 1); } /* invalidate current element */ pData->iCurrElt = -1; pData->pStrm = NULL; } /** * @brief Frees the dynamic file name cache structure. * * This function first frees all entries within the cache and then * deallocates the cache array itself. * * @param pData Pointer to the instance data containing the dynamic file cache. */ static void dynaFileFreeCache(instanceData *__restrict__ const pData) { assert(pData != NULL); dynaFileFreeCacheEntries(pData); if (pData->dynCache != NULL) free(pData->dynCache); } /** * @brief Closes the currently open file stream for a given instance. * * If a signature provider is in use, its `OnFileClose` method is also called. * * @param pData Pointer to the instance data whose file stream is to be closed. * @return RS_RET_OK on success. */ static rsRetVal closeFile(instanceData *__restrict__ const pData) { DEFiRet; if (pData->useSigprov) { pData->sigprov.OnFileClose(pData->sigprovFileData); pData->sigprovFileData = NULL; } strm.Destruct(&pData->pStrm); RETiRet; } /** * @brief Prepares the signature provider for processing a file. * * This function calls the `OnFileOpen` method of the configured signature * provider, passing the file name and obtaining an opaque data pointer for * file-specific signature operations. * * @param pData Pointer to the instance data containing the signature provider. * @param fn The name of the file to be processed. * @return RS_RET_OK on success. */ static rsRetVal sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn) { DEFiRet; pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData); RETiRet; } static int getCompatDefaultFollowSymlinks(const rsconf_t *const cnf) { return cnf == NULL || cnf->globals.compatDefaultsSecure != COMPAT_DEFAULTS_SECURE_STRICT; } static void warnIfFollowingSymlink(const instanceData *__restrict__ const pData, const uchar *__restrict__ const fileName) { struct stat st; if (!pData->bFollowSymlinks || pData->bFollowSymlinksExplicit || runModConf == NULL || runModConf->pConf == NULL || runModConf->pConf->globals.compatDefaultsSecure != COMPAT_DEFAULTS_SECURE_WARN) { return; } if (lstat((const char *)fileName, &st) == 0 && S_ISLNK(st.st_mode)) { LogMsg(0, RS_RET_OK, LOG_WARNING, "omfile: following symbolic link output file '%s'; " "set action(type=\"omfile\" followSymlinks=\"off\") or " "global(compatibility.defaults.secure=\"strict\") to reject final-component symlinks", fileName); } } /** * @brief Prepares file access for a given file name. * * This function handles the creation of parent directories (if configured), * creates the file itself (if it doesn't exist), sets its ownership and * permissions, and then constructs and finalizes the rsyslog stream object * for writing to the file. It also initializes signature and crypto providers * if enabled. * * @param pData Pointer to the instance data for the file output action. * @param newFileName The name of the file to prepare access for. * @return RS_RET_OK on success, or an error code if file creation, * directory creation, or stream construction fails. */ static rsRetVal prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName, const int bFailOnOpenErr) { int fd; char errStr[1024]; /* buffer for strerr() */ DEFiRet; pData->pStrm = NULL; if (access((char *)newFileName, F_OK) != 0) { /* file does not exist, create it (and eventually parent directories */ if (pData->bCreateDirs) { /* We first need to create parent dirs if they are missing. * We do not report any errors here ourselfs but let the code * fall through to error handler below. */ if (makeFileParentDirs(newFileName, ustrlen(newFileName), pData->fDirCreateMode, pData->dirUID, pData->dirGID, pData->bFailOnChown) != 0) { rs_strerror_r(errno, errStr, sizeof(errStr)); parser_errmsg( "omfile: creating parent " "directories for file '%s' failed: %s", newFileName, errStr); ABORT_FINALIZE(RS_RET_ERR); /* we give up */ } } /* no matter if we needed to create directories or not, we now try to create * the file. -- rgerhards, 2008-12-18 (based on patch from William Tisater) */ int openFlags = O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY | O_CLOEXEC; #ifdef O_NOFOLLOW if (!pData->bFollowSymlinks) { openFlags |= O_NOFOLLOW; } #endif fd = open((char *)newFileName, openFlags, pData->fCreateMode); if (fd != -1) { /* check and set uid/gid */ if (pData->fileUID != (uid_t)-1 || pData->fileGID != (gid_t)-1) { /* we need to set owner/group */ if (fchown(fd, pData->fileUID, pData->fileGID) != 0) { rs_strerror_r(errno, errStr, sizeof(errStr)); parser_errmsg("omfile: chown for file '%s' failed: %s", newFileName, errStr); if (pData->bFailOnChown) { close(fd); ABORT_FINALIZE(RS_RET_ERR); /* we give up */ } /* we will silently ignore the chown() failure * if configured to do so. */ } } close(fd); /* close again, as we need a stream further on */ } else if (bFailOnOpenErr) { const int openErrno = errno; rs_strerror_r(openErrno, errStr, sizeof(errStr)); parser_errmsg("omfile: open file '%s' failed: %s", newFileName, errStr); ABORT_FINALIZE((openErrno == ENOENT) ? RS_RET_FILE_NOT_FOUND : RS_RET_FILE_OPEN_ERROR); } } warnIfFollowingSymlink(pData, newFileName); /* the copies below are clumpsy, but there is no way around given the * anomalies in dirname() and basename() [they MODIFY the provided buffer...] */ uchar szNameBuf[MAXFNAME + 1]; uchar szDirName[MAXFNAME + 1]; uchar szBaseName[MAXFNAME + 1]; ustrncpy(szNameBuf, newFileName, MAXFNAME); szNameBuf[MAXFNAME] = '\0'; ustrncpy(szDirName, (uchar *)dirname((char *)szNameBuf), MAXFNAME); szDirName[MAXFNAME] = '\0'; ustrncpy(szNameBuf, newFileName, MAXFNAME); szNameBuf[MAXFNAME] = '\0'; ustrncpy(szBaseName, (uchar *)basename((char *)szNameBuf), MAXFNAME); szBaseName[MAXFNAME] = '\0'; CHKiRet(strm.Construct(&pData->pStrm)); CHKiRet(strm.SetFName(pData->pStrm, szBaseName, ustrlen(szBaseName))); CHKiRet(strm.SetDir(pData->pStrm, szDirName, ustrlen(szDirName))); CHKiRet(strm.SetiZipLevel(pData->pStrm, pData->iZipLevel)); CHKiRet(strm.SetbVeryReliableZip(pData->pStrm, pData->bVeryRobustZip)); CHKiRet(strm.SetsIOBufSize(pData->pStrm, (size_t)pData->iIOBufSize)); CHKiRet(strm.SettOperationsMode(pData->pStrm, STREAMMODE_WRITE_APPEND)); CHKiRet(strm.SettOpenMode(pData->pStrm, cs.fCreateMode)); CHKiRet(strm.SetbNoFollowFinal(pData->pStrm, !pData->bFollowSymlinks)); CHKiRet(strm.SetcompressionDriver(pData->pStrm, runModConf->compressionDriver)); CHKiRet(strm.SetCompressionWorkers(pData->pStrm, runModConf->compressionDriver_workers)); CHKiRet(strm.SetbSync(pData->pStrm, pData->bSyncFile)); CHKiRet(strm.SetsType(pData->pStrm, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetiSizeLimit(pData->pStrm, pData->iSizeLimit)); CHKiRet(strm.SetbSizeLimitCmdPassFileName(pData->pStrm, pData->bSizeLimitCmdPassFileName)); if (pData->useCryprov) { CHKiRet(strm.Setcryprov(pData->pStrm, &pData->cryprov)); CHKiRet(strm.SetcryprovData(pData->pStrm, pData->cryprovData)); } /* set the flush interval only if we actually use it - otherwise it will activate * async processing, which is a real performance waste if we do not do buffered * writes! -- rgerhards, 2009-07-06 */ if (pData->bUseAsyncWriter) CHKiRet(strm.SetiFlushInterval(pData->pStrm, pData->iFlushInterval)); if (pData->pszSizeLimitCmd != NULL) CHKiRet(strm.SetpszSizeLimitCmd(pData->pStrm, ustrdup(pData->pszSizeLimitCmd))); CHKiRet(strm.ConstructFinalize(pData->pStrm)); if (pData->useSigprov) sigprovPrepare(pData, szNameBuf); finalize_it: if (iRet != RS_RET_OK) { if (pData->pStrm != NULL) { closeFile(pData); } } RETiRet; } /** * @brief Handles dynamic file names, ensuring the correct file is open for writing. * * This function checks if the requested dynamic file name is already present * in the cache. If so, it reuses the existing file handle. If not, it attempts * to open the new file, potentially evicting an older entry from the LRU cache * if the cache is full. * * @param pData Pointer to the instance data for the file output action. * @param newFileName The new dynamic file name to prepare. * @return RS_RET_OK on success, or an error code if the file cannot be opened * or memory allocation fails. */ static rsRetVal ATTR_NONNULL() prepareDynFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { uint64 ctOldest; /* "timestamp" of oldest element */ int iOldest; int i; int iFirstFree; int bNewCacheSlot; rsRetVal localRet; dynaFileCacheEntry **pCache; DEFiRet; assert(pData != NULL); assert(newFileName != NULL); if (pData->iDynaFileCacheSize < 1 || pData->dynCache == NULL) { parser_errmsg("omfile: invalid dynafile cache state for '%s' (size %d) - discarding message", (char *)pData->fname, pData->iDynaFileCacheSize); ABORT_FINALIZE(RS_RET_ERR); } pCache = pData->dynCache; /* first check, if we still have the current file */ if ((pData->iCurrElt != -1) && (pCache[pData->iCurrElt] != NULL) && (pCache[pData->iCurrElt]->pName != NULL) && !ustrcmp(newFileName, pCache[pData->iCurrElt]->pName)) { /* great, we are all set */ pCache[pData->iCurrElt]->clkTickAccessed = getClockFileAccess(); STATSCOUNTER_INC(pData->ctrLevel0, pData->mutCtrLevel0); /* LRU needs only a strictly monotonically increasing counter, so such a one could do */ FINALIZE; } /* Cached names were checked before insertion. Validate only paths that * may need a cache lookup or a new file, preserving the level-0 fast path. */ if (!pData->bPermitDynaFilePathEscape) { CHKiRet(validateDynaFilePath(pData, newFileName)); } /* ok, no luck - current file cannot be re-used */ /* if we need to flush (at least) on TXEnd, we need to flush now - because * we do not know if we will otherwise come back to this file to flush it * at end of TX. see https://github.com/rsyslog/rsyslog/issues/2502 */ if (((runModConf->pConf->globals.glblDevOptions & DEV_OPTION_8_1905_HANG_TEST) == 0) && pData->bFlushOnTXEnd && pData->pStrm != NULL) { CHKiRet(strm.Flush(pData->pStrm)); } /* Now let's search the table if we find a matching spot. * While doing so, we also prepare for creation of a new one. */ pData->iCurrElt = -1; /* invalid current element pointer */ iFirstFree = -1; /* not yet found */ bNewCacheSlot = 0; iOldest = 0; /* we assume the first element to be the oldest - that will change as we loop */ ctOldest = getClockFileAccess(); /* there must always be an older one */ for (i = 0; i < pData->iCurrCacheSize; ++i) { if (pCache[i] == NULL || pCache[i]->pName == NULL) { if (iFirstFree == -1) iFirstFree = i; } else { /* got an element, let's see if it matches */ if (!ustrcmp(newFileName, pCache[i]->pName)) { /* we found our element! */ pData->pStrm = pCache[i]->pStrm; if (pData->useSigprov) pData->sigprovFileData = pCache[i]->sigprovFileData; pData->iCurrElt = i; pCache[i]->clkTickAccessed = getClockFileAccess(); /* update "timestamp" for LRU */ FINALIZE; } /* did not find it - so lets keep track of the counters for LRU */ if (pCache[i]->clkTickAccessed < ctOldest) { ctOldest = pCache[i]->clkTickAccessed; iOldest = i; } } } /* we have not found an entry */ STATSCOUNTER_INC(pData->ctrMiss, pData->mutCtrMiss); /* similarly, we need to set the current pStrm to NULL, because otherwise, if prepareFile() fails, * we may end up using an old stream. This bug depends on how exactly prepareFile fails, * but it could be triggered in the common case of a failed open() system call. * rgerhards, 2010-03-22 */ pData->pStrm = NULL, pData->sigprovFileData = NULL; if (iFirstFree == -1 && (pData->iCurrCacheSize < pData->iDynaFileCacheSize)) { /* there is space left, so set it to that index */ iFirstFree = pData->iCurrCacheSize; bNewCacheSlot = 1; } /* Note that the following code sequence does not work with the cache entry itself, * but rather with pData->pStrm, the (sole) stream pointer in the non-dynafile case. * The cache array is only updated after the open was successful. -- rgerhards, 2010-03-21 */ if (iFirstFree == -1) { dynaFileDelCacheEntry(pData, iOldest, 0); STATSCOUNTER_INC(pData->ctrEvict, pData->mutCtrEvict); iFirstFree = iOldest; /* this one *is* now free ;) */ } if (pCache[iFirstFree] == NULL) { /* we need to allocate memory for the cache structure */ CHKmalloc(pCache[iFirstFree] = (dynaFileCacheEntry *)calloc(1, sizeof(dynaFileCacheEntry))); } /* Ok, we finally can open the file */ localRet = prepareFile(pData, newFileName, 1); /* check if we had an error */ if (localRet != RS_RET_OK) { dynaFileDelCacheEntry(pData, iFirstFree, 1); pData->iCurrElt = -1; pData->pStrm = NULL; pData->sigprovFileData = NULL; /* We do no longer care about internal messages. The errmsg rate limiter * will take care of too-frequent error messages. */ parser_errmsg( "Could not open dynamic file '%s' [state %d] - discarding " "message", newFileName, localRet); ABORT_FINALIZE(localRet); } if ((pCache[iFirstFree]->pName = ustrdup(newFileName)) == NULL) { closeFile(pData); /* need to free failed entry! */ dynaFileDelCacheEntry(pData, iFirstFree, 1); pData->iCurrElt = -1; pData->pStrm = NULL; pData->sigprovFileData = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pCache[iFirstFree]->pStrm = pData->pStrm; if (pData->useSigprov) pCache[iFirstFree]->sigprovFileData = pData->sigprovFileData; pCache[iFirstFree]->clkTickAccessed = getClockFileAccess(); pData->iCurrElt = iFirstFree; if (bNewCacheSlot) { pData->iCurrCacheSize++; STATSCOUNTER_SETMAX_NOMUT(pData->ctrMax, (unsigned)pData->iCurrCacheSize); } DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName); finalize_it: if (iRet == RS_RET_OK) pCache[pData->iCurrElt]->nInactive = 0; RETiRet; } /** * @brief Performs the actual buffered write operation to the file stream. * * This function writes the provided buffer to the stream associated with * the instance data. It also calls the signature provider's `OnRecordWrite` * method if a signature provider is in use. * * @param pData Pointer to the instance data containing the stream and provider info. * @param pszBuf Pointer to the buffer containing the data to write. * @param lenBuf The length of the data in the buffer. * @return RS_RET_OK on success, or an error code from the stream write operation. */ static rsRetVal doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf) { DEFiRet; assert(pData != NULL); assert(pszBuf != NULL); const int needsLF = pData->bAddLF && (lenBuf == 0 || pszBuf[lenBuf - 1] != '\n'); uchar addlfBuf[ADDLF_SIGBUF_STACKLEN]; uchar *sigBuf = NULL; uchar *sigWriteBuf = pszBuf; size_t sigLen = 0; rs_size_t sigWriteLen = (rs_size_t)lenBuf; int freeSigBuf = 0; DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, needsLF %d, strt data %.128s\n", pData->pStrm, lenBuf, needsLF, pszBuf); if (pData->pStrm != NULL) { if (lenBuf > 0) { CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); } if (needsLF) { CHKiRet(strm.WriteChar(pData->pStrm, '\n')); } } if (pData->useSigprov) { if (needsLF) { sigLen = (size_t)lenBuf + 1; if (sigLen <= sizeof(addlfBuf)) { sigBuf = addlfBuf; } else { sigBuf = (uchar *)malloc(sigLen); if (sigBuf == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } freeSigBuf = 1; } if (lenBuf > 0) { memcpy(sigBuf, pszBuf, (size_t)lenBuf); } sigBuf[lenBuf] = '\n'; sigWriteBuf = sigBuf; sigWriteLen = (rs_size_t)sigLen; } CHKiRet(pData->sigprov.OnRecordWrite(pData->sigprovFileData, sigWriteBuf, sigWriteLen)); } finalize_it: if (freeSigBuf) { free(sigBuf); } RETiRet; } /** * @brief Writes a message to the configured file. * * This function determines whether the output is to a static file or a * dynamic file. If dynamic, it calls `prepareDynFile` to ensure the correct * file is open. It then calls `doWrite` to perform the actual write operation. * * @param pData Pointer to the instance data for the file output action. * @param pParam Pointer to the action worker instance parameters. * @param iMsg The index of the message within the batch to process. * @return RS_RET_OK on success, or an error code if file preparation * or writing fails. */ static rsRetVal writeFile(instanceData *__restrict__ const pData, const actWrkrIParams_t *__restrict__ const pParam, const int iMsg) { DEFiRet; STATSCOUNTER_INC(pData->ctrRequests, pData->mutCtrRequests); /* first check if we have a dynamic file name and, if so, * check if it still is ok or a new file needs to be created */ if (pData->bDynamicName) { DBGPRINTF("omfile: file to log to: %s\n", actParam(pParam, pData->iNumTpls, iMsg, 1).param); iRet = prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param); if (iRet == RS_RET_DISCARDMSG) { /* A blocked message was not written; keep processing this batch so * successfully written records are not retried by the action core. */ iRet = RS_RET_OK; FINALIZE; } CHKiRet(iRet); } else { /* "regular", non-dynafile */ if (pData->pStrm == NULL) { CHKiRet(prepareFile(pData, pData->fname, 0)); if (pData->pStrm == NULL) { parser_errmsg("Could not open output file '%s'", pData->fname); } } pData->nInactive = 0; } iRet = doWrite(pData, actParam(pParam, pData->iNumTpls, iMsg, 0).param, actParam(pParam, pData->iNumTpls, iMsg, 0).lenStr); finalize_it: RETiRet; } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; pModConf->tplName = NULL; pModConf->fCreateMode = 0644; pModConf->fDirCreateMode = 0700; pModConf->fileUID = -1; pModConf->dirUID = -1; pModConf->fileGID = -1; pModConf->dirGID = -1; pModConf->bDynafileDoNotSuspend = 1; pModConf->bPermitDynaFilePathEscape = 0; pModConf->bRestrictDynaFileTplType = 0; pModConf->bAddLF = 1; pModConf->bFollowSymlinks = -1; pModConf->bFollowSymlinksExplicit = 0; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { parser_errmsg( "error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for omfile:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } if (!strcmp(modpblk.descr[i].name, "template")) { CHKmalloc(loadModConf->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (pszFileDfltTplName != NULL) { parser_errmsg( "omfile: warning: default template was already " "set via legacy directive - may lead to inconsistent " "results."); } } else if (!strcmp(modpblk.descr[i].name, "addlf")) { loadModConf->bAddLF = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "compression.driver")) { if (!es_strcasebufcmp(pvals[i].val.d.estr, (const unsigned char *)"zlib", 4)) { loadModConf->compressionDriver = STRM_COMPRESS_ZIP; } else if (!es_strcasebufcmp(pvals[i].val.d.estr, (const unsigned char *)"zstd", 4)) { loadModConf->compressionDriver = STRM_COMPRESS_ZSTD; } else { parser_errmsg( "omfile: error: invalid compression.driver driver " "name - noch applying setting. Valid drivers: 'zlib' and " "'zstd'."); } } else if (!strcmp(modpblk.descr[i].name, "compression.zstd.workers")) { loadModConf->compressionDriver_workers = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dircreatemode")) { loadModConf->fDirCreateMode = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "filecreatemode")) { loadModConf->fCreateMode = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dirowner")) { loadModConf->dirUID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dirownernum")) { loadModConf->dirUID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dirgroup")) { loadModConf->dirGID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dirgroupnum")) { loadModConf->dirGID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "fileowner")) { loadModConf->fileUID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "fileownernum")) { loadModConf->fileUID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "filegroup")) { loadModConf->fileGID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "filegroupnum")) { loadModConf->fileGID = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "dynafile.donotsuspend")) { loadModConf->bDynafileDoNotSuspend = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "followsymlinks")) { loadModConf->bFollowSymlinks = (int)pvals[i].val.d.n; loadModConf->bFollowSymlinksExplicit = 1; } else if (!strcmp(modpblk.descr[i].name, "dynafile.dangerouspermitpathescape")) { loadModConf->bPermitDynaFilePathEscape = pvals[i].val.d.n; if (loadModConf->bPermitDynaFilePathEscape) { warnDynaFilePathEscapeEnabled("module parameter"); } } else if (!strcmp(modpblk.descr[i].name, "dynafile.restricttemplatetype")) { loadModConf->bRestrictDynaFileTplType = pvals[i].val.d.n; } else { dbgprintf( "omfile: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf /** * @brief Checks the dynamic file cache for entries exceeding their close timeout. * * This function iterates through the dynamic file cache and closes/deletes * entries that have been inactive for longer than their configured * `iCloseTimeout`. It is typically called by the janitor. * * @param pData Pointer to the instance data containing the dynamic file cache. */ static void janitorChkDynaFiles(instanceData *__restrict__ const pData) { int i; dynaFileCacheEntry **pCache = pData->dynCache; for (i = 0; i < pData->iCurrCacheSize; ++i) { if (pCache[i] == NULL) continue; DBGPRINTF("omfile janitor: checking dynafile %d:%s, inactive since %d\n", i, pCache[i]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[i]->pName, (int)pCache[i]->nInactive); if (pCache[i]->nInactive >= pData->iCloseTimeout) { STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); dynaFileDelCacheEntry(pData, i, 1); if (pData->iCurrElt == i) pData->iCurrElt = -1; /* no longer available! */ } else { pCache[i]->nInactive += runModConf->pConf->globals.janitorInterval; } } } /** * @brief Callback function for the janitor. * * This function is called periodically by the rsyslog janitor to clean out * inactive files (both static and dynamic) based on their configured * `iCloseTimeout`. It acquires a mutex to protect access to the file data. * * @param pUsr A pointer to the `instanceData` structure for the file action. */ static void janitorCB(void *pUsr) { instanceData *__restrict__ const pData = (instanceData *)pUsr; pthread_mutex_lock(&pData->mutWrite); if (pData->bDynamicName) { janitorChkDynaFiles(pData); } else { if (pData->pStrm != NULL) { DBGPRINTF("omfile janitor: checking file %s, inactive since %d\n", pData->fname, pData->nInactive); if (pData->nInactive >= pData->iCloseTimeout) { STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); closeFile(pData); } else { pData->nInactive += runModConf->pConf->globals.janitorInterval; } } } pthread_mutex_unlock(&pData->mutWrite); } BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; /* done loading */ /* free legacy config vars */ free(pszFileDfltTplName); pszFileDfltTplName = NULL; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(pModConf->tplName); ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; pData->pStrm = NULL; pData->bAddLF = 1; pthread_mutex_init(&pData->mutWrite, NULL); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINfreeInstance CODESTARTfreeInstance; free(pData->tplName); free(pData->fname); free(pData->dynaFileBasePath); free(pData->pszSizeLimitCmd); if (pData->iCloseTimeout > 0) janitorDelEtry(pData->janitorID); if (pData->bDynamicName) { dynaFileFreeCache(pData); } else if (pData->pStrm != NULL) closeFile(pData); if (pData->stats != NULL) statsobj.Destruct(&(pData->stats)); if (pData->useSigprov) { pData->sigprov.Destruct(&pData->sigprovData); obj.ReleaseObj(__FILE__, pData->sigprovNameFull + 2, pData->sigprovNameFull, (void *)&pData->sigprov); free(pData->sigprovName); free(pData->sigprovNameFull); } if (pData->useCryprov) { pData->cryprov.Destruct(&pData->cryprovData); obj.ReleaseObj(__FILE__, pData->cryprovNameFull + 2, pData->cryprovNameFull, (void *)&pData->cryprov); free(pData->cryprovName); free(pData->cryprovNameFull); } pthread_mutex_destroy(&pData->mutWrite); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINsetActionInfo CODESTARTsetActionInfo; if (pData->bDynamicName && pAction->iNumTpls > 1) { iRet = checkDynaFileTemplateType(pData, pAction->ppTpl[1]); if (iRet != RS_RET_OK) { RETiRet; } iRet = deriveDynaFileBasePath(pData, pAction->ppTpl[1]); } ENDsetActionInfo BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINbeginTransaction CODESTARTbeginTransaction; /* we have nothing to do to begin a transaction */ ENDbeginTransaction BEGINcommitTransaction instanceData *__restrict__ const pData = pWrkrData->pData; rsRetVal localRet; unsigned i; CODESTARTcommitTransaction; if (pData->isDevNull) { goto terminate; } pthread_mutex_lock(&pData->mutWrite); for (i = 0; i < nParams; ++i) { localRet = writeFile(pData, pParams, i); if (localRet != RS_RET_OK && iRet == RS_RET_OK) { iRet = localRet; } } /* Note: pStrm may be NULL if there was an error opening the stream */ /* if bFlushOnTXEnd is set, we need to flush on transaction end - in * any case. It is not relevant if this is using background writes * (which then become pretty slow) or not. And, similarly, no flush * happens when it is not set. Please see * https://github.com/rsyslog/rsyslog/issues/1297 * for a discussion of why we actually need this. * rgerhards, 2017-01-13 */ if (pData->bFlushOnTXEnd && pData->pStrm != NULL) { localRet = strm.Flush(pData->pStrm); if (localRet != RS_RET_OK && iRet == RS_RET_OK) { CHKiRet(localRet); } } finalize_it: pthread_mutex_unlock(&pData->mutWrite); if (iRet == RS_RET_FILE_OPEN_ERROR || iRet == RS_RET_FILE_NOT_FOUND) { iRet = (pData->bDynamicName && runModConf->bDynafileDoNotSuspend) ? RS_RET_OK : RS_RET_SUSPENDED; } terminate: ENDcommitTransaction /** * @brief Sets default parameter values for a new omfile action instance. * * This function initializes various fields of the `instanceData` structure * with their default values, some of which are derived from module-global * configuration settings. * * @param pData Pointer to the `instanceData` structure to be initialized. */ static void setInstParamDefaults(instanceData *__restrict__ const pData) { pData->fname = NULL; pData->tplName = NULL; pData->dynaFileBasePath = NULL; pData->bPermitDynaFilePathEscape = loadModConf->bPermitDynaFilePathEscape; pData->bRestrictDynaFileTplType = loadModConf->bRestrictDynaFileTplType; pData->fileUID = loadModConf->fileUID; pData->fileGID = loadModConf->fileGID; pData->dirUID = loadModConf->dirUID; pData->dirGID = loadModConf->dirGID; pData->bFailOnChown = 1; pData->iDynaFileCacheSize = 10; pData->fCreateMode = loadModConf->fCreateMode; pData->fDirCreateMode = loadModConf->fDirCreateMode; pData->bCreateDirs = 1; pData->bSyncFile = 0; pData->iZipLevel = 0; pData->bVeryRobustZip = 0; pData->bFlushOnTXEnd = FLUSHONTX_DFLT; pData->iIOBufSize = IOBUF_DFLT_SIZE; pData->iFlushInterval = FLUSH_INTRVL_DFLT; pData->bUseAsyncWriter = USE_ASYNCWRITER_DFLT; pData->bAddLF = loadModConf->bAddLF; pData->bFollowSymlinks = loadModConf->bFollowSymlinks; pData->bFollowSymlinksExplicit = loadModConf->bFollowSymlinksExplicit; if (pData->bFollowSymlinks == -1) { pData->bFollowSymlinks = getCompatDefaultFollowSymlinks(loadConf); } pData->sigprovName = NULL; pData->cryprovName = NULL; pData->useSigprov = 0; pData->useCryprov = 0; pData->iCloseTimeout = -1; pData->iSizeLimit = 0; pData->isDevNull = 0; pData->pszSizeLimitCmd = NULL; pData->bSizeLimitCmdPassFileName = 1; } /** * @brief Sets up statistics counters for a new omfile instance. * * This function initializes and registers statistics counters for dynamic * file actions, including requests, cache hits/misses, evictions, and * close timeouts. * * @param pData Pointer to the `instanceData` structure for which to set up stats. * @return RS_RET_OK on success, or an error code if statsobj construction fails. */ static rsRetVal setupInstStatsCtrs(instanceData *__restrict__ const pData) { uchar ctrName[512]; DEFiRet; if (!pData->bDynamicName) { FINALIZE; } /* support statistics gathering */ snprintf((char *)ctrName, sizeof(ctrName), "dynafile cache %s", pData->fname); ctrName[sizeof(ctrName) - 1] = '\0'; /* be on the save side */ CHKiRet(statsobj.Construct(&(pData->stats))); CHKiRet(statsobj.SetName(pData->stats, ctrName)); CHKiRet(statsobj.SetOrigin(pData->stats, (uchar *)"omfile")); STATSCOUNTER_INIT(pData->ctrRequests, pData->mutCtrRequests); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("requests"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrRequests))); STATSCOUNTER_INIT(pData->ctrLevel0, pData->mutCtrLevel0); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("level0"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrLevel0))); STATSCOUNTER_INIT(pData->ctrMiss, pData->mutCtrMiss); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("missed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMiss))); STATSCOUNTER_INIT(pData->ctrEvict, pData->mutCtrEvict); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("evicted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrEvict))); STATSCOUNTER_INIT(pData->ctrMax, pData->mutCtrMax); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("maxused"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMax))); STATSCOUNTER_INIT(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("closetimeouts"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrCloseTimeouts))); CHKiRet(statsobj.ConstructFinalize(pData->stats)); finalize_it: RETiRet; } /** * @brief Initializes the signature provider for an omfile instance. * * This function loads the specified signature provider module, constructs * its data instance, and sets its configuration parameters. If any step * fails, signatures are disabled for this instance. * * @param pData Pointer to the `instanceData` structure. * @param lst List of configuration parameters for the signature provider. */ static void initSigprov(instanceData *__restrict__ const pData, struct nvlst *lst) { uchar szDrvrName[1024]; if (snprintf((char *)szDrvrName, sizeof(szDrvrName), "lmsig_%s", pData->sigprovName) == sizeof(szDrvrName)) { parser_errmsg( "omfile: signature provider " "name is too long: '%s' - signatures disabled", pData->sigprovName); goto done; } pData->sigprovNameFull = ustrdup(szDrvrName); pData->sigprov.ifVersion = sigprovCURR_IF_VERSION; /* The pDrvrName+2 below is a hack to obtain the object name. It * safes us to have yet another variable with the name without "lm" in * front of it. If we change the module load interface, we may re-think * about this hack, but for the time being it is efficient and clean enough. */ if (obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void *)&pData->sigprov) != RS_RET_OK) { parser_errmsg( "omfile: could not load " "signature provider '%s' - signatures disabled", szDrvrName); goto done; } if (pData->sigprov.Construct(&pData->sigprovData) != RS_RET_OK) { parser_errmsg( "omfile: error constructing " "signature provider %s dataset - signatures disabled", szDrvrName); goto done; } pData->sigprov.SetCnfParam(pData->sigprovData, lst); dbgprintf("loaded signature provider %s, data instance at %p\n", szDrvrName, pData->sigprovData); pData->useSigprov = 1; done: return; } /** * @brief Initializes the crypto provider for an omfile instance. * * This function loads the specified crypto provider module, constructs * its data instance, and sets its configuration parameters. If any step * fails, encryption is disabled for this instance. * * @param pData Pointer to the `instanceData` structure. * @param lst List of configuration parameters for the crypto provider. * @return RS_RET_OK on success, or an error code if loading or construction fails. */ static rsRetVal initCryprov(instanceData *__restrict__ const pData, struct nvlst *lst) { uchar szDrvrName[1024]; DEFiRet; if (snprintf((char *)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pData->cryprovName) == sizeof(szDrvrName)) { parser_errmsg( "omfile: crypto provider " "name is too long: '%s' - encryption disabled", pData->cryprovName); ABORT_FINALIZE(RS_RET_ERR); } pData->cryprovNameFull = ustrdup(szDrvrName); pData->cryprov.ifVersion = cryprovCURR_IF_VERSION; /* The pDrvrName+2 below is a hack to obtain the object name. It * safes us to have yet another variable with the name without "lm" in * front of it. If we change the module load interface, we may re-think * about this hack, but for the time being it is efficient and clean enough. */ if (obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void *)&pData->cryprov) != RS_RET_OK) { parser_errmsg( "omfile: could not load " "crypto provider '%s' - encryption disabled", szDrvrName); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } if (pData->cryprov.Construct(&pData->cryprovData) != RS_RET_OK) { parser_errmsg( "omfile: error constructing " "crypto provider %s dataset - encryption disabled", szDrvrName); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst, CRYPROV_PARAMTYPE_REGULAR)); dbgprintf("loaded crypto provider %s, data instance at %p\n", szDrvrName, pData->cryprovData); pData->useCryprov = 1; finalize_it: RETiRet; } BEGINnewActInst struct cnfparamvals *pvals; uchar *tplToUse; int i; CODESTARTnewActInst; DBGPRINTF("newActInst (omfile)\n"); pvals = nvlstGetParams(lst, &actpblk, NULL); if (pvals == NULL) { parser_errmsg( "omfile: either the \"file\" or " "\"dynafile\" parameter must be given"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("action param blk in omfile:\n"); cnfparamsPrint(&actpblk, pvals); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "dynafilecachesize")) { pData->iDynaFileCacheSize = (int)pvals[i].val.d.n; const rsRetVal localRet = normalizeDynaFileCacheSize(&pData->iDynaFileCacheSize); if (localRet != RS_RET_OK && localRet != RS_RET_VAL_OUT_OF_RANGE) { ABORT_FINALIZE(localRet); } } else if (!strcmp(actpblk.descr[i].name, "ziplevel")) { pData->iZipLevel = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "flushinterval")) { pData->iFlushInterval = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "veryrobustzip")) { pData->bVeryRobustZip = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "asyncwriting")) { pData->bUseAsyncWriter = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "flushontxend")) { pData->bFlushOnTXEnd = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "iobuffersize")) { pData->iIOBufSize = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "dirowner")) { pData->dirUID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "dirownernum")) { pData->dirUID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "dirgroup")) { pData->dirGID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "dirgroupnum")) { pData->dirGID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "fileowner")) { pData->fileUID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "fileownernum")) { pData->fileUID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "filegroup")) { pData->fileGID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "filegroupnum")) { pData->fileGID = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "dircreatemode")) { pData->fDirCreateMode = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "filecreatemode")) { pData->fCreateMode = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "failonchownfailure")) { pData->bFailOnChown = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "sync")) { pData->bSyncFile = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "createdirs")) { pData->bCreateDirs = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "addlf")) { pData->bAddLF = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "file")) { CHKmalloc(pData->fname = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); CODE_STD_STRING_REQUESTnewActInst(1); pData->bDynamicName = 0; } else if (!strcmp(actpblk.descr[i].name, "dynafile")) { if (pData->fname != NULL) { parser_errmsg("omfile: both \"file\" and \"dynafile\" set, will use dynafile"); } CHKmalloc(pData->fname = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); CODE_STD_STRING_REQUESTnewActInst(2); pData->bDynamicName = 1; } else if (!strcmp(actpblk.descr[i].name, "followsymlinks")) { pData->bFollowSymlinks = (int)pvals[i].val.d.n; pData->bFollowSymlinksExplicit = 1; } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "dynafile.dangerouspermitpathescape")) { pData->bPermitDynaFilePathEscape = pvals[i].val.d.n; if (pData->bPermitDynaFilePathEscape) { warnDynaFilePathEscapeEnabled("action parameter"); } } else if (!strcmp(actpblk.descr[i].name, "sig.provider")) { CHKmalloc(pData->sigprovName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "cry.provider")) { CHKmalloc(pData->cryprovName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "closetimeout")) { pData->iCloseTimeout = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "rotation.sizelimit")) { pData->iSizeLimit = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "rotation.sizelimitcommand")) { CHKmalloc(pData->pszSizeLimitCmd = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "rotation.sizelimitcommandpassfilename")) { pData->bSizeLimitCmdPassFileName = (int)pvals[i].val.d.n; } else { dbgprintf( "omfile: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } if (pData->fname == NULL || *pData->fname == '\0') { parser_errmsg( "omfile: either the \"file\" or " "\"dynafile\" parameter must be given"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } int allWhiteSpace = 1; for (const char *p = (const char *)pData->fname; *p; ++p) { if (!isspace((unsigned char)*p)) { allWhiteSpace = 0; break; } } if (allWhiteSpace) { parser_errmsg( "omfile: \"file\" or \"dynafile\" parameter " "consist only of whitespace - this is not permitted"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (!strcmp((const char *)pData->fname, "/dev/null")) { pData->isDevNull = 1; } if (pData->sigprovName != NULL) { initSigprov(pData, lst); } if (pData->cryprovName != NULL) { CHKiRet(initCryprov(pData, lst)); } tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName); CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS)); pData->iNumTpls = 1; if (pData->bDynamicName) { /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_TPL_AS_DYNAFILE)); pData->iNumTpls = 2; // TODO: create unified code for this (legacy+v6 system) /* we now allocate the cache table */ CHKmalloc(pData->dynCache = (dynaFileCacheEntry **)calloc(pData->iDynaFileCacheSize, sizeof(dynaFileCacheEntry *))); pData->iCurrElt = -1; /* no current element */ } // TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ setupInstStatsCtrs(pData); if (pData->iCloseTimeout == -1) { /* unset? */ pData->iCloseTimeout = (pData->bDynamicName) ? 10 : 0; } snprintf(pData->janitorID, sizeof(pData->janitorID), "omfile:%sfile:%s:%p", (pData->bDynamicName) ? "dyna" : "", pData->fname, pData); pData->janitorID[sizeof(pData->janitorID) - 1] = '\0'; /* just in case... */ if (pData->iCloseTimeout > 0) janitorAddEtry(janitorCB, pData->janitorID, pData); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINparseSelectorAct uchar fname[MAXFNAME]; CODESTARTparseSelectorAct; /* Note: the indicator sequence permits us to use '$' to signify * outchannel, what otherwise is not possible due to truely * unresolvable grammar conflicts (*this time no way around*). * rgerhards, 2011-07-09 */ if (!strncmp((char *)p, ":omfile:", sizeof(":omfile:") - 1)) { p += sizeof(":omfile:") - 1; } if (!(*p == '$' || *p == '?' || *p == '/' || *p == '.' || *p == '-')) ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); CHKiRet(createInstance(&pData)); /* Legacy selector actions bypass newActInst(), so copy the dynafile * module defaults explicitly when a v6 module block was provided. */ pData->dynaFileBasePath = NULL; pData->bPermitDynaFilePathEscape = 0; pData->bRestrictDynaFileTplType = 0; if (loadModConf != NULL) { pData->bPermitDynaFilePathEscape = loadModConf->bPermitDynaFilePathEscape; pData->bRestrictDynaFileTplType = loadModConf->bRestrictDynaFileTplType; } if (*p == '-') { pData->bSyncFile = 0; p++; } else { pData->bSyncFile = cs.bEnableSync; } pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ switch (*p) { case '$': CODE_STD_STRING_REQUESTparseSelectorAct(1) pData->iNumTpls = 1; /* rgerhards 2005-06-21: this is a special setting for output-channel * definitions. In the long term, this setting will probably replace * anything else, but for the time being we must co-exist with the * traditional mode lines. * rgerhards, 2007-07-24: output-channels will go away. We keep them * for compatibility reasons, but seems to have been a bad idea. */ CHKiRet(cflineParseOutchannel(pData, p, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS)); pData->bDynamicName = 0; break; case '?': /* This is much like a regular file handle, but we need to obtain * a template name. rgerhards, 2007-07-03 */ CODE_STD_STRING_REQUESTparseSelectorAct(2) pData->iNumTpls = 2; ++p; /* eat '?' */ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); pData->fname = ustrdup(fname); pData->bDynamicName = 1; pData->iCurrElt = -1; /* no current element */ /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */ CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_TPL_AS_DYNAFILE)); /* we now allocate the cache table */ CHKmalloc(pData->dynCache = (dynaFileCacheEntry **)calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry *))); break; case '/': case '.': CODE_STD_STRING_REQUESTparseSelectorAct(1) pData->iNumTpls = 1; CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); pData->fname = ustrdup(fname); pData->bDynamicName = 0; break; default: ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); } /* freeze current paremeters for this action */ pData->iDynaFileCacheSize = cs.iDynaFileCacheSize; pData->fCreateMode = cs.fCreateMode; pData->fDirCreateMode = cs.fDirCreateMode; pData->bCreateDirs = cs.bCreateDirs; pData->bFailOnChown = cs.bFailOnChown; pData->fileUID = cs.fileUID; pData->fileGID = cs.fileGID; pData->dirUID = cs.dirUID; pData->dirGID = cs.dirGID; pData->iZipLevel = cs.iZipLevel; pData->bFlushOnTXEnd = cs.bFlushOnTXEnd; pData->iIOBufSize = (int)cs.iIOBufSize; pData->iFlushInterval = cs.iFlushInterval; pData->bUseAsyncWriter = cs.bUseAsyncWriter; pData->bVeryRobustZip = 0; /* cannot be specified via legacy conf */ pData->iCloseTimeout = 0; /* cannot be specified via legacy conf */ setupInstStatsCtrs(pData); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct /** * @brief Resets configuration variables for the omfile module to default values. * * This function is used to revert module-global configuration settings * to their initial states, typically during `resetconfigvariables` processing. * * @param pp Unused pointer, kept for compatibility. * @param pVal Unused pointer, kept for compatibility. * @return RS_RET_OK always. */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { cs.fileUID = -1; cs.fileGID = -1; cs.dirUID = -1; cs.dirGID = -1; cs.bFailOnChown = 1; cs.iDynaFileCacheSize = 10; cs.fCreateMode = 0644; cs.fDirCreateMode = 0700; cs.bCreateDirs = 1; cs.bEnableSync = 0; cs.iZipLevel = 0; cs.bFlushOnTXEnd = FLUSHONTX_DFLT; cs.iIOBufSize = IOBUF_DFLT_SIZE; cs.iFlushInterval = FLUSH_INTRVL_DFLT; cs.bUseAsyncWriter = USE_ASYNCWRITER_DFLT; free(pszFileDfltTplName); pszFileDfltTplName = NULL; return RS_RET_OK; } BEGINdoHUP CODESTARTdoHUP; pthread_mutex_lock(&pData->mutWrite); if (pData->bDynamicName) { dynaFileFreeCacheEntries(pData); } else { if (pData->pStrm != NULL) { closeFile(pData); } } pthread_mutex_unlock(&pData->mutWrite); ENDdoHUP BEGINmodExit CODESTARTmodExit; objRelease(strm, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); DESTROY_ATOMIC_HELPER_MUT(mutClock); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMODTX_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_SetActionInfo_IF_OMOD_QUERIES; CODEqueryEtryPt_doHUP ENDqueryEtryPt BEGINmodInitNoPredecl(File) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr INITLegCnfVars; CHKiRet(objUse(strm, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); INIT_ATOMIC_HELPER_MUT(mutClock); INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING); DBGPRINTF("omfile: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not "); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dynafilecachesize", 0, eCmdHdlrInt, setDynaFileCacheSize, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileziplevel", 0, eCmdHdlrInt, NULL, &cs.iZipLevel, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushinterval", 0, eCmdHdlrInt, NULL, &cs.iFlushInterval, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileasyncwriting", 0, eCmdHdlrBinary, NULL, &cs.bUseAsyncWriter, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &cs.bFlushOnTXEnd, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &cs.iIOBufSize, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &cs.dirUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirownernum", 0, eCmdHdlrInt, NULL, &cs.dirUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &cs.dirGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroupnum", 0, eCmdHdlrInt, NULL, &cs.dirGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &cs.fileUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileownernum", 0, eCmdHdlrInt, NULL, &cs.fileUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &cs.fileGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroupnum", 0, eCmdHdlrInt, NULL, &cs.fileGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fDirCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet( omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &cs.bCreateDirs, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"failonchownfailure", 0, eCmdHdlrBinary, NULL, &cs.bFailOnChown, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileforcechown", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfileenablesync", 0, eCmdHdlrBinary, NULL, &cs.bEnableSync, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionfiledefaulttemplate", 0, eCmdHdlrGetWord, setLegacyDfltTpl, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit rsyslog-8.2608.0/tools/PaxHeaders/pmrfc5424.c0000644000000000000000000000013115241075234015473 xustar0030 mtime=1787067036.651579156 30 atime=1787067036.805582039 29 ctime=1787067795.26274123 rsyslog-8.2608.0/tools/pmrfc5424.c0000664000175000017500000002521415241075234015144 0ustar00rgerrger/* pmrfc5424.c * This is a parser module for RFC5424-formatted messages. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2009-11-03 by RGerhards * * Copyright 2007-2015 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "syslogd.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.rfc5424") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* config data */ BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature /* Helper to parseRFCSyslogMsg. This function parses a field up to * (and including) the SP character after it. The field contents is * returned in a caller-provided buffer. The parsepointer is advanced * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not * SP-terminated or any other error occurs. -- rger, 2005-11-24 * The function now receives the size of the string and makes sure * that it does not process more than that. The *pLenStr counter is * updated on exit. -- rgerhards, 2009-09-23 */ static int parseRFCField(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int iRet = 0; assert(pp2parse != NULL); assert(*pp2parse != NULL); assert(pResult != NULL); p2parse = *pp2parse; /* this is the actual parsing loop */ while (*pLenStr > 0 && *p2parse != ' ') { *pResult++ = *p2parse++; --(*pLenStr); } if (*pLenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ --(*pLenStr); } else { iRet = 1; /* there MUST be an SP! */ } *pResult = '\0'; /* set the new parse pointer */ *pp2parse = p2parse; return iRet; } /* Helper to parseRFCSyslogMsg. This function parses the structured * data field of a message. It does NOT parse inside structured data, * just gets the field as whole. Parsing the single entities is left * to other functions. The parsepointer is advanced * to after the terminating SP. The caller must ensure that the * provided buffer is large enough to hold the to be extracted value. * Returns 0 if everything is fine or 1 if either the field is not * SP-terminated or any other error occurs. -- rger, 2005-11-24 * The function now receives the size of the string and makes sure * that it does not process more than that. The *pLenStr counter is * updated on exit. -- rgerhards, 2009-09-23 */ static int parseRFCStructuredData(uchar **pp2parse, uchar *pResult, int *pLenStr) { uchar *p2parse; int bCont = 1; int iRet = 0; int lenStr; assert(pp2parse != NULL); assert(*pp2parse != NULL); assert(pResult != NULL); p2parse = *pp2parse; lenStr = *pLenStr; /* this is the actual parsing loop * Remeber: structured data starts with [ and includes any characters * until the first ] followed by a SP. There may be spaces inside * structured data. There may also be \] inside the structured data, which * do NOT terminate an element. */ if (lenStr == 0 || (*p2parse != '[' && *p2parse != '-')) return 1; /* this is NOT structured data! */ if (*p2parse == '-') { /* empty structured data? */ *pResult++ = '-'; ++p2parse; --lenStr; } else { while (bCont) { if (lenStr < 2) { /* we now need to check if we have only structured data */ if (lenStr > 0 && *p2parse == ']') { *pResult++ = *p2parse; p2parse++; lenStr--; bCont = 0; } else { iRet = 1; /* this is not valid! */ bCont = 0; } } else if (*p2parse == '\\' && *(p2parse + 1) == ']') { /* this is escaped, need to copy both */ *pResult++ = *p2parse++; *pResult++ = *p2parse++; lenStr -= 2; } else if (*p2parse == ']' && *(p2parse + 1) == ' ') { /* found end, just need to copy the ] and eat the SP */ *pResult++ = *p2parse; p2parse += 1; lenStr -= 1; bCont = 0; } else { *pResult++ = *p2parse++; --lenStr; } } } if (lenStr > 0 && *p2parse == ' ') { ++p2parse; /* eat SP, but only if not at end of string */ --lenStr; } else { iRet = 1; /* there MUST be an SP! */ } *pResult = '\0'; /* set the new parse pointer */ *pp2parse = p2parse; *pLenStr = lenStr; return iRet; } /* parse a RFC5424-formatted syslog message. This function returns * 0 if processing of the message shall continue and 1 if something * went wrong and this messe should be ignored. This function has been * implemented in the effort to support syslog-protocol. Please note that * the name (parse *RFC*) stems from the hope that syslog-protocol will * some time become an RFC. Do not confuse this with informational * RFC 3164 (which is legacy syslog). * * currently supported format: * * VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG * * is already stripped when this function is entered. VERSION already * has been confirmed to be "1", but has NOT been stripped from the message. * * rger, 2005-11-24 */ BEGINparse uchar *p2parse; uchar *pBuf = NULL; int lenMsg; int bContParse = 1; CODESTARTparse; assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* check if we are the right parser */ if (lenMsg < 2 || p2parse[0] != '1' || p2parse[1] != ' ') { ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } DBGPRINTF("Message has RFC5424/syslog-protocol format.\n"); setProtocolVersion(pMsg, MSG_RFC5424_PROTOCOL); p2parse += 2; lenMsg -= 2; /* Now get us some memory we can use as a work buffer while parsing. * We simply allocated a buffer sufficiently large to hold all of the * message, so we can not run into any troubles. I think this is * wiser than to use individual buffers. */ CHKmalloc(pBuf = malloc(lenMsg + 1)); /* IMPORTANT NOTE: * Validation is not actually done below nor are any errors handled. I have * NOT included this for the current proof of concept. However, it is strongly * advisable to add it when this code actually goes into production. * rgerhards, 2005-11-24 */ /* TIMESTAMP */ if (lenMsg >= 2 && p2parse[0] == '-' && p2parse[1] == ' ') { memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime)); p2parse += 2; lenMsg -= 2; } else if (datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse, &lenMsg) == RS_RET_OK) { if (pMsg->msgFlags & IGNDATE) { /* we need to ignore the msg data, so simply copy over reception date */ memcpy(&pMsg->tTIMESTAMP, &pMsg->tRcvdAt, sizeof(struct syslogTime)); } } else { DBGPRINTF("no TIMESTAMP detected!\n"); bContParse = 0; } /* HOSTNAME */ if (bContParse) { parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetHOSTNAME(pMsg, pBuf, ustrlen(pBuf)); } /* APP-NAME */ if (bContParse) { parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetAPPNAME(pMsg, (char *)pBuf); } /* PROCID */ if (bContParse) { parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetPROCID(pMsg, (char *)pBuf); } /* MSGID */ if (bContParse) { parseRFCField(&p2parse, pBuf, &lenMsg); MsgSetMSGID(pMsg, (char *)pBuf); } /* STRUCTURED-DATA */ if (bContParse) { parseRFCStructuredData(&p2parse, pBuf, &lenMsg); MsgSetStructuredData(pMsg, (char *)pBuf); } /* MSG */ MsgSetMSGoffs(pMsg, p2parse - pMsg->pszRawMsg); finalize_it: if (pBuf != NULL) free(pBuf); ENDparse #ifdef ENABLE_FUZZING rsRetVal pmrfc5424FuzzInit(void); void pmrfc5424FuzzExit(void); rsRetVal pmrfc5424FuzzParse(smsg_t *pMsg); rsRetVal pmrfc5424FuzzInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); finalize_it: RETiRet; } void pmrfc5424FuzzExit(void) { objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); } rsRetVal pmrfc5424FuzzParse(smsg_t *pMsg) { return parse(pMsg); } #endif BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit(pmrfc5424) CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); dbgprintf("rfc5424 parser init called\n"); dbgprintf("GetParserName addr %p\n", GetParserName); ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/rscryutil.c0000644000000000000000000000013015216464436016114 xustar0028 mtime=1782212894.0952673 30 atime=1782715518.781788721 30 ctime=1787067795.304742013 rsyslog-8.2608.0/tools/rscryutil.c0000664000175000017500000006057515216464436015577 0ustar00rgerrger/* This is a tool for processing rsyslog encrypted log files. * * Copyright 2013-2019 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either exprs or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "libcry_common.h" #ifdef ENABLE_LIBGCRYPT #include #include "libgcry.h" #endif #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER #include #include "libossl.h" #endif #ifdef ENABLE_LIBGCRYPT typedef struct { int cry_algo; int cry_mode; gcry_cipher_hd_t gcry_chd; } gcry_data; #endif #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER typedef struct { const EVP_CIPHER *cipher; EVP_CIPHER_CTX *chd; } ossl_data; #endif /* rscryutil related config parameters and internals */ typedef struct rscry_config { /* General parameters */ enum { MD_DECRYPT, MD_WRITE_KEYFILE } mode; int verbose; size_t blkLength; char *keyfile; char *keyprog; int randomKeyLen; char *key; unsigned keylen; int optionForce; /* Library specific parameters */ enum { LIB_GCRY, LIB_OSSL } lib; union { #ifdef ENABLE_LIBGCRYPT gcry_data gcry; #endif #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER ossl_data ossl; #endif } libData; } rscry_config; rscry_config cnf; static int initConfig(const char *name) { cnf.mode = MD_DECRYPT; cnf.lib = LIB_GCRY; cnf.verbose = 0; cnf.blkLength = 0; cnf.keyfile = NULL; cnf.keyprog = NULL; cnf.randomKeyLen = -1; cnf.key = NULL; cnf.keylen = 0; cnf.optionForce = 0; /* If no library is set, we are using the default value. gcry must be the last so it remains backwards compatible. */ if (name == NULL) { #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER name = "ossl"; #endif #ifdef ENABLE_LIBGCRYPT name = "gcry"; #endif } if (name && strcmp(name, "gcry") == 0) { /* Use the libgcrypt lib */ #ifdef ENABLE_LIBGCRYPT cnf.lib = LIB_GCRY; cnf.libData.gcry.cry_algo = GCRY_CIPHER_AES128; cnf.libData.gcry.cry_mode = GCRY_CIPHER_MODE_CBC; cnf.libData.gcry.gcry_chd = NULL; #else fprintf(stderr, "rsyslog was not compiled with libgcrypt support.\n"); return 1; #endif } else if (name && strcmp(name, "ossl") == 0) { /* Use the openssl lib */ #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER cnf.lib = LIB_OSSL; cnf.libData.ossl.cipher = EVP_aes_128_cbc(); cnf.libData.ossl.chd = NULL; #else fprintf(stderr, "rsyslog was not compiled with libossl support.\n"); return 1; #endif } else { fprintf(stderr, "invalid option for lib: %s\n", name); return 1; } return 0; } /* We use some common code which expects rsyslog runtime to be * present, most importantly for debug output. As a stand-alone * tool, we do not really have this. So we do some dummy defines * in order to satisfy the needs of the common code. */ int Debug = 0; #ifndef DEBUGLESS void r_dbgprintf(const char *srcname __attribute__((unused)), const char *fmt __attribute__((unused)), ...) {}; #endif void srSleep(int a __attribute__((unused)), int b __attribute__((unused))); /* prototype (avoid compiler warning) */ void srSleep(int a __attribute__((unused)), int b __attribute__((unused))) {} /* this is not really needed by any of our code */ long randomNumber(void); /* prototype (avoid compiler warning) */ long randomNumber(void) { return 0l; } /* this is not really needed by any of our code */ /* rectype/value must be EIF_MAX_*_LEN+1 long! * returns 0 on success or something else on error/EOF */ static int eiGetRecord(FILE *eifp, char *rectype, char *value) { int r; unsigned short i, j; char buf[EIF_MAX_RECTYPE_LEN + EIF_MAX_VALUE_LEN + 128]; /* large enough for any valid record */ if (fgets(buf, sizeof(buf), eifp) == NULL) { r = 1; goto done; } for (i = 0; i < EIF_MAX_RECTYPE_LEN && buf[i] != ':'; ++i) if (buf[i] == '\0') { r = 2; goto done; } else rectype[i] = buf[i]; rectype[i] = '\0'; j = 0; for (++i; i < EIF_MAX_VALUE_LEN && buf[i] != '\n'; ++i, ++j) if (buf[i] == '\0') { r = 3; goto done; } else value[j] = buf[i]; value[j] = '\0'; r = 0; done: return r; } static int eiCheckFiletype(FILE *eifp) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; int r; if ((r = eiGetRecord(eifp, rectype, value)) != 0) goto done; if (strcmp(rectype, "FILETYPE") || strcmp(value, RSGCRY_FILETYPE_NAME)) { fprintf(stderr, "invalid filetype \"cookie\" in encryption " "info file\n"); fprintf(stderr, "\trectype: '%s', value: '%s'\n", rectype, value); r = 1; goto done; } r = 0; done: return r; } static int eiGetIV(FILE *eifp, char *iv, size_t leniv) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; size_t valueLen; unsigned short i, j; int r; unsigned char nibble; if ((r = eiGetRecord(eifp, rectype, value)) != 0) goto done; if (strcmp(rectype, "IV")) { fprintf(stderr, "no IV record found when expected, record type " "seen is '%s'\n", rectype); r = 1; goto done; } valueLen = strlen(value); if (valueLen / 2 != leniv) { fprintf(stderr, "length of IV is %lld, expected %lld\n", (long long)valueLen / 2, (long long)leniv); r = 1; goto done; } for (i = j = 0; i < valueLen; ++i) { if (value[i] >= '0' && value[i] <= '9') nibble = value[i] - '0'; else if (value[i] >= 'a' && value[i] <= 'f') nibble = value[i] - 'a' + 10; else { fprintf(stderr, "invalid IV '%s'\n", value); r = 1; goto done; } if (i % 2 == 0) iv[j] = nibble << 4; else iv[j++] |= nibble; } r = 0; done: return r; } static int eiGetEND(FILE *eifp, off64_t *offs) { char rectype[EIF_MAX_RECTYPE_LEN + 1] = ""; char value[EIF_MAX_VALUE_LEN + 1]; int r; if ((r = eiGetRecord(eifp, rectype, value)) != 0) goto done; if (strcmp(rectype, "END")) { fprintf(stderr, "no END record found when expected, record type " "seen is '%s'\n", rectype); r = 1; goto done; } *offs = atoll(value); r = 0; done: return r; } /* LIBGCRYPT RELATED STARTS */ #ifdef ENABLE_LIBGCRYPT static int gcryInit(FILE *eifp) { int r = 0; gcry_error_t gcryError; char iv[4096]; cnf.blkLength = gcry_cipher_get_algo_blklen(cnf.libData.gcry.cry_algo); // EVP_CIPHER_CTX_get_block_size if (cnf.blkLength > sizeof(iv)) { fprintf(stderr, "internal error[%s:%d]: block length %lld too large for " "iv buffer\n", __FILE__, __LINE__, (long long)cnf.blkLength); r = 1; goto done; } if ((r = eiGetIV(eifp, iv, cnf.blkLength)) != 0) goto done; size_t keyLength = gcry_cipher_get_algo_keylen(cnf.libData.gcry.cry_algo); // EVP_CIPHER_get_key_length assert(cnf.key != NULL); /* "fix" clang 10 static analyzer false positive */ if (strlen(cnf.key) != keyLength) { fprintf(stderr, "invalid key length; key is %u characters, but " "exactly %llu characters are required\n", cnf.keylen, (long long unsigned)keyLength); r = 1; goto done; } gcryError = gcry_cipher_open(&cnf.libData.gcry.gcry_chd, cnf.libData.gcry.cry_algo, cnf.libData.gcry.cry_mode, 0); if (gcryError) { fprintf(stderr, "gcry_cipher_open failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); r = 1; goto done; } gcryError = gcry_cipher_setkey(cnf.libData.gcry.gcry_chd, cnf.key, keyLength); if (gcryError) { fprintf(stderr, "gcry_cipher_setkey failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); r = 1; goto done; } gcryError = gcry_cipher_setiv(cnf.libData.gcry.gcry_chd, iv, cnf.blkLength); if (gcryError) { fprintf(stderr, "gcry_cipher_setiv failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); r = 1; goto done; } done: return r; } static void removePadding(char *buf, size_t *plen) { unsigned len = (unsigned)*plen; unsigned iSrc, iDst; char *frstNUL; frstNUL = memchr(buf, 0x00, *plen); if (frstNUL == NULL) goto done; iDst = iSrc = frstNUL - buf; while (iSrc < len) { if (buf[iSrc] != 0x00) buf[iDst++] = buf[iSrc]; ++iSrc; } *plen = iDst; done: return; } static void gcryDecryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs) { gcry_error_t gcryError; size_t nRead, nReadRaw, nWritten; size_t toRead; size_t leftTillBlkEnd; char buf[64 * 1024]; leftTillBlkEnd = blkEnd - *pCurrOffs; while (leftTillBlkEnd > 0) { toRead = sizeof(buf) <= leftTillBlkEnd ? sizeof(buf) : leftTillBlkEnd; toRead = toRead - toRead % cnf.blkLength; if (toRead == 0) break; nRead = fread(buf, 1, toRead, fpin); if (nRead == 0) { if (ferror(fpin)) perror("fpin"); break; } nReadRaw = nRead; leftTillBlkEnd -= nRead, *pCurrOffs += nRead; gcryError = gcry_cipher_decrypt(cnf.libData.gcry.gcry_chd, // gcry_cipher_hd_t buf, // void * nRead, // size_t NULL, // const void * 0); // size_t if (gcryError) { fprintf(stderr, "gcry_cipher_decrypt failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); return; } removePadding(buf, &nRead); nWritten = fwrite(buf, 1, nRead, fpout); if (nWritten != nRead) { perror("fpout"); return; } if (nReadRaw < toRead) break; } } static int gcryDoDecrypt(FILE *logfp, FILE *eifp, FILE *outfp) { off64_t blkEnd; off64_t currOffs = 0; int r = 1; int fd; struct stat buf; while (1) { /* process block */ if (gcryInit(eifp) != 0) goto done; /* set blkEnd to size of logfp and proceed. */ if ((fd = fileno(logfp)) == -1) { r = -1; goto done; } if ((r = fstat(fd, &buf)) != 0) goto done; blkEnd = buf.st_size; r = eiGetEND(eifp, &blkEnd); if (r != 0 && r != 1) goto done; gcryDecryptBlock(logfp, outfp, blkEnd, &currOffs); gcry_cipher_close(cnf.libData.gcry.gcry_chd); } r = 0; done: return r; } #else // Dummy function definitions static int gcryDoDecrypt(FILE __attribute__((unused)) * logfp, FILE __attribute__((unused)) * eifp, FILE __attribute__((unused)) * outfp) { return 0; } static int rsgcryAlgoname2Algo(char *const __attribute__((unused)) algoname) { return 0; } static int rsgcryModename2Mode(char *const __attribute__((unused)) modename) { return 0; } #endif /* LIBGCRYPT RELATED ENDS */ #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER static int osslInit(FILE *eifp) { int r = 0; char iv[4096]; size_t keyLength; if ((cnf.libData.ossl.chd = EVP_CIPHER_CTX_new()) == NULL) { fprintf(stderr, "internal error[%s:%d]: EVP_CIPHER_CTX_new failed\n", __FILE__, __LINE__); r = 1; goto done; } cnf.blkLength = EVP_CIPHER_get_block_size(cnf.libData.ossl.cipher); if (cnf.blkLength > sizeof(iv)) { fprintf(stderr, "internal error[%s:%d]: block length %lld too large for " "iv buffer\n", __FILE__, __LINE__, (long long)cnf.blkLength); r = 1; goto done; } if ((r = eiGetIV(eifp, iv, cnf.blkLength)) != 0) goto done; keyLength = EVP_CIPHER_get_key_length(cnf.libData.ossl.cipher); assert(cnf.key != NULL); /* "fix" clang 10 static analyzer false positive */ if (strlen(cnf.key) != keyLength) { fprintf(stderr, "invalid key length; key is %u characters, but " "exactly %llu characters are required\n", cnf.keylen, (long long unsigned)keyLength); r = 1; goto done; } if ((r = EVP_DecryptInit_ex(cnf.libData.ossl.chd, cnf.libData.ossl.cipher, NULL, (uchar *)cnf.key, (uchar *)iv)) != 1) { fprintf(stderr, "EVP_DecryptInit_ex failed: %d\n", r); goto done; } if ((r = EVP_CIPHER_CTX_set_padding(cnf.libData.ossl.chd, 0)) != 1) { fprintf(stderr, "EVP_CIPHER_set_padding failed: %d\n", r); goto done; } r = 0; done: return r; } static void osslDecryptBlock(FILE *fpin, FILE *fpout, off64_t blkEnd, off64_t *pCurrOffs) { size_t nRead, nWritten; size_t toRead; size_t leftTillBlkEnd; uchar buf[64 * 1024]; uchar outbuf[64 * 1024]; int r, tmplen, outlen; leftTillBlkEnd = blkEnd - *pCurrOffs; while (1) { toRead = sizeof(buf) <= leftTillBlkEnd ? sizeof(buf) : leftTillBlkEnd; toRead = toRead - toRead % cnf.blkLength; nRead = fread(buf, 1, toRead, fpin); if (nRead == 0) break; leftTillBlkEnd -= nRead, *pCurrOffs += nRead; r = EVP_DecryptUpdate(cnf.libData.ossl.chd, outbuf, &tmplen, buf, nRead); if (r != 1) { fprintf(stderr, "EVP_DecryptUpdate failed: %d\n", r); return; } outlen = tmplen; nWritten = fwrite(outbuf, sizeof(unsigned char), (size_t)outlen, fpout); if (nWritten != (size_t)outlen) { perror("fpout"); return; } } r = EVP_DecryptFinal_ex(cnf.libData.ossl.chd, outbuf + tmplen, &tmplen); if (r != 1) { fprintf(stderr, "EVP_DecryptFinal_ex failed: %d\n", r); return; } outlen += tmplen; } static int osslDoDecrypt(FILE *logfp, FILE *eifp, FILE *outfp) { off64_t blkEnd; off64_t currOffs = 0; int r = 1; int fd; struct stat buf; while (1) { /* process block */ if (osslInit(eifp) != 0) goto done; /* set blkEnd to size of logfp and proceed. */ if ((fd = fileno(logfp)) == -1) { r = -1; goto done; } if ((r = fstat(fd, &buf)) != 0) goto done; blkEnd = buf.st_size; r = eiGetEND(eifp, &blkEnd); if (r != 0 && r != 1) goto done; osslDecryptBlock(logfp, outfp, blkEnd, &currOffs); EVP_CIPHER_CTX_free(cnf.libData.ossl.chd); } r = 0; done: return r; } #else // Dummy function definitions static int osslDoDecrypt(FILE __attribute__((unused)) * logfp, FILE __attribute__((unused)) * eifp, FILE __attribute__((unused)) * outfp) { return 0; } #endif static void decrypt(const char *name) { FILE *logfp = NULL, *eifp = NULL; int r = 0; char eifname[4096]; if (!strcmp(name, "-")) { fprintf(stderr, "decrypt mode cannot work on stdin\n"); goto err; } else { if ((logfp = fopen(name, "r")) == NULL) { perror(name); goto err; } snprintf(eifname, sizeof(eifname), "%s%s", name, ENCINFO_SUFFIX); eifname[sizeof(eifname) - 1] = '\0'; if ((eifp = fopen(eifname, "r")) == NULL) { perror(eifname); goto err; } if (eiCheckFiletype(eifp) != 0) goto err; } if (cnf.lib == LIB_GCRY) { if ((r = gcryDoDecrypt(logfp, eifp, stdout)) != 0) goto err; } else if (cnf.lib == LIB_OSSL) { if ((r = osslDoDecrypt(logfp, eifp, stdout)) != 0) goto err; } fclose(logfp); logfp = NULL; fclose(eifp); eifp = NULL; return; err: fprintf(stderr, "error %d processing file %s\n", r, name); if (eifp != NULL) fclose(eifp); if (logfp != NULL) fclose(logfp); } static void write_keyfile(char *fn) { int fd; int r; mode_t fmode; fmode = O_WRONLY | O_CREAT; if (!cnf.optionForce) fmode |= O_EXCL; if (fn == NULL) { fprintf(stderr, "program error: keyfile is NULL"); exit(1); } if ((fd = open(fn, fmode, S_IRUSR)) == -1) { fprintf(stderr, "error opening keyfile "); perror(fn); exit(1); } if ((r = write(fd, cnf.key, cnf.keylen)) != (ssize_t)cnf.keylen) { fprintf(stderr, "error writing keyfile (ret=%d) ", r); perror(fn); exit(1); } close(fd); } static void getKeyFromFile(const char *fn) { const int r = cryGetKeyFromFile(fn, &cnf.key, &cnf.keylen); if (r != 0) { perror(fn); exit(1); } } static void getRandomKey(void) { int fd; cnf.keylen = cnf.randomKeyLen; cnf.key = malloc(cnf.randomKeyLen); /* do NOT zero-out! */ /* if we cannot obtain data from /dev/urandom, we use whatever * is present at the current memory location as random data. Of * course, this is very weak and we should consider a different * option, especially when not running under Linux (for Linux, * unavailability of /dev/urandom is just a theoretic thing, it * will always work...). -- TODO -- rgerhards, 2013-03-06 */ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0) { if (read(fd, cnf.key, cnf.randomKeyLen) != cnf.randomKeyLen) { fprintf(stderr, "warning: could not read sufficient data " "from /dev/urandom - key may be weak\n"); }; close(fd); } } static void setKey(void) { if (cnf.randomKeyLen != -1) getRandomKey(); else if (cnf.keyfile != NULL) getKeyFromFile(cnf.keyfile); else if (cnf.keyprog != NULL) cryGetKeyFromProg(cnf.keyprog, &cnf.key, &cnf.keylen); if (cnf.key == NULL) { fprintf(stderr, "ERROR: key must be set via some method\n"); exit(1); } } /* Retrieve algorithm and mode from the choosen library. In libgcrypt, this is done in two steps (AES128 + CBC). However, other libraries expect this to be expressed in a single step, e.g. AES-128-CBC in openssl */ static void setAlgoMode(char *algo, char *mode) { if (cnf.lib == LIB_GCRY) { /* Set algorithm and mode for gcrypt */ #ifdef ENABLE_LIBGCRYPT if (algo != NULL) { cnf.libData.gcry.cry_algo = rsgcryAlgoname2Algo(algo); if (cnf.libData.gcry.cry_algo == GCRY_CIPHER_NONE) { fprintf(stderr, "ERROR: algorithm \"%s\" is not " "known/supported\n", algo); exit(1); } } if (mode != NULL) { cnf.libData.gcry.cry_mode = rsgcryModename2Mode(mode); if (cnf.libData.gcry.cry_mode == GCRY_CIPHER_MODE_NONE) { fprintf(stderr, "ERROR: cipher mode \"%s\" is not " "known/supported\n", mode); exit(1); } } #endif } else if (cnf.lib == LIB_OSSL) { #ifdef ENABLE_OPENSSL_CRYPTO_PROVIDER if (algo != NULL) { cnf.libData.ossl.cipher = EVP_CIPHER_fetch(NULL, algo, NULL); if (cnf.libData.ossl.cipher == NULL) { fprintf(stderr, "ERROR: cipher \"%s\" is not " "known/supported\n", algo); exit(1); } } #endif } } static struct option long_options[] = {{"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"decrypt", no_argument, NULL, 'd'}, {"force", no_argument, NULL, 'f'}, {"write-keyfile", required_argument, NULL, 'W'}, {"key", required_argument, NULL, 'K'}, {"generate-random-key", required_argument, NULL, 'r'}, {"keyfile", required_argument, NULL, 'k'}, {"key-program", required_argument, NULL, 'p'}, {"algo", required_argument, NULL, 'a'}, {"mode", required_argument, NULL, 'm'}, {"lib", required_argument, NULL, 'l'}, {NULL, 0, NULL, 0}}; static const char *short_options = "a:dfk:K:m:p:r:vVW:l:"; int main(int argc, char *argv[]) { int opt; char *newKeyFile = NULL; char *lib = NULL; char *algo = NULL, *mode = NULL; /* We need preprocessing to determine, which crypto library is going to be used */ while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1 && lib == NULL) { switch (opt) { case 'l': lib = optarg; break; default: break; } } /* Once we reach this point, we have library specific internals set */ if (initConfig(lib)) exit(1); optind = 1; while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) { switch (opt) { case 'd': cnf.mode = MD_DECRYPT; break; case 'W': cnf.mode = MD_WRITE_KEYFILE; newKeyFile = optarg; break; case 'k': cnf.keyfile = optarg; break; case 'p': cnf.keyprog = optarg; break; case 'f': cnf.optionForce = 1; break; case 'r': cnf.randomKeyLen = atoi(optarg); if (cnf.randomKeyLen > 64 * 1024) { fprintf(stderr, "ERROR: keys larger than 64KiB are " "not supported\n"); exit(1); } break; case 'K': fprintf(stderr, "WARNING: specifying the actual key " "via the command line is highly insecure\n" "Do NOT use this for PRODUCTION use.\n"); cnf.key = optarg; cnf.keylen = strlen(cnf.key); break; case 'a': algo = optarg; break; case 'm': mode = optarg; break; case 'v': cnf.verbose = 1; break; case 'V': fprintf(stderr, "rscryutil " VERSION "\n"); exit(0); break; case 'l': break; case '?': break; default: fprintf(stderr, "getopt_long() returns unknown value %d\n", opt); return 1; } } setKey(); setAlgoMode(algo, mode); assert(cnf.key != NULL); if (cnf.mode == MD_WRITE_KEYFILE) { if (optind != argc) { fprintf(stderr, "ERROR: no file parameters permitted in " "--write-keyfile mode\n"); exit(1); } write_keyfile(newKeyFile); } else { if (optind == argc) decrypt("-"); else { for (int i = optind; i < argc; ++i) decrypt(argv[i]); } } assert(cnf.key != NULL); memset(cnf.key, 0, cnf.keylen); /* zero-out key store */ cnf.keylen = 0; return 0; } rsyslog-8.2608.0/tools/PaxHeaders/Makefile.in0000644000000000000000000000013215241076163015751 xustar0030 mtime=1787067507.942384522 30 atime=1787067576.846669687 30 ctime=1787067795.225740541 rsyslog-8.2608.0/tools/Makefile.in0000664000175000017500000035336015241076163015427 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = rsyslogd$(EXEEXT) $(am__EXEEXT_3) @ENABLE_LIBZSTD_TRUE@am__append_1 = $(ZSTD_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_FUZZING_TRUE@noinst_PROGRAMS = fuzz_rsyslog_message$(EXEEXT) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_3 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_DIAGTOOLS_TRUE@am__append_4 = rsyslog_diag_hostname msggen @ENABLE_USERTOOLS_TRUE@bin_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_5 = rsyslog-segqueue.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_6 = rsyslog-segqueue.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_7 = rsyslog-segqueue.1 @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_8 = logctl @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_9 = rscryutil @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_10 = $(LIBGCRYPT_CFLAGS) @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_11 = ../runtime/libgcry.la $(LIBGCRYPT_LIBS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_12 = $(OPENSSL_CFLAGS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_13 = ../runtime/libossl.la $(OPENSSL_LIBS) @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_14 = rscryutil.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_15 = rscryutil.1 @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__append_16 = rscryutil.1 subdir = tools ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__dist_bin_SCRIPTS_DIST) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am__EXEEXT_1 = \ @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@ logctl$(EXEEXT) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__EXEEXT_2 = rscryutil$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" @ENABLE_DIAGTOOLS_TRUE@am__EXEEXT_3 = rsyslog_diag_hostname$(EXEEXT) \ @ENABLE_DIAGTOOLS_TRUE@ msggen$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS) am__fuzz_rsyslog_message_SOURCES_DIST = syslogd.c rsyslogd.c syslogd.h \ omshell.c omshell.h omusrmsg.c omusrmsg.h omfwd.c omfwd.h \ omfile.c omfile.h ompipe.c ompipe.h omdiscard.c omdiscard.h \ pmrfc5424.c pmrfc5424.h pmrfc3164.c pmrfc3164.h smtradfile.c \ smtradfile.h smfile.c smfile.h smfwd.c smfwd.h smtradfwd.c \ smtradfwd.h iminternal.c iminternal.h ../runtime/dirty.h \ fuzz_rsyslog_message.c am__objects_1 = fuzz_rsyslog_message-syslogd.$(OBJEXT) \ fuzz_rsyslog_message-rsyslogd.$(OBJEXT) \ fuzz_rsyslog_message-omshell.$(OBJEXT) \ fuzz_rsyslog_message-omusrmsg.$(OBJEXT) \ fuzz_rsyslog_message-omfwd.$(OBJEXT) \ fuzz_rsyslog_message-omfile.$(OBJEXT) \ fuzz_rsyslog_message-ompipe.$(OBJEXT) \ fuzz_rsyslog_message-omdiscard.$(OBJEXT) \ fuzz_rsyslog_message-pmrfc5424.$(OBJEXT) \ fuzz_rsyslog_message-pmrfc3164.$(OBJEXT) \ fuzz_rsyslog_message-smtradfile.$(OBJEXT) \ fuzz_rsyslog_message-smfile.$(OBJEXT) \ fuzz_rsyslog_message-smfwd.$(OBJEXT) \ fuzz_rsyslog_message-smtradfwd.$(OBJEXT) \ fuzz_rsyslog_message-iminternal.$(OBJEXT) @ENABLE_FUZZING_TRUE@am_fuzz_rsyslog_message_OBJECTS = \ @ENABLE_FUZZING_TRUE@ $(am__objects_1) \ @ENABLE_FUZZING_TRUE@ fuzz_rsyslog_message-fuzz_rsyslog_message.$(OBJEXT) fuzz_rsyslog_message_OBJECTS = $(am_fuzz_rsyslog_message_OBJECTS) am__DEPENDENCIES_1 = @ENABLE_LIBZSTD_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__DEPENDENCIES_3 = \ @ENABLE_LIBLOGGING_STDLOG_TRUE@ $(am__DEPENDENCIES_1) am__DEPENDENCIES_4 = ../grammar/libgrammar.la ../runtime/librsyslog.la \ ../compat/compat.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_3) @ENABLE_FUZZING_TRUE@fuzz_rsyslog_message_DEPENDENCIES = \ @ENABLE_FUZZING_TRUE@ $(am__DEPENDENCIES_4) 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 = fuzz_rsyslog_message_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(fuzz_rsyslog_message_LDFLAGS) \ $(LDFLAGS) -o $@ am__logctl_SOURCES_DIST = logctl.c @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@am_logctl_OBJECTS = logctl-logctl.$(OBJEXT) logctl_OBJECTS = $(am_logctl_OBJECTS) @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_DEPENDENCIES = $(am__DEPENDENCIES_1) am__msggen_SOURCES_DIST = msggen.c @ENABLE_DIAGTOOLS_TRUE@am_msggen_OBJECTS = msggen.$(OBJEXT) msggen_OBJECTS = $(am_msggen_OBJECTS) msggen_LDADD = $(LDADD) rscryutil_SOURCES = rscryutil.c rscryutil_OBJECTS = rscryutil-rscryutil.$(OBJEXT) @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__DEPENDENCIES_5 = ../runtime/libgcry.la \ @ENABLE_LIBGCRYPT_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__DEPENDENCIES_1) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@am__DEPENDENCIES_6 = ../runtime/libossl.la \ @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__DEPENDENCIES_1) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_DEPENDENCIES = $(am__DEPENDENCIES_5) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__DEPENDENCIES_6) rscryutil_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(rscryutil_LDFLAGS) $(LDFLAGS) -o $@ am__rsyslog_diag_hostname_SOURCES_DIST = gethostn.c @ENABLE_DIAGTOOLS_TRUE@am_rsyslog_diag_hostname_OBJECTS = \ @ENABLE_DIAGTOOLS_TRUE@ gethostn.$(OBJEXT) rsyslog_diag_hostname_OBJECTS = $(am_rsyslog_diag_hostname_OBJECTS) rsyslog_diag_hostname_LDADD = $(LDADD) am_rsyslogd_OBJECTS = rsyslogd-syslogd.$(OBJEXT) \ rsyslogd-rsyslogd.$(OBJEXT) rsyslogd-omshell.$(OBJEXT) \ rsyslogd-omusrmsg.$(OBJEXT) rsyslogd-omfwd.$(OBJEXT) \ rsyslogd-omfile.$(OBJEXT) rsyslogd-ompipe.$(OBJEXT) \ rsyslogd-omdiscard.$(OBJEXT) rsyslogd-pmrfc5424.$(OBJEXT) \ rsyslogd-pmrfc3164.$(OBJEXT) rsyslogd-smtradfile.$(OBJEXT) \ rsyslogd-smfile.$(OBJEXT) rsyslogd-smfwd.$(OBJEXT) \ rsyslogd-smtradfwd.$(OBJEXT) rsyslogd-iminternal.$(OBJEXT) rsyslogd_OBJECTS = $(am_rsyslogd_OBJECTS) rsyslogd_DEPENDENCIES = ../grammar/libgrammar.la \ ../runtime/librsyslog.la ../compat/compat.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_3) rsyslogd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(rsyslogd_LDFLAGS) $(LDFLAGS) -o $@ am__dist_bin_SCRIPTS_DIST = rsyslog-segqueue 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; }; \ } SCRIPTS = $(dist_bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-iminternal.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-omfile.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-omfwd.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-ompipe.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-omshell.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-smfile.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-smfwd.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po \ ./$(DEPDIR)/fuzz_rsyslog_message-syslogd.Po \ ./$(DEPDIR)/gethostn.Po ./$(DEPDIR)/logctl-logctl.Po \ ./$(DEPDIR)/msggen.Po ./$(DEPDIR)/rscryutil-rscryutil.Po \ ./$(DEPDIR)/rsyslogd-iminternal.Po \ ./$(DEPDIR)/rsyslogd-omdiscard.Po \ ./$(DEPDIR)/rsyslogd-omfile.Po ./$(DEPDIR)/rsyslogd-omfwd.Po \ ./$(DEPDIR)/rsyslogd-ompipe.Po ./$(DEPDIR)/rsyslogd-omshell.Po \ ./$(DEPDIR)/rsyslogd-omusrmsg.Po \ ./$(DEPDIR)/rsyslogd-pmrfc3164.Po \ ./$(DEPDIR)/rsyslogd-pmrfc5424.Po \ ./$(DEPDIR)/rsyslogd-rsyslogd.Po \ ./$(DEPDIR)/rsyslogd-smfile.Po ./$(DEPDIR)/rsyslogd-smfwd.Po \ ./$(DEPDIR)/rsyslogd-smtradfile.Po \ ./$(DEPDIR)/rsyslogd-smtradfwd.Po \ ./$(DEPDIR)/rsyslogd-syslogd.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(fuzz_rsyslog_message_SOURCES) $(logctl_SOURCES) \ $(msggen_SOURCES) rscryutil.c $(rsyslog_diag_hostname_SOURCES) \ $(rsyslogd_SOURCES) DIST_SOURCES = $(am__fuzz_rsyslog_message_SOURCES_DIST) \ $(am__logctl_SOURCES_DIST) $(am__msggen_SOURCES_DIST) \ rscryutil.c $(am__rsyslog_diag_hostname_SOURCES_DIST) \ $(rsyslogd_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man1_MANS) $(man5_MANS) $(man8_MANS) am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ CLEANFILES = $(am__append_6) $(am__append_15) man5_MANS = rsyslog.conf.5 man8_MANS = rsyslogd.8 man1_MANS = $(am__append_5) $(am__append_14) rsyslogd_SOURCES = \ syslogd.c \ rsyslogd.c \ syslogd.h \ omshell.c \ omshell.h \ omusrmsg.c \ omusrmsg.h \ omfwd.c \ omfwd.h \ omfile.c \ omfile.h \ ompipe.c \ ompipe.h \ omdiscard.c \ omdiscard.h \ pmrfc5424.c \ pmrfc5424.h \ pmrfc3164.c \ pmrfc3164.h \ smtradfile.c \ smtradfile.h \ smfile.c \ smfile.h \ smfwd.c \ smfwd.h \ smtradfwd.c \ smtradfwd.h \ iminternal.c \ iminternal.h \ \ ../runtime/dirty.h rsyslogd_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_1) \ $(am__append_2) -DSD_EXPORT_SYMBOLS @ENABLE_LIBZSTD_FALSE@rsyslogd_LDADD_ZSTD = @ENABLE_LIBZSTD_TRUE@rsyslogd_LDADD_ZSTD = $(ZSTD_LIBS) # note: it looks like librsyslog.la must be explicitely given on LDDADD, # otherwise dependencies are not properly calculated (resulting in a # potentially incomplete build, a problem we had several times...) rsyslogd_LDADD = ../grammar/libgrammar.la ../runtime/librsyslog.la \ ../compat/compat.la $(ZLIB_LIBS) $(rsyslogd_LDADD_ZSTD) \ $(PTHREADS_LIBS) $(RSRT_LIBS) $(SOL_LIBS) $(LIBUUID_LIBS) \ $(HASH_XXHASH_LIBS) $(LIBRESOLV_LIBS) $(LIBYAML_LIBS) \ $(am__append_3) @OS_AIX_FALSE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -export-dynamic @OS_AIX_TRUE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -brtl -bexpall -f"aix_exports_list" -lsrc @OS_APPLE_TRUE@@OS_LINUX_FALSE@rsyslogd_LDFLAGS = -export-dynamic \ @OS_APPLE_TRUE@@OS_LINUX_FALSE@ -Wl,$(top_builddir)/runtime/.libs/librsyslog.a # Note: do NOT indent the if chain - it will not work! @OS_LINUX_TRUE@rsyslogd_LDFLAGS = -export-dynamic \ @OS_LINUX_TRUE@ #-Wl,--whole-archive,$(top_builddir)/runtime/.libs/librsyslog.a,--no-whole-archive @OS_AIX_FALSE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@exports_list_file = @OS_AIX_TRUE@@OS_APPLE_FALSE@@OS_LINUX_FALSE@exports_list_file = aix_exports_list @OS_APPLE_TRUE@@OS_LINUX_FALSE@exports_list_file = @OS_LINUX_TRUE@exports_list_file = EXTRA_DIST = $(man5_MANS) $(man8_MANS) rscryutil.rst recover_qi.pl \ rsyslog-segqueue.rst $(am__append_7) $(am__append_16) @ENABLE_FUZZING_TRUE@fuzz_rsyslog_message_SOURCES = $(rsyslogd_SOURCES) fuzz_rsyslog_message.c @ENABLE_FUZZING_TRUE@fuzz_rsyslog_message_CPPFLAGS = $(rsyslogd_CPPFLAGS) -DRSYSLOG_FUZZ_TARGET -Dmain=rsyslogd_main @ENABLE_FUZZING_TRUE@fuzz_rsyslog_message_LDADD = $(rsyslogd_LDADD) @ENABLE_FUZZING_TRUE@fuzz_rsyslog_message_LDFLAGS = $(rsyslogd_LDFLAGS) $(LIB_FUZZING_ENGINE) EXTRA_rsyslogd_DEPENDENCIES = $(exports_list_file) @ENABLE_DIAGTOOLS_TRUE@rsyslog_diag_hostname_SOURCES = gethostn.c @ENABLE_DIAGTOOLS_TRUE@msggen_SOURCES = msggen.c @ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@dist_bin_SCRIPTS = rsyslog-segqueue @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_SOURCES = logctl.c @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(LIBMONGOC_CFLAGS) @ENABLE_OMMONGODB_TRUE@@ENABLE_USERTOOLS_TRUE@logctl_LDADD = $(LIBMONGOC_LIBS) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil = rscryutil.c @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_CPPFLAGS = \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ -I../runtime \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(RSRT_CFLAGS) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_10) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_12) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_LDADD = $(am__append_11) \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(am__append_13) @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil_LDFLAGS = \ @ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@-Wl,--whole-archive,--no-whole-archive @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@RSTMANFILE = rscryutil.rst all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 tools/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu tools/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_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 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 fuzz_rsyslog_message$(EXEEXT): $(fuzz_rsyslog_message_OBJECTS) $(fuzz_rsyslog_message_DEPENDENCIES) $(EXTRA_fuzz_rsyslog_message_DEPENDENCIES) @rm -f fuzz_rsyslog_message$(EXEEXT) $(AM_V_CCLD)$(fuzz_rsyslog_message_LINK) $(fuzz_rsyslog_message_OBJECTS) $(fuzz_rsyslog_message_LDADD) $(LIBS) logctl$(EXEEXT): $(logctl_OBJECTS) $(logctl_DEPENDENCIES) $(EXTRA_logctl_DEPENDENCIES) @rm -f logctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(logctl_OBJECTS) $(logctl_LDADD) $(LIBS) msggen$(EXEEXT): $(msggen_OBJECTS) $(msggen_DEPENDENCIES) $(EXTRA_msggen_DEPENDENCIES) @rm -f msggen$(EXEEXT) $(AM_V_CCLD)$(LINK) $(msggen_OBJECTS) $(msggen_LDADD) $(LIBS) rscryutil$(EXEEXT): $(rscryutil_OBJECTS) $(rscryutil_DEPENDENCIES) $(EXTRA_rscryutil_DEPENDENCIES) @rm -f rscryutil$(EXEEXT) $(AM_V_CCLD)$(rscryutil_LINK) $(rscryutil_OBJECTS) $(rscryutil_LDADD) $(LIBS) rsyslog_diag_hostname$(EXEEXT): $(rsyslog_diag_hostname_OBJECTS) $(rsyslog_diag_hostname_DEPENDENCIES) $(EXTRA_rsyslog_diag_hostname_DEPENDENCIES) @rm -f rsyslog_diag_hostname$(EXEEXT) $(AM_V_CCLD)$(LINK) $(rsyslog_diag_hostname_OBJECTS) $(rsyslog_diag_hostname_LDADD) $(LIBS) rsyslogd$(EXEEXT): $(rsyslogd_OBJECTS) $(rsyslogd_DEPENDENCIES) $(EXTRA_rsyslogd_DEPENDENCIES) @rm -f rsyslogd$(EXEEXT) $(AM_V_CCLD)$(rsyslogd_LINK) $(rsyslogd_OBJECTS) $(rsyslogd_LDADD) $(LIBS) install-dist_binSCRIPTS: $(dist_bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | 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; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$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_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-iminternal.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-omfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-omfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-ompipe.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-omshell.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-smfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-smfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuzz_rsyslog_message-syslogd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gethostn.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logctl-logctl.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msggen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rscryutil-rscryutil.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-iminternal.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omdiscard.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-ompipe.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omshell.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-omusrmsg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-pmrfc3164.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-pmrfc5424.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-rsyslogd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smtradfile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-smtradfwd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsyslogd-syslogd.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< fuzz_rsyslog_message-syslogd.o: syslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-syslogd.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-syslogd.Tpo -c -o fuzz_rsyslog_message-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-syslogd.Tpo $(DEPDIR)/fuzz_rsyslog_message-syslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='fuzz_rsyslog_message-syslogd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c fuzz_rsyslog_message-syslogd.obj: syslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-syslogd.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-syslogd.Tpo -c -o fuzz_rsyslog_message-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-syslogd.Tpo $(DEPDIR)/fuzz_rsyslog_message-syslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='fuzz_rsyslog_message-syslogd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi` fuzz_rsyslog_message-rsyslogd.o: rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-rsyslogd.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Tpo -c -o fuzz_rsyslog_message-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Tpo $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='fuzz_rsyslog_message-rsyslogd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c fuzz_rsyslog_message-rsyslogd.obj: rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-rsyslogd.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Tpo -c -o fuzz_rsyslog_message-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Tpo $(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='fuzz_rsyslog_message-rsyslogd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi` fuzz_rsyslog_message-omshell.o: omshell.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omshell.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omshell.Tpo -c -o fuzz_rsyslog_message-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omshell.Tpo $(DEPDIR)/fuzz_rsyslog_message-omshell.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='fuzz_rsyslog_message-omshell.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c fuzz_rsyslog_message-omshell.obj: omshell.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omshell.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omshell.Tpo -c -o fuzz_rsyslog_message-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omshell.Tpo $(DEPDIR)/fuzz_rsyslog_message-omshell.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='fuzz_rsyslog_message-omshell.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi` fuzz_rsyslog_message-omusrmsg.o: omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omusrmsg.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Tpo -c -o fuzz_rsyslog_message-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Tpo $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='fuzz_rsyslog_message-omusrmsg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c fuzz_rsyslog_message-omusrmsg.obj: omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omusrmsg.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Tpo -c -o fuzz_rsyslog_message-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Tpo $(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='fuzz_rsyslog_message-omusrmsg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi` fuzz_rsyslog_message-omfwd.o: omfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omfwd.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omfwd.Tpo -c -o fuzz_rsyslog_message-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-omfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='fuzz_rsyslog_message-omfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c fuzz_rsyslog_message-omfwd.obj: omfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omfwd.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omfwd.Tpo -c -o fuzz_rsyslog_message-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-omfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='fuzz_rsyslog_message-omfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi` fuzz_rsyslog_message-omfile.o: omfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omfile.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omfile.Tpo -c -o fuzz_rsyslog_message-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-omfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='fuzz_rsyslog_message-omfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c fuzz_rsyslog_message-omfile.obj: omfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omfile.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omfile.Tpo -c -o fuzz_rsyslog_message-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-omfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='fuzz_rsyslog_message-omfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi` fuzz_rsyslog_message-ompipe.o: ompipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-ompipe.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-ompipe.Tpo -c -o fuzz_rsyslog_message-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-ompipe.Tpo $(DEPDIR)/fuzz_rsyslog_message-ompipe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='fuzz_rsyslog_message-ompipe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c fuzz_rsyslog_message-ompipe.obj: ompipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-ompipe.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-ompipe.Tpo -c -o fuzz_rsyslog_message-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-ompipe.Tpo $(DEPDIR)/fuzz_rsyslog_message-ompipe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='fuzz_rsyslog_message-ompipe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi` fuzz_rsyslog_message-omdiscard.o: omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omdiscard.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Tpo -c -o fuzz_rsyslog_message-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Tpo $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='fuzz_rsyslog_message-omdiscard.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c fuzz_rsyslog_message-omdiscard.obj: omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-omdiscard.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Tpo -c -o fuzz_rsyslog_message-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Tpo $(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='fuzz_rsyslog_message-omdiscard.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi` fuzz_rsyslog_message-pmrfc5424.o: pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-pmrfc5424.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Tpo -c -o fuzz_rsyslog_message-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Tpo $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='fuzz_rsyslog_message-pmrfc5424.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c fuzz_rsyslog_message-pmrfc5424.obj: pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-pmrfc5424.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Tpo -c -o fuzz_rsyslog_message-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Tpo $(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='fuzz_rsyslog_message-pmrfc5424.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi` fuzz_rsyslog_message-pmrfc3164.o: pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-pmrfc3164.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Tpo -c -o fuzz_rsyslog_message-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Tpo $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='fuzz_rsyslog_message-pmrfc3164.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c fuzz_rsyslog_message-pmrfc3164.obj: pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-pmrfc3164.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Tpo -c -o fuzz_rsyslog_message-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Tpo $(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='fuzz_rsyslog_message-pmrfc3164.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi` fuzz_rsyslog_message-smtradfile.o: smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smtradfile.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Tpo -c -o fuzz_rsyslog_message-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='fuzz_rsyslog_message-smtradfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c fuzz_rsyslog_message-smtradfile.obj: smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smtradfile.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Tpo -c -o fuzz_rsyslog_message-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='fuzz_rsyslog_message-smtradfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi` fuzz_rsyslog_message-smfile.o: smfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smfile.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smfile.Tpo -c -o fuzz_rsyslog_message-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-smfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='fuzz_rsyslog_message-smfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c fuzz_rsyslog_message-smfile.obj: smfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smfile.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smfile.Tpo -c -o fuzz_rsyslog_message-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smfile.Tpo $(DEPDIR)/fuzz_rsyslog_message-smfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='fuzz_rsyslog_message-smfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi` fuzz_rsyslog_message-smfwd.o: smfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smfwd.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smfwd.Tpo -c -o fuzz_rsyslog_message-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-smfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='fuzz_rsyslog_message-smfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c fuzz_rsyslog_message-smfwd.obj: smfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smfwd.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smfwd.Tpo -c -o fuzz_rsyslog_message-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-smfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='fuzz_rsyslog_message-smfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi` fuzz_rsyslog_message-smtradfwd.o: smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smtradfwd.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Tpo -c -o fuzz_rsyslog_message-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='fuzz_rsyslog_message-smtradfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c fuzz_rsyslog_message-smtradfwd.obj: smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-smtradfwd.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Tpo -c -o fuzz_rsyslog_message-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Tpo $(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='fuzz_rsyslog_message-smtradfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi` fuzz_rsyslog_message-iminternal.o: iminternal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-iminternal.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-iminternal.Tpo -c -o fuzz_rsyslog_message-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-iminternal.Tpo $(DEPDIR)/fuzz_rsyslog_message-iminternal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='fuzz_rsyslog_message-iminternal.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c fuzz_rsyslog_message-iminternal.obj: iminternal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-iminternal.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-iminternal.Tpo -c -o fuzz_rsyslog_message-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-iminternal.Tpo $(DEPDIR)/fuzz_rsyslog_message-iminternal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='fuzz_rsyslog_message-iminternal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi` fuzz_rsyslog_message-fuzz_rsyslog_message.o: fuzz_rsyslog_message.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-fuzz_rsyslog_message.o -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Tpo -c -o fuzz_rsyslog_message-fuzz_rsyslog_message.o `test -f 'fuzz_rsyslog_message.c' || echo '$(srcdir)/'`fuzz_rsyslog_message.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Tpo $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fuzz_rsyslog_message.c' object='fuzz_rsyslog_message-fuzz_rsyslog_message.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-fuzz_rsyslog_message.o `test -f 'fuzz_rsyslog_message.c' || echo '$(srcdir)/'`fuzz_rsyslog_message.c fuzz_rsyslog_message-fuzz_rsyslog_message.obj: fuzz_rsyslog_message.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fuzz_rsyslog_message-fuzz_rsyslog_message.obj -MD -MP -MF $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Tpo -c -o fuzz_rsyslog_message-fuzz_rsyslog_message.obj `if test -f 'fuzz_rsyslog_message.c'; then $(CYGPATH_W) 'fuzz_rsyslog_message.c'; else $(CYGPATH_W) '$(srcdir)/fuzz_rsyslog_message.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Tpo $(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fuzz_rsyslog_message.c' object='fuzz_rsyslog_message-fuzz_rsyslog_message.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fuzz_rsyslog_message_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fuzz_rsyslog_message-fuzz_rsyslog_message.obj `if test -f 'fuzz_rsyslog_message.c'; then $(CYGPATH_W) 'fuzz_rsyslog_message.c'; else $(CYGPATH_W) '$(srcdir)/fuzz_rsyslog_message.c'; fi` logctl-logctl.o: logctl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logctl-logctl.o -MD -MP -MF $(DEPDIR)/logctl-logctl.Tpo -c -o logctl-logctl.o `test -f 'logctl.c' || echo '$(srcdir)/'`logctl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logctl-logctl.Tpo $(DEPDIR)/logctl-logctl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logctl.c' object='logctl-logctl.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logctl-logctl.o `test -f 'logctl.c' || echo '$(srcdir)/'`logctl.c logctl-logctl.obj: logctl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logctl-logctl.obj -MD -MP -MF $(DEPDIR)/logctl-logctl.Tpo -c -o logctl-logctl.obj `if test -f 'logctl.c'; then $(CYGPATH_W) 'logctl.c'; else $(CYGPATH_W) '$(srcdir)/logctl.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/logctl-logctl.Tpo $(DEPDIR)/logctl-logctl.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='logctl.c' object='logctl-logctl.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(logctl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logctl-logctl.obj `if test -f 'logctl.c'; then $(CYGPATH_W) 'logctl.c'; else $(CYGPATH_W) '$(srcdir)/logctl.c'; fi` rscryutil-rscryutil.o: rscryutil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rscryutil-rscryutil.o -MD -MP -MF $(DEPDIR)/rscryutil-rscryutil.Tpo -c -o rscryutil-rscryutil.o `test -f 'rscryutil.c' || echo '$(srcdir)/'`rscryutil.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rscryutil-rscryutil.Tpo $(DEPDIR)/rscryutil-rscryutil.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rscryutil.c' object='rscryutil-rscryutil.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rscryutil-rscryutil.o `test -f 'rscryutil.c' || echo '$(srcdir)/'`rscryutil.c rscryutil-rscryutil.obj: rscryutil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rscryutil-rscryutil.obj -MD -MP -MF $(DEPDIR)/rscryutil-rscryutil.Tpo -c -o rscryutil-rscryutil.obj `if test -f 'rscryutil.c'; then $(CYGPATH_W) 'rscryutil.c'; else $(CYGPATH_W) '$(srcdir)/rscryutil.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rscryutil-rscryutil.Tpo $(DEPDIR)/rscryutil-rscryutil.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rscryutil.c' object='rscryutil-rscryutil.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rscryutil_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rscryutil-rscryutil.obj `if test -f 'rscryutil.c'; then $(CYGPATH_W) 'rscryutil.c'; else $(CYGPATH_W) '$(srcdir)/rscryutil.c'; fi` rsyslogd-syslogd.o: syslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.o -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='rsyslogd-syslogd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.o `test -f 'syslogd.c' || echo '$(srcdir)/'`syslogd.c rsyslogd-syslogd.obj: syslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-syslogd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-syslogd.Tpo -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-syslogd.Tpo $(DEPDIR)/rsyslogd-syslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='syslogd.c' object='rsyslogd-syslogd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-syslogd.obj `if test -f 'syslogd.c'; then $(CYGPATH_W) 'syslogd.c'; else $(CYGPATH_W) '$(srcdir)/syslogd.c'; fi` rsyslogd-rsyslogd.o: rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-rsyslogd.o -MD -MP -MF $(DEPDIR)/rsyslogd-rsyslogd.Tpo -c -o rsyslogd-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-rsyslogd.Tpo $(DEPDIR)/rsyslogd-rsyslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='rsyslogd-rsyslogd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-rsyslogd.o `test -f 'rsyslogd.c' || echo '$(srcdir)/'`rsyslogd.c rsyslogd-rsyslogd.obj: rsyslogd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-rsyslogd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-rsyslogd.Tpo -c -o rsyslogd-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-rsyslogd.Tpo $(DEPDIR)/rsyslogd-rsyslogd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslogd.c' object='rsyslogd-rsyslogd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-rsyslogd.obj `if test -f 'rsyslogd.c'; then $(CYGPATH_W) 'rsyslogd.c'; else $(CYGPATH_W) '$(srcdir)/rsyslogd.c'; fi` rsyslogd-omshell.o: omshell.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.o -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='rsyslogd-omshell.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.o `test -f 'omshell.c' || echo '$(srcdir)/'`omshell.c rsyslogd-omshell.obj: omshell.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omshell.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omshell.Tpo -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omshell.Tpo $(DEPDIR)/rsyslogd-omshell.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omshell.c' object='rsyslogd-omshell.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omshell.obj `if test -f 'omshell.c'; then $(CYGPATH_W) 'omshell.c'; else $(CYGPATH_W) '$(srcdir)/omshell.c'; fi` rsyslogd-omusrmsg.o: omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.o -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='rsyslogd-omusrmsg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.o `test -f 'omusrmsg.c' || echo '$(srcdir)/'`omusrmsg.c rsyslogd-omusrmsg.obj: omusrmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omusrmsg.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omusrmsg.Tpo -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omusrmsg.Tpo $(DEPDIR)/rsyslogd-omusrmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omusrmsg.c' object='rsyslogd-omusrmsg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omusrmsg.obj `if test -f 'omusrmsg.c'; then $(CYGPATH_W) 'omusrmsg.c'; else $(CYGPATH_W) '$(srcdir)/omusrmsg.c'; fi` rsyslogd-omfwd.o: omfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='rsyslogd-omfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.o `test -f 'omfwd.c' || echo '$(srcdir)/'`omfwd.c rsyslogd-omfwd.obj: omfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfwd.Tpo -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfwd.Tpo $(DEPDIR)/rsyslogd-omfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfwd.c' object='rsyslogd-omfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfwd.obj `if test -f 'omfwd.c'; then $(CYGPATH_W) 'omfwd.c'; else $(CYGPATH_W) '$(srcdir)/omfwd.c'; fi` rsyslogd-omfile.o: omfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='rsyslogd-omfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.o `test -f 'omfile.c' || echo '$(srcdir)/'`omfile.c rsyslogd-omfile.obj: omfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omfile.Tpo -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omfile.Tpo $(DEPDIR)/rsyslogd-omfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omfile.c' object='rsyslogd-omfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omfile.obj `if test -f 'omfile.c'; then $(CYGPATH_W) 'omfile.c'; else $(CYGPATH_W) '$(srcdir)/omfile.c'; fi` rsyslogd-ompipe.o: ompipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ompipe.o -MD -MP -MF $(DEPDIR)/rsyslogd-ompipe.Tpo -c -o rsyslogd-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-ompipe.Tpo $(DEPDIR)/rsyslogd-ompipe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='rsyslogd-ompipe.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ompipe.o `test -f 'ompipe.c' || echo '$(srcdir)/'`ompipe.c rsyslogd-ompipe.obj: ompipe.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-ompipe.obj -MD -MP -MF $(DEPDIR)/rsyslogd-ompipe.Tpo -c -o rsyslogd-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-ompipe.Tpo $(DEPDIR)/rsyslogd-ompipe.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ompipe.c' object='rsyslogd-ompipe.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-ompipe.obj `if test -f 'ompipe.c'; then $(CYGPATH_W) 'ompipe.c'; else $(CYGPATH_W) '$(srcdir)/ompipe.c'; fi` rsyslogd-omdiscard.o: omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.o -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='rsyslogd-omdiscard.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.o `test -f 'omdiscard.c' || echo '$(srcdir)/'`omdiscard.c rsyslogd-omdiscard.obj: omdiscard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-omdiscard.obj -MD -MP -MF $(DEPDIR)/rsyslogd-omdiscard.Tpo -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-omdiscard.Tpo $(DEPDIR)/rsyslogd-omdiscard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omdiscard.c' object='rsyslogd-omdiscard.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-omdiscard.obj `if test -f 'omdiscard.c'; then $(CYGPATH_W) 'omdiscard.c'; else $(CYGPATH_W) '$(srcdir)/omdiscard.c'; fi` rsyslogd-pmrfc5424.o: pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc5424.o -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc5424.Tpo -c -o rsyslogd-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc5424.Tpo $(DEPDIR)/rsyslogd-pmrfc5424.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='rsyslogd-pmrfc5424.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc5424.o `test -f 'pmrfc5424.c' || echo '$(srcdir)/'`pmrfc5424.c rsyslogd-pmrfc5424.obj: pmrfc5424.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc5424.obj -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc5424.Tpo -c -o rsyslogd-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc5424.Tpo $(DEPDIR)/rsyslogd-pmrfc5424.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc5424.c' object='rsyslogd-pmrfc5424.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc5424.obj `if test -f 'pmrfc5424.c'; then $(CYGPATH_W) 'pmrfc5424.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc5424.c'; fi` rsyslogd-pmrfc3164.o: pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc3164.o -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc3164.Tpo -c -o rsyslogd-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc3164.Tpo $(DEPDIR)/rsyslogd-pmrfc3164.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='rsyslogd-pmrfc3164.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc3164.o `test -f 'pmrfc3164.c' || echo '$(srcdir)/'`pmrfc3164.c rsyslogd-pmrfc3164.obj: pmrfc3164.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-pmrfc3164.obj -MD -MP -MF $(DEPDIR)/rsyslogd-pmrfc3164.Tpo -c -o rsyslogd-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-pmrfc3164.Tpo $(DEPDIR)/rsyslogd-pmrfc3164.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmrfc3164.c' object='rsyslogd-pmrfc3164.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-pmrfc3164.obj `if test -f 'pmrfc3164.c'; then $(CYGPATH_W) 'pmrfc3164.c'; else $(CYGPATH_W) '$(srcdir)/pmrfc3164.c'; fi` rsyslogd-smtradfile.o: smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfile.Tpo -c -o rsyslogd-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfile.Tpo $(DEPDIR)/rsyslogd-smtradfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='rsyslogd-smtradfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfile.o `test -f 'smtradfile.c' || echo '$(srcdir)/'`smtradfile.c rsyslogd-smtradfile.obj: smtradfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfile.Tpo -c -o rsyslogd-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfile.Tpo $(DEPDIR)/rsyslogd-smtradfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfile.c' object='rsyslogd-smtradfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfile.obj `if test -f 'smtradfile.c'; then $(CYGPATH_W) 'smtradfile.c'; else $(CYGPATH_W) '$(srcdir)/smtradfile.c'; fi` rsyslogd-smfile.o: smfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfile.o -MD -MP -MF $(DEPDIR)/rsyslogd-smfile.Tpo -c -o rsyslogd-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfile.Tpo $(DEPDIR)/rsyslogd-smfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='rsyslogd-smfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfile.o `test -f 'smfile.c' || echo '$(srcdir)/'`smfile.c rsyslogd-smfile.obj: smfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfile.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smfile.Tpo -c -o rsyslogd-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfile.Tpo $(DEPDIR)/rsyslogd-smfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfile.c' object='rsyslogd-smfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfile.obj `if test -f 'smfile.c'; then $(CYGPATH_W) 'smfile.c'; else $(CYGPATH_W) '$(srcdir)/smfile.c'; fi` rsyslogd-smfwd.o: smfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-smfwd.Tpo -c -o rsyslogd-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfwd.Tpo $(DEPDIR)/rsyslogd-smfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='rsyslogd-smfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfwd.o `test -f 'smfwd.c' || echo '$(srcdir)/'`smfwd.c rsyslogd-smfwd.obj: smfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smfwd.Tpo -c -o rsyslogd-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smfwd.Tpo $(DEPDIR)/rsyslogd-smfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smfwd.c' object='rsyslogd-smfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smfwd.obj `if test -f 'smfwd.c'; then $(CYGPATH_W) 'smfwd.c'; else $(CYGPATH_W) '$(srcdir)/smfwd.c'; fi` rsyslogd-smtradfwd.o: smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfwd.o -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfwd.Tpo -c -o rsyslogd-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfwd.Tpo $(DEPDIR)/rsyslogd-smtradfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='rsyslogd-smtradfwd.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfwd.o `test -f 'smtradfwd.c' || echo '$(srcdir)/'`smtradfwd.c rsyslogd-smtradfwd.obj: smtradfwd.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-smtradfwd.obj -MD -MP -MF $(DEPDIR)/rsyslogd-smtradfwd.Tpo -c -o rsyslogd-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-smtradfwd.Tpo $(DEPDIR)/rsyslogd-smtradfwd.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smtradfwd.c' object='rsyslogd-smtradfwd.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-smtradfwd.obj `if test -f 'smtradfwd.c'; then $(CYGPATH_W) 'smtradfwd.c'; else $(CYGPATH_W) '$(srcdir)/smtradfwd.c'; fi` rsyslogd-iminternal.o: iminternal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.o -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='rsyslogd-iminternal.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.o `test -f 'iminternal.c' || echo '$(srcdir)/'`iminternal.c rsyslogd-iminternal.obj: iminternal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rsyslogd-iminternal.obj -MD -MP -MF $(DEPDIR)/rsyslogd-iminternal.Tpo -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/rsyslogd-iminternal.Tpo $(DEPDIR)/rsyslogd-iminternal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='iminternal.c' object='rsyslogd-iminternal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(rsyslogd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rsyslogd-iminternal.obj `if test -f 'iminternal.c'; then $(CYGPATH_W) 'iminternal.c'; else $(CYGPATH_W) '$(srcdir)/iminternal.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(man1_MANS) @$(NORMAL_INSTALL) @list1='$(man1_MANS)'; \ list2=''; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || 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 '/\.1[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,^[^1][0-9a-z]*$$,1,;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)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$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)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(man5_MANS) @$(NORMAL_INSTALL) @list1='$(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='$(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: $(man8_MANS) @$(NORMAL_INSTALL) @list1='$(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='$(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) clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(SCRIPTS) $(MANS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(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: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-libtool \ clean-noinstPROGRAMS clean-sbinPROGRAMS mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-iminternal.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-ompipe.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omshell.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-syslogd.Po -rm -f ./$(DEPDIR)/gethostn.Po -rm -f ./$(DEPDIR)/logctl-logctl.Po -rm -f ./$(DEPDIR)/msggen.Po -rm -f ./$(DEPDIR)/rscryutil-rscryutil.Po -rm -f ./$(DEPDIR)/rsyslogd-iminternal.Po -rm -f ./$(DEPDIR)/rsyslogd-omdiscard.Po -rm -f ./$(DEPDIR)/rsyslogd-omfile.Po -rm -f ./$(DEPDIR)/rsyslogd-omfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-ompipe.Po -rm -f ./$(DEPDIR)/rsyslogd-omshell.Po -rm -f ./$(DEPDIR)/rsyslogd-omusrmsg.Po -rm -f ./$(DEPDIR)/rsyslogd-pmrfc3164.Po -rm -f ./$(DEPDIR)/rsyslogd-pmrfc5424.Po -rm -f ./$(DEPDIR)/rsyslogd-rsyslogd.Po -rm -f ./$(DEPDIR)/rsyslogd-smfile.Po -rm -f ./$(DEPDIR)/rsyslogd-smfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-smtradfile.Po -rm -f ./$(DEPDIR)/rsyslogd-smtradfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-syslogd.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local 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-binPROGRAMS install-dist_binSCRIPTS \ install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 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 ./$(DEPDIR)/fuzz_rsyslog_message-fuzz_rsyslog_message.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-iminternal.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omdiscard.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-ompipe.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omshell.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-omusrmsg.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc3164.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-pmrfc5424.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-rsyslogd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smtradfile.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-smtradfwd.Po -rm -f ./$(DEPDIR)/fuzz_rsyslog_message-syslogd.Po -rm -f ./$(DEPDIR)/gethostn.Po -rm -f ./$(DEPDIR)/logctl-logctl.Po -rm -f ./$(DEPDIR)/msggen.Po -rm -f ./$(DEPDIR)/rscryutil-rscryutil.Po -rm -f ./$(DEPDIR)/rsyslogd-iminternal.Po -rm -f ./$(DEPDIR)/rsyslogd-omdiscard.Po -rm -f ./$(DEPDIR)/rsyslogd-omfile.Po -rm -f ./$(DEPDIR)/rsyslogd-omfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-ompipe.Po -rm -f ./$(DEPDIR)/rsyslogd-omshell.Po -rm -f ./$(DEPDIR)/rsyslogd-omusrmsg.Po -rm -f ./$(DEPDIR)/rsyslogd-pmrfc3164.Po -rm -f ./$(DEPDIR)/rsyslogd-pmrfc5424.Po -rm -f ./$(DEPDIR)/rsyslogd-rsyslogd.Po -rm -f ./$(DEPDIR)/rsyslogd-smfile.Po -rm -f ./$(DEPDIR)/rsyslogd-smfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-smtradfile.Po -rm -f ./$(DEPDIR)/rsyslogd-smtradfwd.Po -rm -f ./$(DEPDIR)/rsyslogd-syslogd.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-dist_binSCRIPTS \ uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-coverage-am clean-coverage-local \ clean-generic clean-libtool clean-noinstPROGRAMS \ clean-sbinPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-coverage-am \ distclean-coverage-local distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dist_binSCRIPTS install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-man5 install-man8 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-binPROGRAMS uninstall-dist_binSCRIPTS uninstall-man \ uninstall-man1 uninstall-man5 uninstall-man8 \ uninstall-sbinPROGRAMS .PRECIOUS: Makefile @ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@rsyslog-segqueue.1: rsyslog-segqueue.rst @ENABLE_SEGQUEUE_TOOL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(AM_V_GEN) $(RST2MAN) rsyslog-segqueue.rst $@ @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@rscryutil.1: $(RSTMANFILE) @ENABLE_GENERATE_MAN_PAGES_TRUE@@ENABLE_RSCRYUTIL_TRUE@@ENABLE_USERTOOLS_TRUE@ $(AM_V_GEN) $(RST2MAN) $(RSTMANFILE) $@ aix_exports_list: echo "$(top_builddir)/runtime/.libs/librsyslog_la-*.o" > $@ echo "$(top_builddir)/.libs/librsyslog_la-*.o" >> $@ echo "$(top_builddir)/grammar/.libs/libgrammar_la-*.o" >> $@ # 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: rsyslog-8.2608.0/tools/PaxHeaders/iminternal.h0000644000000000000000000000013115132411300016177 xustar0029 mtime=1768559296.30288621 30 atime=1787067622.169514814 30 ctime=1787067795.292741789 rsyslog-8.2608.0/tools/iminternal.h0000666000175000017500000000300315132411300015642 0ustar00rgerrger/* Definition of the internal messages input module. * * Note: we currently do not have an input module spec, but * we will have one in the future. This module needs then to be * adapted. * * Copyright 2007 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef IMINTERNAL_H_INCLUDED #define IMINTERNAL_H_INCLUDED #include "template.h" /* this is a single entry for a parse routine. It describes exactly * one entry point/handler. * The short name is cslch (Configfile SysLine CommandHandler) */ struct iminternal_s { /* config file sysline parse entry */ smsg_t *pMsg; /* the message (in all its glory) */ }; typedef struct iminternal_s iminternal_t; /* prototypes */ rsRetVal modInitIminternal(void); rsRetVal modExitIminternal(void); rsRetVal iminternalAddMsg(smsg_t *pMsg); rsRetVal iminternalRemoveMsg(smsg_t **ppMsg); #endif /* #ifndef IMINTERNAL_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/omfile.h0000644000000000000000000000013115141401300015307 xustar0030 mtime=1770390208.969869851 29 atime=1787067618.28844245 30 ctime=1787067795.250741006 rsyslog-8.2608.0/tools/omfile.h0000664000175000017500000000277015141401300014762 0ustar00rgerrger/* omfile.h * These are the definitions for the build-in file output module. * * File begun on 2007-07-21 by RGerhards * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OMFILE_H_INCLUDED #define OMFILE_H_INCLUDED 1 /* prototypes */ rsRetVal modInitFile(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); /* the define below is dirty, but we need it for ompipe integration. There is no * other way to have the functionality (well, one way would be to go through the * globals, but that seems not yet justified. -- rgerhards, 2010-03-01 */ extern uchar *pszFileDfltTplName; #endif /* #ifndef OMFILE_H_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/tools/PaxHeaders/syslogd.h0000644000000000000000000000013215145046113015534 xustar0030 mtime=1771326539.073014843 30 atime=1787067622.126514013 30 ctime=1787067795.232740671 rsyslog-8.2608.0/tools/syslogd.h0000664000175000017500000000217015145046113015200 0ustar00rgerrger/* common header for syslogd * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SYSLOGD_H_INCLUDED #define SYSLOGD_H_INCLUDED 1 #include "syslogd-types.h" #include "objomsr.h" #include "modules.h" #include "template.h" #include "action.h" #include "linkedlist.h" /* the following prototypes should go away once we have an input * module interface -- rgerhards, 2007-12-12 */ extern int NoHops; extern int send_to_all; #include "dirty.h" #endif /* #ifndef SYSLOGD_H_INCLUDED */ rsyslog-8.2608.0/tools/PaxHeaders/rsyslogd.c0000644000000000000000000000013215241075234015714 xustar0030 mtime=1787067036.652579174 30 atime=1787067036.805582039 30 ctime=1787067795.229740615 rsyslog-8.2608.0/tools/rsyslogd.c0000664000175000017500000027766115241075234015403 0ustar00rgerrger/* This is the main rsyslogd file. * It contains code * that is known to be validly under ASL 2.0, * because it was either written from scratch by me (rgerhards) or * contributors who agreed to ASL 2.0. * * Copyright 2004-2026 Rainer Gerhards and Adiscon * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_LIBLOGGING_STDLOG #include #else #include #endif #ifdef HAVE_LIBSYSTEMD #include #endif #ifdef ENABLE_LIBCAPNG #include #endif #if defined(HAVE_LINUX_CLOSE_RANGE_H) #include #endif #include "rsyslog.h" #include "wti.h" #include "ratelimit.h" #include "queue.h" #include "parser.h" #include "linkedlist.h" #include "ruleset.h" #include "action.h" #include "iminternal.h" #include "errmsg.h" #include "threads.h" #include "dnscache.h" #include "prop.h" #include "unicode-helper.h" #include "net.h" #include "glbl.h" #include "debug.h" #include "srUtils.h" #include "rainerscript.h" #include "rsconf.h" #include "translate.h" #include "cfsysline.h" #include "datetime.h" #include "operatingstate.h" #include "dirty.h" #include "janitor.h" #include "parserif.h" #include "rswatch.h" /* some global vars we need to differentiate between environments, * for TZ-related things see * https://github.com/rsyslog/rsyslog/issues/2994 */ static int runningInContainer = 0; #ifdef OS_LINUX static int emitTZWarning = 0; #else static int emitTZWarning = 1; #endif static pthread_t mainthread = 0; #ifdef HAVE_LIBSYSTEMD static int systemdWatchdogEnabled = 0; static uint64_t systemdWatchdogUsec = 0; #endif #if defined(_AIX) /* AIXPORT : start * The following includes and declarations are for support of the System * Resource Controller (SRC) . */ #include /* AIXPORT : start*/ #define SRC_FD 13 #define SRCMSG (sizeof(srcpacket)) static void deinitAll(void); #include static struct srcreq srcpacket; int cont; struct srchdr *srchdr; char progname[128]; /* Normally defined as locals in main * But here since the functionality is split * across multiple functions, we make it global */ static int rc; static socklen_t addrsz; static struct sockaddr srcaddr; int src_exists = TRUE; /* src end */ /* * SRC packet processing - . */ #define SRCMIN(a, b) (a < b) ? a : b void dosrcpacket(msgno, txt, len) int msgno; char *txt; int len; { struct srcrep reply; const char *msgtxt; msgtxt = (txt == NULL) ? "" : txt; reply.svrreply.rtncode = msgno; /* AIXPORT : srv was corrected to syslogd */ RS_COPY_LITERAL(reply.svrreply.objname, "syslogd"); if (snprintf(reply.svrreply.rtnmsg, sizeof(reply.svrreply.rtnmsg), "%s", msgtxt) < 0) { reply.svrreply.rtnmsg[0] = '\0'; } reply.svrreply.rtnmsg[sizeof(reply.svrreply.rtnmsg) - 1] = '\0'; srchdr = srcrrqs((char *)&srcpacket); srcsrpy(srchdr, (char *)&reply, len, cont); } #define AIX_SRC_EXISTS_IF if (!src_exists) { #define AIX_SRC_EXISTS_FI } static void aix_close_it(int i) { if (src_exists) { if (i != SRC_FD) (void)close(i); } else close(i); } #else #define AIX_SRC_EXISTS_IF #define AIX_SRC_EXISTS_FI #define aix_close_it(x) close(x) #endif /* AIXPORT : end */ static rsRetVal checkConfigOutputDoesNotOverwriteInput(const char *const outputPath, const char *const configPath) { struct stat outputStat; struct stat configStat; if (outputPath == NULL || !strcmp(outputPath, "-") || configPath == NULL) { return RS_RET_OK; } if (!strcmp(outputPath, configPath)) { fprintf(stderr, "rsyslogd: -o output path must not be the same as the input config file '%s'\n", configPath); return RS_RET_ERR; } if (stat(configPath, &configStat) != 0) { return RS_RET_OK; } if (stat(outputPath, &outputStat) != 0) { return RS_RET_OK; } if (configStat.st_dev == outputStat.st_dev && configStat.st_ino == outputStat.st_ino) { fprintf(stderr, "rsyslogd: -o output path '%s' resolves to the same file as input config file '%s'\n", outputPath, configPath); return RS_RET_ERR; } return RS_RET_OK; } DEFobjCurrIf(obj) DEFobjCurrIf(prop) DEFobjCurrIf(parser) DEFobjCurrIf(ruleset) DEFobjCurrIf(net) DEFobjCurrIf(rsconf) DEFobjCurrIf(module) DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) extern int yydebug; /* interface to parser */ /* forward definitions */ void rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg); void rsyslogdDoDie(int sig); #ifndef PATH_PIDFILE #if defined(_AIX) /* AIXPORT : Add _AIX */ #define PATH_PIDFILE "/etc/rsyslogd.pid" #else #define PATH_PIDFILE "/var/run/rsyslogd.pid" #endif /*_AIX*/ #endif #ifndef PATH_CONFFILE #define PATH_CONFFILE "/etc/rsyslog.conf" #endif /* global data items */ static volatile sig_atomic_t bChildDied = 0; static volatile sig_atomic_t bHadHUP = 0; static volatile sig_atomic_t bHUPInProgress = 0; static int doFork = 1; /* fork - run in daemon mode - read-only after startup */ static volatile sig_atomic_t bFinished = 0; /* signal number requesting termination, or 0 */ const char *PidFile = NULL; #define NO_PIDFILE "NONE" int iConfigVerify = 0; /* is this just a config verify run? */ rsconf_t *ourConf = NULL; /* our config object */ int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */ ratelimit_t *dflt_ratelimiter = NULL; /* ratelimiter for submits without explicit one */ uchar *ConfFile = (uchar *)PATH_CONFFILE; int bHaveMainQueue = 0; /* set to 1 if the main queue - in queueing mode - is available * If the main queue is either not yet ready or not running in * queueing mode (mode DIRECT!), then this is set to 0. */ prop_t *pInternalInputName = NULL; /* there is only one global inputName for all internally-generated messages */ ratelimit_t *internalMsg_ratelimiter = NULL; /* ratelimiter for rsyslog-own messages */ int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */ static uchar *properTerminationFile = NULL; /* testbench-only final shutdown marker path */ static struct queuefilenames_s { struct queuefilenames_s *next; uchar *name; } *queuefilenames = NULL; static __attribute__((noreturn)) void rsyslogd_usage(void) { fprintf(stderr, "usage: rsyslogd [options]\n" "use \"man rsyslogd\" for details. To run rsyslog " "interactively, use \"rsyslogd -n\"\n" "to run it in debug mode use \"rsyslogd -dn\"\n" "For further information see https://www.rsyslog.com/doc/\n"); exit(1); /* "good" exit - done to terminate usage() */ } #ifndef HAVE_SETSID extern void untty(void); /* in syslogd.c, GPLv3 */ static int setsid(void) { untty(); return 0; } #endif /* helper for imdiag. Returns if HUP processing has been requested or is not * yet finished. We know this is racy, but imdiag handles this part by * repeating operations. sig_atomic_t keeps access signal-handler safe; callers * must treat the answer as a transient observation. * 2023-07-26 Rainer Gerhards */ int get_bHadHUP(void) { const int ret = PREFER_LOAD_INT(&bHadHUP) || PREFER_LOAD_INT(&bHUPInProgress); /* note: at this point ret can already be invalid */ return ret; } /* we need a pointer to the conf, because in early startup stage we * need to use loadConf, later on runConf. */ rsRetVal queryLocalHostname(rsconf_t *const pConf) { uchar *LocalHostName = NULL; uchar *LocalDomain = NULL; uchar *LocalFQDNName; DEFiRet; assert(net.getLocalHostname != NULL); /* keep clang static analyzer silent - this IS the case */ CHKiRet(net.getLocalHostname(pConf, &LocalFQDNName)); uchar *dot = (uchar *)strstr((char *)LocalFQDNName, "."); if (dot == NULL) { CHKmalloc(LocalHostName = (uchar *)strdup((char *)LocalFQDNName)); CHKmalloc(LocalDomain = (uchar *)strdup("")); } else { const size_t lenhn = dot - LocalFQDNName; CHKmalloc(LocalHostName = (uchar *)strndup((char *)LocalFQDNName, lenhn)); CHKmalloc(LocalDomain = (uchar *)strdup((char *)dot + 1)); } glbl.SetLocalFQDNName(LocalFQDNName); glbl.SetLocalHostName(LocalHostName); glbl.SetLocalDomain(LocalDomain); glbl.GenerateLocalHostNameProperty(); LocalHostName = NULL; /* handed over */ LocalDomain = NULL; /* handed over */ finalize_it: free(LocalHostName); free(LocalDomain); RETiRet; } static void syncPidFileDir(const char *pidFilePath) { const char *slash = strrchr(pidFilePath, '/'); char *dirPath = NULL; int dirfd = -1; if (slash == NULL) { dirPath = strdup("."); } else if (slash == pidFilePath) { dirPath = strdup("/"); } else { dirPath = strndup(pidFilePath, slash - pidFilePath); } if (dirPath == NULL) { DBGPRINTF("rsyslogd: out of memory syncing pidfile directory\n"); return; } dirfd = open(dirPath, O_RDONLY | O_CLOEXEC | O_NOCTTY); if (dirfd == -1) { DBGPRINTF("rsyslogd: error opening pidfile directory '%s' for sync\n", dirPath); goto finalize_it; } if (fsync(dirfd) != 0) { DBGPRINTF("rsyslogd: error syncing pidfile directory '%s'\n", dirPath); } finalize_it: if (dirfd != -1) { close(dirfd); } free(dirPath); } static rsRetVal writePidFile(void) { FILE *fp = NULL; DEFiRet; const char *tmpPidFile = NULL; int fd = -1; if (!strcmp(PidFile, NO_PIDFILE)) { FINALIZE; } if (asprintf((char **)&tmpPidFile, "%s.tmp", PidFile) == -1) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } DBGPRINTF("rsyslogd: writing pidfile '%s'.\n", tmpPidFile); if ((fp = fopen((char *)tmpPidFile, "w")) == NULL) { perror("rsyslogd: error writing pid file (creation stage)\n"); ABORT_FINALIZE(RS_RET_ERR); } if (fprintf(fp, "%d", (int)glblGetOurPid()) < 0) { perror("rsyslogd: error writing pid file"); ABORT_FINALIZE(RS_RET_ERR); } if (fflush(fp) != 0) { perror("rsyslogd: error flushing pid file"); ABORT_FINALIZE(RS_RET_ERR); } fd = fileno(fp); if (fd == -1) { perror("rsyslogd: error obtaining pid file descriptor"); ABORT_FINALIZE(RS_RET_ERR); } if (fsync(fd) != 0) { perror("rsyslogd: error syncing pid file"); ABORT_FINALIZE(RS_RET_ERR); } if (fclose(fp) != 0) { fp = NULL; perror("rsyslogd: error closing pid file"); ABORT_FINALIZE(RS_RET_ERR); } fp = NULL; if (tmpPidFile != PidFile) { if (rename(tmpPidFile, PidFile) != 0) { perror("rsyslogd: error writing pid file (rename stage)"); ABORT_FINALIZE(RS_RET_ERR); } syncPidFileDir(PidFile); } finalize_it: if (iRet != RS_RET_OK && tmpPidFile != NULL && tmpPidFile != PidFile) { unlink(tmpPidFile); } if (fp != NULL) { fclose(fp); } if (tmpPidFile != PidFile) { free((void *)tmpPidFile); } RETiRet; } static void clearPidFile(void) { if (PidFile != NULL) { if (strcmp(PidFile, NO_PIDFILE)) { unlink(PidFile); } } } /* duplicate startup protection: check, based on pid file, if our instance * is already running. This MUST be called before we write our own pid file. */ static rsRetVal checkStartupOK(void) { FILE *fp = NULL; DEFiRet; DBGPRINTF("rsyslogd: checking if startup is ok, pidfile '%s'.\n", PidFile); if (!strcmp(PidFile, NO_PIDFILE)) { dbgprintf("no pid file shall be written, skipping check\n"); FINALIZE; } if ((fp = fopen((char *)PidFile, "r")) == NULL) FINALIZE; /* all well, no pid file yet */ int pf_pid; if (fscanf(fp, "%d", &pf_pid) != 1) { fprintf(stderr, "rsyslogd: error reading pid file, cannot start up\n"); ABORT_FINALIZE(RS_RET_ERR); } /* ok, we got a pid, let's check if the process is running */ const pid_t pid = (pid_t)pf_pid; if (kill(pid, 0) == 0 || errno != ESRCH) { fprintf(stderr, "rsyslogd: pidfile '%s' and pid %d already exist.\n" "If you want to run multiple instances of rsyslog, you need " "to specify\n" "different pid files for them (-i option).\n", PidFile, (int)getpid()); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (fp != NULL) fclose(fp); RETiRet; } /* note: this function is specific to OS'es which provide * the ability to read open file descriptors via /proc. * returns 0 - success, something else otherwise */ static int close_unneeded_open_files(const char *const procdir, const int beginClose, const int parentPipeFD) { DIR *dir; struct dirent *entry; dir = opendir(procdir); if (dir == NULL) { dbgprintf("closes unneeded files: opendir failed for %s\n", procdir); return 1; } while ((entry = readdir(dir)) != NULL) { const int fd = atoi(entry->d_name); if (fd >= beginClose && (((fd != dbgGetDbglogFd()) && (fd != parentPipeFD)))) { close(fd); } } closedir(dir); return 0; } /* prepares the background processes (if auto-backbrounding) for * operation. */ static void prepareBackground(const int parentPipeFD) { DBGPRINTF("rsyslogd: in child, finalizing initialization\n"); dbgTimeoutToStderr = 0; /* we loose stderr when backgrounding! */ int r = setsid(); if (r == -1) { char err[1024]; char em[2048]; rs_strerror_r(errno, err, sizeof(err)); snprintf(em, sizeof(em) - 1, "rsyslog: error " "auto-backgrounding: %s\n", err); dbgprintf("%s\n", em); fprintf(stderr, "%s", em); } int beginClose = 3; #ifdef HAVE_LIBSYSTEMD /* running under systemd? Then we must make sure we "forward" any * fds passed by it (adjust the pid). */ if (sd_booted()) { const char *lstnPid = getenv("LISTEN_PID"); if (lstnPid != NULL) { char szBuf[64]; const int lstnPidI = atoi(lstnPid); snprintf(szBuf, sizeof(szBuf), "%d", lstnPidI); if (!strcmp(szBuf, lstnPid) && lstnPidI == getppid()) { snprintf(szBuf, sizeof(szBuf), "%d", (int)getpid()); setenv("LISTEN_PID", szBuf, 1); /* ensure we do not close what systemd provided */ const int nFds = sd_listen_fds(0); if (nFds > 0) { beginClose = SD_LISTEN_FDS_START + nFds; } } } } #endif /* close unnecessary open files - first try to use /proc file system, * if that is not possible iterate through all potentially open file * descriptors. This can be lenghty, but in practice /proc should work * for almost all current systems, and the fallback is primarily for * Solaris and AIX, where we do expect a decent max numbers of fds. */ close(0); /* always close stdin, we do not need it */ /* try Linux, Cygwin, NetBSD */ if (close_unneeded_open_files("/proc/self/fd", beginClose, parentPipeFD) != 0) { /* try MacOS, FreeBSD */ if (close_unneeded_open_files("/proc/fd", beginClose, parentPipeFD) != 0) { /* did not work out, so let's close everything... */ int endClose = (parentPipeFD > dbgGetDbglogFd()) ? parentPipeFD : dbgGetDbglogFd(); for (int i = beginClose; i <= endClose; ++i) { if ((i != dbgGetDbglogFd()) && (i != parentPipeFD)) { aix_close_it(i); /* AIXPORT */ } } beginClose = endClose + 1; endClose = getdtablesize(); #if defined(HAVE_CLOSE_RANGE) if (close_range(beginClose, endClose, 0) != 0) { dbgprintf("errno %d after close_range(), fallback to loop\n", errno); #endif for (int i = beginClose; i <= endClose; ++i) { aix_close_it(i); /* AIXPORT */ } #if defined(HAVE_CLOSE_RANGE) } #endif } } seedRandomNumberForChild(); } /* This is called when rsyslog is set to auto-background itself. If so, a child * is forked and the parent waits until it is initialized. * The parent never returns from this function, only this happens for the child. * So if it returns, you know you are in the child. * return: file descriptor to which the child needs to write an "OK" or error * message. */ static int forkRsyslog(void) { int pipefd[2]; pid_t cpid; char err[1024]; char msgBuf[4096]; dbgprintf("rsyslogd: parent ready for forking\n"); if (pipe(pipefd) == -1) { perror("error creating rsyslog \"fork pipe\" - terminating"); exit(1); } AIX_SRC_EXISTS_IF /* AIXPORT */ cpid = fork(); if (cpid == -1) { perror("error forking rsyslogd process - terminating"); exit(1); } AIX_SRC_EXISTS_FI /* AIXPORT */ if (cpid == 0) { prepareBackground(pipefd[1]); close(pipefd[0]); return pipefd[1]; } /* we are now in the parent. All we need to do here is wait for the * startup message, emit it (if necessary) and then terminate. */ close(pipefd[1]); dbgprintf("rsyslogd: parent waiting up to 60 seconds to read startup message\n"); fd_set rfds; struct timeval tv; int retval; FD_ZERO(&rfds); FD_SET(pipefd[0], &rfds); tv.tv_sec = 60; tv.tv_usec = 0; retval = select(pipefd[0] + 1, &rfds, NULL, NULL, &tv); if (retval == -1) rs_strerror_r(errno, err, sizeof(err)); else RS_COPY_LITERAL(err, "OK"); dbgprintf("rsyslogd: select() returns %d: %s\n", retval, err); if (retval == -1) { fprintf(stderr, "rsyslog startup failure, select() failed: %s\n", err); exit(1); } else if (retval == 0) { fprintf(stderr, "rsyslog startup failure, child did not " "respond within startup timeout (60 seconds)\n"); exit(1); } int nRead = read(pipefd[0], msgBuf, sizeof(msgBuf) - 1); if (nRead > 0) { msgBuf[nRead] = '\0'; } else { rs_strerror_r(errno, err, sizeof(err)); snprintf(msgBuf, sizeof(msgBuf) - 1, "error reading \"fork pipe\": %s", err); } if (strcmp(msgBuf, "OK")) { dbgprintf("rsyslog parent startup failure: %s\n", msgBuf); fprintf(stderr, "rsyslog startup failure: %s\n", msgBuf); exit(1); } close(pipefd[0]); dbgprintf("rsyslogd: parent terminates after successful child startup\n"); exit(0); } /* startup processing: this signals the waiting parent that the child is ready * and the parent may terminate. */ static void tellChildReady(const int pipefd, const char *const msg) { dbgprintf("rsyslogd: child signaling OK\n"); const int nWritten = write(pipefd, msg, strlen(msg)); dbgprintf("rsyslogd: child signalled OK, nWritten %d\n", (int)nWritten); close(pipefd); sleep(1); } /* print version and compile-time setting information */ static void printVersion(void) { printf("rsyslogd " VERSION " (aka %4d.%2.2d) compiled with:\n", 2000 + VERSION_YEAR, VERSION_MONTH); printf("\tPLATFORM:\t\t\t\t%s\n", PLATFORM_ID); printf("\tPLATFORM (lsb_release -d):\t\t%s\n", PLATFORM_ID_LSB); #ifdef FEATURE_REGEXP printf("\tFEATURE_REGEXP:\t\t\t\tYes\n"); #else printf("\tFEATURE_REGEXP:\t\t\t\tNo\n"); #endif #if defined(SYSLOG_INET) && defined(USE_GSSAPI) printf("\tGSSAPI Kerberos 5 support:\t\tYes\n"); #else printf("\tGSSAPI Kerberos 5 support:\t\tNo\n"); #endif #ifndef NDEBUG printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n"); #else printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n"); #endif #ifdef HAVE_ATOMIC_BUILTINS printf("\t32bit Atomic operations supported:\tYes\n"); #else printf("\t32bit Atomic operations supported:\tNo\n"); #endif #ifdef HAVE_ATOMIC_BUILTINS64 printf("\t64bit Atomic operations supported:\tYes\n"); #else printf("\t64bit Atomic operations supported:\tNo\n"); #endif #ifdef HAVE_JEMALLOC printf("\tmemory allocator:\t\t\tjemalloc\n"); #else printf("\tmemory allocator:\t\t\tsystem default\n"); #endif #ifdef RTINST printf("\tRuntime Instrumentation (slow code):\tYes\n"); #else printf("\tRuntime Instrumentation (slow code):\tNo\n"); #endif #ifdef USE_LIBUUID printf("\tuuid support:\t\t\t\tYes\n"); #else printf("\tuuid support:\t\t\t\tNo\n"); #endif #ifdef HAVE_LIBSYSTEMD printf("\tsystemd support:\t\t\tYes\n"); #else printf("\tsystemd support:\t\t\tNo\n"); #endif #ifdef ENABLE_IMPSTATS_PUSH printf("\tFEATURE_IMPSTATS_PUSH:\t\t\tYes\n"); #else printf("\tFEATURE_IMPSTATS_PUSH:\t\t\tNo\n"); #endif #if defined(ENABLE_WOLFSSL) printf("\tTLS network stream driver:\t\twolfSSL\n"); #elif defined(ENABLE_OPENSSL) printf("\tTLS network stream driver:\t\tOpenSSL\n"); #elif defined(ENABLE_GNUTLS) printf("\tTLS network stream driver:\t\tGnuTLS\n"); #elif defined(ENABLE_MBEDTLS) printf("\tTLS network stream driver:\t\tMbed TLS\n"); #else printf("\tTLS network stream driver:\t\tnone\n"); #endif /* we keep the following message to so that users don't need * to wonder. */ printf("\tConfig file:\t\t\t\t" PATH_CONFFILE "\n"); printf("\tPID file:\t\t\t\t" PATH_PIDFILE "%s\n", PATH_PIDFILE[0] != '/' ? "(relative to global workingdirectory)" : ""); printf("\tNumber of Bits in RainerScript integers: 64\n"); printf("\nSee https://www.rsyslog.com for more information.\n"); } static rsRetVal rsyslogd_InitStdRatelimiters(void) { DEFiRet; CHKiRet(ratelimitNew(&dflt_ratelimiter, "rsyslogd", "dflt")); CHKiRet(ratelimitNew(&internalMsg_ratelimiter, "rsyslogd", "internal_messages")); ratelimitSetThreadSafe(internalMsg_ratelimiter); ratelimitSetLinuxLike(internalMsg_ratelimiter, loadConf->globals.intMsgRateLimitItv, loadConf->globals.intMsgRateLimitBurst); /* TODO: make internalMsg ratelimit settings configurable */ finalize_it: RETiRet; } /* Method to initialize all global classes and use the objects that we need. * rgerhards, 2008-01-04 * rgerhards, 2008-04-16: the actual initialization is now carried out by the runtime */ static rsRetVal rsyslogd_InitGlobalClasses(void) { DEFiRet; const char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */ /* Intialize the runtime system */ pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */ CHKiRet(rsrtInit(&pErrObj, &obj)); rsrtSetErrLogger(rsyslogd_submitErrMsg); /* Now tell the system which classes we need ourselfs */ pErrObj = "glbl"; CHKiRet(objUse(glbl, CORE_COMPONENT)); pErrObj = "module"; CHKiRet(objUse(module, CORE_COMPONENT)); pErrObj = "datetime"; CHKiRet(objUse(datetime, CORE_COMPONENT)); pErrObj = "ruleset"; CHKiRet(objUse(ruleset, CORE_COMPONENT)); pErrObj = "prop"; CHKiRet(objUse(prop, CORE_COMPONENT)); pErrObj = "parser"; CHKiRet(objUse(parser, CORE_COMPONENT)); pErrObj = "rsconf"; CHKiRet(objUse(rsconf, CORE_COMPONENT)); /* initialize some dummy classes that are not part of the runtime */ pErrObj = "action"; CHKiRet(actionClassInit()); pErrObj = "template"; CHKiRet(templateInit()); /* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */ pErrObj = "net"; CHKiRet(objUse(net, LM_NET_FILENAME)); dnscacheInit(); initRainerscript(); ratelimitModInit(); /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInternalInputName)); CHKiRet(prop.SetString(pInternalInputName, UCHAR_CONSTANT("rsyslogd"), sizeof("rsyslogd") - 1)); CHKiRet(prop.ConstructFinalize(pInternalInputName)); finalize_it: if (iRet != RS_RET_OK) { /* we know we are inside the init sequence, so we can safely emit * messages to stderr. -- rgerhards, 2008-04-02 */ fprintf(stderr, "Error during class init for object '%s' - failing...\n", pErrObj); fprintf(stderr, "rsyslogd initialization failed - global classes could not be initialized.\n" "Did you do a \"make install\"?\n" "Suggested action: run rsyslogd with -d -n options to see what exactly " "fails.\n"); } RETiRet; } /* preprocess a batch of messages, that is ready them for actual processing. This is done * as a first stage and totally in parallel to any other worker active in the system. So * it helps us keep up the overall concurrency level. * rgerhards, 2010-06-09 */ static rsRetVal preprocessBatch(batch_t *pBatch, wti_t *pWti) { prop_t *ip; prop_t *fqdn; prop_t *localName; int bIsPermitted; smsg_t *pMsg; int i; rsRetVal localRet; DEFiRet; for (i = 0; i < pBatch->nElem && !wtiIsShutdownImmediate(pWti); i++) { pMsg = pBatch->pElem[i].pMsg; if ((pMsg->msgFlags & NEEDS_ACLCHK_U) != 0) { DBGPRINTF("msgConsumer: UDP ACL must be checked for message (hostname-based)\n"); if (net.cvthname(pMsg->rcvFrom.pfrominet, &localName, &fqdn, &ip) != RS_RET_OK) continue; bIsPermitted = net.isAllowedSender2((uchar *)"UDP", (struct sockaddr *)pMsg->rcvFrom.pfrominet, (char *)propGetSzStr(fqdn), 1); if (!bIsPermitted) { DBGPRINTF("Message from '%s' discarded, not a permitted sender host\n", propGetSzStr(fqdn)); pBatch->eltState[i] = BATCH_STATE_DISC; } else { /* save some of the info we obtained */ MsgSetRcvFrom(pMsg, localName); CHKiRet(MsgSetRcvFromIP(pMsg, ip)); pMsg->msgFlags &= ~NEEDS_ACLCHK_U; } } if ((pMsg->msgFlags & NEEDS_PARSING) != 0) { if ((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK) { DBGPRINTF("Message discarded, parsing error %d\n", localRet); pBatch->eltState[i] = BATCH_STATE_DISC; } } } finalize_it: RETiRet; } /** * @brief Message Consumer (Worker Thread). * * This function runs on a **separate thread** as part of the Queue Worker Pool. * It consumes a batch of messages dequeued from the main message queue. * * @note No further batching is performed here, as optimization happens in `preprocessBatch`. * * @param notNeeded Unused argument (required for thread signature). * @param pBatch Pointer to the batch of messages to process. * @param pWti Pointer to the Worker Thread Instance (WTI) data. * @return RS_RET_OK on success. */ static rsRetVal msgConsumer(void __attribute__((unused)) * notNeeded, batch_t *pBatch, wti_t *pWti) { DEFiRet; assert(pBatch != NULL); preprocessBatch(pBatch, pWti); ruleset.ProcessBatch(pBatch, pWti); // TODO: the BATCH_STATE_COMM must be set somewhere down the road, but we // do not have this yet and so we emulate -- 2010-06-10 int i; for (i = 0; i < pBatch->nElem && !wtiIsShutdownImmediate(pWti); i++) { pBatch->eltState[i] = BATCH_STATE_COMM; } RETiRet; } /* create a main message queue, now also used for ruleset queues. This function * needs to be moved to some other module, but it is considered acceptable for * the time being (remember that we want to restructure config processing at large!). * rgerhards, 2009-10-27 */ rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName, struct nvlst *lst) { struct queuefilenames_s *qfn; uchar *qfname = NULL; uchar *queueName = pszQueueName; uchar *queueNameOverride = NULL; static int qfn_renamenum = 0; uchar qfrenamebuf[1024]; DEFiRet; if (lst != NULL) { static struct cnfparamdescr mainqdescr[] = {{"name", eCmdHdlrString, 0}}; static struct cnfparamblk mainqpblk = {CNFPARAMBLK_VERSION, sizeof(mainqdescr) / sizeof(mainqdescr[0]), mainqdescr}; struct cnfparamvals *pvals; int nameIdx; pvals = nvlstGetParams(lst, &mainqpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } nameIdx = cnfparamGetIdx(&mainqpblk, "name"); if (nameIdx != -1 && pvals[nameIdx].bUsed) { queueNameOverride = (uchar *)es_str2cstr(pvals[nameIdx].val.d.estr, NULL); if (queueNameOverride != NULL && queueNameOverride[0] != '\0') { queueName = queueNameOverride; } } cnfparamvalsDestruct(pvals, &mainqpblk); } /* create message queue */ CHKiRet_Hdlr(qqueueConstruct(ppQueue, ourConf->globals.mainQ.MainMsgQueType, ourConf->globals.mainQ.iMainMsgQueueNumWorkers, ourConf->globals.mainQ.iMainMsgQueueSize, msgConsumer)) { /* no queue is fatal, we need to give up in that case... */ LogError(0, iRet, "could not create (ruleset) main message queue"); } /* name our main queue object (it's not fatal if it fails...) */ obj.SetName((obj_t *)(*ppQueue), queueName); if (lst == NULL) { /* use legacy parameters? */ /* ... set some properties ... */ #define setQPROP(func, directive, data) \ CHKiRet_Hdlr(func(*ppQueue, data)) { \ LogError(0, NO_ERRCODE, \ "Invalid " #directive \ ", error %d. Ignored, " \ "running with default setting", \ iRet); \ } #define setQPROPstr(func, directive, data) \ CHKiRet_Hdlr(func(*ppQueue, data, (data == NULL) ? 0 : strlen((char *)data))) { \ LogError(0, NO_ERRCODE, \ "Invalid " #directive \ ", error %d. Ignored, " \ "running with default setting", \ iRet); \ } if (ourConf->globals.mainQ.pszMainMsgQFName != NULL) { /* check if the queue file name is unique, else emit an error */ for (qfn = queuefilenames; qfn != NULL; qfn = qfn->next) { dbgprintf("check queue file name '%s' vs '%s'\n", qfn->name, ourConf->globals.mainQ.pszMainMsgQFName); if (!ustrcmp(qfn->name, ourConf->globals.mainQ.pszMainMsgQFName)) { snprintf((char *)qfrenamebuf, sizeof(qfrenamebuf), "%d-%s-%s", ++qfn_renamenum, ourConf->globals.mainQ.pszMainMsgQFName, (queueName == NULL) ? "NONAME" : (char *)queueName); qfname = ustrdup(qfrenamebuf); LogError(0, NO_ERRCODE, "Error: queue file name '%s' already in use " " - using '%s' instead", ourConf->globals.mainQ.pszMainMsgQFName, qfname); break; } } if (qfname == NULL) qfname = ustrdup(ourConf->globals.mainQ.pszMainMsgQFName); qfn = malloc(sizeof(struct queuefilenames_s)); qfn->name = qfname; qfn->next = queuefilenames; queuefilenames = qfn; } setQPROP(qqueueSetMaxFileSize, "$MainMsgQueueFileSize", ourConf->globals.mainQ.iMainMsgQueMaxFileSize); setQPROP(qqueueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", ourConf->globals.mainQ.iMainMsgQueMaxDiskSpace); setQPROP(qqueueSetiDeqBatchSize, "$MainMsgQueueDequeueBatchSize", ourConf->globals.mainQ.iMainMsgQueDeqBatchSize); setQPROPstr(qqueueSetFilePrefix, "$MainMsgQueueFileName", qfname); setQPROP(qqueueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", ourConf->globals.mainQ.iMainMsgQPersistUpdCnt); setQPROP(qqueueSetbSyncQueueFiles, "$MainMsgQueueSyncQueueFiles", ourConf->globals.mainQ.bMainMsgQSyncQeueFiles); setQPROP(qqueueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", ourConf->globals.mainQ.iMainMsgQtoQShutdown); setQPROP(qqueueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion", ourConf->globals.mainQ.iMainMsgQtoActShutdown); setQPROP(qqueueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown", ourConf->globals.mainQ.iMainMsgQtoWrkShutdown); setQPROP(qqueueSettoEnq, "$MainMsgQueueTimeoutEnqueue", ourConf->globals.mainQ.iMainMsgQtoEnq); setQPROP(qqueueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark", ourConf->globals.mainQ.iMainMsgQHighWtrMark); setQPROP(qqueueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark", ourConf->globals.mainQ.iMainMsgQLowWtrMark); setQPROP(qqueueSetiDiscardMrk, "$MainMsgQueueDiscardMark", ourConf->globals.mainQ.iMainMsgQDiscardMark); setQPROP(qqueueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity", ourConf->globals.mainQ.iMainMsgQDiscardSeverity); setQPROP(qqueueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", ourConf->globals.mainQ.iMainMsgQWrkMinMsgs); setQPROP(qqueueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", ourConf->globals.mainQ.bMainMsgQSaveOnShutdown); setQPROP(qqueueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", ourConf->globals.mainQ.iMainMsgQDeqSlowdown); setQPROP(qqueueSetiDeqtWinFromHr, "$MainMsgQueueDequeueTimeBegin", ourConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr); setQPROP(qqueueSetiDeqtWinToHr, "$MainMsgQueueDequeueTimeEnd", ourConf->globals.mainQ.iMainMsgQueueDeqtWinToHr); #undef setQPROP #undef setQPROPstr } else { /* use new style config! */ qqueueSetDefaultsRulesetQueue(*ppQueue); qqueueApplyCnfParam(*ppQueue, lst); } qqueueCorrectParams(*ppQueue); finalize_it: free(queueNameOverride); RETiRet; } rsRetVal startMainQueue(rsconf_t *cnf, qqueue_t *const pQueue) { DEFiRet; CHKiRet_Hdlr(qqueueStart(cnf, pQueue)) { /* no queue is fatal, we need to give up in that case... */ LogError(0, iRet, "could not start (ruleset) main message queue"); if (runConf->globals.bAbortOnFailedQueueStartup) { fprintf(stderr, "rsyslogd: could not start (ruleset) main message queue, " "abortOnFailedQueueStartup is set, so we abort rsyslog now.\n"); fflush(stderr); clearPidFile(); exit(1); /* "good" exit, this is intended here */ } pQueue->qType = QUEUETYPE_DIRECT; CHKiRet_Hdlr(qqueueStart(cnf, pQueue)) { /* no queue is fatal, we need to give up in that case... */ LogError(0, iRet, "fatal error: could not even start queue in direct mode"); } } RETiRet; } /* this is a special function used to submit an error message. This * function is also passed to the runtime library as the generic error * message handler. -- rgerhards, 2008-04-17 */ void rsyslogd_submitErrMsg(const int severity, const int iErr, const uchar *msg) { if (glbl.GetGlobalInputTermState() == 1) { /* After fork the stderr is unusable (dfltErrLogger uses is internally) */ if (!doFork) dfltErrLogger(severity, iErr, msg); } else { logmsgInternal(iErr, LOG_SYSLOG | (severity & 0x07), msg, 0); } } static inline rsRetVal submitMsgWithDfltRatelimiter(smsg_t *pMsg) { return ratelimitAddMsg(dflt_ratelimiter, NULL, pMsg); } static void logmsgInternal_doWrite(smsg_t *pMsg) { const int pri = getPRIi(pMsg); if (pri % 8 <= runConf->globals.intMsgsSeverityFilter) { if (runConf->globals.bProcessInternalMessages) { submitMsg2(pMsg); pMsg = NULL; /* msg obj handed over; do not destruct */ } else { uchar *const msg = getMSG(pMsg); #ifdef ENABLE_LIBLOGGING_STDLOG /* the "emit only once" rate limiter is quick and dirty and not * thread safe. However, that's no problem for the current intend * and it is not justified to create more robust code for the * functionality. -- rgerhards, 2018-05-14 */ static warnmsg_emitted = 0; if (warnmsg_emitted == 0) { stdlog_log(runConf->globals.stdlog_hdl, LOG_WARNING, "%s", "RSYSLOG WARNING: liblogging-stdlog " "functionality will go away soon. For details see " "https://github.com/rsyslog/rsyslog/issues/2706"); warnmsg_emitted = 1; } stdlog_log(runConf->globals.stdlog_hdl, pri2sev(pri), "%s", (char *)msg); #else syslog(pri, "%s", msg); #endif } } if (pMsg != NULL) { msgDestruct(&pMsg); } } /* This function creates a log message object out of the provided * message text and forwards it for logging. */ static rsRetVal logmsgInternalSubmit( const int iErr, const syslog_pri_t pri, const size_t lenMsg, const char *__restrict__ const msg, int flags) { uchar pszTag[33]; smsg_t *pMsg; DEFiRet; if (glblAbortOnProgramError && iErr == RS_RET_PROGRAM_ERROR) { fprintf(stderr, "\n\n\n========================================\n" "rsyslog reports program error: %s\n" "rsyslog is configured to abort in this case, " "this will be done now\n", msg); fflush(stdout); abort(); } CHKiRet(msgConstruct(&pMsg)); MsgSetInputName(pMsg, pInternalInputName); MsgSetRawMsg(pMsg, (char *)msg, lenMsg); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP()); MsgSetMSGoffs(pMsg, 0); /* check if we have an error code associated and, if so, * adjust the tag. -- rgerhards, 2008-06-27 */ if (iErr == NO_ERRCODE) { MsgSetTAG(pMsg, UCHAR_CONSTANT("rsyslogd:"), sizeof("rsyslogd:") - 1); } else { size_t len = snprintf((char *)pszTag, sizeof(pszTag), "rsyslogd%d:", iErr); pszTag[32] = '\0'; /* just to make sure... */ MsgSetTAG(pMsg, pszTag, len); } flags |= INTERNAL_MSG; pMsg->msgFlags = flags; msgSetPRI(pMsg, pri); iminternalAddMsg(pMsg); finalize_it: RETiRet; } /* rgerhards 2004-11-09: the following is a function that can be used * to log a message orginating from the syslogd itself. */ rsRetVal logmsgInternal(int iErr, const syslog_pri_t pri, const uchar *const msg, int flags) { size_t lenMsg; unsigned i; char *bufModMsg = NULL; /* buffer for modified message, should we need to modify */ DEFiRet; /* we first do a path the remove control characters that may have accidently * introduced (program error!). This costs performance, but we do not expect * to be called very frequently in any case ;) -- rgerhards, 2013-12-19. */ lenMsg = ustrlen(msg); for (i = 0; i < lenMsg; ++i) { if (msg[i] < 0x20 || msg[i] == 0x7f) { if (bufModMsg == NULL) { CHKmalloc(bufModMsg = strdup((char *)msg)); } bufModMsg[i] = ' '; } } CHKiRet(logmsgInternalSubmit(iErr, pri, lenMsg, (bufModMsg == NULL) ? (char *)msg : bufModMsg, flags)); /* we now check if we should print internal messages out to stderr. This was * suggested by HKS as a way to help people troubleshoot rsyslog configuration * (by running it interactively. This makes an awful lot of sense, so I add * it here. -- rgerhards, 2008-07-28 * Note that error messages can not be disabled during a config verify. This * permits us to process unmodified config files which otherwise contain a * supressor statement. */ int emit_to_stderr = (ourConf == NULL) ? 1 : (ourConf->globals.bErrMsgToStderr || ourConf->globals.bAllMsgToStderr); int emit_supress_msg = 0; if (Debug == DEBUG_FULL || !doFork) { emit_to_stderr = 1; } if (ourConf != NULL && ourConf->globals.maxErrMsgToStderr != -1) { if (emit_to_stderr && ourConf->globals.maxErrMsgToStderr != -1 && ourConf->globals.maxErrMsgToStderr) { --ourConf->globals.maxErrMsgToStderr; if (ourConf->globals.maxErrMsgToStderr == 0) emit_supress_msg = 1; } else { emit_to_stderr = 0; } } if (emit_to_stderr || iConfigVerify) { if ((ourConf != NULL && ourConf->globals.bAllMsgToStderr) || pri2sev(pri) == LOG_ERR || (iConfigVerify && pri2sev(pri) <= LOG_WARNING)) fprintf(stderr, "rsyslogd: %s\n", (bufModMsg == NULL) ? (char *)msg : bufModMsg); } if (emit_supress_msg) { fprintf(stderr, "rsyslogd: configured max number of error messages " "to stderr reached, further messages will not be output\n" "Consider adjusting\n" " global(errorMessagesToStderr.maxNumber=\"xx\")\n" "if you want more.\n"); } finalize_it: free(bufModMsg); RETiRet; } rsRetVal submitMsg(smsg_t *pMsg) { return submitMsgWithDfltRatelimiter(pMsg); } static rsRetVal ATTR_NONNULL() splitOversizeMessage(smsg_t *const pMsg) { DEFiRet; const char *rawmsg; int nsegments; int len_rawmsg; const int maxlen = glblGetMaxLine(runConf); ISOBJ_TYPE_assert(pMsg, msg); getRawMsg(pMsg, (uchar **)&rawmsg, &len_rawmsg); nsegments = len_rawmsg / maxlen; const int len_last_segment = len_rawmsg % maxlen; DBGPRINTF( "splitting oversize message, size %d, segment size %d, " "nsegments %d, bytes in last fragment %d\n", len_rawmsg, maxlen, nsegments, len_last_segment); smsg_t *pMsg_seg; /* process full segments */ for (int i = 0; i < nsegments; ++i) { CHKmalloc(pMsg_seg = MsgDup(pMsg)); MsgSetRawMsg(pMsg_seg, rawmsg + (i * maxlen), maxlen); submitMsg2(pMsg_seg); } /* if necessary, write partial last segment */ if (len_last_segment != 0) { CHKmalloc(pMsg_seg = MsgDup(pMsg)); MsgSetRawMsg(pMsg_seg, rawmsg + (nsegments * maxlen), len_last_segment); submitMsg2(pMsg_seg); } finalize_it: RETiRet; } /** * @brief Submit a message to the Main Message Queue (Wrapper). * * A helper function that abstracts the main message queue details from callers. * It is commonly used by plugins to inject messages into the processing pipeline. * * @param pMsg The message object to submit. * @return RS_RET_OK on success. */ rsRetVal submitMsg2(smsg_t *pMsg) { qqueue_t *pQueue; ruleset_t *pRuleset; DEFiRet; ISOBJ_TYPE_assert(pMsg, msg); if (getRawMsgLen(pMsg) > glblGetMaxLine(runConf)) { uchar *rawmsg; int dummy; getRawMsg(pMsg, &rawmsg, &dummy); if (glblReportOversizeMessage(runConf)) { LogMsg(0, RS_RET_OVERSIZE_MSG, LOG_WARNING, "message too long (%d) with configured size %d, begin of " "message is: %.80s", getRawMsgLen(pMsg), glblGetMaxLine(runConf), rawmsg); } writeOversizeMessageLog(pMsg); if (glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Split) { splitOversizeMessage(pMsg); /* we have submitted the message segments recursively, so we * can just deleted the original msg object and terminate. */ msgDestruct(&pMsg); FINALIZE; } else if (glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Truncate) { MsgTruncateToMaxSize(pMsg); } else { /* in "accept" mode, we do nothing, simply because "accept" means * to use as-is. */ assert(glblGetOversizeMsgInputMode(runConf) == glblOversizeMsgInputMode_Accept); } } pRuleset = MsgGetRuleset(pMsg); assert(ruleset.GetRulesetQueue != NULL); /* This is only to keep clang static analyzer happy */ pQueue = (pRuleset == NULL) ? runConf->pMsgQueue : ruleset.GetRulesetQueue(pRuleset); /* if a plugin logs a message during shutdown, the queue may no longer exist */ if (pQueue == NULL) { DBGPRINTF( "submitMsg2() could not submit message - " "queue does (no longer?) exist - ignored\n"); FINALIZE; } qqueueEnqMsg(pQueue, pMsg->flowCtlType, pMsg); finalize_it: RETiRet; } /* submit multiple messages at once, very similar to submitMsg, just * for multi_submit_t. All messages need to go into the SAME queue! * rgerhards, 2009-06-16 */ rsRetVal ATTR_NONNULL() multiSubmitMsg2(multi_submit_t *const pMultiSub) { qqueue_t *pQueue; ruleset_t *pRuleset; DEFiRet; if (pMultiSub->nElem == 0) FINALIZE; pRuleset = MsgGetRuleset(pMultiSub->ppMsgs[0]); pQueue = (pRuleset == NULL) ? runConf->pMsgQueue : ruleset.GetRulesetQueue(pRuleset); /* if a plugin logs a message during shutdown, the queue may no longer exist */ if (pQueue == NULL) { DBGPRINTF( "multiSubmitMsg() could not submit message - " "queue does (no longer?) exist - ignored\n"); FINALIZE; } iRet = pQueue->MultiEnq(pQueue, pMultiSub); pMultiSub->nElem = 0; finalize_it: RETiRet; } rsRetVal multiSubmitMsg(multi_submit_t *pMultiSub) /* backward compat. level */ { return multiSubmitMsg2(pMultiSub); } /* flush multiSubmit, e.g. at end of read records */ rsRetVal multiSubmitFlush(multi_submit_t *pMultiSub) { DEFiRet; if (pMultiSub->nElem > 0) { iRet = multiSubmitMsg2(pMultiSub); } RETiRet; } /* some support for command line option parsing. Any non-trivial options must be * buffered until the complete command line has been parsed. This is necessary to * prevent dependencies between the options. That, in turn, means we need to have * something that is capable of buffering options and there values. The follwing * functions handle that. * rgerhards, 2008-04-04 */ typedef struct bufOpt { struct bufOpt *pNext; char optchar; char *arg; } bufOpt_t; static bufOpt_t *bufOptRoot = NULL; static bufOpt_t *bufOptLast = NULL; /* add option buffer */ static rsRetVal bufOptAdd(char opt, char *arg) { DEFiRet; bufOpt_t *pBuf; if ((pBuf = malloc(sizeof(bufOpt_t))) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); pBuf->optchar = opt; pBuf->arg = arg; pBuf->pNext = NULL; if (bufOptLast == NULL) { bufOptRoot = pBuf; /* then there is also no root! */ } else { bufOptLast->pNext = pBuf; } bufOptLast = pBuf; finalize_it: RETiRet; } /* remove option buffer from top of list, return values and destruct buffer itself. * returns RS_RET_END_OF_LINKEDLIST when no more options are present. * (we use int *opt instead of char *opt to keep consistent with getopt()) */ static rsRetVal bufOptRemove(int *opt, char **arg) { DEFiRet; bufOpt_t *pBuf; if (bufOptRoot == NULL) ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST); pBuf = bufOptRoot; *opt = pBuf->optchar; *arg = pBuf->arg; bufOptRoot = pBuf->pNext; free(pBuf); finalize_it: RETiRet; } static void hdlr_sigttin_ou(void) { /* this is just a dummy to care for our sigttin input * module cancel interface and sigttou internal message * notificaton/mainloop wakeup mechanism. The important * point is that it actually does *NOTHING*. */ } static void hdlr_enable(int sig, void (*hdlr)()) { struct sigaction sigAct; memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = hdlr; sigaction(sig, &sigAct, NULL); } static void hdlr_sighup(void) { PREFER_STORE_INT(&bHadHUP, 1); /* at least on FreeBSD we seem not to necessarily awake the main thread. * So let's do it explicitely. */ dbgprintf("awaking mainthread on HUP\n"); pthread_kill(mainthread, SIGTTIN); } static void hdlr_sigchld(void) { PREFER_STORE_INT(&bChildDied, 1); } static void rsyslogdDebugSwitch(void) { time_t tTime; struct tm tp; datetime.GetTime(&tTime); localtime_r(&tTime, &tp); if (debugging_on == 0) { debugging_on = 1; dbgprintf("\n"); dbgprintf("\n"); dbgprintf("********************************************************************************\n"); dbgprintf("Switching debugging_on to true at %2.2d:%2.2d:%2.2d\n", tp.tm_hour, tp.tm_min, tp.tm_sec); dbgprintf("********************************************************************************\n"); } else { dbgprintf("********************************************************************************\n"); dbgprintf("Switching debugging_on to false at %2.2d:%2.2d:%2.2d\n", tp.tm_hour, tp.tm_min, tp.tm_sec); dbgprintf("********************************************************************************\n"); dbgprintf("\n"); dbgprintf("\n"); debugging_on = 0; } } /* This is the main entry point into rsyslogd. Over time, we should try to * modularize it a bit more... * * NOTE on stderr and stdout: they are kept open during a fork. Note that this * may introduce subtle security issues: if we are in a jail, one may break out of * it via these descriptors. But if I close them earlier, error messages will (once * again) not be emitted to the user that starts the daemon. Given that the risk * of a break-in is very low in the startup phase, we decide it is more important * to emit error messages. */ static void initAll(int argc, char **argv) { rsRetVal localRet; int ch; int iHelperUOpt; int bChDirRoot = 1; /* change the current working directory to "/"? */ char *arg; /* for command line option processing */ char *configOutputPath = NULL; enum rsconfTranslateFormat iTranslateFmt = RSCONF_TRANSLATE_NONE; char cwdbuf[128]; /* buffer to obtain/display current working directory */ int parentPipeFD = 0; /* fd of pipe to parent, if auto-backgrounding */ DEFiRet; /* prepare internal signaling */ hdlr_enable(SIGTTIN, hdlr_sigttin_ou); hdlr_enable(SIGTTOU, hdlr_sigttin_ou); /* * Command-line option parser (Pass 1). * * Parses command-line options to determine the operating mode and set initial flags. * * This block implements a "two-pass" strategy: * 1. Immediate flags: Options like debug (`-d`) or no-fork (`-n`) are set immediately. * 2. Deferred arguments: Complex options are buffered into a list (`bufOptAdd`) * to be processed later by `processStartupOptions`. * * This separation allows rsyslog to set up the runtime environment (like debug logging) * before processing complex configurations that might depend on it. */ #if defined(_AIX) while ((ch = getopt(argc, argv, "46ACDdf:F:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) { #else while ((ch = getopt(argc, argv, "46ACDdf:F:hi:M:nN:o:qQS:T:u:vwx")) != EOF) { #endif switch ((char)ch) { case '4': case '6': case 'A': case 'f': /* configuration file */ case 'F': /* translation output format */ case 'i': /* pid file name */ case 'n': /* don't fork */ case 'N': /* enable config verify mode */ case 'q': /* add hostname if DNS resolving has failed */ case 'Q': /* dont resolve hostnames in ACL to IPs */ case 'S': /* Source IP for local client to be used on multihomed host */ case 'T': /* chroot on startup (primarily for testing) */ case 'u': /* misc user settings */ case 'w': /* disable disallowed host warnings */ case 'C': case 'o': /* write output config file */ case 'x': /* disable dns for remote messages */ CHKiRet(bufOptAdd(ch, optarg)); break; #if defined(_AIX) case 'R': /* This option is a no-op for AIX */ break; #endif case 'd': /* debug - must be handled now, so that debug is active during init! */ debugging_on = 1; Debug = 1; yydebug = 1; break; case 'D': /* BISON debug */ yydebug = 1; break; case 'M': /* default module load path -- this MUST be carried out immediately! */ glblModPath = (uchar *)optarg; break; case 'v': /* MUST be carried out immediately! */ printVersion(); exit(0); /* exit for -v option - so this is a "good one" */ case 'h': case '?': default: rsyslogd_usage(); } } if (argc - optind) rsyslogd_usage(); DBGPRINTF("rsyslogd %s startup, module path '%s', cwd:%s\n", VERSION, glblModPath == NULL ? "" : (char *)glblModPath, getcwd(cwdbuf, sizeof(cwdbuf))); /* we are done with the initial option parsing and processing. Now we init the system. */ CHKiRet(rsyslogd_InitGlobalClasses()); /* doing some core initializations */ if ((iRet = modInitIminternal()) != RS_RET_OK) { fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n", iRet); exit(1); /* "good" exit, leaving at init for fatal error */ } /* we now can emit error messages "the regular way" */ if (getenv("TZ") == NULL) { const char *const tz = (access("/etc/localtime", R_OK) == 0) ? "TZ=/etc/localtime" : "TZ=UTC"; putenv((char *)tz); if (emitTZWarning) { LogMsg(0, RS_RET_NO_TZ_SET, LOG_WARNING, "environment variable TZ is not " "set, auto correcting this to %s", tz); } else { dbgprintf("environment variable TZ is not set, auto correcting this to %s\n", tz); } } /* END core initializations - we now come back to carrying out command line options*/ while ((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) { DBGPRINTF("deque option %c, optarg '%s'\n", ch, (arg == NULL) ? "" : arg); switch ((char)ch) { case '4': fprintf(stderr, "rsyslogd: the -4 command line option has gone away.\n" "Please use the global(net.ipprotocol=\"ipv4-only\") " "configuration parameter instead.\n"); break; case '6': fprintf(stderr, "rsyslogd: the -6 command line option will has gone away.\n" "Please use the global(net.ipprotocol=\"ipv6-only\") " "configuration parameter instead.\n"); break; case 'A': fprintf(stderr, "rsyslogd: the -A command line option will go away " "soon.\n" "Please use the omfwd parameter \"upd.sendToAll\" instead.\n"); send_to_all++; break; case 'S': /* Source IP for local client to be used on multihomed host */ fprintf(stderr, "rsyslogd: the -S command line option will go away " "soon.\n" "Please use the omrelp parameter \"localClientIP\" instead.\n"); if (glbl.GetSourceIPofLocalClient() != NULL) { fprintf(stderr, "rsyslogd: Only one -S argument allowed, the first one is taken.\n"); } else { glbl.SetSourceIPofLocalClient((uchar *)arg); } break; case 'f': /* configuration file */ ConfFile = (uchar *)arg; break; case 'i': /* pid file name */ free((void *)PidFile); PidFile = arg; break; case 'n': /* don't fork */ doFork = 0; break; case 'N': /* enable config verify mode */ iConfigVerify = (arg == NULL) ? 0 : atoi(arg); break; case 'F': if (arg == NULL) { fprintf(stderr, "rsyslogd: -F requires a format argument\n"); exit(1); } if (!strcasecmp(arg, "yaml")) { iTranslateFmt = RSCONF_TRANSLATE_YAML; } else if (!strcasecmp(arg, "rainerscript")) { iTranslateFmt = RSCONF_TRANSLATE_RAINERSCRIPT; } else { fprintf(stderr, "rsyslogd: unsupported translation format '%s'\n", arg); exit(1); } break; case 'o': if (configOutputPath != NULL) { fprintf(stderr, "warning: -o option given multiple times. Now using value %s\n", (arg == NULL) ? "-" : arg); } configOutputPath = arg; arg = NULL; break; case 'q': /* add hostname if DNS resolving has failed */ fprintf(stderr, "rsyslogd: the -q command line option has gone away.\n" "Please use the global(net.aclAddHostnameOnFail=\"on\") " "configuration parameter instead.\n"); break; case 'Q': /* dont resolve hostnames in ACL to IPs */ fprintf(stderr, "rsyslogd: the -Q command line option has gone away.\n" "Please use the global(net.aclResolveHostname=\"off\") " "configuration parameter instead.\n"); break; case 'T': /* chroot() immediately at program startup, but only for testing, NOT security yet */ if (arg == NULL) { /* note this case should already be handled by getopt, * but we want to keep the static analyzer happy. */ fprintf(stderr, "-T options needs a parameter\n"); exit(1); } if (chroot(arg) != 0) { perror("chroot"); exit(1); } if (chdir("/") != 0) { perror("chdir"); exit(1); } break; case 'u': /* misc user settings */ iHelperUOpt = (arg == NULL) ? 0 : atoi(arg); if (iHelperUOpt & 0x01) { fprintf(stderr, "rsyslogd: the -u command line option has gone away.\n" "For the 0x01 bit, please use the " "global(parser.parseHostnameAndTag=\"off\") " "configuration parameter instead.\n"); } if (iHelperUOpt & 0x02) { fprintf(stderr, "rsyslogd: the -u command line option will go away " "soon.\n" "For the 0x02 bit, please use the -C option instead."); bChDirRoot = 0; } break; case 'C': bChDirRoot = 0; break; case 'w': /* disable disallowed host warnigs */ fprintf(stderr, "rsyslogd: the -w command line option has gone away.\n" "Please use the global(net.permitWarning=\"off\") " "configuration parameter instead.\n"); break; case 'x': /* disable dns for remote messages */ fprintf(stderr, "rsyslogd: the -x command line option has gone away.\n" "Please use the global(net.enableDNS=\"off\") " "configuration parameter instead.\n"); break; case 'h': case '?': default: rsyslogd_usage(); } } if (iRet != RS_RET_END_OF_LINKEDLIST) FINALIZE; CHKiRet(checkConfigOutputDoesNotOverwriteInput(configOutputPath, (const char *)ConfFile)); if (iTranslateFmt != RSCONF_TRANSLATE_NONE) { if (!iConfigVerify) { fprintf(stderr, "rsyslogd: -F requires -N1 config validation mode\n"); ABORT_FINALIZE(RS_RET_ERR); } if (configOutputPath == NULL) { fprintf(stderr, "rsyslogd: -F requires -o \n"); ABORT_FINALIZE(RS_RET_ERR); } rsconfTranslateConfigure(iTranslateFmt); } else if (configOutputPath != NULL) { if (!strcmp(configOutputPath, "-")) { fp_rs_full_conf_output = stdout; } else { fp_rs_full_conf_output = fopen(configOutputPath, "w"); } if (fp_rs_full_conf_output == NULL) { perror(configOutputPath); fprintf(stderr, "rsyslogd: cannot open config output file %s - -o option will be ignored\n", configOutputPath); } else { time_t tTime; struct tm tp; datetime.GetTime(&tTime); localtime_r(&tTime, &tp); fprintf(fp_rs_full_conf_output, "## full conf created by rsyslog version %s at " "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d ##\n", VERSION, tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday, tp.tm_hour, tp.tm_min, tp.tm_sec); } } if (iConfigVerify) { doFork = 0; fprintf(stderr, "rsyslogd: version %s, config validation run (level %d), master config %s\n", VERSION, iConfigVerify, ConfFile); } resetErrMsgsFlag(); localRet = rsconf.Load(&ourConf, ConfFile); #ifdef ENABLE_LIBCAPNG if (loadConf->globals.bCapabilityDropEnabled) { /* * Drop capabilities to the necessary set */ int capng_rc, capng_failed = 0; typedef struct capabilities_s { int capability; /* capability code */ const char *name; /* name of the capability to be displayed */ /* is the capability present that is needed by rsyslog? if so we do not drop it */ sbool present; capng_type_t type; } capabilities_t; // clang-format off capabilities_t capabilities[] = { { CAP_BLOCK_SUSPEND, "CAP_BLOCK_SUSPEND", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_NET_RAW, "CAP_NET_RAW", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_CHOWN, "CAP_CHOWN", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_LEASE, "CAP_LEASE", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_NET_ADMIN, "CAP_NET_ADMIN", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_NET_BIND_SERVICE, "CAP_NET_BIND_SERVICE", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_DAC_OVERRIDE, "CAP_DAC_OVERRIDE", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED | CAPNG_BOUNDING_SET }, { CAP_SETGID, "CAP_SETGID", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_SETUID, "CAP_SETUID", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_SYS_ADMIN, "CAP_SYS_ADMIN", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_SYS_CHROOT, "CAP_SYS_CHROOT", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_SYS_RESOURCE, "CAP_SYS_RESOURCE", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED }, { CAP_SYSLOG, "CAP_SYSLOG", 0, CAPNG_EFFECTIVE | CAPNG_PERMITTED } }; // clang-format on if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE) { /* Examine which capabilities are available to us, so we do not try to drop something that is not present. We need to do this in two steps, because capng_clear clears the capability set. In the second step, we add back those caps, which were present before clearing the selected posix capabilities set. */ unsigned long caps_len = sizeof(capabilities) / sizeof(capabilities_t); for (unsigned long i = 0; i < caps_len; i++) { if (capng_have_capability(CAPNG_EFFECTIVE, capabilities[i].capability)) { capabilities[i].present = 1; } } capng_clear(CAPNG_SELECT_BOTH); for (unsigned long i = 0; i < caps_len; i++) { if (capabilities[i].present) { DBGPRINTF( "The %s capability is present, " "will try to preserve it.\n", capabilities[i].name); if ((capng_rc = capng_update(CAPNG_ADD, capabilities[i].type, capabilities[i].capability)) != 0) { LogError(0, RS_RET_LIBCAPNG_ERR, "could not update the internal posix capabilities" " settings based on the options passed to it," " capng_update=%d", capng_rc); capng_failed = 1; } } else { DBGPRINTF( "The %s capability is not present, " "will not try to preserve it.\n", capabilities[i].name); } } if ((capng_rc = capng_apply(CAPNG_SELECT_BOTH)) != 0) { LogError(0, RS_RET_LIBCAPNG_ERR, "could not transfer the specified internal posix capabilities " "settings to the kernel, capng_apply=%d", capng_rc); capng_failed = 1; } if (capng_failed) { DBGPRINTF("Capabilities were not dropped successfully.\n"); if (loadConf->globals.bAbortOnFailedLibcapngSetup) { ABORT_FINALIZE(RS_RET_LIBCAPNG_ERR); } } else { DBGPRINTF("Capabilities were dropped successfully\n"); } } else { DBGPRINTF("No capabilities to drop\n"); } } #endif if (fp_rs_full_conf_output != NULL) { if (fp_rs_full_conf_output != stdout) { fclose(fp_rs_full_conf_output); } fp_rs_full_conf_output = NULL; } /* check for "hard" errors that needs us to abort in any case */ if ((localRet == RS_RET_CONF_FILE_NOT_FOUND) || (localRet == RS_RET_NO_ACTIONS)) { /* for extreme testing, we keep the ability to let rsyslog continue * even on hard config errors. Note that this may lead to segfaults * or other malfunction further down the road. */ if ((loadConf->globals.glblDevOptions & DEV_OPTION_KEEP_RUNNING_ON_HARD_CONF_ERROR) == 1) { fprintf(stderr, "rsyslogd: NOTE: developer-only option set to keep rsyslog " "running where it should abort - this can lead to " "more problems later in the run.\n"); } else { ABORT_FINALIZE(localRet); } } glbl.GenerateLocalHostNameProperty(); if (hadErrMsgs()) { if (loadConf->globals.bAbortOnUncleanConfig) { fprintf(stderr, "rsyslogd: global(AbortOnUncleanConfig=\"on\") is set, and " "config is not clean.\n" "Check error log for details, fix errors and restart. As a last\n" "resort, you may want to use global(AbortOnUncleanConfig=\"off\") \n" "to permit a startup with a dirty config.\n"); exit(2); } if (iConfigVerify) { /* a bit dirty, but useful... */ exit(1); } localRet = RS_RET_OK; } CHKiRet(localRet); if (iTranslateFmt != RSCONF_TRANSLATE_NONE) { CHKiRet(rsconfTranslateWriteFile(configOutputPath)); iRet = RS_RET_VALIDATION_RUN; FINALIZE; } CHKiRet(rsyslogd_InitStdRatelimiters()); if (bChDirRoot) { if (chdir("/") != 0) fprintf(stderr, "Can not do 'cd /' - still trying to run\n"); } if (iConfigVerify) FINALIZE; /* after this point, we are in a "real" startup */ thrdInit(); CHKiRet(checkStartupOK()); if (doFork) { parentPipeFD = forkRsyslog(); } glblSetOurPid(getpid()); hdlr_enable(SIGPIPE, SIG_IGN); hdlr_enable(SIGXFSZ, SIG_IGN); if (Debug || loadConf->globals.permitCtlC) { hdlr_enable(SIGUSR1, rsyslogdDebugSwitch); hdlr_enable(SIGINT, rsyslogdDoDie); hdlr_enable(SIGQUIT, rsyslogdDoDie); } else { hdlr_enable(SIGUSR1, SIG_IGN); hdlr_enable(SIGINT, SIG_IGN); hdlr_enable(SIGQUIT, SIG_IGN); } hdlr_enable(SIGTERM, rsyslogdDoDie); hdlr_enable(SIGCHLD, hdlr_sigchld); hdlr_enable(SIGHUP, hdlr_sighup); if (rsconfNeedDropPriv(loadConf)) { /* need to write pid file early as we may loose permissions */ CHKiRet(writePidFile()); } CHKiRet(rsconf.Activate(ourConf)); if (runConf->globals.bLogStatusMsgs) { char bufStartUpMsg[512]; snprintf(bufStartUpMsg, sizeof(bufStartUpMsg), "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] start", (int)glblGetOurPid()); logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, (uchar *)bufStartUpMsg, 0); } if (!rsconfNeedDropPriv(runConf)) { CHKiRet(writePidFile()); } /* END OF INTIALIZATION */ DBGPRINTF("rsyslogd: initialization completed, transitioning to regular run mode\n"); if (doFork) { tellChildReady(parentPipeFD, "OK"); stddbg = -1; /* turn off writing to fd 1 */ close(1); close(2); runConf->globals.bErrMsgToStderr = 0; } finalize_it: rsconfTranslateCleanup(); if (iRet == RS_RET_VALIDATION_RUN) { fprintf(stderr, "rsyslogd: End of config validation run. Bye.\n"); exit(0); } else if (iRet != RS_RET_OK) { fprintf(stderr, "rsyslogd: run failed with error %d (see rsyslog.h " "or try https://www.rsyslog.com/e/%d to learn what that number means)\n", iRet, iRet * -1); exit(1); } } /* this function pulls all internal messages from the buffer * and puts them into the processing engine. * We can only do limited error handling, as this would not * really help us. TODO: add error messages? * rgerhards, 2007-08-03 */ void processImInternal(void) { smsg_t *pMsg; smsg_t *repMsg; assert(internalMsg_ratelimiter != NULL); while (iminternalRemoveMsg(&pMsg) == RS_RET_OK) { rsRetVal localRet = ratelimitMsg(internalMsg_ratelimiter, pMsg, &repMsg); if (repMsg != NULL) { logmsgInternal_doWrite(repMsg); } if (localRet == RS_RET_OK) { logmsgInternal_doWrite(pMsg); } } } /** * @brief Parse and submit a raw message to the main queue (Legacy). * * Decodes a received message and submits it to the main message queue. * * @note **Legacy Function**: This function is provided to support older input plugins that * do not support message creation via the new message interfaces. * **NEW PLUGINS SHOULD NOT USE THIS FUNCTION.** * * @param hname Hostname of the sender. * @param hnameIP IP address of the sender. * @param msg The raw message content. * @param len Length of the message content. * @param flags Message flags. * @param flowCtlType Type of flow control to apply. * @param pInputName Name of the input module. * @param stTime Syslog time stamp. * @param ttGenTime Time the message was generated. * @param pRuleset Ruleset to apply to this message. * @return RS_RET_OK on success. */ rsRetVal parseAndSubmitMessage(const uchar *const hname, const uchar *const hnameIP, const uchar *const msg, const int len, const int flags, const flowControl_t flowCtlType, prop_t *const pInputName, const struct syslogTime *const stTime, const time_t ttGenTime, ruleset_t *const pRuleset) { prop_t *pProp = NULL; smsg_t *pMsg = NULL; DEFiRet; /* we now create our own message object and submit it to the queue */ if (stTime == NULL) { CHKiRet(msgConstruct(&pMsg)); } else { CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); } if (pInputName != NULL) MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (char *)msg, len); MsgSetFlowControlType(pMsg, flowCtlType); MsgSetRuleset(pMsg, pRuleset); pMsg->msgFlags = flags | NEEDS_PARSING; MsgSetRcvFromStr(pMsg, hname, ustrlen(hname), &pProp); CHKiRet(prop.Destruct(&pProp)); CHKiRet(MsgSetRcvFromIPStr(pMsg, hnameIP, ustrlen(hnameIP), &pProp)); CHKiRet(prop.Destruct(&pProp)); CHKiRet(submitMsg2(pMsg)); finalize_it: if (iRet != RS_RET_OK) { DBGPRINTF("parseAndSubmitMessage() error, discarding msg: %s\n", msg); if (pMsg != NULL) { msgDestruct(&pMsg); } } RETiRet; } /* helper to doHUP(), this "HUPs" each action. The necessary locking * is done inside the action class and nothing we need to take care of. */ DEFFUNC_llExecFunc(doHUPActions) { actionCallHUPHdlr((action_t *)pData); return RS_RET_OK; /* we ignore errors, we can not do anything either way */ } /** Processes a HUP after detection in the main loop. * * @brief Handles SIGHUP signal logic. * * @note This function is *called* by the main loop after a signal handler * detected SIGHUP. It is NOT the signal handler itself. * * @note This function **DOES NOT** reload the main configuration (rsyslog.conf). * It is primarily used for **Log Rotation** (closing/reopening output files) * and notifying modules to refresh internal state (like lookup tables). * To reload configuration, a restart is required. * * There is a VERY slim chance of a data race when the hostname is reset. * We prefer to take this risk rather than sync all accesses, because to the best * of my analysis it can not really hurt (the actual property is reference-counted) * but the sync would require some extra CPU for *each* message processed. * -- rgerhards, 2008-10-22 / 2012-04-11 */ static void doHUP(void) { char buf[512]; DBGPRINTF("doHUP: doing modules\n"); if (ourConf != NULL && ourConf->globals.bLogStatusMsgs) { snprintf(buf, sizeof(buf), "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"] rsyslogd was HUPed", (int)glblGetOurPid()); errno = 0; logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, (uchar *)buf, 0); } queryLocalHostname(runConf); /* re-read our name */ ruleset.IterateAllActions(ourConf, doHUPActions, NULL); DBGPRINTF("doHUP: doing modules\n"); modDoHUP(); DBGPRINTF("doHUP: doing lookup tables\n"); lookupDoHUP(); DBGPRINTF("doHUP: doing ratelimits\n"); ratelimitDoHUP(); DBGPRINTF("doHUP: doing errmsgs\n"); errmsgDoHUP(); } /** * @brief Signal Handler for termination (SIGTERM, SIGINT). * * Sets the global `bFinished` flag to indicate the program should terminate. * * @warning This function runs in a **signal handler context**. * It does NOT terminate the process directly, as that would be unsafe in a multi-threaded * environment. Instead, it signals the main loop to exit gracefully. * * @note We avoid using `DBGPRINTF()` or other complex functions here to prevent * deadlocks or undefined behavior if the signal interrupted a critical section. * The `write()` check exists solely to silence compiler warnings on some platforms (e.g., Ubuntu). * * @param sig The signal number received. */ void rsyslogdDoDie(int sig) { #define MSG1 "DoDie called.\n" #define MSG2 "DoDie called 5 times - unconditional exit\n" static volatile sig_atomic_t iRetries = 0; /* debug aid */ dbgprintf(MSG1); if (Debug == DEBUG_FULL) { if (write(1, MSG1, sizeof(MSG1) - 1) == -1) { dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__); } } if (iRetries++ == 4) { if (Debug == DEBUG_FULL) { if (write(1, MSG2, sizeof(MSG2) - 1) == -1) { dbgprintf("%s:%d: write failed\n", __FILE__, __LINE__); } } abort(); } bFinished = sig; if (runConf && runConf->globals.debugOnShutdown) { /* kind of hackish - set to 0, so that debug_swith will enable * and AND emit the "start debug log" message. */ debugging_on = 0; rsyslogdDebugSwitch(); } #undef MSG1 #undef MSG2 /* at least on FreeBSD we seem not to necessarily awake the main thread. * So let's do it explicitely. */ dbgprintf("awaking mainthread\n"); pthread_kill(mainthread, SIGTTIN); } static uint64_t mainloopMonotonicMs(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { return 0; } return ((uint64_t)ts.tv_sec * 1000ULL) + (uint64_t)(ts.tv_nsec / 1000000ULL); } /* The main loop sleeps until the earliest housekeeping deadline among the * periodic janitor run, the systemd watchdog ping, and any pending rswatch * debounce expiry. */ static int mainloopComputeTimeoutMs(uint64_t now_ms, uint64_t next_janitor_run_ms) { uint64_t diff = 0; int timeout_ms; if (next_janitor_run_ms <= now_ms) { timeout_ms = 0; } else { diff = next_janitor_run_ms - now_ms; timeout_ms = (diff > (uint64_t)INT_MAX) ? INT_MAX : (int)diff; } #ifdef HAVE_LIBSYSTEMD if (systemdWatchdogEnabled && systemdWatchdogUsec > 0) { uint64_t watchdogWaitMs = systemdWatchdogUsec / 2000; if (watchdogWaitMs == 0) { watchdogWaitMs = 1; } if (watchdogWaitMs < (uint64_t)timeout_ms) { timeout_ms = (watchdogWaitMs > (uint64_t)INT_MAX) ? INT_MAX : (int)watchdogWaitMs; } } #endif return rswatchComputeTimeoutMs(now_ms, timeout_ms); } static rsRetVal wait_timeout(const sigset_t *sigmask, int timeout_ms) { struct timespec tvSelectTimeout; int rswatch_fd; DEFiRet; if (timeout_ms < 0) { timeout_ms = 0; } tvSelectTimeout.tv_sec = timeout_ms / 1000; tvSelectTimeout.tv_nsec = (timeout_ms % 1000) * 1000000L; rswatch_fd = rswatchGetWaitFd(); #ifdef _AIX if (!src_exists) { long remaining_ms = timeout_ms; do { fd_set rfds; int maxfd = -1; struct timespec stepTimeout; long step_ms = remaining_ms; if (step_ms > 500) { step_ms = 500; } if (step_ms < 0) { step_ms = 0; } stepTimeout.tv_sec = step_ms / 1000; stepTimeout.tv_nsec = (step_ms % 1000) * 1000000L; if (bFinished || PREFER_LOAD_INT(&bHadHUP)) { break; } FD_ZERO(&rfds); if (rswatch_fd != -1) { FD_SET(rswatch_fd, &rfds); maxfd = rswatch_fd; } pselect(maxfd + 1, maxfd >= 0 ? (fd_set *)&rfds : NULL, NULL, NULL, &stepTimeout, sigmask); if (remaining_ms <= 500) { break; } remaining_ms -= 500; } while (remaining_ms > 0); } else { char buf[256]; fd_set rfds; int maxfd = SRC_FD; FD_ZERO(&rfds); FD_SET(SRC_FD, &rfds); if (rswatch_fd != -1) { FD_SET(rswatch_fd, &rfds); if (rswatch_fd > maxfd) { maxfd = rswatch_fd; } } if (pselect(maxfd + 1, (fd_set *)&rfds, NULL, NULL, &tvSelectTimeout, sigmask)) { if (FD_ISSET(SRC_FD, &rfds)) { rc = recvfrom(SRC_FD, &srcpacket, SRCMSG, 0, &srcaddr, &addrsz); if (rc < 0) { if (errno != EINTR) { LogError(errno, NO_ERRCODE, "%s: ERROR: recvfrom failed - disabling AIX SRC", progname); src_exists = FALSE; ABORT_FINALIZE(RS_RET_IO_ERROR); } else { FINALIZE; } } switch (srcpacket.subreq.action) { case START: dosrcpacket(SRC_SUBMSG, "ERROR: rsyslogd does not support this " "option.\n", sizeof(struct srcrep)); break; case STOP: if (srcpacket.subreq.object == SUBSYSTEM) { dosrcpacket(SRC_OK, NULL, sizeof(struct srcrep)); (void)snprintf(buf, sizeof(buf) / sizeof(char), " [origin " "software=\"rsyslogd\" " "swVersion=\"" VERSION "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]" " exiting due to stopsrc.", (int)glblGetOurPid()); errno = 0; logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, (uchar *)buf, 0); FINALIZE; } else { dosrcpacket(SRC_SUBMSG, "ERROR: rsyslogd does not support " "this option.\n", sizeof(struct srcrep)); } break; case REFRESH: dosrcpacket(SRC_SUBMSG, "ERROR: rsyslogd does not support this " "option.\n", sizeof(struct srcrep)); break; default: dosrcpacket(SRC_SUBICMD, NULL, sizeof(struct srcrep)); break; } } } } #else if (rswatch_fd != -1) { fd_set rfds; FD_ZERO(&rfds); FD_SET(rswatch_fd, &rfds); pselect(rswatch_fd + 1, &rfds, NULL, NULL, &tvSelectTimeout, sigmask); } else { pselect(0, NULL, NULL, NULL, &tvSelectTimeout, sigmask); } #endif /* AIXPORT : SRC end */ #ifdef _AIX finalize_it: #endif RETiRet; } /** * @brief Reap Terminated Child Processes. * * Loops through all terminated child processes (`waitpid` with `WNOHANG`) * and reports their exit status. * * Useful for monitoring short-lived helper processes or scripts launched by rsyslog. * Also needed for proper cleanup of child processes in case of termination. */ static void reapChild(void) { pid_t child; do { int status; child = waitpid(-1, &status, WNOHANG); if (child != -1 && child != 0) { glblReportChildProcessExit(runConf, NULL, child, status); } } while (child > 0); } /** * @brief Application Main Loop. * * Handles housekeeping tasks (signal handling, child reaping, time updates) * while worker threads perform the actual log processing. * * @note This function blocks waiting for signals (`wait_timeout`) and only exits when * `bFinished` is set (e.g., by `rsyslogdDoDie`). */ static void mainloop(void) { time_t tTime; sigset_t origmask; sigset_t sigblockset; uint64_t next_janitor_run_ms; sigemptyset(&sigblockset); sigaddset(&sigblockset, SIGTERM); sigaddset(&sigblockset, SIGCHLD); sigaddset(&sigblockset, SIGHUP); next_janitor_run_ms = mainloopMonotonicMs() + ((uint64_t)runConf->globals.janitorInterval * 60ULL * 1000ULL); do { uint64_t now_ms; sigemptyset(&origmask); pthread_sigmask(SIG_BLOCK, &sigblockset, &origmask); if (PREFER_LOAD_INT(&bChildDied)) { PREFER_STORE_INT(&bChildDied, 0); reapChild(); } if (PREFER_LOAD_INT(&bHadHUP)) { PREFER_STORE_INT(&bHadHUP, 0); PREFER_STORE_INT(&bHUPInProgress, 1); doHUP(); PREFER_STORE_INT(&bHUPInProgress, 0); } processImInternal(); if (bFinished) break; /* exit as quickly as possible */ now_ms = mainloopMonotonicMs(); wait_timeout(&origmask, mainloopComputeTimeoutMs(now_ms, next_janitor_run_ms)); pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL); now_ms = mainloopMonotonicMs(); /* File-watch I/O is handled before due dispatch so newly-read events can * arm or extend debounce deadlines within the same wake cycle. */ rswatchProcessIo(now_ms); rswatchDispatchDue(now_ms); #ifdef HAVE_LIBSYSTEMD if (systemdWatchdogEnabled) { sd_notify(0, "WATCHDOG=1"); } #endif if (now_ms >= next_janitor_run_ms) { janitorRun(); assert(datetime.GetTime != NULL); /* This is only to keep clang static analyzer happy */ datetime.GetTime(&tTime); checkGoneAwaySenders(tTime); next_janitor_run_ms = now_ms + ((uint64_t)runConf->globals.janitorInterval * 60ULL * 1000ULL); } } while (!bFinished); /* end do ... while() */ } /* Finalize and destruct all actions. */ rsRetVal rsyslogdSetProperTerminationFile(const uchar *path) { uchar *newPath = NULL; if (path != NULL && path[0] != '\0') { const size_t lenPath = strlen((const char *)path) + 1; newPath = malloc(lenPath); if (newPath == NULL) return RS_RET_OUT_OF_MEMORY; memcpy(newPath, path, lenPath); } free(properTerminationFile); properTerminationFile = newPath; return RS_RET_OK; } int rsyslogdWriteTerminationMarker(const char *status, const char *reason, const char *phase) { if (properTerminationFile == NULL || properTerminationFile[0] == '\0') return 0; if (status == NULL) status = "unknown"; if (reason == NULL) reason = "unknown"; if (phase == NULL) phase = "unknown"; #ifndef O_NOFOLLOW fprintf(stderr, "rsyslogd: proper termination file '%s' cannot be safely opened: " "O_NOFOLLOW is unavailable on this platform\n", (const char *)properTerminationFile); return 1; #else int fd = open((const char *)properTerminationFile, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0600); if (fd < 0) { fprintf(stderr, "rsyslogd: error opening proper termination file '%s': %s\n", (const char *)properTerminationFile, strerror(errno)); return 1; } #ifdef ENABLE_IMDIAG const unsigned overallQueueSize = PREFER_FETCH_32BIT(iOverallQueueSize); #else const unsigned overallQueueSize = 0; #endif char buf[512]; const int len = snprintf(buf, sizeof(buf), "status=%s\nreason=%s\npid=%d\nsignal=%d\nversion=%s\nphase=%s\n" "queue.overall.size=%u\n", status, reason, (int)getpid(), (int)bFinished, VERSION, phase, overallQueueSize); if (len < 0 || (size_t)len >= sizeof(buf)) { fprintf(stderr, "rsyslogd: error formatting proper termination file '%s'\n", (const char *)properTerminationFile); close(fd); return 1; } const char *cursor = buf; size_t remaining = (size_t)len; while (remaining > 0) { const ssize_t written = write(fd, cursor, remaining); if (written < 0) { if (errno == EINTR) continue; fprintf(stderr, "rsyslogd: error writing proper termination file '%s': %s\n", (const char *)properTerminationFile, strerror(errno)); close(fd); return 1; } if (written == 0) { fprintf(stderr, "rsyslogd: short write to proper termination file '%s'\n", (const char *)properTerminationFile); close(fd); return 1; } cursor += written; remaining -= (size_t)written; } if (close(fd) != 0) { fprintf(stderr, "rsyslogd: error closing proper termination file '%s': %s\n", (const char *)properTerminationFile, strerror(errno)); return 1; } return 0; #endif } static void rsyslogd_destructAllActions(void) { ruleset.DestructAllActions(runConf); PREFER_STORE_0_TO_INT(&bHaveMainQueue); /* flag that internal messages need to be temporarily stored */ } /* de-initialize everything, make ready for termination */ static void deinitAll(void) { char buf[256]; DBGPRINTF("exiting on signal %d\n", (int)bFinished); /* IMPORTANT: we should close the inputs first, and THEN send our termination * message. If we do it the other way around, logmsgInternal() may block on * a full queue and the inputs still fill up that queue. Depending on the * scheduling order, we may end up with logmsgInternal being held for a quite * long time. When the inputs are terminated first, that should not happen * because the queue is drained in parallel. The situation could only become * an issue with extremely long running actions in a queue full environment. * However, such actions are at least considered poorly written, if not * outright wrong. So we do not care about this very remote problem. * rgerhards, 2008-01-11 */ /* close the inputs */ DBGPRINTF("Terminating input threads...\n"); glbl.SetGlobalInputTermination(); thrdTerminateAll(); /* and THEN send the termination log message (see long comment above) */ if (bFinished && runConf->globals.bLogStatusMsgs) { (void)snprintf(buf, sizeof(buf), "[origin software=\"rsyslogd\" " "swVersion=\"" VERSION "\" x-pid=\"%d\" x-info=\"https://www.rsyslog.com\"]" " exiting on signal %d.", (int)glblGetOurPid(), (int)bFinished); errno = 0; logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, (uchar *)buf, 0); } processImInternal(); /* make sure not-yet written internal messages are processed */ /* we sleep a couple of ms to give the queue a chance to pick up the late messages * (including exit message); otherwise we have seen cases where the message did * not make it to log files, even on idle systems. */ srSleep(0, 50); /* drain queue (if configured so) and stop main queue worker thread pool */ DBGPRINTF("Terminating main queue...\n"); qqueueDestruct(&runConf->pMsgQueue); runConf->pMsgQueue = NULL; /* Free ressources and close connections. This includes flushing any remaining * repeated msgs. */ DBGPRINTF("Terminating outputs...\n"); rsyslogd_destructAllActions(); DBGPRINTF("all primary multi-thread sources have been terminated - now doing aux cleanup...\n"); DBGPRINTF("destructing current config...\n"); rsconf.Destruct(&runConf); modExitIminternal(); if (pInternalInputName != NULL) prop.Destruct(&pInternalInputName); /* the following line cleans up CfSysLineHandlers that were not based on loadable * modules. As such, they are not yet cleared. */ unregCfSysLineHdlrs(); /* this is the last spot where this can be done - below output modules are unloaded! */ parserClassExit(); rsconfClassExit(); strExit(); ratelimitModExit(); dnscacheDeinit(); thrdExit(); objRelease(net, LM_NET_FILENAME); module.UnloadAndDestructAll(eMOD_LINK_ALL); rsrtExit(); /* runtime MUST always be deinitialized LAST (except for debug system) */ DBGPRINTF("Clean shutdown completed, bye\n"); errmsgExit(); /* dbgClassExit MUST be the last one, because it de-inits the debug system */ dbgClassExit(); /* NO CODE HERE - dbgClassExit() must be the last thing before exit()! */ clearPidFile(); } /** * @brief Application Entry Point. * * Initializes the debug system and invokes the main initialization sequence. * This is kept minimal to ensure the debug system is initialized early and in a portable way. * * @param argc Number of arguments. * @param argv Array of argument strings. * @return 0 on clean exit, non-zero on error. */ #ifdef RSYSLOG_FUZZ_TARGET int rsyslogd_main(int argc, char **argv); #endif int main(int argc, char **argv) { #if defined(_AIX) /* SRC support : fd 0 (stdin) must be the SRC socket * startup. fd 0 is duped to a new descriptor so that stdin can be used * internally by rsyslogd. */ rs_cstr_copy(progname, argv[0], sizeof(progname)); addrsz = sizeof(srcaddr); if ((rc = getsockname(0, &srcaddr, &addrsz)) < 0) { fprintf(stderr, "%s: continuing without SRC support\n", progname); src_exists = FALSE; } if (src_exists) if (dup2(0, SRC_FD) == -1) { fprintf(stderr, "%s: dup2 failed exiting now...\n", progname); /* In the unlikely event of dup2 failing we exit */ exit(-1); } #endif mainthread = pthread_self(); if ((int)getpid() == 1) { fprintf(stderr, "rsyslogd %s: running as pid 1, enabling " "container-specific defaults, press ctl-c to " "terminate rsyslog\n", VERSION); PidFile = strdup("NONE"); /* disables pid file writing */ glblPermitCtlC = 1; runningInContainer = 1; emitTZWarning = 1; } else { /* "dynamic defaults" - non-container case */ PidFile = strdup(PATH_PIDFILE); } if (PidFile == NULL) { fprintf(stderr, "rsyslogd: could not alloc memory for pid file " "default name - aborting\n"); exit(1); } /* disable case-sensitive comparisons in variable subsystem: */ fjson_global_do_case_sensitive_comparison(0); dbgClassInit(); initAll(argc, argv); #ifdef HAVE_LIBSYSTEMD if (rsconfShouldDelayReadyNotify(runConf)) { rsconfWaitForModulesReady(); } if (sd_watchdog_enabled(0, &systemdWatchdogUsec) > 0) { systemdWatchdogEnabled = 1; dbgprintf("systemd watchdog enabled with interval %llu usec\n", (unsigned long long)systemdWatchdogUsec); } sd_notify(0, "READY=1"); if (rsconfShouldDelayReadyNotify(runConf)) { rsconfReadyNotifySent(); } dbgprintf("done signaling to systemd that we are ready!\n"); #endif DBGPRINTF("max message size: %d\n", glblGetMaxLine(runConf)); DBGPRINTF("----RSYSLOGD INITIALIZED\n"); LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd fully started up and initialized " "- begin actual processing"); mainloop(); LogMsg(0, RS_RET_OK, LOG_DEBUG, "rsyslogd shutting down"); deinitAll(); osf_close(); return rsyslogdWriteTerminationMarker("ok", "normal", "main-return"); } rsyslog-8.2608.0/tools/PaxHeaders/msggen.c0000644000000000000000000000013115132411300015310 xustar0029 mtime=1768559296.30288621 30 atime=1782715518.781788721 30 ctime=1787067795.300741938 rsyslog-8.2608.0/tools/msggen.c0000666000175000017500000000211015132411300014751 0ustar00rgerrger/* msggen - a small diagnostic utility that does very quick * syslog() calls. * * Copyright 2008-2014 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include int main(int __attribute__((unused)) argc, char __attribute__((unused)) * argv[]) { int i; openlog("msggen", 0, LOG_LOCAL0); for (i = 0; i < 10; ++i) syslog(LOG_NOTICE, "This is message number %d", i); closelog(); return 0; } rsyslog-8.2608.0/tools/PaxHeaders/omfwd.h0000644000000000000000000000013215141401300015151 xustar0030 mtime=1770390208.969869851 30 atime=1787067618.283442357 30 ctime=1787067795.246740932 rsyslog-8.2608.0/tools/omfwd.h0000664000175000017500000000232515141401300014617 0ustar00rgerrger/* omfwd.h * These are the definitions for the build-in forwarding output module. * * File begun on 2007-07-13 by RGerhards * * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OMFWD_H_INCLUDED #define OMFWD_H_INCLUDED 1 /* prototypes */ rsRetVal modInitFwd(int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal (**)()), modInfo_t *); #endif /* #ifndef OMFWD_H_INCLUDED */ /* * vi:set ai: */ rsyslog-8.2608.0/PaxHeaders/runtime0000644000000000000000000000013215241076622014152 xustar0030 mtime=1787067794.615729173 30 atime=1787067808.783993182 30 ctime=1787067794.615729173 rsyslog-8.2608.0/runtime/0000775000175000017500000000000015241076622013673 5ustar00rgerrgerrsyslog-8.2608.0/runtime/PaxHeaders/tcpclt.c0000644000000000000000000000013115216464436015671 xustar0029 mtime=1782212894.04026641 30 atime=1787067618.350443606 30 ctime=1787067794.595728801 rsyslog-8.2608.0/runtime/tcpclt.c0000664000175000017500000004551615216464436015351 0ustar00rgerrger/* tcpclt.c * * This is the implementation of TCP-based syslog clients (the counterpart * of the tcpsrv class). * * Copyright 2007-2024 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_FCNTL_H #include #endif #include "rsyslog.h" #include "dirty.h" #include "syslogd-types.h" #include "net.h" #include "tcpclt.h" #include "module-template.h" #include "srUtils.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; /* Initialize TCP sockets (for sender) */ static int CreateSocket(struct addrinfo *addrDest) { int fd; struct addrinfo *r; r = addrDest; while (r != NULL) { fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol); if (fd != -1) { /* We can not allow the TCP sender to block syslogd, at least * not in a single-threaded design. That would cause rsyslogd to * loose input messages - which obviously also would affect * other selector lines, too. So we do set it to non-blocking and * handle the situation ourselfs (by discarding messages). IF we run * dual-threaded, however, the situation is different: in this case, * the receivers and the selector line processing are only loosely * coupled via a memory buffer. Now, I think, we can afford the extra * wait time. Thus, we enable blocking mode for TCP if we compile with * pthreads. -- rgerhards, 2005-10-25 * And now, we always run on multiple threads... -- rgerhards, 2007-12-20 */ if (connect(fd, r->ai_addr, r->ai_addrlen) != 0) { if (errno == EINPROGRESS) { /* this is normal - will complete later select */ return fd; } else { char errStr[1024]; dbgprintf("create tcp connection failed, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); } } else { return fd; } close(fd); } else { char errStr[1024]; dbgprintf("couldn't create send socket, reason %s", rs_strerror_r(errno, errStr, sizeof(errStr))); } r = r->ai_next; } dbgprintf("no working socket could be obtained"); return -1; } /* Build frame based on selected framing * This function was created by pulling code from TCPSend() * on 2007-12-27 by rgerhards. Older comments are still relevant. * * In order to support compressed messages via TCP, we must support an * octet-counting based framing (LF may be part of the compressed message). * We are now supporting the same mode that is available in IETF I-D * syslog-transport-tls-05 (current at the time of this writing). This also * eases things when we go ahead and implement that framing. I have now made * available two cases where this framing is used: either by explitely * specifying it in the config file or implicitely when sending a compressed * message. In the later case, compressed and uncompressed messages within * the same session have different framings. If it is explicitely set to * octet-counting, only this framing mode is used within the session. * rgerhards, 2006-12-07 */ static rsRetVal TCPSendBldFrame(tcpclt_t *pThis, char **pmsg, size_t *plen, int *pbMustBeFreed) { DEFiRet; TCPFRAMINGMODE framingToUse; int bIsCompressed; size_t len; size_t frameSize; char *msg; char *buf = NULL; /* if this is non-NULL, it MUST be freed before return! */ assert(plen != NULL); assert(pbMustBeFreed != NULL); assert(pmsg != NULL); msg = *pmsg; len = *plen; bIsCompressed = *msg == 'z'; /* cache this, so that we can modify the message buffer */ /* select framing for this record. If we have a compressed record, we always need to * use octet counting because the data potentially contains all control characters * including LF. */ framingToUse = bIsCompressed ? TCP_FRAMING_OCTET_COUNTING : pThis->tcp_framing; /* now check if we need to add a line terminator. We need to * copy the string in memory in this case, this is probably * quicker than using writev and definitely quicker than doing * two socket calls. * rgerhards 2005-07-22 * * Some messages already contain a \n character at the end * of the message. We append one only if we there is not * already one. This seems the best fit, though this also * means the message does not arrive unaltered at the final * destination. But in the spirit of legacy syslog, this is * probably the best to do... * rgerhards 2005-07-20 */ /* Build frame based on selected framing */ if (framingToUse == TCP_FRAMING_OCTET_STUFFING) { if ((*(msg + len - 1) != pThis->tcp_framingDelimiter)) { if (len > SIZE_MAX - 2) { LogError(0, RS_RET_OUT_OF_MEMORY, "Error: TCP frame too large to append framing delimiter safely. Message is lost."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* in the malloc below, we need to add 2 to the length. The * reason is that we a) add one character and b) len does * not take care of the '\0' byte. Up until today, it was just * +1 , which caused rsyslogd to sometimes dump core. * I have added this comment so that the logic is not accidently * changed again. rgerhards, 2005-10-25 */ if ((buf = malloc(len + 2)) == NULL) { /* extreme mem shortage, try to solve * as good as we can. No point in calling * any alarms, they might as well run out * of memory (the risk is very high, so we * do NOT risk that). If we have a message of * more than 1 byte (what I guess), we simply * overwrite the last character. * rgerhards 2005-07-22 */ if (len > 1) { *(msg + len - 1) = pThis->tcp_framingDelimiter; } else { /* we simply can not do anything in * this case (its an error anyhow...). */ } } else { /* we got memory, so we can copy the message */ memcpy(buf, msg, len); /* do not copy '\0' */ *(buf + len) = pThis->tcp_framingDelimiter; *(buf + len + 1) = '\0'; msg = buf; /* use new one */ ++len; /* care for the \n */ } } } else { /* Octect-Counting * In this case, we need to always allocate a buffer. This is because * we need to put a header in front of the message text */ char szLenBuf[16]; int iLenBuf; /* important: the printf-mask is "%d" because there must be a * space after the len! *//* The chairs of the IETF syslog-sec WG have announced that it is * consensus to do the octet count on the SYSLOG-MSG part only. I am * now changing the code to reflect this. Hopefully, it will not change * once again (there can no compatibility layer programmed for this). * To be on the save side, I just comment the code out. I mark these * comments with "IETF20061218". * rgerhards, 2006-12-19 */ if (len > (size_t)INT_MAX) { LogError(0, RS_RET_OUT_OF_MEMORY, "Error: TCP frame too large for octet-counted framing header. Message is lost."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf), "%d ", (int)len); /* IETF20061218 iLenBuf = snprintf(szLenBuf, sizeof(szLenBuf), "%d ", len + iLenBuf);*/ if (iLenBuf < 0) { ABORT_FINALIZE(RS_RET_ERR); } if (len > SIZE_MAX - (size_t)iLenBuf) { LogError(0, RS_RET_OUT_OF_MEMORY, "Error: TCP frame too large to prepend octet-counted header safely. Message is lost."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } frameSize = len + (size_t)iLenBuf; if ((buf = malloc(frameSize)) == NULL) { /* we are out of memory. This is an extreme situation. We do not * call any alarm handlers because they most likely run out of mem, * too. We are brave enough to call debug output, though. Other than * that, there is nothing left to do. We can not sent the message (as * in case of the other framing, because the message is incomplete. * We could, however, send two chunks (header and text separate), but * that would cause a lot of complexity in the code. So we think it * is appropriate enough to just make sure we do not crash in this * very unlikely case. For this, it is justified just to loose * the message. Rgerhards, 2006-12-07 */ dbgprintf( "Error: out of memory when building TCP octet-counted " "frame. Message is lost, trying to continue.\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } memcpy(buf, szLenBuf, iLenBuf); /* header */ memcpy(buf + iLenBuf, msg, len); /* message */ len = frameSize; /* new message size */ msg = buf; /* set message buffer */ } /* frame building complete, on to actual sending */ *plen = len; if (buf == NULL) { /* msg not modified */ *pbMustBeFreed = 0; } else { *pmsg = msg; *pbMustBeFreed = 1; } finalize_it: RETiRet; } /* Sends a TCP message. It is first checked if the * session is open and, if not, it is opened. Then the send * is tried. If it fails, one silent re-try is made. If the send * fails again, an error status (-1) is returned. If all goes well, * 0 is returned. The TCP session is NOT torn down. * For now, EAGAIN is ignored (causing message loss) - but it is * hard to do something intelligent in this case. With this * implementation here, we can not block and/or defer. Things are * probably a bit better when we move to liblogging. The alternative * would be to enhance the current select server with buffering and * write descriptors. This seems not justified, given the expected * short life span of this code (and the unlikeliness of this event). * rgerhards 2005-07-06 * This function is now expected to stay. Libloging won't be used for * that purpose. I have added the param "len", because it is known by the * caller and so saves us some time. Also, it MUST be given because there * may be NULs inside msg so that we can not rely on strlen(). Please note * that the restrictions outlined above do not existin in multi-threaded * mode, which we assume will now be most often used. So there is no * real issue with the potential message loss in single-threaded builds. * rgerhards, 2006-11-30 * I greatly restructured the function to be more generic and work * with function pointers. So it now can be used with any type of transport, * as long as it follows stream semantics. This was initially done to * support plain TCP and GSS via common code. */ static int Send(tcpclt_t *pThis, void *pData, char *msg, size_t len) { DEFiRet; int bDone = 0; int retry = 0; int bMsgMustBeFreed = 0; /* must msg be freed at end of function? 0 - no, 1 - yes */ ISOBJ_TYPE_assert(pThis, tcpclt); assert(pData != NULL); assert(msg != NULL); assert(len > 0); CHKiRet(TCPSendBldFrame(pThis, &msg, &len, &bMsgMustBeFreed)); while (!bDone) { /* loop is broken when send succeeds or error occurs */ CHKiRet(pThis->initFunc(pData)); iRet = pThis->sendFunc(pData, msg, len); if (iRet == RS_RET_RETRY) { bDone = 1; } else if (iRet == RS_RET_OK || iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) { /* we are done, we also use this as indication that the previous * message was succesfully received (it's not always the case, but its at * least our best shot at it -- rgerhards, 2008-03-12 * As of 2008-06-09, we have implemented an algorithm which detects connection * loss quite good in some (common) scenarios. Thus, the probability of * message duplication due to the code below has increased. We so now have * a config setting, default off, that enables the user to request retransmits. * However, if not requested, we do NOT need to do all the stuff needed for it. */ if (pThis->bResendLastOnRecon == 1) { if (pThis->prevMsg != NULL) free(pThis->prevMsg); /* if we can not alloc a new buffer, we silently ignore it. The worst that * happens is that we lose our message recovery buffer - anything else would * be worse, so don't try anything ;) -- rgerhards, 2008-03-12 */ if ((pThis->prevMsg = malloc(len)) != NULL) { memcpy(pThis->prevMsg, msg, len); pThis->lenPrevMsg = len; } } /* we are done with this record */ bDone = 1; } else { if (retry == 0) { /* OK, one retry */ ++retry; CHKiRet(pThis->prepRetryFunc(pData)); /* try to recover */ /* now try to send our stored previous message (which most probably * didn't make it. Note that if bResendLastOnRecon is 0, prevMsg will * never become non-NULL, so the check below covers all cases. */ if (pThis->prevMsg != NULL) { CHKiRet(pThis->initFunc(pData)); CHKiRet(pThis->sendFunc(pData, pThis->prevMsg, pThis->lenPrevMsg)); } } else { /* OK, max number of retries reached, nothing we can do */ bDone = 1; } } } finalize_it: if (bMsgMustBeFreed) free(msg); RETiRet; } /* set functions */ static rsRetVal SetResendLastOnRecon(tcpclt_t *pThis, const int bResendLastOnRecon) { pThis->bResendLastOnRecon = (short)bResendLastOnRecon; return RS_RET_OK; } static rsRetVal SetSendInit(tcpclt_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->initFunc = pCB; RETiRet; } static rsRetVal SetSendPrepRetry(tcpclt_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->prepRetryFunc = pCB; RETiRet; } static rsRetVal SetSendFrame(tcpclt_t *pThis, rsRetVal (*pCB)(void *, char *, size_t)) { DEFiRet; pThis->sendFunc = pCB; RETiRet; } static rsRetVal SetFraming(tcpclt_t *pThis, TCPFRAMINGMODE framing) { DEFiRet; pThis->tcp_framing = framing; RETiRet; } static rsRetVal SetFramingDelimiter(tcpclt_t *pThis, uchar tcp_framingDelimiter) { DEFiRet; pThis->tcp_framingDelimiter = tcp_framingDelimiter; RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(tcpclt) /* be sure to specify the object type also in END macro! */ pThis->tcp_framingDelimiter = '\n'; ENDobjConstruct(tcpclt) /* ConstructionFinalizer */ static rsRetVal tcpcltConstructFinalize(tcpclt_t __attribute__((unused)) * pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpclt); RETiRet; } /* destructor for the tcpclt object */ BEGINobjDestruct(tcpclt) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(tcpclt); if (pThis->prevMsg != NULL) free(pThis->prevMsg); ENDobjDestruct(tcpclt) /* ------------------------------ handling the interface plumbing ------------------------------ */ /* queryInterface function * rgerhards, 2008-03-12 */ BEGINobjQueryInterface(tcpclt) CODESTARTobjQueryInterface(tcpclt); if (pIf->ifVersion != tcpcltCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = tcpcltConstruct; pIf->ConstructFinalize = tcpcltConstructFinalize; pIf->Destruct = tcpcltDestruct; pIf->CreateSocket = CreateSocket; pIf->Send = Send; /* set functions */ pIf->SetResendLastOnRecon = SetResendLastOnRecon; pIf->SetSendInit = SetSendInit; pIf->SetSendFrame = SetSendFrame; pIf->SetSendPrepRetry = SetSendPrepRetry; pIf->SetFraming = SetFraming; pIf->SetFramingDelimiter = SetFramingDelimiter; finalize_it: ENDobjQueryInterface(tcpclt) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(tcpclt, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(tcpclt); /* release objects we no longer need */ ENDObjClassExit(tcpclt) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINObjClassInit(tcpclt, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ /* set our own handlers */ OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcpcltConstructFinalize); ENDObjClassInit(tcpclt) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; /* de-init in reverse order! */ tcpcltClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselves */ CHKiRet(tcpcltClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/net_ossl_store.c0000644000000000000000000000013215241075234017433 xustar0030 mtime=1787067036.603578257 30 atime=1787067036.681579717 30 ctime=1787067794.558728111 rsyslog-8.2608.0/runtime/net_ossl_store.c0000664000175000017500000005024015241075234017100 0ustar00rgerrger/** * @file net_ossl_store.c * @brief TLS object loading helpers for the OpenSSL netstream driver. * * This module centralizes loading of CA certificates, certificate chains, and * private keys for lmnsd_ossl. On OpenSSL 3 builds it uses the provider/store * API when a strict pkcs11: URI is supplied, while preserving the traditional * filesystem-backed PEM loading path for ordinary filenames. * * Copyright 2026 Cisco Systems, Inc., and/or its affiliates. * Copyright 2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "net_ossl_store.h" #include "debug.h" #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) #include #endif /** * @brief Return the delimiter that terminates a sensitive URI attribute. * @param c Character under inspection. * @return Non-zero when @p c ends the current attribute value. */ static int net_ossl_is_uri_value_delim(int c) { return c == '\0' || c == ';' || c == ','; } /** * @brief Redact a sensitive URI attribute in a caller-supplied buffer. * @param buf Mutable string to update in place. * @param key Attribute key to locate. */ static void ATTR_NONNULL() net_ossl_redact_uri_value(char *buf, const char *key) { char *pos; char *value; char *end; pos = buf; while ((pos = strstr(pos, key)) != NULL) { value = pos + strlen(key); end = value; while (!net_ossl_is_uri_value_delim((unsigned char)*end)) { ++end; } memset(value, '*', (size_t)(end - value)); pos = end; } } /** * @brief Redact sensitive URI or provider configuration values before they are * emitted to logs. * @param input Original path or URI to sanitize. * @param buf Caller-supplied scratch buffer used when redaction is required. * @param bufSize Size of @p buf in bytes. * @return Either @p input when no redaction was required, or @p buf containing * a redacted copy. */ const char *ATTR_NONNULL() net_ossl_sanitize_log_value(const char *input, char **sanitized) { static const char redactedFallback[] = "[redacted]"; *sanitized = NULL; if (strstr(input, "pin-value=") == NULL && strstr(input, "pkcs11-module-token-pin=") == NULL) { return input; } *sanitized = strdup(input); if (*sanitized == NULL) { return redactedFallback; } net_ossl_redact_uri_value(*sanitized, "pin-value="); net_ossl_redact_uri_value(*sanitized, "pkcs11-module-token-pin="); return *sanitized; } void net_ossl_free_sanitized_log_value(char **sanitized) { if (sanitized != NULL) { free(*sanitized); *sanitized = NULL; } } /** * @brief Log the most recent OpenSSL error stack entry for a failed load * operation. * @param errCode rsyslog error code associated with the failure. * @param call OpenSSL API name that failed. * @param objType Human-readable object type being loaded. * @param input Original path or URI that triggered the failure. */ static void ATTR_NONNULL() net_ossl_store_log_error_impl(rsRetVal errCode, const char *call, const char *objType, const char *input) { unsigned long err; char errbuf[256]; char *sanitized = NULL; const char *logInput; logInput = net_ossl_sanitize_log_value(input, &sanitized); err = ERR_get_error(); if (err == 0) { LogError(0, errCode, "%s: %s load failed for '%s'. OpenSSL Error Stack: no OpenSSL error on stack", call, objType, logInput); dbgprintf("%s: %s load failed for '%s'. OpenSSL Error Stack: no OpenSSL error on stack\n", call, objType, logInput); net_ossl_free_sanitized_log_value(&sanitized); return; } while (err != 0) { ERR_error_string_n(err, errbuf, sizeof(errbuf)); LogError(0, errCode, "%s: %s load failed for '%s'. OpenSSL Error Stack: err=0x%lx lib=%d reason=%d msg='%s'", call, objType, logInput, err, ERR_GET_LIB(err), ERR_GET_REASON(err), errbuf); dbgprintf("%s: %s load failed for '%s'. OpenSSL Error Stack: err=0x%lx lib=%d reason=%d msg='%s'\n", call, objType, logInput, err, ERR_GET_LIB(err), ERR_GET_REASON(err), errbuf); err = ERR_get_error(); } net_ossl_free_sanitized_log_value(&sanitized); } /** * @brief Log the current OpenSSL error stack and return the supplied rsyslog * error code. * @param errCode rsyslog error code to return to the caller. * @param call OpenSSL API name that failed. * @param objType Human-readable object type being loaded. * @param input Original path or URI that triggered the failure. * @return The @p errCode argument. */ static rsRetVal ATTR_NONNULL() net_ossl_store_log_error(rsRetVal errCode, const char *call, const char *objType, const char *input) { net_ossl_store_log_error_impl(errCode, call, objType, input); return errCode; } #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) /** * @brief Determine whether a configuration value should be treated as a PKCS#11 * URI. * @param value Configuration value to inspect. * @return Non-zero when @p value begins with the strict @c pkcs11: prefix. */ static int net_ossl_is_uri(const char *value) { return value != NULL && strncmp(value, "pkcs11:", sizeof("pkcs11:") - 1) == 0; } /** * @brief Open an OpenSSL store loader for a URI-backed object source. * @param errCode rsyslog error code to report if opening the store fails. * @param uri Object locator passed to OSSL_STORE. * @param expect Expected OSSL_STORE object type. * @param store Receives the opened store context on success. * @return RS_RET_OK on success, or the caller-supplied rsyslog error code. */ static rsRetVal ATTR_NONNULL(2, 4) net_ossl_store_open(rsRetVal errCode, const char *uri, int expect, OSSL_STORE_CTX **store) { DEFiRet; assert(store != NULL); *store = OSSL_STORE_open_ex(uri, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (*store == NULL) { ABORT_FINALIZE(net_ossl_store_log_error(errCode, "OSSL_STORE_open_ex", "store", uri)); } if (OSSL_STORE_expect(*store, expect) != 1) { /* Preference only; keep going if the loader ignores it. */ net_ossl_store_log_error_impl(RS_RET_OK, "OSSL_STORE_expect", "store", uri); ERR_clear_error(); } finalize_it: RETiRet; } /** * @brief Load CA certificates from an OpenSSL store source into an SSL * context. * @param ctx SSL context that receives the trust anchors. * @param caFile PKCS#11 URI to open through OSSL_STORE. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ static rsRetVal ATTR_NONNULL() net_ossl_store_load_ca_file(SSL_CTX *ctx, const char *caFile) { DEFiRet; OSSL_STORE_CTX *store = NULL; OSSL_STORE_INFO *info = NULL; X509_STORE *x509_store; int loaded = 0; assert(ctx != NULL); assert(caFile != NULL); x509_store = SSL_CTX_get_cert_store(ctx); if (x509_store == NULL) { char *sanitized = NULL; const char *logCaFile = net_ossl_sanitize_log_value(caFile, &sanitized); LogError(0, RS_RET_TLS_CERT_ERR, "SSL_CTX_get_cert_store: CA load failed for '%s': no X509 store on SSL_CTX", logCaFile); dbgprintf("SSL_CTX_get_cert_store: CA load failed for '%s': no X509 store on SSL_CTX\n", logCaFile); net_ossl_free_sanitized_log_value(&sanitized); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } CHKiRet(net_ossl_store_open(RS_RET_TLS_CERT_ERR, caFile, OSSL_STORE_INFO_CERT, &store)); while ((info = OSSL_STORE_load(store)) != NULL) { if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_CERT) { X509 *cert = OSSL_STORE_INFO_get1_CERT(info); if (cert != NULL) { if (X509_STORE_add_cert(x509_store, cert) == 1) { loaded++; } else { unsigned long err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { ERR_clear_error(); loaded++; } else { ABORT_FINALIZE( net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "X509_STORE_add_cert", "CA", caFile)); } } X509_free(cert); } } OSSL_STORE_INFO_free(info); info = NULL; } if (OSSL_STORE_error(store)) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "OSSL_STORE_load", "CA", caFile)); } if (loaded == 0) { char *sanitized = NULL; const char *logCaFile = net_ossl_sanitize_log_value(caFile, &sanitized); LogError(0, RS_RET_TLS_CERT_ERR, "OSSL store CA load failed for '%s': no certificate objects were loaded", logCaFile); dbgprintf("OSSL store CA load failed for '%s': no certificate objects were loaded\n", logCaFile); net_ossl_free_sanitized_log_value(&sanitized); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } finalize_it: if (info != NULL) { OSSL_STORE_INFO_free(info); } if (store != NULL) { OSSL_STORE_close(store); } RETiRet; } /** * @brief Load a certificate chain from an OpenSSL store source into an SSL * context. * @param ctx SSL context that receives the certificate chain. * @param certFile PKCS#11 URI to open through OSSL_STORE. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ static int ATTR_NONNULL() net_ossl_store_cert_issues_other(X509 *candidate, const STACK_OF(X509) * certs) { int i; assert(candidate != NULL); assert(certs != NULL); for (i = 0; i < sk_X509_num(certs); ++i) { X509 *other = sk_X509_value(certs, i); if (other != NULL && other != candidate && X509_check_issued(candidate, other) == X509_V_OK) { return 1; } } return 0; } static rsRetVal ATTR_NONNULL(1, 2, 3) net_ossl_store_select_leaf_cert(STACK_OF(X509) * certs, const char *certFile, X509 **leaf) { DEFiRet; int i; X509 *fallback = NULL; int fallbackCount = 0; X509 *preferred = NULL; int preferredCount = 0; assert(certs != NULL); assert(certFile != NULL); assert(leaf != NULL); *leaf = NULL; for (i = 0; i < sk_X509_num(certs); ++i) { X509 *cert = sk_X509_value(certs, i); if (cert == NULL || net_ossl_store_cert_issues_other(cert, certs)) { continue; } fallback = cert; ++fallbackCount; if (X509_check_ca(cert) == 0) { preferred = cert; ++preferredCount; } } if (preferredCount == 1) { *leaf = preferred; } else if (preferredCount > 1) { char *sanitized = NULL; const char *logCertFile = net_ossl_sanitize_log_value(certFile, &sanitized); LogError(0, RS_RET_TLS_CERT_ERR, "OSSL store certificate load failed for '%s': multiple end-entity certificates were loaded", logCertFile); dbgprintf("OSSL store certificate load failed for '%s': multiple end-entity certificates were loaded\n", logCertFile); net_ossl_free_sanitized_log_value(&sanitized); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } else if (fallbackCount == 1) { *leaf = fallback; } else if (fallbackCount > 1) { char *sanitized = NULL; const char *logCertFile = net_ossl_sanitize_log_value(certFile, &sanitized); LogError(0, RS_RET_TLS_CERT_ERR, "OSSL store certificate load failed for '%s': unable to identify a unique leaf certificate", logCertFile); dbgprintf("OSSL store certificate load failed for '%s': unable to identify a unique leaf certificate\n", logCertFile); net_ossl_free_sanitized_log_value(&sanitized); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() net_ossl_store_load_cert_file(SSL_CTX *ctx, const char *certFile) { DEFiRet; OSSL_STORE_CTX *store = NULL; OSSL_STORE_INFO *info = NULL; STACK_OF(X509) *certs = NULL; X509 *leaf = NULL; int i; assert(ctx != NULL); assert(certFile != NULL); CHKiRet(net_ossl_store_open(RS_RET_TLS_CERT_ERR, certFile, OSSL_STORE_INFO_CERT, &store)); certs = sk_X509_new_null(); if (certs == NULL) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "sk_X509_new_null", "certificate", certFile)); } while ((info = OSSL_STORE_load(store)) != NULL) { if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_CERT) { X509 *cert = OSSL_STORE_INFO_get1_CERT(info); if (cert != NULL && !sk_X509_push(certs, cert)) { X509_free(cert); ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "sk_X509_push", "certificate", certFile)); } } OSSL_STORE_INFO_free(info); info = NULL; } if (OSSL_STORE_error(store)) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "OSSL_STORE_load", "certificate", certFile)); } CHKiRet(net_ossl_store_select_leaf_cert(certs, certFile, &leaf)); if (leaf == NULL) { char *sanitized = NULL; const char *logCertFile = net_ossl_sanitize_log_value(certFile, &sanitized); LogError(0, RS_RET_TLS_CERT_ERR, "OSSL store certificate load failed for '%s': no leaf certificate object was loaded", logCertFile); dbgprintf("OSSL store certificate load failed for '%s': no leaf certificate object was loaded\n", logCertFile); net_ossl_free_sanitized_log_value(&sanitized); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } for (i = 0; i < sk_X509_num(certs); ++i) { X509 *cert = sk_X509_value(certs, i); if (cert != NULL && cert != leaf) { if (SSL_CTX_add_extra_chain_cert(ctx, cert) != 1) { X509_free(cert); sk_X509_set(certs, i, NULL); ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "SSL_CTX_add_extra_chain_cert", "certificate", certFile)); } sk_X509_set(certs, i, NULL); } } if (SSL_CTX_use_certificate(ctx, leaf) != 1) { net_ossl_store_log_error_impl(RS_RET_TLS_CERT_ERR, "SSL_CTX_use_certificate", "certificate", certFile); ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); } finalize_it: if (certs != NULL) { sk_X509_pop_free(certs, X509_free); } if (info != NULL) { OSSL_STORE_INFO_free(info); } if (store != NULL) { OSSL_STORE_close(store); } RETiRet; } /** * @brief Load a private key from an OpenSSL store source into an SSL context. * @param ctx SSL context that receives the private key. * @param keyFile PKCS#11 URI to open through OSSL_STORE. * @return RS_RET_OK on success, or an rsyslog TLS key error code. */ static rsRetVal ATTR_NONNULL() net_ossl_store_load_key_file(SSL_CTX *ctx, const char *keyFile) { DEFiRet; OSSL_STORE_CTX *store = NULL; OSSL_STORE_INFO *info = NULL; EVP_PKEY *pkey = NULL; assert(ctx != NULL); assert(keyFile != NULL); CHKiRet(net_ossl_store_open(RS_RET_TLS_KEY_ERR, keyFile, OSSL_STORE_INFO_PKEY, &store)); while ((info = OSSL_STORE_load(store)) != NULL) { if (OSSL_STORE_INFO_get_type(info) == OSSL_STORE_INFO_PKEY) { pkey = OSSL_STORE_INFO_get1_PKEY(info); OSSL_STORE_INFO_free(info); info = NULL; break; } OSSL_STORE_INFO_free(info); info = NULL; } if (OSSL_STORE_error(store)) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_KEY_ERR, "OSSL_STORE_load", "private key", keyFile)); } if (pkey == NULL || SSL_CTX_use_PrivateKey(ctx, pkey) != 1) { if (pkey == NULL) { char *sanitized = NULL; const char *logKeyFile = net_ossl_sanitize_log_value(keyFile, &sanitized); LogError(0, RS_RET_TLS_KEY_ERR, "OSSL store key load failed for '%s': no private key object was loaded", logKeyFile); dbgprintf("OSSL store key load failed for '%s': no private key object was loaded\n", logKeyFile); net_ossl_free_sanitized_log_value(&sanitized); } else { net_ossl_store_log_error_impl(RS_RET_TLS_KEY_ERR, "SSL_CTX_use_PrivateKey", "private key", keyFile); } ABORT_FINALIZE(RS_RET_TLS_KEY_ERR); } finalize_it: if (pkey != NULL) { EVP_PKEY_free(pkey); } if (info != NULL) { OSSL_STORE_INFO_free(info); } if (store != NULL) { OSSL_STORE_close(store); } RETiRet; } #endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) */ /** * @brief Load CA certificates into an SSL context from a file path or PKCS#11 * URI. * @param ctx SSL context that receives the trust anchors. * @param caFile Path or pkcs11: URI describing the CA certificate source. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ rsRetVal net_ossl_load_ca_file(SSL_CTX *ctx, const char *caFile) { DEFiRet; assert(ctx != NULL); assert(caFile != NULL); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) if (net_ossl_is_uri(caFile)) { CHKiRet(net_ossl_store_load_ca_file(ctx, caFile)); FINALIZE; } #endif if (SSL_CTX_load_verify_locations(ctx, caFile, NULL) != 1) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "SSL_CTX_load_verify_locations", "CA", caFile)); } finalize_it: RETiRet; } /** * @brief Load a certificate chain into an SSL context from a file path or * PKCS#11 URI. * @param ctx SSL context that receives the certificate chain. * @param certFile Path or pkcs11: URI describing the certificate source. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ rsRetVal net_ossl_load_cert_file(SSL_CTX *ctx, const char *certFile) { DEFiRet; assert(ctx != NULL); assert(certFile != NULL); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) if (net_ossl_is_uri(certFile)) { CHKiRet(net_ossl_store_load_cert_file(ctx, certFile)); FINALIZE; } #endif if (SSL_CTX_use_certificate_chain_file(ctx, certFile) != 1) { ABORT_FINALIZE(net_ossl_store_log_error(RS_RET_TLS_CERT_ERR, "SSL_CTX_use_certificate_chain_file", "certificate", certFile)); } finalize_it: RETiRet; } /** * @brief Load a private key into an SSL context from a file path or PKCS#11 * URI. * @param ctx SSL context that receives the private key. * @param keyFile Path or pkcs11: URI describing the private key source. * @return RS_RET_OK on success, or an rsyslog TLS key error code. */ rsRetVal net_ossl_load_key_file(SSL_CTX *ctx, const char *keyFile) { DEFiRet; assert(ctx != NULL); assert(keyFile != NULL); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(ENABLE_WOLFSSL) && !defined(LIBRESSL_VERSION_NUMBER) if (net_ossl_is_uri(keyFile)) { CHKiRet(net_ossl_store_load_key_file(ctx, keyFile)); FINALIZE; } #endif if (SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) != 1) { ABORT_FINALIZE( net_ossl_store_log_error(RS_RET_TLS_KEY_ERR, "SSL_CTX_use_PrivateKey_file", "private key", keyFile)); } finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/zstdw.c0000644000000000000000000000013215145046113015541 xustar0030 mtime=1771326539.022014011 30 atime=1787067618.323443103 30 ctime=1787067794.613729136 rsyslog-8.2608.0/runtime/zstdw.c0000664000175000017500000001367115145046113015215 0ustar00rgerrger/* The zstdw object. * * This is an rsyslog object wrapper around zstd. * * Copyright 2022 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "errmsg.h" #include "stream.h" #include "module-template.h" #include "obj.h" #include "zstdw.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; /* finish buffer, to be called before closing the zstd file. */ static rsRetVal zstd_doCompressFinish(strm_t *pThis, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)) { size_t remaining = 0; DEFiRet; assert(pThis != NULL); if (!pThis->bzInitDone) goto done; char dummybuf; /* not sure if we can pass in NULL as buffer address in this special case */ ZSTD_inBuffer input = {&dummybuf, 0, 0}; do { ZSTD_outBuffer output = {pThis->pZipBuf, pThis->sIOBufSize, 0}; remaining = ZSTD_compressStream2(pThis->zstd.cctx, &output, &input, ZSTD_e_end); if (ZSTD_isError(remaining)) { LogError(0, RS_RET_ZLIB_ERR, "error returned from ZSTD_compressStream2(): %s\n", ZSTD_getErrorName(remaining)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } CHKiRet(strmPhysWrite(pThis, (uchar *)pThis->pZipBuf, output.pos)); } while (remaining != 0); finalize_it: done: RETiRet; } static rsRetVal zstd_doStrmWrite(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)) { DEFiRet; assert(pThis != NULL); assert(pBuf != NULL); if (!pThis->bzInitDone) { pThis->zstd.cctx = (void *)ZSTD_createCCtx(); if (pThis->zstd.cctx == NULL) { LogError(0, RS_RET_ZLIB_ERR, "error creating zstd context (ZSTD_createCCtx failed, " "that's all we know"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_compressionLevel, pThis->iZipLevel); ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_checksumFlag, 1); if (pThis->zstd.num_wrkrs > 0) { ZSTD_CCtx_setParameter(pThis->zstd.cctx, ZSTD_c_nbWorkers, pThis->zstd.num_wrkrs); } pThis->bzInitDone = RSTRUE; } /* now doing the compression */ ZSTD_inBuffer input = {pBuf, lenBuf, 0}; // This following needs to be configurable? It's possibly sufficient to use e_flush // only, as this can also be controlled by veryRobustZip. However, testbench will than // not be able to check when all file lines are complete. ZSTD_EndDirective const mode = bFlush ? ZSTD_e_flush : ZSTD_e_continue; size_t remaining; do { ZSTD_outBuffer output = {pThis->pZipBuf, 128, 0}; remaining = ZSTD_compressStream2(pThis->zstd.cctx, &output, &input, mode); if (ZSTD_isError(remaining)) { LogError(0, RS_RET_ZLIB_ERR, "error returned from ZSTD_compressStream2(): %s", ZSTD_getErrorName(remaining)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } CHKiRet(strmPhysWrite(pThis, (uchar *)pThis->pZipBuf, output.pos)); } while (mode == ZSTD_e_end ? (remaining != 0) : (input.pos != input.size)); finalize_it: if (pThis->bzInitDone && pThis->bVeryReliableZip) { zstd_doCompressFinish(pThis, strmPhysWrite); } RETiRet; } /* destruction of caller's zstd ressources */ static rsRetVal zstd_Destruct(strm_t *const pThis) { DEFiRet; assert(pThis != NULL); if (!pThis->bzInitDone) goto done; const int result = ZSTD_freeCCtx(pThis->zstd.cctx); if (ZSTD_isError(result)) { LogError(0, RS_RET_ZLIB_ERR, "error from ZSTD_freeCCtx(): %s", ZSTD_getErrorName(result)); } pThis->bzInitDone = 0; done: RETiRet; } /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(zstdw) CODESTARTobjQueryInterface(zstdw); if (pIf->ifVersion != zstdwCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } pIf->doStrmWrite = zstd_doStrmWrite; pIf->doCompressFinish = zstd_doCompressFinish; pIf->Destruct = zstd_Destruct; finalize_it: ENDobjQueryInterface(zstdw) /* Initialize the zstdw class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(zstdw, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ ENDObjClassInit(zstdw) /* Exit the class. */ BEGINObjClassExit(zstdw, OBJ_IS_LOADABLE_MODULE) /* class, version */ CODESTARTObjClassExit(zstdw); ENDObjClassExit(zstdw) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; zstdwClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CHKiRet(zstdwClassInit(pModInfo)); ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/tcpclt.h0000644000000000000000000000013015145046113015662 xustar0030 mtime=1771326539.017013929 28 atime=1787067618.4734459 30 ctime=1787067794.597728838 rsyslog-8.2608.0/runtime/tcpclt.h0000664000175000017500000000520115145046113015326 0ustar00rgerrger/* tcpclt.h * * This are the definitions for the TCP based clients class. * * File begun on 2007-07-21 by RGerhards (extracted from syslogd.c) * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef TCPCLT_H_INCLUDED #define TCPCLT_H_INCLUDED 1 #include "obj.h" /* the tcpclt object */ typedef struct tcpclt_s { BEGINobjInstance ; /**< Data to implement generic object - MUST be the first data element! */ TCPFRAMINGMODE tcp_framing; uchar tcp_framingDelimiter; char *prevMsg; short bResendLastOnRecon; /* should the last message be resent on a successful reconnect? */ size_t lenPrevMsg; /* session specific callbacks */ int iNumMsgs; /* number of messages during current "rebind session" */ rsRetVal (*initFunc)(void *); rsRetVal (*sendFunc)(void *, char *, size_t); rsRetVal (*prepRetryFunc)(void *); } tcpclt_t; /* interfaces */ BEGINinterface(tcpclt) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(tcpclt_t **ppThis); rsRetVal (*ConstructFinalize)(tcpclt_t __attribute__((unused)) * pThis); rsRetVal (*Destruct)(tcpclt_t **ppThis); int (*Send)(tcpclt_t *pThis, void *pData, char *msg, size_t len); int (*CreateSocket)(struct addrinfo *addrDest); /* set methods */ rsRetVal (*SetResendLastOnRecon)(tcpclt_t *, int); rsRetVal (*SetSendInit)(tcpclt_t *, rsRetVal (*)(void *)); rsRetVal (*SetSendFrame)(tcpclt_t *, rsRetVal (*)(void *, char *, size_t)); rsRetVal (*SetSendPrepRetry)(tcpclt_t *, rsRetVal (*)(void *)); rsRetVal (*SetFraming)(tcpclt_t *, TCPFRAMINGMODE framing); /* v4, 2017-06-10*/ rsRetVal (*SetFramingDelimiter)(tcpclt_t *, uchar tcp_framingDelimiter); ENDinterface(tcpclt) #define tcpcltCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObjFull(tcpclt); /* the name of our library binary */ #define LM_TCPCLT_FILENAME "lmtcpclt" #endif /* #ifndef TCPCLT_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/linkedlist.h0000644000000000000000000000013115132411300016522 xustar0030 mtime=1768559296.265885624 29 atime=1787067616.82641519 30 ctime=1787067794.314723564 rsyslog-8.2608.0/runtime/linkedlist.h0000666000175000017500000000601215132411300016170 0ustar00rgerrger/* Definition of the linkedlist object. * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef LINKEDLIST_H_INCLUDED #define LINKEDLIST_H_INCLUDED /* this is a single entry for a parse routine. It describes exactly * one entry point/handler. * The short name is cslch (Configfile SysLine CommandHandler) */ struct llElt_s { /* config file sysline parse entry */ struct llElt_s *pNext; void *pKey; /* key for this element */ void *pData; /* user-supplied data pointer */ }; typedef struct llElt_s llElt_t; /* this is the list of known configuration commands with pointers to * their handlers. * The short name is cslc (Configfile SysLine Command) */ struct linkedList_s { /* config file sysline parse entry */ int iNumElts; /* number of elements in list */ rsRetVal (*pEltDestruct)(void *pData); /* destructor for user pointer in llElt_t's */ rsRetVal (*pKeyDestruct)(void *pKey); /* destructor for key pointer in llElt_t's */ int (*cmpOp)(void *, void *); /* pointer to key compare operation function, retval like strcmp */ void *pKey; /* the list key (searchable, if set) */ llElt_t *pRoot; /* list root */ llElt_t *pLast; /* list tail */ }; typedef struct linkedList_s linkedList_t; typedef llElt_t *linkedListCookie_t; /* this type avoids exposing internals and keeps us flexible */ /* prototypes */ rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(void *), rsRetVal (*pKeyDestructor)(void *), int (*pCmpOp)(void *, void *)); rsRetVal llDestroy(linkedList_t *pThis); rsRetVal llDestroyRootElt(linkedList_t *pThis); rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr); rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData); rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData); rsRetVal llGetKey(llElt_t *pThis, void *ppData); rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt); rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void *, void *), void *pParam); rsRetVal llFindAndDelete(linkedList_t *pThis, void *pKey); /* use the macro below to define a function that will be executed by * llExecFunc() */ #define DEFFUNC_llExecFunc(funcName) \ static rsRetVal funcName(void __attribute__((unused)) * pData, void __attribute__((unused)) * pParam) #endif /* #ifndef LINKEDLIST_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/outchannel.c0000644000000000000000000000013215216464436016541 xustar0030 mtime=1782212894.037266362 30 atime=1787067618.126439429 30 ctime=1787067794.491726862 rsyslog-8.2608.0/runtime/outchannel.c0000664000175000017500000001642315216464436016213 0ustar00rgerrger/* This is the output channel processing code of rsyslog. * Output channels - in the long term - will define how * messages will be sent to whatever file or other medium. * Currently, they mainly provide a way to store some file-related * information (most importantly the maximum file size allowed). * Please see syslogd.c for license information. * begun 2005-06-21 rgerhards * * Copyright (C) 2005-2016 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include "stringbuf.h" #include "outchannel.h" #include "rsconf.h" #include "debug.h" /* Constructs a outchannel list object. Returns pointer to it * or NULL (if it fails). */ struct outchannel *ochConstruct(void) { struct outchannel *pOch; if ((pOch = calloc(1, sizeof(struct outchannel))) == NULL) return NULL; /* basic initialisaion is done via calloc() - need to * initialize only values != 0. */ if (loadConf->och.ochLast == NULL) { /* we are the first element! */ loadConf->och.ochRoot = loadConf->och.ochLast = pOch; } else { loadConf->och.ochLast->pNext = pOch; loadConf->och.ochLast = pOch; } return (pOch); } /* skips the next comma and any whitespace * in front and after it. */ static void skip_Comma(uchar **pp) { register uchar *p; assert(pp != NULL); assert(*pp != NULL); p = *pp; while (isspace(*p)) ++p; if (*p == ',') ++p; while (isspace(*p)) ++p; *pp = p; } /* helper to ochAddLine. Parses a comma-delimited field * The field is delimited by SP or comma. Leading whitespace * is "eaten" and does not become part of the field content. */ static rsRetVal get_Field(uchar **pp, uchar **pField) { DEFiRet; register uchar *p; cstr_t *pStrB = NULL; assert(pp != NULL); assert(*pp != NULL); assert(pField != NULL); skip_Comma(pp); p = *pp; CHKiRet(cstrConstruct(&pStrB)); /* copy the field */ while (*p && *p != ' ' && *p != ',') { CHKiRet(cstrAppendChar(pStrB, *p++)); } *pp = p; cstrFinalize(pStrB); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pField, 0)); finalize_it: if (iRet != RS_RET_OK) { if (pStrB != NULL) cstrDestruct(&pStrB); } RETiRet; } /* helper to ochAddLine. Parses a off_t type from the * input line. * returns: 0 - ok, 1 - failure */ static int get_off_t(uchar **pp, off_t *pOff_t) { register uchar *p; off_t val; assert(pp != NULL); assert(*pp != NULL); assert(pOff_t != NULL); skip_Comma(pp); p = *pp; val = 0; while (*p && isdigit((int)*p)) { val = val * 10 + (*p - '0'); ++p; } *pp = p; *pOff_t = val; return 0; } /* helper to ochAddLine. Parses everything from the * current position to the end of line and returns it * to the caller. Leading white space is removed, but * not trailing. */ static rsRetVal get_restOfLine(uchar **pp, uchar **pBuf) { DEFiRet; register uchar *p; cstr_t *pStrB = NULL; assert(pp != NULL); assert(*pp != NULL); assert(pBuf != NULL); skip_Comma(pp); p = *pp; CHKiRet(cstrConstruct(&pStrB)); /* copy the field */ while (*p) { CHKiRet(cstrAppendChar(pStrB, *p++)); } *pp = p; cstrFinalize(pStrB); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, pBuf, 0)); finalize_it: if (iRet != RS_RET_OK) { if (pStrB != NULL) cstrDestruct(&pStrB); } RETiRet; } /* Add a new outchannel line * returns pointer to new object if it succeeds, NULL otherwise. * An outchannel line is primarily a set of fields delemited by commas. * There might be some whitespace between the field (but not within) * and the commas. This can be removed. */ struct outchannel *ochAddLine(char *pName, uchar **ppRestOfConfLine) { struct outchannel *pOch; uchar *p; assert(pName != NULL); assert(ppRestOfConfLine != NULL); if ((pOch = ochConstruct()) == NULL) return NULL; pOch->iLenName = strlen(pName); pOch->pszName = (char *)malloc(pOch->iLenName + 1); if (pOch->pszName == NULL) { dbgprintf("ochAddLine could not alloc memory for outchannel name!"); pOch->iLenName = 0; return NULL; /* I know - we create a memory leak here - but I deem * it acceptable as it is a) a very small leak b) very * unlikely to happen. rgerhards 2004-11-17 */ } memcpy(pOch->pszName, pName, pOch->iLenName + 1); /* now actually parse the line */ p = *ppRestOfConfLine; assert(p != NULL); /* get params */ get_Field(&p, &pOch->pszFileTemplate); if (*p) get_off_t(&p, &pOch->uSizeLimit); if (*p) get_restOfLine(&p, &pOch->cmdOnSizeLimit); *ppRestOfConfLine = p; return (pOch); } /* Find a outchannel object based on name. Search * currently is case-sensitive (should we change?). * returns pointer to outchannel object if found and * NULL otherwise. * rgerhards 2004-11-17 */ struct outchannel *ochFind(char *pName, int iLenName) { struct outchannel *pOch; assert(pName != NULL); pOch = loadConf->och.ochRoot; while (pOch != NULL && !(pOch->iLenName == iLenName && !strcmp(pOch->pszName, pName))) { pOch = pOch->pNext; } return (pOch); } /* Destroy the outchannel structure. This is for de-initialization * at program end. Everything is deleted. * rgerhards 2005-02-22 */ void ochDeleteAll(void) { struct outchannel *pOch, *pOchDel; pOch = runConf->och.ochRoot; while (pOch != NULL) { dbgprintf("Delete Outchannel: Name='%s'\n ", pOch->pszName == NULL ? "NULL" : pOch->pszName); pOchDel = pOch; pOch = pOch->pNext; if (pOchDel->pszName != NULL) free(pOchDel->pszName); if (pOchDel->pszFileTemplate != NULL) free(pOchDel->pszFileTemplate); if (pOchDel->cmdOnSizeLimit != NULL) free(pOchDel->cmdOnSizeLimit); free(pOchDel); } } /* Print the outchannel structure. This is more or less a * debug or test aid, but anyhow I think it's worth it... */ void ochPrintList(rsconf_t *cnf) { struct outchannel *pOch; pOch = cnf->och.ochRoot; while (pOch != NULL) { dbgprintf("Outchannel: Name='%s'\n", pOch->pszName == NULL ? "NULL" : pOch->pszName); dbgprintf("\tFile Template: '%s'\n", pOch->pszFileTemplate == NULL ? "NULL" : (char *)pOch->pszFileTemplate); dbgprintf("\tMax Size.....: %lu\n", (long unsigned)pOch->uSizeLimit); dbgprintf("\tOnSizeLimtCmd: '%s'\n", pOch->cmdOnSizeLimit == NULL ? "NULL" : (char *)pOch->cmdOnSizeLimit); pOch = pOch->pNext; /* done, go next */ } } /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_state.h0000644000000000000000000000013215241075234017227 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.418725502 rsyslog-8.2608.0/runtime/segdisk_state.h0000664000175000017500000000343215241075234016675 0ustar00rgerrger/* Fixed-size durable state codec for queue.type="segmentedDisk". */ #ifndef INCLUDED_SEGDISK_STATE_H #define INCLUDED_SEGDISK_STATE_H #include #include "rsyslog.h" #define SEGDISK_STATE_STORE_VERSION 2u #define SEGDISK_STATE_SLOT_LEN 256u #define SEGDISK_STATE_FILE_LEN (2u * SEGDISK_STATE_SLOT_LEN) typedef struct segdisk_state_image_s { unsigned char uuid[16]; uint64_t generation; uint32_t flags; uint64_t committed_segment; int64_t committed_offset; uint64_t committed_record_sequence; uint64_t first_live_segment; uint64_t last_data_segment; uint64_t active_segment; uint64_t recovery_first; uint64_t recovery_last; uint64_t next_segment; uint64_t known_queue_size; int64_t bytes; uint64_t segments; uint64_t writer_segment; int64_t writer_end; uint64_t writer_sequence; uint64_t writer_count; uint64_t delete_first; uint64_t delete_last; int64_t delete_bytes; uint64_t delete_segments; } segdisk_state_image_t; void segdiskStateEncode(const segdisk_state_image_t *state, uint64_t generation, unsigned char slot[SEGDISK_STATE_SLOT_LEN]); sbool segdiskStateValidate(const unsigned char slot[SEGDISK_STATE_SLOT_LEN]); void segdiskStateDecode(const unsigned char slot[SEGDISK_STATE_SLOT_LEN], segdisk_state_image_t *state); sbool segdiskStateGenerationNewer(uint64_t candidate, uint64_t reference); rsRetVal segdiskStateSelect(const unsigned char slot0[SEGDISK_STATE_SLOT_LEN], sbool present0, const unsigned char slot1[SEGDISK_STATE_SLOT_LEN], sbool present1, segdisk_state_image_t *state, int *selected_slot); #endif rsyslog-8.2608.0/runtime/PaxHeaders/threads.c0000644000000000000000000000013215241075234016023 xustar0030 mtime=1787067036.612578425 30 atime=1787067036.759581178 30 ctime=1787067794.468726434 rsyslog-8.2608.0/runtime/threads.c0000664000175000017500000002254015241075234015472 0ustar00rgerrger/* threads.c * * This file implements threading support helpers (and maybe the thread object) * for rsyslog. * * File begun on 2007-12-14 by RGerhards * * Copyright 2007-2016 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_PRCTL_H #include #endif #include "rsyslog.h" #include "dirty.h" #include "linkedlist.h" #include "threads.h" #include "srUtils.h" #include "errmsg.h" #include "glbl.h" #include "unicode-helper.h" #include "rsconf.h" /* linked list of currently-known threads */ static linkedList_t llThrds; /* methods */ /* Construct a new thread object */ static rsRetVal thrdConstruct(thrdInfo_t **ppThis) { DEFiRet; thrdInfo_t *pThis; assert(ppThis != NULL); CHKmalloc(pThis = calloc(1, sizeof(thrdInfo_t))); pthread_mutex_init(&pThis->mutThrd, NULL); pthread_cond_init(&pThis->condThrdTerm, NULL); INIT_ATOMIC_HELPER_MUT(pThis->mutShallStop); *ppThis = pThis; finalize_it: RETiRet; } /* Destructs a thread object. The object must not be linked to the * linked list of threads. Please note that the thread should have been * stopped before. If not, we try to do it. */ static rsRetVal thrdDestruct(thrdInfo_t *pThis) { DEFiRet; assert(pThis != NULL); pthread_mutex_lock(&pThis->mutThrd); if (pThis->bIsActive == 1) { pthread_mutex_unlock(&pThis->mutThrd); thrdTerminate(pThis); } else { pthread_mutex_unlock(&pThis->mutThrd); pthread_join(pThis->thrdID, NULL); } /* call cleanup function, if any */ if (pThis->pAfterRun != NULL) pThis->pAfterRun(pThis); pthread_mutex_destroy(&pThis->mutThrd); pthread_cond_destroy(&pThis->condThrdTerm); DESTROY_ATOMIC_HELPER_MUT(pThis->mutShallStop); free(pThis->name); free(pThis); RETiRet; } /* terminate a thread via the non-cancel interface * This is a separate function as it involves a bit more of code. * rgerhads, 2009-10-15 */ static rsRetVal thrdTerminateNonCancel(thrdInfo_t *pThis) { struct timespec tTimeout; int ret; int was_active; DEFiRet; assert(pThis != NULL); DBGPRINTF("request term via SIGTTIN for input thread '%s' %p\n", pThis->name, (void *)pThis->thrdID); thrdSetShallStop(pThis); d_pthread_mutex_lock(&pThis->mutThrd); timeoutComp(&tTimeout, runConf->globals.inputTimeoutShutdown); was_active = pThis->bIsActive; while (was_active) { if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslogd debug: info: trying to cooperatively stop " "input %s, timeout %d ms\n", pThis->name, runConf->globals.inputTimeoutShutdown); } DBGPRINTF("thread %s: initiating termination, timeout %d ms\n", pThis->name, runConf->globals.inputTimeoutShutdown); const int r = pthread_kill(pThis->thrdID, SIGTTIN); if (r != 0) { LogError(r, RS_RET_INTERNAL_ERROR, "error terminating thread %s " "this may cause shutdown issues", pThis->name); } ret = d_pthread_cond_timedwait(&pThis->condThrdTerm, &pThis->mutThrd, &tTimeout); if (ret == ETIMEDOUT) { DBGPRINTF( "input thread term: timeout expired waiting on thread %s " "termination - canceling\n", pThis->name); if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslogd debug: input thread term: " "timeout expired waiting on thread %s " "termination - canceling\n", pThis->name); } pthread_cancel(pThis->thrdID); break; } else if (ret != 0) { char errStr[1024]; int err = ret; rs_strerror_r(err, errStr, sizeof(errStr)); DBGPRINTF("input thread term: cond_wait returned with error %d: %s\n", err, errStr); } was_active = pThis->bIsActive; } d_pthread_mutex_unlock(&pThis->mutThrd); if (was_active) { DBGPRINTF("non-cancel input thread termination FAILED for thread %s %p\n", pThis->name, (void *)pThis->thrdID); } else { DBGPRINTF("non-cancel input thread termination succeeded for thread %s %p\n", pThis->name, (void *)pThis->thrdID); } RETiRet; } /* terminate a thread gracefully. */ rsRetVal thrdTerminate(thrdInfo_t *pThis) { DEFiRet; assert(pThis != NULL); if (pThis->bNeedsCancel) { DBGPRINTF("request term via canceling for input thread %s\n", pThis->name); if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslogd debug: request term via canceling for " "input thread %s\n", pThis->name); } pthread_cancel(pThis->thrdID); } else { thrdTerminateNonCancel(pThis); } pthread_join(pThis->thrdID, NULL); /* wait for input thread to complete */ RETiRet; } /* terminate all known threads gracefully. */ rsRetVal thrdTerminateAll(void) { DEFiRet; llDestroy(&llThrds); RETiRet; } /* This is an internal wrapper around the user thread function. Its * purpose is to handle all the necessary housekeeping stuff so that the * user function needs not to be aware of the threading calls. The user * function call has just "normal", non-threading semantics. * rgerhards, 2007-12-17 */ static ATTR_NORETURN void *thrdStarter(void *const arg) { DEFiRet; thrdInfo_t *const pThis = (thrdInfo_t *)arg; #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) uchar thrdName[32] = "in:"; #endif assert(pThis != NULL); assert(pThis->pUsrThrdMain != NULL); #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) ustrncpy(thrdName + 3, pThis->name, 20); dbgOutputTID((char *)thrdName); /* set thread name - we ignore if the call fails, has no harsh consequences... */ if (prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", pThis->name); } else { DBGPRINTF("set thread name to '%s'\n", thrdName); } #endif /* block all signals except SIGTTIN and SIGSEGV */ sigset_t sigSet; sigfillset(&sigSet); sigdelset(&sigSet, SIGTTIN); sigdelset(&sigSet, SIGSEGV); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); /* setup complete, we are now ready to execute the user code. We will not * regain control until the user code is finished, in which case we terminate * the thread. */ iRet = pThis->pUsrThrdMain(pThis); if (iRet == RS_RET_OK) { dbgprintf("thrdStarter: usrThrdMain %s - 0x%lx returned with iRet %d, exiting now.\n", pThis->name, (unsigned long)pThis->thrdID, iRet); } else { LogError(0, iRet, "main thread of %s terminated abnormally", pThis->name); } /* signal master control that we exit (we do the mutex lock mostly to * keep the thread debugger happer, it would not really be necessary with * the logic we employ...) */ d_pthread_mutex_lock(&pThis->mutThrd); pThis->bIsActive = 0; pthread_cond_signal(&pThis->condThrdTerm); d_pthread_mutex_unlock(&pThis->mutThrd); pthread_exit(0); } /* Start a new thread and add it to the list of currently * executing threads. It is added at the end of the list. * rgerhards, 2007-12-14 */ rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t *), rsRetVal (*afterRun)(thrdInfo_t *), sbool bNeedsCancel, uchar *name) { DEFiRet; thrdInfo_t *pThis; #if defined(_AIX) pthread_attr_t aix_attr; #endif assert(thrdMain != NULL); CHKiRet(thrdConstruct(&pThis)); pThis->bIsActive = 1; pThis->pUsrThrdMain = thrdMain; pThis->pAfterRun = afterRun; pThis->bNeedsCancel = bNeedsCancel; pThis->name = ustrdup(name); #if defined(_AIX) pthread_attr_init(&aix_attr); pthread_attr_setstacksize(&aix_attr, 4096 * 512); pthread_create(&pThis->thrdID, &aix_attr, thrdStarter, pThis); #else pthread_create(&pThis->thrdID, &default_thread_attr, thrdStarter, pThis); #endif CHKiRet(llAppend(&llThrds, NULL, pThis)); finalize_it: RETiRet; } /* initialize the thread-support subsystem * must be called once at the start of the program */ rsRetVal thrdInit(void) { DEFiRet; iRet = llInit(&llThrds, (rsRetVal(*)(void *))thrdDestruct, NULL, NULL); RETiRet; } /* de-initialize the thread subsystem * must be called once at the end of the program */ rsRetVal thrdExit(void) { DEFiRet; iRet = llDestroy(&llThrds); RETiRet; } /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/gss-token-util.h0000644000000000000000000000013215171370365017270 xustar0030 mtime=1776677109.436913002 30 atime=1782715518.781788721 30 ctime=1787067794.523727459 rsyslog-8.2608.0/runtime/gss-token-util.h0000664000175000017500000000640215171370365016736 0ustar00rgerrger/* SPDX-License-Identifier: Apache-2.0 */ /* gss-token-util.h * * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef GSS_TOKEN_UTIL_H_INCLUDED #define GSS_TOKEN_UTIL_H_INCLUDED 1 /** * @file gss-token-util.h * @brief Shared helpers for bounded GSS token framing in rsyslog. * * This header centralizes small, header-only helpers that validate GSS wire * framing and derive conservative token-size limits. It exists so the common * GSS runtime helper and both GSS modules use the same length-decoding and * size-bound logic instead of open-coding slightly different checks. * * Current users include: * - `runtime/gss-misc.c` for framed token receive time/size enforcement * - `plugins/imgssapi/imgssapi.c` for server-side handshake/message limits * - `plugins/omgssapi/omgssapi.c` for client-side handshake limits */ #include #include #include #include "rsyslog.h" #define GSS_TOKEN_MAX_HANDSHAKE_BYTES (1024U * 1024U) #define GSS_TOKEN_MAX_WRAP_OVERHEAD_BYTES (64U * 1024U) #define GSS_TOKEN_IO_TIMEOUT_SECS 10U /** * @brief Decode a 4-byte GSS wire length field and validate it against a limit. * * GSS token framing in rsyslog uses a fixed 4-byte network-order length prefix. * Callers use this helper before allocating buffers or attempting to read token * bodies from the peer. * * @param[in] lenbuf Four bytes containing the network-order token length. * @param[in] max_len Maximum token size the caller is willing to accept. * @param[out] token_len Decoded token length on success. * * @retval RS_RET_OK Length decoded and within @p max_len. * @retval RS_RET_INVALID_PARAMS @p token_len is NULL. * @retval RS_RET_INVALID_VALUE Decoded length exceeds @p max_len. */ static inline rsRetVal gssTokenDecodeLength(const unsigned char lenbuf[4], size_t max_len, size_t *const token_len) { const uint32_t wire_len = ((uint32_t)lenbuf[0] << 24) | ((uint32_t)lenbuf[1] << 16) | ((uint32_t)lenbuf[2] << 8) | (uint32_t)lenbuf[3]; if (token_len == NULL) { return RS_RET_INVALID_PARAMS; } *token_len = (size_t)wire_len; if ((size_t)wire_len > max_len) { return RS_RET_INVALID_VALUE; } return RS_RET_OK; } /** * @brief Derive a safe wrapped-token size limit from a plaintext message limit. * * Wrapped GSS messages carry protocol overhead beyond the unwrapped syslog * payload. Receivers use this helper to cap the framed token size while still * accepting valid wrapped messages for a given plaintext maximum. * * @param[in] max_plaintext_len Maximum accepted plaintext message length. * * @return The wrapped-token limit derived from @p max_plaintext_len. If adding * the configured overhead would overflow `size_t`, `SIZE_MAX` is * returned instead. */ static inline size_t gssTokenGetMessageLimit(size_t max_plaintext_len) { if (max_plaintext_len > SIZE_MAX - GSS_TOKEN_MAX_WRAP_OVERHEAD_BYTES) { return SIZE_MAX; } return max_plaintext_len + GSS_TOKEN_MAX_WRAP_OVERHEAD_BYTES; } #endif rsyslog-8.2608.0/runtime/PaxHeaders/perctile_ringbuf.h0000644000000000000000000000013215132411300017704 xustar0030 mtime=1768559296.272885735 30 atime=1787067618.041437845 30 ctime=1787067794.370724608 rsyslog-8.2608.0/runtime/perctile_ringbuf.h0000666000175000017500000000156415132411300017360 0ustar00rgerrger#include #include typedef int64_t ITEM; struct circ_buf { ITEM *buf; int head; int tail; }; struct ringbuf_s { struct circ_buf cb; size_t size; }; typedef struct ringbuf_s ringbuf_t; ringbuf_t *ringbuf_new(size_t count); void ringbuf_del(ringbuf_t *rb); int ringbuf_append(ringbuf_t *rb, ITEM item); int ringbuf_append_with_overwrite(ringbuf_t *rb, ITEM item); int ringbuf_read(ringbuf_t *rb, ITEM *buf, size_t count); size_t ringbuf_read_to_end(ringbuf_t *rb, ITEM *buf, size_t count); bool ringbuf_peek(ringbuf_t *rb, ITEM *item); size_t ringbuf_capacity(ringbuf_t *rb); /* ringbuffer tests */ void ringbuf_init_test(void); void ringbuf_simple_test(void); void ringbuf_append_test(void); void ringbuf_append_wrap_test(void); void ringbuf_append_overwrite_test(void); void ringbuf_read_test(void); void ringbuf_read_to_end_test(void); rsyslog-8.2608.0/runtime/PaxHeaders/ruleset.c0000644000000000000000000000013215241075234016054 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.756581122 30 ctime=1787067794.425725633 rsyslog-8.2608.0/runtime/ruleset.c0000664000175000017500000011436015241075234015525 0ustar00rgerrger/* ruleset.c - rsyslog's ruleset object * * We have a two-way structure of linked lists: one config-specifc linked list * (conf->rulesets.llRulesets) hold alls rule sets that we know. Included in each * list is a list of rules (which contain a list of actions, but that's * a different story). * * Usually, only a single rule set is executed. However, there exist some * situations where all rules must be iterated over, for example on HUP. Thus, * we also provide interfaces to do that. * * Module begun 2009-06-10 by Rainer Gerhards * * Copyright 2009-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "obj.h" #include "cfsysline.h" #include "msg.h" #include "ruleset.h" #include "errmsg.h" #include "parser.h" #include "batch.h" #include "unicode-helper.h" #include "rsconf.h" #include "action.h" #include "rainerscript.h" #include "srUtils.h" #include "modules.h" #include "wti.h" #include "dirty.h" /* for main ruleset queue creation */ /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(parser) /* tables for interfacing with the v6 config system (as far as we need to) */ static struct cnfparamdescr rspdescr[] = {{"name", eCmdHdlrString, CNFPARAM_REQUIRED}, {"parser", eCmdHdlrArray, 0}}; static struct cnfparamblk rspblk = {CNFPARAMBLK_VERSION, sizeof(rspdescr) / sizeof(struct cnfparamdescr), rspdescr}; #define RULESET_CALL_DEPTH_MAX 1024 /* forward definitions */ static rsRetVal processBatch(batch_t *pBatch, wti_t *pWti); static rsRetVal scriptExec(struct cnfstmt *root, smsg_t *pMsg, wti_t *pWti); /* ---------- linked-list key handling functions (ruleset) ---------- */ /* destructor for linked list keys. */ rsRetVal rulesetKeyDestruct(void __attribute__((unused)) * pData) { free(pData); return RS_RET_OK; } /* ---------- END linked-list key handling functions (ruleset) ---------- */ /* iterate over all actions in a script (stmt subtree) */ static void scriptIterateAllActions(struct cnfstmt *root, rsRetVal (*pFunc)(void *, void *), void *pParam) { struct cnfstmt *stmt; for (stmt = root; stmt != NULL; stmt = stmt->next) { switch (stmt->nodetype) { case S_NOP: case S_STOP: case S_SET: case S_UNSET: case S_CALL_INDIRECT: case S_CALL: /* call does not need to do anything - done in called ruleset! */ break; case S_ACT: DBGPRINTF("iterateAllActions calling into action %p\n", stmt->d.act); pFunc(stmt->d.act, pParam); break; case S_IF: if (stmt->d.s_if.t_then != NULL) scriptIterateAllActions(stmt->d.s_if.t_then, pFunc, pParam); if (stmt->d.s_if.t_else != NULL) scriptIterateAllActions(stmt->d.s_if.t_else, pFunc, pParam); break; case S_FOREACH: if (stmt->d.s_foreach.body != NULL) scriptIterateAllActions(stmt->d.s_foreach.body, pFunc, pParam); break; case S_PRIFILT: if (stmt->d.s_prifilt.t_then != NULL) scriptIterateAllActions(stmt->d.s_prifilt.t_then, pFunc, pParam); if (stmt->d.s_prifilt.t_else != NULL) scriptIterateAllActions(stmt->d.s_prifilt.t_else, pFunc, pParam); break; case S_PROPFILT: scriptIterateAllActions(stmt->d.s_propfilt.t_then, pFunc, pParam); break; case S_RELOAD_LOOKUP_TABLE: /* this is a NOP */ break; default: dbgprintf("error: unknown stmt type %u during iterateAll\n", (unsigned)stmt->nodetype); #ifndef NDEBUG fprintf(stderr, "error: unknown stmt type %u during iterateAll\n", (unsigned)stmt->nodetype); #endif assert(0); /* abort under debugging */ break; } } } /* driver to iterate over all of this ruleset actions */ typedef struct iterateAllActions_s { rsRetVal (*pFunc)(void *, void *); void *pParam; } iterateAllActions_t; /* driver to iterate over all actions */ DEFFUNC_llExecFunc(doIterateAllActions) { DEFiRet; ruleset_t *pThis = (ruleset_t *)pData; iterateAllActions_t *pMyParam = (iterateAllActions_t *)pParam; scriptIterateAllActions(pThis->root, pMyParam->pFunc, pMyParam->pParam); RETiRet; } /* iterate over ALL actions present in the WHOLE system. * this is often needed, for example when HUP processing * must be done or a shutdown is pending. */ static rsRetVal iterateAllActions(rsconf_t *conf, rsRetVal (*pFunc)(void *, void *), void *pParam) { iterateAllActions_t params; DEFiRet; assert(pFunc != NULL); params.pFunc = pFunc; params.pParam = pParam; CHKiRet(llExecFunc(&(conf->rulesets.llRulesets), doIterateAllActions, ¶ms)); finalize_it: RETiRet; } /* driver to iterate over all rulesets */ DEFFUNC_llExecFunc(doActivateRulesetQueues) { DEFiRet; ruleset_t *pThis = (ruleset_t *)pData; dbgprintf("Activating Ruleset Queue[%p] for Ruleset %s\n", pThis->pQueue, pThis->pszName); if (pThis->pQueue != NULL) startMainQueue(runConf, pThis->pQueue); RETiRet; } /* activate all ruleset queues */ rsRetVal activateRulesetQueues(void) { llExecFunc(&(runConf->rulesets.llRulesets), doActivateRulesetQueues, NULL); return RS_RET_OK; } static rsRetVal execAct(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti) { DEFiRet; if (actionIsDisabled(stmt->d.act)) { DBGPRINTF("action %d died, do NOT execute\n", stmt->d.act->iActionNbr); FINALIZE; } DBGPRINTF("executing action %d\n", stmt->d.act->iActionNbr); stmt->d.act->submitToActQ(stmt->d.act, pWti, pMsg); if (iRet != RS_RET_DISCARDMSG) { /* note: we ignore the error code here, as we do NEVER want to * stop script execution due to action return code */ iRet = RS_RET_OK; } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() execSet(const struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const __restrict__ pWti) { struct svar result; DEFiRet; cnfexprEval(stmt->d.s_set.expr, &result, pMsg, pWti); msgSetJSONFromVar(pMsg, stmt->d.s_set.varname, &result, stmt->d.s_set.force_reset); varDelete(&result); RETiRet; } static rsRetVal execUnset(struct cnfstmt *stmt, smsg_t *pMsg) { DEFiRet; msgDelJSON(pMsg, stmt->d.s_unset.varname); RETiRet; } static int rulesetCallDepthExceeded(wti_t *const pWti, const char *const rulesetName, const size_t rulesetNameLen) { if (pWti->execState.rulesetCallDepth < RULESET_CALL_DEPTH_MAX) { return 0; } LogError(0, RS_RET_ERR, "ruleset call nesting limit of %u reached; call to ruleset '%.*s' " "ignored to avoid runaway recursion", RULESET_CALL_DEPTH_MAX, (int)rulesetNameLen, rulesetName); return 1; } static rsRetVal execSynchronousRulesetCall(struct cnfstmt *const root, const char *const rulesetName, const size_t rulesetNameLen, smsg_t *const pMsg, wti_t *const pWti) { DEFiRet; if (rulesetCallDepthExceeded(pWti, rulesetName, rulesetNameLen)) { FINALIZE; } ++pWti->execState.rulesetCallDepth; iRet = scriptExec(root, pMsg, pWti); --pWti->execState.rulesetCallDepth; finalize_it: RETiRet; } static rsRetVal execCallIndirect(struct cnfstmt *const __restrict__ stmt, smsg_t *pMsg, wti_t *const __restrict__ pWti) { ruleset_t *pRuleset; struct svar result; int bMustFree; /* dummy parameter */ DEFiRet; assert(stmt->d.s_call_ind.expr != NULL); cnfexprEval(stmt->d.s_call_ind.expr, &result, pMsg, pWti); uchar *const rsName = (uchar *)var2CString(&result, &bMustFree); const rsRetVal localRet = rulesetGetRuleset(runConf, &pRuleset, rsName); if (localRet != RS_RET_OK) { /* in that case, we accept that a NOP will "survive" */ LogError(0, RS_RET_RULESET_NOT_FOUND, "error: CALL_INDIRECT: " "ruleset '%s' cannot be found, treating as NOP\n", rsName); FINALIZE; } DBGPRINTF("CALL_INDIRECT obtained ruleset ptr %p for ruleset '%s' [hasQueue:%d]\n", pRuleset, rsName, rulesetHasQueue(pRuleset)); if (rulesetHasQueue(pRuleset)) { CHKmalloc(pMsg = MsgDup((smsg_t *)pMsg)); DBGPRINTF("CALL_INDIRECT: forwarding message to async ruleset %p\n", pRuleset->pQueue); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); MsgSetRuleset(pMsg, pRuleset); /* Note: we intentionally use submitMsg2() here, as we process messages * that were already run through the rate-limiter. */ submitMsg2(pMsg); } else { CHKiRet(execSynchronousRulesetCall(pRuleset->root, (const char *)rsName, ustrlen(rsName), pMsg, pWti)); } finalize_it: varDelete(&result); free(rsName); RETiRet; } static rsRetVal execCall(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti) { DEFiRet; if (stmt->d.s_call.ruleset == NULL) { CHKiRet(execSynchronousRulesetCall(stmt->d.s_call.stmt, (const char *)es_getBufAddr(stmt->d.s_call.name), es_strlen(stmt->d.s_call.name), pMsg, pWti)); } else { CHKmalloc(pMsg = MsgDup((smsg_t *)pMsg)); DBGPRINTF("CALL: forwarding message to async ruleset %p\n", stmt->d.s_call.ruleset->pQueue); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); MsgSetRuleset(pMsg, stmt->d.s_call.ruleset); /* Note: we intentionally use submitMsg2() here, as we process messages * that were already run through the rate-limiter. */ submitMsg2(pMsg); } finalize_it: RETiRet; } static rsRetVal execIf(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti) { int bRet; DEFiRet; bRet = cnfexprEvalBool(stmt->d.s_if.expr, pMsg, pWti); DBGPRINTF("if condition result is %d\n", bRet); if (bRet) { if (stmt->d.s_if.t_then != NULL) CHKiRet(scriptExec(stmt->d.s_if.t_then, pMsg, pWti)); } else { if (stmt->d.s_if.t_else != NULL) CHKiRet(scriptExec(stmt->d.s_if.t_else, pMsg, pWti)); } finalize_it: RETiRet; } static rsRetVal invokeForeachBodyWith(struct cnfstmt *stmt, json_object *o, smsg_t *pMsg, wti_t *pWti) { struct svar v; v.datatype = 'J'; v.d.json = o; DEFiRet; CHKiRet(msgSetJSONFromVar(pMsg, (uchar *)stmt->d.s_foreach.iter->var, &v, 1)); CHKiRet(scriptExec(stmt->d.s_foreach.body, pMsg, pWti)); finalize_it: RETiRet; } static rsRetVal callForeachArray(struct cnfstmt *stmt, json_object *arr, smsg_t *pMsg, wti_t *pWti) { DEFiRet; int len = json_object_array_length(arr); json_object *curr; for (int i = 0; i < len; i++) { curr = json_object_array_get_idx(arr, i); CHKiRet(invokeForeachBodyWith(stmt, curr, pMsg, pWti)); } finalize_it: RETiRet; } static rsRetVal callForeachObject(struct cnfstmt *stmt, json_object *arr, smsg_t *pMsg, wti_t *pWti) { json_object *entry = NULL; json_object *key = NULL; const char **keys = NULL; json_object *curr = NULL; const char **curr_key; struct json_object_iterator it; struct json_object_iterator itEnd; DEFiRet; int len = json_object_object_length(arr); CHKmalloc(keys = calloc(len, sizeof(char *))); curr_key = keys; it = json_object_iter_begin(arr); itEnd = json_object_iter_end(arr); while (!json_object_iter_equal(&it, &itEnd)) { *curr_key = json_object_iter_peek_name(&it); curr_key++; json_object_iter_next(&it); } CHKmalloc(entry = json_object_new_object()); for (int i = 0; i < len; i++) { if (json_object_object_get_ex(arr, keys[i], &curr)) { CHKmalloc(key = json_object_new_string(keys[i])); json_object_object_add(entry, "key", key); key = NULL; json_object_object_add(entry, "value", json_object_get(curr)); CHKiRet(invokeForeachBodyWith(stmt, entry, pMsg, pWti)); } } finalize_it: if (keys != NULL) free(keys); if (entry != NULL) json_object_put(entry); /* "fix" Coverity scan issue CID 185393: key currently can NOT be NULL * However, instead of just removing the * if (key != NULL) json_object_put(key); * we put an assertion in its place. */ assert(key == NULL); RETiRet; } static rsRetVal ATTR_NONNULL() execForeach(struct cnfstmt *const stmt, smsg_t *const pMsg, wti_t *const pWti) { json_object *arr = NULL; DEFiRet; /* arr can either be an array or an associative-array (obj) */ arr = cnfexprEvalCollection(stmt->d.s_foreach.iter->collection, pMsg, pWti); if (arr == NULL) { DBGPRINTF("foreach loop skipped, as object to iterate upon is empty\n"); FINALIZE; } else if (json_object_is_type(arr, json_type_array) && json_object_array_length(arr) > 0) { CHKiRet(callForeachArray(stmt, arr, pMsg, pWti)); } else if (json_object_is_type(arr, json_type_object) && json_object_object_length(arr) > 0) { CHKiRet(callForeachObject(stmt, arr, pMsg, pWti)); } else { DBGPRINTF("foreach loop skipped, as object to iterate upon is empty or is not an array\n"); FINALIZE; } CHKiRet(msgDelJSON(pMsg, (uchar *)stmt->d.s_foreach.iter->var)); finalize_it: if (arr != NULL) json_object_put(arr); RETiRet; } static rsRetVal execPRIFILT(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti) { int bRet; DEFiRet; if ((stmt->d.s_prifilt.pmask[pMsg->iFacility] == TABLE_NOPRI) || ((stmt->d.s_prifilt.pmask[pMsg->iFacility] & (1 << pMsg->iSeverity)) == 0)) bRet = 0; else bRet = 1; DBGPRINTF("PRIFILT condition result is %d\n", bRet); if (bRet) { if (stmt->d.s_prifilt.t_then != NULL) CHKiRet(scriptExec(stmt->d.s_prifilt.t_then, pMsg, pWti)); } else { if (stmt->d.s_prifilt.t_else != NULL) CHKiRet(scriptExec(stmt->d.s_prifilt.t_else, pMsg, pWti)); } finalize_it: RETiRet; } /* helper to execPROPFILT(), as the evaluation itself is quite lengthy */ static int evalPROPFILT(struct cnfstmt *stmt, smsg_t *pMsg) { unsigned short pbMustBeFreed; uchar *pszPropVal; int bRet = 0; rs_size_t propLen; if (stmt->d.s_propfilt.prop.id == PROP_INVALID) goto done; pszPropVal = MsgGetProp(pMsg, NULL, &stmt->d.s_propfilt.prop, &propLen, &pbMustBeFreed, NULL); /* Now do the compares (short list currently ;)) */ switch (stmt->d.s_propfilt.operation) { case FIOP_CONTAINS: if (rsCStrLocateInSzStr(stmt->d.s_propfilt.pCSCompValue, (uchar *)pszPropVal) != -1) bRet = 1; break; case FIOP_ISEMPTY: if (propLen == 0) bRet = 1; /* process message! */ break; case FIOP_ISEQUAL: if (rsCStrSzStrCmp(stmt->d.s_propfilt.pCSCompValue, pszPropVal, propLen) == 0) bRet = 1; /* process message! */ break; case FIOP_STARTSWITH: if (rsCStrSzStrStartsWithCStr(stmt->d.s_propfilt.pCSCompValue, pszPropVal, propLen) == 0) bRet = 1; /* process message! */ break; case FIOP_ENDSWITH: if (rsCStrSzStrEndsWithCStr(stmt->d.s_propfilt.pCSCompValue, pszPropVal, propLen) == 0) bRet = 1; /* process message! */ break; case FIOP_REGEX: if (rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue, (unsigned char *)pszPropVal, 0, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK) bRet = 1; break; case FIOP_EREREGEX: if (rsCStrSzStrMatchRegex(stmt->d.s_propfilt.pCSCompValue, (unsigned char *)pszPropVal, 1, &stmt->d.s_propfilt.regex_cache) == RS_RET_OK) bRet = 1; break; case FIOP_NOP: default: /* here, it handles NOP (for performance reasons) */ assert(stmt->d.s_propfilt.operation == FIOP_NOP); bRet = 1; /* as good as any other default ;) */ break; } /* now check if the value must be negated */ if (stmt->d.s_propfilt.isNegated) bRet = (bRet == 1) ? 0 : 1; if (Debug) { if (stmt->d.s_propfilt.prop.id == PROP_CEE) { DBGPRINTF("Filter: check for CEE property '%s' (value '%s') ", stmt->d.s_propfilt.prop.name, pszPropVal); } else if (stmt->d.s_propfilt.prop.id == PROP_LOCAL_VAR) { DBGPRINTF("Filter: check for local var '%s' (value '%s') ", stmt->d.s_propfilt.prop.name, pszPropVal); } else if (stmt->d.s_propfilt.prop.id == PROP_GLOBAL_VAR) { DBGPRINTF("Filter: check for global var '%s' (value '%s') ", stmt->d.s_propfilt.prop.name, pszPropVal); } else { DBGPRINTF("Filter: check for property '%s' (value '%s') ", propIDToName(stmt->d.s_propfilt.prop.id), pszPropVal); } if (stmt->d.s_propfilt.isNegated) DBGPRINTF("NOT "); if (stmt->d.s_propfilt.operation == FIOP_ISEMPTY) { DBGPRINTF("%s : %s\n", getFIOPName(stmt->d.s_propfilt.operation), bRet ? "TRUE" : "FALSE"); } else { DBGPRINTF("%s '%s': %s\n", getFIOPName(stmt->d.s_propfilt.operation), rsCStrGetSzStrNoNULL(stmt->d.s_propfilt.pCSCompValue), bRet ? "TRUE" : "FALSE"); } } /* cleanup */ if (pbMustBeFreed) free(pszPropVal); done: return bRet; } static rsRetVal execPROPFILT(struct cnfstmt *stmt, smsg_t *pMsg, wti_t *pWti) { sbool bRet; DEFiRet; bRet = evalPROPFILT(stmt, pMsg); DBGPRINTF("PROPFILT condition result is %d\n", bRet); if (bRet) CHKiRet(scriptExec(stmt->d.s_propfilt.t_then, pMsg, pWti)); finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() execReloadLookupTable(struct cnfstmt *stmt) { assert(stmt != NULL); lookup_ref_t *t; DEFiRet; t = stmt->d.s_reload_lookup_table.table; if (t == NULL) { ABORT_FINALIZE(RS_RET_NONE); } iRet = lookupReload(t, stmt->d.s_reload_lookup_table.stub_value); /* Note that reload dispatched above is performed asynchronously, on a different thread. So rsRetVal it returns means it was triggered successfully, and not that it was reloaded successfully. */ finalize_it: RETiRet; } /* The rainerscript execution engine. It is debatable if that would be better * contained in grammer/rainerscript.c, HOWEVER, that file focusses primarily * on the parsing and object creation part. So as an actual executor, it is * better suited here. * rgerhards, 2012-09-04 */ static rsRetVal ATTR_NONNULL(2, 3) scriptExec(struct cnfstmt *const root, smsg_t *const pMsg, wti_t *const pWti) { struct cnfstmt *stmt; DEFiRet; for (stmt = root; stmt != NULL; stmt = stmt->next) { if (wtiIsShutdownImmediate(pWti)) { DBGPRINTF( "scriptExec: ShutdownImmediate set, " "force terminating\n"); ABORT_FINALIZE(RS_RET_FORCE_TERM); } if (Debug) { cnfstmtPrintOnly(stmt, 2, 0); } switch (stmt->nodetype) { case S_NOP: break; case S_STOP: ABORT_FINALIZE(RS_RET_DISCARDMSG); break; case S_ACT: CHKiRet(execAct(stmt, pMsg, pWti)); break; case S_SET: CHKiRet(execSet(stmt, pMsg, pWti)); break; case S_UNSET: CHKiRet(execUnset(stmt, pMsg)); break; case S_CALL: CHKiRet(execCall(stmt, pMsg, pWti)); break; case S_CALL_INDIRECT: CHKiRet(execCallIndirect(stmt, pMsg, pWti)); break; case S_IF: CHKiRet(execIf(stmt, pMsg, pWti)); break; case S_FOREACH: CHKiRet(execForeach(stmt, pMsg, pWti)); break; case S_PRIFILT: CHKiRet(execPRIFILT(stmt, pMsg, pWti)); break; case S_PROPFILT: CHKiRet(execPROPFILT(stmt, pMsg, pWti)); break; case S_RELOAD_LOOKUP_TABLE: CHKiRet(execReloadLookupTable(stmt)); break; default: dbgprintf("error: unknown stmt type %u during exec\n", (unsigned)stmt->nodetype); break; } } finalize_it: RETiRet; } /* Process (consume) a batch of messages. Calls the actions configured. * This is called by MAIN queues. */ static rsRetVal processBatch(batch_t *pBatch, wti_t *pWti) { int i; smsg_t *pMsg; ruleset_t *pRuleset; rsRetVal localRet; DEFiRet; DBGPRINTF("processBATCH: batch of %d elements must be processed\n", pBatch->nElem); wtiResetExecState(pWti, pBatch); /* execution phase */ for (i = 0; i < batchNumMsgs(pBatch) && !wtiIsShutdownImmediate(pWti); ++i) { pMsg = pBatch->pElem[i].pMsg; DBGPRINTF("processBATCH: next msg %d: %.128s\n", i, pMsg->pszRawMsg); pRuleset = (pMsg->pRuleset == NULL) ? runConf->rulesets.pDflt : pMsg->pRuleset; localRet = scriptExec(pRuleset->root, pMsg, pWti); /* the most important case here is that processing may be aborted * due to pbShutdownImmediate, in which case we MUST NOT flag this * message as committed. If we would do so, the message would * potentially be lost. */ if (localRet == RS_RET_OK) batchSetElemState(pBatch, i, BATCH_STATE_COMM); else if (localRet == RS_RET_SUSPENDED) --i; } /* commit phase */ DBGPRINTF( "END batch execution phase, entering to commit phase " "[processed %d of %d messages]\n", i, batchNumMsgs(pBatch)); actionCommitAllDirect(pWti); DBGPRINTF("processBATCH: batch of %d elements has been processed\n", pBatch->nElem); RETiRet; } /* return the ruleset-assigned parser list. NULL means use the default * parser list. * rgerhards, 2009-11-04 */ static parserList_t *GetParserList(rsconf_t *conf, smsg_t *pMsg) { return (pMsg->pRuleset == NULL) ? conf->rulesets.pDflt->pParserLst : pMsg->pRuleset->pParserLst; } /* Add a script block to the current ruleset */ static void ATTR_NONNULL(1) addScript(ruleset_t *const pThis, struct cnfstmt *const script) { if (script == NULL) /* happens for include() */ return; if (pThis->last == NULL) pThis->root = pThis->last = script; else { pThis->last->next = script; pThis->last = script; } } /* set name for ruleset */ static rsRetVal rulesetSetName(ruleset_t *pThis, uchar *pszName) { DEFiRet; free(pThis->pszName); CHKmalloc(pThis->pszName = ustrdup(pszName)); finalize_it: RETiRet; } /* get current ruleset * We use a non-standard calling interface, as nothing can go wrong and it * is really much more natural to return the pointer directly. */ static ruleset_t *GetCurrent(rsconf_t *conf) { return conf->rulesets.pCurr; } /* get main queue associated with ruleset. If no ruleset-specifc main queue * is set, the primary main message queue is returned. * We use a non-standard calling interface, as nothing can go wrong and it * is really much more natural to return the pointer directly. */ static qqueue_t *GetRulesetQueue(ruleset_t *pThis) { ISOBJ_TYPE_assert(pThis, ruleset); return (pThis->pQueue == NULL) ? runConf->pMsgQueue : pThis->pQueue; } /* Find the ruleset with the given name and return a pointer to its object. */ rsRetVal rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName) { DEFiRet; assert(ppRuleset != NULL); assert(pszName != NULL); CHKiRet(llFind(&(conf->rulesets.llRulesets), pszName, (void *)ppRuleset)); finalize_it: RETiRet; } /* Set a new default rule set. If the default can not be found, no change happens. */ static rsRetVal SetDefaultRuleset(rsconf_t *conf, uchar *pszName) { ruleset_t *pRuleset; DEFiRet; assert(pszName != NULL); CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName)); conf->rulesets.pDflt = pRuleset; DBGPRINTF("default rule set changed to %p: '%s'\n", pRuleset, pszName); finalize_it: RETiRet; } /* Set a new current rule set. If the ruleset can not be found, no change happens */ static rsRetVal SetCurrRuleset(rsconf_t *conf, uchar *pszName) { ruleset_t *pRuleset; DEFiRet; assert(pszName != NULL); CHKiRet(rulesetGetRuleset(conf, &pRuleset, pszName)); conf->rulesets.pCurr = pRuleset; DBGPRINTF("current rule set changed to %p: '%s'\n", pRuleset, pszName); finalize_it: RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(ruleset) /* be sure to specify the object type also in END macro! */ pThis->root = NULL; pThis->last = NULL; ENDobjConstruct(ruleset) /* ConstructionFinalizer * This also adds the rule set to the list of all known rulesets. */ static rsRetVal rulesetConstructFinalize(rsconf_t *conf, ruleset_t *pThis) { uchar *keyName; DEFiRet; ISOBJ_TYPE_assert(pThis, ruleset); /* we must duplicate our name, as the key destructer would also * free it, resulting in a double-free. It's also cleaner to have * two separate copies. */ CHKmalloc(keyName = ustrdup(pThis->pszName)); CHKiRet(llAppend(&(conf->rulesets.llRulesets), keyName, pThis)); /* and also the default, if so far none has been set */ if (conf->rulesets.pDflt == NULL) conf->rulesets.pDflt = pThis; finalize_it: RETiRet; } /* destructor for the ruleset object */ BEGINobjDestruct(ruleset) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(ruleset); DBGPRINTF("destructing ruleset %p, name %p\n", pThis, pThis->pszName); if (pThis->pQueue != NULL) { qqueueDestruct(&pThis->pQueue); } if (pThis->pParserLst != NULL) { parser.DestructParserList(&pThis->pParserLst); } free(pThis->pszName); ENDobjDestruct(ruleset) /* helper for Destructor, shut down queue workers */ DEFFUNC_llExecFunc(doShutdownQueueWorkers) { DEFiRet; ruleset_t *const pThis = (ruleset_t *)pData; DBGPRINTF("shutting down queue workers for ruleset %p, name %s, queue %p\n", pThis, pThis->pszName, pThis->pQueue); ISOBJ_TYPE_assert(pThis, ruleset); if (pThis->pQueue != NULL) { qqueueShutdownWorkers(pThis->pQueue); } RETiRet; } /* helper for Destructor, shut down actions (cnfstmt's in general) */ DEFFUNC_llExecFunc(doDestructCnfStmt) { DEFiRet; ruleset_t *const pThis = (ruleset_t *)pData; DBGPRINTF("shutting down actions and conf stmts for ruleset %p, name %s\n", pThis, pThis->pszName); ISOBJ_TYPE_assert(pThis, ruleset); cnfstmtDestructLst(pThis->root); RETiRet; } /* destruct ALL rule sets that reside in the system. This must * be callable before unloading this module as the module may * not be unloaded before unload of the actions is required. This is * kind of a left-over from previous logic and may be optimized one * everything runs stable again. -- rgerhards, 2009-06-10 */ static rsRetVal destructAllActions(rsconf_t *conf) { DEFiRet; DBGPRINTF("rulesetDestructAllActions\n"); /* we first need to stop all queue workers, else we * may run into trouble with "call" statements calling * into then-destroyed rulesets. * see: https://github.com/rsyslog/rsyslog/issues/1122 */ DBGPRINTF("destructAllActions: queue shutdown\n"); llExecFunc(&(conf->rulesets.llRulesets), doShutdownQueueWorkers, NULL); DBGPRINTF("destructAllActions: action and conf stmt shutdown\n"); llExecFunc(&(conf->rulesets.llRulesets), doDestructCnfStmt, NULL); CHKiRet(llDestroy(&(conf->rulesets.llRulesets))); CHKiRet(llInit(&(conf->rulesets.llRulesets), rulesetDestructForLinkedList, rulesetKeyDestruct, (int (*)(void *, void *))strcasecmp)); conf->rulesets.pDflt = NULL; finalize_it: RETiRet; } /* this is a special destructor for the linkedList class. LinkedList does NOT * provide a pointer to the pointer, but rather the raw pointer itself. So we * must map this, otherwise the destructor will abort. */ rsRetVal rulesetDestructForLinkedList(void *pData) { ruleset_t *pThis = (ruleset_t *)pData; return rulesetDestruct(&pThis); } /* debugprint for the ruleset object */ BEGINobjDebugPrint(ruleset) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(ruleset); dbgoprint((obj_t *)pThis, "rsyslog ruleset %s:\n", pThis->pszName); cnfstmtPrint(pThis->root, 0); dbgoprint((obj_t *)pThis, "ruleset %s assigned parser list:\n", pThis->pszName); printParserList(pThis->pParserLst); ENDobjDebugPrint(ruleset) /* helper for debugPrintAll(), prints a single ruleset */ DEFFUNC_llExecFunc(doDebugPrintAll) { return rulesetDebugPrint((ruleset_t *)pData); } /* debug print all rulesets */ static rsRetVal debugPrintAll(rsconf_t *conf) { DEFiRet; dbgprintf("All Rulesets:\n"); llExecFunc(&(conf->rulesets.llRulesets), doDebugPrintAll, NULL); dbgprintf("End of Rulesets.\n"); RETiRet; } struct cnfstmt *removeNOPs(struct cnfstmt *root); static void rulesetOptimize(ruleset_t *pRuleset) { if (Debug) { dbgprintf("ruleset '%s' before optimization:\n", pRuleset->pszName); rulesetDebugPrint((ruleset_t *)pRuleset); } pRuleset->root = cnfstmtOptimize(pRuleset->root); if (Debug) { dbgprintf("ruleset '%s' after optimization:\n", pRuleset->pszName); rulesetDebugPrint((ruleset_t *)pRuleset); } } /* helper for rulsetOptimizeAll(), optimizes a single ruleset */ DEFFUNC_llExecFunc(doRulesetOptimizeAll) { rulesetOptimize((ruleset_t *)pData); return RS_RET_OK; } /* optimize all rulesets */ rsRetVal rulesetOptimizeAll(rsconf_t *conf) { DEFiRet; dbgprintf("begin ruleset optimization phase\n"); llExecFunc(&(conf->rulesets.llRulesets), doRulesetOptimizeAll, NULL); dbgprintf("ruleset optimization phase finished.\n"); RETiRet; } /* Create a ruleset-specific "main" queue for this ruleset. If one is already * defined, an error message is emitted but nothing else is done. * Note: we use the main message queue parameters for queue creation and access * syslogd.c directly to obtain these. This is far from being perfect, but * considered acceptable for the time being. * rgerhards, 2009-10-27 */ static rsRetVal doRulesetCreateQueue(rsconf_t *conf, int *pNewVal) { uchar *rsname; DEFiRet; if (conf->rulesets.pCurr == NULL) { LogError(0, RS_RET_NO_CURR_RULESET, "error: currently no specific ruleset specified, thus a " "queue can not be added to it"); ABORT_FINALIZE(RS_RET_NO_CURR_RULESET); } if (conf->rulesets.pCurr->pQueue != NULL) { LogError(0, RS_RET_RULES_QUEUE_EXISTS, "error: ruleset already has a main queue, can not " "add another one"); ABORT_FINALIZE(RS_RET_RULES_QUEUE_EXISTS); } if (pNewVal == 0) FINALIZE; /* if it is turned off, we do not need to change anything ;) */ rsname = (conf->rulesets.pCurr->pszName == NULL) ? (uchar *)"[ruleset]" : conf->rulesets.pCurr->pszName; DBGPRINTF("adding a ruleset-specific \"main\" queue for ruleset '%s'\n", rsname); CHKiRet(createMainQueue(&conf->rulesets.pCurr->pQueue, rsname, NULL)); finalize_it: RETiRet; } static rsRetVal rulesetCreateQueue(void __attribute__((unused)) * pVal, int *pNewVal) { return doRulesetCreateQueue(ourConf, pNewVal); } /* Add a ruleset specific parser to the ruleset. Note that adding the first * parser automatically disables the default parsers. If they are needed as well, * the must be added via explicit config directives. * Note: this is the only spot in the code that requires the parser object. In order * to solve some class init bootstrap sequence problems, we get the object handle here * instead of during module initialization. Note that objUse() is capable of being * called multiple times. * rgerhards, 2009-11-04 */ static rsRetVal doRulesetAddParser(ruleset_t *pRuleset, uchar *pName) { parser_t *pParser; DEFiRet; CHKiRet(objUse(parser, CORE_COMPONENT)); iRet = parser.FindParser(loadConf->parsers.pParsLstRoot, &pParser, pName); if (iRet == RS_RET_PARSER_NOT_FOUND) { LogError(0, RS_RET_PARSER_NOT_FOUND, "error: parser '%s' unknown at this time " "(maybe defined too late in rsyslog.conf?)", pName); ABORT_FINALIZE(RS_RET_NO_CURR_RULESET); } else if (iRet != RS_RET_OK) { LogError(0, iRet, "error trying to find parser '%s'\n", pName); FINALIZE; } CHKiRet(parser.AddParserToList(&pRuleset->pParserLst, pParser)); DBGPRINTF("added parser '%s' to ruleset '%s'\n", pName, pRuleset->pszName); finalize_it: free(pName); /* no longer needed */ RETiRet; } static rsRetVal rulesetAddParser(void __attribute__((unused)) * pVal, uchar *pName) { return doRulesetAddParser(loadConf->rulesets.pCurr, pName); } /* Process ruleset() objects */ rsRetVal rulesetProcessCnf(struct cnfobj *o) { struct cnfparamvals *pvals; rsRetVal localRet; uchar *rsName = NULL; uchar *parserName; int nameIdx, parserIdx; ruleset_t *pRuleset; struct cnfarray *ar; int i; int qtype; uchar *rsname; DEFiRet; pvals = nvlstGetParams(o->nvlst, &rspblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } DBGPRINTF("ruleset param blk after rulesetProcessCnf:\n"); cnfparamsPrint(&rspblk, pvals); nameIdx = cnfparamGetIdx(&rspblk, "name"); rsName = (uchar *)es_str2cstr(pvals[nameIdx].val.d.estr, NULL); localRet = rulesetGetRuleset(loadConf, &pRuleset, rsName); if (localRet == RS_RET_OK) { LogError(0, RS_RET_RULESET_EXISTS, "error: ruleset '%s' specified more than once", rsName); cnfstmtDestructLst(o->script); ABORT_FINALIZE(RS_RET_RULESET_EXISTS); } else if (localRet != RS_RET_NOT_FOUND) { ABORT_FINALIZE(localRet); } CHKiRet(rulesetConstruct(&pRuleset)); if ((localRet = rulesetSetName(pRuleset, rsName)) != RS_RET_OK) { rulesetDestruct(&pRuleset); ABORT_FINALIZE(localRet); } if ((localRet = rulesetConstructFinalize(loadConf, pRuleset)) != RS_RET_OK) { rulesetDestruct(&pRuleset); ABORT_FINALIZE(localRet); } addScript(pRuleset, o->script); /* we have only two params, so we do NOT do the usual param loop */ parserIdx = cnfparamGetIdx(&rspblk, "parser"); if (parserIdx != -1 && pvals[parserIdx].bUsed) { ar = pvals[parserIdx].val.d.ar; for (i = 0; i < ar->nmemb; ++i) { parserName = (uchar *)es_str2cstr(ar->arr[i], NULL); doRulesetAddParser(pRuleset, parserName); /* note parserName is freed in doRulesetAddParser()! */ } } /* pick up ruleset queue parameters */ if (queueCnfParamsSet(o->nvlst)) { if (pRuleset->pszName == NULL) { rsname = (uchar *)"[ruleset]"; qtype = pRuleset->pQueue->qType; } else { rsname = pRuleset->pszName; qtype = 3; } DBGPRINTF("adding a ruleset-specific \"main\" queue for ruleset '%s', mode %d\n", rsname, qtype); CHKiRet(createMainQueue(&pRuleset->pQueue, rsname, o->nvlst)); } finalize_it: free(rsName); cnfparamvalsDestruct(pvals, &rspblk); RETiRet; } /* queryInterface function * rgerhards, 2008-02-21 */ BEGINobjQueryInterface(ruleset) CODESTARTobjQueryInterface(ruleset); if (pIf->ifVersion != rulesetCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = rulesetConstruct; pIf->ConstructFinalize = rulesetConstructFinalize; pIf->Destruct = rulesetDestruct; pIf->DebugPrint = rulesetDebugPrint; pIf->IterateAllActions = iterateAllActions; pIf->DestructAllActions = destructAllActions; pIf->AddScript = addScript; pIf->ProcessBatch = processBatch; pIf->SetName = rulesetSetName; pIf->DebugPrintAll = debugPrintAll; pIf->GetCurrent = GetCurrent; pIf->GetRuleset = rulesetGetRuleset; pIf->SetDefaultRuleset = SetDefaultRuleset; pIf->SetCurrRuleset = SetCurrRuleset; pIf->GetRulesetQueue = GetRulesetQueue; pIf->GetParserList = GetParserList; finalize_it: ENDobjQueryInterface(ruleset) /* Exit the ruleset class. * rgerhards, 2009-04-06 */ BEGINObjClassExit(ruleset, OBJ_IS_CORE_MODULE) /* class, version */ objRelease(parser, CORE_COMPONENT); ENDObjClassExit(ruleset) /* Initialize the ruleset class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(ruleset, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, rulesetDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, rulesetConstructFinalize); /* config file handlers */ CHKiRet(regCfSysLineHdlr((uchar *)"rulesetparser", 0, eCmdHdlrGetWord, rulesetAddParser, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"rulesetcreatemainqueue", 0, eCmdHdlrBinary, rulesetCreateQueue, NULL, NULL)); ENDObjClassInit(ruleset) rsyslog-8.2608.0/runtime/PaxHeaders/objomsr.h0000644000000000000000000000013115216464436016060 xustar0030 mtime=1782212894.037266362 29 atime=1787067616.81141491 30 ctime=1787067794.319723657 rsyslog-8.2608.0/runtime/objomsr.h0000664000175000017500000000431315216464436015526 0ustar00rgerrger/* Definition of the omsr (omodStringRequest) object. * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OBJOMSR_H_INCLUDED #define OBJOMSR_H_INCLUDED /* define flags for required template options */ #define OMSR_NO_RQD_TPL_OPTS 0 #define OMSR_RQD_TPL_OPT_SQL 1 /* only one of OMSR_TPL_AS_ARRAY, _AS_MSG, or _AS_JSON must be specified, * if all are given results are unpredictable. */ #define OMSR_TPL_AS_ARRAY 2 /* introduced in 4.1.6, 2009-04-03 */ #define OMSR_TPL_AS_MSG 4 /* introduced in 5.3.4, 2009-11-02 */ #define OMSR_TPL_AS_JSON 8 /* introduced in 6.5.1, 2012-09-02 */ /** Template is used to render a dynamic file name. */ #define OMSR_TPL_AS_DYNAFILE 16 /* next option is 32, 64, ... */ struct omodStringRequest_s { /* strings requested by output module for doAction() */ int iNumEntries; /* number of array entries for data elements below */ uchar **ppTplName; /* pointer to array of template names */ int *piTplOpts; /* pointer to array of check-options when pulling template */ }; typedef struct omodStringRequest_s omodStringRequest_t; /* prototypes */ rsRetVal OMSRdestruct(omodStringRequest_t *pThis); rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries); rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts); rsRetVal OMSRgetSupportedTplOpts(unsigned long *pOpts); int OMSRgetEntryCount(omodStringRequest_t *pThis); int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts); #endif /* #ifndef OBJOMSR_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/batch.h0000644000000000000000000000013215241075234015457 xustar0030 mtime=1787067036.599578182 30 atime=1787067036.745580916 30 ctime=1787067794.255722465 rsyslog-8.2608.0/runtime/batch.h0000664000175000017500000001320015241075234015117 0ustar00rgerrger/* Definition of the batch_t data structure. * I am not sure yet if this will become a full-blown object. For now, this header just * includes the object definition and is not accompanied by code. * * Copyright 2009-2013 by Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef BATCH_H_INCLUDED #define BATCH_H_INCLUDED #include #include #include "msg.h" /* enum for batch states. Actually, we violate a layer here, in that we assume that a batch is used * for action processing. So far, this seems acceptable, the status is simply ignored inside the * main message queue. But over time, it could potentially be useful to split the two. * rgerhad, 2009-05-12 */ #define BATCH_STATE_RDY 0 /* object ready for processing */ #define BATCH_STATE_BAD 1 /* unrecoverable failure while processing, do NOT resubmit to same action */ #define BATCH_STATE_SUB 2 /* message submitted for processing, outcome yet unknown */ #define BATCH_STATE_COMM 3 /* message successfully commited */ #define BATCH_STATE_DISC 4 /* discarded - processed OK, but do not submit to any other action */ typedef unsigned char batch_state_t; /* an object inside a batch, including any information (state!) needed for it to "life". */ struct batch_obj_s { smsg_t *pMsg; }; /* the batch * This object is used to dequeue multiple user pointers which are than handed over * to processing. The size of elements is fixed after queue creation, but may be * modified by config variables (better said: queue properties). * Note that a "user pointer" in rsyslog context so far always is a message * object. We stick to the more generic term because queues may potentially hold * other types of objects, too. * rgerhards, 2009-05-12 * Note that nElem is not necessarily equal to nElemDeq. This is the case when we * discard some elements (because of configuration) during dequeue processing. As * all Elements are only deleted when the batch is processed, we can not immediately * delete them. So we need to keep their number that we can delete them when the batch * is completed (else, the whole process does not work correctly). */ struct batch_s { int maxElem; /* maximum number of elements that this batch supports */ int nElem; /* actual number of element in this entry */ int nElemDeq; /* actual number of elements dequeued (and thus to be deleted) - see comment above! */ qDeqID deqID; /* ID of dequeue operation that generated this batch */ batch_obj_t *pElem; /* batch elements */ batch_state_t *eltState; /* state (array!) for individual objects. NOTE: we have moved this out of batch_obj_t because we get a *much* better cache hit ratio this way. So do not move it back into this structure! Note that this is really a HUGE saving, even if it doesn't look so (both profiler data as well as practical tests indicate that!). */ void *storeData; /* optional queue-store-owned batch completion context */ }; /* get number of msgs for this batch */ #define batchNumMsgs(pBatch) ((pBatch)->nElem) /* set the status of the i-th batch element. Note that once the status is * DISC, it will never be reset. So this function can NOT be used to initialize * the state table. -- rgerhards, 2010-06-10 */ static inline void __attribute__((unused)) batchSetElemState(batch_t *const pBatch, const int i, const batch_state_t newState) { if (pBatch->eltState[i] != BATCH_STATE_DISC) pBatch->eltState[i] = newState; } /* check if an element is a valid entry. We do NOT verify if the * element index is valid. -- rgerhards, 2010-06-10 */ #define batchIsValidElem(pBatch, i) ((pBatch)->eltState[(i)] != BATCH_STATE_DISC) /* free members of a batch "object". Note that we can not do the usual * destruction as the object typically is allocated on the stack and so the * object itself cannot be freed! -- rgerhards, 2010-06-15 */ static inline void __attribute__((unused)) batchFree(batch_t *const pBatch) { free(pBatch->pElem); free(pBatch->eltState); } /* initialiaze a batch "object". The record must already exist, * we "just" initialize it. The max number of elements must be * provided. -- rgerhards, 2010-06-15 */ static inline rsRetVal __attribute__((unused)) batchInit(batch_t *const pBatch, const int maxElem) { DEFiRet; pBatch->maxElem = maxElem; pBatch->storeData = NULL; CHKmalloc(pBatch->pElem = calloc((size_t)maxElem, sizeof(batch_obj_t))); CHKmalloc(pBatch->eltState = calloc((size_t)maxElem, sizeof(batch_state_t))); finalize_it: RETiRet; } #endif /* #ifndef BATCH_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/queue_da.h0000644000000000000000000000013215241075234016166 xustar0030 mtime=1787067036.607578332 30 atime=1787067036.681579717 30 ctime=1787067794.402725204 rsyslog-8.2608.0/runtime/queue_da.h0000664000175000017500000001573015241075234015640 0ustar00rgerrger/* SPDX-License-Identifier: Apache-2.0 */ /* * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 */ /** * @file queue_da.h * @brief Internal API for disk-assisted queue engine selection and markers. * * These declarations encapsulate automatic classic-versus-segmented selection, * the persistent engine marker, and reload-lifecycle comparison for * disk-assisted child queues. */ #ifndef INCLUDED_QUEUE_DA_H #define INCLUDED_QUEUE_DA_H #include "rsyslog.h" /** * @brief Configurable disk-store engine choices for a disk-assisted child. * * AUTO is a policy, not a persistent engine: qdaEngineResolve() maps it to * either DISK or SEGMENTED_DISK using existing spool data, the durable marker, * and features unsupported by the segmented store. Only the two concrete * values may be persisted in a marker. */ typedef enum qda_engine_mode_e { QDA_ENGINE_AUTO = 0, /**< Select a compatible concrete engine at startup. */ QDA_ENGINE_DISK, /**< Use the established .qi and numeric-segment store. */ QDA_ENGINE_SEGMENTED_DISK /**< Use the segmented .segq store. */ } qda_engine_mode_t; /** * @brief Evidence that determined the selected effective engine. * * The reason is retained for diagnostics and warning policy. It records the * decisive input, not every probe performed while resolving the engine. */ typedef enum qda_selection_reason_e { QDA_REASON_CONFIGURED = 0, /**< An explicit concrete selector chose it. */ QDA_REASON_FRESH_DEFAULT, /**< No prior store exists; choose segmented. */ QDA_REASON_MARKER, /**< A retained marker keeps the empty queue sticky. */ QDA_REASON_CLASSIC_DATA, /**< Classic state or numeric segments exist. */ QDA_REASON_SEGMENTED_DATA, /**< Segmented state directory exists. */ QDA_REASON_CLASSIC_FEATURE, /**< Requested options require the classic store. */ QDA_REASON_AUTO_UPGRADE /**< A clean classic marker permits a restart upgrade. */ } qda_selection_reason_t; /** * @brief Inputs used to choose a disk-assisted child engine. * * spool_dir and file_prefix identify the parent queue's persistent namespace. * The resolver examines only this namespace; it never creates, modifies, or * migrates a store. requires_classic_features is true for settings that the * segmented store intentionally does not implement (currently encryption or * an unsafe corruption policy). */ typedef struct qda_engine_config_s { const char *spool_dir; /**< Existing workDirectory; not owned by this object. */ const char *file_prefix; /**< Queue filename prefix within spool_dir; not owned. */ qda_engine_mode_t requested; /**< AUTO or an explicit concrete engine. */ sbool auto_upgrade; /**< Permit a drained classic AUTO queue to switch at restart. */ sbool requires_classic_features; /**< Force classic in AUTO; reject explicit segmented. */ } qda_engine_config_t; /** * @brief Result and probe observations returned by qdaEngineResolve(). * * The data-presence fields deliberately distinguish compatibility evidence * from the chosen engine. Callers use them to decide when a marker must be * replaced before a child is materialized. The structure is initialized by * qdaEngineResolve() and is meaningful only when that function succeeds. */ typedef struct qda_engine_result_s { qda_engine_mode_t effective; /**< Concrete engine to instantiate. */ qda_selection_reason_t reason; /**< Decisive selection evidence. */ sbool classic_data; /**< .qi or numeric classic segments were found. */ sbool segmented_data; /**< .segq directory was found. */ sbool marker_present; /**< A valid .da-engine marker was read. */ qda_engine_mode_t marker_engine; /**< Concrete engine recorded in that marker. */ } qda_engine_result_t; /** * @brief Configuration that controls a disk-assisted child's identity. * * Changing any field requires rebuilding the child on reload. These values * are deliberately separate from generic queue settings: they determine * persistent-store compatibility and idle dematerialization semantics. */ typedef struct qda_lifecycle_config_s { qda_engine_mode_t engine; /**< Configured selector, including AUTO. */ sbool auto_upgrade; /**< AUTO-only clean-drain upgrade policy. */ int idle_timeout; /**< Segmented child idle lifetime in milliseconds. */ } qda_lifecycle_config_t; /** * @brief Resolve the concrete engine for a disk-assisted child without writing. * * Precedence is intentionally data-first: mixed stores and malformed markers * fail, existing classic or segmented data keeps its compatible engine, then * unsupported segmented features force classic in AUTO mode. A valid marker * makes an otherwise empty queue sticky, except when AUTO upgrade is enabled * and the old classic store has demonstrably drained. A fresh AUTO queue * resolves to segmentedDisk. * * @param config Non-NULL selection inputs and spool namespace. * @param result Non-NULL output, zeroed and populated by this call. * @return RS_RET_OK on a concrete selection; RS_RET_PARAM_ERROR for missing * required parameters; RS_RET_INVALID_VALUE for mixed, malformed, or * explicitly incompatible state; another error for I/O or allocation * failure. The function never creates or changes files. */ rsRetVal qdaEngineResolve(const qda_engine_config_t *config, qda_engine_result_t *result); /** * @brief Atomically publish the concrete engine marker for a queue namespace. * * The marker is a small versioned compatibility record, not queue data or * metadata. The helper writes a private temporary file, synchronizes it, * renames it over the marker, and synchronizes the containing directory. This * makes an engine selection durable before its first persistent records exist * and allows an empty dematerialized segmented child to remain sticky. * * @param spool_dir Existing parent workDirectory. * @param file_prefix Parent queue filename prefix. * @param engine Concrete DISK or SEGMENTED_DISK engine to publish; AUTO is invalid. * @return RS_RET_OK or an allocation, parameter, or I/O error. */ rsRetVal qdaEngineWriteMarker(const char *spool_dir, const char *file_prefix, qda_engine_mode_t engine); /** * @brief Return the configuration/marker spelling for an engine value. * * The returned static string is never NULL and must not be freed. Invalid * values return "invalid" for diagnostics; callers must still validate values * before attempting to persist them. */ const char *qdaEngineName(qda_engine_mode_t engine); /** * @brief Compare all settings that require DA child replacement on reload. * * NULL inputs are unequal. This function compares values only; it does not * inspect the spool or determine whether a replacement can safely occur. */ sbool qdaLifecycleConfigEqual(const qda_lifecycle_config_t *left, const qda_lifecycle_config_t *right); #endif rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_store.c0000644000000000000000000000013215241075234017236 xustar0030 mtime=1787067036.610578388 30 atime=1787067036.756581122 30 ctime=1787067794.420725539 rsyslog-8.2608.0/runtime/segdisk_store.c0000664000175000017500000020141715241075234016707 0ustar00rgerrger/* * Log-structured serial queue store. * * Concurrency & locking: callers hold the owning queue mutex for every public * operation. The store therefore owns no mutex. Batch contexts may complete * out of order, but the durable frontier advances only in dequeue order. * * Startup reads only the fixed-size state file. Existing segments are opened * and validated lazily as dequeue reaches them, so startup cost is independent * of backlog bytes and segment count. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "errmsg.h" #include "segdisk_codec.h" #include "segdisk_crc.h" #include "segdisk_state.h" #include "segdisk_store.h" #define SEG_MAGIC "RSSEGH02" #define REC_MAGIC "RSRECD02" #define FOOT_MAGIC "RSSEAL02" #define STORE_VERSION 2u #define STATE_SLOT_LEN SEGDISK_STATE_SLOT_LEN #define STATE_FILE_LEN SEGDISK_STATE_FILE_LEN #define SEG_HDR_LEN 52u #define REC_HDR_LEN 32u #define FOOT_LEN 48u #define MAX_RECORD_SIZE (128u * 1024u * 1024u) #define RECOVERY_SCAN_BUDGET (1024u * 1024u) #define STATE_FLAG_RECOVERY 1u #define STATE_FLAG_DEMATERIALIZING 2u typedef struct segdisk_segment_s { uint64_t id; uint64_t first_sequence; uint64_t last_sequence; uint64_t record_count; int64_t data_end; int64_t file_size; uint32_t rolling_crc; sbool sealed; sbool recovery; char *path; } segdisk_segment_t; typedef struct segdisk_batch_ctx_s { uint64_t sequence; uint64_t end_segment; uint64_t end_record_sequence; int64_t end_offset; int records; int retry_index; int retry_count; unsigned int refs; sbool pending; sbool complete; struct segdisk_batch_ctx_s *next; } segdisk_batch_ctx_t; struct segdisk_store_s { char *dir; char *queue_name; int dir_fd; int state_fd; int active_fd; segdisk_store_config_t cfg; unsigned char uuid[16]; uint64_t generation; uint64_t committed_segment; uint64_t committed_record_sequence; int64_t committed_offset; uint64_t first_live_segment; uint64_t last_data_segment; uint64_t active_segment; uint64_t recovery_first; uint64_t recovery_last; uint64_t next_segment; uint64_t persisted_queue_size; uint64_t persisted_writer_segment; int64_t persisted_writer_end; uint64_t persisted_writer_sequence; uint64_t persisted_writer_count; uint64_t delete_first; uint64_t delete_last; int64_t delete_bytes; uint64_t delete_segments; uint64_t discovery_through_segment; uint64_t read_segment_id; int64_t read_offset; segdisk_segment_t *read_segment; segdisk_segment_t *active; segdisk_batch_ctx_t *pending_head; segdisk_batch_ctx_t *pending_tail; uint64_t next_batch_sequence; uint64_t known_queue_size; unsigned int updates_since_checkpoint; sbool dematerializing; segdisk_store_stats_t stats; #ifdef ENABLE_IMDIAG segdisk_test_fault_point_t test_fault_point; unsigned int test_fault_hits_remaining; #endif }; #ifdef ENABLE_IMDIAG typedef struct segdisk_test_fault_name_s { const char *name; segdisk_test_fault_point_t point; } segdisk_test_fault_name_t; static const segdisk_test_fault_name_t test_fault_names[] = { {"reservation-published", SEGDISK_TEST_FAULT_RESERVATION_PUBLISHED}, {"segment-created", SEGDISK_TEST_FAULT_SEGMENT_CREATED}, {"seal-written", SEGDISK_TEST_FAULT_SEAL_WRITTEN}, {"seal-renamed", SEGDISK_TEST_FAULT_SEAL_RENAMED}, {"checkpoint-published", SEGDISK_TEST_FAULT_CHECKPOINT_PUBLISHED}, {"commit-published", SEGDISK_TEST_FAULT_COMMIT_PUBLISHED}, {"predelete-published", SEGDISK_TEST_FAULT_PREDELETE_PUBLISHED}, {"segment-unlinked", SEGDISK_TEST_FAULT_SEGMENT_UNLINKED}, {"idle-empty-published", SEGDISK_TEST_FAULT_IDLE_EMPTY_PUBLISHED}, {"idle-segments-unlinked", SEGDISK_TEST_FAULT_IDLE_SEGMENTS_UNLINKED}, {"idle-state-unlinked", SEGDISK_TEST_FAULT_IDLE_STATE_UNLINKED}, {"idle-directory-removed", SEGDISK_TEST_FAULT_IDLE_DIRECTORY_REMOVED}, }; static void test_fault(segdisk_store_t *s, const segdisk_test_fault_point_t point) { if (s->test_fault_point != point || s->test_fault_hits_remaining == 0) return; if (--s->test_fault_hits_remaining != 0) return; s->test_fault_point = SEGDISK_TEST_FAULT_NONE; kill(getpid(), SIGKILL); } #else #define test_fault(store, point) ((void)0) #endif static void update_retry_overage(segdisk_store_t *s); /* Directory enumeration is restricted to the exceptional missing-state path. * A valid state file keeps normal startup independent of segment count. */ static rsRetVal directory_has_entries(const int dir_fd, sbool *has_entries) { const int fd = dup(dir_fd); if (fd < 0) return RS_RET_IO_ERROR; DIR *const dir = fdopendir(fd); if (dir == NULL) { close(fd); return RS_RET_IO_ERROR; } *has_entries = 0; errno = 0; struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) { *has_entries = 1; break; } } const int saved_errno = errno; if (closedir(dir) != 0 || (entry == NULL && saved_errno != 0)) return RS_RET_IO_ERROR; return RS_RET_OK; } static int sync_file_data(const int fd) { #if defined(HAVE_FDATASYNC) && !defined(__APPLE__) return fdatasync(fd); #else return fsync(fd); #endif } static void release_batch_ctx(segdisk_batch_ctx_t *ctx) { if (--ctx->refs == 0) free(ctx); } static void put16(unsigned char *p, uint16_t v) { p[0] = (unsigned char)(v >> 8); p[1] = (unsigned char)v; } static void put32(unsigned char *p, uint32_t v) { p[0] = (unsigned char)(v >> 24); p[1] = (unsigned char)(v >> 16); p[2] = (unsigned char)(v >> 8); p[3] = (unsigned char)v; } static void put64(unsigned char *p, uint64_t v) { put32(p, (uint32_t)(v >> 32)); put32(p + 4, (uint32_t)v); } static uint16_t get16(const unsigned char *p) { return (uint16_t)(((uint16_t)p[0] << 8) | p[1]); } static uint32_t get32(const unsigned char *p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3]; } static uint64_t get64(const unsigned char *p) { return ((uint64_t)get32(p) << 32) | get32(p + 4); } static rsRetVal read_full_at(int fd, void *buf, size_t len, int64_t off) { unsigned char *p = buf; while (len != 0) { const ssize_t n = pread(fd, p, len, off); if (n == 0) return RS_RET_EOF; if (n < 0) { if (errno == EINTR) continue; return RS_RET_IO_ERROR; } p += n; len -= (size_t)n; off += n; } return RS_RET_OK; } static rsRetVal read_full(int fd, void *buf, size_t len) { unsigned char *p = buf; while (len != 0) { const ssize_t n = read(fd, p, len); if (n == 0) return RS_RET_EOF; if (n < 0) { if (errno == EINTR) continue; return RS_RET_IO_ERROR; } p += n; len -= (size_t)n; } return RS_RET_OK; } static rsRetVal write_full(int fd, const void *buf, size_t len) { const unsigned char *p = buf; while (len != 0) { const ssize_t n = write(fd, p, len); if (n < 0) { if (errno == EINTR) continue; return RS_RET_IO_ERROR; } p += n; len -= (size_t)n; } return RS_RET_OK; } static rsRetVal pwrite_full(int fd, const void *buf, size_t len, int64_t off) { const unsigned char *p = buf; while (len != 0) { const ssize_t n = pwrite(fd, p, len, off); if (n < 0) { if (errno == EINTR) continue; return RS_RET_IO_ERROR; } p += n; len -= (size_t)n; off += n; } return RS_RET_OK; } static char *path_join(const char *a, const char *b) { char *p = NULL; if (asprintf(&p, "%s/%s", a, b) < 0) return NULL; return p; } static char *segment_path(const segdisk_store_t *s, uint64_t id, const char *suffix) { char name[64]; snprintf(name, sizeof(name), "segment-%020" PRIu64 ".%s", id, suffix); return path_join(s->dir, name); } static rsRetVal sync_dir(segdisk_store_t *s) { return fsync(s->dir_fd) == 0 || errno == EINVAL || errno == ENOTSUP ? RS_RET_OK : RS_RET_IO_ERROR; } static rsRetVal random_uuid(unsigned char uuid[16]) { const int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); if (fd < 0) return RS_RET_IO_ERROR; const rsRetVal r = read_full(fd, uuid, 16); close(fd); if (r == RS_RET_OK) { uuid[6] = (uuid[6] & 0x0f) | 0x40; uuid[8] = (uuid[8] & 0x3f) | 0x80; } return r; } static void capture_state_image(const segdisk_store_t *s, segdisk_state_image_t *state) { memset(state, 0, sizeof(*state)); memcpy(state->uuid, s->uuid, sizeof(state->uuid)); state->generation = s->generation; state->flags = (s->recovery_first != 0 ? STATE_FLAG_RECOVERY : 0u) | (s->dematerializing ? STATE_FLAG_DEMATERIALIZING : 0u); state->committed_segment = s->committed_segment; state->committed_offset = s->committed_offset; state->committed_record_sequence = s->committed_record_sequence; state->first_live_segment = s->first_live_segment; state->last_data_segment = s->last_data_segment; state->active_segment = s->active_segment; state->recovery_first = s->recovery_first; state->recovery_last = s->recovery_last; state->next_segment = s->next_segment; state->known_queue_size = s->known_queue_size; state->bytes = s->stats.bytes; state->segments = (uint64_t)s->stats.segments; state->writer_segment = s->persisted_writer_segment; state->writer_end = s->persisted_writer_end; state->writer_sequence = s->persisted_writer_sequence; state->writer_count = s->persisted_writer_count; state->delete_first = s->delete_first; state->delete_last = s->delete_last; state->delete_bytes = s->delete_bytes; state->delete_segments = s->delete_segments; } static void apply_state_image(segdisk_store_t *s, const segdisk_state_image_t *state) { memcpy(s->uuid, state->uuid, sizeof(s->uuid)); s->generation = state->generation; s->dematerializing = (state->flags & STATE_FLAG_DEMATERIALIZING) != 0; s->committed_segment = state->committed_segment; s->committed_offset = state->committed_offset; s->committed_record_sequence = state->committed_record_sequence; s->first_live_segment = state->first_live_segment; s->last_data_segment = state->last_data_segment; s->active_segment = state->active_segment; s->recovery_first = state->recovery_first; s->recovery_last = state->recovery_last; s->next_segment = state->next_segment; s->persisted_queue_size = state->known_queue_size; s->stats.bytes = state->bytes; s->stats.segments = state->segments > INT_MAX ? INT_MAX : (int)state->segments; s->persisted_writer_segment = state->writer_segment; s->persisted_writer_end = state->writer_end; s->persisted_writer_sequence = state->writer_sequence; s->persisted_writer_count = state->writer_count; s->delete_first = state->delete_first; s->delete_last = state->delete_last; s->delete_bytes = state->delete_bytes; s->delete_segments = state->delete_segments; } static rsRetVal write_state(segdisk_store_t *s, sbool force_sync, sbool topology) { unsigned char b[STATE_SLOT_LEN]; const uint64_t next_generation = s->generation + 1; segdisk_state_image_t state; capture_state_image(s, &state); segdiskStateEncode(&state, next_generation, b); const int slot = (int)(next_generation & 1u); rsRetVal r = pwrite_full(s->state_fd, b, sizeof(b), slot * STATE_SLOT_LEN); if (r == RS_RET_OK && (force_sync || s->cfg.sync_files) && sync_file_data(s->state_fd) != 0) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) { s->generation = next_generation; ++s->stats.checkpoints; ++s->stats.state_writes; if (force_sync || topology) ++s->stats.forced_state_writes; s->updates_since_checkpoint = 0; } return r; } static rsRetVal read_state(segdisk_store_t *s) { unsigned char slots[2][STATE_SLOT_LEN]; const rsRetVal r0 = read_full_at(s->state_fd, slots[0], STATE_SLOT_LEN, 0); const rsRetVal r1 = read_full_at(s->state_fd, slots[1], STATE_SLOT_LEN, STATE_SLOT_LEN); segdisk_state_image_t state; const rsRetVal r = segdiskStateSelect(slots[0], r0 == RS_RET_OK, slots[1], r1 == RS_RET_OK, &state, NULL); if (r == RS_RET_OK && ((state.flags & ~(STATE_FLAG_RECOVERY | STATE_FLAG_DEMATERIALIZING)) != 0 || (state.delete_first == 0) != (state.delete_last == 0) || (state.delete_first != 0 && state.delete_first > state.delete_last) || state.delete_bytes < 0)) return RS_RET_INVALID_VALUE; if (r == RS_RET_OK) apply_state_image(s, &state); return r; } static int segment_name(const char *name) { unsigned long long id; char suffix[16]; if (sscanf(name, "segment-%20llu.%15s", &id, suffix) != 2) return 0; return !strcmp(suffix, "seg") || !strcmp(suffix, "open") || !strcmp(suffix, "recover"); } static rsRetVal remove_remaining_segments(segdisk_store_t *s) { const int scan_fd = openat(s->dir_fd, ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC); if (scan_fd < 0) return RS_RET_IO_ERROR; DIR *dir = fdopendir(scan_fd); if (dir == NULL) { close(scan_fd); return RS_RET_IO_ERROR; } rsRetVal r = RS_RET_OK; struct dirent *de; while (1) { errno = 0; de = readdir(dir); if (de == NULL) { if (errno != 0) r = RS_RET_IO_ERROR; break; } if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || !strcmp(de->d_name, "state")) continue; if (!segment_name(de->d_name)) { r = RS_RET_IO_ERROR; /* A foreign entry prevents rmdir(), but it must not prevent us * from removing the queue's own segments. Continuing here is * important for cleanup-error recovery: the replacement empty * state may only exclude the old segment IDs after every old * segment has actually gone. */ continue; } if (unlinkat(s->dir_fd, de->d_name, 0) != 0 && errno != ENOENT) { r = RS_RET_IO_ERROR; continue; } } if (closedir(dir) != 0) r = RS_RET_IO_ERROR; return r; } static rsRetVal directory_has_segments(segdisk_store_t *s, sbool *has_segments) { const int scan_fd = openat(s->dir_fd, ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC); if (scan_fd < 0) return RS_RET_IO_ERROR; DIR *dir = fdopendir(scan_fd); if (dir == NULL) { close(scan_fd); return RS_RET_IO_ERROR; } *has_segments = 0; struct dirent *de; errno = 0; while ((de = readdir(dir)) != NULL) { if (segment_name(de->d_name)) { *has_segments = 1; break; } } const int scan_errno = errno; if (closedir(dir) != 0) return RS_RET_IO_ERROR; return !*has_segments && scan_errno != 0 ? RS_RET_IO_ERROR : RS_RET_OK; } static rsRetVal write_segment_header(segdisk_store_t *s, int fd, uint64_t id) { unsigned char b[SEG_HDR_LEN] = {0}; memcpy(b, SEG_MAGIC, 8); put16(b + 8, STORE_VERSION); put16(b + 10, SEGDISK_CODEC_VERSION); memcpy(b + 12, s->uuid, 16); put64(b + 28, id); put64(b + 36, 1); put32(b + 44, SEG_HDR_LEN); put32(b + 48, segdiskCrc32c(b, 48)); return write_full(fd, b, sizeof(b)); } static rsRetVal validate_segment_header(segdisk_store_t *s, int fd, segdisk_segment_t *seg) { unsigned char b[SEG_HDR_LEN]; rsRetVal r = read_full_at(fd, b, sizeof(b), 0); if (r != RS_RET_OK || memcmp(b, SEG_MAGIC, 8) || get16(b + 8) != STORE_VERSION || get16(b + 10) != SEGDISK_CODEC_VERSION || memcmp(b + 12, s->uuid, 16) || get64(b + 28) != seg->id || get32(b + 44) != SEG_HDR_LEN || get32(b + 48) != segdiskCrc32c(b, 48)) return RS_RET_INVALID_VALUE; seg->first_sequence = get64(b + 36); return RS_RET_OK; } static void free_segment(segdisk_segment_t **seg) { if (*seg == NULL) return; free((*seg)->path); free(*seg); *seg = NULL; } static rsRetVal probe_segment_path(segdisk_store_t *s, uint64_t id, const char *suffix, char **path) { *path = segment_path(s, id, suffix); if (*path == NULL) return RS_RET_OUT_OF_MEMORY; struct stat st; if (lstat(*path, &st) == 0) return S_ISREG(st.st_mode) ? RS_RET_OK : RS_RET_INVALID_VALUE; const int saved_errno = errno; free(*path); *path = NULL; errno = saved_errno; return saved_errno == ENOENT ? RS_RET_FILE_NOT_FOUND : RS_RET_IO_ERROR; } static rsRetVal load_segment(segdisk_store_t *s, uint64_t id, segdisk_segment_t **out) { segdisk_segment_t *seg = calloc(1, sizeof(*seg)); if (seg == NULL) return RS_RET_OUT_OF_MEMORY; seg->id = id; rsRetVal r = probe_segment_path(s, id, "seg", &seg->path); if (r == RS_RET_OK) { seg->sealed = 1; } else if (r == RS_RET_FILE_NOT_FOUND) { r = probe_segment_path(s, id, "recover", &seg->path); if (r == RS_RET_OK) seg->recovery = 1; } if (r == RS_RET_FILE_NOT_FOUND) r = probe_segment_path(s, id, "open", &seg->path); if (r != RS_RET_OK) { free_segment(&seg); return r; } const int fd = open(seg->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (fd < 0) { free_segment(&seg); return RS_RET_IO_ERROR; } struct stat st; if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) { close(fd); free_segment(&seg); return RS_RET_IO_ERROR; } r = validate_segment_header(s, fd, seg); if (r == RS_RET_OK && seg->sealed) { if (st.st_size < (int64_t)(SEG_HDR_LEN + FOOT_LEN)) { r = RS_RET_INVALID_VALUE; } else { unsigned char foot[FOOT_LEN]; r = read_full_at(fd, foot, sizeof(foot), st.st_size - FOOT_LEN); if (r != RS_RET_OK || memcmp(foot, FOOT_MAGIC, 8) || get64(foot + 8) != id || get32(foot + 44) != segdiskCrc32c(foot, 44)) { r = RS_RET_INVALID_VALUE; } else { seg->first_sequence = get64(foot + 16); seg->last_sequence = get64(foot + 24); seg->record_count = get64(foot + 32); seg->rolling_crc = get32(foot + 40); seg->data_end = st.st_size - FOOT_LEN; } } } else if (r == RS_RET_OK) { seg->data_end = st.st_size; } close(fd); if (r != RS_RET_OK) { ++s->stats.corruption_events; LogError(0, r, "%s: segmentedDisk could not validate segment metadata '%s'", s->queue_name, seg->path); free_segment(&seg); return r; } seg->file_size = st.st_size; *out = seg; return RS_RET_OK; } static void capture_writer(segdisk_store_t *s) { if (s->active == NULL) return; s->persisted_writer_segment = s->active->id; s->persisted_writer_end = s->active->data_end; s->persisted_writer_sequence = s->active->last_sequence; s->persisted_writer_count = s->active->record_count; } static rsRetVal create_active(segdisk_store_t *s) { const uint64_t old_first_live = s->first_live_segment; const uint64_t old_next_segment = s->next_segment; segdisk_segment_t *seg = calloc(1, sizeof(*seg)); if (seg == NULL) return RS_RET_OUT_OF_MEMORY; seg->id = s->next_segment++; seg->first_sequence = 1; seg->data_end = SEG_HDR_LEN; seg->file_size = SEG_HDR_LEN; seg->path = segment_path(s, seg->id, "open"); if (seg->path == NULL) { s->next_segment = old_next_segment; free(seg); return RS_RET_OUT_OF_MEMORY; } s->active_segment = seg->id; if (s->first_live_segment == 0) s->first_live_segment = seg->id; ++s->stats.segments; s->stats.bytes += SEG_HDR_LEN; rsRetVal r = write_state(s, 1, 1); if (r != RS_RET_OK) { s->active_segment = 0; s->first_live_segment = old_first_live; s->next_segment = old_next_segment; --s->stats.segments; s->stats.bytes -= SEG_HDR_LEN; free_segment(&seg); return r; } test_fault(s, SEGDISK_TEST_FAULT_RESERVATION_PUBLISHED); const int fd = open(seg->path, O_RDWR | O_CREAT | O_EXCL | O_APPEND | O_CLOEXEC | O_NOFOLLOW, 0600); if (fd < 0) { s->active_segment = 0; /* The published reservation keeps next_segment monotonic, but an * absent file cannot be the live frontier for an in-process retry. */ s->first_live_segment = old_first_live; --s->stats.segments; s->stats.bytes -= SEG_HDR_LEN; free_segment(&seg); return RS_RET_IO_ERROR; } r = write_segment_header(s, fd, seg->id); if (r == RS_RET_OK && s->cfg.sync_files && sync_file_data(fd) != 0) r = RS_RET_IO_ERROR; if (r != RS_RET_OK) { close(fd); unlink(seg->path); s->active_segment = 0; s->first_live_segment = old_first_live; --s->stats.segments; s->stats.bytes -= SEG_HDR_LEN; free_segment(&seg); return r; } test_fault(s, SEGDISK_TEST_FAULT_SEGMENT_CREATED); s->active = seg; s->active_fd = fd; return RS_RET_OK; } static rsRetVal materialize_empty(segdisk_store_t *s) { if (s->dir_fd >= 0) return RS_RET_OK; rsRetVal r = RS_RET_OK; if (mkdir(s->dir, 0700) != 0 && errno != EEXIST) return RS_RET_IO_ERROR; s->dir_fd = open(s->dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); if (s->dir_fd < 0) return RS_RET_IO_ERROR; s->state_fd = openat(s->dir_fd, "state", O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW, 0600); if (s->state_fd < 0 || ftruncate(s->state_fd, STATE_FILE_LEN) != 0 || random_uuid(s->uuid) != RS_RET_OK) r = RS_RET_IO_ERROR; s->committed_offset = SEG_HDR_LEN; s->persisted_writer_end = SEG_HDR_LEN; s->next_segment = 1; if (r == RS_RET_OK) r = create_active(s); if (r == RS_RET_OK) r = sync_dir(s); if (r == RS_RET_OK) { ++s->stats.materializations; return RS_RET_OK; } if (s->active_fd >= 0) close(s->active_fd); s->active_fd = -1; free_segment(&s->active); if (s->dir_fd >= 0) { remove_remaining_segments(s); unlinkat(s->dir_fd, "state", 0); } if (s->state_fd >= 0) close(s->state_fd); if (s->dir_fd >= 0) close(s->dir_fd); s->state_fd = s->dir_fd = -1; rmdir(s->dir); return r; } static void restore_active_after_seal_failure(segdisk_store_t *s) { const int fd = open(s->active->path, O_RDWR | O_APPEND | O_CLOEXEC | O_NOFOLLOW); if (fd < 0) return; if (ftruncate(fd, s->active->data_end) != 0) { close(fd); return; } s->active_fd = fd; } static rsRetVal seal_active(segdisk_store_t *s) { if (s->active == NULL || s->active->sealed || s->active->record_count == 0) return RS_RET_OK; char *sealed = segment_path(s, s->active->id, "seg"); if (sealed == NULL) return RS_RET_OUT_OF_MEMORY; char *read_path = NULL; if (s->read_segment != NULL && s->read_segment->id == s->active->id) { read_path = strdup(sealed); if (read_path == NULL) { free(sealed); return RS_RET_OUT_OF_MEMORY; } } unsigned char b[FOOT_LEN] = {0}; memcpy(b, FOOT_MAGIC, 8); put64(b + 8, s->active->id); put64(b + 16, s->active->first_sequence); put64(b + 24, s->active->last_sequence); put64(b + 32, s->active->record_count); put32(b + 40, s->active->rolling_crc); put32(b + 44, segdiskCrc32c(b, 44)); rsRetVal r = write_full(s->active_fd, b, sizeof(b)); if (r == RS_RET_OK && s->cfg.sync_files && sync_file_data(s->active_fd) != 0) r = RS_RET_IO_ERROR; if (close(s->active_fd) != 0 && r == RS_RET_OK) r = RS_RET_IO_ERROR; s->active_fd = -1; if (r != RS_RET_OK) { restore_active_after_seal_failure(s); free(read_path); free(sealed); return r; } test_fault(s, SEGDISK_TEST_FAULT_SEAL_WRITTEN); if (rename(s->active->path, sealed) != 0) { restore_active_after_seal_failure(s); free(read_path); free(sealed); return RS_RET_IO_ERROR; } test_fault(s, SEGDISK_TEST_FAULT_SEAL_RENAMED); free(s->active->path); s->active->path = sealed; s->active->sealed = 1; s->active->file_size += FOOT_LEN; s->active->data_end = s->active->file_size - FOOT_LEN; s->stats.bytes += FOOT_LEN; s->last_data_segment = s->active->id; if (s->read_segment != NULL && s->read_segment->id == s->active->id) { free(s->read_segment->path); s->read_segment->path = read_path; s->read_segment->sealed = 1; s->read_segment->data_end = s->active->data_end; s->read_segment->file_size = s->active->file_size; } capture_writer(s); s->active_segment = 0; free_segment(&s->active); return s->cfg.sync_files ? sync_dir(s) : RS_RET_OK; } static rsRetVal make_record( smsg_t *msg, uint64_t sequence, unsigned char **out, size_t *outlen, uint32_t *rolling_crc) { unsigned char *payload = NULL; size_t payload_len = 0; rsRetVal r = segdiskCodecEncode(msg, &payload, &payload_len); if (r != RS_RET_OK) return r; if (payload_len > MAX_RECORD_SIZE) { free(payload); return RS_RET_FILE_TOO_LARGE; } const size_t len = REC_HDR_LEN + payload_len; unsigned char *record = malloc(len); if (record == NULL) { free(payload); return RS_RET_OUT_OF_MEMORY; } memset(record, 0, REC_HDR_LEN); memcpy(record, REC_MAGIC, 8); put16(record + 8, STORE_VERSION); put32(record + 12, (uint32_t)payload_len); put64(record + 16, sequence); put32(record + 24, segdiskCrc32c(record, 24)); const uint32_t payload_crc = segdiskCrc32c(payload, payload_len); put32(record + 28, payload_crc); memcpy(record + REC_HDR_LEN, payload, payload_len); free(payload); *out = record; *outlen = len; *rolling_crc = segdiskCrc32c(record, REC_HDR_LEN) ^ payload_crc; return RS_RET_OK; } static void update_retry_overage(segdisk_store_t *s) { s->stats.retry_overage_bytes = s->cfg.max_disk_space > 0 && s->stats.bytes > s->cfg.max_disk_space ? s->stats.bytes - s->cfg.max_disk_space : 0; if (s->stats.retry_overage_bytes > s->stats.retry_overage_max_bytes) s->stats.retry_overage_max_bytes = s->stats.retry_overage_bytes; } static rsRetVal append_record(segdisk_store_t *s, smsg_t *msg, sbool internal, int64_t *written) { if (s->dir_fd < 0) { const rsRetVal materialize_ret = materialize_empty(s); if (materialize_ret != RS_RET_OK) return materialize_ret; } if (s->active == NULL) { rsRetVal r = create_active(s); if (r != RS_RET_OK) return r; } unsigned char *record = NULL; size_t len = 0; uint32_t rolling_crc; rsRetVal r = make_record(msg, s->active->record_count + 1, &record, &len, &rolling_crc); if (r != RS_RET_OK) return r; const sbool rotate = s->active->record_count != 0 && s->cfg.max_file_size > 0 && s->active->file_size + (int64_t)len + FOOT_LEN > s->cfg.max_file_size; if (rotate) { r = seal_active(s); if (r == RS_RET_OK) r = create_active(s); if (r != RS_RET_OK) { free(record); return r; } free(record); record = NULL; r = make_record(msg, 1, &record, &len, &rolling_crc); if (r != RS_RET_OK) return r; } r = write_full(s->active_fd, record, len); if (r == RS_RET_OK && s->cfg.sync_files && sync_file_data(s->active_fd) != 0) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) { s->active->data_end += len; s->active->file_size += len; s->active->last_sequence = ++s->active->record_count; s->active->rolling_crc ^= rolling_crc; s->last_data_segment = s->active->id; ++s->known_queue_size; s->stats.bytes += len; if (written != NULL) *written = len; } free(record); if (r == RS_RET_OK && s->active->record_count == 1 && s->cfg.max_file_size > 0 && s->active->file_size + FOOT_LEN > s->cfg.max_file_size) r = seal_active(s); if (r == RS_RET_OK && internal) update_retry_overage(s); return r; } static sbool segment_is_undiscovered(const segdisk_store_t *s, uint64_t id) { return id != 0 && id <= s->discovery_through_segment; } static rsRetVal record_at(segdisk_store_t *s, segdisk_segment_t *seg, int64_t *off, smsg_t **msg, uint64_t *sequence, int *skipped, int *discovered, size_t *scan_budget) { if (seg->id == s->active_segment && s->active != NULL) seg->data_end = s->active->data_end; const int fd = open(seg->path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (fd < 0) return RS_RET_IO_ERROR; while (*off + (int64_t)REC_HDR_LEN <= seg->data_end) { unsigned char h[REC_HDR_LEN]; rsRetVal r = read_full_at(fd, h, sizeof(h), *off); if (r != RS_RET_OK) { close(fd); return r; } if (memcmp(h, REC_MAGIC, 8) || get16(h + 8) != STORE_VERSION || get32(h + 24) != segdiskCrc32c(h, 24) || get32(h + 12) > MAX_RECORD_SIZE || *off + REC_HDR_LEN + get32(h + 12) > seg->data_end) { ++s->stats.corruption_events; ++s->stats.corruption_bytes; ++s->stats.recovery_bytes; ++*off; if (*scan_budget == 0) { close(fd); return RS_RET_RETRY; } --*scan_budget; continue; } const uint32_t n = get32(h + 12); unsigned char *payload = malloc(n == 0 ? 1 : n); if (payload == NULL) { close(fd); return RS_RET_OUT_OF_MEMORY; } r = read_full_at(fd, payload, n, *off + REC_HDR_LEN); *sequence = get64(h + 16); const sbool newly_discovered = segment_is_undiscovered(s, seg->id); if (newly_discovered) { ++*discovered; ++s->known_queue_size; ++s->stats.recovery_records; s->stats.recovery_bytes += REC_HDR_LEN + n; } *off += REC_HDR_LEN + n; if (r != RS_RET_OK || segdiskCrc32c(payload, n) != get32(h + 28) || segdiskCodecDecode(payload, n, msg) != RS_RET_OK) { free(payload); ++s->stats.corruption_events; ++s->stats.corruption_records; ++*skipped; continue; } free(payload); close(fd); return RS_RET_OK; } if (*off < seg->data_end && seg->id != s->active_segment) { const size_t tail = (size_t)(seg->data_end - *off); s->stats.corruption_bytes += tail; s->stats.recovery_bytes += tail; *off = seg->data_end; } close(fd); return RS_RET_NO_DATA; } static void append_pending(segdisk_store_t *s, segdisk_batch_ctx_t *ctx) { if (s->pending_tail == NULL) s->pending_head = s->pending_tail = ctx; else { s->pending_tail->next = ctx; s->pending_tail = ctx; } } static rsRetVal unlink_segment_id(segdisk_store_t *s, uint64_t id, sbool account) { const char *const suffixes[] = {"seg", "recover", "open"}; rsRetVal r = RS_RET_OK; for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { char *path = segment_path(s, id, suffixes[i]); if (path == NULL) return RS_RET_OUT_OF_MEMORY; struct stat st; if (lstat(path, &st) == 0) { if (unlink(path) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; else { test_fault(s, SEGDISK_TEST_FAULT_SEGMENT_UNLINKED); if (account) { s->stats.bytes -= st.st_size; if (s->stats.segments > 0) --s->stats.segments; } } } else if (errno != ENOENT) { r = RS_RET_IO_ERROR; } free(path); if (r != RS_RET_OK) break; } return r; } static rsRetVal cleanup_one_pending_delete(segdisk_store_t *s) { if (s->delete_first == 0) return RS_RET_OK; if (unlink_segment_id(s, s->delete_first, 0) != RS_RET_OK || sync_dir(s) != RS_RET_OK) return RS_RET_IO_ERROR; const uint64_t old_delete_first = s->delete_first; const uint64_t old_delete_last = s->delete_last; const int64_t old_delete_bytes = s->delete_bytes; const uint64_t old_delete_segments = s->delete_segments; const int64_t old_bytes = s->stats.bytes; const int old_segments = s->stats.segments; if (s->delete_first == s->delete_last) { s->delete_first = s->delete_last = 0; s->delete_bytes = 0; s->delete_segments = 0; s->stats.bytes = old_delete_bytes > s->stats.bytes ? 0 : s->stats.bytes - old_delete_bytes; s->stats.segments = old_delete_segments > (uint64_t)s->stats.segments ? 0 : s->stats.segments - (int)old_delete_segments; } else { ++s->delete_first; } const rsRetVal r = write_state(s, 1, 1); if (r != RS_RET_OK) { s->delete_first = old_delete_first; s->delete_last = old_delete_last; s->delete_bytes = old_delete_bytes; s->delete_segments = old_delete_segments; s->stats.bytes = old_bytes; s->stats.segments = old_segments; } return r; } static rsRetVal delete_committed(segdisk_store_t *s) { const uint64_t target = s->committed_segment; if (target != 0 && s->first_live_segment < target) { const uint64_t old_first = s->first_live_segment; const uint64_t old_recovery_first = s->recovery_first; const uint64_t old_recovery_last = s->recovery_last; const uint64_t old_delete_first = s->delete_first; const uint64_t old_delete_last = s->delete_last; const int64_t old_delete_bytes = s->delete_bytes; const uint64_t old_delete_segments = s->delete_segments; int64_t bytes = 0; uint64_t segments = 0; for (uint64_t id = old_first; id < target; ++id) { const char *const suffixes[] = {"seg", "recover", "open"}; for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { char *path = segment_path(s, id, suffixes[i]); if (path == NULL) return RS_RET_OUT_OF_MEMORY; struct stat st; if (lstat(path, &st) == 0) { if (st.st_size < 0 || st.st_size > INT64_MAX - bytes || segments == UINT64_MAX) { free(path); return RS_RET_FILE_TOO_LARGE; } bytes += st.st_size; ++segments; } free(path); } } if (bytes > INT64_MAX - s->delete_bytes || segments > UINT64_MAX - s->delete_segments) return RS_RET_FILE_TOO_LARGE; if (s->delete_first == 0) s->delete_first = old_first; s->delete_last = target - 1; s->delete_bytes += bytes; s->delete_segments += segments; s->first_live_segment = target; if (s->recovery_first != 0 && target > s->recovery_first) { if (target > s->recovery_last) s->recovery_first = s->recovery_last = 0; else s->recovery_first = target; } const rsRetVal r = write_state(s, 1, 1); if (r != RS_RET_OK) { s->first_live_segment = old_first; s->recovery_first = old_recovery_first; s->recovery_last = old_recovery_last; s->delete_first = old_delete_first; s->delete_last = old_delete_last; s->delete_bytes = old_delete_bytes; s->delete_segments = old_delete_segments; return r; } test_fault(s, SEGDISK_TEST_FAULT_PREDELETE_PUBLISHED); } while (s->delete_first != 0 && cleanup_one_pending_delete(s) == RS_RET_OK) { } if (s->delete_first != 0) LogError(0, RS_RET_IO_ERROR, "%s: segmentedDisk could not remove all committed segment files; " "the durable pending-delete range will be retried", s->queue_name); update_retry_overage(s); return RS_RET_OK; } static rsRetVal advance_completed(segdisk_store_t *s) { unsigned int advanced = 0; segdisk_batch_ctx_t *last = NULL; for (segdisk_batch_ctx_t *ctx = s->pending_head; ctx != NULL && ctx->complete; ctx = ctx->next) { last = ctx; advanced += (unsigned int)ctx->records; } if (last == NULL) return RS_RET_OK; const uint64_t old_segment = s->committed_segment; const int64_t old_offset = s->committed_offset; const uint64_t old_sequence = s->committed_record_sequence; const uint64_t old_size = s->known_queue_size; const unsigned int old_updates = s->updates_since_checkpoint; s->committed_segment = last->end_segment; s->committed_offset = last->end_offset; s->committed_record_sequence = last->end_record_sequence; s->known_queue_size = advanced > s->known_queue_size ? 0 : s->known_queue_size - advanced; s->updates_since_checkpoint += advanced; rsRetVal r = RS_RET_OK; if (s->cfg.checkpoint_interval != 0 && s->updates_since_checkpoint >= s->cfg.checkpoint_interval) { capture_writer(s); r = write_state(s, 0, 0); if (r == RS_RET_OK) { test_fault(s, SEGDISK_TEST_FAULT_CHECKPOINT_PUBLISHED); test_fault(s, SEGDISK_TEST_FAULT_COMMIT_PUBLISHED); } } if (r == RS_RET_OK) r = delete_committed(s); if (r != RS_RET_OK) { s->committed_segment = old_segment; s->committed_offset = old_offset; s->committed_record_sequence = old_sequence; s->known_queue_size = old_size; s->updates_since_checkpoint = old_updates; return r; } segdisk_batch_ctx_t *const after = last->next; while (s->pending_head != after) { segdisk_batch_ctx_t *ctx = s->pending_head; s->pending_head = ctx->next; ctx->pending = 0; release_batch_ctx(ctx); } if (s->pending_head == NULL) s->pending_tail = NULL; return RS_RET_OK; } static rsRetVal prepare_existing_active(segdisk_store_t *s) { if (s->active_segment == 0) return RS_RET_OK; const int64_t accounted_bytes = s->persisted_writer_segment == s->active_segment && s->persisted_writer_end >= SEG_HDR_LEN ? s->persisted_writer_end : SEG_HDR_LEN; int64_t actual_bytes = -1; char *open_path = NULL; ++s->stats.startup_segment_files_probed; rsRetVal r = probe_segment_path(s, s->active_segment, "open", &open_path); if (r == RS_RET_OK) { struct stat st; if (lstat(open_path, &st) != 0 || !S_ISREG(st.st_mode)) { free(open_path); return RS_RET_IO_ERROR; } actual_bytes = st.st_size; char *recover_path = segment_path(s, s->active_segment, "recover"); if (recover_path == NULL) { free(open_path); return RS_RET_OUT_OF_MEMORY; } if (rename(open_path, recover_path) != 0) r = RS_RET_IO_ERROR; free(recover_path); if (r == RS_RET_OK) { if (s->recovery_first == 0) s->recovery_first = s->active_segment; s->recovery_last = s->active_segment; if (s->last_data_segment < s->active_segment) s->last_data_segment = s->active_segment; } free(open_path); } else if (r == RS_RET_FILE_NOT_FOUND) { char *recover = NULL; ++s->stats.startup_segment_files_probed; r = probe_segment_path(s, s->active_segment, "recover", &recover); if (r == RS_RET_OK) { struct stat st; if (lstat(recover, &st) != 0 || !S_ISREG(st.st_mode)) { free(recover); return RS_RET_IO_ERROR; } actual_bytes = st.st_size; } free(recover); if (r == RS_RET_OK) { if (s->recovery_first == 0) s->recovery_first = s->active_segment; s->recovery_last = s->active_segment; if (s->last_data_segment < s->active_segment) s->last_data_segment = s->active_segment; } } if (r == RS_RET_FILE_NOT_FOUND) { char *sealed = NULL; ++s->stats.startup_segment_files_probed; r = probe_segment_path(s, s->active_segment, "seg", &sealed); if (r == RS_RET_OK) { struct stat st; if (lstat(sealed, &st) != 0 || !S_ISREG(st.st_mode)) { free(sealed); return RS_RET_IO_ERROR; } actual_bytes = st.st_size; } free(sealed); if (r == RS_RET_OK && s->last_data_segment < s->active_segment) s->last_data_segment = s->active_segment; } if (r == RS_RET_FILE_NOT_FOUND) { if (s->stats.segments > 0) --s->stats.segments; if (s->stats.bytes >= accounted_bytes) s->stats.bytes -= accounted_bytes; /* Reservation publication can survive a crash before file creation. * The ID remains consumed, but the nonexistent segment is not live. */ if (s->first_live_segment == s->active_segment) s->first_live_segment = 0; r = RS_RET_OK; } else if (r == RS_RET_OK && actual_bytes >= 0) { s->stats.bytes += actual_bytes - accounted_bytes; } s->active_segment = 0; return r; } /* A valid older state slot may be selected after the newer reservation slot * was torn. In that case only the older slot's next ID can already exist. It * is adopted as recovery data without enumerating the spool directory. */ static rsRetVal adopt_reserved_segment(segdisk_store_t *s) { const uint64_t id = s->next_segment; const char *found_suffix = NULL; char *path = NULL; const char *const suffixes[] = {"open", "recover", "seg"}; for (size_t i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { ++s->stats.startup_segment_files_probed; rsRetVal r = probe_segment_path(s, id, suffixes[i], &path); if (r == RS_RET_OK) { found_suffix = suffixes[i]; break; } if (r != RS_RET_FILE_NOT_FOUND) return r; } if (found_suffix == NULL) return RS_RET_OK; struct stat st; if (lstat(path, &st) != 0 || !S_ISREG(st.st_mode)) { free(path); return RS_RET_IO_ERROR; } if (!strcmp(found_suffix, "open")) { char *recover = segment_path(s, id, "recover"); if (recover == NULL) { free(path); return RS_RET_OUT_OF_MEMORY; } if (rename(path, recover) != 0) { free(recover); free(path); return RS_RET_IO_ERROR; } free(recover); } free(path); /* If the missing published active ID was the old frontier, this adopted * next-ID segment is now the earliest live recovery data. */ if (s->first_live_segment == 0) s->first_live_segment = id; if (s->recovery_first == 0) s->recovery_first = id; s->recovery_last = id; if (s->last_data_segment < id) s->last_data_segment = id; ++s->stats.segments; s->stats.bytes += st.st_size; ++s->next_segment; return RS_RET_OK; } static void reset_after_dematerialize(segdisk_store_t *s); static rsRetVal finish_interrupted_dematerialization(segdisk_store_t *s) { rsRetVal r = remove_remaining_segments(s); if (r == RS_RET_OK) r = sync_dir(s); if (r == RS_RET_OK && unlinkat(s->dir_fd, "state", 0) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) r = sync_dir(s); if (r == RS_RET_OK && rmdir(s->dir) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; if (r != RS_RET_OK) return r; if (s->state_fd >= 0) close(s->state_fd); if (s->dir_fd >= 0) close(s->dir_fd); s->state_fd = s->dir_fd = -1; reset_after_dematerialize(s); ++s->stats.dematerializations; return RS_RET_OK; } rsRetVal segdiskStoreOpen(segdisk_store_t **out, const segdisk_store_config_t *cfg, int *queue_size) { if (out == NULL || cfg == NULL || cfg->work_dir == NULL || cfg->file_prefix == NULL || queue_size == NULL) return RS_RET_PARAM_ERROR; if (cfg->file_prefix[0] == '\0' || strchr(cfg->file_prefix, '/') != NULL || strchr(cfg->file_prefix, '\\') != NULL || !strcmp(cfg->file_prefix, ".") || !strcmp(cfg->file_prefix, "..")) return RS_RET_INVALID_VALUE; segdisk_store_t *s = calloc(1, sizeof(*s)); if (s == NULL) return RS_RET_OUT_OF_MEMORY; rsRetVal fail_ret = RS_RET_IO_ERROR; s->dir_fd = s->state_fd = s->active_fd = -1; s->cfg = *cfg; s->committed_offset = SEG_HDR_LEN; s->persisted_writer_end = SEG_HDR_LEN; s->next_segment = 1; s->queue_name = strdup(cfg->queue_name == NULL ? cfg->file_prefix : cfg->queue_name); if (s->queue_name == NULL || asprintf(&s->dir, "%s/%s.segq", cfg->work_dir, cfg->file_prefix) < 0) goto oom; char *legacy_qi = NULL; if (asprintf(&legacy_qi, "%s/%s.qi", cfg->work_dir, cfg->file_prefix) < 0) goto oom; struct stat legacy_st; if (lstat(legacy_qi, &legacy_st) == 0) { /* DA engine resolution happens before this constructor. Auto mode * sends any existing .qi to the classic child, and an explicit * segmented selector is rejected as a data conflict. Keep this * store-level guard for pure segmentedDisk queues and races: a .qi is * persistent classic state even if it describes zero records, so it * must be drained/removed before auto-upgrade can select segmented. */ LogError(0, RS_RET_INVALID_VALUE, "%s: segmentedDisk refuses legacy queue state '%s'", s->queue_name, legacy_qi); free(legacy_qi); goto invalid; } free(legacy_qi); if (cfg->lazy_create) { struct stat dir_st; if (lstat(s->dir, &dir_st) != 0 && errno == ENOENT) { *queue_size = 0; *out = s; return RS_RET_OK; } } sbool directory_created = 0; if (mkdir(s->dir, 0700) == 0) directory_created = 1; else if (errno != EEXIST) goto ioerr; s->dir_fd = open(s->dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); if (s->dir_fd < 0) goto ioerr; s->state_fd = openat(s->dir_fd, "state", O_RDWR | O_CLOEXEC | O_NOFOLLOW); if (s->state_fd < 0 && errno != ENOENT) goto ioerr; if (s->state_fd < 0) { const sbool has_v1_state = faccessat(s->dir_fd, "meta", F_OK, 0) == 0 || faccessat(s->dir_fd, "checkpoint", F_OK, 0) == 0; if (has_v1_state) { LogError(0, RS_RET_INVALID_VALUE, "%s: experimental segmentedDisk v1 state is incompatible with store format v2; " "offline recovery is required", s->queue_name); goto invalid; } sbool has_entries = 0; if (!directory_created && directory_has_entries(s->dir_fd, &has_entries) != RS_RET_OK) goto ioerr; if (has_entries) { LogError(0, RS_RET_INVALID_VALUE, "%s: segmentedDisk state is missing while queue files exist; offline recovery is required", s->queue_name); goto invalid; } if (cfg->lazy_create && !directory_created) { /* A crash after durable state removal but before rmdir leaves an * empty directory. For a DA child this is the final, unambiguous * cleanup residue, so finish dematerialization instead of * creating a fresh empty store during startup. */ close(s->dir_fd); s->dir_fd = -1; if (rmdir(s->dir) != 0 && errno != ENOENT) goto ioerr; *queue_size = 0; *out = s; return RS_RET_OK; } s->state_fd = openat(s->dir_fd, "state", O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW, 0600); if (s->state_fd < 0 || ftruncate(s->state_fd, STATE_FILE_LEN) != 0 || random_uuid(s->uuid) != RS_RET_OK) goto ioerr; if (create_active(s) != RS_RET_OK) goto ioerr; if (sync_dir(s) != RS_RET_OK) goto ioerr; } else { struct stat state_st; if (fstat(s->state_fd, &state_st) != 0 || state_st.st_size != STATE_FILE_LEN) goto invalid; if (read_state(s) != RS_RET_OK) { LogError(0, RS_RET_INVALID_VALUE, "%s: segmentedDisk has no valid state slot; offline recovery is required", s->queue_name); goto invalid; } if (s->dematerializing) { if (finish_interrupted_dematerialization(s) != RS_RET_OK) goto ioerr; if (cfg->lazy_create) { *queue_size = 0; *out = s; return RS_RET_OK; } if (materialize_empty(s) != RS_RET_OK) goto ioerr; *queue_size = 0; *out = s; return RS_RET_OK; } if (prepare_existing_active(s) != RS_RET_OK) goto ioerr; if (adopt_reserved_segment(s) != RS_RET_OK) goto ioerr; s->discovery_through_segment = s->last_data_segment; if (create_active(s) != RS_RET_OK) goto ioerr; } ++s->stats.materializations; s->known_queue_size = 0; *queue_size = 0; s->stats.replayed = s->persisted_queue_size; s->read_segment_id = s->committed_segment != 0 ? s->committed_segment : s->first_live_segment; if (s->read_segment_id == 0) s->read_segment_id = s->first_live_segment; s->read_offset = s->committed_segment == s->read_segment_id && s->committed_offset >= SEG_HDR_LEN ? s->committed_offset : SEG_HDR_LEN; *out = s; return RS_RET_OK; oom: fail_ret = RS_RET_OUT_OF_MEMORY; goto fail; ioerr: goto fail; invalid: fail_ret = RS_RET_INVALID_VALUE; fail: if (s->active_fd >= 0) close(s->active_fd); if (s->state_fd >= 0) close(s->state_fd); if (s->dir_fd >= 0) close(s->dir_fd); free_segment(&s->active); free_segment(&s->read_segment); free(s->dir); free(s->queue_name); free(s); return fail_ret; } rsRetVal segdiskStoreAppend(segdisk_store_t *s, smsg_t *msg, sbool internal, int64_t *written) { return append_record(s, msg, internal, written); } sbool segdiskStoreMayHaveData(const segdisk_store_t *s) { if (s == NULL) return 0; if (s->delete_first != 0) return 1; if (s->read_segment != NULL && s->read_offset < s->read_segment->data_end) return 1; if (s->read_segment == NULL && s->read_segment_id != 0 && s->read_segment_id <= s->last_data_segment) return 1; return s->active != NULL && s->active->record_count != 0 && (s->read_segment_id < s->active->id || s->read_offset < s->active->data_end); } sbool segdiskStoreCanDematerialize(const segdisk_store_t *s) { /* recovery_first is durable topology, not an undiscovered-work flag: it * may still name the final, fully inspected recovery segment until the * commit frontier enters a later segment. segdiskStoreMayHaveData() uses * the live read cursor and is the authoritative recovery-work check. A * durable cleanup already in progress is also eligible: failed repair may * retain stale cursors, but cleanup intent proves the store was empty. */ return s != NULL && s->dir_fd >= 0 && s->known_queue_size == 0 && s->pending_head == NULL && s->delete_first == 0 && (s->dematerializing || !segdiskStoreMayHaveData(s)); } rsRetVal segdiskStoreDequeueBatch(segdisk_store_t *s, batch_t *batch, int max, int *skipped, int *discovered) { if (s->dir_fd < 0) return RS_RET_NO_DATA; if (batch->storeData != NULL) return RS_RET_INTERNAL_ERROR; if (s->delete_first != 0) { if (cleanup_one_pending_delete(s) != RS_RET_OK) LogError(0, RS_RET_IO_ERROR, "%s: segmentedDisk pending segment deletion failed and will be retried", s->queue_name); if (s->delete_first != 0) return RS_RET_RETRY; } segdisk_batch_ctx_t *ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) return RS_RET_OUT_OF_MEMORY; ctx->sequence = s->next_batch_sequence++; ctx->refs = 1; ctx->pending = 1; int n = 0; int consumed = 0; sbool recovery_pending = 0; *skipped = 0; *discovered = 0; size_t scan_budget = RECOVERY_SCAN_BUDGET; while (n < max) { if (s->read_segment == NULL) { if (s->read_segment_id == 0) s->read_segment_id = s->first_live_segment; while (s->read_segment_id != 0 && s->read_segment_id <= s->last_data_segment) { rsRetVal r = load_segment(s, s->read_segment_id, &s->read_segment); if (r == RS_RET_FILE_NOT_FOUND) { ++s->stats.corruption_events; ++s->stats.corruption_segments; LogError(0, RS_RET_FILE_NOT_FOUND, "%s: segmentedDisk expected segment %" PRIu64 " is missing during lazy dequeue; continuing with the next segment", s->queue_name, s->read_segment_id); ++s->read_segment_id; s->read_offset = SEG_HDR_LEN; continue; } if (r != RS_RET_OK) { free(ctx); return r; } if (s->committed_segment == s->read_segment_id && s->committed_offset >= SEG_HDR_LEN && s->committed_offset <= s->read_segment->data_end) s->read_offset = s->committed_offset; else if (s->read_offset < SEG_HDR_LEN) s->read_offset = SEG_HDR_LEN; break; } if (s->read_segment == NULL) break; } smsg_t *msg = NULL; uint64_t sequence = 0; const int skipped_before = *skipped; rsRetVal r = record_at(s, s->read_segment, &s->read_offset, &msg, &sequence, skipped, discovered, &scan_budget); consumed += *skipped - skipped_before; if (r == RS_RET_RETRY) { ++s->stats.recovery_pending; recovery_pending = 1; break; } if (r == RS_RET_NO_DATA) { if (s->read_segment->id == s->active_segment) break; ++s->read_segment_id; s->read_offset = SEG_HDR_LEN; free_segment(&s->read_segment); continue; } if (r != RS_RET_OK) { free(ctx); return r; } ++consumed; ctx->end_segment = s->read_segment->id; ctx->end_offset = s->read_offset; ctx->end_record_sequence = sequence; batch->pElem[n].pMsg = msg; batch->eltState[n] = BATCH_STATE_RDY; ++n; } if (consumed == 0) { free(ctx); return recovery_pending ? RS_RET_RETRY : RS_RET_NO_DATA; } ctx->records = consumed; append_pending(s, ctx); if (n == 0) { ctx->complete = 1; const rsRetVal r = advance_completed(s); return r == RS_RET_OK ? RS_RET_NO_DATA : r; } batch->storeData = ctx; ++ctx->refs; batch->nElem = n; batch->nElemDeq = ctx->records; return RS_RET_OK; } rsRetVal segdiskStoreCompleteBatch(segdisk_store_t *s, batch_t *batch, int *committed, int *retried) { segdisk_batch_ctx_t *ctx = batch->storeData; if (ctx == NULL) return RS_RET_INTERNAL_ERROR; *committed = ctx->records; if (!ctx->pending) { *retried = ctx->retry_count; batch->storeData = NULL; release_batch_ctx(ctx); return RS_RET_OK; } while (ctx->retry_index < batch->nElem) { const int i = ctx->retry_index; if (batch->eltState[i] == BATCH_STATE_RDY || batch->eltState[i] == BATCH_STATE_SUB) { rsRetVal r = append_record(s, batch->pElem[i].pMsg, 1, NULL); if (r != RS_RET_OK) { *retried = ctx->retry_count; return r; } ++ctx->retry_count; } ++ctx->retry_index; } *retried = ctx->retry_count; ctx->complete = 1; const rsRetVal r = advance_completed(s); if (r == RS_RET_OK) { batch->storeData = NULL; release_batch_ctx(ctx); } return r; } rsRetVal segdiskStoreCheckpoint(segdisk_store_t *s, sbool force_sync) { if (s->dir_fd < 0) return RS_RET_OK; capture_writer(s); const rsRetVal r = write_state(s, force_sync, force_sync); if (r == RS_RET_OK) test_fault(s, SEGDISK_TEST_FAULT_CHECKPOINT_PUBLISHED); return r; } static void reset_after_dematerialize(segdisk_store_t *s) { memset(s->uuid, 0, sizeof(s->uuid)); s->generation = 0; s->committed_segment = 0; s->committed_record_sequence = 0; s->committed_offset = SEG_HDR_LEN; s->first_live_segment = 0; s->last_data_segment = 0; s->active_segment = 0; s->recovery_first = 0; s->recovery_last = 0; s->next_segment = 1; s->persisted_queue_size = 0; s->persisted_writer_segment = 0; s->persisted_writer_end = SEG_HDR_LEN; s->persisted_writer_sequence = 0; s->persisted_writer_count = 0; s->delete_first = 0; s->delete_last = 0; s->delete_bytes = 0; s->delete_segments = 0; s->discovery_through_segment = 0; s->read_segment_id = 0; s->read_offset = SEG_HDR_LEN; s->next_batch_sequence = 0; s->known_queue_size = 0; s->updates_since_checkpoint = 0; s->dematerializing = 0; s->stats.bytes = 0; s->stats.segments = 0; s->stats.retry_overage_bytes = 0; } static rsRetVal restore_empty_materialized(segdisk_store_t *s, uint64_t next_segment) { unsigned char old_uuid[sizeof(s->uuid)]; memcpy(old_uuid, s->uuid, sizeof(old_uuid)); const uint64_t old_generation = s->generation; if (s->dir_fd < 0) { s->dir_fd = open(s->dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); if (s->dir_fd < 0) return RS_RET_IO_ERROR; } /* The failed cleanup can have stopped after unlinking only part of the * old topology. Make a best effort to finish removing queue-owned files, * then prove none remain before publishing a fresh empty topology. A * foreign file may still make remove_remaining_segments() report failure; * that is harmless here because it is deliberately excluded from the * segment-only verification and will make the next rmdir retry fail. * Conversely, an undeletable segment leaves the cleanup-in-progress state * authoritative and prevents stale records from being hidden by a new * normal state. */ (void)remove_remaining_segments(s); sbool has_segments; if (directory_has_segments(s, &has_segments) != RS_RET_OK || has_segments) return RS_RET_IO_ERROR; const sbool state_present = faccessat(s->dir_fd, "state", F_OK, 0) == 0; if (!state_present) { if (s->state_fd >= 0) close(s->state_fd); s->state_fd = openat(s->dir_fd, "state", O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW, 0600); if (s->state_fd < 0 || ftruncate(s->state_fd, STATE_FILE_LEN) != 0) return RS_RET_IO_ERROR; } reset_after_dematerialize(s); s->next_segment = next_segment == 0 ? 1 : next_segment; if (state_present) { memcpy(s->uuid, old_uuid, sizeof(s->uuid)); s->generation = old_generation; } else if (random_uuid(s->uuid) != RS_RET_OK) { return RS_RET_IO_ERROR; } /* Keep every state publication in cleanup-in-progress form until the new * active segment is durable. Thus a crash during reconstruction finishes * deletion on restart instead of accepting a partially rebuilt store. */ s->dematerializing = 1; if (!state_present) { const rsRetVal state_ret = write_state(s, 1, 1); if (state_ret != RS_RET_OK) { close(s->state_fd); s->state_fd = -1; unlinkat(s->dir_fd, "state", 0); return state_ret; } } rsRetVal r = create_active(s); if (r == RS_RET_OK) { s->dematerializing = 0; r = write_state(s, 1, 1); if (r != RS_RET_OK) s->dematerializing = 1; } if (r == RS_RET_OK) r = sync_dir(s); return r; } rsRetVal segdiskStoreDematerialize(segdisk_store_t *s) { if (s == NULL) return RS_RET_PARAM_ERROR; if (s->dir_fd < 0) return RS_RET_OK; if (!segdiskStoreCanDematerialize(s)) return RS_RET_RETRY; const uint64_t restore_next_segment = s->next_segment; s->dematerializing = 1; rsRetVal r = write_state(s, 1, 1); if (r != RS_RET_OK) { /* No destructive step is permitted until the cleanup intent is * durable. The previous normal state and the still-open active * segment therefore remain a complete recoverable store when state * publication itself fails. */ s->dematerializing = 0; ++s->stats.idle_cleanup_failures; return r; } test_fault(s, SEGDISK_TEST_FAULT_IDLE_EMPTY_PUBLISHED); if (s->active_fd >= 0) { if (close(s->active_fd) != 0 && r == RS_RET_OK) r = RS_RET_IO_ERROR; s->active_fd = -1; } if (r == RS_RET_OK) r = remove_remaining_segments(s); if (r == RS_RET_OK) r = sync_dir(s); if (r == RS_RET_OK) test_fault(s, SEGDISK_TEST_FAULT_IDLE_SEGMENTS_UNLINKED); if (r == RS_RET_OK && unlinkat(s->dir_fd, "state", 0) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) test_fault(s, SEGDISK_TEST_FAULT_IDLE_STATE_UNLINKED); if (r == RS_RET_OK) r = sync_dir(s); free_segment(&s->active); free_segment(&s->read_segment); if (r == RS_RET_OK && rmdir(s->dir) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) test_fault(s, SEGDISK_TEST_FAULT_IDLE_DIRECTORY_REMOVED); if (r == RS_RET_OK) { if (s->state_fd >= 0) close(s->state_fd); if (s->dir_fd >= 0) close(s->dir_fd); s->state_fd = s->dir_fd = -1; reset_after_dematerialize(s); ++s->stats.dematerializations; } else { ++s->stats.idle_cleanup_failures; const rsRetVal restore_ret = restore_empty_materialized(s, restore_next_segment); if (restore_ret != RS_RET_OK) { /* r is already a hard failure returned to the queue callback. A * failed repair does not soften it: the durable * cleanup-in-progress state (or a state-free empty directory * after segment removal) makes restart complete deletion, while * the live worker retries cleanup in this process. */ LogError(0, restore_ret, "%s: failed to restore an empty segmentedDisk store after idle cleanup error", s->queue_name); } } return r; } #ifdef ENABLE_IMDIAG rsRetVal segdiskStoreSetTestFault(segdisk_store_t *s, const char *point, unsigned int hit_count) { if (s == NULL || point == NULL || hit_count == 0) return RS_RET_PARAM_ERROR; for (size_t i = 0; i < sizeof(test_fault_names) / sizeof(test_fault_names[0]); ++i) { if (!strcmp(point, test_fault_names[i].name)) { s->test_fault_point = test_fault_names[i].point; s->test_fault_hits_remaining = hit_count; return RS_RET_OK; } } return RS_RET_INVALID_VALUE; } void segdiskStoreClearTestFault(segdisk_store_t *s) { if (s == NULL) return; s->test_fault_point = SEGDISK_TEST_FAULT_NONE; s->test_fault_hits_remaining = 0; } #endif rsRetVal segdiskStoreClose(segdisk_store_t **ps, sbool empty) { if (ps == NULL || *ps == NULL) return RS_RET_OK; segdisk_store_t *s = *ps; rsRetVal r = RS_RET_OK; if (s->dir_fd < 0) { free(s->dir); free(s->queue_name); free(s); *ps = NULL; return RS_RET_OK; } if (s->active_fd >= 0) { if (!empty && s->active != NULL && s->active->record_count != 0) r = seal_active(s); else { close(s->active_fd); s->active_fd = -1; } } if (empty && s->dir_fd >= 0) { const uint64_t end = s->active_segment > s->last_data_segment ? s->active_segment : s->last_data_segment; for (uint64_t id = s->first_live_segment; id != 0 && id <= end; ++id) { rsRetVal local = unlink_segment_id(s, id, 0); if (local != RS_RET_OK && r == RS_RET_OK) r = local; } if (r == RS_RET_OK) r = remove_remaining_segments(s); if (r == RS_RET_OK && unlinkat(s->dir_fd, "state", 0) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; } else if (s->dir_fd >= 0 && r == RS_RET_OK) { capture_writer(s); r = write_state(s, 1, 1); } free_segment(&s->active); free_segment(&s->read_segment); while (s->pending_head != NULL) { segdisk_batch_ctx_t *n = s->pending_head->next; s->pending_head->pending = 0; release_batch_ctx(s->pending_head); s->pending_head = n; } if (s->state_fd >= 0) close(s->state_fd); if (s->dir_fd >= 0) close(s->dir_fd); if (empty && r == RS_RET_OK && rmdir(s->dir) != 0 && errno != ENOENT) r = RS_RET_IO_ERROR; free(s->dir); free(s->queue_name); free(s); *ps = NULL; return r; } void segdiskStoreGetStats(const segdisk_store_t *s, segdisk_store_stats_t *stats) { *stats = s->stats; } rsyslog-8.2608.0/runtime/PaxHeaders/stream.h0000644000000000000000000000013115241075234015670 xustar0030 mtime=1787067036.611578407 29 atime=1787067036.75758114 30 ctime=1787067794.379724775 rsyslog-8.2608.0/runtime/stream.h0000664000175000017500000003554115241075234015345 0ustar00rgerrger/* Definition of serial stream class (strm). * * A serial stream provides serial data access. In theory, serial streams * can be implemented via a number of methods (e.g. files or in-memory * streams). In practice, there currently only exist the file type (aka * "driver"). * * In practice, many stream features are bound to files. I have not yet made * any serious effort, except for the naming of this class, to try to make * the interfaces very generic. However, I assume that we could work much * like in the strm class, where some properties are simply ignored when * the wrong strm mode is selected (which would translate here to the wrong * stream mode). * * Most importantly, this class provides generic input and output functions * which can directly be used to work with the strms and file output. It * provides such useful things like a circular file buffer and, hopefully * at a later stage, a lazy writer. The object is also seriazable and thus * can easily be persistet. The bottom line is that it makes much sense to * use this class whereever possible as its features may grow in the future. * * An important note on writing gzip format via zlib (kept anonymous * by request): * * -------------------------------------------------------------------------- * We'd like to make sure the output file is in full gzip format * (compatible with gzip -d/zcat etc). There is a flag in how the output * is initialized within zlib to properly add the gzip wrappers to the * output. (gzip is effectively a small metadata wrapper around raw * zstream output.) * * I had written an old bit of code to do this - the documentation on * deflatInit2() was pretty tricky to nail down on this specific feature: * * int deflateInit2 (z_streamp strm, int level, int method, int windowBits, * int memLevel, int strategy); * * I believe "31" would be the value for the "windowBits" field that you'd * want to try: * * deflateInit2(zstrmptr, 6, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY); * -------------------------------------------------------------------------- * * Copyright 2008-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef STREAM_H_INCLUDED #define STREAM_H_INCLUDED typedef struct strm_s strm_t; /* forward reference because of zlib... */ #include // TODO: fix via own module #include #include #include #include "obj-types.h" #include "glbl.h" #include "stream.h" #include "zlibw.h" #include "cryprov.h" /* stream types */ typedef enum { STREAMTYPE_FILE_SINGLE = 0, /**< read a single file */ STREAMTYPE_FILE_CIRCULAR = 1, /**< circular files */ STREAMTYPE_FILE_MONITOR = 2, /**< monitor a (third-party) file */ STREAMTYPE_NAMED_PIPE = 3 /**< file is a named pipe (so far, tested for output only) */ } strmType_t; typedef enum { /* when extending, do NOT change existing modes! */ STREAMMMODE_INVALID = 0, STREAMMODE_READ = 1, STREAMMODE_WRITE = 2, STREAMMODE_WRITE_TRUNC = 3, STREAMMODE_WRITE_APPEND = 4 } strmMode_t; typedef enum { STRM_COMPRESS_ZIP = 0, STRM_COMPRESS_ZSTD = 1 } strm_compressionDriver_t; #define STREAM_ASYNC_NUMBUFS 2 /* must be a power of 2 -- TODO: make configurable */ /* The strm_t data structure */ struct strm_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ strmType_t sType; /* descriptive properties */ unsigned int iCurrFNum; /* current file number (NOT descriptor, but the number in the file name!) */ uchar *pszFName; /* prefix for generated filenames */ int lenFName; strmMode_t tOperationsMode; mode_t tOpenMode; int64 iMaxFileSize; /* maximum size a file may grow to */ unsigned int iMaxFiles; /* maximum number of files if a circular mode is in use */ int iFileNumDigits; /* min number of digits to use in file number (only in circular mode) */ sbool bDeleteOnClose; /* set to 1 to auto-delete on close -- be careful with that setting! */ int64 iCurrOffs; /* current offset */ int64 *pUsrWCntr; /* NULL or a user-provided counter that receives the nbr of bytes written since the last CntrSet() */ sbool bPrevWasNL; /* used for readLine() when reading multi-line messages */ /* dynamic properties, valid only during file open, not to be persistet */ sbool bDisabled; /* should file no longer be written to? (currently set only if omfile file size limit fails) */ sbool bSync; /* sync this file after every write? */ sbool bReopenOnTruncate; int rotationCheck; /* rotation check mode */ size_t sIOBufSize; /* size of IO buffer */ uchar *pszDir; /* Directory */ int lenDir; int fd; /* the file descriptor, -1 if closed */ int fdDir; /* the directory's descriptor, in case bSync is requested (-1 if closed) */ int readTimeout; /* 0: do not timeout */ time_t lastRead; /* for timeout processing */ ino_t inode; /* current inode for files being monitored (undefined else) */ uchar *pszCurrFName; /* name of current file (if open) */ uchar *pIOBuf; /* the iobuffer currently in use to gather data */ char *pIOBuf_truncation; /* iobuffer used during trucation detection block re-reads */ size_t iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */ size_t iBufPtr; /* pointer into current buffer */ int iUngetC; /* char set via UngetChar() call or -1 if none set */ sbool bInRecord; /* if 1, indicates that we are currently writing a not-yet complete record */ int iZipLevel; /* zip level (0..9). If 0, zip is completely disabled */ Bytef *pZipBuf; /* support for async flush procesing */ sbool bAsyncWrite; /* do asynchronous writes (always if a flush interval is given) */ sbool bStopWriter; /* shall writer thread terminate? */ sbool bDoTimedWait; /* instruct writer thread to do a times wait to support flush timeouts */ sbool bzInitDone; /* did we do an init of zstrm already? */ sbool bFlushNow; /* shall we flush with the next async write? */ sbool bVeryReliableZip; /* shall we write interim headers to create a very reliable ZIP file? */ int iFlushInterval; /* flush in which interval - 0, no flushing */ pthread_mutex_t mut; /* mutex for flush in async mode */ pthread_cond_t notFull; pthread_cond_t notEmpty; pthread_cond_t isEmpty; unsigned short iEnq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */ unsigned short iDeq; /* this MUST be unsigned as we use module arithmetic (else invalid indexing happens!) */ cryprov_if_t *cryprov; /* ptr to crypto provider; NULL = do not encrypt */ void *cryprovData; /* opaque data ptr for provider use */ void *cryprovFileData; /* opaque data ptr for file instance */ short iCnt; /* current nbr of elements in buffer */ z_stream zstrm; /* zip stream to use */ struct { uchar *pBuf; size_t lenBuf; } asyncBuf[STREAM_ASYNC_NUMBUFS]; struct { int num_wrkrs; /* nbr of worker threads */ void *cctx; } zstd; /* supporting per-instance data if zstd is used */ pthread_t writerThreadID; /* support for omfile size-limiting commands, special counters, NOT persisted! */ off_t iSizeLimit; /* file size limit, 0 = no limit */ uchar *pszSizeLimitCmd; /* command to carry out when size limit is reached */ sbool bSizeLimitCmdPassFileName; /* pass current file name as arg to size limit command? */ sbool bIsTTY; /* is this a tty file? */ cstr_t *prevLineSegment; /* for ReadLine, previous, unprocessed part of file */ cstr_t *prevMsgSegment; /* for ReadMultiLine, previous, yet unprocessed part of msg */ int64 strtOffs; /* start offset in file for current line/msg */ int fileNotFoundError; /* boolean; if set, report file not found errors, else silently ignore */ int noRepeatedErrorOutput; /* if a file is missing the Error is only given once */ sbool bNoFollowFinal; /* if set, do not follow final path component on open */ int ignoringMsg; strm_compressionDriver_t compressionDriver; }; /* interfaces */ BEGINinterface(strm) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(strm_t **ppThis); rsRetVal (*ConstructFinalize)(strm_t *pThis); rsRetVal (*Destruct)(strm_t **ppThis); rsRetVal (*SetFileName)(strm_t *pThis, uchar *pszName, size_t iLenName); rsRetVal (*ReadChar)(strm_t *pThis, uchar *pC); rsRetVal (*UnreadChar)(strm_t *pThis, uchar c); rsRetVal (*SeekCurrOffs)(strm_t *pThis); rsRetVal (*Write)(strm_t *const pThis, const uchar *const pBuf, size_t lenBuf); rsRetVal (*WriteChar)(strm_t *pThis, uchar c); rsRetVal (*WriteLong)(strm_t *pThis, long i); rsRetVal (*SetFileNotFoundError)(strm_t *pThis, int pFileNotFoundError); rsRetVal (*SetFName)(strm_t *pThis, uchar *pszPrefix, size_t iLenPrefix); rsRetVal (*SetDir)(strm_t *pThis, uchar *pszDir, size_t iLenDir); rsRetVal (*Flush)(strm_t *pThis); rsRetVal (*RecordBegin)(strm_t *pThis); rsRetVal (*RecordEnd)(strm_t *pThis); rsRetVal (*Serialize)(strm_t *pThis, strm_t *pStrm); rsRetVal (*GetCurrOffset)(strm_t *pThis, int64 *pOffs); rsRetVal (*SetWCntr)(strm_t *pThis, number_t *pWCnt); rsRetVal (*Dup)(strm_t *pThis, strm_t **ppNew); rsRetVal (*Sync)(strm_t *pStrmDest, const strm_t *pStrmSrc); rsRetVal (*SetCompressionWorkers)(strm_t *const pThis, int num_wrkrs); INTERFACEpropSetMeth(strm, bDeleteOnClose, int); INTERFACEpropSetMeth(strm, iMaxFileSize, int64); INTERFACEpropSetMeth(strm, iMaxFiles, int); INTERFACEpropSetMeth(strm, iFileNumDigits, int); INTERFACEpropSetMeth(strm, tOperationsMode, int); INTERFACEpropSetMeth(strm, tOpenMode, mode_t); INTERFACEpropSetMeth(strm, bNoFollowFinal, int); INTERFACEpropSetMeth(strm, compressionDriver, strm_compressionDriver_t); INTERFACEpropSetMeth(strm, sType, strmType_t); INTERFACEpropSetMeth(strm, iZipLevel, int); INTERFACEpropSetMeth(strm, bSync, int); INTERFACEpropSetMeth(strm, bReopenOnTruncate, int); INTERFACEpropSetMeth(strm, sIOBufSize, size_t); INTERFACEpropSetMeth(strm, iSizeLimit, off_t); INTERFACEpropSetMeth(strm, iFlushInterval, int); INTERFACEpropSetMeth(strm, pszSizeLimitCmd, uchar *); INTERFACEpropSetMeth(strm, bSizeLimitCmdPassFileName, int); /* v6 added */ rsRetVal (*ReadLine)(strm_t *pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF, const uchar *, uint32_t trimLineOverBytes, int64 *const strtOffs); /* v7 added 2012-09-14 */ INTERFACEpropSetMeth(strm, bVeryReliableZip, int); /* v8 added 2013-03-21 */ rsRetVal (*CheckFileChange)(strm_t *pThis); /* v9 added 2013-04-04 */ INTERFACEpropSetMeth(strm, cryprov, cryprov_if_t *); INTERFACEpropSetMeth(strm, cryprovData, void *); ENDinterface(strm) #define strmCURR_IF_VERSION 17 /* increment whenever you change the interface structure! */ /* V10, 2013-09-10: added new parameter bEscapeLF, changed mode to uint8_t (rgerhards) */ /* V11, 2015-12-03: added new parameter bReopenOnTruncate */ /* V12, 2015-12-11: added new parameter trimLineOverBytes, changed mode to uint32_t */ /* V13, 2017-09-06: added new parameter strtoffs to ReadLine() */ /* V14, 2019-11-13: added new parameter bEscapeLFString (rgerhards) */ /* V15, ?? - description missing */ /* V16, 2026-01-28: added new parameter bSizeLimitCmdPassFileName (rgerhards) */ /* V17, 2026-06-23: added bNoFollowFinal stream property setter */ #define strmGetCurrFileNum(pStrm) ((pStrm)->iCurrFNum) /* prototypes */ PROTOTYPEObjClassInit(strm); PROTOTYPEObjQueryInterface(strm); PROTOTYPEobjConstruct(strm); PROTOTYPEobjDestruct(strm); PROTOTYPEpropSetMeth(strm, iMaxFileSize, int64); PROTOTYPEpropSetMeth(strm, iFileNumDigits, int); PROTOTYPEpropSetMeth(strm, tOperationsMode, int); PROTOTYPEpropSetMeth(strm, tOpenMode, mode_t); PROTOTYPEpropSetMeth(strm, bNoFollowFinal, int); PROTOTYPEpropSetMeth(strm, compressionDriver, strm_compressionDriver_t); PROTOTYPEpropSetMeth(strm, sType, strmType_t); PROTOTYPEpropSetMeth(strm, iZipLevel, int); PROTOTYPEpropSetMeth(strm, bVeryReliableZip, int); PROTOTYPEpropSetMeth(strm, bSync, int); PROTOTYPEpropSetMeth(strm, bReopenOnTruncate, int); PROTOTYPEpropSetMeth(strm, sIOBufSize, size_t); PROTOTYPEpropSetMeth(strm, iSizeLimit, off_t); PROTOTYPEpropSetMeth(strm, iFlushInterval, int); PROTOTYPEpropSetMeth(strm, pszSizeLimitCmd, uchar *); PROTOTYPEpropSetMeth(strm, bSizeLimitCmdPassFileName, int); PROTOTYPEpropSetMeth(strm, cryprov, cryprov_if_t *); PROTOTYPEpropSetMeth(strm, cryprovData, void *); rsRetVal strmMultiFileSeek(strm_t *pThis, unsigned int fileNum, off64_t offs, off64_t *bytesDel); rsRetVal ATTR_NONNULL(1, 2) strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, const sbool bEscapeLF, const uchar *const escapeLFString, const sbool discardTruncatedMsg, const sbool msgDiscardingError, int64 *const strtOffs); int strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis); void strmDebugOutBuf(const strm_t *const pThis); void strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val); const uchar *ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis); const uchar *ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis); int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis); #endif /* #ifndef STREAM_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/yamlconf.h0000644000000000000000000000013215171370365016213 xustar0030 mtime=1776677109.451913233 30 atime=1787067616.847415581 30 ctime=1787067794.452726136 rsyslog-8.2608.0/runtime/yamlconf.h0000664000175000017500000000375415171370365015670 0ustar00rgerrger/* yamlconf.h - YAML configuration file loader for rsyslog * * Provides yamlconf_load(), which parses a .yaml/.yml config file and * populates the rsyslog loadConf object by building the same cnfobj/nvlst * structures the RainerScript bison parser produces, then routing them * through the existing cnfDoObj() / cnfDoScript() dispatcher. * * Compilation is conditional on HAVE_LIBYAML (configure.ac detects yaml-0.1 * via pkg-config). The caller in rsconf.c is responsible for the #ifdef guard. * * Copyright 2025 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YAMLCONF_H_INCLUDED #define YAMLCONF_H_INCLUDED #include "rsyslog.h" #ifdef HAVE_LIBYAML /* Load a rsyslog configuration from a YAML file. * * fname - path to the .yaml / .yml config file * * Returns RS_RET_OK on success, RS_RET_CONF_FILE_NOT_FOUND if the file cannot * be opened, RS_RET_CONF_PARSE_ERROR on YAML or semantic errors. On error * LogError() is called with a descriptive message before returning. * * This function populates the global loadConf object (runtime/rsconf.c) by * calling cnfDoObj() / cnfDoScript() / cnfAddConfigBuffer() exactly as the * RainerScript yyparse() path does. The caller (rsconf.c::load()) must have * already called rsconfConstruct() before invoking this function. */ rsRetVal yamlconf_load(const char *fname); #endif /* HAVE_LIBYAML */ #endif /* YAMLCONF_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/conf.h0000644000000000000000000000013215132411300015306 xustar0030 mtime=1768559296.261885561 30 atime=1787067616.819415059 30 ctime=1787067794.283722986 rsyslog-8.2608.0/runtime/conf.h0000666000175000017500000000575015132411300014763 0ustar00rgerrger/* Definitions for config file handling (not yet an object). * * Copyright 2008-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_CONF_H #define INCLUDED_CONF_H #include "action.h" /* definitions used for doNameLine to differentiate between different command types * (with otherwise identical code). This is a left-over from the previous config * system. It stays, because it is still useful. So do not wonder why it looks * somewhat strange (at least its name). -- rgerhards, 2007-08-01 */ enum eDirective { DIR_TEMPLATE = 0, DIR_OUTCHANNEL = 1, DIR_ALLOWEDSENDER = 2 }; extern ecslConfObjType currConfObj; extern int bConfStrictScoping; /* force strict scoping during config processing? */ /* interfaces */ BEGINinterface(conf) /* name must also be changed in ENDinterface macro! */ rsRetVal (*doNameLine)(uchar **pp, void *pVal); rsRetVal (*cfsysline)(uchar *p); rsRetVal (*doModLoad)(uchar **pp, __attribute__((unused)) void *pVal); rsRetVal (*GetNbrActActions)(rsconf_t *conf, int *); /* version 4 -- 2010-07-23 rgerhards */ /* "just" added global variables * FYI: we reconsider repacking as a non-object, as only the core currently * accesses this module. The current object structure complicates things without * any real benefit. */ /* version 5 -- 2011-04-19 rgerhards */ /* complete revamp, we now use the rsconf object */ /* version 6 -- 2011-07-06 rgerhards */ /* again a complete revamp, using flex/bison based parser now */ ENDinterface(conf) #define confCURR_IF_VERSION 6 /* increment whenever you change the interface structure! */ /* in Version 3, entry point "ReInitConf()" was removed, as we do not longer need * to support restart-type HUP -- rgerhards, 2009-07-15 */ /* prototypes */ PROTOTYPEObj(conf); /* TODO: the following 2 need to go in conf obj interface... */ rsRetVal cflineParseTemplateName(uchar **pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName); rsRetVal cflineParseFileName( uchar *p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl); rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[]); rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction); extern EHostnameCmpMode eDfltHostnameCmpMode; extern cstr_t *pDfltHostnameCmp; extern cstr_t *pDfltProgNameCmp; #endif /* #ifndef INCLUDED_CONF_H */ rsyslog-8.2608.0/runtime/PaxHeaders/msg.h0000644000000000000000000000013215241075234015164 xustar0030 mtime=1787067036.602578238 30 atime=1787067036.748580972 30 ctime=1787067794.307723433 rsyslog-8.2608.0/runtime/msg.h0000664000175000017500000004267615241075234014647 0ustar00rgerrger/* msg.h * Header file for all msg-related functions. * * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) * * Copyright 2007-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "template.h" /* this is a quirk, but these two are too interdependant... */ #ifndef MSG_H_INCLUDED #define MSG_H_INCLUDED 1 #include #include #include #include #include "obj.h" #include "syslogd-types.h" #include "template.h" #include "atomic.h" /* rgerhards 2004-11-08: The following structure represents a * syslog message. * * Important Note: * The message object is used for multiple purposes (once it * has been created). Once created, it actully is a read-only * object (though we do not specifically express this). In order * to avoid multiple copies of the same object, we use a * reference counter. This counter is set to 1 by the constructer * and increased by 1 with a call to MsgAddRef(). The destructor * checks the reference count. If it is more than 1, only the counter * will be decremented. If it is 1, however, the object is actually * destroyed. To make this work, it is vital that MsgAddRef() is * called each time a "copy" is stored somewhere. * * WARNING: this structure is not calloc()ed, so be careful when * adding new fields. You need to initialize them in * msgBaseConstruct(). That function header comment also describes * why this is the case. */ struct msg { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ flowControl_t flowCtlType; /**< type of flow control we can apply, for enqueueing, needs not to be persisted because once data has entered the queue, this property is no longer needed. */ pthread_mutex_t mut; int iRefCount; /* reference counter (0 = unused) */ sbool bParseSuccess; /* set to reflect state of last executed higher level parser */ unsigned short iSeverity; /* the severity */ unsigned short iFacility; /* Facility code */ int offAfterPRI; /* offset, at which raw message WITHOUT PRI part starts in pszRawMsg */ int offMSG; /* offset at which the MSG part starts in pszRawMsg */ short iProtocolVersion; /* protocol version of message received 0 - legacy, 1 syslog-protocol) */ int msgFlags; /* flags associated with this message */ int iLenRawMsg; /* length of raw message */ int iLenMSG; /* Length of the MSG part */ int iLenTAG; /* Length of the TAG part */ int iLenHOSTNAME; /* Length of HOSTNAME */ int iLenPROGNAME; /* Length of PROGNAME (-1 = not yet set) */ uchar *pszRawMsg; /* message as it was received on the wire. This is important in case we * need to preserve cryptographic verifiers. */ uchar *pszHOSTNAME; /* HOSTNAME from syslog message */ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 characters) */ char *pszRcvdAt3339; /* time as RFC3164 formatted string (32 characters at most) */ char *pszRcvdAt_MySQL; /* rcvdAt as MySQL formatted string (always 14 characters) */ char *pszRcvdAt_PgSQL; /* rcvdAt as PgSQL formatted string (always 21 characters) */ char *pszTIMESTAMP3164; /* TIMESTAMP as RFC3164 formatted string (always 15 characters) */ char *pszTIMESTAMP3339; /* TIMESTAMP as RFC3339 formatted string (32 characters at most) */ char *pszTIMESTAMP_MySQL; /* TIMESTAMP as MySQL formatted string (always 14 characters) */ char *pszTIMESTAMP_PgSQL; /* TIMESTAMP as PgSQL formatted string (always 21 characters) */ uchar *pszStrucData; /* STRUCTURED-DATA */ rs_size_t lenStrucData; /* (cached) length of STRUCTURED-DATA */ cstr_t *pCSAPPNAME; /* APP-NAME */ cstr_t *pCSPROCID; /* PROCID */ cstr_t *pCSMSGID; /* MSGID */ prop_t *pInputName; /* input name property */ prop_t *pRcvFromIP; /* IP of system message was received from */ prop_t *pRcvFromPort; /* port of system message was received from */ union { prop_t *pRcvFrom; /* name of system message was received from */ struct sockaddr_storage *pfrominet; /* unresolved name */ } rcvFrom; ruleset_t *pRuleset; /* ruleset to be used for processing this message */ time_t ttGenTime; /* time msg object was generated, same as tRcvdAt, but a Unix timestamp. While this field looks redundant, it is required because a Unix timestamp is used at later processing stages (namely in the output arena). Thanks to the subleties of how time is defined, there is no reliable way to reconstruct the Unix timestamp from the syslogTime fields (in practice, we may be close enough to reliable, but I prefer to leave the subtle things to the OS, where it obviously is solved in way or another...). */ struct syslogTime tRcvdAt; /* time the message entered this program */ struct syslogTime tTIMESTAMP; /* (parsed) value of the timestamp */ struct json_object *json; struct json_object *localvars; #ifdef HAVE_LOGNORM_TURBO /* Opaque turbo result slot — set by mmnormalize turbo path. * Enables zero-JSON data flow: template resolution reads fields * directly from the snapshot without building a json-c tree. * No liblognorm dependency: uses void* + function pointer callbacks. */ void *turbo_result; void (*turbo_result_free)(void *); void (*turbo_result_to_json)(void *, struct json_object **); int (*turbo_result_get_str)(void *, const uchar *, int, const uchar **, rs_size_t *); /* Shared-ownership refcount for turbo_result across MsgDup() copies. * NULL while a single message owns the snapshot (the common case: * no allocation, no atomics); lazily allocated on the first dup. * The last owner (counter reaches 0) frees the snapshot. */ unsigned *turbo_result_refs; #endif /* some fixed-size buffers to save malloc()/free() for frequently used fields (from the default templates) */ uchar szRawMsg[CONF_RAWMSG_BUFSIZE]; /* most messages are small, and these are stored here (without malloc/free!) */ uchar szHOSTNAME[CONF_HOSTNAME_BUFSIZE]; union { uchar *ptr; /* pointer to progname value */ uchar szBuf[CONF_PROGNAME_BUFSIZE]; } PROGNAME; union { uchar *pszTAG; /* pointer to tag value */ uchar szBuf[CONF_TAG_BUFSIZE]; } TAG; char pszTimestamp3164[CONST_LEN_TIMESTAMP_3164 + 1]; char pszTimestamp3339[CONST_LEN_TIMESTAMP_3339 + 1]; char pszTIMESTAMP_SecFrac[7]; /* Note: a pointer is 64 bits/8 char, so this is actually fewer than a pointer! */ char pszRcvdAt_SecFrac[7]; /* same as above. Both are fractional seconds for their respective timestamp */ char pszTIMESTAMP_Unix[12]; /* almost as small as a pointer! */ char pszRcvdAt_Unix[12]; char dfltTZ[8]; /* 7 chars max, less overhead than ptr! */ uchar *pszUUID; /* The message's UUID */ }; /* message flags (msgFlags), not an enum for historical reasons */ #define NOFLAG 0x000 /* no flag is set (to be used when a flag must be specified and none is required) */ #define INTERNAL_MSG 0x001 /* msg generated by logmsgInternal() --> special handling */ /* 0x002 not used because it was previously a known value - rgerhards, 2008-10-09 */ #define IGNDATE 0x004 /* ignore, if given, date in message and use date of reception as msg date */ #define MARK 0x008 /* this message is a mark */ #define NEEDS_PARSING 0x010 /* raw message, must be parsed before processing can be done */ #define PARSE_HOSTNAME 0x020 /* parse the hostname during message parsing */ #define NEEDS_DNSRESOL 0x040 /* fromhost address is unresolved and must be locked up via DNS reverse lookup first */ #define NEEDS_ACLCHK_U 0x080 /* check UDP ACLs after DNS resolution has been done in main queue consumer */ #define NO_PRI_IN_RAW 0x100 /* rawmsg does not include a PRI (Solaris!), but PRI is already set correctly in the msg object */ #define PRESERVE_CASE 0x200 /* preserve case in fromhost */ #define NO_LEGACY_Z_DECOMPRESS 0x400 /* skip built-in legacy 'z' transport-frame decompression */ /* (syslog) protocol types */ #define MSG_LEGACY_PROTOCOL 0 #define MSG_RFC5424_PROTOCOL 1 #define MAX_VARIABLE_NAME_LEN 1024 /* function prototypes */ PROTOTYPEObjClassInit(msg); rsRetVal msgConstruct(smsg_t **ppThis); rsRetVal msgConstructWithTime(smsg_t **ppThis, const struct syslogTime *stTime, const time_t ttGenTime); rsRetVal msgConstructForDeserializer(smsg_t **ppThis); rsRetVal msgConstructFinalizer(smsg_t *pThis); rsRetVal msgDestruct(smsg_t **ppM); smsg_t *MsgDup(smsg_t *pOld); #ifdef HAVE_LOGNORM_TURBO /** * @brief Release a message's reference to its turbo parse snapshot. * * The snapshot can be shared across MsgDup() copies. This function decrements * the shared ownership count, frees the snapshot for the last owner, and * clears the message's snapshot pointer and all associated callbacks. Callers * must hold @p pMsg's mutex or otherwise have exclusive access to the message. * Never invoke turbo_result_free directly. * * @param pMsg Message whose turbo snapshot reference is released. */ void MsgReleaseTurboResult(smsg_t *pMsg); #endif smsg_t *MsgAddRef(smsg_t *pM); void setProtocolVersion(smsg_t *pM, int iNewVersion); /** Set a message's input-name property. * @param pMsg message to update * @param inputName property retained by the message; the caller remains * responsible for releasing its own reference */ void MsgSetInputName(smsg_t *pMsg, prop_t *inputName); rsRetVal MsgSetInputNameStr(smsg_t *pMsg, const uchar *text, int len); rsRetVal MsgSetRcvFromText(smsg_t *pMsg, const uchar *text, int len); rsRetVal MsgSetRcvFromIPText(smsg_t *pMsg, const uchar *text, int len); rsRetVal MsgSetRcvFromPortText(smsg_t *pMsg, const uchar *text, int len); void MsgSetDfltTZ(smsg_t *pThis, char *tz); rsRetVal MsgSetAPPNAME(smsg_t *pMsg, const char *pszAPPNAME); rsRetVal MsgSetPROCID(smsg_t *pMsg, const char *pszPROCID); rsRetVal MsgSetMSGID(smsg_t *pMsg, const char *pszMSGID); void MsgSetParseSuccess(smsg_t *pMsg, int bSuccess); void MsgSetTAG(smsg_t *pMsg, const uchar *pszBuf, const size_t lenBuf); void MsgSetRuleset(smsg_t *pMsg, ruleset_t *); rsRetVal MsgSetRulesetByName(smsg_t *pMsg, cstr_t *rulesetName); rsRetVal MsgSetFlowControlType(smsg_t *pMsg, flowControl_t eFlowCtl); rsRetVal MsgSetStructuredData(smsg_t *const pMsg, const char *pszStrucData); rsRetVal MsgAddToStructuredData(smsg_t *pMsg, uchar *toadd, rs_size_t len); void MsgGetStructuredData(smsg_t *pM, uchar **pBuf, rs_size_t *len); rsRetVal msgSetFromSockinfo(smsg_t *pThis, struct sockaddr_storage *sa); rsRetVal msgSetFromSockinfoLen(smsg_t *pThis, const struct sockaddr_storage *sa, size_t salen); /** Set a message's received-from property. * @param pMsg message to update * @param rcvFrom property retained by the message; the caller remains * responsible for releasing its own reference */ void MsgSetRcvFrom(smsg_t *pMsg, prop_t *rcvFrom); void MsgSetRcvFromStr(smsg_t *const pMsg, const uchar *pszRcvFrom, const int, prop_t **); rsRetVal MsgSetRcvFromIP(smsg_t *pMsg, prop_t *); rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp); rsRetVal MsgSetRcvFromPort(smsg_t *pMsg, prop_t *); rsRetVal MsgSetRcvFromPortStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp); void MsgSetHOSTNAME(smsg_t *pMsg, const uchar *pszHOSTNAME, const int lenHOSTNAME); rsRetVal MsgSetAfterPRIOffs(smsg_t *pMsg, int offs); void MsgSetMSGoffs(smsg_t *pMsg, int offs); void MsgSetRawMsgWOSize(smsg_t *pMsg, char *pszRawMsg); void ATTR_NONNULL() MsgSetRawMsg(smsg_t *const pThis, const char *const pszRawMsg, const size_t lenMsg); rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar *pszMSG, int lenMSG); uchar *MsgGetProp(smsg_t *pMsg, struct templateEntry *pTpe, msgPropDescr_t *pProp, rs_size_t *pPropLen, unsigned short *pbMustBeFreed, struct syslogTime *ttNow); void getTAG(smsg_t *pM, uchar **ppBuf, int *piLen, sbool); const char *getTimeReported(smsg_t *pM, enum tplFormatTypes eFmt); const char *getPRI(smsg_t *pMsg); int getPRIi(const smsg_t *const pM); int ATTR_NONNULL() getRawMsgLen(const smsg_t *const pMsg); void getRawMsg(const smsg_t *pM, uchar **pBuf, int *piLen); void ATTR_NONNULL() MsgTruncateToMaxSize(smsg_t *const pThis); rsRetVal msgAddJSON(smsg_t *pM, uchar *name, struct json_object *json, int force_reset, int sharedReference); rsRetVal msgAddMetadata(smsg_t *msg, uchar *metaname, uchar *metaval); rsRetVal msgAddMultiMetadata(smsg_t *msg, const uchar **metaname, const uchar **metaval, const int count); rsRetVal MsgGetSeverity(smsg_t *pThis, int *piSeverity); rsRetVal MsgDeserialize(smsg_t *pMsg, strm_t *pStrm); rsRetVal MsgSetPropsViaJSON(smsg_t *__restrict__ const pMsg, const uchar *__restrict__ const json); rsRetVal MsgSetPropsViaJSON_Object(smsg_t *__restrict__ const pMsg, struct json_object *json); const uchar *msgGetJSONMESG(smsg_t *__restrict__ const pMsg); /** * @brief Acquire the message mutex. * * @param pMsg Message instance to lock. */ void MsgLock(smsg_t *pMsg); /** * @brief Release the message mutex. * * @param pMsg Message instance to unlock. */ void MsgUnlock(smsg_t *pMsg); uchar *getMSG(smsg_t *pM); const char *getHOSTNAME(smsg_t *pM); char *getPROCID(smsg_t *pM, sbool bLockMutex); char *getAPPNAME(smsg_t *pM, sbool bLockMutex); void setMSGLen(smsg_t *pM, int lenMsg); int getMSGLen(smsg_t *pM); void getInputName(const smsg_t *const pM, uchar **ppsz, int *const plen); int getHOSTNAMELen(smsg_t *pM); uchar *getProgramName(smsg_t *pM, sbool bLockMutex); uchar *getRcvFrom(smsg_t *pM); uchar *getRcvFromIP(smsg_t *pM); uchar *getRcvFromPort(smsg_t *pM); void MsgGetRcvFromProp(smsg_t *pM, propid_t propid, uchar **ppsz, int *plen); rsRetVal propNameToID(const uchar *pName, propid_t *pPropID); uchar *propIDToName(propid_t propID); rsRetVal ATTR_NONNULL() msgCheckVarExists(smsg_t *const pMsg, msgPropDescr_t *pProp); rsRetVal msgGetJSONPropJSON(smsg_t *pMsg, msgPropDescr_t *pProp, struct json_object **pjson); rsRetVal msgGetJSONPropJSONorString(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **pjson, uchar **pcstr); rsRetVal getJSONPropVal( smsg_t *pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed); rsRetVal msgSetJSONFromVar(smsg_t *pMsg, uchar *varname, struct svar *var, int force_reset); rsRetVal msgDelJSON(smsg_t *pMsg, uchar *varname); rsRetVal jsonFind(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **jsonres); struct json_object *jsonDeepCopy(struct json_object *src); rsRetVal msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen); void msgPropDescrDestruct(msgPropDescr_t *pProp); void msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri); #define msgGetProtocolVersion(pM) ((pM)->iProtocolVersion) /* returns non-zero if the message has structured data, 0 otherwise */ #define MsgHasStructuredData(pM) (((pM)->pszStrucData == NULL) ? 0 : 1) /* ------------------------------ some inline functions ------------------------------ */ /* add Metadata to the message. This is stored in a special JSON * container. Note that only string types are currently supported, * what should pose absolutely no problem with the string-ish nature * of rsyslog metadata. * added 2015-01-09 rgerhards */ /* set raw message size. This is needed in some cases where a trunctation is necessary * but the raw message must not be newly set. The most important (and currently only) * use case is if we remove trailing LF or NUL characters. Note that the size can NOT * be extended, only shrunk! * rgerhards, 2009-08-26 */ static inline void __attribute__((unused)) MsgSetRawMsgSize(smsg_t *const __restrict__ pMsg, const size_t newLen) { assert(newLen <= (size_t)pMsg->iLenRawMsg); pMsg->iLenRawMsg = newLen; pMsg->pszRawMsg[newLen] = '\0'; } /* get the ruleset that is associated with the ruleset. * May be NULL. -- rgerhards, 2009-10-27 */ #define MsgGetRuleset(pMsg) ((pMsg)->pRuleset) #endif /* #ifndef MSG_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_ptcp.h0000644000000000000000000000013215241075234016210 xustar0030 mtime=1787067036.604578276 30 atime=1787067036.751581028 30 ctime=1787067794.570728335 rsyslog-8.2608.0/runtime/nsd_ptcp.h0000664000175000017500000000405315241075234015656 0ustar00rgerrger/* An implementation of the nsd interface for plain tcp sockets. * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NSD_PTCP_H #define INCLUDED_NSD_PTCP_H #include #include "tcpsrv.h" #include "nsd.h" typedef nsd_if_t nsd_ptcp_if_t; /* we just *implement* this interface */ /* the nsd_ptcp object */ struct nsd_ptcp_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ prop_t *remoteIP; /**< IP address of remote peer (currently used in server mode, only) */ uchar *pRemHostName; /**< host name of remote peer (currently used in server mode, only) */ struct sockaddr_storage remAddr; /**< remote addr as sockaddr - used for legacy ACL code */ int sock; /**< the socket we use for regular, single-socket, operations */ int iKeepAliveIntvl; /**< socket layer KEEPALIVE interval */ int iKeepAliveProbes; /**< socket layer KEEPALIVE probes */ int iKeepAliveTime; /**< socket layer KEEPALIVE timeout */ int tcp_user_timeout_ms; /**< socket layer TCP_USER_TIMEOUT in milliseconds */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsd_ptcpCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObjFull(nsd_ptcp); /* the name of our library binary */ #define LM_NSD_PTCP_FILENAME "lmnsd_ptcp" #endif /* #ifndef INCLUDED_NSD_PTCP_H */ rsyslog-8.2608.0/runtime/PaxHeaders/net.c0000644000000000000000000000013115241075234015156 xustar0030 mtime=1787067036.602578238 29 atime=1787067036.74958099 30 ctime=1787067794.525727496 rsyslog-8.2608.0/runtime/net.c0000664000175000017500000017500715241075234014635 0ustar00rgerrger/* net.c * Implementation of network-related stuff. * * File begun on 2007-07-20 by RGerhards (extracted from syslogd.c) * This file is under development and has not yet arrived at being fully * self-contained and a real object. So far, it is mostly an excerpt * of the "old" networking code without any modifications. However, it * helps to have things at the right place one we go to the meat of it. * * Starting 2007-12-24, I have begun to shuffle more network-related code * from syslogd.c to over here. I am not sure if it will stay here in the * long term, but it is good to have it out of syslogd.c. Maybe this here is * an interim location ;) * * Copyright 2007-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETIFADDRS #include #else #include "compat/ifaddrs.h" #endif /* HAVE_GETIFADDRS */ #include #include #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "parse.h" #include "srUtils.h" #include "obj.h" #include "errmsg.h" #include "net.h" #include "dnscache.h" #include "prop.h" #include "rsconf.h" #ifdef OS_SOLARIS #include #define s6_addr32 _S6_un._S6_u32 typedef unsigned int u_int32_t; #endif MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) /* support for defining allowed TCP and UDP senders. We use the same * structure to implement this (a linked list), but we define two different * list roots, one for UDP and one for TCP. * rgerhards, 2005-09-26 */ /* All of the five below are read-only after startup */ struct AllowedSenders *pAllowedSenders_UDP = NULL; /* the roots of the allowed sender */ struct AllowedSenders *pAllowedSenders_TCP = NULL; /* lists. If NULL, all senders are ok! */ static struct AllowedSenders *pLastAllowedSenders_UDP = NULL; /* and now the pointers to the last */ static struct AllowedSenders *pLastAllowedSenders_TCP = NULL; /* element in the respective list */ #ifdef USE_GSSAPI struct AllowedSenders *pAllowedSenders_GSS = NULL; static struct AllowedSenders *pLastAllowedSenders_GSS = NULL; #endif /* ------------------------------ begin permitted peers code ------------------------------ */ /* sets the correct allow root pointer based on provided type * rgerhards, 2008-12-01 */ static rsRetVal setAllowRoot(struct AllowedSenders **ppAllowRoot, uchar *pszType) { DEFiRet; if (!strcmp((char *)pszType, "UDP")) *ppAllowRoot = pAllowedSenders_UDP; else if (!strcmp((char *)pszType, "TCP")) *ppAllowRoot = pAllowedSenders_TCP; #ifdef USE_GSSAPI else if (!strcmp((char *)pszType, "GSS")) *ppAllowRoot = pAllowedSenders_GSS; #endif else { dbgprintf("program error: invalid allowed sender ID '%s', denying...\n", pszType); ABORT_FINALIZE(RS_RET_CODE_ERR); /* everything is invalid for an invalid type */ } finalize_it: RETiRet; } /* re-initializes (sets to NULL) the correct allow root pointer * rgerhards, 2009-01-12 */ static rsRetVal reinitAllowRoot(uchar *pszType) { DEFiRet; if (!strcmp((char *)pszType, "UDP")) pAllowedSenders_UDP = NULL; else if (!strcmp((char *)pszType, "TCP")) pAllowedSenders_TCP = NULL; #ifdef USE_GSSAPI else if (!strcmp((char *)pszType, "GSS")) pAllowedSenders_GSS = NULL; #endif else { dbgprintf("program error: invalid allowed sender ID '%s', denying...\n", pszType); ABORT_FINALIZE(RS_RET_CODE_ERR); /* everything is invalid for an invalid type */ } finalize_it: RETiRet; } /* add a wildcard entry to this permitted peer. Entries are always * added at the tail of the list. pszStr and lenStr identify the wildcard * entry to be added. Note that the string is NOT \0 terminated, so * we must rely on lenStr for when it is finished. * rgerhards, 2008-05-27 */ static rsRetVal AddPermittedPeerWildcard(permittedPeers_t *pPeer, uchar *pszStr, size_t lenStr) { permittedPeerWildcard_t *pNew = NULL; size_t iSrc; size_t iDst; DEFiRet; assert(pPeer != NULL); assert(pszStr != NULL); CHKmalloc(pNew = calloc(1, sizeof(*pNew))); if (lenStr == 0) { /* empty domain components are permitted */ pNew->wildcardType = PEER_WILDCARD_EMPTY_COMPONENT; FINALIZE; } else { /* alloc memory for the domain component. We may waste a byte or * two, but that's ok. */ CHKmalloc(pNew->pszDomainPart = malloc(lenStr + 1)); } if (pszStr[0] == '*') { pNew->wildcardType = PEER_WILDCARD_AT_START; iSrc = 1; /* skip '*' */ } else { iSrc = 0; } for (iDst = 0; iSrc < lenStr && pszStr[iSrc] != '*'; ++iSrc, ++iDst) { pNew->pszDomainPart[iDst] = pszStr[iSrc]; } if (iSrc < lenStr) { if (iSrc + 1 == lenStr && pszStr[iSrc] == '*') { if (pNew->wildcardType == PEER_WILDCARD_AT_START) { ABORT_FINALIZE(RS_RET_INVALID_WILDCARD); } else { pNew->wildcardType = PEER_WILDCARD_AT_END; } } else { /* we have an invalid wildcard, something follows the asterisk! */ ABORT_FINALIZE(RS_RET_INVALID_WILDCARD); } } if (lenStr == 1 && pNew->wildcardType == PEER_WILDCARD_AT_START) { pNew->wildcardType = PEER_WILDCARD_MATCH_ALL; } /* if we reach this point, we had a valid wildcard. We now need to * properly terminate the domain component string. */ pNew->pszDomainPart[iDst] = '\0'; pNew->lenDomainPart = strlen((char *)pNew->pszDomainPart); finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) { if (pNew->pszDomainPart != NULL) free(pNew->pszDomainPart); free(pNew); } } else { /* enqueue the element */ if (pPeer->pWildcardRoot == NULL) { pPeer->pWildcardRoot = pNew; pPeer->pWildcardLast = pNew; } else { pPeer->pWildcardLast->pNext = pNew; } pPeer->pWildcardLast = pNew; } RETiRet; } /* Destruct a permitted peer's wildcard list -- rgerhards, 2008-05-27 */ static rsRetVal DestructPermittedPeerWildcards(permittedPeers_t *pPeer) { permittedPeerWildcard_t *pCurr; permittedPeerWildcard_t *pDel; DEFiRet; assert(pPeer != NULL); for (pCurr = pPeer->pWildcardRoot; pCurr != NULL; /*EMPTY*/) { pDel = pCurr; pCurr = pCurr->pNext; free(pDel->pszDomainPart); free(pDel); } pPeer->pWildcardRoot = NULL; pPeer->pWildcardLast = NULL; RETiRet; } /* add a permitted peer. PermittedPeers is an interim solution until we can provide * access control via enhanced RainerScript methods. * Note: the provided string is handed over to this function, caller must * no longer access it. -- rgerhards, 2008-05-19 */ static rsRetVal AddPermittedPeer(permittedPeers_t **ppRootPeer, uchar *pszID) { permittedPeers_t *pNew = NULL; DEFiRet; assert(ppRootPeer != NULL); assert(pszID != NULL); CHKmalloc(pNew = calloc(1, sizeof(permittedPeers_t))); /* we use calloc() for consistency with "real" objects */ CHKmalloc(pNew->pszID = (uchar *)strdup((char *)pszID)); if (*ppRootPeer != NULL) { pNew->pNext = *ppRootPeer; } *ppRootPeer = pNew; finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) free(pNew); } RETiRet; } /* Destruct a permitted peers list -- rgerhards, 2008-05-19 */ static rsRetVal DestructPermittedPeers(permittedPeers_t **ppRootPeer) { permittedPeers_t *pCurr; permittedPeers_t *pDel; DEFiRet; assert(ppRootPeer != NULL); for (pCurr = *ppRootPeer; pCurr != NULL; /*EMPTY*/) { pDel = pCurr; pCurr = pCurr->pNext; DestructPermittedPeerWildcards(pDel); free(pDel->pszID); free(pDel); } *ppRootPeer = NULL; RETiRet; } /* Compile a wildcard. The function first checks if there is a wildcard * present and compiles it only if so ;) It sets the etryType status * accordingly. * rgerhards, 2008-05-27 */ static rsRetVal PermittedPeerWildcardCompile(permittedPeers_t *pPeer) { uchar *pC; uchar *pStart; DEFiRet; assert(pPeer != NULL); assert(pPeer->pszID != NULL); /* first check if we have a wildcard */ for (pC = pPeer->pszID; *pC != '\0' && *pC != '*'; ++pC) /*EMPTY, just skip*/ ; if (*pC == '\0') { /* no wildcard found, we are mostly done */ pPeer->etryType = PERM_PEER_TYPE_PLAIN; FINALIZE; } /* if we reach this point, the string contains wildcards. So let's * compile the structure. To do so, we must parse from dot to dot * and create a wildcard entry for each domain component we find. * We must also flag problems if we have an asterisk in the middle * of the text (it is supported at the start or end only). */ pPeer->etryType = PERM_PEER_TYPE_WILDCARD; pC = pPeer->pszID; while (*pC != '\0') { pStart = pC; /* find end of domain component */ for (; *pC != '\0' && *pC != '.'; ++pC) /*EMPTY, just skip*/ ; CHKiRet(AddPermittedPeerWildcard(pPeer, pStart, pC - pStart)); /* now check if we have an empty component at end of string */ if (*pC == '.' && *(pC + 1) == '\0') { /* pStart is a dummy, it is not used if length is 0 */ CHKiRet(AddPermittedPeerWildcard(pPeer, pStart, 0)); } if (*pC != '\0') ++pC; } finalize_it: if (iRet != RS_RET_OK) { LogError(0, iRet, "error compiling wildcard expression '%s'", pPeer->pszID); } RETiRet; } /* Do a (potential) wildcard match. The function first checks if the wildcard * has already been compiled and, if not, compiles it. If the peer entry in * question does NOT contain a wildcard, a simple strcmp() is done. * *pbIsMatching is set to 0 if there is no match and something else otherwise. * rgerhards, 2008-05-27 */ static rsRetVal PermittedPeerWildcardMatch(permittedPeers_t *const pPeer, const uchar *pszNameToMatch, int *const pbIsMatching) { const permittedPeerWildcard_t *pWildcard; const uchar *pC; size_t iWildcard, iName; /* work indexes for backward comparisons */ DEFiRet; assert(pPeer != NULL); assert(pszNameToMatch != NULL); assert(pbIsMatching != NULL); if (pPeer->etryType == PERM_PEER_TYPE_UNDECIDED) { PermittedPeerWildcardCompile(pPeer); } if (pPeer->etryType == PERM_PEER_TYPE_PLAIN) { *pbIsMatching = !strcmp((char *)pPeer->pszID, (char *)pszNameToMatch); FINALIZE; } /* we have a wildcard, so we need to extract the domain components and * check then against the provided wildcards. */ pWildcard = pPeer->pWildcardRoot; pC = pszNameToMatch; while (*pC != '\0') { if (pWildcard == NULL) { /* we have more domain components than we have wildcards --> no match */ *pbIsMatching = 0; FINALIZE; } const uchar *const pStart = pC; /* start of current domain component */ while (*pC != '\0' && *pC != '.') { ++pC; } /* got the component, now do the match */ switch (pWildcard->wildcardType) { case PEER_WILDCARD_NONE: if (pWildcard->lenDomainPart != (size_t)(pC - pStart) || strncmp((char *)pStart, (char *)pWildcard->pszDomainPart, pC - pStart)) { *pbIsMatching = 0; FINALIZE; } break; case PEER_WILDCARD_AT_START: /* we need to do the backwards-matching manually */ if (pWildcard->lenDomainPart > (size_t)(pC - pStart)) { *pbIsMatching = 0; FINALIZE; } iName = (size_t)(pC - pStart) - pWildcard->lenDomainPart; iWildcard = 0; while (iWildcard < pWildcard->lenDomainPart) { // I give up, I see now way to remove false positive -- rgerhards, 2017-10-23 #ifndef __clang_analyzer__ if (pWildcard->pszDomainPart[iWildcard] != pStart[iName]) { *pbIsMatching = 0; FINALIZE; } #endif ++iName; ++iWildcard; } break; case PEER_WILDCARD_AT_END: if (pWildcard->lenDomainPart > (size_t)(pC - pStart) || strncmp((char *)pStart, (char *)pWildcard->pszDomainPart, pWildcard->lenDomainPart)) { *pbIsMatching = 0; FINALIZE; } break; case PEER_WILDCARD_MATCH_ALL: /* everything is OK, just continue */ break; case PEER_WILDCARD_EMPTY_COMPONENT: if (pC - pStart > 0) { /* if it is not empty, it is no match... */ *pbIsMatching = 0; FINALIZE; } break; default: // We need to satisfy compiler which does not properly handle enum break; } pWildcard = pWildcard->pNext; /* we processed this entry */ /* skip '.' if we had it and so prepare for next iteration */ if (*pC == '.') ++pC; } if (pWildcard != NULL) { /* we have more domain components than in the name to be * checked. So this is no match. */ *pbIsMatching = 0; FINALIZE; } *pbIsMatching = 1; /* finally... it matches ;) */ finalize_it: RETiRet; } /* ------------------------------ end permitted peers code ------------------------------ */ /* Code for handling allowed/disallowed senders */ static void MaskIP6(struct in6_addr *addr, uint8_t bits) { register uint8_t i; assert(addr != NULL); assert(bits <= 128); i = bits / 32; if (bits % 32) addr->s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32))); for (; i < (sizeof addr->s6_addr32) / 4; i++) addr->s6_addr32[i] = 0; } static void MaskIP4(struct in_addr *addr, uint8_t bits) { assert(addr != NULL); assert(bits <= 32); addr->s_addr &= htonl(0xffffffff << (32 - bits)); } #define SIN(sa) ((struct sockaddr_in *)(void *)(sa)) #define SIN6(sa) ((struct sockaddr_in6 *)(void *)(sa)) /* This is a cancel-safe getnameinfo() version, because we learned * (via drd/valgrind) that getnameinfo() seems to have some issues * when being cancelled, at least if the module was dlloaded. * rgerhards, 2008-09-30 */ static int mygetnameinfo( const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { int iCancelStateSave; int i; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); i = getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); pthread_setcancelstate(iCancelStateSave, NULL); return i; } /* This function adds an allowed sender entry to the ACL linked list. * In any case, a single entry is added. If an error occurs, the * function does its error reporting itself. All validity checks * must already have been done by the caller. * This is a helper to AddAllowedSender(). * rgerhards, 2007-07-17 */ static rsRetVal AddAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast, struct NetAddr *iAllow, uint8_t iSignificantBits) { struct AllowedSenders *pEntry = NULL; assert(ppRoot != NULL); assert(ppLast != NULL); assert(iAllow != NULL); if ((pEntry = (struct AllowedSenders *)calloc(1, sizeof(struct AllowedSenders))) == NULL) { return RS_RET_OUT_OF_MEMORY; /* no options left :( */ } memcpy(&(pEntry->allowedSender), iAllow, sizeof(struct NetAddr)); pEntry->pNext = NULL; pEntry->SignificantBits = iSignificantBits; /* enqueue */ if (*ppRoot == NULL) { *ppRoot = pEntry; } else { (*ppLast)->pNext = pEntry; } *ppLast = pEntry; return RS_RET_OK; } /* function to clear the allowed sender structure in cases where * it must be freed (occurs most often when HUPed). * rgerhards, 2008-12-02: revamped this code when we fixed the interface * definition. Now an iterative algorithm is used. */ static void clearAllowedSenders(uchar *pszType) { struct AllowedSenders *pPrev; struct AllowedSenders *pCurr = NULL; if (setAllowRoot(&pCurr, pszType) != RS_RET_OK) return; /* if something went wrong, so let's leave */ while (pCurr != NULL) { pPrev = pCurr; pCurr = pCurr->pNext; /* now delete the entry we are right now processing */ if (F_ISSET(pPrev->allowedSender.flags, ADDR_NAME)) free(pPrev->allowedSender.addr.HostWildcard); else free(pPrev->allowedSender.addr.NetAddr); free(pPrev); } /* indicate root pointer is de-init (was forgotten previously, resulting in * all kinds of interesting things) -- rgerhards, 2009-01-12 */ reinitAllowRoot(pszType); } static void DestructAllowedSenders(struct AllowedSenders **ppRoot) { struct AllowedSenders *pPrev; struct AllowedSenders *pCurr; assert(ppRoot != NULL); pCurr = *ppRoot; while (pCurr != NULL) { pPrev = pCurr; pCurr = pCurr->pNext; if (F_ISSET(pPrev->allowedSender.flags, ADDR_NAME)) free(pPrev->allowedSender.addr.HostWildcard); else free(pPrev->allowedSender.addr.NetAddr); free(pPrev); } *ppRoot = NULL; } /* function to add an allowed sender to the allowed sender list. The * root of the list is caller-provided, so it can be used for all * supported lists. The caller must provide a pointer to the root, * as it eventually needs to be updated. Also, a pointer to the * pointer to the last element must be provided (to speed up adding * list elements). * rgerhards, 2005-09-26 * If a hostname is given there are possible multiple entries * added (all addresses from that host). */ static rsRetVal AddAllowedSender(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast, struct NetAddr *iAllow, uint8_t iSignificantBits) { struct addrinfo *restmp = NULL; DEFiRet; assert(ppRoot != NULL); assert(ppLast != NULL); assert(iAllow != NULL); if (!F_ISSET(iAllow->flags, ADDR_NAME)) { if (iSignificantBits == 0) /* we handle this seperatly just to provide a better * error message. */ LogError(0, NO_ERRCODE, "You can not specify 0 bits of the netmask, this would " "match ALL systems. If you really intend to do that, " "remove all $AllowedSender directives."); switch (iAllow->addr.NetAddr->sa_family) { case AF_INET: if ((iSignificantBits < 1) || (iSignificantBits > 32)) { LogError(0, NO_ERRCODE, "Invalid number of bits (%d) in IPv4 address - adjusted to 32", (int)iSignificantBits); iSignificantBits = 32; } MaskIP4(&(SIN(iAllow->addr.NetAddr)->sin_addr), iSignificantBits); break; case AF_INET6: if ((iSignificantBits < 1) || (iSignificantBits > 128)) { LogError(0, NO_ERRCODE, "Invalid number of bits (%d) in IPv6 address - adjusted to 128", iSignificantBits); iSignificantBits = 128; } MaskIP6(&(SIN6(iAllow->addr.NetAddr)->sin6_addr), iSignificantBits); break; default: /* rgerhards, 2007-07-16: We have an internal program error in this * case. However, there is not much we can do against it right now. Of * course, we could abort, but that would probably cause more harm * than good. So we continue to run. We simply do not add this line - the * worst thing that happens is that one host will not be allowed to * log. */ LogError(0, NO_ERRCODE, "Internal error caused AllowedSender to be ignored, AF = %d", iAllow->addr.NetAddr->sa_family); ABORT_FINALIZE(RS_RET_ERR); } /* OK, entry constructed, now lets add it to the ACL list */ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits); } else { /* we need to process a hostname ACL */ if (glbl.GetDisableDNS(loadConf)) { LogError(0, NO_ERRCODE, "Ignoring hostname based ACLs because DNS is disabled."); ABORT_FINALIZE(RS_RET_OK); } if (!strchr(iAllow->addr.HostWildcard, '*') && !strchr(iAllow->addr.HostWildcard, '?') && loadConf->globals.ACLDontResolve == 0) { /* single host - in this case, we pull its IP addresses from DNS * and add IP-based ACLs. */ struct addrinfo hints, *res; struct NetAddr allowIP; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; #ifdef AI_ADDRCONFIG /* seems not to be present on all systems */ hints.ai_flags = AI_ADDRCONFIG; #endif if (getaddrinfo(iAllow->addr.HostWildcard, NULL, &hints, &res) != 0) { LogError(0, NO_ERRCODE, "DNS error: Can't resolve \"%s\"", iAllow->addr.HostWildcard); if (loadConf->globals.ACLAddHostnameOnFail) { LogError(0, NO_ERRCODE, "Adding hostname \"%s\" to ACL as a wildcard " "entry.", iAllow->addr.HostWildcard); iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits); FINALIZE; } else { LogError(0, NO_ERRCODE, "Hostname \"%s\" WON\'T be added to ACL.", iAllow->addr.HostWildcard); ABORT_FINALIZE(RS_RET_NOENTRY); } } restmp = res; for (; res != NULL; res = res->ai_next) { switch (res->ai_family) { case AF_INET: /* add IPv4 */ iSignificantBits = 32; allowIP.flags = 0; if ((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen); if ((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits)) != RS_RET_OK) { free(allowIP.addr.NetAddr); FINALIZE; } break; case AF_INET6: /* IPv6 - but need to check if it is a v6-mapped IPv4 */ if (IN6_IS_ADDR_V4MAPPED(&SIN6(res->ai_addr)->sin6_addr)) { /* extract & add IPv4 */ iSignificantBits = 32; allowIP.flags = 0; if ((allowIP.addr.NetAddr = (struct sockaddr *)malloc(sizeof(struct sockaddr))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } SIN(allowIP.addr.NetAddr)->sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN SIN(allowIP.addr.NetAddr)->sin_len = sizeof(struct sockaddr_in); #endif SIN(allowIP.addr.NetAddr)->sin_port = 0; memcpy(&(SIN(allowIP.addr.NetAddr)->sin_addr.s_addr), &(SIN6(res->ai_addr)->sin6_addr.s6_addr32[3]), sizeof(in_addr_t)); if ((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits)) != RS_RET_OK) { free(allowIP.addr.NetAddr); FINALIZE; } } else { /* finally add IPv6 */ iSignificantBits = 128; allowIP.flags = 0; if ((allowIP.addr.NetAddr = malloc(res->ai_addrlen)) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } memcpy(allowIP.addr.NetAddr, res->ai_addr, res->ai_addrlen); if ((iRet = AddAllowedSenderEntry(ppRoot, ppLast, &allowIP, iSignificantBits)) != RS_RET_OK) { free(allowIP.addr.NetAddr); FINALIZE; } } break; default: // We need to satisfy compiler which does not properly handle enum break; } } } else { /* wildcards in hostname - we need to add a text-based ACL. * For this, we already have everything ready and just need * to pass it along... */ iRet = AddAllowedSenderEntry(ppRoot, ppLast, iAllow, iSignificantBits); } } finalize_it: if (restmp != NULL) { freeaddrinfo(restmp); } RETiRet; } static const char *SENDER_TEXT[4] = {"", "UDP", "TCP", "GSS"}; /* Print an allowed sender list. The caller must tell us which one. * iListToPrint = 1 means UDP, 2 means TCP * rgerhards, 2005-09-27 */ static void PrintAllowedSenders(int iListToPrint) { struct AllowedSenders *pSender; uchar szIP[64]; #ifdef USE_GSSAPI #define iListToPrint_MAX 3 #else #define iListToPrint_MAX 2 #endif assert((iListToPrint > 0) && (iListToPrint <= iListToPrint_MAX)); dbgprintf("Allowed %s Senders:\n", SENDER_TEXT[iListToPrint]); pSender = (iListToPrint == 1) ? pAllowedSenders_UDP : #ifdef USE_GSSAPI (iListToPrint == 3) ? pAllowedSenders_GSS : #endif pAllowedSenders_TCP; if (pSender == NULL) { dbgprintf("\tNo restrictions set.\n"); } else { while (pSender != NULL) { if (F_ISSET(pSender->allowedSender.flags, ADDR_NAME)) dbgprintf("\t%s\n", pSender->allowedSender.addr.HostWildcard); else { if (mygetnameinfo(pSender->allowedSender.addr.NetAddr, SALEN(pSender->allowedSender.addr.NetAddr), (char *)szIP, 64, NULL, 0, NI_NUMERICHOST) == 0) { dbgprintf("\t%s/%u\n", szIP, pSender->SignificantBits); } else { /* getnameinfo() failed - but as this is only a * debug function, we simply spit out an error and do * not care much about it. */ dbgprintf( "\tERROR in getnameinfo() - something may be wrong " "- ignored for now\n"); } } pSender = pSender->pNext; } } } /* parse an allowed sender config line and add the allowed senders * (if the line is correct). * rgerhards, 2005-09-27 */ static rsRetVal addAllowedSenderLine(char *pName, uchar **ppRestOfConfLine) { struct AllowedSenders **ppRoot; struct AllowedSenders **ppLast; rsParsObj *pPars; rsRetVal iRet; struct NetAddr *uIP = NULL; int iBits; assert(pName != NULL); assert(ppRestOfConfLine != NULL); assert(*ppRestOfConfLine != NULL); if (!strcasecmp(pName, "udp")) { ppRoot = &pAllowedSenders_UDP; ppLast = &pLastAllowedSenders_UDP; } else if (!strcasecmp(pName, "tcp")) { ppRoot = &pAllowedSenders_TCP; ppLast = &pLastAllowedSenders_TCP; #ifdef USE_GSSAPI } else if (!strcasecmp(pName, "gss")) { ppRoot = &pAllowedSenders_GSS; ppLast = &pLastAllowedSenders_GSS; #endif } else { LogError(0, RS_RET_ERR, "Invalid protocol '%s' in allowed sender " "list, line ignored", pName); return RS_RET_ERR; } /* OK, we now know the protocol and have valid list pointers. * So let's process the entries. We are using the parse class * for this. */ /* create parser object starting with line string without leading colon */ if ((iRet = rsParsConstructFromSz(&pPars, (uchar *)*ppRestOfConfLine)) != RS_RET_OK) { LogError(0, iRet, "Error %d constructing parser object - ignoring allowed sender list", iRet); return (iRet); } while (!parsIsAtEndOfParseString(pPars)) { if (parsPeekAtCharAtParsPtr(pPars) == '#') break; /* a comment-sign stops processing of line */ /* now parse a single IP address */ if ((iRet = parsAddrWithBits(pPars, &uIP, &iBits)) != RS_RET_OK) { LogError(0, iRet, "Error %d parsing address in allowed sender" "list - ignoring.", iRet); rsParsDestruct(pPars); return (iRet); } if ((iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits)) != RS_RET_OK) { if (iRet == RS_RET_NOENTRY) { LogError(0, iRet, "Error %d adding allowed sender entry " "- ignoring.", iRet); } else { LogError(0, iRet, "Error %d adding allowed sender entry " "- terminating, nothing more will be added.", iRet); rsParsDestruct(pPars); free(uIP); return (iRet); } } free(uIP); /* copy stored in AllowedSenders list */ } /* cleanup */ *ppRestOfConfLine += parsGetCurrentPosition(pPars); return rsParsDestruct(pPars); } static rsRetVal addAllowedSenderEntry(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast, uchar *pszAllowedSender) { rsParsObj *pPars = NULL; struct NetAddr *uIP = NULL; int iBits; DEFiRet; assert(ppRoot != NULL); assert(ppLast != NULL); assert(pszAllowedSender != NULL); CHKiRet(rsParsConstructFromSz(&pPars, pszAllowedSender)); CHKiRet(parsAddrWithBits(pPars, &uIP, &iBits)); if (!parsIsAtEndOfParseString(pPars)) { LogError(0, RS_RET_INVALID_PARAMS, "Invalid extra data after allowedSender entry '%s'", pszAllowedSender); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } iRet = AddAllowedSender(ppRoot, ppLast, uIP, iBits); if (iRet == RS_RET_NOENTRY) { LogError(0, iRet, "Error %d adding allowedSender entry '%s' - ignoring.", iRet, pszAllowedSender); iRet = RS_RET_OK; } CHKiRet(iRet); finalize_it: if (uIP != NULL) { free(uIP); /* copy stored in AllowedSenders list */ } if (pPars != NULL) { rsParsDestruct(pPars); } RETiRet; } /* compares a host to an allowed sender list entry. Handles all subleties * including IPv4/v6 as well as domain name wildcards. * This is a helper to isAllowedSender. * Returns 0 if they do not match, 1 if they match and 2 if a DNS name would have been required. * contributed 2007-07-16 by mildew@gmail.com */ static int MaskCmp(struct NetAddr *pAllow, uint8_t bits, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS) { assert(pAllow != NULL); assert(pFrom != NULL); if (F_ISSET(pAllow->flags, ADDR_NAME)) { if (bChkDNS == 0) return 2; dbgprintf("MaskCmp: host=\"%s\"; pattern=\"%s\"\n", pszFromHost, pAllow->addr.HostWildcard); #if !defined(FNM_CASEFOLD) /* TODO: I don't know if that then works, seen on HP UX, what I have not in lab... ;) */ return (fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE) == 0); #else return (fnmatch(pAllow->addr.HostWildcard, pszFromHost, FNM_NOESCAPE | FNM_CASEFOLD) == 0); #endif } else { /* We need to compare an IP address */ switch (pFrom->sa_family) { case AF_INET: if (AF_INET == pAllow->addr.NetAddr->sa_family) return ((SIN(pFrom)->sin_addr.s_addr & htonl(0xffffffff << (32 - bits))) == SIN(pAllow->addr.NetAddr)->sin_addr.s_addr); else return 0; break; case AF_INET6: switch (pAllow->addr.NetAddr->sa_family) { case AF_INET6: { struct in6_addr ip, net; register uint8_t i; memcpy(&ip, &(SIN6(pFrom))->sin6_addr, sizeof(struct in6_addr)); memcpy(&net, &(SIN6(pAllow->addr.NetAddr))->sin6_addr, sizeof(struct in6_addr)); i = bits / 32; if (bits % 32) ip.s6_addr32[i++] &= htonl(0xffffffff << (32 - (bits % 32))); for (; i < (sizeof ip.s6_addr32) / 4; i++) ip.s6_addr32[i] = 0; return (memcmp(ip.s6_addr, net.s6_addr, sizeof ip.s6_addr) == 0 && (SIN6(pAllow->addr.NetAddr)->sin6_scope_id != 0 ? SIN6(pFrom)->sin6_scope_id == SIN6(pAllow->addr.NetAddr)->sin6_scope_id : 1)); } case AF_INET: { struct in6_addr *ip6 = &(SIN6(pFrom))->sin6_addr; struct in_addr *net = &(SIN(pAllow->addr.NetAddr))->sin_addr; if ((ip6->s6_addr32[3] & (u_int32_t)htonl((0xffffffff << (32 - bits)))) == net->s_addr && #if BYTE_ORDER == LITTLE_ENDIAN (ip6->s6_addr32[2] == (u_int32_t)0xffff0000) && #else (ip6->s6_addr32[2] == (u_int32_t)0x0000ffff) && #endif (ip6->s6_addr32[1] == 0) && (ip6->s6_addr32[0] == 0)) return 1; else return 0; } default: /* Unsupported AF */ return 0; } /* fallthrough */ default: /* Unsupported AF */ return 0; } } } /* check if a sender is allowed. The root of the the allowed sender. * list must be proveded by the caller. As such, this function can be * used to check both UDP and TCP allowed sender lists. * returns 1, if the sender is allowed, 0 if not and 2 if we could not * obtain a result because we would need a dns name, which we don't have * (2 was added rgerhards, 2009-11-16). * rgerhards, 2005-09-26 */ static int isAllowedSenderList(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS) { struct AllowedSenders *pAllow; int bNeededDNS = 0; /* partial check because we could not resolve DNS? */ int ret; assert(pFrom != NULL); if (pAllowRoot == NULL) return 1; /* checking disabled, everything is valid! */ /* now we loop through the list of allowed senders. As soon as * we find a match, we return back (indicating allowed). We loop * until we are out of allowed senders. If so, we fall through the * loop and the function's terminal return statement will indicate * that the sender is disallowed. */ for (pAllow = pAllowRoot; pAllow != NULL; pAllow = pAllow->pNext) { ret = MaskCmp(&(pAllow->allowedSender), pAllow->SignificantBits, pFrom, pszFromHost, bChkDNS); if (ret == 1) return 1; else if (ret == 2) bNeededDNS = 2; } return bNeededDNS; } static int isAllowedSender2(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS) { struct AllowedSenders *pAllowRoot = NULL; assert(pFrom != NULL); if (setAllowRoot(&pAllowRoot, pszType) != RS_RET_OK) return 0; /* if something went wrong, we deny access - that's the better choice... */ return isAllowedSenderList(pAllowRoot, pFrom, pszFromHost, bChkDNS); } /* legacy API, not to be used any longer */ static int isAllowedSender(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost) { return isAllowedSender2(pszType, pFrom, pszFromHost, 1); } /* The following #ifdef sequence is a small compatibility * layer. It tries to work around the different availality * levels of SO_BSDCOMPAT on linuxes... * I borrowed this code from * http://www.erlang.org/ml-archive/erlang-questions/200307/msg00037.html * It still needs to be a bit better adapted to rsyslog. * rgerhards 2005-09-19 */ #include static int should_use_so_bsdcompat(void) { #ifndef OS_BSD static int use_so_bsdcompat = -1; /* we guard the init code just by an atomic fetch to local variable. This still * is racy, but the worst that can happen is that we do the very same init twice. * This does hurt less than locking a mutex. */ const int local_use_so_bsdcompat = PREFER_FETCH_32BIT(use_so_bsdcompat); if (local_use_so_bsdcompat == -1) { struct utsname myutsname; unsigned int version, patchlevel; if (uname(&myutsname) < 0) { char errStr[1024]; dbgprintf("uname: %s\r\n", rs_strerror_r(errno, errStr, sizeof(errStr))); PREFER_STORE_1_TO_INT(&use_so_bsdcompat); FINALIZE; } /* Format is .. * where the first three are unsigned integers and the last * is an arbitrary string. We only care about the first two. */ if (sscanf(myutsname.release, "%u.%u", &version, &patchlevel) != 2) { dbgprintf("uname: unexpected release '%s'\r\n", myutsname.release); PREFER_STORE_1_TO_INT(&use_so_bsdcompat); FINALIZE; } /* SO_BSCOMPAT is deprecated and triggers warnings in 2.5 * kernels. It is a no-op in 2.4 but not in 2.2 kernels. */ if (version > 2 || (version == 2 && patchlevel >= 5)) { PREFER_STORE_0_TO_INT(&use_so_bsdcompat); FINALIZE; } } finalize_it: return PREFER_FETCH_32BIT(use_so_bsdcompat); #else /* #ifndef OS_BSD */ return 1; #endif /* #ifndef OS_BSD */ } #ifndef SO_BSDCOMPAT /* this shall prevent compiler errors due to undfined name */ #define SO_BSDCOMPAT 0 #endif /* print out which socket we are listening on. This is only * a debug aid. rgerhards, 2007-07-02 */ static void debugListenInfo(int fd, char *type) { const char *szFamily; int port; union { struct sockaddr_storage sa; struct sockaddr_in sa4; struct sockaddr_in6 sa6; } sockaddr; socklen_t saLen = sizeof(sockaddr.sa); if (getsockname(fd, (struct sockaddr *)&sockaddr.sa, &saLen) == 0) { switch (sockaddr.sa.ss_family) { case PF_INET: szFamily = "IPv4"; port = ntohs(sockaddr.sa4.sin_port); break; case PF_INET6: szFamily = "IPv6"; port = ntohs(sockaddr.sa6.sin6_port); break; default: szFamily = "other"; port = -1; break; } dbgprintf("Listening on %s syslogd socket %d (%s/port %d).\n", type, fd, szFamily, port); return; } /* we can not obtain peer info. We are just providing * debug info, so this is no reason to break the program * or do any serious error reporting. */ dbgprintf("Listening on syslogd socket %d - could not obtain peer info.\n", fd); } /* Return a printable representation of a host addresses. If * a parameter is NULL, it is not set. rgerhards, 2013-01-22 */ static rsRetVal cvthname(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip) { DEFiRet; assert(f != NULL); iRet = dnscacheLookup(f, fqdn, NULL, localName, ip); RETiRet; } /* get the name of the local host. A pointer to a character pointer is passed * in, which on exit points to the local hostname. This buffer is dynamically * allocated and must be free()ed by the caller. If the functions returns an * error, the pointer is NULL. * This function always tries to return a FQDN, even so be quering DNS. So it * is safe to assume for the caller that when the function does not return * a FQDN, it simply is not available. The domain part of that string is * normalized to lower case. The hostname is kept in mixed case for historic * reasons. */ #define EMPTY_HOSTNAME_REPLACEMENT "localhost-empty-hostname" static rsRetVal getLocalHostname(rsconf_t *const pConf, uchar **ppName) { DEFiRet; char hnbuf[8192]; uchar *fqdn = NULL; int empty_hostname = 1; if (gethostname(hnbuf, sizeof(hnbuf)) != 0) { RS_COPY_LITERAL(hnbuf, EMPTY_HOSTNAME_REPLACEMENT); } else { /* now guard against empty hostname * see https://github.com/rsyslog/rsyslog/issues/1040 */ if (hnbuf[0] == '\0') { RS_COPY_LITERAL(hnbuf, EMPTY_HOSTNAME_REPLACEMENT); } else { empty_hostname = 0; hnbuf[sizeof(hnbuf) - 1] = '\0'; /* be on the safe side... */ } } char *dot = strstr(hnbuf, "."); struct addrinfo *res = NULL; if (!empty_hostname && dot == NULL && pConf != NULL && !glbl.GetDisableDNS(pConf)) { /* we need to (try) to find the real name via resolver */ struct addrinfo flags; memset(&flags, 0, sizeof(flags)); flags.ai_flags = AI_CANONNAME; int error = getaddrinfo((char *)hnbuf, NULL, &flags, &res); if (error != 0 && error != EAI_NONAME && error != EAI_AGAIN && error != EAI_FAIL) { /* If we get one of errors above, network is probably * not working yet, so we fall back to local hostname below */ LogError(0, RS_RET_ERR, "getaddrinfo failed obtaining local " "hostname - using '%s' instead; error: %s", hnbuf, gai_strerror(error)); } if (res != NULL) { /* When AI_CANONNAME is set first member of res linked-list */ /* should contain what we need */ if (res->ai_canonname != NULL && res->ai_canonname[0] != '\0') { CHKmalloc(fqdn = (uchar *)strdup(res->ai_canonname)); dot = strstr((char *)fqdn, "."); } } } if (fqdn == NULL) { /* already was FQDN or we could not obtain a better one */ CHKmalloc(fqdn = (uchar *)strdup(hnbuf)); } if (dot != NULL) for (char *p = dot + 1; *p; ++p) *p = tolower(*p); *ppName = fqdn; finalize_it: if (res != NULL) { freeaddrinfo(res); } RETiRet; } /* closes the UDP listen sockets (if they exist) and frees * all dynamically assigned memory. */ static void closeUDPListenSockets(int *pSockArr) { register int i; assert(pSockArr != NULL); if (pSockArr != NULL) { for (i = 0; i < *pSockArr; i++) close(pSockArr[i + 1]); free(pSockArr); } } /* create a single UDP socket and bail out if an error occurs. * This is called from a loop inside create_udp_socket which * iterates through potentially multiple sockets. NOT to be * used elsewhere. */ static rsRetVal ATTR_NONNULL(1, 2) create_single_udp_socket(int *const s, /* socket */ struct addrinfo *const r, const uchar *const hostname, const int bIsServer, const int rcvbuf, const int sndbuf, const int ipfreebind, const char *const device) { const int on = 1; int sockflags; int actrcvbuf; int actsndbuf; socklen_t optlen; char errStr[1024]; DEFiRet; assert(r != NULL); // does NOT work with -O2 or higher due to ATTR_NONNULL! assert(s != NULL); #if defined(_AIX) /* AIXPORT : socktype will be SOCK_DGRAM, as set in hints before */ *s = socket(r->ai_family, SOCK_DGRAM, r->ai_protocol); #else *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); #endif if (*s < 0) { if (!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) { LogError(errno, NO_ERRCODE, "create_udp_socket(), socket"); /* it is debateble if PF_INET with EAFNOSUPPORT should * also be ignored... */ } ABORT_FINALIZE(RS_RET_ERR); } #ifdef IPV6_V6ONLY if (r->ai_family == AF_INET6) { int ion = 1; if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ion, sizeof(ion)) < 0) { LogError(errno, RS_RET_ERR, "error creating UDP socket - setsockopt"); ABORT_FINALIZE(RS_RET_ERR); } } #endif if (device) { #if defined(SO_BINDTODEVICE) if (setsockopt(*s, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0) #endif { LogError(errno, RS_RET_ERR, "create UDP socket bound to device failed"); ABORT_FINALIZE(RS_RET_ERR); } } if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { LogError(errno, RS_RET_ERR, "create UDP socket failed to set REUSEADDR"); ABORT_FINALIZE(RS_RET_ERR); } /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ /* AIXPORT : SO_BSDCOMPAT socket option is deprecated, and its usage * has been discontinued on most unixes, AIX does not support this option, * hence avoid the call. */ #if !defined(OS_BSD) && !defined(__hpux) && !defined(_AIX) if (should_use_so_bsdcompat()) { if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, (char *)&on, sizeof(on)) < 0) { LogError(errno, RS_RET_ERR, "create UDP socket failed to set BSDCOMPAT"); ABORT_FINALIZE(RS_RET_ERR); } } #endif if (bIsServer) { DBGPRINTF("net.c: trying to set server socket %d to non-blocking mode\n", *s); if ((sockflags = fcntl(*s, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* SETFL could fail too, so get it caught by the subsequent * error check. */ sockflags = fcntl(*s, F_SETFL, sockflags); } if (sockflags == -1) { LogError(errno, RS_RET_ERR, "net.c: socket %d fcntl(O_NONBLOCK)", *s); ABORT_FINALIZE(RS_RET_ERR); } } if (sndbuf != 0) { #if defined(SO_SNDBUFFORCE) if (setsockopt(*s, SOL_SOCKET, SO_SNDBUFFORCE, &sndbuf, sizeof(sndbuf)) < 0) #endif { /* if we fail, try to do it the regular way. Experiments show that at * least some platforms do not return an error here, but silently set * it to the max permitted value. So we do our error check a bit * differently by querying the size below. */ if (setsockopt(*s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0) { /* keep Coverity happy */ DBGPRINTF( "setsockopt in %s:%d failed - this is expected and " "handled at later stages\n", __FILE__, __LINE__); } } /* report socket buffer sizes */ optlen = sizeof(actsndbuf); if (getsockopt(*s, SOL_SOCKET, SO_SNDBUF, &actsndbuf, &optlen) == 0) { LogMsg(0, NO_ERRCODE, LOG_INFO, "socket %d, actual os socket sndbuf size is %d", *s, actsndbuf); if (sndbuf != 0 && actsndbuf / 2 != sndbuf) { LogError(errno, NO_ERRCODE, "could not set os socket sndbuf size %d for socket %d, " "value now is %d", sndbuf, *s, actsndbuf / 2); } } else { DBGPRINTF("could not obtain os socket rcvbuf size for socket %d: %s\n", *s, rs_strerror_r(errno, errStr, sizeof(errStr))); } } if (rcvbuf != 0) { #if defined(SO_RCVBUFFORCE) if (setsockopt(*s, SOL_SOCKET, SO_RCVBUFFORCE, &rcvbuf, sizeof(rcvbuf)) < 0) #endif { /* if we fail, try to do it the regular way. Experiments show that at * least some platforms do not return an error here, but silently set * it to the max permitted value. So we do our error check a bit * differently by querying the size below. */ if (setsockopt(*s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0) { /* keep Coverity happy */ DBGPRINTF( "setsockopt in %s:%d failed - this is expected and " "handled at later stages\n", __FILE__, __LINE__); } } optlen = sizeof(actrcvbuf); if (getsockopt(*s, SOL_SOCKET, SO_RCVBUF, &actrcvbuf, &optlen) == 0) { LogMsg(0, NO_ERRCODE, LOG_INFO, "socket %d, actual os socket rcvbuf size %d\n", *s, actrcvbuf); if (rcvbuf != 0 && actrcvbuf / 2 != rcvbuf) { LogError(errno, NO_ERRCODE, "cannot set os socket rcvbuf size %d for socket %d, value now is %d", rcvbuf, *s, actrcvbuf / 2); } } else { DBGPRINTF("could not obtain os socket rcvbuf size for socket %d: %s\n", *s, rs_strerror_r(errno, errStr, sizeof(errStr))); } } if (bIsServer) { /* rgerhards, 2007-06-22: if we run on a kernel that does not support * the IPV6_V6ONLY socket option, we need to use a work-around. On such * systems the IPv6 socket does also accept IPv4 sockets. So an IPv4 * socket can not listen on the same port as an IPv6 socket. The only * workaround is to ignore the "socket in use" error. This is what we * do if we have to. */ if ((bind(*s, r->ai_addr, r->ai_addrlen) < 0) #ifndef IPV6_V6ONLY && (errno != EADDRINUSE) #endif ) { if (errno == EADDRNOTAVAIL && ipfreebind != IPFREEBIND_DISABLED) { if (setsockopt(*s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on)) < 0) { LogError(errno, RS_RET_ERR, "setsockopt(IP_FREEBIND)"); } else if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { LogError(errno, RS_RET_ERR, "bind with IP_FREEBIND"); } else { if (ipfreebind >= IPFREEBIND_ENABLED_WITH_LOG) LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "bound address %s IP free", hostname); FINALIZE; } } ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (iRet != RS_RET_OK) { if (*s != -1) { close(*s); *s = -1; } } RETiRet; } /* creates the UDP listen sockets * hostname and/or pszPort may be NULL, but not both! * bIsServer indicates if a server socket should be created * 1 - server, 0 - client * Note: server sockets are created in non-blocking mode, client ones * are blocking. * param rcvbuf indicates desired rcvbuf size; 0 means OS default, * similar for sndbuf. */ static int *create_udp_socket(uchar *hostname, uchar *pszPort, const int bIsServer, const int rcvbuf, const int sndbuf, const int ipfreebind, char *device) { struct addrinfo hints, *res, *r; int error, maxs, *s, *socks; rsRetVal localRet; assert(!((pszPort == NULL) && (hostname == NULL))); /* one of them must be non-NULL */ memset(&hints, 0, sizeof(hints)); if (bIsServer) hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; else hints.ai_flags = AI_NUMERICSERV; hints.ai_family = glbl.GetDefPFFamily(runConf); hints.ai_socktype = SOCK_DGRAM; #if defined(_AIX) /* AIXPORT : SOCK_DGRAM has the protocol IPPROTO_UDP * getaddrinfo needs this hint on AIX */ hints.ai_protocol = IPPROTO_UDP; #endif error = getaddrinfo((char *)hostname, (char *)pszPort, &hints, &res); if (error) { LogError(0, NO_ERRCODE, "%s", gai_strerror(error)); LogError(0, NO_ERRCODE, "UDP message reception disabled due to error logged in last message.\n"); return NULL; } /* Count max number of sockets we may open */ for (maxs = 0, r = res; r != NULL; r = r->ai_next, maxs++) /* EMPTY */ ; socks = malloc((maxs + 1) * sizeof(int)); if (socks == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "couldn't allocate memory for UDP " "sockets, suspending UDP message reception"); freeaddrinfo(res); return NULL; } *socks = 0; /* num of sockets counter at start of array */ s = socks + 1; for (r = res; r != NULL; r = r->ai_next) { localRet = create_single_udp_socket(s, r, hostname, bIsServer, rcvbuf, sndbuf, ipfreebind, device); if (localRet == RS_RET_OK) { (*socks)++; s++; } } if (res != NULL) freeaddrinfo(res); if (Debug && *socks != maxs) dbgprintf( "We could initialize %d UDP listen sockets out of %d we received " "- this may or may not be an error indication.\n", *socks, maxs); if (*socks == 0) { LogError(0, NO_ERRCODE, "No UDP socket could successfully be initialized, " "some functionality may be disabled.\n"); /* we do NOT need to close any sockets, because there were none... */ free(socks); return (NULL); } return (socks); } /* check if two provided socket addresses point to the same host. Note that the * length of the sockets must be provided as third parameter. This is necessary to * compare non IPv4/v6 hosts, in which case we do a simple memory compare of the * address structure (in that case, the same host may not reliably be detected). * Note that we need to do the comparison not on the full structure, because it contains things * like the port, which we do not need to look at when thinking about hostnames. So we look * at the relevant fields, what means a somewhat more complicated processing. * Also note that we use a non-standard calling interface, as this is much more natural and * it looks extremely unlikely that we get an exception of any kind here. What we * return is mimiced after memcmp(), and as such useful for building binary trees * (the order relation may be a bit arbritrary, but at least it is consistent). * rgerhards, 2009-09-03 */ static int CmpHost(struct sockaddr_storage *s1, struct sockaddr_storage *s2, size_t socklen) { int ret; if (((struct sockaddr *)s1)->sa_family != ((struct sockaddr *)s2)->sa_family) { ret = memcmp(s1, s2, socklen); goto finalize_it; } if (((struct sockaddr *)s1)->sa_family == AF_INET) { if (((struct sockaddr_in *)s1)->sin_addr.s_addr == ((struct sockaddr_in *)s2)->sin_addr.s_addr) { ret = 0; } else if (((struct sockaddr_in *)s1)->sin_addr.s_addr < ((struct sockaddr_in *)s2)->sin_addr.s_addr) { ret = -1; } else { ret = 1; } } else if (((struct sockaddr *)s1)->sa_family == AF_INET6) { /* IPv6 addresses are always 16 octets long */ ret = memcmp(((struct sockaddr_in6 *)s1)->sin6_addr.s6_addr, ((struct sockaddr_in6 *)s2)->sin6_addr.s6_addr, 16); } else { ret = memcmp(s1, s2, socklen); } finalize_it: return ret; } /* check if restrictions (ALCs) exists. The goal of this function is to disable the * somewhat time-consuming ACL checks if no restrictions are defined (the usual case). * This also permits to gain some speedup by using firewall-based ACLs instead of * rsyslog ACLs (the recommended method. * rgerhards, 2009-11-16 */ static rsRetVal HasRestrictions(uchar *pszType, int *bHasRestrictions) { struct AllowedSenders *pAllowRoot = NULL; DEFiRet; CHKiRet(setAllowRoot(&pAllowRoot, pszType)); *bHasRestrictions = (pAllowRoot == NULL) ? 0 : 1; finalize_it: if (iRet != RS_RET_OK) { *bHasRestrictions = 1; /* in this case it is better to check individually */ DBGPRINTF("Error %d trying to obtain ACL restriction state of '%s'\n", iRet, pszType); } RETiRet; } /* return the IP address (IPv4/6) for the provided interface. Returns * RS_RET_NOT_FOUND if interface can not be found in interface list. * The family must be correct (AF_INET vs. AF_INET6, AF_UNSPEC means * either of *these two*). * The function re-queries the interface list (at least in theory). * However, it caches entries in order to avoid too-frequent requery. * rgerhards, 2012-03-06 */ static rsRetVal getIFIPAddr(uchar *szif, int family, uchar *pszbuf, int lenBuf) { #ifdef _AIX struct ifaddrs_rsys *ifaddrs = NULL; struct ifaddrs_rsys *ifa; #else struct ifaddrs *ifaddrs = NULL; struct ifaddrs *ifa; #endif union { struct sockaddr *sa; struct sockaddr_in *ipv4; struct sockaddr_in6 *ipv6; } savecast; void *pAddr; DEFiRet; if (getifaddrs(&ifaddrs) != 0) { ABORT_FINALIZE(RS_RET_ERR); } for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { if (strcmp(ifa->ifa_name, (char *)szif)) continue; savecast.sa = ifa->ifa_addr; if ((family == AF_INET6 || family == AF_UNSPEC) && ifa->ifa_addr->sa_family == AF_INET6) { pAddr = &(savecast.ipv6->sin6_addr); inet_ntop(AF_INET6, pAddr, (char *)pszbuf, lenBuf); break; } else if (/* (family == AF_INET || family == AF_UNSPEC) &&*/ ifa->ifa_addr->sa_family == AF_INET) { pAddr = &(savecast.ipv4->sin_addr); inet_ntop(AF_INET, pAddr, (char *)pszbuf, lenBuf); break; } } if (ifaddrs != NULL) freeifaddrs(ifaddrs); if (ifa == NULL) iRet = RS_RET_NOT_FOUND; finalize_it: RETiRet; } /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(net) CODESTARTobjQueryInterface(net); if (pIf->ifVersion != netCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->cvthname = cvthname; /* things to go away after proper modularization */ pIf->addAllowedSenderLine = addAllowedSenderLine; pIf->addAllowedSenderEntry = addAllowedSenderEntry; pIf->DestructAllowedSenders = DestructAllowedSenders; pIf->PrintAllowedSenders = PrintAllowedSenders; pIf->clearAllowedSenders = clearAllowedSenders; pIf->debugListenInfo = debugListenInfo; pIf->create_udp_socket = create_udp_socket; pIf->closeUDPListenSockets = closeUDPListenSockets; pIf->isAllowedSender = isAllowedSender; pIf->isAllowedSender2 = isAllowedSender2; pIf->should_use_so_bsdcompat = should_use_so_bsdcompat; pIf->getLocalHostname = getLocalHostname; pIf->AddPermittedPeer = AddPermittedPeer; pIf->DestructPermittedPeers = DestructPermittedPeers; pIf->PermittedPeerWildcardMatch = PermittedPeerWildcardMatch; pIf->CmpHost = CmpHost; pIf->HasRestrictions = HasRestrictions; pIf->isAllowedSenderList = isAllowedSenderList; pIf->GetIFIPAddr = getIFIPAddr; pIf->netns_save = netns_save; pIf->netns_restore = netns_restore; pIf->netns_switch = netns_switch; pIf->netns_socket = netns_socket; finalize_it: ENDobjQueryInterface(net) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(net, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(net); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); ENDObjClassExit(net) /* Initialize the net class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(net, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); /* set our own handlers */ ENDObjClassInit(net) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; netClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(netClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/errmsg.h0000644000000000000000000000013215241075234015675 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.337723993 rsyslog-8.2608.0/runtime/errmsg.h0000664000175000017500000001160515241075234015344 0ustar00rgerrger/* The errmsg object. It is used to emit error message inside rsyslog. * * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_ERRMSG_H #define INCLUDED_ERRMSG_H #include "obj-types.h" #define NO_ERRCODE -1 /* prototypes */ /** * @brief Close and reset internal resources of the errmsg subsystem. * * Closes the oversize-message log fd if open. Intended for orderly shutdown. * @note This function is not thread-safe as it accesses a global flag without locks. */ void errmsgExit(void); /** * @brief Reopen oversize-message resources on configuration reload (HUP). * * Intended to be called from rsyslog's SIGHUP handler. This closes the * oversize-message log file descriptor so the next write will reopen it * using the current configuration. This follows the traditional syslogd * pattern of reloading or reopening resources on HUP. * * Thread-safe. */ void errmsgDoHUP(void); /** * @brief Reset the "had error messages" flag. * * Must be called before processing config files to start with a clean state. * @note This function is not thread-safe as it accesses a global flag without locks. */ void resetErrMsgsFlag(void); /** * @brief Query whether a LOG_ERR message has been logged since the last reset. * * @return nonzero if a LOG_ERR was emitted since resetErrMsgsFlag(), else 0. * * @note This function is not thread-safe as it accesses a global flag without locks. */ int hadErrMsgs(void); /** * @brief Log an error message with errno and error code context. * * Formats and writes an error message to the rsyslog internal log. * Use this for reporting fatal or unexpected conditions. * * @param iErrno The system errno value (0 if not applicable). * @param iErrCode Internal rsyslog error code. * @param fmt printf-style format string. * @param ... Arguments matching the format string. * * @note Pass the errno value obtained at the point of failure. * Do not pass 0 and later resolve errno via strerror() or * similar functions — this leads to incorrect messages. * AI AGENTS: Always use LogError(errno, ...) when reporting * system errors. Do not use strerror() or rs_strerror_r(). */ void __attribute__((format(printf, 3, 4))) LogError(const int iErrno, const int iErrCode, const char *fmt, ...); /** * @brief Log a message with severity, errno, and error code context. * * More general form of LogError() that permits explicit severity. * * @param iErrno The system errno value (0 if not applicable). * @param iErrCode Internal rsyslog error code. * @param severity Syslog severity level (LOG_ERR, LOG_WARNING, etc.). * @param fmt printf-style format string. * @param ... Arguments matching the format string. * * @note Always pass the errno value captured immediately after the * failing call. Do not pass 0 and later call strerror() or * equivalent — this is a common bug. * AI AGENTS: Always use LogMsg(errno, ...) when reporting * system errors. Do not use strerror() or rs_strerror_r(). */ void __attribute__((format(printf, 4, 5))) LogMsg( const int iErrno, const int iErrCode, const int severity, const char *fmt, ...); /** * @brief Append a JSON record about an oversize message to the oversize-message log. * * Behavior: * - No-op if the oversize message error file is not configured. * - Lazily opens the file on first use and reuses the file descriptor. * - Access is serialized via oversizeMsgLogMut. * - Writes one full-message JSON line per entry, including fields such as * "rawmsg", "msg", "inputname", "fromhost-ip", "timereported", and * "timegenerated". * - Also writes "input" as a compatibility alias for "inputname". * - On open/write errors, emits LogError(...) but returns no error; no further recovery is attempted. * The reason is that there is nothing useful that could be done in that case. * * @param pMsg Pointer to the message object (must not be NULL). * @retval RS_RET_OK on success, or when no oversize log is configured. * @retval RS_RET_OUT_OF_MEMORY on memory allocation failure. * * @note Output is newline-terminated JSON (not NUL-terminated). */ rsRetVal ATTR_NONNULL() writeOversizeMessageLog(const smsg_t *const pMsg); #endif /* #ifndef INCLUDED_ERRMSG_H */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_ossl.c0000644000000000000000000000013215241075234016215 xustar0030 mtime=1787067036.604578276 30 atime=1787067036.751581028 30 ctime=1787067794.563728204 rsyslog-8.2608.0/runtime/nsd_ossl.c0000664000175000017500000020331315241075234015663 0ustar00rgerrger/* nsd_ossl.c * * An implementation of the nsd interface for OpenSSL. * * Copyright 2018-2025 Adiscon GmbH. * Author: Andre Lorbach * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "cfsysline.h" #include "obj.h" #include "stringbuf.h" #include "errmsg.h" #include "net.h" #include "netstrm.h" #include "netstrms.h" #include "datetime.h" #include "net_ossl.h" // Include OpenSSL Helpers #include "nsd_ptcp.h" #include "nsd_ossl.h" #include "srUtils.h" #include "unicode-helper.h" #include "rsconf.h" MODULE_TYPE_LIB MODULE_TYPE_KEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(datetime) DEFobjCurrIf(nsd_ptcp) DEFobjCurrIf(net_ossl) /* Some prototypes for helper functions used inside openssl driver */ static rsRetVal applyGnutlsPriorityString(nsd_ossl_t *const pNsd); /* retry an interrupted OSSL operation */ static rsRetVal doRetry(nsd_ossl_t *pNsd) { DEFiRet; nsd_ossl_t *pNsdOSSL = (nsd_ossl_t *)pNsd; dbgprintf("doRetry: requested retry of %d operation - executing\n", pNsd->rtryCall); /* We follow a common scheme here: first, we do the systen call and * then we check the result. So far, the result is checked after the * switch, because the result check is the same for all calls. Note that * this may change once we deal with the read and write calls (but * probably this becomes an issue only when we begin to work on TLS * for relp). -- rgerhards, 2008-04-30 */ switch (pNsd->rtryCall) { case osslRtry_handshake: dbgprintf("doRetry: start osslHandshakeCheck, nsd: %p\n", pNsd); /* Reset retry flag before calling handshake check. * If it needs more retries, it will set it again. */ pNsd->rtryCall = osslRtry_None; /* Do the handshake again*/ CHKiRet(osslHandshakeCheck(pNsdOSSL)); break; case osslRtry_recv: case osslRtry_None: default: assert(0); /* this shall not happen! */ dbgprintf("doRetry: ERROR, pNsd->rtryCall invalid in nsdsel_ossl.c:%d\n", __LINE__); break; } finalize_it: if (iRet != RS_RET_OK && iRet != RS_RET_CLOSED && iRet != RS_RET_RETRY) pNsd->bAbortConn = 1; /* request abort */ RETiRet; } /*--------------------------------------OpenSSL helpers ------------------------------------------*/ void nsd_ossl_lastOpenSSLErrorMsg( nsd_ossl_t const *pThis, const int ret, SSL *ssl, int severity, const char *pszCallSource, const char *pszOsslApi) { uchar *fromHost = NULL; int errno_store = errno; if (pThis != NULL) { nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHost); } // Call helper in net_ossl net_ossl.osslLastOpenSSLErrorMsg(fromHost, ret, ssl, severity, pszCallSource, pszOsslApi); free(fromHost); errno = errno_store; } #ifndef ENABLE_WOLFSSL #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) long BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) * argp, size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl, int ret, size_t __attribute__((unused)) * processed) #else long BIO_debug_callback( BIO *bio, int cmd, const char __attribute__((unused)) * argp, int argi, long __attribute__((unused)) argl, long ret) #endif { long ret2 = ret; // Helper value to avoid printf compile errors long<>int long r = 1; if (BIO_CB_RETURN & cmd) r = ret; dbgprintf("openssl debugmsg: BIO[%p]: ", (void *)bio); switch (cmd) { case BIO_CB_FREE: dbgprintf("Free - %s\n", RSYSLOG_BIO_method_name(bio)); break; /* Disabled due API changes for OpenSSL 1.1.0+ */ #if OPENSSL_VERSION_NUMBER < 0x10100000L case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) dbgprintf("read(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio)); else dbgprintf("read(%d,%lu) - %s\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) dbgprintf("write(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio)); else dbgprintf("write(%d,%lu) - %s\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; #else case BIO_CB_READ: dbgprintf("read %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_WRITE: dbgprintf("write %s\n", RSYSLOG_BIO_method_name(bio)); break; #endif case BIO_CB_PUTS: dbgprintf("puts() - %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_GETS: dbgprintf("gets(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_CTRL: dbgprintf("ctrl(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_RETURN | BIO_CB_READ: dbgprintf("read return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_WRITE: dbgprintf("write return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_GETS: dbgprintf("gets return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_PUTS: dbgprintf("puts return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_CTRL: dbgprintf("ctrl return %ld\n", ret2); break; default: dbgprintf("bio callback - unknown type (%d)\n", cmd); break; } return (r); } #endif /* !ENABLE_WOLFSSL */ /* * SNI should not be used if the hostname is a bare IP address */ static rsRetVal SetServerNameIfPresent(nsd_ossl_t *pThis, uchar *host) { struct sockaddr_in sa; struct sockaddr_in6 sa6; int inet_pton_ret; DEFiRet; /* Always use the configured remote SNI if present */ if (pThis->remoteSNI != NULL) { if (SSL_set_tlsext_host_name(pThis->pNetOssl->ssl, (char *)pThis->remoteSNI) != 1) { nsd_ossl_lastOpenSSLErrorMsg(pThis, 0, pThis->pNetOssl->ssl, LOG_ERR, "SetServerNameIfPresent", "SSL_set_tlsext_host_name"); ABORT_FINALIZE(RS_RET_SYS_ERR); } FINALIZE; } /* Otherwise, figure out if host is an IP address */ inet_pton_ret = inet_pton(AF_INET, CHAR_CONVERT(host), &(sa.sin_addr)); if (inet_pton_ret == 0) { // host wasn't a bare IPv4 address: try IPv6 inet_pton_ret = inet_pton(AF_INET6, CHAR_CONVERT(host), &(sa6.sin6_addr)); } /* Then make a decision */ switch (inet_pton_ret) { case 1: // host is a valid IP address: don't use SNI FINALIZE; case 0: // host isn't a valid IP address: assume it's a domain name, use SNI if (SSL_set_tlsext_host_name(pThis->pNetOssl->ssl, (char *)host) != 1) { nsd_ossl_lastOpenSSLErrorMsg(pThis, 0, pThis->pNetOssl->ssl, LOG_ERR, "SetServerNameIfPresent", "SSL_set_tlsext_host_name"); ABORT_FINALIZE(RS_RET_SYS_ERR); } FINALIZE; default: // unexpected error nsd_ossl_lastOpenSSLErrorMsg(pThis, 0, pThis->pNetOssl->ssl, LOG_ERR, "SetServerNameIfPresent", "inet_pton"); ABORT_FINALIZE(RS_RET_INVALID_HNAME); } finalize_it: RETiRet; } /* try to receive a record from the remote peer. This works with * our own abstraction and handles local buffering and EAGAIN. * See details on local buffering in Rcv(9 header-comment. * This function MUST only be called when the local buffer is * empty. Calling it otherwise will cause losss of current buffer * data. * rgerhards, 2008-06-24 */ rsRetVal osslRecordRecv(nsd_ossl_t *pThis, unsigned *const nextIODirection) { ssize_t lenRcvd; DEFiRet; int err; ISOBJ_TYPE_assert(pThis, nsd_ossl); DBGPRINTF("osslRecordRecv: start\n"); lenRcvd = SSL_read(pThis->pNetOssl->ssl, pThis->pszRcvBuf, NSD_OSSL_MAX_RCVBUF); if (lenRcvd > 0) { DBGPRINTF("osslRecordRecv: SSL_read received %zd bytes\n", lenRcvd); pThis->lenRcvBuf = lenRcvd; pThis->ptrRcvBuf = 0; /* Check for additional data in SSL buffer */ int iBytesLeft = SSL_pending(pThis->pNetOssl->ssl); if (iBytesLeft > 0) { DBGPRINTF("osslRecordRecv: %d Bytes pending after SSL_Read, expand buffer.\n", iBytesLeft); /* realloc buffer size and preserve char content */ char *const newbuf = realloc(pThis->pszRcvBuf, NSD_OSSL_MAX_RCVBUF + iBytesLeft); CHKmalloc(newbuf); pThis->pszRcvBuf = newbuf; /* 2nd read will read missing bytes from the current SSL Packet */ lenRcvd = SSL_read(pThis->pNetOssl->ssl, pThis->pszRcvBuf + NSD_OSSL_MAX_RCVBUF, iBytesLeft); if (lenRcvd > 0) { DBGPRINTF("osslRecordRecv: 2nd SSL_read received %zd bytes\n", (NSD_OSSL_MAX_RCVBUF + lenRcvd)); pThis->lenRcvBuf = NSD_OSSL_MAX_RCVBUF + lenRcvd; } else { goto sslerr; } } } else { sslerr: err = SSL_get_error(pThis->pNetOssl->ssl, lenRcvd); if (err == SSL_ERROR_ZERO_RETURN) { DBGPRINTF("osslRecordRecv: SSL_ERROR_ZERO_RETURN received, connection may closed already\n"); ABORT_FINALIZE(RS_RET_RETRY); } else if (err == SSL_ERROR_SYSCALL) { #ifdef ENABLE_WOLFSSL if (SSL_want_read(pThis->pNetOssl->ssl) || SSL_want_write(pThis->pNetOssl->ssl)) { pThis->rtryCall = osslRtry_recv; pThis->rtryOsslErr = SSL_want_write(pThis->pNetOssl->ssl) ? SSL_ERROR_WANT_WRITE : SSL_ERROR_WANT_READ; ABORT_FINALIZE(RS_RET_RETRY); } #endif /* Output error and abort */ nsd_ossl_lastOpenSSLErrorMsg(pThis, lenRcvd, pThis->pNetOssl->ssl, LOG_INFO, "osslRecordRecv", "SSL_read 1"); iRet = RS_RET_TLS_ERR_SYSCALL; /* Check for underlaying socket errors **/ if (errno == ECONNRESET) { DBGPRINTF("osslRecordRecv: SSL_ERROR_SYSCALL Errno %d, connection reset by peer\n", errno); /* Connection was dropped from remote site */ iRet = RS_RET_CLOSED; } else { DBGPRINTF("osslRecordRecv: SSL_ERROR_SYSCALL Errno %d\n", errno); } ABORT_FINALIZE(iRet); } else if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { DBGPRINTF("osslRecordRecv: SSL_get_error #1 = %d, lenRcvd=%zd\n", err, lenRcvd); /* Output OpenSSL error*/ nsd_ossl_lastOpenSSLErrorMsg(pThis, lenRcvd, pThis->pNetOssl->ssl, LOG_ERR, "osslRecordRecv", "SSL_read 2"); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } else { DBGPRINTF("osslRecordRecv: SSL_get_error #2 = %d, lenRcvd=%zd\n", err, lenRcvd); pThis->rtryCall = osslRtry_recv; pThis->rtryOsslErr = err; /* Store SSL ErrorCode into*/ ABORT_FINALIZE(RS_RET_RETRY); } } finalize_it: if (pThis->rtryCall != osslRtry_None && pThis->rtryOsslErr == SSL_ERROR_WANT_WRITE) { *nextIODirection = NSDSEL_WR; } else { *nextIODirection = NSDSEL_RD; } dbgprintf("osslRecordRecv return. nsd %p, iRet %d, lenRcvd %zd, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, lenRcvd, pThis->lenRcvBuf, pThis->ptrRcvBuf); RETiRet; } static rsRetVal retrySendSideRecordRecv(nsd_ossl_t *const pThis) { DEFiRet; unsigned nextIODirection; rsRetVal recvRet; if (pThis->pszRcvBuf == NULL) { CHKmalloc(pThis->pszRcvBuf = malloc(NSD_OSSL_MAX_RCVBUF)); pThis->lenRcvBuf = -1; } if (pThis->lenRcvBuf == -1) { recvRet = osslRecordRecv(pThis, &nextIODirection); if (recvRet != RS_RET_OK && recvRet != RS_RET_RETRY) ABORT_FINALIZE(recvRet); if (recvRet == RS_RET_RETRY) ABORT_FINALIZE(RS_RET_RETRY); pThis->rtryCall = osslRtry_None; pThis->rtryOsslErr = SSL_ERROR_NONE; if (pThis->lenRcvBuf == 0) ABORT_FINALIZE(RS_RET_CLOSED); } finalize_it: RETiRet; } static rsRetVal osslInitSession(nsd_ossl_t *pThis, osslSslState_t osslType) /* , nsd_ossl_t *pServer) */ { DEFiRet; BIO *conn; char pristringBuf[4096]; nsd_ptcp_t *pPtcp = (nsd_ptcp_t *)pThis->pTcp; if (!(pThis->pNetOssl->ssl = SSL_new(pThis->pNetOssl->ctx))) { pThis->pNetOssl->ssl = NULL; nsd_ossl_lastOpenSSLErrorMsg(pThis, 0, pThis->pNetOssl->ssl, LOG_ERR, "osslInitSession", "SSL_new"); ABORT_FINALIZE(RS_RET_TLS_BASEINIT_FAIL); } // Set SSL_MODE_AUTO_RETRY to SSL obj SSL_set_mode(pThis->pNetOssl->ssl, SSL_MODE_AUTO_RETRY); if (pThis->pNetOssl->authMode != OSSL_AUTH_CERTANON) { dbgprintf("osslInitSession: enable certificate checking (Mode=%d, VerifyDepth=%d)\n", pThis->pNetOssl->authMode, pThis->DrvrVerifyDepth); /* Enable certificate valid checking */ net_ossl.osslSetSslVerifyCallback(pThis->pNetOssl->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); if (pThis->DrvrVerifyDepth != 0) { SSL_set_verify_depth(pThis->pNetOssl->ssl, pThis->DrvrVerifyDepth); } } else if (pThis->gnutlsPriorityString == NULL) { /* Allow ANON Ciphers only in ANON Mode and if no custom priority string is defined */ #ifdef ENABLE_WOLFSSL memcpy(pristringBuf, "ADH-AES256-GCM-SHA384:ADH-AES128-SHA", sizeof("ADH-AES256-GCM-SHA384:ADH-AES128-SHA")); #elif OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) /* NOTE: do never use: +eNULL, it DISABLES encryption! */ memcpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0", sizeof("ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL@SECLEVEL=0")); #else memcpy(pristringBuf, "ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL", sizeof("ALL:+COMPLEMENTOFDEFAULT:+ADH:+ECDH:+aNULL")); #endif dbgprintf("osslInitSession: setting anon ciphers: %s\n", pristringBuf); if (SSL_set_cipher_list(pThis->pNetOssl->ssl, pristringBuf) == 0) { #ifdef ENABLE_WOLFSSL LogMsg(0, RS_RET_SYS_ERR, LOG_ERR, "osslInitSession: Error setting anon ciphers '%s' (wolfSSL requires --enable-anon)\n", pristringBuf); #else dbgprintf("osslInitSession: Error setting ciphers '%s'\n", pristringBuf); #endif ABORT_FINALIZE(RS_RET_SYS_ERR); } } /* Create BIO from ptcp socket! * Use BIO_NOCLOSE to prevent OpenSSL from closing the socket when * SSL_free is called. The socket is owned and will be closed by ptcp. */ conn = BIO_new_socket(pPtcp->sock, BIO_NOCLOSE); dbgprintf("osslInitSession: Init conn BIO[%p] done\n", (void *)conn); /* Set debug Callback for conn BIO as well! */ net_ossl.osslSetBioCallback(conn); /* TODO: still needed? Set to NON blocking ! */ BIO_set_nbio(conn, 1); SSL_set_bio(pThis->pNetOssl->ssl, conn, conn); if (osslType == osslServer) { /* Server Socket */ SSL_set_accept_state(pThis->pNetOssl->ssl); /* sets ssl to work in server mode. */ pThis->pNetOssl->sslState = osslServer; /*set Server state */ } else { /* Client Socket */ SSL_set_connect_state(pThis->pNetOssl->ssl); /*sets ssl to work in client mode.*/ pThis->pNetOssl->sslState = osslClient; /*set Client state */ } pThis->bHaveSess = 1; /* we are done */ FINALIZE; finalize_it: RETiRet; } /* check if it is OK to talk to the remote peer * rgerhards, 2008-05-21 */ rsRetVal osslChkPeerAuth(nsd_ossl_t *pThis) { DEFiRet; X509 *certpeer = NULL; ISOBJ_TYPE_assert(pThis, nsd_ossl); uchar *fromHostIP = NULL; nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHostIP); /* call the actual function based on current auth mode */ switch (pThis->pNetOssl->authMode) { case OSSL_AUTH_CERTNAME: /* if we check the name, we must ensure the cert is valid */ certpeer = net_ossl.osslGetpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP); dbgprintf("osslChkPeerAuth: Check peer certname[%p]=%s\n", (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL")); CHKiRet(net_ossl.osslChkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP)); CHKiRet(net_ossl.osslChkpeername(pThis->pNetOssl, certpeer, fromHostIP)); break; case OSSL_AUTH_CERTFINGERPRINT: certpeer = net_ossl.osslGetpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP); dbgprintf("osslChkPeerAuth: Check peer fingerprint[%p]=%s\n", (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL")); CHKiRet(net_ossl.osslChkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP)); CHKiRet(net_ossl.osslPeerfingerprint(pThis->pNetOssl, certpeer, fromHostIP)); break; case OSSL_AUTH_CERTVALID: certpeer = net_ossl.osslGetpeercert(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP); dbgprintf("osslChkPeerAuth: Check peer valid[%p]=%s\n", (void *)pThis->pNetOssl->ssl, (certpeer != NULL ? "VALID" : "NULL")); CHKiRet(net_ossl.osslChkpeercertvalidity(pThis->pNetOssl, pThis->pNetOssl->ssl, fromHostIP)); break; case OSSL_AUTH_CERTANON: default: break; } finalize_it: if (certpeer != NULL) { X509_free(certpeer); } if (fromHostIP != NULL) { free(fromHostIP); } RETiRet; } /* end a OpenSSL session * The function checks if we have a session and ends it only if so. So it can * always be called, even if there currently is no session. */ static rsRetVal osslEndSess(nsd_ossl_t *pThis) { DEFiRet; uchar *fromHostIP = NULL; int ret; int err; /* try closing SSL Connection */ if (pThis->bHaveSess) { DBGPRINTF("osslEndSess: closing SSL Session ...\n"); ret = SSL_shutdown(pThis->pNetOssl->ssl); nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHostIP); if (ret <= 0) { err = SSL_get_error(pThis->pNetOssl->ssl, ret); DBGPRINTF("osslEndSess: shutdown failed with err = %d\n", err); /* ignore those SSL Errors on shutdown */ if (err != SSL_ERROR_SYSCALL && err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { /* Output Warning only */ nsd_ossl_lastOpenSSLErrorMsg(pThis, ret, pThis->pNetOssl->ssl, LOG_WARNING, "osslEndSess", "SSL_shutdown"); } /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more: * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html */ char rcvBuf[NSD_OSSL_MAX_RCVBUF]; int iBytesRet = SSL_read(pThis->pNetOssl->ssl, rcvBuf, NSD_OSSL_MAX_RCVBUF); DBGPRINTF("osslEndSess: Forcing ssl shutdown SSL_read (%d) to do a bidirectional shutdown\n", iBytesRet); if (ret < 0) { /* Unsuccessful shutdown, log as INFO */ LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: " "TLS session terminated successfully to remote syslog server '%s' with SSL Error '%d':" " End Session", fromHostIP, ret); } dbgprintf( "osslEndSess: TLS session terminated successfully to remote syslog server '%s'" " End Session", fromHostIP); } else { dbgprintf( "osslEndSess: TLS session terminated successfully with remote syslog server '%s':" " End Session", fromHostIP); } /* Session closed */ pThis->bHaveSess = 0; } if (fromHostIP != NULL) { free(fromHostIP); } RETiRet; } static void osslAbortSess(nsd_ossl_t *pThis) { if (pThis->pNetOssl->ssl != NULL) { SSL_free(pThis->pNetOssl->ssl); pThis->pNetOssl->ssl = NULL; } pThis->bHaveSess = 0; pThis->bAbortConn = 1; pThis->iMode = 0; pThis->rtryCall = osslRtry_None; } /* ---------------------------- end OpenSSL specifics ---------------------------- */ /* Standard-Constructor */ BEGINobjConstruct(nsd_ossl) /* be sure to specify the object type also in END macro! */ DBGPRINTF("nsd_ossl_construct: [%p]\n", pThis); /* construct nsd_ptcp helper */ CHKiRet(nsd_ptcp.Construct(&pThis->pTcp)); /* construct net_ossl helper */ CHKiRet(net_ossl.Construct(&pThis->pNetOssl)); finalize_it: ENDobjConstruct(nsd_ossl) /* destructor for the nsd_ossl object */ BEGINobjDestruct(nsd_ossl) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsd_ossl); DBGPRINTF("nsd_ossl_destruct: [%p] Mode %d\n", pThis, pThis->iMode); if (pThis->iMode == 1) { osslEndSess(pThis); } /* TODO MOVE Free SSL obj also if we do not have a session - or are NOT in TLS mode! */ if (pThis->pNetOssl->ssl != NULL) { DBGPRINTF("nsd_ossl_destruct: [%p] FREE pThis->pNetOssl->ssl \n", pThis); /* If pTcp is NULL, we configure the BIO to close it on SSL_free This is a purely defensive measure and is this case is not actually expected */ assert(pThis->pTcp != NULL); if (pThis->pTcp == NULL) { BIO *bio = SSL_get_rbio(pThis->pNetOssl->ssl); if (bio != NULL) { BIO_set_close(bio, BIO_CLOSE); } } SSL_free(pThis->pNetOssl->ssl); pThis->pNetOssl->ssl = NULL; } /**/ if (pThis->pTcp != NULL) { nsd_ptcp.Destruct(&pThis->pTcp); } if (pThis->pNetOssl != NULL) { net_ossl.Destruct(&pThis->pNetOssl); } free(pThis->pszConnectHost); free(pThis->pszRcvBuf); free(pThis->remoteSNI); ENDobjDestruct(nsd_ossl) /* Set the driver mode. For us, this has the following meaning: * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS) * 1 - work in TLS mode * rgerhards, 2008-04-28 */ static rsRetVal SetMode(nsd_t *pNsd, const int mode) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (mode != 0 && mode != 1) { LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by" " ossl netstream driver", mode); } pThis->iMode = mode; RETiRet; } /* Set the authentication mode. For us, the following is supported: * anon - no certificate checks whatsoever (discouraged, but supported) * x509/certvalid - (just) check certificate validity * x509/fingerprint - certificate fingerprint * x509/name - cerfificate name check * mode == NULL is valid and defaults to x509/name * rgerhards, 2008-05-16 */ static rsRetVal SetAuthMode(nsd_t *const pNsd, uchar *const mode) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (mode == NULL || !strcasecmp((char *)mode, "x509/name")) { pThis->pNetOssl->authMode = OSSL_AUTH_CERTNAME; } else if (!strcasecmp((char *)mode, "x509/fingerprint")) { pThis->pNetOssl->authMode = OSSL_AUTH_CERTFINGERPRINT; } else if (!strcasecmp((char *)mode, "x509/certvalid")) { pThis->pNetOssl->authMode = OSSL_AUTH_CERTVALID; } else if (!strcasecmp((char *)mode, "anon")) { pThis->pNetOssl->authMode = OSSL_AUTH_CERTANON; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by " "ossl netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetAuthMode: Set Mode %s/%d\n", mode, pThis->pNetOssl->authMode); finalize_it: RETiRet; } /* Set the PermitExpiredCerts mode. For us, the following is supported: * on - fail if certificate is expired * off - ignore expired certificates * warn - warn if certificate is expired * alorbach, 2018-12-20 */ static rsRetVal SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); /* default is set to off! */ if (mode == NULL || !strcasecmp((char *)mode, "off")) { pThis->permitExpiredCerts = OSSL_EXPIRED_DENY; } else if (!strcasecmp((char *)mode, "warn")) { pThis->permitExpiredCerts = OSSL_EXPIRED_WARN; } else if (!strcasecmp((char *)mode, "on")) { pThis->permitExpiredCerts = OSSL_EXPIRED_PERMIT; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by " "ossl netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetPermitExpiredCerts: Set Mode %s/%d\n", mode, pThis->permitExpiredCerts); /* TODO: clear stored IDs! */ finalize_it: RETiRet; } /* Set permitted peers. It is depending on the auth mode if this are * fingerprints or names. -- rgerhards, 2008-05-19 */ static rsRetVal SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (pPermPeers == NULL) FINALIZE; if (pThis->pNetOssl->authMode != OSSL_AUTH_CERTFINGERPRINT && pThis->pNetOssl->authMode != OSSL_AUTH_CERTNAME) { LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by " "ossl netstream driver in the configured authentication mode - ignored"); ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); } pThis->pNetOssl->pPermPeers = pPermPeers; finalize_it: RETiRet; } /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_ossl) who utilize ourselfs * for some of their functionality. -- rgerhards, 2008-04-18 */ static rsRetVal SetSock(nsd_t *pNsd, int sock) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); assert(sock >= 0); DBGPRINTF("SetSock for [%p]: Setting sock %d\n", pNsd, sock); nsd_ptcp.SetSock(pThis->pTcp, sock); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); assert(keepAliveIntvl >= 0); dbgprintf("SetKeepAliveIntvl: keepAliveIntvl=%d\n", keepAliveIntvl); nsd_ptcp.SetKeepAliveIntvl(pThis->pTcp, keepAliveIntvl); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); assert(keepAliveProbes >= 0); dbgprintf("SetKeepAliveProbes: keepAliveProbes=%d\n", keepAliveProbes); nsd_ptcp.SetKeepAliveProbes(pThis->pTcp, keepAliveProbes); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); assert(keepAliveTime >= 0); dbgprintf("SetKeepAliveTime: keepAliveTime=%d\n", keepAliveTime); nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime); RETiRet; } /* TCP user timeout option */ static rsRetVal SetTcpUserTimeout(nsd_t *pNsd, int tcpUserTimeout) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); assert(tcpUserTimeout >= 0); dbgprintf("SetTcpUserTimeout: tcpUserTimeout=%d\n", tcpUserTimeout); nsd_ptcp.SetTcpUserTimeout(pThis->pTcp, tcpUserTimeout); RETiRet; } /* abort a connection. This is meant to be called immediately * before the Destruct call. -- rgerhards, 2008-03-24 */ static rsRetVal Abort(nsd_t *pNsd) { nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (pThis->iMode == 0) { nsd_ptcp.Abort(pThis->pTcp); } RETiRet; } /* Callback after netstrm obj init in nsd_ptcp - permits us to add some data */ static rsRetVal LstnInitDrvr(netstrm_t *const pThis) { DEFiRet; nsd_ossl_t *pNsdOssl = (nsd_ossl_t *)pThis->pDrvrData; /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for all newer versions! */ #if OPENSSL_VERSION_NUMBER < 0x10100000L CHKiRet(net_ossl.osslCtxInit(pNsdOssl->pNetOssl, SSLv23_method())); #else CHKiRet(net_ossl.osslCtxInit(pNsdOssl->pNetOssl, TLS_method())); #endif // Apply PriorityString after Ctx Creation applyGnutlsPriorityString(pNsdOssl); finalize_it: RETiRet; } /* initialize the tcp socket for a listner * Here, we use the ptcp driver - because there is nothing special * at this point with OpenSSL. Things become special once we accept * a session, but not during listener setup. */ static rsRetVal LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal (*fAddLstn)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params) { DEFiRet; dbgprintf("LstnInit for openssl: entering LstnInit (%p) for %s:%s SessMax=%d\n", fAddLstn, cnf_params->pszAddr, cnf_params->pszPort, iSessMax); pNS->fLstnInitDrvr = LstnInitDrvr; /* Init TCP Listener using base ptcp class */ iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params); RETiRet; } /* This function checks if the connection is still alive - well, kind of... * This is a dummy here. For details, check function common in ptcp driver. * rgerhards, 2008-06-09 */ static rsRetVal CheckConnection(nsd_t __attribute__((unused)) * pNsd) { nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); dbgprintf("CheckConnection for %p\n", pNsd); return nsd_ptcp.CheckConnection(pThis->pTcp); } /* Provide access to the underlying OS socket. */ static rsRetVal GetSock(nsd_t *pNsd, int *pSock) { nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; return nsd_ptcp.GetSock(pThis->pTcp, pSock); } /* get the remote hostname. The returned hostname must be freed by the caller. * rgerhards, 2008-04-25 */ static rsRetVal GetRemoteHName(nsd_t *pNsd, uchar **ppszHName) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName); dbgprintf("GetRemoteHName for %p = %s\n", pNsd, *ppszHName); RETiRet; } /* Provide access to the sockaddr_storage of the remote peer. This * is needed by the legacy ACL system. --- gerhards, 2008-12-01 */ static rsRetVal GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); iRet = nsd_ptcp.GetRemAddr(pThis->pTcp, ppAddr); dbgprintf("GetRemAddr for %p\n", pNsd); RETiRet; } /* get the remote host's IP address. Caller must Destruct the object. */ static rsRetVal GetRemoteIP(nsd_t *pNsd, prop_t **ip) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ip); dbgprintf("GetRemoteIP for %p\n", pNsd); RETiRet; } /* Perform all necessary checks after Handshake */ rsRetVal osslPostHandshakeCheck(nsd_ossl_t *pNsd) { DEFiRet; uchar *fromHostIP = NULL; char szDbg[255]; const SSL_CIPHER *sslCipher; nsd_ptcp.GetRemoteHName((nsd_t *)pNsd->pTcp, &fromHostIP); /* Some extra output for debugging openssl */ if (SSL_get_shared_ciphers(pNsd->pNetOssl->ssl, szDbg, sizeof szDbg) != NULL) dbgprintf("osslPostHandshakeCheck: Debug Shared ciphers = %s\n", szDbg); #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(ENABLE_WOLFSSL) if (SSL_get_shared_curve(pNsd->pNetOssl->ssl, -1) == 0) { // This is not a failure LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: " "Information, no shared curve between syslog client '%s' and server", fromHostIP); } #endif dbgprintf("osslPostHandshakeCheck: Debug Protocol Version: %s\n", SSL_get_version(pNsd->pNetOssl->ssl)); sslCipher = (const SSL_CIPHER *)SSL_get_current_cipher(pNsd->pNetOssl->ssl); if (sslCipher != NULL) { if (SSL_CIPHER_get_version(sslCipher) == NULL) { LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:" "TLS version mismatch between syslog client '%s' and server.", fromHostIP); } dbgprintf("osslPostHandshakeCheck: Debug Cipher Version: %s Name: %s\n", SSL_CIPHER_get_version(sslCipher), SSL_CIPHER_get_name(sslCipher)); } else { LogError(0, RS_RET_NO_ERRCODE, "nsd_ossl:No shared ciphers between syslog client '%s' and server.", fromHostIP); } FINALIZE; finalize_it: if (fromHostIP != NULL) { free(fromHostIP); } RETiRet; } /* Perform all necessary actions for Handshake */ rsRetVal osslHandshakeCheck(nsd_ossl_t *pNsd) { DEFiRet; uchar *fromHostIP = NULL; int remotePort = -1; uchar remotePortStr[8]; int res, resErr; dbgprintf("osslHandshakeCheck: Starting TLS Handshake for ssl[%p]\n", (void *)pNsd->pNetOssl->ssl); if (pNsd->pNetOssl->sslState == osslServer) { /* Handle Server SSL Object */ if ((res = SSL_accept(pNsd->pNetOssl->ssl)) <= 0) { /* Obtain SSL Error code */ nsd_ptcp.GetRemoteHName(pNsd->pTcp, &fromHostIP); nsd_ptcp.GetRemotePort(pNsd->pTcp, &remotePort); resErr = SSL_get_error(pNsd->pNetOssl->ssl, res); if (resErr == SSL_ERROR_WANT_READ || resErr == SSL_ERROR_WANT_WRITE) { pNsd->rtryCall = osslRtry_handshake; pNsd->rtryOsslErr = resErr; /* Store SSL ErrorCode into*/ dbgprintf( "osslHandshakeCheck: OpenSSL Server handshake does not complete " "immediately - setting to retry (this is OK and normal)\n"); FINALIZE; } else { nsd_ptcp.FmtRemotePortStr(remotePort, remotePortStr, sizeof(remotePortStr)); if (resErr == SSL_ERROR_SYSCALL) { dbgprintf( "osslHandshakeCheck: OpenSSL Server handshake failed with " "SSL_ERROR_SYSCALL - Aborting handshake.\n"); nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_WARNING, "osslHandshakeCheck Server", "SSL_accept"); LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "nsd_ossl:TLS session terminated with remote client '%s:%s': " "Handshake failed with SSL_ERROR_SYSCALL", fromHostIP, remotePortStr); osslAbortSess(pNsd); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } else { nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_ERR, "osslHandshakeCheck Server", "SSL_accept"); LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "nsd_ossl:TLS session terminated with remote client '%s:%s': " "Handshake failed with error code: %d", fromHostIP, remotePortStr, resErr); osslAbortSess(pNsd); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } } } } else { /* Handle Client SSL Object */ if ((res = SSL_do_handshake(pNsd->pNetOssl->ssl)) <= 0) { /* Obtain SSL Error code */ nsd_ptcp.GetRemoteHName(pNsd->pTcp, &fromHostIP); resErr = SSL_get_error(pNsd->pNetOssl->ssl, res); if (resErr == SSL_ERROR_WANT_READ || resErr == SSL_ERROR_WANT_WRITE) { pNsd->rtryCall = osslRtry_handshake; pNsd->rtryOsslErr = resErr; /* Store SSL ErrorCode into*/ dbgprintf( "osslHandshakeCheck: OpenSSL Client handshake does not complete " "immediately - setting to retry (this is OK and normal)\n"); FINALIZE; } else if (resErr == SSL_ERROR_SYSCALL) { dbgprintf( "osslHandshakeCheck: OpenSSL Client handshake failed with SSL_ERROR_SYSCALL " "- Aborting handshake.\n"); nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_WARNING, "osslHandshakeCheck Client", "SSL_do_handshake"); osslAbortSess(pNsd); ABORT_FINALIZE(RS_RET_NO_ERRCODE /*RS_RET_RETRY*/); } else { dbgprintf( "osslHandshakeCheck: OpenSSL Client handshake failed with %d " "- Aborting handshake.\n", resErr); nsd_ossl_lastOpenSSLErrorMsg(pNsd, res, pNsd->pNetOssl->ssl, LOG_ERR, "osslHandshakeCheck Client", "SSL_do_handshake"); nsd_ptcp.GetRemotePort(pNsd->pTcp, &remotePort); nsd_ptcp.FmtRemotePortStr(remotePort, remotePortStr, sizeof(remotePortStr)); LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "nsd_ossl:TLS session terminated with remote syslog server '%s:%s':" "Handshake failed with error code: %d", fromHostIP, remotePortStr, resErr); osslAbortSess(pNsd); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } } } /* Do post handshake stuff */ CHKiRet(osslPostHandshakeCheck(pNsd)); /* Now check authorization */ CHKiRet(osslChkPeerAuth(pNsd)); finalize_it: if (fromHostIP != NULL) { free(fromHostIP); } if (iRet == RS_RET_OK) { /* If no error occurred, set socket to SSL mode */ pNsd->iMode = 1; } RETiRet; } /* accept an incoming connection request - here, we do the usual accept * handling. TLS specific handling is done thereafter (and if we run in TLS * mode at this time). * rgerhards, 2008-04-25 */ static rsRetVal AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew, char *const connInfo) { DEFiRet; nsd_ossl_t *pNew = NULL; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); CHKiRet(nsd_osslConstruct(&pNew)); CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp)); dbgprintf("AcceptConnReq for [%p]: Accepting connection ... \n", (void *)pThis); CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp, connInfo)); if (pThis->iMode == 0) { /*we are in non-TLS mode, so we are done */ DBGPRINTF("AcceptConnReq: NOT in TLS mode!\n"); *ppNew = (nsd_t *)pNew; FINALIZE; } /* If we reach this point, we are in TLS mode */ pNew->pNetOssl->authMode = pThis->pNetOssl->authMode; pNew->permitExpiredCerts = pThis->permitExpiredCerts; pNew->pNetOssl->pPermPeers = pThis->pNetOssl->pPermPeers; pNew->pNetOssl->bSANpriority = pThis->pNetOssl->bSANpriority; pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth; pNew->DrvrTlsRevocationCheck = pThis->DrvrTlsRevocationCheck; pNew->gnutlsPriorityString = pThis->gnutlsPriorityString; pNew->pNetOssl->ctx = pThis->pNetOssl->ctx; pNew->pNetOssl->ctx_is_copy = 1; // do not free on pNew Destruction CHKiRet(osslInitSession(pNew, osslServer)); /* Store nsd_ossl_t* reference in SSL obj * Index allocation: 0=pTcp, 1=permitExpiredCerts, 2=imdtls instance, 3=revocationCheck */ SSL_set_ex_data(pNew->pNetOssl->ssl, 0, pNew->pTcp); SSL_set_ex_data(pNew->pNetOssl->ssl, 1, &pNew->permitExpiredCerts); SSL_set_ex_data(pNew->pNetOssl->ssl, 3, &pNew->DrvrTlsRevocationCheck); /* We now do the handshake */ CHKiRet(osslHandshakeCheck(pNew)); *ppNew = (nsd_t *)pNew; finalize_it: /* Accept appears to be done here */ if (pNew != NULL) { DBGPRINTF("AcceptConnReq: END iRet = %d, pNew=[%p], pNsd->rtryCall=%d\n", iRet, pNew, pNew->rtryCall); } if (iRet != RS_RET_OK) { if (pNew != NULL) { nsd_osslDestruct(&pNew); } } RETiRet; } /* receive data from a tcp socket * The lenBuf parameter must contain the max buffer size on entry and contains * the number of octets read on exit. This function * never blocks, not even when called on a blocking socket. That is important * for client sockets, which are set to block during send, but should not * block when trying to read data. -- rgerhards, 2008-03-17 * The function now follows the usual iRet calling sequence. * With GnuTLS, we may need to restart a recv() system call. If so, we need * to supply the SAME buffer on the retry. We can not assure this, as the * caller is free to call us with any buffer location (and in current * implementation, it is on the stack and extremely likely to change). To * work-around this problem, we allocate a buffer ourselfs and always receive * into that buffer. We pass data on to the caller only after we have received it. * To save some space, we allocate that internal buffer only when it is actually * needed, which means when we reach this function for the first time. To keep * the algorithm simple, we always supply data only from the internal buffer, * even if it is a single byte. As we have a stream, the caller must be prepared * to accept messages in any order, so we do not need to take care about this. * Please note that the logic also forces us to do some "faking" in select(), as * we must provide a fake "is ready for readign" status if we have data inside our * buffer. -- rgerhards, 2008-06-23 */ static rsRetVal Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf, int *const oserr, unsigned *const nextIODirection) { DEFiRet; ssize_t iBytesCopy; /* how many bytes are to be copied to the client buffer? */ nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); DBGPRINTF("Rcv for %p\n", pNsd); if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf, oserr, nextIODirection)); FINALIZE; } /* --- in TLS mode now --- */ if (pThis->rtryCall == osslRtry_handshake) { /* note: we are in receive, so we acually will retry receive in any case */ CHKiRet(doRetry(pThis)); ABORT_FINALIZE(RS_RET_RETRY); } /* Buffer logic applies only if we are in TLS mode. Here we * assume that we will switch from plain to TLS, but never back. This * assumption may be unsafe, but it is the model for the time being and I * do not see any valid reason why we should switch back to plain TCP after * we were in TLS mode. However, in that case we may lose something that * is already in the receive buffer ... risk accepted. -- rgerhards, 2008-06-23 */ if (pThis->pszRcvBuf == NULL) { /* we have no buffer, so we need to malloc one */ CHKmalloc(pThis->pszRcvBuf = malloc(NSD_OSSL_MAX_RCVBUF)); pThis->lenRcvBuf = -1; } /* now check if we have something in our buffer. If so, we satisfy * the request from buffer contents. */ if (pThis->lenRcvBuf == -1) { /* no data present, must read */ CHKiRet(osslRecordRecv(pThis, nextIODirection)); } if (pThis->lenRcvBuf == 0) { /* EOS */ *oserr = errno; ABORT_FINALIZE(RS_RET_CLOSED); } /* if we reach this point, data is present in the buffer and must be copied */ iBytesCopy = pThis->lenRcvBuf - pThis->ptrRcvBuf; if (iBytesCopy > *pLenBuf) { iBytesCopy = *pLenBuf; } else { pThis->lenRcvBuf = -1; /* buffer will be emptied below */ } memcpy(pBuf, pThis->pszRcvBuf + pThis->ptrRcvBuf, iBytesCopy); pThis->ptrRcvBuf += iBytesCopy; *pLenBuf = iBytesCopy; finalize_it: if (iRet != RS_RET_OK) { if (iRet == RS_RET_CLOSED) { if (pThis->pNetOssl->ssl != NULL) { /* Set SSL Shutdown */ SSL_shutdown(pThis->pNetOssl->ssl); dbgprintf("osslRcv SSL_shutdown done\n"); } } else if (iRet != RS_RET_RETRY) { /* We need to free the receive buffer in error error case unless a retry is wanted. , if we * allocated one. -- rgerhards, 2008-12-03 -- moved here by alorbach, 2015-12-01 */ *pLenBuf = 0; free(pThis->pszRcvBuf); pThis->pszRcvBuf = NULL; } else { /* RS_RET_RETRY | Check for SSL Shutdown */ if (SSL_get_shutdown(pThis->pNetOssl->ssl) == SSL_RECEIVED_SHUTDOWN) { dbgprintf("osslRcv received SSL_RECEIVED_SHUTDOWN!\n"); iRet = RS_RET_CLOSED; /* Send Shutdown message back */ SSL_shutdown(pThis->pNetOssl->ssl); } } } dbgprintf("osslRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf); RETiRet; } /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has * been written. * rgerhards, 2008-03-19 */ static rsRetVal Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) { DEFiRet; int iSent; int err; #ifdef ENABLE_WOLFSSL unsigned wolfsslSendReadRetries = 0; #endif nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; DBGPRINTF("Send for %p\n", pNsd); ISOBJ_TYPE_assert(pThis, nsd_ossl); if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf)); FINALIZE; } if (pThis->rtryCall == osslRtry_recv) { CHKiRet(retrySendSideRecordRecv(pThis)); } while (1) { iSent = SSL_write(pThis->pNetOssl->ssl, pBuf, *pLenBuf); if (iSent > 0) { *pLenBuf = iSent; break; } else { err = SSL_get_error(pThis->pNetOssl->ssl, iSent); if (err == SSL_ERROR_ZERO_RETURN) { DBGPRINTF("Send: SSL_ERROR_ZERO_RETURN received, connection closed by peer\n"); ABORT_FINALIZE(RS_RET_CLOSED); } else if (err == SSL_ERROR_SYSCALL) { #ifdef ENABLE_WOLFSSL if (SSL_want_read(pThis->pNetOssl->ssl) || SSL_want_write(pThis->pNetOssl->ssl)) { ABORT_FINALIZE(RS_RET_RETRY); } #endif /* Output error and abort */ nsd_ossl_lastOpenSSLErrorMsg(pThis, iSent, pThis->pNetOssl->ssl, LOG_INFO, "Send", "SSL_write"); iRet = RS_RET_TLS_ERR_SYSCALL; /* Check for underlaying socket errors **/ if (errno == ECONNRESET) { dbgprintf("Send: SSL_ERROR_SYSCALL Connection was reset by remote\n"); /* Connection was dropped from remote site */ iRet = RS_RET_CLOSED; } else { DBGPRINTF("Send: SSL_ERROR_SYSCALL Errno %d\n", errno); } ABORT_FINALIZE(iRet); } else if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { /* Output error and abort */ nsd_ossl_lastOpenSSLErrorMsg(pThis, iSent, pThis->pNetOssl->ssl, LOG_ERR, "Send", "SSL_write"); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } else { /* * OpenSSL needs us to READ or WRITE to make progress. * In TLS 1.3, servers may send post-handshake messages (e.g. KeyUpdate) * which require the client to read before it can continue writing. */ if (err == SSL_ERROR_WANT_READ) { #ifdef ENABLE_WOLFSSL /* * wolfSSL's OpenSSL compatibility layer has historically needed * this local progress loop for the wolfSSL CI lane. Keep real * OpenSSL on the nonblocking retry propagation path below. */ unsigned nextIODirection; rsRetVal recvRet; if (pThis->pszRcvBuf == NULL) { CHKmalloc(pThis->pszRcvBuf = malloc(NSD_OSSL_MAX_RCVBUF)); pThis->lenRcvBuf = -1; } if (pThis->lenRcvBuf == -1) { recvRet = osslRecordRecv(pThis, &nextIODirection); if (recvRet != RS_RET_OK && recvRet != RS_RET_RETRY) ABORT_FINALIZE(recvRet); if (recvRet == RS_RET_RETRY) { if (++wolfsslSendReadRetries >= 100) ABORT_FINALIZE(RS_RET_RETRY); srSleep(0, 10000); pThis->rtryCall = osslRtry_None; pThis->rtryOsslErr = SSL_ERROR_NONE; continue; } wolfsslSendReadRetries = 0; pThis->rtryCall = osslRtry_None; pThis->rtryOsslErr = SSL_ERROR_NONE; if (pThis->lenRcvBuf == 0) ABORT_FINALIZE(RS_RET_CLOSED); } #else /* * Preserve any application data read while driving send-side TLS * control traffic. TLS 1.3 post-handshake messages can make * SSL_write() need a read, and SSL_read() may return application * bytes after processing that control traffic. */ CHKiRet(retrySendSideRecordRecv(pThis)); /* Continue loop to retry SSL_write */ #endif } else { /* Check for SSL Shutdown */ if (SSL_get_shutdown(pThis->pNetOssl->ssl) == SSL_RECEIVED_SHUTDOWN) { dbgprintf("osslRcv received SSL_RECEIVED_SHUTDOWN!\n"); ABORT_FINALIZE(RS_RET_CLOSED); } } } } } finalize_it: RETiRet; } /* Enable KEEPALIVE handling on the socket. * rgerhards, 2009-06-02 */ static rsRetVal EnableKeepAlive(nsd_t *pNsd) { nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); return nsd_ptcp.EnableKeepAlive(pThis->pTcp); } /* open a connection to a remote host (server). With OpenSSL, we always * open a plain tcp socket and then, if in TLS mode, do a handshake on it. */ static rsRetVal Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device) { DEFiRet; DBGPRINTF("openssl: entering Connect family=%d, device=%s\n", family, device); nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; uchar *fromHostIP = NULL; ISOBJ_TYPE_assert(pThis, nsd_ossl); assert(port != NULL); assert(host != NULL); /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for all newer versions! */ #if OPENSSL_VERSION_NUMBER < 0x10100000L CHKiRet(net_ossl.osslCtxInit(pThis->pNetOssl, SSLv23_method())); #else CHKiRet(net_ossl.osslCtxInit(pThis->pNetOssl, TLS_method())); #endif // Apply PriorityString after Ctx Creation applyGnutlsPriorityString(pThis); // Perform TCP Connect CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host, device)); if (pThis->iMode == 0) { /*we are in non-TLS mode, so we are done */ DBGPRINTF("Connect: NOT in TLS mode!\n"); FINALIZE; } nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHostIP); LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "nsd_ossl: " "TLS Connection initiated with remote syslog server '%s'.", fromHostIP); /*if we reach this point we are in tls mode */ DBGPRINTF("Connect: TLS Mode\n"); /* Do SSL Session init */ CHKiRet(osslInitSession(pThis, osslClient)); CHKiRet(SetServerNameIfPresent(pThis, host)); /* Store nsd_ossl_t* reference in SSL obj * Index allocation: 0=pTcp, 1=permitExpiredCerts, 2=imdtls instance, 3=revocationCheck */ SSL_set_ex_data(pThis->pNetOssl->ssl, 0, pThis->pTcp); SSL_set_ex_data(pThis->pNetOssl->ssl, 1, &pThis->permitExpiredCerts); SSL_set_ex_data(pThis->pNetOssl->ssl, 3, &pThis->DrvrTlsRevocationCheck); /* We now do the handshake */ iRet = osslHandshakeCheck(pThis); finalize_it: if (fromHostIP != NULL) { free(fromHostIP); } /* Connect appears to be done here */ dbgprintf("Connect: END iRet = %d, pThis=[%p], pNsd->rtryCall=%d\n", iRet, pThis, pThis->rtryCall); if (iRet != RS_RET_OK) { if (pThis->bHaveSess) { pThis->bHaveSess = 0; SSL_free(pThis->pNetOssl->ssl); pThis->pNetOssl->ssl = NULL; } } RETiRet; } static rsRetVal SetGnutlsPriorityString(nsd_t *const pNsd, uchar *const gnutlsPriorityString) { DEFiRet; nsd_ossl_t __attribute__((unused)) *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) sbool ApplySettings = 0; if ((gnutlsPriorityString != NULL && pThis->gnutlsPriorityString == NULL) || (gnutlsPriorityString != NULL && strcmp((const char *)pThis->gnutlsPriorityString, (const char *)gnutlsPriorityString) != 0)) { ApplySettings = 1; } pThis->gnutlsPriorityString = gnutlsPriorityString; dbgprintf("gnutlsPriorityString: set to '%s' Apply %s\n", (gnutlsPriorityString != NULL ? (char *)gnutlsPriorityString : "NULL"), (ApplySettings == 1 ? "TRUE" : "FALSE")); if (ApplySettings == 1) { /* Apply Settings if necessary */ applyGnutlsPriorityString(pThis); } #else LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support SSL_CONF_cmd API" "(maybe it is too old?). Cannot use gnutlsPriorityString ('%s'). For more see: " "https://www.rsyslog.com/doc/master/configuration/modules/imtcp.html#gnutlsprioritystring", gnutlsPriorityString); #endif RETiRet; } static rsRetVal applyGnutlsPriorityString(nsd_ossl_t __attribute__((unused)) *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ossl); #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) /* Note: we disable unkonwn functions. The corresponding error message is * generated during SetGntuTLSPriorityString(). */ if (pThis->gnutlsPriorityString == NULL || pThis->pNetOssl->ctx == NULL) { FINALIZE; } else { CHKiRet(net_ossl.osslApplyTlscgfcmd(pThis->pNetOssl, pThis->gnutlsPriorityString)); } #endif #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) finalize_it: #endif RETiRet; } /* Set the driver cert extended key usage check setting, for now it is empty wrapper. * TODO: implement openSSL version * jvymazal, 2019-08-16 */ static rsRetVal SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) * pNsd, int ChkExtendedKeyUsage) { DEFiRet; if (ChkExtendedKeyUsage != 0) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " "not supported by ossl netstream driver", ChkExtendedKeyUsage); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set the driver name checking strictness * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored) * jvymazal, 2019-08-16, csiltala, 2025-07-28 */ static rsRetVal SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (prioritizeSan != 0 && prioritizeSan != 1) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " "not supported by ossl netstream driver", prioritizeSan); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } pThis->pNetOssl->bSANpriority = prioritizeSan; finalize_it: RETiRet; } /* Set the driver tls verifyDepth * alorbach, 2019-12-20 */ static rsRetVal SetTlsVerifyDepth(nsd_t *pNsd, int verifyDepth) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); if (verifyDepth == 0) { FINALIZE; } assert(verifyDepth >= 2); pThis->DrvrVerifyDepth = verifyDepth; finalize_it: RETiRet; } /* Set TLS revocation check (OCSP/CRL) * 0 - disable revocation checking (default for compatibility) * 1 - enable revocation checking via OCSP (and CRL when implemented) */ static rsRetVal SetTlsRevocationCheck(nsd_t *pNsd, int enabled) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); pThis->DrvrTlsRevocationCheck = (enabled != 0) ? 1 : 0; pThis->pNetOssl->bTlsRevocationCheck = pThis->DrvrTlsRevocationCheck; dbgprintf("SetTlsRevocationCheck: revocation check %s\n", pThis->DrvrTlsRevocationCheck ? "enabled" : "disabled"); RETiRet; } static rsRetVal SetTlsCAFile(nsd_t *pNsd, const uchar *const caFile) { DEFiRet; nsd_ossl_t *const pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); free((void *)pThis->pNetOssl->pszCAFile); pThis->pNetOssl->pszCAFile = NULL; if (caFile != NULL) { CHKmalloc(pThis->pNetOssl->pszCAFile = (const uchar *)strdup((const char *)caFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCRLFile(nsd_t *pNsd, const uchar *const crlFile) { DEFiRet; nsd_ossl_t *const pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); free((void *)pThis->pNetOssl->pszCRLFile); pThis->pNetOssl->pszCRLFile = NULL; if (crlFile != NULL) { CHKmalloc(pThis->pNetOssl->pszCRLFile = (const uchar *)strdup((const char *)crlFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCAExtraFiles(nsd_t *pNsd, const uchar *const extraCaFiles) { DEFiRet; nsd_ossl_t *const pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); free((void *)pThis->pNetOssl->pszExtraCAFiles); pThis->pNetOssl->pszExtraCAFiles = NULL; if (extraCaFiles != NULL) { CHKmalloc(pThis->pNetOssl->pszExtraCAFiles = (const uchar *)strdup((const char *)extraCaFiles)); } finalize_it: RETiRet; } static rsRetVal SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_ossl_t *const pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); free((void *)pThis->pNetOssl->pszKeyFile); pThis->pNetOssl->pszKeyFile = NULL; if (pszFile != NULL) { CHKmalloc(pThis->pNetOssl->pszKeyFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCertFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_ossl_t *const pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); free((void *)pThis->pNetOssl->pszCertFile); pThis->pNetOssl->pszCertFile = NULL; if (pszFile != NULL) { CHKmalloc(pThis->pNetOssl->pszCertFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } /* Set the TLS SNI of the remote server */ static rsRetVal SetRemoteSNI(nsd_t *pNsd, uchar *remoteSNI) { DEFiRet; nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ossl); free(pThis->remoteSNI); if (remoteSNI == NULL) { pThis->remoteSNI = NULL; } else { CHKmalloc(pThis->remoteSNI = (uchar *)strdup((char *)remoteSNI)); } finalize_it: RETiRet; } static rsRetVal GetRemotePort(nsd_t *pNsd, int *port) { nsd_ossl_t *pThis = (nsd_ossl_t *)pNsd; ISOBJ_TYPE_assert((pThis), nsd_ossl); return nsd_ptcp.GetRemotePort(pThis->pTcp, port); } static rsRetVal FmtRemotePortStr(const int port, uchar *const buf, const size_t len) { return nsd_ptcp.FmtRemotePortStr(port, buf, len); } /* queryInterface function */ BEGINobjQueryInterface(nsd_ossl) CODESTARTobjQueryInterface(nsd_ossl); if (pIf->ifVersion != nsdCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = (rsRetVal(*)(nsd_t **))nsd_osslConstruct; pIf->Destruct = (rsRetVal(*)(nsd_t **))nsd_osslDestruct; pIf->Abort = Abort; pIf->LstnInit = LstnInit; pIf->AcceptConnReq = AcceptConnReq; pIf->Rcv = Rcv; pIf->Send = Send; pIf->Connect = Connect; pIf->GetSock = GetSock; pIf->SetSock = SetSock; pIf->SetMode = SetMode; pIf->SetAuthMode = SetAuthMode; pIf->SetPermitExpiredCerts = SetPermitExpiredCerts; pIf->SetPermPeers = SetPermPeers; pIf->CheckConnection = CheckConnection; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->GetRemAddr = GetRemAddr; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetTcpUserTimeout = SetTcpUserTimeout; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; /* we don't NEED this interface! */ pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; /* we don't NEED this interface! */ pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsRevocationCheck = SetTlsRevocationCheck; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsCAExtraFiles = SetTlsCAExtraFiles; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; pIf->GetRemotePort = GetRemotePort; pIf->FmtRemotePortStr = FmtRemotePortStr; pIf->SetRemoteSNI = SetRemoteSNI; finalize_it: ENDobjQueryInterface(nsd_ossl) /* exit our class */ BEGINObjClassExit(nsd_ossl, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsd_ossl); /* release objects we no longer need */ objRelease(net_ossl, CORE_COMPONENT); objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME); objRelease(net, LM_NET_FILENAME); objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDObjClassExit(nsd_ossl) /* Initialize the nsd_ossl class. Must be called as the very first method * before anything else is called inside this class. */ BEGINObjClassInit(nsd_ossl, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME)); CHKiRet(objUse(net_ossl, CORE_COMPONENT)); ENDObjClassInit(nsd_ossl) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; nsd_osslClassExit(); net_osslClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ DBGPRINTF("modInit\n"); CHKiRet(net_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ CHKiRet(nsd_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/prop.c0000644000000000000000000000013215141320042015336 xustar0030 mtime=1770364962.097420001 30 atime=1787067617.934435849 30 ctime=1787067794.435725819 rsyslog-8.2608.0/runtime/prop.c0000666000175000017500000001745115141320042015014 0ustar00rgerrger/* prop.c - rsyslog's prop object * * This object is meant to support message properties that are stored * seperately from the message. The main intent is to support properties * that are "constant" during a period of time, so that many messages may * contain a reference to the same property. It is important, though, that * properties are destroyed when they are no longer needed. * * Please note that this is a performance-critical part of the software and * as such we may use some methods in here which do not look elegant, but * which are fast... * * Module begun 2009-06-17 by Rainer Gerhards * * Copyright 2009-2016 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "obj.h" #include "obj-types.h" #include "unicode-helper.h" #include "atomic.h" #include "prop.h" /* static data */ DEFobjStaticHelpers; // extern uchar *propGetSzStr(prop_t *pThis); /* expand inline function here */ /* Standard-Constructor */ BEGINobjConstruct(prop) /* be sure to specify the object type also in END macro! */ pThis->iRefCount = 1; INIT_ATOMIC_HELPER_MUT(pThis->mutRefCount); ENDobjConstruct(prop) /* destructor for the prop object */ BEGINobjDestruct(prop) /* be sure to specify the object type also in END and CODESTART macros! */ int currRefCount; CODESTARTobjDestruct(prop); currRefCount = ATOMIC_DEC_AND_FETCH(&pThis->iRefCount, &pThis->mutRefCount); if (currRefCount == 0) { /* (only) in this case we need to actually destruct the object */ if (pThis->len >= CONF_PROP_BUFSIZE) free(pThis->szVal.psz); DESTROY_ATOMIC_HELPER_MUT(pThis->mutRefCount); } else { pThis = NULL; /* tell framework NOT to destructing the object! */ } ENDobjDestruct(prop) /* set string, we make our own private copy! This MUST only be called BEFORE * ConstructFinalize()! */ static rsRetVal SetString(prop_t *pThis, const uchar *psz, const int len) { DEFiRet; ISOBJ_TYPE_assert(pThis, prop); if (pThis->len >= CONF_PROP_BUFSIZE) free(pThis->szVal.psz); pThis->len = len; if (len < CONF_PROP_BUFSIZE) { memcpy(pThis->szVal.sz, psz, len + 1); } else { if (pThis->szVal.psz != NULL) { free(pThis->szVal.psz); } CHKmalloc(pThis->szVal.psz = malloc(len + 1)); memcpy(pThis->szVal.psz, psz, len + 1); } finalize_it: RETiRet; } /* get string length */ static int GetStringLen(prop_t *pThis) { return pThis->len; } /* get string */ static rsRetVal GetString(prop_t *pThis, uchar **ppsz, int *plen) { ISOBJ_TYPE_assert(pThis, prop); if (pThis->len < CONF_PROP_BUFSIZE) { *ppsz = pThis->szVal.sz; } else { *ppsz = pThis->szVal.psz; } *plen = pThis->len; return RS_RET_OK; } /* ConstructionFinalizer * rgerhards, 2008-01-09 */ static rsRetVal propConstructFinalize(prop_t __attribute__((unused)) * pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, prop); RETiRet; } /* add a new reference. It is VERY IMPORTANT to call this function whenever * the property is handed over to some entitiy that later call Destruct() on it. */ static rsRetVal AddRef(prop_t *pThis) { if (pThis == NULL) { DBGPRINTF( "prop/AddRef is passed a NULL ptr - ignoring it " "- further problems may occur\n"); FINALIZE; } ATOMIC_INC(&pThis->iRefCount, &pThis->mutRefCount); finalize_it: return RS_RET_OK; } /* this is a "do it all in one shot" function that creates a new property, * assigns the provided string to it and finalizes the property. Among the * convenience, it is also (very, very) slightly faster. * rgerhards, 2009-07-01 */ static rsRetVal CreateStringProp(prop_t **ppThis, const uchar *psz, const int len) { prop_t *pThis = NULL; DEFiRet; CHKiRet(propConstruct(&pThis)); CHKiRet(SetString(pThis, psz, len)); CHKiRet(propConstructFinalize(pThis)); *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { if (pThis != NULL) propDestruct(&pThis); } RETiRet; } /* another one-stop function, quite useful: it takes a property pointer and * a string. If the string is already contained in the property, nothing happens. * If the string is different (or the pointer NULL), the current property * is destructed and a new one created. This can be used to get a specific * name in those cases where there is a good chance that the property * immediatly previously processed already contained the value we need - in * which case we save us all the creation overhead by just reusing the already * existing property). * rgerhards, 2009-07-01 */ static rsRetVal CreateOrReuseStringProp(prop_t **ppThis, const uchar *psz, const int len) { uchar *pszPrev; int lenPrev; DEFiRet; assert(ppThis != NULL); if (*ppThis == NULL) { /* we need to create a property */ CHKiRet(CreateStringProp(ppThis, psz, len)); } else { /* already exists, check if we can re-use it */ GetString(*ppThis, &pszPrev, &lenPrev); if (len != lenPrev || ustrcmp(psz, pszPrev)) { /* different, need to discard old & create new one */ propDestruct(ppThis); CHKiRet(CreateStringProp(ppThis, psz, len)); } /* else we can re-use the existing one! */ } finalize_it: RETiRet; } /* debugprint for the prop object */ BEGINobjDebugPrint(prop) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(prop); dbgprintf("prop object %p - no further debug info implemented\n", pThis); ENDobjDebugPrint(prop) /* queryInterface function * rgerhards, 2008-02-21 */ BEGINobjQueryInterface(prop) CODESTARTobjQueryInterface(prop); if (pIf->ifVersion != propCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = propConstruct; pIf->ConstructFinalize = propConstructFinalize; pIf->Destruct = propDestruct; pIf->DebugPrint = propDebugPrint; pIf->SetString = SetString; pIf->GetString = GetString; pIf->GetStringLen = GetStringLen; pIf->AddRef = AddRef; pIf->CreateStringProp = CreateStringProp; pIf->CreateOrReuseStringProp = CreateOrReuseStringProp; finalize_it: ENDobjQueryInterface(prop) /* Exit the prop class. * rgerhards, 2009-04-06 */ BEGINObjClassExit(prop, OBJ_IS_CORE_MODULE) /* class, version */ ENDObjClassExit(prop) /* Initialize the prop class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(prop, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, propDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, propConstructFinalize); ENDObjClassInit(prop) /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/lmcry_gcry.c0000644000000000000000000000013015216464436016551 xustar0028 mtime=1782212894.0272662 30 atime=1783339708.064810735 30 ctime=1787067794.507727161 rsyslog-8.2608.0/runtime/lmcry_gcry.c0000664000175000017500000002503615216464436016225 0ustar00rgerrger/* lmcry_gcry.c * * An implementation of the cryprov interface for libgcrypt. * * Copyright 2013-2017 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "cryprov.h" #include "parserif.h" #include "libgcry.h" #include "lmcry_gcry.h" #include "libcry_common.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfpdescrRegular[] = {{"cry.key", eCmdHdlrGetWord, 0}, {"cry.keyfile", eCmdHdlrGetWord, 0}, {"cry.keyprogram", eCmdHdlrGetWord, 0}, {"cry.mode", eCmdHdlrGetWord, 0}, /* CBC, ECB, etc */ {"cry.algo", eCmdHdlrGetWord, 0}}; static struct cnfparamblk pblkRegular = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrRegular) / sizeof(struct cnfparamdescr), cnfpdescrRegular}; static struct cnfparamdescr cnfpdescrQueue[] = {{"queue.cry.key", eCmdHdlrGetWord, 0}, {"queue.cry.keyfile", eCmdHdlrGetWord, 0}, {"queue.cry.keyprogram", eCmdHdlrGetWord, 0}, {"queue.cry.mode", eCmdHdlrGetWord, 0}, /* CBC, ECB, etc */ {"queue.cry.algo", eCmdHdlrGetWord, 0}}; static struct cnfparamblk pblkQueue = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrQueue) / sizeof(struct cnfparamdescr), cnfpdescrQueue}; #if 0 static void errfunc(__attribute__((unused)) void *usrptr, uchar *emsg) { LogError(0, RS_RET_CRYPROV_ERR, "Crypto Provider" "Error: %s - disabling encryption", emsg); } #endif /* Standard-Constructor */ BEGINobjConstruct(lmcry_gcry) CHKmalloc(pThis->ctx = gcryCtxNew()); finalize_it: ENDobjConstruct(lmcry_gcry) /* destructor for the lmcry_gcry object */ BEGINobjDestruct(lmcry_gcry) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(lmcry_gcry); rsgcryCtxDel(pThis->ctx); ENDobjDestruct(lmcry_gcry) /* apply all params from param block to us. This must be called * after construction, but before the OnFileOpen() entry point. * Defaults are expected to have been set during construction. */ static rsRetVal SetCnfParam(void *pT, struct nvlst *lst, int paramType) { lmcry_gcry_t *pThis = (lmcry_gcry_t *)pT; int i, r; unsigned keylen = 0; uchar *key = NULL; uchar *keyfile = NULL; uchar *keyprogram = NULL; uchar *algo = NULL; uchar *mode = NULL; int nKeys; /* number of keys (actually methods) specified */ struct cnfparamvals *pvals; struct cnfparamblk *pblk; DEFiRet; pblk = (paramType == CRYPROV_PARAMTYPE_REGULAR) ? &pblkRegular : &pblkQueue; nKeys = 0; pvals = nvlstGetParams(lst, pblk, NULL); if (pvals == NULL) { parser_errmsg("error crypto provider gcryconfig parameters]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("param blk in lmcry_gcry:\n"); cnfparamsPrint(pblk, pvals); } for (i = 0; i < pblk->nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblk->descr[i].name, "cry.key") || !strcmp(pblk->descr[i].name, "queue.cry.key")) { CHKmalloc(key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++nKeys; } else if (!strcmp(pblk->descr[i].name, "cry.keyfile") || !strcmp(pblk->descr[i].name, "queue.cry.keyfile")) { CHKmalloc(keyfile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++nKeys; } else if (!strcmp(pblk->descr[i].name, "cry.keyprogram") || !strcmp(pblk->descr[i].name, "queue.cry.keyprogram")) { CHKmalloc(keyprogram = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++nKeys; } else if (!strcmp(pblk->descr[i].name, "cry.mode") || !strcmp(pblk->descr[i].name, "queue.cry.mode")) { CHKmalloc(mode = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk->descr[i].name, "cry.algo") || !strcmp(pblk->descr[i].name, "queue.cry.algo")) { CHKmalloc(algo = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { DBGPRINTF( "lmcry_gcry: program error, non-handled " "param '%s'\n", pblk->descr[i].name); } } if (algo != NULL) { iRet = rsgcrySetAlgo(pThis->ctx, algo); if (iRet != RS_RET_OK) { LogError(0, iRet, "cry.algo '%s' is not know/supported", algo); FINALIZE; } } if (mode != NULL) { iRet = rsgcrySetMode(pThis->ctx, mode); if (iRet != RS_RET_OK) { LogError(0, iRet, "cry.mode '%s' is not know/supported", mode); FINALIZE; } } /* note: key must be set AFTER algo/mode is set (as it depends on them) */ if (nKeys != 1) { LogError(0, RS_RET_INVALID_PARAMS, "excactly one of the following " "parameters can be specified: cry.key, cry.keyfile, cry.keyprogram\n"); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } if (key != NULL) { LogError(0, RS_RET_ERR, "Note: specifying an actual key directly from the " "config file is highly insecure - DO NOT USE FOR PRODUCTION"); keylen = strlen((char *)key); } if (keyfile != NULL) { r = cryGetKeyFromFile((char *)keyfile, (char **)&key, &keylen); if (r != 0) { LogError(errno, RS_RET_ERR, "error reading keyfile %s", keyfile); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } } if (keyprogram != NULL) { r = cryGetKeyFromProg((char *)keyprogram, (char **)&key, &keylen); if (r != 0) { LogError(0, RS_RET_ERR, "error %d obtaining key from program %s\n", r, keyprogram); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } } /* if we reach this point, we have a valid key */ r = rsgcrySetKey(pThis->ctx, key, keylen); if (r > 0) { LogError(0, RS_RET_INVALID_PARAMS, "Key length %d expected, but " "key of length %d given", r, keylen); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } finalize_it: free(key); free(keyfile); free(algo); free(keyprogram); free(mode); if (pvals != NULL) cnfparamvalsDestruct(pvals, pblk); RETiRet; } static void SetDeleteOnClose(void *pF, int val) { gcryfileSetDeleteOnClose(pF, val); } static rsRetVal GetBytesLeftInBlock(void *pF, ssize_t *left) { return gcryfileGetBytesLeftInBlock((gcryfile)pF, left); } static rsRetVal DeleteStateFiles(uchar *logfn) { return gcryfileDeleteState(logfn); } static rsRetVal OnFileOpen(void *pT, uchar *fn, void *pGF, char openMode) { lmcry_gcry_t *pThis = (lmcry_gcry_t *)pT; gcryfile *pgf = (gcryfile *)pGF; DEFiRet; DBGPRINTF("lmcry_gcry: open file '%s', mode '%c'\n", fn, openMode); iRet = rsgcryInitCrypt(pThis->ctx, pgf, fn, openMode); if (iRet != RS_RET_OK) { LogError(0, iRet, "Encryption Provider" "Error: cannot open .encinfo file - disabling log file"); } RETiRet; } static rsRetVal Decrypt(void *pF, uchar *rec, size_t *lenRec) { DEFiRet; iRet = rsgcryDecrypt(pF, rec, lenRec); RETiRet; } static rsRetVal Encrypt(void *pF, uchar *rec, size_t *lenRec) { DEFiRet; iRet = rsgcryEncrypt(pF, rec, lenRec); RETiRet; } static rsRetVal OnFileClose(void *pF, off64_t offsLogfile) { DEFiRet; gcryfileDestruct(pF, offsLogfile); RETiRet; } BEGINobjQueryInterface(lmcry_gcry) CODESTARTobjQueryInterface(lmcry_gcry); if (pIf->ifVersion != cryprovCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } pIf->Construct = (rsRetVal(*)(void *))lmcry_gcryConstruct; pIf->SetCnfParam = SetCnfParam; pIf->SetDeleteOnClose = SetDeleteOnClose; pIf->Destruct = (rsRetVal(*)(void *))lmcry_gcryDestruct; pIf->OnFileOpen = OnFileOpen; pIf->Encrypt = Encrypt; pIf->Decrypt = Decrypt; pIf->OnFileClose = OnFileClose; pIf->DeleteStateFiles = DeleteStateFiles; pIf->GetBytesLeftInBlock = GetBytesLeftInBlock; finalize_it: ENDobjQueryInterface(lmcry_gcry) BEGINObjClassExit(lmcry_gcry, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(lmcry_gcry); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); rsgcryExit(); ENDObjClassExit(lmcry_gcry) BEGINObjClassInit(lmcry_gcry, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); if (rsgcryInit() != 0) { LogError(0, RS_RET_CRYPROV_ERR, "error initializing " "crypto provider - cannot encrypt"); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } ENDObjClassInit(lmcry_gcry) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; lmcry_gcryClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(lmcry_gcryClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/template.c0000644000000000000000000000013215241075234016204 xustar0030 mtime=1787067036.612578425 30 atime=1787067036.759581178 30 ctime=1787067794.496726956 rsyslog-8.2608.0/runtime/template.c0000664000175000017500000040032615241075234015655 0ustar00rgerrger/* This is the template processing code of rsyslog. * begun 2004-11-17 rgerhards * * Copyright 2004-2019 Rainer Gerhards and Adiscon * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Note: there is a tiny bit of code left where I could not get any response * from the author if this code can be placed under ASL2.0. I have guarded this * with #ifdef STRICT_GPLV3. Only if that macro is defined, the code will be * compiled. Otherwise this feature is not present. The plan is to do a * different implementation in the future to get rid of this problem. * rgerhards, 2012-08-25 */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include "stringbuf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "dirty.h" #include "obj.h" #include "errmsg.h" #include "strgen.h" #include "rsconf.h" #include "msg.h" #include "parserif.h" #include "unicode-helper.h" /* states for lazily built JSON tree used in list templates with jsonf mode */ #define TPL_JSON_TREE_NOT_BUILT 0 #define TPL_JSON_TREE_BUILT 1 #define TPL_JSON_TREE_UNSUPPORTED 2 enum tplJsonNodeType { tplJsonNodeObject = 0, tplJsonNodeValue = 1 }; struct tplJsonNode { enum tplJsonNodeType type; uchar *name; size_t nameLen; struct templateEntry *pTpe; /* only valid for value nodes */ struct tplJsonNode *parent; struct tplJsonNode *firstChild; struct tplJsonNode *lastChild; struct tplJsonNode *nextSibling; }; static struct tplJsonNode *tplJsonNodeNew(enum tplJsonNodeType type, const uchar *name, size_t nameLen); static void tplJsonNodeAddChild(struct tplJsonNode *parent, struct tplJsonNode *child); static void tplJsonNodeFree(struct tplJsonNode *node); static rsRetVal tplJsonEnsureContainer( struct tplJsonNode *parent, const uchar *name, size_t nameLen, struct tplJsonNode **ppContainer, int *pUnsupported); static rsRetVal tplJsonAddValueNode( struct tplJsonNode *parent, struct templateEntry *pTpe, const uchar *name, size_t nameLen, int *pUnsupported); static rsRetVal tplJsonBuildTree(struct template *pTpl); static rsRetVal tplJsonRender(struct template *pTpl, smsg_t *pMsg, actWrkrIParams_t *iparam, struct syslogTime *ttNow); static rsRetVal tplJsonRenderChildren( const struct tplJsonNode *parent, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppDst, int *pNeedComma); static rsRetVal tplAddSize(size_t a, size_t b, size_t *sum); /** Returns true when at least one field lacks explicit secure path handling. */ static int tplNeedsDynafileSecureDefault(const struct template *const pTpl) { const struct templateEntry *pTpe; assert(pTpl != NULL); for (pTpe = pTpl->pEntryRoot; pTpe != NULL; pTpe = pTpe->pNext) { if (pTpe->eEntryType == FIELD && !pTpe->data.field.options.bSecPathDrop && !pTpe->data.field.options.bSecPathReplace) { return 1; } } return 0; } /** Applies the strict dynafile path default to fields without explicit mode. */ static void tplApplyDynafileSecureDefault(struct template *const pTpl) { struct templateEntry *pTpe; assert(pTpl != NULL); for (pTpe = pTpl->pEntryRoot; pTpe != NULL; pTpe = pTpe->pNext) { if (pTpe->eEntryType == FIELD && !pTpe->data.field.options.bSecPathDrop && !pTpe->data.field.options.bSecPathReplace) { pTpe->data.field.options.bSecPathReplace = 1; pTpe->bComplexProcessing = 1; } } pTpl->bAppliedDynafileSecureDefault = 1; } /** Records a template use and enforces compatibility.defaults.secure policy. */ void tplNoteUse(struct template *const pTpl, const int bDynafile) { assert(pTpl != NULL); if (bDynafile) { pTpl->bUsedAsDynafile = 1; } else { pTpl->bUsedAsNonDynafile = 1; } if (pTpl->bUsedAsDynafile && pTpl->bUsedAsNonDynafile && !pTpl->bWarnedDynafileMixedUse) { if (loadConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_STRICT) { parser_warnmsg( "template '%s' is used both as an omfile dynafile template and for other output; " "strict secure dynafile defaults apply to the shared template, use separate templates " "if literal slashes must be preserved outside dynafile paths", pTpl->pszName); } else { parser_warnmsg( "template '%s' is used both as an omfile dynafile template and for other output; " "in strict mode, secure dynafile defaults apply to the shared template, use separate " "templates if literal slashes must be preserved outside dynafile paths", pTpl->pszName); } pTpl->bWarnedDynafileMixedUse = 1; } if (!bDynafile || !tplNeedsDynafileSecureDefault(pTpl)) { return; } if (loadConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_STRICT) { if (!pTpl->bAppliedDynafileSecureDefault) { tplApplyDynafileSecureDefault(pTpl); } } else if (loadConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_WARN && !pTpl->bWarnedDynafileSecureDefault) { parser_warnmsg( "backward-compatible insecure default in use: omfile dynafile template '%s' has " "fields without securepath handling; use global(compatibility.defaults.secure=\"strict\") " "to default them to secpath-replace", pTpl->pszName); pTpl->bWarnedDynafileSecureDefault = 1; } } static rsRetVal tplJsonRenderNode( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput); static rsRetVal tplJsonRenderValue( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput); static rsRetVal tplJsonRenderObject( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput); static void tplWarnDuplicateJsonKeys(struct template *pTpl); /** * \brief Allocate a fresh JSON tree node for dotted jsonf rendering. * * The node optionally owns a copy of \p name so descendants can be * addressed without depending on the template entry backing storage. * * \param type Node role (object container or scalar value). * \param name Optional name for the node. * \param nameLen Length of \p name in bytes (without terminator). * \return Newly allocated node or NULL on allocation failure. */ static struct tplJsonNode *tplJsonNodeNew(enum tplJsonNodeType type, const uchar *name, size_t nameLen) { struct tplJsonNode *node = calloc(1, sizeof(struct tplJsonNode)); if (node == NULL) return NULL; node->type = type; node->pTpe = NULL; if (name != NULL && nameLen > 0) { if (nameLen == SIZE_MAX) { free(node); return NULL; } node->name = malloc(nameLen + 1); if (node->name == NULL) { free(node); return NULL; } memcpy(node->name, name, nameLen); node->name[nameLen] = '\0'; node->nameLen = nameLen; } return node; } /** * \brief Link a child node to its parent while maintaining sibling order. * * The helper records both first and last child so breadth-first iteration * is cheap when walking the tree later during rendering. * * \param parent Parent object that will receive \p child. * \param child Node to link; ownership is transferred to \p parent. */ static void tplJsonNodeAddChild(struct tplJsonNode *parent, struct tplJsonNode *child) { if (parent == NULL || child == NULL) return; child->parent = parent; child->nextSibling = NULL; if (parent->firstChild == NULL) { parent->firstChild = parent->lastChild = child; } else { parent->lastChild->nextSibling = child; parent->lastChild = child; } } /** * \brief Recursively dispose a JSON node subtree. * * Frees all descendants, the node name buffer, and the node itself. * Safe to call with NULL. * * \param node Root of the subtree to release. */ static void tplJsonNodeFree(struct tplJsonNode *node) { if (node == NULL) return; struct tplJsonNode *child = node->firstChild; while (child != NULL) { struct tplJsonNode *next = child->nextSibling; tplJsonNodeFree(child); child = next; } free(node->name); free(node); } /** * \brief Ensure an object child exists for the given dotted segment. * * Creates an intermediate container when necessary and flags the template * as unsupported if the segment collides with an existing value node. * * \param parent Current node that should hold the container. * \param name Segment name to ensure. * \param nameLen Length of \p name. * \param ppContainer Out parameter receiving the container when found. * \param pUnsupported Set to 1 when the template cannot be expressed. * \retval RS_RET_OK Container exists or was created. * \retval RS_RET_OUT_OF_MEMORY Allocation failed. */ static rsRetVal tplJsonEnsureContainer(struct tplJsonNode *parent, const uchar *name, size_t nameLen, struct tplJsonNode **ppContainer, int *pUnsupported) { struct tplJsonNode *child; if (ppContainer != NULL) *ppContainer = NULL; if (pUnsupported != NULL) *pUnsupported = 0; if (parent == NULL) return RS_RET_ERR; for (child = parent->firstChild; child != NULL; child = child->nextSibling) { if (child->nameLen == nameLen && memcmp(child->name, name, nameLen) == 0) { if (child->type != tplJsonNodeObject) { if (pUnsupported != NULL) *pUnsupported = 1; return RS_RET_OK; } if (ppContainer != NULL) *ppContainer = child; return RS_RET_OK; } } child = tplJsonNodeNew(tplJsonNodeObject, name, nameLen); if (child == NULL) return RS_RET_OUT_OF_MEMORY; tplJsonNodeAddChild(parent, child); if (ppContainer != NULL) *ppContainer = child; return RS_RET_OK; } /** * \brief Attach a value node for a template entry at the current tree level. * * Rejects collisions where an existing object node already occupies the * desired name and propagates an unsupported flag to the caller. * * \param parent Object node receiving the value. * \param pTpe Template entry that supplies the value. * \param name Final path segment for the value. * \param nameLen Length of \p name. * \param pUnsupported Output flag marked when a collision is detected. * \retval RS_RET_OK Value node linked or collision recorded. * \retval RS_RET_OUT_OF_MEMORY Allocation failed. */ static rsRetVal tplJsonAddValueNode( struct tplJsonNode *parent, struct templateEntry *pTpe, const uchar *name, size_t nameLen, int *pUnsupported) { struct tplJsonNode *child; if (pUnsupported != NULL) *pUnsupported = 0; if (parent == NULL) return RS_RET_ERR; for (child = parent->firstChild; child != NULL; child = child->nextSibling) { if (child->nameLen == nameLen && memcmp(child->name, name, nameLen) == 0) { if (child->type == tplJsonNodeObject) { if (pUnsupported != NULL) *pUnsupported = 1; return RS_RET_OK; } child->pTpe = pTpe; return RS_RET_OK; } } child = tplJsonNodeNew(tplJsonNodeValue, name, nameLen); if (child == NULL) return RS_RET_OUT_OF_MEMORY; child->pTpe = pTpe; tplJsonNodeAddChild(parent, child); return RS_RET_OK; } /** * \brief Build the JSON tree representation for a jsonf list template. * * Walks dotted outname segments, creating containers as required and * recording which templates cannot be represented as structured JSON. * * \param pTpl Template to analyse; its tree fields are updated in place. * \retval RS_RET_OK on success or when jsonf is unsupported for the template. * \retval RS_RET_OUT_OF_MEMORY on allocation failure. */ static rsRetVal tplJsonBuildTree(struct template *pTpl) { struct tplJsonNode *root = NULL; struct templateEntry *pTpe; int unsupported = 0; DEFiRet; if (pTpl->bJsonTreeBuilt != TPL_JSON_TREE_NOT_BUILT) RETiRet; CHKmalloc(root = tplJsonNodeNew(tplJsonNodeObject, NULL, 0)); for (pTpe = pTpl->pEntryRoot; pTpe != NULL; pTpe = pTpe->pNext) { if (pTpe->fieldName == NULL || pTpe->lenFieldName == 0) { unsupported = 1; break; } if (pTpe->eEntryType == CONSTANT) { if (!pTpe->data.constant.bJSONf) { unsupported = 1; break; } } else if (pTpe->eEntryType == FIELD) { if (!pTpe->data.field.options.bJSONf && !pTpe->data.field.options.bJSONfr) { unsupported = 1; break; } } else { unsupported = 1; break; } struct tplJsonNode *parent = root; const uchar *segStart = pTpe->fieldName; const uchar *ptr = pTpe->fieldName; const uchar *end = pTpe->fieldName + pTpe->lenFieldName; while (ptr < end) { if (*ptr == '.') { if (ptr == segStart) { unsupported = 1; break; } struct tplJsonNode *container = NULL; const size_t segLen = (size_t)(ptr - segStart); CHKiRet(tplJsonEnsureContainer(parent, segStart, segLen, &container, &unsupported)); if (unsupported) break; parent = container; ++ptr; segStart = ptr; continue; } ++ptr; } if (unsupported) break; const size_t segLen = (size_t)(end - segStart); if (segLen == 0) { unsupported = 1; break; } CHKiRet(tplJsonAddValueNode(parent, pTpe, segStart, segLen, &unsupported)); if (unsupported) break; } if (unsupported) { tplJsonNodeFree(root); pTpl->pJsonRoot = NULL; pTpl->bJsonTreeBuilt = TPL_JSON_TREE_UNSUPPORTED; LogError(0, NO_ERRCODE, "template '%s' with option jsonftree has conflicting keys (e.g. 'a' and 'a.b'); " "falling back to flat JSON output.", pTpl->pszName != NULL ? pTpl->pszName : ""); } else { pTpl->pJsonRoot = root; pTpl->bJsonTreeBuilt = TPL_JSON_TREE_BUILT; } finalize_it: if (iRet != RS_RET_OK) { tplJsonNodeFree(root); } RETiRet; } /** * \brief Render a list template with jsonf option via the pre-built tree. * * Serialises the lazily cached tree into the caller-provided work buffer * producing canonical JSON with nested objects. * * \param pTpl Template to render; must already have a built tree. * \param pMsg Message supplying field data. * \param iparam Worker output buffer descriptor. * \param ttNow Timestamp context for field formatting. * \retval RS_RET_OK on success or an error code from subordinate lookups. */ static rsRetVal tplJsonRender(struct template *pTpl, smsg_t *pMsg, actWrkrIParams_t *iparam, struct syslogTime *ttNow) { es_str_t *out = NULL; char *rendered = NULL; int needComma = 0; DEFiRet; if (pTpl->pJsonRoot == NULL) RETiRet; CHKmalloc(out = es_newStr(128)); es_addChar(&out, '{'); CHKiRet(tplJsonRenderChildren(pTpl->pJsonRoot, pMsg, ttNow, &out, &needComma)); es_addBufConstcstr(&out, "}\n"); const int len = es_strlen(out); if (len < 0) { ABORT_FINALIZE(RS_RET_ERR); } size_t neededLen; CHKiRet(tplAddSize((size_t)len, 1, &neededLen)); if (neededLen > iparam->lenBuf) { CHKiRet(ExtendBuf(iparam, neededLen)); } CHKmalloc(rendered = es_str2cstr(out, NULL)); memcpy(iparam->param, rendered, (size_t)len); iparam->param[len] = '\0'; iparam->lenStr = len; finalize_it: if (rendered != NULL) free(rendered); if (out != NULL) es_deleteStr(out); RETiRet; } /** * \brief Render all children of a JSON node, inserting commas as needed. * * Recursively descends into the tree and appends emitted fragments to the * destination string buffer. * * \param parent Node whose children should be rendered. * \param pMsg Message that provides runtime values. * \param ttNow Timestamp context for property formatting. * \param ppDst Destination string buffer reference. * \param pNeedComma Tracks whether a comma should precede the next child. */ static rsRetVal tplJsonRenderChildren( const struct tplJsonNode *parent, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppDst, int *pNeedComma) { const struct tplJsonNode *child = parent->firstChild; es_str_t *childStr = NULL; int childHasOutput = 0; DEFiRet; while (child != NULL) { childStr = NULL; childHasOutput = 0; CHKiRet(tplJsonRenderNode(child, pMsg, ttNow, &childStr, &childHasOutput)); if (childHasOutput) { if (*pNeedComma) es_addBufConstcstr(ppDst, ", "); es_addStr(ppDst, childStr); *pNeedComma = 1; } if (childStr != NULL) { es_deleteStr(childStr); childStr = NULL; } child = child->nextSibling; } finalize_it: if (childStr != NULL) es_deleteStr(childStr); RETiRet; } /** * \brief Dispatch renderer for a node depending on its type. * * Value nodes are expanded into name/value pairs, while object nodes yield * nested JSON objects. * * \param node Node to render. * \param pMsg Message providing data. * \param ttNow Timestamp context. * \param ppOut Output string produced for this node. * \param pHasOutput Flag indicating whether a value was emitted. */ static rsRetVal tplJsonRenderNode( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput) { if (node->type == tplJsonNodeValue) { return tplJsonRenderValue(node, pMsg, ttNow, ppOut, pHasOutput); } return tplJsonRenderObject(node, pMsg, ttNow, ppOut, pHasOutput); } /** * \brief Render a scalar template entry into a JSON name/value fragment. * * Handles both constant and property-backed entries, including trimming any * legacy jsonf field prefixes and skipping empty expansions. * * \param node Value node describing the template entry. * \param pMsg Message context for property lookups. * \param ttNow Timestamp context. * \param ppOut Newly allocated string with the rendered fragment. * \param pHasOutput Set to 1 if the fragment contains data. */ static rsRetVal tplJsonRenderValue( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput) { uchar *pVal = NULL; rs_size_t lenVal = 0; unsigned short bMustBeFreed = 0; es_str_t *out = NULL; const uchar *valuePtr; size_t valueLen; const uchar *colon; DEFiRet; *ppOut = NULL; *pHasOutput = 0; if (node->pTpe == NULL || node->name == NULL || node->nameLen == 0) RETiRet; if (node->pTpe->eEntryType == CONSTANT) { pVal = node->pTpe->data.constant.pConstant; lenVal = node->pTpe->data.constant.iLenConstant; } else if (node->pTpe->eEntryType == FIELD) { pVal = MsgGetProp(pMsg, node->pTpe, &node->pTpe->data.field.msgProp, &lenVal, &bMustBeFreed, ttNow); } else { RETiRet; } if (pVal == NULL || lenVal <= 0) { FINALIZE; } valuePtr = pVal; valueLen = (size_t)lenVal; colon = memchr(pVal, ':', (size_t)lenVal); if (colon != NULL) { const uchar *keyStart = pVal; const uchar *keyEnd = colon; while (keyStart < colon && isspace((int)*keyStart)) ++keyStart; while (keyEnd > keyStart && isspace((int)*(keyEnd - 1))) --keyEnd; const size_t prefixLen = (size_t)(keyEnd - keyStart); int matchesKey = 0; if (prefixLen >= 2 && keyStart[0] == '"' && keyEnd[-1] == '"' && node->pTpe->fieldName != NULL) { if ((size_t)node->pTpe->lenFieldName == prefixLen - 2 && memcmp(keyStart + 1, node->pTpe->fieldName, node->pTpe->lenFieldName) == 0) { matchesKey = 1; } } if (matchesKey) { size_t offset = (size_t)((colon + 1) - pVal); if (offset >= (size_t)lenVal) { FINALIZE; } valuePtr = pVal + offset; valueLen = (size_t)lenVal - offset; } } if (node->pTpe->eEntryType == FIELD && node->pTpe->data.field.options.dataType == TPE_DATATYPE_NUMBER) { while (valueLen > 0 && isspace((int)*valuePtr)) { ++valuePtr; --valueLen; } while (valueLen > 0 && isspace((int)valuePtr[valueLen - 1])) --valueLen; if (node->pTpe->data.field.options.bOmitIfZero && valueLen == 1 && valuePtr[0] == '0') { FINALIZE; } } if (valueLen == 0) { FINALIZE; } size_t requiredLen; CHKiRet(tplAddSize(node->nameLen, valueLen, &requiredLen)); CHKiRet(tplAddSize(requiredLen, 4, &requiredLen)); if (requiredLen > (size_t)INT_MAX) { parser_errmsg("error: jsonf value to be rendered is too large"); ABORT_FINALIZE(RS_RET_ERR); } CHKmalloc(out = es_newStr((int)requiredLen)); es_addChar(&out, '"'); es_addBuf(&out, (const char *)node->name, node->nameLen); es_addBufConstcstr(&out, "\":"); es_addBuf(&out, (const char *)valuePtr, valueLen); *ppOut = out; out = NULL; *pHasOutput = 1; finalize_it: if (bMustBeFreed && pVal != NULL) free(pVal); if (out != NULL) es_deleteStr(out); RETiRet; } /** * \brief Render an object node and all nested children into JSON. * * Skips empty objects to preserve legacy behaviour while ensuring commas * and braces are placed consistently. * * \param node Object node to render. * \param pMsg Message supplying data for descendants. * \param ttNow Timestamp context. * \param ppOut Output string containing the rendered object. * \param pHasOutput Flag set when the object emitted any fields. */ static rsRetVal tplJsonRenderObject( const struct tplJsonNode *node, smsg_t *pMsg, struct syslogTime *ttNow, es_str_t **ppOut, int *pHasOutput) { es_str_t *out = NULL; es_str_t *childStr = NULL; int needComma = 0; const struct tplJsonNode *child; DEFiRet; *ppOut = NULL; *pHasOutput = 0; if (node->name == NULL || node->nameLen == 0) RETiRet; size_t requiredLen; CHKiRet(tplAddSize(node->nameLen, 5, &requiredLen)); if (requiredLen > (size_t)INT_MAX) { parser_errmsg("error: jsonf object key to be rendered is too large"); ABORT_FINALIZE(RS_RET_ERR); } CHKmalloc(out = es_newStr((int)requiredLen)); es_addChar(&out, '"'); es_addBuf(&out, (const char *)node->name, node->nameLen); es_addBufConstcstr(&out, "\": {"); child = node->firstChild; while (child != NULL) { childStr = NULL; int childHasOutput = 0; CHKiRet(tplJsonRenderNode(child, pMsg, ttNow, &childStr, &childHasOutput)); if (childHasOutput) { if (needComma) es_addBufConstcstr(&out, ", "); es_addStr(&out, childStr); needComma = 1; } if (childStr != NULL) { es_deleteStr(childStr); childStr = NULL; } child = child->nextSibling; } if (!needComma) { FINALIZE; } es_addChar(&out, '}'); *ppOut = out; out = NULL; *pHasOutput = 1; finalize_it: if (childStr != NULL) es_deleteStr(childStr); if (out != NULL) es_deleteStr(out); RETiRet; } static void tplWarnDuplicateJsonKeys(struct template *pTpl) { struct templateEntry *curr; if (pTpl == NULL) return; for (curr = pTpl->pEntryRoot; curr != NULL; curr = curr->pNext) { struct templateEntry *scan; int isJsonField = 0; if (curr->fieldName == NULL || curr->lenFieldName <= 0) continue; if (curr->eEntryType == CONSTANT) { isJsonField = curr->data.constant.bJSONf; } else if (curr->eEntryType == FIELD) { isJsonField = curr->data.field.options.bJSONf || curr->data.field.options.bJSONfr; } if (!isJsonField) continue; for (scan = pTpl->pEntryRoot; scan != curr; scan = scan->pNext) { int scanJsonField = 0; if (scan->fieldName == NULL || scan->lenFieldName <= 0) continue; if (scan->eEntryType == CONSTANT) { scanJsonField = scan->data.constant.bJSONf; } else if (scan->eEntryType == FIELD) { scanJsonField = scan->data.field.options.bJSONf || scan->data.field.options.bJSONfr; } if (!scanJsonField) continue; if (scan->lenFieldName == curr->lenFieldName && memcmp(scan->fieldName, curr->fieldName, curr->lenFieldName) == 0) { LogError(0, NO_ERRCODE, "template '%s': duplicate JSON key '%.*s' encountered; later definition takes precedence", pTpl->pszName != NULL ? pTpl->pszName : "", curr->lenFieldName, curr->fieldName); break; } } } } PRAGMA_IGNORE_Wswitch_enum /* static data */ DEFobjCurrIf(obj) DEFobjCurrIf(strgen) /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfparamdescr[] = {{"name", eCmdHdlrString, 1}, {"type", eCmdHdlrString, 1}, {"string", eCmdHdlrString, 0}, {"plugin", eCmdHdlrString, 0}, {"subtree", eCmdHdlrString, 0}, {"option.stdsql", eCmdHdlrBinary, 0}, {"option.sql", eCmdHdlrBinary, 0}, {"option.json", eCmdHdlrBinary, 0}, {"option.jsonf", eCmdHdlrBinary, 0}, {"option.jsonftree", eCmdHdlrBinary, 0}, {"option.casesensitive", eCmdHdlrBinary, 0}}; static struct cnfparamblk pblk = {CNFPARAMBLK_VERSION, sizeof(cnfparamdescr) / sizeof(struct cnfparamdescr), cnfparamdescr}; static struct cnfparamdescr cnfparamdescrProperty[] = {{"name", eCmdHdlrString, 1}, {"outname", eCmdHdlrString, 0}, {"dateformat", eCmdHdlrString, 0}, {"date.inutc", eCmdHdlrBinary, 0}, {"compressspace", eCmdHdlrBinary, 0}, {"caseconversion", eCmdHdlrString, 0}, {"controlcharacters", eCmdHdlrString, 0}, {"securepath", eCmdHdlrString, 0}, {"format", eCmdHdlrString, 0}, {"position.from", eCmdHdlrInt, 0}, {"position.to", eCmdHdlrInt, 0}, {"position.relativetoend", eCmdHdlrBinary, 0}, {"field.number", eCmdHdlrInt, 0}, {"field.delimiter", eCmdHdlrInt, 0}, {"regex.expression", eCmdHdlrString, 0}, {"regex.type", eCmdHdlrString, 0}, {"regex.nomatchmode", eCmdHdlrString, 0}, {"regex.match", eCmdHdlrInt, 0}, {"regex.submatch", eCmdHdlrInt, 0}, {"droplastlf", eCmdHdlrBinary, 0}, {"fixedwidth", eCmdHdlrBinary, 0}, {"datatype", eCmdHdlrString, 0}, {"onempty", eCmdHdlrString, 0}, {"mandatory", eCmdHdlrBinary, 0}, {"omitifzero", eCmdHdlrBinary, 0}, {"spifno1stsp", eCmdHdlrBinary, 0}}; static struct cnfparamblk pblkProperty = { CNFPARAMBLK_VERSION, sizeof(cnfparamdescrProperty) / sizeof(struct cnfparamdescr), cnfparamdescrProperty}; static struct cnfparamdescr cnfparamdescrConstant[] = { {"value", eCmdHdlrString, 1}, {"format", eCmdHdlrString, 0}, {"outname", eCmdHdlrString, 0}}; static struct cnfparamblk pblkConstant = { CNFPARAMBLK_VERSION, sizeof(cnfparamdescrConstant) / sizeof(struct cnfparamdescr), cnfparamdescrConstant}; #ifdef FEATURE_REGEXP DEFobjCurrIf(regexp) static int bFirstRegexpErrmsg = 1; /**< did we already do a "can't load regexp" error message? */ static rsRetVal tplValidateRegexMatchSelector(struct template *const pTpl, const char *const paramName, const int selector) { if (selector < 0 || selector >= TPL_REGEX_MAX_MATCHES) { LogError(0, RS_RET_ERR, "template %s error: %s=%d is invalid (supported range 0..%d)", pTpl->pszName != NULL ? pTpl->pszName : "", paramName, selector, TPL_REGEX_MAX_MATCHES - 1); return RS_RET_ERR; } return RS_RET_OK; } #endif /* helper to tplToString and strgen's, extends buffer */ #define ALLOC_INC 128 rsRetVal ExtendBuf(actWrkrIParams_t *__restrict__ const iparam, const size_t iMinSize) { uchar *pNewBuf; size_t iNewSize; DEFiRet; if (iMinSize > SIZE_MAX - ALLOC_INC) { parser_errmsg("error: template output buffer size overflow"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iNewSize = (iMinSize / ALLOC_INC + 1) * ALLOC_INC; CHKmalloc(pNewBuf = (uchar *)realloc(iparam->param, iNewSize)); iparam->param = pNewBuf; iparam->lenBuf = iNewSize; finalize_it: RETiRet; } static rsRetVal tplAddSize(const size_t a, const size_t b, size_t *const sum) { if (a > SIZE_MAX - b) { parser_errmsg("error: template size calculation overflow"); return RS_RET_OUT_OF_MEMORY; } *sum = a + b; return RS_RET_OK; } static int tplParseNonNegativeInt(uchar **const pp, int *const out) { uchar *p = *pp; int val = 0; int overflow = 0; while (isdigit((int)*p)) { const int digit = *p++ - '0'; if (val > (INT_MAX - digit) / 10) { overflow = 1; val = INT_MAX; while (isdigit((int)*p)) ++p; break; } val = val * 10 + digit; } *pp = p; *out = val; return overflow; } /* This functions converts a template into a string. * * The function takes a pointer to a template and a pointer to a msg object * as well as a pointer to an output buffer and its size. Note that the output * buffer pointer may be NULL, size 0, in which case a new one is allocated. * The output buffer is grown as required. It is the caller's duty to free the * buffer when it is done. Note that it is advisable to reuse memory, as this * offers big performance improvements. * rewritten 2009-06-19 rgerhards */ rsRetVal tplToString(struct template *__restrict__ const pTpl, smsg_t *__restrict__ const pMsg, actWrkrIParams_t *__restrict__ const iparam, struct syslogTime *const ttNow) { DEFiRet; struct templateEntry *__restrict__ pTpe; size_t iBuf; unsigned short bMustBeFreed = 0; uchar *pVal; rs_size_t iLenVal = 0; int need_comma = 0; if (pTpl->pStrgen != NULL) { CHKiRet(pTpl->pStrgen(pMsg, iparam)); FINALIZE; } if (pTpl->bHaveSubtree) { /* only a single CEE subtree must be provided */ /* note: we could optimize the code below, however, this is * not worth the effort, as this passing mode is not expected * in subtree mode and so most probably only used for debug & test. */ getJSONPropVal(pMsg, &pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed); if (iLenVal < 0) { ABORT_FINALIZE(RS_RET_ERR); } if ((size_t)iLenVal >= iparam->lenBuf) { /* we reserve one char for the final \0! */ size_t neededLen; CHKiRet(tplAddSize((size_t)iLenVal, 1, &neededLen)); CHKiRet(ExtendBuf(iparam, neededLen)); } memcpy(iparam->param, pVal, iLenVal + 1); iparam->lenStr = iLenVal; FINALIZE; } /* we have a "regular" template with template entries */ if (pTpl->optFormatEscape == JSONF && pTpl->bJsonTreeEnabled) { if (pTpl->bJsonTreeBuilt == TPL_JSON_TREE_NOT_BUILT) { CHKiRet(tplJsonBuildTree(pTpl)); } if (pTpl->bJsonTreeBuilt == TPL_JSON_TREE_BUILT && pTpl->pJsonRoot != NULL) { CHKiRet(tplJsonRender(pTpl, pMsg, iparam, ttNow)); FINALIZE; } } /* loop through the template. We obtain one value * and copy it over to our dynamic string buffer. Then, we * free the obtained value (if requested). We continue this * loop until we got hold of all values. */ pTpe = pTpl->pEntryRoot; iBuf = 0; const int isJsonFlat = (pTpl->optFormatEscape == JSONF && (!pTpl->bJsonTreeEnabled || pTpl->bJsonTreeBuilt == TPL_JSON_TREE_UNSUPPORTED)); if (isJsonFlat) { if (iparam->lenBuf < 2) /* we reserve one char for the final \0! */ CHKiRet(ExtendBuf(iparam, 2)); iBuf = 1; *iparam->param = '{'; } while (pTpe != NULL) { if (pTpe->eEntryType == CONSTANT) { pVal = (uchar *)pTpe->data.constant.pConstant; iLenVal = pTpe->data.constant.iLenConstant; bMustBeFreed = 0; } else if (pTpe->eEntryType == FIELD) { pVal = (uchar *)MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp, &iLenVal, &bMustBeFreed, ttNow); if (pVal == NULL) { DBGPRINTF("template property evaluation returned NULL, using empty value\n"); pVal = UCHAR_CONSTANT(""); iLenVal = 0; bMustBeFreed = 0; } /* we now need to check if we should use SQL option. In this case, * we must go over the generated string and escape '\'' characters. * rgerhards, 2005-09-22: the option values below look somewhat misplaced, * but they are handled in this way because of legacy (don't break any * existing thing). */ if (pTpl->optFormatEscape == SQL_ESCAPE) doEscape(&pVal, &iLenVal, &bMustBeFreed, SQL_ESCAPE); else if (pTpl->optFormatEscape == JSON_ESCAPE) doEscape(&pVal, &iLenVal, &bMustBeFreed, JSON_ESCAPE); else if (pTpl->optFormatEscape == STDSQL_ESCAPE) doEscape(&pVal, &iLenVal, &bMustBeFreed, STDSQL_ESCAPE); } else { DBGPRINTF("TplToString: invalid entry type %d\n", pTpe->eEntryType); pVal = (uchar *)"*LOGIC ERROR*"; iLenVal = sizeof("*LOGIC ERROR*") - 1; bMustBeFreed = 0; } /* got source, now copy over */ const int isLastEntry = (pTpe->pNext == NULL); const size_t closingLen = (isJsonFlat && isLastEntry) ? 2 : 0; size_t requiredLen = closingLen; if (iLenVal > 0) { if (need_comma) CHKiRet(tplAddSize(requiredLen, 2, &requiredLen)); CHKiRet(tplAddSize(requiredLen, (size_t)iLenVal, &requiredLen)); } if (requiredLen > 0) { size_t neededLen; CHKiRet(tplAddSize(iBuf, requiredLen, &neededLen)); if (neededLen >= iparam->lenBuf) { CHKiRet(tplAddSize(neededLen, 1, &neededLen)); CHKiRet(ExtendBuf(iparam, neededLen)); } } if (iLenVal > 0) { /* may be zero depending on property */ if (need_comma) { memcpy(iparam->param + iBuf, ", ", 2); iBuf += 2; } memcpy(iparam->param + iBuf, pVal, iLenVal); iBuf += iLenVal; if (isJsonFlat) { need_comma = 1; } } if (closingLen > 0) { memcpy(iparam->param + iBuf, "}\n", 2); iBuf += 2; } if (bMustBeFreed) { free(pVal); bMustBeFreed = 0; } pTpe = pTpe->pNext; } if (iBuf == iparam->lenBuf) { /* in the weired case of an *empty* template, this can happen. * it is debatable if we should really fix it here or simply * forbid that case. However, performance toll is minimal, so * I tend to permit it. -- 2010-11-05 rgerhards */ CHKiRet(ExtendBuf(iparam, iBuf + 1)); } iparam->param[iBuf] = '\0'; iparam->lenStr = iBuf; finalize_it: if (bMustBeFreed) { free(pVal); bMustBeFreed = 0; } RETiRet; } /* This functions converts a template into a json object. * For further general details, see the very similar funtion * tpltoString(). * rgerhards, 2012-08-29 */ rsRetVal tplToJSON(struct template *pTpl, smsg_t *pMsg, struct json_object **pjson, struct syslogTime *ttNow) { struct templateEntry *pTpe; rs_size_t propLen; unsigned short bMustBeFreed; uchar *pVal; struct json_object *json, *jsonf; rsRetVal localRet; DEFiRet; if (pTpl->bHaveSubtree) { if (jsonFind(pMsg, &pTpl->subtree, pjson) != RS_RET_OK) *pjson = NULL; if (*pjson == NULL) { /* we need to have a root object! */ *pjson = json_object_new_object(); } else { json_object_get(*pjson); /* inc refcount */ } FINALIZE; } json = json_object_new_object(); for (pTpe = pTpl->pEntryRoot; pTpe != NULL; pTpe = pTpe->pNext) { if (pTpe->eEntryType == CONSTANT) { if (pTpe->fieldName == NULL) continue; jsonf = json_object_new_string((char *)pTpe->data.constant.pConstant); json_object_object_add(json, (char *)pTpe->fieldName, jsonf); } else if (pTpe->eEntryType == FIELD) { if (pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR || pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR) { localRet = msgGetJSONPropJSON(pMsg, &pTpe->data.field.msgProp, &jsonf); if (localRet == RS_RET_OK) { json_object_object_add(json, (char *)pTpe->fieldName, json_object_get(jsonf)); } else { DBGPRINTF("tplToJSON: error %d looking up property %s\n", localRet, pTpe->fieldName); if (pTpe->data.field.options.bMandatory) { json_object_object_add(json, (char *)pTpe->fieldName, NULL); } } } else { pVal = (uchar *)MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp, &propLen, &bMustBeFreed, ttNow); if (pTpe->data.field.options.bMandatory || propLen > 0) { if (propLen < 0 || propLen == INT_MAX) { ABORT_FINALIZE(RS_RET_ERR); } jsonf = json_object_new_string_len((char *)pVal, propLen + 1); json_object_object_add(json, (char *)pTpe->fieldName, jsonf); } if (bMustBeFreed) { /* json-c makes its own private copy! */ free(pVal); } } } } assert(iRet == RS_RET_OK); *pjson = json; finalize_it: RETiRet; } /* Helper to doEscape. This is called if doEscape * runs out of memory allocating the escaped string. * Then we are in trouble. We can * NOT simply return the unmodified string because this * may cause SQL injection. But we also can not simply * abort the run, this would be a DoS. I think an appropriate * measure is to remove the dangerous \' characters (SQL). We * replace them by \", which will break the message and * signatures eventually present - but this is the * best thing we can do now (or does anybody * have a better idea?). rgerhards 2004-11-23 * added support for escape mode (see doEscape for details). * if mode = SQL_ESCAPE, then backslashes are changed to slashes. * rgerhards 2005-09-22 */ static void doEmergencyEscape(register uchar *p, int mode) { while (*p) { if ((mode == SQL_ESCAPE || mode == STDSQL_ESCAPE) && *p == '\'') { *p = '"'; } else if (mode == JSON_ESCAPE) { if (*p == '"') { *p = '\''; } else if (*p == '\\') { *p = '/'; } } else if ((mode == SQL_ESCAPE) && *p == '\\') { *p = '/'; } ++p; } } /* SQL-Escape a string. Single quotes are found and * replaced by two of them. A new buffer is allocated * for the provided string and the provided buffer is * freed. The length is updated. Parameter pbMustBeFreed * is set to 1 if a new buffer is allocated. Otherwise, * it is left untouched. * -- * We just discovered a security issue. MySQL is so * "smart" to not only support the standard SQL mechanism * for escaping quotes, but to also provide its own (using * c-type syntax with backslashes). As such, it is actually * possible to do sql injection via rsyslogd. The cure is now * to escape backslashes, too. As we have found on the web, some * other databases seem to be similar "smart" (why do we have standards * at all if they are violated without any need???). Even better, MySQL's * smartness depends on config settings. So we add a new option to this * function that allows the caller to select if they want to standard or * "smart" encoding ;) * -- * Parameter "mode" is STDSQL_ESCAPE, SQL_ESCAPE "smart" SQL engines, or * JSON_ESCAPE for everyone requiring escaped JSON (e.g. ElasticSearch). * 2005-09-22 rgerhards */ rsRetVal doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int mode) { DEFiRet; uchar *p = NULL; int iLen; cstr_t *pStrB = NULL; uchar *pszGenerated; assert(pp != NULL); assert(*pp != NULL); assert(pLen != NULL); assert(pbMustBeFreed != NULL); /* first check if we need to do anything at all... */ if (mode == STDSQL_ESCAPE) for (p = *pp; *p && *p != '\''; ++p); else if (mode == SQL_ESCAPE) for (p = *pp; *p && *p != '\'' && *p != '\\'; ++p); else if (mode == JSON_ESCAPE) for (p = *pp; *p && (*p == '"' || *p == '\\'); ++p); /* when we get out of the loop, we are either at the * string terminator or the first character to escape */ if (p && *p == '\0') FINALIZE; /* nothing to do in this case! */ p = *pp; iLen = *pLen; CHKiRet(cstrConstruct(&pStrB)); while (*p) { if ((mode == SQL_ESCAPE || mode == STDSQL_ESCAPE) && *p == '\'') { CHKiRet(cstrAppendChar(pStrB, (mode == STDSQL_ESCAPE) ? '\'' : '\\')); iLen++; /* reflect the extra character */ } else if ((mode == SQL_ESCAPE) && *p == '\\') { CHKiRet(cstrAppendChar(pStrB, '\\')); iLen++; /* reflect the extra character */ } else if ((mode == JSON_ESCAPE) && (*p == '"' || *p == '\\')) { CHKiRet(cstrAppendChar(pStrB, '\\')); iLen++; /* reflect the extra character */ } CHKiRet(cstrAppendChar(pStrB, *p)); ++p; } cstrFinalize(pStrB); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pszGenerated, 0)); if (*pbMustBeFreed) free(*pp); /* discard previous value */ *pp = pszGenerated; *pLen = iLen; *pbMustBeFreed = 1; finalize_it: if (iRet != RS_RET_OK) { doEmergencyEscape(*pp, mode); if (pStrB != NULL) cstrDestruct(&pStrB); } RETiRet; } /* Constructs a template entry object. Returns pointer to it * or NULL (if it fails). Pointer to associated template list entry * must be provided. */ static struct templateEntry *tpeConstruct(struct template *pTpl) { struct templateEntry *pTpe; assert(pTpl != NULL); if ((pTpe = calloc(1, sizeof(struct templateEntry))) == NULL) return NULL; /* basic initialization is done via calloc() - need to * initialize only values != 0. */ if (pTpl->pEntryLast == NULL) { /* we are the first element! */ pTpl->pEntryRoot = pTpl->pEntryLast = pTpe; } else { pTpl->pEntryLast->pNext = pTpe; pTpl->pEntryLast = pTpe; } pTpl->tpenElements++; return (pTpe); } /* Helper function to apply case-sensitivity to templates. */ static void apply_case_sensitivity(struct template *pTpl) { if (pTpl->optCaseSensitive) return; struct templateEntry *pTpe; for (pTpe = pTpl->pEntryRoot; pTpe != NULL; pTpe = pTpe->pNext) { if (pTpe->eEntryType == FIELD) { if (pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR || pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR) { uchar *p; p = pTpe->fieldName; for (; *p; ++p) *p = tolower(*p); p = pTpe->data.field.msgProp.name; for (; *p; ++p) *p = tolower(*p); } } } } /* Constructs a template list object. Returns pointer to it * or NULL (if it fails). */ static struct template *tplConstruct(rsconf_t *conf) { struct template *pTpl; if ((pTpl = calloc(1, sizeof(struct template))) == NULL) return NULL; /* basic initialisation is done via calloc() - need to * initialize only values != 0. */ if (conf->templates.last == NULL) { /* we are the first element! */ conf->templates.root = conf->templates.last = pTpl; } else { conf->templates.last->pNext = pTpl; conf->templates.last = pTpl; } return (pTpl); } /* helper to tplAddLine. Parses a constant and generates * the necessary structure. * Parameter "bDoEscapes" is to support legacy vs. v6+ config system. In * legacy, we must do escapes ourselves, whereas v6+ passes in already * escaped strings (which we are NOT permitted to further escape, this would * cause invalid result strings!). Note: if escapes are not permitted, * quotes (") are just a regular character and do NOT terminate the constant! */ static rsRetVal do_Constant(unsigned char **pp, struct template *pTpl, int bDoEscapes) { register unsigned char *p; cstr_t *pStrB; struct templateEntry *pTpe; int i; DEFiRet; assert(pp != NULL); assert(*pp != NULL); assert(pTpl != NULL); p = *pp; CHKiRet(cstrConstruct(&pStrB)); /* process the message and expand escapes * (additional escapes can be added here if needed) */ while (*p && *p != '%' && !(bDoEscapes && *p == '\"')) { if (bDoEscapes && *p == '\\') { switch (*++p) { case '\0': /* the best we can do - it's invalid anyhow... */ cstrAppendChar(pStrB, *p); break; case 'n': cstrAppendChar(pStrB, '\n'); ++p; break; case 'r': cstrAppendChar(pStrB, '\r'); ++p; break; case '\\': cstrAppendChar(pStrB, '\\'); ++p; break; case '%': cstrAppendChar(pStrB, '%'); ++p; break; case '0': /* numerical escape sequence */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { uchar *numStart = p; if (tplParseNonNegativeInt(&numStart, &i)) { LogError(0, NO_ERRCODE, "template numeric escape value too large, using %d as substitute", UCHAR_MAX); i = UCHAR_MAX; } else if (i > UCHAR_MAX) { i = UCHAR_MAX; } p = numStart; cstrAppendChar(pStrB, i); break; } default: cstrAppendChar(pStrB, *p++); break; } } else cstrAppendChar(pStrB, *p++); } if ((pTpe = tpeConstruct(pTpl)) == NULL) { rsCStrDestruct(&pStrB); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pTpe->eEntryType = CONSTANT; cstrFinalize(pStrB); /* We obtain the length from the counted string object * (before we delete it). Later we might take additional * benefit from the counted string object. * 2005-09-09 rgerhards */ pTpe->data.constant.iLenConstant = rsCStrLen(pStrB); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pTpe->data.constant.pConstant, 0)); *pp = p; finalize_it: RETiRet; } /* Helper that checks to see if a property already has a format * type defined */ static int hasFormat(struct templateEntry *pTpe) { return (pTpe->data.field.options.bCSV || pTpe->data.field.options.bJSON || pTpe->data.field.options.bJSONf || pTpe->data.field.options.bJSONr); } /* Helper to do_Parameter(). This parses the formatting options * specified in a template variable. It returns the passed-in pointer * updated to the next processed character. */ static void doOptions(unsigned char **pp, struct templateEntry *pTpe) { register unsigned char *p; unsigned char Buf[64]; size_t i; assert(pp != NULL); assert(*pp != NULL); assert(pTpe != NULL); p = *pp; while (*p && *p != '%' && *p != ':') { /* outer loop - until end of options */ memset(Buf, 0, sizeof(Buf)); /* silence valgrind warnings */ i = 0; while ((i < sizeof(Buf) - 1) && *p && *p != '%' && *p != ':' && *p != ',') { /* inner loop - until end of ONE option */ Buf[i++] = tolower((int)*p); ++p; } Buf[i] = '\0'; /* terminate */ /* check if we need to skip oversize option */ while (*p && *p != '%' && *p != ':' && *p != ',') ++p; /* just skip */ if (*p == ',') ++p; /* eat ',' */ /* OK, we got the option, so now lets look what * it tells us... */ if (!strcmp((char *)Buf, "date-mysql")) { pTpe->data.field.eDateFormat = tplFmtMySQLDate; } else if (!strcmp((char *)Buf, "date-pgsql")) { pTpe->data.field.eDateFormat = tplFmtPgSQLDate; } else if (!strcmp((char *)Buf, "date-rfc3164")) { pTpe->data.field.eDateFormat = tplFmtRFC3164Date; } else if (!strcmp((char *)Buf, "date-rfc3164-buggyday")) { pTpe->data.field.eDateFormat = tplFmtRFC3164BuggyDate; } else if (!strcmp((char *)Buf, "date-rfc3339")) { pTpe->data.field.eDateFormat = tplFmtRFC3339Date; } else if (!strcmp((char *)Buf, "date-unixtimestamp")) { pTpe->data.field.eDateFormat = tplFmtUnixDate; } else if (!strcmp((char *)Buf, "date-subseconds")) { pTpe->data.field.eDateFormat = tplFmtSecFrac; } else if (!strcmp((char *)Buf, "date-wdayname")) { pTpe->data.field.eDateFormat = tplFmtWDayName; } else if (!strcmp((char *)Buf, "date-wday")) { pTpe->data.field.eDateFormat = tplFmtWDay; } else if (!strcmp((char *)Buf, "date-year")) { pTpe->data.field.eDateFormat = tplFmtYear; } else if (!strcmp((char *)Buf, "date-month")) { pTpe->data.field.eDateFormat = tplFmtMonth; } else if (!strcmp((char *)Buf, "date-day")) { pTpe->data.field.eDateFormat = tplFmtDay; } else if (!strcmp((char *)Buf, "date-hour")) { pTpe->data.field.eDateFormat = tplFmtHour; } else if (!strcmp((char *)Buf, "date-minute")) { pTpe->data.field.eDateFormat = tplFmtMinute; } else if (!strcmp((char *)Buf, "date-second")) { pTpe->data.field.eDateFormat = tplFmtSecond; } else if (!strcmp((char *)Buf, "date-tzoffshour")) { pTpe->data.field.eDateFormat = tplFmtTZOffsHour; } else if (!strcmp((char *)Buf, "date-tzoffsmin")) { pTpe->data.field.eDateFormat = tplFmtTZOffsMin; } else if (!strcmp((char *)Buf, "date-tzoffsdirection")) { pTpe->data.field.eDateFormat = tplFmtTZOffsDirection; } else if (!strcmp((char *)Buf, "date-ordinal")) { pTpe->data.field.eDateFormat = tplFmtOrdinal; } else if (!strcmp((char *)Buf, "date-week")) { pTpe->data.field.eDateFormat = tplFmtWeek; } else if (!strcmp((char *)Buf, "date-iso-week")) { pTpe->data.field.eDateFormat = tplFmtISOWeek; } else if (!strcmp((char *)Buf, "date-iso-week-year")) { pTpe->data.field.eDateFormat = tplFmtISOWeekYear; } else if (!strcmp((char *)Buf, "date-utc")) { pTpe->data.field.options.bDateInUTC = 1; } else if (!strcmp((char *)Buf, "lowercase")) { pTpe->data.field.eCaseConv = tplCaseConvLower; } else if (!strcmp((char *)Buf, "uppercase")) { pTpe->data.field.eCaseConv = tplCaseConvUpper; } else if (!strcmp((char *)Buf, "sp-if-no-1st-sp")) { pTpe->data.field.options.bSPIffNo1stSP = 1; } else if (!strcmp((char *)Buf, "compressspace")) { pTpe->data.field.options.bCompressSP = 1; } else if (!strcmp((char *)Buf, "escape-cc")) { pTpe->data.field.options.bEscapeCC = 1; pTpe->data.field.options.bEscapeCCOctal = 0; pTpe->data.field.options.bDropCC = 0; pTpe->data.field.options.bSpaceCC = 0; } else if (!strcmp((char *)Buf, "drop-cc")) { pTpe->data.field.options.bDropCC = 1; pTpe->data.field.options.bEscapeCC = 0; pTpe->data.field.options.bEscapeCCOctal = 0; pTpe->data.field.options.bSpaceCC = 0; } else if (!strcmp((char *)Buf, "space-cc")) { pTpe->data.field.options.bSpaceCC = 1; pTpe->data.field.options.bEscapeCC = 0; pTpe->data.field.options.bEscapeCCOctal = 0; pTpe->data.field.options.bDropCC = 0; } else if (!strcmp((char *)Buf, "drop-last-lf")) { pTpe->data.field.options.bDropLastLF = 1; } else if (!strcmp((char *)Buf, "secpath-drop")) { pTpe->data.field.options.bSecPathDrop = 1; } else if (!strcmp((char *)Buf, "secpath-replace")) { pTpe->data.field.options.bSecPathReplace = 1; } else if (!strcmp((char *)Buf, "pos-end-relative")) { pTpe->data.field.options.bFromPosEndRelative = 1; } else if (!strcmp((char *)Buf, "fixed-width")) { pTpe->data.field.options.bFixedWidth = 1; } else if (!strcmp((char *)Buf, "csv")) { if (hasFormat(pTpe)) { LogError(0, NO_ERRCODE, "error: can only specify " "one option out of (json, jsonf, jsonr, jsonfr, csv) - csv ignored"); } else { pTpe->data.field.options.bCSV = 1; } } else if (!strcmp((char *)Buf, "json")) { if (hasFormat(pTpe)) { LogError(0, NO_ERRCODE, "error: can only specify " "one option out of (json, jsonf, jsonr, jsonfr, csv) - json ignored"); } else { pTpe->data.field.options.bJSON = 1; } } else if (!strcmp((char *)Buf, "jsonf")) { if (hasFormat(pTpe)) { LogError(0, NO_ERRCODE, "error: can only specify " "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonf ignored"); } else { pTpe->data.field.options.bJSONf = 1; } } else if (!strcmp((char *)Buf, "jsonr")) { if (hasFormat(pTpe)) { LogError(0, NO_ERRCODE, "error: can only specify " "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonr ignored"); } else { pTpe->data.field.options.bJSONr = 1; } } else if (!strcmp((char *)Buf, "jsonfr")) { if (hasFormat(pTpe)) { LogError(0, NO_ERRCODE, "error: can only specify " "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonfr ignored"); } else { pTpe->data.field.options.bJSONfr = 1; } } else if (!strcmp((char *)Buf, "mandatory-field")) { pTpe->data.field.options.bMandatory = 1; } else { LogError(0, NO_ERRCODE, "template error: invalid field option '%s' " "specified - ignored", Buf); } } *pp = p; } /* helper to tplAddLine. Parses a parameter and generates * the necessary structure. */ static rsRetVal do_Parameter(uchar **pp, struct template *pTpl) { uchar *p; cstr_t *pStrProp = NULL; cstr_t *pStrField = NULL; struct templateEntry *pTpe; int iNum; /* to compute numbers */ #ifdef FEATURE_REGEXP /* APR: variables for regex */ rsRetVal iRetLocal; int longitud; unsigned char *regex_char; unsigned char *regex_end; #endif DEFiRet; assert(pp != NULL); assert(*pp != NULL); assert(pTpl != NULL); p = (uchar *)*pp; CHKiRet(cstrConstruct(&pStrProp)); CHKmalloc(pTpe = tpeConstruct(pTpl)); pTpe->eEntryType = FIELD; while (*p && *p != '%' && *p != ':') { cstrAppendChar(pStrProp, *p); ++p; } /* got the name */ cstrFinalize(pStrProp); CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(pStrProp), cstrLen(pStrProp))); /* Check frompos, if it has an R, then topos should be a regex */ if (*p == ':') { pTpe->bComplexProcessing = 1; ++p; /* eat ':' */ #ifdef FEATURE_REGEXP if (*p == 'R') { /* APR: R found! regex alarm ! :) */ ++p; /* eat ':' */ /* first come the regex type */ if (*p == ',') { ++p; /* eat ',' */ if (p[0] == 'B' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) { pTpe->data.field.typeRegex = TPL_REGEX_BRE; p += 3; /* eat indicator sequence */ } else if (p[0] == 'E' && p[1] == 'R' && p[2] == 'E' && (p[3] == ',' || p[3] == ':')) { pTpe->data.field.typeRegex = TPL_REGEX_ERE; p += 3; /* eat indicator sequence */ } else { LogError(0, NO_ERRCODE, "error: invalid regular expression " "type, rest of line %s", (char *)p); } } /* now check for submatch ID */ pTpe->data.field.iSubMatchToUse = 0; if (*p == ',') { /* in this case a number follows, which indicates which match * shall be used. This must be a single digit. */ ++p; /* eat ',' */ if (isdigit((int)*p)) { pTpe->data.field.iSubMatchToUse = *p - '0'; ++p; /* eat digit */ } } /* now pull what to do if we do not find a match */ if (*p == ',') { ++p; /* eat ',' */ if (p[0] == 'D' && p[1] == 'F' && p[2] == 'L' && p[3] == 'T' && (p[4] == ',' || p[4] == ':')) { pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_DFLTSTR; p += 4; /* eat indicator sequence */ } else if (p[0] == 'B' && p[1] == 'L' && p[2] == 'A' && p[3] == 'N' && p[4] == 'K' && (p[5] == ',' || p[5] == ':')) { pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_BLANK; p += 5; /* eat indicator sequence */ } else if (p[0] == 'F' && p[1] == 'I' && p[2] == 'E' && p[3] == 'L' && p[4] == 'D' && (p[5] == ',' || p[5] == ':')) { pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_WHOLE_FIELD; p += 5; /* eat indicator sequence */ } else if (p[0] == 'Z' && p[1] == 'E' && p[2] == 'R' && p[3] == 'O' && (p[4] == ',' || p[4] == ':')) { pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_ZERO; p += 4; /* eat indicator sequence */ } else if (p[0] == ',') { /* empty, use default */ pTpe->data.field.nomatchAction = TPL_REGEX_NOMATCH_USE_DFLTSTR; /* do NOT eat indicator sequence, as this was already eaten - the * comma itself is already part of the next field. */ } else { LogError(0, NO_ERRCODE, "template %s error: invalid regular " "expression type, rest of line %s", pTpl->pszName, (char *)p); } } /* now check for match ID */ pTpe->data.field.iMatchToUse = 0; if (*p == ',') { /* in this case a number follows, which indicates which match * shall be used. This must be a single digit. */ ++p; /* eat ',' */ if (isdigit((int)*p)) { pTpe->data.field.iMatchToUse = *p - '0'; ++p; /* eat digit */ } } if (*p != ':') { /* There is something more than an R , this is invalid ! */ /* Complain on extra characters */ LogError(0, NO_ERRCODE, "error: invalid character in frompos " "after \"R\", property: '%%%s'", (char *)*pp); } else { pTpe->data.field.has_regex = 1; dbgprintf("we have a regexp and use match #%d, submatch #%d\n", pTpe->data.field.iMatchToUse, pTpe->data.field.iSubMatchToUse); } } else { /* now we fall through the "regular" FromPos code */ #endif /* #ifdef FEATURE_REGEXP */ if (*p == 'F') { #ifdef STRICT_GPLV3 pTpe->data.field.field_expand = 0; #endif /* we have a field counter, so indicate it in the template */ ++p; /* eat 'F' */ if (*p == ':') { /* no delimiter specified, so use the default (HT) */ pTpe->data.field.has_fields = 1; pTpe->data.field.field_delim = 9; } else if (*p == ',') { ++p; /* eat ',' */ /* configured delimiter follows, so we need to obtain * it. Important: the following number must be the * **DECIMAL** ASCII value of the delimiter character. */ pTpe->data.field.has_fields = 1; if (!isdigit((int)*p)) { /* complain and use default */ LogError(0, NO_ERRCODE, "error: invalid character in " "frompos after \"F,\", property: '%%%s' - using 9 (HT) as field delimiter", (char *)*pp); pTpe->data.field.field_delim = 9; } else { if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: delimiter value in template is too large - using 9 (HT) as substitute"); iNum = 9; } if (iNum < 0 || iNum > 255) { LogError(0, NO_ERRCODE, "error: non-USASCII delimiter " "character value %d in template - using 9 (HT) as substitute", iNum); pTpe->data.field.field_delim = 9; } else { pTpe->data.field.field_delim = iNum; #ifdef STRICT_GPLV3 if (*p == '+') { pTpe->data.field.field_expand = 1; p++; } #endif if (*p == ',') { /* real fromPos? */ ++p; if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: frompos value in template is too large - using %d", INT_MAX); } pTpe->data.field.iFromPos = iNum; } else if (*p != ':') { parser_errmsg( "error: invalid character " "'%c' in frompos after \"F,\", property: '%s' " "be sure to use DECIMAL character " "codes!", *p, (char *)*pp); ABORT_FINALIZE(RS_RET_SYNTAX_ERROR); } } } } else { /* invalid character after F, so we need to reject * this. */ LogError(0, NO_ERRCODE, "error: invalid character in frompos " "after \"F\", property: '%%%s'", (char *)*pp); } } else { /* we now have a simple offset in frompos (the previously "normal" case) */ if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: frompos value in template is too large - using %d", INT_MAX); } pTpe->data.field.iFromPos = iNum; /* skip to next known good */ while (*p && *p != '%' && *p != ':') { /* TODO: complain on extra characters */ dbgprintf("error: extra character in frompos: '%s'\n", p); ++p; } } #ifdef FEATURE_REGEXP } #endif /* #ifdef FEATURE_REGEXP */ } /* check topos (holds an regex if FromPos is "R"*/ if (*p == ':') { ++p; /* eat ':' */ #ifdef FEATURE_REGEXP if (pTpe->data.field.has_regex) { dbgprintf("debug: has regex \n"); /* APR 2005-09 I need the string that represent the regex */ /* The regex end is: "--end" */ /* TODO : this is hardcoded and cant be escaped, please change */ regex_end = (unsigned char *)strstr((char *)p, "--end"); if (regex_end == NULL) { dbgprintf("error: can not find regex end in: '%s'\n", p); pTpe->data.field.has_regex = 0; } else { /* We get here ONLY if the regex end was found */ longitud = regex_end - p; /* Malloc for the regex string */ regex_char = (unsigned char *)malloc(longitud + 1); if (regex_char == NULL) { dbgprintf("Could not allocate memory for template parameter!\n"); pTpe->data.field.has_regex = 0; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* Get the regex string for compiling later */ memcpy(regex_char, p, longitud); regex_char[longitud] = '\0'; dbgprintf("debug: regex detected: '%s'\n", regex_char); /* Now i compile the regex */ /* Remember that the re is an attribute of the Template entry */ if ((iRetLocal = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) { int iOptions; iOptions = (pTpe->data.field.typeRegex == TPL_REGEX_ERE) ? REG_EXTENDED : 0; int errcode; if ((errcode = regexp.regcomp(&(pTpe->data.field.re), (char *)regex_char, iOptions)) != 0) { char errbuff[512]; regexp.regerror(errcode, &(pTpe->data.field.re), errbuff, sizeof(errbuff)); DBGPRINTF("Template.c: Error in regular expression: %s\n", errbuff); pTpe->data.field.has_regex = 2; } } else { /* regexp object could not be loaded */ dbgprintf( "error %d trying to load regexp library - this may be desired " "and thus OK", iRetLocal); if (bFirstRegexpErrmsg) { /* prevent flood of messages, maybe even an endless loop! */ bFirstRegexpErrmsg = 0; LogError(0, NO_ERRCODE, "regexp library could not be loaded " "(error %d), regexp ignored", iRetLocal); } pTpe->data.field.has_regex = 2; } /* Finally we move the pointer to the end of the regex * so it aint parsed twice or something weird */ p = regex_end + 5 /*strlen("--end")*/; free(regex_char); } } else if (*p == '$') { /* shortcut for "end of message */ p++; /* eat '$' */ /* in this case, we do a quick, somewhat dirty but totally * legitimate trick: we simply use a topos that is higher than * potentially ever can happen. The code below checks that no copy * will occur after the end of string, so this is perfectly legal. * rgerhards, 2006-10-17 */ pTpe->data.field.iToPos = 9999999; } else { /* fallthrough to "regular" ToPos code */ #endif /* #ifdef FEATURE_REGEXP */ if (pTpe->data.field.has_fields == 1) { if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: field number in template is too large - using %d", INT_MAX); } pTpe->data.field.iFieldNr = iNum; if (*p == ',') { /* get real toPos? */ ++p; if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: topos value in template is too large - using %d", INT_MAX); } pTpe->data.field.iToPos = iNum; } } else { if (tplParseNonNegativeInt(&p, &iNum)) { LogError(0, NO_ERRCODE, "error: topos value in template is too large - using %d", INT_MAX); } pTpe->data.field.iToPos = iNum; } /* skip to next known good */ while (*p && *p != '%' && *p != ':') { /* TODO: complain on extra characters */ dbgprintf("error: extra character in frompos: '%s'\n", p); ++p; } #ifdef FEATURE_REGEXP } #endif /* #ifdef FEATURE_REGEXP */ } /* check options */ if (*p == ':') { ++p; /* eat ':' */ doOptions(&p, pTpe); } if (pTpe->data.field.options.bFromPosEndRelative) { if (pTpe->data.field.iToPos > pTpe->data.field.iFromPos) { iNum = pTpe->data.field.iToPos; pTpe->data.field.iToPos = pTpe->data.field.iFromPos; pTpe->data.field.iFromPos = iNum; } } else { if (pTpe->data.field.iToPos < pTpe->data.field.iFromPos) { iNum = pTpe->data.field.iToPos; pTpe->data.field.iToPos = pTpe->data.field.iFromPos; pTpe->data.field.iFromPos = iNum; } } /* check field name */ if (*p == ':') { ++p; /* eat ':' */ CHKiRet(cstrConstruct(&pStrField)); while (*p != ':' && *p != '%' && *p != '\0') { cstrAppendChar(pStrField, *p); ++p; } cstrFinalize(pStrField); } /* save field name - if none was given, use the property name instead */ if (pStrField == NULL) { if (pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) { /* in CEE case, we remove "$!"/"$." from the fieldname - it's just our indicator */ pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp) + 2); pTpe->lenFieldName = cstrLen(pStrProp) - 2; } else { pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp)); pTpe->lenFieldName = cstrLen(pStrProp); } } else { pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrField)); pTpe->lenFieldName = ustrlen(pTpe->fieldName); cstrDestruct(&pStrField); } if (pTpe->fieldName == NULL) { DBGPRINTF("template/do_Parameter: fieldName is NULL!\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (*p) ++p; /* eat '%' */ *pp = p; finalize_it: if (pStrProp != NULL) cstrDestruct(&pStrProp); RETiRet; } /* Add a new entry for a template module. * returns pointer to new object if it succeeds, NULL otherwise. * rgerhards, 2010-05-31 */ static rsRetVal tplAddTplMod(struct template *pTpl, uchar **ppRestOfConfLine) { uchar *pSrc; uchar szMod[2048]; unsigned lenMod; strgen_t *pStrgen; DEFiRet; pSrc = *ppRestOfConfLine; lenMod = 0; while (*pSrc && !isspace(*pSrc) && lenMod < sizeof(szMod) - 1) { szMod[lenMod] = *pSrc++; lenMod++; } szMod[lenMod] = '\0'; *ppRestOfConfLine = pSrc; CHKiRet(strgen.FindStrgen(&pStrgen, szMod)); pTpl->pStrgen = pStrgen->pModule->mod.sm.strgen; DBGPRINTF("template bound to strgen '%s'\n", szMod); /* check if the name potentially contains some well-known options * Note: we have opted to let the name contain all options. This sounds * useful, because the strgen MUST actually implement a specific set * of options. Doing this via the name looks to the enduser as if the * regular syntax were used, and it make sure the strgen postively * acknowledged implementing the option. -- rgerhards, 2011-03-21 */ if (lenMod > 6 && !strcasecmp((char *)szMod + lenMod - 7, ",stdsql")) { pTpl->optFormatEscape = STDSQL_ESCAPE; DBGPRINTF("strgen supports the stdsql option\n"); } else if (lenMod > 3 && !strcasecmp((char *)szMod + lenMod - 4, ",sql")) { pTpl->optFormatEscape = SQL_ESCAPE; DBGPRINTF("strgen supports the sql option\n"); } else if (lenMod > 4 && !strcasecmp((char *)szMod + lenMod - 4, ",json")) { pTpl->optFormatEscape = JSON_ESCAPE; DBGPRINTF("strgen supports the json option\n"); } finalize_it: RETiRet; } /* Add a new template line * returns pointer to new object if it succeeds, NULL otherwise. */ struct template *tplAddLine(rsconf_t *conf, const char *pName, uchar **ppRestOfConfLine) { struct template *pTpl; unsigned char *p; int bDone; size_t i; rsRetVal localRet; assert(pName != NULL); assert(ppRestOfConfLine != NULL); if ((pTpl = tplConstruct(conf)) == NULL) return NULL; DBGPRINTF("tplAddLine processing template '%s'\n", pName); pTpl->iLenName = strlen(pName); pTpl->pszName = (char *)malloc(pTpl->iLenName + 1); if (pTpl->pszName == NULL) { dbgprintf("tplAddLine could not alloc memory for template name!"); pTpl->iLenName = 0; return NULL; /* I know - we create a memory leak here - but I deem * it acceptable as it is a) a very small leak b) very * unlikely to happen. rgerhards 2004-11-17 */ } memcpy(pTpl->pszName, pName, pTpl->iLenName + 1); /* now actually parse the line */ p = *ppRestOfConfLine; assert(p != NULL); while (isspace((int)*p)) /* skip whitespace */ ++p; switch (*p) { case '"': /* just continue */ break; case '=': *ppRestOfConfLine = p + 1; localRet = tplAddTplMod(pTpl, ppRestOfConfLine); if (localRet != RS_RET_OK) { LogError(0, localRet, "Template '%s': error %d defining template via strgen module", pTpl->pszName, localRet); /* we simply make the template defunct in this case by setting * its name to a zero-string. We do not free it, as this would * require additional code and causes only a very small memory * consumption. Memory is freed, however, in normal operation * and most importantly by HUPing syslogd. */ *pTpl->pszName = '\0'; } return NULL; default: dbgprintf("Template '%s' invalid, does not start with '\"'!\n", pTpl->pszName); /* we simply make the template defunct in this case by setting * its name to a zero-string. We do not free it, as this would * require additional code and causes only a very small memory * consumption. */ *pTpl->pszName = '\0'; return NULL; } ++p; /* we finally go to the actual template string - so let's have some fun... */ bDone = *p ? 0 : 1; while (!bDone) { switch (*p) { case '\0': bDone = 1; break; case '%': /* parameter */ ++p; /* eat '%' */ if (do_Parameter(&p, pTpl) != RS_RET_OK) { dbgprintf("tplAddLine error: parameter invalid"); return NULL; }; break; default: /* constant */ do_Constant(&p, pTpl, 1); break; } if (*p == '"') { /* end of template string? */ ++p; /* eat it! */ bDone = 1; } } /* we now have the template - let's look at the options (if any) * we process options until we reach the end of the string or * an error occurs - whichever is first. */ while (*p) { while (isspace((int)*p)) /* skip whitespace */ ++p; if (*p != ',') break; ++p; /* eat ',' */ while (isspace((int)*p)) /* skip whitespace */ ++p; /* read option word */ char optBuf[128] = {'\0'}; /* buffer for options - should be more than enough... */ i = 0; while ((i < (sizeof(optBuf) - 1)) && *p && *p != '=' && *p != ',' && *p != '\n') { optBuf[i++] = tolower((int)*p); ++p; } optBuf[i] = '\0'; if (*p == '\n') ++p; /* as of now, the no form is nonsense... but I do include * it anyhow... ;) rgerhards 2004-11-22 */ if (!strcmp(optBuf, "stdsql")) { pTpl->optFormatEscape = STDSQL_ESCAPE; } else if (!strcmp(optBuf, "json")) { pTpl->optFormatEscape = JSON_ESCAPE; } else if (!strcmp(optBuf, "sql")) { pTpl->optFormatEscape = SQL_ESCAPE; } else if (!strcmp(optBuf, "nosql")) { pTpl->optFormatEscape = NO_ESCAPE; } else if (!strcmp(optBuf, "casesensitive")) { pTpl->optCaseSensitive = 1; } else if (!strcmp(optBuf, "jsonf")) { pTpl->optFormatEscape = JSONF; pTpl->bJsonTreeEnabled = 0; } else if (!strcmp(optBuf, "jsonftree")) { pTpl->optFormatEscape = JSONF; pTpl->bJsonTreeEnabled = 1; } else { dbgprintf("Invalid option '%s' ignored.\n", optBuf); } } *ppRestOfConfLine = p; apply_case_sensitivity(pTpl); if (pTpl->optFormatEscape == JSONF) tplWarnDuplicateJsonKeys(pTpl); return (pTpl); } static rsRetVal createConstantTpe(struct template *pTpl, struct cnfobj *o) { struct templateEntry *pTpe; es_str_t *value = NULL; /* init just to keep compiler happy - mandatory parameter */ int i; int is_jsonf = 0; struct cnfparamvals *pvals = NULL; struct json_object *json = NULL; struct json_object *jval = NULL; uchar *outname = NULL; const char *sz = NULL; DEFiRet; /* pull params */ pvals = nvlstGetParams(o->nvlst, &pblkConstant, NULL); if (pvals == NULL) { parser_errmsg("error processing template parameters"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } cnfparamsPrint(&pblkConstant, pvals); for (i = 0; i < pblkConstant.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblkConstant.descr[i].name, "value")) { value = pvals[i].val.d.estr; } else if (!strcmp(pblkConstant.descr[i].name, "outname")) { CHKmalloc(outname = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblkConstant.descr[i].name, "format")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"jsonf", sizeof("jsonf") - 1)) { is_jsonf = 1; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid format type '%s' for constant", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else { LogError(0, RS_RET_INTERNAL_ERROR, "template:constantTpe: program error, non-handled " "param '%s'\n", pblkConstant.descr[i].name); } } if (is_jsonf && outname == NULL) { parser_errmsg("constant set to format jsonf, but outname not specified - aborting"); ABORT_FINALIZE(RS_RET_ERR); } /* just double-check */ assert(value != NULL); if (value == NULL) { parser_errmsg("constant template entry is missing mandatory value parameter"); ABORT_FINALIZE(RS_RET_ERR); } /* apply */ CHKmalloc(pTpe = tpeConstruct(pTpl)); es_unescapeStr(value); pTpe->eEntryType = CONSTANT; pTpe->fieldName = outname; if (outname != NULL) pTpe->lenFieldName = ustrlen(outname); pTpe->data.constant.bJSONf = is_jsonf; if (is_jsonf) { json = json_object_new_object(); CHKmalloc(json); CHKmalloc(sz = es_str2cstr(value, NULL)); jval = json_object_new_string(sz); if (jval == NULL) { free((void *)sz); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } free((void *)sz); json_object_object_add(json, (char *)outname, jval); const char *jsonStr = json_object_get_string(json); CHKmalloc(jsonStr); const size_t jsonLen = strlen(jsonStr); if (jsonLen < 2) { parser_errmsg("error: failed to serialize jsonf constant"); ABORT_FINALIZE(RS_RET_ERR); } const size_t fragmentLen = jsonLen - 2; uchar *fragment = (uchar *)strndup(jsonStr + 1, fragmentLen); CHKmalloc(fragment); size_t fragLen = ustrlen(fragment); while (fragLen > 0 && isspace((int)fragment[fragLen - 1])) { --fragLen; } fragment[fragLen] = '\0'; size_t lead = 0; while (lead < fragLen && isspace((int)fragment[lead])) ++lead; if (lead > 0) { memmove(fragment, fragment + lead, fragLen - lead + 1); fragLen -= lead; } pTpe->data.constant.pConstant = fragment; pTpe->data.constant.iLenConstant = fragLen; json_object_put(json); json = NULL; } else { pTpe->data.constant.iLenConstant = es_strlen(value); CHKmalloc(pTpe->data.constant.pConstant = (uchar *)es_str2cstr(value, NULL)); } finalize_it: if (json != NULL) json_object_put(json); if (pvals != NULL) cnfparamvalsDestruct(pvals, &pblkConstant); RETiRet; } static rsRetVal createPropertyTpe(struct template *pTpl, struct cnfobj *o) { struct templateEntry *pTpe; uchar *name = NULL; uchar *outname = NULL; int i; int droplastlf = 0; int spifno1stsp = 0; int mandatory = 0; int omitifzero = 0; int frompos = -1; int topos = 0; int topos_set = 0; int fieldnum = -1; int fielddelim = 9; /* default is HT (USACSII 9) */ int fixedwidth = 0; int re_matchToUse = 0; int re_submatchToUse = 0; int bComplexProcessing = 0; int bPosRelativeToEnd = 0; int bDateInUTC = 0; int bCompressSP = 0; unsigned dataType = TPE_DATATYPE_STRING; unsigned onEmpty = TPE_DATAEMPTY_KEEP; char *re_expr = NULL; struct cnfparamvals *pvals = NULL; enum { F_NONE, F_CSV, F_JSON, F_JSONF, F_JSONR, F_JSONFR } formatType = F_NONE; enum { CC_NONE, CC_ESCAPE, CC_ESCAPE_OCTAL, CC_SPACE, CC_DROP } controlchr = CC_NONE; enum { SP_NONE, SP_DROP, SP_REPLACE } secpath = SP_NONE; enum tplFormatCaseConvTypes caseconv = tplCaseConvNo; enum tplFormatTypes datefmt = tplFmtDefault; enum tplRegexType re_type = TPL_REGEX_BRE; enum tlpRegexNoMatchType re_nomatchType = TPL_REGEX_NOMATCH_USE_DFLTSTR; DEFiRet; /* pull params */ pvals = nvlstGetParams(o->nvlst, &pblkProperty, NULL); if (pvals == NULL) { parser_errmsg("error processing template entry config parameters"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } cnfparamsPrint(&pblkProperty, pvals); for (i = 0; i < pblkProperty.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblkProperty.descr[i].name, "name")) { CHKmalloc(name = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblkProperty.descr[i].name, "datatype")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"string", sizeof("string") - 1)) { dataType = TPE_DATATYPE_STRING; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"number", sizeof("number") - 1)) { dataType = TPE_DATATYPE_NUMBER; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"bool", sizeof("bool") - 1)) { dataType = TPE_DATATYPE_BOOL; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"auto", sizeof("auto") - 1)) { dataType = TPE_DATATYPE_AUTO; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid dataType '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "onempty")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"keep", sizeof("keep") - 1)) { onEmpty = TPE_DATAEMPTY_KEEP; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"skip", sizeof("skip") - 1)) { onEmpty = TPE_DATAEMPTY_SKIP; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"null", sizeof("null") - 1)) { onEmpty = TPE_DATAEMPTY_NULL; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid onEmpty value '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "droplastlf")) { droplastlf = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "fixedwidth")) { fixedwidth = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "mandatory")) { mandatory = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "omitifzero")) { omitifzero = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "spifno1stsp")) { spifno1stsp = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "outname")) { CHKmalloc(outname = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblkProperty.descr[i].name, "position.from")) { frompos = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "position.to")) { topos = pvals[i].val.d.n; topos_set = 1; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "position.relativetoend")) { bPosRelativeToEnd = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "field.number")) { fieldnum = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "field.delimiter")) { fielddelim = pvals[i].val.d.n; bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "regex.expression")) { CHKmalloc(re_expr = es_str2cstr(pvals[i].val.d.estr, NULL)); bComplexProcessing = 1; } else if (!strcmp(pblkProperty.descr[i].name, "regex.type")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"BRE", sizeof("BRE") - 1)) { re_type = TPL_REGEX_BRE; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"ERE", sizeof("ERE") - 1)) { re_type = TPL_REGEX_ERE; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid regex.type '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "regex.nomatchmode")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"DFLT", sizeof("DFLT") - 1)) { re_nomatchType = TPL_REGEX_NOMATCH_USE_DFLTSTR; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"BLANK", sizeof("BLANK") - 1)) { re_nomatchType = TPL_REGEX_NOMATCH_USE_BLANK; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"FIELD", sizeof("FIELD") - 1)) { re_nomatchType = TPL_REGEX_NOMATCH_USE_WHOLE_FIELD; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"ZERO", sizeof("ZERO") - 1)) { re_nomatchType = TPL_REGEX_NOMATCH_USE_ZERO; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid format type '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "regex.match")) { bComplexProcessing = 1; re_matchToUse = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "regex.submatch")) { bComplexProcessing = 1; re_submatchToUse = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "format")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"csv", sizeof("csv") - 1)) { formatType = F_CSV; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"json", sizeof("json") - 1)) { formatType = F_JSON; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"jsonf", sizeof("jsonf") - 1)) { formatType = F_JSONF; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"jsonr", sizeof("jsonr") - 1)) { formatType = F_JSONR; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"jsonfr", sizeof("jsonfr") - 1)) { formatType = F_JSONFR; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid format type '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "controlcharacters")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"escape", sizeof("escape") - 1)) { controlchr = CC_ESCAPE; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"escape-octal", sizeof("escape-octal") - 1)) { controlchr = CC_ESCAPE_OCTAL; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"space", sizeof("space") - 1)) { controlchr = CC_SPACE; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"drop", sizeof("drop") - 1)) { controlchr = CC_DROP; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid controlcharacter mode '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "securepath")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"drop", sizeof("drop") - 1)) { secpath = SP_DROP; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"replace", sizeof("replace") - 1)) { secpath = SP_REPLACE; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid securepath mode '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "caseconversion")) { bComplexProcessing = 1; if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"lower", sizeof("lower") - 1)) { caseconv = tplCaseConvLower; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"upper", sizeof("upper") - 1)) { caseconv = tplCaseConvUpper; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid caseconversion type '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblkProperty.descr[i].name, "compressspace")) { bComplexProcessing = 1; bCompressSP = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "date.inutc")) { bDateInUTC = pvals[i].val.d.n; } else if (!strcmp(pblkProperty.descr[i].name, "dateformat")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"mysql", sizeof("mysql") - 1)) { datefmt = tplFmtMySQLDate; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"pgsql", sizeof("pgsql") - 1)) { datefmt = tplFmtPgSQLDate; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"rfc3164", sizeof("rfc3164") - 1)) { datefmt = tplFmtRFC3164Date; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"rfc3164-buggyday", sizeof("rfc3164-buggyday") - 1)) { datefmt = tplFmtRFC3164BuggyDate; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"rfc3339", sizeof("rfc3339") - 1)) { datefmt = tplFmtRFC3339Date; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"unixtimestamp", sizeof("unixtimestamp") - 1)) { datefmt = tplFmtUnixDate; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"subseconds", sizeof("subseconds") - 1)) { datefmt = tplFmtSecFrac; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"wdayname", sizeof("wdayname") - 1)) { datefmt = tplFmtWDayName; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"wday", sizeof("wday") - 1)) { datefmt = tplFmtWDay; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"year", sizeof("year") - 1)) { datefmt = tplFmtYear; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"month", sizeof("month") - 1)) { datefmt = tplFmtMonth; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"day", sizeof("day") - 1)) { datefmt = tplFmtDay; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"hour", sizeof("hour") - 1)) { datefmt = tplFmtHour; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"minute", sizeof("minute") - 1)) { datefmt = tplFmtMinute; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"second", sizeof("second") - 1)) { datefmt = tplFmtSecond; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"tzoffshour", sizeof("tzoffshour") - 1)) { datefmt = tplFmtTZOffsHour; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"tzoffsmin", sizeof("tzoffsmin") - 1)) { datefmt = tplFmtTZOffsMin; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"tzoffsdirection", sizeof("tzoffsdirection") - 1)) { datefmt = tplFmtTZOffsDirection; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"ordinal", sizeof("ordinal") - 1)) { datefmt = tplFmtOrdinal; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"week", sizeof("week") - 1)) { datefmt = tplFmtWeek; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid date format '%s' for property", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else { dbgprintf( "template:propertyTpe: program error, non-handled " "param '%s'\n", pblkProperty.descr[i].name); } } if (name == NULL) { CHKmalloc(name = (uchar *)strdup("")); } if (outname == NULL) { /* we need to drop "$!" prefix, if present */ if (ustrlen(name) >= 2 && !strncmp((char *)name, "$!", 2)) outname = ustrdup(name + 2); else outname = ustrdup(name); } /* sanity check */ if (topos_set == 0 && frompos != -1) topos = 2000000000; /* large enough ;) */ if (frompos == -1 && topos_set != 0) frompos = 0; if (bPosRelativeToEnd) { if (topos > frompos) { LogError(0, RS_RET_ERR, "position.to=%d is higher than postion.from=%d " "in 'relativeToEnd' mode\n", topos, frompos); ABORT_FINALIZE(RS_RET_ERR); } } else { if ((topos >= 0) && (topos < frompos)) { LogError(0, RS_RET_ERR, "position.to=%d is lower than postion.from=%d\n", topos, frompos); ABORT_FINALIZE(RS_RET_ERR); } } if (fieldnum != -1 && re_expr != NULL) { LogError(0, RS_RET_ERR, "both field extraction and regex extraction " "specified - this is not possible, remove one"); ABORT_FINALIZE(RS_RET_ERR); } #ifdef FEATURE_REGEXP if (re_expr != NULL) { CHKiRet(tplValidateRegexMatchSelector(pTpl, "regex.match", re_matchToUse)); CHKiRet(tplValidateRegexMatchSelector(pTpl, "regex.submatch", re_submatchToUse)); } #endif /* apply */ CHKmalloc(pTpe = tpeConstruct(pTpl)); pTpe->eEntryType = FIELD; CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, name, strlen((char *)name))); pTpe->data.field.options.bDropLastLF = droplastlf; pTpe->data.field.options.bSPIffNo1stSP = spifno1stsp; pTpe->data.field.options.bMandatory = mandatory; pTpe->data.field.options.bOmitIfZero = omitifzero; pTpe->data.field.options.bFixedWidth = fixedwidth; pTpe->data.field.options.dataType = dataType; pTpe->data.field.options.onEmpty = onEmpty; pTpe->data.field.eCaseConv = caseconv; switch (formatType) { case F_NONE: /* all set ;) */ break; case F_CSV: pTpe->data.field.options.bCSV = 1; break; case F_JSON: pTpe->data.field.options.bJSON = 1; break; case F_JSONF: pTpe->data.field.options.bJSONf = 1; break; case F_JSONR: pTpe->data.field.options.bJSONr = 1; break; case F_JSONFR: pTpe->data.field.options.bJSONfr = 1; break; default: // No action needed for other cases break; } switch (controlchr) { case CC_NONE: /* all set ;) */ break; case CC_ESCAPE: pTpe->data.field.options.bEscapeCC = 1; break; case CC_ESCAPE_OCTAL: pTpe->data.field.options.bEscapeCCOctal = 1; break; case CC_SPACE: pTpe->data.field.options.bSpaceCC = 1; break; case CC_DROP: pTpe->data.field.options.bDropCC = 1; break; default: // No action needed for other cases break; } switch (secpath) { case SP_NONE: /* all set ;) */ break; case SP_DROP: pTpe->data.field.options.bSecPathDrop = 1; break; case SP_REPLACE: pTpe->data.field.options.bSecPathReplace = 1; break; default: // No action needed for other cases break; } pTpe->fieldName = outname; if (outname != NULL) pTpe->lenFieldName = ustrlen(outname); outname = NULL; pTpe->bComplexProcessing = bComplexProcessing; pTpe->data.field.eDateFormat = datefmt; pTpe->data.field.options.bDateInUTC = bDateInUTC; pTpe->data.field.options.bCompressSP = bCompressSP; if (fieldnum != -1) { pTpe->data.field.has_fields = 1; pTpe->data.field.iFieldNr = fieldnum; pTpe->data.field.field_delim = fielddelim; } if (frompos != -1) { pTpe->data.field.iFromPos = frompos; pTpe->data.field.iToPos = topos; pTpe->data.field.options.bFromPosEndRelative = bPosRelativeToEnd; } if (re_expr != NULL) { rsRetVal iRetLocal; pTpe->data.field.typeRegex = re_type; pTpe->data.field.nomatchAction = re_nomatchType; pTpe->data.field.iMatchToUse = re_matchToUse; pTpe->data.field.iSubMatchToUse = re_submatchToUse; pTpe->data.field.has_regex = 1; if ((iRetLocal = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) { int iOptions; iOptions = (pTpe->data.field.typeRegex == TPL_REGEX_ERE) ? REG_EXTENDED : 0; if (regexp.regcomp(&(pTpe->data.field.re), (char *)re_expr, iOptions) != 0) { LogError(0, NO_ERRCODE, "error compiling regex '%s'", re_expr); pTpe->data.field.has_regex = 2; ABORT_FINALIZE(RS_RET_ERR); } } else { /* regexp object could not be loaded */ if (bFirstRegexpErrmsg) { /* prevent flood of messages, maybe even an endless loop! */ bFirstRegexpErrmsg = 0; LogError(0, NO_ERRCODE, "regexp library could not be loaded (error %d), " "regexp ignored", iRetLocal); } pTpe->data.field.has_regex = 2; ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &pblkProperty); free(name); free(outname); free(re_expr); RETiRet; } /* create a template in list mode, is build from sub-objects */ static rsRetVal createListTpl(struct template *pTpl, struct cnfobj *o) { struct objlst *lst; DEFiRet; dbgprintf("create template from subobjs\n"); objlstPrint(o->subobjs); for (lst = o->subobjs; lst != NULL; lst = lst->next) { switch (lst->obj->objType) { case CNFOBJ_PROPERTY: CHKiRet(createPropertyTpe(pTpl, lst->obj)); break; case CNFOBJ_CONSTANT: CHKiRet(createConstantTpe(pTpl, lst->obj)); break; default: dbgprintf( "program error: invalid object type %d " "in createLstTpl\n", lst->obj->objType); break; } nvlstChkUnused(lst->obj->nvlst); } finalize_it: RETiRet; } /* Add a new template via the v6 config system. */ rsRetVal ATTR_NONNULL() tplProcessCnf(struct cnfobj *o) { struct template *pTpl = NULL; struct cnfparamvals *pvals = NULL; int lenName = 0; /* init just to keep compiler happy: mandatory parameter */ char *name = NULL; uchar *tplStr = NULL; uchar *plugin = NULL; uchar *p; msgPropDescr_t subtree; sbool bHaveSubtree = 0; enum { T_STRING, T_PLUGIN, T_LIST, T_SUBTREE } tplType = T_STRING; /* init just to keep compiler happy: mandatory parameter */ int i; int o_sql = 0, o_stdsql = 0, o_jsonf = 0, o_jsonftree = 0, o_json = 0, o_casesensitive = 0; /* options */ int numopts; rsRetVal localRet; uchar *cstr = NULL; DEFiRet; pvals = nvlstGetParams(o->nvlst, &pblk, NULL); if (pvals == NULL) { parser_errmsg("error processing template config parameters"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } cnfparamsPrint(&pblk, pvals); for (i = 0; i < pblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblk.descr[i].name, "name")) { lenName = es_strlen(pvals[i].val.d.estr); CHKmalloc(name = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "type")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"string", sizeof("string") - 1)) { tplType = T_STRING; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"plugin", sizeof("plugin") - 1)) { tplType = T_PLUGIN; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"list", sizeof("list") - 1)) { tplType = T_LIST; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"subtree", sizeof("subtree") - 1)) { tplType = T_SUBTREE; } else { uchar *typeStr; CHKmalloc(typeStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid template type '%s'", typeStr); free(typeStr); ABORT_FINALIZE(RS_RET_ERR); } } else if (!strcmp(pblk.descr[i].name, "string")) { CHKmalloc(tplStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "subtree")) { uchar *st_str = es_getBufAddr(pvals[i].val.d.estr); if (st_str[0] != '$' || st_str[1] != '!') { CHKmalloc(cstr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_ERR, "invalid subtree " "parameter, variable must start with '$!' but " "var name is '%s'", cstr); ABORT_FINALIZE(RS_RET_ERR); } else { CHKmalloc(cstr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); CHKiRet(msgPropDescrFill(&subtree, (uchar *)cstr, ustrlen(cstr))); bHaveSubtree = 1; } } else if (!strcmp(pblk.descr[i].name, "plugin")) { CHKmalloc(plugin = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "option.stdsql")) { o_stdsql = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "option.sql")) { o_sql = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "option.json")) { o_json = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "option.jsonf")) { o_jsonf = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "option.jsonftree")) { o_jsonftree = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "option.casesensitive")) { o_casesensitive = pvals[i].val.d.n; } else { dbgprintf( "template: program error, non-handled " "param '%s'\n", pblk.descr[i].name); } } /* the following check is just for clang static anaylzer: this condition * cannot occur if all is setup well, because "name" is a required parameter * inside the param block and so the code should err out above. */ if (name == NULL) { DBGPRINTF("template/tplProcessConf: logic error name == NULL - pblk wrong?\n"); ABORT_FINALIZE(RS_RET_ERR); } /* do config sanity checks */ if (tplStr == NULL) { if (tplType == T_STRING) { LogError(0, RS_RET_ERR, "template '%s' of type string needs " "string parameter", name); ABORT_FINALIZE(RS_RET_ERR); } } else { if (tplType != T_STRING) { LogError(0, RS_RET_ERR, "template '%s' is not a string " "template but has a string specified - ignored", name); } } if (plugin == NULL) { if (tplType == T_PLUGIN) { LogError(0, RS_RET_ERR, "template '%s' of type plugin needs " "plugin parameter", name); ABORT_FINALIZE(RS_RET_ERR); } } else { if (tplType != T_PLUGIN) { LogError(0, RS_RET_ERR, "template '%s' is not a plugin " "template but has a plugin specified - ignored", name); } } if (!bHaveSubtree) { if (tplType == T_SUBTREE) { LogError(0, RS_RET_ERR, "template '%s' of type subtree needs " "subtree parameter", name); ABORT_FINALIZE(RS_RET_ERR); } } else { if (tplType != T_SUBTREE) { LogError(0, RS_RET_ERR, "template '%s' is not a subtree " "template but has a subtree specified - ignored", name); } } if (o->subobjs == NULL) { if (tplType == T_LIST) { LogError(0, RS_RET_ERR, "template '%s' of type list has " "no parameters specified", name); ABORT_FINALIZE(RS_RET_ERR); } } else { if (tplType != T_LIST) { LogError(0, RS_RET_ERR, "template '%s' is not a list " "template but has parameters specified - ignored", name); } } numopts = 0; if (o_sql) ++numopts; if (o_stdsql) ++numopts; if (o_json) ++numopts; if (o_jsonf) ++numopts; if (o_jsonftree) ++numopts; if (numopts > 1) { LogError(0, RS_RET_ERR, "template '%s' has multiple incompatible " "options of sql, stdsql, json, jsonf or jsonftree specified", name); ABORT_FINALIZE(RS_RET_ERR); } /* config ok */ if ((pTpl = tplConstruct(loadConf)) == NULL) { DBGPRINTF("template.c: tplConstruct failed!\n"); ABORT_FINALIZE(RS_RET_ERR); } pTpl->pszName = (char *)name; name = NULL; pTpl->iLenName = lenName; switch (tplType) { case T_STRING: p = tplStr; while (*p) { switch (*p) { case '%': /* parameter */ ++p; /* eat '%' */ CHKiRet(do_Parameter(&p, pTpl)); break; default: /* constant */ do_Constant(&p, pTpl, 0); break; } } break; case T_PLUGIN: p = plugin; /* TODO: the use of tplAddTplMod() can be improved! */ localRet = tplAddTplMod(pTpl, &p); if (localRet != RS_RET_OK) { LogError(0, localRet, "template '%s': error %d " "defining template via plugin (strgen) module", pTpl->pszName, localRet); ABORT_FINALIZE(localRet); } break; case T_LIST: CHKiRet(createListTpl(pTpl, o)); break; case T_SUBTREE: memcpy(&pTpl->subtree, &subtree, sizeof(msgPropDescr_t)); pTpl->bHaveSubtree = 1; break; default: // No action needed for other cases break; } pTpl->optFormatEscape = NO_ESCAPE; if (o_stdsql) pTpl->optFormatEscape = STDSQL_ESCAPE; else if (o_sql) pTpl->optFormatEscape = SQL_ESCAPE; else if (o_json) pTpl->optFormatEscape = JSON_ESCAPE; else if (o_jsonf || o_jsonftree) pTpl->optFormatEscape = JSONF; if (o_jsonftree) pTpl->bJsonTreeEnabled = 1; if (o_casesensitive) pTpl->optCaseSensitive = 1; apply_case_sensitivity(pTpl); if (pTpl->optFormatEscape == JSONF) tplWarnDuplicateJsonKeys(pTpl); finalize_it: if (iRet != RS_RET_OK && bHaveSubtree) { msgPropDescrDestruct(&subtree); } free(name); free(cstr); free(tplStr); free(plugin); if (pvals != NULL) cnfparamvalsDestruct(pvals, &pblk); if (iRet != RS_RET_OK) { if (pTpl != NULL) { /* we simply make the template defunct in this case by setting * its name to a zero-string. We do not free it, as this would * require additional code and causes only a very small memory * consumption. TODO: maybe in next iteration... */ *pTpl->pszName = '\0'; } } RETiRet; } /* Find a template object based on name. Search * currently is case-sensitive (should we change?). * returns pointer to template object if found and * NULL otherwise. * rgerhards 2004-11-17 */ struct template *tplFind(rsconf_t *conf, char *pName, int iLenName) { struct template *pTpl; assert(pName != NULL); pTpl = conf->templates.root; while (pTpl != NULL && !(pTpl->iLenName == iLenName && !strcmp(pTpl->pszName, pName))) { pTpl = pTpl->pNext; } return (pTpl); } /* Destroy the template structure. This is for de-initialization * at program end. Everything is deleted. * rgerhards 2005-02-22 * I have commented out dbgprintfs, because they are not needed for * "normal" debugging. Uncomment them, if they are needed. * rgerhards, 2007-07-05 */ void tplDeleteAll(rsconf_t *conf) { struct template *pTpl, *pTplDel; struct templateEntry *pTpe, *pTpeDel; pTpl = conf->templates.root; while (pTpl != NULL) { pTpe = pTpl->pEntryRoot; while (pTpe != NULL) { pTpeDel = pTpe; pTpe = pTpe->pNext; switch (pTpeDel->eEntryType) { case UNDEFINED: break; case CONSTANT: free(pTpeDel->data.constant.pConstant); break; case FIELD: /* check if we have a regexp and, if so, delete it */ #ifdef FEATURE_REGEXP if (pTpeDel->data.field.has_regex != 0) { if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { regexp.regfree(&(pTpeDel->data.field.re)); } } #endif msgPropDescrDestruct(&pTpeDel->data.field.msgProp); break; default: // No action needed for other cases break; } free(pTpeDel->fieldName); free(pTpeDel); } pTplDel = pTpl; pTpl = pTpl->pNext; free(pTplDel->pszName); if (pTplDel->bHaveSubtree) msgPropDescrDestruct(&pTplDel->subtree); tplJsonNodeFree(pTplDel->pJsonRoot); free(pTplDel); } } /* Destroy all templates obtained from conf file * preserving hardcoded ones. This is called from init(). */ void tplDeleteNew(rsconf_t *conf) { struct template *pTpl, *pTplDel; struct templateEntry *pTpe, *pTpeDel; if (conf->templates.root == NULL || conf->templates.lastStatic == NULL) return; pTpl = conf->templates.lastStatic->pNext; conf->templates.lastStatic->pNext = NULL; conf->templates.last = conf->templates.lastStatic; while (pTpl != NULL) { pTpe = pTpl->pEntryRoot; while (pTpe != NULL) { pTpeDel = pTpe; pTpe = pTpe->pNext; switch (pTpeDel->eEntryType) { case UNDEFINED: break; case CONSTANT: free(pTpeDel->data.constant.pConstant); break; case FIELD: #ifdef FEATURE_REGEXP /* check if we have a regexp and, if so, delete it */ if (pTpeDel->data.field.has_regex != 0) { if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { regexp.regfree(&(pTpeDel->data.field.re)); } } #endif msgPropDescrDestruct(&pTpeDel->data.field.msgProp); break; default: // No action needed for other cases break; } free(pTpeDel->fieldName); free(pTpeDel); } pTplDel = pTpl; pTpl = pTpl->pNext; free(pTplDel->pszName); if (pTplDel->bHaveSubtree) msgPropDescrDestruct(&pTplDel->subtree); tplJsonNodeFree(pTplDel->pJsonRoot); free(pTplDel); } } /* Store the pointer to the last hardcoded template */ void tplLastStaticInit(rsconf_t *conf, struct template *tpl) { conf->templates.lastStatic = tpl; } /* Print the template structure. This is more or less a * debug or test aid, but anyhow I think it's worth it... */ void tplPrintList(rsconf_t *conf) { struct template *pTpl; struct templateEntry *pTpe; pTpl = conf->templates.root; while (pTpl != NULL) { dbgprintf("Template: Name='%s' ", pTpl->pszName == NULL ? "NULL" : pTpl->pszName); if (pTpl->optFormatEscape == SQL_ESCAPE) dbgprintf("[SQL-Format (MySQL)] "); else if (pTpl->optFormatEscape == JSON_ESCAPE) dbgprintf("[JSON-Escaped Format] "); else if (pTpl->optFormatEscape == STDSQL_ESCAPE) dbgprintf("[SQL-Format (standard SQL)] "); else if (pTpl->optFormatEscape == JSONF) dbgprintf("[JSON fields] "); if (pTpl->optCaseSensitive) dbgprintf("[Case Sensitive Vars] "); dbgprintf("\n"); pTpe = pTpl->pEntryRoot; while (pTpe != NULL) { dbgprintf("\tEntry(%lx): type %d, ", (unsigned long)pTpe, pTpe->eEntryType); switch (pTpe->eEntryType) { case UNDEFINED: dbgprintf("(UNDEFINED)"); break; case CONSTANT: dbgprintf("(CONSTANT), value: '%s'", pTpe->data.constant.pConstant); break; case FIELD: dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.msgProp.id); if (pTpe->data.field.msgProp.id == PROP_CEE) { dbgprintf("[EE-Property: '%s'] ", pTpe->data.field.msgProp.name); } else if (pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) { dbgprintf("[Local Var: '%s'] ", pTpe->data.field.msgProp.name); } switch (pTpe->data.field.eDateFormat) { case tplFmtDefault: break; case tplFmtMySQLDate: dbgprintf("[Format as MySQL-Date] "); break; case tplFmtPgSQLDate: dbgprintf("[Format as PgSQL-Date] "); break; case tplFmtRFC3164Date: dbgprintf("[Format as RFC3164-Date] "); break; case tplFmtRFC3339Date: dbgprintf("[Format as RFC3339-Date] "); break; case tplFmtUnixDate: dbgprintf("[Format as Unix timestamp] "); break; case tplFmtSecFrac: dbgprintf("[fractional seconds, only] "); break; case tplFmtRFC3164BuggyDate: dbgprintf("[Format as buggy RFC3164-Date] "); break; case tplFmtWDayName: dbgprintf("[Format as weekday name] "); break; case tplFmtYear: dbgprintf("[Format as year] "); break; case tplFmtMonth: dbgprintf("[Format as month] "); break; case tplFmtDay: dbgprintf("[Format as day] "); break; case tplFmtHour: dbgprintf("[Format as hour] "); break; case tplFmtMinute: dbgprintf("[Format as minute] "); break; case tplFmtSecond: dbgprintf("[Format as second] "); break; case tplFmtTZOffsHour: dbgprintf("[Format as offset hour] "); break; case tplFmtTZOffsMin: dbgprintf("[Format as offset minute] "); break; case tplFmtTZOffsDirection: dbgprintf("[Format as offset direction] "); break; case tplFmtWDay: dbgprintf("[Format as weekday] "); break; case tplFmtOrdinal: dbgprintf("[Format as ordinal] "); break; case tplFmtWeek: dbgprintf("[Format as week] "); break; default: dbgprintf("[UNKNOWN eDateFormat %d] ", pTpe->data.field.eDateFormat); } switch (pTpe->data.field.eCaseConv) { case tplCaseConvNo: break; case tplCaseConvLower: dbgprintf("[Converted to Lower Case] "); break; case tplCaseConvUpper: dbgprintf("[Converted to Upper Case] "); break; default: // No action needed for other cases break; } if (pTpe->data.field.options.bEscapeCC) { dbgprintf("[escape control-characters] "); } if (pTpe->data.field.options.bDropCC) { dbgprintf("[drop control-characters] "); } if (pTpe->data.field.options.bSpaceCC) { dbgprintf("[replace control-characters with space] "); } if (pTpe->data.field.options.bSecPathDrop) { dbgprintf("[slashes are dropped] "); } if (pTpe->data.field.options.bSecPathReplace) { dbgprintf("[slashes are replaced by '_'] "); } if (pTpe->data.field.options.bSPIffNo1stSP) { dbgprintf("[SP iff no first SP] "); } if (pTpe->data.field.options.bCSV) { dbgprintf("[format as CSV (RFC4180)]"); } if (pTpe->data.field.options.bJSON) { dbgprintf("[format as JSON] "); } if (pTpe->data.field.options.bJSONf) { dbgprintf("[format as JSON field] "); } if (pTpe->data.field.options.bJSONr) { dbgprintf("[format as JSON without re-escaping] "); } if (pTpe->data.field.options.bJSONfr) { dbgprintf("[format as JSON field without re-escaping] "); } if (pTpe->data.field.options.bMandatory) { dbgprintf("[mandatory field] "); } if (pTpe->data.field.options.bDropLastLF) { dbgprintf("[drop last LF in msg] "); } if (pTpe->data.field.has_fields == 1) { dbgprintf("[substring, field #%d only (delimiter %d)] ", pTpe->data.field.iFieldNr, pTpe->data.field.field_delim); } if (pTpe->data.field.iFromPos != 0 || pTpe->data.field.iToPos != 0) { dbgprintf("[substring, from character %d to %d] ", pTpe->data.field.iFromPos, pTpe->data.field.iToPos); } break; default: // No action needed for other cases break; } if (pTpe->bComplexProcessing) dbgprintf("[COMPLEX]"); dbgprintf("\n"); pTpe = pTpe->pNext; } pTpl = pTpl->pNext; /* done, go next */ } } int tplGetEntryCount(struct template *pTpl) { assert(pTpl != NULL); return (pTpl->tpenElements); } rsRetVal templateInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(strgen, CORE_COMPONENT)); finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/outchannel.h0000644000000000000000000000013015216464436016544 xustar0030 mtime=1782212894.037266362 30 atime=1787067618.282442338 28 ctime=1787067794.4937269 rsyslog-8.2608.0/runtime/outchannel.h0000664000175000017500000000237315216464436016217 0ustar00rgerrger/* This is the header for the output channel code of rsyslog. * begun 2005-06-21 rgerhards * * Copyright(C) 2005-2012 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OUTCHANNEL_H #define OUTCHANNEL_H struct outchannel { struct outchannel *pNext; char *pszName; int iLenName; uchar *pszFileTemplate; off_t uSizeLimit; uchar *cmdOnSizeLimit; }; struct outchannel *ochConstruct(void); struct outchannel *ochAddLine(char *pName, unsigned char **pRestOfConfLine); struct outchannel *ochFind(char *pName, int iLenName); void ochDeleteAll(void); void ochPrintList(rsconf_t *cnf); #endif /* #ifdef OUTCHANNEL_H */ rsyslog-8.2608.0/runtime/PaxHeaders/perctile_stats.h0000644000000000000000000000013215216464436017433 xustar0030 mtime=1782212894.037266362 30 atime=1787067616.835415358 30 ctime=1787067794.375724701 rsyslog-8.2608.0/runtime/perctile_stats.h0000664000175000017500000000524115216464436017101 0ustar00rgerrger/* * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_PERCTILE_STATS_H #define INCLUDED_PERCTILE_STATS_H #include "hashtable.h" #include "statsobj.h" struct perctile_ctr_s { // percentile [0,100] uint8_t percentile; size_t index; intctr_t ctr_perctile_stat; ctr_t *ref_ctr_percentile_stat; }; struct perctile_stat_s { uchar name[128]; sbool bReported; struct ringbuf_s *rb_observed_stats; // array of requested perctile to track struct perctile_ctr_s *ctrs; size_t perctile_ctrs_count; pthread_rwlock_t stats_lock; intctr_t ctrWindowCount; ctr_t *refCtrWindowCount; intctr_t ctrWindowMin; ctr_t *refCtrWindowMin; intctr_t ctrWindowMax; ctr_t *refCtrWindowMax; intctr_t ctrWindowSum; ctr_t *refCtrWindowSum; }; struct perctile_bucket_s { struct perctile_buckets_s *bkts; uchar *name; uchar *delim; // lock for entire bucket pthread_rwlock_t lock; struct hashtable *htable; struct perctile_bucket_s *next; statsobj_t *statsobj; STATSCOUNTER_DEF(ctrNewKeyAdd, mutCtrNewKeyAdd); ctr_t *pNewKeyAddCtr; STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow); ctr_t *pOpsOverflowCtr; uint32_t window_size; // These percentile values apply to all perctile stats in this bucket. uint8_t *perctile_values; size_t perctile_values_count; }; struct perctile_buckets_s { uint8_t initialized; statsobj_t *global_stats; pthread_rwlock_t lock; struct perctile_bucket_s *listBuckets; }; // keep these local for now. typedef struct perctile_ctr_s perctile_ctr_t; typedef struct perctile_stat_s perctile_stat_t; typedef struct perctile_bucket_s perctile_bucket_t; rsRetVal perctileClassInit(void); void perctileBucketsDestruct(void); rsRetVal perctile_initCnf(perctile_buckets_t *b); perctile_bucket_t *perctile_findBucket(const uchar *name); rsRetVal perctile_processCnf(struct cnfobj *cnf); rsRetVal perctile_obs(perctile_bucket_t *perctile_bkt, uchar *key, int64_t value); #endif /* #ifndef INCLUDED_PERCTILE_STATS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/cfsysline.h0000644000000000000000000000013215132411300016360 xustar0030 mtime=1768559296.261885561 30 atime=1787067617.983436763 30 ctime=1787067794.461726303 rsyslog-8.2608.0/runtime/cfsysline.h0000666000175000017500000000541615132411300016034 0ustar00rgerrger/* Definition of the cfsysline (config file system line) object. * * Copyright 2007-2012 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CFSYSLINE_H_INCLUDED #define CFSYSLINE_H_INCLUDED #include "linkedlist.h" /* this is a single entry for a parse routine. It describes exactly * one entry point/handler. * The short name is cslch (Configfile SysLine CommandHandler) */ struct cslCmdHdlr_s { /* config file sysline parse entry */ ecslConfObjType __attribute__((deprecated)) eConfObjType; /* which config object is this for? */ ecslCmdHdrlType eType; /* which type of handler is this? */ rsRetVal (*cslCmdHdlr)(); /* function pointer to use with handler (params depending on eType) */ void *pData; /* user-supplied data pointer */ int *permitted; /* is this parameter currently permitted? (NULL=don't check) */ }; typedef struct cslCmdHdlr_s cslCmdHdlr_t; /* this is the list of known configuration commands with pointers to * their handlers. * The short name is cslc (Configfile SysLine Command) */ struct cslCmd_s { /* config file sysline parse entry */ int bChainingPermitted; /* may multiple handlers be chained for this command? */ linkedList_t llCmdHdlrs; /* linked list of command handlers */ }; typedef struct cslCmd_s cslCmd_t; /* prototypes */ rsRetVal regCfSysLineHdlr(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie); rsRetVal regCfSysLineHdlr2(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie, int *permitted); rsRetVal unregCfSysLineHdlrs(void); rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie); rsRetVal processCfSysLineCommand(uchar *pCmd, uchar **p); rsRetVal cfsyslineInit(void); void dbgPrintCfSysLineHandlers(void); #endif /* #ifndef CFSYSLINE_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/msg_replace_helper.h0000644000000000000000000000013215216464436020226 xustar0030 mtime=1782212894.029266232 30 atime=1787067618.236441481 30 ctime=1787067794.309723471 rsyslog-8.2608.0/runtime/msg_replace_helper.h0000664000175000017500000000554015216464436017676 0ustar00rgerrger/* msg_replace_helper.h * * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_MSG_REPLACE_HELPER_H #define INCLUDED_MSG_REPLACE_HELPER_H #include #include #include #include "rsyslog.h" static rsRetVal msgReplaceRawMsgSegment(uchar **ppRawMsg, uchar *stackBuf, int stackBufSize, int offMSG, int lenOldMSG, int *pLenRawMsg, const uchar *pszMSG, int lenMSG) { int lenNew; int lenSuffix; uchar *bufNew; assert(ppRawMsg != NULL); assert(*ppRawMsg != NULL); assert(stackBuf != NULL); assert(pLenRawMsg != NULL); assert(pszMSG != NULL); assert(offMSG >= 0); assert(lenOldMSG >= 0); assert(*pLenRawMsg >= offMSG + lenOldMSG); lenNew = *pLenRawMsg + lenMSG - lenOldMSG; lenSuffix = *pLenRawMsg - offMSG - lenOldMSG; bufNew = *ppRawMsg; if (lenMSG > lenOldMSG && ((bufNew == stackBuf && lenNew >= stackBufSize) || (bufNew != stackBuf && lenNew > *pLenRawMsg))) { if (bufNew == stackBuf) { bufNew = malloc(lenNew + 1); if (bufNew == NULL) { return RS_RET_OUT_OF_MEMORY; } memcpy(bufNew, *ppRawMsg, offMSG); if (lenSuffix > 0) { memcpy(bufNew + offMSG + lenMSG, *ppRawMsg + offMSG + lenOldMSG, lenSuffix); } } else { uchar *tmp = realloc(bufNew, lenNew + 1); if (tmp == NULL) { return RS_RET_OUT_OF_MEMORY; } bufNew = tmp; if (lenSuffix > 0) { memmove(bufNew + offMSG + lenMSG, bufNew + offMSG + lenOldMSG, lenSuffix); } } } else if (lenSuffix > 0 && lenMSG != lenOldMSG) { memmove(bufNew + offMSG + lenMSG, bufNew + offMSG + lenOldMSG, lenSuffix); } if (lenMSG > 0) { memcpy(bufNew + offMSG, pszMSG, lenMSG); } bufNew[lenNew] = '\0'; *ppRawMsg = bufNew; *pLenRawMsg = lenNew; return RS_RET_OK; } #endif rsyslog-8.2608.0/runtime/PaxHeaders/rswatch.c0000644000000000000000000000013215216464436016054 xustar0030 mtime=1782212894.039266394 30 atime=1787067618.250441742 30 ctime=1787067794.430725726 rsyslog-8.2608.0/runtime/rswatch.c0000664000175000017500000003321415216464436015523 0ustar00rgerrger/* rswatch.c * generic watched-file support for runtime-managed reloaders * * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_INOTIFY_H #include #endif #include "rswatch.h" struct rswatch_handle_s { char *id; char *path; char *dir; char *base; unsigned int debounce_ms; rswatch_cb_t cb; void *ctx; #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) int wd; sbool pending; uint64_t due_at_ms; #endif struct rswatch_handle_s *next; }; #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) typedef struct rswatch_state_s { pthread_mutex_t mut; rswatch_handle_t *handles; int ino_fd; sbool disabled; } rswatch_state_t; /* One process-global watcher state is sufficient because all activity is * multiplexed through the main housekeeping loop. */ static rswatch_state_t g_rswatch = {PTHREAD_MUTEX_INITIALIZER, NULL, -1, 0}; #endif #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) static char *rswatchDupDirname(const char *path) { const char *slash; size_t len; char *out; if (path == NULL || *path == '\0') { return NULL; } slash = strrchr(path, '/'); if (slash == NULL) { return strdup("."); } if (slash == path) { return strdup("/"); } len = (size_t)(slash - path); out = malloc(len + 1); if (out == NULL) { return NULL; } memcpy(out, path, len); out[len] = '\0'; return out; } static char *rswatchDupBasename(const char *path) { const char *slash; if (path == NULL || *path == '\0') { return NULL; } slash = strrchr(path, '/'); return strdup((slash == NULL) ? path : slash + 1); } #endif static void rswatchFreeHandle(rswatch_handle_t *handle) { if (handle == NULL) { return; } free(handle->id); free(handle->path); free(handle->dir); free(handle->base); free(handle); } #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) static rsRetVal rswatchSetNonBlocking(int fd) { int flags; DEFiRet; if (fd == -1) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if ((flags = fcntl(fd, F_GETFL)) == -1) { ABORT_FINALIZE(RS_RET_IO_ERROR); } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: RETiRet; } static rsRetVal rswatchSetCloseOnExec(int fd) { int flags; DEFiRet; if (fd == -1) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if ((flags = fcntl(fd, F_GETFD)) == -1) { ABORT_FINALIZE(RS_RET_IO_ERROR); } if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: RETiRet; } static rsRetVal rswatchEnsureInfraLocked(void) { int saved_errno = 0; DEFiRet; if (g_rswatch.disabled) { ABORT_FINALIZE(RS_RET_IO_ERROR); } if (g_rswatch.ino_fd == -1) { g_rswatch.ino_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); saved_errno = errno; if (g_rswatch.ino_fd == -1) { #ifndef IN_CLOEXEC g_rswatch.ino_fd = inotify_init1(IN_NONBLOCK); if (g_rswatch.ino_fd != -1) { CHKiRet(rswatchSetCloseOnExec(g_rswatch.ino_fd)); } saved_errno = errno; #endif if (g_rswatch.ino_fd == -1 && saved_errno == ENOSYS) { g_rswatch.ino_fd = inotify_init(); if (g_rswatch.ino_fd != -1) { CHKiRet(rswatchSetNonBlocking(g_rswatch.ino_fd)); CHKiRet(rswatchSetCloseOnExec(g_rswatch.ino_fd)); } } if (g_rswatch.ino_fd == -1) { ABORT_FINALIZE(RS_RET_INOTIFY_INIT_FAILED); } } } finalize_it: if (iRet != RS_RET_OK && g_rswatch.ino_fd != -1) { close(g_rswatch.ino_fd); g_rswatch.ino_fd = -1; } RETiRet; } static int rswatchFindDirWatchLocked(const char *dir) { rswatch_handle_t *handle; for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { if (!strcmp(handle->dir, dir)) { return handle->wd; } } return -1; } static sbool rswatchDirInUseLocked(int wd) { rswatch_handle_t *handle; for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { if (handle->wd == wd) { return 1; } } return 0; } static void rswatchDisableLocked(int err, const char *reason) { rswatch_handle_t *handle; if (!g_rswatch.disabled) { LogError(err, RS_RET_IO_ERROR, "rswatch: %s, disabling watched-file reload support", reason); } g_rswatch.disabled = 1; if (g_rswatch.ino_fd != -1) { close(g_rswatch.ino_fd); g_rswatch.ino_fd = -1; } for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { handle->wd = -1; handle->pending = 0; handle->due_at_ms = 0; } } /* Each matching event resets the quiet-period deadline. This coalesces bursty * editor save patterns into a single later reload callback. */ static void rswatchMarkEventLocked(int wd, const char *name, uint64_t now_ms) { rswatch_handle_t *handle; if (name == NULL || *name == '\0') { return; } for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { if (handle->wd == wd && !strcmp(handle->base, name)) { handle->pending = 1; handle->due_at_ms = now_ms + handle->debounce_ms; } } } static rswatch_handle_t *rswatchPopDueLocked(uint64_t now_ms) { rswatch_handle_t *handle; for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { if (handle->pending && handle->due_at_ms <= now_ms) { handle->pending = 0; return handle; } } return NULL; } #endif rsRetVal rswatchRegister(const rswatch_desc_t *desc, rswatch_handle_t **out) { rswatch_handle_t *handle = NULL; #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) sbool bLocked = 0; #endif DEFiRet; if (out != NULL) { *out = NULL; } if (desc == NULL || desc->id == NULL || desc->path == NULL || *desc->path == '\0' || desc->cb == NULL) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } #if !defined(HAVE_INOTIFY_INIT) || !defined(HAVE_SYS_INOTIFY_H) ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED); #else int wd; CHKmalloc(handle = calloc(1, sizeof(*handle))); CHKmalloc(handle->id = strdup(desc->id)); CHKmalloc(handle->path = strdup(desc->path)); CHKmalloc(handle->dir = rswatchDupDirname(desc->path)); CHKmalloc(handle->base = rswatchDupBasename(desc->path)); handle->debounce_ms = desc->debounce_ms; handle->cb = desc->cb; handle->ctx = desc->ctx; handle->wd = -1; pthread_mutex_lock(&g_rswatch.mut); bLocked = 1; CHKiRet(rswatchEnsureInfraLocked()); wd = rswatchFindDirWatchLocked(handle->dir); if (wd == -1) { wd = inotify_add_watch(g_rswatch.ino_fd, handle->dir, IN_CLOSE_WRITE | IN_MOVED_TO | IN_ATTRIB | IN_CREATE); if (wd == -1) { ABORT_FINALIZE(RS_RET_IO_ERROR); } } handle->wd = wd; handle->next = g_rswatch.handles; g_rswatch.handles = handle; if (out != NULL) { *out = handle; } handle = NULL; #endif finalize_it: #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) if (bLocked) { pthread_mutex_unlock(&g_rswatch.mut); } #endif if (handle != NULL) { rswatchFreeHandle(handle); } RETiRet; } void rswatchUnregister(rswatch_handle_t *handle) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) rswatch_handle_t **pp; if (handle == NULL) { return; } pthread_mutex_lock(&g_rswatch.mut); pp = &g_rswatch.handles; while (*pp != NULL) { if (*pp != handle) { pp = &(*pp)->next; continue; } *pp = handle->next; if (!g_rswatch.disabled && g_rswatch.ino_fd != -1 && handle->wd != -1 && !rswatchDirInUseLocked(handle->wd)) { inotify_rm_watch(g_rswatch.ino_fd, handle->wd); } if (g_rswatch.handles == NULL && g_rswatch.ino_fd != -1) { close(g_rswatch.ino_fd); g_rswatch.ino_fd = -1; g_rswatch.disabled = 0; } pthread_mutex_unlock(&g_rswatch.mut); rswatchFreeHandle(handle); return; } pthread_mutex_unlock(&g_rswatch.mut); #else (void)handle; #endif } int rswatchGetWaitFd(void) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) int fd; pthread_mutex_lock(&g_rswatch.mut); fd = (g_rswatch.disabled || g_rswatch.handles == NULL) ? -1 : g_rswatch.ino_fd; pthread_mutex_unlock(&g_rswatch.mut); return fd; #else return -1; #endif } int rswatchComputeTimeoutMs(uint64_t now_ms, int default_timeout_ms) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) rswatch_handle_t *handle; uint64_t diff; int timeout_ms = default_timeout_ms; pthread_mutex_lock(&g_rswatch.mut); if (g_rswatch.disabled || g_rswatch.handles == NULL) { pthread_mutex_unlock(&g_rswatch.mut); return timeout_ms; } for (handle = g_rswatch.handles; handle != NULL; handle = handle->next) { if (!handle->pending) { continue; } if (handle->due_at_ms <= now_ms) { timeout_ms = 0; break; } diff = handle->due_at_ms - now_ms; if (diff > (uint64_t)INT_MAX) { diff = (uint64_t)INT_MAX; } if (timeout_ms < 0 || (int)diff < timeout_ms) { timeout_ms = (int)diff; } } pthread_mutex_unlock(&g_rswatch.mut); return timeout_ms; #else (void)now_ms; return default_timeout_ms; #endif } void rswatchProcessIo(uint64_t now_ms) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) char buf[4096]; ssize_t rd; pthread_mutex_lock(&g_rswatch.mut); if (g_rswatch.disabled || g_rswatch.ino_fd == -1) { pthread_mutex_unlock(&g_rswatch.mut); return; } pthread_mutex_unlock(&g_rswatch.mut); while ((rd = read(g_rswatch.ino_fd, buf, sizeof(buf))) > 0) { ssize_t off = 0; pthread_mutex_lock(&g_rswatch.mut); /* inotify read() is expected to return complete events, but keep the * parser defensive in case a short trailing fragment is ever seen. */ while (off + (ssize_t)sizeof(struct inotify_event) <= rd) { struct inotify_event evhdr; const char *name = NULL; memcpy(&evhdr, buf + off, sizeof(evhdr)); /* This is not expected from inotify read(), but keep the parser * defensive if the trailing name payload is ever truncated. */ if (off + (ssize_t)sizeof(struct inotify_event) + (ssize_t)evhdr.len > rd) { break; } if (evhdr.len > 0) { name = buf + off + sizeof(evhdr); } if ((evhdr.mask & (IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_ATTRIB)) != 0) { rswatchMarkEventLocked(evhdr.wd, name, now_ms); } off += (ssize_t)(sizeof(struct inotify_event) + evhdr.len); } pthread_mutex_unlock(&g_rswatch.mut); } if (rd < 0 && errno != EAGAIN && errno != EINTR) { pthread_mutex_lock(&g_rswatch.mut); rswatchDisableLocked(errno, "watch backend read failed"); pthread_mutex_unlock(&g_rswatch.mut); } #else (void)now_ms; #endif } void rswatchDispatchDue(uint64_t now_ms) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) while (1) { rswatch_handle_t *handle; rswatch_cb_t cb; void *ctx; pthread_mutex_lock(&g_rswatch.mut); if (g_rswatch.disabled) { pthread_mutex_unlock(&g_rswatch.mut); return; } handle = rswatchPopDueLocked(now_ms); if (handle == NULL) { pthread_mutex_unlock(&g_rswatch.mut); return; } cb = handle->cb; ctx = handle->ctx; pthread_mutex_unlock(&g_rswatch.mut); /* Dispatch unlocked so reload code can take its own locks without * inheriting rswatch's internal lock ordering. */ cb(ctx, "watch"); } #else (void)now_ms; #endif } void rswatchExit(void) { #if defined(HAVE_INOTIFY_INIT) && defined(HAVE_SYS_INOTIFY_H) rswatch_handle_t *handle; pthread_mutex_lock(&g_rswatch.mut); handle = g_rswatch.handles; g_rswatch.handles = NULL; if (g_rswatch.ino_fd != -1) { close(g_rswatch.ino_fd); g_rswatch.ino_fd = -1; } g_rswatch.disabled = 0; pthread_mutex_unlock(&g_rswatch.mut); while (handle != NULL) { rswatch_handle_t *next = handle->next; rswatchFreeHandle(handle); handle = next; } #endif } rsyslog-8.2608.0/runtime/PaxHeaders/compat_queue.h0000644000000000000000000000013215241075234017065 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.745580916 30 ctime=1787067794.362724459 rsyslog-8.2608.0/runtime/compat_queue.h0000664000175000017500000000477215241075234016543 0ustar00rgerrger/* * Compatibility helpers for BSD sys/queue.h users. * * Use the platform STAILQ macros when configure found them. Some platforms * provide sys/queue.h without that subset, so keep the local fallback limited * to the macros used by rsyslog. */ #ifndef INCLUDED_COMPAT_QUEUE_H #define INCLUDED_COMPAT_QUEUE_H #include #ifdef HAVE_SYS_QUEUE_H #include #endif #ifndef HAVE_SYS_QUEUE_STAILQ #ifndef STAILQ_HEAD #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first; \ struct type **stqh_last; \ } #endif #ifndef STAILQ_ENTRY #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; \ } #endif #ifndef STAILQ_INIT #define STAILQ_INIT(head) \ do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (0) #endif #ifndef STAILQ_EMPTY #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #endif #ifndef STAILQ_FIRST #define STAILQ_FIRST(head) ((head)->stqh_first) #endif #ifndef STAILQ_INSERT_TAIL #define STAILQ_INSERT_TAIL(head, elm, field) \ do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (0) #endif #ifndef STAILQ_REMOVE_HEAD #define STAILQ_REMOVE_HEAD(head, field) \ do { \ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) { \ (head)->stqh_last = &(head)->stqh_first; \ } \ } while (0) #endif #ifndef STAILQ_NEXT #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #endif #ifndef STAILQ_FOREACH #define STAILQ_FOREACH(var, head, field) \ for ((var) = STAILQ_FIRST(head); (var); (var) = STAILQ_NEXT((var), field)) #endif #endif #endif /* #ifndef INCLUDED_COMPAT_QUEUE_H */ rsyslog-8.2608.0/runtime/PaxHeaders/translate.h0000644000000000000000000000013215171370365016400 xustar0030 mtime=1776677109.449913202 30 atime=1787067618.231441388 30 ctime=1787067794.446726024 rsyslog-8.2608.0/runtime/translate.h0000664000175000017500000000623015171370365016045 0ustar00rgerrger/** @file translate.h * @brief Interfaces for canonical config translation. * * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef RUNTIME_TRANSLATE_H_INCLUDED #define RUNTIME_TRANSLATE_H_INCLUDED #include "rsyslog.h" #include "grammar/rainerscript.h" /** @brief Supported translation output formats. */ enum rsconfTranslateFormat { RSCONF_TRANSLATE_NONE = 0, RSCONF_TRANSLATE_RAINERSCRIPT, RSCONF_TRANSLATE_YAML }; /** * @brief Configure translation mode for the current validation run. * * Resets any previously retained translation state before enabling the * selected output format. * * @param fmt Translation output format, or @c RSCONF_TRANSLATE_NONE to disable. */ void rsconfTranslateConfigure(enum rsconfTranslateFormat fmt); /** * @brief Release all retained translation state. */ void rsconfTranslateCleanup(void); /** * @brief Check whether translation capture is enabled. * * @return Non-zero when config translation is active. */ int rsconfTranslateEnabled(void); /** * @brief Check whether translation capture hit a fatal error. * * @return Non-zero when translation should fail instead of writing output. */ int rsconfTranslateHasFatal(void); /** * @brief Clone a name-value list for later translation output. * * @param lst List head to clone. * @return Cloned list, or NULL on allocation failure. */ struct nvlst *rsconfTranslateCloneNvlst(const struct nvlst *lst); /** * @brief Capture a config object before normal processing consumes it. * * @param o Parsed config object. * @param source Source file name, if known. * @param line Source line number. */ void rsconfTranslateCaptureObj(const struct cnfobj *o, const char *source, int line); /** * @brief Capture executable script statements for later emission. * * @param script Statement tree to serialize. * @param source Source file name, if known. * @param line Source line number. */ void rsconfTranslateCaptureScript(const struct cnfstmt *script, const char *source, int line); /** * @brief Record a fatal unsupported construct for translation. * * @param source Source file name, if known. * @param line Source line number. * @param fmt Printf-style explanation of the unsupported construct. */ void rsconfTranslateAddUnsupported(const char *source, int line, const char *fmt, ...) __attribute__((format(printf, 3, 4))); /** * @brief Write the translated configuration document. * * @param path Output path, or "-" for stdout. * @return rsyslog status code for the write operation. */ rsRetVal rsconfTranslateWriteFile(const char *path); #endif rsyslog-8.2608.0/runtime/PaxHeaders/action.h0000644000000000000000000000013215241075234015653 xustar0030 mtime=1787067036.599578182 30 atime=1787067036.745580916 30 ctime=1787067794.463726341 rsyslog-8.2608.0/runtime/action.h0000664000175000017500000002110715241075234015320 0ustar00rgerrger/* action.h * Header file for the action object * * File begun on 2007-08-06 by RGerhards (extracted from syslogd.c, which * was under BSD license at the time of rsyslog fork) * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file action.h * @brief Public API for output actions. * * Actions represent configured output destinations. Each action may run * via its own queue or directly from a worker thread. When supported by * the output module, actions treat a batch of messages as a transaction * and coordinate commits via this interface. These are not strict * database-style transactions; a rollback may not be possible and * message delivery follows an "at least once" principle. */ #ifndef ACTION_H_INCLUDED #define ACTION_H_INCLUDED 1 #include "syslogd-types.h" #include "queue.h" typedef struct ratelimit_s ratelimit_t; /* external data */ extern int glbliActionResumeRetryCount; /** * @struct action_s * @brief Runtime representation of an output action. * * Holds configuration and runtime state for a single action. * * Actions may be processed by multiple worker threads. The primary * mutex @c mutAction serializes state changes such as suspension and * resume handling. When the associated output module supports * transactions, the fields in this structure track in-flight batches * and commit status. These transactions are best-effort batches; on * failure only partial rollback may be possible, so delivery is * guaranteed at least once. */ struct action_s { time_t f_time; /* used for "max. n messages in m seconds" processing */ time_t tActNow; /* the current time for an action execution. Initially set to -1 and populated on an as-needed basis. This is a performance optimization. */ time_t tLastExec; /* time this action was last executed */ int iActionNbr; /* this action's number (ID) */ sbool bExecWhenPrevSusp; /* execute only when previous action is suspended? */ sbool bWriteAllMarkMsgs; /* should all mark msgs be written (not matter how recent the action was executed)? */ sbool bReportSuspension; /* should suspension (and reactivation) of the action reported */ sbool bReportSuspensionCont; int bDisabled; /* disable flag; accessed atomically via mutCAS helper */ sbool isTransactional; sbool bCopyMsg; int iSecsExecOnceInterval; /* if non-zero, minimum seconds to wait until action is executed again */ time_t ttResumeRtry; /* when is it time to retry the resume? */ int iResumeInterval; /* resume interval for this action */ int iResumeIntervalMax; /* maximum resume interval for this action --> -1: unbounded */ int iResumeRetryCount; /* how often shall we retry a suspended action? (-1 --> eternal) */ int iNbrNoExec; /* number of matches that did not yet yield to an exec */ int iExecEveryNthOccur; /* execute this action only every n-th occurrence (with n=0,1 -> always) */ int iExecEveryNthOccurTO; /* timeout for n-th occurrence feature */ time_t tLastOccur; /* time last occurrence was seen (for timing them out) */ struct modInfo_s *pMod; /* pointer to output module handling this selector */ void *pModData; /* pointer to module data - content is module-specific */ struct nvlst *pSyntaxLst; /* cloned config syntax for translation/export */ sbool bRepMsgHasMsg; /* "message repeated..." has msg fragment in it (0-no, 1-yes) */ rsRetVal (*submitToActQ)(action_t *, wti_t *, smsg_t *); /* function submit message to action queue */ rsRetVal (*qConstruct)(struct queue_s *pThis); sbool bUsesMsgPassingMode; sbool bNeedReleaseBatch; /* do we need to release batch ressources? Depends on ParamPassig modes... */ int iNumTpls; /* number of array entries for template element below */ struct template **ppTpl; /* array of template to use - strings must be passed to doAction * in this order. */ paramPassing_t *peParamPassing; /* mode of parameter passing to action for that template */ qqueue_t *pQueue; /* action queue */ pthread_mutex_t mutAction; /* primary action mutex */ uchar *pszName; /* action name */ uchar *pszRatelimitName; /* optional output ratelimit policy name */ ratelimit_t *ratelimiter; /* optional action-level output ratelimiter */ DEF_ATOMIC_HELPER_MUT(mutCAS); /* error file */ const char *pszErrFile; int fdErrFile; size_t maxErrFileSize; size_t currentErrFileSize; pthread_mutex_t mutErrFile; /* external stat file system */ const char *pszExternalStateFile; /* for per-worker HUP processing */ pthread_mutex_t mutWrkrDataTable; /* protects table structures */ void **wrkrDataTable; int wrkrDataTableSize; int nWrkr; /* for statistics subsystem */ statsobj_t *statsobj; STATSCOUNTER_DEF(ctrProcessed, mutCtrProcessed) STATSCOUNTER_DEF(ctrBatchesProcessed, mutCtrBatchesProcessed) STATSCOUNTER_DEF(ctrFail, mutCtrFail) STATSCOUNTER_DEF(ctrSuspend, mutCtrSuspend) STATSCOUNTER_DEF(ctrSuspendDuration, mutCtrSuspendDuration) STATSCOUNTER_DEF(ctrResume, mutCtrResume) STATSCOUNTER_DEF(ctrRateLimitAllowed, mutCtrRateLimitAllowed) STATSCOUNTER_DEF(ctrRateLimitDropped, mutCtrRateLimitDropped) STATSCOUNTER_DEF(ctrRateLimitPaced, mutCtrRateLimitPaced) STATSCOUNTER_DEF(ctrRateLimitPacedUsec, mutCtrRateLimitPacedUsec) }; static inline int actionLoadDisabled(action_t *const pAction) { return ATOMIC_LOAD_32BIT(&pAction->bDisabled, &pAction->mutCAS); } static inline void actionStoreDisabled(action_t *const pAction, const int value) { if (value == 0) { ATOMIC_STORE_32BIT(&pAction->bDisabled, &pAction->mutCAS, 0); } else { ATOMIC_STORE_32BIT(&pAction->bDisabled, &pAction->mutCAS, 1); } } static inline int actionIsDisabled(action_t *const pAction) { return actionLoadDisabled(pAction) != 0; } /* function prototypes */ /** Create a new action instance. */ rsRetVal actionConstruct(action_t **ppThis); /** Finalize initialization after configuration parameters were applied. */ rsRetVal actionConstructFinalize(action_t *pThis, struct nvlst *lst); /** Destroy an action instance and free all associated resources. */ rsRetVal actionDestruct(action_t *pThis); /** Set the global default resume interval for actions. */ rsRetVal actionSetGlobalResumeInterval(int iNewVal); /** * Execute an action outside of a queue context. * Primarily used for historic modules that expect this style. */ rsRetVal actionDoAction(action_t *pAction); /** Enqueue a message for processing by an action. */ rsRetVal actionWriteToAction(action_t *pAction, smsg_t *pMsg, wti_t *); /** Trigger the HUP handler of an action if provided by the module. */ rsRetVal actionCallHUPHdlr(action_t *pAction); /** Initialize global resources used by the action subsystem. */ rsRetVal actionClassInit(void); /** * Register a configured action with the ruleset. * The action instance becomes owned by the configuration once added. */ rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, struct cnfparamvals *actParams, struct nvlst *lst); /** Start the message queues of all configured actions. */ rsRetVal activateActions(void); /** Create a new action from configuration parameters. */ rsRetVal actionNewInst(struct nvlst *lst, action_t **ppAction); rsRetVal actionProcessCnf(struct cnfobj *o); /** Commit all outstanding transactions for direct queues. */ void actionCommitAllDirect(wti_t *pWti); /** Remove a worker instance from the action's bookkeeping. */ void actionRemoveWorker(action_t *const pAction, void *const actWrkrData); /** Release parameter memory allocated by prepareDoActionParams(). */ void releaseDoActionParams(action_t *const pAction, wti_t *const pWti, int action_destruct); /** Return the action name; never returns NULL. */ const uchar *actionGetName(const action_t *const pAction); #endif /* #ifndef ACTION_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/wti.c0000644000000000000000000000013215241075234015174 xustar0030 mtime=1787067036.613578444 30 atime=1787067036.760581197 30 ctime=1787067794.391724999 rsyslog-8.2608.0/runtime/wti.c0000664000175000017500000005270715241075234014653 0ustar00rgerrger/* wti.c * * This file implements the worker thread instance (wti) class. * * File begun on 2008-01-20 by RGerhards based on functions from the * previous queue object class (the wti functions have been extracted) * * There is some in-depth documentation available in doc/dev_queue.html * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it * if you are getting acquainted to the object. * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "stringbuf.h" #include "srUtils.h" #include "errmsg.h" #include "wtp.h" #include "wti.h" #include "obj.h" #include "glbl.h" #include "action.h" #include "atomic.h" #include "rsconf.h" /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) pthread_key_t thrd_wti_key; /* methods */ /* get the header for debug messages * The caller must NOT free or otherwise modify the returned string! */ uchar *ATTR_NONNULL() wtiGetDbgHdr(const wti_t *const pThis) { ISOBJ_TYPE_assert(pThis, wti); if (pThis->pszDbgHdr == NULL) return (uchar *)"wti"; /* should not normally happen */ else return pThis->pszDbgHdr; } /* return the current worker processing state. For the sake of * simplicity, we do not use the iRet interface. -- rgerhards, 2009-07-17 */ int ATTR_NONNULL() wtiGetState(wti_t *pThis) { return ATOMIC_LOAD_32BIT(&pThis->bIsRunning, &pThis->mutIsRunning); } /* join terminated worker thread * This may be called in any thread state, it will be a NOP if the * thread is not to join. */ void ATTR_NONNULL() wtiJoinThrd(wti_t *const pThis) { int r; ISOBJ_TYPE_assert(pThis, wti); if (wtiGetState(pThis) == WRKTHRD_WAIT_JOIN) { DBGPRINTF("%s: joining terminated worker\n", wtiGetDbgHdr(pThis)); if ((r = pthread_join(pThis->thrdID, NULL)) != 0) { LogMsg(r, RS_RET_INTERNAL_ERROR, LOG_WARNING, "rsyslog bug? wti cannot join terminated wrkr"); return; } DBGPRINTF("%s: worker fully terminated\n", wtiGetDbgHdr(pThis)); wtiSetState(pThis, WRKTHRD_STOPPED); if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: thread joined\n", wtiGetDbgHdr(pThis)); } } } /* Set this thread to "always running" state (can not be unset) * rgerhards, 2009-07-20 */ rsRetVal ATTR_NONNULL() wtiSetAlwaysRunning(wti_t *pThis) { ISOBJ_TYPE_assert(pThis, wti); pThis->bAlwaysRunning = RSTRUE; return RS_RET_OK; } /* Set status (thread is running or not), actually an property of * use for wtp, but we need to have it per thread instance (thus it * is inside wti). -- rgerhards, 2009-07-17 */ rsRetVal ATTR_NONNULL() wtiSetState(wti_t *pThis, const int newVal) { ISOBJ_TYPE_assert(pThis, wti); if (newVal == WRKTHRD_STOPPED) { ATOMIC_STORE_32BIT(&pThis->bIsRunning, &pThis->mutIsRunning, 0); } else { ATOMIC_OR_INT_TO_INT(&pThis->bIsRunning, &pThis->mutIsRunning, newVal); } return RS_RET_OK; } /* Compare and Set state (atomic). */ rsRetVal ATTR_NONNULL() wtiCASState(wti_t *pThis, const int oldVal, const int newVal) { ISOBJ_TYPE_assert(pThis, wti); if (ATOMIC_CAS(&pThis->bIsRunning, oldVal, newVal, &pThis->mutIsRunning)) { return RS_RET_OK; } else { return RS_RET_FALSE; } } /* advise all workers to start by interrupting them. That should unblock all srSleep() * calls. */ rsRetVal wtiWakeupThrd(wti_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, wti); if (wtiGetState(pThis)) { /* we first try the cooperative "cancel" interface */ pthread_kill(pThis->thrdID, SIGTTIN); DBGPRINTF("sent SIGTTIN to worker thread %p\n", (void *)pThis->thrdID); } RETiRet; } /* Cancel the thread. If the thread is not running. But it is save and legal to * call wtiCancelThrd() in such situations. This function only returns when the * thread has terminated. Else we may get race conditions all over the code... * Note that when waiting for the thread to terminate, we do a busy wait, checking * progress every 10ms. It is very unlikely that we will ever cancel a thread * and, if so, it will only happen at the end of the rsyslog run. So doing this * kind of non-optimal wait is considered preferable over using condition variables. * rgerhards, 2008-02-26 */ rsRetVal ATTR_NONNULL() wtiCancelThrd(wti_t *pThis, const uchar *const cancelobj) { DEFiRet; int state; wtp_t *pWtp; pthread_t thrdID; ISOBJ_TYPE_assert(pThis, wti); pWtp = pThis->pWtp; ISOBJ_TYPE_assert(pWtp, wtp); wtiJoinThrd(pThis); /* Lock wtp mutex to safely check state and access thrdID atomically. * This prevents race where thread terminates and thrdID becomes invalid * between state check and pthread_kill/pthread_cancel calls. */ d_pthread_mutex_lock(&pWtp->mutWtp); state = wtiGetState(pThis); if (state == WRKTHRD_RUNNING || state == WRKTHRD_INITIALIZING) { thrdID = pThis->thrdID; /* Safe copy under mutex */ d_pthread_mutex_unlock(&pWtp->mutWtp); LogMsg(0, RS_RET_ERR, LOG_WARNING, "%s: need to do cooperative cancellation " "- some data may be lost, increase timeout?", cancelobj); pthread_kill(thrdID, SIGTTIN); DBGPRINTF("sent SIGTTIN to worker thread %p, giving it a chance to terminate\n", (void *)thrdID); srSleep(0, 50000); wtiJoinThrd(pThis); } else { d_pthread_mutex_unlock(&pWtp->mutWtp); if (state == WRKTHRD_STOPPED) { FINALIZE; /* Already stopped, nothing to do */ } } /* Second attempt with hard cancellation if needed */ d_pthread_mutex_lock(&pWtp->mutWtp); state = wtiGetState(pThis); if (state == WRKTHRD_RUNNING || state == WRKTHRD_INITIALIZING) { thrdID = pThis->thrdID; /* Safe copy under mutex */ d_pthread_mutex_unlock(&pWtp->mutWtp); LogMsg(0, RS_RET_ERR, LOG_WARNING, "%s: need to do hard cancellation", cancelobj); if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: need to do hard cancellation\n", cancelobj); } pthread_cancel(thrdID); pthread_kill(thrdID, SIGTTIN); DBGPRINTF("cooperative worker termination failed, using cancellation...\n"); DBGOPRINT((obj_t *)pThis, "canceling worker thread\n"); /* Wait for thread to terminate */ while ((state = wtiGetState(pThis)) != WRKTHRD_STOPPED && state != WRKTHRD_WAIT_JOIN) { DBGOPRINT((obj_t *)pThis, "waiting on termination, state %d\n", state); srSleep(0, 10000); } } else { d_pthread_mutex_unlock(&pWtp->mutWtp); } wtiJoinThrd(pThis); finalize_it: RETiRet; } /* note: this function is only called once in action.c */ rsRetVal wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams) { actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]); actWrkrIParams_t *iparams; size_t allocCount; size_t newMax; size_t startOffset; size_t zeroCount; DEFiRet; if (wrkrInfo->p.tx.currIParam == wrkrInfo->p.tx.maxIParams) { /* we need to extend */ newMax = (wrkrInfo->p.tx.maxIParams == 0) ? CONF_IPARAMS_BUFSIZE : 2u * (size_t)wrkrInfo->p.tx.maxIParams; if ((size_t)pAction->iNumTpls > SIZE_MAX / newMax) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } allocCount = (size_t)pAction->iNumTpls * newMax; if (allocCount > SIZE_MAX / sizeof(actWrkrIParams_t)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(iparams = realloc(wrkrInfo->p.tx.iparams, sizeof(actWrkrIParams_t) * allocCount)); startOffset = (size_t)wrkrInfo->p.tx.currIParam * (size_t)pAction->iNumTpls; zeroCount = ((size_t)newMax - (size_t)wrkrInfo->p.tx.maxIParams) * (size_t)pAction->iNumTpls; memset(iparams + startOffset, 0, sizeof(actWrkrIParams_t) * zeroCount); wrkrInfo->p.tx.iparams = iparams; wrkrInfo->p.tx.maxIParams = (int)newMax; } *piparams = wrkrInfo->p.tx.iparams + wrkrInfo->p.tx.currIParam * pAction->iNumTpls; ++wrkrInfo->p.tx.currIParam; finalize_it: RETiRet; } /* Destructor */ BEGINobjDestruct(wti) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(wti); if (wtiGetState(pThis) != WRKTHRD_STOPPED) { DBGPRINTF("%s: rsyslog bug: worker not stopped during shutdown\n", wtiGetDbgHdr(pThis)); if (dbgTimeoutToStderr) { fprintf(stderr, "RSYSLOG BUG: %s: worker not stopped during shutdown\n", wtiGetDbgHdr(pThis)); } else { assert(wtiGetState(pThis) == WRKTHRD_STOPPED); } } /* actual destruction */ batchFree(&pThis->batch); free(pThis->actWrkrInfo); pthread_cond_destroy(&pThis->pcondBusy); DESTROY_ATOMIC_HELPER_MUT(pThis->mutIsRunning); free(pThis->pszDbgHdr); ENDobjDestruct(wti) /* Standard-Constructor for the wti object */ BEGINobjConstruct(wti) /* be sure to specify the object type also in END macro! */ INIT_ATOMIC_HELPER_MUT(pThis->mutIsRunning); pthread_cond_init(&pThis->pcondBusy, NULL); ENDobjConstruct(wti) /* Construction finalizer * rgerhards, 2008-01-17 */ rsRetVal wtiConstructFinalize(wti_t *pThis) { DEFiRet; int iDeqBatchSize; ISOBJ_TYPE_assert(pThis, wti); DBGPRINTF("%s: finalizing construction of worker instance data (for %d actions)\n", wtiGetDbgHdr(pThis), runConf->actions.iActionNbr); /* initialize our thread instance descriptor (no concurrency here) */ pThis->bIsRunning = WRKTHRD_STOPPED; /* must use calloc as we need zero-init */ CHKmalloc(pThis->actWrkrInfo = calloc(runConf->actions.iActionNbr, sizeof(actWrkrInfo_t))); if (pThis->pWtp == NULL) { dbgprintf("wtiConstructFinalize: pWtp not set, this may be intentional\n"); FINALIZE; } /* we now alloc the array for user pointers. We obtain the max from the queue itself. */ CHKiRet(pThis->pWtp->pfGetDeqBatchSize(pThis->pWtp->pUsr, &iDeqBatchSize)); CHKiRet(batchInit(&pThis->batch, iDeqBatchSize)); finalize_it: RETiRet; } /* cancellation cleanup handler for queueWorker () * Most importantly, it must bring back the batch into a consistent state. * Keep in mind that cancellation is disabled if we run into * the cancel cleanup handler (and have been cancelled). * rgerhards, 2008-01-16 */ static void wtiWorkerCancelCleanup(void *arg) { wti_t *pThis = (wti_t *)arg; wtp_t *pWtp; ISOBJ_TYPE_assert(pThis, wti); pWtp = pThis->pWtp; ISOBJ_TYPE_assert(pWtp, wtp); DBGPRINTF("%s: cancellation cleanup handler called.\n", wtiGetDbgHdr(pThis)); pWtp->pfObjProcessed(pWtp->pUsr, pThis); DBGPRINTF("%s: done cancellation cleanup handler.\n", wtiGetDbgHdr(pThis)); } /* wait for queue to become non-empty or timeout * this is introduced as helper to support queue minimum batch sizes, but may * also be used for other cases. This function waits until the queue is non-empty * or a timeout occurs. The timeout must be passed in as absolute value. * @returns 0 if timeout occurs (queue still empty), something else otherwise */ int ATTR_NONNULL() wtiWaitNonEmpty(wti_t *const pThis, const struct timespec timeout) { wtp_t *__restrict__ const pWtp = pThis->pWtp; int r; DBGOPRINT((obj_t *)pThis, "waiting on queue to become non-empty\n"); if (d_pthread_cond_timedwait(&pThis->pcondBusy, pWtp->pmutUsr, &timeout) != 0) { r = 0; } else { r = 1; } DBGOPRINT((obj_t *)pThis, "waited on queue to become non-empty, result %d\n", r); return r; } /* wait for queue to become non-empty or timeout * helper to wtiWorker. Note the the predicate is * re-tested by the caller, so it is OK to NOT do it here. * rgerhards, 2009-05-20 */ static void ATTR_NONNULL() doIdleProcessing(wti_t *const pThis, wtp_t *const pWtp, int *const pbInactivityTOOccurred) { struct timespec t; DBGPRINTF("%s: worker IDLE, waiting for work.\n", wtiGetDbgHdr(pThis)); if (pThis->bAlwaysRunning) { /* never shut down any started worker */ d_pthread_cond_wait(&pThis->pcondBusy, pWtp->pmutUsr); } else { const int timeout = pThis->workerIndex == 0 && pWtp->toFirstWrkShutdown != -2 ? pWtp->toFirstWrkShutdown : pWtp->toWrkShutdown; timeoutComp(&t, timeout); /* get absolute timeout */ if (d_pthread_cond_timedwait(&pThis->pcondBusy, pWtp->pmutUsr, &t) != 0) { DBGPRINTF("%s: inactivity timeout, worker terminating...\n", wtiGetDbgHdr(pThis)); *pbInactivityTOOccurred = 1; /* indicate we had a timeout */ } } DBGOPRINT((obj_t *)pThis, "worker awoke from idle processing\n"); } /* generic worker thread framework. Note that we prohibit cancellation * during almost all times, because it can have very undesired side effects. * However, we may need to cancel a thread if the consumer blocks for too * long (during shutdown). So what we do is block cancellation, and every * consumer must enable it during the periods where it is safe. */ PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wempty_body rsRetVal wtiWorker(wti_t *__restrict__ const pThis) { wtp_t *__restrict__ const pWtp = pThis->pWtp; /* our worker thread pool -- shortcut */ action_t *__restrict__ pAction; rsRetVal localRet; rsRetVal terminateRet; actWrkrInfo_t *__restrict__ wrkrInfo; int iCancelStateSave; int i, j, k; DEFiRet; dbgSetThrdName(pThis->pszDbgHdr); pthread_cleanup_push(wtiWorkerCancelCleanup, pThis); int bInactivityTOOccurred = 0; /* Cancellation contract: * - default state is DISABLE in worker context * - queue consumers enable it only around explicitly cancel-safe work * - critical cleanup/state transitions run with cancellation disabled */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); DBGPRINTF("wti %p: worker starting\n", pThis); /* now we have our identity, on to real processing */ /* note: in this loop, the mutex is "never" unlocked. Of course, * this is not true: it actually is unlocked when the actual processing * is done, as part of pWtp->pfDoWork() processing. Note that this * function is required to re-lock it when done. We cannot do the * lock/unlock here ourselves, as pfDoWork() needs to access queue * structures itself. * The same goes for pfRateLimiter(). While we could unlock/lock when * we call it, in practice the function is often called without any * ratelimiting actually done. Only the rate limiter itself knows * that. As such, it needs to bear the burden of doing the locking * when required. -- rgerhards, 2013-11-20 */ d_pthread_mutex_lock(pWtp->pmutUsr); while (1) { /* loop will be broken below */ if (pWtp->pfRateLimiter != NULL) { /* call rate-limiter, if defined */ pWtp->pfRateLimiter(pWtp->pUsr); } /* first check if we are in shutdown process (but evaluate a bit later) */ terminateRet = wtpChkStopWrkr(pWtp, MUTEX_ALREADY_LOCKED); if (terminateRet == RS_RET_TERMINATE_NOW) { /* we now need to free the old batch */ localRet = pWtp->pfObjProcessed(pWtp->pUsr, pThis); DBGOPRINT((obj_t *)pThis, "terminating worker because of " "TERMINATE_NOW mode, del iRet %d\n", localRet); break; } /* try to execute and process whatever we have */ localRet = pWtp->pfDoWork(pWtp->pUsr, pThis); if (localRet == RS_RET_ERR_QUEUE_EMERGENCY) { break; /* end of loop */ } else if (localRet == RS_RET_IDLE) { if (terminateRet == RS_RET_TERMINATE_WHEN_IDLE || bInactivityTOOccurred) { if (bInactivityTOOccurred && pWtp->pfIdleTimeout != NULL && pWtp->pWrkr[0] == pThis && pWtp->pfIdleTimeout(pWtp->pUsr) == RS_RET_RETRY) { bInactivityTOOccurred = 0; continue; } DBGOPRINT((obj_t *)pThis, "terminating worker terminateRet=%d, " "bInactivityTOOccurred=%d\n", terminateRet, bInactivityTOOccurred); break; /* end of loop */ } doIdleProcessing(pThis, pWtp, &bInactivityTOOccurred); continue; /* request next iteration */ } bInactivityTOOccurred = 0; /* reset for next run */ } d_pthread_mutex_unlock(pWtp->pmutUsr); DBGPRINTF("DDDD: wti %p: worker cleanup action instances\n", pThis); for (i = 0; i < runConf->actions.iActionNbr; ++i) { wrkrInfo = &(pThis->actWrkrInfo[i]); dbgprintf("wti %p, action %d, ptr %p\n", pThis, i, wrkrInfo->actWrkrData); if (wrkrInfo->actWrkrData != NULL) { pAction = wrkrInfo->pAction; actionRemoveWorker(pAction, wrkrInfo->actWrkrData); pAction->pMod->mod.om.freeWrkrInstance(wrkrInfo->actWrkrData); if (pAction->isTransactional) { /* free iparam "cache" - we need to go through to max! */ for (j = 0; j < wrkrInfo->p.tx.maxIParams; ++j) { for (k = 0; k < pAction->iNumTpls; ++k) { free(actParam(wrkrInfo->p.tx.iparams, pAction->iNumTpls, j, k).param); } } free(wrkrInfo->p.tx.iparams); wrkrInfo->p.tx.iparams = NULL; wrkrInfo->p.tx.currIParam = 0; wrkrInfo->p.tx.maxIParams = 0; } else { releaseDoActionParams(pAction, pThis, 1); } wrkrInfo->actWrkrData = NULL; /* re-init for next activation */ } } /* indicate termination */ pthread_cleanup_pop(0); /* remove cleanup handler */ pthread_setcancelstate(iCancelStateSave, NULL); dbgprintf("wti %p: exiting\n", pThis); RETiRet; } PRAGMA_DIAGNOSTIC_POP /* some simple object access methods */ rsRetVal wtiSetpWtp(wti_t *pThis, wtp_t *pVal) { pThis->pWtp = pVal; return RS_RET_OK; } /* set the debug header message * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. Must be called only before object is finalized. * rgerhards, 2008-01-09 */ rsRetVal wtiSetDbgHdr(wti_t *pThis, uchar *pszMsg, const size_t lenMsg) { DEFiRet; ISOBJ_TYPE_assert(pThis, wti); assert(pszMsg != NULL); if (lenMsg < 1) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (pThis->pszDbgHdr != NULL) { free(pThis->pszDbgHdr); } if ((pThis->pszDbgHdr = malloc(lenMsg + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pszDbgHdr, pszMsg, lenMsg + 1); /* always think about the \0! */ finalize_it: RETiRet; } /* This function returns (and creates if necessary) a dummy wti suitable * for use by the rule engine. It is intended to be used for direct-mode * main queues (folks, don't do that!). Once created, data is stored in * thread-specific storage. * Note: we do NOT do error checking -- if this functions fails, all the * rest will fail as well... (also, it will only fail under OOM, so...). * Memleak: we leak pWti's when run in direct mode. However, this is only * a cosmetic leak, as we need them until all inputs are terminated, * what means essentially until rsyslog itself is terminated. So we * don't care -- it's just not nice in valgrind, but that's it. */ wti_t *wtiGetDummy(void) { wti_t *pWti; pWti = (wti_t *)pthread_getspecific(thrd_wti_key); if (pWti == NULL) { wtiConstruct(&pWti); if (pWti != NULL) wtiConstructFinalize(pWti); if (pthread_setspecific(thrd_wti_key, pWti) != 0) { DBGPRINTF("wtiGetDummy: error setspecific thrd_wti_key\n"); } } return pWti; } /* dummy */ static rsRetVal wtiQueryInterface(interface_t __attribute__((unused)) * i) { return RS_RET_NOT_IMPLEMENTED; } /* exit our class */ BEGINObjClassExit(wti, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(wti); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); pthread_key_delete(thrd_wti_key); ENDObjClassExit(wti) /* Initialize the wti class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-01-09 */ BEGINObjClassInit(wti, 1, OBJ_IS_CORE_MODULE) /* one is the object version (most important for persisting) */ int r; /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); r = pthread_key_create(&thrd_wti_key, NULL); if (r != 0) { dbgprintf("wti.c: pthread_key_create failed\n"); ABORT_FINALIZE(RS_RET_ERR); } ENDObjClassInit(wti) rsyslog-8.2608.0/runtime/PaxHeaders/gss-misc.h0000644000000000000000000000013215171370365016130 xustar0030 mtime=1776677109.436913002 30 atime=1782715518.779788687 30 ctime=1787067794.520727403 rsyslog-8.2608.0/runtime/gss-misc.h0000664000175000017500000000305115171370365015573 0ustar00rgerrger/* Definitions for gssutil class. This implements a session of the * plain TCP server. * * Copyright 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef GSS_MISC_H_INCLUDED #define GSS_MISC_H_INCLUDED 1 #include #include #include "obj.h" /* interfaces */ BEGINinterface(gssutil) /* name must also be changed in ENDinterface macro! */ int (*recv_token)(int s, gss_buffer_t tok, size_t max_tok_len, unsigned int timeout_secs); int (*send_token)(int s, gss_buffer_t tok); void (*display_status)(char *m, OM_uint32 maj_stat, OM_uint32 min_stat); void (*display_ctx_flags)(OM_uint32 flags); ENDinterface(gssutil) #define gssutilCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(gssutil); /* the name of our library binary */ #define LM_GSSUTIL_FILENAME "lmgssutil" #endif /* #ifndef GSS_MISC_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/timezones.h0000644000000000000000000000013115132411300016375 xustar0029 mtime=1768559296.27888583 30 atime=1787067616.836415376 30 ctime=1787067794.502727067 rsyslog-8.2608.0/runtime/timezones.h0000666000175000017500000000221115132411300016040 0ustar00rgerrger/* header for timezones.c * * Copyright 2022 Attila Lakatos and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_TIMEZONES_H #define INCLUDED_TIMEZONES_H #include "rsconf.h" /* timezone specific parameters*/ struct timezones_s { tzinfo_t *tzinfos; int ntzinfos; }; void displayTimezones(rsconf_t *cnf); void sortTimezones(rsconf_t *cnf); void glblProcessTimezone(struct cnfobj *o); tzinfo_t *glblFindTimezone(rsconf_t *cnf, char *id); void freeTimezones(rsconf_t *cnf); #endif rsyslog-8.2608.0/runtime/PaxHeaders/rsconf.h0000644000000000000000000000013115241075234015667 xustar0029 mtime=1787067036.60857835 30 atime=1787067036.756581122 30 ctime=1787067794.293723173 rsyslog-8.2608.0/runtime/rsconf.h0000664000175000017500000003517615241075234015350 0ustar00rgerrger/* The rsconf object. It models a complete rsyslog configuration. * * Copyright 2011-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_RSCONF_H #define INCLUDED_RSCONF_H #include "linkedlist.h" #include "queue.h" #include "lookup.h" #include "dynstats.h" #include "perctile_stats.h" #include "timezones.h" #include "ratelimit.h" /* --- configuration objects (the plan is to have ALL upper layers in this file) --- */ #define REPORT_CHILD_PROCESS_EXITS_NONE 0 #define REPORT_CHILD_PROCESS_EXITS_ERRORS 1 #define REPORT_CHILD_PROCESS_EXITS_ALL 2 #define COMPAT_CONFIGFORMAT_ENABLE 0 #define COMPAT_CONFIGFORMAT_WARN 1 #define COMPAT_CONFIGFORMAT_DISABLE 2 #define COMPAT_DEFAULTS_SECURE_STRICT 0 #define COMPAT_DEFAULTS_SECURE_BACKWARD_COMPATIBLE 1 #define COMPAT_DEFAULTS_SECURE_WARN 2 #ifndef DFLT_INT_MSGS_SEV_FILTER #define DFLT_INT_MSGS_SEV_FILTER 6 /* Warning level and more important */ #endif struct queuecnf_s { int iMainMsgQueueSize; /* size of the main message queue above */ int iMainMsgQHighWtrMark; /* high water mark for disk-assisted queues */ int iMainMsgQLowWtrMark; /* low water mark for disk-assisted queues */ int iMainMsgQDiscardMark; /* begin to discard messages */ int iMainMsgQDiscardSeverity; /* by default, discard nothing to prevent unintentional loss */ int iMainMsgQueueNumWorkers; /* number of worker threads for the mm queue above */ queueType_t MainMsgQueType; /* type of the main message queue above */ uchar *pszMainMsgQFName; /* prefix for the main message queue file */ int64 iMainMsgQueMaxFileSize; int iMainMsgQPersistUpdCnt; /* persist queue info every n updates */ int bMainMsgQSyncQeueFiles; /* sync queue files on every write? */ int iMainMsgQtoQShutdown; /* queue shutdown (ms) */ int iMainMsgQtoActShutdown; /* action shutdown (in phase 2) */ int iMainMsgQtoEnq; /* timeout for queue enque */ int iMainMsgQtoWrkShutdown; /* timeout for worker thread shutdown */ int iMainMsgQWrkMinMsgs; /* minimum messages per worker needed to start a new one */ int iMainMsgQDeqSlowdown; /* dequeue slowdown (simple rate limiting) */ int64 iMainMsgQueMaxDiskSpace; /* max disk space allocated 0 ==> unlimited */ int64 iMainMsgQueDeqBatchSize; /* dequeue batch size */ int bMainMsgQSaveOnShutdown; /* save queue on shutdown (when DA enabled)? */ int iMainMsgQueueDeqtWinFromHr; /* hour begin of time frame when queue is to be dequeued */ int iMainMsgQueueDeqtWinToHr; /* hour begin of time frame when queue is to be dequeued */ }; /* parser config parameters */ struct parsercnf_s { uchar cCCEscapeChar; /* character to be used to start an escape sequence for control chars */ int bDropTrailingLF; /* drop trailing LF's on reception? */ int bDropTrailingCR; /* drop trailing CR's on reception? */ int bEscapeCCOnRcv; /* escape control characters on reception: 0 - no, 1 - yes */ int bSpaceLFOnRcv; /* replace newlines with spaces on reception: 0 - no, 1 - yes */ int bEscape8BitChars; /* escape characters > 127 on reception: 0 - no, 1 - yes */ int bEscapeTab; /* escape tab control character when doing CC escapes: 0 - no, 1 - yes */ int bParserEscapeCCCStyle; /* escape control characters in c style: 0 - no, 1 - yes */ int bPermitSlashInProgramname; int bParseHOSTNAMEandTAG; /* parser modification (based on startup params!) */ }; /* globals are data items that are really global, and can be set only * once (at least in theory, because the legacy system permits them to * be re-set as often as the user likes). */ struct globals_s { #ifdef ENABLE_LIBCAPNG int bAbortOnFailedLibcapngSetup; int bCapabilityDropEnabled; #endif int bDebugPrintTemplateList; int bDebugPrintModuleList; int bDebugPrintCfSysLineHandlerList; int bLogStatusMsgs; /* log rsyslog start/stop/HUP messages? */ int bAllMsgToStderr; /* print all internal messages to stderr */ int bErrMsgToStderr; /* print error messages to stderr (in addition to everything else)? */ int maxErrMsgToStderr; /* how many messages to forward at most to stderr? */ int bAbortOnUncleanConfig; /* abort run (rather than starting with partial config) if there was any issue in conf */ int bAbortOnFailedQueueStartup; /* similar to bAbortOnUncleanConfig, but abort if a queue startup fails. This is not exactly an unclan config. */ int compatConfigFormatLegacy; /* policy for legacy $-directives */ int compatConfigFormatSyslogd; /* policy for classic syslogd PRI selectors */ int compatConfigFormatProperty; /* policy for classic property-based selector filters */ int compatDefaultsSecure; /* policy for defaults that affect secure-by-default behavior */ int systemdNotifyReadyDelay; /* delay sd_notify READY=1 until opt-in modules report ready */ int uidDropPriv; /* user-id to which priveleges should be dropped to */ int gidDropPriv; /* group-id to which priveleges should be dropped to */ int gidDropPrivKeepSupplemental; /* keep supplemental groups when dropping? */ int abortOnIDResolutionFail; int umask; /* umask to use */ uchar *pszConfDAGFile; /* name of config DAG file, non-NULL means generate one */ uchar *pszWorkDir; int bDropMalPTRMsgs; /* Drop messages which have malicious PTR records during DNS lookup */ uchar *operatingStateFile; int debugOnShutdown; /* start debug log when we are shut down */ int iGnuTLSLoglevel; /* Sets GNUTLS Debug Level */ uchar *pszDfltNetstrmDrvrCAF; /* default CA file for the netstrm driver */ uchar *pszDfltNetstrmDrvrCRLF; /* default CRL file for the netstrm driver */ uchar *pszDfltNetstrmDrvrCertFile; /* default cert file for the netstrm driver (server) */ uchar *pszDfltNetstrmDrvrKeyFile; /* default key file for the netstrm driver (server) */ uchar *pszDfltNetstrmDrvr; /* module name of default netstream driver */ uchar *pszNetstrmDrvrCAExtraFiles; /* CA extra file for the netstrm driver */ uchar *pszDfltOpensslEngine; /* custom openssl engine */ uchar *oversizeMsgErrorFile; /* File where oversize messages are written to */ int reportOversizeMsg; /* shall error messages be generated for oversize messages? */ int oversizeMsgInputMode; /* Mode which oversize messages will be forwarded */ int reportChildProcessExits; int bActionReportSuspension; int bActionReportSuspensionCont; short janitorInterval; /* interval (in minutes) at which the janitor runs */ int reportNewSenders; int reportGoneAwaySenders; int senderStatsTimeout; int senderKeepTrack; /* keep track of known senders? */ int inputTimeoutShutdown; /* input shutdown timeout in ms */ int iDefPFFamily; /* protocol family (IPv4, IPv6 or both) */ int ACLAddHostnameOnFail; /* add hostname to acl when DNS resolving has failed */ int ACLDontResolve; /* add hostname to acl instead of resolving it to IP(s) */ int bDisableDNS; /* don't look up IP addresses of remote messages */ int bProcessInternalMessages; /* Should rsyslog itself process internal messages? * 1 - yes * 0 - send them to libstdlog (e.g. to push to journal) or syslog() */ int iMaxOpenFiles; /* requested RLIMIT_NOFILE value, 0 means leave OS limit unchanged */ uint64_t glblDevOptions; /* to be used by developers only */ int intMsgRateLimitItv; int intMsgRateLimitBurst; int intMsgsSeverityFilter; /* filter for logging internal messages by syslog sev. */ int permitCtlC; int actq_dflt_toQShutdown; /* queue shutdown */ int actq_dflt_toActShutdown; /* action shutdown (in phase 2) */ int actq_dflt_toEnq; /* timeout for queue enque */ int actq_dflt_toWrkShutdown; /* timeout for worker thread shutdown */ int ruleset_dflt_toQShutdown; /* queue shutdown */ int ruleset_dflt_toActShutdown; /* action shutdown (in phase 2) */ int ruleset_dflt_toEnq; /* timeout for queue enque */ int ruleset_dflt_toWrkShutdown; /* timeout for worker thread shutdown */ unsigned dnscacheDefaultTTL; /* 24 hrs default TTL */ int dnscacheEnableTTL; /* expire entries or not (0) ? */ int shutdownQueueDoubleSize; int optionDisallowWarning; /* complain if message from disallowed sender is received */ int bSupportCompressionExtension; #ifdef ENABLE_LIBLOGGING_STDLOG stdlog_channel_t stdlog_hdl; /* handle to be used for stdlog */ uchar *stdlog_chanspec; #endif int iMaxLine; /* maximum length of a syslog message */ // TODO are the following ones defaults? int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */ // TODO: other representation for main queue? Or just load it differently? queuecnf_t mainQ; /* main queue parameters */ parsercnf_t parser; /* parser parameters */ }; /* (global) defaults are global in the sense that they are accessible * to all code, but they can change value and other objects (like * actions) actually copy the value a global had at the time the action * was defined. In that sense, a global default is just that, a default, * wich can (and will) be changed in the course of config file * processing. Once the config file has been processed, defaults * can be dropped. The current code does not do this for simplicity. * That is not a problem, because the defaults do not take up much memory. * At a later stage, we may think about dropping them. -- rgerhards, 2011-04-19 */ struct defaults_s { int remove_me_when_first_real_member_is_added; }; /* list of modules loaded in this configuration (config specific module list) */ struct cfgmodules_etry_s { cfgmodules_etry_t *next; modInfo_t *pMod; void *modCnf; /* pointer to the input module conf */ /* the following data is input module specific */ sbool canActivate; /* OK to activate this config? */ sbool canRun; /* OK to run this config? */ }; struct cfgmodules_s { cfgmodules_etry_t *root; }; /* outchannel-specific data */ struct outchannels_s { struct outchannel *ochRoot; /* the root of the outchannel list */ struct outchannel *ochLast; /* points to the last element of the outchannel list */ }; struct templates_s { struct template *root; /* the root of the template list */ struct template *last; /* points to the last element of the template list */ struct template *lastStatic; /* last static element of the template list */ }; struct parsers_s { /* This is the list of all parsers known to us. * This is also used to unload all modules on shutdown. */ parserList_t *pParsLstRoot; /* this is the list of the default parsers, to be used if no others * are specified. */ parserList_t *pDfltParsLst; }; struct actions_s { /* number of active actions */ unsigned nbrActions; /* number of actions created. It is used to obtain unique IDs for the action. They * should not be relied on for any long-term activity (e.g. disk queue names!), but they are nice * to have during one instance of an rsyslogd run. For example, I use them to name actions when there * is no better name available. */ int iActionNbr; char **action_names; size_t n_action_names; size_t n_action_names_alloc; }; struct rulesets_s { linkedList_t llRulesets; /* this is NOT a pointer - no typo here ;) */ /* support for legacy rsyslog.conf format */ ruleset_t *pCurr; /* currently "active" ruleset */ ruleset_t *pDflt; /* current default ruleset, e.g. for binding to actions which have no other */ }; /* --- end configuration objects --- */ /* the rsconf object */ struct rsconf_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ cfgmodules_t modules; globals_t globals; defaults_t defaults; templates_t templates; parsers_t parsers; lookup_tables_t lu_tabs; dynstats_buckets_t dynstats_buckets; perctile_buckets_t perctile_buckets; outchannels_t och; actions_t actions; rulesets_t rulesets; /* note: rulesets include the complete output part: * - rules * - filter (as part of the action) * - actions * Of course, we need to debate if we shall change that some time... */ timezones_t timezones; qqueue_t *pMsgQueue; /* the main message queue */ ratelimit_cfgs_t ratelimit_cfgs; }; /* interfaces */ BEGINinterface(rsconf) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(rsconf); rsRetVal (*Destruct)(rsconf_t **ppThis); rsRetVal (*Load)(rsconf_t **ppThis, uchar *confFile); rsRetVal (*Activate)(rsconf_t *ppThis); ENDinterface(rsconf) // TODO: switch version to 1 for first "complete" version!!!! 2011-04-20 #define rsconfCURR_IF_VERSION 0 /* increment whenever you change the interface above! */ /* prototypes */ PROTOTYPEObjFull(rsconf); /* globally-visible external data */ extern rsconf_t *runConf; /* the currently running config */ extern rsconf_t *loadConf; /* the config currently being loaded (no concurrent config load supported!) */ int rsconfNeedDropPriv(rsconf_t *const cnf); /* module readiness barrier (see rsconf.c for details). * Only meaningful when rsyslog is managed by systemd; stubs compile away * otherwise so imfile and other opt-in modules need no #ifdef guards. */ #ifdef HAVE_LIBSYSTEMD void rsconfRegisterReadiness(void); void rsconfSignalReady(void); void rsconfWaitForModulesReady(void); void rsconfReadyNotifySent(void); int rsconfShouldDelayReadyNotify(rsconf_t *cnf); #else static inline void rsconfRegisterReadiness(void) {} static inline void rsconfSignalReady(void) {} #endif /* some defaults (to be removed?) */ #define DFLT_bLogStatusMsgs 1 #endif /* #ifndef INCLUDED_RSCONF_H */ rsyslog-8.2608.0/runtime/PaxHeaders/glbl.c0000644000000000000000000000013215241075234015311 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.277722875 rsyslog-8.2608.0/runtime/glbl.c0000664000175000017500000021652215241075234014765 0ustar00rgerrger/* glbl.c - this module holds global defintions and data items. * These are shared among the runtime library. Their use should be * limited to cases where it is actually needed. The main intension for * implementing them was support for the transistion from v2 to v4 * (with fully modular design), but it turned out that there may also * be some other good use cases besides backwards-compatibility. * * Module begun 2008-04-16 by Rainer Gerhards * * Copyright 2008-2024 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "obj.h" #include "unicode-helper.h" #include "cfsysline.h" #include "glbl.h" #include "prop.h" #include "atomic.h" #include "errmsg.h" #include "action.h" #include "parserif.h" #include "rainerscript.h" #include "srUtils.h" #include "operatingstate.h" #include "net.h" #include "rsconf.h" #include "queue.h" #include "dnscache.h" #include "parser.h" #include "timezones.h" /* some defaults */ #ifndef DFLT_NETSTRM_DRVR #define DFLT_NETSTRM_DRVR ((uchar *)"ptcp") #endif /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(prop) DEFobjCurrIf(net) /* static data * For this object, these variables are obviously what makes the "meat" of the * class... */ static struct cnfobj *mainqCnfObj = NULL; /* main queue object, to be used later in startup sequence */ static int bPreserveFQDN = 0; /* should FQDNs always be preserved? */ static prop_t *propLocalIPIF = NULL; /* IP address to report for the local host (default is 127.0.0.1) */ static int propLocalIPIF_set = 0; /* is propLocalIPIF already set? */ static prop_t *propLocalHostName = NULL; /* our hostname as FQDN - read-only after startup */ static prop_t *propLocalHostNameToDelete = NULL; /* see GenerateLocalHostName function hdr comment! */ static uchar *LocalHostName = NULL; /* our hostname - read-only after startup, except HUP */ static uchar *LocalHostNameOverride = NULL; /* user-overridden hostname - read-only after startup */ static uchar *LocalFQDNName = NULL; /* our hostname as FQDN - read-only after startup, except HUP */ static uchar *LocalDomain = NULL; /* our local domain name - read-only after startup, except HUP */ static int iMaxLine = 8096; int bTerminateInputs = 0; /* global switch that inputs shall terminate ASAP (1=> terminate) */ volatile sig_atomic_t bTerminateInputsSigSafe = 0; int glblUnloadModules = 1; int glblAbortOnProgramError = 0; char **glblDbgFiles = NULL; size_t glblDbgFilesNum = 0; int glblDbgWhitelist = 1; int glblPermitCtlC = 0; /* For global option CompactJsonString: * Compact the JSON variable string, without extra space. * Considering compatibility issues, the default options(CompactJsonString = "off") * keep the same as before. */ int glblJsonFormatOpt = JSON_C_TO_STRING_SPACED; pid_t glbl_ourpid; #ifndef HAVE_ATOMIC_BUILTINS DEF_ATOMIC_HELPER_MUT(mutTerminateInputs); #endif #ifdef USE_UNLIMITED_SELECT static int iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof(fd_mask); /* size of select() bitmask in bytes */ #endif static uchar *SourceIPofLocalClient = NULL; /* [ar] Source IP for local client to be used on multihomed host */ static uchar *GetDfltNetstrmDrvr(rsconf_t *cnf); /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfparamdescr[] = { {"workdirectory", eCmdHdlrString, 0}, {"operatingstatefile", eCmdHdlrString, 0}, {"dropmsgswithmaliciousdnsptrrecords", eCmdHdlrBinary, 0}, {"localhostname", eCmdHdlrGetWord, 0}, {"compactjsonstring", eCmdHdlrBinary, 0}, {"preservefqdn", eCmdHdlrBinary, 0}, {"debug.onshutdown", eCmdHdlrBinary, 0}, {"debug.logfile", eCmdHdlrString, 0}, {"debug.gnutls", eCmdHdlrNonNegInt, 0}, {"debug.abortonprogramerror", eCmdHdlrBinary, 0}, {"debug.unloadmodules", eCmdHdlrBinary, 0}, {"defaultnetstreamdrivercafile", eCmdHdlrString, 0}, {"defaultnetstreamdrivercrlfile", eCmdHdlrString, 0}, {"defaultnetstreamdriverkeyfile", eCmdHdlrString, 0}, {"defaultnetstreamdrivercertfile", eCmdHdlrString, 0}, {"defaultnetstreamdriver", eCmdHdlrString, 0}, {"defaultopensslengine", eCmdHdlrString, 0}, {"netstreamdrivercaextrafiles", eCmdHdlrString, 0}, {"maxmessagesize", eCmdHdlrSize, 0}, {"oversizemsg.errorfile", eCmdHdlrGetWord, 0}, {"oversizemsg.report", eCmdHdlrBinary, 0}, {"oversizemsg.input.mode", eCmdHdlrGetWord, 0}, {"reportchildprocessexits", eCmdHdlrGetWord, 0}, {"action.reportsuspension", eCmdHdlrBinary, 0}, {"action.reportsuspensioncontinuation", eCmdHdlrBinary, 0}, {"parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0}, {"parser.droptrailinglfonreception", eCmdHdlrBinary, 0}, {"parser.droptrailingcronreception", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0}, {"parser.spacelfonreceive", eCmdHdlrBinary, 0}, {"parser.escape8bitcharactersonreceive", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharactertab", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0}, {"parser.parsehostnameandtag", eCmdHdlrBinary, 0}, {"parser.permitslashinprogramname", eCmdHdlrBinary, 0}, {"stdlog.channelspec", eCmdHdlrString, 0}, {"janitor.interval", eCmdHdlrPositiveInt, 0}, {"senders.reportnew", eCmdHdlrBinary, 0}, {"senders.reportgoneaway", eCmdHdlrBinary, 0}, {"senders.timeoutafter", eCmdHdlrPositiveInt, 0}, {"senders.keeptrack", eCmdHdlrBinary, 0}, {"inputs.timeout.shutdown", eCmdHdlrPositiveInt, 0}, {"privdrop.group.keepsupplemental", eCmdHdlrBinary, 0}, {"privdrop.group.id", eCmdHdlrPositiveInt, 0}, {"privdrop.group.name", eCmdHdlrGID, 0}, {"privdrop.user.id", eCmdHdlrPositiveInt, 0}, {"privdrop.user.name", eCmdHdlrUID, 0}, {"net.ipprotocol", eCmdHdlrGetWord, 0}, {"net.acladdhostnameonfail", eCmdHdlrBinary, 0}, {"net.aclresolvehostname", eCmdHdlrBinary, 0}, {"net.enabledns", eCmdHdlrBinary, 0}, {"net.permitACLwarning", eCmdHdlrBinary, 0}, {"maxopenfiles", eCmdHdlrPositiveInt, 0}, {"compatibility.configformat.legacy", eCmdHdlrGetWord, 0}, {"compatibility.configformat.syslogd", eCmdHdlrGetWord, 0}, {"compatibility.configformat.property", eCmdHdlrGetWord, 0}, {"compatibility.defaults.secure", eCmdHdlrGetWord, 0}, {"systemd.notifyreadydelay", eCmdHdlrBinary, 0}, {"abortonuncleanconfig", eCmdHdlrBinary, 0}, {"abortonfailedqueuestartup", eCmdHdlrBinary, 0}, {"variables.casesensitive", eCmdHdlrBinary, 0}, {"environment", eCmdHdlrArray, 0}, {"processinternalmessages", eCmdHdlrBinary, 0}, {"umask", eCmdHdlrFileCreateMode, 0}, {"security.abortonidresolutionfail", eCmdHdlrBinary, 0}, {"internal.developeronly.options", eCmdHdlrInt, 0}, {"internalmsg.ratelimit.interval", eCmdHdlrPositiveInt, 0}, {"internalmsg.ratelimit.burst", eCmdHdlrPositiveInt, 0}, {"internalmsg.severity", eCmdHdlrSeverity, 0}, {"allmessagestostderr", eCmdHdlrBinary, 0}, {"errormessagestostderr.maxnumber", eCmdHdlrPositiveInt, 0}, {"shutdown.enable.ctlc", eCmdHdlrBinary, 0}, {"default.action.queue.timeoutshutdown", eCmdHdlrInt, 0}, {"default.action.queue.timeoutactioncompletion", eCmdHdlrInt, 0}, {"default.action.queue.timeoutenqueue", eCmdHdlrInt, 0}, {"default.action.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutshutdown", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutactioncompletion", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutenqueue", eCmdHdlrInt, 0}, {"default.ruleset.queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0}, {"reverselookup.cache.ttl.default", eCmdHdlrNonNegInt, 0}, {"reverselookup.cache.ttl.enable", eCmdHdlrBinary, 0}, {"parser.supportcompressionextension", eCmdHdlrBinary, 0}, {"shutdown.queue.doublesize", eCmdHdlrBinary, 0}, {"debug.files", eCmdHdlrArray, 0}, {"debug.whitelist", eCmdHdlrBinary, 0}, {"libcapng.default", eCmdHdlrBinary, 0}, {"libcapng.enable", eCmdHdlrBinary, 0}, }; static struct cnfparamblk paramblk = {CNFPARAMBLK_VERSION, sizeof(cnfparamdescr) / sizeof(struct cnfparamdescr), cnfparamdescr}; static struct cnfparamvals *cnfparamvals = NULL; /* we need to support multiple calls into our param block, so we need * to persist the current settings. Note that this must be re-set * each time a new config load begins. This is a hint if we will * ever implement multi-config support, which is just an idea right now. */ int glblGetMaxLine(rsconf_t *cnf) { /* glblGetMaxLine might be invoked before our configuration exists */ return ((cnf != NULL) ? cnf->globals.iMaxLine : iMaxLine); } int GetGnuTLSLoglevel(rsconf_t *cnf) { /* * Loadable netstream drivers can be initialized while a configuration is * still being parsed, before runConf points at an active configuration. */ if (cnf == NULL) { cnf = loadConf; } return ((cnf != NULL) ? cnf->globals.iGnuTLSLoglevel : 0); } /* define a macro for the simple properties' set and get functions * (which are always the same). This is only suitable for pretty * simple cases which require neither checks nor memory allocation. */ #define SIMP_PROP(nameFunc, nameVar, dataType) \ SIMP_PROP_GET(nameFunc, nameVar, dataType) \ SIMP_PROP_SET(nameFunc, nameVar, dataType) #define SIMP_PROP_SET(nameFunc, nameVar, dataType) \ static rsRetVal Set##nameFunc(dataType newVal) { \ nameVar = newVal; \ return RS_RET_OK; \ } #define SIMP_PROP_GET(nameFunc, nameVar, dataType) \ static dataType Get##nameFunc(void) { \ return (nameVar); \ } SIMP_PROP(PreserveFQDN, bPreserveFQDN, int) SIMP_PROP(mainqCnfObj, mainqCnfObj, struct cnfobj *) #ifdef USE_UNLIMITED_SELECT SIMP_PROP(FdSetSize, iFdSetSize, int) #endif #undef SIMP_PROP #undef SIMP_PROP_SET #undef SIMP_PROP_GET /* This is based on the previous SIMP_PROP but as a getter it uses * additional parameter specifying the configuration it belongs to. * The setter uses loadConf */ #define SIMP_PROP(nameFunc, nameVar, dataType) \ SIMP_PROP_GET(nameFunc, nameVar, dataType) \ SIMP_PROP_SET(nameFunc, nameVar, dataType) #define SIMP_PROP_SET(nameFunc, nameVar, dataType) \ static rsRetVal Set##nameFunc(dataType newVal) { \ loadConf->globals.nameVar = newVal; \ return RS_RET_OK; \ } #define SIMP_PROP_GET(nameFunc, nameVar, dataType) \ static dataType Get##nameFunc(rsconf_t *cnf) { \ return (cnf->globals.nameVar); \ } SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int) SIMP_PROP(DisableDNS, bDisableDNS, int) SIMP_PROP(ParserEscapeControlCharactersCStyle, parser.bParserEscapeCCCStyle, int) SIMP_PROP(ParseHOSTNAMEandTAG, parser.bParseHOSTNAMEandTAG, int) SIMP_PROP(OptionDisallowWarning, optionDisallowWarning, int) /* We omit setter on purpose, because we want to customize it */ SIMP_PROP_GET(DfltNetstrmDrvrCAF, pszDfltNetstrmDrvrCAF, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrCRLF, pszDfltNetstrmDrvrCRLF, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrCertFile, pszDfltNetstrmDrvrCertFile, uchar *) SIMP_PROP_GET(DfltNetstrmDrvrKeyFile, pszDfltNetstrmDrvrKeyFile, uchar *) SIMP_PROP_GET(NetstrmDrvrCAExtraFiles, pszNetstrmDrvrCAExtraFiles, uchar *) SIMP_PROP_GET(ParserControlCharacterEscapePrefix, parser.cCCEscapeChar, uchar) SIMP_PROP_GET(ParserDropTrailingLFOnReception, parser.bDropTrailingLF, int) SIMP_PROP_GET(ParserDropTrailingCROnReception, parser.bDropTrailingCR, int) SIMP_PROP_GET(ParserEscapeControlCharactersOnReceive, parser.bEscapeCCOnRcv, int) SIMP_PROP_GET(ParserSpaceLFOnReceive, parser.bSpaceLFOnRcv, int) SIMP_PROP_GET(ParserEscape8BitCharactersOnReceive, parser.bEscape8BitChars, int) SIMP_PROP_GET(ParserEscapeControlCharacterTab, parser.bEscapeTab, int) #undef SIMP_PROP #undef SIMP_PROP_SET #undef SIMP_PROP_GET /* return global input termination status * rgerhards, 2009-07-20 */ static int GetGlobalInputTermState(void) { return ATOMIC_LOAD_32BIT(&bTerminateInputs, &mutTerminateInputs); } /* set global termination state to "terminate". Note that this is a * "once in a lifetime" action which can not be undone. -- gerhards, 2009-07-20 */ static void SetGlobalInputTermination(void) { /* Signal handlers must not take mutTerminateInputs in no-atomic builds. * Publish this one-way mirror first so a shutdown signal delivered during * termination setup may already break input-side blocking calls. */ PREFER_STORE_INT(&bTerminateInputsSigSafe, 1); ATOMIC_STORE_32BIT(&bTerminateInputs, &mutTerminateInputs, 1); } /* set the local host IP address to a specific string. Helper to * small set of functions. No checks done, caller must ensure it is * ok to call. Most importantly, the IP address must not already have * been set. -- rgerhards, 2012-03-21 */ static rsRetVal storeLocalHostIPIF(uchar *myIP) { DEFiRet; if (propLocalIPIF != NULL) { CHKiRet(prop.Destruct(&propLocalIPIF)); } CHKiRet(prop.Construct(&propLocalIPIF)); CHKiRet(prop.SetString(propLocalIPIF, myIP, ustrlen(myIP))); CHKiRet(prop.ConstructFinalize(propLocalIPIF)); DBGPRINTF("rsyslog/glbl: using '%s' as localhost IP\n", myIP); finalize_it: RETiRet; } /* This function is used to set the IP address that is to be * reported for the local host. Note that in order to ease things * for the v6 config interface, we do not allow this to be set more * than once. * rgerhards, 2012-03-21 */ static rsRetVal setLocalHostIPIF(void __attribute__((unused)) * pVal, uchar *pNewVal) { uchar myIP[128]; rsRetVal localRet; DEFiRet; CHKiRet(objUse(net, CORE_COMPONENT)); if (propLocalIPIF_set) { LogError(0, RS_RET_ERR, "$LocalHostIPIF is already set " "and cannot be reset; place it at TOP OF rsyslog.conf!"); ABORT_FINALIZE(RS_RET_ERR); } localRet = net.GetIFIPAddr(pNewVal, AF_UNSPEC, myIP, (int)sizeof(myIP)); if (localRet != RS_RET_OK) { LogError(0, RS_RET_ERR, "$LocalHostIPIF: IP address for interface " "'%s' cannnot be obtained - ignoring directive", pNewVal); } else { storeLocalHostIPIF(myIP); } finalize_it: free(pNewVal); /* no longer needed -> is in prop! */ RETiRet; } /* This function is used to set the global work directory name. * It verifies that the provided directory actually exists and * emits an error message if not. * rgerhards, 2011-02-16 */ static rsRetVal setWorkDir(void __attribute__((unused)) * pVal, uchar *pNewVal) { size_t lenDir; int i; struct stat sb; DEFiRet; /* remove trailing slashes */ lenDir = ustrlen(pNewVal); i = lenDir - 1; while (i > 0 && pNewVal[i] == '/') { --i; } if (i < 0) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: empty value " "- directive ignored"); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } if (i != (int)lenDir - 1) { pNewVal[i + 1] = '\0'; LogError(0, RS_RET_WRN_WRKDIR, "$WorkDirectory: trailing slashes " "removed, new value is '%s'", pNewVal); } if (stat((char *)pNewVal, &sb) != 0) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s can not be " "accessed, probably does not exist - directive ignored", pNewVal); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } if (!S_ISDIR(sb.st_mode)) { LogError(0, RS_RET_ERR_WRKDIR, "$WorkDirectory: %s not a directory - directive ignored", pNewVal); ABORT_FINALIZE(RS_RET_ERR_WRKDIR); } free(loadConf->globals.pszWorkDir); loadConf->globals.pszWorkDir = pNewVal; finalize_it: RETiRet; } static rsRetVal setDfltNetstrmDrvrCAF(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCAF); loadConf->globals.pszDfltNetstrmDrvrCAF = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercafile file '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setNetstrmDrvrCAExtraFiles(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; char *token; char *saveptr; int error = 0; char *valCopy = NULL; free(loadConf->globals.pszNetstrmDrvrCAExtraFiles); /* Validate files without modifying the original comma-separated string */ if (pNewVal != NULL) { valCopy = strdup((const char *)pNewVal); if (valCopy == NULL) { LogError(errno, RS_RET_OUT_OF_MEMORY, "error: strdup failed in setNetstrmDrvrCAExtraFiles"); free(pNewVal); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } for (token = strtok_r(valCopy, ",", &saveptr); token != NULL; token = strtok_r(NULL, ",", &saveptr)) { while (isspace((unsigned char)*token)) { token++; } char *end = token + strlen(token) - 1; while (end > token && isspace((unsigned char)*end)) { end--; } *(end + 1) = '\0'; if (*token == '\0') { continue; } fp = fopen((const char *)token, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: netstreamdrivercaextrafiles file '%s' " "could not be accessed", token); error = 1; } else { fclose(fp); } } } if (!error) { loadConf->globals.pszNetstrmDrvrCAExtraFiles = pNewVal; } else { /* Validation failed: prevent leak of newly allocated pNewVal */ free(pNewVal); loadConf->globals.pszNetstrmDrvrCAExtraFiles = NULL; } finalize_it: if (valCopy != NULL) { free(valCopy); } RETiRet; } static rsRetVal setDfltNetstrmDrvrCRLF(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCRLF); loadConf->globals.pszDfltNetstrmDrvrCRLF = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercrlfile file '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvrCertFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrCertFile); loadConf->globals.pszDfltNetstrmDrvrCertFile = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdrivercertfile '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvrKeyFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; FILE *fp; free(loadConf->globals.pszDfltNetstrmDrvrKeyFile); loadConf->globals.pszDfltNetstrmDrvrKeyFile = pNewVal; fp = fopen((const char *)pNewVal, "r"); if (fp == NULL) { LogError(errno, RS_RET_NO_FILE_ACCESS, "error: defaultnetstreamdriverkeyfile '%s' " "could not be accessed", pNewVal); } else { fclose(fp); } RETiRet; } static rsRetVal setDfltNetstrmDrvr(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; free(loadConf->globals.pszDfltNetstrmDrvr); loadConf->globals.pszDfltNetstrmDrvr = pNewVal; RETiRet; } static rsRetVal setDfltOpensslEngine(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; free(loadConf->globals.pszDfltOpensslEngine); loadConf->globals.pszDfltOpensslEngine = pNewVal; RETiRet; } /* Set the maximum number of files the rsyslog process may open. */ rsRetVal glblSetMaxOpenFiles(void __attribute__((unused)) * pVal, int iFiles) { struct rlimit maxFiles; struct rlimit currentLimit; DEFiRet; if (getrlimit(RLIMIT_NOFILE, ¤tLimit) < 0) { currentLimit.rlim_max = 0; } maxFiles.rlim_cur = iFiles; maxFiles.rlim_max = iFiles; if (setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) { /* NOTE: under valgrind, we seem to be unable to extend the size! */ LogError(errno, RS_RET_ERR_RLIM_NOFILE, "could not set process file limit to %d " "[current hard limit %llu]", iFiles, (unsigned long long)currentLimit.rlim_max); ABORT_FINALIZE(RS_RET_ERR_RLIM_NOFILE); } #ifdef USE_UNLIMITED_SELECT SetFdSetSize(howmany(iFiles, __NFDBITS) * sizeof(fd_mask)); #endif DBGPRINTF("Max number of files set to %d [current hard limit %llu].\n", iFiles, (unsigned long long)currentLimit.rlim_max); finalize_it: RETiRet; } static rsRetVal setParserControlCharacterEscapePrefix(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; loadConf->globals.parser.cCCEscapeChar = *pNewVal; RETiRet; } static rsRetVal setParserDropTrailingLFOnReception(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bDropTrailingLF = pNewVal; RETiRet; } static rsRetVal setParserDropTrailingCROnReception(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bDropTrailingCR = pNewVal; RETiRet; } static rsRetVal setParserEscapeControlCharactersOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscapeCCOnRcv = pNewVal; RETiRet; } static rsRetVal setParserSpaceLFOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bSpaceLFOnRcv = pNewVal; RETiRet; } static rsRetVal setParserEscape8BitCharactersOnReceive(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscape8BitChars = pNewVal; RETiRet; } static rsRetVal setParserEscapeControlCharacterTab(void __attribute__((unused)) * pVal, int pNewVal) { DEFiRet; loadConf->globals.parser.bEscapeTab = pNewVal; RETiRet; } /* This function is used both by legacy and RainerScript conf. It is a real setter. */ static void setMaxLine(const int64_t iNew) { if (iNew < 128) { LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize tried to set " "to %lld, but cannot be less than 128 - set to 128 " "instead", (long long)iNew); loadConf->globals.iMaxLine = 128; } else if (iNew > (int64_t)INT_MAX) { LogError(0, RS_RET_INVALID_VALUE, "maxMessageSize larger than " "INT_MAX (%d) - reduced to INT_MAX", INT_MAX); loadConf->globals.iMaxLine = INT_MAX; } else { loadConf->globals.iMaxLine = (int)iNew; } } static rsRetVal legacySetMaxMessageSize(void __attribute__((unused)) * pVal, int64_t iNew) { setMaxLine(iNew); return RS_RET_OK; } static rsRetVal setDebugFile(void __attribute__((unused)) * pVal, uchar *pNewVal) { DEFiRet; dbgSetDebugFile(pNewVal); free(pNewVal); RETiRet; } static rsRetVal setDebugLevel(void __attribute__((unused)) * pVal, int level) { DEFiRet; dbgSetDebugLevel(level); dbgprintf("debug level %d set via config file\n", level); dbgprintf("This is rsyslog version " VERSION "\n"); RETiRet; } static rsRetVal ATTR_NONNULL() setOversizeMsgInputMode(const uchar *const mode) { DEFiRet; if (!strcmp((char *)mode, "truncate")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate; } else if (!strcmp((char *)mode, "split")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Split; } else if (!strcmp((char *)mode, "accept")) { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept; } else { loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Truncate; } RETiRet; } static rsRetVal ATTR_NONNULL() setReportChildProcessExits(const uchar *const mode) { DEFiRet; if (!strcmp((char *)mode, "none")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_NONE; } else if (!strcmp((char *)mode, "errors")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS; } else if (!strcmp((char *)mode, "all")) { loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ALL; } else { LogError(0, RS_RET_CONF_PARAM_INVLD, "invalid value '%s' for global parameter reportChildProcessExits -- ignored", mode); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Convert enable/warn/disable config-format policy text to its internal enum. */ static rsRetVal ATTR_NONNULL() setCompatConfigFormatMode(const char *const param, const uchar *const mode, int *const dst) { DEFiRet; if (!strcmp((const char *)mode, "enable")) { *dst = COMPAT_CONFIGFORMAT_ENABLE; } else if (!strcmp((const char *)mode, "warn")) { *dst = COMPAT_CONFIGFORMAT_WARN; } else if (!strcmp((const char *)mode, "disable")) { *dst = COMPAT_CONFIGFORMAT_DISABLE; } else { parser_errmsg("invalid value '%s' for global parameter %s", mode, param); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Convert strict/backward-compatible/warn secure-defaults policy text to its internal enum. */ static rsRetVal ATTR_NONNULL() setCompatDefaultsSecure(const uchar *const mode) { DEFiRet; if (!strcmp((const char *)mode, "strict")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_STRICT; loadConf->globals.bAbortOnUncleanConfig = 1; } else if (!strcmp((const char *)mode, "backward-compatible")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_BACKWARD_COMPATIBLE; } else if (!strcmp((const char *)mode, "warn")) { loadConf->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_WARN; } else { parser_errmsg("invalid value '%s' for global parameter compatibility.defaults.secure", mode); iRet = RS_RET_CONF_PARAM_INVLD; } RETiRet; } /** Apply a global compatibility enum string during config parsing. */ static rsRetVal ATTR_NONNULL() processCompatGlobalParam(const char *const name, struct cnfparamvals *const pval) { char *mode; DEFiRet; mode = es_str2cstr(pval->val.d.estr, NULL); if (mode == NULL) { parser_errmsg("out of memory processing global parameter %s", name); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (!strcmp(name, "compatibility.configformat.legacy")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatLegacy)); } else if (!strcmp(name, "compatibility.configformat.syslogd")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatSyslogd)); } else if (!strcmp(name, "compatibility.configformat.property")) { CHKiRet(setCompatConfigFormatMode(name, (uchar *)mode, &loadConf->globals.compatConfigFormatProperty)); } else if (!strcmp(name, "compatibility.defaults.secure")) { CHKiRet(setCompatDefaultsSecure((uchar *)mode)); } finalize_it: free(mode); RETiRet; } /** Emit a compatibility warning through the parser diagnostics path. */ static void ATTR_NONNULL() compatParserWarnmsg(const char *const msg) { parser_warnmsg("%s", msg); } /** Emit warning/error for compatibility-controlled legacy syntax and say how to re-enable it. */ static int ATTR_NONNULL() permitCompatSyntax(const int mode, const char *const kind, const char *const text, const char *const option) { int permitted = 1; if (mode == COMPAT_CONFIGFORMAT_WARN) { char msg[1024]; snprintf(msg, sizeof(msg), "obsolete %s syntax encountered: '%s'", kind, text); msg[sizeof(msg) - 1] = '\0'; compatParserWarnmsg(msg); } else if (mode == COMPAT_CONFIGFORMAT_DISABLE) { parser_errmsg("obsolete %s syntax disabled: '%s'; use global(%s=\"enable\") to enable it", kind, text, option); permitted = 0; } return permitted; } int glblPermitLegacyConfigDirective(rsconf_t *cnf, const char *directive) { return permitCompatSyntax(cnf->globals.compatConfigFormatLegacy, "$-directive", directive, "compatibility.configformat.legacy"); } int glblPermitSyslogdConfigFilter(rsconf_t *cnf, const char *filter) { return permitCompatSyntax(cnf->globals.compatConfigFormatSyslogd, "classic syslogd filter", filter, "compatibility.configformat.syslogd"); } int glblPermitPropertyConfigFilter(rsconf_t *cnf, const char *filter) { return permitCompatSyntax(cnf->globals.compatConfigFormatProperty, "classic property-based filter", filter, "compatibility.configformat.property"); } void glblWarnIfInsecureDefault(rsconf_t *cnf, const char *detail) { if (cnf != NULL && cnf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_WARN) { parser_warnmsg( "backward-compatible insecure default in use: %s; " "use global(compatibility.defaults.secure=\"strict\") to enable the secure default", detail); } } const uchar *glblGetEffectiveNetstrmDrvr(rsconf_t *cnf, const uchar *localDrvr) { if (localDrvr != NULL) { return localDrvr; } if (cnf == NULL) { return DFLT_NETSTRM_DRVR; } return GetDfltNetstrmDrvr(cnf); } int glblIsTlsCapableNetstrmDrvr(const uchar *drvr) { return drvr != NULL && (!strcasecmp((const char *)drvr, "ossl") || !strcasecmp((const char *)drvr, "gtls") || !strcasecmp((const char *)drvr, "mbedtls")); } static int getDefPFFamily(rsconf_t *cnf) { return cnf->globals.iDefPFFamily; } /* return our local IP. * If no local IP is set, "127.0.0.1" is selected *and* set. This * is an intensional side effect that we do in order to keep things * consistent and avoid config errors (this will make us not accept * setting the local IP address once a module has obtained it - so * it forces the $LocalHostIPIF directive high up in rsyslog.conf) * rgerhards, 2012-03-21 */ static prop_t *GetLocalHostIP(void) { assert(propLocalIPIF != NULL); return (propLocalIPIF); } /* set our local hostname. Free previous hostname, if it was already set. * Note that we do now do this in a thread. As such, the method here * is NOT 100% clean. If we run into issues, we need to think about * refactoring the whole way we handle the local host name processing. * Possibly using a PROP might be the right solution then. */ static rsRetVal SetLocalHostName(uchar *const newname) { uchar *toFree; if (LocalHostName == NULL || strcmp((const char *)LocalHostName, (const char *)newname)) { toFree = LocalHostName; LocalHostName = newname; } else { toFree = newname; } free(toFree); return RS_RET_OK; } /* return our local hostname. if it is not set, "[localhost]" is returned */ uchar *glblGetLocalHostName(void) { uchar *pszRet; if (LocalHostNameOverride != NULL) { pszRet = LocalHostNameOverride; goto done; } if (LocalHostName == NULL) pszRet = (uchar *)"[localhost]"; else { if (GetPreserveFQDN() == 1) pszRet = LocalFQDNName; else pszRet = LocalHostName; } done: return (pszRet); } /* return the name of the file where oversize messages are written to */ uchar *glblGetOversizeMsgErrorFile(rsconf_t *cnf) { return cnf->globals.oversizeMsgErrorFile; } const uchar *glblGetOperatingStateFile(rsconf_t *cnf) { return cnf->globals.operatingStateFile; } /* return the mode with which oversize messages will be put forward */ int glblGetOversizeMsgInputMode(rsconf_t *cnf) { return cnf->globals.oversizeMsgInputMode; } int glblReportOversizeMessage(rsconf_t *cnf) { return cnf->globals.reportOversizeMsg; } /* logs a message indicating that a child process has terminated. * If name != NULL, prints it as the program name. */ void glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status) { DBGPRINTF("waitpid for child %ld returned status: %2.2x\n", (long)pid, status); if (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_NONE || (cnf->globals.reportChildProcessExits == REPORT_CHILD_PROCESS_EXITS_ERRORS && WIFEXITED(status) && WEXITSTATUS(status) == 0)) { return; } if (WIFEXITED(status)) { int severity = WEXITSTATUS(status) == 0 ? LOG_INFO : LOG_WARNING; if (name != NULL) { LogMsg(0, NO_ERRCODE, severity, "program '%s' (pid %ld) exited with status %d", name, (long)pid, WEXITSTATUS(status)); } else { LogMsg(0, NO_ERRCODE, severity, "child process (pid %ld) exited with status %d", (long)pid, WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { if (name != NULL) { LogMsg(0, NO_ERRCODE, LOG_WARNING, "program '%s' (pid %ld) terminated by signal %d", name, (long)pid, WTERMSIG(status)); } else { LogMsg(0, NO_ERRCODE, LOG_WARNING, "child process (pid %ld) terminated by signal %d", (long)pid, WTERMSIG(status)); } } } /* set our local domain name. Free previous domain, if it was already set. */ static rsRetVal SetLocalDomain(uchar *newname) { free(LocalDomain); LocalDomain = newname; return RS_RET_OK; } /* return our local hostname. if it is not set, "[localhost]" is returned */ static uchar *GetLocalDomain(void) { return LocalDomain; } /* generate the local hostname property. This must be done after the hostname info * has been set as well as PreserveFQDN. * rgerhards, 2009-06-30 * NOTE: This function tries to avoid locking by not destructing the previous value * immediately. This is so that current readers can continue to use the previous name. * Otherwise, we would need to use read/write locks to protect the update process. * In order to do so, we save the previous value and delete it when we are called again * the next time. Note that this in theory is racy and can lead to a double-free. * In practice, however, the window of exposure to trigger this is extremely short * and as this functions is very infrequently being called (on HUP), the trigger * condition for this bug is so highly unlikely that it never occurs in practice. * Probably if you HUP rsyslog every few milliseconds, but who does that... * To further reduce risk potential, we do only update the property when there * actually is a hostname change, which makes it even less likely. * rgerhards, 2013-10-28 */ static rsRetVal GenerateLocalHostNameProperty(void) { uchar *pszPrev; int lenPrev; prop_t *hostnameNew; uchar *pszName; DEFiRet; if (propLocalHostNameToDelete != NULL) prop.Destruct(&propLocalHostNameToDelete); if (LocalHostNameOverride == NULL) { if (LocalHostName == NULL) pszName = (uchar *)"[localhost]"; else { if (GetPreserveFQDN() == 1) pszName = LocalFQDNName; else pszName = LocalHostName; } } else { /* local hostname is overriden via config */ pszName = LocalHostNameOverride; } DBGPRINTF("GenerateLocalHostName uses '%s'\n", pszName); if (propLocalHostName == NULL) pszPrev = (uchar *)""; /* make sure strcmp() below does not match */ else prop.GetString(propLocalHostName, &pszPrev, &lenPrev); if (ustrcmp(pszPrev, pszName)) { /* we need to update */ CHKiRet(prop.Construct(&hostnameNew)); CHKiRet(prop.SetString(hostnameNew, pszName, ustrlen(pszName))); CHKiRet(prop.ConstructFinalize(hostnameNew)); propLocalHostNameToDelete = propLocalHostName; propLocalHostName = hostnameNew; } finalize_it: RETiRet; } /* return our local hostname as a string property */ static prop_t *GetLocalHostNameProp(void) { return (propLocalHostName); } static rsRetVal SetLocalFQDNName(uchar *newname) { free(LocalFQDNName); LocalFQDNName = newname; return RS_RET_OK; } /* return the current localhost name as FQDN (requires FQDN to be set) */ static uchar *GetLocalFQDNName(void) { return (LocalFQDNName == NULL ? (uchar *)"[localhost]" : LocalFQDNName); } /* return the current working directory */ static uchar *GetWorkDir(rsconf_t *cnf) { return (cnf->globals.pszWorkDir == NULL ? (uchar *)"" : cnf->globals.pszWorkDir); } /* return the "raw" working directory, which means * NULL if unset. */ const uchar *glblGetWorkDirRaw(rsconf_t *cnf) { return cnf->globals.pszWorkDir; } /* return the current default netstream driver */ static uchar *GetDfltNetstrmDrvr(rsconf_t *cnf) { return (cnf->globals.pszDfltNetstrmDrvr == NULL ? DFLT_NETSTRM_DRVR : cnf->globals.pszDfltNetstrmDrvr); } /* return the current default openssl engine name */ static uchar *GetDfltOpensslEngine(rsconf_t *cnf) { return (cnf->globals.pszDfltOpensslEngine); } /* [ar] Source IP for local client to be used on multihomed host */ static rsRetVal SetSourceIPofLocalClient(uchar *newname) { if (SourceIPofLocalClient != NULL) { free(SourceIPofLocalClient); } SourceIPofLocalClient = newname; return RS_RET_OK; } static uchar *GetSourceIPofLocalClient(void) { return (SourceIPofLocalClient); } /* queryInterface function * rgerhards, 2008-02-21 */ BEGINobjQueryInterface(glbl) CODESTARTobjQueryInterface(glbl); if (pIf->ifVersion != glblCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->GetWorkDir = GetWorkDir; pIf->GenerateLocalHostNameProperty = GenerateLocalHostNameProperty; pIf->GetLocalHostNameProp = GetLocalHostNameProp; pIf->GetLocalHostIP = GetLocalHostIP; pIf->SetGlobalInputTermination = SetGlobalInputTermination; pIf->GetGlobalInputTermState = GetGlobalInputTermState; pIf->GetSourceIPofLocalClient = GetSourceIPofLocalClient; /* [ar] */ pIf->SetSourceIPofLocalClient = SetSourceIPofLocalClient; /* [ar] */ pIf->GetDefPFFamily = getDefPFFamily; pIf->GetDisableDNS = GetDisableDNS; pIf->GetMaxLine = glblGetMaxLine; pIf->GetOptionDisallowWarning = GetOptionDisallowWarning; pIf->GetDfltNetstrmDrvrCAF = GetDfltNetstrmDrvrCAF; pIf->GetDfltNetstrmDrvrCRLF = GetDfltNetstrmDrvrCRLF; pIf->GetDfltNetstrmDrvrCertFile = GetDfltNetstrmDrvrCertFile; pIf->GetDfltNetstrmDrvrKeyFile = GetDfltNetstrmDrvrKeyFile; pIf->GetDfltNetstrmDrvr = GetDfltNetstrmDrvr; pIf->GetDfltOpensslEngine = GetDfltOpensslEngine; pIf->GetNetstrmDrvrCAExtraFiles = GetNetstrmDrvrCAExtraFiles; pIf->GetParserControlCharacterEscapePrefix = GetParserControlCharacterEscapePrefix; pIf->GetParserDropTrailingLFOnReception = GetParserDropTrailingLFOnReception; pIf->GetParserDropTrailingCROnReception = GetParserDropTrailingCROnReception; pIf->GetParserEscapeControlCharactersOnReceive = GetParserEscapeControlCharactersOnReceive; pIf->GetParserSpaceLFOnReceive = GetParserSpaceLFOnReceive; pIf->GetParserEscape8BitCharactersOnReceive = GetParserEscape8BitCharactersOnReceive; pIf->GetParserEscapeControlCharacterTab = GetParserEscapeControlCharacterTab; pIf->GetLocalHostName = glblGetLocalHostName; pIf->SetLocalHostName = SetLocalHostName; #define SIMP_PROP(name) \ pIf->Get##name = Get##name; \ pIf->Set##name = Set##name; SIMP_PROP(PreserveFQDN); SIMP_PROP(DropMalPTRMsgs); SIMP_PROP(mainqCnfObj); SIMP_PROP(LocalFQDNName) SIMP_PROP(LocalDomain) SIMP_PROP(ParserEscapeControlCharactersCStyle) SIMP_PROP(ParseHOSTNAMEandTAG) #ifdef USE_UNLIMITED_SELECT SIMP_PROP(FdSetSize) #endif #undef SIMP_PROP finalize_it: ENDobjQueryInterface(glbl) /* Reset config variables to default values. * rgerhards, 2008-04-17 */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { free(loadConf->globals.pszDfltNetstrmDrvr); loadConf->globals.pszDfltNetstrmDrvr = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCAF); loadConf->globals.pszDfltNetstrmDrvrCAF = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCRLF); loadConf->globals.pszDfltNetstrmDrvrCRLF = NULL; free(loadConf->globals.pszDfltNetstrmDrvrKeyFile); loadConf->globals.pszDfltNetstrmDrvrKeyFile = NULL; free(loadConf->globals.pszDfltNetstrmDrvrCertFile); loadConf->globals.pszDfltNetstrmDrvrCertFile = NULL; free(loadConf->globals.pszDfltOpensslEngine); loadConf->globals.pszDfltOpensslEngine = NULL; free(LocalHostNameOverride); LocalHostNameOverride = NULL; free(loadConf->globals.oversizeMsgErrorFile); loadConf->globals.oversizeMsgErrorFile = NULL; loadConf->globals.oversizeMsgInputMode = glblOversizeMsgInputMode_Accept; loadConf->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS; free(loadConf->globals.pszWorkDir); loadConf->globals.pszWorkDir = NULL; free((void *)loadConf->globals.operatingStateFile); loadConf->globals.operatingStateFile = NULL; loadConf->globals.bDropMalPTRMsgs = 0; loadConf->globals.systemdNotifyReadyDelay = 0; bPreserveFQDN = 0; loadConf->globals.iMaxLine = 8192; loadConf->globals.reportOversizeMsg = 1; loadConf->globals.parser.cCCEscapeChar = '#'; loadConf->globals.parser.bDropTrailingLF = 1; loadConf->globals.parser.bDropTrailingCR = 0; loadConf->globals.parser.bEscapeCCOnRcv = 1; /* default is to escape control characters */ loadConf->globals.parser.bSpaceLFOnRcv = 0; loadConf->globals.parser.bEscape8BitChars = 0; /* default is not to escape control characters */ loadConf->globals.parser.bEscapeTab = 1; /* default is to escape tab characters */ loadConf->globals.parser.bParserEscapeCCCStyle = 0; #ifdef USE_UNLIMITED_SELECT iFdSetSize = howmany(FD_SETSIZE, __NFDBITS) * sizeof(fd_mask); #endif return RS_RET_OK; } /* Prepare for new config */ void glblPrepCnf(void) { free(mainqCnfObj); mainqCnfObj = NULL; free(cnfparamvals); cnfparamvals = NULL; } /* handle the timezone() object. Each incarnation adds one additional * zone info to the global table of time zones. */ int bs_arrcmp_glblDbgFiles(const void *s1, const void *s2) { return strcmp((char *)s1, *(char **)s2); } /* handle a global config object. Note that multiple global config statements * are permitted (because of plugin support), so once we got a param block, * we need to hold to it. * rgerhards, 2011-07-19 */ void glblProcessCnf(struct cnfobj *o) { int i; cnfparamvals = nvlstGetParams(o->nvlst, ¶mblk, cnfparamvals); if (cnfparamvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing global " "config parameters [global(...)]"); goto done; } if (Debug) { dbgprintf("glbl param blk after glblProcessCnf:\n"); cnfparamsPrint(¶mblk, cnfparamvals); } /* The next thing is a bit hackish and should be changed in higher * versions. There are a select few parameters which we need to * act on immediately. These are processed here. */ for (i = 0; i < paramblk.nParams; ++i) { if (!cnfparamvals[i].bUsed) continue; if (!strcmp(paramblk.descr[i].name, "processinternalmessages")) { loadConf->globals.bProcessInternalMessages = (int)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "internal.developeronly.options")) { loadConf->globals.glblDevOptions = (uint64_t)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "stdlog.channelspec")) { #ifndef ENABLE_LIBLOGGING_STDLOG LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with liblogging-stdlog support. " "The 'stdlog.channelspec' parameter " "is ignored. Note: the syslog API is used instead.\n"); #else loadConf->globals.stdlog_chanspec = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); /* we need to re-open with the new channel */ stdlog_close(loadConf->globals.stdlog_hdl); loadConf->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG, (char *)loadConf->globals.stdlog_chanspec); cnfparamvals[i].bUsed = TRUE; #endif } else if (!strcmp(paramblk.descr[i].name, "operatingstatefile")) { if (loadConf->globals.operatingStateFile != NULL) { LogError(errno, RS_RET_PARAM_ERROR, "error: operatingStateFile already set to '%s' - " "new value ignored", loadConf->globals.operatingStateFile); } else { loadConf->globals.operatingStateFile = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); osf_open(); } } else if (!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) { loadConf->globals.abortOnIDResolutionFail = (int)cnfparamvals[i].val.d.n; cnfparamvals[i].bUsed = TRUE; } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdriver")) { uchar *const cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); if (cstr == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "out of memory processing defaultnetstreamdriver"); } else { setDfltNetstrmDrvr(NULL, cstr); } cnfparamvals[i].bUsed = TRUE; } else if (!strncmp(paramblk.descr[i].name, "compatibility.", 14)) { if (processCompatGlobalParam(paramblk.descr[i].name, &cnfparamvals[i]) == RS_RET_OK) { cnfparamvals[i].bUsed = 1; } else { dbgprintf("glblProcessCnf: failed to process early global parameter '%s'\n", paramblk.descr[i].name); } } } done: return; } /* Set mainq parameters. Note that when this is not called, we'll use the * legacy parameter config. mainq parameters can only be set once. */ void glblProcessMainQCnf(struct cnfobj *o) { if (mainqCnfObj == NULL) { mainqCnfObj = o; } else { LogError(0, RS_RET_ERR, "main_queue() object can only be specified " "once - all but first ignored\n"); } } /* destruct the main q cnf object after it is no longer needed. This is * also used to do some final checks. */ void glblDestructMainqCnfObj(void) { /* Only destruct if not NULL! */ if (mainqCnfObj != NULL) { nvlstChkUnused(mainqCnfObj->nvlst); cnfobjDestruct(mainqCnfObj); mainqCnfObj = NULL; } } static int qs_arrcmp_glblDbgFiles(const void *s1, const void *s2) { return strcmp(*((char **)s1), *((char **)s2)); } /* set an environment variable */ static rsRetVal do_setenv(const char *const var) { char varname[128]; const char *val = var; size_t i; DEFiRet; for (i = 0; *val != '='; ++i, ++val) { if (i == sizeof(varname) - i) { parser_errmsg( "environment variable name too long " "[max %zu chars] or malformed entry: '%s'", sizeof(varname) - 1, var); ABORT_FINALIZE(RS_RET_ERR_SETENV); } if (*val == '\0') { parser_errmsg( "environment variable entry is missing " "equal sign (for value): '%s'", var); ABORT_FINALIZE(RS_RET_ERR_SETENV); } varname[i] = *val; } varname[i] = '\0'; ++val; DBGPRINTF("do_setenv, var '%s', val '%s'\n", varname, val); if (setenv(varname, val, 1) != 0) { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); parser_errmsg( "error setting environment variable " "'%s' to '%s': %s", varname, val, errStr); ABORT_FINALIZE(RS_RET_ERR_SETENV); } finalize_it: RETiRet; } /* This processes the "regular" parameters which are to be set after the * config has been fully loaded. */ rsRetVal glblDoneLoadCnf(void) { int i; unsigned char *cstr; DEFiRet; CHKiRet(objUse(net, CORE_COMPONENT)); sortTimezones(loadConf); DBGPRINTF("Timezone information table (%d entries):\n", loadConf->timezones.ntzinfos); displayTimezones(loadConf); if (cnfparamvals == NULL) goto finalize_it; for (i = 0; i < paramblk.nParams; ++i) { if (!cnfparamvals[i].bUsed) continue; if (!strcmp(paramblk.descr[i].name, "workdirectory")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setWorkDir(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "libcapng.default")) { #ifdef ENABLE_LIBCAPNG loadConf->globals.bAbortOnFailedLibcapngSetup = (int)cnfparamvals[i].val.d.n; #else LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with libcap-ng support."); #endif } else if (!strcmp(paramblk.descr[i].name, "libcapng.enable")) { #ifdef ENABLE_LIBCAPNG loadConf->globals.bCapabilityDropEnabled = (int)cnfparamvals[i].val.d.n; #else LogError(0, RS_RET_ERR, "rsyslog wasn't " "compiled with libcap-ng support."); #endif } else if (!strcmp(paramblk.descr[i].name, "variables.casesensitive")) { const int val = (int)cnfparamvals[i].val.d.n; fjson_global_do_case_sensitive_comparison(val); DBGPRINTF("global/config: set case sensitive variables to %d\n", val); } else if (!strcmp(paramblk.descr[i].name, "localhostname")) { free(LocalHostNameOverride); LocalHostNameOverride = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdriverkeyfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrKeyFile(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercertfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCertFile(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercafile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCAF(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultnetstreamdrivercrlfile")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltNetstrmDrvrCRLF(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "defaultopensslengine")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setDfltOpensslEngine(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "netstreamdrivercaextrafiles")) { cstr = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setNetstrmDrvrCAExtraFiles(NULL, cstr); } else if (!strcmp(paramblk.descr[i].name, "preservefqdn")) { bPreserveFQDN = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "compactjsonstring")) { glblJsonFormatOpt = cnfparamvals[i].val.d.n ? JSON_C_TO_STRING_PLAIN : JSON_C_TO_STRING_SPACED; } else if (!strcmp(paramblk.descr[i].name, "dropmsgswithmaliciousdnsptrrecords")) { loadConf->globals.bDropMalPTRMsgs = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "action.reportsuspension")) { loadConf->globals.bActionReportSuspension = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "action.reportsuspensioncontinuation")) { loadConf->globals.bActionReportSuspensionCont = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "maxmessagesize")) { setMaxLine(cnfparamvals[i].val.d.n); } else if (!strcmp(paramblk.descr[i].name, "maxopenfiles")) { loadConf->globals.iMaxOpenFiles = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.errorfile")) { free(loadConf->globals.oversizeMsgErrorFile); loadConf->globals.oversizeMsgErrorFile = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.report")) { loadConf->globals.reportOversizeMsg = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "oversizemsg.input.mode")) { const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setOversizeMsgInputMode((uchar *)tmp); free((void *)tmp); } else if (!strcmp(paramblk.descr[i].name, "reportchildprocessexits")) { const char *const tmp = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setReportChildProcessExits((uchar *)tmp); free((void *)tmp); } else if (!strcmp(paramblk.descr[i].name, "debug.onshutdown")) { loadConf->globals.debugOnShutdown = (int)cnfparamvals[i].val.d.n; LogMsg(0, RS_RET_OK, LOG_INFO, "debug: onShutdown set to %d", loadConf->globals.debugOnShutdown); } else if (!strcmp(paramblk.descr[i].name, "debug.gnutls")) { loadConf->globals.iGnuTLSLoglevel = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.abortonprogramerror")) { glblAbortOnProgramError = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.unloadmodules")) { glblUnloadModules = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "parser.controlcharacterescapeprefix")) { uchar *tmp = (uchar *)es_str2cstr(cnfparamvals[i].val.d.estr, NULL); setParserControlCharacterEscapePrefix(NULL, tmp); free(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.droptrailinglfonreception")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserDropTrailingLFOnReception(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.droptrailingcronreception")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserDropTrailingCROnReception(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscapeControlCharactersOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.spacelfonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserSpaceLFOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escape8bitcharactersonreceive")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscape8BitCharactersOnReceive(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharactertab")) { const int tmp = (int)cnfparamvals[i].val.d.n; setParserEscapeControlCharacterTab(NULL, tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) { const int tmp = (int)cnfparamvals[i].val.d.n; SetParserEscapeControlCharactersCStyle(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.parsehostnameandtag")) { const int tmp = (int)cnfparamvals[i].val.d.n; SetParseHOSTNAMEandTAG(tmp); } else if (!strcmp(paramblk.descr[i].name, "parser.permitslashinprogramname")) { loadConf->globals.parser.bPermitSlashInProgramname = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.logfile")) { if (pszAltDbgFileName == NULL) { pszAltDbgFileName = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); /* can actually happen if debug system also opened altdbg */ if (altdbg != -1) { close(altdbg); } if ((altdbg = open(pszAltDbgFileName, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) { LogError(0, RS_RET_ERR, "debug log file '%s' could not be opened", pszAltDbgFileName); } } LogMsg(0, RS_RET_OK, LOG_INFO, "debug log file is '%s', fd %d", pszAltDbgFileName, altdbg); } else if (!strcmp(paramblk.descr[i].name, "janitor.interval")) { loadConf->globals.janitorInterval = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.ipprotocol")) { char *proto = es_str2cstr(cnfparamvals[i].val.d.estr, NULL); if (!strcmp(proto, "unspecified")) { loadConf->globals.iDefPFFamily = PF_UNSPEC; } else if (!strcmp(proto, "ipv4-only")) { loadConf->globals.iDefPFFamily = PF_INET; } else if (!strcmp(proto, "ipv6-only")) { loadConf->globals.iDefPFFamily = PF_INET6; } else { LogError(0, RS_RET_ERR, "invalid net.ipprotocol " "parameter '%s' -- ignored", proto); } free(proto); } else if (!strcmp(paramblk.descr[i].name, "senders.reportnew")) { loadConf->globals.reportNewSenders = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.reportgoneaway")) { loadConf->globals.reportGoneAwaySenders = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.timeoutafter")) { loadConf->globals.senderStatsTimeout = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "senders.keeptrack")) { loadConf->globals.senderKeepTrack = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "inputs.timeout.shutdown")) { loadConf->globals.inputTimeoutShutdown = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.keepsupplemental")) { loadConf->globals.gidDropPrivKeepSupplemental = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.id")) { loadConf->globals.gidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.group.name")) { loadConf->globals.gidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.user.id")) { loadConf->globals.uidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "privdrop.user.name")) { loadConf->globals.uidDropPriv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "security.abortonidresolutionfail")) { loadConf->globals.abortOnIDResolutionFail = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.acladdhostnameonfail")) { loadConf->globals.ACLAddHostnameOnFail = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "net.aclresolvehostname")) { loadConf->globals.ACLDontResolve = !((int)cnfparamvals[i].val.d.n); } else if (!strcmp(paramblk.descr[i].name, "net.enabledns")) { SetDisableDNS(!((int)cnfparamvals[i].val.d.n)); } else if (!strcmp(paramblk.descr[i].name, "net.permitwarning")) { SetOptionDisallowWarning(!((int)cnfparamvals[i].val.d.n)); } else if (!strncmp(paramblk.descr[i].name, "compatibility.", 14)) { /* processed immediately by glblProcessCnf(), as later syntax depends on it */ } else if (!strcmp(paramblk.descr[i].name, "systemd.notifyreadydelay")) { loadConf->globals.systemdNotifyReadyDelay = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "abortonuncleanconfig")) { loadConf->globals.bAbortOnUncleanConfig = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "abortonfailedqueuestartup")) { loadConf->globals.bAbortOnFailedQueueStartup = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.burst")) { loadConf->globals.intMsgRateLimitBurst = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.ratelimit.interval")) { loadConf->globals.intMsgRateLimitItv = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "internalmsg.severity")) { loadConf->globals.intMsgsSeverityFilter = (int)cnfparamvals[i].val.d.n; if ((loadConf->globals.intMsgsSeverityFilter < 0) || (loadConf->globals.intMsgsSeverityFilter > 7)) { parser_errmsg("invalid internalmsg.severity value"); loadConf->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER; } } else if (!strcmp(paramblk.descr[i].name, "environment")) { for (int j = 0; j < cnfparamvals[i].val.d.ar->nmemb; ++j) { char *const var = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL); do_setenv(var); free(var); } } else if (!strcmp(paramblk.descr[i].name, "errormessagestostderr.maxnumber")) { loadConf->globals.maxErrMsgToStderr = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "allmessagestostderr")) { loadConf->globals.bAllMsgToStderr = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "debug.files")) { free(glblDbgFiles); /* "fix" Coverity false positive */ glblDbgFilesNum = cnfparamvals[i].val.d.ar->nmemb; glblDbgFiles = (char **)malloc(cnfparamvals[i].val.d.ar->nmemb * sizeof(char *)); for (int j = 0; j < cnfparamvals[i].val.d.ar->nmemb; ++j) { glblDbgFiles[j] = es_str2cstr(cnfparamvals[i].val.d.ar->arr[j], NULL); } qsort(glblDbgFiles, glblDbgFilesNum, sizeof(char *), qs_arrcmp_glblDbgFiles); } else if (!strcmp(paramblk.descr[i].name, "debug.whitelist")) { glblDbgWhitelist = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "shutdown.queue.doublesize")) { loadConf->globals.shutdownQueueDoubleSize = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "umask")) { loadConf->globals.umask = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "shutdown.enable.ctlc")) { loadConf->globals.permitCtlC = (int)cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutshutdown")) { loadConf->globals.actq_dflt_toQShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutactioncompletion")) { loadConf->globals.actq_dflt_toActShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutenqueue")) { loadConf->globals.actq_dflt_toEnq = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.action.queue.timeoutworkerthreadshutdown")) { loadConf->globals.actq_dflt_toWrkShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutshutdown")) { loadConf->globals.ruleset_dflt_toQShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutactioncompletion")) { loadConf->globals.ruleset_dflt_toActShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutenqueue")) { loadConf->globals.ruleset_dflt_toEnq = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "default.ruleset.queue.timeoutworkerthreadshutdown")) { loadConf->globals.ruleset_dflt_toWrkShutdown = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.default")) { loadConf->globals.dnscacheDefaultTTL = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "reverselookup.cache.ttl.enable")) { loadConf->globals.dnscacheEnableTTL = cnfparamvals[i].val.d.n; } else if (!strcmp(paramblk.descr[i].name, "parser.supportcompressionextension")) { loadConf->globals.bSupportCompressionExtension = cnfparamvals[i].val.d.n; } else { dbgprintf( "glblDoneLoadCnf: program error, non-handled " "param '%s'\n", paramblk.descr[i].name); } } if (loadConf->globals.debugOnShutdown && Debug != DEBUG_FULL) { Debug = DEBUG_ONDEMAND; stddbg = -1; } if (loadConf->globals.compatDefaultsSecure == COMPAT_DEFAULTS_SECURE_STRICT) { loadConf->globals.bAbortOnUncleanConfig = 1; } else if (!loadConf->globals.bAbortOnUncleanConfig) { glblWarnIfInsecureDefault(loadConf, "global(abortOnUncleanConfig=\"off\")"); } finalize_it: /* we have now read the config. We need to query the local host name now * as it was set by the config. * * Note: early messages are already emited, and have "[localhost]" as * hostname. These messages are currently in iminternal queue. Once they * are taken from that queue, the hostname will be adapted. */ queryLocalHostname(loadConf); RETiRet; } /* Initialize the glbl class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(prop, CORE_COMPONENT)); /* initialize properties */ storeLocalHostIPIF((uchar *)"127.0.0.1"); /* config handlers are never unregistered and need not be - we are always loaded ;) */ CHKiRet(regCfSysLineHdlr((uchar *)"debugfile", 0, eCmdHdlrGetWord, setDebugFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"debuglevel", 0, eCmdHdlrInt, setDebugLevel, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, setWorkDir, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, SetDropMalPTRMsgs, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriver", 0, eCmdHdlrGetWord, setDfltNetstrmDrvr, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultopensslengine", 0, eCmdHdlrGetWord, setDfltOpensslEngine, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCAF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercrlfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCRLF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrKeyFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, setDfltNetstrmDrvrCertFile, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"localhostname", 0, eCmdHdlrGetWord, NULL, &LocalHostNameOverride, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"localhostipif", 0, eCmdHdlrGetWord, setLocalHostIPIF, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"netstreamdrivercaextrafiles", 0, eCmdHdlrGetWord, setNetstrmDrvrCAExtraFiles, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"optimizeforuniprocessor", 0, eCmdHdlrGoneAway, NULL, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"preservefqdn", 0, eCmdHdlrBinary, NULL, &bPreserveFQDN, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"maxmessagesize", 0, eCmdHdlrSize, legacySetMaxMessageSize, NULL, NULL)); /* Deprecated parser config options */ CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, setParserControlCharacterEscapePrefix, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, setParserDropTrailingLFOnReception, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"droptrailingcronreception", 0, eCmdHdlrBinary, setParserDropTrailingCROnReception, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, setParserEscapeControlCharactersOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"spacelfonreceive", 0, eCmdHdlrBinary, setParserSpaceLFOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escape8bitcharactersonreceive", 0, eCmdHdlrBinary, setParserEscape8BitCharactersOnReceive, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactertab", 0, eCmdHdlrBinary, setParserEscapeControlCharacterTab, NULL, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); INIT_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassInit(glbl) /* Exit the glbl class. * rgerhards, 2008-04-17 */ BEGINObjClassExit(glbl, OBJ_IS_CORE_MODULE) /* class, version */ free(LocalDomain); free(LocalHostName); free(LocalHostNameOverride); free(LocalFQDNName); objRelease(prop, CORE_COMPONENT); if (propLocalHostNameToDelete != NULL) prop.Destruct(&propLocalHostNameToDelete); DESTROY_ATOMIC_HELPER_MUT(mutTerminateInputs); ENDObjClassExit(glbl) rsyslog-8.2608.0/runtime/PaxHeaders/atomic.h0000644000000000000000000000013215241075234015652 xustar0030 mtime=1787067036.599578182 30 atime=1787067036.745580916 30 ctime=1787067794.252722409 rsyslog-8.2608.0/runtime/atomic.h0000664000175000017500000005060615241075234015325 0ustar00rgerrger/* This header supplies atomic operations. So far, we rely on GCC's * atomic builtins. During configure, we check if atomic operations are * available. If they are not, I am making the necessary provisioning to live without them if * they are not available. Please note that you should only use the macros * here if you think you can actually live WITHOUT an explicit atomic operation, * because in the non-presence of them, we simply do it without atomicity. * Which, for word-aligned data types, usually (but only usually!) should work. * * We are using the functions described in * http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html * * THESE MACROS MUST ONLY BE USED WITH WORD-SIZED DATA TYPES! * * Usage guidance (important for portability and static analysis tools): * - Operations are provided as macros or inline functions. Prefer simple lvalues * for the "data" argument to avoid double-evaluation surprises. * - The "phlpmut" argument is a helper mutex used when atomics are unavailable. * If atomics are supported, these helper mutex macros become no-ops. * Callers must still pass a valid pointer where required to keep signatures * uniform across platforms. * - Some macros are "best effort" (PREFER_*). They may degrade to non-atomic * operations when no atomic support is available. Use them only for * statistics or counters where occasional lost updates are acceptable. * - The remaining ATOMIC_* helpers provide true atomicity when available and * fall back to mutex-based critical sections when not. * - Mixing atomic loads/stores with plain reads/writes to the same variable is * undefined on modern compilers. If you use ATOMIC_* on a variable, access it * exclusively via these helpers (or other synchronized paths). * * Copyright 2008-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_ATOMIC_H #define INCLUDED_ATOMIC_H #include #include "typedefs.h" /* for this release, we disable atomic calls because there seem to be some * portability problems and we can not fix that without destabilizing the build. * They simply came in too late. -- rgerhards, 2008-04-02 */ #ifdef HAVE_ATOMIC_BUILTINS /* * Return-value helpers mirror their names and the mutex fallback below: * *_AND_FETCH returns the value after the operation. */ #define ATOMIC_SUB(data, val, phlpmut) __atomic_fetch_sub((data), (val), __ATOMIC_SEQ_CST) #define ATOMIC_SUB_unsigned(data, val, phlpmut) __atomic_fetch_sub((data), (val), __ATOMIC_SEQ_CST) #define ATOMIC_ADD(data, val) __atomic_fetch_add(&(data), (val), __ATOMIC_SEQ_CST) #define ATOMIC_INC(data, phlpmut) ((void)__atomic_fetch_add((data), 1, __ATOMIC_SEQ_CST)) #define ATOMIC_INC_AND_FETCH_int(data, phlpmut) __atomic_add_fetch((data), 1, __ATOMIC_SEQ_CST) #define ATOMIC_INC_AND_FETCH_unsigned(data, phlpmut) __atomic_add_fetch((data), 1, __ATOMIC_SEQ_CST) #define ATOMIC_DEC(data, phlpmut) ((void)__atomic_sub_fetch((data), 1, __ATOMIC_SEQ_CST)) #define ATOMIC_DEC_AND_FETCH(data, phlpmut) __atomic_sub_fetch((data), 1, __ATOMIC_SEQ_CST) #define ATOMIC_LOAD_32BIT(data, phlpmut) ((int)__atomic_load_n((data), __ATOMIC_ACQUIRE)) #define ATOMIC_LOAD_32BIT_unsigned(data, phlpmut) ((unsigned)__atomic_load_n((data), __ATOMIC_ACQUIRE)) #define ATOMIC_LOAD_32BIT_RELAXED(data, phlpmut) ((int)__atomic_load_n((data), __ATOMIC_RELAXED)) #define ATOMIC_LOAD_32BIT_RELAXED_unsigned(data, phlpmut) ((unsigned)__atomic_load_n((data), __ATOMIC_RELAXED)) #define ATOMIC_STORE_32BIT(data, phlpmut, val) ((void)__atomic_store_n((data), (val), __ATOMIC_RELEASE)) #define ATOMIC_STORE_32BIT_unsigned(data, phlpmut, val) ((void)__atomic_store_n((data), (val), __ATOMIC_RELEASE)) #define ATOMIC_STORE_32BIT_RELAXED(data, phlpmut, val) ((void)__atomic_store_n((data), (val), __ATOMIC_RELAXED)) #define ATOMIC_STORE_32BIT_RELAXED_unsigned(data, phlpmut, val) \ ((void)__atomic_store_n((data), (val), __ATOMIC_RELAXED)) #define ATOMIC_STORE_1_TO_32BIT(data) ((void)__atomic_store_n(&(data), 1, __ATOMIC_RELEASE)) #define ATOMIC_OR_INT_TO_INT(data, phlpmut, val) __atomic_fetch_or((data), (val), __ATOMIC_SEQ_CST) #define ATOMIC_CAS(data, oldVal, newVal, phlpmut) \ ({ \ __typeof__(*(data)) rs_atomic_expected = (oldVal); \ __atomic_compare_exchange_n((data), &rs_atomic_expected, (newVal), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ }) #define ATOMIC_CAS_time_t(data, oldVal, newVal, phlpmut) \ ({ \ __typeof__(*(data)) rs_atomic_expected = (oldVal); \ __atomic_compare_exchange_n((data), &rs_atomic_expected, (newVal), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ }) #define ATOMIC_CAS_VAL(data, oldVal, newVal, phlpmut) \ ({ \ __typeof__(*(data)) rs_atomic_expected = (oldVal); \ (void)__atomic_compare_exchange_n((data), &rs_atomic_expected, (newVal), 0, __ATOMIC_SEQ_CST, \ __ATOMIC_SEQ_CST); \ rs_atomic_expected; \ }) /* Atomic operations for pointers (word-sized on all supported platforms) */ #define ATOMIC_LOAD_PTR(data, phlpmut) ((void *)__atomic_load_n((data), __ATOMIC_ACQUIRE)) #define ATOMIC_STORE_PTR(data, phlpmut, val) ((void)__atomic_store_n((data), (val), __ATOMIC_RELEASE)) #define ATOMIC_CAS_PTR(data, oldVal, newVal, phlpmut) \ ({ \ __typeof__(*(data)) rs_atomic_expected = (oldVal); \ __atomic_compare_exchange_n((data), &rs_atomic_expected, (newVal), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ }) /* functions below are not needed if we have atomics */ #define DEF_ATOMIC_HELPER_MUT(x) #define INIT_ATOMIC_HELPER_MUT(x) #define DESTROY_ATOMIC_HELPER_MUT(x) /* the following operations should preferably be done atomically, but it is * not fatal if not -- that means we can live with some missed updates. So be * sure to use these macros only if that really does not matter! */ /* * PREFER_* keeps its weak contract: the no-atomics build below still uses * plain accesses. PREFER_FETCH_32BIT callers pass a scalar lvalue, not a * pointer; the atomic branch takes its address locally. */ #define PREFER_ATOMIC_INC(data) ((void)__atomic_fetch_add(&(data), 1, __ATOMIC_RELAXED)) #define PREFER_LOAD_INT(data) ((int)__atomic_load_n((data), __ATOMIC_RELAXED)) #define PREFER_FETCH_32BIT(data) ((unsigned)__atomic_load_n(&(data), __ATOMIC_RELAXED)) #define PREFER_STORE_INT(data, val) ((void)__atomic_store_n((data), (val), __ATOMIC_RELAXED)) #define PREFER_STORE_0_TO_INT(data) ((void)__atomic_store_n((data), 0, __ATOMIC_RELAXED)) #define PREFER_STORE_1_TO_INT(data) ((void)__atomic_store_n((data), 1, __ATOMIC_RELAXED)) #else /* note that we gained practical proof that theoretical problems DO occur * if we do not properly address them. See this blog post for details: * http://blog.gerhards.net/2009/01/rsyslog-data-race-analysis.html * The bottom line is that if there are no atomics available, we should NOT * simply go ahead and do without them - use mutexes or other things. The * code needs to be checked against all those cases. -- rgerhards, 2009-01-30 */ #include #define ATOMIC_INC(data, phlpmut) \ { \ pthread_mutex_lock(phlpmut); \ ++(*(data)); \ pthread_mutex_unlock(phlpmut); \ } #define ATOMIC_OR_INT_TO_INT(data, hlpmut, val) \ { \ pthread_mutex_lock(hlpmut); \ *(data) |= (val); \ pthread_mutex_unlock(hlpmut); \ } static inline int ATOMIC_CAS(int *data, int oldVal, int newVal, pthread_mutex_t *phlpmut) { int bSuccess; pthread_mutex_lock(phlpmut); if (*data == oldVal) { *data = newVal; bSuccess = 1; } else { bSuccess = 0; } pthread_mutex_unlock(phlpmut); return (bSuccess); } static inline int ATOMIC_CAS_time_t(time_t *data, time_t oldVal, time_t newVal, pthread_mutex_t *phlpmut) { int bSuccess; pthread_mutex_lock(phlpmut); if (*data == oldVal) { *data = newVal; bSuccess = 1; } else { bSuccess = 0; } pthread_mutex_unlock(phlpmut); return (bSuccess); } static inline int ATOMIC_CAS_VAL(int *data, int oldVal, int newVal, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = *data; if (*data == oldVal) { *data = newVal; } pthread_mutex_unlock(phlpmut); return (val); } #define ATOMIC_DEC(data, phlpmut) \ { \ pthread_mutex_lock(phlpmut); \ --(*(data)); \ pthread_mutex_unlock(phlpmut); \ } static inline int ATOMIC_INC_AND_FETCH_int(int *data, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = ++(*data); pthread_mutex_unlock(phlpmut); return (val); } static inline unsigned ATOMIC_INC_AND_FETCH_unsigned(unsigned *data, pthread_mutex_t *phlpmut) { unsigned val; pthread_mutex_lock(phlpmut); val = ++(*data); pthread_mutex_unlock(phlpmut); return (val); } static inline int ATOMIC_DEC_AND_FETCH(int *data, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = --(*data); pthread_mutex_unlock(phlpmut); return (val); } static inline int ATOMIC_LOAD_32BIT(int *data, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = (*data); pthread_mutex_unlock(phlpmut); return val; } static inline int ATOMIC_LOAD_32BIT_RELAXED(int *data, pthread_mutex_t *phlpmut) { int val; pthread_mutex_lock(phlpmut); val = (*data); pthread_mutex_unlock(phlpmut); return val; } static inline void ATOMIC_STORE_32BIT(int *data, pthread_mutex_t *phlpmut, int val) { pthread_mutex_lock(phlpmut); *data = val; pthread_mutex_unlock(phlpmut); } static inline void ATOMIC_STORE_32BIT_RELAXED(int *data, pthread_mutex_t *phlpmut, int val) { pthread_mutex_lock(phlpmut); *data = val; pthread_mutex_unlock(phlpmut); } static inline unsigned ATOMIC_LOAD_32BIT_unsigned(unsigned *data, pthread_mutex_t *phlpmut) { unsigned val; pthread_mutex_lock(phlpmut); val = (*data); pthread_mutex_unlock(phlpmut); return val; } static inline unsigned ATOMIC_LOAD_32BIT_RELAXED_unsigned(unsigned *data, pthread_mutex_t *phlpmut) { unsigned val; pthread_mutex_lock(phlpmut); val = (*data); pthread_mutex_unlock(phlpmut); return val; } static inline void ATOMIC_STORE_32BIT_unsigned(unsigned *data, pthread_mutex_t *phlpmut, unsigned val) { pthread_mutex_lock(phlpmut); *data = val; pthread_mutex_unlock(phlpmut); } static inline void ATOMIC_STORE_32BIT_RELAXED_unsigned(unsigned *data, pthread_mutex_t *phlpmut, unsigned val) { pthread_mutex_lock(phlpmut); *data = val; pthread_mutex_unlock(phlpmut); } static inline void ATOMIC_SUB(int *data, int val, pthread_mutex_t *phlpmut) { pthread_mutex_lock(phlpmut); (*data) -= val; pthread_mutex_unlock(phlpmut); } static inline void ATOMIC_SUB_unsigned(unsigned *data, int val, pthread_mutex_t *phlpmut) { pthread_mutex_lock(phlpmut); (*data) -= val; pthread_mutex_unlock(phlpmut); } /* Atomic operations for pointers - fallback to mutex-protected operations */ static inline void *ATOMIC_LOAD_PTR(void **data, pthread_mutex_t *phlpmut) { void *val; pthread_mutex_lock(phlpmut); val = *data; pthread_mutex_unlock(phlpmut); return val; } static inline void ATOMIC_STORE_PTR(void **data, pthread_mutex_t *phlpmut, void *val) { pthread_mutex_lock(phlpmut); *data = val; pthread_mutex_unlock(phlpmut); } static inline int ATOMIC_CAS_PTR(void **data, void *oldVal, void *newVal, pthread_mutex_t *phlpmut) { int bSuccess; pthread_mutex_lock(phlpmut); if (*data == oldVal) { *data = newVal; bSuccess = 1; } else { bSuccess = 0; } pthread_mutex_unlock(phlpmut); return bSuccess; } #define DEF_ATOMIC_HELPER_MUT(x) pthread_mutex_t x #define INIT_ATOMIC_HELPER_MUT(x) pthread_mutex_init(&(x), NULL) #define DESTROY_ATOMIC_HELPER_MUT(x) pthread_mutex_destroy(&(x)) #define PREFER_ATOMIC_INC(data) ((void)++data) #define PREFER_LOAD_INT(data) (*(data)) /* Caller passes the scalar object, not its address. No-atomic builds deliberately * use a plain read for these weak flags/counters where a racy value is acceptable. */ #define PREFER_FETCH_32BIT(data) ((unsigned)(data)) #define PREFER_STORE_INT(data, val) (*(data) = (val)) #define PREFER_STORE_0_TO_INT(data) (*(data) = 0) #define PREFER_STORE_1_TO_INT(data) (*(data) = 1) #endif /* we need to handle 64bit atomics seperately as some platforms have * 32 bit atomics, but not 64 bit ones... -- rgerhards, 2010-12-01 */ #ifdef HAVE_ATOMIC_BUILTINS64 #define ATOMIC_INC_uint64(data, phlpmut) ((void)__atomic_fetch_add((data), 1, __ATOMIC_SEQ_CST)) #define ATOMIC_ADD_uint64(data, phlpmut, value) ((void)__atomic_fetch_add((data), (value), __ATOMIC_SEQ_CST)) #define ATOMIC_SUB_uint64(data, phlpmut, value) ((void)__atomic_fetch_sub((data), (value), __ATOMIC_SEQ_CST)) #define ATOMIC_DEC_uint64(data, phlpmut) ((void)__atomic_sub_fetch((data), 1, __ATOMIC_SEQ_CST)) #define ATOMIC_INC_AND_FETCH_uint64(data, phlpmut) __atomic_add_fetch((data), 1, __ATOMIC_SEQ_CST) #define ATOMIC_LOAD_uint64(data, phlpmut) ((uint64)__atomic_load_n((data), __ATOMIC_ACQUIRE)) #define ATOMIC_CAS_uint64(data, oldVal, newVal, phlpmut) \ ({ \ __typeof__(*(data)) rs_atomic_expected = (oldVal); \ __atomic_compare_exchange_n((data), &rs_atomic_expected, (newVal), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ }) #define ATOMIC_STORE_uint64(data, phlpmut, value) ((void)__atomic_store_n((data), (value), __ATOMIC_RELEASE)) #define ATOMIC_INC_uint64_RELAXED(data, phlpmut) ((void)__atomic_fetch_add((data), 1, __ATOMIC_RELAXED)) #define ATOMIC_ADD_uint64_RELAXED(data, phlpmut, value) \ ((void)__atomic_fetch_add((data), (value), __ATOMIC_RELAXED)) #define ATOMIC_DEC_uint64_RELAXED(data, phlpmut) ((void)__atomic_sub_fetch((data), 1, __ATOMIC_RELAXED)) #define ATOMIC_LOAD_time_t_ACQUIRE(data, phlpmut) ((time_t)__atomic_load_n((data), __ATOMIC_ACQUIRE)) #define ATOMIC_LOAD_time_t_RELAXED(data, phlpmut) ((time_t)__atomic_load_n((data), __ATOMIC_RELAXED)) #define ATOMIC_STORE_time_t_RELAXED(data, phlpmut, value) \ ((void)__atomic_store_n((data), (value), __ATOMIC_RELAXED)) #define PREFER_LOAD_time_t(data) ((time_t)__atomic_load_n((data), __ATOMIC_RELAXED)) #define PREFER_STORE_time_t(data, value) ((void)__atomic_store_n((data), (value), __ATOMIC_RELAXED)) #define PREFER_LOAD_uint64(data) ((uint64)__atomic_load_n((data), __ATOMIC_RELAXED)) #define PREFER_STORE_uint64(data, value) ((void)__atomic_store_n((data), (value), __ATOMIC_RELAXED)) #define DEF_ATOMIC_HELPER_MUT64(x) #define INIT_ATOMIC_HELPER_MUT64(x) #define DESTROY_ATOMIC_HELPER_MUT64(x) #else #define ATOMIC_INC_uint64(data, phlpmut) \ { \ pthread_mutex_lock(phlpmut); \ ++(*(data)); \ pthread_mutex_unlock(phlpmut); \ } #define ATOMIC_ADD_uint64(data, phlpmut, value) \ { \ pthread_mutex_lock(phlpmut); \ *data += value; \ pthread_mutex_unlock(phlpmut); \ } #define ATOMIC_SUB_uint64(data, phlpmut, value) \ { \ pthread_mutex_lock(phlpmut); \ *data -= value; \ pthread_mutex_unlock(phlpmut); \ } #define ATOMIC_DEC_uint64(data, phlpmut) \ { \ pthread_mutex_lock(phlpmut); \ --(*(data)); \ pthread_mutex_unlock(phlpmut); \ } #define ATOMIC_INC_uint64_RELAXED(data, phlpmut) ATOMIC_INC_uint64(data, phlpmut) #define ATOMIC_ADD_uint64_RELAXED(data, phlpmut, value) ATOMIC_ADD_uint64(data, phlpmut, value) #define ATOMIC_DEC_uint64_RELAXED(data, phlpmut) ATOMIC_DEC_uint64(data, phlpmut) #define PREFER_LOAD_time_t(data) (*(data)) #define PREFER_STORE_time_t(data, value) (*(data) = (value)) #define PREFER_LOAD_uint64(data) (*(data)) #define PREFER_STORE_uint64(data, value) (*(data) = (value)) #define ATOMIC_STORE_uint64(data, phlpmut, value) \ { \ pthread_mutex_lock(phlpmut); \ *(data) = (value); \ pthread_mutex_unlock(phlpmut); \ } static inline time_t ATOMIC_LOAD_time_t_ACQUIRE(time_t *data, pthread_mutex_t *phlpmut) { time_t val; pthread_mutex_lock(phlpmut); val = *data; pthread_mutex_unlock(phlpmut); return val; } static inline time_t ATOMIC_LOAD_time_t_RELAXED(time_t *data, pthread_mutex_t *phlpmut) { time_t val; pthread_mutex_lock(phlpmut); val = *data; pthread_mutex_unlock(phlpmut); return val; } static inline void ATOMIC_STORE_time_t_RELAXED(time_t *data, pthread_mutex_t *phlpmut, time_t value) { pthread_mutex_lock(phlpmut); *data = value; pthread_mutex_unlock(phlpmut); } static inline uint64 ATOMIC_INC_AND_FETCH_uint64(uint64 *data, pthread_mutex_t *phlpmut) { uint64 val; pthread_mutex_lock(phlpmut); val = ++(*data); pthread_mutex_unlock(phlpmut); return (val); } static inline uint64 ATOMIC_LOAD_uint64(uint64 *data, pthread_mutex_t *phlpmut) { uint64 val; pthread_mutex_lock(phlpmut); val = *data; pthread_mutex_unlock(phlpmut); return val; } static inline int ATOMIC_CAS_uint64(uint64 *data, uint64 oldVal, uint64 newVal, pthread_mutex_t *phlpmut) { int bSuccess; pthread_mutex_lock(phlpmut); if (*data == oldVal) { *data = newVal; bSuccess = 1; } else { bSuccess = 0; } pthread_mutex_unlock(phlpmut); return bSuccess; } #define DEF_ATOMIC_HELPER_MUT64(x) pthread_mutex_t x #define INIT_ATOMIC_HELPER_MUT64(x) pthread_mutex_init(&(x), NULL) #define DESTROY_ATOMIC_HELPER_MUT64(x) pthread_mutex_destroy(&(x)) #endif /* #ifdef HAVE_ATOMIC_BUILTINS64 */ #endif /* #ifndef INCLUDED_ATOMIC_H */ rsyslog-8.2608.0/runtime/PaxHeaders/debug.h0000644000000000000000000000013115132411300015446 xustar0030 mtime=1768559296.262885577 30 atime=1787067616.802414742 29 ctime=1787067794.34672416 rsyslog-8.2608.0/runtime/debug.h0000666000175000017500000000622615132411300015123 0ustar00rgerrger/* debug.h * * Definitions for the debug module. * * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DEBUG_H_INCLUDED #define DEBUG_H_INCLUDED #include #include "obj-types.h" /* some settings for various debug modes */ #define DEBUG_OFF 0 #define DEBUG_ONDEMAND 1 #define DEBUG_FULL 2 /* external static data elements (some time to be replaced) */ extern int Debug; /* debug flag - read-only after startup */ extern int debugging_on; /* read-only, except on sig USR1 */ extern int stddbg; /* the handle for regular debug output, set to stdout if not forking, -1 otherwise */ extern int dbgTimeoutToStderr; /* prototypes */ rsRetVal dbgClassInit(void); rsRetVal dbgClassExit(void); void dbgSetDebugFile(uchar *fn); void dbgSetDebugLevel(int level); void dbgSetThrdName(const uchar *pszName); void dbgOutputTID(char *name); int dbgGetDbglogFd(void); /* external data */ extern char *pszAltDbgFileName; /* if set, debug output is *also* sent to here */ extern int altdbg; /* and the handle for alternate debug output */ /* macros */ #ifdef DEBUGLESS #define DBGL_UNUSED __attribute__((__unused__)) static inline void r_dbgoprint(const char DBGL_UNUSED *srcname, obj_t DBGL_UNUSED *pObj, const char DBGL_UNUSED *fmt, ...) {} static inline void r_dbgprintf(const char DBGL_UNUSED *srcname, const char DBGL_UNUSED *fmt, ...) {} #else #define DBGL_UNUSED void r_dbgoprint(const char *srcname, obj_t *pObj, const char *fmt, ...) __attribute__((format(printf, 3, 4))); void r_dbgprintf(const char *srcname, const char *fmt, ...) __attribute__((format(printf, 2, 3))); #endif #define DBGPRINTF(...) \ if (Debug) { \ r_dbgprintf(__FILE__, __VA_ARGS__); \ } #define DBGOPRINT(...) \ if (Debug) { \ r_dbgoprint(__FILE__, __VA_ARGS__); \ } #define dbgprintf(...) r_dbgprintf(__FILE__, __VA_ARGS__) #define dbgoprint(...) r_dbgoprint(__FILE__, __VA_ARGS__) /* things originally introduced for now removed rtinst */ #define d_pthread_mutex_lock(x) pthread_mutex_lock(x) #define d_pthread_mutex_trylock(x) pthread_mutex_trylock(x) #define d_pthread_mutex_unlock(x) pthread_mutex_unlock(x) #define d_pthread_cond_wait(cond, mut) pthread_cond_wait(cond, mut) #define d_pthread_cond_timedwait(cond, mut, to) pthread_cond_timedwait(cond, mut, to) #endif /* #ifndef DEBUG_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/Makefile.am0000644000000000000000000000013215241075234016261 xustar0030 mtime=1787067036.599578182 30 atime=1787067036.744580897 30 ctime=1787067794.213721682 rsyslog-8.2608.0/runtime/Makefile.am0000664000175000017500000002121515241075234015726 0ustar00rgerrgersbin_PROGRAMS = man_MANS = noinst_LIBRARIES = noinst_LTLIBRARIES = librsyslog.la pkglib_LTLIBRARIES = #pkglib_LTLIBRARIES = librsyslog.la librsyslog_la_SOURCES = \ rsyslog.c \ rsyslog.h \ typedefs.h \ dnscache.c \ dnscache.h \ unicode-helper.h \ atomic.h \ batch.h \ syslogd-types.h \ module-template.h \ im-helper.h \ obj-types.h \ sigprov.h \ cryprov.h \ nsd.h \ glbl.h \ glbl.c \ unlimited_select.h \ conf.c \ conf.h \ janitor.c \ janitor.h \ rsconf.c \ rsconf.h \ parser.h \ parser.c \ strgen.h \ strgen.c \ msg.c \ msg.h \ msg_replace_helper.h \ linkedlist.c \ linkedlist.h \ objomsr.c \ objomsr.h \ stringbuf.c \ stringbuf.h \ datetime.c \ datetime.h \ srutils.c \ srUtils.h \ errmsg.c \ errmsg.h \ operatingstate.c \ operatingstate.h \ debug.c \ debug.h \ obj.c \ obj.h \ modules.c \ modules.h \ statsobj.c \ statsobj.h \ compat_queue.h \ dynstats.c \ dynstats.h \ perctile_ringbuf.c \ perctile_ringbuf.h \ perctile_stats.c \ perctile_stats.h \ statsobj.h \ stream.c \ stream.h \ var.c \ var.h \ wtp.c \ wtp.h \ wti.c \ wti.h \ queue.c \ queue.h \ queue_da.c \ queue_da.h \ segdisk_codec.c \ segdisk_codec.h \ segdisk_crc.c \ segdisk_crc.h \ segdisk_format.h \ segdisk_state.c \ segdisk_state.h \ segdisk_store.c \ segdisk_store.h \ ruleset.c \ ruleset.h \ rswatch.c \ rswatch.h \ prop.c \ prop.h \ ratelimit.c \ ratelimit.h \ translate.c \ translate.h \ yamlconf.c \ yamlconf.h \ lookup.c \ lookup.h \ cfsysline.c \ cfsysline.h \ \ action.h \ action.c \ threads.c \ threads.h \ dirty.h \ \ parse.c \ parse.h \ \ hashtable.c \ hashtable.h \ hashtable_itr.c \ hashtable_itr.h \ hashtable_private.h \ \ outchannel.c \ outchannel.h \ template.c \ template.h \ timezones.c \ timezones.h #if OS_LINUX #librsyslog_la_SOURCES += \ #endif if WITH_MODDIRS librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" else librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I\$(top_srcdir) -I\$(top_srcdir)/grammar -I\$(top_builddir)/grammar endif #librsyslog_la_LDFLAGS = -module -avoid-version librsyslog_la_CPPFLAGS += $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) ${LIBESTR_CFLAGS} $(LIBYAML_CFLAGS) librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) $(LIBFASTJSON_LIBS) ${LIBESTR_LIBS} $(LIBYAML_LIBS) -lm if ENABLE_LIBLOGGING_STDLOG librsyslog_la_CPPFLAGS += ${LIBLOGGING_STDLOG_CFLAGS} librsyslog_la_LIBADD += $(LIBLOGGING_STDLOG_LIBS) endif librsyslog_la_CPPFLAGS += -I\$(top_srcdir)/tools # # regular expression support # if ENABLE_REGEXP pkglib_LTLIBRARIES += lmregexp.la lmregexp_la_SOURCES = regexp.c regexp.h lmregexp_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmregexp_la_LDFLAGS = -module -avoid-version lmregexp_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG lmregexp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmregexp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif endif # # zlib support # pkglib_LTLIBRARIES += lmzlibw.la lmzlibw_la_SOURCES = zlibw.c zlibw.h lmzlibw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmzlibw_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS) lmzlibw_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG lmzlibw_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmzlibw_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif # # basic network support, needed for rsyslog startup (e.g. our own system name) # pkglib_LTLIBRARIES += lmnet.la lmnet_la_SOURCES = net.c net.h netns_socket.c netns_socket.h lmnet_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmnet_la_LDFLAGS = -module -avoid-version ../compat/compat_la-getifaddrs.lo lmnet_la_LIBADD = if ENABLE_INET pkglib_LTLIBRARIES += lmnetstrms.la if ENABLE_LIBLOGGING_STDLOG lmnet_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmnet_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif # network stream master class and stream factory lmnetstrms_la_SOURCES = netstrms.c netstrms.h \ netstrm.c netstrm.h lmnetstrms_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmnetstrms_la_LDFLAGS = -module -avoid-version lmnetstrms_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG lmnetstrms_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmnetstrms_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif # netstream drivers # plain tcp driver - main driver pkglib_LTLIBRARIES += lmnsd_ptcp.la lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h lmnsd_ptcp_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmnsd_ptcp_la_LDFLAGS = -module -avoid-version lmnsd_ptcp_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG lmnsd_ptcp_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmnsd_ptcp_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif endif # if ENABLE_INET # # openssl base and netstream driver # if ENABLE_OSSL # noinst_LTLIBRARIES += lmnsd_ossl.la pkglib_LTLIBRARIES += lmnsd_ossl.la lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h net_ossl_store.c net_ossl_store.h nsd_ossl.c nsd_ossl.h lmnsd_ossl_la_LDFLAGS = -module -avoid-version if ENABLE_WOLFSSL lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(WOLFSSL_CFLAGS) lmnsd_ossl_la_LIBADD = $(WOLFSSL_LIBS) $(GAI_LIBS) else lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS) $(GAI_LIBS) endif endif # # GnuTLS netstream driver # if ENABLE_GNUTLS pkglib_LTLIBRARIES += lmnsd_gtls.la lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h lmnsd_gtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GNUTLS_CFLAGS) lmnsd_gtls_la_LDFLAGS = -module -avoid-version lmnsd_gtls_la_LIBADD = $(GNUTLS_LIBS) endif # # Mbed TLS netstream driver # if ENABLE_MBEDTLS pkglib_LTLIBRARIES += lmnsd_mbedtls.la lmnsd_mbedtls_la_SOURCES = nsd_mbedtls.c nsd_mbedtls.h lmnsd_mbedtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(MBEDTLS_CFLAGS) lmnsd_mbedtls_la_LDFLAGS = -module -avoid-version lmnsd_mbedtls_la_LIBADD = $(MBEDTLS_LIBS) endif # # support library for libgcrypt # if ENABLE_LIBGCRYPT noinst_LTLIBRARIES += libgcry.la libgcry_la_SOURCES = libgcry.c libcry_common.c libcry_common.h libgcry.h libgcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS) pkglib_LTLIBRARIES += lmcry_gcry.la lmcry_gcry_la_DEPENDENCIES = libgcry.la lmcry_gcry_la_SOURCES = lmcry_gcry.c lmcry_gcry.h lmcry_gcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS) lmcry_gcry_la_LDFLAGS = -module -avoid-version lmcry_gcry_la_LIBADD = libgcry.la $(LIBGCRYPT_LIBS) endif # # support library for openssl crypto provider # if ENABLE_OPENSSL_CRYPTO_PROVIDER # Helper noinst_LTLIBRARIES += libossl.la libossl_la_SOURCES = libossl.c libossl.h libcry_common.c libcry_common.h libossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) pkglib_LTLIBRARIES += lmcry_ossl.la lmcry_ossl_la_DEPENDENCIES = libossl.la lmcry_ossl_la_SOURCES = lmcry_ossl.c lmcry_ossl.h lmcry_ossl_la_CPPFLAGS = $(RSRT_CFLAGS) $(OPENSSL_FLAGS) lmcry_ossl_la_LDFLAGS = -module -avoid-version lmcry_ossl_la_LIBADD = libossl.la $(OPENSSL_LIBS) endif # # support library for zstd # if ENABLE_LIBZSTD pkglib_LTLIBRARIES += lmzstdw.la lmzstdw_la_SOURCES = zstdw.c zstdw.h lmzstdw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmzstdw_la_LDFLAGS = -module -avoid-version $(ZSTD_LIBS) lmzstdw_la_LIBADD = -lzstd endif # # gssapi support # if ENABLE_GSSAPI pkglib_LTLIBRARIES += lmgssutil.la lmgssutil_la_SOURCES = gss-misc.c gss-misc.h gss-token-util.h lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GSS_CFLAGS) lmgssutil_la_LDFLAGS = -module -avoid-version lmgssutil_la_LIBADD = $(GSS_LIBS) endif pkglib_LTLIBRARIES += lmtcpsrv.la lmtcpclt.la # # # TCP (stream) server support # lmtcpsrv_la_SOURCES = \ tcps_sess.c \ tcps_sess.h \ tcpsrv.c \ tcpsrv.h lmtcpsrv_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmtcpsrv_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS) lmtcpsrv_la_LIBADD = if ENABLE_LIBZSTD lmtcpsrv_la_CPPFLAGS += $(ZSTD_CFLAGS) lmtcpsrv_la_LDFLAGS += $(ZSTD_LIBS) endif if ENABLE_LIBLOGGING_STDLOG lmtcpsrv_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmtcpsrv_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif # # TCP (stream) client support # lmtcpclt_la_SOURCES = \ tcpclt.c \ tcpclt.h lmtcpclt_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) lmtcpclt_la_LDFLAGS = -module -avoid-version lmtcpclt_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG lmtcpclt_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) lmtcpclt_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif # # support library for Guardtime KSI-LS12 # if ENABLE_KSI_LS12 pkglib_LTLIBRARIES += lmsig_ksi_ls12.la lmsig_ksi_ls12_la_SOURCES = lmsig_ksi-ls12.c lmsig_ksi-ls12.h lib_ksils12.c \ lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h lmsig_ksi_ls12_la_CPPFLAGS = $(RSRT_CFLAGS) $(GT_KSI_LS12_CFLAGS) lmsig_ksi_ls12_la_LDFLAGS = -module -avoid-version $(GT_KSI_LS12_LIBS) endif rsyslog-8.2608.0/runtime/PaxHeaders/linkedlist.c0000644000000000000000000000013215163426372016541 xustar0030 mtime=1775119610.131692432 30 atime=1787067617.958436297 30 ctime=1787067794.312723527 rsyslog-8.2608.0/runtime/linkedlist.c0000664000175000017500000002463615163426372016220 0ustar00rgerrger/* linkedlist.c * This file set implements a generic linked list object. It can be used * wherever a linke list is required. * * NOTE: we do not currently provide a constructor and destructor for the * object itself as we assume it will always be part of another strucuture. * Having a pointer to it, I think, does not really make sense but costs * performance. Consequently, there is is llInit() and llDestroy() and they * do what a constructor and destructur do, except for creating the * linkedList_t structure itself. * * File begun on 2007-07-31 by RGerhards * * Copyright (C) 2007-2012 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "linkedlist.h" /* Initialize an existing linkedList_t structure * pKey destructor may be zero to take care of non-keyed lists. */ rsRetVal llInit(linkedList_t *pThis, rsRetVal (*pEltDestructor)(void *), rsRetVal (*pKeyDestructor)(void *), int (*pCmpOp)(void *, void *)) { assert(pThis != NULL); assert(pEltDestructor != NULL); pThis->pEltDestruct = pEltDestructor; pThis->pKeyDestruct = pKeyDestructor; pThis->cmpOp = pCmpOp; pThis->pKey = NULL; pThis->iNumElts = 0; pThis->pRoot = NULL; pThis->pLast = NULL; return RS_RET_OK; }; /* llDestroyEltData - destroys a list element * It is a separate function as the * functionality is needed in multiple code-pathes. */ static rsRetVal llDestroyElt(linkedList_t *pList, llElt_t *pElt) { DEFiRet; assert(pList != NULL); assert(pElt != NULL); /* we ignore errors during destruction, as we need to try * free the element in any case. */ if (pElt->pData != NULL) pList->pEltDestruct(pElt->pData); if (pElt->pKey != NULL) pList->pKeyDestruct(pElt->pKey); free(pElt); pList->iNumElts--; /* one less */ RETiRet; } /* llDestroy - destroys a COMPLETE linkedList */ rsRetVal llDestroy(linkedList_t *pThis) { DEFiRet; llElt_t *pElt; assert(pThis != NULL); pElt = pThis->pRoot; while (pElt != NULL) { /* keep the list structure in a consistent state as * the destructor bellow may reference it again */ pThis->pRoot = pElt->pNext; if (pElt->pNext == NULL) pThis->pLast = NULL; /* we ignore errors during destruction, as we need to try * finish the linked list in any case. */ llDestroyElt(pThis, pElt); pElt = pThis->pRoot; } RETiRet; } /* llDestroyRootElt - destroy the root element but otherwise * keeps this list intact. -- rgerhards, 2007-08-03 */ rsRetVal llDestroyRootElt(linkedList_t *pThis) { DEFiRet; llElt_t *pPrev; if (pThis->pRoot == NULL) { ABORT_FINALIZE(RS_RET_EMPTY_LIST); } pPrev = pThis->pRoot; if (pPrev->pNext == NULL) { /* it was the only list element */ pThis->pLast = NULL; pThis->pRoot = NULL; } else { /* there are other list elements */ pThis->pRoot = pPrev->pNext; } CHKiRet(llDestroyElt(pThis, pPrev)); finalize_it: RETiRet; } /* get next user data element of a linked list. The caller must also * provide a "cookie" to the function. On initial call, it must be * NULL. Other than that, the caller is not allowed to to modify the * cookie. In the current implementation, the cookie is an actual * pointer to the current list element, but this is nothing that the * caller should rely on. */ rsRetVal llGetNextElt(linkedList_t *pThis, linkedListCookie_t *ppElt, void **ppUsr) { llElt_t *pElt; DEFiRet; assert(pThis != NULL); assert(ppElt != NULL); assert(ppUsr != NULL); pElt = *ppElt; pElt = (pElt == NULL) ? pThis->pRoot : pElt->pNext; if (pElt == NULL) { iRet = RS_RET_END_OF_LINKEDLIST; } else { *ppUsr = pElt->pData; } *ppElt = pElt; RETiRet; } /* return the key of an Elt * rgerhards, 2007-09-11: note that ppDatea is actually a void**, * but I need to make it a void* to avoid lots of compiler warnings. * It will be converted later down in the code. */ rsRetVal llGetKey(llElt_t *pThis, void *ppData) { assert(pThis != NULL); assert(ppData != NULL); *(void **)ppData = pThis->pKey; return RS_RET_OK; } /* construct a new llElt_t */ static rsRetVal llEltConstruct(llElt_t **ppThis, void *pKey, void *pData) { DEFiRet; llElt_t *pThis; assert(ppThis != NULL); if ((pThis = (llElt_t *)calloc(1, sizeof(llElt_t))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pThis->pKey = pKey; pThis->pData = pData; finalize_it: *ppThis = pThis; RETiRet; } /* append a user element to the end of the linked list. This includes setting a key. If no * key is desired, simply pass in a NULL pointer for it. */ rsRetVal llAppend(linkedList_t *pThis, void *pKey, void *pData) { llElt_t *pElt; DEFiRet; CHKiRet(llEltConstruct(&pElt, pKey, pData)); pThis->iNumElts++; /* one more */ if (pThis->pLast == NULL) { pThis->pRoot = pElt; } else { pThis->pLast->pNext = pElt; } pThis->pLast = pElt; finalize_it: RETiRet; } /* unlink a requested element. As we have singly-linked lists, the * caller also needs to pass in the previous element (or NULL, if it is the * root element). * rgerhards, 2007-11-21 */ static rsRetVal llUnlinkElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev) { assert(pElt != NULL); if (pEltPrev == NULL) { /* root element? */ pThis->pRoot = pElt->pNext; } else { /* regular element */ pEltPrev->pNext = pElt->pNext; } if (pElt == pThis->pLast) pThis->pLast = pEltPrev; return RS_RET_OK; } /* unlinks and immediately deletes an element. Previous element must * be given (or zero if the root element is to be deleted). * rgerhards, 2007-11-21 */ static rsRetVal llUnlinkAndDelteElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev) { DEFiRet; assert(pElt != NULL); CHKiRet(llUnlinkElt(pThis, pElt, pEltPrev)); CHKiRet(llDestroyElt(pThis, pElt)); finalize_it: RETiRet; } /* find a user element based on the provided key - this is the * internal variant, which also tracks the last element pointer * before the found element. This is necessary to delete elements. * NULL means there is no element in front of it, aka the found elt * is the root elt. * rgerhards, 2007-11-21 */ static rsRetVal llFindElt(linkedList_t *pThis, void *pKey, llElt_t **ppElt, llElt_t **ppEltPrev) { DEFiRet; llElt_t *pElt; llElt_t *pEltPrev = NULL; int bFound = 0; assert(pThis != NULL); assert(pKey != NULL); assert(ppElt != NULL); assert(ppEltPrev != NULL); pElt = pThis->pRoot; while (pElt != NULL && bFound == 0) { if (pThis->cmpOp(pKey, pElt->pKey) == 0) bFound = 1; else { pEltPrev = pElt; pElt = pElt->pNext; } } if (bFound == 1) { *ppElt = pElt; *ppEltPrev = pEltPrev; } else iRet = RS_RET_NOT_FOUND; RETiRet; } /* find a user element based on the provided key */ rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData) { DEFiRet; llElt_t *pElt; llElt_t *pEltPrev; CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev)); /* if we reach this point, we have found the element */ *ppData = pElt->pData; finalize_it: RETiRet; } /* find a delete an element based on user-provided key. The element is * delete, the caller does not receive anything. If we need to receive * the element before destruction, we may implement an llFindAndUnlink() * at that time. * rgerhards, 2007-11-21 */ rsRetVal llFindAndDelete(linkedList_t *pThis, void *pKey) { DEFiRet; llElt_t *pElt; llElt_t *pEltPrev; CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev)); /* if we reach this point, we have found an element */ CHKiRet(llUnlinkAndDelteElt(pThis, pElt, pEltPrev)); finalize_it: RETiRet; } /* provide the count of linked list elements */ rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt) { DEFiRet; assert(pThis != NULL); assert(piCnt != NULL); *piCnt = pThis->iNumElts; RETiRet; } /* execute a function on all list members. The functions receives a * user-supplied parameter, which may be either a simple value * or a pointer to a structure with more data. If the user-supplied * function does not return RS_RET_OK, this function here terminates. * rgerhards, 2007-08-02 * rgerhards, 2007-11-21: added functionality to delete a list element. * If the called user function returns RS_RET_OK_DELETE_LISTENTRY the current element * is deleted. */ rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void *, void *), void *pParam) { DEFiRet; rsRetVal iRetLL; void *pData; linkedListCookie_t llCookie = NULL; linkedListCookie_t llCookiePrev = NULL; /* previous list element (needed for deletion, NULL = at root) */ assert(pThis != NULL); assert(pFunc != NULL); while ((iRetLL = llGetNextElt(pThis, &llCookie, (void **)&pData)) == RS_RET_OK) { iRet = pFunc(pData, pParam); if (iRet == RS_RET_OK_DELETE_LISTENTRY) { /* delete element */ CHKiRet(llUnlinkAndDelteElt(pThis, llCookie, llCookiePrev)); /* we need to revert back, as we have just deleted the current element. * So the actual current element is the one before it, which happens to be * stored in llCookiePrev. -- rgerhards, 2007-11-21 */ llCookie = llCookiePrev; } else if (iRet != RS_RET_OK) { FINALIZE; } llCookiePrev = llCookie; } if (iRetLL != RS_RET_END_OF_LINKEDLIST) iRet = iRetLL; finalize_it: RETiRet; } /* vim:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/dnscache.h0000644000000000000000000000013215132411300016131 xustar0030 mtime=1768559296.262885577 30 atime=1787067618.195440716 30 ctime=1787067794.248722334 rsyslog-8.2608.0/runtime/dnscache.h0000666000175000017500000000237115132411300015602 0ustar00rgerrger/* Definitions for dnscache module. * * Copyright 2011-2019 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_DNSCACHE_H #define INCLUDED_DNSCACHE_H rsRetVal dnscacheInit(void); rsRetVal dnscacheDeinit(void); rsRetVal ATTR_NONNULL(1, 5) dnscacheLookup(struct sockaddr_storage *const addr, prop_t **const fqdn, prop_t **const fqdnLowerCase, prop_t **const localName, prop_t **const ip); #endif /* #ifndef INCLUDED_DNSCACHE_H */ rsyslog-8.2608.0/runtime/PaxHeaders/modules.h0000644000000000000000000000013115145046112016041 xustar0029 mtime=1771326538.99501357 30 atime=1787067616.810414892 30 ctime=1787067794.355724328 rsyslog-8.2608.0/runtime/modules.h0000664000175000017500000002327415145046112015516 0ustar00rgerrger/* modules.h * * Definition for build-in and plug-ins module handler. This file is the base * for all dynamically loadable module support. In theory, in v3 all modules * are dynamically loaded, in practice we currently do have a few build-in * once. This may become removed. * * The loader keeps track of what is loaded. For library modules, it is also * used to find objects (libraries) and to obtain the queryInterface function * for them. A reference count is maintened for libraries, so that they are * unloaded only when nobody still accesses them. * * File begun on 2007-07-22 by RGerhards * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef MODULES_H_INCLUDED #define MODULES_H_INCLUDED 1 #include "objomsr.h" #include "rainerscript.h" typedef struct action_s action_t; /* the following define defines the current version of the module interface. * It can be used by any module which want's to simply prevent version conflicts * and does not intend to do specific old-version emulations. * rgerhards, 2008-03-04 * version 3 adds modInfo_t ptr to call of modInit -- rgerhards, 2008-03-10 * version 4 removes needUDPSocket OM callback -- rgerhards, 2008-03-22 * version 5 changes the way parsing works for input modules. This is * an important change, parseAndSubmitMessage() goes away. Other * module types are not affected. -- rgerhards, 2008-10-09 * version 6 introduces scoping support (starting with the output * modules) -- rgerhards, 2010-07-27 */ #define CURR_MOD_IF_VERSION 6 typedef enum eModType_ { eMOD_IN = 0, /* input module */ eMOD_OUT = 1, /* output module */ eMOD_LIB = 2, /* library module */ eMOD_PARSER = 3, /* parser module */ eMOD_STRGEN = 4, /* strgen module */ eMOD_FUNCTION = 5, /*rscript function module*/ eMOD_ANY = 6 /* meta-name for "any type of module" -- to be used in function calls */ } eModType_t; #ifdef DEBUG typedef struct modUsr_s { struct modUsr_s *pNext; char *pszFile; } modUsr_t; #endif /* how is this module linked? */ typedef enum eModLinkType_ { eMOD_LINK_STATIC, eMOD_LINK_DYNAMIC_UNLOADED, /* dynalink module, currently not loaded */ eMOD_LINK_DYNAMIC_LOADED, /* dynalink module, currently loaded */ eMOD_LINK_ALL /* special: all linkage types, e.g. for unload */ } eModLinkType_t; /* remember which shared libs we dlopen()-ed */ struct dlhandle_s { uchar *pszName; void *pModHdlr; struct dlhandle_s *next; }; /* should this module be kept linked? */ typedef enum eModKeepType_ { eMOD_NOKEEP, eMOD_KEEP } eModKeepType_t; struct modInfo_s { struct modInfo_s *pPrev; /* support for creating a double linked module list */ struct modInfo_s *pNext; /* support for creating a linked module list */ int iIFVers; /* Interface version of module */ eModType_t eType; /* type of this module */ eModLinkType_t eLinkType; eModKeepType_t eKeepType; /* keep the module dynamically linked on unload */ uchar *pszName; /* printable module name, e.g. for dbgprintf */ uchar *cnfName; /* name to be used in config statements (e.g. 'name="omusrmsg"') */ unsigned uRefCnt; /* reference count for this module; 0 -> may be unloaded */ sbool bSetModCnfCalled; /* is setModCnf already called? Needed for built-in modules */ /* functions supported by all types of modules */ rsRetVal (*modInit)(int, int *, rsRetVal (**)(void *)); /* initialize the module */ /* be sure to support version handshake! */ rsRetVal (*modQueryEtryPt)(uchar *name, rsRetVal (**EtryPoint)()); /* query entry point addresses */ rsRetVal (*isCompatibleWithFeature)(syslogFeature); rsRetVal (*freeInstance)(void *); /* called before termination or module unload */ rsRetVal (*dbgPrintInstInfo)(void *); /* called before termination or module unload */ rsRetVal (*tryResume)(void *); /* called to see if module actin can be resumed now */ rsRetVal (*modExit)(void); /* called before termination or module unload */ rsRetVal (*modGetID)(void **); /* get its unique ID from module */ rsRetVal (*doHUP)(void *); /* HUP handler, action level */ rsRetVal (*doHUPWrkr)(void *); /* HUP handler, wrkr instance level */ /* v2 config system specific */ rsRetVal (*beginCnfLoad)(void *newCnf, rsconf_t *pConf); rsRetVal (*setModCnf)(struct nvlst *lst); rsRetVal (*endCnfLoad)(void *Cnf); rsRetVal (*checkCnf)(void *Cnf); rsRetVal (*activateCnfPrePrivDrop)(void *Cnf); rsRetVal (*activateCnf)(void *Cnf); /* make provided config the running conf */ rsRetVal (*freeCnf)(void *Cnf); /* end v2 config system specific */ union { struct { /* data for input modules */ /* TODO: remove? */ rsRetVal (*willRun)(void); /* check if the current config will be able to run*/ rsRetVal (*runInput)(thrdInfo_t *); /* function to gather input and submit to queue */ rsRetVal (*afterRun)(thrdInfo_t *); /* function to gather input and submit to queue */ rsRetVal (*newInpInst)(struct nvlst *lst); int bCanRun; /* cached value of whether willRun() succeeded */ } im; struct { /* data for output modules */ /* below: perform the configured action */ rsRetVal (*beginTransaction)(void *); rsRetVal (*commitTransaction)(void *const, actWrkrIParams_t *const, const unsigned); rsRetVal (*doAction)(void **params, void *pWrkrData); rsRetVal (*endTransaction)(void *); rsRetVal (*parseSelectorAct)(uchar **, void **, omodStringRequest_t **); rsRetVal (*newActInst)(uchar *modName, struct nvlst *lst, void **, omodStringRequest_t **); rsRetVal (*SetShutdownImmdtPtr)(void *pData, void *pPtr); rsRetVal (*createWrkrInstance)(void *ppWrkrData, void *pData); rsRetVal (*freeWrkrInstance)(void *pWrkrData); rsRetVal (*setActionInfo)(void *pData, action_t *pAction); sbool supportsTX; /* set if the module supports transactions */ } om; struct { /* data for library modules */ char dummy; } lm; struct { /* data for parser modules */ rsRetVal (*newParserInst)(struct nvlst *lst, void *pinst); rsRetVal (*checkParserInst)(void *pinst); rsRetVal (*freeParserInst)(void *pinst); rsRetVal (*parse2)(instanceConf_t *const, smsg_t *); rsRetVal (*parse)(smsg_t *); } pm; struct { /* data for strgen modules */ rsRetVal (*strgen)(const smsg_t *const, actWrkrIParams_t *const iparam); } sm; struct { /* data for rscript modules */ rsRetVal (*getFunctArray)(int *const, struct scriptFunct **); } fm; } mod; void *pModHdlr; /* handler to the dynamic library holding the module */ #ifdef DEBUG /* we add some home-grown support to track our users (and detect who does not free us). */ modUsr_t *pModUsrRoot; #endif }; /* interfaces */ BEGINinterface(module) /* name must also be changed in ENDinterface macro! */ modInfo_t *(*GetNxt)(modInfo_t *pThis); cfgmodules_etry_t *(*GetNxtCnfType)(rsconf_t *cnf, cfgmodules_etry_t *pThis, eModType_t rqtdType); uchar *(*GetName)(modInfo_t *pThis); uchar *(*GetStateName)(modInfo_t *pThis); rsRetVal (*Use)(const char *srcFile, modInfo_t *pThis); /**< must be called before a module is used (ref counting) */ rsRetVal (*Release)(const char *srcFile, modInfo_t **ppThis); /**< release a module (ref counting) */ void (*PrintList)(void); rsRetVal (*UnloadAndDestructAll)(eModLinkType_t modLinkTypesToUnload); rsRetVal (*doModInit)(rsRetVal (*modInit)(), uchar *name, void *pModHdlr, modInfo_t **pNew); rsRetVal (*Load)(uchar *name, sbool bConfLoad, struct nvlst *lst); rsRetVal (*SetModDir)(uchar *name); modInfo_t *(*FindWithCnfName)(rsconf_t *cnf, uchar *name, eModType_t rqtdType); /* added v3, 2011-07-19 */ ENDinterface(module) #define moduleCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */ /* Changes: * v2 * - added param bCondLoad to Load call - 2011-04-27 * - removed GetNxtType, added GetNxtCnfType - 2011-04-27 * v3 (see above) * v4 * - added third parameter to Load() - 2012-06-20 */ /* prototypes */ PROTOTYPEObj(module); /* in v6, we go back to in-core static link for core objects, at least those * that are not called from plugins. * ... and we need to know that none of the module functions are called from plugins! * rgerhards, 2012-09-24 */ rsRetVal modulesProcessCnf(struct cnfobj *o); uchar *modGetName(modInfo_t *pThis); rsRetVal ATTR_NONNULL(1) addModToCnfList(cfgmodules_etry_t **pNew, cfgmodules_etry_t *pLast); rsRetVal readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast); void modDoHUP(void); #endif /* #ifndef MODULES_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/net_ossl.c0000644000000000000000000000013115241075234016216 xustar0030 mtime=1787067036.603578257 29 atime=1787067036.74958099 30 ctime=1787067794.554728037 rsyslog-8.2608.0/runtime/net_ossl.c0000664000175000017500000030720015241075234015665 0ustar00rgerrger/* net.c * Implementation of network-related stuff. * * File begun on 2023-08-29 by Alorbach (extracted from net.c) * * Copyright 2023 Andre Lorbach and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__GLIBC__) #include #endif #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "parse.h" #include "srUtils.h" #include "obj.h" #include "errmsg.h" #include "net.h" #include "net_ossl.h" #include "net_ossl_store.h" #include "nsd_ptcp.h" #include "rsconf.h" #define OCSP_TIMEOUT 5 #define OCSP_CACHE_MAX_ENTRIES 100 #define OCSP_CACHE_DEFAULT_TTL 3600 /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(nsd_ptcp) /* Prototypes for openssl helper functions */ void net_ossl_lastOpenSSLErrorMsg( uchar *fromHost, int ret, SSL *ssl, int severity, const char *pszCallSource, const char *pszOsslApi); void net_ossl_set_ssl_verify_callback(SSL *pSsl, int flags); void net_ossl_set_ctx_verify_callback(SSL_CTX *pCtx, int flags); void net_ossl_set_bio_callback(BIO *conn); int net_ossl_verify_callback(int status, X509_STORE_CTX *store); #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) rsRetVal net_ossl_apply_tlscgfcmd(net_ossl_t *pThis, uchar *tlscfgcmd); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L rsRetVal net_ossl_chkpeercertvalidity(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP); X509 *net_ossl_getpeercert(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP); rsRetVal net_ossl_peerfingerprint(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP); #ifndef ENABLE_WOLFSSL void ocsp_cache_cleanup(void); #endif rsRetVal net_ossl_chkpeername(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP); #ifdef ENABLE_WOLFSSL static rsRetVal net_ossl_wolfssl_enable_leaf_crl(SSL_CTX *ctx, const char *crlFile) { WOLFSSL_CERT_MANAGER *cm; DEFiRet; cm = wolfSSL_CTX_GetCertManager(ctx); if (cm == NULL) { LogError(0, RS_RET_CRL_INVALID, "wolfSSL: CertManager unavailable after loading CRL '%s'", crlFile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } /* wolfSSL_X509_STORE_add_crl enables chain-wide CRL checks, while the * DER loader does not enable CRL checks at all. Normalize both paths to * OpenSSL's X509_V_FLAG_CRL_CHECK behavior: verify the leaf certificate. */ if (wolfSSL_CertManagerDisableCRL(cm) != WOLFSSL_SUCCESS) { LogError(0, RS_RET_CRL_INVALID, "wolfSSL: CRL checking could not be reset for CRL '%s'", crlFile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } if (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) != WOLFSSL_SUCCESS) { LogError(0, RS_RET_CRL_INVALID, "wolfSSL: CRL checking could not be enabled for CRL '%s'", crlFile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } finalize_it: RETiRet; } #endif /*--------------------------------------MT OpenSSL helpers ------------------------------------------*/ #ifndef ENABLE_WOLFSSL #if defined(__GLIBC__) typedef struct ocsp_gai_req_s { struct gaicb request; struct addrinfo hints; char *host; char *port; } ocsp_gai_req_t; static void ocsp_gai_req_free(ocsp_gai_req_t *req) { if (req == NULL) return; if (req->request.ar_result != NULL) freeaddrinfo(req->request.ar_result); free(req->host); free(req->port); free(req); } static void *ocsp_gai_cleanup_thread(void *arg) { ocsp_gai_req_t *req = (ocsp_gai_req_t *)arg; const struct gaicb *requests[1]; requests[0] = &req->request; (void)gai_suspend(requests, 1, NULL); (void)gai_error(&req->request); ocsp_gai_req_free(req); return NULL; } static int ocsp_gai_cleanup_async(ocsp_gai_req_t *req) { pthread_t tid; if (pthread_create(&tid, NULL, ocsp_gai_cleanup_thread, req) != 0) { const struct gaicb *requests[1]; requests[0] = &req->request; (void)gai_suspend(requests, 1, NULL); (void)gai_error(&req->request); ocsp_gai_req_free(req); } else { pthread_detach(tid); } return EAI_AGAIN; } #endif static int ocsp_getaddrinfo(const char *host, const char *port, const struct addrinfo *hints, struct addrinfo **res) { #if defined(__GLIBC__) ocsp_gai_req_t *req; struct gaicb *requests[1]; struct timespec timeout; int ret; req = calloc(1, sizeof(*req)); if (req == NULL) return EAI_MEMORY; req->host = strdup(host); req->port = strdup(port); if (req->host == NULL || req->port == NULL) { ocsp_gai_req_free(req); return EAI_MEMORY; } req->hints = *hints; req->request.ar_name = req->host; req->request.ar_service = req->port; req->request.ar_request = &req->hints; requests[0] = &req->request; ret = getaddrinfo_a(GAI_NOWAIT, requests, 1, NULL); if (ret != 0) { ocsp_gai_req_free(req); return ret; } timeout.tv_sec = OCSP_TIMEOUT; timeout.tv_nsec = 0; ret = gai_suspend((const struct gaicb *const *)requests, 1, &timeout); if (ret == EAI_AGAIN) { ret = gai_cancel(&req->request); if (ret == EAI_CANCELED) { ocsp_gai_req_free(req); return EAI_AGAIN; } if (ret == EAI_NOTCANCELED) { return ocsp_gai_cleanup_async(req); } if (ret == EAI_ALLDONE) { ret = 0; } } if (ret != 0) { ocsp_gai_req_free(req); return ret; } ret = gai_error(&req->request); if (ret == 0) { *res = req->request.ar_result; req->request.ar_result = NULL; } else { (void)gai_cancel(&req->request); } ocsp_gai_req_free(req); return ret; #else return getaddrinfo(host, port, hints, res); #endif } static MUTEX_TYPE *mutex_buf = NULL; static sbool openssl_initialized = 0; // Avoid multiple initialization / deinitialization void locking_function(int mode, int n, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { if (mode & CRYPTO_LOCK) MUTEX_LOCK(mutex_buf[n]); else MUTEX_UNLOCK(mutex_buf[n]); } unsigned long id_function(void) { return ((unsigned long)THREAD_ID); } struct CRYPTO_dynlock_value *dyn_create_function(__attribute__((unused)) const char *file, __attribute__((unused)) int line) { struct CRYPTO_dynlock_value *value; value = (struct CRYPTO_dynlock_value *)malloc(sizeof(struct CRYPTO_dynlock_value)); if (!value) return NULL; MUTEX_SETUP(value->mutex); return value; } void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { if (mode & CRYPTO_LOCK) MUTEX_LOCK(l->mutex); else MUTEX_UNLOCK(l->mutex); } void dyn_destroy_function(struct CRYPTO_dynlock_value *l, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { MUTEX_CLEANUP(l->mutex); free(l); } /* set up support functions for openssl multi-threading. This must * be done at library initialisation. If the function fails, * processing can not continue normally. On failure, 0 is * returned, on success 1. */ int opensslh_THREAD_setup(void) { int i; if (openssl_initialized == 1) { DBGPRINTF("openssl: multithread setup already initialized\n"); return 1; } mutex_buf = (MUTEX_TYPE *)malloc(CRYPTO_num_locks() * sizeof(MUTEX_TYPE)); if (mutex_buf == NULL) return 0; for (i = 0; i < CRYPTO_num_locks(); i++) MUTEX_SETUP(mutex_buf[i]); #if OPENSSL_VERSION_NUMBER < 0x10100000L CRYPTO_set_id_callback(id_function); #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ CRYPTO_set_locking_callback(locking_function); /* The following three CRYPTO_... functions are the OpenSSL functions for registering the callbacks we implemented above */ CRYPTO_set_dynlock_create_callback(dyn_create_function); CRYPTO_set_dynlock_lock_callback(dyn_lock_function); CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function); DBGPRINTF("openssl: multithread setup finished\n"); openssl_initialized = 1; return 1; } /* shut down openssl - do this only when you are totally done * with openssl. */ int opensslh_THREAD_cleanup(void) { int i; if (openssl_initialized == 0) { DBGPRINTF("openssl: multithread cleanup already done\n"); return 1; } if (!mutex_buf) return 0; #if OPENSSL_VERSION_NUMBER < 0x10100000L CRYPTO_set_id_callback(NULL); #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ CRYPTO_set_locking_callback(NULL); CRYPTO_set_dynlock_create_callback(NULL); CRYPTO_set_dynlock_lock_callback(NULL); CRYPTO_set_dynlock_destroy_callback(NULL); for (i = 0; i < CRYPTO_num_locks(); i++) MUTEX_CLEANUP(mutex_buf[i]); free(mutex_buf); mutex_buf = NULL; DBGPRINTF("openssl: multithread cleanup finished\n"); openssl_initialized = 0; return 1; } #else int opensslh_THREAD_setup(void) { return 1; } int opensslh_THREAD_cleanup(void) { return 1; } #endif /* !ENABLE_WOLFSSL */ /*-------------------------------------- MT OpenSSL helpers -----------------------------------------*/ /*--------------------------------------OpenSSL helpers ------------------------------------------*/ /* globally initialize OpenSSL */ void osslGlblInit(void) { DBGPRINTF("osslGlblInit: ENTER\n"); #ifdef ENABLE_WOLFSSL if (!SSL_library_init()) { LogError(0, RS_RET_NO_ERRCODE, "Error: OpenSSL initialization failed!"); } #else if ((opensslh_THREAD_setup() == 0) || #if OPENSSL_VERSION_NUMBER < 0x10100000L /* Setup OpenSSL library < 1.1.0 */ !SSL_library_init() #else /* Setup OpenSSL library >= 1.1.0 with system default settings */ OPENSSL_init_ssl(0, NULL) == 0 #endif ) { LogError(0, RS_RET_NO_ERRCODE, "Error: OpenSSL initialization failed!"); } #endif #if defined(ENABLE_WOLFSSL) && defined(DEBUG_WOLFSSL) wolfSSL_Debugging_ON(); #endif /* Load readable error strings */ SSL_load_error_strings(); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) /* * ERR_load_*(), ERR_func_error_string(), ERR_get_error_line(), ERR_get_error_line_data(), ERR_get_state() * OpenSSL now loads error strings automatically so these functions are not needed. * SEE FOR MORE: * https://www.openssl.org/docs/manmaster/man7/migration_guide.html * */ #else /* Load error strings into mem*/ ERR_load_BIO_strings(); ERR_load_crypto_strings(); #endif PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wdeprecated_declarations #ifndef OPENSSL_NO_ENGINE // Initialize OpenSSL engine library ENGINE_load_builtin_engines(); /* Register all of them for every algorithm they collectively implement */ ENGINE_register_all_complete(); // Iterate through all available engines ENGINE *osslEngine = ENGINE_get_first(); const char *engine_id = NULL; const char *engine_name = NULL; while (osslEngine) { // Print engine ID and name if the engine is loaded if (ENGINE_get_init_function(osslEngine)) { // Check if engine is initialized engine_id = ENGINE_get_id(osslEngine); engine_name = ENGINE_get_name(osslEngine); DBGPRINTF("osslGlblInit: Loaded Engine: ID = %s, Name = %s\n", engine_id, engine_name); } osslEngine = ENGINE_get_next(osslEngine); } // Free the engine reference when done ENGINE_free(osslEngine); #else DBGPRINTF("osslGlblInit: OpenSSL compiled without ENGINE support - ENGINE support disabled\n"); #endif /* OPENSSL_NO_ENGINE */ PRAGMA_DIAGNOSTIC_POP } /* globally de-initialize OpenSSL */ void osslGlblExit(void) { DBGPRINTF("openssl: entering osslGlblExit\n"); #ifndef ENABLE_WOLFSSL ocsp_cache_cleanup(); #endif #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); } /** * @brief Create and configure the OpenSSL SSL_CTX for a listener or outbound * connection. * * The context is populated from the effective netstream driver configuration, * including CA certificates, certificate chains, and private keys. Those TLS * objects may come from ordinary PEM files or, on supported OpenSSL 3 builds, * from strict pkcs11: URIs handled through the URI-aware lmnsd_ossl helpers. * * @param pThis OpenSSL netstream instance being initialized. * @param method SSL/TLS method used to create the context. * @return RS_RET_OK on success, or an rsyslog TLS-related error code. */ static rsRetVal net_ossl_osslCtxInit(net_ossl_t *pThis, const SSL_METHOD *method) { DEFiRet; int bHaveCA; int bHaveCRL; int bHaveCert; int bHaveKey; int bHaveExtraCAFiles; const char *caFile, *crlFile, *certFile, *keyFile; char *caFileSanitized, *crlFileSanitized, *certFileSanitized, *keyFileSanitized, *extraCaFilesSanitized; char *extraCaFiles, *extraCaFilesCopy, *extraCaFile; caFileSanitized = crlFileSanitized = certFileSanitized = keyFileSanitized = extraCaFilesSanitized = NULL; extraCaFilesCopy = NULL; /* Setup certificates */ caFile = (char *)((pThis->pszCAFile == NULL) ? glbl.GetDfltNetstrmDrvrCAF(runConf) : pThis->pszCAFile); if (caFile == NULL) { LogMsg(0, RS_RET_CA_CERT_MISSING, LOG_WARNING, "Warning: CA certificate is not set"); bHaveCA = 0; } else { dbgprintf("osslCtxInit: OSSL CA file: '%s'\n", net_ossl_sanitize_log_value(caFile, &caFileSanitized)); bHaveCA = 1; } crlFile = (char *)((pThis->pszCRLFile == NULL) ? glbl.GetDfltNetstrmDrvrCRLF(runConf) : pThis->pszCRLFile); if (crlFile == NULL) { bHaveCRL = 0; } else { dbgprintf("osslCtxInit: OSSL CRL file: '%s'\n", net_ossl_sanitize_log_value(crlFile, &crlFileSanitized)); bHaveCRL = 1; } certFile = (char *)((pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile); if (certFile == NULL) { LogMsg(0, RS_RET_CERT_MISSING, LOG_WARNING, "Warning: Certificate file is not set"); bHaveCert = 0; } else { dbgprintf("osslCtxInit: OSSL CERT file: '%s'\n", net_ossl_sanitize_log_value(certFile, &certFileSanitized)); bHaveCert = 1; } keyFile = (char *)((pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile); if (keyFile == NULL) { LogMsg(0, RS_RET_CERTKEY_MISSING, LOG_WARNING, "Warning: Key file is not set"); bHaveKey = 0; } else { dbgprintf("osslCtxInit: OSSL KEY file: '%s'\n", net_ossl_sanitize_log_value(keyFile, &keyFileSanitized)); bHaveKey = 1; } extraCaFiles = (char *)((pThis->pszExtraCAFiles == NULL) ? glbl.GetNetstrmDrvrCAExtraFiles(runConf) : pThis->pszExtraCAFiles); if (extraCaFiles == NULL) { bHaveExtraCAFiles = 0; } else { dbgprintf("osslCtxInit: OSSL EXTRA CA files: '%s'\n", net_ossl_sanitize_log_value(extraCaFiles, &extraCaFilesSanitized)); bHaveExtraCAFiles = 1; } /* Create main CTX Object based on method parameter */ if (pThis->ctx != NULL) { SSL_CTX_free(pThis->ctx); pThis->ctx = NULL; } pThis->ctx = SSL_CTX_new(method); if (bHaveExtraCAFiles == 1) { CHKmalloc(extraCaFilesCopy = strdup(extraCaFiles)); extraCaFiles = extraCaFilesCopy; while ((extraCaFile = strsep(&extraCaFiles, ","))) { iRet = net_ossl_load_ca_file(pThis->ctx, extraCaFile); if (iRet != RS_RET_OK) { char *extraCaFileSanitized = NULL; const char *logExtraCaFile = net_ossl_sanitize_log_value(extraCaFile, &extraCaFileSanitized); LogError(0, iRet, "Error: Extra Certificate file '%s' could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages", logExtraCaFile); net_ossl_free_sanitized_log_value(&extraCaFileSanitized); ABORT_FINALIZE(iRet); } } } if (bHaveCA == 1) { iRet = net_ossl_load_ca_file(pThis->ctx, caFile); if (iRet != RS_RET_OK) { char *caFileLoadSanitized = NULL; const char *logCaFile = net_ossl_sanitize_log_value(caFile, &caFileLoadSanitized); LogError(0, iRet, "Error: CA certificate '%s' could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages", logCaFile); net_ossl_free_sanitized_log_value(&caFileLoadSanitized); ABORT_FINALIZE(iRet); } } if (bHaveCRL == 1) { #if defined(ENABLE_WOLFSSL) /* wolfSSL_CTX_LoadCRLFile / LoadCRLBuffer drop every PEM block after * the first; wolfSSL_PEM_X509_INFO_read_bio iterates correctly. */ WOLFSSL_BIO *crlBio = NULL; WOLF_STACK_OF(WOLFSSL_X509_INFO) *crlStack = NULL; WOLFSSL_X509_STORE *crlStore = NULL; int loaded = 0; int crlIdx; crlBio = wolfSSL_BIO_new_file(crlFile, "rb"); if (crlBio == NULL) { LogError(errno, RS_RET_CRL_MISSING, "Error: CRL '%s' could not be opened", crlFile); ABORT_FINALIZE(RS_RET_CRL_MISSING); } crlStore = wolfSSL_CTX_get_cert_store(pThis->ctx); crlStack = wolfSSL_PEM_X509_INFO_read_bio(crlBio, NULL, NULL, NULL); if (crlStack != NULL) { if (crlStore != NULL) { for (crlIdx = 0; crlIdx < wolfSSL_sk_X509_INFO_num(crlStack); crlIdx++) { WOLFSSL_X509_INFO *info = wolfSSL_sk_X509_INFO_value(crlStack, crlIdx); if (info == NULL || info->crl == NULL) continue; if (wolfSSL_X509_STORE_add_crl(crlStore, info->crl) == WOLFSSL_SUCCESS) { loaded++; } else { LogMsg(0, RS_RET_CRL_INVALID, LOG_WARNING, "wolfSSL: CRL block #%d in '%s' failed to add to store, skipping", crlIdx + 1, crlFile); } } } wolfSSL_sk_pop_free(crlStack, NULL); } wolfSSL_BIO_free(crlBio); if (loaded == 0) { /* No PEM CRL blocks parsed - try the raw file as DER (single CRL) */ if (wolfSSL_CTX_LoadCRLFile(pThis->ctx, crlFile, WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { LogError(0, RS_RET_CRL_INVALID, "Error: CRL '%s' could not be loaded (tried PEM bundle and DER). " "Check at least: 1) file path is correct, 2) file exists, " "3) permissions are correct, 4) file content is correct.", crlFile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } loaded = 1; } CHKiRet(net_ossl_wolfssl_enable_leaf_crl(pThis->ctx, crlFile)); dbgprintf("osslCtxInit: loaded %d CRL(s) from '%s' into wolfSSL CertManager\n", loaded, crlFile); #elif OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) // Get X509_STORE reference X509_STORE *store = SSL_CTX_get_cert_store(pThis->ctx); if (!X509_STORE_load_file(store, crlFile)) { LogError(0, RS_RET_CRL_INVALID, "Error: CRL could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "X509_STORE_load_file"); ABORT_FINALIZE(RS_RET_CRL_INVALID); } X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK); #else #if OPENSSL_VERSION_NUMBER >= 0x10002000L // Get X509_STORE reference X509_STORE *store = SSL_CTX_get_cert_store(pThis->ctx); // Load the CRL PEM file FILE *fp = fopen(crlFile, "r"); if (fp == NULL) { LogError(0, RS_RET_CRL_MISSING, "Error: CRL could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "fopen"); ABORT_FINALIZE(RS_RET_CRL_MISSING); } X509_CRL *crl = PEM_read_X509_CRL(fp, NULL, NULL, NULL); fclose(fp); if (crl == NULL) { LogError(0, RS_RET_CRL_INVALID, "Error: Unable to read CRL." "OpenSSL error info may follow in next messages"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "PEM_read_X509_CRL"); ABORT_FINALIZE(RS_RET_CRL_INVALID); } // Add the CRL to the X509_STORE if (!X509_STORE_add_crl(store, crl)) { LogError(0, RS_RET_CRL_INVALID, "Error: Unable to add CRL to store." "OpenSSL error info may follow in next messages"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "X509_STORE_add_crl"); X509_CRL_free(crl); ABORT_FINALIZE(RS_RET_CRL_INVALID); } // Set the X509_STORE to the SSL_CTX // SSL_CTX_set_cert_store(pThis->ctx, store); // Enable CRL checking X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new(); X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); SSL_CTX_set1_param(pThis->ctx, param); X509_VERIFY_PARAM_free(param); #else LogError(0, RS_RET_SYS_ERR, "Warning: TLS library does not support X509_STORE_load_file" "(requires OpenSSL 3.x or higher). Cannot use Certificate revocation list (CRL) '%s'.", crlFile); #endif #endif } #ifdef ENABLE_WOLFSSL if (pThis->bTlsRevocationCheck) { WOLFSSL_CERT_MANAGER *cm = wolfSSL_CTX_GetCertManager(pThis->ctx); if (cm == NULL || wolfSSL_CertManagerEnableOCSP(cm, WOLFSSL_OCSP_CHECKALL) != WOLFSSL_SUCCESS) { LogError(0, RS_RET_SYS_ERR, "Error: unable to enable OCSP revocation checking in wolfSSL " "(was wolfSSL built with --enable-ocsp?)"); ABORT_FINALIZE(RS_RET_SYS_ERR); } dbgprintf("osslCtxInit: wolfSSL OCSP revocation checking enabled\n"); } #endif if (bHaveKey == 1) { iRet = net_ossl_load_key_file(pThis->ctx, keyFile); if (iRet != RS_RET_OK) { LogError(0, iRet, "Error: Key could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages"); ABORT_FINALIZE(iRet); } } if (bHaveCert == 1) { iRet = net_ossl_load_cert_file(pThis->ctx, certFile); if (iRet != RS_RET_OK) { LogError(0, iRet, "Error: Certificate file could not be accessed. " "Check at least: 1) file path is correct, 2) file exist, " "3) permissions are correct, 4) file content is correct. " "OpenSSL error info may follow in next messages"); ABORT_FINALIZE(iRet); } } if (bHaveCert == 1 && bHaveKey == 1 && SSL_CTX_check_private_key(pThis->ctx) != 1) { LogError(0, RS_RET_TLS_KEY_ERR, "Error: Certificate and key are not usable together. " "OpenSSL error info may follow in next messages"); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "osslCtxInit", "SSL_CTX_check_private_key"); ABORT_FINALIZE(RS_RET_TLS_KEY_ERR); } /* Set CTX Options */ SSL_CTX_set_options(pThis->ctx, SSL_OP_NO_SSLv2); /* Disable insecure SSLv2 Protocol */ SSL_CTX_set_options(pThis->ctx, SSL_OP_NO_SSLv3); /* Disable insecure SSLv3 Protocol */ SSL_CTX_sess_set_cache_size(pThis->ctx, 1024); /* TODO: make configurable? */ /* Set default VERIFY Options for OpenSSL CTX - and CALLBACK */ if (pThis->authMode == OSSL_AUTH_CERTANON) { dbgprintf("osslCtxInit: SSL_VERIFY_NONE\n"); net_ossl_set_ctx_verify_callback(pThis->ctx, SSL_VERIFY_NONE); } else { dbgprintf("osslCtxInit: SSL_VERIFY_PEER\n"); net_ossl_set_ctx_verify_callback(pThis->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); } SSL_CTX_set_timeout(pThis->ctx, 30); /* Default Session Timeout, TODO: Make configureable */ SSL_CTX_set_mode(pThis->ctx, SSL_MODE_AUTO_RETRY); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) /* Enable Support for automatic ephemeral/temporary DH parameter selection. */ SSL_CTX_set_dh_auto(pThis->ctx, 1); #endif #ifndef ENABLE_WOLFSSL #if OPENSSL_VERSION_NUMBER >= 0x10002000L #if OPENSSL_VERSION_NUMBER <= 0x101010FFL /* Enable Support for automatic EC temporary key parameter selection. */ SSL_CTX_set_ecdh_auto(pThis->ctx, 1); #else /* * SSL_CTX_set_ecdh_auto and SSL_CTX_set_tmp_ecdh are depreceated in higher * OpenSSL Versions, so we no more need them - see for more: * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_ecdh_auto.html */ #endif #else dbgprintf( "osslCtxInit: openssl to old, cannot use SSL_CTX_set_ecdh_auto." "Using SSL_CTX_set_tmp_ecdh with NID_X9_62_prime256v1/() instead.\n"); SSL_CTX_set_tmp_ecdh(pThis->ctx, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); #endif #endif finalize_it: net_ossl_free_sanitized_log_value(&caFileSanitized); net_ossl_free_sanitized_log_value(&crlFileSanitized); net_ossl_free_sanitized_log_value(&certFileSanitized); net_ossl_free_sanitized_log_value(&keyFileSanitized); net_ossl_free_sanitized_log_value(&extraCaFilesSanitized); free(extraCaFilesCopy); RETiRet; } /* Helper function to print usefull OpenSSL errors */ void net_ossl_lastOpenSSLErrorMsg( uchar *fromHost, int ret, SSL *ssl, int severity, const char *pszCallSource, const char *pszOsslApi) { unsigned long un_error = 0; int iSSLErr = 0; if (ssl == NULL) { /* Output Error Info*/ DBGPRINTF("lastOpenSSLErrorMsg: Error in '%s' with ret=%d\n", pszCallSource, ret); } else { /* if object is set, get error code */ iSSLErr = SSL_get_error(ssl, ret); /* Output Debug as well */ DBGPRINTF( "lastOpenSSLErrorMsg: %s Error in '%s': '%s(%d)' with ret=%d, errno=%d(%s), sslapi='%s'\n", (iSSLErr == SSL_ERROR_SSL ? "SSL_ERROR_SSL" : (iSSLErr == SSL_ERROR_SYSCALL ? "SSL_ERROR_SYSCALL" : "SSL_ERROR_UNKNOWN")), pszCallSource, ERR_error_string(iSSLErr, NULL), iSSLErr, ret, errno, strerror(errno), pszOsslApi); /* Output error message */ LogMsg(0, RS_RET_NO_ERRCODE, severity, "%s Error in '%s': '%s(%d)' with ret=%d, errno=%d(%s), sslapi='%s'\n", (iSSLErr == SSL_ERROR_SSL ? "SSL_ERROR_SSL" : (iSSLErr == SSL_ERROR_SYSCALL ? "SSL_ERROR_SYSCALL" : "SSL_ERROR_UNKNOWN")), pszCallSource, ERR_error_string(iSSLErr, NULL), iSSLErr, ret, errno, strerror(errno), pszOsslApi); } /* Loop through ERR_get_error */ while ((un_error = ERR_get_error()) > 0) { LogMsg(0, RS_RET_NO_ERRCODE, severity, "net_ossl:remote '%s' OpenSSL Error Stack: %s", fromHost, ERR_error_string(un_error, NULL)); } } #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) /* initialize tls config commands in openssl context */ rsRetVal net_ossl_apply_tlscgfcmd(net_ossl_t *pThis, uchar *tlscfgcmd) { DEFiRet; char *pCurrentPos; char *pNextPos; char *pszCmd; char *pszValue; int iConfErr; if (tlscfgcmd == NULL) { FINALIZE; } dbgprintf("net_ossl_apply_tlscgfcmd: Apply tlscfgcmd: '%s'\n", tlscfgcmd); /* Set working pointer */ pCurrentPos = (char *)tlscfgcmd; if (pCurrentPos != NULL && strlen(pCurrentPos) > 0) { // Create CTX Config Helper SSL_CONF_CTX *cctx; cctx = SSL_CONF_CTX_new(); if (pThis->sslState == osslServer) { SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); } else { SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); } SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); SSL_CONF_CTX_set_ssl_ctx(cctx, pThis->ctx); do { pNextPos = index(pCurrentPos, '='); if (pNextPos != NULL) { while (*pCurrentPos != '\0' && (*pCurrentPos == ' ' || *pCurrentPos == '\t')) pCurrentPos++; pszCmd = strndup(pCurrentPos, pNextPos - pCurrentPos); pCurrentPos = pNextPos + 1; pNextPos = index(pCurrentPos, '\n'); pNextPos = (pNextPos == NULL ? index(pCurrentPos, ';') : pNextPos); pszValue = (pNextPos == NULL ? strdup(pCurrentPos) : strndup(pCurrentPos, pNextPos - pCurrentPos)); pCurrentPos = (pNextPos == NULL ? NULL : pNextPos + 1); /* Add SSL Conf Command */ iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue); if (iConfErr > 0) { dbgprintf( "net_ossl_apply_tlscgfcmd: Successfully added Command " "'%s':'%s'\n", pszCmd, pszValue); } else { LogError(0, RS_RET_SYS_ERR, "Failed to add OpenSSL command %s:'%s' " "in net_ossl_apply_tlscgfcmd with error '%d'. " "The command or value may be unsupported by " "this native OpenSSL build.", pszCmd, pszValue, iConfErr); } free(pszCmd); free(pszValue); } else { /* Abort further parsing */ pCurrentPos = NULL; } } while (pCurrentPos != NULL); /* Finalize SSL Conf */ iConfErr = SSL_CONF_CTX_finish(cctx); if (!iConfErr) { LogError(0, RS_RET_SYS_ERR, "Error: setting openssl command parameters: %s. " "Requested settings may be unavailable on this native " "OpenSSL build. " "OpenSSL error info may follow in next messages", tlscfgcmd); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "net_ossl_apply_tlscgfcmd", "SSL_CONF_CTX_finish"); } SSL_CONF_CTX_free(cctx); } finalize_it: RETiRet; } #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L /* Convert a fingerprint to printable data. The conversion is carried out * according IETF I-D syslog-transport-tls-12. The fingerprint string is * returned in a new cstr object. It is the caller's responsibility to * destruct that object. * rgerhards, 2008-05-08 */ static rsRetVal net_ossl_genfingerprintstr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr, const char *prefix) { cstr_t *pStr = NULL; uchar buf[4]; size_t i; DEFiRet; CHKiRet(rsCStrConstruct(&pStr)); CHKiRet(rsCStrAppendStrWithLen(pStr, (uchar *)prefix, strlen(prefix))); for (i = 0; i < sizeFingerprint; ++i) { snprintf((char *)buf, sizeof(buf), ":%2.2X", pFingerprint[i]); CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3)); } cstrFinalize(pStr); *ppStr = pStr; finalize_it: if (iRet != RS_RET_OK) { if (pStr != NULL) rsCStrDestruct(&pStr); } RETiRet; } static const unsigned char *ossl_asn1_string_data(const ASN1_STRING *const str) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) return ASN1_STRING_get0_data(str); #else return ASN1_STRING_data((ASN1_STRING *)str); #endif } static rsRetVal ossl_asn1_string_to_cstr(ASN1_STRING *const str, uchar **const ppszOut) { uchar *pszOut = NULL; int len; const unsigned char *data = NULL; #ifndef ENABLE_WOLFSSL unsigned char *utf8 = NULL; #endif DEFiRet; *ppszOut = NULL; if (str == NULL) { FINALIZE; } #ifndef ENABLE_WOLFSSL len = ASN1_STRING_to_UTF8(&utf8, str); if (len < 0 || utf8 == NULL) { FINALIZE; } data = utf8; #else len = ASN1_STRING_length(str); data = ossl_asn1_string_data(str); #endif if (len < 0 || data == NULL) { FINALIZE; } if (memchr(data, '\0', (size_t)len) != NULL) { FINALIZE; } CHKmalloc(pszOut = malloc((size_t)len + 1)); memcpy(pszOut, data, (size_t)len); pszOut[len] = '\0'; *ppszOut = pszOut; pszOut = NULL; finalize_it: free(pszOut); #ifndef ENABLE_WOLFSSL if (utf8 != NULL) { OPENSSL_free(utf8); } #endif RETiRet; } static rsRetVal ossl_append_identity(cstr_t *const pStr, const char *const prefix, const uchar *const identity) { DEFiRet; CHKiRet(rsCStrAppendStrWithLen(pStr, (const uchar *)prefix, strlen(prefix))); CHKiRet(rsCStrAppendStrWithLen(pStr, identity, strlen((const char *)identity))); CHKiRet(rsCStrAppendStrWithLen(pStr, (const uchar *)"; ", 2)); finalize_it: RETiRet; } static rsRetVal net_ossl_matchpeeridentity(net_ossl_t *pThis, X509 *certpeer, const uchar *pszPeerID, int *pbFoundPositiveMatch, const sbool allowX509CheckHost) { permittedPeers_t *pPeer; #if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(ENABLE_WOLFSSL) int osslRet; unsigned int x509flags = 0; #endif char *x509name = NULL; DEFiRet; if (certpeer == NULL) { ABORT_FINALIZE(RS_RET_TLS_NO_CERT); } ISOBJ_TYPE_assert(pThis, net_ossl); assert(pszPeerID != NULL); assert(pbFoundPositiveMatch != NULL); if (pThis->pPermPeers) { /* do we have configured peer IDs? */ for (pPeer = pThis->pPermPeers; pPeer != NULL; pPeer = pPeer->pNext) { CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch)); if (*pbFoundPositiveMatch) break; #if OPENSSL_VERSION_NUMBER >= 0x10002000L || defined(ENABLE_WOLFSSL) /* if we did not succeed so far, try ossl X509_check_host * ( Includes check against SubjectAlternativeName ) * if prioritizeSAN set, only check against SAN */ if (!allowX509CheckHost || pPeer->etryType == PERM_PEER_TYPE_WILDCARD) { continue; } else if (pThis->bSANpriority == 1) { #if OPENSSL_VERSION_NUMBER >= 0x10100004L && !defined(LIBRESSL_VERSION_NUMBER) && \ defined(X509_CHECK_FLAG_NEVER_CHECK_SUBJECT) x509flags = X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; #else /* Security hard-stop: with older OpenSSL-compatible APIs (notably wolfSSL * compatibility mode), we cannot request SAN-only matching. Calling * X509_check_host() with default flags may fall back to CN, which would * violate PrioritizeSAN semantics and RFC 6125 behavior. */ dbgprintf("net_ossl_matchpeeridentity: PrioritizeSAN not supported by this OpenSSL-compatible API\n"); continue; #endif // OPENSSL_VERSION_NUMBER >= 0x10100004L } /* Obtain Namex509 name from subject */ if (x509name == NULL) { x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0); } osslRet = X509_check_host(certpeer, (const char *)pPeer->pszID, strlen((const char *)pPeer->pszID), x509flags, NULL); if (osslRet == 1) { /* Found Peer cert in allowed Peerslist */ dbgprintf("net_ossl_matchpeeridentity: Client ('%s') is allowed (X509_check_host)\n", x509name); *pbFoundPositiveMatch = 1; break; } else if (osslRet < 0) { net_ossl_lastOpenSSLErrorMsg(NULL, osslRet, NULL, LOG_ERR, "net_ossl_matchpeeridentity", "X509_check_host"); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } #endif } } else { LogMsg(0, RS_RET_TLS_NO_CERT, LOG_WARNING, "net_ossl_chkonepeername: Peername check could not be done: " "no peernames configured."); } finalize_it: if (x509name != NULL) { OPENSSL_free(x509name); } RETiRet; } static rsRetVal net_ossl_chkonepeername(net_ossl_t *pThis, X509 *certpeer, const uchar *pszPeerID, int *pbFoundPositiveMatch) { DEFiRet; CHKiRet(net_ossl_matchpeeridentity(pThis, certpeer, pszPeerID, pbFoundPositiveMatch, 1)); finalize_it: RETiRet; } static rsRetVal net_ossl_match_sans( net_ossl_t *pThis, X509 *certpeer, cstr_t *pStr, int *bHaveSAN, int *bFoundPositiveMatch) { DEFiRet; GENERAL_NAMES *names = NULL; GENERAL_NAME *name; ASN1_STRING *dns; ASN1_OCTET_STRING *ip; uchar *dnsName = NULL; const unsigned char *ipData; const char *addr; char ipAddress[INET6_ADDRSTRLEN]; int count; int i; if (*bFoundPositiveMatch) { FINALIZE; } names = X509_get_ext_d2i(certpeer, NID_subject_alt_name, NULL, NULL); if (names == NULL) { FINALIZE; } count = sk_GENERAL_NAME_num(names); /* PrioritizeSAN suppresses CN fallback when any SAN exists, even if it is * not a DNS/IP identity usable by x509/name matching. */ if (count > 0) { *bHaveSAN = 1; } for (i = 0; i < count && !*bFoundPositiveMatch; ++i) { name = sk_GENERAL_NAME_value(names, i); if (name == NULL) { continue; } if (name->type == GEN_DNS) { dns = name->d.dNSName; CHKiRet(ossl_asn1_string_to_cstr(dns, &dnsName)); if (dnsName == NULL) { continue; } dbgprintf("net_ossl_match_sans: subject alt dnsName: '%s'\n", dnsName); CHKiRet(ossl_append_identity(pStr, "DNSname: ", dnsName)); CHKiRet(net_ossl_matchpeeridentity(pThis, certpeer, dnsName, bFoundPositiveMatch, 0)); free(dnsName); dnsName = NULL; } else if (name->type == GEN_IPADD) { ip = name->d.iPAddress; ipData = ossl_asn1_string_data(ip); if (ipData == NULL) { continue; } if (ASN1_STRING_length(ip) == 4) { addr = inet_ntop(AF_INET, ipData, ipAddress, sizeof(ipAddress)); } else if (ASN1_STRING_length(ip) == 16) { addr = inet_ntop(AF_INET6, ipData, ipAddress, sizeof(ipAddress)); } else { continue; } if (addr == NULL) { continue; } dbgprintf("net_ossl_match_sans: subject alt ipAddr: '%s'\n", ipAddress); CHKiRet(ossl_append_identity(pStr, "IPaddress: ", (const uchar *)ipAddress)); CHKiRet(net_ossl_matchpeeridentity(pThis, certpeer, (const uchar *)ipAddress, bFoundPositiveMatch, 0)); } } finalize_it: free(dnsName); if (names != NULL) { GENERAL_NAMES_free(names); } RETiRet; } static rsRetVal net_ossl_match_cn(net_ossl_t *pThis, X509 *certpeer, cstr_t *pStr, int *bFoundPositiveMatch) { X509_NAME *subject; X509_NAME_ENTRY *entry; ASN1_STRING *cn; uchar *cnName = NULL; int idx; DEFiRet; subject = RSYSLOG_X509_NAME_oneline(certpeer); if (subject == NULL) { FINALIZE; } idx = X509_NAME_get_index_by_NID(subject, NID_commonName, -1); if (idx < 0) { FINALIZE; } entry = X509_NAME_get_entry(subject, idx); if (entry == NULL) { FINALIZE; } cn = X509_NAME_ENTRY_get_data(entry); CHKiRet(ossl_asn1_string_to_cstr(cn, &cnName)); if (cnName == NULL) { FINALIZE; } dbgprintf("net_ossl_match_cn: now checking auth for CN '%s'\n", cnName); CHKiRet(ossl_append_identity(pStr, "CN: ", cnName)); CHKiRet(net_ossl_matchpeeridentity(pThis, certpeer, cnName, bFoundPositiveMatch, 0)); finalize_it: free(cnName); RETiRet; } /* Check the peer's ID in fingerprint auth mode. * rgerhards, 2008-05-22 */ rsRetVal net_ossl_peerfingerprint(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP) { DEFiRet; unsigned int n; uchar fingerprint[20 /*EVP_MAX_MD_SIZE**/]; uchar fingerprintSha256[32 /*EVP_MAX_MD_SIZE**/]; size_t size; size_t sizeSha256; cstr_t *pstrFingerprint = NULL; cstr_t *pstrFingerprintSha256 = NULL; int bFoundPositiveMatch; permittedPeers_t *pPeer; const EVP_MD *fdig = EVP_sha1(); const EVP_MD *fdigSha256 = EVP_sha256(); ISOBJ_TYPE_assert(pThis, net_ossl); if (certpeer == NULL) { ABORT_FINALIZE(RS_RET_TLS_NO_CERT); } /* obtain the SHA1 fingerprint */ size = sizeof(fingerprint); if (!X509_digest(certpeer, fdig, fingerprint, &n)) { dbgprintf("net_ossl_peerfingerprint: error X509cert is not valid!\n"); ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } sizeSha256 = sizeof(fingerprintSha256); if (!X509_digest(certpeer, fdigSha256, fingerprintSha256, &n)) { dbgprintf("net_ossl_peerfingerprint: error X509cert is not valid!\n"); ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } CHKiRet(net_ossl_genfingerprintstr(fingerprint, size, &pstrFingerprint, "SHA1")); dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA1 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprint)); CHKiRet(net_ossl_genfingerprintstr(fingerprintSha256, sizeSha256, &pstrFingerprintSha256, "SHA256")); dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA256 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprintSha256)); /* now search through the permitted peers to see if we can find a permitted one */ bFoundPositiveMatch = 0; pPeer = pThis->pPermPeers; while (pPeer != NULL && !bFoundPositiveMatch) { if (!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA1 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else if (!rsCStrSzStrCmp(pstrFingerprintSha256, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("net_ossl_peerfingerprint: peer's certificate SHA256 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else { dbgprintf("net_ossl_peerfingerprint: NOMATCH peer certificate: %s\n", pPeer->pszID); pPeer = pPeer->pNext; } } if (!bFoundPositiveMatch) { dbgprintf("net_ossl_peerfingerprint: invalid peer fingerprint, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { errno = 0; LogMsg(0, RS_RET_INVALID_FINGERPRINT, LOG_WARNING, "net_ossl:TLS session terminated with remote syslog server '%s': " "Fingerprint check failed, not permitted to talk to %s", fromHostIP, cstrGetSzStrNoNULL(pstrFingerprint)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } finalize_it: if (pstrFingerprint != NULL) cstrDestruct(&pstrFingerprint); if (pstrFingerprintSha256 != NULL) cstrDestruct(&pstrFingerprintSha256); RETiRet; } /* Check the peer's ID in name auth mode. */ rsRetVal net_ossl_chkpeername(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP) { DEFiRet; int bFoundPositiveMatch; int bHaveSAN; cstr_t *pStr = NULL; char *x509name = NULL; ISOBJ_TYPE_assert(pThis, net_ossl); bFoundPositiveMatch = 0; bHaveSAN = 0; CHKiRet(rsCStrConstruct(&pStr)); /* Obtain Namex509 name from subject */ x509name = X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(certpeer), NULL, 0); if (x509name == NULL) { LogMsg(0, RS_RET_CERT_INVALID_DN, LOG_WARNING, "net_ossl_chkpeername: could not obtain X.509 subject name"); ABORT_FINALIZE(RS_RET_CERT_INVALID_DN); } dbgprintf("net_ossl_chkpeername: checking - peername '%s' on server '%s'\n", x509name, fromHostIP); CHKiRet(ossl_append_identity(pStr, "name: ", (const uchar *)x509name)); CHKiRet(net_ossl_chkonepeername(pThis, certpeer, (uchar *)x509name, &bFoundPositiveMatch)); CHKiRet(net_ossl_match_sans(pThis, certpeer, pStr, &bHaveSAN, &bFoundPositiveMatch)); if (!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) { CHKiRet(net_ossl_match_cn(pThis, certpeer, pStr, &bFoundPositiveMatch)); } if (!bFoundPositiveMatch) { dbgprintf("net_ossl_chkpeername: invalid peername, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { cstrFinalize(pStr); errno = 0; LogMsg(0, RS_RET_INVALID_FINGERPRINT, LOG_WARNING, "net_ossl:TLS session terminated with remote syslog server: " "peer name not authorized, not permitted to talk to %s", cstrGetSzStrNoNULL(pStr)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } else { dbgprintf("net_ossl_chkpeername: permitted to talk!\n"); } finalize_it: if (x509name != NULL) { OPENSSL_free(x509name); } if (pStr != NULL) rsCStrDestruct(&pStr); RETiRet; } /* check the ID of the remote peer - used for both fingerprint and * name authentication. */ X509 *net_ossl_getpeercert(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP) { X509 *certpeer; ISOBJ_TYPE_assert(pThis, net_ossl); /* Get peer certificate from SSL */ certpeer = SSL_get_peer_certificate(ssl); if (certpeer == NULL) { if (pThis->bReportAuthErr == 1 && 1) { errno = 0; pThis->bReportAuthErr = 0; LogMsg(0, RS_RET_TLS_NO_CERT, LOG_WARNING, "net_ossl:TLS session terminated with remote syslog server '%s': " "Peer check failed, peer did not provide a certificate.", fromHostIP); } } return certpeer; } /* Verify the validity of the remote peer's certificate. */ rsRetVal net_ossl_chkpeercertvalidity(net_ossl_t __attribute__((unused)) * pThis, SSL *ssl, uchar *fromHostIP) { DEFiRet; int iVerErr = X509_V_OK; ISOBJ_TYPE_assert(pThis, net_ossl); PermitExpiredCerts *pPermitExpiredCerts = (PermitExpiredCerts *)SSL_get_ex_data(ssl, 1); #ifdef ENABLE_WOLFSSL iVerErr = wolfSSL_get_verify_result(ssl); #else iVerErr = SSL_get_verify_result(ssl); #endif if (iVerErr != X509_V_OK) { if (iVerErr == X509_V_ERR_CERT_HAS_EXPIRED) { if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_DENY) { LogMsg(0, RS_RET_CERT_EXPIRED, LOG_INFO, "net_ossl:TLS session terminated with remote syslog server '%s': " "not permitted to talk to peer, certificate invalid: " "Certificate expired: %s", fromHostIP, X509_verify_cert_error_string(iVerErr)); ABORT_FINALIZE(RS_RET_CERT_EXPIRED); } else if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_WARN) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "net_ossl:CertValidity check - warning talking to peer '%s': " "certificate expired: %s", fromHostIP, X509_verify_cert_error_string(iVerErr)); } else { dbgprintf( "net_ossl_chkpeercertvalidity: talking to peer '%s': " "certificate expired: %s\n", fromHostIP, X509_verify_cert_error_string(iVerErr)); } /* Else do nothing */ } else if (iVerErr == X509_V_ERR_CERT_REVOKED) { LogMsg(0, RS_RET_CERT_REVOKED, LOG_INFO, "net_ossl:TLS session terminated with remote syslog server '%s': " "not permitted to talk to peer, certificate invalid: " "certificate revoked '%s'", fromHostIP, X509_verify_cert_error_string(iVerErr)); ABORT_FINALIZE(RS_RET_CERT_EXPIRED); } else { LogMsg(0, RS_RET_CERT_INVALID, LOG_INFO, "net_ossl:TLS session terminated with remote syslog server '%s': " "not permitted to talk to peer, certificate validation failed: %s", fromHostIP, X509_verify_cert_error_string(iVerErr)); ABORT_FINALIZE(RS_RET_CERT_INVALID); } } else { dbgprintf("net_ossl_chkpeercertvalidity: client certificate validation success: %s\n", X509_verify_cert_error_string(iVerErr)); } finalize_it: RETiRet; } /*--------------------------------------OCSP Support ------------------------------------------*/ #ifndef ENABLE_WOLFSSL /* OCSP is not available in WolfSSL builds */ /* OCSP Response Cache * * Concurrency & Locking: * - Cache is shared across all workers (global state) * - Protected by ocsp_cache_mutex (pthread_mutex_t) * - All cache operations (lookup/store/cleanup) acquire mutex before access * - Cache entries store OCSP responses with expiration times * * Non-blocking I/O: * - Socket operations use non-blocking mode during connect with timeout * - Once connected, sockets use SO_RCVTIMEO/SO_SNDTIMEO for bounded I/O * - Maximum timeout per OCSP responder: OCSP_TIMEOUT (5 seconds) * * Cache Strategy: * - Key: certificate serial number + issuer name hash (SHA-256) * - TTL: Based on OCSP response nextUpdate field, or OCSP_CACHE_DEFAULT_TTL (1 hour) * - Eviction: Prefers expired entries, then FIFO from tail when cache reaches MAX_ENTRIES * - Expired entries removed during lookup to maintain cache efficiency * - Thread-safe: All cache operations protected by mutex */ typedef struct ocsp_cache_entry_s { char *cache_key; /* cert serial + issuer hash */ int cert_status; /* V_OCSP_CERTSTATUS_* */ time_t expires_at; /* when this entry expires */ struct ocsp_cache_entry_s *next; } ocsp_cache_entry_t; static ocsp_cache_entry_t *ocsp_cache_head = NULL; static int ocsp_cache_count = 0; static pthread_mutex_t ocsp_cache_mutex = PTHREAD_MUTEX_INITIALIZER; static char *ocsp_make_cache_key(X509 *cert, X509 *issuer) { DEFiRet; ASN1_INTEGER *serial = X509_get_serialNumber(cert); unsigned char md[EVP_MAX_MD_SIZE]; unsigned int md_len = 0; unsigned char key_md[EVP_MAX_MD_SIZE]; unsigned int key_md_len = 0; char *key = NULL; int key_len; BIGNUM *bn = NULL; char *serial_hex = NULL; if (!serial || !issuer) ABORT_FINALIZE(RS_RET_ERR); /* Hash issuer name for compact key */ X509_NAME *issuer_name = X509_get_subject_name(issuer); if (!X509_NAME_digest(issuer_name, EVP_sha256(), md, &md_len)) { ABORT_FINALIZE(RS_RET_ERR); } /* Hash issuer public key to avoid collisions across key rollovers */ if (!X509_pubkey_digest(issuer, EVP_sha256(), key_md, &key_md_len)) { ABORT_FINALIZE(RS_RET_ERR); } /* Format: serial-number:issuer-name-hash:issuer-key-hash */ bn = ASN1_INTEGER_to_BN(serial, NULL); if (!bn) ABORT_FINALIZE(RS_RET_ERR); serial_hex = BN_bn2hex(bn); if (!serial_hex) ABORT_FINALIZE(RS_RET_ERR); key_len = strlen(serial_hex) + (md_len * 2) + (key_md_len * 2) + 3; CHKmalloc(key = malloc(key_len)); char *p = key; int written = snprintf(p, key_len, "%s:", serial_hex); if (written < 0 || written >= key_len) { ABORT_FINALIZE(RS_RET_ERR); } p += written; size_t remaining = (size_t)key_len - (size_t)written; for (unsigned int i = 0; i < md_len; i++) { if (remaining < 3) { ABORT_FINALIZE(RS_RET_ERR); } written = snprintf(p, remaining, "%02x", md[i]); if (written != 2) { ABORT_FINALIZE(RS_RET_ERR); } p += written; remaining -= (size_t)written; } if (remaining < 2) { ABORT_FINALIZE(RS_RET_ERR); } *p++ = ':'; *p = '\0'; remaining--; for (unsigned int i = 0; i < key_md_len; i++) { if (remaining < 3) { ABORT_FINALIZE(RS_RET_ERR); } written = snprintf(p, remaining, "%02x", key_md[i]); if (written != 2) { ABORT_FINALIZE(RS_RET_ERR); } p += written; remaining -= (size_t)written; } finalize_it: if (iRet != RS_RET_OK) { free(key); key = NULL; } if (bn) BN_free(bn); if (serial_hex) OPENSSL_free(serial_hex); return key; } static int ocsp_cache_lookup(const char *cache_key, int *cert_status) { int found = 0; time_t now = time(NULL); pthread_mutex_lock(&ocsp_cache_mutex); ocsp_cache_entry_t **pp = &ocsp_cache_head; while (*pp) { ocsp_cache_entry_t *entry = *pp; if (strcmp(entry->cache_key, cache_key) == 0) { if (entry->expires_at > now) { *cert_status = entry->cert_status; found = 1; dbgprintf("OCSP: Cache hit for key %s, status=%d\n", cache_key, *cert_status); } else { /* Remove expired entry */ dbgprintf("OCSP: Removing expired cache entry for key %s\n", cache_key); *pp = entry->next; free(entry->cache_key); free(entry); ocsp_cache_count--; } break; } pp = &(*pp)->next; } pthread_mutex_unlock(&ocsp_cache_mutex); return found; } static void ocsp_cache_store(const char *cache_key, int cert_status, time_t ttl) { DEFiRet; pthread_mutex_lock(&ocsp_cache_mutex); /* Check if already exists and update */ ocsp_cache_entry_t *entry = ocsp_cache_head; while (entry) { if (strcmp(entry->cache_key, cache_key) == 0) { entry->cert_status = cert_status; entry->expires_at = time(NULL) + ttl; dbgprintf("OCSP: Cache updated for key %s\n", cache_key); pthread_mutex_unlock(&ocsp_cache_mutex); return; } entry = entry->next; } /* Try to evict expired entries first before removing valid ones */ if (ocsp_cache_count >= OCSP_CACHE_MAX_ENTRIES) { time_t now = time(NULL); ocsp_cache_entry_t **pp = &ocsp_cache_head; ocsp_cache_entry_t *expired_entry = NULL; /* Find first expired entry */ while (*pp) { if ((*pp)->expires_at <= now) { expired_entry = *pp; *pp = expired_entry->next; free(expired_entry->cache_key); free(expired_entry); ocsp_cache_count--; break; } pp = &(*pp)->next; } /* If no expired entries found, evict from tail (true FIFO) */ if (!expired_entry && ocsp_cache_head) { pp = &ocsp_cache_head; while ((*pp)->next) { pp = &(*pp)->next; } ocsp_cache_entry_t *to_remove = *pp; *pp = NULL; free(to_remove->cache_key); free(to_remove); ocsp_cache_count--; } } /* Add new entry */ ocsp_cache_entry_t *new_entry = NULL; CHKmalloc(new_entry = malloc(sizeof(ocsp_cache_entry_t))); CHKmalloc(new_entry->cache_key = strdup(cache_key)); new_entry->cert_status = cert_status; new_entry->expires_at = time(NULL) + ttl; new_entry->next = ocsp_cache_head; ocsp_cache_head = new_entry; ocsp_cache_count++; dbgprintf("OCSP: Cache stored for key %s, count=%d\n", cache_key, ocsp_cache_count); finalize_it: if (iRet == RS_RET_OUT_OF_MEMORY) { LogError(0, RS_RET_OUT_OF_MEMORY, "OCSP: Failed to allocate cache entry\n"); } if (iRet != RS_RET_OK) { if (new_entry) { free(new_entry->cache_key); free(new_entry); } } pthread_mutex_unlock(&ocsp_cache_mutex); } void ocsp_cache_cleanup(void) { pthread_mutex_lock(&ocsp_cache_mutex); ocsp_cache_entry_t *entry = ocsp_cache_head; while (entry) { ocsp_cache_entry_t *next = entry->next; free(entry->cache_key); free(entry); entry = next; } ocsp_cache_head = NULL; ocsp_cache_count = 0; pthread_mutex_unlock(&ocsp_cache_mutex); } /* * CRL is not implemented! * * This is just a sanity-check stub, to fail on CRL-only certificates. * CRL-only certificate means: Certificate CRL DP, but not OCSP/AuthorityInfoAccess information. * * Returns: * 0: if CRL check failed (Error, or Revoked when is_revoked is set) * 1: if the certificate status is "GOOD" * 2: if the certificate holds no CRL URL */ static int crl_check(X509 *current_cert, int *is_revoked) { int ret = 0; STACK_OF(DIST_POINT) * crldp; STACK_OF(OPENSSL_STRING) * ocsp_uris; /* Reset revoked status. Needs to be set in case CRL gets implemented. */ if (is_revoked) *is_revoked = 0; crldp = X509_get_ext_d2i(current_cert, NID_crl_distribution_points, NULL, NULL); ocsp_uris = X509_get1_ocsp(current_cert); if (crldp && ocsp_uris == NULL) { LogError(0, RS_RET_NO_ERRCODE, "CRL support is not implemented. " "CRL-only certificates can't be validated!\n"); ret = 0; /* abort verification. CRL-only not supported. */ } else if (!crldp) { ret = 2; } if (ocsp_uris) X509_email_free(ocsp_uris); if (crldp) sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); return ret; } /* * Find the issuer certificate, which is mandatory to generate * a OCSP request. * * Query first locally configured and trusted certificates (e.g CAs). * * Last resort: Use the certificate chain of the peer, to get hold of * untrusted certificates (e.g. intermediate certificates). * * The resulting issuer certificate might be an untrusted certificate, * which should be used to generate OCSP requests. */ static X509 *ocsp_find_issuer(X509 *target_cert, const char *cert_name, SSL_CTX *ctx, STACK_OF(X509) * untrusted_peer_certs) { X509 *issuer = NULL; X509_STORE *store = SSL_CTX_get_cert_store(ctx); STACK_OF(X509_OBJECT) * objs; /* find issuer among local trusted issuers */ if (store != NULL) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L objs = X509_STORE_get0_objects(store); for (int i = 0; i < sk_X509_OBJECT_num(objs); i++) { X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i)); if (cert && X509_check_issued(cert, target_cert) == X509_V_OK) { issuer = cert; break; } } #else /* OpenSSL 1.0.2 compatibility: direct access to store fields */ objs = store->objs; for (int i = 0; i < sk_X509_OBJECT_num(objs); i++) { X509_OBJECT *x509obj = sk_X509_OBJECT_value(objs, i); X509 *cert = x509obj->type == X509_LU_X509 ? x509obj->data.x509 : NULL; if (cert && X509_check_issued(cert, target_cert) == X509_V_OK) { issuer = cert; break; } } #endif } if (!issuer) { /* Look for intermediate certificates in the remote cert-chain */ for (int i = 0; i < sk_X509_num(untrusted_peer_certs); i++) { X509 *cert = sk_X509_value(untrusted_peer_certs, i); if (X509_check_issued(cert, target_cert) == X509_V_OK) { issuer = cert; break; } } } /* No issuer, no revocation check possible */ if (!issuer) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Could not find any issuer for: \"%s\"\n", cert_name); } return issuer; } static const char *ocsp_get_response_status_err(int c) { switch (c) { case OCSP_RESPONSE_STATUS_SUCCESSFUL: return "Successful"; case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST: return "Malformed request"; case OCSP_RESPONSE_STATUS_INTERNALERROR: return "Internal error in OCSP responder"; case OCSP_RESPONSE_STATUS_TRYLATER: return "Try again later"; case OCSP_RESPONSE_STATUS_SIGREQUIRED: return "Must sign the request"; case OCSP_RESPONSE_STATUS_UNAUTHORIZED: return "Request unauthorized"; default: return "Unknown Response Status"; } } /* * Returns 1 if the cert status is "GOOD" * Stores result in cache if successful */ static int ocsp_check_validate_response_and_cert(OCSP_RESPONSE *rsp, OCSP_REQUEST *req, STACK_OF(X509) * untrusted_peer_certs, OCSP_CERTID *id, SSL_CTX *ctx, const char *cert_name, X509 *cert, X509 *issuer, int *is_revoked) { int s, ret = 0; long leeway_sec = 300; /* 5 Minutes */ long maxage = -1; /* No maximum age for ThisUpdate response */ int status, reason; ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; OCSP_BASICRESP *bs = NULL; X509_STORE *store = SSL_CTX_get_cert_store(ctx); bs = OCSP_response_get1_basic(rsp); if (bs == NULL) { LogError(0, RS_RET_NO_ERRCODE, "Failed to decode the basic OCSP response.\n"); goto err; } s = OCSP_check_nonce(req, bs); if (s == -1) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "Warning: no Nonce in OCSP response from peer. " "(No replay attack protection available)\n"); } else if (s == 0) { LogError(0, RS_RET_NO_ERRCODE, "Nonce mismatch in OCSP response.\n"); goto err; } s = OCSP_basic_verify(bs, untrusted_peer_certs, store, 0); if (s <= 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP response verification failed.\n"); goto err; } if (!OCSP_resp_find_status(bs, id, &status, &reason, &rev, &thisupd, &nextupd)) { LogError(0, RS_RET_NO_ERRCODE, "Failed to get OCSP response status for: %s\n", cert_name); goto err; } s = OCSP_check_validity(thisupd, nextupd, leeway_sec, maxage); if (s == 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP response is not valid (either expired or not yet valid).\n"); goto err; } /* Check certificate status */ switch (status) { case V_OCSP_CERTSTATUS_GOOD: dbgprintf("OCSP: Certificate status is GOOD for: %s\n", cert_name); ret = 1; break; case V_OCSP_CERTSTATUS_REVOKED: LogMsg(0, RS_RET_CERT_REVOKED, LOG_ERR, "OCSP: Certificate status is REVOKED for: %s (reason: %s)\n", cert_name, OCSP_crl_reason_str(reason)); if (is_revoked) *is_revoked = 1; ret = 0; break; case V_OCSP_CERTSTATUS_UNKNOWN: LogError(0, RS_RET_NO_ERRCODE, "OCSP: Certificate status is UNKNOWN for: %s\n", cert_name); ret = 0; break; default: LogError(0, RS_RET_NO_ERRCODE, "OCSP: Unknown certificate status for: %s\n", cert_name); ret = 0; break; } /* Store result in cache */ char *cache_key = ocsp_make_cache_key(cert, issuer); if (cache_key) { int should_cache = 1; time_t cache_ttl = OCSP_CACHE_DEFAULT_TTL; /* Use nextUpdate if available for more accurate cache expiry */ if (nextupd) { /* Use ASN1_TIME_diff() which properly handles UTC times without timezone issues */ int pday, psec; if (ASN1_TIME_diff(&pday, &psec, NULL, nextupd) == 1) { /* nextupd is in the future */ time_t seconds_until_expiry = (pday * 86400) + psec; if (seconds_until_expiry > 0) { cache_ttl = seconds_until_expiry; } else { /* avoid caching stale responses accepted only via OCSP leeway */ should_cache = 0; } } else { dbgprintf("OCSP: ASN1_TIME_diff() failed, using default TTL\n"); } } if (should_cache) { ocsp_cache_store(cache_key, status, cache_ttl); } else { dbgprintf("OCSP: nextUpdate is not in the future, skipping cache store\n"); } free(cache_key); } err: if (bs) OCSP_BASICRESP_free(bs); return ret; } static BIO *ocsp_connect(const char *host, const char *port, const char *device) { BIO *bio = NULL; int sock = -1; struct addrinfo hints, *res = NULL, *rp; int s; int flags; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; s = ocsp_getaddrinfo(host, port, &hints, &res); if (s != 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: getaddrinfo failed for %s:%s: %s\n", host, port, gai_strerror(s)); goto err; } for (rp = res; rp != NULL; rp = rp->ai_next) { sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) continue; if (device && *device) { #ifdef SO_BINDTODEVICE if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)) < 0) { LogError(errno, RS_RET_NO_ERRCODE, "OCSP: Failed to bind socket to device %s\n", device); close(sock); sock = -1; continue; } #else LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "OCSP: SO_BINDTODEVICE not supported, ignoring device parameter\n"); #endif } /* Set socket to non-blocking for timeout support */ flags = fcntl(sock, F_GETFL, 0); if (flags != -1) { fcntl(sock, F_SETFL, flags | O_NONBLOCK); } if (connect(sock, rp->ai_addr, rp->ai_addrlen) == 0) { break; /* Success */ } if (errno == EINPROGRESS) { fd_set wfds; struct timeval tv; FD_ZERO(&wfds); FD_SET(sock, &wfds); tv.tv_sec = OCSP_TIMEOUT; tv.tv_usec = 0; s = select(sock + 1, NULL, &wfds, NULL, &tv); if (s > 0) { int error = 0; socklen_t len = sizeof(error); if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) == 0 && error == 0) { break; /* Success */ } } } close(sock); sock = -1; } if (sock == -1 || rp == NULL) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to connect to %s:%s\n", host, port); goto err; } /* Set socket back to blocking mode with read/write timeout */ flags = fcntl(sock, F_GETFL, 0); if (flags != -1) { fcntl(sock, F_SETFL, flags & ~O_NONBLOCK); } /* Set socket read and write timeouts to prevent indefinite blocking during OCSP I/O */ struct timeval timeout; timeout.tv_sec = OCSP_TIMEOUT; timeout.tv_usec = 0; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "OCSP: Failed to set socket read timeout (errno %d), continuing without timeout\n", errno); } if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "OCSP: Failed to set socket write timeout (errno %d), continuing without timeout\n", errno); } bio = BIO_new_socket(sock, BIO_CLOSE); if (!bio) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to create BIO\n"); close(sock); goto err; } err: if (res) freeaddrinfo(res); return bio; } static OCSP_RESPONSE *ocsp_send_and_receive(BIO *bio, const char *host, const char *path, OCSP_REQUEST *req) { OCSP_RESPONSE *rsp = NULL; char *req_data = NULL; unsigned char *rsp_data = NULL; int req_len; int rv; /* Encode OCSP request */ req_len = i2d_OCSP_REQUEST(req, (unsigned char **)&req_data); if (req_len <= 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to encode OCSP request\n"); goto err; } /* Send HTTP POST request */ rv = BIO_printf(bio, "POST %s HTTP/1.0\r\n" "Host: %s\r\n" "Content-Type: application/ocsp-request\r\n" "Content-Length: %d\r\n" "\r\n", path, host, req_len); if (rv <= 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to send HTTP header\n"); goto err; } /* Send request data */ if (BIO_write(bio, req_data, req_len) != req_len) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to send OCSP request data\n"); goto err; } if (BIO_flush(bio) != 1) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to flush BIO\n"); goto err; } /* Read HTTP response - skip headers */ char buf[1024]; int in_headers = 1; long content_length = -1; const long MAX_OCSP_RESPONSE_SIZE = 1024 * 1024; /* 1MB limit */ size_t rsp_len = 0; const size_t rsp_limit = (size_t)MAX_OCSP_RESPONSE_SIZE; const size_t read_limit = rsp_limit + 1; while (in_headers) { rv = BIO_gets(bio, buf, sizeof(buf)); if (rv <= 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to read HTTP response headers\n"); goto err; } /* Parse Content-Length header */ if (strncasecmp(buf, "Content-Length:", 15) == 0) { char *endptr; errno = 0; content_length = strtol(buf + 15, &endptr, 10); if (errno != 0 || endptr == buf + 15 || content_length < 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Invalid Content-Length header\n"); goto err; } if (content_length > MAX_OCSP_RESPONSE_SIZE) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Response Content-Length (%ld) exceeds maximum allowed size (%ld)\n", content_length, MAX_OCSP_RESPONSE_SIZE); goto err; } } /* Empty line marks end of headers */ if (strcmp(buf, "\r\n") == 0 || strcmp(buf, "\n") == 0) { in_headers = 0; } } rsp_data = malloc(read_limit); if (rsp_data == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "OCSP: Failed to allocate response buffer\n"); goto err; } while (rsp_len < read_limit) { size_t wanted = read_limit - rsp_len; if (content_length >= 0) { size_t remaining = (size_t)content_length - rsp_len; if (remaining == 0) { break; } if (wanted > remaining) { wanted = remaining; } } rv = BIO_read(bio, rsp_data + rsp_len, (int)wanted); if (rv < 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to read HTTP response body\n"); goto err; } if (rv == 0) { break; } rsp_len += (size_t)rv; } if (rsp_len > rsp_limit) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Response exceeds maximum allowed size (%ld)\n", MAX_OCSP_RESPONSE_SIZE); goto err; } if (content_length > 0 && rsp_len != (size_t)content_length) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Incomplete response body\n"); goto err; } if (rsp_len == 0) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Empty response body\n"); goto err; } const unsigned char *p = rsp_data; rsp = d2i_OCSP_RESPONSE(NULL, &p, (long)rsp_len); if (!rsp) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to parse OCSP response\n"); goto err; } err: if (req_data) OPENSSL_free(req_data); free(rsp_data); return rsp; } static int ocsp_is_supported_protocol(const char *url) { return (strncmp(url, "http://", 7) == 0); } static int ocsp_request_per_responder(const char *url, X509 *cert, X509 *issuer, STACK_OF(X509) * untrusted_peer_certs, SSL_CTX *ctx, const char *device, int *is_revoked) { int ret = 0; char *host = NULL, *port = NULL, *path = NULL; int use_ssl = 0; BIO *bio = NULL; OCSP_REQUEST *req = NULL; OCSP_RESPONSE *rsp = NULL; OCSP_CERTID *id = NULL; char cert_name[256]; X509_NAME_oneline(X509_get_subject_name(cert), cert_name, sizeof(cert_name)); /* Parse URL */ if (!OCSP_parse_url((char *)url, &host, &port, &path, &use_ssl)) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to parse URL: %s\n", url); goto err; } /* Only HTTP is supported */ if (use_ssl) { dbgprintf("OCSP: HTTPS not supported, skipping %s\n", url); goto err; } dbgprintf("OCSP: Connecting to %s:%s%s\n", host, port, path); /* Connect to OCSP responder */ bio = ocsp_connect(host, port, device); if (!bio) { goto err; } /* Create OCSP request */ req = OCSP_REQUEST_new(); if (!req) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to create OCSP request\n"); goto err; } id = OCSP_cert_to_id(NULL, cert, issuer); if (!id) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to create OCSP certificate ID\n"); goto err; } if (!OCSP_request_add0_id(req, id)) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Failed to add certificate ID to OCSP request\n"); OCSP_CERTID_free(id); goto err; } /* Add nonce extension for replay attack protection */ OCSP_request_add1_nonce(req, NULL, -1); /* Send request and receive response */ rsp = ocsp_send_and_receive(bio, host, path, req); if (!rsp) { goto err; } /* Check response status */ int response_status = OCSP_response_status(rsp); if (response_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { LogError(0, RS_RET_NO_ERRCODE, "OCSP: Response status: %s\n", ocsp_get_response_status_err(response_status)); goto err; } /* Validate response and check certificate status */ ret = ocsp_check_validate_response_and_cert(rsp, req, untrusted_peer_certs, id, ctx, cert_name, cert, issuer, is_revoked); err: if (rsp) OCSP_RESPONSE_free(rsp); if (req) OCSP_REQUEST_free(req); if (bio) BIO_free_all(bio); if (host) OPENSSL_free(host); if (port) OPENSSL_free(port); if (path) OPENSSL_free(path); return ret; } static int ocsp_check( X509 *current_cert, STACK_OF(X509) * untrusted_peer_certs, SSL_CTX *ctx, const char *device, int *is_revoked) { int ret = 0; char cert_name[256]; X509 *issuer = NULL; STACK_OF(OPENSSL_STRING) *ocsp_responders = NULL; const char *url = NULL; int at_least_one_responder = 0; char *cache_key = NULL; int cached_status; X509_NAME_oneline(X509_get_subject_name(current_cert), cert_name, sizeof(cert_name)); /* Reset revoked status */ if (is_revoked) *is_revoked = 0; /* * 1. Lookup the issuer cert of the current certificate, required to marshal a OCSP request. */ if (!(issuer = ocsp_find_issuer(current_cert, cert_name, ctx, untrusted_peer_certs))) goto err; /* * 2. Check cache first to avoid network I/O */ cache_key = ocsp_make_cache_key(current_cert, issuer); if (cache_key && ocsp_cache_lookup(cache_key, &cached_status)) { if (cached_status == V_OCSP_CERTSTATUS_GOOD) { dbgprintf("OCSP: Cache indicates certificate is GOOD for: %s\n", cert_name); ret = 1; goto err; } else if (cached_status == V_OCSP_CERTSTATUS_REVOKED) { LogMsg(0, RS_RET_CERT_REVOKED, LOG_ERR, "OCSP: Cached status shows certificate is REVOKED for: %s\n", cert_name); if (is_revoked) *is_revoked = 1; goto err; } /* UNKNOWN status: fall through to network check */ } /* * 3. Sanity check prior generating OCSP request. * * - No OCSP URL, no OCSP revocation verification required, skip the current cert. * - Only HTTP protocol is supported. If no OCSP responder with a supported protocol * is available, this MUST fail the OCSP verification and abort the TLS handshake. */ ocsp_responders = X509_get1_ocsp(current_cert); if (ocsp_responders == NULL) { ret = 2; goto err; /* continue with cert path validation */ } for (int i = 0; i < sk_OPENSSL_STRING_num(ocsp_responders); i++) { url = sk_OPENSSL_STRING_value(ocsp_responders, i); if (ocsp_is_supported_protocol(url)) { at_least_one_responder = 1; break; } } if (!at_least_one_responder) { LogError(0, RS_RET_NO_ERRCODE, "None of the OCSP responders are supported by " "this implementation:\n"); for (int i = 0; i < sk_OPENSSL_STRING_num(ocsp_responders); i++) { url = sk_OPENSSL_STRING_value(ocsp_responders, i); LogError(0, RS_RET_NO_ERRCODE, "\t%s\n", url); } goto err; } /* * Try all supported OCSP responders one by one. * * One successful OCSP status response is enough. Not all responders * need to be queried. */ for (int i = 0; i < sk_OPENSSL_STRING_num(ocsp_responders); i++) { url = sk_OPENSSL_STRING_value(ocsp_responders, i); if (ocsp_request_per_responder(url, current_cert, issuer, untrusted_peer_certs, ctx, device, is_revoked)) { ret = 1; goto err; } /* When revoked don't try other sources/OCSP responders */ if (is_revoked && *is_revoked) goto err; /* If the status is unknown, try the next available responder */ } err: if (ocsp_responders) X509_email_free(ocsp_responders); if (cache_key) free(cache_key); return ret; } #endif /* !ENABLE_WOLFSSL */ /*--------------------------------------End OCSP Support ------------------------------------------*/ /* Verify Callback for X509 Certificate validation. Force visibility as this function is not called anywhere but * only used as callback! */ int net_ossl_verify_callback(int status, X509_STORE_CTX *store) { char szdbgdata1[256]; char szdbgdata2[256]; dbgprintf("verify_callback: status %d\n", status); if (status == 0) { /* Retrieve all needed pointers */ X509 *cert = X509_STORE_CTX_get_current_cert(store); int depth = X509_STORE_CTX_get_error_depth(store); SSL *ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()); int err = X509_STORE_CTX_get_error(store); int iVerifyMode = SSL_get_verify_mode(ssl); nsd_t *pNsdTcp = (nsd_t *)SSL_get_ex_data(ssl, 0); PermitExpiredCerts *pPermitExpiredCerts = (PermitExpiredCerts *)SSL_get_ex_data(ssl, 1); dbgprintf("verify_callback: Certificate validation failed, Mode (%d)!\n", iVerifyMode); X509_NAME_oneline(X509_get_issuer_name(cert), szdbgdata1, sizeof(szdbgdata1)); X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(cert), szdbgdata2, sizeof(szdbgdata2)); uchar *fromHost = NULL; if (pNsdTcp != NULL) { nsd_ptcp.GetRemoteHName(pNsdTcp, &fromHost); } if (iVerifyMode != SSL_VERIFY_NONE) { /* Handle expired Certificates **/ if (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) { if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_PERMIT) { dbgprintf( "verify_callback: EXPIRED cert but PERMITTED at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err)); /* Set Status to OK*/ status = 1; } else if (pPermitExpiredCerts != NULL && *pPermitExpiredCerts == OSSL_EXPIRED_WARN) { LogMsg(0, RS_RET_CERT_EXPIRED, LOG_WARNING, "Certificate EXPIRED warning at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s peer '%s'", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err), fromHost); /* Set Status to OK*/ status = 1; } else /* also default - if (pPermitExpiredCerts == OSSL_EXPIRED_DENY)*/ { LogMsg(0, RS_RET_CERT_EXPIRED, LOG_ERR, "Certificate EXPIRED at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n\t" "not permitted to talk to peer '%s', certificate invalid: " "certificate expired", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err), fromHost); } } else if (err == X509_V_ERR_CERT_REVOKED) { LogMsg(0, RS_RET_CERT_REVOKED, LOG_ERR, "Certificate REVOKED at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n\t" "not permitted to talk to peer '%s', certificate invalid: " "certificate revoked", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err), fromHost); } else { /* all other error codes cause failure */ LogMsg(0, RS_RET_NO_ERRCODE, LOG_ERR, "Certificate error at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s - peer '%s'", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err), fromHost); } } else { /* do not verify certs in ANON mode, just log into debug */ dbgprintf( "verify_callback: Certificate validation DISABLED but Error at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err)); /* Set Status to OK*/ status = 1; } free(fromHost); } if (status == 0) return 0; /* Verification failed */ #ifndef ENABLE_WOLFSSL /* OCSP revocation checking is not available in WolfSSL builds */ /* * Certificate revocation checks (only if enabled via StreamDriver.TlsRevocationCheck) */ X509 *cert = X509_STORE_CTX_get_current_cert(store); SSL *ssl = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()); /* Check if revocation checking is enabled * Note: Using index 3 to avoid collision with imdtls which uses index 2 * Index allocation: 0=pTcp, 1=permitExpiredCerts, 2=imdtls instance, 3=revocationCheck */ int *pTlsRevocationCheck = (int *)SSL_get_ex_data(ssl, 3); int tlsRevocationCheck = (pTlsRevocationCheck != NULL) ? *pTlsRevocationCheck : 0; if (tlsRevocationCheck == 0) { /* Revocation checking is disabled, skip OCSP/CRL checks */ return status; } STACK_OF(X509) *untrusted_peer_certs = X509_STORE_CTX_get1_chain(store); SSL_CTX *ctx = SSL_get_SSL_CTX(ssl); int ret, is_revoked = 0; const char *device = NULL; /* Try to get device name from nsd object if available */ /* Note: device binding is not currently supported in the refactored code */ /* This is left here for future enhancement */ /* 1. OCSP with caching and non-blocking I/O */ /* Note: OCSP checks use non-blocking sockets with OCSP_TIMEOUT (5 sec) per responder. * Results are cached to minimize network I/O on subsequent TLS handshakes. * See: https://github.com/rsyslog/rsyslog/issues/6469 */ ret = ocsp_check(cert, untrusted_peer_certs, ctx, device, &is_revoked); if (ret == 1) { /* Status is OK */ status = 1; goto done; } else if (ret == 2) { /* No OCSP URL, give CRL a chance */ status = 1; } else if (is_revoked) { /* Cert is revoked, fail verification */ status = 0; goto done; } else { /* If OCSP failed, but cert was not revoked, then the Status might be still OK. * Try alternative sources (e.g. CRL), in compliance with RFC 6960, Chapter 2.2, Page 7-8. */ status = 0; } /* 2. CRL */ /* CRL support is not implemented. * This stub will fail if the cert holds a CRL Distribution Point. */ ret = crl_check(cert, &is_revoked); if (ret == 1) { /* Status is OK */ status = 1; } else if (ret == 2) { /* No CRL, keep the existing status */ ; } else { /* Cert is revoked, or check failed -> fail verification */ status = 0; } done: if (untrusted_peer_certs) sk_X509_pop_free(untrusted_peer_certs, X509_free); #endif /* !ENABLE_WOLFSSL */ return status; } #ifndef ENABLE_WOLFSSL #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) static long RSYSLOG_BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) * argp, size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl, int ret, size_t __attribute__((unused)) * processed) #else static long RSYSLOG_BIO_debug_callback( BIO *bio, int cmd, const char __attribute__((unused)) * argp, int argi, long __attribute__((unused)) argl, long ret) #endif { long ret2 = ret; long r = 1; if (BIO_CB_RETURN & cmd) r = ret; dbgprintf("openssl debugmsg: BIO[%p]: ", (void *)bio); switch (cmd) { case BIO_CB_FREE: dbgprintf("Free - %s\n", RSYSLOG_BIO_method_name(bio)); break; /* Disabled due API changes for OpenSSL 1.1.0+ */ #if OPENSSL_VERSION_NUMBER < 0x10100000L case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) dbgprintf("read(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio)); else dbgprintf("read(%d,%lu) - %s\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) dbgprintf("write(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio)); else dbgprintf("write(%d,%lu) - %s\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; #else case BIO_CB_READ: dbgprintf("read %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_WRITE: dbgprintf("write %s\n", RSYSLOG_BIO_method_name(bio)); break; #endif case BIO_CB_PUTS: dbgprintf("puts() - %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_GETS: dbgprintf("gets(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_CTRL: dbgprintf("ctrl(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_RETURN | BIO_CB_READ: dbgprintf("read return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_WRITE: dbgprintf("write return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_GETS: dbgprintf("gets return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_PUTS: dbgprintf("puts return %ld\n", ret2); break; case BIO_CB_RETURN | BIO_CB_CTRL: dbgprintf("ctrl return %ld\n", ret2); break; default: dbgprintf("bio callback - unknown type (%d)\n", cmd); break; } return (r); } #endif /* !ENABLE_WOLFSSL */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) // Requires at least OpenSSL v1.1.1 PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wunused_parameter static int net_ossl_generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len) { unsigned char result[EVP_MAX_MD_SIZE]; unsigned int resultlength; unsigned char *sslHello; unsigned int length; sslHello = (unsigned char *)"rsyslog"; length = strlen((char *)sslHello); // Generate the cookie using SHA256 hash if (!EVP_Digest(sslHello, length, result, &resultlength, EVP_sha256(), NULL)) { return 0; } memcpy(cookie, result, resultlength); *cookie_len = resultlength; dbgprintf("net_ossl_generate_cookie: generate cookie SUCCESS\n"); return 1; } PRAGMA_DIAGNOSTIC_POP static int net_ossl_verify_cookie(SSL *ssl, const unsigned char *cookie, unsigned int cookie_len) { unsigned char cookie_gen[EVP_MAX_MD_SIZE]; unsigned int cookie_gen_len; // Generate a cookie using the same method as in net_ossl_generate_cookie if (!net_ossl_generate_cookie(ssl, cookie_gen, &cookie_gen_len)) { dbgprintf("net_ossl_verify_cookie: generate cookie FAILED\n"); return 0; } // Check if the generated cookie matches the cookie received if (cookie_len == cookie_gen_len && memcmp(cookie, cookie_gen, cookie_len) == 0) { dbgprintf("net_ossl_verify_cookie: compare cookie SUCCESS\n"); return 1; } dbgprintf("net_ossl_verify_cookie: compare cookie FAILED\n"); return 0; } static rsRetVal net_ossl_init_engine(__attribute__((unused)) net_ossl_t *pThis) { // OpenSSL Engine Support feature relies on an outdated version of OpenSSL and is // strictly experimental. No support or guarantees are provided. Use at your own risk. DEFiRet; #ifndef OPENSSL_NO_ENGINE const char *engine_id = NULL; const char *engine_name = NULL; PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wdeprecated_declarations // Get the default RSA engine ENGINE *default_engine = ENGINE_get_default_RSA(); if (default_engine) { engine_id = ENGINE_get_id(default_engine); engine_name = ENGINE_get_name(default_engine); DBGPRINTF("net_ossl_init_engine: Default RSA Engine: ID = %s, Name = %s\n", engine_id, engine_name); // Free the engine reference when done ENGINE_free(default_engine); } else { DBGPRINTF("net_ossl_init_engine: No default RSA Engine set.\n"); } /* Setting specific Engine */ if (runConf != NULL && glbl.GetDfltOpensslEngine(runConf) != NULL) { default_engine = ENGINE_by_id((char *)glbl.GetDfltOpensslEngine(runConf)); if (default_engine && ENGINE_init(default_engine)) { /* engine initialised */ ENGINE_set_default_DSA(default_engine); ENGINE_set_default_ciphers(default_engine); /* Switch to Engine */ DBGPRINTF("net_ossl_init_engine: Changed default Engine to %s\n", glbl.GetDfltOpensslEngine(runConf)); /* Release the functional reference from ENGINE_init() */ ENGINE_finish(default_engine); } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: ENGINE_init failed to load Engine '%s'" "ossl netstream driver", glbl.GetDfltOpensslEngine(runConf)); net_ossl_lastOpenSSLErrorMsg(NULL, 0, NULL, LOG_ERR, "net_ossl_init_engine", "ENGINE_init"); } // Free the engine reference when done ENGINE_free(default_engine); } else { DBGPRINTF("net_ossl_init_engine: use openssl default Engine"); } PRAGMA_DIAGNOSTIC_POP #else DBGPRINTF("net_ossl_init_engine: OpenSSL compiled without ENGINE support - ENGINE support disabled\n"); #endif /* OPENSSL_NO_ENGINE */ RETiRet; } static rsRetVal net_ossl_ctx_init_cookie(net_ossl_t *pThis) { DEFiRet; // Set our cookie generation and verification callbacks SSL_CTX_set_options(pThis->ctx, SSL_OP_COOKIE_EXCHANGE); SSL_CTX_set_cookie_generate_cb(pThis->ctx, net_ossl_generate_cookie); SSL_CTX_set_cookie_verify_cb(pThis->ctx, net_ossl_verify_cookie); RETiRet; } #endif // OPENSSL_VERSION_NUMBER >= 0x10100000L /* ------------------------------ end OpenSSL helpers ------------------------------------------*/ /* ------------------------------ OpenSSL Callback set helpers ---------------------------------*/ void net_ossl_set_ssl_verify_callback(SSL *pSsl, int flags) { /* Enable certificate valid checking */ SSL_set_verify(pSsl, flags, net_ossl_verify_callback); } void net_ossl_set_ctx_verify_callback(SSL_CTX *pCtx, int flags) { /* Enable certificate valid checking */ SSL_CTX_set_verify(pCtx, flags, net_ossl_verify_callback); } void net_ossl_set_bio_callback(BIO *conn) { #ifndef ENABLE_WOLFSSL #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) BIO_set_callback_ex(conn, RSYSLOG_BIO_debug_callback_ex); #else BIO_set_callback(conn, RSYSLOG_BIO_debug_callback); #endif // OPENSSL_VERSION_NUMBER >= 0x10100000L #else (void)conn; #endif } /* ------------------------------ End OpenSSL Callback set helpers -----------------------------*/ /* Standard-Constructor */ BEGINobjConstruct(net_ossl) /* be sure to specify the object type also in END macro! */ DBGPRINTF("net_ossl_construct: [%p]\n", pThis); pThis->bReportAuthErr = 1; pThis->bSANpriority = 0; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) CHKiRet(net_ossl_init_engine(pThis)); finalize_it: #endif ENDobjConstruct(net_ossl) /* destructor for the net_ossl object */ BEGINobjDestruct(net_ossl) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(net_ossl); DBGPRINTF("net_ossl_destruct: [%p]\n", pThis); /* Free SSL obj also if we do not have a session - or are NOT in TLS mode! */ if (pThis->ssl != NULL) { DBGPRINTF("net_ossl_destruct: [%p] FREE pThis->ssl \n", pThis); SSL_free(pThis->ssl); pThis->ssl = NULL; } if (pThis->ctx != NULL && !pThis->ctx_is_copy) { SSL_CTX_free(pThis->ctx); pThis->ctx = NULL; } free((void *)pThis->pszCAFile); free((void *)pThis->pszCRLFile); free((void *)pThis->pszKeyFile); free((void *)pThis->pszCertFile); free((void *)pThis->pszExtraCAFiles); ENDobjDestruct(net_ossl) /* queryInterface function */ BEGINobjQueryInterface(net_ossl) CODESTARTobjQueryInterface(net_ossl); DBGPRINTF("netosslQueryInterface\n"); if (pIf->ifVersion != net_osslCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } pIf->Construct = (rsRetVal(*)(net_ossl_t **))net_osslConstruct; pIf->Destruct = (rsRetVal(*)(net_ossl_t **))net_osslDestruct; pIf->osslCtxInit = net_ossl_osslCtxInit; pIf->osslChkpeername = net_ossl_chkpeername; pIf->osslPeerfingerprint = net_ossl_peerfingerprint; pIf->osslGetpeercert = net_ossl_getpeercert; pIf->osslChkpeercertvalidity = net_ossl_chkpeercertvalidity; #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) pIf->osslApplyTlscgfcmd = net_ossl_apply_tlscgfcmd; #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L pIf->osslSetBioCallback = net_ossl_set_bio_callback; pIf->osslSetCtxVerifyCallback = net_ossl_set_ctx_verify_callback; pIf->osslSetSslVerifyCallback = net_ossl_set_ssl_verify_callback; pIf->osslLastOpenSSLErrorMsg = net_ossl_lastOpenSSLErrorMsg; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) pIf->osslCtxInitCookie = net_ossl_ctx_init_cookie; pIf->osslInitEngine = net_ossl_init_engine; #endif finalize_it: ENDobjQueryInterface(net_ossl) /* exit our class */ BEGINObjClassExit(net_ossl, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(net_ossl); DBGPRINTF("netosslClassExit\n"); /* release objects we no longer need */ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME); objRelease(net, LM_NET_FILENAME); objRelease(glbl, CORE_COMPONENT); /* shut down OpenSSL */ osslGlblExit(); ENDObjClassExit(net_ossl) /* Initialize the net_ossl class. Must be called as the very first method * before anything else is called inside this class. */ BEGINObjClassInit(net_ossl, 1, OBJ_IS_CORE_MODULE) /* class, version */ DBGPRINTF("net_osslClassInit\n"); // request objects we use CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME)); // Do global TLS init stuff osslGlblInit(); ENDObjClassInit(net_ossl) /* --------------- here now comes the plumbing that makes as a library module --------------- */ /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/var.c0000644000000000000000000000013015132411300015142 xustar0029 mtime=1768559296.27888583 29 atime=1787067618.06743833 30 ctime=1787067794.382724831 rsyslog-8.2608.0/runtime/var.c0000666000175000017500000001013315132411300014610 0ustar00rgerrger/* var.c - a typeless variable class * * This class is used to represent variable values, which may have any type. * Among others, it will be used inside rsyslog's expression system, but * also internally at any place where a typeless variable is needed. * * Module begun 2008-02-20 by Rainer Gerhards, with some code taken * from the obj.c/.h files. * * Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "obj.h" #include "srUtils.h" #include "var.h" /* static data */ DEFobjStaticHelpers; /* Standard-Constructor */ BEGINobjConstruct(var) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(var) /* ConstructionFinalizer * rgerhards, 2008-01-09 */ static rsRetVal varConstructFinalize(var_t __attribute__((unused)) * pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, var); RETiRet; } /* destructor for the var object */ BEGINobjDestruct(var) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(var); if (pThis->pcsName != NULL) rsCStrDestruct(&pThis->pcsName); if (pThis->varType == VARTYPE_STR) { if (pThis->val.pStr != NULL) rsCStrDestruct(&pThis->val.pStr); } ENDobjDestruct(var) /* DebugPrint support for the var object */ BEGINobjDebugPrint(var) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(var); switch (pThis->varType) { case VARTYPE_STR: dbgoprint((obj_t*)pThis, "type: cstr, val '%s'\n", rsCStrGetSzStrNoNULL(pThis->val.pStr)); break; case VARTYPE_NUMBER: dbgoprint((obj_t*)pThis, "type: number, val %lld\n", pThis->val.num); break; case VARTYPE_SYSLOGTIME: case VARTYPE_NONE: default: dbgoprint((obj_t*)pThis, "type %d currently not supported in debug output\n", pThis->varType); break; } ENDobjDebugPrint(var) /* queryInterface function * rgerhards, 2008-02-21 */ BEGINobjQueryInterface(var) CODESTARTobjQueryInterface(var); if (pIf->ifVersion != varCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = varConstruct; pIf->ConstructFinalize = varConstructFinalize; pIf->Destruct = varDestruct; pIf->DebugPrint = varDebugPrint; finalize_it: ENDobjQueryInterface(var) /* Initialize the var class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(var, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ /* now set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, varDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, varConstructFinalize); ENDObjClassInit(var) /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/regexp.h0000644000000000000000000000013215132411300015653 xustar0030 mtime=1768559296.273885751 30 atime=1787067616.820415078 30 ctime=1787067794.575728428 rsyslog-8.2608.0/runtime/regexp.h0000666000175000017500000000316115132411300015322 0ustar00rgerrger/* The regexp object. It encapsulates the C regexp functionality. The primary * purpose of this wrapper class is to enable rsyslogd core to be build without * regexp libraries. * * Copyright 2008-2012 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_REGEXP_H #define INCLUDED_REGEXP_H #include /* interfaces */ BEGINinterface(regexp) /* name must also be changed in ENDinterface macro! */ int (*regcomp)(regex_t *preg, const char *regex, int cflags); int (*regexec)(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); size_t (*regerror)(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); void (*regfree)(regex_t *preg); ENDinterface(regexp) #define regexpCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(regexp); /* the name of our library binary */ #define LM_REGEXP_FILENAME "lmregexp" #endif /* #ifndef INCLUDED_REGEXP_H */ rsyslog-8.2608.0/runtime/PaxHeaders/syslogd-types.h0000644000000000000000000000013215132411300017207 xustar0030 mtime=1768559296.277885814 30 atime=1787067616.806414817 30 ctime=1787067794.257722502 rsyslog-8.2608.0/runtime/syslogd-types.h0000666000175000017500000000774015132411300016665 0ustar00rgerrger/* syslogd-type.h * This file contains type defintions used by syslogd and its modules. * It is a required input for any module. * * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) * * Copyright 2007-2018 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SYSLOGD_TYPES_INCLUDED #define SYSLOGD_TYPES_INCLUDED 1 #include "stringbuf.h" #include /* we use RSTRUE/FALSE to prevent name claches with other packages */ #define RSFALSE 0 #define RSTRUE 1 #define MAXFNAME 4096 /* max file pathname length */ #define _DB_MAXCONNINFOLEN 2048 /* maximum length connection string */ #define _DB_MAXDBLEN 128 /* maximum number of db */ #define _DB_MAXUNAMELEN 128 /* maximum number of user name */ #define _DB_MAXPWDLEN 128 /* maximum number of user's pass */ #define _DB_DELAYTIMEONERROR 20 /* If an error occur we stop logging until a delayed time is over */ /* we define features of the syslog code. This features can be used * to check if modules are compatible with them - and possible other * applications I do not yet envision. -- rgerhards, 2007-07-24 */ typedef enum _syslogFeature { sFEATURERepeatedMsgReduction = 1, /* for output modules */ sFEATURENonCancelInputTermination = 2, /* for input modules */ sFEATUREAutomaticSanitazion = 3, /* for parser modules */ sFEATUREAutomaticPRIParsing = 4 /* for parser modules */ } syslogFeature; /* we define our own facility and severities */ /* facility and severity codes */ typedef struct _syslogCode { char *c_name; int c_val; } syslogCODE; /* values for host comparisons specified with host selector blocks * (+host, -host). rgerhards 2005-10-18. */ enum _EHostnameCmpMode { HN_NO_COMP = 0, /* do not compare hostname */ HN_COMP_MATCH = 1, /* hostname must match */ HN_COMP_NOMATCH = 2 /* hostname must NOT match */ }; typedef enum _EHostnameCmpMode EHostnameCmpMode; /* time type numerical values for structure below */ #define TIME_TYPE_UNINIT 0 #define TIME_TYPE_RFC3164 1 #define TIME_TYPE_RFC5424 2 /* rgerhards 2004-11-11: the following structure represents * a time as it is used in syslog. * rgerhards, 2009-06-23: packed structure for better cache performance * (but left ultimate decision about packing to compiler) */ struct syslogTime { intTiny timeType; /* 0 - unitinialized , 1 - RFC 3164, 2 - syslog-protocol */ intTiny month; intTiny day; intTiny wday; intTiny hour; /* 24 hour clock */ intTiny minute; intTiny second; intTiny secfracPrecision; intTiny OffsetMinute; /* UTC offset in minutes */ intTiny OffsetHour; /* UTC offset in hours * full UTC offset minutes = OffsetHours*60 + OffsetMinute. Then use * OffsetMode to know the direction. */ char OffsetMode; /* UTC offset + or - */ short year; int secfrac; /* fractional seconds (must be 32 bit!) */ intTiny inUTC; /* forced UTC? */ }; typedef struct syslogTime syslogTime_t; struct tzinfo { char *id; char offsMode; int8_t offsHour; int8_t offsMin; }; typedef struct tzinfo tzinfo_t; typedef enum { ACT_STRING_PASSING = 0, ACT_ARRAY_PASSING = 1, ACT_MSG_PASSING = 2, ACT_JSON_PASSING = 3 } paramPassing_t; #endif /* #ifndef SYSLOGD_TYPES_INCLUDED */ /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/modules.c0000644000000000000000000000013215241075234016041 xustar0030 mtime=1787067036.601578219 30 atime=1787067036.746580934 30 ctime=1787067794.353724291 rsyslog-8.2608.0/runtime/modules.c0000664000175000017500000015066015241075234015515 0ustar00rgerrger/* modules.c * This is the implementation of syslogd modules object. * This object handles plug-ins and build-in modules of all kind. * * Modules are reference-counted. Anyone who access a module must call * Use() before any function is accessed and Release() when he is done. * When the reference count reaches 0, rsyslog unloads the module (that * may be changed in the future to cache modules). Rsyslog does NOT * unload modules with a reference count > 0, even if the unload * method is called! * * File begun on 2007-07-22 by RGerhards * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef OS_BSD #include "libgen.h" #endif #include /* TODO: replace this with the libtools equivalent! */ #include #include #include "rsyslog.h" #include "rainerscript.h" #include "cfsysline.h" #include "rsconf.h" #include "modules.h" #include "errmsg.h" #include "parser.h" #include "strgen.h" /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(strgen) static modInfo_t *pLoadedModules = NULL; /* list of currently-loaded modules */ static modInfo_t *pLoadedModulesLast = NULL; /* tail-pointer */ /* already dlopen()-ed libs */ static struct dlhandle_s *pHandles = NULL; static uchar *pModDir; /* directory where loadable modules are found */ /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = {{"load", eCmdHdlrGetWord, 1}}; static struct cnfparamblk pblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; typedef rsRetVal (*pModInit_t)(int, int *, rsRetVal (**)(), rsRetVal (*)(), modInfo_t *); static const char cfgModRefSrc[] = "cfgmodules"; static rsRetVal Use(const char *srcFile, modInfo_t *pThis); /* we provide a set of dummy functions for modules that do not support the * some interfaces. * On the commit feature: As the modules do not support it, they commit each message they * receive, and as such the dummies can always return RS_RET_OK without causing * harm. This simplifies things as in action processing we do not need to check * if the transactional entry points exist. */ static rsRetVal dummyBeginTransaction(__attribute__((unused)) void *dummy) { return RS_RET_OK; } static rsRetVal dummyEndTransaction(__attribute__((unused)) void *dummy) { return RS_RET_OK; } static rsRetVal dummyIsCompatibleWithFeature(__attribute__((unused)) syslogFeature eFeat) { return RS_RET_INCOMPATIBLE; } static rsRetVal dummynewActInst(uchar *modName, struct nvlst __attribute__((unused)) * dummy1, void __attribute__((unused)) * *dummy2, omodStringRequest_t __attribute__((unused)) * *dummy3) { LogError(0, RS_RET_CONFOBJ_UNSUPPORTED, "config objects are not " "supported by module '%s' -- legacy config options " "MUST be used instead", modName); return RS_RET_CONFOBJ_UNSUPPORTED; } #ifdef DEBUG /* we add some home-grown support to track our users (and detect who does not free us). In * the long term, this should probably be migrated into debug.c (TODO). -- rgerhards, 2008-03-11 */ /* add a user to the current list of users (always at the root) */ static void modUsrAdd(modInfo_t *pThis, const char *pszUsr) { modUsr_t *pUsr; if ((pUsr = calloc(1, sizeof(modUsr_t))) == NULL) goto finalize_it; if ((pUsr->pszFile = strdup(pszUsr)) == NULL) { free(pUsr); goto finalize_it; } if (pThis->pModUsrRoot != NULL) { pUsr->pNext = pThis->pModUsrRoot; } pThis->pModUsrRoot = pUsr; finalize_it: return; } /* remove a user from the current user list * rgerhards, 2008-03-11 */ static void modUsrDel(modInfo_t *pThis, const char *pszUsr) { modUsr_t *pUsr; modUsr_t *pPrev = NULL; for (pUsr = pThis->pModUsrRoot; pUsr != NULL; pUsr = pUsr->pNext) { if (!strcmp(pUsr->pszFile, pszUsr)) break; else pPrev = pUsr; } if (pUsr == NULL) { dbgprintf("oops - tried to delete user %s from module %s and it wasn't registered as one...\n", pszUsr, pThis->pszName); } else { if (pPrev == NULL) { /* This was at the root! */ pThis->pModUsrRoot = pUsr->pNext; } else { pPrev->pNext = pUsr->pNext; } /* free resources */ free(pUsr->pszFile); free(pUsr); pUsr = NULL; /* just to make sure... */ } } /* print a short list all all source files using the module in question * rgerhards, 2008-03-11 */ static void modUsrPrint(modInfo_t *pThis) { modUsr_t *pUsr; for (pUsr = pThis->pModUsrRoot; pUsr != NULL; pUsr = pUsr->pNext) { dbgprintf("\tmodule %s is currently in use by file %s\n", pThis->pszName, pUsr->pszFile); } } /* print all loaded modules and who is accessing them. This is primarily intended * to be called at end of run to detect "module leaks" and who is causing them. * rgerhards, 2008-03-11 */ static void modUsrPrintAll(void) { modInfo_t *pMod; for (pMod = pLoadedModules; pMod != NULL; pMod = pMod->pNext) { dbgprintf("printing users of loadable module %s, refcount %u, ptr %p, type %d\n", pMod->pszName, pMod->uRefCnt, pMod, pMod->eType); modUsrPrint(pMod); } } #endif /* #ifdef DEBUG */ /* Construct a new module object */ static rsRetVal moduleConstruct(modInfo_t **pThis) { modInfo_t *pNew; if ((pNew = calloc(1, sizeof(modInfo_t))) == NULL) return RS_RET_OUT_OF_MEMORY; /* OK, we got the element, now initialize members that should * not be zero-filled. */ *pThis = pNew; return RS_RET_OK; } /* Destructs a module object. The object must not be linked to the * linked list of modules. Please note that all other dependencies on this * modules must have been removed before (e.g. CfSysLineHandlers!) */ static void moduleDestruct(modInfo_t *pThis) { assert(pThis != NULL); free(pThis->pszName); free(pThis->cnfName); if (pThis->pModHdlr != NULL) { #ifdef VALGRIND DBGPRINTF( "moduleDestruct: compiled with valgrind, do " "not unload module\n"); #else if (glblUnloadModules) { if (pThis->eKeepType == eMOD_NOKEEP) { dlclose(pThis->pModHdlr); } } else { DBGPRINTF( "moduleDestruct: not unloading module " "due to user configuration\n"); } #endif } free(pThis); } /* This enables a module to query the core for specific features. * rgerhards, 2009-04-22 */ static rsRetVal queryCoreFeatureSupport(int *pBool, unsigned uFeat) { DEFiRet; if (pBool == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); *pBool = (uFeat & CORE_FEATURE_BATCHING) ? 1 : 0; finalize_it: RETiRet; } /* The following function is the queryEntryPoint for host-based entry points. * Modules may call it to get access to core interface functions. Please note * that utility functions can be accessed via shared libraries - at least this * is my current shool of thinking. * Please note that the implementation as a query interface allows one to take * care of plug-in interface version differences. -- rgerhards, 2007-07-31 * ... but often it better not to use a new interface. So we now add core * functions here that a plugin may request. -- rgerhards, 2009-04-22 */ static rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)()) { DEFiRet; if ((name == NULL) || (pEtryPoint == NULL)) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (!strcmp((char *)name, "regCfSysLineHdlr")) { *pEtryPoint = regCfSysLineHdlr; } else if (!strcmp((char *)name, "objGetObjInterface")) { *pEtryPoint = objGetObjInterface; } else if (!strcmp((char *)name, "OMSRgetSupportedTplOpts")) { *pEtryPoint = OMSRgetSupportedTplOpts; } else if (!strcmp((char *)name, "queryCoreFeatureSupport")) { *pEtryPoint = queryCoreFeatureSupport; } else { *pEtryPoint = NULL; /* to be on the safe side */ ABORT_FINALIZE(RS_RET_ENTRY_POINT_NOT_FOUND); } finalize_it: RETiRet; } /* get the name of a module */ uchar *modGetName(modInfo_t *pThis) { return ((pThis->pszName == NULL) ? (uchar *)"" : pThis->pszName); } /* get the state-name of a module. The state name is its name * together with a short description of the module state (which * is pulled from the module itself. * rgerhards, 2007-07-24 * TODO: the actual state name is not yet pulled */ static uchar *modGetStateName(modInfo_t *pThis) { return (modGetName(pThis)); } /* Add a module to the loaded module linked list */ static void ATTR_NONNULL() addModToGlblList(modInfo_t *const pThis) { assert(pThis != NULL); if (pLoadedModules == NULL) { pLoadedModules = pLoadedModulesLast = pThis; } else { /* there already exist entries */ pThis->pPrev = pLoadedModulesLast; pLoadedModulesLast->pNext = pThis; pLoadedModulesLast = pThis; } } /* ready module for config processing. this includes checking if the module * is already in the config, so this function may return errors. Returns a * pointer to the last module inthe current config. That pointer needs to * be passed to addModToCnfLst() when it is called later in the process. */ rsRetVal readyModForCnf(modInfo_t *pThis, cfgmodules_etry_t **ppNew, cfgmodules_etry_t **ppLast) { cfgmodules_etry_t *pNew = NULL; cfgmodules_etry_t *pLast; DEFiRet; assert(pThis != NULL); if (loadConf == NULL) { FINALIZE; /* we are in an early init state */ } /* check for duplicates and, as a side-activity, identify last node */ pLast = loadConf->modules.root; if (pLast != NULL) { while (1) { /* loop broken inside */ if (pLast->pMod == pThis) { DBGPRINTF("module '%s' already in this config\n", modGetName(pThis)); if (strncmp((char *)modGetName(pThis), "builtin:", sizeof("builtin:") - 1)) { LogError(0, RS_RET_MODULE_ALREADY_IN_CONF, "module '%s' already in this config, cannot be added\n", modGetName(pThis)); ABORT_FINALIZE(RS_RET_MODULE_ALREADY_IN_CONF); } FINALIZE; } if (pLast->next == NULL) break; pLast = pLast->next; } } /* if we reach this point, pLast is the tail pointer and this module is new * inside the currently loaded config. So, iff it is an input module, let's * pass it a pointer which it can populate with a pointer to its module conf. */ CHKmalloc(pNew = malloc(sizeof(cfgmodules_etry_t))); pNew->canActivate = 1; pNew->next = NULL; pNew->pMod = pThis; if (pThis->beginCnfLoad != NULL) { CHKiRet(pThis->beginCnfLoad(&pNew->modCnf, loadConf)); } *ppLast = pLast; *ppNew = pNew; finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) free(pNew); } RETiRet; } /* abort the creation of a module entry without adding it to the * module list. Needed to prevent mem leaks. */ static inline void abortCnfUse(cfgmodules_etry_t **pNew) { if (pNew != NULL) { free(*pNew); *pNew = NULL; } } /* Add a module to the config module list for current loadConf. * Requires last pointer obtained by readyModForCnf(). * The module pointer is handed over to this function. It is no * longer available to caller one we are called. */ rsRetVal ATTR_NONNULL(1) addModToCnfList(cfgmodules_etry_t **const pNew, cfgmodules_etry_t *const pLast) { DEFiRet; assert(*pNew != NULL); if (loadConf == NULL) { abortCnfUse(pNew); FINALIZE; /* we are in an early init state */ } /* The config keeps a raw modInfo_t pointer and later calls module entry * points during rsconf teardown, so hold an explicit module reference for * the lifetime of the cfgmodules entry. */ CHKiRet(Use(cfgModRefSrc, (*pNew)->pMod)); if (pLast == NULL) { loadConf->modules.root = *pNew; } else { /* there already exist entries */ pLast->next = *pNew; } finalize_it: *pNew = NULL; RETiRet; } /* Get the next module pointer - this is used to traverse the list. * The function returns the next pointer or NULL, if there is no next one. * The last object must be provided to the function. If NULL is provided, * it starts at the root of the list. Even in this case, NULL may be * returned - then, the list is empty. * rgerhards, 2007-07-23 */ static modInfo_t *GetNxt(modInfo_t *pThis) { modInfo_t *pNew; if (pThis == NULL) pNew = pLoadedModules; else pNew = pThis->pNext; return (pNew); } /* this function is like GetNxt(), but it returns pointers to * the configmodules entry, which than can be used to obtain the * actual module pointer. Note that it returns those for * modules of specific type only. Only modules from the provided * config are returned. Note that processing speed could be improved, * but this is really not relevant, as config file loading is not really * something we are concerned about in regard to runtime. */ static cfgmodules_etry_t *GetNxtCnfType(rsconf_t *cnf, cfgmodules_etry_t *node, eModType_t rqtdType) { if (node == NULL) { /* start at beginning of module list */ node = cnf->modules.root; } else { node = node->next; } if (rqtdType != eMOD_ANY) { /* if any, we already have the right one! */ while (node != NULL && node->pMod->eType != rqtdType) { node = node->next; } } return node; } /* Find a module with the given conf name and type. Returns NULL if none * can be found, otherwise module found. */ static modInfo_t *FindWithCnfName(rsconf_t *cnf, uchar *name, eModType_t rqtdType) { cfgmodules_etry_t *node; ; for (node = cnf->modules.root; node != NULL; node = node->next) { if (node->pMod->eType != rqtdType || node->pMod->cnfName == NULL) continue; if (!strcasecmp((char *)node->pMod->cnfName, (char *)name)) break; } return node == NULL ? NULL : node->pMod; } /* Prepare a module for unloading. * This is currently a dummy, to be filled when we have a plug-in * interface - rgerhards, 2007-08-09 * rgerhards, 2007-11-21: * When this function is called, all instance-data must already have * been destroyed. In the case of output modules, this happens when the * rule set is being destroyed. When we implement other module types, we * need to think how we handle it there (and if we have any instance data). * rgerhards, 2008-03-10: reject unload request if the module has a reference * count > 0. */ static rsRetVal modPrepareUnload(modInfo_t *pThis) { DEFiRet; void *pModCookie; assert(pThis != NULL); if (pThis->uRefCnt > 0) { dbgprintf("rejecting unload of module '%s' because it has a refcount of %d\n", pThis->pszName, pThis->uRefCnt); ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED); } CHKiRet(pThis->modGetID(&pModCookie)); pThis->modExit(); /* tell the module to get ready for unload */ CHKiRet(unregCfSysLineHdlrs4Owner(pModCookie)); finalize_it: RETiRet; } /* Add an already-loaded module to the module linked list. This function does * everything needed to fully initialize the module. */ static rsRetVal doModInit(pModInit_t modInit, uchar *name, void *pModHdlr, modInfo_t **pNewModule) { rsRetVal localRet; modInfo_t *pNew = NULL; uchar *pName; strgen_t *pStrgen; /* used for strgen modules */ rsRetVal (*GetName)(uchar **); rsRetVal (*modGetType)(eModType_t *pType); rsRetVal (*modGetKeepType)(eModKeepType_t *pKeepType); struct dlhandle_s *pHandle = NULL; rsRetVal (*getModCnfName)(uchar **cnfName); uchar *cnfName; DEFiRet; assert(modInit != NULL); if ((iRet = moduleConstruct(&pNew)) != RS_RET_OK) { pNew = NULL; FINALIZE; } CHKiRet((*modInit)(CURR_MOD_IF_VERSION, &pNew->iIFVers, &pNew->modQueryEtryPt, queryHostEtryPt, pNew)); if (pNew->iIFVers != CURR_MOD_IF_VERSION) { ABORT_FINALIZE(RS_RET_MISSING_INTERFACE); } /* We now poll the module to see what type it is. We do this only once as this * can never change in the lifetime of an module. -- rgerhards, 2007-12-14 */ CHKiRet((*pNew->modQueryEtryPt)((uchar *)"getType", &modGetType)); CHKiRet((*modGetType)(&pNew->eType)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"getKeepType", &modGetKeepType)); CHKiRet((*modGetKeepType)(&pNew->eKeepType)); dbgprintf("module %s of type %d being loaded (keepType=%d).\n", name, pNew->eType, pNew->eKeepType); /* OK, we know we can successfully work with the module. So we now fill the * rest of the data elements. First we load the interfaces common to all * module types. */ CHKiRet((*pNew->modQueryEtryPt)((uchar *)"modGetID", &pNew->modGetID)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"modExit", &pNew->modExit)); localRet = (*pNew->modQueryEtryPt)((uchar *)"isCompatibleWithFeature", &pNew->isCompatibleWithFeature); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) pNew->isCompatibleWithFeature = dummyIsCompatibleWithFeature; else if (localRet != RS_RET_OK) ABORT_FINALIZE(localRet); localRet = (*pNew->modQueryEtryPt)((uchar *)"setModCnf", &pNew->setModCnf); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) pNew->setModCnf = NULL; else if (localRet != RS_RET_OK) ABORT_FINALIZE(localRet); /* optional calls for new config system */ localRet = (*pNew->modQueryEtryPt)((uchar *)"getModCnfName", &getModCnfName); if (localRet == RS_RET_OK) { if (getModCnfName(&cnfName) == RS_RET_OK) pNew->cnfName = (uchar *)strdup((char *)cnfName); /**< we do not care if strdup() fails, we can accept that */ else pNew->cnfName = NULL; dbgprintf("module config name is '%s'\n", cnfName); } localRet = (*pNew->modQueryEtryPt)((uchar *)"beginCnfLoad", &pNew->beginCnfLoad); if (localRet == RS_RET_OK) { dbgprintf("module %s supports rsyslog v6 config interface\n", name); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"endCnfLoad", &pNew->endCnfLoad)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"freeCnf", &pNew->freeCnf)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"checkCnf", &pNew->checkCnf)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"activateCnf", &pNew->activateCnf)); localRet = (*pNew->modQueryEtryPt)((uchar *)"activateCnfPrePrivDrop", &pNew->activateCnfPrePrivDrop); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->activateCnfPrePrivDrop = NULL; } else { CHKiRet(localRet); } } else if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->beginCnfLoad = NULL; /* flag as non-present */ } else { ABORT_FINALIZE(localRet); } /* ... and now the module-specific interfaces */ switch (pNew->eType) { case eMOD_IN: CHKiRet((*pNew->modQueryEtryPt)((uchar *)"runInput", &pNew->mod.im.runInput)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"willRun", &pNew->mod.im.willRun)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"afterRun", &pNew->mod.im.afterRun)); pNew->mod.im.bCanRun = 0; localRet = (*pNew->modQueryEtryPt)((uchar *)"newInpInst", &pNew->mod.im.newInpInst); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.im.newInpInst = NULL; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } localRet = (*pNew->modQueryEtryPt)((uchar *)"doHUP", &pNew->doHUP); if (localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) ABORT_FINALIZE(localRet); break; case eMOD_OUT: CHKiRet((*pNew->modQueryEtryPt)((uchar *)"freeInstance", &pNew->freeInstance)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"dbgPrintInstInfo", &pNew->dbgPrintInstInfo)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"tryResume", &pNew->tryResume)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"createWrkrInstance", &pNew->mod.om.createWrkrInstance)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"freeWrkrInstance", &pNew->mod.om.freeWrkrInstance)); /* try load optional interfaces */ localRet = (*pNew->modQueryEtryPt)((uchar *)"doHUP", &pNew->doHUP); if (localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) ABORT_FINALIZE(localRet); localRet = (*pNew->modQueryEtryPt)((uchar *)"doHUPWrkr", &pNew->doHUPWrkr); if (localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) ABORT_FINALIZE(localRet); localRet = (*pNew->modQueryEtryPt)((uchar *)"SetShutdownImmdtPtr", &pNew->mod.om.SetShutdownImmdtPtr); if (localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) ABORT_FINALIZE(localRet); localRet = (*pNew->modQueryEtryPt)((uchar *)"setActionInfo", &pNew->mod.om.setActionInfo); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.setActionInfo = NULL; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } pNew->mod.om.supportsTX = 1; localRet = (*pNew->modQueryEtryPt)((uchar *)"beginTransaction", &pNew->mod.om.beginTransaction); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.beginTransaction = dummyBeginTransaction; pNew->mod.om.supportsTX = 0; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } localRet = (*pNew->modQueryEtryPt)((uchar *)"doAction", &pNew->mod.om.doAction); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.doAction = NULL; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } localRet = (*pNew->modQueryEtryPt)((uchar *)"commitTransaction", &pNew->mod.om.commitTransaction); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.commitTransaction = NULL; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } if (pNew->mod.om.doAction == NULL && pNew->mod.om.commitTransaction == NULL) { LogError(0, RS_RET_INVLD_OMOD, "module %s does neither provide doAction() " "nor commitTransaction() interface - cannot " "load", name); ABORT_FINALIZE(RS_RET_INVLD_OMOD); } if (pNew->mod.om.commitTransaction != NULL) { if (pNew->mod.om.doAction != NULL) { LogError(0, RS_RET_INVLD_OMOD, "module %s provides both doAction() " "and commitTransaction() interface, using " "commitTransaction()", name); pNew->mod.om.doAction = NULL; } if (pNew->mod.om.beginTransaction == NULL) { LogError(0, RS_RET_INVLD_OMOD, "module %s provides both commitTransaction() " "but does not provide beginTransaction() - " "cannot load", name); ABORT_FINALIZE(RS_RET_INVLD_OMOD); } } localRet = (*pNew->modQueryEtryPt)((uchar *)"endTransaction", &pNew->mod.om.endTransaction); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.endTransaction = dummyEndTransaction; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } localRet = (*pNew->modQueryEtryPt)((uchar *)"newActInst", &pNew->mod.om.newActInst); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.om.newActInst = dummynewActInst; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } break; case eMOD_LIB: break; case eMOD_PARSER: localRet = (*pNew->modQueryEtryPt)((uchar *)"parse2", &pNew->mod.pm.parse2); if (localRet == RS_RET_OK) { pNew->mod.pm.parse = NULL; CHKiRet((*pNew->modQueryEtryPt)((uchar *)"newParserInst", &pNew->mod.pm.newParserInst)); localRet = (*pNew->modQueryEtryPt)((uchar *)"checkParserInst", &pNew->mod.pm.checkParserInst); if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.pm.checkParserInst = NULL; } else { CHKiRet(localRet); } CHKiRet((*pNew->modQueryEtryPt)((uchar *)"freeParserInst", &pNew->mod.pm.freeParserInst)); } else if (localRet == RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) { pNew->mod.pm.parse2 = NULL; pNew->mod.pm.newParserInst = NULL; pNew->mod.pm.checkParserInst = NULL; pNew->mod.pm.freeParserInst = NULL; CHKiRet((*pNew->modQueryEtryPt)((uchar *)"parse", &pNew->mod.pm.parse)); } else { ABORT_FINALIZE(localRet); } CHKiRet((*pNew->modQueryEtryPt)((uchar *)"GetParserName", &GetName)); CHKiRet(GetName(&pName)); CHKiRet(parserConstructViaModAndName(pNew, pName, NULL)); break; case eMOD_STRGEN: /* first, we need to obtain the strgen object. We could not do that during * init as that would have caused class bootstrap issues which are not * absolutely necessary. Note that we can call objUse() multiple times, it * handles that. */ CHKiRet(objUse(strgen, CORE_COMPONENT)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"strgen", &pNew->mod.sm.strgen)); CHKiRet((*pNew->modQueryEtryPt)((uchar *)"GetName", &GetName)); CHKiRet(GetName(&pName)); CHKiRet(strgen.Construct(&pStrgen)); CHKiRet(strgen.SetName(pStrgen, pName)); CHKiRet(strgen.SetModPtr(pStrgen, pNew)); CHKiRet(strgen.ConstructFinalize(pStrgen)); break; case eMOD_FUNCTION: CHKiRet((*pNew->modQueryEtryPt)((uchar *)"getFunctArray", &pNew->mod.fm.getFunctArray)); int version; struct scriptFunct *functArray; pNew->mod.fm.getFunctArray(&version, &functArray); dbgprintf("LLL: %s\n", functArray[0].fname); addMod2List(version, functArray); break; case eMOD_ANY: /* this is mostly to keep the compiler happy! */ DBGPRINTF("PROGRAM ERROR: eMOD_ANY set as module type\n"); assert(0); break; default: // No action needed for other cases break; } pNew->pszName = (uchar *)strdup((char *)name); /* we do not care if strdup() fails, we can accept that */ pNew->pModHdlr = pModHdlr; if (pModHdlr == NULL) { pNew->eLinkType = eMOD_LINK_STATIC; } else { pNew->eLinkType = eMOD_LINK_DYNAMIC_LOADED; /* if we need to keep the linked module, save it */ if (pNew->eKeepType == eMOD_KEEP) { /* see if we have this one already */ for (pHandle = pHandles; pHandle; pHandle = pHandle->next) { if (!strcmp((char *)name, (char *)pHandle->pszName)) break; } /* not found, create it */ if (!pHandle) { if ((pHandle = malloc(sizeof(*pHandle))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if ((pHandle->pszName = (uchar *)strdup((char *)name)) == NULL) { free(pHandle); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pHandle->pModHdlr = pModHdlr; pHandle->next = pHandles; pHandles = pHandle; } } } /* we initialized the structure, now let's add it to the linked list of modules */ addModToGlblList(pNew); *pNewModule = pNew; finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) moduleDestruct(pNew); *pNewModule = NULL; } RETiRet; } /* Print loaded modules. This is more or less a * debug or test aid, but anyhow I think it's worth it... * This only works if the dbgprintf() subsystem is initialized. * TODO: update for new input modules! */ static void modPrintList(void) { modInfo_t *pMod; pMod = GetNxt(NULL); while (pMod != NULL) { dbgprintf("Loaded Module: Name='%s', IFVersion=%d, ", (char *)modGetName(pMod), pMod->iIFVers); dbgprintf("type="); switch (pMod->eType) { case eMOD_OUT: dbgprintf("output"); break; case eMOD_IN: dbgprintf("input"); break; case eMOD_LIB: dbgprintf("library"); break; case eMOD_PARSER: dbgprintf("parser"); break; case eMOD_STRGEN: dbgprintf("strgen"); break; case eMOD_FUNCTION: dbgprintf("function"); break; case eMOD_ANY: /* this is mostly to keep the compiler happy! */ DBGPRINTF("PROGRAM ERROR: eMOD_ANY set as module type\n"); assert(0); break; default: // No action needed for other cases break; } dbgprintf(" module.\n"); dbgprintf("Entry points:\n"); dbgprintf("\tqueryEtryPt: 0x%lx\n", (unsigned long)pMod->modQueryEtryPt); dbgprintf("\tdbgPrintInstInfo: 0x%lx\n", (unsigned long)pMod->dbgPrintInstInfo); dbgprintf("\tfreeInstance: 0x%lx\n", (unsigned long)pMod->freeInstance); dbgprintf("\tbeginCnfLoad: 0x%lx\n", (unsigned long)pMod->beginCnfLoad); dbgprintf("\tSetModCnf: 0x%lx\n", (unsigned long)pMod->setModCnf); dbgprintf("\tcheckCnf: 0x%lx\n", (unsigned long)pMod->checkCnf); dbgprintf("\tactivateCnfPrePrivDrop: 0x%lx\n", (unsigned long)pMod->activateCnfPrePrivDrop); dbgprintf("\tactivateCnf: 0x%lx\n", (unsigned long)pMod->activateCnf); dbgprintf("\tfreeCnf: 0x%lx\n", (unsigned long)pMod->freeCnf); switch (pMod->eType) { case eMOD_OUT: dbgprintf("Output Module Entry Points:\n"); dbgprintf("\tdoAction: %p\n", pMod->mod.om.doAction); dbgprintf("\tparseSelectorAct: %p\n", pMod->mod.om.parseSelectorAct); dbgprintf("\tnewActInst: %p\n", (pMod->mod.om.newActInst == dummynewActInst) ? NULL : pMod->mod.om.newActInst); dbgprintf("\ttryResume: %p\n", pMod->tryResume); dbgprintf("\tdoHUP: %p\n", pMod->doHUP); dbgprintf( "\tBeginTransaction: %p\n", ((pMod->mod.om.beginTransaction == dummyBeginTransaction) ? NULL : pMod->mod.om.beginTransaction)); dbgprintf("\tEndTransaction: %p\n", ((pMod->mod.om.endTransaction == dummyEndTransaction) ? NULL : pMod->mod.om.endTransaction)); break; case eMOD_IN: dbgprintf("Input Module Entry Points\n"); dbgprintf("\trunInput: 0x%lx\n", (unsigned long)pMod->mod.im.runInput); dbgprintf("\twillRun: 0x%lx\n", (unsigned long)pMod->mod.im.willRun); dbgprintf("\tafterRun: 0x%lx\n", (unsigned long)pMod->mod.im.afterRun); break; case eMOD_LIB: break; case eMOD_PARSER: dbgprintf("Parser Module Entry Points\n"); dbgprintf("\tparse: 0x%lx\n", (unsigned long)pMod->mod.pm.parse); dbgprintf("\tparse2: %p\n", pMod->mod.pm.parse2); dbgprintf("\tnewParserInst: %p\n", pMod->mod.pm.newParserInst); dbgprintf("\tcheckParserInst: %p\n", pMod->mod.pm.checkParserInst); dbgprintf("\tfreeParserInst: %p\n", pMod->mod.pm.freeParserInst); break; case eMOD_STRGEN: dbgprintf("Strgen Module Entry Points\n"); dbgprintf("\tstrgen: 0x%lx\n", (unsigned long)pMod->mod.sm.strgen); break; case eMOD_FUNCTION: dbgprintf("Function Module Entry Points\n"); dbgprintf("\tgetFunctArray: 0x%lx\n", (unsigned long)pMod->mod.fm.getFunctArray); break; case eMOD_ANY: /* this is mostly to keep the compiler happy! */ break; default: // No action needed for other cases break; } dbgprintf("\n"); pMod = GetNxt(pMod); /* done, go next */ } } /* HUP all modules that support it - except for actions, which * need (and have) specialised HUP handling. */ void modDoHUP(void) { modInfo_t *pMod; pthread_mutex_lock(&mutObjGlobalOp); pMod = GetNxt(NULL); while (pMod != NULL) { if (pMod->eType != eMOD_OUT && pMod->doHUP != NULL) { DBGPRINTF("HUPing module %s\n", (char *)modGetName(pMod)); pMod->doHUP(NULL); } pMod = GetNxt(pMod); /* done, go next */ } pthread_mutex_unlock(&mutObjGlobalOp); } /* unlink and destroy a module. The caller must provide a pointer to the module * itself as well as one to its immediate predecessor. * rgerhards, 2008-02-26 */ static rsRetVal modUnlinkAndDestroy(modInfo_t **ppThis) { DEFiRet; modInfo_t *pThis; assert(ppThis != NULL); pThis = *ppThis; assert(pThis != NULL); pthread_mutex_lock(&mutObjGlobalOp); /* first check if we are permitted to unload */ if (pThis->eType == eMOD_LIB) { if (pThis->uRefCnt > 0) { dbgprintf("module %s NOT unloaded because it still has a refcount of %u\n", pThis->pszName, pThis->uRefCnt); ABORT_FINALIZE(RS_RET_MODULE_STILL_REFERENCED); } } /* we need to unlink the module before we can destruct it -- rgerhards, 2008-02-26 */ if (pThis->pPrev == NULL) { /* module is root, so we need to set a new root */ pLoadedModules = pThis->pNext; } else { pThis->pPrev->pNext = pThis->pNext; } if (pThis->pNext == NULL) { pLoadedModulesLast = pThis->pPrev; } else { pThis->pNext->pPrev = pThis->pPrev; } /* finally, we are ready for the module to go away... */ dbgprintf("Unloading module %s\n", modGetName(pThis)); CHKiRet(modPrepareUnload(pThis)); *ppThis = pThis->pNext; moduleDestruct(pThis); finalize_it: pthread_mutex_unlock(&mutObjGlobalOp); RETiRet; } /* unload all loaded modules of a specific type (use eMOD_ALL if you want to * unload all module types). The unload happens only if the module is no longer * referenced. So some modules may survive this call. * rgerhards, 2008-03-11 */ static rsRetVal modUnloadAndDestructAll(eModLinkType_t modLinkTypesToUnload) { DEFiRet; modInfo_t *pModCurr; /* module currently being processed */ pModCurr = GetNxt(NULL); while (pModCurr != NULL) { if (modLinkTypesToUnload == eMOD_LINK_ALL || pModCurr->eLinkType == modLinkTypesToUnload) { if (modUnlinkAndDestroy(&pModCurr) == RS_RET_MODULE_STILL_REFERENCED) { pModCurr = GetNxt(pModCurr); } else { /* Note: if the module was successfully unloaded, it has updated the * pModCurr pointer to the next module. However, the unload process may * still have indirectly referenced the pointer list in a way that the * unloaded module is not aware of. So we restart the unload process * to make sure we do not fall into a trap (what we did ;)). The * performance toll is minimal. -- rgerhards, 2008-04-28 */ pModCurr = GetNxt(NULL); } } else { pModCurr = GetNxt(pModCurr); } } RETiRet; } /* find module with given name in global list */ static rsRetVal findModule(uchar *pModName, int iModNameLen, modInfo_t **pMod) { modInfo_t *pModInfo; uchar *pModNameCmp; DEFiRet; pModInfo = GetNxt(NULL); while (pModInfo != NULL) { if (!strncmp((char *)pModName, (char *)(pModNameCmp = modGetName(pModInfo)), iModNameLen) && (!*(pModNameCmp + iModNameLen) || !strcmp((char *)pModNameCmp + iModNameLen, ".so"))) { dbgprintf("Module '%s' found\n", pModName); break; } pModInfo = GetNxt(pModInfo); } *pMod = pModInfo; RETiRet; } /* load a module and initialize it, based on doModLoad() from conf.c * rgerhards, 2008-03-05 * varmojfekoj added support for dynamically loadable modules on 2007-08-13 * rgerhards, 2007-09-25: please note that the non-threadsafe function dlerror() is * called below. This is ok because modules are currently only loaded during * configuration file processing, which is executed on a single thread. Should we * change that design at any stage (what is unlikely), we need to find a * replacement. * rgerhards, 2011-04-27: * Parameter "bConfLoad" tells us if the load was triggered by a config handler, in * which case we need to tie the loaded module to the current config. If bConfLoad == 0, * the system loads a module for internal reasons, this is not directly tied to a * configuration. We could also think if it would be useful to add only certain types * of modules, but the current implementation at least looks simpler. * Note: pvals = NULL means legacy config system */ static rsRetVal ATTR_NONNULL(1) Load(uchar *const pModName, const sbool bConfLoad, struct nvlst *const lst) { size_t iPathLen, iModNameLen; int bHasExtension; void *pModHdlr; pModInit_t pModInit; modInfo_t *pModInfo; cfgmodules_etry_t *pNew = NULL; cfgmodules_etry_t *pLast = NULL; uchar *pModDirCurr, *pModDirNext; struct dlhandle_s *pHandle = NULL; uchar pathBuf[PATH_MAX + 1]; uchar *pPathBuf = pathBuf; size_t lenPathBuf = sizeof(pathBuf); rsRetVal localRet; cstr_t *load_err_msg = NULL; DEFiRet; assert(pModName != NULL); DBGPRINTF("Requested to load module '%s'\n", pModName); iModNameLen = strlen((char *)pModName); /* overhead for a full path is potentially 1 byte for a slash, * three bytes for ".so" and one byte for '\0'. */ #define PATHBUF_OVERHEAD 1 + iModNameLen + 3 + 1 pthread_mutex_lock(&mutObjGlobalOp); if (iModNameLen > 3 && !strcmp((char *)pModName + iModNameLen - 3, ".so")) { iModNameLen -= 3; bHasExtension = RSTRUE; } else bHasExtension = RSFALSE; CHKiRet(findModule(pModName, iModNameLen, &pModInfo)); if (pModInfo != NULL) { DBGPRINTF("Module '%s' already loaded\n", pModName); if (bConfLoad) { localRet = readyModForCnf(pModInfo, &pNew, &pLast); if (pModInfo->setModCnf != NULL && localRet == RS_RET_OK) { if (!strncmp((char *)pModName, "builtin:", sizeof("builtin:") - 1)) { if (pModInfo->bSetModCnfCalled) { LogError(0, RS_RET_DUP_PARAM, "parameters for built-in module %s already set - ignored\n", pModName); ABORT_FINALIZE(RS_RET_DUP_PARAM); } else { /* for built-in moules, we need to call setModConf, * because there is no way to set parameters at load * time for obvious reasons... */ if (lst != NULL) pModInfo->setModCnf(lst); pModInfo->bSetModCnfCalled = 1; } } else { /* regular modules need to be added to conf list (for * builtins, this happend during initial load). */ addModToCnfList(&pNew, pLast); } } } FINALIZE; } pModDirCurr = (uchar *)((pModDir == NULL) ? _PATH_MODDIR : (char *)pModDir); pModDirNext = NULL; pModHdlr = NULL; do { /* now build our load module name */ if (*pModName == '/' || *pModName == '.') { if (lenPathBuf < PATHBUF_OVERHEAD) { if (pPathBuf != pathBuf) /* already malloc()ed memory? */ free(pPathBuf); /* we always alloc enough memory for everything we potentiall need to add */ lenPathBuf = PATHBUF_OVERHEAD; CHKmalloc(pPathBuf = malloc(lenPathBuf)); } *pPathBuf = '\0'; /* we do not need to append the path - its already in the module name */ iPathLen = 0; } else { *pPathBuf = '\0'; iPathLen = strlen((char *)pModDirCurr); pModDirNext = (uchar *)strchr((char *)pModDirCurr, ':'); if (pModDirNext) iPathLen = (size_t)(pModDirNext - pModDirCurr); if (iPathLen == 0) { if (pModDirNext) { pModDirCurr = pModDirNext + 1; continue; } break; } else if (iPathLen > lenPathBuf - PATHBUF_OVERHEAD) { if (pPathBuf != pathBuf) /* already malloc()ed memory? */ free(pPathBuf); /* we always alloc enough memory for everything we potentiall need to add */ lenPathBuf = iPathLen + PATHBUF_OVERHEAD; CHKmalloc(pPathBuf = malloc(lenPathBuf)); } memcpy((char *)pPathBuf, (char *)pModDirCurr, iPathLen); if ((pPathBuf[iPathLen - 1] != '/')) { /* we have space, made sure in previous check */ pPathBuf[iPathLen++] = '/'; } pPathBuf[iPathLen] = '\0'; if (pModDirNext) pModDirCurr = pModDirNext + 1; } /* ... add actual name ... */ const size_t modNameLen = strlen((char *)pModName); memcpy(pPathBuf + iPathLen, pModName, modNameLen); iPathLen += modNameLen; pPathBuf[iPathLen] = '\0'; /* now see if we have an extension and, if not, append ".so" */ if (!bHasExtension) { /* we do not have an extension and so need to add ".so" * TODO: I guess this is highly importable, so we should change the * algo over time... -- rgerhards, 2008-03-05 */ memcpy(pPathBuf + iPathLen, ".so", sizeof(".so")); } /* complete load path constructed, so ... GO! */ dbgprintf("loading module '%s'\n", pPathBuf); /* see if we have this one already */ for (pHandle = pHandles; pHandle; pHandle = pHandle->next) { if (!strcmp((char *)pModName, (char *)pHandle->pszName)) { pModHdlr = pHandle->pModHdlr; break; } } /* not found, try to dynamically link it */ if (!pModHdlr) { pModHdlr = dlopen((char *)pPathBuf, RTLD_NOW); } if (pModHdlr == NULL) { char errmsg[4096]; snprintf(errmsg, sizeof(errmsg), "%strying to load module %s: %s", (load_err_msg == NULL) ? "" : " //////// ", pPathBuf, dlerror()); if (load_err_msg == NULL) { rsCStrConstructFromszStr(&load_err_msg, (uchar *)errmsg); } else { rsCStrAppendStr(load_err_msg, (uchar *)errmsg); } } } while (pModHdlr == NULL && *pModName != '/' && pModDirNext); if (load_err_msg != NULL) { cstrFinalize(load_err_msg); } if (!pModHdlr) { LogError(0, RS_RET_MODULE_LOAD_ERR_DLOPEN, "could not load module '%s', errors: %s", pModName, (load_err_msg == NULL) ? "NONE SEEN???" : (const char *)cstrGetSzStrNoNULL(load_err_msg)); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_DLOPEN); } if (!(pModInit = (pModInit_t)dlsym(pModHdlr, "modInit"))) { LogError(0, RS_RET_MODULE_LOAD_ERR_NO_INIT, "could not load module '%s', dlsym: %s\n", pPathBuf, dlerror()); dlclose(pModHdlr); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_NO_INIT); } if ((iRet = doModInit(pModInit, (uchar *)pModName, pModHdlr, &pModInfo)) != RS_RET_OK) { LogError(0, RS_RET_MODULE_LOAD_ERR_INIT_FAILED, "could not load module '%s', rsyslog error %d\n", pPathBuf, iRet); dlclose(pModHdlr); ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_INIT_FAILED); } if (bConfLoad) { readyModForCnf(pModInfo, &pNew, &pLast); if (pModInfo->setModCnf != NULL) { if (lst != NULL) { localRet = pModInfo->setModCnf(lst); if (localRet != RS_RET_OK) { LogError(0, localRet, "module '%s', failed processing config parameters", pPathBuf); ABORT_FINALIZE(localRet); } } pModInfo->bSetModCnfCalled = 1; } addModToCnfList(&pNew, pLast); } finalize_it: if (load_err_msg != NULL) { cstrDestruct(&load_err_msg); } if (pPathBuf != pathBuf) /* used malloc()ed memory? */ free(pPathBuf); if (iRet != RS_RET_OK) abortCnfUse(&pNew); free(pNew); /* is NULL again if properly consumed, else clean up */ pthread_mutex_unlock(&mutObjGlobalOp); RETiRet; } /* the v6+ way of loading modules: process a "module(...)" directive. * rgerhards, 2012-06-20 */ rsRetVal modulesProcessCnf(struct cnfobj *o) { struct cnfparamvals *pvals; uchar *cnfModName = NULL; int typeIdx; DEFiRet; pvals = nvlstGetParams(o->nvlst, &pblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("modulesProcessCnf params:\n"); cnfparamsPrint(&pblk, pvals); typeIdx = cnfparamGetIdx(&pblk, "load"); if (pvals[typeIdx].bUsed == 0) { LogError(0, RS_RET_CONF_RQRD_PARAM_MISSING, "module type missing"); ABORT_FINALIZE(RS_RET_CONF_RQRD_PARAM_MISSING); } cnfModName = (uchar *)es_str2cstr(pvals[typeIdx].val.d.estr, NULL); iRet = Load(cnfModName, 1, o->nvlst); finalize_it: free(cnfModName); cnfparamvalsDestruct(pvals, &pblk); RETiRet; } /* set the default module load directory. A NULL value may be provided, in * which case any previous value is deleted but no new one set. The caller-provided * string is duplicated. If it needs to be freed, that's the caller's duty. * rgerhards, 2008-03-07 */ static rsRetVal SetModDir(uchar *pszModDir) { DEFiRet; dbgprintf("setting default module load directory '%s'\n", pszModDir); if (pModDir != NULL) { free(pModDir); } pModDir = (uchar *)strdup((char *)pszModDir); RETiRet; } /* Reference-Counting object access: add 1 to the current reference count. Must be * called by anyone interested in using a module. -- rgerhards, 20080-03-10 */ static rsRetVal Use(const char *srcFile, modInfo_t *pThis) { DEFiRet; assert(pThis != NULL); pThis->uRefCnt++; dbgprintf("source file %s requested reference for module '%s', reference count now %u\n", srcFile, pThis->pszName, pThis->uRefCnt); #ifdef DEBUG modUsrAdd(pThis, srcFile); #endif RETiRet; } /* Reference-Counting object access: subract one from the current refcount. Must * by called by anyone who no longer needs a module. If count reaches 0, the * module is unloaded. -- rgerhards, 20080-03-10 */ static rsRetVal Release(const char *srcFile, modInfo_t **ppThis) { DEFiRet; modInfo_t *pThis; assert(ppThis != NULL); pThis = *ppThis; assert(pThis != NULL); if (pThis->uRefCnt == 0) { /* oops, we are already at 0? */ dbgprintf("internal error: module '%s' already has a refcount of 0 (released by %s)!\n", pThis->pszName, srcFile); } else { --pThis->uRefCnt; dbgprintf("file %s released module '%s', reference count now %u\n", srcFile, pThis->pszName, pThis->uRefCnt); #ifdef DEBUG modUsrDel(pThis, srcFile); modUsrPrint(pThis); #endif } if (pThis->uRefCnt == 0) { /* we have a zero refcount, so we must unload the module */ dbgprintf("module '%s' has zero reference count, unloading...\n", pThis->pszName); modUnlinkAndDestroy(&pThis); /* we must NOT do a *ppThis = NULL, because ppThis now points into freed memory! * If in doubt, see obj.c::ReleaseObj() for how we are called. */ } RETiRet; } /* exit our class * rgerhards, 2008-03-11 */ BEGINObjClassExit(module, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(module); /* release objects we no longer need */ free(pModDir); #ifdef DEBUG modUsrPrintAll(); /* debug aid - TODO: integrate with debug.c, at least the settings! */ #endif ENDObjClassExit(module) /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(module) CODESTARTobjQueryInterface(module); if (pIf->ifVersion != moduleCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->GetNxt = GetNxt; pIf->GetNxtCnfType = GetNxtCnfType; pIf->GetName = modGetName; pIf->GetStateName = modGetStateName; pIf->PrintList = modPrintList; pIf->FindWithCnfName = FindWithCnfName; pIf->UnloadAndDestructAll = modUnloadAndDestructAll; pIf->doModInit = doModInit; pIf->SetModDir = SetModDir; pIf->Load = Load; pIf->Use = Use; pIf->Release = Release; finalize_it: ENDobjQueryInterface(module) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-03-05 */ BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */ uchar *pModPath; /* use any module load path specified in the environment */ if ((pModPath = (uchar *)getenv("RSYSLOG_MODDIR")) != NULL) { SetModDir(pModPath); } /* now check if another module path was set via the command line (-M) * if so, that overrides the environment. Please note that we must use * a global setting here because the command line parser can NOT call * into the module object, because it is not initialized at that point. So * instead a global setting is changed and we pick it up as soon as we * initialize -- rgerhards, 2008-04-04 */ if (glblModPath != NULL) { SetModDir(glblModPath); } /* request objects we use */ ENDObjClassInit(module) /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/tcpsrv.c0000644000000000000000000000013215241075234015712 xustar0030 mtime=1787067036.611578407 30 atime=1787067036.758581159 30 ctime=1787067794.604728968 rsyslog-8.2608.0/runtime/tcpsrv.c0000664000175000017500000026305115241075234015365 0ustar00rgerrger/* tcpsrv.c * * Common code for plain TCP syslog based servers. This is currently being * utilized by imtcp and imgssapi. * * NOTE: this is *not* a generic TCP server, but one for syslog servers. For * generic stream servers, please use ./runtime/strmsrv.c! * * There are actually two classes within the tcpserver code: one is * the tcpsrv itself, the other one is its sessions. This is a helper * class to tcpsrv. * * The common code here calls upon specific functionality by using * callbacks. The specialised input modules need to set the proper * callbacks before the code is run. The tcpsrv then calls back * into the specific input modules at the appropriate time. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2007-12-21 by RGerhards (extracted from syslogd.c[which was * licensed under BSD at the time of the rsyslog fork]) * * Copyright 2007-2025 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_FCNTL_H #include #endif #if !defined(ENABLE_IMTCP_EPOLL) #include #endif #include "rsyslog.h" #include "dirty.h" #include "cfsysline.h" #include "module-template.h" #include "net.h" #include "srUtils.h" #include "conf.h" #include "tcpsrv.h" #include "obj.h" #include "glbl.h" #include "netstrms.h" #include "netstrm.h" #include "errmsg.h" #include "ruleset.h" #include "ratelimit.h" #include "unicode-helper.h" #include "nsd_ptcp.h" PRAGMA_IGNORE_Wswitch_enum MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* defines */ #define TCPSESS_MAX_DEFAULT 200 /* default for nbr of tcp sessions if no number is given */ #define TCPLSTN_MAX_DEFAULT 20 /* default for nbr of listeners */ /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(conf); DEFobjCurrIf(glbl); DEFobjCurrIf(ruleset); DEFobjCurrIf(tcps_sess); DEFobjCurrIf(net); DEFobjCurrIf(netstrms); DEFobjCurrIf(netstrm); DEFobjCurrIf(prop); DEFobjCurrIf(statsobj); DEFobjCurrIf(regexp); #define NSPOLL_MAX_EVENTS_PER_WAIT 128 static void enqueueWork(tcpsrv_io_descr_t *const pioDescr); /* We check which event notification mechanism we have and use the best available one. * We switch back from library-specific drivers, because event notification always works * at the socket layer and is conceptually the same. As such, we can reduce code, code * complexity, and a bit of runtime overhead by using a compile time selection and * abstraction of the event notification mechanism. * rgerhards, 2025-01-16 */ #if defined(ENABLE_IMTCP_EPOLL) static rsRetVal ATTR_NONNULL() eventNotify_init(tcpsrv_t *const pThis) { DEFiRet; #if defined(ENABLE_IMTCP_EPOLL) && defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1) DBGPRINTF("tcpsrv uses epoll_create1()\n"); pThis->evtdata.epoll.efd = epoll_create1(EPOLL_CLOEXEC); if (pThis->evtdata.epoll.efd < 0 && errno == ENOSYS) #endif { DBGPRINTF("tcpsrv uses epoll_create()\n"); pThis->evtdata.epoll.efd = epoll_create(100); /* size is ignored in newer kernels, but 100 is not bad... */ } if (pThis->evtdata.epoll.efd < 0) { DBGPRINTF("epoll_create1() could not create fd\n"); ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() eventNotify_exit(tcpsrv_t *const pThis) { DEFiRet; close(pThis->evtdata.epoll.efd); RETiRet; } /* Modify socket set */ static rsRetVal ATTR_NONNULL() epoll_Ctl(tcpsrv_t *const pThis, tcpsrv_io_descr_t *const pioDescr, const int isLstn, const int op) { DEFiRet; const int id = pioDescr->id; const int sock = pioDescr->sock; assert(sock >= 0); if (op == EPOLL_CTL_ADD) { dbgprintf("adding epoll entry %d, socket %d\n", id, sock); pioDescr->event.events = EPOLLIN | EPOLLET | EPOLLONESHOT; pioDescr->event.data.ptr = (void *)pioDescr; if (epoll_ctl(pThis->evtdata.epoll.efd, EPOLL_CTL_ADD, sock, &pioDescr->event) < 0) { LogError(errno, RS_RET_ERR_EPOLL_CTL, "epoll_ctl failed on fd %d, isLstn %d\n", sock, isLstn); } } else if (op == EPOLL_CTL_DEL) { dbgprintf("removing epoll entry %d, socket %d\n", id, sock); if (epoll_ctl(pThis->evtdata.epoll.efd, EPOLL_CTL_DEL, sock, NULL) < 0) { if (errno == EBADF || errno == ENOENT) { /* already gone-away, everything is well */ DBGPRINTF("epoll_ctl: fd %d already removed, isLstn %d", sock, isLstn); } else { LogError(errno, RS_RET_ERR_EPOLL_CTL, "epoll_ctl failed on fd %d, isLstn %d\n", sock, isLstn); ABORT_FINALIZE(RS_RET_ERR_EPOLL_CTL); } } } else { dbgprintf("program error: invalid NSDPOLL_mode %d - ignoring request\n", op); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: DBGPRINTF("Done processing epoll entry %d, iRet %d\n", id, iRet); RETiRet; } /* Wait for io to become ready. After the successful call, idRdy contains the * id set by the caller for that i/o event, ppUsr is a pointer to a location * where the user pointer shall be stored. * numEntries contains the maximum number of entries on entry and the actual * number of entries actually read on exit. * rgerhards, 2009-11-18 */ static rsRetVal ATTR_NONNULL() epoll_Wait(tcpsrv_t *const pThis, const int timeout, int *const numEntries, tcpsrv_io_descr_t *pWorkset[]) { struct epoll_event event[NSPOLL_MAX_EVENTS_PER_WAIT]; int nfds; int i; DEFiRet; assert(pWorkset != NULL); if (*numEntries > NSPOLL_MAX_EVENTS_PER_WAIT) *numEntries = NSPOLL_MAX_EVENTS_PER_WAIT; DBGPRINTF("doing epoll_wait for max %d events\n", *numEntries); nfds = epoll_wait(pThis->evtdata.epoll.efd, event, *numEntries, timeout); if (nfds == -1) { if (errno == EINTR) { ABORT_FINALIZE(RS_RET_EINTR); } else { DBGPRINTF("epoll_wait() returned with error code %d\n", errno); ABORT_FINALIZE(RS_RET_ERR_EPOLL); } } else if (nfds == 0) { ABORT_FINALIZE(RS_RET_TIMEOUT); } /* we got valid events, so tell the caller... */ DBGPRINTF("epoll_wait returned %d entries\n", nfds); for (i = 0; i < nfds; ++i) { pWorkset[i] = event[i].data.ptr; /* default is no error, on error we terminate, so we need only to set in error case! */ if (event[i].events & EPOLLERR) { ATOMIC_STORE_32BIT(&pWorkset[i]->isInError, &pWorkset[i]->mut_isInError, 1); } } *numEntries = nfds; finalize_it: RETiRet; } #else /* no epoll, let's use poll() ------------------------------------------------------------ */ #define FDSET_INCREMENT 1024 /* increment for struct pollfds array allocation */ static rsRetVal ATTR_NONNULL() eventNotify_init(tcpsrv_t *const pThis ATTR_UNUSED) { return RS_RET_OK; } static rsRetVal ATTR_NONNULL() eventNotify_exit(tcpsrv_t *const pThis) { DEFiRet; free(pThis->evtdata.poll.fds); RETiRet; } /* Add a socket to the poll set */ static rsRetVal ATTR_NONNULL() poll_Add(tcpsrv_t *const pThis, netstrm_t *const pStrm, const nsdsel_waitOp_t waitOp) { DEFiRet; int sock; CHKiRet(netstrm.GetSock(pStrm, &sock)); if (pThis->evtdata.poll.currfds == pThis->evtdata.poll.maxfds) { struct pollfd *newfds; CHKmalloc(newfds = realloc(pThis->evtdata.poll.fds, sizeof(struct pollfd) * (pThis->evtdata.poll.maxfds + FDSET_INCREMENT))); pThis->evtdata.poll.maxfds += FDSET_INCREMENT; pThis->evtdata.poll.fds = newfds; } switch (waitOp) { case NSDSEL_RD: pThis->evtdata.poll.fds[pThis->evtdata.poll.currfds].events = POLLIN; break; case NSDSEL_WR: pThis->evtdata.poll.fds[pThis->evtdata.poll.currfds].events = POLLOUT; break; case NSDSEL_RDWR: pThis->evtdata.poll.fds[pThis->evtdata.poll.currfds].events = POLLIN | POLLOUT; break; default: break; } pThis->evtdata.poll.fds[pThis->evtdata.poll.currfds].fd = sock; ++pThis->evtdata.poll.currfds; finalize_it: RETiRet; } /* perform the poll() piNumReady returns how many descriptors are ready for IO */ static rsRetVal ATTR_NONNULL() poll_Poll(tcpsrv_t *const pThis, int *const piNumReady) { DEFiRet; assert(piNumReady != NULL); /* Output debug first*/ if (Debug) { dbgprintf("calling poll, active fds (%d): ", pThis->evtdata.poll.currfds); for (uint32_t i = 0; i <= pThis->evtdata.poll.currfds; ++i) dbgprintf("%d ", pThis->evtdata.poll.fds[i].fd); dbgprintf("\n"); } assert(pThis->evtdata.poll.currfds >= 1); /* now do the select */ *piNumReady = poll(pThis->evtdata.poll.fds, pThis->evtdata.poll.currfds, -1); if (*piNumReady < 0) { if (errno == EINTR) { DBGPRINTF("tcpsrv received EINTR\n"); } else { LogMsg(errno, RS_RET_POLL_ERR, LOG_WARNING, "ndssel_ptcp: poll system call failed, may cause further troubles"); } *piNumReady = 0; } RETiRet; } /* check if a socket is ready for IO */ static rsRetVal ATTR_NONNULL() poll_IsReady(tcpsrv_t *const pThis, netstrm_t *const pStrm, const nsdsel_waitOp_t waitOp, int *const pbIsReady) { DEFiRet; int sock; CHKiRet(netstrm.GetSock(pStrm, &sock)); uint32_t idx; for (idx = 0; idx < pThis->evtdata.poll.currfds; ++idx) { if (pThis->evtdata.poll.fds[idx].fd == sock) break; } if (idx >= pThis->evtdata.poll.currfds) { LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_ERR, "ndssel_ptcp: could not find socket %d which should be present", sock); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } const short revent = pThis->evtdata.poll.fds[idx].revents; if (revent & POLLNVAL) { DBGPRINTF("ndssel_ptcp: revent & POLLNVAL is TRUE, we had a race, ignoring, revent = %d", revent); *pbIsReady = 0; } switch (waitOp) { case NSDSEL_RD: *pbIsReady = revent & POLLIN; break; case NSDSEL_WR: *pbIsReady = revent & POLLOUT; break; case NSDSEL_RDWR: *pbIsReady = revent & (POLLIN | POLLOUT); break; default: break; } finalize_it: RETiRet; } #endif /* event notification compile time selection */ static void freeLstnParams(tcpLstnParams_t *cnf_params) { if (cnf_params == NULL) { return; } if (cnf_params->pInputName != NULL) { prop.Destruct(&cnf_params->pInputName); } free((void *)cnf_params->pszInputName); free((void *)cnf_params->pszPort); free((void *)cnf_params->pszAddr); free((void *)cnf_params->pszLstnPortFileName); free((void *)cnf_params->pszNetworkNamespace); free((void *)cnf_params->pszStrmDrvrName); free((void *)cnf_params->pszStartRegex); free((void *)cnf_params->pszRatelimitName); free(cnf_params); } /* add new listener port to listener port list * rgerhards, 2009-05-21 */ static rsRetVal ATTR_NONNULL() addNewLstnPort(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params) { tcpLstnPortList_t *pEntry; uchar statname[64]; DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); /* create entry */ CHKmalloc(pEntry = (tcpLstnPortList_t *)calloc(1, sizeof(tcpLstnPortList_t))); pEntry->cnf_params = cnf_params; INIT_ATOMIC_HELPER_MUT64(pEntry->mutCompressionZstdWindow); u_cstr_copy(pEntry->cnf_params->dfltTZ, pThis->dfltTZ, sizeof(pEntry->cnf_params->dfltTZ)); pEntry->cnf_params->bSPFramingFix = pThis->bSPFramingFix; pEntry->cnf_params->bPreserveCase = pThis->bPreserveCase; pEntry->pSrv = pThis; pEntry->compressionMode = pThis->compressionMode; pEntry->compressionDriver = pThis->compressionDriver; pEntry->compressionMaxExpansionRatio = pThis->compressionMaxExpansionRatio; pEntry->compressionMaxDecompressedBytesPerReceive = pThis->compressionMaxDecompressedBytesPerReceive; pEntry->compressionMaxTotalZstdWindowBytes = pThis->compressionMaxTotalZstdWindowBytes; #ifdef FEATURE_REGEXP if (cnf_params->pszStartRegex != NULL) { if (glbl.GetMaxLine(runConf) > (INT_MAX - 1) / 2) { LogError(0, RS_RET_ERR, "imtcp: framing.delimiter.regex requires maxMessageSize <= %d to avoid session buffer overflow", (INT_MAX - 1) / 2); ABORT_FINALIZE(RS_RET_ERR); } const int errcode = regexp.regcomp(&pEntry->start_preg, (char *)cnf_params->pszStartRegex, REG_EXTENDED); if (errcode != 0) { char errbuff[512]; regexp.regerror(errcode, &pEntry->start_preg, errbuff, sizeof(errbuff)); LogError(0, RS_RET_ERR, "imtcp: error in framing.delimiter.regex expansion: %s", errbuff); ABORT_FINALIZE(RS_RET_ERR); } pEntry->bHasStartRegex = 1; } #else if (cnf_params->pszStartRegex != NULL) { LogError(0, RS_RET_ERR, "imtcp: framing.delimiter.regex set, but regexp support not available"); ABORT_FINALIZE(RS_RET_ERR); } #endif /* support statistics gathering */ if (pEntry->cnf_params->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfig(&(pEntry->ratelimiter), runConf, (char *)pEntry->cnf_params->pszRatelimitName, "tcpsrv", NULL)); } else { CHKiRet(ratelimitNew(&(pEntry->ratelimiter), "tcpsrv", NULL)); ratelimitSetLinuxLike(pEntry->ratelimiter, pThis->ratelimitInterval, pThis->ratelimitBurst); } ratelimitSetThreadSafe(pEntry->ratelimiter); CHKiRet(statsobj.Construct(&(pEntry->stats))); snprintf((char *)statname, sizeof(statname), "%s(%s)", cnf_params->pszInputName, cnf_params->pszPort); statname[sizeof(statname) - 1] = '\0'; /* just to be on the save side... */ CHKiRet(statsobj.SetName(pEntry->stats, statname)); CHKiRet(statsobj.SetOrigin(pEntry->stats, pThis->pszOrigin)); STATSCOUNTER_INIT(pEntry->ctrSubmit, pEntry->mutCtrSubmit); STATSCOUNTER_INIT(pEntry->ctrBytesRcvd, pEntry->mutCtrBytesRcvd); STATSCOUNTER_INIT(pEntry->ctrBytesDecompressed, pEntry->mutCtrBytesDecompressed); STATSCOUNTER_INIT(pEntry->ctrDecompressErr, pEntry->mutCtrDecompressErr); CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrSubmit))); CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("bytes.received"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrBytesRcvd))); CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("bytes.decompressed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrBytesDecompressed))); CHKiRet(statsobj.AddCounter(pEntry->stats, UCHAR_CONSTANT("decompression.errors"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pEntry->ctrDecompressErr))); CHKiRet(statsobj.ConstructFinalize(pEntry->stats)); /* all OK - add to list */ pEntry->pNext = pThis->pLstnPorts; pThis->pLstnPorts = pEntry; finalize_it: if (iRet != RS_RET_OK) { if (pEntry != NULL) { if (pEntry->ratelimiter != NULL) { ratelimitDestruct(pEntry->ratelimiter); } if (pEntry->stats != NULL) { statsobj.Destruct(&pEntry->stats); } #ifdef FEATURE_REGEXP if (pEntry->bHasStartRegex) { regexp.regfree(&pEntry->start_preg); } #endif DESTROY_ATOMIC_HELPER_MUT64(pEntry->mutCompressionZstdWindow); free(pEntry); } } RETiRet; } /* configure TCP listener settings. * Note: pszPort is handed over to us - the caller MUST NOT free it! * rgerhards, 2008-03-20 */ static rsRetVal ATTR_NONNULL() configureTCPListen(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params) { assert(cnf_params->pszPort != NULL); int i; sbool added = 0; DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); /* extract port */ const uchar *pPort = cnf_params->pszPort; i = 0; while (isdigit((int)*pPort)) { i = i * 10 + *pPort++ - '0'; } if (i >= 0 && i <= 65535) { CHKiRet(addNewLstnPort(pThis, cnf_params)); added = 1; } else { LogError(0, NO_ERRCODE, "Invalid TCP listen port %s - ignored.\n", cnf_params->pszPort); } finalize_it: if (iRet != RS_RET_OK || !added) { freeLstnParams(cnf_params); } RETiRet; } /* Initialize the session table * returns 0 if OK, somewhat else otherwise */ static rsRetVal ATTR_NONNULL() TCPSessTblInit(tcpsrv_t *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pThis->pSessions == NULL); DBGPRINTF("Allocating buffer for %d TCP sessions.\n", pThis->iSessMax); if ((pThis->pSessions = (tcps_sess_t **)calloc(pThis->iSessMax, sizeof(tcps_sess_t *))) == NULL) { DBGPRINTF("Error: TCPSessInit() could not alloc memory for TCP session table.\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } finalize_it: RETiRet; } static tcps_sess_t tcpsess_slot_reserved; #if !defined(ENABLE_IMTCP_EPOLL) static inline tcps_sess_t *ATTR_NONNULL() TCPSessTblLoad(tcpsrv_t *const pThis, const int i) { tcps_sess_t *const pSess = (tcps_sess_t *)ATOMIC_LOAD_PTR((void **)&pThis->pSessions[i], &pThis->mut_sessions); return pSess == &tcpsess_slot_reserved ? NULL : pSess; } #endif static inline void ATTR_NONNULL(1) TCPSessTblStore(tcpsrv_t *const pThis, const int i, tcps_sess_t *const pSess) { ATOMIC_STORE_PTR((void **)&pThis->pSessions[i], &pThis->mut_sessions, pSess); } /* Atomically reserve a free spot in the session table. If the table is full, * -1 is returned, else the index of the reserved entry (0 or higher). Readers * treat the reservation marker like an empty slot until initialization is done. */ static int ATTR_NONNULL() TCPSessTblClaimFreeSpot(tcpsrv_t *const pThis) { register int i; ISOBJ_TYPE_assert(pThis, tcpsrv); for (i = 0; i < pThis->iSessMax; ++i) { if (ATOMIC_CAS_PTR((void **)&pThis->pSessions[i], NULL, &tcpsess_slot_reserved, &pThis->mut_sessions)) break; } return ((i < pThis->iSessMax) ? i : -1); } #if !defined(ENABLE_IMTCP_EPOLL) /* Get the next session index. Free session tables entries are * skipped. This function is provided the index of the last * session entry, or -1 if no previous entry was obtained. It * returns the index of the next session or -1, if there is no * further entry in the table. Please note that the initial call * might as well return -1, if there is no session at all in the * session table. */ static int ATTR_NONNULL() TCPSessGetNxtSess(tcpsrv_t *pThis, const int iCurr) { register int i; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pThis->pSessions != NULL); for (i = iCurr + 1; i < pThis->iSessMax; ++i) { if (TCPSessTblLoad(pThis, i) != NULL) break; } return ((i < pThis->iSessMax) ? i : -1); } #endif /* De-Initialize TCP listener sockets. * This function deinitializes everything, including freeing the * session table. No TCP listen receive operations are permitted * unless the subsystem is reinitialized. * rgerhards, 2007-06-21 */ static void ATTR_NONNULL() deinit_tcp_listener(tcpsrv_t *const pThis) { int i; tcpLstnPortList_t *pEntry; tcpLstnPortList_t *pDel; ISOBJ_TYPE_assert(pThis, tcpsrv); if (pThis->pSessions != NULL) { #if !defined(ENABLE_IMTCP_EPOLL) /* close all TCP connections! */ i = TCPSessGetNxtSess(pThis, -1); while (i != -1) { tcps_sess_t *pSess = TCPSessTblLoad(pThis, i); tcps_sess.Destruct(&pSess); TCPSessTblStore(pThis, i, NULL); /* now get next... */ i = TCPSessGetNxtSess(pThis, i); } #endif /* we are done with the session table - so get rid of it... */ free(pThis->pSessions); pThis->pSessions = NULL; /* just to make sure... */ } /* free list of tcp listen ports */ pEntry = pThis->pLstnPorts; while (pEntry != NULL) { #ifdef FEATURE_REGEXP if (pEntry->bHasStartRegex) { regexp.regfree(&pEntry->start_preg); } #endif freeLstnParams(pEntry->cnf_params); if (pEntry->ratelimiter != NULL) { ratelimitDestruct(pEntry->ratelimiter); } if (pEntry->stats != NULL) { statsobj.Destruct(&(pEntry->stats)); } DESTROY_ATOMIC_HELPER_MUT64(pEntry->mutCompressionZstdWindow); pDel = pEntry; pEntry = pEntry->pNext; free(pDel); } /* finally close our listen streams */ for (i = 0; i < pThis->iLstnCurr; ++i) { netstrm.Destruct(pThis->ppLstn + i); } } /* add a listen socket to our listen socket array. This is a callback * invoked from the netstrm class. -- rgerhards, 2008-04-23 */ static rsRetVal ATTR_NONNULL() addTcpLstn(void *pUsr, netstrm_t *const pLstn) { tcpLstnPortList_t *pPortList = (tcpLstnPortList_t *)pUsr; tcpsrv_t *pThis = pPortList->pSrv; DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); ISOBJ_TYPE_assert(pLstn, netstrm); if (pThis->iLstnCurr >= pThis->iLstnMax) ABORT_FINALIZE(RS_RET_MAX_LSTN_REACHED); pThis->ppLstn[pThis->iLstnCurr] = pLstn; pThis->ppLstnPort[pThis->iLstnCurr] = pPortList; ++pThis->iLstnCurr; finalize_it: RETiRet; } /* Initialize TCP listener socket for a single port * Note: at this point, TLS vs. non-TLS does not matter; TLS params are * set on connect! * rgerhards, 2009-05-21 */ static rsRetVal ATTR_NONNULL() initTCPListener(tcpsrv_t *pThis, tcpLstnPortList_t *pPortEntry) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pPortEntry != NULL); CHKiRet(netstrm.LstnInit(pThis->pNS, (void *)pPortEntry, addTcpLstn, pThis->iSessMax, pPortEntry->cnf_params)); finalize_it: RETiRet; } /* Initialize TCP sockets (for listener) and listens on them */ static rsRetVal ATTR_NONNULL() create_tcp_socket(tcpsrv_t *const pThis) { DEFiRet; rsRetVal localRet; tcpLstnPortList_t *pEntry; ISOBJ_TYPE_assert(pThis, tcpsrv); /* init all configured ports */ pEntry = pThis->pLstnPorts; while (pEntry != NULL) { localRet = initTCPListener(pThis, pEntry); if (localRet != RS_RET_OK) { char *ns = pEntry->cnf_params->pszNetworkNamespace; LogError( 0, localRet, "Could not create tcp listener, ignoring port " "%s bind-address %s%s%s.", (pEntry->cnf_params->pszPort == NULL) ? "**UNSPECIFIED**" : (const char *)pEntry->cnf_params->pszPort, (pEntry->cnf_params->pszAddr == NULL) ? "**UNSPECIFIED**" : (const char *)pEntry->cnf_params->pszAddr, (ns == NULL) ? "" : " namespace ", (ns == NULL) ? "" : ns); } pEntry = pEntry->pNext; } /* OK, we had success. Now it is also time to * initialize our connections */ if (TCPSessTblInit(pThis) != 0) { /* OK, we are in some trouble - we could not initialize the * session table, so we can not continue. We need to free all * we have assigned so far, because we can not really use it... */ LogError(0, RS_RET_ERR, "Could not initialize TCP session table, suspending TCP " "message reception."); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: RETiRet; } /* Accept new TCP connection; make entry in session table. If there * is no more space left in the connection table, the new TCP * connection is immediately dropped. * ppSess has a pointer to the newly created session, if it succeeds. * If it does not succeed, no session is created and ppSess is * undefined. If the user has provided an OnSessAccept Callback, * this one is executed immediately after creation of the * session object, so that it can do its own initialization. * rgerhards, 2008-03-02 */ static ATTR_NONNULL() rsRetVal SessAccept(tcpsrv_t *const pThis, tcpLstnPortList_t *const pLstnInfo, tcps_sess_t **ppSess, int *const piSessIdx, netstrm_t *pStrm, char *const connInfo) { DEFiRet; tcps_sess_t *pSess = NULL; netstrm_t *pNewStrm = NULL; const tcpLstnParams_t *const cnf_params = pLstnInfo->cnf_params; int iSess = -1; struct sockaddr_storage *addr; uchar *fromHostFQDN = NULL; prop_t *fromHostIP = NULL; prop_t *fromHostPort = NULL; const char *fromHostNameStr = "(hostname unknown)"; const char *fromHostIPStr = "(IP unknown)"; const char *fromHostPortStr = "(port unknown)"; ISOBJ_TYPE_assert(pThis, tcpsrv); assert(pLstnInfo != NULL); assert(piSessIdx != NULL); CHKiRet(netstrm.AcceptConnReq(pStrm, &pNewStrm, connInfo)); /* Add to session list */ iSess = TCPSessTblClaimFreeSpot(pThis); if (iSess == -1) { errno = 0; LogError(0, RS_RET_MAX_SESS_REACHED, "too many tcp sessions - dropping incoming request"); ABORT_FINALIZE(RS_RET_MAX_SESS_REACHED); } if (pThis->bUseKeepAlive) { CHKiRet(netstrm.SetKeepAliveProbes(pNewStrm, pThis->iKeepAliveProbes)); CHKiRet(netstrm.SetKeepAliveTime(pNewStrm, pThis->iKeepAliveTime)); CHKiRet(netstrm.SetKeepAliveIntvl(pNewStrm, pThis->iKeepAliveIntvl)); CHKiRet(netstrm.EnableKeepAlive(pNewStrm)); } /* we found a free spot and can construct our session object */ if (pThis->gnutlsPriorityString != NULL) { CHKiRet(netstrm.SetGnutlsPriorityString(pNewStrm, pThis->gnutlsPriorityString)); } CHKiRet(tcps_sess.Construct(&pSess)); CHKiRet(tcps_sess.SetTcpsrv(pSess, pThis)); CHKiRet(tcps_sess.SetLstnInfo(pSess, pLstnInfo)); if (pThis->OnMsgReceive != NULL) CHKiRet(tcps_sess.SetOnMsgReceive(pSess, pThis->OnMsgReceive)); /* get the host name */ CHKiRet(netstrm.GetRemoteHName(pNewStrm, &fromHostFQDN)); fromHostNameStr = szStrOrDefault(fromHostFQDN, "(hostname unknown)"); if (!cnf_params->bPreserveCase) { /* preserve_case = off */ uchar *p; for (p = fromHostFQDN; *p; p++) { if (isupper((int)*p)) { *p = tolower((int)*p); } } } CHKiRet(netstrm.GetRemoteIP(pNewStrm, &fromHostIP)); fromHostIPStr = propGetSzStrOrDefault(fromHostIP, "(IP unknown)"); CHKiRet(netstrm.GetRemAddr(pNewStrm, &addr)); char portbuf[8]; uint16_t port; if (addr->ss_family == AF_INET) port = ntohs(((struct sockaddr_in *)addr)->sin_port); else if (addr->ss_family == AF_INET6) port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); else port = 0; snprintf(portbuf, sizeof(portbuf), "%u", port); CHKiRet(prop.Construct(&fromHostPort)); CHKiRet(prop.SetString(fromHostPort, (uchar *)portbuf, strlen(portbuf))); CHKiRet(prop.ConstructFinalize(fromHostPort)); fromHostPortStr = propGetSzStrOrDefault(fromHostPort, "(port unknown)"); /* Here we check if a host is permitted to send us messages. If it isn't, we do not further * process the message but log a warning (if we are configured to do this). * rgerhards, 2005-09-26 */ if (!pThis->pIsPermittedHost((struct sockaddr *)addr, (char *)fromHostFQDN, pThis->pUsr, pSess->pUsr)) { DBGPRINTF("%s is not an allowed sender\n", fromHostFQDN); if (glbl.GetOptionDisallowWarning(runConf)) { errno = 0; LogError(0, RS_RET_HOST_NOT_PERMITTED, "connection request from disallowed " "sender %s (%s:%s) discarded", fromHostNameStr, fromHostIPStr, fromHostPortStr); } ABORT_FINALIZE(RS_RET_HOST_NOT_PERMITTED); } /* OK, we have an allowed sender, so let's continue, what * means we can finally fill in the session object. */ CHKiRet(tcps_sess.SetHost(pSess, fromHostFQDN)); fromHostFQDN = NULL; /* we handed this string over */ fromHostNameStr = propGetSzStrOrDefault(pSess->fromHost, "(hostname unknown)"); CHKiRet(tcps_sess.SetHostIP(pSess, fromHostIP)); fromHostIPStr = propGetSzStrOrDefault(pSess->fromHostIP, "(IP unknown)"); fromHostIP = NULL; CHKiRet(tcps_sess.SetHostPort(pSess, fromHostPort)); fromHostPortStr = propGetSzStrOrDefault(pSess->fromHostPort, "(port unknown)"); fromHostPort = NULL; CHKiRet(tcps_sess.SetStrm(pSess, pNewStrm)); pNewStrm = NULL; /* prevent it from being freed in error handler, now done in tcps_sess! */ CHKiRet(tcps_sess.SetMsgIdx(pSess, 0)); CHKiRet(tcps_sess.ConstructFinalize(pSess)); /* check if we need to call our callback */ if (pThis->pOnSessAccept != NULL) { CHKiRet(pThis->pOnSessAccept(pThis, pSess, connInfo)); } *ppSess = pSess; TCPSessTblStore(pThis, iSess, pSess); *piSessIdx = iSess; pSess = NULL; /* this is now also handed over */ if (pThis->bEmitMsgOnOpen) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "imtcp: connection established with host: %s (%s:%s)", fromHostNameStr, fromHostIPStr, fromHostPortStr); } finalize_it: if (iRet != RS_RET_OK) { if (iSess >= 0) TCPSessTblStore(pThis, iSess, NULL); if (iRet != RS_RET_HOST_NOT_PERMITTED && pThis->bEmitMsgOnOpen) { LogError(0, NO_ERRCODE, "imtcp: connection could not be " "established with host: %s (%s:%s)", fromHostNameStr, fromHostIPStr, fromHostPortStr); } if (pSess != NULL) tcps_sess.Destruct(&pSess); if (pNewStrm != NULL) netstrm.Destruct(&pNewStrm); if (fromHostIP != NULL) prop.Destruct(&fromHostIP); if (fromHostPort != NULL) prop.Destruct(&fromHostPort); free(fromHostFQDN); } RETiRet; } /** * \brief Close a TCP session and release associated resources. * * Closes the session referenced by \p pioDescr, runs the module-specific * close hook, and updates the event notification set. On EPOLL builds the * I/O descriptor is heap-allocated and is freed here after best-effort * removal from the epoll set. * * No locking is performed; callers are responsible for any required * mutex handling before/after this call. * * \param[in] pThis Server instance. * \param[in] pioDescr I/O descriptor for the session to close * (pioDescr->ptrType == NSD_PTR_TYPE_SESS). * * \pre \p pioDescr and its \c pSess are valid. * \post The session object is destroyed. On EPOLL builds, \p pioDescr is * freed; on non-EPOLL builds, the session table entry is cleared. * \post Callers must not access \p pioDescr or \c pSess after return. * * \note epoll removal is performed on a best-effort basis; teardown proceeds * regardless of epoll_ctl outcome. * * \retval RS_RET_OK */ static ATTR_NONNULL() rsRetVal closeSess(tcpsrv_t *const pThis, tcpsrv_io_descr_t *const pioDescr) { DEFiRet; assert(pioDescr->ptrType == NSD_PTR_TYPE_SESS); tcps_sess_t *pSess = pioDescr->ptr.pSess; #if defined(ENABLE_IMTCP_EPOLL) /* note: we do not check the result of epoll_Ctl because we cannot do * anything against a failure BUT we need to do the cleanup in any case. */ epoll_Ctl(pThis, pioDescr, 0, EPOLL_CTL_DEL); #endif assert(pThis->pOnRegularClose != NULL); pThis->pOnRegularClose(pSess); tcps_sess.Destruct(&pSess); TCPSessTblStore(pThis, pioDescr->id, NULL); #if defined(ENABLE_IMTCP_EPOLL) /* in epoll mode, pioDescr is dynamically allocated */ DESTROY_ATOMIC_HELPER_MUT(pioDescr->mut_isInError); free(pioDescr); #endif RETiRet; } /** * @brief Re-arm EPOLLONESHOT for this session’s descriptor. * * Uses EPOLL_CTL_MOD to (re)register the descriptor for the next I/O event, * selecting EPOLLIN or EPOLLOUT from `pioDescr->ioDirection` and always * enabling `EPOLLET | EPOLLONESHOT`. The epoll user data is set to the * given `pioDescr` so the same descriptor is delivered on the next event. * * @pre `pioDescr` is valid; `pioDescr->sock` and * `pioDescr->pSrv->evtdata.epoll.efd` refer to open fds. * @pre `pioDescr->ioDirection` ∈ { `NSDSEL_RD`, `NSDSEL_WR` }. * @pre Called by the thread that owns the descriptor (no concurrent epoll_ctl). * * @post On success, the descriptor is armed for the next edge-triggered event. * On failure, the previous epoll registration remains unchanged. * * @param[in] pioDescr I/O descriptor to (re)arm. * @retval RS_RET_OK on success. * @retval RS_RET_ERR_EPOLL_CTL on epoll_ctl failure (error is logged). * * @note Compiled only when ENABLE_IMTCP_EPOLL is defined. */ #if defined(ENABLE_IMTCP_EPOLL) static ATTR_NONNULL() rsRetVal rearmIoEvent(tcpsrv_io_descr_t *const pioDescr) { DEFiRet; /* Debug-only invariants */ assert(pioDescr->ioDirection == NSDSEL_RD || pioDescr->ioDirection == NSDSEL_WR); assert(pioDescr->pSrv != NULL && pioDescr->pSrv->evtdata.epoll.efd >= 0); assert(pioDescr->sock >= 0); const uint32_t waitIOEvent = (pioDescr->ioDirection == NSDSEL_WR) ? EPOLLOUT : EPOLLIN; struct epoll_event event = {.events = waitIOEvent | EPOLLET | EPOLLONESHOT, .data = {.ptr = pioDescr}}; if (epoll_ctl(pioDescr->pSrv->evtdata.epoll.efd, EPOLL_CTL_MOD, pioDescr->sock, &event) < 0) { LogError(errno, RS_RET_ERR_EPOLL_CTL, "epoll_ctl failed re-arm socket %d", pioDescr->sock); ABORT_FINALIZE(RS_RET_ERR_EPOLL_CTL); } finalize_it: RETiRet; } #endif /** * @brief Receive and dispatch data for a TCP session with starvation control and EPOLL re-arm. * * Flow: * - Read via pThis->pRcvData(), forward to tcps_sess.DataRcvd(). * - Starvation: after `starvationMaxReads`, enqueue `pioDescr` (handoff) and return (no re-arm). * - Would-block (RS_RET_RETRY): re-arm EPOLLONESHOT and return. * - Close/error: exit the loop and close the session after unlocking. * * Locking: * - If workQueue.numWrkr > 1, this function locks `pSess->mut` on entry and always unlocks * before return (including close/error and starvation/handoff paths). * - **Re-arm timing:** on the would-block path, `rearmIoEvent(pioDescr)` is called *before* * unlocking `pSess->mut` to keep ownership until the EPOLL_CTL_MOD completes. * - `closeSess()` is called *after* unlocking. * * Starvation accounting: * - `read_calls` counts only successful reads (RS_RET_OK), so the cap reflects actual data * consumption, not retries/closures/errors. * * @pre `pioDescr`, `pioDescr->ptr.pSess`, and `pioDescr->pSrv` are valid; I/O is non-blocking. * @post On close paths, both `pioDescr` and `pSess` are invalid on return. */ static rsRetVal ATTR_NONNULL(1) doReceive(tcpsrv_io_descr_t *const pioDescr, tcpsrvWrkrData_t *const wrkrData ATTR_UNUSED) { char buf[128 * 1024]; /* reception buffer - may hold a partial or multiple messages */ ssize_t iRcvd; rsRetVal localRet; DEFiRet; int oserr = 0; unsigned read_calls = 0; tcps_sess_t *const pSess = pioDescr->ptr.pSess; tcpsrv_t *const pThis = pioDescr->pSrv; const unsigned maxReads = pThis->starvationMaxReads; ISOBJ_TYPE_assert(pThis, tcpsrv); const char *const peerIP = propGetSzStrOrDefault(pSess->fromHostIP, "(IP unknown)"); const char *const peerPort = propGetSzStrOrDefault(pSess->fromHostPort, "(port unknown)"); DBGPRINTF("netstream %p with new data from remote peer %s:%s\n", (pSess)->pStrm, peerIP, peerPort); if (pThis->workQueue.numWrkr > 1) { pthread_mutex_lock(&pSess->mut); } /* explicit state machine */ enum RecvState { RS_READING, RS_STARVATION, RS_DONE_REARM, RS_DONECLOSE, RS_DONE_HANDOFF }; enum RecvState state = RS_READING; #if defined(ENABLE_IMTCP_EPOLL) /* If we had EPOLLERR, log additional info; processing continues. */ if (ATOMIC_LOAD_32BIT(&pioDescr->isInError, &pioDescr->mut_isInError)) { ATOMIC_STORE_32BIT(&pioDescr->isInError, &pioDescr->mut_isInError, 0); int error = 0; socklen_t len = sizeof(error); const int sock = pioDescr->sock; if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { LogError(error, RS_RET_IO_ERROR, "epoll subsystem signaled EPOLLERR for stream %p, peer %s:%s", (pSess)->pStrm, peerIP, peerPort); } } #endif /* Sanity (debug builds): I/O direction must be valid. */ assert(pioDescr->ioDirection == NSDSEL_RD || pioDescr->ioDirection == NSDSEL_WR); /* Loop while in non-terminal states (positive check for readability). */ while (state == RS_READING || state == RS_STARVATION) { switch (state) { case RS_READING: /* maxReads==0 is intentional and documented: it disables starvation protection. */ while (state == RS_READING && (maxReads == 0 || read_calls < maxReads)) { iRet = pThis->pRcvData(pSess, buf, sizeof(buf), &iRcvd, &oserr, &pioDescr->ioDirection); switch (iRet) { case RS_RET_CLOSED: if (pThis->bEmitMsgOnClose) { errno = 0; LogError(0, RS_RET_PEER_CLOSED_CONN, "Netstream session %p closed by remote peer %s:%s.", (pSess)->pStrm, peerIP, peerPort); } state = RS_DONECLOSE; break; case RS_RET_RETRY: #if defined(ENABLE_IMTCP_EPOLL) if (pThis->workQueue.numWrkr > 1 && read_calls == 0) { STATSCOUNTER_ADD(wrkrData->ctrEmptyRead, wrkrData->mutCtrEmptyRead, 1); } #endif state = RS_DONE_REARM; /* would block → exit and re-arm */ break; case RS_RET_OK: /* Successful read counts toward starvation cap */ if (pThis->workQueue.numWrkr > 1) { ++read_calls; } localRet = tcps_sess.DataRcvd(pSess, buf, iRcvd); if (localRet != RS_RET_OK && localRet != RS_RET_QUEUE_FULL) { LogError(oserr, localRet, "Tearing down TCP Session from %s:%s", peerIP, peerPort); state = RS_DONECLOSE; } break; default: LogError(oserr, iRet, "netstream session %p from %s:%s will be closed due to error", pSess->pStrm, peerIP, peerPort); state = RS_DONECLOSE; break; } } if (state == RS_READING) { state = RS_STARVATION; /* hit the read cap */ } break; case RS_STARVATION: dbgprintf("starvation avoidance triggered, ctr=%u, maxReads=%u\n", read_calls, maxReads); assert(pThis->workQueue.numWrkr > 1); #if defined(ENABLE_IMTCP_EPOLL) STATSCOUNTER_INC(wrkrData->ctrStarvation, wrkrData->mutCtrStarvation); #endif enqueueWork(pioDescr); state = RS_DONE_HANDOFF; /* queued behind existing work → exit, no re-arm */ break; default: assert(0 && "unhandled RecvState inside doReceive loop"); state = RS_DONECLOSE; break; } } /* Postcondition: we must have transitioned to a terminal state. */ assert(state == RS_DONE_REARM || state == RS_DONECLOSE || state == RS_DONE_HANDOFF); #if defined(ENABLE_IMTCP_EPOLL) if (pThis->workQueue.numWrkr > 1) { STATSCOUNTER_ADD(wrkrData->ctrRead, wrkrData->mutCtrRead, read_calls); } if (state == RS_DONE_REARM) { rearmIoEvent(pioDescr); /* re-arm while still holding pSess->mut */ } #endif if (pThis->workQueue.numWrkr > 1) { pthread_mutex_unlock(&pSess->mut); } if (state == RS_DONECLOSE) { closeSess(pThis, pioDescr); /* also frees pioDescr in epoll builds */ } RETiRet; } /* This function processes a single incoming connection */ static rsRetVal ATTR_NONNULL(1) doSingleAccept(tcpsrv_io_descr_t *const pioDescr) { tcps_sess_t *pNewSess = NULL; tcpsrv_io_descr_t *pDescrNew = NULL; const int idx = pioDescr->id; int iSess = -1; tcpsrv_t *const pThis = pioDescr->pSrv; char connInfo[TCPSRV_CONNINFO_SIZE] = "\0"; DEFiRet; DBGPRINTF("New connect on NSD %p.\n", pThis->ppLstn[idx]); iRet = SessAccept(pThis, pThis->ppLstnPort[idx], &pNewSess, &iSess, pThis->ppLstn[idx], connInfo); if (iRet == RS_RET_NO_MORE_DATA) { goto no_more_data; } if (iRet == RS_RET_OK) { #if defined(ENABLE_IMTCP_EPOLL) /* pDescrNew is only dyn allocated in epoll mode! */ CHKmalloc(pDescrNew = (tcpsrv_io_descr_t *)calloc(1, sizeof(tcpsrv_io_descr_t))); pDescrNew->pSrv = pThis; pDescrNew->id = iSess; pDescrNew->isInError = 0; INIT_ATOMIC_HELPER_MUT(pDescrNew->mut_isInError); pDescrNew->ptrType = NSD_PTR_TYPE_SESS; pDescrNew->ioDirection = NSDSEL_RD; CHKiRet(netstrm.GetSock(pNewSess->pStrm, &pDescrNew->sock)); pDescrNew->ptr.pSess = pNewSess; CHKiRet(epoll_Ctl(pThis, pDescrNew, 0, EPOLL_CTL_ADD)); #endif DBGPRINTF("New session created with NSD %p.\n", pNewSess); } else { DBGPRINTF("tcpsrv: error %d during accept\n", iRet); } #if defined(ENABLE_IMTCP_EPOLL) finalize_it: #endif if (iRet != RS_RET_OK) { const tcpLstnParams_t *cnf_params = pThis->ppLstnPort[idx]->cnf_params; LogError(0, iRet, "tcpsrv listener (inputname: '%s') failed " "to process incoming connection %s with error %d", (cnf_params->pszInputName == NULL) ? (uchar *)"*UNSET*" : cnf_params->pszInputName, connInfo, iRet); if (pDescrNew != NULL) { DESTROY_ATOMIC_HELPER_MUT(pDescrNew->mut_isInError); free(pDescrNew); } srSleep(0, 20000); /* Sleep 20ms */ } no_more_data: RETiRet; } /* This function processes all pending accepts on this fd */ static rsRetVal ATTR_NONNULL(1) doAccept(tcpsrv_io_descr_t *const pioDescr, tcpsrvWrkrData_t *const wrkrData ATTR_UNUSED) { DEFiRet; int bRun = 1; #if defined(ENABLE_IMTCP_EPOLL) int nAccept = 0; #endif while (bRun) { iRet = doSingleAccept(pioDescr); if (iRet != RS_RET_OK) { bRun = 0; } #if defined(ENABLE_IMTCP_EPOLL) ++nAccept; #endif } #if defined(ENABLE_IMTCP_EPOLL) if (pioDescr->pSrv->workQueue.numWrkr > 1) { STATSCOUNTER_ADD(wrkrData->ctrAccept, wrkrData->mutCtrAccept, nAccept); } rearmIoEvent(pioDescr); /* listeners must ALWAYS be re-armed */ #endif RETiRet; } /* process a single workset item */ static rsRetVal ATTR_NONNULL(1) processWorksetItem(tcpsrv_io_descr_t *const pioDescr, tcpsrvWrkrData_t *const wrkrData ATTR_UNUSED) { DEFiRet; DBGPRINTF("tcpsrv: processing item %d, socket %d\n", pioDescr->id, pioDescr->sock); if (pioDescr->ptrType == NSD_PTR_TYPE_LSTN) { iRet = doAccept(pioDescr, wrkrData); } else { iRet = doReceive(pioDescr, wrkrData); } RETiRet; } /* work queue functions */ static void ATTR_NONNULL() * wrkr(void *arg); /* forward-def of wrkr */ /** * @brief Start the worker thread pool for tcpsrv (best-effort, single-path cleanup). * * @details * This function allocates worker arrays, initializes synchronization primitives, * and spawns `workQueue.numWrkr` threads running `wrkr()`. * * ### Why all cleanup happens in `finalize_it` * This routine runs during initialization. If we fail here, the process is very * likely unable to run successfully anyway. To keep the code robust and * maintainable as more CHKiRet checks are added over time, we centralize **all** * rollback into the single `finalize_it` block: * * - guarantees a single, well-tested teardown path * - avoids fragile “partial cleanupsâ€� spread across multiple branches * - tolerates partial initialization (some threads created, some not; mutex/cond * initialized or not), destroying only what actually succeeded * - ignores secondary errors from pthread_*destroy/cancel/join — this is an * extreme error path and best-effort cleanup is sufficient * * ### Thread cancellation model * If any threads were created before failure, we call `pthread_cancel()` and then * `pthread_join()` on each. Worker threads block in `pthread_cond_wait()` which is * a POSIX cancellation point, so cancellation is reliable here. * * @param pThis Server instance (must have `workQueue.numWrkr > 1`). * @retval RS_RET_OK on success; error code on failure (resources cleaned up). */ static rsRetVal ATTR_NONNULL() startWrkrPool(tcpsrv_t *const pThis) { DEFiRet; workQueue_t *const queue = &pThis->workQueue; int mut_initialized = 0; int cond_initialized = 0; unsigned created = 0; assert(queue->numWrkr > 1); /* Initialize queue state first. */ queue->head = NULL; queue->tail = NULL; /* Allocate arrays. */ CHKmalloc(queue->wrkr_tids = calloc(queue->numWrkr, sizeof(pthread_t))); CHKmalloc(queue->wrkr_data = calloc(queue->numWrkr, sizeof(tcpsrvWrkrData_t))); /* Init sync primitives. */ if (pthread_mutex_init(&queue->mut, NULL) != 0) { ABORT_FINALIZE(RS_RET_ERR); } mut_initialized = 1; if (pthread_cond_init(&queue->workRdy, NULL) != 0) { ABORT_FINALIZE(RS_RET_ERR); } cond_initialized = 1; /* Spawn workers. */ pThis->currWrkrs = 0; for (unsigned i = 0; i < queue->numWrkr; ++i) { if (pthread_create(&queue->wrkr_tids[i], &default_thread_attr, wrkr, pThis) != 0) { iRet = RS_RET_ERR; break; } ++created; } finalize_it: if (iRet != RS_RET_OK) { /* Best-effort rollback in strict reverse order of construction. */ /* If any threads were created, cancel and join them. */ if (created > 0) { for (unsigned i = 0; i < created; ++i) { (void)pthread_cancel(queue->wrkr_tids[i]); /* cond_wait is a cancellation point */ } for (unsigned i = 0; i < created; ++i) { (void)pthread_join(queue->wrkr_tids[i], NULL); } } /* Destroy sync primitives IFF they were successfully initialized. */ if (cond_initialized) { (void)pthread_cond_destroy(&queue->workRdy); } if (mut_initialized) { (void)pthread_mutex_destroy(&queue->mut); } /* Free arrays (they might be NULL if allocation failed early). */ free(queue->wrkr_tids); free(queue->wrkr_data); queue->wrkr_tids = NULL; queue->wrkr_data = NULL; } RETiRet; } /** * @brief Safely stops the worker thread pool. * * This function can be called multiple times or in partial-init states. * It checks preconditions and only performs cleanup operations that are safe. */ static void ATTR_NONNULL() stopWrkrPool(tcpsrv_t *const pThis) { workQueue_t *const queue = &pThis->workQueue; /* Guard against being called when pool was never started or already stopped. */ if (queue->numWrkr <= 1 || queue->wrkr_tids == NULL) { return; } /* Signal all workers to wake and exit. */ pthread_mutex_lock(&queue->mut); pthread_cond_broadcast(&queue->workRdy); pthread_mutex_unlock(&queue->mut); /* Wait for all worker threads to finish. */ for (unsigned i = 0; i < queue->numWrkr; i++) { pthread_join(queue->wrkr_tids[i], NULL); } /* Free allocated resources. */ free(queue->wrkr_tids); free(queue->wrkr_data); /* Destroy synchronization primitives. */ pthread_mutex_destroy(&queue->mut); pthread_cond_destroy(&queue->workRdy); queue->wrkr_tids = NULL; queue->wrkr_data = NULL; } static tcpsrv_io_descr_t ATTR_NONNULL() * dequeueWork(tcpsrv_t *pSrv) { workQueue_t *const queue = &pSrv->workQueue; tcpsrv_io_descr_t *pioDescr; pthread_mutex_lock(&queue->mut); while ((queue->head == NULL) && !glbl.GetGlobalInputTermState()) { pthread_cond_wait(&queue->workRdy, &queue->mut); } if (queue->head == NULL) { pioDescr = NULL; goto finalize_it; } pioDescr = queue->head; queue->head = pioDescr->next; if (queue->head == NULL) { queue->tail = NULL; } finalize_it: pthread_mutex_unlock(&queue->mut); return pioDescr; } /** * @brief Queue a ready I/O descriptor for worker processing (best-effort). * * Appends @p pioDescr to the work FIFO and signals one worker. Performs its * own locking; callers must not hold workQueue::mut. No epoll re-arm is done here. * * Intent: * - File-local helper for starvation/handoff paths. * - Best-effort, side-effect only; no return value. In debug builds you may assert * on obvious misuse, but callers do not recover here. * * Threading & Ownership: * - Thread-safe; may be called from the event loop or a worker. * - Stores a non-owning pointer; @p pioDescr must remain valid until a worker * dequeues it. * * Preconditions: * - @p pioDescr != NULL and @p pioDescr->pSrv != NULL. * - Multi-thread mode active (workQueue.numWrkr > 1). * * Postconditions: * - @p pioDescr is placed at the queue tail and one worker is signaled. */ static void ATTR_NONNULL() enqueueWork(tcpsrv_io_descr_t *const pioDescr) { workQueue_t *const queue = &pioDescr->pSrv->workQueue; pthread_mutex_lock(&queue->mut); pioDescr->next = NULL; if (queue->tail == NULL) { assert(queue->head == NULL); queue->head = pioDescr; } else { queue->tail->next = pioDescr; } queue->tail = pioDescr; pthread_cond_signal(&queue->workRdy); pthread_mutex_unlock(&queue->mut); } /* Worker thread function */ static void ATTR_NONNULL() * wrkr(void *arg) { tcpsrv_t *const pThis = (tcpsrv_t *)arg; workQueue_t *const queue = &pThis->workQueue; tcpsrv_io_descr_t *pioDescr; pthread_mutex_lock(&queue->mut); const int wrkrIdx = pThis->currWrkrs++; pthread_mutex_unlock(&queue->mut); int deinit_stats = 0; rsRetVal localRet; tcpsrvWrkrData_t *const wrkrData = &(queue->wrkr_data[wrkrIdx]); uchar shortThrdName[16]; snprintf((char *)shortThrdName, sizeof(shortThrdName), "w%d/%s", wrkrIdx, (pThis->pszInputName == NULL) ? (uchar *)"tcpsrv" : pThis->pszInputName); uchar thrdName[32]; snprintf((char *)thrdName, sizeof(thrdName), "w%d/%s", wrkrIdx, (pThis->pszInputName == NULL) ? (uchar *)"tcpsrv" : pThis->pszInputName); dbgSetThrdName(thrdName); /* set thread name - we ignore if it fails, has no harsh consequences... */ #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) if (prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", thrdName); } #elif defined(HAVE_PTHREAD_SETNAME_NP) #if defined(__APPLE__) /* The macOS variant takes only the thread name and returns an int. */ int r = pthread_setname_np((char *)shortThrdName); if (r != 0) { DBGPRINTF("pthread_setname_np failed, not setting thread name for '%s'\n", shortThrdName); } #elif defined(__FreeBSD__) /* FreeBSD variant has a void return type. */ pthread_setname_np(pthread_self(), (char *)shortThrdName); #elif defined(__NetBSD__) /* NetBSD variant takes a format string and returns an int. */ int r = pthread_setname_np(pthread_self(), "%s", (void *)shortThrdName); if (r != 0) { DBGPRINTF("pthread_setname_np failed, not setting thread name for '%s'\n", shortThrdName); } #else /* The glibc variant takes thread ID and name, and returns an int. */ int r = pthread_setname_np(pthread_self(), (char *)shortThrdName); if (r != 0) { DBGPRINTF("pthread_setname_np failed, not setting thread name for '%s'\n", shortThrdName); } #endif #endif if ((localRet = statsobj.Construct(&wrkrData->stats)) == RS_RET_OK) { statsobj.SetName(wrkrData->stats, thrdName); statsobj.SetOrigin(wrkrData->stats, (uchar *)"imtcp"); STATSCOUNTER_INIT(wrkrData->ctrRuns, wrkrData->mutCtrRuns); statsobj.AddCounter(wrkrData->stats, UCHAR_CONSTANT("runs"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(wrkrData->ctrRuns)); STATSCOUNTER_INIT(wrkrData->ctrRead, wrkrData->mutCtrRead); statsobj.AddCounter(wrkrData->stats, UCHAR_CONSTANT("read"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(wrkrData->ctrRead)); STATSCOUNTER_INIT(wrkrData->ctrEmptyRead, wrkrData->mutCtrEmptyRead); statsobj.AddCounter(wrkrData->stats, UCHAR_CONSTANT("emptyread"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(wrkrData->ctrEmptyRead)); STATSCOUNTER_INIT(wrkrData->ctrStarvation, wrkrData->mutCtrStarvation); statsobj.AddCounter(wrkrData->stats, UCHAR_CONSTANT("starvation_protect"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(wrkrData->ctrStarvation)); STATSCOUNTER_INIT(wrkrData->ctrAccept, wrkrData->mutCtrAccept); statsobj.AddCounter(wrkrData->stats, UCHAR_CONSTANT("accept"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(wrkrData->ctrAccept)); statsobj.ConstructFinalize(wrkrData->stats); deinit_stats = 1; } else { LogMsg(errno, localRet, LOG_WARNING, "tcpsrv worker %s could not create statistics " "counter. Thus, this worker does not provide them. Processing " "is otherwise unaffected", thrdName); } /**** main loop ****/ while (1) { pioDescr = dequeueWork(pThis); if (pioDescr == NULL) { break; } /* note: we ignore the result as we cannot do anything against errors in any * case. Also, errors are reported inside processWorksetItem(). */ processWorksetItem(pioDescr, wrkrData); STATSCOUNTER_ADD(wrkrData->ctrRuns, wrkrData->mutCtrRuns, 1); } /**** de-init ****/ if (deinit_stats) { statsobj.Destruct(&wrkrData->stats); } return NULL; } /* Process a workset, that is handle io. We become activated * from either poll or epoll handler. We split the workload * out to a pool of threads, but try to avoid context switches * as much as possible. */ static rsRetVal ATTR_NONNULL() processWorkset(const int numEntries, tcpsrv_io_descr_t *const pioDescr[]) { int i; unsigned numWrkr; DEFiRet; assert(numEntries > 0); if (numEntries <= 0 || pioDescr[0] == NULL || pioDescr[0]->pSrv == NULL) return RS_RET_INTERNAL_ERROR; numWrkr = pioDescr[0]->pSrv->workQueue.numWrkr; /* pSrv is always the same! */ DBGPRINTF("tcpsrv: ready to process %d event entries\n", numEntries); for (i = 0; i < numEntries; ++i) { if (numWrkr == 1) { /* we process all on this thread, no need for context switch */ processWorksetItem(pioDescr[i], NULL); } else { enqueueWork(pioDescr[i]); } } RETiRet; } #if !defined(ENABLE_IMTCP_EPOLL) /* This function is called to gather input. */ PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wempty_body static ATTR_NONNULL() rsRetVal RunPoll(tcpsrv_t *const pThis) { DEFiRet; int nfds; int i; int iWorkset; int iTCPSess; int bIsReady; tcps_sess_t *pSess; tcpsrv_io_descr_t *pWorkset[NSPOLL_MAX_EVENTS_PER_WAIT]; tcpsrv_io_descr_t workset[NSPOLL_MAX_EVENTS_PER_WAIT]; const int sizeWorkset = sizeof(workset) / sizeof(tcpsrv_io_descr_t); rsRetVal localRet; ISOBJ_TYPE_assert(pThis, tcpsrv); DBGPRINTF("tcpsrv uses poll() [ex-select()] interface\n"); /* init the workset pointers, they will remain fixed */ for (i = 0; i < sizeWorkset; ++i) { pWorkset[i] = workset + i; } /* we init the fd set with "constant" data and only later on add the sessions. * Note: further optimization would be to keep the sessions as long as possible, * but this is currently not considered worth the effort as non-epoll platforms * become really rare. 2025-02-25 RGerhards */ pThis->evtdata.poll.maxfds = FDSET_INCREMENT; /* we need to alloc one pollfd more, because the list must be 0-terminated! */ CHKmalloc(pThis->evtdata.poll.fds = calloc(FDSET_INCREMENT + 1, sizeof(struct pollfd))); /* Add the TCP listen sockets to the list of read descriptors. */ for (i = 0; i < pThis->iLstnCurr; ++i) { CHKiRet(poll_Add(pThis, pThis->ppLstn[i], NSDSEL_RD)); } while (1) { pThis->evtdata.poll.currfds = pThis->iLstnCurr; /* listeners are "fixed" */ /* do the sessions */ iTCPSess = TCPSessGetNxtSess(pThis, -1); while (iTCPSess != -1) { pSess = TCPSessTblLoad(pThis, iTCPSess); if (pSess == NULL) { iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); continue; } /* TODO: access to pNsd is NOT really CLEAN, use method... */ CHKiRet(poll_Add(pThis, pSess->pStrm, NSDSEL_RD)); DBGPRINTF("tcpsrv process session %d:\n", iTCPSess); /* now get next... */ iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } /* zero-out the last fd - space for it is always reserved! */ assert(pThis->evtdata.poll.maxfds != pThis->evtdata.poll.currfds); pThis->evtdata.poll.fds[pThis->evtdata.poll.currfds].fd = 0; /* wait for io to become ready */ CHKiRet(poll_Poll(pThis, &nfds)); if (glbl.GetGlobalInputTermState() == 1) break; /* terminate input! */ iWorkset = 0; for (i = 0; i < pThis->iLstnCurr && nfds; ++i) { if (glbl.GetGlobalInputTermState() == 1) ABORT_FINALIZE(RS_RET_FORCE_TERM); CHKiRet(poll_IsReady(pThis, pThis->ppLstn[i], NSDSEL_RD, &bIsReady)); if (bIsReady) { workset[iWorkset].pSrv = pThis; workset[iWorkset].ptrType = NSD_PTR_TYPE_LSTN; workset[iWorkset].id = i; workset[iWorkset].isInError = 0; workset[iWorkset].ioDirection = NSDSEL_RD; /* non-epoll: ensure sane default */ CHKiRet(netstrm.GetSock(pThis->ppLstn[i], &(workset[iWorkset].sock))); workset[iWorkset].ptr.ppLstn = pThis->ppLstn; /* this is a flag to indicate listen sock */ ++iWorkset; if (iWorkset >= (int)sizeWorkset) { processWorkset(iWorkset, pWorkset); iWorkset = 0; } --nfds; /* indicate we have processed one */ } } /* now check the sessions */ iTCPSess = TCPSessGetNxtSess(pThis, -1); while (nfds && iTCPSess != -1) { if (glbl.GetGlobalInputTermState() == 1) ABORT_FINALIZE(RS_RET_FORCE_TERM); pSess = TCPSessTblLoad(pThis, iTCPSess); if (pSess == NULL) { iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); continue; } localRet = poll_IsReady(pThis, pSess->pStrm, NSDSEL_RD, &bIsReady); if (bIsReady || localRet != RS_RET_OK) { workset[iWorkset].pSrv = pThis; workset[iWorkset].ptrType = NSD_PTR_TYPE_SESS; workset[iWorkset].id = iTCPSess; workset[iWorkset].isInError = 0; workset[iWorkset].ioDirection = NSDSEL_RD; /* non-epoll: ensure sane default */ CHKiRet(netstrm.GetSock(pSess->pStrm, &(workset[iWorkset].sock))); workset[iWorkset].ptr.pSess = pSess; ++iWorkset; if (iWorkset >= (int)sizeWorkset) { processWorkset(iWorkset, pWorkset); iWorkset = 0; } if (bIsReady) --nfds; /* indicate we have processed one */ } iTCPSess = TCPSessGetNxtSess(pThis, iTCPSess); } if (iWorkset > 0) { processWorkset(iWorkset, pWorkset); } /* we need to copy back close descriptors */ finalize_it: /* this is a very special case - this time only we do not exit the function, * because that would not help us either. So we simply retry it. Let's see * if that actually is a better idea. Exiting the loop wasn't we always * crashed, which made sense (the rest of the engine was not prepared for * that) -- rgerhards, 2008-05-19 */ continue; /* keep compiler happy, block end after label is non-standard */ } RETiRet; } PRAGMA_DIAGNOSTIC_POP #endif /* conditional exclude when epoll is available */ #if defined(ENABLE_IMTCP_EPOLL) static rsRetVal ATTR_NONNULL() RunEpoll(tcpsrv_t *const pThis) { DEFiRet; int i; tcpsrv_io_descr_t *workset[NSPOLL_MAX_EVENTS_PER_WAIT]; int numEntries; rsRetVal localRet; DBGPRINTF("tcpsrv uses epoll() interface\n"); /* Add the TCP listen sockets to the list of sockets to monitor */ for (i = 0; i < pThis->iLstnCurr; ++i) { DBGPRINTF("Trying to add listener %d, pUsr=%p\n", i, pThis->ppLstn); CHKmalloc(pThis->ppioDescrPtr[i] = (tcpsrv_io_descr_t *)calloc(1, sizeof(tcpsrv_io_descr_t))); pThis->ppioDescrPtr[i]->pSrv = pThis; pThis->ppioDescrPtr[i]->id = i; pThis->ppioDescrPtr[i]->isInError = 0; pThis->ppioDescrPtr[i]->ioDirection = NSDSEL_RD; INIT_ATOMIC_HELPER_MUT(pThis->ppioDescrPtr[i]->mut_isInError); CHKiRet(netstrm.GetSock(pThis->ppLstn[i], &(pThis->ppioDescrPtr[i]->sock))); pThis->ppioDescrPtr[i]->ptrType = NSD_PTR_TYPE_LSTN; pThis->ppioDescrPtr[i]->ptr.ppLstn = pThis->ppLstn; CHKiRet(epoll_Ctl(pThis, pThis->ppioDescrPtr[i], 1, EPOLL_CTL_ADD)); DBGPRINTF("Added listener %d\n", i); } while (glbl.GetGlobalInputTermState() == 0) { numEntries = sizeof(workset) / sizeof(tcpsrv_io_descr_t *); localRet = epoll_Wait(pThis, -1, &numEntries, workset); if (glbl.GetGlobalInputTermState() == 1) { break; /* terminate input! */ } /* check if we need to ignore the i/o ready state. We do this if we got an invalid * return state. Validly, this can happen for RS_RET_EINTR, for other cases it may * not be the right thing, but what is the right thing is really hard at this point... * Note: numEntries can be validly 0 in some rare cases (eg spurios wakeup). */ if (localRet != RS_RET_OK || numEntries == 0) { continue; } processWorkset(numEntries, workset); } /* Workers can still process listener events queued just before shutdown. * Join them before freeing listener descriptors so rearmIoEvent() cannot * observe descriptor storage that RunEpoll() is tearing down. */ stopWrkrPool(pThis); /* remove the tcp listen sockets from the epoll set */ for (i = 0; i < pThis->iLstnCurr; ++i) { CHKiRet(epoll_Ctl(pThis, pThis->ppioDescrPtr[i], 1, EPOLL_CTL_DEL)); DESTROY_ATOMIC_HELPER_MUT(pThis->ppioDescrPtr[i]->mut_isInError); free(pThis->ppioDescrPtr[i]); } finalize_it: RETiRet; } #endif /* This function is called to gather input. It tries doing that via the epoll() * interface. If the driver does not support that, it falls back to calling its * select() equivalent. * rgerhards, 2009-11-18 */ static rsRetVal ATTR_NONNULL() Run(tcpsrv_t *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (pThis->iLstnCurr == 0) { dbgprintf("tcpsrv: no listeners at all (probably init error), terminating\n"); FINALIZE; } #if !defined(ENABLE_IMTCP_EPOLL) /* if we do not have epoll(), we need to run single-threaded */ pThis->workQueue.numWrkr = 1; #endif eventNotify_init(pThis); if (pThis->workQueue.numWrkr > 1) { iRet = startWrkrPool(pThis); if (iRet != RS_RET_OK) { LogError(errno, iRet, "tcpsrv could not start worker pool " "- now running single threaded '%s')", (pThis->pszInputName == NULL) ? (uchar *)"*UNSET*" : pThis->pszInputName); pThis->workQueue.numWrkr = 1; } } #if defined(ENABLE_IMTCP_EPOLL) iRet = RunEpoll(pThis); #else /* fall back to select */ iRet = RunPoll(pThis); #endif stopWrkrPool(pThis); eventNotify_exit(pThis); finalize_it: RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(tcpsrv) /* be sure to specify the object type also in END macro! */ INIT_ATOMIC_HELPER_MUT(pThis->mut_sessions); pThis->iSessMax = TCPSESS_MAX_DEFAULT; pThis->iLstnMax = TCPLSTN_MAX_DEFAULT; pThis->addtlFrameDelim = TCPSRV_NO_ADDTL_DELIMITER; pThis->maxFrameSize = 200000; pThis->bDisableLFDelim = 0; pThis->discardTruncatedMsg = 0; pThis->OnMsgReceive = NULL; pThis->dfltTZ[0] = '\0'; pThis->bSPFramingFix = 0; pThis->ratelimitInterval = 0; pThis->ratelimitBurst = 10000; pThis->bUseFlowControl = 1; pThis->pszDrvrName = NULL; pThis->bPreserveCase = 1; /* preserve case in fromhost; default to true. */ pThis->iSynBacklog = 0; /* default: unset */ pThis->DrvrTlsVerifyDepth = 0; pThis->DrvrTlsRevocationCheck = 0; pThis->compressionMode = TCPSRV_COMPRESS_NEVER; pThis->compressionDriver = TCPSRV_COMPRESS_DRIVER_ZLIB; pThis->compressionMaxExpansionRatio = TCPSRV_COMPRESS_MAX_EXPANSION_RATIO_DEFAULT; pThis->compressionMaxDecompressedBytesPerReceive = TCPSRV_COMPRESS_MAX_DECOMPRESSED_BYTES_PER_RECEIVE_DEFAULT; pThis->compressionMaxTotalZstdWindowBytes = TCPSRV_COMPRESS_MAX_TOTAL_ZSTD_WINDOW_BYTES_DEFAULT; ENDobjConstruct(tcpsrv) /* ConstructionFinalizer */ static rsRetVal ATTR_NONNULL() tcpsrvConstructFinalize(tcpsrv_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); /* prepare network stream subsystem */ CHKiRet(netstrms.Construct(&pThis->pNS)); CHKiRet(netstrms.SetSynBacklog(pThis->pNS, pThis->iSynBacklog)); if (pThis->pszDrvrName != NULL) CHKiRet(netstrms.SetDrvrName(pThis->pNS, pThis->pszDrvrName)); CHKiRet(netstrms.SetDrvrMode(pThis->pNS, pThis->iDrvrMode)); CHKiRet(netstrms.SetDrvrCheckExtendedKeyUsage(pThis->pNS, pThis->DrvrChkExtendedKeyUsage)); CHKiRet(netstrms.SetDrvrPrioritizeSAN(pThis->pNS, pThis->DrvrPrioritizeSan)); CHKiRet(netstrms.SetDrvrTlsVerifyDepth(pThis->pNS, pThis->DrvrTlsVerifyDepth)); CHKiRet(netstrms.SetDrvrTlsRevocationCheck(pThis->pNS, pThis->DrvrTlsRevocationCheck)); if (pThis->pszDrvrAuthMode != NULL) CHKiRet(netstrms.SetDrvrAuthMode(pThis->pNS, pThis->pszDrvrAuthMode)); /* Call SetDrvrPermitExpiredCerts required * when param is NULL default handling for ExpiredCerts is set! */ CHKiRet(netstrms.SetDrvrPermitExpiredCerts(pThis->pNS, pThis->pszDrvrPermitExpiredCerts)); CHKiRet(netstrms.SetDrvrTlsCAFile(pThis->pNS, pThis->pszDrvrCAFile)); CHKiRet(netstrms.SetDrvrTlsCRLFile(pThis->pNS, pThis->pszDrvrCRLFile)); CHKiRet(netstrms.SetDrvrTlsKeyFile(pThis->pNS, pThis->pszDrvrKeyFile)); CHKiRet(netstrms.SetDrvrTlsCertFile(pThis->pNS, pThis->pszDrvrCertFile)); if (pThis->pPermPeers != NULL) CHKiRet(netstrms.SetDrvrPermPeers(pThis->pNS, pThis->pPermPeers)); if (pThis->gnutlsPriorityString != NULL) CHKiRet(netstrms.SetDrvrGnutlsPriorityString(pThis->pNS, pThis->gnutlsPriorityString)); CHKiRet(netstrms.ConstructFinalize(pThis->pNS)); /* set up listeners */ CHKmalloc(pThis->ppLstn = calloc(pThis->iLstnMax, sizeof(netstrm_t *))); CHKmalloc(pThis->ppLstnPort = calloc(pThis->iLstnMax, sizeof(tcpLstnPortList_t *))); CHKmalloc(pThis->ppioDescrPtr = calloc(pThis->iLstnMax, sizeof(tcpsrv_io_descr_t *))); iRet = pThis->OpenLstnSocks(pThis); finalize_it: if (iRet != RS_RET_OK) { if (pThis->pNS != NULL) netstrms.Destruct(&pThis->pNS); free(pThis->ppLstn); pThis->ppLstn = NULL; free(pThis->ppLstnPort); pThis->ppLstnPort = NULL; free(pThis->ppioDescrPtr); pThis->ppioDescrPtr = NULL; LogError(0, iRet, "tcpsrv could not create listener (inputname: '%s')", (pThis->pszInputName == NULL) ? (uchar *)"*UNSET*" : pThis->pszInputName); } RETiRet; } /* destructor for the tcpsrv object */ BEGINobjDestruct(tcpsrv) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(tcpsrv); if (pThis->OnDestruct != NULL) pThis->OnDestruct(pThis->pUsr); stopWrkrPool(pThis); deinit_tcp_listener(pThis); if (pThis->pNS != NULL) netstrms.Destruct(&pThis->pNS); free(pThis->pszDrvrName); free(pThis->pszDrvrAuthMode); free(pThis->pszDrvrPermitExpiredCerts); free(pThis->pszDrvrCAFile); free(pThis->pszDrvrCRLFile); free(pThis->pszDrvrKeyFile); free(pThis->pszDrvrCertFile); free(pThis->ppLstn); free(pThis->ppLstnPort); free(pThis->ppioDescrPtr); free(pThis->pszOrigin); DESTROY_ATOMIC_HELPER_MUT(pThis->mut_sessions); ENDobjDestruct(tcpsrv) /* debugprint for the tcpsrv object */ BEGINobjDebugPrint(tcpsrv) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(tcpsrv); ENDobjDebugPrint(tcpsrv) /* set functions */ static rsRetVal ATTR_NONNULL(1) SetCBIsPermittedHost(tcpsrv_t *pThis, int (*pCB)(struct sockaddr *addr, char *fromHostFQDN, void *, void *)) { DEFiRet; pThis->pIsPermittedHost = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBRcvData(tcpsrv_t *pThis, rsRetVal (*pRcvData)(tcps_sess_t *, char *, size_t, ssize_t *, int *, unsigned *)) { DEFiRet; pThis->pRcvData = pRcvData; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnListenDeinit(tcpsrv_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->pOnListenDeinit = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnSessAccept(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t *, tcps_sess_t *, char *)) { DEFiRet; pThis->pOnSessAccept = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->OnDestruct = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnSessConstructFinalize(tcpsrv_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->OnSessConstructFinalize = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnSessDestruct(tcpsrv_t *pThis, rsRetVal (*pCB)(void *)) { DEFiRet; pThis->pOnSessDestruct = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnRegularClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t *)) { DEFiRet; pThis->pOnRegularClose = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOnErrClose(tcpsrv_t *pThis, rsRetVal (*pCB)(tcps_sess_t *)) { DEFiRet; pThis->pOnErrClose = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCBOpenLstnSocks(tcpsrv_t *pThis, rsRetVal (*pCB)(tcpsrv_t *)) { DEFiRet; pThis->OpenLstnSocks = pCB; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetUsrP(tcpsrv_t *pThis, void *pUsr) { DEFiRet; pThis->pUsr = pUsr; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetKeepAlive(tcpsrv_t *pThis, const int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive set to %d\n", iVal); pThis->bUseKeepAlive = iVal; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetKeepAliveIntvl(tcpsrv_t *pThis, const int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive interval set to %d\n", iVal); pThis->iKeepAliveIntvl = iVal; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetKeepAliveProbes(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive probes set to %d\n", iVal); pThis->iKeepAliveProbes = iVal; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetKeepAliveTime(tcpsrv_t *pThis, int iVal) { DEFiRet; DBGPRINTF("tcpsrv: keep-alive timeout set to %d\n", iVal); pThis->iKeepAliveTime = iVal; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetGnutlsPriorityString(tcpsrv_t *pThis, uchar *iVal) { DEFiRet; DBGPRINTF("tcpsrv: gnutlsPriorityString set to %s\n", (iVal == NULL) ? "(null)" : (const char *)iVal); pThis->gnutlsPriorityString = iVal; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetOnMsgReceive(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *, int)) { DEFiRet; assert(OnMsgReceive != NULL); pThis->OnMsgReceive = OnMsgReceive; RETiRet; } /* set enable/disable standard LF frame delimiter (use with care!) * -- rgerhards, 2010-01-03 */ static rsRetVal ATTR_NONNULL(1) SetbDisableLFDelim(tcpsrv_t *pThis, int bVal) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->bDisableLFDelim = bVal; RETiRet; } /* discard the truncated msg part * -- PascalWithopf, 2017-04-20 */ static rsRetVal ATTR_NONNULL(1) SetDiscardTruncatedMsg(tcpsrv_t *pThis, int discard) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->discardTruncatedMsg = discard; RETiRet; } /* Set additional framing to use (if any) -- rgerhards, 2008-12-10 */ static rsRetVal ATTR_NONNULL(1) SetAddtlFrameDelim(tcpsrv_t *pThis, int iDelim) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->addtlFrameDelim = iDelim; RETiRet; } /* Set max frame size for octet counted -- PascalWithopf, 2017-04-20*/ static rsRetVal ATTR_NONNULL(1) SetMaxFrameSize(tcpsrv_t *pThis, int maxFrameSize) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->maxFrameSize = maxFrameSize; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCompressionMode(tcpsrv_t *pThis, int mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != TCPSRV_COMPRESS_NEVER && mode != TCPSRV_COMPRESS_STREAM_ALWAYS) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pThis->compressionMode = (uint8_t)mode; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCompressionDriver(tcpsrv_t *pThis, int driver) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (driver != TCPSRV_COMPRESS_DRIVER_ZLIB && driver != TCPSRV_COMPRESS_DRIVER_ZSTD) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } #ifndef ENABLE_LIBZSTD if (driver == TCPSRV_COMPRESS_DRIVER_ZSTD) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } #endif pThis->compressionDriver = (uint8_t)driver; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCompressionMaxExpansionRatio(tcpsrv_t *pThis, const uint64_t ratio) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->compressionMaxExpansionRatio = ratio; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCompressionMaxDecompressedBytesPerReceive(tcpsrv_t *pThis, const uint64_t maxBytes) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->compressionMaxDecompressedBytesPerReceive = maxBytes; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetCompressionMaxTotalZstdWindowBytes(tcpsrv_t *pThis, const uint64_t maxBytes) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->compressionMaxTotalZstdWindowBytes = maxBytes; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDfltTZ(tcpsrv_t *const pThis, uchar *const tz) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); u_cstr_copy(pThis->dfltTZ, tz, sizeof(pThis->dfltTZ)); RETiRet; } static rsRetVal ATTR_NONNULL(1) SetbSPFramingFix(tcpsrv_t *pThis, const sbool val) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->bSPFramingFix = val; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetOrigin(tcpsrv_t *pThis, uchar *origin) { DEFiRet; free(pThis->pszOrigin); pThis->pszOrigin = (origin == NULL) ? NULL : ustrdup(origin); RETiRet; } /* Set the input name to use -- rgerhards, 2008-12-10 */ static rsRetVal ATTR_NONNULL(1) SetInputName(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params, const uchar *const name) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (name == NULL) { cnf_params->pszInputName = NULL; } else { CHKmalloc(cnf_params->pszInputName = ustrdup(name)); pThis->pszInputName = cnf_params->pszInputName; } /* we need to create a property */ CHKiRet(prop.Construct(&cnf_params->pInputName)); CHKiRet(prop.SetString(cnf_params->pInputName, cnf_params->pszInputName, ustrlen(cnf_params->pszInputName))); CHKiRet(prop.ConstructFinalize(cnf_params->pInputName)); finalize_it: RETiRet; } static rsRetVal SetNetworkNamespace(tcpsrv_t *pThis __attribute__((unused)), tcpLstnParams_t *const cnf_params, const char *const networkNamespace) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); free(cnf_params->pszNetworkNamespace); if (!networkNamespace || !*networkNamespace) { cnf_params->pszNetworkNamespace = NULL; } else { #ifdef HAVE_SETNS CHKmalloc(cnf_params->pszNetworkNamespace = strdup(networkNamespace)); #else // ndef HAVE_SETNS LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "Namespaces are not supported"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); #endif // #else ndef HAVE_SETNS } finalize_it: RETiRet; } /* Set the linux-like ratelimiter settings */ static rsRetVal ATTR_NONNULL(1) SetLinuxLikeRatelimiters(tcpsrv_t *pThis, unsigned int ratelimitInterval, unsigned int ratelimitBurst) { DEFiRet; pThis->ratelimitInterval = ratelimitInterval; pThis->ratelimitBurst = ratelimitBurst; RETiRet; } /* Set connection open notification */ static rsRetVal ATTR_NONNULL(1) SetNotificationOnRemoteOpen(tcpsrv_t *pThis, const int bNewVal) { pThis->bEmitMsgOnOpen = bNewVal; return RS_RET_OK; } /* Set connection close notification */ static rsRetVal ATTR_NONNULL(1) SetNotificationOnRemoteClose(tcpsrv_t *pThis, const int bNewVal) { DEFiRet; pThis->bEmitMsgOnClose = bNewVal; RETiRet; } /* here follows a number of methods that shuffle authentication settings down * to the drivers. Drivers not supporting these settings may return an error * state. * -------------------------------------------------------------------------- */ /* set the driver mode -- rgerhards, 2008-04-30 */ static rsRetVal ATTR_NONNULL(1) SetDrvrMode(tcpsrv_t *pThis, const int iMode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->iDrvrMode = iMode; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrName(tcpsrv_t *pThis, uchar *const name) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); free(pThis->pszDrvrName); CHKmalloc(pThis->pszDrvrName = ustrdup(name)); finalize_it: RETiRet; } /* set the driver authentication mode -- rgerhards, 2008-05-19 */ static rsRetVal ATTR_NONNULL(1) SetDrvrAuthMode(tcpsrv_t *pThis, uchar *const mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); CHKmalloc(pThis->pszDrvrAuthMode = ustrdup(mode)); finalize_it: RETiRet; } /* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20 */ static rsRetVal ATTR_NONNULL(1) SetDrvrPermitExpiredCerts(tcpsrv_t *pThis, uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != NULL) { CHKmalloc(pThis->pszDrvrPermitExpiredCerts = ustrdup(mode)); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrCAFile(tcpsrv_t *const pThis, uchar *const mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCAFile = ustrdup(mode)); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrCRLFile(tcpsrv_t *const pThis, uchar *const mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCRLFile = ustrdup(mode)); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrKeyFile(tcpsrv_t *pThis, uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != NULL) { CHKmalloc(pThis->pszDrvrKeyFile = ustrdup(mode)); } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrCertFile(tcpsrv_t *pThis, uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCertFile = ustrdup(mode)); } finalize_it: RETiRet; } /* set the driver's permitted peers -- rgerhards, 2008-05-19 */ static rsRetVal ATTR_NONNULL(1) SetDrvrPermPeers(tcpsrv_t *pThis, permittedPeers_t *pPermPeers) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->pPermPeers = pPermPeers; RETiRet; } /* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */ static rsRetVal ATTR_NONNULL(1) SetDrvrCheckExtendedKeyUsage(tcpsrv_t *pThis, int ChkExtendedKeyUsage) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage; RETiRet; } /* set the driver name checking policy -- jvymazal, 2019-08-16 */ static rsRetVal ATTR_NONNULL(1) SetDrvrPrioritizeSAN(tcpsrv_t *pThis, int prioritizeSan) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->DrvrPrioritizeSan = prioritizeSan; RETiRet; } /* set the driver Set the driver tls verifyDepth -- alorbach, 2019-12-20 */ static rsRetVal ATTR_NONNULL(1) SetDrvrTlsVerifyDepth(tcpsrv_t *pThis, int verifyDepth) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->DrvrTlsVerifyDepth = verifyDepth; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetDrvrTlsRevocationCheck(tcpsrv_t *pThis, int enabled) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->DrvrTlsRevocationCheck = (enabled != 0) ? 1 : 0; RETiRet; } /* End of methods to shuffle authentication settings to the driver.; * -------------------------------------------------------------------------- */ /* set max number of listeners * this must be called before ConstructFinalize, or it will have no effect! * rgerhards, 2009-08-17 */ static rsRetVal ATTR_NONNULL(1) SetLstnMax(tcpsrv_t *pThis, int iMax) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->iLstnMax = iMax; RETiRet; } /* set if flow control shall be supported */ static rsRetVal ATTR_NONNULL(1) SetUseFlowControl(tcpsrv_t *pThis, int bUseFlowControl) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->bUseFlowControl = bUseFlowControl; RETiRet; } /* set max number of sessions * this must be called before ConstructFinalize, or it will have no effect! * rgerhards, 2009-04-09 */ static rsRetVal ATTR_NONNULL(1) SetSessMax(tcpsrv_t *pThis, int iMax) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->iSessMax = iMax; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetPreserveCase(tcpsrv_t *pThis, int bPreserveCase) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcpsrv); pThis->bPreserveCase = bPreserveCase; RETiRet; } static rsRetVal ATTR_NONNULL(1) SetSynBacklog(tcpsrv_t *pThis, const int iSynBacklog) { pThis->iSynBacklog = iSynBacklog; return RS_RET_OK; } static rsRetVal ATTR_NONNULL(1) SetStarvationMaxReads(tcpsrv_t *pThis, const unsigned int maxReads) { pThis->starvationMaxReads = maxReads; return RS_RET_OK; } static rsRetVal ATTR_NONNULL(1) SetNumWrkr(tcpsrv_t *pThis, const int numWrkr) { pThis->workQueue.numWrkr = numWrkr; return RS_RET_OK; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(tcpsrv) CODESTARTobjQueryInterface(tcpsrv); if (pIf->ifVersion != tcpsrvCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->DebugPrint = tcpsrvDebugPrint; pIf->Construct = tcpsrvConstruct; pIf->ConstructFinalize = tcpsrvConstructFinalize; pIf->Destruct = tcpsrvDestruct; pIf->configureTCPListen = configureTCPListen; pIf->create_tcp_socket = create_tcp_socket; pIf->Run = Run; pIf->SetNetworkNamespace = SetNetworkNamespace; pIf->SetKeepAlive = SetKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetUsrP = SetUsrP; pIf->SetInputName = SetInputName; pIf->SetOrigin = SetOrigin; pIf->SetDfltTZ = SetDfltTZ; pIf->SetbSPFramingFix = SetbSPFramingFix; pIf->SetAddtlFrameDelim = SetAddtlFrameDelim; pIf->SetMaxFrameSize = SetMaxFrameSize; pIf->SetCompressionMode = SetCompressionMode; pIf->SetCompressionDriver = SetCompressionDriver; pIf->SetCompressionMaxExpansionRatio = SetCompressionMaxExpansionRatio; pIf->SetCompressionMaxDecompressedBytesPerReceive = SetCompressionMaxDecompressedBytesPerReceive; pIf->SetCompressionMaxTotalZstdWindowBytes = SetCompressionMaxTotalZstdWindowBytes; pIf->SetbDisableLFDelim = SetbDisableLFDelim; pIf->SetDiscardTruncatedMsg = SetDiscardTruncatedMsg; pIf->SetSessMax = SetSessMax; pIf->SetUseFlowControl = SetUseFlowControl; pIf->SetLstnMax = SetLstnMax; pIf->SetDrvrMode = SetDrvrMode; pIf->SetDrvrAuthMode = SetDrvrAuthMode; pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts; pIf->SetDrvrCAFile = SetDrvrCAFile; pIf->SetDrvrCRLFile = SetDrvrCRLFile; pIf->SetDrvrKeyFile = SetDrvrKeyFile; pIf->SetDrvrCertFile = SetDrvrCertFile; pIf->SetDrvrName = SetDrvrName; pIf->SetDrvrPermPeers = SetDrvrPermPeers; pIf->SetCBIsPermittedHost = SetCBIsPermittedHost; pIf->SetCBOpenLstnSocks = SetCBOpenLstnSocks; pIf->SetCBRcvData = SetCBRcvData; pIf->SetCBOnListenDeinit = SetCBOnListenDeinit; pIf->SetCBOnSessAccept = SetCBOnSessAccept; pIf->SetCBOnSessConstructFinalize = SetCBOnSessConstructFinalize; pIf->SetCBOnSessDestruct = SetCBOnSessDestruct; pIf->SetCBOnDestruct = SetCBOnDestruct; pIf->SetCBOnRegularClose = SetCBOnRegularClose; pIf->SetCBOnErrClose = SetCBOnErrClose; pIf->SetOnMsgReceive = SetOnMsgReceive; pIf->SetLinuxLikeRatelimiters = SetLinuxLikeRatelimiters; pIf->SetNotificationOnRemoteClose = SetNotificationOnRemoteClose; pIf->SetNotificationOnRemoteOpen = SetNotificationOnRemoteOpen; pIf->SetPreserveCase = SetPreserveCase; pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth; pIf->SetDrvrTlsRevocationCheck = SetDrvrTlsRevocationCheck; pIf->SetSynBacklog = SetSynBacklog; pIf->SetNumWrkr = SetNumWrkr; pIf->SetStarvationMaxReads = SetStarvationMaxReads; finalize_it: ENDobjQueryInterface(tcpsrv) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(tcpsrv, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(tcpsrv); /* release objects we no longer need */ objRelease(tcps_sess, DONT_LOAD_LIB); objRelease(conf, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(netstrms, DONT_LOAD_LIB); objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(net, LM_NET_FILENAME); #ifdef FEATURE_REGEXP objRelease(regexp, LM_REGEXP_FILENAME); #endif ENDObjClassExit(tcpsrv) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINObjClassInit(tcpsrv, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(netstrm, DONT_LOAD_LIB)); CHKiRet(objUse(tcps_sess, DONT_LOAD_LIB)); CHKiRet(objUse(conf, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); #ifdef FEATURE_REGEXP CHKiRet(objUse(regexp, LM_REGEXP_FILENAME)); #endif /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcpsrvDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcpsrvConstructFinalize); ENDObjClassInit(tcpsrv) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; /* de-init in reverse order! */ tcpsrvClassExit(); tcps_sessClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselves */ CHKiRet(tcps_sessClassInit(pModInfo)); CHKiRet(tcpsrvClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/wti.h0000644000000000000000000000013215241075234015201 xustar0030 mtime=1787067036.613578444 30 atime=1787067036.760581197 30 ctime=1787067794.393725036 rsyslog-8.2608.0/runtime/wti.h0000664000175000017500000001640715241075234014655 0ustar00rgerrger/* Definition of the worker thread instance (wti) class. * * Copyright 2008-2017 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef WTI_H_INCLUDED #define WTI_H_INCLUDED #include #include #include "wtp.h" #include "obj.h" #include "batch.h" #include "action.h" #define ACT_STATE_RDY 0 /* action ready, waiting for new transaction */ #define ACT_STATE_ITX 1 /* transaction active, waiting for new data or commit */ /* 2 currently not being used */ #define ACT_STATE_RTRY 3 /* failure occurred, trying to restablish ready state */ #define ACT_STATE_SUSP 4 /* suspended due to failure (return fail until timeout expired) */ #define ACT_STATE_DATAFAIL \ 5 /* suspended due to failure in data, which means the message in \ questions needs to be dropped as it will always fail. The \ action must still do a "normal" retry in order to bring \ it back to regular state. */ #define ACT_STATE_DISABLED \ 6 /* action encountered an unrecoverable failure and is \ permanently disabled for this process lifetime */ /* note: 3 bit bit field --> highest value is 7! */ typedef struct actWrkrInfo { action_t *pAction; void *actWrkrData; uint16_t uResumeOKinRow; /* number of times in a row that resume said OK with an immediate failure following */ int iNbrResRtry; /* number of retries since last suspend */ sbool bHadAutoCommit; /* did an auto-commit happen during doAction()? */ struct { unsigned actState : 3; } flags; union { struct { actWrkrIParams_t *iparams; /* dynamically sized array for transactional outputs */ int currIParam; int maxIParams; /* current max */ } tx; struct { actWrkrIParams_t actParams[CONF_OMOD_NUMSTRINGS_MAXSIZE]; } nontx; } p; /* short name for "parameters" */ } actWrkrInfo_t; /* the worker thread instance class */ struct wti_s { BEGINobjInstance ; pthread_t thrdID; /* thread ID */ int bIsRunning; /* is this thread currently running? (must be int for atomic op!) */ sbool bAlwaysRunning; /* should this thread always run? */ int workerIndex; /* stable slot in the owning worker pool */ int *pbShutdownImmediate; /* end processing of this batch immediately if set to 1 */ DEF_ATOMIC_HELPER_MUT(*pmutShutdownImmediate); /* fallback mutex for atomic access */ wtp_t *pWtp; /* my worker thread pool (important if only the work thread instance is passed! */ batch_t batch; /* pointer to an object array meaningful for current user pointer (e.g. queue pUsr data elemt) */ uchar *pszDbgHdr; /* header string for debug messages */ actWrkrInfo_t *actWrkrInfo; /* *array* of action wrkr infos for all actions (sized for max nbr of actions in config!) */ pthread_cond_t pcondBusy; /* condition to wake up the worker, protected by pmutUsr in wtp */ DEF_ATOMIC_HELPER_MUT(mutIsRunning); struct { uint8_t script_errno; /* errno-type interface for RainerScript functions */ uint8_t bPrevWasSuspended; uint8_t bDoAutoCommit; /* do a commit after each message * this is usually set for batches with 0 element, but may * also be added as a user-selectable option (not implemented yet) */ uint16_t rulesetCallDepth; /* synchronous ruleset call nesting depth */ } execState; /* state for the execution engine */ }; static inline int wtiIsShutdownImmediate(const wti_t *const pWti) { #ifdef HAVE_ATOMIC_BUILTINS return ATOMIC_LOAD_32BIT(pWti->pbShutdownImmediate, NULL); #else return ATOMIC_LOAD_32BIT(pWti->pbShutdownImmediate, pWti->pmutShutdownImmediate); #endif } /* prototypes */ rsRetVal wtiConstruct(wti_t **ppThis); rsRetVal wtiConstructFinalize(wti_t *const pThis); rsRetVal wtiDestruct(wti_t **ppThis); rsRetVal wtiWorker(wti_t *const pThis); rsRetVal wtiSetDbgHdr(wti_t *const pThis, uchar *pszMsg, size_t lenMsg); uchar *ATTR_NONNULL() wtiGetDbgHdr(const wti_t *const pThis); rsRetVal wtiCancelThrd(wti_t *const pThis, const uchar *const cancelobj); void ATTR_NONNULL() wtiJoinThrd(wti_t *const pThis); rsRetVal wtiSetAlwaysRunning(wti_t *const pThis); rsRetVal wtiSetState(wti_t *const pThis, int bNew); rsRetVal wtiCASState(wti_t *const pThis, const int oldVal, const int newVal); rsRetVal wtiWakeupThrd(wti_t *const pThis); int wtiGetState(wti_t *const pThis); wti_t *wtiGetDummy(void); int ATTR_NONNULL() wtiWaitNonEmpty(wti_t *const pThis, const struct timespec timeout); PROTOTYPEObjClassInit(wti); PROTOTYPEObjClassExit(wti); PROTOTYPEpropSetMeth(wti, pszDbgHdr, uchar *); PROTOTYPEpropSetMeth(wti, pWtp, wtp_t *); #define getActionStateByNbr(pWti, iActNbr) ((uint8_t)((pWti)->actWrkrInfo[(iActNbr)].flags.actState)) #define getActionState(pWti, pAction) (((uint8_t)(pWti)->actWrkrInfo[(pAction)->iActionNbr].flags.actState)) #define setActionState(pWti, pAction, newState) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].flags.actState = (newState)) #define getActionResumeInRow(pWti, pAction) (((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow)) #define setActionResumeInRow(pWti, pAction, val) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow = (val)) #define incActionResumeInRow(pWti, pAction) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].uResumeOKinRow++) #define getActionNbrResRtry(pWti, pAction) (((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry)) #define setActionNbrResRtry(pWti, pAction, val) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry = (val)) #define incActionNbrResRtry(pWti, pAction) ((pWti)->actWrkrInfo[(pAction)->iActionNbr].iNbrResRtry++) #define wtiInitIParam(piparams) (memset((piparams), 0, sizeof(actWrkrIParams_t))) #define wtiGetScriptErrno(pWti) ((pWti)->execState.script_errno) #define wtiSetScriptErrno(pWti, newval) (pWti)->execState.script_errno = (newval) static inline uint8_t ATTR_UNUSED ATTR_NONNULL(1) wtiGetPrevWasSuspended(const wti_t *const pWti) { assert(pWti != NULL); return pWti->execState.bPrevWasSuspended; } static inline void __attribute__((unused)) wtiResetExecState(wti_t *const pWti, batch_t *const pBatch) { wtiSetScriptErrno(pWti, 0); pWti->execState.bPrevWasSuspended = 0; pWti->execState.bDoAutoCommit = (batchNumMsgs(pBatch) == 1); pWti->execState.rulesetCallDepth = 0; } rsRetVal wtiNewIParam(wti_t *const pWti, action_t *const pAction, actWrkrIParams_t **piparams); #endif /* #ifndef WTI_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/strgen.h0000644000000000000000000000013215145046113015675 xustar0030 mtime=1771326539.016013913 30 atime=1787067618.056438125 30 ctime=1787067794.300723303 rsyslog-8.2608.0/runtime/strgen.h0000664000175000017500000000441315145046113015343 0ustar00rgerrger/* header for strgen.c * * Copyright 2010-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_STRGEN_H #define INCLUDED_STRGEN_H /* we create a small helper object, a list of strgens, that we can use to * build a chain of them whereever this is needed. */ struct strgenList_s { strgen_t *pStrgen; strgenList_t *pNext; }; /* the strgen object, a dummy because we have only static methods */ struct strgen_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ uchar *pName; /* name of this strgen */ modInfo_t *pModule; /* pointer to strgen's module */ }; /* interfaces */ BEGINinterface(strgen) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(strgen_t **ppThis); rsRetVal (*ConstructFinalize)(strgen_t *pThis); rsRetVal (*Destruct)(strgen_t **ppThis); rsRetVal (*SetName)(strgen_t *pThis, uchar *name); rsRetVal (*SetModPtr)(strgen_t *pThis, modInfo_t *pMod); rsRetVal (*FindStrgen)(strgen_t **ppThis, uchar *name); rsRetVal (*InitStrgenList)(strgenList_t **pListRoot); rsRetVal (*DestructStrgenList)(strgenList_t **pListRoot); rsRetVal (*AddStrgenToList)(strgenList_t **pListRoot, strgen_t *pStrgen); ENDinterface(strgen) #define strgenCURR_IF_VERSION 1 /* increment whenever you change the interface above! */ /* prototypes */ PROTOTYPEObjFull(strgen); #endif /* #ifndef INCLUDED_STRGEN_H */ rsyslog-8.2608.0/runtime/PaxHeaders/dnscache.c0000644000000000000000000000013215171370365016146 xustar0030 mtime=1776677109.435912987 30 atime=1787067617.987436838 30 ctime=1787067794.246722297 rsyslog-8.2608.0/runtime/dnscache.c0000664000175000017500000004054515171370365015622 0ustar00rgerrger/* dnscache.c * Implementation of a real DNS cache * * File begun on 2011-06-06 by RGerhards * The initial implementation is far from being optimal. The idea is to * first get somethting that'S functionally OK, and then evolve the algorithm. * In any case, even the initial implementaton is far faster than what we had * before. -- rgerhards, 2011-06-06 * * Copyright 2011-2019 by Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include "syslogd-types.h" #include "glbl.h" #include "errmsg.h" #include "obj.h" #include "unicode-helper.h" #include "net.h" #include "hashtable.h" #include "prop.h" #include "dnscache.h" #include "rsconf.h" /* module data structures */ struct dnscache_entry_s { struct sockaddr_storage addr; prop_t *fqdn; prop_t *fqdnLowerCase; prop_t *localName; /* only local name, without domain part (if configured so) */ prop_t *ip; time_t validUntil; struct dnscache_entry_s *next; unsigned nUsed; }; typedef struct dnscache_entry_s dnscache_entry_t; struct dnscache_s { pthread_rwlock_t rwlock; struct hashtable *ht; unsigned nEntries; }; typedef struct dnscache_s dnscache_t; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) static dnscache_t dnsCache; static prop_t *staticErrValue; /* Our hash function. */ static unsigned int hash_from_key_fn(void *k) { int len = 0; uchar *rkey; /* we treat this as opaque bytes */ unsigned hashval = 1; switch (((struct sockaddr *)k)->sa_family) { case AF_INET: len = sizeof(struct in_addr); rkey = (uchar *)&(((struct sockaddr_in *)k)->sin_addr); break; case AF_INET6: len = sizeof(struct in6_addr); rkey = (uchar *)&(((struct sockaddr_in6 *)k)->sin6_addr); break; default: dbgprintf("hash_from_key_fn: unknown address family!\n"); len = 0; rkey = NULL; } while (len--) { /* the casts are done in order to prevent undefined behavior sanitizer * from triggering warnings. Actually, it would be OK if we have just * "random" truncation. */ hashval = (unsigned)(hashval * (unsigned long long)33) + *rkey++; } if (((struct sockaddr *)k)->sa_family == AF_INET6) { const uint32_t scope_id = ((struct sockaddr_in6 *)k)->sin6_scope_id; for (size_t i = 0; i < sizeof(scope_id); ++i) { hashval = (unsigned)(hashval * (unsigned long long)33) + ((scope_id >> (i * 8)) & 0xff); } } return hashval; } static int key_equals_fn(void *key1, void *key2) { int RetVal = 0; if (((struct sockaddr *)key1)->sa_family != ((struct sockaddr *)key2)->sa_family) { return 0; } switch (((struct sockaddr *)key1)->sa_family) { case AF_INET: RetVal = !memcmp(&((struct sockaddr_in *)key1)->sin_addr, &((struct sockaddr_in *)key2)->sin_addr, sizeof(struct in_addr)); break; case AF_INET6: RetVal = !memcmp(&((struct sockaddr_in6 *)key1)->sin6_addr, &((struct sockaddr_in6 *)key2)->sin6_addr, sizeof(struct in6_addr)) && ((struct sockaddr_in6 *)key1)->sin6_scope_id == ((struct sockaddr_in6 *)key2)->sin6_scope_id; break; default: // No action needed for other cases break; } return RetVal; } /* destruct a cache entry. * Precondition: entry must already be unlinked from list */ static void ATTR_NONNULL() entryDestruct(dnscache_entry_t *const etry) { if (etry->fqdn != NULL) prop.Destruct(&etry->fqdn); if (etry->fqdnLowerCase != NULL) prop.Destruct(&etry->fqdnLowerCase); if (etry->localName != NULL) prop.Destruct(&etry->localName); if (etry->ip != NULL) prop.Destruct(&etry->ip); free(etry); } /* init function (must be called once) */ rsRetVal dnscacheInit(void) { DEFiRet; if ((dnsCache.ht = create_hashtable(100, hash_from_key_fn, key_equals_fn, (void (*)(void *))entryDestruct)) == NULL) { DBGPRINTF("dnscache: error creating hash table!\n"); ABORT_FINALIZE(RS_RET_ERR); // TODO: make this degrade, but run! } dnsCache.nEntries = 0; pthread_rwlock_init(&dnsCache.rwlock, NULL); CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); prop.Construct(&staticErrValue); prop.SetString(staticErrValue, (uchar *)"???", 3); prop.ConstructFinalize(staticErrValue); finalize_it: RETiRet; } /* deinit function (must be called once) */ rsRetVal dnscacheDeinit(void) { DEFiRet; prop.Destruct(&staticErrValue); hashtable_destroy(dnsCache.ht, 1); /* 1 => free all values automatically */ pthread_rwlock_destroy(&dnsCache.rwlock); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); RETiRet; } /* This is a cancel-safe getnameinfo() version, because we learned * (via drd/valgrind) that getnameinfo() seems to have some issues * when being cancelled, at least if the module was dlloaded. * rgerhards, 2008-09-30 */ static int mygetnameinfo( const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { int iCancelStateSave; int i; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); i = getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); pthread_setcancelstate(iCancelStateSave, NULL); return i; } /* get only the local part of the hostname and set it in cache entry */ static void setLocalHostName(dnscache_entry_t *etry) { uchar *fqdnLower; uchar *p; int i; uchar hostbuf[NI_MAXHOST]; if (glbl.GetPreserveFQDN()) { prop.AddRef(etry->fqdnLowerCase); etry->localName = etry->fqdnLowerCase; goto done; } /* strip domain, if configured for this entry */ fqdnLower = propGetSzStr(etry->fqdnLowerCase); p = (uchar *)strchr((char *)fqdnLower, '.'); /* find start of domain name "machine.example.com" */ if (p == NULL) { /* do we have a domain part? */ prop.AddRef(etry->fqdnLowerCase); /* no! */ etry->localName = etry->fqdnLowerCase; goto done; } i = p - fqdnLower; /* length of hostname */ memcpy(hostbuf, fqdnLower, i); hostbuf[i] = '\0'; /* at this point, we have not found anything, so we again use the * already-created complete full name property. */ prop.AddRef(etry->fqdnLowerCase); etry->localName = etry->fqdnLowerCase; done: return; } /* resolve an address. * * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats) * for some explanation of the code found below. We do by default not * discard message where we detected malicouos DNS PTR records. However, * there is a user-configurabel option that will tell us if * we should abort. For this, the return value tells the caller if the * message should be processed (1) or discarded (0). */ static rsRetVal ATTR_NONNULL() resolveAddr(struct sockaddr_storage *addr, dnscache_entry_t *etry) { DEFiRet; int error; sigset_t omask, nmask; struct addrinfo hints, *res; char szIP[NI_MAXHOST]; char fqdnBuf[NI_MAXHOST]; rs_size_t fqdnLen; rs_size_t i; error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *)addr), (char *)szIP, sizeof(szIP), NULL, 0, NI_NUMERICHOST); if (error) { dbgprintf("Malformed from address %s\n", gai_strerror(error)); ABORT_FINALIZE(RS_RET_INVALID_SOURCE); } if (!glbl.GetDisableDNS(runConf)) { sigemptyset(&nmask); sigaddset(&nmask, SIGHUP); pthread_sigmask(SIG_BLOCK, &nmask, &omask); error = mygetnameinfo((struct sockaddr *)addr, SALEN((struct sockaddr *)addr), fqdnBuf, NI_MAXHOST, NULL, 0, NI_NAMEREQD); if (error == 0) { memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; /* we now do a lookup once again. This one should fail, * because we should not have obtained a non-numeric address. If * we got a numeric one, someone messed with DNS! */ if (getaddrinfo(fqdnBuf, NULL, &hints, &res) == 0) { freeaddrinfo(res); /* OK, we know we have evil. The question now is what to do about * it. One the one hand, the message might probably be intended * to harm us. On the other hand, losing the message may also harm us. * Thus, the behaviour is controlled by the $DropMsgsWithMaliciousDnsPTRRecords * option. If it tells us we should discard, we do so, else we proceed, * but log an error message together with it. * time being, we simply drop the name we obtained and use the IP - that one * is OK in any way. We do also log the error message. rgerhards, 2007-07-16 */ if (glbl.GetDropMalPTRMsgs(runConf) == 1) { LogError(0, RS_RET_MALICIOUS_ENTITY, "Malicious PTR record, message dropped " "IP = \"%s\" HOST = \"%s\"", szIP, fqdnBuf); pthread_sigmask(SIG_SETMASK, &omask, NULL); ABORT_FINALIZE(RS_RET_MALICIOUS_ENTITY); } /* Please note: we deal with a malicous entry. Thus, we have crafted * the snprintf() below so that all text is in front of the entry - maybe * it contains characters that make the message unreadable * (OK, I admit this is more or less impossible, but I am paranoid...) * rgerhards, 2007-07-16 */ LogError(0, NO_ERRCODE, "Malicious PTR record (message accepted, but used IP " "instead of PTR name: IP = \"%s\" HOST = \"%s\"", szIP, fqdnBuf); error = 1; /* that will trigger using IP address below. */ } else { /* we have a valid entry, so let's create the respective properties */ fqdnLen = strlen(fqdnBuf); prop.CreateStringProp(&etry->fqdn, (uchar *)fqdnBuf, fqdnLen); for (i = 0; i < fqdnLen; ++i) fqdnBuf[i] = tolower(fqdnBuf[i]); prop.CreateStringProp(&etry->fqdnLowerCase, (uchar *)fqdnBuf, fqdnLen); } } pthread_sigmask(SIG_SETMASK, &omask, NULL); } finalize_it: if (iRet != RS_RET_OK) { RS_COPY_LITERAL(szIP, "?error.obtaining.ip?"); error = 1; /* trigger hostname copies below! */ } prop.CreateStringProp(&etry->ip, (uchar *)szIP, strlen(szIP)); if (error || glbl.GetDisableDNS(runConf)) { dbgprintf("Host name for your address (%s) unknown\n", szIP); prop.AddRef(etry->ip); etry->fqdn = etry->ip; prop.AddRef(etry->ip); etry->fqdnLowerCase = etry->ip; } setLocalHostName(etry); RETiRet; } static rsRetVal ATTR_NONNULL() addEntry(struct sockaddr_storage *const addr, dnscache_entry_t **const pEtry) { int r; dnscache_entry_t *etry = NULL; DEFiRet; /* entry still does not exist, so add it */ struct sockaddr_storage *const keybuf = malloc(sizeof(struct sockaddr_storage)); CHKmalloc(keybuf); CHKmalloc(etry = malloc(sizeof(dnscache_entry_t))); resolveAddr(addr, etry); assert(etry != NULL); memcpy(&etry->addr, addr, SALEN((struct sockaddr *)addr)); etry->nUsed = 0; if (runConf->globals.dnscacheEnableTTL) { etry->validUntil = time(NULL) + runConf->globals.dnscacheDefaultTTL; } memcpy(keybuf, addr, sizeof(struct sockaddr_storage)); r = hashtable_insert(dnsCache.ht, keybuf, etry); if (r == 0) { DBGPRINTF("dnscache: inserting element failed\n"); } *pEtry = etry; finalize_it: if (iRet != RS_RET_OK) { free(keybuf); } RETiRet; } static rsRetVal ATTR_NONNULL(1, 5) findEntry(struct sockaddr_storage *const addr, prop_t **const fqdn, prop_t **const fqdnLowerCase, prop_t **const localName, prop_t **const ip) { DEFiRet; pthread_rwlock_rdlock(&dnsCache.rwlock); dnscache_entry_t *etry = hashtable_search(dnsCache.ht, addr); DBGPRINTF("findEntry: 1st lookup found %p\n", etry); if (etry == NULL || (runConf->globals.dnscacheEnableTTL && (etry->validUntil <= time(NULL)))) { pthread_rwlock_unlock(&dnsCache.rwlock); pthread_rwlock_wrlock(&dnsCache.rwlock); etry = hashtable_search(dnsCache.ht, addr); /* re-query, might have changed */ DBGPRINTF("findEntry: 2nd lookup found %p\n", etry); if (etry == NULL || (runConf->globals.dnscacheEnableTTL && (etry->validUntil <= time(NULL)))) { if (etry != NULL) { DBGPRINTF( "hashtable: entry timed out, discarding it; " "valid until %lld, now %lld\n", (long long)etry->validUntil, (long long)time(NULL)); dnscache_entry_t *const deleted = hashtable_remove(dnsCache.ht, addr); if (deleted != etry) { LogError(0, RS_RET_INTERNAL_ERROR, "dnscache %d: removed different " "hashtable entry than expected - please report issue; " "rsyslog version is %s", __LINE__, VERSION); } entryDestruct(etry); } /* now entry doesn't exist in any case, so let's (re)create it */ CHKiRet(addEntry(addr, &etry)); } } prop.AddRef(etry->ip); *ip = etry->ip; if (fqdn != NULL) { prop.AddRef(etry->fqdn); *fqdn = etry->fqdn; } if (fqdnLowerCase != NULL) { prop.AddRef(etry->fqdnLowerCase); *fqdnLowerCase = etry->fqdnLowerCase; } if (localName != NULL) { prop.AddRef(etry->localName); *localName = etry->localName; } finalize_it: pthread_rwlock_unlock(&dnsCache.rwlock); RETiRet; } /* This is the main function: it looks up an entry and returns it's name * and IP address. If the entry is not yet inside the cache, it is added. * If the entry can not be resolved, an error is reported back. If fqdn * or fqdnLowerCase are NULL, they are not set. */ rsRetVal ATTR_NONNULL(1, 5) dnscacheLookup(struct sockaddr_storage *const addr, prop_t **const fqdn, prop_t **const fqdnLowerCase, prop_t **const localName, prop_t **const ip) { DEFiRet; iRet = findEntry(addr, fqdn, fqdnLowerCase, localName, ip); if (iRet != RS_RET_OK) { DBGPRINTF("dnscacheLookup failed with iRet %d\n", iRet); prop.AddRef(staticErrValue); *ip = staticErrValue; if (fqdn != NULL) { prop.AddRef(staticErrValue); *fqdn = staticErrValue; } if (fqdnLowerCase != NULL) { prop.AddRef(staticErrValue); *fqdnLowerCase = staticErrValue; } if (localName != NULL) { prop.AddRef(staticErrValue); *localName = staticErrValue; } } RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_format.h0000644000000000000000000000013215241075234017377 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.413725409 rsyslog-8.2608.0/runtime/segdisk_format.h0000664000175000017500000000035715241075234017050 0ustar00rgerrger/* Shared format versions for queue.type="segmentedDisk". * This file is part of the rsyslog project, released under ASL 2.0. */ #ifndef INCLUDED_SEGDISK_FORMAT_H #define INCLUDED_SEGDISK_FORMAT_H #define SEGDISK_CODEC_VERSION 1 #endif rsyslog-8.2608.0/runtime/PaxHeaders/var.h0000644000000000000000000000013215145046113015163 xustar0030 mtime=1771326539.020013978 30 atime=1787067616.814414966 30 ctime=1787067794.384724869 rsyslog-8.2608.0/runtime/var.h0000664000175000017500000000354715145046113014640 0ustar00rgerrger/* The var object. * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_VAR_H #define INCLUDED_VAR_H #include "stringbuf.h" /* data types */ typedef enum { VARTYPE_NONE = 0, /* currently no value set */ VARTYPE_STR = 1, VARTYPE_NUMBER = 2, VARTYPE_SYSLOGTIME = 3 } varType_t; /* the var object */ typedef struct var_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ cstr_t *pcsName; varType_t varType; union { number_t num; es_str_t *str; cstr_t *pStr; syslogTime_t vSyslogTime; } val; } var_t; /* interfaces */ BEGINinterface(var) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(var); rsRetVal (*Construct)(var_t **ppThis); rsRetVal (*ConstructFinalize)(var_t __attribute__((unused)) * pThis); rsRetVal (*Destruct)(var_t **ppThis); ENDinterface(var) #define varCURR_IF_VERSION 2 /* increment whenever you change the interface above! */ /* v2 - 2011-07-15/rger: on the way to remove var */ /* prototypes */ PROTOTYPEObjFull(var); PROTOTYPEObjDebugPrint(var); #endif /* #ifndef INCLUDED_VAR_H */ rsyslog-8.2608.0/runtime/PaxHeaders/zstdw.h0000644000000000000000000000013215132411300015534 xustar0030 mtime=1768559296.279885846 30 atime=1787067618.375444072 30 ctime=1787067794.616729192 rsyslog-8.2608.0/runtime/zstdw.h0000666000175000017500000000317415132411300015207 0ustar00rgerrger/* The zstdw object. It encapsulates the zstd functionality. The primary * purpose of this wrapper class is to enable rsyslogd core to be build without * zstd libraries. * * Copyright 2022 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_ZSTDW_H #define INCLUDED_ZSTDW_H /* interfaces */ BEGINinterface(zstdw) /* name must also be changed in ENDinterface macro! */ rsRetVal (*doStrmWrite)(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)); rsRetVal (*doCompressFinish)(strm_t *pThis, rsRetVal (*Destruct)(strm_t *pThis, uchar *pBuf, size_t lenBuf)); rsRetVal (*Destruct)(strm_t *pThis); ENDinterface(zstdw) #define zstdwCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(zstdw); /* the name of our library binary */ #define LM_ZSTDW_FILENAME "lmzstdw" #endif /* #ifndef INCLUDED_ZSTDW_H */ rsyslog-8.2608.0/runtime/PaxHeaders/lmcry_ossl.c0000644000000000000000000000013015216464436016565 xustar0028 mtime=1782212894.0272662 30 atime=1782715518.781788721 30 ctime=1787067794.512727254 rsyslog-8.2608.0/runtime/lmcry_ossl.c0000664000175000017500000002214015216464436016232 0ustar00rgerrger/* lmcry_ossl.c * * An implementation of the cryprov interface for openssl. * * Copyright 2013-2017 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "cryprov.h" #include "parserif.h" #include "libossl.h" #include "lmcry_ossl.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfpdescrRegular[] = {{"cry.key", eCmdHdlrGetWord, 0}, {"cry.keyfile", eCmdHdlrGetWord, 0}, {"cry.mode", eCmdHdlrGetWord, 0}, {"cry.algo", eCmdHdlrGetWord, 0}}; static struct cnfparamblk pblkRegular = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrRegular) / sizeof(struct cnfparamdescr), cnfpdescrRegular}; static struct cnfparamdescr cnfpdescrQueue[] = {{"queue.cry.key", eCmdHdlrGetWord, 0}, {"queue.cry.keyfile", eCmdHdlrGetWord, 0}, {"queue.cry.mode", eCmdHdlrGetWord, 0}, {"queue.cry.algo", eCmdHdlrGetWord, 0}}; static struct cnfparamblk pblkQueue = {CNFPARAMBLK_VERSION, sizeof(cnfpdescrQueue) / sizeof(struct cnfparamdescr), cnfpdescrQueue}; /* Standard-Constructor */ BEGINobjConstruct(lmcry_ossl) CHKmalloc(pThis->ctx = osslCtxNew()); finalize_it: ENDobjConstruct(lmcry_ossl) /* destructor for the lmcry_ossl object */ BEGINobjDestruct(lmcry_ossl) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(lmcry_ossl); rsosslCtxDel(pThis->ctx); ENDobjDestruct(lmcry_ossl) /* apply all params from param block to us. This must be called * after construction, but before the OnFileOpen() entry point. * Defaults are expected to have been set during construction. */ static rsRetVal SetCnfParam(void *pT, struct nvlst *lst, int paramType) { lmcry_ossl_t *pThis = (lmcry_ossl_t *)pT; int i, r; unsigned keylen = 0; uchar *key = NULL; uchar *keyfile = NULL; uchar *algomode = NULL; int nKeys; /* number of keys (actually methods) specified */ struct cnfparamvals *pvals; struct cnfparamblk *pblk; DEFiRet; pblk = (paramType == CRYPROV_PARAMTYPE_REGULAR) ? &pblkRegular : &pblkQueue; nKeys = 0; pvals = nvlstGetParams(lst, pblk, NULL); if (pvals == NULL) { parser_errmsg("error crypto provider ossl config parameters"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("param blk in lmcry_ossl:\n"); cnfparamsPrint(pblk, pvals); } for (i = 0; i < pblk->nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblk->descr[i].name, "cry.key") || !strcmp(pblk->descr[i].name, "queue.cry.key")) { CHKmalloc(key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++nKeys; } else if (!strcmp(pblk->descr[i].name, "cry.keyfile") || !strcmp(pblk->descr[i].name, "queue.cry.keyfile")) { CHKmalloc(keyfile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); ++nKeys; } else if (!strcmp(pblk->descr[i].name, "cry.algo") || !strcmp(pblk->descr[i].name, "queue.cry.algo")) { CHKmalloc(algomode = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { DBGPRINTF( "lmcry_ossl: program error, non-handled " "param '%s'\n", pblk->descr[i].name); } } if (algomode != NULL) { iRet = rsosslSetAlgoMode(pThis->ctx, algomode); if (iRet != RS_RET_OK) { LogError(0, iRet, "cry.algo '%s' is not know/supported", algomode); FINALIZE; } } /* note: key must be set AFTER algo/mode is set (as it depends on them) */ if (nKeys != 1) { LogError(0, RS_RET_INVALID_PARAMS, "excactly one of the following " "parameters can be specified: cry.key, cry.keyfile\n"); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } if (key != NULL) { LogError(0, RS_RET_ERR, "Note: specifying an actual key directly from the " "config file is highly insecure - DO NOT USE FOR PRODUCTION"); keylen = strlen((char *)key); } if (keyfile != NULL) { r = osslGetKeyFromFile((char *)keyfile, (char **)&key, &keylen); if (r != 0) { LogError(errno, RS_RET_ERR, "error reading keyfile %s", keyfile); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } } /* if we reach this point, we have a valid key */ r = rsosslSetKey(pThis->ctx, key, keylen); if (r > 0) { LogError(0, RS_RET_INVALID_PARAMS, "Key length %d expected, but " "key of length %d given", r, keylen); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } finalize_it: free(key); free(keyfile); free(algomode); if (pvals != NULL) cnfparamvalsDestruct(pvals, pblk); RETiRet; } static void SetDeleteOnClose(void *pF, int val) { osslfileSetDeleteOnClose(pF, val); } static rsRetVal GetBytesLeftInBlock(void *pF, ssize_t *left) { return osslfileGetBytesLeftInBlock((osslfile)pF, left); } static rsRetVal DeleteStateFiles(uchar *logfn) { return osslfileDeleteState(logfn); } static rsRetVal OnFileOpen(void *pT, uchar *fn, void *pGF, char openMode) { lmcry_ossl_t *pThis = (lmcry_ossl_t *)pT; osslfile *pgf = (osslfile *)pGF; DEFiRet; DBGPRINTF("lmcry_ossl: open file '%s', mode '%c'\n", fn, openMode); iRet = rsosslInitCrypt(pThis->ctx, pgf, fn, openMode); if (iRet != RS_RET_OK) { LogError(0, iRet, "Encryption Provider" "Error: cannot open .encinfo file - disabling log file"); } RETiRet; } static rsRetVal Decrypt(void *pF, uchar *rec, size_t *lenRec) { DEFiRet; iRet = rsosslDecrypt(pF, rec, lenRec); RETiRet; } static rsRetVal Encrypt(void *pF, uchar *rec, size_t *lenRec) { DEFiRet; iRet = rsosslEncrypt(pF, rec, lenRec); RETiRet; } static rsRetVal OnFileClose(void *pF, off64_t offsLogfile) { DEFiRet; osslfileDestruct(pF, offsLogfile); RETiRet; } BEGINobjQueryInterface(lmcry_ossl) CODESTARTobjQueryInterface(lmcry_ossl); if (pIf->ifVersion != cryprovCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } pIf->Construct = (rsRetVal(*)(void *))lmcry_osslConstruct; pIf->SetCnfParam = SetCnfParam; pIf->SetDeleteOnClose = SetDeleteOnClose; pIf->Destruct = (rsRetVal(*)(void *))lmcry_osslDestruct; pIf->OnFileOpen = OnFileOpen; pIf->Encrypt = Encrypt; pIf->Decrypt = Decrypt; pIf->OnFileClose = OnFileClose; pIf->DeleteStateFiles = DeleteStateFiles; pIf->GetBytesLeftInBlock = GetBytesLeftInBlock; finalize_it: ENDobjQueryInterface(lmcry_ossl) BEGINObjClassExit(lmcry_ossl, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(lmcry_ossl); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); rsosslExit(); ENDObjClassExit(lmcry_ossl) BEGINObjClassInit(lmcry_ossl, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); if (rsosslInit() != 0) { LogError(0, RS_RET_CRYPROV_ERR, "error initializing " "ossl crypto provider - cannot encrypt"); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } ENDObjClassInit(lmcry_ossl) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; lmcry_osslClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(lmcry_osslClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/dynstats.c0000644000000000000000000000013215241075234016242 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.745580916 30 ctime=1787067794.364724496 rsyslog-8.2608.0/runtime/dynstats.c0000664000175000017500000015544115241075234015720 0ustar00rgerrger/* * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "errmsg.h" #include "rsconf.h" #include "datetime.h" #include "unicode-helper.h" #include "hashtable_itr.h" #include "compat_queue.h" /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(statsobj) DEFobjCurrIf(datetime) #define DYNSTATS_PARAM_NAME "name" #define DYNSTATS_PARAM_RESETTABLE "resettable" #define DYNSTATS_PARAM_MAX_CARDINALITY "maxCardinality" #define DYNSTATS_PARAM_UNUSED_METRIC_LIFE "unusedMetricLife" /* in seconds */ #define DYNSTATS_PARAM_PERSISTSTATEINTERVAL "persistStateInterval" #define DYNSTATS_PARAM_PERSISTSTATE_TIME_INTERVAL "persistStateTimeInterval" #define DYNSTATS_PARAM_STATEFILE_DIRECTORY "statefile.directory" #define DYNSTATS_DEFAULT_RESETTABILITY 1 #define DYNSTATS_DEFAULT_MAX_CARDINALITY 2000 #define DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE 3600 /* seconds */ #define DYNSTATS_DEFAULT_PERSISTSTATEINTERVAL 0 /* seconds, default is 0, or never */ #define DYNSTATS_DEFAULT_PERSISTSTATE_TIME_INTERVAL 0 /* seconds, default is 0, or never */ #define DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH 100 #define DYNSTATS_METRIC_NAME_SEPARATOR '.' #define DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING 1.25 #define DYNSTATS_BUCKET_PERSIST_NAME "name" #define DYNSTATS_BUCKET_PERSIST_VALUES_NAME "values" static struct cnfparamdescr modpdescr[] = { {DYNSTATS_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED}, {DYNSTATS_PARAM_RESETTABLE, eCmdHdlrBinary, 0}, {DYNSTATS_PARAM_MAX_CARDINALITY, eCmdHdlrPositiveInt, 0}, {DYNSTATS_PARAM_UNUSED_METRIC_LIFE, eCmdHdlrPositiveInt, 0}, /* in minutes */ {DYNSTATS_PARAM_PERSISTSTATEINTERVAL, eCmdHdlrPositiveInt, 0}, {DYNSTATS_PARAM_PERSISTSTATE_TIME_INTERVAL, eCmdHdlrPositiveInt, 0}, {DYNSTATS_PARAM_STATEFILE_DIRECTORY, eCmdHdlrString, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static rsRetVal dynstats_addNewCtr(dynstats_bucket_t *b, const uchar *metric, uint8_t doInitialIncrement, uint64_t doInitialOffset); static int getFullStateFileName(dynstats_bucket_t *b, uchar *pszstatefile, uchar *pszout, int buflen); static uchar *getStateFileName(const dynstats_bucket_t *const pbucket, uchar *const __restrict__ buf, const size_t lenbuf) ATTR_NONNULL(1, 2); static rsRetVal persistBucketState(dynstats_bucket_t *b, sbool useWorker) ATTR_NONNULL(1); static rsRetVal initFileWriteWorker(dynstats_buckets_t *bkts); static rsRetVal enqueueFileWriteTask(dynstats_bucket_t *b, const char *file_name, const char *content); static void startFileWriteWorker(dynstats_buckets_t *bkts); static void stopFileWriteWorker(dynstats_buckets_t *bkts); static void destroyFileWriteWorker(dynstats_buckets_t *bkts); rsRetVal dynstatsClassInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); finalize_it: RETiRet; } static void dynstats_destroyCtr(dynstats_ctr_t *ctr) { statsobj.DestructUnlinkedCounter(ctr->pCtr); free(ctr->metric); free(ctr); } static void dynstats_destroyStatsCounter(statsobj_t *stats, ctr_t **ref) { if (*ref != NULL) { if (stats != NULL) { statsobj.DestructCounter(stats, *ref); } else { statsobj.DestructUnlinkedCounter(*ref); } *ref = NULL; } } static void /* assumes exclusive access to bucket */ dynstats_destroyCountersIn(dynstats_bucket_t *b, htable *table, dynstats_ctr_t *ctrs) { dynstats_ctr_t *ctr; int ctrs_purged = 0; hashtable_destroy(table, 0); while (ctrs != NULL) { ctr = ctrs; ctrs = ctrs->next; dynstats_destroyCtr(ctr); ctrs_purged++; } STATSCOUNTER_ADD(b->ctrMetricsPurged, b->mutCtrMetricsPurged, ctrs_purged); ATOMIC_SUB_unsigned(&b->metricCount, ctrs_purged, &b->mutMetricCount); } static void dynstats_destroyBucket(dynstats_bucket_t *b) { dynstats_buckets_t *bkts; sbool need_persist = 0; if (b == NULL) { return; } bkts = b->bkts; if (bkts == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket '%s' has no parent buckets structure, cannot destroy.", (char *)b->name); return; } pthread_rwlock_rdlock(&b->lock); need_persist = (b->persist_state_write_count_interval || b->persist_state_interval_secs || ATOMIC_LOAD_time_t_RELAXED(&b->persist_expiration_time, &b->mutPersistExpirationTime)); pthread_rwlock_unlock(&b->lock); /* Persist state BEFORE taking lock for destruction to avoid holding lock during I/O. * At this point the worker is stopped and this bucket is removed from the list, * so no other threads should be accessing it. */ if (need_persist) { pthread_rwlock_wrlock(&b->lock); persistBucketState(b, 0); pthread_rwlock_unlock(&b->lock); } /* Drop stats registry visibility before taking the bucket lock for * teardown. Stats scrapes hold mutStats while read notifiers take bucket * locks, so statsobj destruction must not run under bucket locks. */ if (b->stats != NULL) { statsobj.UnlinkAllCounters(b->stats); statsobj.Destruct(&b->stats); } pthread_rwlock_wrlock(&b->lock); dynstats_destroyCountersIn(b, b->table, b->ctrs); dynstats_destroyCountersIn(b, b->survivor_table, b->survivor_ctrs); dynstats_destroyStatsCounter(NULL, &b->pCtrFlushedBytes); dynstats_destroyStatsCounter(NULL, &b->pCtrFlushed); dynstats_destroyStatsCounter(NULL, &b->pCtrFlushedErrors); free(b->name); free(b->state_file_directory); pthread_rwlock_unlock(&b->lock); pthread_rwlock_destroy(&b->lock); pthread_mutex_destroy(&b->mutMetricCount); DESTROY_ATOMIC_HELPER_MUT64(b->mutPersistExpirationTime); dynstats_destroyStatsCounter(bkts->global_stats, &b->pOpsOverflowCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pNewMetricAddCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pNoMetricCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pMetricsPurgedCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pOpsIgnoredCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pPurgeTriggeredCtr); free(b); } /** * @brief Build one bucket meta-counter name and register it. * * Uses the caller-provided `metric_name_buff` layout: * `"."`, where `metric_suffix` points right after * the separator. The suffix copy is bounded and explicitly NUL-terminated. * * @param global_stats global dynstats stats object that owns the entry * @param metric_name_buff mutable full-name buffer reused across calls * @param metric_suffix write position for the suffix inside the buffer * @param suffix_literal counter suffix to append (e.g. "ops_overflow") * @param counter caller-owned counter storage to register * @param counter_ref out: created stats counter handle * * @note `statsobj.AddManagedCounter()` duplicates the counter name, so * `metric_name_buff` only needs to remain valid for the duration of this call. */ static rsRetVal dynstats_addBucketMetaCounter(statsobj_t *global_stats, uchar *metric_name_buff, uchar *metric_suffix, const uchar *suffix_literal, intctr_t *counter, ctr_t **counter_ref) { ustrncpy(metric_suffix, suffix_literal, DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH); /* Clamp at fixed boundary in case source length reaches/exceeds max copy width. */ metric_suffix[DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH] = '\0'; return statsobj.AddManagedCounter(global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, counter, counter_ref, 1); } /** * @brief Register the built-in meta counters for one dynstats bucket. * * This creates and registers counters like `ops_overflow`, `new_metric_add`, * and related operational metrics under the global dynstats stats object. * * @param bkts dynstats bucket collection that owns the global stats object * @param b bucket that owns the counter storage and resulting refs * @param name bucket name used as metric-name prefix * * @note Counter names are generated once during bucket creation time. */ static rsRetVal dynstats_addBucketMetrics(dynstats_buckets_t *bkts, dynstats_bucket_t *b, const uchar *name) { uchar *metric_name_buff, *metric_suffix; const uchar *suffix_literal; size_t name_len; DEFiRet; name_len = ustrlen(name); /* Layout: "" + '.' + + '\0' => +2 avoids off-by-one overflow. */ CHKmalloc(metric_name_buff = malloc(name_len + DYNSTATS_MAX_BUCKET_NS_METRIC_LENGTH + 2)); /* Name generation algorithm: * 1) Seed reusable buffer with "\0". * 2) Move to the end and append '.' once. * 3) For each suffix, overwrite only the suffix segment and terminate. * This avoids repeated full-string formatting and keeps bounds explicit. */ memcpy(metric_name_buff, name, name_len + 1); metric_suffix = metric_name_buff + name_len; *metric_suffix = DYNSTATS_METRIC_NAME_SEPARATOR; metric_suffix++; suffix_literal = UCHAR_CONSTANT("ops_overflow"); STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrOpsOverflow), &b->pOpsOverflowCtr)); suffix_literal = UCHAR_CONSTANT("new_metric_add"); STATSCOUNTER_INIT(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrNewMetricAdd), &b->pNewMetricAddCtr)); suffix_literal = UCHAR_CONSTANT("no_metric"); STATSCOUNTER_INIT(b->ctrNoMetric, b->mutCtrNoMetric); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrNoMetric), &b->pNoMetricCtr)); suffix_literal = UCHAR_CONSTANT("metrics_purged"); STATSCOUNTER_INIT(b->ctrMetricsPurged, b->mutCtrMetricsPurged); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrMetricsPurged), &b->pMetricsPurgedCtr)); suffix_literal = UCHAR_CONSTANT("ops_ignored"); STATSCOUNTER_INIT(b->ctrOpsIgnored, b->mutCtrOpsIgnored); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrOpsIgnored), &b->pOpsIgnoredCtr)); suffix_literal = UCHAR_CONSTANT("purge_triggered"); STATSCOUNTER_INIT(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered); CHKiRet(dynstats_addBucketMetaCounter(bkts->global_stats, metric_name_buff, metric_suffix, suffix_literal, &(b->ctrPurgeTriggered), &b->pPurgeTriggeredCtr)); finalize_it: free(metric_name_buff); if (iRet != RS_RET_OK) { dynstats_destroyStatsCounter(bkts->global_stats, &b->pOpsOverflowCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pNewMetricAddCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pNoMetricCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pMetricsPurgedCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pOpsIgnoredCtr); dynstats_destroyStatsCounter(bkts->global_stats, &b->pPurgeTriggeredCtr); } RETiRet; } static void no_op_free(void __attribute__((unused)) * ignore) {} static rsRetVal /* assumes exclusive access to bucket */ dynstats_rebuildSurvivorTable(dynstats_bucket_t *b) { htable *survivor_table = NULL; htable *new_table = NULL; size_t htab_sz; DEFiRet; htab_sz = (size_t)(DYNSTATS_HASHTABLE_SIZE_OVERPROVISIONING * b->maxCardinality + 1); if (b->table == NULL) { CHKmalloc(survivor_table = create_hashtable(htab_sz, hash_from_string, key_equals_string, no_op_free)); } CHKmalloc(new_table = create_hashtable(htab_sz, hash_from_string, key_equals_string, no_op_free)); statsobj.UnlinkAllCounters(b->stats); if (b->survivor_table != NULL) { dynstats_destroyCountersIn(b, b->survivor_table, b->survivor_ctrs); } b->survivor_table = (b->table == NULL) ? survivor_table : b->table; b->survivor_ctrs = b->ctrs; b->table = new_table; b->ctrs = NULL; finalize_it: if (iRet != RS_RET_OK) { LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to evict " "TTL-expired metrics of dyn-stats bucket named: %s", b->name); if (new_table == NULL) { LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to " "initialize hash-table for dyn-stats bucket named: %s", b->name); } else { assert(0); /* "can" not happen -- triggers Coverity CID 184307: hashtable_destroy(new_table, 0); We keep this as guard should code above change in the future */ } if (b->table == NULL) { if (survivor_table == NULL) { LogError(errno, RS_RET_INTERNAL_ERROR, "error trying to initialize " "ttl-survivor hash-table for dyn-stats bucket named: %s", b->name); } else { hashtable_destroy(survivor_table, 0); } } } RETiRet; } static rsRetVal dynstats_resetBucket(dynstats_bucket_t *b) { DEFiRet; pthread_rwlock_wrlock(&b->lock); CHKiRet(dynstats_rebuildSurvivorTable(b)); STATSCOUNTER_INC(b->ctrPurgeTriggered, b->mutCtrPurgeTriggered); timeoutComp(&b->metricCleanupTimeout, b->unusedMetricLife); finalize_it: pthread_rwlock_unlock(&b->lock); RETiRet; } static void dynstats_resetIfExpired(dynstats_bucket_t *b) { long timeout; pthread_rwlock_rdlock(&b->lock); timeout = timeoutVal(&b->metricCleanupTimeout); pthread_rwlock_unlock(&b->lock); if (timeout == 0) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "dynstats: bucket '%s' is being reset", b->name); dynstats_resetBucket(b); } } static void dynstats_readCallback(statsobj_t __attribute__((unused)) * ignore, void *b) { dynstats_buckets_t *bkts; bkts = &runConf->dynstats_buckets; pthread_rwlock_rdlock(&bkts->lock); dynstats_resetIfExpired((dynstats_bucket_t *)b); pthread_rwlock_unlock(&bkts->lock); } static rsRetVal dynstats_initNewBucketStats(dynstats_bucket_t *b) { DEFiRet; CHKiRet(statsobj.Construct(&b->stats)); CHKiRet(statsobj.SetOrigin(b->stats, UCHAR_CONSTANT("dynstats.bucket"))); CHKiRet(statsobj.SetName(b->stats, b->name)); CHKiRet(statsobj.SetReportingNamespace(b->stats, UCHAR_CONSTANT("values"))); char bucket_stat_name[512]; int bufsize = sizeof(bucket_stat_name); int rc; rc = snprintf(bucket_stat_name, bufsize, "%s_%s", b->name, "flushed_bytes"); if (rc < 0 || rc >= bufsize) { LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: buffer too small for stat name"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } STATSCOUNTER_INIT(b->ctrFlushedBytes, b->mutCtrFlushedBytes); CHKiRet(statsobj.AddManagedCounter(b->stats, (uchar *)bucket_stat_name, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &b->ctrFlushedBytes, &b->pCtrFlushedBytes, 0)); rc = snprintf(bucket_stat_name, bufsize, "%s_%s", b->name, "flushed_counts"); if (rc < 0 || rc >= bufsize) { LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: buffer too small for stat name"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } STATSCOUNTER_INIT(b->ctrFlushed, b->mutCtrFlushed); CHKiRet(statsobj.AddManagedCounter(b->stats, (uchar *)bucket_stat_name, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &b->ctrFlushed, &b->pCtrFlushed, 0)); rc = snprintf(bucket_stat_name, bufsize, "%s_%s", b->name, "flush_errors"); if (rc < 0 || rc >= bufsize) { LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: buffer too small for stat name"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } STATSCOUNTER_INIT(b->ctrFlushedErrors, b->mutCtrFlushedErrors); CHKiRet(statsobj.AddManagedCounter(b->stats, (uchar *)bucket_stat_name, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &b->ctrFlushedErrors, &b->pCtrFlushedErrors, 0)); statsobj.SetReadNotifier(b->stats, dynstats_readCallback, b); CHKiRet(statsobj.ConstructFinalize(b->stats)); finalize_it: RETiRet; } /* try to open a file which has a state file. If the state file does not * exist or cannot be read, an error is returned. */ static rsRetVal ATTR_NONNULL(1) loadPersistedState(dynstats_bucket_t *b) { DEFiRet; struct stat stat_buf; uchar statefile[MAXFNAME]; uchar state_file_path[MAXFNAME]; json_object *json_obj = NULL; uchar *const state_file_name = getStateFileName(b, statefile, sizeof(statefile)); assert(state_file_name); /* Get full path and file name */ if (getFullStateFileName(b, state_file_name, state_file_path, sizeof(state_file_path)) == -1) { ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("opening statefile for '%s', state file '%s'\n", b->name, state_file_path); /* check if the file exists */ if (stat((char *)state_file_path, &stat_buf) == -1) { LogMsg(0, RS_RET_FILE_NOT_FOUND, LOG_INFO, "dyn_stats: warning state file doesn't exist: '%s'", state_file_path); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } json_obj = fjson_object_from_file((const char *)state_file_path); if (!json_obj) { LogMsg(0, RS_RET_JSON_UNUSABLE, LOG_INFO, "dyn_stats: error couldn't read json from file: '%s'", state_file_path); ABORT_FINALIZE(RS_RET_JSON_UNUSABLE); } /* expected json format * { "name": "bucketname", "values": { "foo": "1" } } */ json_object *json_obj_metrics = NULL; if (json_object_object_get_ex(json_obj, DYNSTATS_BUCKET_PERSIST_VALUES_NAME, &json_obj_metrics)) { struct json_object_iterator it, itEnd; for (it = json_object_iter_begin(json_obj_metrics), itEnd = json_object_iter_end(json_obj_metrics); !json_object_iter_equal(&it, &itEnd); json_object_iter_next(&it)) { const uchar *metric = (const uchar *)json_object_iter_peek_name(&it); if (metric == NULL) { continue; } json_object *val_obj = json_object_iter_peek_value(&it); if (val_obj == NULL) { continue; } if (!json_object_is_type(val_obj, json_type_int)) { LogError(0, RS_RET_JSON_UNUSABLE, "dynstats: state file '%s' contains non-integer value for metric '%s'", state_file_path, metric); continue; } int64_t val_signed = json_object_get_int64(val_obj); if (val_signed < 0) { LogError(0, RS_RET_JSON_UNUSABLE, "dynstats: state file '%s' contains negative value %lld for metric '%s' - ignoring", state_file_path, (long long)val_signed, metric); continue; } uint64_t val = (uint64_t)val_signed; // now add the counter to the bucket with offset rsRetVal iRetCtr = dynstats_addNewCtr(b, metric, 0, val); if (iRetCtr != RS_RET_OK) { LogError(0, iRetCtr, "dynstats: failed to add metric '%s' from state file", metric); } } } finalize_it: if (json_obj != NULL) { json_object_put(json_obj); } RETiRet; } static rsRetVal dynstats_openStateFile(dynstats_bucket_t *b) { DEFiRet; CHKiRet(loadPersistedState(b)); finalize_it: RETiRet; } /** * @brief Create and initialize a dynstats bucket from configuration values. * * The function allocates bucket state, initializes runtime/stat structures, * registers per-bucket meta counters, optionally loads persisted state, and * links the bucket into the active dynstats list. * * @param name bucket name * @param resettable whether bucket counters are resettable * @param maxCardinality maximum tracked metric keys in bucket * @param unusedMetricLife metric TTL in seconds * @param persistStateInterval persist after this many updates (0 disables) * @param persistStateTimeInterval persist after this many seconds (0 disables) * @param stateFileDirectory optional directory for state files */ static rsRetVal dynstats_newBucket(const uchar *name, uint8_t resettable, uint32_t maxCardinality, uint32_t unusedMetricLife, uint32_t persistStateInterval, uint32_t persistStateTimeInterval, const uchar *stateFileDirectory) { dynstats_bucket_t *b; dynstats_buckets_t *bkts; uint8_t lock_initialized, metric_count_mutex_initialized, persist_expiration_mutex_initialized; pthread_rwlockattr_t bucket_lock_attr; DEFiRet; lock_initialized = metric_count_mutex_initialized = persist_expiration_mutex_initialized = 0; b = NULL; bkts = &loadConf->dynstats_buckets; if (bkts->initialized) { if (dynstats_findBucket(name) != NULL) { LogMsg(0, RS_RET_OK, LOG_WARNING, "dynstats: duplicate bucket name '%s' in current config set; impstats output may be ambiguous", name); } CHKmalloc(b = calloc(1, sizeof(dynstats_bucket_t))); b->bkts = bkts; b->resettable = resettable; b->maxCardinality = maxCardinality; b->unusedMetricLife = 1000 * unusedMetricLife; b->persist_state_write_count_interval = persistStateInterval; b->persist_state_interval_secs = persistStateTimeInterval; b->n_updates = 0; CHKmalloc(b->name = ustrdup(name)); if (stateFileDirectory) { CHKmalloc(b->state_file_directory = ustrdup(stateFileDirectory)); } pthread_rwlockattr_init(&bucket_lock_attr); #ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP pthread_rwlockattr_setkind_np(&bucket_lock_attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #endif pthread_rwlock_init(&b->lock, &bucket_lock_attr); lock_initialized = 1; pthread_mutex_init(&b->mutMetricCount, NULL); metric_count_mutex_initialized = 1; INIT_ATOMIC_HELPER_MUT64(b->mutPersistExpirationTime); persist_expiration_mutex_initialized = 1; CHKiRet(dynstats_initNewBucketStats(b)); CHKiRet(dynstats_resetBucket(b)); CHKiRet(dynstats_addBucketMetrics(bkts, b, name)); if (b && (b->persist_state_write_count_interval || b->persist_state_interval_secs)) { time_t now; rsRetVal rc = dynstats_openStateFile(b); if (rc != RS_RET_OK) { LogMsg(0, rc, LOG_INFO, "dynstats: openStateFile failed - " "there should be messages before this one with the reason.\n"); } if (datetime.GetTime(&now) == -1) { ABORT_FINALIZE(RS_RET_INVLD_TIME); } pthread_rwlock_wrlock(&b->lock); if (persistStateTimeInterval > 0) { ATOMIC_STORE_time_t_RELAXED(&b->persist_expiration_time, &b->mutPersistExpirationTime, now + persistStateTimeInterval); } pthread_rwlock_unlock(&b->lock); /* Start the file write worker if not already started */ startFileWriteWorker(bkts); } pthread_rwlock_wrlock(&bkts->lock); if (bkts->list == NULL) { bkts->list = b; } else { b->next = bkts->list; bkts->list = b; } pthread_rwlock_unlock(&bkts->lock); } else { LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket creation failed, as " "global-initialization of buckets was unsuccessful"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } finalize_it: if (iRet != RS_RET_OK) { if (b != NULL) { if (lock_initialized) { if (!metric_count_mutex_initialized) { pthread_mutex_init(&b->mutMetricCount, NULL); } if (!persist_expiration_mutex_initialized) { INIT_ATOMIC_HELPER_MUT64(b->mutPersistExpirationTime); } dynstats_destroyBucket(b); } else { free(b->name); free(b->state_file_directory); free(b); } } } RETiRet; } /** * @brief Process one `dyn_stats` config object and create the bucket. * * Parses config parameters, applies defaults, and forwards the normalized * values to `dynstats_newBucket()`. * * @param o parsed config object for dynstats bucket creation */ rsRetVal dynstats_processCnf(struct cnfobj *o) { struct cnfparamvals *pvals; short i; uchar *name = NULL; uchar *stateFileDirectory = NULL; uint8_t resettable = DYNSTATS_DEFAULT_RESETTABILITY; uint32_t maxCardinality = DYNSTATS_DEFAULT_MAX_CARDINALITY; uint32_t unusedMetricLife = DYNSTATS_DEFAULT_UNUSED_METRIC_LIFE; uint32_t persistStateInterval = DYNSTATS_DEFAULT_PERSISTSTATEINTERVAL; uint32_t persistStateTimeInterval = DYNSTATS_DEFAULT_PERSISTSTATE_TIME_INTERVAL; DEFiRet; pvals = nvlstGetParams(o->nvlst, &modpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_NAME)) { CHKmalloc(name = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_RESETTABLE)) { resettable = (pvals[i].val.d.n != 0); } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_MAX_CARDINALITY)) { maxCardinality = (uint32_t)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_UNUSED_METRIC_LIFE)) { unusedMetricLife = (uint32_t)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_PERSISTSTATEINTERVAL)) { persistStateInterval = (uint32_t)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_PERSISTSTATE_TIME_INTERVAL)) { persistStateTimeInterval = (uint32_t)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, DYNSTATS_PARAM_STATEFILE_DIRECTORY)) { CHKmalloc(stateFileDirectory = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { dbgprintf( "dyn_stats: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } if (name != NULL) { CHKiRet(dynstats_newBucket(name, resettable, maxCardinality, unusedMetricLife, persistStateInterval, persistStateTimeInterval, stateFileDirectory)); } finalize_it: free(name); free(stateFileDirectory); cnfparamvalsDestruct(pvals, &modpblk); RETiRet; } rsRetVal dynstats_initCnf(dynstats_buckets_t *bkts) { DEFiRet; bkts->initialized = 0; bkts->list = NULL; CHKiRet(statsobj.Construct(&bkts->global_stats)); CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("dynstats"))); CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global"))); CHKiRet(statsobj.SetReportingNamespace(bkts->global_stats, UCHAR_CONSTANT("values"))); CHKiRet(statsobj.ConstructFinalize(bkts->global_stats)); pthread_rwlock_init(&bkts->lock, NULL); bkts->initialized = 1; bkts->wrkrStarted = 0; CHKiRet(initFileWriteWorker(bkts)); finalize_it: if (iRet != RS_RET_OK) { statsobj.Destruct(&bkts->global_stats); } RETiRet; } void dynstats_destroyAllBuckets(rsconf_t *cnf) { dynstats_buckets_t *bkts; dynstats_bucket_t *b; if (cnf == NULL) { return; } bkts = &cnf->dynstats_buckets; if (bkts->initialized) { pthread_mutex_lock(&bkts->work_q.mut); if (bkts->wrkrStarted) { pthread_mutex_unlock(&bkts->work_q.mut); stopFileWriteWorker(bkts); } else { pthread_mutex_unlock(&bkts->work_q.mut); } while (1) { pthread_rwlock_wrlock(&bkts->lock); b = bkts->list; if (b == NULL) { pthread_rwlock_unlock(&bkts->lock); break; } bkts->list = b->next; b->next = NULL; pthread_rwlock_unlock(&bkts->lock); dynstats_destroyBucket(b); } if (bkts->global_stats != NULL) { statsobj.UnlinkAllCounters(bkts->global_stats); statsobj.Destruct(&bkts->global_stats); } pthread_rwlock_destroy(&bkts->lock); destroyFileWriteWorker(bkts); } } dynstats_bucket_t *dynstats_findBucket(const uchar *name) { dynstats_buckets_t *bkts; dynstats_bucket_t *b; bkts = &loadConf->dynstats_buckets; if (bkts->initialized) { pthread_rwlock_rdlock(&bkts->lock); b = bkts->list; while (b != NULL) { if (!ustrcmp(name, b->name)) { break; } b = b->next; } pthread_rwlock_unlock(&bkts->lock); } else { b = NULL; LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: bucket lookup failed, as global-initialization " "of buckets was unsuccessful"); } return b; } static rsRetVal dynstats_createCtr(dynstats_bucket_t *b, const uchar *metric, dynstats_ctr_t **ctr) { DEFiRet; CHKmalloc(*ctr = calloc(1, sizeof(dynstats_ctr_t))); CHKmalloc((*ctr)->metric = ustrdup(metric)); STATSCOUNTER_INIT((*ctr)->ctr, (*ctr)->mutCtr); CHKiRet(statsobj.AddManagedCounter(b->stats, metric, ctrType_IntCtr, b->resettable ? CTR_FLAG_MUST_RESET : CTR_FLAG_NONE, &(*ctr)->ctr, &(*ctr)->pCtr, 0)); finalize_it: if (iRet != RS_RET_OK) { if ((*ctr) != NULL) { free((*ctr)->metric); free(*ctr); *ctr = NULL; } } RETiRet; } /* not supported in older platforms - disable */ #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif /* * Helper function adapted from imfile of the same name - possible candidate for refactor. * Updates configured state file with the state of the specified bucket */ static rsRetVal ATTR_NONNULL(1) writeStateFile(dynstats_bucket_t *b, const char *file_name, const char *content) { assert(b); const size_t toWrite = strlen(content); ssize_t w = 0; int fd = -1; char *tmp_file_name = NULL; DEFiRet; /* Create temp file name */ size_t name_len = strlen(file_name); CHKmalloc(tmp_file_name = malloc(name_len + 5)); /* .tmp + null */ snprintf(tmp_file_name, name_len + 5, "%s.tmp", file_name); fd = open(tmp_file_name, O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600); if (fd < 0) { LogError(errno, RS_RET_IO_ERROR, "dynstats: cannot open state file '%s' for " "persisting file state - some data will probably be duplicated " "on next startup", tmp_file_name); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* note: write is buffered; actual sync happens via atomicWriteStateFile */ w = write(fd, content, toWrite); if (w != (ssize_t)toWrite) { LogError(errno, RS_RET_IO_ERROR, "dynstats: partial write to state file '%s' " "this may cause trouble in the future. We will try to delete the " "state file, as this provides most consistent state", tmp_file_name); unlink(tmp_file_name); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* Sync to disk to ensure data is safe before rename */ if (fsync(fd) != 0) { LogError(errno, RS_RET_IO_ERROR, "dynstats: fsync failed for '%s'", tmp_file_name); unlink(tmp_file_name); ABORT_FINALIZE(RS_RET_IO_ERROR); } if (close(fd) != 0) { LogError(errno, RS_RET_IO_ERROR, "dynstats: close failed for '%s'", tmp_file_name); unlink(tmp_file_name); fd = -1; ABORT_FINALIZE(RS_RET_IO_ERROR); } fd = -1; if (rename(tmp_file_name, file_name) != 0) { LogError(errno, RS_RET_IO_ERROR, "dynstats: rename failed from '%s' to '%s'", tmp_file_name, file_name); unlink(tmp_file_name); ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: if (fd >= 0) { close(fd); } free(tmp_file_name); if (iRet == RS_RET_IO_ERROR) { STATSCOUNTER_INC(b->ctrFlushedErrors, b->mutCtrFlushedErrors); } if (iRet == RS_RET_OK) { STATSCOUNTER_ADD(b->ctrFlushedBytes, b->mutCtrFlushedBytes, w); STATSCOUNTER_INC(b->ctrFlushed, b->mutCtrFlushed); } RETiRet; } static const uchar *getStateFileDir(dynstats_bucket_t *b) { const uchar *wrkdir; assert(b != NULL); if (b->state_file_directory == NULL) { rsconf_t *cnf = (runConf != NULL) ? runConf : loadConf; wrkdir = glblGetWorkDirRaw(cnf); } else { wrkdir = b->state_file_directory; } return (wrkdir); } /* * Helper function to combine statefile and workdir */ static int getFullStateFileName(dynstats_bucket_t *b, uchar *pszstatefile, uchar *pszout, int buflen) { int lenout; const uchar *pszworkdir; /* Get Raw Workdir, if it is NULL we need to propper handle it */ pszworkdir = getStateFileDir(b); /* Construct file name */ lenout = snprintf((char *)pszout, buflen, "%s/%s", (char *)(pszworkdir == NULL ? "." : (char *)pszworkdir), (char *)pszstatefile); if (lenout >= buflen) { LogError(0, RS_RET_ERR, "dynstats: state file path too long for bucket '%s'", (char *)b->name); return -1; } /* return out length */ return lenout; } /* this generates a state file name suitable for the given file. To avoid * malloc calls, it must be passed a buffer which should be MAXFNAME large. * Note: the buffer is not necessarily populated ... always ONLY use the * RETURN VALUE! * This function is guranteed to work only on config data and DOES NOT * open or otherwise modify disk file state. */ static uchar *ATTR_NONNULL(1, 2) getStateFileName(const dynstats_bucket_t *const pbucket, uchar *const __restrict__ buf, const size_t lenbuf) { DBGPRINTF("getStateFileName for '%s'\n", pbucket->name); if (strchr((const char *)pbucket->name, '/') != NULL) { /* Basic path traversal protection - bucket names should not contain slashes */ char sanitized_name[MAXFNAME]; const size_t bucket_name_len = strlen((const char *)pbucket->name); const size_t name_len = bucket_name_len < sizeof(sanitized_name) - 1 ? bucket_name_len : sizeof(sanitized_name) - 1; memcpy(sanitized_name, pbucket->name, name_len); sanitized_name[name_len] = '\0'; for (char *p = sanitized_name; *p; p++) { if (*p == '/') *p = '_'; } snprintf((char *)buf, lenbuf, "dynstats-state:%s", sanitized_name); LogMsg(0, RS_RET_OK, LOG_WARNING, "dynstats: bucket name '%s' contains slashes, " "sanitized to '%s' for state file", pbucket->name, sanitized_name); } else { snprintf((char *)buf, lenbuf, "dynstats-state:%s", pbucket->name); } DBGPRINTF("getStateFileName: state file name now is %s\n", buf); return buf; } /* This function persists dynstats_bucket_t data, which for the time being: * metric bucket counters */ static rsRetVal ATTR_NONNULL(1) persistBucketState(dynstats_bucket_t *b, sbool useWorker) { DEFiRet; uchar statefile[MAXFNAME]; uchar statefname[MAXFNAME]; struct json_object *jval = NULL; struct json_object *json = NULL; struct json_object *json_bucket_values = NULL; assert(b->name); uchar *const statefn = getStateFileName(b, statefile, sizeof(statefile)); /* Get full path and file name */ if (getFullStateFileName(b, statefn, statefname, sizeof(statefname)) == -1) { ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("persisting state for '%s', state file '%s'\n", b->name, statefname); CHKmalloc(json = json_object_new_object()); jval = json_object_new_string((char *)b->name); if (jval == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } json_object_object_add(json, DYNSTATS_BUCKET_PERSIST_NAME, jval); // walk the hashtable and create a val for each CHKmalloc(json_bucket_values = json_object_new_object()); json_object_object_add(json, DYNSTATS_BUCKET_PERSIST_VALUES_NAME, json_bucket_values); if (b->table != NULL && hashtable_count(b->table) > 0) { struct hashtable_itr *itr = hashtable_iterator(b->table); if (itr == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "dynstats: failed to allocate hashtable iterator"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } dynstats_ctr_t *pctr = NULL; do { pctr = (dynstats_ctr_t *)hashtable_iterator_value(itr); jval = json_object_new_int64(pctr->ctr); if (jval == NULL) { free(itr); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } json_object_object_add(json_bucket_values, (const char *)pctr->metric, jval); } while (hashtable_iterator_advance(itr)); free(itr); } const char *jstr = json_object_to_json_string_ext(json, JSON_C_TO_STRING_PLAIN); if (jstr == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "dynstats: failed to serialize JSON"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (useWorker) { CHKiRet(enqueueFileWriteTask(b, (const char *)statefname, jstr)); } else { CHKiRet(writeStateFile(b, (const char *)statefname, jstr)); } finalize_it: if (iRet != RS_RET_OK) { LogError(0, iRet, "dynstats: could not persist state " "file %s - data may be repeated on next " "startup. Is WorkDirectory set?", statefname); } if (json) { json_object_put(json); } RETiRet; } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" /* TODO: how can we fix these warnings? */ #endif static rsRetVal dynstats_addNewCtr(dynstats_bucket_t *b, const uchar *metric, uint8_t doInitialIncrement, uint64_t doInitialOffset) { dynstats_ctr_t *ctr = NULL; dynstats_ctr_t *found_ctr, *survivor_ctr, *effective_ctr = NULL; int created = 0; int bucketLockHeld = 0; int bucketMutationCommitted = 0; int destroyCreatedCtrOnFailure = 0; int survivorUnlinked = 0; int tableInserted = 0; uchar *copy_of_key = NULL; DEFiRet; created = 0; ctr = NULL; if ((unsigned)ATOMIC_LOAD_32BIT_unsigned(&b->metricCount, &b->mutMetricCount) >= b->maxCardinality) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKiRet(dynstats_createCtr(b, metric, &ctr)); CHKiConcCtrl(pthread_rwlock_wrlock(&b->lock)); bucketLockHeld = 1; found_ctr = (dynstats_ctr_t *)hashtable_search(b->table, ctr->metric); if (found_ctr != NULL) { if (doInitialIncrement) { STATSCOUNTER_INC(found_ctr->ctr, found_ctr->mutCtr); } } else { copy_of_key = ustrdup(ctr->metric); if (copy_of_key != NULL) { survivor_ctr = (dynstats_ctr_t *)hashtable_search(b->survivor_table, ctr->metric); if (survivor_ctr == NULL) { effective_ctr = ctr; } else { effective_ctr = survivor_ctr; if (survivor_ctr->prev != NULL) { survivor_ctr->prev->next = survivor_ctr->next; } if (survivor_ctr->next != NULL) { survivor_ctr->next->prev = survivor_ctr->prev; } if (survivor_ctr == b->survivor_ctrs) { b->survivor_ctrs = survivor_ctr->next; } survivorUnlinked = 1; } if ((created = hashtable_insert(b->table, copy_of_key, effective_ctr))) { tableInserted = 1; CHKiRet(statsobj.AddPreCreatedCtr(b->stats, effective_ctr->pCtr)); } } if (created) { if (b->ctrs != NULL) { b->ctrs->prev = effective_ctr; } effective_ctr->prev = NULL; effective_ctr->next = b->ctrs; b->ctrs = effective_ctr; if (doInitialIncrement) { STATSCOUNTER_INC(effective_ctr->ctr, effective_ctr->mutCtr); } if (doInitialOffset) { // doInitialOffset regardless of the state of GatherStats effective_ctr->ctr += doInitialOffset; } } } bucketMutationCommitted = 1; const int ret = pthread_rwlock_unlock(&b->lock); if (ret != 0) { LogError(ret, RS_RET_CONC_CTRL_ERR, "dynstats: error unlocking bucket mutex"); abort(); } bucketLockHeld = 0; if (found_ctr != NULL) { // ignore } else if (created && (effective_ctr != survivor_ctr)) { ATOMIC_INC(&b->metricCount, &b->mutMetricCount); STATSCOUNTER_INC(b->ctrNewMetricAdd, b->mutCtrNewMetricAdd); } else if (!created) { if (copy_of_key != NULL) { free(copy_of_key); } ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } finalize_it: if (bucketLockHeld) { if (iRet != RS_RET_OK && !bucketMutationCommitted && tableInserted) { if (effective_ctr == ctr) { destroyCreatedCtrOnFailure = 1; } hashtable_remove(b->table, copy_of_key); copy_of_key = NULL; created = 0; } if (iRet != RS_RET_OK && !bucketMutationCommitted && survivorUnlinked) { if (effective_ctr->prev != NULL) { effective_ctr->prev->next = effective_ctr; } if (effective_ctr->next != NULL) { effective_ctr->next->prev = effective_ctr; } if (b->survivor_ctrs == effective_ctr->next) { b->survivor_ctrs = effective_ctr; } } const int cleanupRet = pthread_rwlock_unlock(&b->lock); if (cleanupRet != 0) { LogError(cleanupRet, RS_RET_CONC_CTRL_ERR, "dynstats: error unlocking bucket mutex during error cleanup"); abort(); } } if ((destroyCreatedCtrOnFailure || (!created) || (effective_ctr != ctr)) && (ctr != NULL)) { dynstats_destroyCtr(ctr); } RETiRet; } #if defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic pop #endif static sbool dynstats_shouldPersist(dynstats_bucket_t *b, time_t now) { sbool shouldPersist = FALSE; time_t expire; if (b->persist_state_write_count_interval > 0) { if (ATOMIC_INC_AND_FETCH_unsigned(&b->n_updates, &b->mutMetricCount) >= b->persist_state_write_count_interval) { shouldPersist = TRUE; } } expire = ATOMIC_LOAD_time_t_ACQUIRE(&b->persist_expiration_time, &b->mutPersistExpirationTime); if (!shouldPersist && expire && now >= expire) { shouldPersist = TRUE; } return shouldPersist; } static sbool dynstats_shouldPersistLocked(dynstats_bucket_t *b, time_t now) { const time_t expire = ATOMIC_LOAD_time_t_RELAXED(&b->persist_expiration_time, &b->mutPersistExpirationTime); if (b->persist_state_write_count_interval > 0 && (uint32_t)ATOMIC_LOAD_32BIT_unsigned(&b->n_updates, &b->mutMetricCount) >= b->persist_state_write_count_interval) { return TRUE; } if (expire && now >= expire) { return TRUE; } return FALSE; } rsRetVal dynstats_inc(dynstats_bucket_t *b, uchar *metric) { dynstats_ctr_t *ctr = NULL; DEFiRet; if (!GatherStats) { FINALIZE; } if (ustrlen(metric) == 0) { STATSCOUNTER_INC(b->ctrNoMetric, b->mutCtrNoMetric); FINALIZE; } if (pthread_rwlock_tryrdlock(&b->lock) == 0) { ctr = (dynstats_ctr_t *)hashtable_search(b->table, metric); if (ctr != NULL) { STATSCOUNTER_INC(ctr->ctr, ctr->mutCtr); } pthread_rwlock_unlock(&b->lock); } else { ABORT_FINALIZE(RS_RET_NOENTRY); } if (ctr == NULL) { CHKiRet(dynstats_addNewCtr(b, metric, 1, 0)); } if (b->persist_state_write_count_interval == 0 && b->persist_state_interval_secs == 0) { FINALIZE; } time_t now; if (datetime.GetTime(&now) != -1) { if (dynstats_shouldPersist(b, now)) { pthread_rwlock_wrlock(&b->lock); if (dynstats_shouldPersistLocked(b, now)) { rsRetVal persist_ret = persistBucketState(b, 1); if (persist_ret == RS_RET_OK) { if (b->persist_state_write_count_interval) { ATOMIC_SUB_unsigned(&b->n_updates, b->persist_state_write_count_interval, &b->mutMetricCount); } if (b->persist_state_interval_secs) { ATOMIC_STORE_time_t_RELAXED(&b->persist_expiration_time, &b->mutPersistExpirationTime, now + b->persist_state_interval_secs); } } } pthread_rwlock_unlock(&b->lock); } } finalize_it: if (iRet != RS_RET_OK) { if (iRet == RS_RET_NOENTRY) { /* NOTE: this is not tested (because it requires very strong orchestration to guarantee contended lock for testing) */ STATSCOUNTER_INC(b->ctrOpsIgnored, b->mutCtrOpsIgnored); } else { STATSCOUNTER_INC(b->ctrOpsOverflow, b->mutCtrOpsOverflow); } } RETiRet; } typedef struct file_write_entry_s { STAILQ_ENTRY(file_write_entry_s) link; const char *name; const char *content; dynstats_bucket_t *bucket; } file_write_entry_t; static void processWorkItem(file_write_entry_t *task) { // write out the file /* NOTE: accessing task->bucket is safe here because stopFileWriteWorker() * is called before dynstats_destroyBucket() in dynstats_destroyAllBuckets(), * which ensures the worker thread has finished processing all pending tasks * before any bucket is freed. */ DBGPRINTF("dynstats: worker processing - '%s', '%.100s'\n", task->name, task->content); writeStateFile(task->bucket, task->name, task->content); } static void destroyFileWriteTask(file_write_entry_t *task) { free((void *)task->name); free((void *)task->content); free(task); } static void *fileWriteWorker(void *data) { dynstats_buckets_t *bkts = (dynstats_buckets_t *)data; if (!bkts) { return NULL; } pthread_mutex_lock(&bkts->work_q.mut); ++bkts->wrkrRunning; pthread_mutex_unlock(&bkts->work_q.mut); file_write_entry_t *task; while (1) { task = NULL; pthread_mutex_lock(&bkts->work_q.mut); if (bkts->work_q.size == 0) { --bkts->wrkrRunning; if (bkts->wrkrTermState == 1) { pthread_mutex_unlock(&bkts->work_q.mut); break; } else { DBGPRINTF("dynstats: worker %llu waiting on new work items\n", (unsigned long long)bkts->wrkrInfo.tid); pthread_cond_wait(&bkts->work_q.wakeup_worker, &bkts->work_q.mut); DBGPRINTF("dynstats: worker %llu awoken\n", (unsigned long long)bkts->wrkrInfo.tid); /* Check termination flag after waking up */ if (bkts->wrkrTermState == 1) { pthread_mutex_unlock(&bkts->work_q.mut); break; } } ++bkts->wrkrRunning; } if (bkts->work_q.size > 0) { task = STAILQ_FIRST(&bkts->work_q.q); STAILQ_REMOVE_HEAD(&bkts->work_q.q, link); bkts->work_q.size--; } pthread_mutex_unlock(&bkts->work_q.mut); if (task != NULL) { processWorkItem(task); destroyFileWriteTask(task); } } return NULL; } static rsRetVal initFileWriteWorker(dynstats_buckets_t *bkts) { DEFiRet; CHKiConcCtrl(pthread_mutex_init(&bkts->work_q.mut, NULL)); CHKiConcCtrl(pthread_cond_init(&bkts->work_q.wakeup_worker, NULL)); STAILQ_INIT(&bkts->work_q.q); bkts->work_q.size = 0; bkts->work_q.ctrMaxSz = 0; CHKiRet(statsobj.Construct(&bkts->work_q.stats)); CHKiRet(statsobj.SetName(bkts->work_q.stats, (uchar *)"file-write-worker")); CHKiRet(statsobj.SetOrigin(bkts->work_q.stats, (uchar *)"dynstats")); STATSCOUNTER_INIT(bkts->work_q.ctrEnq, bkts->work_q.mutCtrEnq); CHKiRet(statsobj.AddCounter(bkts->work_q.stats, UCHAR_CONSTANT("enqueued"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &bkts->work_q.ctrEnq)); CHKiRet(statsobj.AddCounter(bkts->work_q.stats, UCHAR_CONSTANT("maxqsize"), ctrType_Int, CTR_FLAG_NONE, &bkts->work_q.ctrMaxSz)); CHKiRet(statsobj.ConstructFinalize(bkts->work_q.stats)); finalize_it: RETiRet; } static void ATTR_NONNULL(1) destroyFileWriteWorker(dynstats_buckets_t *bkts) { file_write_entry_t *task; if (bkts->work_q.stats != NULL) { statsobj.Destruct(&bkts->work_q.stats); } pthread_mutex_lock(&bkts->work_q.mut); while (!STAILQ_EMPTY(&bkts->work_q.q)) { task = STAILQ_FIRST(&bkts->work_q.q); STAILQ_REMOVE_HEAD(&bkts->work_q.q, link); LogError(0, RS_RET_INTERNAL_ERROR, "dynstats: discarded enqueued io-work to allow shutdown " "- ignored"); destroyFileWriteTask(task); } bkts->work_q.size = 0; pthread_mutex_unlock(&bkts->work_q.mut); pthread_cond_destroy(&bkts->work_q.wakeup_worker); pthread_mutex_destroy(&bkts->work_q.mut); } static rsRetVal ATTR_NONNULL(1) enqueueFileWriteTask(dynstats_bucket_t *b, const char *file_name, const char *content) { file_write_entry_t *task; file_write_entry_t *queued_task; dynstats_buckets_t *bkts; DEFiRet; assert(b != NULL); bkts = b->bkts; if (!bkts) { FINALIZE; } task = NULL; pthread_mutex_lock(&bkts->work_q.mut); STAILQ_FOREACH(queued_task, &bkts->work_q.q, link) { if (queued_task->bucket == b) { char *new_content = strdup(content); if (new_content == NULL) { pthread_mutex_unlock(&bkts->work_q.mut); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } free((void *)queued_task->content); queued_task->content = new_content; pthread_mutex_unlock(&bkts->work_q.mut); FINALIZE; } } task = malloc(sizeof(file_write_entry_t)); if (task == NULL) { pthread_mutex_unlock(&bkts->work_q.mut); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } task->bucket = b; task->name = strdup(file_name); task->content = strdup(content); if (task->name == NULL || task->content == NULL) { if (task->name) free((void *)task->name); if (task->content) free((void *)task->content); free(task); task = NULL; /* Prevent double-free in error handler if it existed, though here finalize handles NULL task check */ pthread_mutex_unlock(&bkts->work_q.mut); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } STAILQ_INSERT_TAIL(&bkts->work_q.q, task, link); bkts->work_q.size++; STATSCOUNTER_INC(bkts->work_q.ctrEnq, bkts->work_q.mutCtrEnq); STATSCOUNTER_SETMAX_NOMUT(bkts->work_q.ctrMaxSz, bkts->work_q.size); if (bkts->work_q.size == 1) { pthread_cond_signal(&bkts->work_q.wakeup_worker); } pthread_mutex_unlock(&bkts->work_q.mut); finalize_it: if (iRet != RS_RET_OK) { if (task == NULL) { LogError(0, iRet, "dynstats: couldn't allocate memory to enqueue io-request - ignored"); } } RETiRet; } static void startFileWriteWorker(dynstats_buckets_t *bkts) { pthread_mutex_lock(&bkts->work_q.mut); /* locking to keep Coverity happy */ if (bkts->wrkrStarted) { pthread_mutex_unlock(&bkts->work_q.mut); return; } bkts->wrkrRunning = 0; bkts->wrkrTermState = 0; bkts->wrkrStarted = 1; int ret = pthread_create(&bkts->wrkrInfo.tid, NULL, fileWriteWorker, bkts); if (ret != 0) { bkts->wrkrStarted = 0; pthread_mutex_unlock(&bkts->work_q.mut); LogError(ret, RS_RET_INTERNAL_ERROR, "dynstats: failed to create worker thread"); return; } pthread_mutex_unlock(&bkts->work_q.mut); DBGPRINTF("dynstats: worker started tid: %llu workers\n", (unsigned long long)bkts->wrkrInfo.tid); } static void ATTR_NONNULL(1) stopFileWriteWorker(dynstats_buckets_t *bkts) { DBGPRINTF("dynstats: stopping worker pool\n"); pthread_mutex_lock(&bkts->work_q.mut); bkts->wrkrTermState = 1; pthread_cond_broadcast(&bkts->work_q.wakeup_worker); /* awake wrkr if not running */ pthread_mutex_unlock(&bkts->work_q.mut); pthread_join(bkts->wrkrInfo.tid, NULL); DBGPRINTF("dynstats: info: worker stopped\n"); } rsyslog-8.2608.0/runtime/PaxHeaders/nsd_mbedtls.c0000644000000000000000000000013215241075234016667 xustar0030 mtime=1787067036.604578276 30 atime=1787067036.750581009 30 ctime=1787067794.548727925 rsyslog-8.2608.0/runtime/nsd_mbedtls.c0000664000175000017500000014676715241075234016360 0ustar00rgerrger/* nsd_mbedtls.c * * An implementation of the nsd interface for Mbed TLS. * * Copyright (C) 2007-2023 Rainer Gerhards and Adiscon GmbH. * Copyright (C) 2023 CS Group. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "obj.h" #include "nsd_ptcp.h" #include "nsd_mbedtls.h" #include "rsconf.h" #include "net.h" #include "atomic.h" MODULE_TYPE_LIB MODULE_TYPE_KEEP /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl); DEFobjCurrIf(net); DEFobjCurrIf(nsd_ptcp); static int bTlsVersionWorkaroundReported = 0; #ifndef HAVE_ATOMIC_BUILTINS static DEF_ATOMIC_HELPER_MUT(mutTlsVersionWorkaroundReported); #define MUT_TLS_VERSION_WORKAROUND_REPORTED &mutTlsVersionWorkaroundReported #else #define MUT_TLS_VERSION_WORKAROUND_REPORTED NULL #endif /* Mbed TLS debug level (0..5) * 5 is the most logs. */ #define MBEDTLS_DEBUG_LEVEL 0 #define DEFAULT_MAX_DEPTH 5 static inline nsd_mbedtls_t *nsd_mbedtls_from_nsd(nsd_t *const pNsd) { return (nsd_mbedtls_t *)(void *)pNsd; } #if MBEDTLS_DEBUG_LEVEL > 0 static void debug(void __attribute__((unused)) * ctx, int __attribute__((unused)) level, const char *file, int line, const char *str) { dbgprintf("%s:%04d: %s", file, line, str); } #endif #define logMbedtlsError(err, mbedtls_err) \ do { \ char error_buf[128]; \ int aux = (mbedtls_err < 0 ? -mbedtls_err : mbedtls_err); \ const char *sig = (mbedtls_err < 0 ? "-" : ""); \ mbedtls_strerror(mbedtls_err, error_buf, 100); \ LogError(0, err, "Mbed TLS Error: %s0x%04X - %s", sig, aux, error_buf); \ } while (0) /* initialize Mbed TLS credential structure */ static rsRetVal mbedtlsInitCred(nsd_mbedtls_t *const pThis) { DEFiRet; const uchar *cafile; const uchar *crlfile; const uchar *keyFile; const uchar *certFile; int r; keyFile = (pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile; if (keyFile != NULL) { mbedtls_pk_free(&(pThis->pkey)); mbedtls_pk_init(&(pThis->pkey)); #if MBEDTLS_VERSION_MAJOR >= 3 if ((r = mbedtls_pk_parse_keyfile(&(pThis->pkey), (const char *)keyFile, NULL, mbedtls_ctr_drbg_random, &(pThis->ctr_drbg))) != 0) { #else if ((r = mbedtls_pk_parse_keyfile(&(pThis->pkey), (const char *)keyFile, NULL)) != 0) { #endif logMbedtlsError(RS_RET_NO_ERRCODE, r); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } pThis->bHaveKey = 1; } certFile = (pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile; if (certFile != NULL) { mbedtls_x509_crt_free(&(pThis->srvcert)); mbedtls_x509_crt_init(&(pThis->srvcert)); if ((r = mbedtls_x509_crt_parse_file(&(pThis->srvcert), (const char *)certFile)) != 0) { logMbedtlsError(RS_RET_NO_ERRCODE, r); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } pThis->bHaveCert = 1; } cafile = (pThis->pszCAFile == NULL) ? glbl.GetDfltNetstrmDrvrCAF(runConf) : pThis->pszCAFile; if (cafile != NULL) { mbedtls_x509_crt_free(&(pThis->cacert)); mbedtls_x509_crt_init(&(pThis->cacert)); if ((r = mbedtls_x509_crt_parse_file(&(pThis->cacert), (const char *)cafile)) != 0) { logMbedtlsError(RS_RET_NO_ERRCODE, r); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } pThis->bHaveCaCert = 1; } crlfile = (pThis->pszCRLFile == NULL) ? glbl.GetDfltNetstrmDrvrCRLF(runConf) : pThis->pszCRLFile; if (crlfile != NULL) { mbedtls_x509_crl_free(&(pThis->crl)); mbedtls_x509_crl_init(&(pThis->crl)); if ((r = mbedtls_x509_crl_parse_file(&(pThis->crl), (const char *)crlfile)) != 0) { logMbedtlsError(RS_RET_NO_ERRCODE, r); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } pThis->bHaveCrl = 1; } finalize_it: if (iRet) { LogMsg(0, RS_RET_ERR, LOG_ERR, "nsd mbedtls: error parsing crypto config"); } RETiRet; } /* globally initialize Mbed TLS */ static rsRetVal mbedtlsGlblInit(void) { DEFiRet; dbgprintf("mbedtlsGlblInit: Running Version: '%#010x'\n", MBEDTLS_VERSION_NUMBER); RETiRet; } static rsRetVal get_custom_string(char **out) { DEFiRet; struct timeval tv; struct tm tm; CHKiRet(gettimeofday(&tv, NULL)); if (localtime_r(&(tv.tv_sec), &tm) == NULL) { ABORT_FINALIZE(RS_RET_NO_ERRCODE); } if (asprintf(out, "nsd_mbedtls-%04d-%02d-%02d %02d:%02d:%02d:%08lld", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (long long)tv.tv_usec) == -1) { *out = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } finalize_it: RETiRet; } static rsRetVal mbedtlsInitSession(nsd_mbedtls_t *pThis) { DEFiRet; char *cust = NULL; CHKiRet(get_custom_string(&cust)); CHKiRet(mbedtls_ctr_drbg_seed(&(pThis->ctr_drbg), mbedtls_entropy_func, &(pThis->entropy), (const unsigned char *)cust, strlen(cust))); finalize_it: if (iRet != RS_RET_OK) { LogError(0, iRet, "mbedtlsInitSession failed to INIT Session"); } free(cust); RETiRet; } /* globally de-initialize Mbed TLS */ static rsRetVal mbedtlsGlblExit(void) { DEFiRet; RETiRet; } /* end a Mbed TLS session * The function checks if we have a session and ends it only if so. So it can * always be called, even if there currently is no session. */ static rsRetVal mbedtlsEndSess(nsd_mbedtls_t *pThis) { DEFiRet; int mbedtlsRet; if (pThis->bHaveSess) { while ((mbedtlsRet = mbedtls_ssl_close_notify(&(pThis->ssl))) != 0) { if (mbedtlsRet != MBEDTLS_ERR_SSL_WANT_READ && mbedtlsRet != MBEDTLS_ERR_SSL_WANT_WRITE) break; } pThis->bHaveSess = 0; } RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(nsd_mbedtls) /* be sure to specify the object type also in END macro! */ iRet = nsd_ptcp.Construct(&pThis->pTcp); mbedtls_ssl_init(&(pThis->ssl)); mbedtls_ssl_config_init(&(pThis->conf)); mbedtls_x509_crt_init(&(pThis->cacert)); mbedtls_x509_crl_init(&(pThis->crl)); mbedtls_pk_init(&(pThis->pkey)); mbedtls_x509_crt_init(&(pThis->srvcert)); mbedtls_ctr_drbg_init(&(pThis->ctr_drbg)); mbedtls_entropy_init(&(pThis->entropy)); pThis->bReportAuthErr = 1; #if MBEDTLS_DEBUG_LEVEL > 0 mbedtls_debug_set_threshold(MBEDTLS_DEBUG_LEVEL); #endif ENDobjConstruct(nsd_mbedtls) /* destructor for the nsd_mbedtls object */ BEGINobjDestruct(nsd_mbedtls) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsd_mbedtls) if (pThis->iMode == 1) { mbedtlsEndSess(pThis); } if (pThis->pTcp != NULL) { nsd_ptcp.Destruct(&pThis->pTcp); } free((void *)pThis->pszCAFile); free((void *)pThis->pszCRLFile); free((void *)pThis->pszKeyFile); free((void *)pThis->pszCertFile); free((void *)pThis->anzCipherSuites); free((void *)pThis->pszConnectHost); mbedtls_entropy_free(&(pThis->entropy)); mbedtls_ctr_drbg_free(&(pThis->ctr_drbg)); mbedtls_x509_crt_free(&(pThis->srvcert)); mbedtls_pk_free(&(pThis->pkey)); mbedtls_x509_crl_free(&(pThis->crl)); mbedtls_x509_crt_free(&(pThis->cacert)); mbedtls_ssl_config_free(&(pThis->conf)); mbedtls_ssl_free(&(pThis->ssl)); ENDobjDestruct(nsd_mbedtls) /* Set the driver mode. For us, this has the following meaning: * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS) * 1 - work in TLS mode * rgerhards, 2008-04-28 */ static rsRetVal SetMode(nsd_t *const pNsd, const int mode) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); dbgprintf("(tls) mode: %d\n", mode); if (mode != 0 && mode != 1) { LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by " "mbedtls netstream driver", mode); ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE); } pThis->iMode = mode; finalize_it: RETiRet; } /* Set the authentication mode. For us, the following is supported: * anon - no certificate checks whatsoever (discouraged, but supported) * x509/certvalid - (just) check certificate validity * x509/fingerprint - certificate fingerprint * x509/name - cerfificate name check * mode == NULL is valid and defaults to x509/name * rgerhards, 2008-05-16 */ static rsRetVal SetAuthMode(nsd_t *pNsd, uchar *mode) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (mode == NULL || !strcasecmp((char *)mode, "x509/name")) { pThis->authMode = MBEDTLS_AUTH_CERTNAME; } else if (!strcasecmp((char *)mode, "x509/fingerprint")) { pThis->authMode = MBEDTLS_AUTH_CERTFINGERPRINT; } else if (!strcasecmp((char *)mode, "x509/certvalid")) { pThis->authMode = MBEDTLS_AUTH_CERTVALID; } else if (!strcasecmp((char *)mode, "anon")) { pThis->authMode = MBEDTLS_AUTH_CERTANON; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by " "mbedtls netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetAuthMode to %s\n", (mode != NULL ? (char *)mode : "NULL")); finalize_it: RETiRet; } /* Set the PermitExpiredCerts mode. For us, the following is supported: * on - fail if certificate is expired * off - ignore expired certificates * warn - warn if certificate is expired * alorbach, 2018-12-20 */ static rsRetVal SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); /* default is set to off! */ if (mode == NULL || !strcasecmp((char *)mode, "off")) { pThis->permitExpiredCerts = MBEDTLS_EXPIRED_DENY; } else if (!strcasecmp((char *)mode, "warn")) { pThis->permitExpiredCerts = MBEDTLS_EXPIRED_WARN; } else if (!strcasecmp((char *)mode, "on")) { pThis->permitExpiredCerts = MBEDTLS_EXPIRED_PERMIT; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by " "mbedtls netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetPermitExpiredCerts: Set Mode %s/%d\n", (mode != NULL ? (char *)mode : "NULL"), pThis->permitExpiredCerts); /* TODO: clear stored IDs! */ finalize_it: RETiRet; } /* Set permitted peers. It is depending on the auth mode if this are * fingerprints or names. -- rgerhards, 2008-05-19 */ static rsRetVal SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (pPermPeers == NULL) FINALIZE; if (pThis->authMode != MBEDTLS_AUTH_CERTFINGERPRINT && pThis->authMode != MBEDTLS_AUTH_CERTNAME) { LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by " "mbedtls netstream driver in the configured authentication mode - ignored"); ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); } pThis->pPermPeers = pPermPeers; finalize_it: RETiRet; } /* Set the priority string, aka the cipher suite list in * decreasing priority order (most important priority first) */ static rsRetVal SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); int nCipherSuiteId; char *pCurrentPos; char *pSave; int count = 0; char *str = NULL; int *tmp; const char *separators = ",; \n"; ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (gnutlsPriorityString != NULL) { CHKmalloc(str = strdup((const char *)gnutlsPriorityString)); for (pCurrentPos = strtok_r(str, separators, &pSave); pCurrentPos != NULL; pCurrentPos = strtok_r(NULL, separators, &pSave)) { if (*pCurrentPos == '\0') { continue; } nCipherSuiteId = mbedtls_ssl_get_ciphersuite_id(pCurrentPos); if (nCipherSuiteId == 0) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "SetGnutlsPriorityString: %s " "is not supported", pCurrentPos); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } CHKmalloc(tmp = realloc(pThis->anzCipherSuites, (count + 2) * sizeof(int))); pThis->anzCipherSuites = tmp; pThis->anzCipherSuites[count] = nCipherSuiteId; pThis->anzCipherSuites[count + 1] = 0; ++count; } } finalize_it: free(str); RETiRet; } /* Set the driver cert extended key usage check setting * 0 - ignore contents of extended key usage * 1 - verify that cert contents is compatible with appropriate OID * jvymazal, 2019-08-16 */ static rsRetVal SetCheckExtendedKeyUsage(nsd_t *pNsd, int ChkExtendedKeyUsage) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (ChkExtendedKeyUsage != 0 && ChkExtendedKeyUsage != 1) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " "not supported by mbedtls netstream driver", ChkExtendedKeyUsage); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetCheckExtendedKeyUsage: %d\n", ChkExtendedKeyUsage); pThis->dataTypeCheck = ChkExtendedKeyUsage; finalize_it: RETiRet; } /* Set the driver name checking strictness * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored) * jvymazal, 2019-08-16 */ static rsRetVal SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (prioritizeSan != 0 && prioritizeSan != 1) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " "not supported by mbedtls netstream driver", prioritizeSan); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } pThis->bSANpriority = prioritizeSan; finalize_it: RETiRet; } /* Set the driver tls verifyDepth * alorbach, 2019-12-20 */ static rsRetVal SetTlsVerifyDepth(nsd_t *pNsd, int verifyDepth) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); pThis->DrvrVerifyDepth = verifyDepth; dbgprintf("SetTlsVerifyDepth: %d\n", pThis->DrvrVerifyDepth); RETiRet; } static rsRetVal SetTlsCAFile(nsd_t *pNsd, const uchar *const caFile) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); free((void *)pThis->pszCAFile); if (caFile == NULL) { pThis->pszCAFile = NULL; } else { CHKmalloc(pThis->pszCAFile = (const uchar *)strdup((const char *)caFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCRLFile(nsd_t *pNsd, const uchar *const crlFile) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); free((void *)pThis->pszCRLFile); if (crlFile == NULL) { pThis->pszCRLFile = NULL; } else { CHKmalloc(pThis->pszCRLFile = (const uchar *)strdup((const char *)crlFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCAExtraFiles(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: extra CA Files setting not supported by " "mbedtls netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); free((void *)pThis->pszKeyFile); if (pszFile == NULL) { pThis->pszKeyFile = NULL; } else { CHKmalloc(pThis->pszKeyFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCertFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); free((void *)pThis->pszCertFile); if (pszFile == NULL) { pThis->pszCertFile = NULL; } else { CHKmalloc(pThis->pszCertFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } static rsRetVal SetRemoteSNI(nsd_t __attribute__((unused)) * pNsd, uchar *pszRemoteSNI) { DEFiRet; if (pszRemoteSNI != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: remote SNI setting not supported by " "mbedtls netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsRevocationCheck(nsd_t *pNsd, int enabled) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); pThis->DrvrTlsRevocationCheck = (enabled != 0) ? 1 : 0; if (pThis->DrvrTlsRevocationCheck) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS revocation checking not supported by " "mbedtls netstream driver (mbedTLS does not implement OCSP checking)"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_mbedtls) who utilize ourselfs * for some of their functionality. -- rgerhards, 2008-04-18 */ static rsRetVal SetSock(nsd_t *pNsd, int sock) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); DBGPRINTF("SetSock for [%p]: Setting sock %d\n", pNsd, sock); nsd_ptcp.SetSock(pThis->pTcp, sock); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); assert(keepAliveIntvl >= 0); nsd_ptcp.SetKeepAliveIntvl(pThis->pTcp, keepAliveIntvl); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); assert(keepAliveProbes >= 0); nsd_ptcp.SetKeepAliveProbes(pThis->pTcp, keepAliveProbes); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); assert(keepAliveTime >= 0); nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime); RETiRet; } /* TCP user timeout option */ static rsRetVal SetTcpUserTimeout(nsd_t *pNsd, int tcpUserTimeout) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_mbedtls); assert(tcpUserTimeout >= 0); nsd_ptcp.SetTcpUserTimeout(pThis->pTcp, tcpUserTimeout); RETiRet; } /* abort a connection. This is meant to be called immediately * before the Destruct call. -- rgerhards, 2008-03-24 */ static rsRetVal Abort(nsd_t *pNsd) { nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_mbedtls); if (pThis->iMode == 0) { nsd_ptcp.Abort(pThis->pTcp); } RETiRet; } /* Allow Mbed TLS to read data from the network. */ static int mbedtlsNetRecv(void *ctx, unsigned char *buf, size_t len) { nsd_mbedtls_t *pThis = (nsd_mbedtls_t *)ctx; ssize_t slen = len; int oserr; DEFiRet; slen = recv(pThis->sock, buf, len, 0); oserr = errno; if (slen < 0) { switch (oserr) { case EAGAIN: #if EAGAIN != EWOULDBLOCK case EWOULDBLOCK: #endif case EINTR: ABORT_FINALIZE(MBEDTLS_ERR_SSL_WANT_READ); case EPIPE: case ECONNRESET: ABORT_FINALIZE(MBEDTLS_ERR_NET_CONN_RESET); default: ABORT_FINALIZE(MBEDTLS_ERR_NET_RECV_FAILED); } } iRet = slen; finalize_it: RETiRet; } /* Allow Mbed TLS to write data to the network. */ static int mbedtlsNetSend(void *ctx, const unsigned char *buf, size_t len) { nsd_mbedtls_t *pThis = (nsd_mbedtls_t *)ctx; ssize_t slen = len; DEFiRet; iRet = nsd_ptcp.Send(pThis->pTcp, (unsigned char *)buf, &slen); if (iRet < RS_RET_OK) { ABORT_FINALIZE(MBEDTLS_ERR_NET_SEND_FAILED); } iRet = slen; finalize_it: RETiRet; } static int mbedtlsAuthMode(nsd_mbedtls_t *const pThis) { int mode; switch (pThis->authMode) { case MBEDTLS_AUTH_CERTNAME: case MBEDTLS_AUTH_CERTVALID: case MBEDTLS_AUTH_CERTFINGERPRINT: if (pThis->dataTypeCheck == MBEDTLS_NONE) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; else mode = MBEDTLS_SSL_VERIFY_REQUIRED; break; case MBEDTLS_AUTH_CERTANON: mode = MBEDTLS_SSL_VERIFY_NONE; break; default: assert(0); /* this shall not happen! */ dbgprintf("ERROR: pThis->authMode %d invalid in nsd_mbedtls.c:%d\n", pThis->authMode, __LINE__); mode = MBEDTLS_SSL_VERIFY_REQUIRED; break; } return mode; } static void mbedtlsApplyTlsVersionWorkaround(nsd_mbedtls_t *const pThis, mbedtls_ssl_config *const conf) { #if defined(MBEDTLS_SSL_PROTO_TLS1_3) const char *reason = NULL; if (MBEDTLS_VERSION_NUMBER < 0x03060100) { reason = "because Mbed TLS versions before 3.6.1 have known TLS 1.3 regressions"; } else if (pThis->authMode == MBEDTLS_AUTH_CERTANON || pThis->authMode == MBEDTLS_AUTH_CERTVALID) { reason = "because Mbed TLS with TLS 1.3 fails rsyslog mixed-driver interoperability tests in weak authentication " "modes"; } else { return; } mbedtls_ssl_conf_max_tls_version(conf, MBEDTLS_SSL_VERSION_TLS1_2); if (ATOMIC_CAS(&bTlsVersionWorkaroundReported, 0, 1, MUT_TLS_VERSION_WORKAROUND_REPORTED)) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "mbedtls netstream driver: limiting TLS protocol version to TLS 1.2 %s", reason); } #else (void)pThis; (void)conf; #endif } /* Obtain fingerprint of crt in buf of size *len. * *len will be filled with actual fingerprint length on output. */ static rsRetVal mbedtlsCertFingerprint(const mbedtls_x509_crt *crt, mbedtls_md_type_t mdType, uchar *buf, size_t *len) { const mbedtls_md_info_t *mdInfo; size_t mdLen = 0; DEFiRet; mdInfo = mbedtls_md_info_from_type(mdType); if (mdInfo == NULL) ABORT_FINALIZE(RS_RET_CODE_ERR); mdLen = mbedtls_md_get_size(mdInfo); if (*len < mdLen) ABORT_FINALIZE(RS_RET_PROVIDED_BUFFER_TOO_SMALL); if (crt == NULL || buf == NULL) ABORT_FINALIZE(RS_RET_CODE_ERR); if (mbedtls_md(mdInfo, crt->raw.p, crt->raw.len, buf) != 0) ABORT_FINALIZE(RS_RET_CODE_ERR); finalize_it: *len = mdLen; RETiRet; } /* Convert a fingerprint to printable data. The conversion is carried out * according IETF I-D syslog-transport-tls-12. The fingerprint string is * returned in a new cstr object. It is the caller's responsibility to * destruct that object. * rgerhards, 2008-05-08 */ static rsRetVal GenFingerprintStr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr, const char *prefix) { cstr_t *pStr = NULL; uchar buf[4]; size_t i; DEFiRet; CHKiRet(rsCStrConstruct(&pStr)); CHKiRet(rsCStrAppendStrWithLen(pStr, (uchar *)prefix, strlen(prefix))); for (i = 0; i < sizeFingerprint; ++i) { snprintf((char *)buf, sizeof(buf), ":%2.2X", pFingerprint[i]); CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3)); } cstrFinalize(pStr); *ppStr = pStr; finalize_it: if (iRet != RS_RET_OK) { if (pStr != NULL) rsCStrDestruct(&pStr); } RETiRet; } static rsRetVal mbedtlsChkPeerFingerprint(nsd_mbedtls_t *pThis, mbedtls_x509_crt *crt) { uchar fingerprint[20]; uchar fingerprintSha256[32]; size_t size; size_t sizeSha256; cstr_t *pstrFingerprint = NULL; cstr_t *pstrFingerprintSha256 = NULL; int bFoundPositiveMatch; permittedPeers_t *pPeer; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_mbedtls); /* obtain the SHA1 fingerprint */ size = sizeof(fingerprint); sizeSha256 = sizeof(fingerprintSha256); CHKiRet(mbedtlsCertFingerprint(crt, MBEDTLS_MD_SHA1, fingerprint, &size)); CHKiRet(mbedtlsCertFingerprint(crt, MBEDTLS_MD_SHA256, fingerprintSha256, &sizeSha256)); CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint, "SHA1")); CHKiRet(GenFingerprintStr(fingerprintSha256, sizeSha256, &pstrFingerprintSha256, "SHA256")); dbgprintf("peer's certificate SHA1 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprint)); dbgprintf("peer's certificate SHA256 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprintSha256)); /* now search through the permitted peers to see if we can find a permitted one */ bFoundPositiveMatch = 0; pPeer = pThis->pPermPeers; while (pPeer != NULL && !bFoundPositiveMatch) { if (!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("mbedtlsChkPeerFingerprint: peer's certificate SHA1 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else if (!rsCStrSzStrCmp(pstrFingerprintSha256, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("mbedtlsChkPeerFingerprint: peer's certificate SHA256 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else { pPeer = pPeer->pNext; } } if (!bFoundPositiveMatch) { dbgprintf("invalid peer fingerprint, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer fingerprint '%s' unknown - we are " "not permitted to talk to it", cstrGetSzStrNoNULL(pstrFingerprint)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } finalize_it: if (pstrFingerprint != NULL) cstrDestruct(&pstrFingerprint); if (pstrFingerprintSha256 != NULL) cstrDestruct(&pstrFingerprintSha256); RETiRet; } /* Perform a match on ONE peer name obtained from the certificate. This name * is checked against the set of configured credentials. *pbFoundPositiveMatch is * set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized * to 0 by the caller (this is a performance enhancement as we expect to be * called multiple times). * TODO: implemet wildcards? * rgerhards, 2008-05-26 */ static rsRetVal mbedtlsChkOnePeerName(nsd_mbedtls_t *pThis, uchar *pszPeerID, int *pbFoundPositiveMatch) { permittedPeers_t *pPeer; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_mbedtls); assert(pszPeerID != NULL); assert(pbFoundPositiveMatch != NULL); if (pThis->pPermPeers) { /* do we have configured peer IDs? */ pPeer = pThis->pPermPeers; while (pPeer != NULL) { CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch)); if (*pbFoundPositiveMatch) break; pPeer = pPeer->pNext; } } else { /* we do not have configured peer IDs, so we use defaults */ if (pThis->pszConnectHost && !strcmp((char *)pszPeerID, (char *)pThis->pszConnectHost)) { *pbFoundPositiveMatch = 1; } } finalize_it: RETiRet; } static int mbedtlsNameHasEmbeddedNul(const unsigned char *name, size_t nameLen) { if (name == NULL || nameLen == 0) { return 0; } return memchr(name, '\0', nameLen) != NULL; } static int mbedtlsCnHasEmbeddedNul(const mbedtls_x509_crt *crt) { const mbedtls_x509_name *name; for (name = &crt->subject; name != NULL; name = name->next) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 && mbedtlsNameHasEmbeddedNul(name->val.p, name->val.len)) { return 1; } } return 0; } /* Get the common name (CN) from a certificate * Caller must free() the returned string */ static char *mbedtlsCnFromCrt(const mbedtls_x509_crt *crt) { const mbedtls_x509_name *name; for (name = &crt->subject; name != NULL; name = name->next) { if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0) { return strndup((const char *)(name->val.p), name->val.len); } } return NULL; } static rsRetVal mbedtlsChkPeerName(nsd_mbedtls_t *pThis, mbedtls_x509_crt *crt) { uchar lnBuf[256]; const mbedtls_x509_sequence *san; int bFoundPositiveMatch; char *str = NULL; int bHaveSAN = 0; cstr_t *pStr = NULL; DEFiRet; bFoundPositiveMatch = 0; CHKiRet(rsCStrConstruct(&pStr)); /* Check SANs */ for (san = &crt->subject_alt_names; !bFoundPositiveMatch && san != NULL && san->buf.p != NULL; san = san->next) { if (san->buf.tag == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME)) { if (mbedtlsNameHasEmbeddedNul(san->buf.p, san->buf.len)) { if (pThis->bReportAuthErr == 1) { errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: certificate SAN dNSName contains embedded NUL byte"); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } CHKmalloc(str = strndup((const char *)(san->buf.p), san->buf.len)); bHaveSAN = 1; dbgprintf("subject alt dnsName: '%s'\n", str); snprintf((char *)lnBuf, sizeof(lnBuf), "DNSname: %s; ", str); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(mbedtlsChkOnePeerName(pThis, (uchar *)str, &bFoundPositiveMatch)); free(str); str = NULL; } } /* Check also CN only if not configured per stricter RFC 6125 or no SAN present*/ if (!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) { if (mbedtlsCnHasEmbeddedNul(crt)) { if (pThis->bReportAuthErr == 1) { errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: certificate commonName contains embedded NUL byte"); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } str = mbedtlsCnFromCrt(crt); if (str != NULL) { /* NULL if there was no CN present */ dbgprintf("mbedtls now checking auth for CN '%s'\n", str); snprintf((char *)lnBuf, sizeof(lnBuf), "CN: %s; ", str); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(mbedtlsChkOnePeerName(pThis, (uchar *)str, &bFoundPositiveMatch)); } } if (!bFoundPositiveMatch) { dbgprintf("invalid peer name, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { cstrFinalize(pStr); errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer name not authorized - " "not permitted to talk to it. Names: %s", cstrGetSzStrNoNULL(pStr)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } finalize_it: if (pStr != NULL) rsCStrDestruct(&pStr); free(str); RETiRet; } /* This is a callback fonction to allow extra checks * in addition to default verifications already done by Mbed TLS's * default processing. */ static int verify(void *ctx, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { nsd_mbedtls_t *pThis = (nsd_mbedtls_t *)ctx; DEFiRet; if (depth > (pThis->DrvrVerifyDepth != 0 ? pThis->DrvrVerifyDepth : DEFAULT_MAX_DEPTH)) ABORT_FINALIZE(MBEDTLS_ERR_X509_FATAL_ERROR); if (depth > 0) FINALIZE; /* Nothing more to be done with issuer's certificates */ /* Mbed TLS API states that if any of the following checks fails, * the verify callback should set the corresponding flag (or * clear it if the check is not cared about) and return 0. * (see mbedtls_x509_crt_verify() documentation) */ if ((*flags) & MBEDTLS_X509_BADCERT_EXPIRED) { if (pThis->permitExpiredCerts == MBEDTLS_EXPIRED_DENY) { FINALIZE; } if (pThis->permitExpiredCerts == MBEDTLS_EXPIRED_WARN) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "Warning, certificate expired but expired certs are permitted"); } else { dbgprintf( "Mbed TLS gives MBEDTLS_X509_BADCERT_EXPIRED" ", but expired certs are permitted.\n"); } *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; } if (pThis->authMode == MBEDTLS_AUTH_CERTFINGERPRINT) { if (mbedtlsChkPeerFingerprint(pThis, crt) != RS_RET_OK) { *flags |= MBEDTLS_X509_BADCERT_OTHER; } } else if (pThis->authMode == MBEDTLS_AUTH_CERTNAME) { if (mbedtlsChkPeerName(pThis, crt) != RS_RET_OK) { *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; } } /* Other auth modes have already been handled by default processing */ finalize_it: RETiRet; } static rsRetVal CheckVerifyResult(nsd_mbedtls_t *pThis) { DEFiRet; uint32_t flags; flags = mbedtls_ssl_get_verify_result(&(pThis->ssl)); if (mbedtlsAuthMode(pThis) != MBEDTLS_SSL_VERIFY_OPTIONAL) FINALIZE; if (pThis->dataTypeCheck == MBEDTLS_NONE && (flags & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE)) { dbgprintf("Mbed TLS gives MBEDTLS_X509_BADCERT_EXT_KEY_USAGE but check disabled\n"); flags &= ~MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; } if (flags != 0) { logMbedtlsError(RS_RET_CERT_INVALID, MBEDTLS_ERR_X509_CERT_VERIFY_FAILED); ABORT_FINALIZE(RS_RET_CERT_INVALID); } finalize_it: if (flags != 0) { char vrfy_buf[512]; if (mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "Mbed TLS verify info : ", flags) < 0) LogError(0, RS_RET_PROVIDED_BUFFER_TOO_SMALL, "Can't get Mbed TLS verify info"); else LogError(0, RS_RET_CERT_INVALID, "%s", vrfy_buf); } RETiRet; } static rsRetVal zeroTermIntArrayDup(int *array, int **copy) { int c, i; int *p = NULL; DEFiRet; c = 0; while (array[c] != 0) ++c; CHKmalloc(p = malloc((c + 1) * sizeof(int))); for (i = 0; i <= c; ++i) p[i] = array[i]; finalize_it: *copy = p; RETiRet; } /* accept an incoming connection request - here, we do the usual accept * handling. TLS specific handling is done thereafter (and if we run in TLS * mode at this time). * rgerhards, 2008-04-25 */ static rsRetVal AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew, char *const connInfo) { DEFiRet; nsd_mbedtls_t *pNew = NULL; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); int mbedtlsRet; ISOBJ_TYPE_assert(pThis, nsd_mbedtls); CHKiRet(nsd_mbedtlsConstruct(&pNew)); // TODO: prevent construct/destruct! CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp)); CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp, connInfo)); if (pThis->iMode == 0) { /* we are in non-TLS mode, so we are done */ *ppNew = (nsd_t *)pNew; FINALIZE; } /* copy Properties to pnew first */ pNew->authMode = pThis->authMode; pNew->bSANpriority = pThis->bSANpriority; pNew->pPermPeers = pThis->pPermPeers; pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth; pNew->DrvrTlsRevocationCheck = pThis->DrvrTlsRevocationCheck; pNew->dataTypeCheck = pThis->dataTypeCheck; pNew->permitExpiredCerts = pThis->permitExpiredCerts; if (pThis->anzCipherSuites) CHKiRet(zeroTermIntArrayDup(pThis->anzCipherSuites, &(pNew->anzCipherSuites))); if (pThis->pszCertFile) CHKmalloc(pNew->pszCertFile = (const uchar *)strdup((const char *)(pThis->pszCertFile))); if (pThis->pszKeyFile) CHKmalloc(pNew->pszKeyFile = (const uchar *)strdup((const char *)(pThis->pszKeyFile))); if (pThis->pszCAFile) CHKmalloc(pNew->pszCAFile = (const uchar *)strdup((const char *)(pThis->pszCAFile))); if (pThis->pszCRLFile) CHKmalloc(pNew->pszCRLFile = (const uchar *)strdup((const char *)(pThis->pszCRLFile))); pNew->iMode = pThis->iMode; /* if we reach this point, we are in TLS mode */ CHKiRet(mbedtlsInitSession(pNew)); CHKiRet(mbedtlsInitCred(pNew)); CHKiRet(mbedtls_ssl_config_defaults(&(pNew->conf), MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)); mbedtlsApplyTlsVersionWorkaround(pNew, &(pNew->conf)); mbedtls_ssl_conf_rng(&(pNew->conf), mbedtls_ctr_drbg_random, &(pNew->ctr_drbg)); mbedtls_ssl_conf_authmode(&(pNew->conf), mbedtlsAuthMode(pNew)); mbedtls_ssl_conf_ca_chain(&(pNew->conf), pNew->bHaveCaCert ? &(pNew->cacert) : NULL, pNew->bHaveCrl ? &(pNew->crl) : NULL); mbedtls_ssl_conf_verify(&(pNew->conf), verify, pNew); if (pNew->bHaveKey && pNew->bHaveCert) CHKiRet(mbedtls_ssl_conf_own_cert(&(pNew->conf), &(pNew->srvcert), &(pNew->pkey))); #if MBEDTLS_DEBUG_LEVEL > 0 mbedtls_ssl_conf_dbg(&(pNew->conf), debug, stdout); #endif if (pNew->anzCipherSuites != NULL) mbedtls_ssl_conf_ciphersuites(&(pNew->conf), pNew->anzCipherSuites); CHKiRet(mbedtls_ssl_setup(&(pNew->ssl), &(pNew->conf))); // peer id will be checked in verify() callback CHKiRet(mbedtls_ssl_set_hostname(&(pNew->ssl), NULL)); CHKiRet(nsd_ptcp.GetSock(pNew->pTcp, &(pNew->sock))); mbedtls_ssl_set_bio(&(pNew->ssl), pNew, mbedtlsNetSend, mbedtlsNetRecv, NULL); mbedtlsRet = mbedtls_ssl_handshake(&(pNew->ssl)); if (mbedtlsRet != 0 && mbedtlsRet != MBEDTLS_ERR_SSL_WANT_READ && mbedtlsRet != MBEDTLS_ERR_SSL_WANT_WRITE) { logMbedtlsError(RS_RET_TLS_HANDSHAKE_ERR, mbedtlsRet); ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR); } if (mbedtlsRet == 0) { CHKiRet(CheckVerifyResult(pNew)); } pNew->bHaveSess = 1; *ppNew = (nsd_t *)pNew; finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) nsd_mbedtlsDestruct(&pNew); } RETiRet; } /* receive data from a tcp socket * The lenBuf parameter must contain the max buffer size on entry and contains * the number of octets read on exit. This function * never blocks, not even when called on a blocking socket. That is important * for client sockets, which are set to block during send, but should not * block when trying to read data. -- rgerhards, 2008-03-17 */ static rsRetVal Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf, int *const oserr, unsigned *const nextIODirection) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); int n = 0; if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf, oserr, nextIODirection)); FINALIZE; } /* --- in TLS mode now --- */ n = mbedtls_ssl_read(&(pThis->ssl), pBuf, *pLenBuf); if (n == MBEDTLS_ERR_SSL_WANT_READ || n == MBEDTLS_ERR_SSL_WANT_WRITE) ABORT_FINALIZE(RS_RET_RETRY); if (n == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ABORT_FINALIZE(RS_RET_CLOSED); if (n < 0) { logMbedtlsError(RS_RET_RCV_ERR, n); ABORT_FINALIZE(RS_RET_RCV_ERR); } if (n == 0) ABORT_FINALIZE(RS_RET_RETRY); CHKiRet(CheckVerifyResult(pThis)); *pLenBuf = n; finalize_it: dbgprintf("mbedtlsRcv return. nsd %p, iRet %d, lenRcvBuf %ld\n", pThis, iRet, (long)(*pLenBuf)); if (iRet != RS_RET_OK && iRet != RS_RET_RETRY) *pLenBuf = 0; RETiRet; } /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has * been written. * rgerhards, 2008-03-19 */ static rsRetVal Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) { int iSent; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_mbedtls); if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf)); FINALIZE; } /* in TLS mode now */ iSent = mbedtls_ssl_write(&(pThis->ssl), pBuf, *pLenBuf); if (iSent == MBEDTLS_ERR_SSL_WANT_READ || iSent == MBEDTLS_ERR_SSL_WANT_WRITE) { ABORT_FINALIZE(RS_RET_RETRY); } else if (iSent <= 0) { logMbedtlsError(RS_RET_NO_ERRCODE, iSent); ABORT_FINALIZE(RS_RET_IO_ERROR); } CHKiRet(CheckVerifyResult(pThis)); *pLenBuf = iSent; finalize_it: RETiRet; } /* Enable KEEPALIVE handling on the socket. * rgerhards, 2009-06-02 */ static rsRetVal EnableKeepAlive(nsd_t *pNsd) { nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); return nsd_ptcp.EnableKeepAlive(pThis->pTcp); } /* open a connection to a remote host (server). */ static rsRetVal Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); int mbedtlsRet; dbgprintf("Connect to %s:%s\n", host, port); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); assert(port != NULL); assert(host != NULL); CHKiRet(mbedtlsInitSession(pThis)); CHKiRet(mbedtlsInitCred(pThis)); CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host, device)); if (pThis->iMode == 0) FINALIZE; /* we reach this point if in TLS mode */ CHKiRet(mbedtls_ssl_config_defaults(&(pThis->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)); mbedtlsApplyTlsVersionWorkaround(pThis, &(pThis->conf)); mbedtls_ssl_conf_rng(&(pThis->conf), mbedtls_ctr_drbg_random, &(pThis->ctr_drbg)); mbedtls_ssl_conf_authmode(&(pThis->conf), mbedtlsAuthMode(pThis)); mbedtls_ssl_conf_ca_chain(&(pThis->conf), pThis->bHaveCaCert ? &(pThis->cacert) : NULL, pThis->bHaveCrl ? &(pThis->crl) : NULL); mbedtls_ssl_conf_verify(&(pThis->conf), verify, pThis); if (pThis->bHaveKey && pThis->bHaveCert) CHKiRet(mbedtls_ssl_conf_own_cert(&(pThis->conf), &(pThis->srvcert), &(pThis->pkey))); #if MBEDTLS_DEBUG_LEVEL > 0 mbedtls_ssl_conf_dbg(&(pThis->conf), debug, stdout); #endif if (pThis->anzCipherSuites != NULL) mbedtls_ssl_conf_ciphersuites(&(pThis->conf), pThis->anzCipherSuites); CHKiRet(mbedtls_ssl_setup(&(pThis->ssl), &(pThis->conf))); // peer id will be checked in verify() callback CHKiRet(mbedtls_ssl_set_hostname(&(pThis->ssl), NULL)); CHKmalloc(pThis->pszConnectHost = (uchar *)strdup((char *)host)); CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &(pThis->sock))); mbedtls_ssl_set_bio(&(pThis->ssl), pThis, mbedtlsNetSend, mbedtlsNetRecv, NULL); mbedtlsRet = mbedtls_ssl_handshake(&(pThis->ssl)); if (mbedtlsRet != 0 && mbedtlsRet != MBEDTLS_ERR_SSL_WANT_READ && mbedtlsRet != MBEDTLS_ERR_SSL_WANT_WRITE) { logMbedtlsError(RS_RET_TLS_HANDSHAKE_ERR, mbedtlsRet); ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR); } if (mbedtlsRet == 0) { CHKiRet(CheckVerifyResult(pThis)); } pThis->bHaveSess = 1; finalize_it: if (iRet != RS_RET_OK) { free(pThis->pszConnectHost); pThis->pszConnectHost = NULL; } RETiRet; } static rsRetVal ATTR_NONNULL(1, 3, 5) LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal (*fAddLstn)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *cnf_params) { DEFiRet; iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params); RETiRet; } /* This function checks if the connection is still alive - well, kind of... * This is a dummy here. For details, check function common in ptcp driver. * rgerhards, 2008-06-09 */ static rsRetVal CheckConnection(nsd_t *pNsd) { nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); dbgprintf("CheckConnection for %p\n", pNsd); return nsd_ptcp.CheckConnection(pThis->pTcp); } /* Provide access to the underlying OS socket. */ static rsRetVal GetSock(nsd_t *pNsd, int *pSock) { nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); return nsd_ptcp.GetSock(pThis->pTcp, pSock); } /* get the remote hostname. The returned hostname must be freed by the caller. * rgerhards, 2008-04-25 */ static rsRetVal GetRemoteHName(nsd_t *pNsd, uchar **ppszHName) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName); RETiRet; } /* Provide access to the sockaddr_storage of the remote peer. This * is needed by the legacy ACL system. --- gerhards, 2008-12-01 */ static rsRetVal GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); iRet = nsd_ptcp.GetRemAddr(pThis->pTcp, ppAddr); RETiRet; } /* get the remote host's IP address. Caller must Destruct the object. */ static rsRetVal GetRemoteIP(nsd_t *pNsd, prop_t **ip) { DEFiRet; nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ip); RETiRet; } static rsRetVal GetRemotePort(nsd_t *pNsd, int *port) { nsd_mbedtls_t *pThis = nsd_mbedtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_mbedtls); return nsd_ptcp.GetRemotePort(pThis->pTcp, port); } static rsRetVal FmtRemotePortStr(const int port, uchar *const buf, const size_t len) { return nsd_ptcp.FmtRemotePortStr(port, buf, len); } /* queryInterface function */ BEGINobjQueryInterface(nsd_mbedtls) CODESTARTobjQueryInterface( nsd_mbedtls) if (pIf->ifVersion != nsdCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = (rsRetVal(*)(nsd_t **))nsd_mbedtlsConstruct; pIf->Destruct = (rsRetVal(*)(nsd_t **))nsd_mbedtlsDestruct; pIf->Abort = Abort; pIf->LstnInit = LstnInit; pIf->AcceptConnReq = AcceptConnReq; pIf->Rcv = Rcv; pIf->Send = Send; pIf->Connect = Connect; pIf->GetSock = GetSock; pIf->SetSock = SetSock; pIf->SetMode = SetMode; pIf->SetAuthMode = SetAuthMode; pIf->SetPermitExpiredCerts = SetPermitExpiredCerts; pIf->SetPermPeers = SetPermPeers; pIf->CheckConnection = CheckConnection; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->GetRemAddr = GetRemAddr; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetTcpUserTimeout = SetTcpUserTimeout; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCAExtraFiles = SetTlsCAExtraFiles; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->GetRemotePort = GetRemotePort; pIf->FmtRemotePortStr = FmtRemotePortStr; pIf->SetRemoteSNI = SetRemoteSNI; pIf->SetTlsRevocationCheck = SetTlsRevocationCheck; finalize_it: ENDobjQueryInterface(nsd_mbedtls) /* exit our class */ BEGINObjClassExit(nsd_mbedtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsd_mbedtls) mbedtlsGlblExit(); /* shut down Mbed TLS */ /* release objects we no longer need */ objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME); objRelease(net, LM_NET_FILENAME); objRelease(glbl, CORE_COMPONENT); #ifndef HAVE_ATOMIC_BUILTINS DESTROY_ATOMIC_HELPER_MUT(mutTlsVersionWorkaroundReported); #endif ENDObjClassExit(nsd_mbedtls) /* Initialize the nsd_mbedtls class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsd_mbedtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ #ifndef HAVE_ATOMIC_BUILTINS INIT_ATOMIC_HELPER_MUT(mutTlsVersionWorkaroundReported); #endif bTlsVersionWorkaroundReported = 0; /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME)); CHKiRet(objUse(net, LM_NET_FILENAME)); /* now do global TLS init stuff */ CHKiRet(mbedtlsGlblInit()); ENDObjClassInit(nsd_mbedtls) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit nsd_mbedtlsClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt CODEqueryEtryPt_STD_LIB_QUERIES ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(nsd_mbedtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/strgen.c0000644000000000000000000000013215145046113015670 xustar0030 mtime=1771326539.016013913 30 atime=1787067617.951436166 30 ctime=1787067794.303723359 rsyslog-8.2608.0/runtime/strgen.c0000664000175000017500000001745115145046113015344 0ustar00rgerrger/* strgen.c * Module to handle string generators. These are C modules that receive * the message object and return a custom-built string. The primary purpose * for their existence is performance -- they do the same as template strings, but * potentially faster (if well implmented). * * Module begun 2010-06-01 by Rainer Gerhards * * Copyright 2010 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "msg.h" #include "obj.h" #include "errmsg.h" #include "strgen.h" #include "ruleset.h" #include "unicode-helper.h" #include "cfsysline.h" /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(ruleset) /* static data */ /* config data */ /* This is the list of all strgens known to us. * This is also used to unload all modules on shutdown. */ strgenList_t *pStrgenLstRoot = NULL; /* initialize (but NOT allocate) a strgen list. Primarily meant as a hook * which can be used to extend the list in the future. So far, just sets * it to NULL. */ static rsRetVal InitStrgenList(strgenList_t **pListRoot) { *pListRoot = NULL; return RS_RET_OK; } /* destruct a strgen list. The list elements are destroyed, but the strgen objects * themselves are not modified. (That is done at a late stage during rsyslogd * shutdown and need not be considered here.) */ static rsRetVal DestructStrgenList(strgenList_t **ppListRoot) { strgenList_t *pStrgenLst; strgenList_t *pStrgenLstDel; pStrgenLst = *ppListRoot; while (pStrgenLst != NULL) { pStrgenLstDel = pStrgenLst; pStrgenLst = pStrgenLst->pNext; free(pStrgenLstDel); } *ppListRoot = NULL; return RS_RET_OK; } /* Add a strgen to the list. We use a VERY simple and ineffcient algorithm, * but it is employed only for a few milliseconds during config processing. So * I prefer to keep it very simple and with simple data structures. Unfortunately, * we need to preserve the order, but I don't like to add a tail pointer as that * would require a container object. So I do the extra work to skip to the tail * when adding elements... */ static rsRetVal AddStrgenToList(strgenList_t **ppListRoot, strgen_t *pStrgen) { strgenList_t *pThis; strgenList_t *pTail; DEFiRet; CHKmalloc(pThis = malloc(sizeof(strgenList_t))); pThis->pStrgen = pStrgen; pThis->pNext = NULL; if (*ppListRoot == NULL) { pThis->pNext = *ppListRoot; *ppListRoot = pThis; } else { /* find tail first */ for (pTail = *ppListRoot; pTail->pNext != NULL; pTail = pTail->pNext) /* just search, do nothing else */ ; /* add at tail */ pTail->pNext = pThis; } finalize_it: RETiRet; } /* find a strgen based on the provided name */ static rsRetVal FindStrgen(strgen_t **ppStrgen, uchar *pName) { strgenList_t *pThis; DEFiRet; for (pThis = pStrgenLstRoot; pThis != NULL; pThis = pThis->pNext) { if (ustrcmp(pThis->pStrgen->pName, pName) == 0) { *ppStrgen = pThis->pStrgen; FINALIZE; /* found it, iRet still eq. OK! */ } } iRet = RS_RET_PARSER_NOT_FOUND; finalize_it: RETiRet; } /* --- END helper functions for strgen list handling --- */ BEGINobjConstruct(strgen) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(strgen) /* ConstructionFinalizer. The most important chore is to add the strgen object * to our global list of available strgens. * rgerhards, 2009-11-03 */ static rsRetVal strgenConstructFinalize(strgen_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, strgen); CHKiRet(AddStrgenToList(&pStrgenLstRoot, pThis)); DBGPRINTF("Strgen '%s' added to list of available strgens.\n", pThis->pName); finalize_it: RETiRet; } BEGINobjDestruct(strgen) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(strgen); dbgprintf("destructing strgen '%s'\n", pThis->pName); free(pThis->pName); ENDobjDestruct(strgen) /* set the strgen name - string is copied over, call can continue to use it, * but must free it if desired. */ static rsRetVal SetName(strgen_t *pThis, uchar *name) { DEFiRet; ISOBJ_TYPE_assert(pThis, strgen); assert(name != NULL); if (pThis->pName != NULL) { free(pThis->pName); pThis->pName = NULL; } CHKmalloc(pThis->pName = ustrdup(name)); finalize_it: RETiRet; } /* set a pointer to "our" module. Note that no module * pointer must already be set. */ static rsRetVal SetModPtr(strgen_t *pThis, modInfo_t *pMod) { ISOBJ_TYPE_assert(pThis, strgen); assert(pMod != NULL); assert(pThis->pModule == NULL); pThis->pModule = pMod; return RS_RET_OK; } /* queryInterface function-- rgerhards, 2009-11-03 */ BEGINobjQueryInterface(strgen) CODESTARTobjQueryInterface(strgen); if (pIf->ifVersion != strgenCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = strgenConstruct; pIf->ConstructFinalize = strgenConstructFinalize; pIf->Destruct = strgenDestruct; pIf->SetName = SetName; pIf->SetModPtr = SetModPtr; pIf->InitStrgenList = InitStrgenList; pIf->DestructStrgenList = DestructStrgenList; pIf->AddStrgenToList = AddStrgenToList; pIf->FindStrgen = FindStrgen; finalize_it: ENDobjQueryInterface(strgen) /* This destroys the master strgenlist and all of its strgen entries. MUST only be * done when the module is shut down. Strgen modules are NOT unloaded, rsyslog * does that at a later stage for all dynamically loaded modules. */ static void destroyMasterStrgenList(void) { strgenList_t *pStrgenLst; strgenList_t *pStrgenLstDel; pStrgenLst = pStrgenLstRoot; while (pStrgenLst != NULL) { strgenDestruct(&pStrgenLst->pStrgen); pStrgenLstDel = pStrgenLst; pStrgenLst = pStrgenLst->pNext; free(pStrgenLstDel); } } /* Exit our class. * rgerhards, 2009-11-04 */ BEGINObjClassExit(strgen, OBJ_IS_CORE_MODULE) /* class, version */ destroyMasterStrgenList(); objRelease(glbl, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDObjClassExit(strgen) /* Initialize the strgen class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2009-11-02 */ BEGINObjClassInit(strgen, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); InitStrgenList(&pStrgenLstRoot); ENDObjClassInit(strgen) rsyslog-8.2608.0/runtime/PaxHeaders/netstrms.h0000644000000000000000000000013215145046112016251 xustar0030 mtime=1771326538.999013635 30 atime=1787067618.233441425 30 ctime=1787067794.536727701 rsyslog-8.2608.0/runtime/netstrms.h0000664000175000017500000001210515145046112015714 0ustar00rgerrger/* Definitions for the stream-based netstrm sworking class. * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_NETSTRMS_H #define INCLUDED_NETSTRMS_H #include "nsd.h" /* we need our driver interface to be defined */ /* the netstrms object */ struct netstrms_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ uchar *pBaseDrvrName; /**< nsd base driver name to use, or NULL if system default */ uchar *pDrvrName; /**< full base driver name (set when driver is loaded) */ int iDrvrMode; /**< current default driver mode */ uchar *pszDrvrAuthMode; /**< current driver authentication mode */ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */ int DrvrVerifyDepth; /**< Verify Depth for certificate chains */ int DrvrTlsRevocationCheck; /**< Enable TLS revocation checking (OCSP/CRL) */ uchar *pszDrvrPermitExpiredCerts; const uchar *pszDrvrCAFile; const uchar *pszDrvrCRLFile; const uchar *pszDrvrKeyFile; const uchar *pszDrvrCertFile; uchar *gnutlsPriorityString; /**< priorityString for connection */ uchar *remoteSNI; /**< Remote SNI to use instead of the server hostname */ int iSynBacklog; /**< socket layer syn backlog for listen() */ permittedPeers_t *pPermPeers; /**< current driver's permitted peers */ rsRetVal (*fLstnInitDrvr)(netstrm_t *); /**< "late" driver-specific lstn init function NULL if none */ nsd_if_t Drvr; /**< our stream driver */ }; /* interface */ BEGINinterface(netstrms) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(netstrms_t **ppThis); rsRetVal (*ConstructFinalize)(netstrms_t *pThis); rsRetVal (*Destruct)(netstrms_t **ppThis); rsRetVal (*CreateStrm)(netstrms_t *pThis, netstrm_t **ppStrm); rsRetVal (*SetDrvrName)(netstrms_t *pThis, uchar *pszName); rsRetVal (*SetDrvrMode)(netstrms_t *pThis, int iMode); rsRetVal (*SetDrvrAuthMode)(netstrms_t *pThis, uchar *); rsRetVal (*SetDrvrPermitExpiredCerts)(netstrms_t *pThis, uchar *); rsRetVal (*SetDrvrPermPeers)(netstrms_t *pThis, permittedPeers_t *); int (*GetDrvrMode)(netstrms_t *pThis); uchar *(*GetDrvrAuthMode)(netstrms_t *pThis); uchar *(*GetDrvrPermitExpiredCerts)(netstrms_t *pThis); permittedPeers_t *(*GetDrvrPermPeers)(netstrms_t *pThis); rsRetVal (*SetDrvrGnutlsPriorityString)(netstrms_t *pThis, uchar *); uchar *(*GetDrvrGnutlsPriorityString)(netstrms_t *pThis); rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis, int ChkExtendedKeyUsage); int (*GetDrvrCheckExtendedKeyUsage)(netstrms_t *pThis); rsRetVal (*SetDrvrPrioritizeSAN)(netstrms_t *pThis, int prioritizeSan); int (*GetDrvrPrioritizeSAN)(netstrms_t *pThis); rsRetVal (*SetDrvrTlsVerifyDepth)(netstrms_t *pThis, int verifyDepth); rsRetVal (*SetDrvrTlsRevocationCheck)(netstrms_t *pThis, int enabled); int (*GetDrvrTlsVerifyDepth)(netstrms_t *pThis); int (*GetDrvrTlsRevocationCheck)(netstrms_t *pThis); rsRetVal (*SetDrvrRemoteSNI)(netstrms_t *pThis, uchar *); uchar *(*GetDrvrRemoteSNI)(netstrms_t *pThis); /* v2 */ rsRetVal (*SetDrvrTlsCAFile)(netstrms_t *pThis, const uchar *); const uchar *(*GetDrvrTlsCAFile)(netstrms_t *pThis); rsRetVal (*SetDrvrTlsKeyFile)(netstrms_t *pThis, const uchar *); const uchar *(*GetDrvrTlsKeyFile)(netstrms_t *pThis); rsRetVal (*SetDrvrTlsCertFile)(netstrms_t *pThis, const uchar *); const uchar *(*GetDrvrTlsCertFile)(netstrms_t *pThis); /* v3 */ rsRetVal (*SetDrvrTlsCRLFile)(netstrms_t *pThis, const uchar *); const uchar *(*GetDrvrTlsCRLFile)(netstrms_t *pThis); /* v4 */ rsRetVal (*SetSynBacklog)(netstrms_t *pThis, const int); ENDinterface(netstrms) #define netstrmsCURR_IF_VERSION 5 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObjFull(netstrms); /* the name of our library binary */ #define LM_NETSTRMS_FILENAME "lmnetstrms" #endif /* #ifndef INCLUDED_NETSTRMS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/rswatch.h0000644000000000000000000000013215171370365016056 xustar0030 mtime=1776677109.444913125 30 atime=1787067616.836415376 30 ctime=1787067794.432725763 rsyslog-8.2608.0/runtime/rswatch.h0000664000175000017500000000525515171370365015531 0ustar00rgerrger#ifndef INCLUDED_RSWATCH_H #define INCLUDED_RSWATCH_H /* * rswatch is the runtime-internal watched-file scheduler used by subsystems * that can reload a single configuration file without doing a full HUP sweep. * * Algorithm overview * - Each registration describes one concrete file path plus a debounce window * and a callback. * - On inotify-capable builds, rswatch watches the file's parent directory and * matches events by basename. This deliberately handles the common * write-temp-and-rename save pattern, where the file inode changes but the * configured path stays the same. * - I/O readiness is integrated into rsyslogd's main housekeeping loop via * rswatchGetWaitFd(), rswatchComputeTimeoutMs(), rswatchProcessIo(), and * rswatchDispatchDue(). rswatch itself does not create a worker thread. * - When rswatchProcessIo() sees an event for a watched basename, it marks the * registration pending and stores due_at = now + debounce_ms. * - rswatchDispatchDue() later pops registrations whose debounce deadline has * expired and invokes their callback. * * Concurrency and locking * - The subsystem has one process-global state object guarded by one mutex. * - The mutex protects the registration list, the backend fd, backend-disable * state, and per-registration pending/due bookkeeping. * - Callbacks are never executed while the rswatch mutex is held. This keeps * reload code free to take its own locks and avoids turning rswatch into a * lock-ordering bottleneck in the main loop. * - Registrations and unregistrations are expected on configuration/control * paths, not on message-processing hot paths. * * Failure model * - On builds without inotify support, registration returns * RS_RET_NOT_IMPLEMENTED so callers can degrade to HUP-only behavior. * - If the backend fails after registrations exist, rswatch disables itself, * clears pending state, and leaves already-registered users in place so the * rest of rsyslog continues to operate without watched reloads. */ #include #include "rsyslog.h" typedef struct rswatch_handle_s rswatch_handle_t; typedef void (*rswatch_cb_t)(void *ctx, const char *trigger); typedef struct rswatch_desc_s { const char *id; const char *path; unsigned int debounce_ms; rswatch_cb_t cb; void *ctx; } rswatch_desc_t; rsRetVal rswatchRegister(const rswatch_desc_t *desc, rswatch_handle_t **out); void rswatchUnregister(rswatch_handle_t *handle); int rswatchGetWaitFd(void); int rswatchComputeTimeoutMs(uint64_t now_ms, int default_timeout_ms); void rswatchProcessIo(uint64_t now_ms); void rswatchDispatchDue(uint64_t now_ms); void rswatchExit(void); #endif /* INCLUDED_RSWATCH_H */ rsyslog-8.2608.0/runtime/PaxHeaders/tcps_sess.c0000644000000000000000000000013215241075234016377 xustar0030 mtime=1787067036.611578407 30 atime=1787067036.758581159 30 ctime=1787067794.599728875 rsyslog-8.2608.0/runtime/tcps_sess.c0000664000175000017500000013535215241075234016054 0ustar00rgerrger/* tcps_sess.c * * This implements a session of the tcpsrv object. For general * comments, see header of tcpsrv.c. * * NOTE: read comments in module-template.h to understand how this file * works! * * File begun on 2008-03-01 by RGerhards (extracted from tcpsrv.c, which * based on the BSD-licensed syslogd.c) * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #ifdef ENABLE_LIBZSTD #define ZSTD_STATIC_LINKING_ONLY #include #endif #include "rsyslog.h" #include "dirty.h" #include "unicode-helper.h" #include "module-template.h" #include "net.h" #include "tcpsrv.h" #include "tcps_sess.h" #include "obj.h" #include "errmsg.h" #include "netstrm.h" #include "msg.h" #include "datetime.h" #include "prop.h" #include "ratelimit.h" #include "debug.h" #include "rsconf.h" /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl); DEFobjCurrIf(netstrm); DEFobjCurrIf(prop); DEFobjCurrIf(datetime); DEFobjCurrIf(regexp); /* forward definitions */ static rsRetVal Close(tcps_sess_t *pThis); static rsRetVal finishCompressedStream(tcps_sess_t *pThis); /* Standard-Constructor */ BEGINobjConstruct(tcps_sess) /* be sure to specify the object type also in END macro! */ size_t bufSize; pThis->iMsg = 0; /* just make sure... */ pThis->iMaxLine = glbl.GetMaxLine(runConf); pThis->inputState = eAtStrtFram; /* indicate frame header expected */ pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */ pthread_mutex_init(&pThis->mut, NULL); pThis->fromHost = NULL; pThis->fromHostIP = NULL; pThis->fromHostPort = NULL; pThis->iCurrLine = 0; pThis->pMsg_save = NULL; pThis->tlsProbeBytes = 0; pThis->tlsProbeDone = 0; pThis->tlsMismatchWarned = 0; pThis->compressionMode = TCPSRV_COMPRESS_NEVER; pThis->compressionDriver = TCPSRV_COMPRESS_DRIVER_ZLIB; pThis->compressionMaxTotalZstdWindowBytes = TCPSRV_COMPRESS_MAX_TOTAL_ZSTD_WINDOW_BYTES_DEFAULT; pThis->compressionTotalBytesIn = 0; pThis->compressionTotalBytesOut = 0; pThis->zipInitDone = 0; pThis->compressedStreamEnded = 0; pThis->streamDecompressed = 0; pThis->zstdDctx = NULL; pThis->zstd_frame_header_len = 0; pThis->zstd_frame_header_processed = 0; pThis->zstd_window_reservation = 0; memset(&pThis->zstrm, 0, sizeof(pThis->zstrm)); memset(pThis->tlsProbeBuf, 0, sizeof(pThis->tlsProbeBuf)); /* now allocate the message reception buffer */ bufSize = (size_t)pThis->iMaxLine + 1; CHKmalloc(pThis->pMsg = (uchar *)malloc(bufSize)); finalize_it: ENDobjConstruct(tcps_sess) /* ConstructionFinalizer */ static rsRetVal tcps_sessConstructFinalize(tcps_sess_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); #ifdef FEATURE_REGEXP if (pThis->pLstnInfo->bHasStartRegex) { size_t regexBufSize; uchar *pMsgTmp; if (pThis->iMaxLine > (INT_MAX - 1) / 2) { LogError(0, RS_RET_ERR, "imtcp: framing.delimiter.regex requires maxMessageSize <= %d to avoid session buffer overflow", (INT_MAX - 1) / 2); ABORT_FINALIZE(RS_RET_ERR); } regexBufSize = ((size_t)pThis->iMaxLine * 2) + 1; /* in this case, we need a second buffer and a larger primary one */ CHKmalloc(pMsgTmp = (uchar *)realloc(pThis->pMsg, regexBufSize)); pThis->pMsg = pMsgTmp; CHKmalloc(pThis->pMsg_save = (uchar *)malloc(regexBufSize)); } #endif if (pThis->pSrv->OnSessConstructFinalize != NULL) { CHKiRet(pThis->pSrv->OnSessConstructFinalize(&pThis->pUsr)); } finalize_it: RETiRet; } #ifdef ENABLE_LIBZSTD static sbool reserve_zstd_window(tcps_sess_t *const pThis, const uint64 window_size) { tcpLstnPortList_t *const listener = pThis->pLstnInfo; const uint64 limit = pThis->compressionMaxTotalZstdWindowBytes; uint64 in_use; assert(listener != NULL); assert(pThis->zstd_window_reservation == 0); if (window_size > limit) return RSFALSE; in_use = ATOMIC_LOAD_uint64(&listener->compressionZstdWindowBytesInUse, &listener->mutCompressionZstdWindow); for (;;) { if (in_use > limit - window_size) return RSFALSE; if (ATOMIC_CAS_uint64(&listener->compressionZstdWindowBytesInUse, in_use, in_use + window_size, &listener->mutCompressionZstdWindow)) { pThis->zstd_window_reservation = window_size; return RSTRUE; } in_use = ATOMIC_LOAD_uint64(&listener->compressionZstdWindowBytesInUse, &listener->mutCompressionZstdWindow); } } static void release_zstd_window_reservation(tcps_sess_t *const pThis) { if (pThis->zstd_window_reservation == 0 || pThis->pLstnInfo == NULL) return; assert(ATOMIC_LOAD_uint64(&pThis->pLstnInfo->compressionZstdWindowBytesInUse, &pThis->pLstnInfo->mutCompressionZstdWindow) >= pThis->zstd_window_reservation); ATOMIC_SUB_uint64(&pThis->pLstnInfo->compressionZstdWindowBytesInUse, &pThis->pLstnInfo->mutCompressionZstdWindow, pThis->zstd_window_reservation); pThis->zstd_window_reservation = 0; } #endif static void release_zlib_decoder(tcps_sess_t *const pThis) { if (!pThis->zipInitDone) return; inflateEnd(&pThis->zstrm); memset(&pThis->zstrm, 0, sizeof(pThis->zstrm)); pThis->zipInitDone = 0; } /* destructor for the tcps_sess object */ BEGINobjDestruct(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(tcps_sess); release_zlib_decoder(pThis); #ifdef ENABLE_LIBZSTD if (pThis->zstdDctx != NULL) { ZSTD_freeDCtx((ZSTD_DCtx *)pThis->zstdDctx); pThis->zstdDctx = NULL; } release_zstd_window_reservation(pThis); #endif if (pThis->pStrm != NULL) netstrm.Destruct(&pThis->pStrm); if (pThis->pSrv->pOnSessDestruct != NULL) { pThis->pSrv->pOnSessDestruct(&pThis->pUsr); } pthread_mutex_destroy(&pThis->mut); /* now destruct our own properties */ if (pThis->fromHost != NULL) CHKiRet(prop.Destruct(&pThis->fromHost)); if (pThis->fromHostIP != NULL) CHKiRet(prop.Destruct(&pThis->fromHostIP)); if (pThis->fromHostPort != NULL) CHKiRet(prop.Destruct(&pThis->fromHostPort)); free(pThis->pMsg); free(pThis->pMsg_save); ENDobjDestruct(tcps_sess) /* debugprint for the tcps_sess object */ BEGINobjDebugPrint(tcps_sess) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(tcps_sess); ENDobjDebugPrint(tcps_sess) /* set property functions */ /* set the hostname. Note that the caller *hands over* the string. That is, * the caller no longer controls it once SetHost() has received it. Most importantly, * the caller must not free it. -- rgerhards, 2008-04-24 */ static rsRetVal SetHost(tcps_sess_t *pThis, uchar *pszHost) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); if (pThis->fromHost == NULL) CHKiRet(prop.Construct(&pThis->fromHost)); CHKiRet(prop.SetString(pThis->fromHost, pszHost, ustrlen(pszHost))); finalize_it: free(pszHost); /* we must free according to our (old) calling conventions */ RETiRet; } /* set the remote host's IP. Note that the caller *hands over* the property. That is, * the caller no longer controls it once SetHostIP() has received it. Most importantly, * the caller must not destruct it. -- rgerhards, 2008-05-16 */ static rsRetVal SetHostIP(tcps_sess_t *pThis, prop_t *ip) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); if (pThis->fromHostIP != NULL) { prop.Destruct(&pThis->fromHostIP); } pThis->fromHostIP = ip; RETiRet; } static rsRetVal SetHostPort(tcps_sess_t *pThis, prop_t *port) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); if (pThis->fromHostPort != NULL) { prop.Destruct(&pThis->fromHostPort); } pThis->fromHostPort = port; RETiRet; } static rsRetVal SetStrm(tcps_sess_t *pThis, netstrm_t *pStrm) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); pThis->pStrm = pStrm; RETiRet; } static inline int isLikelyTlsClientHello(const uchar buf[5]) { if (buf[0] != 0x16) return 0; /* handshake record */ if (buf[1] != 0x03) return 0; /* TLS major version */ if (buf[2] > 0x04) return 0; /* accept TLS 1.0 - 1.3 */ const unsigned recordLen = ((unsigned)buf[3] << 8) | buf[4]; if (recordLen < 40 || recordLen > 16384) return 0; /* sanity */ return 1; } static ATTR_NONNULL() rsRetVal maybeDetectTlsClientHello(tcps_sess_t *pThis, const char *data, size_t len) { DEFiRet; if (pThis->tlsProbeDone) FINALIZE; if (pThis->pSrv->pszOrigin == NULL || strcmp((const char *)pThis->pSrv->pszOrigin, "imtcp") != 0) { pThis->tlsProbeDone = 1; FINALIZE; } if (pThis->pSrv->iDrvrMode != 0) { pThis->tlsProbeDone = 1; FINALIZE; } while (len > 0 && pThis->tlsProbeBytes < sizeof(pThis->tlsProbeBuf)) { pThis->tlsProbeBuf[pThis->tlsProbeBytes++] = (uchar)*data++; --len; } if (pThis->tlsProbeBytes >= sizeof(pThis->tlsProbeBuf)) { if (!pThis->tlsMismatchWarned && isLikelyTlsClientHello(pThis->tlsProbeBuf)) { const char *const host = propGetSzStrOrDefault(pThis->fromHost, "(host unknown)"); const char *const ip = propGetSzStrOrDefault(pThis->fromHostIP, "(IP unknown)"); const char *const port = propGetSzStrOrDefault(pThis->fromHostPort, "(port unknown)"); LogError(0, RS_RET_SERVER_NO_TLS, "imtcp: TLS handshake detected from %s (%s:%s) but listener is not TLS-enabled. " "Enable TLS on this listener or disable TLS on the client. " "See https://www.rsyslog.com/doc/faq/imtcp-tls-gibberish.html for troubleshooting.", host, ip, port); pThis->tlsMismatchWarned = 1; ABORT_FINALIZE(RS_RET_SERVER_NO_TLS); } pThis->tlsProbeDone = 1; } finalize_it: RETiRet; } static rsRetVal SetMsgIdx(tcps_sess_t *pThis, int idx) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); pThis->iMsg = idx; RETiRet; } /* set our parent, the tcpsrv object */ static rsRetVal SetTcpsrv(tcps_sess_t *pThis, tcpsrv_t *pSrv) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); ISOBJ_TYPE_assert(pSrv, tcpsrv); pThis->pSrv = pSrv; RETiRet; } /* set our parent listener info*/ static rsRetVal SetLstnInfo(tcps_sess_t *pThis, tcpLstnPortList_t *pLstnInfo) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); assert(pLstnInfo != NULL); pThis->pLstnInfo = pLstnInfo; /* set cached elements */ pThis->bSuppOctetFram = pLstnInfo->cnf_params->bSuppOctetFram; pThis->bSPFramingFix = pLstnInfo->cnf_params->bSPFramingFix; pThis->compressionMode = pLstnInfo->compressionMode; pThis->compressionDriver = pLstnInfo->compressionDriver; pThis->compressionMaxExpansionRatio = pLstnInfo->compressionMaxExpansionRatio; pThis->compressionMaxDecompressedBytesPerReceive = pLstnInfo->compressionMaxDecompressedBytesPerReceive; pThis->compressionMaxTotalZstdWindowBytes = pLstnInfo->compressionMaxTotalZstdWindowBytes; RETiRet; } static rsRetVal SetUsrP(tcps_sess_t *pThis, void *pUsr) { DEFiRet; pThis->pUsr = pUsr; RETiRet; } static rsRetVal SetOnMsgReceive(tcps_sess_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *, int)) { DEFiRet; pThis->DoSubmitMessage = OnMsgReceive; RETiRet; } /* This is a helper for submitting the message to the rsyslog core. * It does some common processing, including resetting the various * state variables to a "processed" state. * Note that this function is also called if we had a buffer overflow * due to a too-long message. So far, there is no indication this * happened and it may be worth thinking about different handling * of this case (what obviously would require a change to this * function or some related code). * rgerhards, 2009-04-23 */ static rsRetVal defaultDoSubmitMessage(tcps_sess_t *pThis, struct syslogTime *stTime, time_t ttGenTime, multi_submit_t *pMultiSub) { smsg_t *pMsg; rsRetVal localRet; DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params; if (pThis->iMsg == 0) { DBGPRINTF("discarding zero-sized message\n"); FINALIZE; } if (pThis->DoSubmitMessage != NULL) { pThis->DoSubmitMessage(pThis, pThis->pMsg, pThis->iMsg); FINALIZE; } /* we now create our own message object and submit it to the queue */ CHKiRet(msgConstructWithTime(&pMsg, stTime, ttGenTime)); MsgSetRawMsg(pMsg, (char *)pThis->pMsg, pThis->iMsg); MsgSetInputName(pMsg, cnf_params->pInputName); if (cnf_params->dfltTZ[0] != '\0') MsgSetDfltTZ(pMsg, (char *)cnf_params->dfltTZ); MsgSetFlowControlType(pMsg, pThis->pSrv->bUseFlowControl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; if (pThis->streamDecompressed) { pMsg->msgFlags |= NO_LEGACY_Z_DECOMPRESS; } MsgSetRcvFrom(pMsg, pThis->fromHost); CHKiRet(MsgSetRcvFromIP(pMsg, pThis->fromHostIP)); CHKiRet(MsgSetRcvFromPort(pMsg, pThis->fromHostPort)); MsgSetRuleset(pMsg, cnf_params->pRuleset); if (pThis->bFrameOversize) { writeOversizeMessageLog(pMsg); } localRet = ratelimitAddMsg(pThis->pLstnInfo->ratelimiter, pMultiSub, pMsg); if (localRet == RS_RET_OK) { STATSCOUNTER_INC(pThis->pLstnInfo->ctrSubmit, pThis->pLstnInfo->mutCtrSubmit); } else if (localRet == RS_RET_DISCARDMSG) { DBGPRINTF("tcps_sess: message discarded by ratelimit helper\n"); iRet = RS_RET_OK; } else { DBGPRINTF("tcps_sess: ratelimit helper returned error %d, continuing\n", localRet); iRet = RS_RET_OK; } finalize_it: /* reset status variables */ pThis->iMsg = 0; pThis->bFrameOversize = 0; RETiRet; } /* This should be called before a normal (non forced) close * of a TCP session. This function checks if there is any unprocessed * message left in the TCP stream. Such a message is probably a * fragment. If everything goes well, we must be right at the * beginning of a new frame without any data received from it. If * not, there is some kind of a framing error. I think I remember that * some legacy syslog/TCP implementations have non-LF terminated * messages at the end of the stream. For now, we allow this behaviour. * Later, it should probably become a configuration option. * rgerhards, 2006-12-07 */ static rsRetVal PrepareClose(tcps_sess_t *pThis) { struct syslogTime stTime; time_t ttGenTime; DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); CHKiRet(finishCompressedStream(pThis)); if (pThis->inputState == eAtStrtFram) { /* this is how it should be. There is no unprocessed * data left and such we have nothing to do. For simplicity * reasons, we immediately return in that case. */ FINALIZE; } /* we have some data left! */ if (pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) { /* In this case, we have an invalid frame count and thus * generate an error message and discard the frame. */ LogError(0, NO_ERRCODE, "Incomplete frame at end of stream in session %p - " "ignoring extra data (a message may be lost).", pThis->pStrm); /* nothing more to do */ } else { /* here, we have traditional framing. Missing LF at the end * of message may occur. As such, we process the message in * this case. */ DBGPRINTF("Extra data at end of stream in legacy syslog/tcp message - processing\n"); datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME); defaultDoSubmitMessage(pThis, &stTime, ttGenTime, NULL); } finalize_it: RETiRet; } #ifdef FEATURE_REGEXP static rsRetVal ATTR_NONNULL() processDataRcvd_regexFraming(tcps_sess_t *const __restrict__ pThis, char **const buff, struct syslogTime *const stTime, const time_t ttGenTime, multi_submit_t *const pMultiSub, unsigned *const __restrict__ pnMsgs) { DEFiRet; const char c = **buff; if (pThis->iMsg >= 2 * pThis->iMaxLine) { LogError(0, RS_RET_OVERSIZE_MSG, "imtcp: more then double max message size (%d) " "received without finding frame terminator via regex - assuming " "end of frame now.", pThis->iMsg + 1); defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); pThis->iMsg = 0; pThis->iCurrLine = 0; } pThis->pMsg[pThis->iMsg++] = c; pThis->pMsg[pThis->iMsg] = '\0'; if (c == '\n') { pThis->iCurrLine = pThis->iMsg; } else { const int isMatch = !regexp.regexec(&pThis->pLstnInfo->start_preg, (char *)pThis->pMsg + pThis->iCurrLine, 0, NULL, 0); if (pThis->iCurrLine > 0 && isMatch) { DBGPRINTF("regex match (%d), framing line: %s\n", pThis->iCurrLine, pThis->pMsg); const size_t len_save = pThis->iMsg - pThis->iCurrLine; memmove(pThis->pMsg_save, pThis->pMsg + pThis->iCurrLine, len_save); pThis->pMsg_save[len_save] = '\0'; pThis->iMsg = pThis->iCurrLine - 1; /* remove trailing LF */ defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); memmove(pThis->pMsg, pThis->pMsg_save, len_save + 1); pThis->iMsg = len_save; pThis->iCurrLine = 0; } } RETiRet; } #endif /** * @brief Close a TCP session and release session-owned properties. * * Tears down the network stream and frees per-session sender properties * (hostname/IP). This does not flush pending data; callers should invoke * PrepareClose() beforehand when needed. The netstrm close result is ignored * because we are shutting down a session and there is no recovery path for a * close failure. */ static rsRetVal Close(tcps_sess_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); if (pThis->pStrm != NULL) { netstrm.Destruct(&pThis->pStrm); } if (pThis->fromHost != NULL) { prop.Destruct(&pThis->fromHost); } if (pThis->fromHostIP != NULL) prop.Destruct(&pThis->fromHostIP); RETiRet; } /* process the data received. As TCP is stream based, we need to process the * data inside a state machine. The actual data received is passed in byte-by-byte * from DataRcvd, and this function here compiles messages from them and submits * the end result to the queue. Introducing this function fixes a long-term bug ;) * rgerhards, 2008-03-14 */ static rsRetVal ATTR_NONNULL(1) processDataRcvd(tcps_sess_t *pThis, char **buff, const int buffLen, struct syslogTime *stTime, const time_t ttGenTime, multi_submit_t *pMultiSub, unsigned *const __restrict__ pnMsgs) { DEFiRet; const char c = **buff; const tcpLstnParams_t *const cnf_params = pThis->pLstnInfo->cnf_params; ISOBJ_TYPE_assert(pThis, tcps_sess); #ifdef FEATURE_REGEXP if (pThis->pLstnInfo->bHasStartRegex) { processDataRcvd_regexFraming(pThis, buff, stTime, ttGenTime, pMultiSub, pnMsgs); FINALIZE; } #endif if (pThis->inputState == eInMsgCheckMultiLine) { if (c == '<') { defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); pThis->inputState = eAtStrtFram; } else { /* this was a continuation line, so we need to add the LF * that we "missed" at the end of the previous packet. */ if (pThis->iMsg < pThis->iMaxLine) { *(pThis->pMsg + pThis->iMsg++) = '\n'; } pThis->inputState = eInMsg; } } if (pThis->inputState == eAtStrtFram) { if (c >= '0' && c <= '9' && pThis->bSuppOctetFram) { pThis->inputState = eInOctetCnt; pThis->bFrameOversize = 0; pThis->iOctetsRemain = 0; pThis->eFraming = TCP_FRAMING_OCTET_COUNTING; } else if (c == ' ' && pThis->bSPFramingFix) { /* Cisco ASA very occasionally sends a SP after a LF, which * thrashes framing if not taken special care of. Here, * we permit space *in front of the next frame* and * ignore it. */ FINALIZE; } else { pThis->inputState = eInMsg; pThis->bFrameOversize = 0; pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; } } if (pThis->inputState == eInMsg) { #if 0 // set to 1 for ultra-verbose DBGPRINTF("DEBUG: processDataRcvd c=%c remain=%d\n", c, pThis->iOctetsRemain); #endif if ((((c == '\n') && !pThis->pSrv->bDisableLFDelim) || ((pThis->pSrv->addtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER) && (c == pThis->pSrv->addtlFrameDelim))) && pThis->eFraming == TCP_FRAMING_OCTET_STUFFING) { /* record delimiter? */ if (cnf_params->bMultiLine) { if (buffLen > 1) { if (*(*buff + 1) == '<') { defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); pThis->inputState = eAtStrtFram; } else { if (pThis->iMsg < pThis->iMaxLine) { *(pThis->pMsg + pThis->iMsg++) = c; } } } else { /* at end of buffer, check next packet */ pThis->inputState = eInMsgCheckMultiLine; FINALIZE; } } else { defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); pThis->inputState = eAtStrtFram; } } else { /* IMPORTANT: here we copy the actual frame content to the message - for BOTH framing modes! * If we have a message that is larger than the max msg size, we truncate it. This is the best * we can do in light of what the engine supports. -- rgerhards, 2008-03-14 */ if (pThis->iMsg < pThis->iMaxLine) { *(pThis->pMsg + pThis->iMsg++) = c; } else { /* emergency, we now need to flush, no matter if we are at end of message or not... */ DBGPRINTF("error: message received is larger than max msg size, we %s it - c=%x\n", pThis->pSrv->discardTruncatedMsg == 1 ? "truncate" : "split", c); pThis->bFrameOversize = 1; defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); if (pThis->pSrv->discardTruncatedMsg == 1) { if (pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) { pThis->iOctetsRemain--; if (pThis->iOctetsRemain == 0) { pThis->inputState = eAtStrtFram; FINALIZE; } } pThis->inputState = eInMsgTruncating; FINALIZE; } } } if (pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) { /* do we need to find end-of-frame via octet counting? */ pThis->iOctetsRemain--; if (pThis->iOctetsRemain < 1) { /* we have end of frame! */ defaultDoSubmitMessage(pThis, stTime, ttGenTime, pMultiSub); ++(*pnMsgs); pThis->inputState = eAtStrtFram; } } } else if (pThis->inputState == eInMsgTruncating) { if (pThis->eFraming == TCP_FRAMING_OCTET_COUNTING) { DBGPRINTF("DEBUG: TCP_FRAMING_OCTET_COUNTING eInMsgTruncating c=%c remain=%d\n", c, pThis->iOctetsRemain); pThis->iOctetsRemain--; if (pThis->iOctetsRemain < 1) { pThis->inputState = eAtStrtFram; } } else { if (((c == '\n') && !pThis->pSrv->bDisableLFDelim) || ((pThis->pSrv->addtlFrameDelim != TCPSRV_NO_ADDTL_DELIMITER) && (c == pThis->pSrv->addtlFrameDelim))) { pThis->inputState = eAtStrtFram; } } } else { assert(pThis->inputState == eInOctetCnt); if (c >= '0' && c <= '9') { /* isdigit() the faster way */ if (pThis->iOctetsRemain <= 200000000) { pThis->iOctetsRemain = pThis->iOctetsRemain * 10 + c - '0'; } if (pThis->iMsg < pThis->iMaxLine) { *(pThis->pMsg + pThis->iMsg++) = c; } } else { /* done with the octet count, so this must be the SP terminator */ DBGPRINTF("TCP Message with octet-counter, size %d.\n", pThis->iOctetsRemain); const char *const peerName = propGetSzStrOrDefault(pThis->fromHost, "(hostname unknown)"); const char *const peerIP = propGetSzStrOrDefault(pThis->fromHostIP, "(IP unknown)"); const char *const peerPort = propGetSzStrOrDefault(pThis->fromHostPort, "(port unknown)"); if (c != ' ') { LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from " "peer: (hostname) %s, (ip) %s, (port) %s: delimiter is not SP but has " "ASCII value %d.", cnf_params->pszInputName, peerName, peerIP, peerPort, c); } if (pThis->iOctetsRemain < 1) { LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from " "peer: (hostname) %s, (ip) %s, (port) %s: invalid octet count %d.", cnf_params->pszInputName, peerName, peerIP, peerPort, pThis->iOctetsRemain); pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; } else if (pThis->iOctetsRemain > pThis->iMaxLine) { pThis->bFrameOversize = 1; /* while we can not do anything against it, we can at least log an indication * that something went wrong) -- rgerhards, 2008-03-14 */ LogError(0, NO_ERRCODE, "imtcp %s: received oversize message from peer: " "(hostname) %s, (ip) %s, (port) %s: size is %d bytes, max msg size " "is %d, truncating...", cnf_params->pszInputName, peerName, peerIP, peerPort, pThis->iOctetsRemain, pThis->iMaxLine); } if (pThis->iOctetsRemain > pThis->pSrv->maxFrameSize) { LogError(0, NO_ERRCODE, "imtcp %s: Framing Error in received TCP message from " "peer: (hostname) %s, (ip) %s, (port) %s: frame too large: %d, change " "to octet stuffing", cnf_params->pszInputName, peerName, peerIP, peerPort, pThis->iOctetsRemain); pThis->eFraming = TCP_FRAMING_OCTET_STUFFING; } else { pThis->iMsg = 0; } pThis->inputState = eInMsg; } } finalize_it: RETiRet; } /* Processes the data received via a TCP session. If there * is no other way to handle it, data is discarded. * Input parameter data is the data received, iLen is its * len as returned from recv(). iLen must be 1 or more (that * is errors must be handled by caller!). iTCPSess must be * the index of the TCP session that received the data. * rgerhards 2005-07-04 * And another change while generalizing. We now return either * RS_RET_OK, which means the session should be kept open * or anything else, which means it must be closed. * rgerhards, 2008-03-01 * As a performance optimization, we pick up the timestamp here. Actually, * this *is* the *correct* reception step for all the data we received, because * we have just received a bunch of data! -- rgerhards, 2009-06-16 */ #define NUM_MULTISUB 1024 static rsRetVal DataRcvdUncompressed(tcps_sess_t *pThis, char *pData, const size_t iLen, const sbool detectTls) { multi_submit_t multiSub; smsg_t *pMsgs[NUM_MULTISUB]; struct syslogTime stTime; time_t ttGenTime; char *pEnd; unsigned nMsgs = 0; DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); assert(pData != NULL); assert(iLen > 0); if (detectTls) { CHKiRet(maybeDetectTlsClientHello(pThis, pData, iLen)); } datetime.getCurrTime(&stTime, &ttGenTime, TIME_IN_LOCALTIME); multiSub.ppMsgs = pMsgs; multiSub.maxElem = NUM_MULTISUB; multiSub.nElem = 0; /* We now copy the message to the session buffer. */ pEnd = pData + iLen; /* this is one off, which is intentional */ while (pData < pEnd) { CHKiRet(processDataRcvd(pThis, &pData, pEnd - pData, &stTime, ttGenTime, &multiSub, &nMsgs)); pData++; } iRet = multiSubmitFlush(&multiSub); if (runConf->globals.senderKeepTrack) statsRecordSender(propGetSzStr(pThis->fromHost), nMsgs, ttGenTime); finalize_it: RETiRet; } #undef NUM_MULTISUB static rsRetVal DataRcvdUncompressedFromStream(tcps_sess_t *const pThis, char *const pData, const size_t iLen, const sbool detectTls) { const sbool previous = pThis->streamDecompressed; pThis->streamDecompressed = RSTRUE; const rsRetVal localRet = DataRcvdUncompressed(pThis, pData, iLen, detectTls); pThis->streamDecompressed = previous; return localRet; } static const char *compressionDriverName(const tcps_sess_t *const pThis) { switch (pThis->compressionDriver) { case TCPSRV_COMPRESS_DRIVER_ZSTD: return "zstd"; case TCPSRV_COMPRESS_DRIVER_ZLIB: default: return "zlib"; } } static void logCompressedStreamFailure(tcps_sess_t *const pThis, const char *const reason, const char *const detail) { const char *const host = propGetSzStrOrDefault(pThis->fromHost, "(host unknown)"); const char *const ip = propGetSzStrOrDefault(pThis->fromHostIP, "(IP unknown)"); const char *const port = propGetSzStrOrDefault(pThis->fromHostPort, "(port unknown)"); pThis->compressedStreamFailed = 1; STATSCOUNTER_INC(pThis->pLstnInfo->ctrDecompressErr, pThis->pLstnInfo->mutCtrDecompressErr); LogError(0, RS_RET_ZLIB_ERR, "imtcp: %s from %s (%s:%s), driver=%s%s%s", reason, host, ip, port, compressionDriverName(pThis), detail == NULL ? "" : ": ", detail == NULL ? "" : detail); } typedef struct decompressReceiveGuard_s { uint64_t decompressedBytes; } decompressReceiveGuard_t; static rsRetVal checkDecompressedBytesLimit(tcps_sess_t *const pThis, decompressReceiveGuard_t *const guard, const size_t len) { DEFiRet; if (UINT64_MAX - guard->decompressedBytes < len) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "per-receive decompressed byte counter overflowed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } const uint64_t newReceiveTotal = guard->decompressedBytes + len; if (pThis->compressionMaxDecompressedBytesPerReceive != 0 && newReceiveTotal > pThis->compressionMaxDecompressedBytesPerReceive) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "decompressed bytes exceeded configured per-receive limit"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (UINT64_MAX - pThis->compressionTotalBytesOut < len) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "stream decompressed byte counter overflowed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } const uint64_t newStreamTotal = pThis->compressionTotalBytesOut + len; if (pThis->compressionMaxExpansionRatio != 0) { const uint64_t maxByRatio = pThis->compressionTotalBytesIn > UINT64_MAX / pThis->compressionMaxExpansionRatio ? UINT64_MAX : pThis->compressionTotalBytesIn * pThis->compressionMaxExpansionRatio; if (newStreamTotal > maxByRatio) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "decompressed bytes exceeded configured expansion ratio"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } } guard->decompressedBytes = newReceiveTotal; pThis->compressionTotalBytesOut = newStreamTotal; finalize_it: RETiRet; } static rsRetVal DataRcvdCompressedZlib(tcps_sess_t *const pThis, char *const pData, const size_t iLen, decompressReceiveGuard_t *const guard) { uchar out[64 * 1024]; DEFiRet; if (pThis->compressedStreamEnded) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "data after end of zlib stream"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (!pThis->zipInitDone) { memset(&pThis->zstrm, 0, sizeof(pThis->zstrm)); const int zret = inflateInit(&pThis->zstrm); if (zret != Z_OK) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "zlib inflateInit failed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pThis->zipInitDone = 1; } pThis->zstrm.next_in = (Bytef *)pData; pThis->zstrm.avail_in = (uInt)iLen; do { pThis->zstrm.next_out = out; pThis->zstrm.avail_out = sizeof(out); const uInt oldAvailIn = pThis->zstrm.avail_in; const int zret = inflate(&pThis->zstrm, Z_SYNC_FLUSH); const size_t have = sizeof(out) - pThis->zstrm.avail_out; if (have != 0) { CHKiRet(checkDecompressedBytesLimit(pThis, guard, have)); STATSCOUNTER_ADD(pThis->pLstnInfo->ctrBytesDecompressed, pThis->pLstnInfo->mutCtrBytesDecompressed, have); CHKiRet(DataRcvdUncompressedFromStream(pThis, (char *)out, have, 0)); } if (zret == Z_STREAM_END) { pThis->compressedStreamEnded = 1; if (pThis->zstrm.avail_in != 0) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "data after end of zlib stream"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } release_zlib_decoder(pThis); DBGPRINTF("tcps_sess: released zlib decoder after stream completion\n"); break; } if (zret != Z_OK && zret != Z_BUF_ERROR) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "zlib inflate failed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (zret == Z_BUF_ERROR && have == 0 && pThis->zstrm.avail_in == oldAvailIn) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "zlib inflate made no progress"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } } while (pThis->zstrm.avail_in != 0 || pThis->zstrm.avail_out == 0); finalize_it: if (iRet != RS_RET_OK) release_zlib_decoder(pThis); RETiRet; } static rsRetVal DataRcvdCompressedZstd(tcps_sess_t *const pThis, char *const pData, const size_t iLen, decompressReceiveGuard_t *const guard) { #ifdef ENABLE_LIBZSTD uchar out[64 * 1024]; DEFiRet; if (pThis->compressedStreamEnded) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "data after end of zstd stream"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } size_t input_offset = 0; while (pThis->compressionMaxTotalZstdWindowBytes != 0 && !pThis->zstd_frame_header_processed) { ZSTD_frameHeader frame_header; const size_t header_ret = ZSTD_getFrameHeader(&frame_header, pThis->zstd_frame_header, pThis->zstd_frame_header_len); if (ZSTD_isError(header_ret)) { logCompressedStreamFailure(pThis, "received invalid compressed stream", ZSTD_getErrorName(header_ret)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (header_ret == 0) { if (frame_header.frameType == ZSTD_frame) { if (!reserve_zstd_window(pThis, frame_header.windowSize)) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "zstd decoder window budget exhausted"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } } pThis->zstd_frame_header_processed = RSTRUE; break; } if (header_ret > TCPSRV_ZSTD_FRAME_HEADER_MAX || header_ret <= pThis->zstd_frame_header_len) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "invalid zstd frame header size"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } const size_t need = header_ret - pThis->zstd_frame_header_len; const size_t available = iLen - input_offset; const size_t take = need < available ? need : available; memcpy(pThis->zstd_frame_header + pThis->zstd_frame_header_len, pData + input_offset, take); pThis->zstd_frame_header_len += take; input_offset += take; if (take < need) { FINALIZE; } } if (pThis->zstdDctx == NULL) { pThis->zstdDctx = ZSTD_createDCtx(); if (pThis->zstdDctx == NULL) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "zstd context allocation failed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } } const unsigned input_parts = pThis->compressionMaxTotalZstdWindowBytes == 0 ? 1 : 2; for (unsigned input_part = 0; input_part < input_parts; ++input_part) { ZSTD_inBuffer input; if (pThis->compressionMaxTotalZstdWindowBytes == 0) { input = (ZSTD_inBuffer){pData, iLen, 0}; } else if (input_part == 0) { if (pThis->zstd_frame_header_len == 0) { continue; } input = (ZSTD_inBuffer){pThis->zstd_frame_header, pThis->zstd_frame_header_len, 0}; } else { input = (ZSTD_inBuffer){pData + input_offset, iLen - input_offset, 0}; } if (input.size == 0) { continue; } ZSTD_outBuffer output; do { output.dst = out; output.size = sizeof(out); output.pos = 0; const size_t old_input_pos = input.pos; const size_t remaining = ZSTD_decompressStream((ZSTD_DCtx *)pThis->zstdDctx, &output, &input); if (ZSTD_isError(remaining)) { logCompressedStreamFailure(pThis, "received invalid compressed stream", ZSTD_getErrorName(remaining)); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (output.pos != 0) { CHKiRet(checkDecompressedBytesLimit(pThis, guard, output.pos)); STATSCOUNTER_ADD(pThis->pLstnInfo->ctrBytesDecompressed, pThis->pLstnInfo->mutCtrBytesDecompressed, output.pos); CHKiRet(DataRcvdUncompressedFromStream(pThis, (char *)out, output.pos, 0)); } if (remaining == 0) { pThis->compressedStreamEnded = 1; if (input.pos != input.size || (pThis->compressionMaxTotalZstdWindowBytes != 0 && input_part == 0 && iLen != input_offset)) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "data after end of zstd stream"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } ZSTD_freeDCtx((ZSTD_DCtx *)pThis->zstdDctx); pThis->zstdDctx = NULL; release_zstd_window_reservation(pThis); break; } if (input.pos == old_input_pos && output.pos == 0) { break; } } while (input.pos < input.size || output.pos == output.size); if (pThis->compressedStreamEnded) { break; } } if (pThis->compressionMaxTotalZstdWindowBytes != 0 && pThis->zstd_frame_header_processed) { /* Incomplete headers exit through FINALIZE above and remain buffered across receives. */ pThis->zstd_frame_header_len = 0; } finalize_it: if (iRet != RS_RET_OK) { ZSTD_freeDCtx((ZSTD_DCtx *)pThis->zstdDctx); pThis->zstdDctx = NULL; release_zstd_window_reservation(pThis); } RETiRet; #else DEFiRet; (void)pData; (void)iLen; (void)guard; logCompressedStreamFailure(pThis, "received invalid compressed stream", "zstd support is not built in"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); finalize_it: RETiRet; #endif } static rsRetVal finishCompressedStream(tcps_sess_t *pThis) { DEFiRet; if (pThis->compressionMode != TCPSRV_COMPRESS_STREAM_ALWAYS) { FINALIZE; } if (pThis->compressedStreamFailed) { FINALIZE; } if (pThis->compressionDriver == TCPSRV_COMPRESS_DRIVER_ZLIB) { if (!pThis->zipInitDone || pThis->compressedStreamEnded) { FINALIZE; } logCompressedStreamFailure(pThis, "detected truncated compressed stream", "zlib stream ended before trailer"); release_zlib_decoder(pThis); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } if (pThis->compressionDriver == TCPSRV_COMPRESS_DRIVER_ZSTD && !pThis->compressedStreamEnded) { if (pThis->zstdDctx == NULL && pThis->zstd_frame_header_len == 0) { FINALIZE; } logCompressedStreamFailure(pThis, "detected truncated compressed stream", "zstd stream ended before trailer"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } finalize_it: RETiRet; } static rsRetVal DataRcvd(tcps_sess_t *pThis, char *pData, const size_t iLen) { DEFiRet; ISOBJ_TYPE_assert(pThis, tcps_sess); assert(pData != NULL); assert(iLen > 0); STATSCOUNTER_ADD(pThis->pLstnInfo->ctrBytesRcvd, pThis->pLstnInfo->mutCtrBytesRcvd, iLen); if (pThis->compressionMode != TCPSRV_COMPRESS_STREAM_ALWAYS) { CHKiRet(DataRcvdUncompressed(pThis, pData, iLen, 1)); } else { if (UINT64_MAX - pThis->compressionTotalBytesIn < iLen) { logCompressedStreamFailure(pThis, "received invalid compressed stream", "stream compressed byte counter overflowed"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pThis->compressionTotalBytesIn += iLen; decompressReceiveGuard_t guard = {.decompressedBytes = 0}; if (pThis->compressionDriver == TCPSRV_COMPRESS_DRIVER_ZSTD) { CHKiRet(DataRcvdCompressedZstd(pThis, pData, iLen, &guard)); } else { CHKiRet(DataRcvdCompressedZlib(pThis, pData, iLen, &guard)); } } finalize_it: RETiRet; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(tcps_sess) CODESTARTobjQueryInterface(tcps_sess); if (pIf->ifVersion != tcps_sessCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->DebugPrint = tcps_sessDebugPrint; pIf->Construct = tcps_sessConstruct; pIf->ConstructFinalize = tcps_sessConstructFinalize; pIf->Destruct = tcps_sessDestruct; pIf->PrepareClose = PrepareClose; pIf->Close = Close; pIf->DataRcvd = DataRcvd; pIf->SetUsrP = SetUsrP; pIf->SetTcpsrv = SetTcpsrv; pIf->SetLstnInfo = SetLstnInfo; pIf->SetHost = SetHost; pIf->SetHostIP = SetHostIP; pIf->SetHostPort = SetHostPort; pIf->SetStrm = SetStrm; pIf->SetMsgIdx = SetMsgIdx; pIf->SetOnMsgReceive = SetOnMsgReceive; finalize_it: ENDobjQueryInterface(tcps_sess) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(tcps_sess, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(tcps_sess); /* release objects we no longer need */ objRelease(netstrm, LM_NETSTRMS_FILENAME); objRelease(datetime, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); #ifdef FEATURE_REGEXP objRelease(regexp, LM_REGEXP_FILENAME); #endif ENDObjClassExit(tcps_sess) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINObjClassInit(tcps_sess, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ CHKiRet(objUse(netstrm, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); #ifdef FEATURE_REGEXP CHKiRet(objUse(regexp, LM_REGEXP_FILENAME)); #endif CHKiRet(objUse(glbl, CORE_COMPONENT)); objRelease(glbl, CORE_COMPONENT); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, tcps_sessDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, tcps_sessConstructFinalize); ENDObjClassInit(tcps_sess) /* vim:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/net.h0000644000000000000000000000013115241075234015163 xustar0030 mtime=1787067036.602578238 29 atime=1787067036.74958099 30 ctime=1787067794.527727533 rsyslog-8.2608.0/runtime/net.h0000664000175000017500000002526215241075234014637 0ustar00rgerrger/* Definitions for network-related stuff. * * Copyright 2007-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_NET_H #define INCLUDED_NET_H #include #include #include /* this is needed on HP UX -- rgerhards, 2008-03-04 */ #include "netns_socket.h" typedef enum _TCPFRAMINGMODE { TCP_FRAMING_OCTET_STUFFING = 0, /* traditional LF-delimited */ TCP_FRAMING_OCTET_COUNTING = 1 /* -transport-tls like octet count */ } TCPFRAMINGMODE; #define F_SET(where, flag) ((where) |= (flag)) #define F_ISSET(where, flag) (((where) & (flag)) == (flag)) #define F_UNSET(where, flag) ((where) &= ~(flag)) #define ADDR_NAME 0x01 /* address is hostname wildcard) */ #define ADDR_PRI6 0x02 /* use IPv6 address prior to IPv4 when resolving */ /* portability: incase IP_FREEBIND is not defined */ #ifndef IP_FREEBIND #define IP_FREEBIND 0 #endif /* defines for IP_FREEBIND, currently being used in imudp */ #define IPFREEBIND_DISABLED 0x00 /* don't enable IP_FREEBIND in sock option */ #define IPFREEBIND_ENABLED_NO_LOG 0x01 /* enable IP_FREEBIND but no warn on success */ #define IPFREEBIND_ENABLED_WITH_LOG 0x02 /* enable IP_FREEBIND and warn on success */ #ifdef OS_BSD #ifndef _KERNEL #define s6_addr32 __u6_addr.__u6_addr32 #endif #endif struct NetAddr { uint8_t flags; union { struct sockaddr *NetAddr; char *HostWildcard; } addr; }; #ifndef SO_BSDCOMPAT /* this shall prevent compiler errors due to undefined name */ #define SO_BSDCOMPAT 0 #endif /* IPv6 compatibility layer for older platforms * We need to handle a few things different if we are running * on an older platform which does not support all the glory * of IPv6. We try to limit toll on features and reliability, * but obviously it is better to run rsyslog on a platform that * supports everything... * rgerhards, 2007-06-22 */ #ifndef AI_NUMERICSERV #define AI_NUMERICSERV 0 #endif #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN #define SALEN(sa) ((sa)->sa_len) #else static inline size_t __attribute__((unused)) SALEN(struct sockaddr *sa) { switch (sa->sa_family) { case AF_INET: return (sizeof(struct sockaddr_in)); case AF_INET6: return (sizeof(struct sockaddr_in6)); default: return 0; } } #endif struct AllowedSenders { struct NetAddr allowedSender; /* ip address allowed */ uint8_t SignificantBits; /* defines how many bits should be discarded (eqiv to mask) */ struct AllowedSenders *pNext; }; /* this structure is a helper to implement wildcards in permittedPeers_t. It specifies * the domain component and the matching mode. * rgerhards, 2008-05-27 */ struct permittedPeerWildcard_s { uchar *pszDomainPart; size_t lenDomainPart; enum { PEER_WILDCARD_NONE = 0, /**< no wildcard in this entry */ PEER_WILDCARD_AT_START = 1, /**< wildcard at start of entry (*name) */ PEER_WILDCARD_AT_END = 2, /**< wildcard at end of entry (name*) */ PEER_WILDCARD_MATCH_ALL = 3, /**< only * wildcard, matches all values */ PEER_WILDCARD_EMPTY_COMPONENT = 4 /**< special case: domain component empty (e.g. "..") */ } wildcardType; permittedPeerWildcard_t *pNext; }; /* for fingerprints and hostnames, we need to have a temporary linked list of * permitted values. Unforutnately, we must also duplicate this in the netstream * drivers. However, this is the best interim solution (with the least effort). * A clean implementation requires that we have more capable variables and the * full-fledged scripting engine available. So we have opted to do the interim * solution so that our users can begin to enjoy authenticated TLS. The next step * (hopefully) is to enhance RainerScript. -- rgerhards, 2008-05-19 */ struct permittedPeers_s { uchar *pszID; enum { PERM_PEER_TYPE_UNDECIDED = 0, /**< we have not yet decided the type (fine in some auth modes) */ PERM_PEER_TYPE_PLAIN = 1, /**< just plain text contained */ PERM_PEER_TYPE_WILDCARD = 2, /**< wildcards are contained, wildcard struture is filled */ } etryType; permittedPeers_t *pNext; permittedPeerWildcard_t *pWildcardRoot; /**< root of the wildcard, NULL if not initialized */ permittedPeerWildcard_t *pWildcardLast; /**< end of the wildcard list, NULL if not initialized */ }; /* interfaces */ BEGINinterface(net) /* name must also be changed in ENDinterface macro! */ rsRetVal (*cvthname)(struct sockaddr_storage *f, prop_t **localName, prop_t **fqdn, prop_t **ip); /* things to go away after proper modularization */ rsRetVal (*addAllowedSenderLine)(char *pName, uchar **ppRestOfConfLine); rsRetVal (*addAllowedSenderEntry)(struct AllowedSenders **ppRoot, struct AllowedSenders **ppLast, uchar *pszAllowedSender); void (*DestructAllowedSenders)(struct AllowedSenders **ppRoot); void (*PrintAllowedSenders)(int iListToPrint); void (*clearAllowedSenders)(uchar *); void (*debugListenInfo)(int fd, char *type); int *(*create_udp_socket)(uchar *hostname, uchar *LogPort, int bIsServer, int rcvbuf, int sndbuf, int ipfreebind, char *device); void (*closeUDPListenSockets)(int *finet); int (*isAllowedSender)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost); /* deprecated! */ rsRetVal (*getLocalHostname)(rsconf_t *const, uchar **); int (*should_use_so_bsdcompat)(void); /* permitted peer handling should be replaced by something better (see comments above) */ rsRetVal (*AddPermittedPeer)(permittedPeers_t **ppRootPeer, uchar *pszID); rsRetVal (*DestructPermittedPeers)(permittedPeers_t **ppRootPeer); rsRetVal (*PermittedPeerWildcardMatch)(permittedPeers_t *pPeer, const uchar *pszNameToMatch, int *pbIsMatching); /* v5 interface additions */ int (*CmpHost)(struct sockaddr_storage *, struct sockaddr_storage *, size_t); /* v6 interface additions - 2009-11-16 */ rsRetVal (*HasRestrictions)(uchar *, int *bHasRestrictions); int (*isAllowedSenderList)(struct AllowedSenders *pAllowRoot, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS); int (*isAllowedSender2)(uchar *pszType, struct sockaddr *pFrom, const char *pszFromHost, int bChkDNS); /* v7 interface additions - 2012-03-06 */ rsRetVal (*GetIFIPAddr)(uchar *szif, int family, uchar *pszbuf, int lenBuf); /* v8 cvthname() signature change -- rgerhards, 2013-01-18 */ /* v9 create_udp_socket() signature change -- dsahern, 2016-11-11 */ /* v10 moved data members to rsconf_t -- alakatos, 2021-12-29 */ /* v11 netns functions -- balsup, 2025-09-11 */ /* * @brief Open a socket on the given namespace * @param fdp A place to store the descriptor. This must not be NULL. * A failure will store -1 here. * @param domain The communication domain argument to the underlying socket call * @param type The type argument to the underlying socket call * @param protocol The protocol argument to the underlying socket call * @param ns The desired namespace. This may be NULL or the empty string if * the current namespace is desired. * @return RS_RET_OK on success, otherwise a failure code. * @details This is a wrapper to socket, allowing one to open a socket in * a given namespace. For platforms that do not support network * namespaces, an error will be returned if the ns parameter * is not NULL or the empty string. */ rsRetVal (*netns_socket)(int *fdp, int domain, int type, int protocol, const char *ns); /* * @brief Switch to the given network namespace * @param ns The desired namespace. If this is NULL or the empty string, then * this function is a no-op. * @return RS_RET_OK on success, otherwise a failure code. * @details For platforms that do not support network namespaces, an error will * be returned if the ns parameter is not NULL or the empty string. */ rsRetVal (*netns_switch)(const char *ns); /* * @brief Save a descriptor to the current network namespace * @param fd The location to store the descriptor for the current * namespace. This must not not be NULL, and the * descriptor must be pre-initialized to -1, i.e. *fd == -1 * is a precondition. This style is to prevent inadvertent * descriptor leaks that might arise by overwriting a valid * descriptor. * @return RS_RET_OK on success, otherwise a failure code. * @details For platforms that do not support network namespaces, this * function is a no-op and will always return RS_RET_OK. */ rsRetVal (*netns_save)(int *fd); /* * @brief Restore the original network namespace * @param fd A pointer to a descriptor associated with the original * namespace. This must not not be NULL. If the descriptor * is -1, then this function is a no-op. A valid descriptor * is always closed as a side-effect of this function, * with the descriptor being updated to -1. * @return RS_RET_OK on success, otherwise a failure code. * @details For platforms that do not support network namespaces, this * function cannot change the network namespace. However, if * presented with an fd that is not -1, it will still close * that fd and reset the value to -1. */ rsRetVal (*netns_restore)(int *fd); ENDinterface(net) #define netCURR_IF_VERSION 12 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(net); /* the name of our library binary */ #define LM_NET_FILENAME "lmnet" #endif /* #ifndef INCLUDED_NET_H */ rsyslog-8.2608.0/runtime/PaxHeaders/obj.c0000644000000000000000000000013215241075234015143 xustar0030 mtime=1787067036.605578294 30 atime=1787067036.751581028 30 ctime=1787067794.348724198 rsyslog-8.2608.0/runtime/obj.c0000664000175000017500000012776615241075234014632 0ustar00rgerrger/* obj.c * * This file implements a generic object "class". All other classes can * use the service of this base class here to include auto-destruction and * other capabilities in a generic manner. * * As of 2008-02-29, I (rgerhards) am adding support for dynamically loadable * objects. In essence, each object will soon be available via its interface, * only. Before any object's code is accessed (including global static methods), * the caller needs to obtain an object interface. To do so, it needs to provide * the object name and the file where the object is expected to reside in. A * file may not be given, in which case the object is expected to reside in * the rsyslog core. The caller than receives an interface pointer which can * be utilized to access all the object's methods. This method enables rsyslog * to load library modules on demand. In order to keep overhead low, callers * should request object interface only once in the object Init function and * free them when they exit. The only exception is when a caller needs to * access an object only conditional, in which case a pointer to its interface * shall be acquired as need first arises but still be released only on exit * or when there definitely is no further need. The whole idea is to limit * the very performance-intense act of dynamically loading an objects library. * Of course, it is possible to violate this suggestion, but than you should * have very good reasoning to do so. * * Please note that there is one trick we need to do. Each object queries * the object interfaces and it does so via objUse(). objUse, however, is * part of the obj object's interface (implemented via the file you are * just reading). So in order to obtain a pointer to objUse, we need to * call it - obviously not possible. One solution would be that objUse is * hardcoded into all callers. That, however, would bring us into slight * trouble with actually dynamically loaded modules, as we should NOT * rely on the OS loader to resolve symbols back to the caller (this * is a feature not universally available and highly importable). Of course, * we can solve this with a pHostQueryEtryPoint() call. It still sounds * somewhat unnatural to call a regular interface function via a special * method. So what we do instead is define a special function called * objGetObjInterface() which delivers our own interface. That function * than will be defined global and be queriable via pHostQueryEtryPoint(). * I agree, technically this is much the same, but from an architecture * point of view it looks cleaner (at least to me). * * Please note that there is another egg-hen problem: we use a linked list, * which is provided by the linkedList object. However, we need to * initialize the linked list before we can provide the UseObj() * functionality. That, in turn, would probably be required by the * linkedList object. So the solution is to use a backdoor just to * init the linked list and from then on use the usual interfaces. * * File begun on 2008-01-04 by RGerhards * * Copyright 2008-2024 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */ /* how many objects are supported by rsyslogd? */ #define OBJ_NUM_IDS 100 #include "rsyslog.h" #include "syslogd-types.h" #include "srUtils.h" #include "obj.h" #include "stream.h" #include "modules.h" #include "errmsg.h" #include "cfsysline.h" #include "unicode-helper.h" #include "datetime.h" #include "atomic.h" /* static data */ DEFobjCurrIf(obj) /* we define our own interface, as this is expected by some macros! */ DEFobjCurrIf(var) DEFobjCurrIf(module) DEFobjCurrIf(strm) static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information pointers */ pthread_mutex_t mutObjGlobalOp; /* mutex to guard global operations of the object system */ /* cookies for serialized lines */ #define COOKIE_OBJLINE '<' #define COOKIE_PROPLINE '+' #define COOKIE_ENDLINE '>' #define COOKIE_BLANKLINE '.' /* forward definitions */ static rsRetVal FindObjInfo(const char *szObjName, objInfo_t **ppInfo); /* methods */ /* This is a dummy method to be used when a standard method has not been * implemented by an object. Having it allows us to simply call via the * jump table without any NULL pointer checks - which gains quite * some performance. -- rgerhards, 2008-01-04 */ static rsRetVal objInfoNotImplementedDummy(void __attribute__((unused)) * pThis) { return RS_RET_NOT_IMPLEMENTED; } /* and now the macro to check if something is not implemented * must be provided an objInfo_t pointer. */ #define objInfoIsImplemented(pThis, method) \ (pThis->objMethods[method] != (rsRetVal(*)(void *, ...))objInfoNotImplementedDummy) /* construct an object Info object. Each class shall do this on init. The * resulting object shall be cached during the lifetime of the class and each * object shall receive a reference. A constructor and destructor MUST be provided for all * objects, thus they are in the parameter list. * pszID is the identifying object name and must point to constant pool memory. It is never freed. */ static rsRetVal InfoConstruct(objInfo_t **ppThis, uchar *pszID, int iObjVers, rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *), rsRetVal (*pQueryIF)(interface_t *), modInfo_t *pModInfo) { DEFiRet; int i; objInfo_t *pThis; assert(ppThis != NULL); if ((pThis = calloc(1, sizeof(objInfo_t))) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); pThis->pszID = pszID; pThis->lenID = ustrlen(pszID); pThis->pszName = ustrdup(pszID); /* it's OK if we have NULL ptr, GetName() will deal with that! */ pThis->iObjVers = iObjVers; pThis->QueryIF = pQueryIF; pThis->pModInfo = pModInfo; pThis->objMethods[0] = (rsRetVal(*)(void *, ...))pConstruct; pThis->objMethods[1] = (rsRetVal(*)(void *, ...))pDestruct; for (i = 2; i < OBJ_NUM_METHODS; ++i) { pThis->objMethods[i] = (rsRetVal(*)(void *, ...))objInfoNotImplementedDummy; } *ppThis = pThis; finalize_it: RETiRet; } /* destruct the objInfo object - must be done only when no more instances exist. * rgerhards, 2008-03-10 */ static rsRetVal InfoDestruct(objInfo_t **ppThis) { DEFiRet; objInfo_t *pThis; assert(ppThis != NULL); pThis = *ppThis; assert(pThis != NULL); free(pThis->pszName); free(pThis); *ppThis = NULL; RETiRet; } /* set a method handler */ static rsRetVal InfoSetMethod(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void *)) { pThis->objMethods[objMethod] = (rsRetVal(*)(void *, ...))pHandler; return RS_RET_OK; } /* destruct the base object properties. * rgerhards, 2008-01-29 */ static rsRetVal DestructObjSelf(obj_t *pThis) { DEFiRet; ISOBJ_assert(pThis); free(pThis->pszName); RETiRet; } /* --------------- object serializiation / deserialization support --------------- */ /* serialize the header of an object * pszRecType must be either "Obj" (Object) or "OPB" (Object Property Bag) */ static rsRetVal objSerializeHeader(strm_t *pStrm, obj_t *pObj, uchar *pszRecType) { DEFiRet; ISOBJ_TYPE_assert(pStrm, strm); ISOBJ_assert(pObj); assert(!strcmp((char *)pszRecType, "Obj") || !strcmp((char *)pszRecType, "OPB")); /* object cookie and serializer version (so far always 1) */ CHKiRet(strm.WriteChar(pStrm, COOKIE_OBJLINE)); CHKiRet(strm.Write(pStrm, (uchar *)pszRecType, 3)); /* record types are always 3 octets */ CHKiRet(strm.WriteChar(pStrm, ':')); CHKiRet(strm.WriteChar(pStrm, '1')); /* object type, version and string length */ CHKiRet(strm.WriteChar(pStrm, ':')); CHKiRet(strm.Write(pStrm, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID)); CHKiRet(strm.WriteChar(pStrm, ':')); CHKiRet(strm.WriteLong(pStrm, objGetVersion(pObj))); /* record trailer */ CHKiRet(strm.WriteChar(pStrm, ':')); CHKiRet(strm.WriteChar(pStrm, '\n')); finalize_it: RETiRet; } /* begin serialization of an object * rgerhards, 2008-01-06 */ static rsRetVal BeginSerialize(strm_t *pStrm, obj_t *pObj) { DEFiRet; ISOBJ_TYPE_assert(pStrm, strm); ISOBJ_assert(pObj); CHKiRet(strm.RecordBegin(pStrm)); CHKiRet(objSerializeHeader(pStrm, pObj, (uchar *)"Obj")); finalize_it: RETiRet; } /* begin serialization of an object's property bag * Note: a property bag is used to serialize some of an objects * properties, but not necessarily all. A good example is the queue * object, which at some stage needs to serialize a number of its * properties, but not the queue data itself. From the object point * of view, a property bag can not be used to re-instantiate an object. * Otherwise, the serialization is exactly the same. * rgerhards, 2008-01-11 */ static rsRetVal BeginSerializePropBag(strm_t *pStrm, obj_t *pObj) { DEFiRet; ISOBJ_TYPE_assert(pStrm, strm); ISOBJ_assert(pObj); CHKiRet(strm.RecordBegin(pStrm)); CHKiRet(objSerializeHeader(pStrm, pObj, (uchar *)"OPB")); finalize_it: RETiRet; } /* append a property */ static rsRetVal SerializeProp(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr) { DEFiRet; uchar *pszBuf = NULL; size_t lenBuf = 0; uchar szBuf[64]; varType_t vType = VARTYPE_NONE; ISOBJ_TYPE_assert(pStrm, strm); assert(pszPropName != NULL); /*dbgprintf("objSerializeProp: strm %p, propName '%s', type %d, pUsr %p\n", pStrm, pszPropName, propType, pUsr);*/ /* if we have no user pointer, there is no need to write this property. * TODO: think if that's the righ point of view * rgerhards, 2008-01-06 */ if (pUsr == NULL) { ABORT_FINALIZE(RS_RET_OK); } /* TODO: use the stream functions for data conversion here - should be quicker */ switch (propType) { case PROPTYPE_PSZ: pszBuf = (uchar *)pUsr; lenBuf = ustrlen(pszBuf); vType = VARTYPE_STR; break; case PROPTYPE_SHORT: CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), (number_t) * ((short *)pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_INT: CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), (number_t) * ((int *)pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_LONG: CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), (number_t) * ((long *)pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_INT64: CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), *((int64 *)pUsr))); pszBuf = szBuf; lenBuf = ustrlen(szBuf); vType = VARTYPE_NUMBER; break; case PROPTYPE_CSTR: pszBuf = rsCStrGetSzStrNoNULL((cstr_t *)pUsr); lenBuf = rsCStrLen((cstr_t *)pUsr); vType = VARTYPE_STR; break; case PROPTYPE_SYSLOGTIME: lenBuf = snprintf((char *)szBuf, sizeof(szBuf), "%d:%d:%d:%d:%d:%d:%d:%d:%d:%c:%d:%d", ((syslogTime_t *)pUsr)->timeType, ((syslogTime_t *)pUsr)->year, ((syslogTime_t *)pUsr)->month, ((syslogTime_t *)pUsr)->day, ((syslogTime_t *)pUsr)->hour, ((syslogTime_t *)pUsr)->minute, ((syslogTime_t *)pUsr)->second, ((syslogTime_t *)pUsr)->secfrac, ((syslogTime_t *)pUsr)->secfracPrecision, ((syslogTime_t *)pUsr)->OffsetMode, ((syslogTime_t *)pUsr)->OffsetHour, ((syslogTime_t *)pUsr)->OffsetMinute); if (lenBuf > sizeof(szBuf) - 1) ABORT_FINALIZE(RS_RET_PROVIDED_BUFFER_TOO_SMALL); vType = VARTYPE_SYSLOGTIME; pszBuf = szBuf; break; case PROPTYPE_NONE: default: dbgprintf("invalid PROPTYPE %d\n", propType); break; } /* cookie */ CHKiRet(strm.WriteChar(pStrm, COOKIE_PROPLINE)); /* name */ CHKiRet(strm.Write(pStrm, pszPropName, ustrlen(pszPropName))); CHKiRet(strm.WriteChar(pStrm, ':')); /* type */ CHKiRet(strm.WriteLong(pStrm, (int)vType)); CHKiRet(strm.WriteChar(pStrm, ':')); /* length */ CHKiRet(strm.WriteLong(pStrm, lenBuf)); CHKiRet(strm.WriteChar(pStrm, ':')); /* data */ CHKiRet(strm.Write(pStrm, (uchar *)pszBuf, lenBuf)); /* trailer */ CHKiRet(strm.WriteChar(pStrm, ':')); CHKiRet(strm.WriteChar(pStrm, '\n')); finalize_it: RETiRet; } /* end serialization of an object. The caller receives a * standard C string, which he must free when no longer needed. */ static rsRetVal EndSerialize(strm_t *pStrm) { DEFiRet; assert(pStrm != NULL); CHKiRet(strm.WriteChar(pStrm, COOKIE_ENDLINE)); CHKiRet(strm.Write(pStrm, (uchar *)"End\n", sizeof("END\n") - 1)); CHKiRet(strm.WriteChar(pStrm, COOKIE_BLANKLINE)); CHKiRet(strm.WriteChar(pStrm, '\n')); CHKiRet(strm.RecordEnd(pStrm)); finalize_it: RETiRet; } /* define a helper to make code below a bit cleaner (and quicker to write) */ #define NEXTC CHKiRet(strm.ReadChar(pStrm, &c)) /*;dbgprintf("c: %c\n", c)*/ /* de-serialize an embedded, non-octect-counted string. This is useful * for deserializing the object name inside the header. The string is * terminated by the first occurrence of the ':' character. * rgerhards, 2008-02-29 */ static rsRetVal objDeserializeEmbedStr(cstr_t **ppStr, strm_t *pStrm) { DEFiRet; uchar c; cstr_t *pStr = NULL; assert(ppStr != NULL); CHKiRet(cstrConstruct(&pStr)); NEXTC; while (c != ':') { CHKiRet(cstrAppendChar(pStr, c)); NEXTC; } cstrFinalize(pStr); *ppStr = pStr; finalize_it: if (iRet != RS_RET_OK && pStr != NULL) cstrDestruct(&pStr); RETiRet; } /* de-serialize a number */ static rsRetVal objDeserializeNumber(number_t *pNum, strm_t *pStrm) { DEFiRet; number_t i; int bIsNegative; uchar c; assert(pNum != NULL); NEXTC; if (c == '-') { bIsNegative = 1; NEXTC; } else { bIsNegative = 0; } /* we check this so that we get more meaningful error codes */ if (!isdigit(c)) ABORT_FINALIZE(RS_RET_INVALID_NUMBER); i = 0; while (isdigit(c)) { i = i * 10 + c - '0'; NEXTC; } if (c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER); if (bIsNegative) i *= -1; *pNum = i; finalize_it: RETiRet; } /* de-serialize a string, length must be provided but may be 0 */ static rsRetVal objDeserializeStr(cstr_t **ppCStr, int iLen, strm_t *pStrm) { DEFiRet; int i; uchar c; cstr_t *pCStr = NULL; assert(ppCStr != NULL); assert(iLen >= 0); CHKiRet(cstrConstruct(&pCStr)); NEXTC; for (i = 0; i < iLen; ++i) { CHKiRet(cstrAppendChar(pCStr, c)); NEXTC; } cstrFinalize(pCStr); /* check terminator */ if (c != ':') { /* Initialized to NULL */ *ppCStr = NULL; ABORT_FINALIZE(RS_RET_INVALID_DELIMITER); } *ppCStr = pCStr; finalize_it: if (iRet != RS_RET_OK && pCStr != NULL) cstrDestruct(&pCStr); RETiRet; } /* de-serialize a syslogTime -- rgerhards,2008-01-08 */ #define GETVAL(var) \ CHKiRet(objDeserializeNumber(&l, pStrm)); \ pTime->var = l; static rsRetVal objDeserializeSyslogTime(syslogTime_t *pTime, strm_t *pStrm) { DEFiRet; number_t l; uchar c; assert(pTime != NULL); GETVAL(timeType); GETVAL(year); GETVAL(month); GETVAL(day); GETVAL(hour); GETVAL(minute); GETVAL(second); GETVAL(secfrac); GETVAL(secfracPrecision); /* OffsetMode is a single character! */ NEXTC; pTime->OffsetMode = c; NEXTC; if (c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER); GETVAL(OffsetHour); GETVAL(OffsetMinute); finalize_it: RETiRet; } #undef GETVAL /* de-serialize an object header * rgerhards, 2008-01-07 */ static rsRetVal objDeserializeHeader(uchar *pszRecType, cstr_t **ppstrID, int *poVers, strm_t *pStrm) { DEFiRet; number_t oVers; uchar c; assert(ppstrID != NULL); assert(poVers != NULL); assert(!strcmp((char *)pszRecType, "Obj") || !strcmp((char *)pszRecType, "OPB")); /* check header cookie */ NEXTC; if (c != COOKIE_OBJLINE) ABORT_FINALIZE(RS_RET_INVALID_HEADER); NEXTC; if (c != pszRecType[0]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE); NEXTC; if (c != pszRecType[1]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE); NEXTC; if (c != pszRecType[2]) ABORT_FINALIZE(RS_RET_INVALID_HEADER_RECTYPE); NEXTC; if (c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER); NEXTC; if (c != '1') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS); NEXTC; if (c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS); /* object type and version */ CHKiRet(objDeserializeEmbedStr(ppstrID, pStrm)); CHKiRet(objDeserializeNumber(&oVers, pStrm)); /* and now we skip over the rest until the delemiting \n */ NEXTC; while (c != '\n') { NEXTC; } *poVers = oVers; finalize_it: RETiRet; } /* Deserialize a single property. Pointer must be positioned at begin of line. Whole line * up until the \n is read. */ rsRetVal objDeserializeProperty(var_t *pProp, strm_t *pStrm) { DEFiRet; number_t i; number_t iLen; uchar c; int step = 0; /* which step was successful? */ int64 offs; assert(pProp != NULL); /* check cookie */ NEXTC; if (c != COOKIE_PROPLINE) { /* oops, we've read one char that does not belong to use - unget it first */ CHKiRet(strm.UnreadChar(pStrm, c)); ABORT_FINALIZE(RS_RET_NO_PROPLINE); } /* get the property name first */ CHKiRet(cstrConstruct(&pProp->pcsName)); NEXTC; while (c != ':') { CHKiRet(cstrAppendChar(pProp->pcsName, c)); NEXTC; } cstrFinalize(pProp->pcsName); step = 1; /* property type */ CHKiRet(objDeserializeNumber(&i, pStrm)); pProp->varType = i; step = 2; /* size (needed for strings) */ CHKiRet(objDeserializeNumber(&iLen, pStrm)); step = 3; /* we now need to deserialize the value */ switch (pProp->varType) { case VARTYPE_STR: CHKiRet(objDeserializeStr(&pProp->val.pStr, iLen, pStrm)); break; case VARTYPE_NUMBER: CHKiRet(objDeserializeNumber(&pProp->val.num, pStrm)); break; case VARTYPE_SYSLOGTIME: CHKiRet(objDeserializeSyslogTime(&pProp->val.vSyslogTime, pStrm)); break; case VARTYPE_NONE: default: dbgprintf("invalid VARTYPE %d\n", pProp->varType); break; } step = 4; /* we should now be at the end of the line. So the next char must be \n */ NEXTC; if (c != '\n') ABORT_FINALIZE(RS_RET_INVALID_PROPFRAME); finalize_it: /* ensure the type of var is reset back to VARTYPE_NONE since * the deconstruct method of var might free unallocated memory */ if (iRet != RS_RET_OK && iRet != RS_RET_NO_PROPLINE) { if (pProp->varType == VARTYPE_STR && step < 4) { pProp->val.pStr = NULL; } if (step <= 2) { pProp->varType = VARTYPE_NONE; } } if (Debug && iRet != RS_RET_OK && iRet != RS_RET_NO_PROPLINE) { strm.GetCurrOffset(pStrm, &offs); dbgprintf("error %d deserializing property name, offset %lld, step %d\n", iRet, offs, step); strmDebugOutBuf(pStrm); if (step >= 1) { dbgprintf("error property name: '%s'\n", rsCStrGetSzStrNoNULL(pProp->pcsName)); } if (step >= 2) { dbgprintf("error var type: '%d'\n", pProp->varType); } if (step >= 3) { dbgprintf("error len: '%d'\n", (int)iLen); } if (step >= 4) { switch (pProp->varType) { case VARTYPE_STR: dbgprintf("error data string: '%s'\n", rsCStrGetSzStrNoNULL(pProp->val.pStr)); break; case VARTYPE_NUMBER: dbgprintf("error number: %d\n", (int)pProp->val.num); break; case VARTYPE_SYSLOGTIME: dbgprintf( "syslog time was successfully parsed (but " "is not displayed\n"); break; case VARTYPE_NONE: default: break; } } } RETiRet; } /* de-serialize an object trailer. This does not get any data but checks if the * format is ok. * rgerhards, 2008-01-07 */ static rsRetVal objDeserializeTrailer(strm_t *pStrm) { DEFiRet; uchar c; /* check header cookie */ NEXTC; if (c != COOKIE_ENDLINE) ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != 'E') ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != 'n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != 'd') ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != COOKIE_BLANKLINE) ABORT_FINALIZE(RS_RET_INVALID_TRAILER); NEXTC; if (c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER); finalize_it: if (Debug && iRet != RS_RET_OK) { dbgprintf("objDeserializeTrailer fails with %d\n", iRet); } RETiRet; } /* This method tries to recover a serial store if it got out of sync. * To do so, it scans the line beginning cookies and waits for the object * cookie. If that is found, control is returned. If the store is exhausted, * we will receive an RS_RET_EOF error as part of NEXTC, which will also * terminate this function. So we may either return with somehting that * looks like a valid object or end of store. * rgerhards, 2008-01-07 */ static rsRetVal objDeserializeTryRecover(strm_t *pStrm) { DEFiRet; uchar c; int bWasNL; int bRun; assert(pStrm != NULL); bRun = 1; bWasNL = 0; while (bRun) { NEXTC; if (c == '\n') bWasNL = 1; else { if (bWasNL == 1 && c == COOKIE_OBJLINE) bRun = 0; /* we found it! */ else bWasNL = 0; } } CHKiRet(strm.UnreadChar(pStrm, c)); finalize_it: dbgprintf("deserializer has possibly been able to re-sync and recover, state %d\n", iRet); RETiRet; } static void varResetState(var_t *pVar) { rsCStrDestruct(&pVar->pcsName); /* no longer needed */ if (pVar->varType == VARTYPE_STR) { rsCStrDestruct(&pVar->val.pStr); } memset(&pVar->val, 0, sizeof(pVar->val)); pVar->varType = VARTYPE_NONE; } /* De-serialize the properties of an object. This includes processing * of the trailer. Header must already have been processed. * rgerhards, 2008-01-11 */ static rsRetVal objDeserializeProperties(obj_t *pObj, rsRetVal (*objSetProperty)(void *, ...), strm_t *pStrm) { DEFiRet; var_t *pVar = NULL; ISOBJ_assert(pObj); ISOBJ_TYPE_assert(pStrm, strm); CHKiRet(var.Construct(&pVar)); CHKiRet(var.ConstructFinalize(pVar)); iRet = objDeserializeProperty(pVar, pStrm); while (iRet == RS_RET_OK) { CHKiRet(objSetProperty(pObj, pVar)); varResetState(pVar); iRet = objDeserializeProperty(pVar, pStrm); } if (iRet != RS_RET_NO_PROPLINE) FINALIZE; CHKiRet(objDeserializeTrailer(pStrm)); /* do trailer checks */ finalize_it: if (pVar != NULL) var.Destruct(&pVar); RETiRet; } /* De-Serialize an object. * Params: Pointer to object Pointer (pObj) (like a obj_t**, but can not do that due to compiler warning) * expected object ID (to check against), a fixup function that can modify the object before it is finalized * and a user pointer that is to be passed to that function in addition to the object. The fixup function * pointer may be NULL, in which case none is called. * The caller must destruct the created object. * rgerhards, 2008-01-07 */ static rsRetVal Deserialize( void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t *, void *), void *pUsr) { DEFiRet; rsRetVal iRetLocal; obj_t *pObj = NULL; int oVers = 0; /* keep compiler happy, but it is totally useless but takes up some execution time... */ cstr_t *pstrID = NULL; objInfo_t *pObjInfo; assert(ppObj != NULL); assert(pszTypeExpected != NULL); ISOBJ_TYPE_assert(pStrm, strm); /* we de-serialize the header. if all goes well, we are happy. However, if * we experience a problem, we try to recover. We do this by skipping to * the next object header. This is defined via the line-start cookies. In * worst case, we exhaust the queue, but then we receive EOF return state, * from objDeserializeTryRecover(), what will cause us to ultimately give up. * rgerhards, 2008-07-08 */ do { iRetLocal = objDeserializeHeader((uchar *)"Obj", &pstrID, &oVers, pStrm); if (iRetLocal != RS_RET_OK) { dbgprintf("objDeserialize error %d during header processing - trying to recover\n", iRetLocal); CHKiRet(objDeserializeTryRecover(pStrm)); } } while (iRetLocal != RS_RET_OK); if (rsCStrSzStrCmp(pstrID, pszTypeExpected, ustrlen(pszTypeExpected))) ABORT_FINALIZE(RS_RET_INVALID_OID); CHKiRet(FindObjInfo((char *)cstrGetSzStrNoNULL(pstrID), &pObjInfo)); CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCT](&pObj)); /* we got the object, now we need to fill the properties */ CHKiRet( objDeserializeProperties(pObj, (rsRetVal(*)(void *, ...))pObjInfo->objMethods[objMethod_SETPROPERTY], pStrm)); /* check if we need to call a fixup function that modifies the object * before it is finalized. -- rgerhards, 2008-01-13 */ if (fFixup != NULL) CHKiRet(fFixup(pObj, pUsr)); /* we have a valid object, let's finalize our work and return */ if (objInfoIsImplemented(pObjInfo, objMethod_CONSTRUCTION_FINALIZER)) CHKiRet(pObjInfo->objMethods[objMethod_CONSTRUCTION_FINALIZER](pObj)); *((obj_t **)ppObj) = pObj; finalize_it: if (iRet != RS_RET_OK && pObj != NULL) free(pObj); /* TODO: check if we can call destructor 2008-01-13 rger */ if (pstrID != NULL) rsCStrDestruct(&pstrID); RETiRet; } /* De-Serialize an object, with known constructur and destructor. Params like Deserialize(). * Note: this is for the queue subsystem, and optimized for its use. * rgerhards, 2012-11-03 */ rsRetVal objDeserializeWithMethods(void *ppObj, uchar *pszTypeExpected, int lenTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t *, void *), void *pUsr, rsRetVal (*objConstruct)(void **), rsRetVal (*objConstructFinalize)(void *), rsRetVal (*objDeserialize)(void *, strm_t *)) { DEFiRet; rsRetVal iRetLocal; obj_t *pObj = NULL; int oVers = 0; /* keep compiler happy, but it is totally useless but takes up some execution time... */ cstr_t *pstrID = NULL; assert(ppObj != NULL); assert(pszTypeExpected != NULL); ISOBJ_TYPE_assert(pStrm, strm); /* we de-serialize the header. if all goes well, we are happy. However, if * we experience a problem, we try to recover. We do this by skipping to * the next object header. This is defined via the line-start cookies. In * worst case, we exhaust the queue, but then we receive EOF return state, * from objDeserializeTryRecover(), what will cause us to ultimately give up. * rgerhards, 2008-07-08 */ do { iRetLocal = objDeserializeHeader((uchar *)"Obj", &pstrID, &oVers, pStrm); if (iRetLocal != RS_RET_OK) { dbgprintf( "objDeserialize error %d during header processing - " "trying to recover\n", iRetLocal); CHKiRet(objDeserializeTryRecover(pStrm)); } } while (iRetLocal != RS_RET_OK); if (rsCStrSzStrCmp(pstrID, pszTypeExpected, lenTypeExpected)) ABORT_FINALIZE(RS_RET_INVALID_OID); CHKiRet(objConstruct((void **)&pObj)); /* we got the object, now we need to fill the properties */ CHKiRet(objDeserialize(pObj, pStrm)); CHKiRet(objDeserializeTrailer(pStrm)); /* do trailer checks */ /* check if we need to call a fixup function that modifies the object * before it is finalized. -- rgerhards, 2008-01-13 */ if (fFixup != NULL) CHKiRet(fFixup(pObj, pUsr)); /* we have a valid object, let's finalize our work and return */ if (objConstructFinalize != NULL) { CHKiRet(objConstructFinalize(pObj)); } *((obj_t **)ppObj) = pObj; finalize_it: if (iRet != RS_RET_OK && pObj != NULL) free(pObj); /* TODO: check if we can call destructor 2008-01-13 rger */ if (pstrID != NULL) rsCStrDestruct(&pstrID); if (Debug && iRet != RS_RET_OK) { dbgprintf("objDeserializeWithMethods fails with %d, stream state:\n", iRet); strmDebugOutBuf(pStrm); } RETiRet; } /* De-Serialize an object property bag. As a property bag contains only partial properties, * it is not instanciable. Thus, the caller must provide a pointer of an already-instanciated * object of the correct type. * Params: Pointer to object (pObj) * Pointer to be passed to the function * The caller must destruct the created object. * rgerhards, 2008-01-07 */ static rsRetVal DeserializePropBag(obj_t *pObj, strm_t *pStrm) { DEFiRet; rsRetVal iRetLocal; cstr_t *pstrID = NULL; int oVers; objInfo_t *pObjInfo; ISOBJ_assert(pObj); ISOBJ_TYPE_assert(pStrm, strm); /* we de-serialize the header. if all goes well, we are happy. However, if * we experience a problem, we try to recover. We do this by skipping to * the next object header. This is defined via the line-start cookies. In * worst case, we exhaust the queue, but then we receive EOF return state * from objDeserializeTryRecover(), what will cause us to ultimately give up. * rgerhards, 2008-07-08 */ do { iRetLocal = objDeserializeHeader((uchar *)"OPB", &pstrID, &oVers, pStrm); if (iRetLocal != RS_RET_OK) { dbgprintf("objDeserializePropBag error %d during header - trying to recover\n", iRetLocal); CHKiRet(objDeserializeTryRecover(pStrm)); } } while (iRetLocal != RS_RET_OK); if (rsCStrSzStrCmp(pstrID, pObj->pObjInfo->pszID, pObj->pObjInfo->lenID)) ABORT_FINALIZE(RS_RET_INVALID_OID); CHKiRet(FindObjInfo((char *)cstrGetSzStrNoNULL(pstrID), &pObjInfo)); /* we got the object, now we need to fill the properties */ CHKiRet( objDeserializeProperties(pObj, (rsRetVal(*)(void *, ...))pObjInfo->objMethods[objMethod_SETPROPERTY], pStrm)); finalize_it: if (pstrID != NULL) rsCStrDestruct(&pstrID); RETiRet; } #undef NEXTC /* undef helper macro */ /* --------------- end object serializiation / deserialization support --------------- */ /* set the object (instance) name * rgerhards, 2008-01-29 * TODO: change the naming to a rsCStr obj! (faster) */ static rsRetVal SetName(obj_t *pThis, uchar *pszName) { DEFiRet; free(pThis->pszName); CHKmalloc(pThis->pszName = ustrdup(pszName)); finalize_it: RETiRet; } /* get the object (instance) name * Note that we use a non-standard calling convention. Thus function must never * fail, else we run into real big problems. So it must make sure that at least someting * is returned. * rgerhards, 2008-01-30 */ uchar *ATTR_NONNULL() objGetName(obj_t *const pThis) { uchar *ret; uchar szName[128]; ISOBJ_assert(pThis); if (pThis->pszName == NULL) { snprintf((char *)szName, sizeof(szName), "%s %p", objGetClassName(pThis), pThis); SetName(pThis, szName); /* looks strange, but we NEED to re-check because if there was an * error in objSetName(), the pointer may still be NULL */ if (pThis->pszName == NULL) { ret = objGetClassName(pThis); } else { ret = pThis->pszName; } } else { ret = pThis->pszName; } return ret; } /* Find the objInfo object for the current object * rgerhards, 2008-02-29 */ static rsRetVal FindObjInfo(const char *const __restrict__ strOID, objInfo_t **ppInfo) { DEFiRet; int bFound; int i; bFound = 0; i = 0; while (!bFound && i < OBJ_NUM_IDS) { if (arrObjInfo[i] != NULL && !strcmp(strOID, (const char *)arrObjInfo[i]->pszID)) { bFound = 1; break; } ++i; } if (!bFound) ABORT_FINALIZE(RS_RET_NOT_FOUND); *ppInfo = arrObjInfo[i]; finalize_it: if (iRet != RS_RET_OK) { dbgprintf("caller requested object '%s', not found (iRet %d)\n", strOID, iRet); } RETiRet; } /* register a classes' info pointer, so that we can reference it later, if needed to * (e.g. for de-serialization support). * rgerhards, 2008-01-07 * In this function, we look for a free space in the object table. While we do so, we * also detect if the same object has already been registered, which is not valid. * rgerhards, 2008-02-29 */ static rsRetVal RegisterObj(uchar *pszObjName, objInfo_t *pInfo) { DEFiRet; int bFound; int i; assert(pszObjName != NULL); assert(pInfo != NULL); bFound = 0; i = 0; while (!bFound && i < OBJ_NUM_IDS && arrObjInfo[i] != NULL) { if (arrObjInfo[i] != NULL && !ustrcmp(arrObjInfo[i]->pszID, pszObjName)) { bFound = 1; break; } ++i; } if (bFound) ABORT_FINALIZE(RS_RET_OBJ_ALREADY_REGISTERED); if (i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE); arrObjInfo[i] = pInfo; #if DEV_DEBUG == 1 dbgprintf( "object '%s' successfully registered with " "index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF); #endif finalize_it: if (iRet != RS_RET_OK) { LogError(0, NO_ERRCODE, "registering object '%s' failed with error code %d", pszObjName, iRet); } RETiRet; } /* deregister a classes' info pointer, usually called because the class is unloaded. * After deregistration, the class can no longer be accessed, except if it is reloaded. * rgerhards, 2008-03-10 */ static rsRetVal UnregisterObj(uchar *pszObjName) { DEFiRet; int bFound; int i; assert(pszObjName != NULL); bFound = 0; i = 0; while (!bFound && i < OBJ_NUM_IDS) { if (arrObjInfo[i] != NULL && !ustrcmp(arrObjInfo[i]->pszID, pszObjName)) { bFound = 1; break; } ++i; } if (!bFound) ABORT_FINALIZE(RS_RET_OBJ_NOT_REGISTERED); InfoDestruct(&arrObjInfo[i]); #if DEV_DEBUG == 1 dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i); #endif finalize_it: if (iRet != RS_RET_OK) { dbgprintf("unregistering object '%s' failed with error code %d\n", pszObjName, iRet); } RETiRet; } /* This function shall be called by anyone who would like to use an object. It will * try to locate the object, load it into memory if not already present and return * a pointer to the objects interface. * rgerhards, 2008-02-29 */ /* Note on atomic operations: * ifIsLoaded uses PREFER_FETCH_32BIT for reads to prevent data races on platforms with atomics. * Writes always occur under mutObjGlobalOp and use matching PREFER stores. * On platforms without atomics, PREFER_* degrades to plain operations (acceptable for 20+ years). * The mutex provides full synchronization; atomics only improve diagnostic cleanliness (TSAN). */ static ATTR_NO_SANITIZE_UNDEFINED rsRetVal UseObj(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) { DEFiRet; objInfo_t *pObjInfo; #if DEV_DEBUG == 1 /* Best-effort atomic read before mutex: avoids TSAN warnings on platforms with atomics */ dbgprintf( "source file %s requests object '%s', " " ifIsLoaded %d\n", srcFile, pObjName, PREFER_FETCH_32BIT(pIf->ifIsLoaded)); #endif pthread_mutex_lock(&mutObjGlobalOp); /* Best-effort atomic reads: avoid UB/TSAN warnings from concurrent plain-write by other threads. * Synchronization is provided by mutex; these are defensive reads only. */ if (PREFER_FETCH_32BIT(pIf->ifIsLoaded) == 1) { ABORT_FINALIZE(RS_RET_OK); /* we are already set */ } if (PREFER_FETCH_32BIT(pIf->ifIsLoaded) == 2) { ABORT_FINALIZE(RS_RET_LOAD_ERROR); /* we had a load error and can not continue */ } /* we must be careful that we do not enter in infinite loop if an error occurs during * loading a module. ModLoad emits an error message in such cases and that potentially * can trigger the same code here. So we initially set the module state to "load error" * and set it to "fully initialized" when the load succeeded. It's a bit hackish, but * looks like a good solution. -- rgerhards, 2008-03-07 */ PREFER_STORE_INT(&pIf->ifIsLoaded, 2); iRet = FindObjInfo((const char *)pObjName, &pObjInfo); if (iRet == RS_RET_NOT_FOUND) { /* in this case, we need to see if we can dynamically load the object */ if (pObjFile == NULL) { FINALIZE; /* no chance, we have lost... */ } else { CHKiRet(module.Load(pObjFile, 0, NULL)); /* NOW, we must find it or we have a problem... */ CHKiRet(FindObjInfo((const char *)pObjName, &pObjInfo)); } } else if (iRet != RS_RET_OK) { FINALIZE; /* give up */ } /* if we reach this point, we have a valid pObjInfo */ if (pObjFile != NULL) { /* NULL means core module */ module.Use(srcFile, pObjInfo->pModInfo); /* increase refcount */ } // TODO: fix interface pointer type, remove ATTR_NO_SANITIZE_UNDEFINED above // The supression is just an interim solution until the pointer issue // has been fully analyzed and aligned (or considered OK w/ reasoning). CHKiRet(pObjInfo->QueryIF(pIf)); PREFER_STORE_1_TO_INT(&pIf->ifIsLoaded); finalize_it: pthread_mutex_unlock(&mutObjGlobalOp); RETiRet; } /* This function shall be called when a caller is done with an object. Its primary * purpose is to keep the reference count correct, which is highly important for * modules residing in loadable modules. * rgerhards, 2008-03-10 */ static rsRetVal ReleaseObj(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf) { DEFiRet; objInfo_t *pObjInfo; /* dev debug only dbgprintf("source file %s releasing object '%s', ifIsLoaded %d\n", srcFile, pObjName, PREFER_FETCH_32BIT(pIf->ifIsLoaded)); */ pthread_mutex_lock(&mutObjGlobalOp); if (pObjFile == NULL) FINALIZE; /* if it is not a lodable module, we do not need to do anything... */ if (PREFER_FETCH_32BIT(pIf->ifIsLoaded) == 0) { FINALIZE; /* we are not loaded - this is perfectly OK... */ } else if (PREFER_FETCH_32BIT(pIf->ifIsLoaded) == 2) { /* Clean up failed load attempt */ PREFER_STORE_0_TO_INT(&pIf->ifIsLoaded); FINALIZE; /* we had a load error and can not/must not continue */ } CHKiRet(FindObjInfo((const char *)pObjName, &pObjInfo)); /* if we reach this point, we have a valid pObjInfo */ module.Release(srcFile, &pObjInfo->pModInfo); /* decrease refcount */ PREFER_STORE_0_TO_INT(&pIf->ifIsLoaded); finalize_it: pthread_mutex_unlock(&mutObjGlobalOp); RETiRet; } /* queryInterface function * rgerhards, 2008-02-29 */ PROTOTYPEObjQueryInterface(obj); BEGINobjQueryInterface(obj) CODESTARTobjQueryInterface(obj); if (pIf->ifVersion != objCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->UseObj = UseObj; pIf->ReleaseObj = ReleaseObj; pIf->InfoConstruct = InfoConstruct; pIf->DestructObjSelf = DestructObjSelf; pIf->BeginSerializePropBag = BeginSerializePropBag; pIf->InfoSetMethod = InfoSetMethod; pIf->BeginSerialize = BeginSerialize; pIf->SerializeProp = SerializeProp; pIf->EndSerialize = EndSerialize; pIf->RegisterObj = RegisterObj; pIf->UnregisterObj = UnregisterObj; pIf->Deserialize = Deserialize; pIf->DeserializePropBag = DeserializePropBag; pIf->SetName = SetName; pIf->GetName = objGetName; finalize_it: ENDobjQueryInterface(obj) /* This function returns a pointer to our own interface. It is used as the * hook that every object (including dynamically loaded ones) can use to * obtain a pointer to our interface which than can be used to obtain * pointers to any other interface in the system. This function must be * externally visible because of its special nature. * rgerhards, 2008-02-29 [nice - will have that date the next time in 4 years ;)] */ rsRetVal objGetObjInterface(obj_if_t *pIf) { DEFiRet; assert(pIf != NULL); objQueryInterface(pIf); RETiRet; } /* exit our class * rgerhards, 2008-03-11 */ rsRetVal objClassExit(void) { DEFiRet; /* release objects we no longer need */ objRelease(strm, CORE_COMPONENT); objRelease(var, CORE_COMPONENT); objRelease(module, CORE_COMPONENT); /* TODO: implement the class exits! */ #if 0 cfsyslineExit(pModInfo); varClassExit(pModInfo); #endif moduleClassExit(); RETiRet; } /* initialize our own class * Please note that this also initializes those classes that we rely on. * Though this is a bit dirty, we need to do it - otherwise we can't get * around that bootstrap problem. We need to face the fact the the obj * class is a little different from the rest of the system, as it provides * the core class loader functionality. * rgerhards, 2008-02-29 */ rsRetVal objClassInit(modInfo_t *pModInfo) { pthread_mutexattr_t mutAttr; int i; DEFiRet; /* first, initialize the object system itself. This must be done * before any other object is created. */ for (i = 0; i < OBJ_NUM_IDS; ++i) { arrObjInfo[i] = NULL; } /* the mutex must be recursive, because objects may call into other * object identifiers recursively. */ pthread_mutexattr_init(&mutAttr); pthread_mutexattr_settype(&mutAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&mutObjGlobalOp, &mutAttr); /* request objects we use */ CHKiRet(objGetObjInterface(&obj)); /* get ourselves ;) */ /* init classes we use (limit to as few as possible!) */ CHKiRet(datetimeClassInit(pModInfo)); CHKiRet(cfsyslineInit()); CHKiRet(varClassInit(pModInfo)); CHKiRet(moduleClassInit(pModInfo)); CHKiRet(strmClassInit(pModInfo)); CHKiRet(objUse(var, CORE_COMPONENT)); CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/cryprov.h0000644000000000000000000000013215132411300016065 xustar0030 mtime=1768559296.261885561 30 atime=1787067616.818415041 30 ctime=1787067794.270722744 rsyslog-8.2608.0/runtime/cryprov.h0000666000175000017500000000412215132411300015532 0ustar00rgerrger/* The interface definition for (file) crypto providers. * * This is just an abstract driver interface, which needs to be * implemented by concrete classes. * * Copyright 2013 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_CRYPROV_H #define INCLUDED_CRYPROV_H /* we unfortunately need to have two different param names depending on the * context in which parameters are set. Other than (re/over)engineering the core * interface, we just define some values to keep track of that. */ #define CRYPROV_PARAMTYPE_REGULAR 0 #define CRYPROV_PARAMTYPE_DISK 1 /* interface */ BEGINinterface(cryprov) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(void *ppThis); rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst, int paramType); rsRetVal (*Destruct)(void *ppThis); rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData, char openMode); rsRetVal (*Encrypt)(void *pFileInstData, uchar *buf, size_t *lenBuf); rsRetVal (*Decrypt)(void *pFileInstData, uchar *buf, size_t *lenBuf); rsRetVal (*OnFileClose)(void *pFileInstData, off64_t offsLogfile); rsRetVal (*DeleteStateFiles)(uchar *logfn); rsRetVal (*GetBytesLeftInBlock)(void *pFileInstData, ssize_t *left); void (*SetDeleteOnClose)(void *pFileInstData, int val); ENDinterface(cryprov) #define cryprovCURR_IF_VERSION 3 /* increment whenever you change the interface structure! */ #endif /* #ifndef INCLUDED_CRYPROV_H */ rsyslog-8.2608.0/runtime/PaxHeaders/netns_socket.h0000644000000000000000000000013215132733117017075 xustar0030 mtime=1768666703.945620814 30 atime=1787067618.190440623 30 ctime=1787067794.532727627 rsyslog-8.2608.0/runtime/netns_socket.h0000666000175000017500000000227715132733117016553 0ustar00rgerrger/* Definitions for netns_socket API * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NETNS_SOCKET_H #define INCLUDED_NETNS_SOCKET_H #include "rsyslog.h" /* * Open a socket in the named network namespace */ rsRetVal netns_socket(int *fdp, int domain, int type, int protocol, const char *ns); /* * Switch to the named networknamespace */ rsRetVal netns_switch(const char *ns); /* * Save and restore our current network namespace */ rsRetVal ATTR_NONNULL() netns_save(int *fd); rsRetVal ATTR_NONNULL() netns_restore(int *fd); #endif /* #ifndef INCLUDED_NETNS_SOCKET_H */ rsyslog-8.2608.0/runtime/PaxHeaders/lib_ksils12.h0000644000000000000000000000013215132411300016477 xustar0030 mtime=1768559296.265885624 30 atime=1782715518.784788772 30 ctime=1787067794.587728651 rsyslog-8.2608.0/runtime/lib_ksils12.h0000666000175000017500000002453415132411300016155 0ustar00rgerrger/* lib_ksils12.h - rsyslog's KSI-LS12 support library * * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_KSILS12_H #define INCLUDED_KSILS12_H #include #include "lib_ksi_queue.h" #define MAX_ROOTS 64 /* Flags and record types for TLV handling */ #define RSGT_FLAG_NONCRIT 0x20 #define RSGT_FLAG_FORWARD 0x40 #define RSGT_TYPE_MASK 0x1f #define RSGT_FLAG_TLV16 0x80 /* check return state of operation and abort, if non-OK */ #define CHKr(code) \ if ((r = code) != 0) goto done /* check the return value of a ksi api call and log a message in case of error */ #define CHECK_KSI_API(code, context, msg) \ if ((res = code) != 0) do { \ reportKSIAPIErr(context, NULL, msg, res); \ goto cleanup; \ } while (0) typedef enum LOGSIG_SyncMode_en { /** The block hashes and ksi signatures in one file */ LOGSIG_ASYNCHRONOUS = 0x00, /** The block hashes and ksi signatures split into separate files */ LOGSIG_SYNCHRONOUS = 0x01 } LOGSIG_SyncMode; enum { /* Signer state assigned before the signer thread is initialized. State remains * until thread initialization begins. In case of system failure to create new * thread state remains the same. */ SIGNER_IDLE = 0x01, /* Signer state assigned while signer thread initialization is in progress. */ SIGNER_INIT = 0x02, /* Signer state assigned when signer thread is initialized and ready to work. */ SIGNER_STARTED = 0x04, /* Thread state assigned when signer thread is being closed (signer thread returns). */ SIGNER_STOPPED = 0x08 }; /* Max number of roots inside the forest. This permits blocks of up to * 2^MAX_ROOTS records. We assume that 64 is sufficient for all use * cases ;) [and 64 is not really a waste of memory, so we do not even * try to work with reallocs and such...] */ typedef struct rsksictx_s *rsksictx; typedef struct ksifile_s *ksifile; typedef struct ksierrctx_s ksierrctx_t; /* context for gt calls. This primarily serves as a container for the * config settings. The actual file-specific data is kept in ksifile. */ struct rsksictx_s { KSI_CTX *ksi_ctx; /* libksi's context object */ KSI_DataHasher *hasher; KSI_HashAlgorithm hashAlg; KSI_HashAlgorithm hmacAlg; uint8_t bKeepRecordHashes; uint8_t bKeepTreeHashes; uint64_t confInterval; time_t tConfRequested; uint64_t blockLevelLimit; uint32_t blockTimeLimit; uint32_t blockSigTimeout; uint32_t effectiveBlockLevelLimit; /* level limit adjusted by gateway settings */ uint32_t threadSleepms; uint8_t syncMode; uid_t fileUID; /* IDs for creation */ uid_t dirUID; gid_t fileGID; gid_t dirGID; int fCreateMode; /* mode to use when creating files */ int fDirCreateMode; /* mode to use when creating files */ char *aggregatorUri; char *aggregatorId; char *aggregatorKey; char *aggregatorEndpoints[KSI_CTX_HA_MAX_SUBSERVICES]; int aggregatorEndpointCount; char *random_source; pthread_mutex_t module_lock; pthread_t signer_thread; ProtectedQueue *signer_queue; #if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22 size_t roundCount; /* Count of signing requests in round. */ uint8_t bRoundLock; /* A lock for async. signer. */ #endif int signer_state; uint8_t disabled; /* permits to disable the plugin --> set to 1 */ ksifile *ksi; /* List of signature files for keeping track of block timeouts. */ size_t ksiCapacity; size_t ksiCount; char *debugFileName; int debugLevel; FILE *debugFile; uint64_t max_requests; void (*errFunc)(void *, unsigned char *); void (*logFunc)(void *, unsigned char *); void *usrptr; /* for error function */ }; /* this describes a file, as far as librsksi is concerned */ struct ksifile_s { /* the following data items are mirrored from rsksictx to * increase cache hit ratio (they are frequently accesed). */ KSI_HashAlgorithm hashAlg; uint8_t bKeepRecordHashes; uint8_t bKeepTreeHashes; uint64_t blockSizeLimit; uint32_t blockTimeLimit; /* end mirrored properties */ uint8_t disabled; /* permits to disable this file --> set to 1 */ uint8_t *IV; /* initial value for blinding masks */ unsigned char lastLeaf[KSI_MAX_IMPRINT_LEN]; /* last leaf hash (maybe of previous block) --> preserve on term */ unsigned char *blockfilename; unsigned char *ksifilename; unsigned char *statefilename; uint64_t nRecords; /* current number of records in current block */ uint64_t bInBlk; /* are we currently inside a blk --> need to finish on close */ time_t blockStarted; int8_t nRoots; /* algo engineering: roots structure is split into two arrays * in order to improve cache hits. */ KSI_DataHash *roots[MAX_ROOTS]; /* data members for the associated TLV file */ FILE *blockFile; FILE *sigFile; /* Note that this may only be closed by signer thread or when signer thread has terminated. */ rsksictx ctx; }; /* the following defines the ksistate file record. Currently, this record * is fixed, we may change that over time. */ struct rsksistatefile { char hdr[9]; /* must be "KSISTAT10" */ uint8_t hashID; uint8_t lenHash; /* after that, the hash value is contained within the file */ }; /* error states */ #define RSGTE_SUCCESS 0 /* Success state */ #define RSGTE_IO 1 /* any kind of io error */ #define RSGTE_FMT 2 /* data fromat error */ #define RSGTE_INVLTYP 3 /* invalid TLV type record (unexcpected at this point) */ #define RSGTE_OOM 4 /* ran out of memory */ #define RSGTE_LEN 5 /* error related to length records */ #define RSGTE_SIG_EXTEND 6 /* error extending signature */ #define RSGTE_INVLD_RECCNT \ 7 /* mismatch between actual records and records \ given in block-sig record */ #define RSGTE_INVLHDR 8 /* invalid file header */ #define RSGTE_EOF 9 /* specific EOF */ #define RSGTE_MISS_REC_HASH 10 /* record hash missing when expected */ #define RSGTE_MISS_TREE_HASH 11 /* tree hash missing when expected */ #define RSGTE_INVLD_REC_HASH 12 /* invalid record hash (failed verification) */ #define RSGTE_INVLD_TREE_HASH 13 /* invalid tree hash (failed verification) */ #define RSGTE_INVLD_REC_HASHID 14 /* invalid record hash ID (failed verification) */ #define RSGTE_INVLD_TREE_HASHID 15 /* invalid tree hash ID (failed verification) */ #define RSGTE_MISS_BLOCKSIG 16 /* block signature record missing when expected */ #define RSGTE_INVLD_SIGNATURE 17 /* Signature is invalid (KSI_Signature_verifyDataHash)*/ #define RSGTE_TS_CREATEHASH 18 /* error creating HASH (KSI_DataHash_create) */ #define RSGTE_TS_DERENCODE 19 /* error DER-Encoding a timestamp */ #define RSGTE_HASH_CREATE 20 /* error creating a hash */ #define RSGTE_END_OF_SIG 21 /* unexpected end of signature - more log line exist */ #define RSGTE_END_OF_LOG 22 /* unexpected end of log file - more signatures exist */ #define RSGTE_EXTRACT_HASH 23 /* error extracting hashes for record */ #define RSGTE_CONFIG_ERROR 24 /* Configuration error */ #define RSGTE_NETWORK_ERROR 25 /* Network error */ #define RSGTE_MISS_KSISIG 26 /* KSI signature missing */ #define RSGTE_INTERNAL 27 /* Internal error */ #define getIVLenKSI(bh) (hashOutputLengthOctetsKSI((bh)->hashID)) #define rsksiSetBlockLevelLimit(ctx, limit) ((ctx)->blockLevelLimit = (ctx)->effectiveBlockLevelLimit = limit) #define rsksiSetBlockTimeLimit(ctx, limit) ((ctx)->blockTimeLimit = limit) #define rsksiSetBlockSigTimeout(ctx, val) ((ctx)->blockSigTimeout = val) #define rsksiSetConfInterval(ctx, val) ((ctx)->confInterval = val) #define rsksiSetKeepRecordHashes(ctx, val) ((ctx)->bKeepRecordHashes = val) #define rsksiSetKeepTreeHashes(ctx, val) ((ctx)->bKeepTreeHashes = val) #define rsksiSetFileFormat(ctx, val) ((ctx)->fileFormat = val) #define rsksiSetSyncMode(ctx, val) ((ctx)->syncMode = val) #define rsksiSetRandomSource(ctx, val) ((ctx)->random_source = strdup(val)) #define rsksiSetFileUID(ctx, val) ((ctx)->fileUID = val) /* IDs for creation */ #define rsksiSetDirUID(ctx, val) ((ctx)->dirUID = val) #define rsksiSetFileGID(ctx, val) ((ctx)->fileGID = val) #define rsksiSetDirGID(ctx, val) ((ctx)->dirGID = val) #define rsksiSetCreateMode(ctx, val) ((ctx)->fCreateMode = val) #define rsksiSetDirCreateMode(ctx, val) ((ctx)->fDirCreateMode = val) #define rsksiSetDebugLevel(ctx, val) ((ctx)->debugLevel = val) int rsksiSetDebugFile(rsksictx ctx, char *val); int rsksiSetAggregator(rsksictx ctx, char *uri, char *loginid, char *key); int rsksiSetHashFunction(rsksictx ctx, char *algName); int rsksiSetHmacFunction(rsksictx ctx, char *algName); int rsksiInitModule(rsksictx ctx); rsksictx rsksiCtxNew(void); void rsksisetErrFunc(rsksictx ctx, void (*func)(void *, unsigned char *), void *usrptr); void rsksisetLogFunc(rsksictx ctx, void (*func)(void *, unsigned char *), void *usrptr); void reportKSIAPIErr(rsksictx ctx, ksifile ksi, const char *apiname, int ecode); ksifile rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn); int rsksifileDestruct(ksifile ksi); void rsksiCtxDel(rsksictx ctx); void sigblkInitKSI(ksifile ksi); int sigblkAddRecordKSI(ksifile ksi, const unsigned char *rec, const size_t len); int sigblkAddLeaf(ksifile ksi, const unsigned char *rec, const size_t len, bool metadata); unsigned sigblkCalcLevel(unsigned leaves); int sigblkFinishKSI(ksifile ksi); int sigblkAddMetadata(ksifile ksi, const char *key, const char *value); int sigblkCreateMask(ksifile ksi, KSI_DataHash **m); int sigblkCreateHash(ksifile ksi, KSI_DataHash **r, const unsigned char *rec, const size_t len); int sigblkHashTwoNodes(ksifile ksi, KSI_DataHash **node, KSI_DataHash *m, KSI_DataHash *r, uint8_t level); #endif /* #ifndef INCLUDED_KSILS12_H */ rsyslog-8.2608.0/runtime/PaxHeaders/hashtable_itr.h0000644000000000000000000000013215132411300017172 xustar0030 mtime=1768559296.264885609 30 atime=1787067618.121439336 30 ctime=1787067794.486726769 rsyslog-8.2608.0/runtime/hashtable_itr.h0000666000175000017500000000767015132411300016652 0ustar00rgerrger/* Copyright (C) 2002, 2004 Christopher Clark */ #ifndef __HASHTABLE_ITR_CWC22__ #define __HASHTABLE_ITR_CWC22__ #include "hashtable_private.h" /* needed to enable inlining */ /*****************************************************************************/ /* This struct is only concrete here to allow the inlining of two of the * accessor functions. */ struct hashtable_itr { struct hashtable *h; struct entry *e; struct entry *parent; unsigned int index; }; /*****************************************************************************/ /* hashtable_iterator */ struct hashtable_itr *hashtable_iterator(struct hashtable *h); /*****************************************************************************/ /* hashtable_iterator_key * - return the value of the (key,value) pair at the current position */ #define hashtable_iterator_key(i) ((i)->e->k) /*****************************************************************************/ /* value - return the value of the (key,value) pair at the current position */ #define hashtable_iterator_value(i) ((i)->e->v) /*****************************************************************************/ /* advance - advance the iterator to the next element * returns zero if advanced to end of table */ int hashtable_iterator_advance(struct hashtable_itr *itr); /*****************************************************************************/ /* remove - remove current element and advance the iterator to the next element * NB: if you need the value to free it, read it before * removing. ie: beware memory leaks! * returns zero if advanced to end of table */ int hashtable_iterator_remove(struct hashtable_itr *itr); /*****************************************************************************/ /* search - overwrite the supplied iterator, to point to the entry * matching the supplied key. * h points to the hashtable to be searched. * returns zero if not found. */ int hashtable_iterator_search(struct hashtable_itr *itr, struct hashtable *h, void *k); #define DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ int fnname(struct hashtable_itr *i, struct hashtable *h, keytype *k) { \ return (hashtable_iterator_search(i, h, k)); \ } #endif /* __HASHTABLE_ITR_CWC22__*/ /* * Copyright (c) 2002, 2004, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ rsyslog-8.2608.0/runtime/PaxHeaders/lib_ksils12.c0000644000000000000000000000013215216464436016517 xustar0030 mtime=1782212894.026266184 30 atime=1782715518.784788772 30 ctime=1787067794.584728595 rsyslog-8.2608.0/runtime/lib_ksils12.c0000664000175000017500000017734315216464436016202 0ustar00rgerrger/* lib_ksils12.c - rsyslog's KSI-LS12 support library * * Regarding the online algorithm for Merkle tree signing. Expected * calling sequence is: * * sigblkConstruct * for each signature block: * sigblkInitKSI * for each record: * sigblkAddRecordKSI * sigblkFinishKSI * sigblkDestruct * * Obviously, the next call after sigblkFinsh must either be to * sigblkInitKSI or sigblkDestruct (if no more signature blocks are * to be emitted, e.g. on file close). sigblkDestruct saves state * information (most importantly last block hash) and sigblkConstruct * reads (or initilizes if not present) it. * * Copyright 2013-2018 Adiscon GmbH and Guardtime, Inc. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "errmsg.h" #include "lib_ksils12.h" #include "lib_ksi_queue.h" #ifndef VERSION #define VERSION "no-version" #endif #define KSI_BUF_SIZE 4096 static const char *blockFileSuffix = ".logsig.parts/blocks.dat"; static const char *sigFileSuffix = ".logsig.parts/block-signatures.dat"; static const char *ls12FileSuffix = ".logsig"; static const char *blockCloseReason = "com.guardtime.blockCloseReason"; #define LS12_FILE_HEADER "LOGSIG12" #define LS12_BLOCKFILE_HEADER "LOG12BLK" #define LS12_SIGFILE_HEADER "LOG12SIG" #define LS12_SIGNATURE_TIMEOUT 60 /* Worker queue item type identifier */ typedef enum QITEM_type_en { QITEM_SIGNATURE_REQUEST = 0x00, QITEM_CLOSE_FILE, QITEM_NEW_FILE, QITEM_QUIT } QITEM_type; /* Worker queue item status identifier */ typedef enum QITEM_status_en { /* State assigned to any item added to queue (initial state). */ QITEM_WAITING = 0x00, /* State assigned to #QITEM_SIGNATURE_REQUEST item when it is sent out. */ QITEM_SENT, /* State assigned to #QITEM_SIGNATURE_REQUEST item when request failed or succeeded. */ QITEM_DONE } QITEM_status; /* Worker queue job item */ typedef struct QueueItem_st { QITEM_type type; QITEM_status status; KSI_DataHash *root; FILE *file; /* To keep track of the target signature file. */ uint64_t intarg1; /* Block time limit or record count or not used. */ uint64_t intarg2; /* Level of the sign request or not used. */ KSI_AsyncHandle *respHandle; int ksi_status; time_t request_time; } QueueItem; static bool queueAddCloseFile(rsksictx ctx, ksifile kf); static bool queueAddNewFile(rsksictx ctx, ksifile kf); static bool queueAddQuit(rsksictx ctx); static bool queueAddSignRequest(rsksictx ctx, ksifile kf, KSI_DataHash *root, unsigned level); static int sigblkFinishKSINoSignature(ksifile ksi, const char *reason); void *signer_thread(void *arg); static void __attribute__((format(printf, 2, 3))) report(rsksictx ctx, const char *errmsg, ...) { char buf[1024]; int r; va_list args; va_start(args, errmsg); r = vsnprintf(buf, sizeof(buf), errmsg, args); buf[sizeof(buf) - 1] = '\0'; va_end(args); if (ctx->logFunc == NULL) return; if (r > 0 && r < (int)sizeof(buf)) ctx->logFunc(ctx->usrptr, (uchar *)buf); else ctx->logFunc(ctx->usrptr, (uchar *)errmsg); } static void reportErr(rsksictx ctx, const char *const errmsg) { if (ctx->errFunc == NULL) goto done; ctx->errFunc(ctx->usrptr, (uchar *)errmsg); done: return; } static const char *level2str(int level) { switch (level) { case KSI_LOG_DEBUG: return "DEBUG"; case KSI_LOG_INFO: return "INFO"; case KSI_LOG_NOTICE: return "NOTICE"; case KSI_LOG_WARN: return "WARN"; case KSI_LOG_ERROR: return "ERROR"; default: return "UNKNOWN LOG LEVEL"; } } void reportKSIAPIErr(rsksictx ctx, ksifile ksi, const char *apiname, int ecode) { char errbuf[4096]; char ksi_errbuf[4096]; KSI_ERR_getBaseErrorMessage(ctx->ksi_ctx, ksi_errbuf, sizeof(ksi_errbuf), NULL, NULL); snprintf(errbuf, sizeof(errbuf), "%s[%s:%d]: %s (%s)", (ksi == NULL) ? (uchar *)"" : ksi->blockfilename, apiname, ecode, KSI_getErrorString(ecode), ksi_errbuf); errbuf[sizeof(errbuf) - 1] = '\0'; reportErr(ctx, errbuf); } void rsksisetErrFunc(rsksictx ctx, void (*func)(void *, uchar *), void *usrptr) { ctx->usrptr = usrptr; ctx->errFunc = func; } void rsksisetLogFunc(rsksictx ctx, void (*func)(void *, uchar *), void *usrptr) { ctx->usrptr = usrptr; ctx->logFunc = func; } static ksifile rsksifileConstruct(rsksictx ctx) { ksifile ksi = NULL; if ((ksi = calloc(1, sizeof(struct ksifile_s))) == NULL) goto done; ksi->ctx = ctx; ksi->hashAlg = ctx->hashAlg; ksi->blockTimeLimit = ctx->blockTimeLimit; ksi->blockSizeLimit = 1 << (ctx->effectiveBlockLevelLimit - 1); ksi->bKeepRecordHashes = ctx->bKeepRecordHashes; ksi->bKeepTreeHashes = ctx->bKeepTreeHashes; ksi->lastLeaf[0] = ctx->hashAlg; done: return ksi; } /* return the actual length in to-be-written octets of an integer */ static uint8_t tlvGetIntSize(uint64_t val) { uint8_t n = 0; while (val != 0) { val >>= 8; n++; } return n; } static int tlvWriteOctetString(FILE *f, const uint8_t *data, uint16_t len) { if (fwrite(data, len, 1, f) != 1) return RSGTE_IO; return 0; } static int tlvWriteHeader8(FILE *f, int flags, uint8_t tlvtype, int len) { unsigned char buf[2]; assert((flags & RSGT_TYPE_MASK) == 0); assert((tlvtype & RSGT_TYPE_MASK) == tlvtype); buf[0] = (flags & ~RSGT_FLAG_TLV16) | tlvtype; buf[1] = len & 0xff; return tlvWriteOctetString(f, buf, 2); } static int tlvWriteHeader16(FILE *f, int flags, uint16_t tlvtype, uint16_t len) { uint16_t typ; unsigned char buf[4]; assert((flags & RSGT_TYPE_MASK) == 0); assert((tlvtype >> 8 & RSGT_TYPE_MASK) == (tlvtype >> 8)); typ = ((flags | RSGT_FLAG_TLV16) << 8) | tlvtype; buf[0] = typ >> 8; buf[1] = typ & 0xff; buf[2] = (len >> 8) & 0xff; buf[3] = len & 0xff; return tlvWriteOctetString(f, buf, 4); } static int tlvGetHeaderSize(uint16_t tag, size_t size) { if (tag <= RSGT_TYPE_MASK && size <= 0xff) return 2; if ((tag >> 8) <= RSGT_TYPE_MASK && size <= 0xffff) return 4; return 0; } static int tlvWriteHeader(FILE *f, int flags, uint16_t tlvtype, uint16_t len) { int headersize = tlvGetHeaderSize(tlvtype, flags); if (headersize == 2) return tlvWriteHeader8(f, flags, tlvtype, len); else if (headersize == 4) return tlvWriteHeader16(f, flags, tlvtype, len); else return 0; } static int tlvWriteOctetStringTLV(FILE *f, int flags, uint16_t tlvtype, const uint8_t *data, uint16_t len) { if (tlvWriteHeader(f, flags, tlvtype, len) != 0) return RSGTE_IO; if (fwrite(data, len, 1, f) != 1) return RSGTE_IO; return 0; } static int tlvWriteInt64TLV(FILE *f, int flags, uint16_t tlvtype, uint64_t val) { unsigned char buf[8]; uint8_t count = tlvGetIntSize(val); uint64_t nTmp; if (tlvWriteHeader(f, flags, tlvtype, count) != 0) return RSGTE_IO; nTmp = val; for (int i = count - 1; i >= 0; i--) { buf[i] = 0xFF & nTmp; nTmp = nTmp >> 8; } if (fwrite(buf, count, 1, f) != 1) return RSGTE_IO; return 0; } static int tlvWriteHashKSI(ksifile ksi, uint16_t tlvtype, KSI_DataHash *rec) { int r; const unsigned char *imprint; size_t imprint_len; r = KSI_DataHash_getImprint(rec, &imprint, &imprint_len); if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_getImprint", r); return r; } return tlvWriteOctetStringTLV(ksi->blockFile, 0, tlvtype, imprint, imprint_len); } static int tlvWriteBlockHdrKSI(ksifile ksi) { unsigned tlvlen; uint8_t hash_algo = ksi->hashAlg; int r; tlvlen = 2 + 1 /* hash algo TLV */ + 2 + KSI_getHashLength(ksi->hashAlg) /* iv */ + 2 + KSI_getHashLength(ksi->lastLeaf[0]) + 1; /* last hash */; /* write top-level TLV object block-hdr */ CHKr(tlvWriteHeader(ksi->blockFile, 0x00, 0x0901, tlvlen)); /* hash-algo */ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x01, &hash_algo, 1)); /* block-iv */ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x02, ksi->IV, KSI_getHashLength(ksi->hashAlg))); /* last-hash */ CHKr(tlvWriteOctetStringTLV(ksi->blockFile, 0x00, 0x03, ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1)); done: return r; } static int tlvWriteKSISigLS12(FILE *outfile, size_t record_count, uchar *der, uint16_t lenDer) { int r = 0; int totalSize = 2 + tlvGetIntSize(record_count) + 4 + lenDer; CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize)); CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count)); CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x0905, der, lenDer)); done: return r; } static int tlvWriteNoSigLS12(FILE *outfile, size_t record_count, const KSI_DataHash *hash, const char *errorText) { int r = 0; int totalSize = 0; int noSigSize = 0; const unsigned char *imprint = NULL; size_t imprintLen = 0; KSI_DataHash_getImprint(hash, &imprint, &imprintLen); noSigSize = 2 + imprintLen + (errorText ? (2 + strlen(errorText) + 1) : 0); totalSize = 2 + tlvGetIntSize(record_count) + 2 + noSigSize; CHKr(tlvWriteHeader(outfile, 0x00, 0x0904, totalSize)); CHKr(tlvWriteInt64TLV(outfile, 0x00, 0x01, record_count)); CHKr(tlvWriteHeader(outfile, 0x00, 0x02, noSigSize)); CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x01, imprint, imprintLen)); if (errorText) CHKr(tlvWriteOctetStringTLV(outfile, 0x00, 0x02, (uint8_t *)errorText, strlen(errorText) + 1)); done: return r; } static int tlvCreateMetadata( ksifile ksi, uint64_t record_index, const char *key, const char *value, unsigned char *buffer, size_t *len) { int r = 0; KSI_TlvElement *metadata = NULL, *attrib_tlv = NULL; KSI_Utf8String *key_tlv = NULL, *value_tlv = NULL; KSI_Integer *index_tlv = NULL; CHKr(KSI_TlvElement_new(&metadata)); metadata->ftlv.tag = 0x0911; CHKr(KSI_Integer_new(ksi->ctx->ksi_ctx, record_index, &index_tlv)); CHKr(KSI_TlvElement_setInteger(metadata, 0x01, index_tlv)); CHKr(KSI_TlvElement_new(&attrib_tlv)); attrib_tlv->ftlv.tag = 0x02; CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, key, strlen(key) + 1, &key_tlv)); CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x01, key_tlv)); CHKr(KSI_Utf8String_new(ksi->ctx->ksi_ctx, value, strlen(value) + 1, &value_tlv)); CHKr(KSI_TlvElement_setUtf8String(attrib_tlv, 0x02, value_tlv)); CHKr(KSI_TlvElement_setElement(metadata, attrib_tlv)); CHKr(KSI_TlvElement_serialize(metadata, buffer, 0xFFFF, len, 0)); done: if (metadata) KSI_TlvElement_free(metadata); if (attrib_tlv) KSI_TlvElement_free(attrib_tlv); if (key_tlv) KSI_Utf8String_free(key_tlv); if (value_tlv) KSI_Utf8String_free(value_tlv); if (index_tlv) KSI_Integer_free(index_tlv); return r; } #define KSI_FILE_AMOUNT_INC 32 static int rsksiExpandRegisterIfNeeded(rsksictx ctx, size_t inc) { int ret = RSGTE_INTERNAL; ksifile *tmp = NULL; if (ctx == NULL || inc == 0) { return RSGTE_INTERNAL; } if (ctx->ksiCount < ctx->ksiCapacity) { return RSGTE_SUCCESS; } /* If needed allocate memory for the buffer. */ tmp = (ksifile *)realloc(ctx->ksi, sizeof(ksifile) * (ctx->ksiCapacity + inc)); if (tmp == NULL) { ret = RSGTE_OOM; goto done; } /* Make sure that allocated pointers are all set to NULL. */ memset(tmp + ctx->ksiCapacity, 0, sizeof(ksifile) * inc); /* Update buffer capacity. */ ctx->ksiCapacity += inc; ctx->ksi = tmp; tmp = NULL; ret = RSGTE_SUCCESS; done: free(tmp); return ret; } static int rsksiRegisterKsiFile(rsksictx ctx, ksifile ksi) { int ret = RSGTE_INTERNAL; if (ctx == NULL || ksi == NULL) { return RSGTE_INTERNAL; } /* To be extra sure that ksifile buffer is initialized correctly, clear variables. */ if (ctx->ksi == NULL) { ctx->ksiCount = 0; ctx->ksiCapacity = 0; } ret = rsksiExpandRegisterIfNeeded(ctx, KSI_FILE_AMOUNT_INC); if (ret != RSGTE_SUCCESS) goto done; ctx->ksi[ctx->ksiCount] = ksi; ctx->ksiCount++; ret = RSGTE_SUCCESS; done: return ret; } static int rsksiDeregisterKsiFile(rsksictx ctx, ksifile ksi) { int ret = RSGTE_INTERNAL; size_t i = 0; if (ctx == NULL || ksi == NULL) { return RSGTE_INTERNAL; } for (i = 0; i < ctx->ksiCount; i++) { if (ctx->ksi[i] != NULL && ctx->ksi[i] == ksi) { size_t lastElement = ctx->ksiCount - 1; if (i != lastElement) { ctx->ksi[i] = ctx->ksi[lastElement]; } ctx->ksi[lastElement] = NULL; ctx->ksiCount--; ret = RSGTE_SUCCESS; goto done; } } done: return ret; } /* support for old platforms - graceful degrade */ #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif /* read rsyslog log state file; if we cannot access it or the * contents looks invalid, we flag it as non-present (and thus * begin a new hash chain). * The context is initialized accordingly. */ static bool ksiReadStateFile(ksifile ksi) { int fd = -1; struct rsksistatefile sf; bool ret = false; fd = open((char *)ksi->statefilename, O_RDONLY | O_NOCTTY | O_CLOEXEC, 0600); if (fd == -1) goto done; #ifdef __clang_analyzer__ /* scan-build false positive: this state file read is intentionally covered * by module_lock while opening the KSI file so the signer thread cannot see * partially restored state. Skip it for analyzer-only control flow. */ goto done; #else if (read(fd, &sf, sizeof(sf)) != sizeof(sf)) goto done; if (strncmp(sf.hdr, "KSISTAT10", 9)) goto done; if (KSI_getHashLength(sf.hashID) != sf.lenHash || KSI_getHashLength(sf.hashID) > KSI_MAX_IMPRINT_LEN - 1) goto done; if (read(fd, ksi->lastLeaf + 1, sf.lenHash) != sf.lenHash) goto done; ksi->lastLeaf[0] = sf.hashID; ret = true; #endif done: if (!ret) { memset(ksi->lastLeaf, 0, sizeof(ksi->lastLeaf)); ksi->lastLeaf[0] = ksi->hashAlg; } if (fd != -1) close(fd); return ret; } /* persist all information that we need to re-open and append * to a log signature file. */ static void ksiWwriteStateFile(ksifile ksi) { int fd; struct rsksistatefile sf; fd = open((char *)ksi->statefilename, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY | O_CLOEXEC, ksi->ctx->fCreateMode); if (fd == -1) goto done; if (ksi->ctx->fileUID != (uid_t)-1 || ksi->ctx->fileGID != (gid_t)-1) { /* we need to set owner/group */ if (fchown(fd, ksi->ctx->fileUID, ksi->ctx->fileGID) != 0) { report(ksi->ctx, "lmsig_ksi: chown for file '%s' failed: %s", ksi->statefilename, strerror(errno)); } } memcpy(sf.hdr, "KSISTAT10", 9); sf.hashID = ksi->hashAlg; sf.lenHash = KSI_getHashLength(ksi->lastLeaf[0]); /* if the write fails, we cannot do anything against that. We check * the condition just to keep the compiler happy. */ if (write(fd, &sf, sizeof(sf))) { }; if (write(fd, ksi->lastLeaf + 1, sf.lenHash)) { }; close(fd); done: return; } static int ksiCloseSigFile(ksifile ksi) { fclose(ksi->blockFile); ksi->blockFile = NULL; if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) queueAddCloseFile(ksi->ctx, ksi); ksiWwriteStateFile(ksi); return 0; } static int mkpath(char *path, mode_t mode, uid_t uid, gid_t gid) { if (path == NULL) return 1; for (char *p = strchr(path + 1, '/'); p; p = strchr(p + 1, '/')) { *p = '\0'; if (mkdir(path, mode) == 0) { if (uid != (uid_t)-1 || gid != (uid_t)-1) { if (chown(path, uid, gid)) { LogError(errno, RS_RET_IO_ERROR, "ksils12 signatures: could not change to " "configured owner - files may be unaccessible"); } } } else if (errno != EEXIST) { *p = '/'; return -1; } *p = '/'; } return 0; } static FILE *ksiCreateFile( rsksictx ctx, const char *path, uid_t uid, gid_t gid, int mode, bool lockit, const char *header) { int fd = -1; struct stat stat_st; FILE *f = NULL; struct flock lock = {F_WRLCK, SEEK_SET, 0, 0, 0}; if (path == NULL) return NULL; if (mkpath((char *)path, ctx->fDirCreateMode, ctx->dirUID, ctx->dirGID) != 0) { report(ctx, "ksiCreateFile: mkpath failed for %s", path); goto done; } fd = open(path, O_RDWR | O_APPEND | O_NOCTTY | O_CLOEXEC, 0600); if (fd == -1) { fd = open(path, O_RDWR | O_CREAT | O_NOCTTY | O_CLOEXEC, mode); if (fd == -1) { report(ctx, "creating file '%s' failed: %s", path, strerror(errno)); goto done; } if (uid != (uid_t)-1 || gid != (gid_t)-1) { if (fchown(fd, uid, gid) != 0) { report(ctx, "lmsig_ksi: chown for file '%s' failed: %s", path, strerror(errno)); } } } if (lockit && fcntl(fd, F_SETLK, &lock) != 0) report(ctx, "fcntl error: %s", strerror(errno)); f = fdopen(fd, "a"); if (f == NULL) { report(ctx, "fdopen for '%s' failed: %s", path, strerror(errno)); goto done; } setvbuf(f, NULL, _IOFBF, KSI_BUF_SIZE); if (fstat(fd, &stat_st) == -1) { reportErr(ctx, "ksiOpenSigFile: can not stat file"); goto done; } if (stat_st.st_size == 0 && header != NULL) { if (fwrite(header, strlen(header), 1, f) != 1) { report(ctx, "ksiOpenSigFile: fwrite for file %s failed: %s", path, strerror(errno)); goto done; } } /* Write header immediately as when using dynafile it is possible that the same * file is opened 2x in sequence (caused by small dynafile cache where files are * frequently closed and reopened). If the header already exists double header is * not written. The content of the file is ordered by signer thread. */ fflush(f); done: return f; } static void handle_ksi_config(rsksictx ctx, KSI_AsyncService *as, KSI_Config *config) { int res = KSI_UNKNOWN_ERROR; KSI_Integer *intValue = NULL; if (KSI_Config_getMaxRequests(config, &intValue) == KSI_OK && intValue != NULL) { ctx->max_requests = KSI_Integer_getUInt64(intValue); report(ctx, "KSI gateway has reported a max requests value of %llu", (long long unsigned)ctx->max_requests); if (as) { /* libksi expects size_t. */ size_t optValue = 0; optValue = ctx->max_requests; res = KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_MAX_REQUEST_COUNT, (void *)optValue); if (res != KSI_OK) reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_setOption(max_request)", res); optValue = 3 * ctx->max_requests * ctx->blockSigTimeout; KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE, (void *)optValue); } } intValue = NULL; if (KSI_Config_getMaxLevel(config, &intValue) == KSI_OK && intValue != NULL) { uint64_t newLevel = 0; newLevel = KSI_Integer_getUInt64(intValue); report(ctx, "KSI gateway has reported a max level value of %llu", (long long unsigned)newLevel); newLevel = MIN(newLevel, ctx->blockLevelLimit); if (ctx->effectiveBlockLevelLimit != newLevel) { report(ctx, "Changing the configured block level limit from %llu to %llu", (long long unsigned)ctx->effectiveBlockLevelLimit, (long long unsigned)newLevel); ctx->effectiveBlockLevelLimit = newLevel; } else if (newLevel < 2) { report(ctx, "KSI gateway has reported an invalid level limit value (%llu), " "plugin disabled", (long long unsigned)newLevel); ctx->disabled = true; } } intValue = NULL; if (KSI_Config_getAggrPeriod(config, &intValue) == KSI_OK && intValue != NULL) { uint64_t newThreadSleep = 0; newThreadSleep = KSI_Integer_getUInt64(intValue); report(ctx, "KSI gateway has reported an aggregation period value of %llu", (long long unsigned)newThreadSleep); newThreadSleep = MIN(newThreadSleep, ctx->threadSleepms); if (ctx->threadSleepms != newThreadSleep) { report(ctx, "Changing async signer thread sleep from %llu to %llu", (long long unsigned)ctx->threadSleepms, (long long unsigned)newThreadSleep); ctx->threadSleepms = newThreadSleep; } } } static int isAggrConfNeeded(rsksictx ctx) { time_t now = 0; now = time(NULL); if ((uint64_t)ctx->tConfRequested + ctx->confInterval <= (uint64_t)now || ctx->tConfRequested == 0) { ctx->tConfRequested = now; return 1; } return 0; } /* note: if file exists, the last hash for chaining must * be read from file. */ static int ksiOpenSigFile(ksifile ksi) { int r = 0, tmpRes = 0; const char *header; FILE *signatureFile = NULL; if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) header = LS12_BLOCKFILE_HEADER; else header = LS12_FILE_HEADER; ksi->blockFile = ksiCreateFile(ksi->ctx, (char *)ksi->blockfilename, ksi->ctx->fileUID, ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, header); if (ksi->blockFile == NULL) { r = RSGTE_IO; goto done; } /* create the file for ksi signatures if needed */ if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) { signatureFile = ksiCreateFile(ksi->ctx, (char *)ksi->ksifilename, ksi->ctx->fileUID, ksi->ctx->fileGID, ksi->ctx->fCreateMode, true, LS12_SIGFILE_HEADER); if (signatureFile == NULL) { r = RSGTE_IO; goto done; } ksi->sigFile = signatureFile; queueAddNewFile(ksi->ctx, ksi); } /* we now need to obtain the last previous hash, so that * we can continue the hash chain. We do not check for error * as a state file error can be recovered by graceful degredation. */ ksiReadStateFile(ksi); if (ksi->ctx->syncMode == LOGSIG_SYNCHRONOUS) { if (isAggrConfNeeded(ksi->ctx)) { KSI_Config *config = NULL; tmpRes = KSI_receiveAggregatorConfig(ksi->ctx->ksi_ctx, &config); if (tmpRes == KSI_OK) { handle_ksi_config(ksi->ctx, NULL, config); } else { reportKSIAPIErr(ksi->ctx, NULL, "KSI_receiveAggregatorConfig", tmpRes); } KSI_Config_free(config); } } done: return r; } /* * As of some Linux and security expert I spoke to, /dev/urandom * provides very strong random numbers, even if it runs out of * entropy. As far as he knew, this is save for all applications * (and he had good proof that I currently am not permitted to * reproduce). -- rgerhards, 2013-03-04 */ static void seedIVKSI(ksifile ksi) { int hashlen; int fd; const char *rnd_device = ksi->ctx->random_source ? ksi->ctx->random_source : "/dev/urandom"; hashlen = KSI_getHashLength(ksi->hashAlg); ksi->IV = malloc(hashlen); /* do NOT zero-out! */ /* * If /dev/urandom is unavailable, the current memory content is used as a * weak fallback for random data. This is a theoretical case, as this * library only supports Linux, where /dev/urandom is expected to be * reliably available. */ if ((fd = open(rnd_device, O_RDONLY)) >= 0) { #ifdef __clang_analyzer__ /* scan-build false positive: seedIVKSI is called while module_lock * serializes signer state; reading /dev/urandom here is intentional. */ #else if (read(fd, ksi->IV, hashlen) == hashlen) { }; /* keep compiler happy */ #endif close(fd); } } static int create_signer_thread(rsksictx ctx) { int r; if (ctx->signer_state != SIGNER_STARTED) { if ((r = pthread_mutex_init(&ctx->module_lock, 0))) report(ctx, "pthread_mutex_init: %s", strerror(r)); ctx->signer_queue = ProtectedQueue_new(10); ctx->signer_state = SIGNER_INIT; if ((r = pthread_create(&ctx->signer_thread, NULL, signer_thread, ctx))) { report(ctx, "pthread_create: %s", strerror(r)); ctx->signer_state = SIGNER_IDLE; return RSGTE_INTERNAL; } /* Lock until init. */ while (*((volatile int *)&ctx->signer_state) & SIGNER_INIT); if (ctx->signer_state != SIGNER_STARTED) { return RSGTE_INTERNAL; } } return RSGTE_SUCCESS; } rsksictx rsksiCtxNew(void) { rsksictx ctx; ctx = calloc(1, sizeof(struct rsksictx_s)); KSI_CTX_new(&ctx->ksi_ctx); // TODO: error check (probably via a generic macro?) ctx->hasher = NULL; ctx->hashAlg = KSI_getHashAlgorithmByName("default"); ctx->blockTimeLimit = 0; ctx->bKeepTreeHashes = false; ctx->bKeepRecordHashes = true; ctx->max_requests = (1 << 8); ctx->blockSigTimeout = 10; ctx->confInterval = 3600; ctx->tConfRequested = 0; ctx->threadSleepms = 1000; ctx->errFunc = NULL; ctx->usrptr = NULL; ctx->fileUID = -1; ctx->fileGID = -1; ctx->dirUID = -1; ctx->dirGID = -1; ctx->fCreateMode = 0644; ctx->fDirCreateMode = 0700; #if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22 ctx->roundCount = 0; ctx->bRoundLock = 0; #endif ctx->syncMode = LOGSIG_SYNCHRONOUS; ctx->signer_state = SIGNER_IDLE; ctx->disabled = false; ctx->ksi = NULL; /*if (pthread_mutex_init(&ctx->module_lock, 0)) report(ctx, "pthread_mutex_init: %s", strerror(errno)); ctx->signer_queue = ProtectedQueue_new(10);*/ /* Creating a thread this way works only in daemon mode but not when being run interactively when not forked */ /*ret = pthread_atfork(NULL, NULL, create_signer_thread); if (ret != 0) report(ctx, "pthread_atfork error: %s", strerror(ret));*/ return ctx; } static int rsksiStreamLogger(void *logCtx, int logLevel, const char *message) { char time_buf[32]; struct tm *tm_info; time_t timer; FILE *f = (FILE *)logCtx; timer = time(NULL); tm_info = localtime(&timer); if (tm_info == NULL) { return KSI_UNKNOWN_ERROR; } if (f != NULL) { flockfile(f); /* for thread safety */ if (strftime(time_buf, sizeof(time_buf), "%d.%m.%Y %H:%M:%S", tm_info)) { if (fprintf(f, "%s [%s] %lu - %s\n", level2str(logLevel), time_buf, pthread_self(), message) > 0) { } } funlockfile(f); } return KSI_OK; } int rsksiInitModule(rsksictx ctx) { int res = 0; if (ctx->debugFileName != NULL) { ctx->debugFile = fopen(ctx->debugFileName, "w"); if (ctx->debugFile) { res = KSI_CTX_setLoggerCallback(ctx->ksi_ctx, rsksiStreamLogger, ctx->debugFile); if (res != KSI_OK) reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res); res = KSI_CTX_setLogLevel(ctx->ksi_ctx, ctx->debugLevel); if (res != KSI_OK) reportKSIAPIErr(ctx, NULL, "Unable to set log level", res); } else { report(ctx, "Could not open logfile %s: %s", ctx->debugFileName, strerror(errno)); } } KSI_CTX_setOption(ctx->ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void *)((size_t)ctx->hmacAlg)); return create_signer_thread(ctx); } /* either returns ksifile object or NULL if something went wrong */ ksifile rsksiCtxOpenFile(rsksictx ctx, unsigned char *logfn) { int ret = RSGTE_INTERNAL; ksifile ksi; char fn[MAXFNAME + 1]; if (ctx->disabled) return NULL; pthread_mutex_lock(&ctx->module_lock); /* The thread cannot be be created in rsksiCtxNew because in daemon mode the process forks after rsksiCtxNew and the thread disappears */ if (ctx->signer_state != SIGNER_STARTED) { ret = rsksiInitModule(ctx); if (ret != RSGTE_SUCCESS) { report(ctx, "Unable to init. KSI module, signing service disabled"); ctx->disabled = true; pthread_mutex_unlock(&ctx->module_lock); return NULL; } } if ((ksi = rsksifileConstruct(ctx)) == NULL) goto done; snprintf(fn, sizeof(fn), "%s.ksistate", logfn); fn[MAXFNAME] = '\0'; /* be on safe side */ ksi->statefilename = (uchar *)strdup(fn); if (ctx->syncMode == LOGSIG_ASYNCHRONOUS) { /* filename for blocks of hashes*/ snprintf(fn, sizeof(fn), "%s%s", logfn, blockFileSuffix); fn[MAXFNAME] = '\0'; /* be on safe side */ ksi->blockfilename = (uchar *)strdup(fn); /* filename for KSI signatures*/ snprintf(fn, sizeof(fn), "%s%s", logfn, sigFileSuffix); fn[MAXFNAME] = '\0'; /* be on safe side */ ksi->ksifilename = (uchar *)strdup(fn); } else if (ctx->syncMode == LOGSIG_SYNCHRONOUS) { snprintf(fn, sizeof(fn), "%s%s", logfn, ls12FileSuffix); fn[MAXFNAME] = '\0'; /* be on safe side */ ksi->blockfilename = (uchar *)strdup(fn); } if (ksiOpenSigFile(ksi) != 0) { reportErr(ctx, "signature file open failed"); /* Free memory */ free(ksi); ksi = NULL; } done: /* Register ksi file in rsksictx for keeping track of block timeouts. */ rsksiRegisterKsiFile(ctx, ksi); pthread_mutex_unlock(&ctx->module_lock); return ksi; } /* Returns RSGTE_SUCCESS on success, error code otherwise. If algo is unknown or * is not trusted, default hash function is used. */ int rsksiSetHashFunction(rsksictx ctx, char *algName) { if (ctx == NULL || algName == NULL) { return RSGTE_INTERNAL; } int r, id = KSI_getHashAlgorithmByName(algName); if (!KSI_isHashAlgorithmSupported(id)) { report(ctx, "Hash function '%s' is not supported - using default", algName); ctx->hashAlg = KSI_getHashAlgorithmByName("default"); } else { if (!KSI_isHashAlgorithmTrusted(id)) { report(ctx, "Hash function '%s' is not trusted - using default", algName); ctx->hashAlg = KSI_getHashAlgorithmByName("default"); } else ctx->hashAlg = id; } if ((r = KSI_DataHasher_open(ctx->ksi_ctx, ctx->hashAlg, &ctx->hasher)) != KSI_OK) { reportKSIAPIErr(ctx, NULL, "KSI_DataHasher_open", r); ctx->disabled = true; return r; } return RSGTE_SUCCESS; } int rsksiSetHmacFunction(rsksictx ctx, char *algName) { int id = KSI_getHashAlgorithmByName(algName); if (!KSI_isHashAlgorithmSupported(id)) { report(ctx, "HMAC function '%s' is not supported - using default", algName); ctx->hmacAlg = KSI_getHashAlgorithmByName("default"); } else { if (!KSI_isHashAlgorithmTrusted(id)) { report(ctx, "HMAC function '%s' is not trusted - using default", algName); ctx->hmacAlg = KSI_getHashAlgorithmByName("default"); } else ctx->hmacAlg = id; } return 0; } int rsksifileDestruct(ksifile ksi) { int r = 0; rsksictx ctx = NULL; if (ksi == NULL) return RSGTE_INTERNAL; pthread_mutex_lock(&ksi->ctx->module_lock); ctx = ksi->ctx; /* Deregister ksifile so it is not used by signer thread anymore. Note that files are not closed yet! */ rsksiDeregisterKsiFile(ctx, ksi); if (!ksi->disabled && ksi->bInBlk) { sigblkAddMetadata(ksi, blockCloseReason, "Block closed due to file closure."); r = sigblkFinishKSI(ksi); } /* Note that block file is closed immediately but signature file will be closed * by the signer thread scheduled by signer thread work queue. */ if (!ksi->disabled) r = ksiCloseSigFile(ksi); free(ksi->blockfilename); free(ksi->statefilename); free(ksi->ksifilename); free(ksi); pthread_mutex_unlock(&ctx->module_lock); return r; } /* This can only be used when signer thread has terminated or within the thread. */ static void rsksifileForceFree(ksifile ksi) { if (ksi == NULL) return; if (ksi->sigFile != NULL) fclose(ksi->sigFile); if (ksi->blockFile != NULL) fclose(ksi->blockFile); free(ksi->blockfilename); free(ksi->statefilename); free(ksi->ksifilename); free(ksi); return; } /* This can only be used when signer thread has terminated or within the thread. */ static void rsksictxForceFreeSignatures(rsksictx ctx) { size_t i = 0; if (ctx == NULL || ctx->ksi == NULL) return; for (i = 0; i < ctx->ksiCount; i++) { if (ctx->ksi[i] != NULL) { rsksifileForceFree(ctx->ksi[i]); ctx->ksi[i] = NULL; } } ctx->ksiCount = 0; return; } /* This can only be used when signer thread has terminated or within the thread. */ static int rsksictxForceCloseWithoutSig(rsksictx ctx, const char *reason) { size_t i = 0; if (ctx == NULL || ctx->ksi == NULL) return RSGTE_INTERNAL; for (i = 0; i < ctx->ksiCount; i++) { if (ctx->ksi[i] != NULL) { int ret = RSGTE_INTERNAL; /* Only if block contains records, create metadata, close the block and add * no signature marker. Closing block without record will produce redundant * blocks that needs to be signed afterward. */ if (ctx->ksi[i]->nRecords > 0) { ret = sigblkFinishKSINoSignature(ctx->ksi[i], reason); if (ret != RSGTE_SUCCESS) return ret; } /* Free files and remove object from the list. */ rsksifileForceFree(ctx->ksi[i]); ctx->ksi[i] = NULL; } } ctx->ksiCount = 0; return RSGTE_SUCCESS; } void rsksiCtxDel(rsksictx ctx) { if (ctx == NULL) return; /* Note that even in sync. mode signer thread is created and needs to be closed * correctly. */ if (ctx->signer_state == SIGNER_STARTED) { queueAddQuit(ctx); /* Wait until thread closes to be able to safely free the resources. */ pthread_join(ctx->signer_thread, NULL); ProtectedQueue_free(ctx->signer_queue); pthread_mutex_destroy(&ctx->module_lock); } free(ctx->aggregatorUri); free(ctx->aggregatorId); free(ctx->aggregatorKey); free(ctx->debugFileName); if (ctx->random_source) free(ctx->random_source); KSI_DataHasher_free(ctx->hasher); KSI_CTX_free(ctx->ksi_ctx); if (ctx->debugFile != NULL) fclose(ctx->debugFile); /* After signer thread is terminated there should be no open signature files, * but to be extra sure that all files are closed, recheck the list of opened * signature files. */ rsksictxForceFreeSignatures(ctx); free(ctx->ksi); free(ctx); } /* new sigblk is initialized, but maybe in existing ctx */ void sigblkInitKSI(ksifile ksi) { if (ksi == NULL) goto done; seedIVKSI(ksi); memset(ksi->roots, 0, sizeof(ksi->roots)); ksi->nRoots = 0; ksi->nRecords = 0; ksi->bInBlk = 1; ksi->blockStarted = time(NULL); ksi->blockSizeLimit = 1 << (ksi->ctx->effectiveBlockLevelLimit - 1); /* flush the optional debug file when starting a new block */ if (ksi->ctx->debugFile != NULL) fflush(ksi->ctx->debugFile); done: return; } int sigblkCreateMask(ksifile ksi, KSI_DataHash **m) { int r = 0; CHKr(KSI_DataHasher_reset(ksi->ctx->hasher)); CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->lastLeaf, KSI_getHashLength(ksi->lastLeaf[0]) + 1)); CHKr(KSI_DataHasher_add(ksi->ctx->hasher, ksi->IV, KSI_getHashLength(ksi->hashAlg))); CHKr(KSI_DataHasher_close(ksi->ctx->hasher, m)); done: if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r); r = RSGTE_HASH_CREATE; } return r; } int sigblkCreateHash(ksifile ksi, KSI_DataHash **out, const uchar *rec, const size_t len) { int r = 0; CHKr(KSI_DataHasher_reset(ksi->ctx->hasher)); CHKr(KSI_DataHasher_add(ksi->ctx->hasher, rec, len)); CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out)); done: if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHasher", r); r = RSGTE_HASH_CREATE; } return r; } int sigblkHashTwoNodes(ksifile ksi, KSI_DataHash **out, KSI_DataHash *left, KSI_DataHash *right, uint8_t level) { int r = 0; CHKr(KSI_DataHasher_reset(ksi->ctx->hasher)); CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, left)); CHKr(KSI_DataHasher_addImprint(ksi->ctx->hasher, right)); CHKr(KSI_DataHasher_add(ksi->ctx->hasher, &level, 1)); CHKr(KSI_DataHasher_close(ksi->ctx->hasher, out)); done: if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_DataHash_create", r); r = RSGTE_HASH_CREATE; } return r; } int sigblkAddMetadata(ksifile ksi, const char *key, const char *value) { unsigned char buffer[0xFFFF]; size_t encoded_size = 0; int ret = 0; tlvCreateMetadata(ksi, ksi->nRecords, key, value, buffer, &encoded_size); sigblkAddLeaf(ksi, buffer, encoded_size, true); return ret; } int sigblkAddRecordKSI(ksifile ksi, const uchar *rec, const size_t len) { int ret = 0; if (ksi == NULL || ksi->disabled) return 0; pthread_mutex_lock(&ksi->ctx->module_lock); if ((ret = sigblkAddLeaf(ksi, rec, len, false)) != 0) goto done; if (ksi->nRecords == ksi->blockSizeLimit) { sigblkFinishKSI(ksi); sigblkInitKSI(ksi); } done: pthread_mutex_unlock(&ksi->ctx->module_lock); return ret; } int sigblkAddLeaf(ksifile ksi, const uchar *leafData, const size_t leafLength, bool metadata) { KSI_DataHash *mask, *leafHash, *treeNode, *tmpTreeNode; uint8_t j; const unsigned char *pTmp; size_t len; int r = 0; if (ksi == NULL || ksi->disabled) goto done; CHKr(sigblkCreateMask(ksi, &mask)); CHKr(sigblkCreateHash(ksi, &leafHash, leafData, leafLength)); if (ksi->nRecords == 0) tlvWriteBlockHdrKSI(ksi); /* metadata record has to be written into the block file too*/ if (metadata) tlvWriteOctetString(ksi->blockFile, leafData, leafLength); if (ksi->bKeepRecordHashes) tlvWriteHashKSI(ksi, 0x0902, leafHash); /* normal leaf and metadata record are hashed in different order */ if (!metadata) { /* hash leaf */ if ((r = sigblkHashTwoNodes(ksi, &treeNode, mask, leafHash, 1)) != 0) goto done; } else { if ((r = sigblkHashTwoNodes(ksi, &treeNode, leafHash, mask, 1)) != 0) goto done; } /* persists x here if Merkle tree needs to be persisted! */ if (ksi->bKeepTreeHashes) tlvWriteHashKSI(ksi, 0x0903, treeNode); KSI_DataHash_getImprint(treeNode, &pTmp, &len); memcpy(ksi->lastLeaf, pTmp, len); for (j = 0; j < ksi->nRoots; ++j) { if (ksi->roots[j] == NULL) { ksi->roots[j] = treeNode; treeNode = NULL; break; } else if (treeNode != NULL) { /* hash interim node */ tmpTreeNode = treeNode; r = sigblkHashTwoNodes(ksi, &treeNode, ksi->roots[j], tmpTreeNode, j + 2); KSI_DataHash_free(ksi->roots[j]); ksi->roots[j] = NULL; KSI_DataHash_free(tmpTreeNode); if (r != 0) goto done; if (ksi->bKeepTreeHashes) tlvWriteHashKSI(ksi, 0x0903, treeNode); } } if (treeNode != NULL) { /* new level, append "at the top" */ ksi->roots[ksi->nRoots] = treeNode; ++ksi->nRoots; assert(ksi->nRoots < MAX_ROOTS); treeNode = NULL; } ++ksi->nRecords; /* cleanup (x is cleared as part of the roots array) */ KSI_DataHash_free(mask); KSI_DataHash_free(leafHash); done: return r; } static int sigblkCheckTimeOut(rsksictx ctx) { int ret = RSGTE_INTERNAL; time_t now; char buf[KSI_BUF_SIZE]; size_t i = 0; if (ctx == NULL) { return RSGTE_INTERNAL; } pthread_mutex_lock(&ctx->module_lock); if (ctx->ksi == NULL || ctx->disabled || !ctx->blockTimeLimit) { ret = RSGTE_SUCCESS; goto done; } now = time(NULL); for (i = 0; i < ctx->ksiCount; i++) { ksifile ksi = ctx->ksi[i]; if (ksi == NULL) continue; /* To avoide unexpected crash. */ if (!ksi->bInBlk) continue; /* Not inside a block, nothing to close nor sign. */ if ((time_t)(ksi->blockStarted + ctx->blockTimeLimit) > now) continue; snprintf(buf, KSI_BUF_SIZE, "Block closed due to reaching time limit %d", ctx->blockTimeLimit); sigblkAddMetadata(ksi, blockCloseReason, buf); sigblkFinishKSI(ksi); sigblkInitKSI(ksi); } done: pthread_mutex_unlock(&ctx->module_lock); return ret; } static int sigblkSign(ksifile ksi, KSI_DataHash *hash, int level) { unsigned char *der = NULL; size_t lenDer = 0; int r = KSI_OK; int ret = 0; KSI_Signature *sig = NULL; /* Sign the root hash. */ r = KSI_Signature_signAggregated(ksi->ctx->ksi_ctx, hash, level, &sig); if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_createAggregated", r); ret = 1; goto signing_done; } /* Serialize Signature. */ r = KSI_Signature_serialize(sig, &der, &lenDer); if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "KSI_Signature_serialize", r); ret = 1; lenDer = 0; goto signing_done; } signing_done: /* if signing failed the signature will be written as zero size */ if (r == KSI_OK) { r = tlvWriteKSISigLS12(ksi->blockFile, ksi->nRecords, der, lenDer); if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteKSISigLS12", r); ret = 1; } } else r = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, hash, KSI_getErrorString(r)); if (r != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteBlockSigKSI", r); ret = 1; } if (sig != NULL) KSI_Signature_free(sig); if (der != NULL) KSI_free(der); return ret; } unsigned sigblkCalcLevel(unsigned leaves) { unsigned level = 0; unsigned c = leaves; while (c > 1) { level++; c >>= 1; } if (1 << level < (int)leaves) level++; return level; } static int sigblkFinishTree(ksifile ksi, KSI_DataHash **hsh) { int ret = RSGTE_INTERNAL; KSI_DataHash *root = NULL; KSI_DataHash *rootDel = NULL; int8_t j = 0; if (ksi == NULL || hsh == NULL) { goto done; } if (ksi->nRecords == 0) { ret = RSGTE_SUCCESS; goto done; } root = NULL; for (j = 0; j < ksi->nRoots; ++j) { if (root == NULL) { root = ksi->roots[j]; ksi->roots[j] = NULL; } else if (ksi->roots[j] != NULL) { rootDel = root; root = NULL; ret = sigblkHashTwoNodes(ksi, &root, ksi->roots[j], rootDel, j + 2); KSI_DataHash_free(ksi->roots[j]); ksi->roots[j] = NULL; KSI_DataHash_free(rootDel); rootDel = NULL; if (ksi->bKeepTreeHashes) { tlvWriteHashKSI(ksi, 0x0903, root); } if (ret != KSI_OK) goto done; /* checks sigblkHashTwoNodes() result! */ } } *hsh = root; root = NULL; ret = RSGTE_SUCCESS; done: KSI_DataHash_free(root); KSI_DataHash_free(rootDel); return ret; } int sigblkFinishKSI(ksifile ksi) { KSI_DataHash *root = NULL; int ret = RSGTE_INTERNAL; unsigned level = 0; if (ksi == NULL) { goto done; } if (ksi->nRecords == 0) { ret = RSGTE_SUCCESS; goto done; } ret = sigblkFinishTree(ksi, &root); if (ret != RSGTE_SUCCESS) goto done; // Multiplying leaves count by 2 to account for blinding masks level = sigblkCalcLevel(2 * ksi->nRecords); // in case of async mode we append the root hash to signer queue if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) { ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, NULL); if (ret != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret); goto done; } queueAddSignRequest(ksi->ctx, ksi, root, level); root = NULL; } else { sigblkSign(ksi, root, level); } ret = RSGTE_SUCCESS; done: KSI_DataHash_free(root); free(ksi->IV); ksi->IV = NULL; ksi->bInBlk = 0; return ret; } static int sigblkFinishKSINoSignature(ksifile ksi, const char *reason) { KSI_DataHash *root = NULL; int ret = RSGTE_INTERNAL; if (ksi == NULL || ksi->ctx == NULL || (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS && ksi->sigFile == NULL) || ksi->blockFile == NULL || reason == NULL) { goto done; } ret = sigblkAddMetadata(ksi, blockCloseReason, reason); if (ret != RSGTE_SUCCESS) goto done; ret = sigblkFinishTree(ksi, &root); if (ret != RSGTE_SUCCESS) goto done; ret = tlvWriteNoSigLS12(ksi->blockFile, ksi->nRecords, root, reason); if (ret != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret); goto done; } if (ksi->ctx->syncMode == LOGSIG_ASYNCHRONOUS) { ret = tlvWriteNoSigLS12(ksi->sigFile, ksi->nRecords, root, reason); if (ret != KSI_OK) { reportKSIAPIErr(ksi->ctx, ksi, "tlvWriteNoSigLS12", ret); goto done; } } ret = RSGTE_SUCCESS; done: KSI_DataHash_free(root); free(ksi->IV); ksi->IV = NULL; ksi->bInBlk = 0; return ret; } int rsksiSetAggregator(rsksictx ctx, char *uri, char *loginid, char *key) { int r; char *strTmp, *strTmpUri; /* only use the strings if they are not empty */ ctx->aggregatorUri = (uri != NULL && strlen(uri) != 0) ? strdup(uri) : NULL; ctx->aggregatorId = (loginid != NULL && strlen(loginid) != 0) ? strdup(loginid) : NULL; ctx->aggregatorKey = (key != NULL && strlen(key) != 0) ? strdup(key) : NULL; /* split the URI string up for possible HA endpoints */ strTmp = ctx->aggregatorUri; while ((strTmpUri = strsep(&strTmp, "|")) != NULL) { if (ctx->aggregatorEndpointCount >= KSI_CTX_HA_MAX_SUBSERVICES) { report(ctx, "Maximum number (%d) of service endoints reached, ignoring endpoint: %s", KSI_CTX_HA_MAX_SUBSERVICES, strTmpUri); } else { ctx->aggregatorEndpoints[ctx->aggregatorEndpointCount] = strTmpUri; ctx->aggregatorEndpointCount++; } } r = KSI_CTX_setAggregator(ctx->ksi_ctx, ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey); if (r != KSI_OK) { ctx->disabled = true; reportKSIAPIErr(ctx, NULL, "KSI_CTX_setAggregator", r); return KSI_INVALID_ARGUMENT; } return r; } int rsksiSetDebugFile(rsksictx ctx, char *val) { if (!val) return KSI_INVALID_ARGUMENT; ctx->debugFileName = strdup(val); return KSI_OK; } static bool add_queue_item( rsksictx ctx, QITEM_type type, KSI_DataHash *root, FILE *sigFile, uint64_t intarg1, uint64_t intarg2) { QueueItem *qi = (QueueItem *)malloc(sizeof(QueueItem)); if (!qi) { ctx->disabled = true; return false; } qi->root = root; qi->file = sigFile; qi->type = type; qi->status = QITEM_WAITING; qi->intarg1 = intarg1; qi->intarg2 = intarg2; qi->respHandle = NULL; qi->ksi_status = KSI_UNKNOWN_ERROR; qi->request_time = time(NULL); if (ProtectedQueue_addItem(ctx->signer_queue, qi) == false) { ctx->disabled = true; free(qi); return false; } return true; } static bool queueAddCloseFile(rsksictx ctx, ksifile ksi) { return add_queue_item(ctx, QITEM_CLOSE_FILE, NULL, ksi->sigFile, 0, 0); } static bool queueAddNewFile(rsksictx ctx, ksifile ksi) { return add_queue_item(ctx, QITEM_NEW_FILE, NULL, ksi->sigFile, time(NULL) + ctx->blockTimeLimit, 0); } static bool queueAddQuit(rsksictx ctx) { return add_queue_item(ctx, QITEM_QUIT, NULL, NULL, 0, 0); } static bool queueAddSignRequest(rsksictx ctx, ksifile ksi, KSI_DataHash *root, unsigned level) { return add_queue_item(ctx, QITEM_SIGNATURE_REQUEST, root, ksi->sigFile, ksi->nRecords, level); } static bool save_response(rsksictx ctx, FILE *outfile, QueueItem *item) { bool ret = false; KSI_Signature *sig = NULL; unsigned char *raw = NULL; size_t raw_len; int res = KSI_OK; if (item->respHandle != NULL && item->ksi_status == KSI_OK) { CHECK_KSI_API(KSI_AsyncHandle_getSignature(item->respHandle, &sig), ctx, "KSI_AsyncHandle_getSignature"); CHECK_KSI_API(KSI_Signature_serialize(sig, &raw, &raw_len), ctx, "KSI_Signature_serialize"); tlvWriteKSISigLS12(outfile, item->intarg1, raw, raw_len); KSI_free(raw); } else { tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(item->ksi_status)); } ret = true; cleanup: if (res != KSI_OK) tlvWriteNoSigLS12(outfile, item->intarg1, item->root, KSI_getErrorString(res)); KSI_Signature_free(sig); return ret; } static KSI_DataHash *clone_hash(KSI_CTX *ksi_ctx, const KSI_DataHash *hash) { int res = KSI_UNKNOWN_ERROR; const unsigned char *imprint = NULL; size_t imprint_len = 0; KSI_DataHash *tmp = NULL; if (hash == NULL) return NULL; res = KSI_DataHash_getImprint(hash, &imprint, &imprint_len); if (res != KSI_OK) return NULL; res = KSI_DataHash_fromImprint(ksi_ctx, imprint, imprint_len, &tmp); if (res != KSI_OK) return NULL; return tmp; } static bool process_requests_async(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) { bool ret = false; QueueItem *item = NULL; int res = KSI_OK, tmpRes; KSI_AsyncHandle *reqHandle = NULL; KSI_AsyncHandle *respHandle = NULL; KSI_DataHash *clonedHash = NULL; KSI_AggregationReq *req = NULL; KSI_Config *config = NULL; KSI_Integer *level; long extError; KSI_Utf8String *errorMsg; int state, ksi_status; unsigned i; size_t p; KSI_AsyncService_getPendingCount(as, &p); /* Check if there are pending/available responses and associate them with the request items */ while (true) { respHandle = NULL; item = NULL; tmpRes = KSI_AsyncService_run(as, &respHandle, &p); if (tmpRes != KSI_OK) reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_run", tmpRes); if (respHandle == NULL) { /* nothing received */ break; } #if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22 if (p != 0 && ctx->roundCount > 0) { ctx->roundCount--; } else { ctx->bRoundLock = 0; ctx->roundCount = 0; } #endif state = KSI_ASYNC_STATE_UNDEFINED; CHECK_KSI_API(KSI_AsyncHandle_getState(respHandle, &state), ctx, "KSI_AsyncHandle_getState"); if (state == KSI_ASYNC_STATE_PUSH_CONFIG_RECEIVED) { res = KSI_AsyncHandle_getConfig(respHandle, &config); if (res == KSI_OK) { handle_ksi_config(ctx, as, config); KSI_AsyncHandle_free(respHandle); } else reportKSIAPIErr(ctx, NULL, "KSI_AsyncHandle_getConfig", res); } else if (state == KSI_ASYNC_STATE_RESPONSE_RECEIVED) { CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void **)&item), ctx, "KSI_AsyncHandle_getRequestCtx"); item->respHandle = respHandle; item->ksi_status = KSI_OK; } else if (state == KSI_ASYNC_STATE_ERROR) { CHECK_KSI_API(KSI_AsyncHandle_getRequestCtx(respHandle, (const void **)&item), ctx, "KSI_AsyncHandle_getRequestCtx"); errorMsg = NULL; KSI_AsyncHandle_getError(respHandle, &ksi_status); KSI_AsyncHandle_getExtError(respHandle, &extError); KSI_AsyncHandle_getErrorMessage(respHandle, &errorMsg); report(ctx, "Asynchronous request returned error %s (%d), %lu %s", KSI_getErrorString(ksi_status), ksi_status, extError, errorMsg ? KSI_Utf8String_cstr(errorMsg) : ""); KSI_AsyncHandle_free(respHandle); if (item) item->ksi_status = ksi_status; } if (item) item->status = QITEM_DONE; } KSI_AsyncService_getPendingCount(as, &p); /* Send all the new requests in the back of the queue to the server */ for (i = 0; i < ProtectedQueue_count(ctx->signer_queue); i++) { item = NULL; if (!ProtectedQueue_getItem(ctx->signer_queue, i, (void **)&item) || !item) continue; /* ingore non request queue items */ if (item->type != QITEM_SIGNATURE_REQUEST) continue; /* stop at first processed item */ if (item->status != QITEM_WAITING) continue; /* Due to a bug in libksi it is possible that async signer may send out * more signing requests than permitted by the gateway. Workaround is to * keep track of signing requests here. */ #if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22 if (ctx->roundCount >= ctx->max_requests) ctx->bRoundLock = 1; if (ctx->bRoundLock) break; #endif /* The data hash is produced in another thread by another KSI_CTX and * libksi internal uses KSI_DataHash cache to reduce the amount of * memory allocations by recycling old objects. Lets clone the hash * value with current KSI_CTX as we can not be sure that this thread is * not affecting the data hash cache operated by another thread. */ clonedHash = clone_hash(ksi_ctx, item->root); CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &req), ctx, "KSI_AggregationReq_new"); CHECK_KSI_API(KSI_AggregationReq_setRequestHash((KSI_AggregationReq *)req, clonedHash), ctx, "KSI_AggregationReq_setRequestHash"); clonedHash = NULL; CHECK_KSI_API(KSI_Integer_new(ksi_ctx, item->intarg2, &level), ctx, "KSI_Integer_new"); CHECK_KSI_API(KSI_AggregationReq_setRequestLevel(req, level), ctx, "KSI_AggregationReq_setRequestLevel"); CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, req, &reqHandle), ctx, "KSI_AsyncAggregationHandle_new"); CHECK_KSI_API(KSI_AsyncHandle_setRequestCtx(reqHandle, (void *)item, NULL), ctx, "KSI_AsyncRequest_setRequestContext"); res = KSI_AsyncService_addRequest(as, reqHandle); /* this can fail because of throttling */ if (res == KSI_OK) { item->status = QITEM_SENT; #if KSI_SDK_VER_MAJOR == 3 && KSI_SDK_VER_MINOR < 22 ctx->roundCount++; #endif } else { reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addRequest", res); KSI_AsyncHandle_free(reqHandle); item->status = QITEM_DONE; item->ksi_status = res; break; } if (i != 0 && i % ctx->max_requests == 0) { CHECK_KSI_API(KSI_AsyncService_run(as, NULL, NULL), ctx, "KSI_AsyncService_run"); } } CHECK_KSI_API(KSI_AsyncService_run(as, NULL, NULL), ctx, "KSI_AsyncService_run"); /* Save all consequent fulfilled responses in the front of the queue to the signature file */ while (ProtectedQueue_count(ctx->signer_queue)) { item = NULL; if (!ProtectedQueue_getItem(ctx->signer_queue, 0, (void **)&item)) break; if (!item) { ProtectedQueue_popFront(ctx->signer_queue, (void **)&item); continue; } /* stop at first non request queue item (maybe file close/open, quit) */ if (item->type != QITEM_SIGNATURE_REQUEST) break; /* stop at first unfinished queue item because the signatures need to be ordered */ if (item->status != QITEM_DONE) break; ProtectedQueue_popFront(ctx->signer_queue, (void **)&item); save_response(ctx, item->file, item); fflush(item->file); /* the main thread has to be locked when the hash is freed to avoid a race condition */ pthread_mutex_lock(&ctx->module_lock); KSI_DataHash_free(item->root); KSI_AsyncHandle_free(item->respHandle); free(item); pthread_mutex_unlock(&ctx->module_lock); } ret = true; cleanup: KSI_DataHash_free(clonedHash); KSI_AsyncService_getPendingCount(as, &p); return ret; } /* This can only be used when signer thread has terminated or within the thread. */ static bool rsksictxCloseAllPendingBlocksWithoutSignature(rsksictx ctx, const char *reason) { bool ret = false; QueueItem *item = NULL; int res = KSI_OK; /* Save all consequent fulfilled responses in the front of the queue to the signature file */ while (ProtectedQueue_count(ctx->signer_queue)) { item = NULL; ProtectedQueue_popFront(ctx->signer_queue, (void **)&item); if (item == NULL) { continue; } /* Skip non request queue item. */ if (item->type == QITEM_SIGNATURE_REQUEST) { res = tlvWriteNoSigLS12(item->file, item->intarg1, item->root, reason); if (res != KSI_OK) { reportKSIAPIErr(ctx, NULL, "tlvWriteNoSigLS12", res); ret = false; goto cleanup; } fflush(item->file); } KSI_DataHash_free(item->root); KSI_AsyncHandle_free(item->respHandle); free(item); } ret = true; cleanup: return ret; } static void request_async_config(rsksictx ctx, KSI_CTX *ksi_ctx, KSI_AsyncService *as) { KSI_Config *cfg = NULL; KSI_AsyncHandle *cfgHandle = NULL; KSI_AggregationReq *cfgReq = NULL; int res; bool bSuccess = false; CHECK_KSI_API(KSI_AggregationReq_new(ksi_ctx, &cfgReq), ctx, "KSI_AggregationReq_new"); CHECK_KSI_API(KSI_Config_new(ksi_ctx, &cfg), ctx, "KSI_Config_new"); CHECK_KSI_API(KSI_AggregationReq_setConfig(cfgReq, cfg), ctx, "KSI_AggregationReq_setConfig"); CHECK_KSI_API(KSI_AsyncAggregationHandle_new(ksi_ctx, cfgReq, &cfgHandle), ctx, "KSI_AsyncAggregationHandle_new"); CHECK_KSI_API(KSI_AsyncService_addRequest(as, cfgHandle), ctx, "KSI_AsyncService_addRequest"); bSuccess = true; cleanup: if (!bSuccess) { if (cfgHandle) KSI_AsyncHandle_free(cfgHandle); else if (cfgReq) KSI_AggregationReq_free(cfgReq); else if (cfg) KSI_Config_free(cfg); } } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" void *signer_thread(void *arg) { int res = KSI_UNKNOWN_ERROR; rsksictx ctx = (rsksictx)arg; KSI_CTX *ksi_ctx = NULL; KSI_AsyncService *as = NULL; size_t size_t_value = 0; size_t ksiFileCount = 0; int endpoints = 0; bool bSleep = true; CHECK_KSI_API(KSI_CTX_new(&ksi_ctx), ctx, "KSI_CTX_new"); CHECK_KSI_API(KSI_CTX_setAggregator(ksi_ctx, ctx->aggregatorUri, ctx->aggregatorId, ctx->aggregatorKey), ctx, "KSI_CTX_setAggregator"); if (ctx->debugFile) { res = KSI_CTX_setLoggerCallback(ksi_ctx, rsksiStreamLogger, ctx->debugFile); if (res != KSI_OK) reportKSIAPIErr(ctx, NULL, "Unable to set logger callback", res); res = KSI_CTX_setLogLevel(ksi_ctx, ctx->debugLevel); if (res != KSI_OK) reportKSIAPIErr(ctx, NULL, "Unable to set log level", res); } CHECK_KSI_API(KSI_CTX_setOption(ksi_ctx, KSI_OPT_AGGR_HMAC_ALGORITHM, (void *)((size_t)ctx->hmacAlg)), ctx, "KSI_CTX_setOption"); res = KSI_SigningHighAvailabilityService_new(ksi_ctx, &as); if (res != KSI_OK) { reportKSIAPIErr(ctx, NULL, "KSI_SigningAsyncService_new", res); } else { int i = 0; for (i = 0; i < ctx->aggregatorEndpointCount; i++) { res = KSI_AsyncService_addEndpoint(as, ctx->aggregatorEndpoints[i], ctx->aggregatorId, ctx->aggregatorKey); if (res != KSI_OK) { // This can fail if the protocol is not supported by async api. reportKSIAPIErr(ctx, NULL, "KSI_AsyncService_addEndpoint", res); continue; } endpoints++; } } if (endpoints == 0) { /* no endpoint accepted, deleting the service */ report(ctx, "No endpoints added, signing service disabled"); ctx->disabled = true; KSI_AsyncService_free(as); as = NULL; goto cleanup; } /* Lets use buffer value, as libksi requires size_t. */ size_t_value = ctx->max_requests; KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_REQUEST_CACHE_SIZE, (void *)size_t_value); size_t_value = ctx->blockSigTimeout; KSI_AsyncService_setOption(as, KSI_ASYNC_OPT_SND_TIMEOUT, (void *)size_t_value); ctx->signer_state = SIGNER_STARTED; while (true) { QueueItem *item = NULL; if (isAggrConfNeeded(ctx)) { request_async_config(ctx, ksi_ctx, as); } /* Wait for a work item or timeout*/ if (bSleep) { ProtectedQueue_waitForItem(ctx->signer_queue, NULL, ctx->threadSleepms); } bSleep = true; /* Check for block time limit. */ sigblkCheckTimeOut(ctx); /* in case there are no items go around*/ if (ProtectedQueue_count(ctx->signer_queue) == 0) { process_requests_async(ctx, ksi_ctx, as); continue; } /* process signing requests only if there is an open signature file */ if (ksiFileCount > 0) { /* check for pending/unsent requests in asynchronous service */ if (!process_requests_async(ctx, ksi_ctx, as)) { // probably fatal error, disable signing, error should be already reported ctx->disabled = true; goto cleanup; } } /* if there are sig. requests still in the front, then we have to start over*/ if (ProtectedQueue_peekFront(ctx->signer_queue, (void **)&item) && item->type == QITEM_SIGNATURE_REQUEST) continue; /* Handle other types of work items */ if (ProtectedQueue_popFront(ctx->signer_queue, (void **)&item) != 0) { /* There is no point to sleep after processing non request type item * as there is great possibility that next item can already be * processed. */ bSleep = false; if (item->type == QITEM_CLOSE_FILE) { if (item->file) { fclose(item->file); item->file = NULL; } if (ksiFileCount > 0) ksiFileCount--; } else if (item->type == QITEM_NEW_FILE) { ksiFileCount++; } else if (item->type == QITEM_QUIT) { free(item); /* Will look into work queue for pending KSI signatures and will output * unsigned block marker instead of actual KSI signature to finalize this * thread quickly. */ rsksictxCloseAllPendingBlocksWithoutSignature( ctx, "Signing not finished due to sudden closure of lmsig_ksi-ls12 module."); rsksictxForceCloseWithoutSig(ctx, "Block closed due to sudden closure of lmsig_ksi-ls12 module."); goto cleanup; } free(item); } } cleanup: KSI_AsyncService_free(as); KSI_CTX_free(ksi_ctx); ctx->signer_state = SIGNER_STOPPED; return NULL; } #pragma GCC diagnostic push rsyslog-8.2608.0/runtime/PaxHeaders/hashtable_private.h0000644000000000000000000000013215132411300020046 xustar0030 mtime=1768559296.264885609 30 atime=1787067618.117439262 30 ctime=1787067794.489726825 rsyslog-8.2608.0/runtime/hashtable_private.h0000666000175000017500000000535315132411300017522 0ustar00rgerrger/* Copyright (C) 2002, 2004 Christopher Clark */ #ifndef __HASHTABLE_PRIVATE_CWC22_H__ #define __HASHTABLE_PRIVATE_CWC22_H__ #include "hashtable.h" /*****************************************************************************/ struct entry { void *k, *v; unsigned int h; struct entry *next; }; struct hashtable { unsigned int tablelength; struct entry **table; unsigned int entrycount; unsigned int loadlimit; unsigned int primeindex; unsigned int (*hashfn)(void *k); int (*eqfn)(void *k1, void *k2); void (*dest)(void *v); /* destructor for values, if NULL use free() */ }; /*****************************************************************************/ unsigned int hash(struct hashtable *h, void *k); /*****************************************************************************/ /* indexFor */ #define indexFor(tablelength, hashvalue) ((hashvalue) % (tablelength)) /*****************************************************************************/ #define freekey(X) free(X) /*****************************************************************************/ #endif /* __HASHTABLE_PRIVATE_CWC22_H__*/ /* * Copyright (c) 2002, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ rsyslog-8.2608.0/runtime/PaxHeaders/rsconf.c0000644000000000000000000000013115241075234015662 xustar0029 mtime=1787067036.60857835 30 atime=1787067036.755581103 30 ctime=1787067794.291723135 rsyslog-8.2608.0/runtime/rsconf.c0000664000175000017500000022255015241075234015335 0ustar00rgerrger/* rsconf.c - the rsyslog configuration system. * * Module begun 2011-04-19 by Rainer Gerhards * * Copyright 2011-2023 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "obj.h" #include "srUtils.h" #include "ruleset.h" #include "modules.h" #include "conf.h" #include "queue.h" #include "rsconf.h" #include "cfsysline.h" #include "errmsg.h" #include "action.h" #include "glbl.h" #include "unicode-helper.h" #include "omshell.h" #include "omusrmsg.h" #include "omfwd.h" #include "omfile.h" #include "ompipe.h" #include "omdiscard.h" #include "pmrfc5424.h" #include "pmrfc3164.h" #include "smfile.h" #include "smtradfile.h" #include "smfwd.h" #include "smtradfwd.h" #include "parser.h" #include "outchannel.h" #include "threads.h" #include "datetime.h" #include "parserif.h" #include "modules.h" #include "dirty.h" #include "template.h" #include "timezones.h" #include "ratelimit.h" #include "translate.h" #ifdef HAVE_LIBYAML #include "yamlconf.h" #endif extern char *yytext; extern int yylineno; extern int yyparse(void); /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(ruleset) DEFobjCurrIf(module) DEFobjCurrIf(conf) DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* exported static data */ rsconf_t *runConf = NULL; /* the currently running config */ rsconf_t *loadConf = NULL; /* the config currently being loaded (no concurrent config load supported!) */ static const char cfgModRefSrc[] = "cfgmodules"; #ifdef HAVE_LIBSYSTEMD /* module readiness barrier: modules that need startup time call rsconfRegisterReadiness(), * then rsconfSignalReady() once initialised. When global(systemd.notifyReadyDelay="on") * is configured, rsconfWaitForModulesReady() blocks until all registered modules have * signalled, then sd_notify(READY=1) can fire safely. The whole barrier is compiled only * when systemd support is present; on non-systemd builds, rsconf.h provides inline no-ops * for Register/Signal so opt-in modules need no #ifdef guards of their own. */ static pthread_mutex_t mutModulesReady = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t condModulesReady; static pthread_once_t onceModulesReadyCond = PTHREAD_ONCE_INIT; static clockid_t clockModulesReady = CLOCK_REALTIME; static int nModulesPendingReady = 0; static int bModulesReadyWaitStarted = 0; static int bModulesReadyWaitActive = 0; static int bModulesReadyNotifySent = 0; static void initModulesReadyCond(void) { pthread_condattr_t attr; if (pthread_condattr_init(&attr) != 0) { pthread_cond_init(&condModulesReady, NULL); return; } if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) == 0) { clockModulesReady = CLOCK_MONOTONIC; } if (pthread_cond_init(&condModulesReady, &attr) != 0) { pthread_cond_init(&condModulesReady, NULL); clockModulesReady = CLOCK_REALTIME; } pthread_condattr_destroy(&attr); } int rsconfShouldDelayReadyNotify(rsconf_t *cnf) { return cnf != NULL && cnf->globals.systemdNotifyReadyDelay; } void rsconfRegisterReadiness(void) { pthread_once(&onceModulesReadyCond, initModulesReadyCond); if (!rsconfShouldDelayReadyNotify(runConf)) return; pthread_mutex_lock(&mutModulesReady); if (bModulesReadyNotifySent) { /* Reload-time module setup happens after the one-shot systemd READY=1. */ } else if (bModulesReadyWaitActive) { LogError(0, RS_RET_SYS_ERR, "rsyslogd: module registered readiness after systemd READY wait " "started - ignoring late registration"); } else if (bModulesReadyWaitStarted) { /* The initial barrier already closed; do not corrupt the pending count. */ } else { ++nModulesPendingReady; } pthread_mutex_unlock(&mutModulesReady); } void rsconfSignalReady(void) { pthread_once(&onceModulesReadyCond, initModulesReadyCond); if (!rsconfShouldDelayReadyNotify(runConf)) return; pthread_mutex_lock(&mutModulesReady); if (nModulesPendingReady > 0 && --nModulesPendingReady == 0) pthread_cond_broadcast(&condModulesReady); pthread_mutex_unlock(&mutModulesReady); } /* Wait up to 60 s for all registered modules to signal readiness. */ void rsconfWaitForModulesReady(void) { struct timespec ts; pthread_once(&onceModulesReadyCond, initModulesReadyCond); pthread_mutex_lock(&mutModulesReady); bModulesReadyWaitStarted = 1; bModulesReadyWaitActive = 1; pthread_mutex_unlock(&mutModulesReady); if (clock_gettime(clockModulesReady, &ts) != 0) { LogError(errno, RS_RET_SYS_ERR, "rsyslogd: cannot compute module readiness timeout - sending READY=1 anyway"); pthread_mutex_lock(&mutModulesReady); bModulesReadyWaitActive = 0; pthread_mutex_unlock(&mutModulesReady); return; } ts.tv_sec += 60; pthread_mutex_lock(&mutModulesReady); while (nModulesPendingReady > 0) { const int rc = pthread_cond_timedwait(&condModulesReady, &mutModulesReady, &ts); if (rc == ETIMEDOUT) { LogError(0, RS_RET_TIMED_OUT, "rsyslogd: timed out waiting for input modules to signal readiness " "(%d module(s) outstanding) - sending READY=1 anyway", nModulesPendingReady); break; } else if (rc != 0) { LogError(0, RS_RET_SYS_ERR, "rsyslogd: pthread_cond_timedwait error %d waiting for module " "readiness - sending READY=1 anyway", rc); break; } } bModulesReadyWaitActive = 0; pthread_mutex_unlock(&mutModulesReady); } void rsconfReadyNotifySent(void) { pthread_once(&onceModulesReadyCond, initModulesReadyCond); pthread_mutex_lock(&mutModulesReady); bModulesReadyNotifySent = 1; pthread_mutex_unlock(&mutModulesReady); } #endif /* HAVE_LIBSYSTEMD */ /* hardcoded standard templates (used for defaults) */ static uchar template_DebugFormat[] = "\"Debug line with all properties:\nFROMHOST: '%FROMHOST%', fromhost-ip: " "'%fromhost-ip%', HOSTNAME: '%HOSTNAME%', PRI: %PRI%,\nsyslogtag '%syslogtag%', programname: '%programname%', " "APP-NAME: '%APP-NAME%', PROCID: '%PROCID%', MSGID: '%MSGID%',\nTIMESTAMP: '%TIMESTAMP%', " "STRUCTURED-DATA: '%STRUCTURED-DATA%',\nmsg: '%msg%'\nescaped msg: '%msg:::drop-cc%'\ninputname: %inputname% " "rawmsg: '%rawmsg%'\n$!:%$!%\n$.:%$.%\n$/:%$/%\n\n\""; static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% " "%PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\""; static uchar template_SyslogRFC5424Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% " "%PROCID% %MSGID% %STRUCTURED-DATA% %msg%\""; static uchar template_TraditionalFileFormat[] = "=RSYSLOG_TraditionalFileFormat"; static uchar template_FileFormat[] = "=RSYSLOG_FileFormat"; static uchar template_ForwardFormat[] = "=RSYSLOG_ForwardFormat"; static uchar template_TraditionalForwardFormat[] = "=RSYSLOG_TraditionalForwardFormat"; static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n " "%syslogtag%%msg%\n\r\""; static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\""; static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, " "DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, " "'%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, " "'%syslogtag%')\",SQL"; static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, " "DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, " "'%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, " "'%syslogtag%')\",STDSQL"; static uchar template_spoofadr[] = "\"%fromhost-ip%\""; static uchar template_SysklogdFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%\n\""; static uchar template_StdJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\",\\\"fromhost\\\":\\\"" "%HOSTNAME:::json%\\\",\\\"facility\\\":\\\"%syslogfacility-text%\\\",\\\"priority\\\":\\\"" "%syslogpriority-text%\\\",\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\",\\\"timegenerated\\\":\\\"" "%timegenerated:::date-rfc3339%\\\"}\""; static uchar template_FullJSONFmt[] = "\"{\\\"message\\\":\\\"%msg:::json%\\\"," "\\\"fromhost\\\":\\\"%HOSTNAME:::json%\\\"," "\\\"programname\\\":\\\"%programname%\\\"," "\\\"procid\\\":\\\"%PROCID%\\\"," "\\\"msgid\\\":\\\"%MSGID%\\\"," "\\\"facility\\\":\\\"%syslogfacility-text%\\\"," "\\\"priority\\\":\\\"%syslogpriority-text%\\\"," "\\\"timereported\\\":\\\"%timereported:::date-rfc3339%\\\"," "\\\"timegenerated\\\":\\\"%timegenerated:::date-rfc3339%\\\"}\""; static uchar template_StdClickHouseFmt[] = "\"INSERT INTO rsyslog.SystemEvents (severity, facility, " "timestamp, hostname, tag, message) VALUES (%syslogseverity%, %syslogfacility%, " "'%timereported:::date-unixtimestamp%', '%hostname%', '%syslogtag%', '%msg%')\",STDSQL"; static uchar template_StdOmSenderTrack_senderid[] = "\"%fromhost-ip%\""; /* default template for omsendertrack "senderid" parameter*/ static uchar template_PerSourceKey[] = "\"%hostname%\""; /* default template for per-source ratelimiting */ /* end templates */ /* tables for interfacing with the v6 config system (as far as we need to) */ static struct cnfparamdescr inppdescr[] = {{"type", eCmdHdlrString, CNFPARAM_REQUIRED}}; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; static struct cnfparamdescr parserpdescr[] = {{"type", eCmdHdlrString, CNFPARAM_REQUIRED}, {"name", eCmdHdlrString, CNFPARAM_REQUIRED}}; static struct cnfparamblk parserpblk = {CNFPARAMBLK_VERSION, sizeof(parserpdescr) / sizeof(struct cnfparamdescr), parserpdescr}; /* ratelimit() */ static struct cnfparamdescr ratelimitpdescr[] = {{"name", eCmdHdlrString, CNFPARAM_REQUIRED}, {"interval", eCmdHdlrInt, 0}, {"burst", eCmdHdlrInt, 0}, {"severity", eCmdHdlrSeverity, 0}, {"policy", eCmdHdlrString, 0}, {"policyWatch", eCmdHdlrBinary, 0}, {"policyWatchDebounce", eCmdHdlrString, 0}, {"perSource", eCmdHdlrBinary, 0}, {"perSourcePolicy", eCmdHdlrString, 0}, {"perSourceKeyTpl", eCmdHdlrString, 0}, {"perSourceMaxStates", eCmdHdlrInt, 0}, {"perSourceTopN", eCmdHdlrInt, 0}}; static struct cnfparamblk ratelimitpblk = {CNFPARAMBLK_VERSION, sizeof(ratelimitpdescr) / sizeof(struct cnfparamdescr), ratelimitpdescr}; int rsconfNeedDropPriv(rsconf_t *const cnf) { return ((cnf->globals.gidDropPriv != 0) || (cnf->globals.uidDropPriv != 0)); } static void cnfSetDefaults(rsconf_t *pThis) { #ifdef ENABLE_LIBCAPNG pThis->globals.bAbortOnFailedLibcapngSetup = 1; pThis->globals.bCapabilityDropEnabled = 1; #endif pThis->globals.bAbortOnUncleanConfig = 0; pThis->globals.bAbortOnFailedQueueStartup = 0; pThis->globals.compatConfigFormatLegacy = COMPAT_CONFIGFORMAT_ENABLE; pThis->globals.compatConfigFormatSyslogd = COMPAT_CONFIGFORMAT_ENABLE; pThis->globals.compatConfigFormatProperty = COMPAT_CONFIGFORMAT_ENABLE; pThis->globals.compatDefaultsSecure = COMPAT_DEFAULTS_SECURE_WARN; pThis->globals.bReduceRepeatMsgs = 0; pThis->globals.bDebugPrintTemplateList = 1; pThis->globals.bDebugPrintModuleList = 0; pThis->globals.bDebugPrintCfSysLineHandlerList = 0; pThis->globals.bLogStatusMsgs = DFLT_bLogStatusMsgs; pThis->globals.bAllMsgToStderr = 0; pThis->globals.bErrMsgToStderr = 1; pThis->globals.maxErrMsgToStderr = -1; pThis->globals.umask = -1; pThis->globals.gidDropPrivKeepSupplemental = 0; pThis->globals.abortOnIDResolutionFail = 1; pThis->templates.root = NULL; pThis->templates.last = NULL; pThis->templates.lastStatic = NULL; pThis->actions.nbrActions = 0; pThis->actions.iActionNbr = 0; pThis->actions.action_names = NULL; pThis->actions.n_action_names = 0; pThis->actions.n_action_names_alloc = 0; pThis->globals.pszWorkDir = NULL; pThis->globals.bDropMalPTRMsgs = 0; pThis->globals.operatingStateFile = NULL; pThis->globals.iGnuTLSLoglevel = 0; pThis->globals.debugOnShutdown = 0; pThis->globals.pszDfltNetstrmDrvrCAF = NULL; pThis->globals.pszDfltNetstrmDrvrCRLF = NULL; pThis->globals.pszDfltNetstrmDrvrCertFile = NULL; pThis->globals.pszDfltNetstrmDrvrKeyFile = NULL; pThis->globals.pszDfltNetstrmDrvr = NULL; pThis->globals.oversizeMsgErrorFile = NULL; pThis->globals.reportOversizeMsg = 1; pThis->globals.oversizeMsgInputMode = 0; pThis->globals.reportChildProcessExits = REPORT_CHILD_PROCESS_EXITS_ERRORS; pThis->globals.bActionReportSuspension = 1; pThis->globals.bActionReportSuspensionCont = 0; pThis->globals.janitorInterval = 10; pThis->globals.reportNewSenders = 0; pThis->globals.reportGoneAwaySenders = 0; pThis->globals.senderStatsTimeout = 12 * 60 * 60; /* 12 hr timeout for senders */ pThis->globals.senderKeepTrack = 0; pThis->globals.inputTimeoutShutdown = 1000; pThis->globals.iDefPFFamily = PF_UNSPEC; pThis->globals.ACLAddHostnameOnFail = 0; pThis->globals.ACLDontResolve = 0; pThis->globals.bDisableDNS = 0; pThis->globals.bProcessInternalMessages = 0; const char *const log_dflt = getenv("RSYSLOG_DFLT_LOG_INTERNAL"); if (log_dflt != NULL && !strcmp(log_dflt, "1")) pThis->globals.bProcessInternalMessages = 1; pThis->globals.iMaxOpenFiles = 0; pThis->globals.glblDevOptions = 0; pThis->globals.intMsgRateLimitItv = 60; pThis->globals.intMsgRateLimitBurst = 100; pThis->globals.intMsgsSeverityFilter = DFLT_INT_MSGS_SEV_FILTER; pThis->globals.permitCtlC = glblPermitCtlC; pThis->globals.actq_dflt_toQShutdown = 10; pThis->globals.actq_dflt_toActShutdown = 1000; pThis->globals.actq_dflt_toEnq = 2000; pThis->globals.actq_dflt_toWrkShutdown = 60000; pThis->globals.ruleset_dflt_toQShutdown = 1500; pThis->globals.ruleset_dflt_toActShutdown = 1000; pThis->globals.ruleset_dflt_toEnq = 2000; pThis->globals.ruleset_dflt_toWrkShutdown = 60000; pThis->globals.dnscacheDefaultTTL = 24 * 60 * 60; pThis->globals.dnscacheEnableTTL = 0; pThis->globals.shutdownQueueDoubleSize = 0; pThis->globals.optionDisallowWarning = 1; pThis->globals.bSupportCompressionExtension = 1; #ifdef ENABLE_LIBLOGGING_STDLOG pThis->globals.stdlog_hdl = stdlog_open("rsyslogd", 0, STDLOG_SYSLOG, NULL); pThis->globals.stdlog_chanspec = NULL; #endif pThis->globals.iMaxLine = 8096; /* timezone specific*/ pThis->timezones.tzinfos = NULL; pThis->timezones.ntzinfos = 0; /* queue params */ pThis->globals.mainQ.iMainMsgQueueSize = 100000; pThis->globals.mainQ.iMainMsgQHighWtrMark = 80000; pThis->globals.mainQ.iMainMsgQLowWtrMark = 20000; pThis->globals.mainQ.iMainMsgQDiscardMark = -1; pThis->globals.mainQ.iMainMsgQDiscardSeverity = 8; pThis->globals.mainQ.iMainMsgQueueNumWorkers = 2; pThis->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY; pThis->globals.mainQ.pszMainMsgQFName = NULL; pThis->globals.mainQ.iMainMsgQueMaxFileSize = 1024 * 1024; pThis->globals.mainQ.iMainMsgQPersistUpdCnt = 0; pThis->globals.mainQ.bMainMsgQSyncQeueFiles = 0; pThis->globals.mainQ.iMainMsgQtoQShutdown = 1500; pThis->globals.mainQ.iMainMsgQtoActShutdown = 1000; pThis->globals.mainQ.iMainMsgQtoEnq = 2000; pThis->globals.mainQ.iMainMsgQtoWrkShutdown = 60000; pThis->globals.mainQ.iMainMsgQWrkMinMsgs = 40000; pThis->globals.mainQ.iMainMsgQDeqSlowdown = 0; pThis->globals.mainQ.iMainMsgQueMaxDiskSpace = 0; pThis->globals.mainQ.iMainMsgQueDeqBatchSize = 256; pThis->globals.mainQ.bMainMsgQSaveOnShutdown = 1; pThis->globals.mainQ.iMainMsgQueueDeqtWinFromHr = 0; pThis->globals.mainQ.iMainMsgQueueDeqtWinToHr = 25; pThis->pMsgQueue = NULL; pThis->globals.parser.cCCEscapeChar = '#'; pThis->globals.parser.bDropTrailingLF = 1; pThis->globals.parser.bDropTrailingCR = 0; pThis->globals.parser.bEscapeCCOnRcv = 1; pThis->globals.parser.bSpaceLFOnRcv = 0; pThis->globals.parser.bEscape8BitChars = 0; pThis->globals.parser.bEscapeTab = 1; pThis->globals.parser.bParserEscapeCCCStyle = 0; pThis->globals.parser.bPermitSlashInProgramname = 0; pThis->globals.parser.bParseHOSTNAMEandTAG = 1; pThis->parsers.pDfltParsLst = NULL; pThis->parsers.pParsLstRoot = NULL; } /* Standard-Constructor */ BEGINobjConstruct(rsconf) /* be sure to specify the object type also in END macro! */ cnfSetDefaults(pThis); lookupInitCnf(&pThis->lu_tabs); CHKiRet(dynstats_initCnf(&pThis->dynstats_buckets)); CHKiRet(perctile_initCnf(&pThis->perctile_buckets)); CHKiRet(ratelimit_cfgsInit(&pThis->ratelimit_cfgs)); CHKiRet(llInit(&pThis->rulesets.llRulesets, rulesetDestructForLinkedList, rulesetKeyDestruct, (int (*)(void *, void *))strcasecmp)); finalize_it: ENDobjConstruct(rsconf) /* ConstructionFinalizer */ static rsRetVal rsconfConstructFinalize(rsconf_t __attribute__((unused)) * pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, rsconf); RETiRet; } /* call freeCnf() module entry points. * Module references are released later, after all other config-owned objects * that may still call back into those modules have been destroyed. */ static void freeCnf(rsconf_t *pThis) { cfgmodules_etry_t *etry; etry = pThis->modules.root; while (etry != NULL) { if (etry->pMod->beginCnfLoad != NULL) { dbgprintf("calling freeCnf(%p) for module '%s'\n", etry->modCnf, (char *)module.GetName(etry->pMod)); etry->pMod->freeCnf(etry->modCnf); } etry = etry->next; } } static void releaseCnfModRefs(rsconf_t *pThis) { cfgmodules_etry_t *etry, *del; etry = pThis->modules.root; while (etry != NULL) { del = etry; etry = etry->next; module.Release(cfgModRefSrc, &del->pMod); free(del); } pThis->modules.root = NULL; } static void freeActionNames(rsconf_t *pThis) { size_t i; for (i = 0; i < pThis->actions.n_action_names; ++i) { free(pThis->actions.action_names[i]); } free(pThis->actions.action_names); pThis->actions.action_names = NULL; pThis->actions.n_action_names = 0; pThis->actions.n_action_names_alloc = 0; } /* destructor for the rsconf object */ BEGINobjDestruct(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(rsconf); freeCnf(pThis); tplDeleteAll(pThis); dynstats_destroyAllBuckets(pThis); perctileBucketsDestruct(); ochDeleteAll(); freeTimezones(pThis); parser.DestructParserList(&pThis->parsers.pDfltParsLst); parser.destroyMasterParserList(pThis->parsers.pParsLstRoot); free(pThis->globals.mainQ.pszMainMsgQFName); free(pThis->globals.pszConfDAGFile); free(pThis->globals.pszWorkDir); free(pThis->globals.operatingStateFile); free(pThis->globals.pszDfltNetstrmDrvrCAF); free(pThis->globals.pszDfltNetstrmDrvrCRLF); free(pThis->globals.pszDfltNetstrmDrvrCertFile); free(pThis->globals.pszDfltNetstrmDrvrKeyFile); free(pThis->globals.pszDfltNetstrmDrvr); free(pThis->globals.oversizeMsgErrorFile); #ifdef ENABLE_LIBLOGGING_STDLOG stdlog_close(pThis->globals.stdlog_hdl); free(pThis->globals.stdlog_chanspec); #endif lookupDestroyCnf(); freeActionNames(pThis); llDestroy(&(pThis->rulesets.llRulesets)); ratelimit_cfgsDestruct(&pThis->ratelimit_cfgs); releaseCnfModRefs(pThis); ENDobjDestruct(rsconf) /* DebugPrint support for the rsconf object */ PROTOTYPEObjDebugPrint(rsconf); BEGINobjDebugPrint(rsconf) /* be sure to specify the object type also in END and CODESTART macros! */ cfgmodules_etry_t *modNode; dbgprintf("configuration object %p\n", pThis); dbgprintf("Global Settings:\n"); dbgprintf(" bDebugPrintTemplateList.............: %d\n", pThis->globals.bDebugPrintTemplateList); dbgprintf(" bDebugPrintModuleList : %d\n", pThis->globals.bDebugPrintModuleList); dbgprintf(" bDebugPrintCfSysLineHandlerList.....: %d\n", pThis->globals.bDebugPrintCfSysLineHandlerList); dbgprintf(" bLogStatusMsgs : %d\n", pThis->globals.bLogStatusMsgs); dbgprintf(" bErrMsgToStderr.....................: %d\n", pThis->globals.bErrMsgToStderr); dbgprintf(" drop Msgs with malicious PTR Record : %d\n", glbl.GetDropMalPTRMsgs(pThis)); ruleset.DebugPrintAll(pThis); dbgprintf("\n"); if (pThis->globals.bDebugPrintTemplateList) tplPrintList(pThis); if (pThis->globals.bDebugPrintModuleList) module.PrintList(); if (pThis->globals.bDebugPrintCfSysLineHandlerList) dbgPrintCfSysLineHandlers(); /* we use the now traditional messages, albeit they originally were expected to become * "streamlined". Also we do not add any more, as the config system ouputs this data in * any case and we have seen no need for more info in the past 10+ years. */ dbgprintf("Main queue size %d messages.\n", pThis->globals.mainQ.iMainMsgQueueSize); dbgprintf("Main queue worker threads: %d, wThread shutdown: %d, Perists every %d updates.\n", pThis->globals.mainQ.iMainMsgQueueNumWorkers, pThis->globals.mainQ.iMainMsgQtoWrkShutdown, pThis->globals.mainQ.iMainMsgQPersistUpdCnt); dbgprintf("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n", pThis->globals.mainQ.iMainMsgQtoQShutdown, pThis->globals.mainQ.iMainMsgQtoActShutdown, pThis->globals.mainQ.iMainMsgQtoEnq); dbgprintf("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d\n", pThis->globals.mainQ.iMainMsgQHighWtrMark, pThis->globals.mainQ.iMainMsgQLowWtrMark, pThis->globals.mainQ.iMainMsgQDiscardMark, pThis->globals.mainQ.iMainMsgQDiscardSeverity); dbgprintf("Main queue save on shutdown %d, max disk space allowed %lld\n", pThis->globals.mainQ.bMainMsgQSaveOnShutdown, pThis->globals.mainQ.iMainMsgQueMaxDiskSpace); dbgprintf("Work Directory: '%s'.\n", glbl.GetWorkDir(pThis)); ochPrintList(pThis); dbgprintf("Modules used in this configuration:\n"); for (modNode = pThis->modules.root; modNode != NULL; modNode = modNode->next) { dbgprintf(" %s\n", module.GetName(modNode->pMod)); } CODESTARTobjDebugPrint(rsconf); ENDobjDebugPrint(rsconf) static rsRetVal parserProcessCnf(struct cnfobj *o) { struct cnfparamvals *pvals; modInfo_t *pMod; uchar *cnfModName = NULL; uchar *parserName = NULL; int paramIdx; void *parserInst; parser_t *myparser; DEFiRet; pvals = nvlstGetParams(o->nvlst, &parserpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } DBGPRINTF("input param blk after parserProcessCnf:\n"); cnfparamsPrint(&parserpblk, pvals); paramIdx = cnfparamGetIdx(&parserpblk, "name"); parserName = (uchar *)es_str2cstr(pvals[paramIdx].val.d.estr, NULL); if (parser.FindParser(loadConf->parsers.pParsLstRoot, &myparser, parserName) != RS_RET_PARSER_NOT_FOUND) { LogError(0, RS_RET_PARSER_NAME_EXISTS, "parser module name '%s' already exists", parserName); ABORT_FINALIZE(RS_RET_PARSER_NAME_EXISTS); } paramIdx = cnfparamGetIdx(&parserpblk, "type"); cnfModName = (uchar *)es_str2cstr(pvals[paramIdx].val.d.estr, NULL); if ((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_PARSER)) == NULL) { LogError(0, RS_RET_MOD_UNKNOWN, "parser module name '%s' is unknown", cnfModName); ABORT_FINALIZE(RS_RET_MOD_UNKNOWN); } if (pMod->mod.pm.newParserInst == NULL) { LogError(0, RS_RET_MOD_NO_PARSER_STMT, "parser module '%s' does not support parser() statement", cnfModName); ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT); } CHKiRet(pMod->mod.pm.newParserInst(o->nvlst, &parserInst)); /* all well, so let's (try) to add parser to config */ CHKiRet(parserConstructViaModAndName(pMod, parserName, parserInst)); finalize_it: free(cnfModName); free(parserName); cnfparamvalsDestruct(pvals, &parserpblk); RETiRet; } /* Process input() objects */ static rsRetVal inputProcessCnf(struct cnfobj *o) { struct cnfparamvals *pvals; modInfo_t *pMod; uchar *cnfModName = NULL; int typeIdx; DEFiRet; pvals = nvlstGetParams(o->nvlst, &inppblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } DBGPRINTF("input param blk after inputProcessCnf:\n"); cnfparamsPrint(&inppblk, pvals); typeIdx = cnfparamGetIdx(&inppblk, "type"); cnfModName = (uchar *)es_str2cstr(pvals[typeIdx].val.d.estr, NULL); if ((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_IN)) == NULL) { LogError(0, RS_RET_MOD_UNKNOWN, "input module name '%s' is unknown", cnfModName); ABORT_FINALIZE(RS_RET_MOD_UNKNOWN); } if (pMod->mod.im.newInpInst == NULL) { LogError(0, RS_RET_MOD_NO_INPUT_STMT, "input module '%s' does not support input() statement", cnfModName); ABORT_FINALIZE(RS_RET_MOD_NO_INPUT_STMT); } iRet = pMod->mod.im.newInpInst(o->nvlst); finalize_it: free(cnfModName); cnfparamvalsDestruct(pvals, &inppblk); RETiRet; } /* Process ratelimit() objects */ static rsRetVal initFunc_ratelimit(struct cnfobj *o) { struct cnfparamvals *pvals; int i; uchar *name = NULL; int interval = 0; int burst = 10000; int severity = -1; /* -1 means not set/all */ uchar *policy = NULL; int policy_watch = 0; uchar *policy_watch_debounce = NULL; int per_source_enabled = 0; uchar *per_source_policy = NULL; uchar *per_source_key_tpl = NULL; int per_source_max_states = 0; int per_source_topn = 0; sbool has_inline_policy_params = 0; sbool has_legacy_per_source_params = 0; DEFiRet; pvals = nvlstGetParams(o->nvlst, &ratelimitpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } for (i = 0; i < ratelimitpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(ratelimitpblk.descr[i].name, "name")) { CHKmalloc(name = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(ratelimitpblk.descr[i].name, "interval")) { interval = (int)pvals[i].val.d.n; has_inline_policy_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "burst")) { burst = (int)pvals[i].val.d.n; has_inline_policy_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "severity")) { severity = (int)pvals[i].val.d.n; has_inline_policy_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "policy")) { CHKmalloc(policy = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(ratelimitpblk.descr[i].name, "policyWatch")) { policy_watch = (int)pvals[i].val.d.n; } else if (!strcmp(ratelimitpblk.descr[i].name, "policyWatchDebounce")) { CHKmalloc(policy_watch_debounce = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(ratelimitpblk.descr[i].name, "perSource")) { per_source_enabled = (int)pvals[i].val.d.n; has_legacy_per_source_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "perSourcePolicy")) { CHKmalloc(per_source_policy = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); has_legacy_per_source_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "perSourceKeyTpl")) { CHKmalloc(per_source_key_tpl = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); has_legacy_per_source_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "perSourceMaxStates")) { per_source_max_states = (int)pvals[i].val.d.n; has_legacy_per_source_params = 1; } else if (!strcmp(ratelimitpblk.descr[i].name, "perSourceTopN")) { per_source_topn = (int)pvals[i].val.d.n; has_legacy_per_source_params = 1; } } if (per_source_policy != NULL && !per_source_enabled) { per_source_enabled = 1; } if (per_source_max_states < 0 || per_source_topn < 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: perSourceMaxStates/perSourceTopN must be >= 0 for '%s'", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (interval < 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: interval must be >= 0 for '%s'", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (burst < 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: burst must be >= 0 for '%s'", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKiRet(ratelimitAddConfig(loadConf, (char *)name, (unsigned)interval, (unsigned)burst, severity, (char *)policy, policy_watch, (char *)policy_watch_debounce, per_source_enabled, (char *)per_source_policy, (char *)per_source_key_tpl, (unsigned)per_source_max_states, (unsigned)per_source_topn, has_inline_policy_params, has_legacy_per_source_params)); finalize_it: free(name); free(policy); free(policy_watch_debounce); free(per_source_policy); free(per_source_key_tpl); cnfparamvalsDestruct(pvals, &ratelimitpblk); RETiRet; } /*------------------------------ interface to flex/bison parser ------------------------------*/ void parser_warnmsg(const char *fmt, ...) { va_list ap; char errBuf[1024]; va_start(ap, fmt); if (vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf)) errBuf[sizeof(errBuf) - 1] = '\0'; LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "warning during parsing file %s, on or before line %d: %s", cnfcurrfn, yylineno, errBuf); va_end(ap); } void parser_errmsg(const char *fmt, ...) { va_list ap; char errBuf[1024]; va_start(ap, fmt); if (vsnprintf(errBuf, sizeof(errBuf), fmt, ap) == sizeof(errBuf)) errBuf[sizeof(errBuf) - 1] = '\0'; if (cnfcurrfn == NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "error during config processing: %s", errBuf); } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "error during parsing file %s, on or before line %d: %s", cnfcurrfn, yylineno, errBuf); } va_end(ap); } int yyerror(const char *s); /* we need this prototype to make compiler happy */ int yyerror(const char *s) { parser_errmsg("%s on token '%s'", s, yytext); return 0; } void ATTR_NONNULL() cnfDoObj(struct cnfobj *const o) { int bDestructObj = 1; int bChkUnuse = 1; assert(o != NULL); dbgprintf("cnf:global:obj: "); cnfobjPrint(o); /* We need to check for object disabling as early as here to cover most * of them at once and avoid needless initializations * - jvymazal 2020-02-12 */ if (nvlstChkDisabled(o->nvlst)) { dbgprintf("object disabled by configuration\n"); return; } if (rsconfTranslateEnabled()) { rsconfTranslateCaptureObj(o, cnfcurrfn, yylineno); } switch (o->objType) { case CNFOBJ_GLOBAL: glblProcessCnf(o); break; case CNFOBJ_TIMEZONE: glblProcessTimezone(o); break; case CNFOBJ_MAINQ: glblProcessMainQCnf(o); bDestructObj = 0; break; case CNFOBJ_MODULE: modulesProcessCnf(o); break; case CNFOBJ_INPUT: inputProcessCnf(o); break; case CNFOBJ_LOOKUP_TABLE: lookupTableDefProcessCnf(o); break; case CNFOBJ_DYN_STATS: dynstats_processCnf(o); break; case CNFOBJ_PERCTILE_STATS: perctile_processCnf(o); break; case CNFOBJ_PARSER: parserProcessCnf(o); break; case CNFOBJ_RATELIMIT: initFunc_ratelimit(o); break; case CNFOBJ_TPL: if (tplProcessCnf(o) != RS_RET_OK) parser_errmsg("error processing template object"); break; case CNFOBJ_RULESET: rulesetProcessCnf(o); break; case CNFOBJ_PROPERTY: case CNFOBJ_CONSTANT: /* these types are processed at a later stage */ bChkUnuse = 0; break; case CNFOBJ_ACTION: default: dbgprintf("cnfDoObj program error: unexpected object type %u\n", o->objType); break; } if (bDestructObj) { if (bChkUnuse) nvlstChkUnused(o->nvlst); cnfobjDestruct(o); } } void cnfDoScript(struct cnfstmt *script) { if (rsconfTranslateEnabled()) { rsconfTranslateCaptureScript(script, cnfcurrfn, yylineno); } dbgprintf("cnf:global:script\n"); ruleset.AddScript(ruleset.GetCurrent(loadConf), script); } void cnfDoCfsysline(char *ln) { if (rsconfTranslateEnabled()) { rsconfTranslateAddUnsupported(cnfcurrfn, yylineno, "legacy $-directive '%s' is not supported by the translator", ln); } DBGPRINTF("cnf:global:cfsysline: %s\n", ln); if (!glblPermitLegacyConfigDirective(loadConf, ln)) { free(ln); return; } /* the legacy system needs the "$" stripped */ conf.cfsysline((uchar *)ln + 1); free(ln); } void cnfDoBSDTag(char *ln) { if (rsconfTranslateEnabled()) { rsconfTranslateAddUnsupported(cnfcurrfn, yylineno, "BSD-style tag block '%s' is not supported by the translator", ln); } DBGPRINTF("cnf:global:BSD tag: %s\n", ln); LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED, "BSD-style blocks are no longer supported in rsyslog, " "see https://www.rsyslog.com/g/BSD for details and a " "solution (Block '%s')", ln); free(ln); } void cnfDoBSDHost(char *ln) { if (rsconfTranslateEnabled()) { rsconfTranslateAddUnsupported(cnfcurrfn, yylineno, "BSD-style host block '%s' is not supported by the translator", ln); } DBGPRINTF("cnf:global:BSD host: %s\n", ln); LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED, "BSD-style blocks are no longer supported in rsyslog, " "see https://www.rsyslog.com/g/BSD for details and a " "solution (Block '%s')", ln); free(ln); } /*------------------------------ end interface to flex/bison parser ------------------------------*/ /* drop to specified group * Returns RS_RET_ERR_DROP_PRIV if the requested group privileges cannot be set. */ static rsRetVal doDropPrivGid(rsconf_t *cnf) { int res; uchar szBuf[1024]; DEFiRet; if (!cnf->globals.gidDropPrivKeepSupplemental) { res = setgroups(0, NULL); /* remove all supplemental group IDs */ if (res) { LogError(errno, RS_RET_ERR_DROP_PRIV, "could not remove supplemental group IDs via setgroups(): missing CAP_SETGID or insufficient " "privilege"); ABORT_FINALIZE(RS_RET_ERR_DROP_PRIV); } DBGPRINTF("setgroups(0, NULL): %d\n", res); } res = setgid(cnf->globals.gidDropPriv); if (res) { LogError(errno, RS_RET_ERR_DROP_PRIV, "could not set requested group id %d via setgid(): missing CAP_SETGID or insufficient privilege", cnf->globals.gidDropPriv); ABORT_FINALIZE(RS_RET_ERR_DROP_PRIV); } DBGPRINTF("setgid(%d): %d\n", cnf->globals.gidDropPriv, res); snprintf((char *)szBuf, sizeof(szBuf), "rsyslogd's groupid changed to %d", cnf->globals.gidDropPriv); logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, szBuf, 0); finalize_it: RETiRet; } /* drop to specified user * Returns RS_RET_ERR_DROP_PRIV if the requested user privileges cannot be set. */ static rsRetVal doDropPrivUid(rsconf_t *cnf) { int res; uchar szBuf[1024]; struct passwd *pw; gid_t gid; DEFiRet; /* Try to set appropriate supplementary groups for this user. * Failure is not fatal. */ pw = getpwuid(cnf->globals.uidDropPriv); if (pw) { gid = getgid(); res = initgroups(pw->pw_name, gid); if (res) { LogError(errno, RS_RET_ERR_DROP_PRIV, "could not initialize supplemental groups for user id %d via initgroups(): missing CAP_SETGID or " "insufficient privilege", cnf->globals.uidDropPriv); } DBGPRINTF("initgroups(%s, %ld): %d\n", pw->pw_name, (long)gid, res); } else { LogError(errno, NO_ERRCODE, "could not get username for userid '%d'", cnf->globals.uidDropPriv); } res = setuid(cnf->globals.uidDropPriv); if (res) { LogError(errno, RS_RET_ERR_DROP_PRIV, "could not set requested user id %d via setuid(): missing CAP_SETUID or insufficient privilege", cnf->globals.uidDropPriv); ABORT_FINALIZE(RS_RET_ERR_DROP_PRIV); } DBGPRINTF("setuid(%d): %d\n", cnf->globals.uidDropPriv, res); snprintf((char *)szBuf, sizeof(szBuf), "rsyslogd's userid changed to %d", cnf->globals.uidDropPriv); logmsgInternal(NO_ERRCODE, LOG_SYSLOG | LOG_INFO, szBuf, 0); finalize_it: RETiRet; } /* drop privileges. This will drop to the configured privileges, if * set by the user. After this method has been executed, the previous * privileges can no be re-gained. */ static rsRetVal dropPrivileges(rsconf_t *cnf) { DEFiRet; if (cnf->globals.gidDropPriv != 0) { CHKiRet(doDropPrivGid(cnf)); DBGPRINTF("group privileges have been dropped to gid %u\n", (unsigned)cnf->globals.gidDropPriv); } if (cnf->globals.uidDropPriv != 0) { CHKiRet(doDropPrivUid(cnf)); DBGPRINTF("user privileges have been dropped to uid %u\n", (unsigned)cnf->globals.uidDropPriv); } finalize_it: RETiRet; } /* tell the rsysog core (including ourselfs) that the config load is done and * we need to prepare to move over to activate mode. */ static inline rsRetVal tellCoreConfigLoadDone(void) { DBGPRINTF("telling rsyslog core that config load for %p is done\n", loadConf); return glblDoneLoadCnf(); } /* Tell input modules that the config parsing stage is over. */ static rsRetVal tellModulesConfigLoadDone(void) { cfgmodules_etry_t *node; DBGPRINTF("telling modules that config load for %p is done\n", loadConf); node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY); while (node != NULL) { DBGPRINTF("beginCnfLoad(%p) for module '%s'\n", node->pMod->beginCnfLoad, node->pMod->pszName); if (node->pMod->beginCnfLoad != NULL) { DBGPRINTF("calling endCnfLoad() for module '%s'\n", node->pMod->pszName); node->pMod->endCnfLoad(node->modCnf); } node = module.GetNxtCnfType(loadConf, node, eMOD_ANY); // loadConf -> runConf } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* Tell input modules to verify config object */ static rsRetVal tellModulesCheckConfig(void) { cfgmodules_etry_t *node; rsRetVal localRet; DBGPRINTF("telling modules to check config %p\n", loadConf); node = module.GetNxtCnfType(loadConf, NULL, eMOD_ANY); while (node != NULL) { if (node->pMod->beginCnfLoad != NULL) { localRet = node->pMod->checkCnf(node->modCnf); DBGPRINTF("module %s tells us config can %sbe activated\n", node->pMod->pszName, (localRet == RS_RET_OK) ? "" : "NOT "); if (localRet == RS_RET_OK) { node->canActivate = 1; } else { node->canActivate = 0; } } node = module.GetNxtCnfType(loadConf, node, eMOD_ANY); // runConf -> loadConf } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* verify parser instances after full config load */ static rsRetVal checkParserInstances(void) { parserList_t *node; rsRetVal localRet; DEFiRet; node = loadConf->parsers.pParsLstRoot; while (node != NULL) { if (node->pParser->pModule->mod.pm.checkParserInst != NULL) { localRet = node->pParser->pModule->mod.pm.checkParserInst(node->pParser->pInst); if (localRet != RS_RET_OK) { iRet = localRet; break; } } node = node->pNext; } RETiRet; } /* Tell modules to activate current running config (pre privilege drop) */ static rsRetVal tellModulesActivateConfigPrePrivDrop(void) { cfgmodules_etry_t *node; rsRetVal localRet; DBGPRINTF("telling modules to activate config (before dropping privs) %p\n", runConf); node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY); while (node != NULL) { if (node->pMod->beginCnfLoad != NULL && node->pMod->activateCnfPrePrivDrop != NULL && node->canActivate) { DBGPRINTF("pre priv drop activating config %p for module %s\n", runConf, node->pMod->pszName); localRet = node->pMod->activateCnfPrePrivDrop(node->modCnf); if (localRet != RS_RET_OK) { LogError(0, localRet, "activation of module %s failed", node->pMod->pszName); node->canActivate = 0; /* in a sense, could not activate... */ } } node = module.GetNxtCnfType(runConf, node, eMOD_ANY); } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* Tell modules to activate current running config */ static rsRetVal tellModulesActivateConfig(void) { cfgmodules_etry_t *node; rsRetVal localRet; DBGPRINTF("telling modules to activate config %p\n", runConf); node = module.GetNxtCnfType(runConf, NULL, eMOD_ANY); while (node != NULL) { if (node->pMod->beginCnfLoad != NULL && node->canActivate) { DBGPRINTF("activating config %p for module %s\n", runConf, node->pMod->pszName); localRet = node->pMod->activateCnf(node->modCnf); if (localRet != RS_RET_OK) { LogError(0, localRet, "activation of module %s failed", node->pMod->pszName); node->canActivate = 0; /* in a sense, could not activate... */ } } node = module.GetNxtCnfType(runConf, node, eMOD_ANY); } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* Actually run the input modules. This happens after privileges are dropped, * if that is requested. */ static rsRetVal runInputModules(void) { cfgmodules_etry_t *node; int bNeedsCancel; node = module.GetNxtCnfType(runConf, NULL, eMOD_IN); while (node != NULL) { if (node->canRun) { bNeedsCancel = (node->pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination) == RS_RET_OK) ? 0 : 1; DBGPRINTF("running module %s with config %p, term mode: %s\n", node->pMod->pszName, node, bNeedsCancel ? "cancel" : "cooperative/SIGTTIN"); thrdCreate(node->pMod->mod.im.runInput, node->pMod->mod.im.afterRun, bNeedsCancel, (node->pMod->cnfName == NULL) ? node->pMod->pszName : node->pMod->cnfName); } node = module.GetNxtCnfType(runConf, node, eMOD_IN); } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* Make the modules check if they are ready to start. */ static rsRetVal startInputModules(void) { DEFiRet; cfgmodules_etry_t *node; node = module.GetNxtCnfType(runConf, NULL, eMOD_IN); while (node != NULL) { if (node->canActivate) { iRet = node->pMod->mod.im.willRun(); node->canRun = (iRet == RS_RET_OK); if (!node->canRun) { DBGPRINTF("module %s will not run, iRet %d\n", node->pMod->pszName, iRet); } } else { node->canRun = 0; } node = module.GetNxtCnfType(runConf, node, eMOD_IN); } return RS_RET_OK; /* intentional: we do not care about module errors */ } /* load the main queue */ static rsRetVal loadMainQueue(void) { DEFiRet; struct cnfobj *mainqCnfObj; mainqCnfObj = glbl.GetmainqCnfObj(); DBGPRINTF("loadMainQueue: mainq cnf obj ptr is %p\n", mainqCnfObj); /* create message queue */ iRet = createMainQueue(&loadConf->pMsgQueue, UCHAR_CONSTANT("main Q"), (mainqCnfObj == NULL) ? NULL : mainqCnfObj->nvlst); if (iRet == RS_RET_OK) { if (runConf != NULL) { /* dynamic config reload */ int areEqual = queuesEqual(loadConf->pMsgQueue, runConf->pMsgQueue); DBGPRINTF("Comparison of old and new main queues: %d\n", areEqual); if (areEqual) { /* content of the new main queue is the same as it was in previous conf */ qqueueDestruct(&loadConf->pMsgQueue); loadConf->pMsgQueue = runConf->pMsgQueue; } } } if (iRet != RS_RET_OK) { /* no queue is fatal, we need to give up in that case... */ fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet); FINALIZE; } finalize_it: glblDestructMainqCnfObj(); RETiRet; } /* activate the main queue */ static rsRetVal activateMainQueue(void) { DEFiRet; DBGPRINTF("activateMainQueue: will try to activate main queue %p\n", runConf->pMsgQueue); iRet = startMainQueue(runConf, runConf->pMsgQueue); if (iRet != RS_RET_OK) { /* no queue is fatal, we need to give up in that case... */ fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet); FINALIZE; } if (runConf->globals.mainQ.MainMsgQueType == QUEUETYPE_DIRECT) { PREFER_STORE_0_TO_INT(&bHaveMainQueue); } else { PREFER_STORE_1_TO_INT(&bHaveMainQueue); } DBGPRINTF("Main processing queue is initialized and running\n"); finalize_it: RETiRet; } /* set the processes umask (upon configuration request) */ static inline rsRetVal setUmask(int iUmask) { if (iUmask != -1) { umask(iUmask); DBGPRINTF("umask set to 0%3.3o.\n", iUmask); } return RS_RET_OK; } /* Remove resources from previous config */ static void cleanupOldCnf(rsconf_t *cnf) { if (cnf == NULL) FINALIZE; if (runConf->pMsgQueue != cnf->pMsgQueue) qqueueDestruct(&cnf->pMsgQueue); finalize_it: return; } /* Activate an already-loaded configuration. The configuration will become * the new running conf (if successful). Note that in theory this method may * be called when there already is a running conf. In practice, the current * version of rsyslog does not support this. Future versions probably will. * Begun 2011-04-20, rgerhards */ static rsRetVal activate(rsconf_t *cnf) { DEFiRet; rsconf_t *runCnfOld = runConf; /* at this point, we "switch" over to the running conf */ runConf = cnf; loadConf = NULL; #if 0 /* currently the DAG is not supported -- code missing! */ /* TODO: re-enable this functionality some time later! */ /* check if we need to generate a config DAG and, if so, do that */ if(ourConf->globals.pszConfDAGFile != NULL) generateConfigDAG(ourConf->globals.pszConfDAGFile); #endif setUmask(cnf->globals.umask); if (cnf->globals.iMaxOpenFiles > 0) { CHKiRet(glblSetMaxOpenFiles(NULL, cnf->globals.iMaxOpenFiles)); } /* the output part and the queue is now ready to run. So it is a good time * to initialize the inputs. Please note that the net code above should be * shuffled to down here once we have everything in input modules. * rgerhards, 2007-12-14 * NOTE: as of 2009-06-29, the input modules are initialized, but not yet run. * Keep in mind. though, that the outputs already run if the queue was * persisted to disk. -- rgerhards */ tellModulesActivateConfigPrePrivDrop(); CHKiRet(dropPrivileges(cnf)); lookupActivateConf(); tellModulesActivateConfig(); startInputModules(); CHKiRet(activateActions()); CHKiRet(activateRulesetQueues()); CHKiRet(activateMainQueue()); /* finally let the inputs run... */ runInputModules(); qqueueDoneLoadCnf(); /* we no longer need config-load-only data structures */ dbgprintf("configuration %p activated\n", cnf); cleanupOldCnf(runCnfOld); finalize_it: RETiRet; } /* -------------------- some legacy config handlers -------------------- * TODO: move to conf.c? */ /* legacy config system: set the action resume interval */ static rsRetVal setActionResumeInterval(void __attribute__((unused)) * pVal, int iNewVal) { return actionSetGlobalResumeInterval(iNewVal); } /* set the processes max number of files immediately for legacy $MaxOpenFiles * configs. */ static rsRetVal setMaxFiles(void *pVal, int iFiles) { return glblSetMaxOpenFiles(pVal, iFiles); } /* Switch the default ruleset (that, what servcies bind to if nothing specific * is specified). * rgerhards, 2009-06-12 */ static rsRetVal setDefaultRuleset(void __attribute__((unused)) * pVal, uchar *pszName) { DEFiRet; CHKiRet(ruleset.SetDefaultRuleset(ourConf, pszName)); finalize_it: free(pszName); /* no longer needed */ RETiRet; } /* Switch to either an already existing rule set or start a new one. The * named rule set becomes the new "current" rule set (what means that new * actions are added to it). * rgerhards, 2009-06-12 */ static rsRetVal setCurrRuleset(void __attribute__((unused)) * pVal, uchar *pszName) { ruleset_t *pRuleset; rsRetVal localRet; DEFiRet; localRet = ruleset.SetCurrRuleset(ourConf, pszName); if (localRet == RS_RET_NOT_FOUND) { DBGPRINTF("begin new current rule set '%s'\n", pszName); CHKiRet(ruleset.Construct(&pRuleset)); CHKiRet(ruleset.SetName(pRuleset, pszName)); CHKiRet(ruleset.ConstructFinalize(ourConf, pRuleset)); rulesetSetCurrRulesetPtr(pRuleset); } else { ABORT_FINALIZE(localRet); } finalize_it: free(pszName); /* no longer needed */ RETiRet; } /* set the main message queue mode * rgerhards, 2008-01-03 */ static rsRetVal setMainMsgQueType(void __attribute__((unused)) * pVal, uchar *pszType) { DEFiRet; if (!strcasecmp((char *)pszType, "fixedarray")) { loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY; DBGPRINTF("main message queue type set to FIXED_ARRAY\n"); } else if (!strcasecmp((char *)pszType, "linkedlist")) { loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_LINKEDLIST; DBGPRINTF("main message queue type set to LINKEDLIST\n"); } else if (!strcasecmp((char *)pszType, "disk")) { loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DISK; DBGPRINTF("main message queue type set to DISK\n"); } else if (!strcasecmp((char *)pszType, "segmenteddisk")) { loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_SEGMENTED_DISK; DBGPRINTF("main message queue type set to SEGMENTED_DISK\n"); } else if (!strcasecmp((char *)pszType, "direct")) { loadConf->globals.mainQ.MainMsgQueType = QUEUETYPE_DIRECT; DBGPRINTF("main message queue type set to DIRECT (no queueing at all)\n"); } else { LogError(0, RS_RET_INVALID_PARAMS, "unknown mainmessagequeuetype parameter: %s", (char *)pszType); iRet = RS_RET_INVALID_PARAMS; } free(pszType); /* no longer needed */ RETiRet; } /* -------------------- end legacy config handlers -------------------- */ /* legacy config system: reset config variables to default values. */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { free(loadConf->globals.mainQ.pszMainMsgQFName); freeActionNames(loadConf); cnfSetDefaults(loadConf); return RS_RET_OK; } /* legacy config system: set the action resume interval */ static rsRetVal setModDir(void __attribute__((unused)) * pVal, uchar *pszNewVal) { DEFiRet; iRet = module.SetModDir(pszNewVal); free(pszNewVal); RETiRet; } /* "load" a build in module and register it for the current load config */ static rsRetVal regBuildInModule(rsRetVal (*modInit)(), uchar *name, void *pModHdlr) { cfgmodules_etry_t *pNew; cfgmodules_etry_t *pLast; modInfo_t *pMod; DEFiRet; CHKiRet(module.doModInit(modInit, name, pModHdlr, &pMod)); readyModForCnf(pMod, &pNew, &pLast); addModToCnfList(&pNew, pLast); finalize_it: RETiRet; } /* load build-in modules * very first version begun on 2007-07-23 by rgerhards */ static rsRetVal loadBuildInModules(void) { DEFiRet; CHKiRet(regBuildInModule(modInitFile, UCHAR_CONSTANT("builtin:omfile"), NULL)); CHKiRet(regBuildInModule(modInitPipe, UCHAR_CONSTANT("builtin:ompipe"), NULL)); CHKiRet(regBuildInModule(modInitShell, UCHAR_CONSTANT("builtin-shell"), NULL)); CHKiRet(regBuildInModule(modInitDiscard, UCHAR_CONSTANT("builtin:omdiscard"), NULL)); #ifdef SYSLOG_INET CHKiRet(regBuildInModule(modInitFwd, UCHAR_CONSTANT("builtin:omfwd"), NULL)); #endif /* dirty, but this must be for the time being: the usrmsg module must always be * loaded as last module. This is because it processes any type of action selector. * If we load it before other modules, these others will never have a chance of * working with the config file. We may change that implementation so that a user name * must start with an alnum, that would definitely help (but would it break backwards * compatibility?). * rgerhards, 2007-07-23 * User names now must begin with: * [a-zA-Z0-9_.] */ CHKiRet(regBuildInModule(modInitUsrMsg, (uchar *)"builtin:omusrmsg", NULL)); /* load build-in parser modules */ CHKiRet(regBuildInModule(modInitpmrfc5424, UCHAR_CONSTANT("builtin:pmrfc5424"), NULL)); CHKiRet(regBuildInModule(modInitpmrfc3164, UCHAR_CONSTANT("builtin:pmrfc3164"), NULL)); /* and set default parser modules. Order is *very* important, legacy * (3164) parser needs to go last! */ CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc5424"))); CHKiRet(parser.AddDfltParser(UCHAR_CONSTANT("rsyslog.rfc3164"))); /* load build-in strgen modules */ CHKiRet(regBuildInModule(modInitsmfile, UCHAR_CONSTANT("builtin:smfile"), NULL)); CHKiRet(regBuildInModule(modInitsmtradfile, UCHAR_CONSTANT("builtin:smtradfile"), NULL)); CHKiRet(regBuildInModule(modInitsmfwd, UCHAR_CONSTANT("builtin:smfwd"), NULL)); CHKiRet(regBuildInModule(modInitsmtradfwd, UCHAR_CONSTANT("builtin:smtradfwd"), NULL)); finalize_it: if (iRet != RS_RET_OK) { /* we need to do fprintf, as we do not yet have an error reporting system * in place. */ fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n", iRet); } RETiRet; } /* initialize the legacy config system */ static rsRetVal initLegacyConf(void) { DEFiRet; uchar *pTmp; ruleset_t *pRuleset; DBGPRINTF("doing legacy config system init\n"); /* construct the default ruleset */ ruleset.Construct(&pRuleset); ruleset.SetName(pRuleset, UCHAR_CONSTANT("RSYSLOG_DefaultRuleset")); ruleset.ConstructFinalize(loadConf, pRuleset); rulesetSetCurrRulesetPtr(pRuleset); /* now register config handlers */ CHKiRet(regCfSysLineHdlr((uchar *)"sleep", 0, eCmdHdlrGoneAway, NULL, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"logrsyslogstatusmessages", 0, eCmdHdlrBinary, NULL, &loadConf->globals.bLogStatusMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"errormessagestostderr", 0, eCmdHdlrBinary, NULL, &loadConf->globals.bErrMsgToStderr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"abortonuncleanconfig", 0, eCmdHdlrBinary, NULL, &loadConf->globals.bAbortOnUncleanConfig, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &loadConf->globals.bReduceRepeatMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &(loadConf->globals.bDebugPrintTemplateList), NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &(loadConf->globals.bDebugPrintModuleList), NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary, NULL, &(loadConf->globals.bDebugPrintCfSysLineHandlerList), NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouser", 0, eCmdHdlrUID, NULL, &loadConf->globals.uidDropPriv, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"privdroptouserid", 0, eCmdHdlrInt, NULL, &loadConf->globals.uidDropPriv, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroup", 0, eCmdHdlrGID, NULL, &loadConf->globals.gidDropPriv, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"privdroptogroupid", 0, eCmdHdlrInt, NULL, &loadConf->globals.gidDropPriv, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"generateconfiggraph", 0, eCmdHdlrGetWord, NULL, &loadConf->globals.pszConfDAGFile, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, NULL, &loadConf->globals.umask, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"maxopenfiles", 0, eCmdHdlrInt, setMaxFiles, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, conf.doModLoad, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"defaultruleset", 0, eCmdHdlrGetWord, setDefaultRuleset, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"ruleset", 0, eCmdHdlrGetWord, setCurrRuleset, NULL, NULL)); /* handler for "larger" config statements (tie into legacy conf system) */ CHKiRet( regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void *)DIR_TEMPLATE, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void *)DIR_OUTCHANNEL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void *)DIR_ALLOWEDSENDER, NULL)); /* the following are parameters for the main message queue. I have the * strong feeling that this needs to go to a different space, but that * feeling may be wrong - we'll see how things evolve. * rgerhards, 2011-04-21 */ CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &loadConf->globals.mainQ.pszMainMsgQFName, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQueueSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQHighWtrMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQLowWtrMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQDiscardMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity, NULL, &loadConf->globals.mainQ.iMainMsgQDiscardSeverity, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQPersistUpdCnt, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesyncqueuefiles", 0, eCmdHdlrBinary, NULL, &loadConf->globals.mainQ.bMainMsgQSyncQeueFiles, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord, setMainMsgQueType, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrPositiveInt, NULL, &loadConf->globals.mainQ.iMainMsgQueueNumWorkers, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQtoQShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQtoActShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQtoEnq, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQtoWrkShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQDeqSlowdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQWrkMinMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &loadConf->globals.mainQ.iMainMsgQueMaxFileSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuebatchsize", 0, eCmdHdlrSize, NULL, &loadConf->globals.mainQ.iMainMsgQueDeqBatchSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &loadConf->globals.mainQ.iMainMsgQueMaxDiskSpace, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &loadConf->globals.mainQ.bMainMsgQSaveOnShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinFromHr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &loadConf->globals.mainQ.iMainMsgQueueDeqtWinToHr, NULL)); /* moddir is a bit hard problem -- because it actually needs to * modify a setting that is specific to module.c. The important point * is that this action MUST actually be carried out during config load, * because we must load modules in order to get their config extensions * (no way around). * TODO: think about a clean solution */ CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord, setModDir, NULL, NULL)); /* finally, the reset handler */ CHKiRet( regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); /* initialize the build-in templates */ pTmp = template_DebugFormat; tplAddLine(ourConf, "RSYSLOG_DebugFormat", &pTmp); pTmp = template_SyslogProtocol23Format; tplAddLine(ourConf, "RSYSLOG_SyslogProtocol23Format", &pTmp); pTmp = template_SyslogRFC5424Format; tplAddLine(ourConf, "RSYSLOG_SyslogRFC5424Format", &pTmp); pTmp = template_FileFormat; /* new format for files with high-precision stamp */ tplAddLine(ourConf, "RSYSLOG_FileFormat", &pTmp); pTmp = template_TraditionalFileFormat; tplAddLine(ourConf, "RSYSLOG_TraditionalFileFormat", &pTmp); pTmp = template_WallFmt; tplAddLine(ourConf, " WallFmt", &pTmp); pTmp = template_ForwardFormat; tplAddLine(ourConf, "RSYSLOG_ForwardFormat", &pTmp); pTmp = template_TraditionalForwardFormat; tplAddLine(ourConf, "RSYSLOG_TraditionalForwardFormat", &pTmp); pTmp = template_StdUsrMsgFmt; tplAddLine(ourConf, " StdUsrMsgFmt", &pTmp); pTmp = template_StdDBFmt; tplAddLine(ourConf, " StdDBFmt", &pTmp); pTmp = template_SysklogdFileFormat; tplAddLine(ourConf, "RSYSLOG_SysklogdFileFormat", &pTmp); pTmp = template_StdPgSQLFmt; tplAddLine(ourConf, " StdPgSQLFmt", &pTmp); pTmp = template_StdJSONFmt; tplAddLine(ourConf, " StdJSONFmt", &pTmp); pTmp = template_FullJSONFmt; tplAddLine(ourConf, " FullJSONFmt", &pTmp); pTmp = template_StdClickHouseFmt; tplAddLine(ourConf, " StdClickHouseFmt", &pTmp); pTmp = template_StdOmSenderTrack_senderid; tplAddLine(ourConf, " StdOmSenderTrack-senderid", &pTmp); pTmp = template_PerSourceKey; tplAddLine(ourConf, "RSYSLOG_PerSourceKey", &pTmp); pTmp = template_spoofadr; tplLastStaticInit(ourConf, tplAddLine(ourConf, "RSYSLOG_omudpspoofDfltSourceTpl", &pTmp)); finalize_it: RETiRet; } /* validate the configuration pointed by conf, generate error messages, do * optimizations, etc, etc,... */ static rsRetVal validateConf(rsconf_t *cnf) { DEFiRet; /* some checks */ if (cnf->globals.mainQ.iMainMsgQueueNumWorkers < 1) { LogError(0, NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n"); cnf->globals.mainQ.iMainMsgQueueNumWorkers = 1; } if (cnf->globals.mainQ.MainMsgQueType == QUEUETYPE_SEGMENTED_DISK) { if (glbl.GetWorkDir(cnf) == NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "No $WorkDirectory specified - can not run main " "message queue in segmentedDisk mode.\n"); return RS_RET_CONF_PARAM_INVLD; } if (cnf->globals.mainQ.pszMainMsgQFName == NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "No $MainMsgQueueFileName specified - can not run main " "message queue in segmentedDisk mode.\n"); return RS_RET_CONF_PARAM_INVLD; } } else if (cnf->globals.mainQ.MainMsgQueType == QUEUETYPE_DISK) { errno = 0; /* for logerror! */ if (glbl.GetWorkDir(cnf) == NULL) { LogError(0, NO_ERRCODE, "No $WorkDirectory specified - can not run main " "message queue in disk-backed mode. Using 'FixedArray' instead.\n"); cnf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY; } if (cnf->globals.mainQ.pszMainMsgQFName == NULL) { LogError(0, NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main " "message queue in disk-backed mode. Using 'FixedArray' instead.\n"); cnf->globals.mainQ.MainMsgQueType = QUEUETYPE_FIXED_ARRAY; } } RETiRet; } /* Load a configuration. This will do all necessary steps to create * the in-memory representation of the configuration, including support * for multiple configuration languages. * Note that to support the legacy language we must provide some global * object that holds the currently-being-loaded config ptr. * Begun 2011-04-20, rgerhards */ static rsRetVal load(rsconf_t **cnf, uchar *confFile) { int iNbrActions = 0; int r; rsRetVal delayed_iRet = RS_RET_OK; DEFiRet; CHKiRet(rsconfConstruct(&loadConf)); ourConf = loadConf; // TODO: remove, once ourConf is gone! CHKiRet(loadBuildInModules()); CHKiRet(initLegacyConf()); /* open the configuration file; route .yaml/.yml to the YAML loader */ { const char *ext = strrchr((const char *)confFile, '.'); int is_yaml = (ext != NULL && (!strcmp(ext, ".yaml") || !strcmp(ext, ".yml"))); #ifdef HAVE_LIBYAML if (is_yaml) { rsRetVal yr = yamlconf_load((const char *)confFile); if (yr == RS_RET_OK) { r = 0; } else if (yr == RS_RET_CONF_FILE_NOT_FOUND) { r = 2; } else { r = 1; } /* Flush any inline RainerScript script: blocks that were queued * into the flex buffer stack by cnfAddConfigBuffer(). */ if (r == 0 && cnfHasPendingBuffers()) { r = yyparse(); } } else { #endif r = cnfSetLexFile((char *)confFile); if (r == 0) r = yyparse(); #ifdef HAVE_LIBYAML } #else if (is_yaml) { LogError(0, RS_RET_ERR, "YAML config file '%s' requested but rsyslog was built " "without libyaml support (install libyaml-dev and " "recompile)", confFile); r = 1; } #endif if (r == 0) conf.GetNbrActActions(loadConf, &iNbrActions); } /* we run the optimizer even if we have an error, as it may spit out * additional error messages and we want to see these even if we abort. */ rulesetOptimizeAll(loadConf); if (r == 1) { LogError(0, RS_RET_CONF_PARSE_ERROR, "could not interpret master " "config file '%s'.", confFile); /* we usually keep running with the failure, so we need to continue for now */ delayed_iRet = RS_RET_CONF_PARSE_ERROR; } else if (r == 2) { /* file not found? */ LogError(errno, RS_RET_CONF_FILE_NOT_FOUND, "could not open config file '%s'", confFile); ABORT_FINALIZE(RS_RET_CONF_FILE_NOT_FOUND); } else if ((iNbrActions == 0) && !(iConfigVerify & CONF_VERIFY_PARTIAL_CONF)) { LogError(0, RS_RET_NO_ACTIONS, "there are no active actions configured. " "Inputs would run, but no output whatsoever were created."); ABORT_FINALIZE(RS_RET_NO_ACTIONS); } tellLexEndParsing(); DBGPRINTF("Number of actions in this configuration: %d\n", loadConf->actions.iActionNbr); CHKiRet(tellCoreConfigLoadDone()); tellModulesConfigLoadDone(); tellModulesCheckConfig(); CHKiRet(checkParserInstances()); CHKiRet(validateConf(loadConf)); CHKiRet(loadMainQueue()); if (iConfigVerify && !rsconfTranslateEnabled()) { if (iRet == RS_RET_OK) iRet = RS_RET_VALIDATION_RUN; FINALIZE; } /* all OK, pass loaded conf to caller */ *cnf = loadConf; /* Keep loadConf valid until activation. If the config system is ever * extended beyond a single in-flight load and explicit config context is * threaded through all load-time helpers, reconsider clearing it here. */ dbgprintf("rsyslog finished loading master config %p\n", loadConf); rsconfDebugPrint(loadConf); finalize_it: if (iRet == RS_RET_OK && delayed_iRet != RS_RET_OK) { iRet = delayed_iRet; } RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(rsconf) CODESTARTobjQueryInterface(rsconf); if (pIf->ifVersion != rsconfCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Destruct = rsconfDestruct; pIf->DebugPrint = rsconfDebugPrint; pIf->Load = load; pIf->Activate = activate; finalize_it: ENDobjQueryInterface(rsconf) /* Initialize the rsconf class. Must be called as the very first method * before anything else is called inside this class. */ BEGINObjClassInit(rsconf, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(conf, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); /* now set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, rsconfDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, rsconfConstructFinalize); ENDObjClassInit(rsconf) /* De-initialize the rsconf class. */ BEGINObjClassExit(rsconf, OBJ_IS_CORE_MODULE) /* class, version */ objRelease(ruleset, CORE_COMPONENT); objRelease(module, CORE_COMPONENT); objRelease(conf, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); ENDObjClassExit(rsconf) rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_store.h0000644000000000000000000000013215241075234017243 xustar0030 mtime=1787067036.610578388 30 atime=1787067036.681579717 30 ctime=1787067794.422725577 rsyslog-8.2608.0/runtime/segdisk_store.h0000664000175000017500000001041615241075234016711 0ustar00rgerrger/* Log-structured serial store for queue.type="segmentedDisk". */ #ifndef INCLUDED_SEGDISK_STORE_H #define INCLUDED_SEGDISK_STORE_H #include #include #include "rsyslog.h" #include "batch.h" /** Opaque segmented queue store. All access is serialized by its queue lock. */ typedef struct segdisk_store_s segdisk_store_t; /** Configuration captured when a segmented store object is constructed. * * lazy_create keeps a DA child unmaterialized until its first append. It does * not change the eager lifecycle of a pure segmentedDisk queue. */ typedef struct segdisk_store_config_s { const char *work_dir; const char *file_prefix; const char *queue_name; int64_t max_file_size; int64_t max_disk_space; unsigned int checkpoint_interval; sbool sync_files; sbool lazy_create; } segdisk_store_config_t; /** Monotonic operation counters and current physical store gauges. * * bytes and segments describe the current topology. The remaining fields are * cumulative counters, including lazy materialization and idle-cleanup * outcomes; startup_payload_bytes_read is expected to remain zero. */ typedef struct segdisk_store_stats_s { int64_t bytes; int segments; uint64_t checkpoints; uint64_t replayed; uint64_t corruption_events; uint64_t corruption_bytes; uint64_t corruption_records; int64_t retry_overage_bytes; int64_t retry_overage_max_bytes; uint64_t state_writes; uint64_t forced_state_writes; uint64_t recovery_bytes; uint64_t recovery_records; uint64_t startup_payload_bytes_read; uint64_t startup_segment_files_probed; uint64_t recovery_pending; uint64_t corruption_segments; uint64_t materializations; uint64_t dematerializations; uint64_t idle_cleanup_failures; } segdisk_store_stats_t; #ifdef ENABLE_IMDIAG typedef enum segdisk_test_fault_point_e { SEGDISK_TEST_FAULT_NONE = 0, SEGDISK_TEST_FAULT_RESERVATION_PUBLISHED, SEGDISK_TEST_FAULT_SEGMENT_CREATED, SEGDISK_TEST_FAULT_SEAL_WRITTEN, SEGDISK_TEST_FAULT_SEAL_RENAMED, SEGDISK_TEST_FAULT_CHECKPOINT_PUBLISHED, SEGDISK_TEST_FAULT_COMMIT_PUBLISHED, SEGDISK_TEST_FAULT_PREDELETE_PUBLISHED, SEGDISK_TEST_FAULT_SEGMENT_UNLINKED, SEGDISK_TEST_FAULT_IDLE_EMPTY_PUBLISHED, SEGDISK_TEST_FAULT_IDLE_SEGMENTS_UNLINKED, SEGDISK_TEST_FAULT_IDLE_STATE_UNLINKED, SEGDISK_TEST_FAULT_IDLE_DIRECTORY_REMOVED, } segdisk_test_fault_point_t; #endif /** * Concurrency & Locking * --------------------- * Every function below is called with the owning queue mutex held. The same * mutex is shared by a DA parent and its child, so no store function acquires * an independent lifecycle lock. Append serializes synchronously and retains * no message reference. A dequeued batch retains internal completion state * until CompleteBatch commits or retry-appends every element. * * Dematerialize is destructive and succeeds only when CanDematerialize proves * there is no known data, undiscovered recovery work, pending batch, retry, * completion, or deletion. Failure leaves a materialized recoverable store. * Close destroys the object; Dematerialize resets the same object for a later * lazy append. GetStats and test-fault operations are safe before lazy * materialization. */ rsRetVal segdiskStoreOpen(segdisk_store_t **store, const segdisk_store_config_t *config, int *queue_size); rsRetVal segdiskStoreAppend(segdisk_store_t *store, smsg_t *msg, sbool internal_retry, int64_t *written); rsRetVal segdiskStoreDequeueBatch(segdisk_store_t *store, batch_t *batch, int max, int *skipped, int *discovered); rsRetVal segdiskStoreCompleteBatch(segdisk_store_t *store, batch_t *batch, int *committed, int *retried); rsRetVal segdiskStoreCheckpoint(segdisk_store_t *store, sbool force_sync); rsRetVal segdiskStoreDematerialize(segdisk_store_t *store); rsRetVal segdiskStoreClose(segdisk_store_t **store, sbool empty); void segdiskStoreGetStats(const segdisk_store_t *store, segdisk_store_stats_t *stats); sbool segdiskStoreMayHaveData(const segdisk_store_t *store); sbool segdiskStoreCanDematerialize(const segdisk_store_t *store); #ifdef ENABLE_IMDIAG rsRetVal segdiskStoreSetTestFault(segdisk_store_t *store, const char *point, unsigned int hit_count); void segdiskStoreClearTestFault(segdisk_store_t *store); #endif #endif rsyslog-8.2608.0/runtime/PaxHeaders/zlibw.c0000644000000000000000000000013215171370365015525 xustar0030 mtime=1776677109.451913233 30 atime=1787067618.032437677 30 ctime=1787067794.609729061 rsyslog-8.2608.0/runtime/zlibw.c0000664000175000017500000001757415171370365015207 0ustar00rgerrger/* The zlibwrap object. * * This is an rsyslog object wrapper around zlib. * * Copyright 2009-2022 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "stream.h" #include "zlibw.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; /* ------------------------------ methods ------------------------------ */ /* zlib make strong use of macros for its interface functions, so we can not simply * pass function pointers to them. Instead, we create very small wrappers which call * the relevant entry points. */ static int myDeflateInit(z_streamp strm, int level) { return deflateInit(strm, level); } static int myDeflateInit2(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy) { return deflateInit2(strm, level, method, windowBits, memLevel, strategy); } static int myDeflateEnd(z_streamp strm) { return deflateEnd(strm); } static int myDeflate(z_streamp strm, int flush) { return deflate(strm, flush); } /* finish zlib buffer */ static rsRetVal doCompressFinish(strm_t *pThis, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)) { int zRet; /* zlib return state */ DEFiRet; unsigned outavail; assert(pThis != NULL); assert(pThis->compressionDriver == STRM_COMPRESS_ZIP); if (!pThis->bzInitDone) goto done; pThis->zstrm.avail_in = 0; /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld\n", pThis->zstrm.avail_in, pThis->zstrm.total_in); pThis->zstrm.avail_out = pThis->sIOBufSize; pThis->zstrm.next_out = pThis->pZipBuf; zRet = deflate(&pThis->zstrm, Z_FINISH); /* no bad return value */ DBGPRINTF("after deflate, ret %d, avail_out %d\n", zRet, pThis->zstrm.avail_out); outavail = pThis->sIOBufSize - pThis->zstrm.avail_out; if (outavail != 0) { CHKiRet(strmPhysWrite(pThis, (uchar *)pThis->pZipBuf, outavail)); } } while (pThis->zstrm.avail_out == 0); finalize_it: zRet = deflateEnd(&pThis->zstrm); if (zRet != Z_OK) { LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/deflateEnd()", zRet); } pThis->bzInitDone = 0; done: RETiRet; } /* write the output buffer in zip mode * This means we compress it first and then do a physical write. * Note that we always do a full deflateInit ... deflate ... deflateEnd * sequence. While this is not optimal, we need to do it because we need * to ensure that the file is readable even when we are aborted. Doing the * full sequence brings us as far towards this goal as possible (and not * doing it would be a total failure). It may be worth considering to * add a config switch so that the user can decide the risk he is ready * to take, but so far this is not yet implemented (not even requested ;)). * rgerhards, 2009-06-04 */ static rsRetVal doStrmWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlush, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)) { int zRet; /* zlib return state */ DEFiRet; unsigned outavail = 0; assert(pThis != NULL); assert(pBuf != NULL); assert(pThis->compressionDriver == STRM_COMPRESS_ZIP); if (!pThis->bzInitDone) { /* allocate deflate state */ pThis->zstrm.zalloc = Z_NULL; pThis->zstrm.zfree = Z_NULL; pThis->zstrm.opaque = Z_NULL; /* see note in file header for the params we use with deflateInit2() */ zRet = deflateInit2(&pThis->zstrm, pThis->iZipLevel, Z_DEFLATED, 31, 9, Z_DEFAULT_STRATEGY); if (zRet != Z_OK) { LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/deflateInit2()", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pThis->bzInitDone = RSTRUE; } /* now doing the compression */ pThis->zstrm.next_in = (Bytef *)pBuf; pThis->zstrm.avail_in = lenBuf; /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("in deflate() loop, avail_in %d, total_in %ld, bFlush %d\n", pThis->zstrm.avail_in, pThis->zstrm.total_in, bFlush); pThis->zstrm.avail_out = pThis->sIOBufSize; pThis->zstrm.next_out = pThis->pZipBuf; zRet = deflate(&pThis->zstrm, bFlush ? Z_SYNC_FLUSH : Z_NO_FLUSH); /* no bad return value */ DBGPRINTF("after deflate, ret %d, avail_out %d, to write %d\n", zRet, pThis->zstrm.avail_out, outavail); if (zRet != Z_OK) { LogError(0, RS_RET_ZLIB_ERR, "error %d returned from zlib/Deflate()", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } outavail = pThis->sIOBufSize - pThis->zstrm.avail_out; if (outavail != 0) { CHKiRet(strmPhysWrite(pThis, (uchar *)pThis->pZipBuf, outavail)); } } while (pThis->zstrm.avail_out == 0); finalize_it: if (pThis->bzInitDone && pThis->bVeryReliableZip) { doCompressFinish(pThis, strmPhysWrite); } RETiRet; } /* destruction of caller's zlib resources - a dummy for us */ static rsRetVal zlib_Destruct(ATTR_UNUSED strm_t *pThis) { return RS_RET_OK; } /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(zlibw) CODESTARTobjQueryInterface(zlibw); if (pIf->ifVersion != zlibwCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->DeflateInit = myDeflateInit; pIf->DeflateInit2 = myDeflateInit2; pIf->Deflate = myDeflate; pIf->DeflateEnd = myDeflateEnd; pIf->doStrmWrite = doStrmWrite; pIf->doCompressFinish = doCompressFinish; pIf->Destruct = zlib_Destruct; finalize_it: ENDobjQueryInterface(zlibw) /* Initialize the zlibw class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(zlibw, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ /* set our own handlers */ ENDObjClassInit(zlibw) /* Exit the class. */ BEGINObjClassExit(zlibw, OBJ_IS_LOADABLE_MODULE) /* class, version */ CODESTARTObjClassExit(zlibw); ENDObjClassExit(zlibw) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; zlibwClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CHKiRet(zlibwClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ /* Initialize all classes that are in our module - this includes ourselfs */ ENDmodInit /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/objomsr.c0000644000000000000000000000013215216464436016054 xustar0030 mtime=1782212894.036266346 30 atime=1787067617.871434675 30 ctime=1787067794.316723601 rsyslog-8.2608.0/runtime/objomsr.c0000664000175000017500000001050615216464436015522 0ustar00rgerrger/* objomsr.c * Implementation of the omsr (omodStringRequest) object. * * File begun on 2007-07-27 by RGerhards * * Copyright 2007-2012 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include "rsyslog.h" #include "objomsr.h" /* destructor */ rsRetVal OMSRdestruct(omodStringRequest_t *pThis) { int i; assert(pThis != NULL); /* free the strings */ if (pThis->ppTplName != NULL) { for (i = 0; i < pThis->iNumEntries; ++i) { free(pThis->ppTplName[i]); } free(pThis->ppTplName); } if (pThis->piTplOpts != NULL) free(pThis->piTplOpts); free(pThis); return RS_RET_OK; } /* constructor */ rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries) { omodStringRequest_t *pThis = NULL; DEFiRet; assert(ppThis != NULL); assert(iNumEntries >= 0); if (iNumEntries > CONF_OMOD_NUMSTRINGS_MAXSIZE) { ABORT_FINALIZE(RS_RET_MAX_OMSR_REACHED); } CHKmalloc(pThis = calloc(1, sizeof(omodStringRequest_t))); /* got the structure, so fill it */ if (iNumEntries > 0) { pThis->iNumEntries = iNumEntries; /* allocate string for template name array. The individual strings will be * allocated as the code progresses (we do not yet know the string sizes) */ CHKmalloc(pThis->ppTplName = calloc(iNumEntries, sizeof(uchar *))); /* allocate the template options array. */ CHKmalloc(pThis->piTplOpts = calloc(iNumEntries, sizeof(int))); } finalize_it: if (iRet != RS_RET_OK) { if (pThis != NULL) { OMSRdestruct(pThis); pThis = NULL; } } *ppThis = pThis; RETiRet; } /* set a template name and option to the object. Index must be given. The pTplName must be * pointing to memory that can be freed. If in doubt, the caller must strdup() the value. */ rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts) { assert(pThis != NULL); assert(iEntry < pThis->iNumEntries); if (pThis->ppTplName[iEntry] != NULL) free(pThis->ppTplName[iEntry]); pThis->ppTplName[iEntry] = pTplName; pThis->piTplOpts[iEntry] = iTplOpts; return RS_RET_OK; } /* get number of entries for this object */ int OMSRgetEntryCount(omodStringRequest_t *pThis) { assert(pThis != NULL); return pThis->iNumEntries; } /* return data for a specific entry. All data returned is * read-only and lasts only as long as the object lives. If the caller * needs it for an extended period of time, the caller must copy the * strings. Please note that the string pointer may be NULL, which is the * case when it was never set. */ int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts) { assert(pThis != NULL); assert(ppTplName != NULL); assert(piTplOpts != NULL); assert(iEntry < pThis->iNumEntries); *ppTplName = pThis->ppTplName[iEntry]; *piTplOpts = pThis->piTplOpts[iEntry]; return RS_RET_OK; } /* return the full set of template options that are supported by this version of * OMSR. They are returned in an unsigned long value. The caller can mask that * value to check on the option he is interested in. * Note that this interface was added in 4.1.6, so a plugin must obtain a pointer * to this interface via queryHostEtryPt(). * rgerhards, 2009-04-03 */ rsRetVal OMSRgetSupportedTplOpts(unsigned long *pOpts) { DEFiRet; assert(pOpts != NULL); *pOpts = OMSR_RQD_TPL_OPT_SQL | OMSR_TPL_AS_ARRAY | OMSR_TPL_AS_MSG | OMSR_TPL_AS_JSON | OMSR_TPL_AS_DYNAFILE; RETiRet; } /* vim:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/wtp.c0000644000000000000000000000013215241075234015203 xustar0030 mtime=1787067036.613578444 30 atime=1787067036.760581197 30 ctime=1787067794.386724906 rsyslog-8.2608.0/runtime/wtp.c0000664000175000017500000006176015241075234014661 0ustar00rgerrger/* wtp.c * * This file implements the worker thread pool (wtp) class. * * File begun on 2008-01-20 by RGerhards * * There is some in-depth documentation available in doc/dev_queue.html * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it * if you are getting acquainted to the object. * * Copyright 2008-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_PRCTL_H #include #endif #include "rsyslog.h" #include "stringbuf.h" #include "srUtils.h" #include "wtp.h" #include "wti.h" #include "obj.h" #include "unicode-helper.h" #include "glbl.h" #include "errmsg.h" /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) /* forward-definitions */ /* methods */ /* get the header for debug messages * The caller must NOT free or otherwise modify the returned string! */ static uchar *wtpGetDbgHdr(wtp_t *pThis) { ISOBJ_TYPE_assert(pThis, wtp); if (pThis->pszDbgHdr == NULL) return (uchar *)"wtp"; /* should not normally happen */ else return pThis->pszDbgHdr; } /* Not implemented dummy function for constructor */ static rsRetVal NotImplementedDummy_voidp_int(__attribute__((unused)) void *p1, __attribute__((unused)) int p2) { return RS_RET_NOT_IMPLEMENTED; } static rsRetVal NotImplementedDummy_voidp_intp(__attribute__((unused)) void *p1, __attribute__((unused)) int *p2) { return RS_RET_NOT_IMPLEMENTED; } static rsRetVal NotImplementedDummy_voidp_voidp(__attribute__((unused)) void *p1, __attribute__((unused)) void *p2) { return RS_RET_NOT_IMPLEMENTED; } static rsRetVal NotImplementedDummy_voidp_wti_tp(__attribute__((unused)) void *p1, __attribute__((unused)) wti_t *p2) { return RS_RET_NOT_IMPLEMENTED; } /* Standard-Constructor for the wtp object */ BEGINobjConstruct(wtp) /* be sure to specify the object type also in END macro! */ pThis->toFirstWrkShutdown = -2; pthread_mutex_init(&pThis->mutWtp, NULL); pthread_cond_init(&pThis->condThrdInitDone, NULL); pthread_cond_init(&pThis->condThrdTrm, NULL); pthread_attr_init(&pThis->attrThrd); /* Set thread scheduling policy to default */ #ifdef HAVE_PTHREAD_SETSCHEDPARAM pthread_attr_setschedpolicy(&pThis->attrThrd, default_thr_sched_policy); pthread_attr_setschedparam(&pThis->attrThrd, &default_sched_param); pthread_attr_setinheritsched(&pThis->attrThrd, PTHREAD_EXPLICIT_SCHED); #endif /* set all function pointers to "not implemented" dummy so that we can safely call them */ pThis->pfChkStopWrkr = (rsRetVal(*)(void *, int))NotImplementedDummy_voidp_int; pThis->pfGetDeqBatchSize = (rsRetVal(*)(void *, int *))NotImplementedDummy_voidp_intp; pThis->pfDoWork = (rsRetVal(*)(void *, void *))NotImplementedDummy_voidp_voidp; pThis->pfObjProcessed = (rsRetVal(*)(void *, wti_t *))NotImplementedDummy_voidp_wti_tp; INIT_ATOMIC_HELPER_MUT(pThis->mutCurNumWrkThrd); INIT_ATOMIC_HELPER_MUT(pThis->mutWtpState); ENDobjConstruct(wtp) /* Construction finalizer * rgerhards, 2008-01-17 */ rsRetVal wtpConstructFinalize(wtp_t *pThis) { DEFiRet; int i; uchar pszBuf[64]; size_t lenBuf; wti_t *pWti; ISOBJ_TYPE_assert(pThis, wtp); DBGPRINTF("%s: finalizing construction of worker thread pool (numworkerThreads %d)\n", wtpGetDbgHdr(pThis), pThis->iNumWorkerThreads); /* alloc and construct workers - this can only be done in finalizer as we previously do * not know the max number of workers */ CHKmalloc(pThis->pWrkr = malloc(sizeof(wti_t *) * pThis->iNumWorkerThreads)); for (i = 0; i < pThis->iNumWorkerThreads; ++i) { CHKiRet(wtiConstruct(&pThis->pWrkr[i])); pWti = pThis->pWrkr[i]; lenBuf = snprintf((char *)pszBuf, sizeof(pszBuf), "%.*s/w%d", (int)(sizeof(pszBuf) - 6), /* leave 6 chars for \0, "/w" and number: */ wtpGetDbgHdr(pThis), i); if (lenBuf >= sizeof(pszBuf)) { LogError(0, RS_RET_INTERNAL_ERROR, "%s:%d debug header too long: %zd - in " "thory this cannot happen - truncating", __FILE__, __LINE__, lenBuf); lenBuf = sizeof(pszBuf) - 1; pszBuf[lenBuf] = '\0'; } CHKiRet(wtiSetDbgHdr(pWti, pszBuf, lenBuf)); CHKiRet(wtiSetpWtp(pWti, pThis)); pWti->workerIndex = i; CHKiRet(wtiConstructFinalize(pWti)); } finalize_it: RETiRet; } /* Destructor */ BEGINobjDestruct(wtp) /* be sure to specify the object type also in END and CODESTART macros! */ int i; CODESTARTobjDestruct(wtp); d_pthread_mutex_lock(&pThis->mutWtp); /* make sure nobody is still using the mutex */ assert(pThis->iCurNumWrkThrd == 0); /* destruct workers */ for (i = 0; i < pThis->iNumWorkerThreads; ++i) wtiDestruct(&pThis->pWrkr[i]); free(pThis->pWrkr); pThis->pWrkr = NULL; /* actual destruction */ d_pthread_mutex_unlock(&pThis->mutWtp); pthread_cond_destroy(&pThis->condThrdTrm); pthread_cond_destroy(&pThis->condThrdInitDone); pthread_mutex_destroy(&pThis->mutWtp); pthread_attr_destroy(&pThis->attrThrd); DESTROY_ATOMIC_HELPER_MUT(pThis->mutCurNumWrkThrd); DESTROY_ATOMIC_HELPER_MUT(pThis->mutWtpState); free(pThis->pszDbgHdr); ENDobjDestruct(wtp) /* Set worker thread pool state. -- rgerhards, 2008-01-21 * * This function is called from multiple contexts: * 1. During shutdown (wtpShutdownAll, queue destructor) * 2. During persistence mode changes (queuePersist) * * IMPORTANT: Uses atomic store because worker threads read wtpState atomically * in wtpChkStopWrkr(). Mixing plain stores with atomic loads violates the C11 * memory model and creates undefined behavior. * * The atomic store ensures: * - Immediate visibility to all worker threads * - SHUTDOWN_IMMEDIATE is seen without delay * - Proper memory barriers on all architectures (including ARM) * * rgerhards, 2008-01-21 */ rsRetVal wtpSetState(wtp_t *pThis, wtpState_t iNewState) { ISOBJ_TYPE_assert(pThis, wtp); ATOMIC_STORE_32BIT((int *)&pThis->wtpState, &pThis->mutWtpState, iNewState); return RS_RET_OK; } /* join terminated worker threads */ static void ATTR_NONNULL() wtpJoinTerminatedWrkr(wtp_t *const pThis) { int i; for (i = 0; i < pThis->iNumWorkerThreads; ++i) { wtiJoinThrd(pThis->pWrkr[i]); } } /* check if the worker shall shutdown (1 = yes, 0 = no) * Note: there may be two mutexes locked, the bLockUsrMutex is the one in our "user" * (e.g. the queue clas) * rgerhards, 2008-01-21 */ rsRetVal wtpChkStopWrkr(wtp_t *pThis, int bLockUsrMutex) { DEFiRet; wtpState_t wtpState; ISOBJ_TYPE_assert(pThis, wtp); /* we need a consistent value, but it doesn't really matter if it is changed * right after the load - then we simply do one more iteration in the worker */ wtpState = (wtpState_t)ATOMIC_LOAD_32BIT((int *)&pThis->wtpState, &pThis->mutWtpState); if (wtpState == wtpState_SHUTDOWN_IMMEDIATE) { ABORT_FINALIZE(RS_RET_TERMINATE_NOW); } else if (wtpState == wtpState_SHUTDOWN) { ABORT_FINALIZE(RS_RET_TERMINATE_WHEN_IDLE); } /* try customer handler if one was set and we do not yet have a definite result */ if (pThis->pfChkStopWrkr != NULL) { iRet = pThis->pfChkStopWrkr(pThis->pUsr, bLockUsrMutex); } finalize_it: RETiRet; } PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wempty_body /* Send a shutdown command to all workers and see if they terminate. * A timeout may be specified. This function may also be called with * the current number of workers being 0, in which case it does not * shut down any worker. * rgerhards, 2008-01-14 */ rsRetVal ATTR_NONNULL() wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *ptTimeout) { DEFiRet; int bTimedOut; int i; ISOBJ_TYPE_assert(pThis, wtp); /* lock mutex to prevent races (may otherwise happen during idle processing and such...) */ d_pthread_mutex_lock(pThis->pmutUsr); wtpSetState(pThis, tShutdownCmd); /* awake workers in retry loop */ for (i = 0; i < pThis->iNumWorkerThreads; ++i) { wtpJoinTerminatedWrkr(pThis); pthread_cond_signal(&pThis->pWrkr[i]->pcondBusy); wtiWakeupThrd(pThis->pWrkr[i]); } d_pthread_mutex_unlock(pThis->pmutUsr); /* wait for worker thread termination */ d_pthread_mutex_lock(&pThis->mutWtp); pthread_cleanup_push(mutexCancelCleanup, &pThis->mutWtp); bTimedOut = 0; /* Use atomic read for consistency - iCurNumWrkThrd is updated atomically by * worker threads. Even though we hold mutWtp, workers update this counter * atomically, so we must read it atomically to ensure we see the latest value. */ while (ATOMIC_LOAD_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd) > 0 && !bTimedOut) { wtpJoinTerminatedWrkr(pThis); DBGPRINTF("%s: waiting %ldms on worker thread termination, %d still running\n", wtpGetDbgHdr(pThis), timeoutVal(ptTimeout), ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); if (d_pthread_cond_timedwait(&pThis->condThrdTrm, &pThis->mutWtp, ptTimeout) != 0) { DBGPRINTF("%s: timeout waiting on worker thread termination\n", wtpGetDbgHdr(pThis)); bTimedOut = 1; /* we exit the loop on timeout */ } /* awake workers in retry loop */ for (i = 0; i < pThis->iNumWorkerThreads; ++i) { wtiWakeupThrd(pThis->pWrkr[i]); } } /* The final worker can transition to WAIT_JOIN and decrement the active * count to zero just before the loop exits. Join it now so destructors see * the stable STOPPED state instead of a joinable terminated worker. */ wtpJoinTerminatedWrkr(pThis); pthread_cleanup_pop(1); if (bTimedOut) iRet = RS_RET_TIMED_OUT; RETiRet; } PRAGMA_DIAGNOSTIC_POP /* Unconditionally cancel all running worker threads. * rgerhards, 2008-01-14 */ rsRetVal ATTR_NONNULL() wtpCancelAll(wtp_t *pThis, const uchar *const cancelobj) { DEFiRet; int i; ISOBJ_TYPE_assert(pThis, wtp); /* go through all workers and cancel those that are active */ for (i = 0; i < pThis->iNumWorkerThreads; ++i) { wtiCancelThrd(pThis->pWrkr[i], cancelobj); } RETiRet; } /* this function contains shared code for both regular worker shutdown as * well as shutdown via cancellation. We can not simply use pthread_cleanup_pop(1) * as this introduces a race in the debug system (RETiRet system). * rgerhards, 2009-10-26 */ static void wtpWrkrExecCleanup(wti_t *pWti) { wtp_t *pThis; ISOBJ_TYPE_assert(pWti, wti); pThis = pWti->pWtp; ISOBJ_TYPE_assert(pThis, wtp); // TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: enter WrkrExecCleanup\n", wtiGetDbgHdr(pWti)); } /* the order of the next two statements is important! */ wtiSetState(pWti, WRKTHRD_WAIT_JOIN); ATOMIC_DEC(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); /* note: numWorkersNow is only for message generation, so we do not try * hard to get it 100% accurate (as curently done, it is not). */ const int numWorkersNow = ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); DBGPRINTF("%s: Worker thread %lx, terminated, num workers now %d\n", wtpGetDbgHdr(pThis), (unsigned long)pWti, numWorkersNow); if (numWorkersNow > 0) { // TODO: did the thread ID experiment (pthread_self) work out? rgerhards, 2024-07-25 LogMsg(0, RS_RET_OPERATION_STATUS, LOG_INFO, "%s: worker thread %lx (%" PRIuPTR ") terminated, now %d active worker threads", wtpGetDbgHdr(pThis), (unsigned long)pWti, (uintptr_t)pthread_self(), numWorkersNow); } } /* cancellation cleanup handler for executing worker decrements the worker counter. * rgerhards, 2009-07-20 */ static void wtpWrkrExecCancelCleanup(void *arg) { wti_t *pWti = (wti_t *)arg; wtp_t *pThis; ISOBJ_TYPE_assert(pWti, wti); pThis = pWti->pWtp; ISOBJ_TYPE_assert(pThis, wtp); DBGPRINTF("%s: Worker thread %lx requested to be cancelled.\n", wtpGetDbgHdr(pThis), (unsigned long)pWti); wtpWrkrExecCleanup(pWti); pthread_cond_broadcast(&pThis->condThrdTrm); /* activate anyone waiting on thread shutdown */ } /* wtp worker shell. This is started and calls into the actual * wti worker. * rgerhards, 2008-01-21 */ PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wempty_body static void *wtpWorker( void *arg) /* the arg is actually a wti object, even though we are in wtp! */ { wti_t *pWti = (wti_t *)arg; wtp_t *pThis; sigset_t sigSet; #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) uchar *pszDbgHdr; uchar thrdName[32] = "rs:"; #endif ISOBJ_TYPE_assert(pWti, wti); pThis = pWti->pWtp; ISOBJ_TYPE_assert(pThis, wtp); /* block all signals except SIGTTIN and SIGSEGV */ sigfillset(&sigSet); sigdelset(&sigSet, SIGTTIN); sigdelset(&sigSet, SIGSEGV); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); /* Avoid a startup race: cancellation can be requested very early during * shutdown. If that happens before our cleanup handler is registered, * the thread can exit without transitioning state to WAIT_JOIN. * Keep cancellation disabled until cleanup registration is complete. */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); pthread_cleanup_push(wtpWrkrExecCancelCleanup, pWti); #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) /* set thread name - we ignore if the call fails, has no harsh consequences... */ pszDbgHdr = wtpGetDbgHdr(pThis); ustrncpy(thrdName + 3, pszDbgHdr, 20); if (prctl(PR_SET_NAME, thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", wtpGetDbgHdr(pThis)); } dbgOutputTID((char *)thrdName); #endif // TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: worker %p started\n", wtpGetDbgHdr(pThis), pThis); } /* let the parent know we're done with initialization */ d_pthread_mutex_lock(&pThis->mutWtp); /* Startup invariant: once a worker is visible as RUNNING, cancellation * cleanup is already installed and will transition it to WAIT_JOIN. */ wtiSetState(pWti, WRKTHRD_RUNNING); pthread_cond_broadcast(&pThis->condThrdInitDone); d_pthread_mutex_unlock(&pThis->mutWtp); wtiWorker(pWti); pthread_cleanup_pop(0); d_pthread_mutex_lock(&pThis->mutWtp); pthread_cleanup_push(mutexCancelCleanup, &pThis->mutWtp); wtpWrkrExecCleanup(pWti); pthread_cond_broadcast(&pThis->condThrdTrm); /* activate anyone waiting on thread shutdown */ pthread_cleanup_pop(1); /* unlock mutex */ if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %p: worker exiting\n", pWti); } pthread_exit(0); return NULL; /* To suppress warning */ } PRAGMA_DIAGNOSTIC_POP /* start a new worker */ static rsRetVal ATTR_NONNULL() wtpStartWrkr(wtp_t *const pThis, const int permit_during_shutdown) { wti_t *pWti; int i; int iState; DEFiRet; ISOBJ_TYPE_assert(pThis, wtp); // TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards if (dbgTimeoutToStderr) { fprintf(stderr, "%s: worker start requested, num workers currently %d\n", wtpGetDbgHdr(pThis), ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); } d_pthread_mutex_lock(&pThis->mutWtp); /* Check state under mutex to prevent TOCTOU race where worker could be * created during shutdown. Must hold mutWtp to ensure state doesn't change * between check and worker creation. * * Note: An atomic read is required as wtpState is protected by its own * lock (mutWtpState). This lock on mutWtp ensures the check and * subsequent worker creation are an atomic unit, fixing the TOCTOU race. */ const wtpState_t wtpState = (wtpState_t)ATOMIC_LOAD_32BIT((int *)&pThis->wtpState, &pThis->mutWtpState); if (wtpState != wtpState_RUNNING && !permit_during_shutdown) { d_pthread_mutex_unlock(&pThis->mutWtp); DBGPRINTF("%s: worker start requested during shutdown - ignored\n", wtpGetDbgHdr(pThis)); if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: worker start requested during shutdown - ignored\n", wtpGetDbgHdr(pThis)); } return RS_RET_ERR; /* exceptional case, but really makes sense here! */ } wtpJoinTerminatedWrkr(pThis); /* find free spot in thread table. */ for (i = 0; i < pThis->iNumWorkerThreads; ++i) { if (wtiCASState(pThis->pWrkr[i], WRKTHRD_STOPPED, WRKTHRD_INITIALIZING) == RS_RET_OK) { break; } } if (i == pThis->iNumWorkerThreads) ABORT_FINALIZE(RS_RET_NO_MORE_THREADS); const sbool first_worker_runs_forever = i == 0 && (!pThis->bAllowFirstWorkerToTimeout || pThis->toFirstWrkShutdown == -1 || (pThis->toFirstWrkShutdown == -2 && pThis->toWrkShutdown == -1)); if (first_worker_runs_forever || (i != 0 && pThis->toWrkShutdown == -1)) { wtiSetAlwaysRunning(pThis->pWrkr[i]); } pWti = pThis->pWrkr[i]; iState = pthread_create(&(pWti->thrdID), &pThis->attrThrd, wtpWorker, (void *)pWti); if (iState != 0) { wtiSetState(pWti, WRKTHRD_STOPPED); LogError(iState, RS_RET_ERR, "%s: pthread_create failed while starting a worker", wtpGetDbgHdr(pThis)); ABORT_FINALIZE(RS_RET_ERR); } ATOMIC_INC(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); /* we got one more! */ // TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards if (dbgTimeoutToStderr) { fprintf(stderr, "%s: wrkr start initiated with state %d, num workers now %d\n", wtpGetDbgHdr(pThis), iState, ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); } DBGPRINTF("%s: started with state %d, num workers now %d\n", wtpGetDbgHdr(pThis), iState, ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); /* wait for the new thread to initialize its signal mask and * cancellation cleanup handler before proceeding */ do { d_pthread_cond_wait(&pThis->condThrdInitDone, &pThis->mutWtp); } while ((iState = wtiGetState(pWti)) == WRKTHRD_INITIALIZING); DBGPRINTF("%s: new worker finished initialization with state %d, num workers now %d\n", wtpGetDbgHdr(pThis), iState, ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); // TESTBENCH bughunt - remove when done! 2018-11-05 rgerhards if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslog debug: %s: started with state %d, num workers now %d\n", wtpGetDbgHdr(pThis), iState, ATOMIC_LOAD_32BIT_RELAXED(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd)); } finalize_it: d_pthread_mutex_unlock(&pThis->mutWtp); RETiRet; } /* set the number of worker threads that should be running. If less than currently running, * a new worker may be started. Please note that there is no guarantee the number of workers * said will be running after we exit this function. It is just a hint. If the number is * higher than one, and no worker is started, the "busy" condition is signaled to awake a worker. * So the caller can assume that there is at least one worker re-checking if there is "work to do" * after this function call. * Parameter "permit_during_shutdown" if true, permits worker starts while the system is * in shutdown state. The prime use case for this is persisting disk queues in enqueue only * mode, which is activated during shutdown. */ rsRetVal ATTR_NONNULL() wtpAdviseMaxWorkers(wtp_t *const pThis, int nMaxWrkr, const int permit_during_shutdown) { DEFiRet; int nMissing; /* number workers missing to run */ int i, nRunning; ISOBJ_TYPE_assert(pThis, wtp); if (nMaxWrkr == 0) FINALIZE; if (nMaxWrkr > pThis->iNumWorkerThreads) /* limit to configured maximum */ nMaxWrkr = pThis->iNumWorkerThreads; const int curNumWrkThrd = ATOMIC_LOAD_32BIT(&pThis->iCurNumWrkThrd, &pThis->mutCurNumWrkThrd); nMissing = nMaxWrkr - curNumWrkThrd; if (nMissing > 0) { if (curNumWrkThrd > 0) { LogMsg(0, RS_RET_OPERATION_STATUS, LOG_INFO, "%s: high activity - starting %d additional worker thread(s), " "currently %d active worker threads.", wtpGetDbgHdr(pThis), nMissing, curNumWrkThrd); } /* start the rqtd nbr of workers */ for (i = 0; i < nMissing; ++i) { CHKiRet(wtpStartWrkr(pThis, permit_during_shutdown)); } } else { /* we have needed number of workers, but they may be sleeping */ for (i = 0, nRunning = 0; i < pThis->iNumWorkerThreads && nRunning < nMaxWrkr; ++i) { if (wtiGetState(pThis->pWrkr[i]) != WRKTHRD_STOPPED) { pthread_cond_signal(&pThis->pWrkr[i]->pcondBusy); nRunning++; } } } finalize_it: RETiRet; } rsRetVal wtpWakeupAllWrkr(wtp_t *pThis) { if (pThis == NULL) return RS_RET_PARAM_ERROR; d_pthread_mutex_lock(&pThis->mutWtp); for (int i = 0; i < pThis->iNumWorkerThreads; ++i) { if (wtiGetState(pThis->pWrkr[i]) != WRKTHRD_STOPPED) pthread_cond_signal(&pThis->pWrkr[i]->pcondBusy); } d_pthread_mutex_unlock(&pThis->mutWtp); return RS_RET_OK; } /* some simple object access methods * Note: the semicolons behind the macros are actually empty declarations. This is * a work-around for clang-format's missing understanding of generative macros. * Some compilers may flag this empty declarations by a warning. If so, we need * to disable this warning. Alternatively, we could exclude this code from being * reformatted by clang-format; */ DEFpropSetMeth(wtp, toWrkShutdown, long); DEFpropSetMeth(wtp, toFirstWrkShutdown, long); DEFpropSetMeth(wtp, wtpState, wtpState_t); DEFpropSetMeth(wtp, iNumWorkerThreads, int); DEFpropSetMeth(wtp, pUsr, void *); DEFpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t); DEFpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal (*pVal)(void *, int)); DEFpropSetMethFP(wtp, pfRateLimiter, rsRetVal (*pVal)(void *)); DEFpropSetMethFP(wtp, pfGetDeqBatchSize, rsRetVal (*pVal)(void *, int *)); DEFpropSetMethFP(wtp, pfDoWork, rsRetVal (*pVal)(void *, void *)); DEFpropSetMethFP(wtp, pfObjProcessed, rsRetVal (*pVal)(void *, wti_t *)); DEFpropSetMethFP(wtp, pfIdleTimeout, rsRetVal (*pVal)(void *)); DEFpropSetMeth(wtp, bAllowFirstWorkerToTimeout, sbool); /* set the debug header message * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. Must be called only before object is finalized. * rgerhards, 2008-01-09 */ rsRetVal wtpSetDbgHdr(wtp_t *pThis, uchar *pszMsg, size_t lenMsg) { DEFiRet; ISOBJ_TYPE_assert(pThis, wtp); assert(pszMsg != NULL); if (lenMsg < 1) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (pThis->pszDbgHdr != NULL) { free(pThis->pszDbgHdr); pThis->pszDbgHdr = NULL; } if ((pThis->pszDbgHdr = malloc(lenMsg + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pszDbgHdr, pszMsg, lenMsg + 1); /* always think about the \0! */ finalize_it: RETiRet; } /* dummy */ static rsRetVal wtpQueryInterface(interface_t __attribute__((unused)) * i) { return RS_RET_NOT_IMPLEMENTED; } /* exit our class */ BEGINObjClassExit(wtp, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(wtp); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(wtp) /* Initialize the stream class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-01-09 */ BEGINObjClassInit(wtp, 1, OBJ_IS_CORE_MODULE) /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDObjClassInit(wtp) rsyslog-8.2608.0/runtime/PaxHeaders/lookup.c0000644000000000000000000000013015216464436015710 xustar0028 mtime=1782212894.0272662 30 atime=1787067618.026437565 30 ctime=1787067794.454726173 rsyslog-8.2608.0/runtime/lookup.c0000664000175000017500000012560215216464436015364 0ustar00rgerrger/* lookup.c * Support for lookup tables in RainerScript. * * Copyright 2013-2023 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "errmsg.h" #include "lookup.h" #include "msg.h" #include "rsconf.h" #include "dirty.h" #include "unicode-helper.h" #include "regexp.h" PRAGMA_IGNORE_Wdeprecated_declarations /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) #ifdef FEATURE_REGEXP DEFobjCurrIf(regexp) #endif /* forward definitions */ static rsRetVal lookupReadFile(lookup_t *pThis, const uchar *name, const uchar *filename); static void lookupDestruct(lookup_t *pThis); /* static data */ /* tables for interfacing with the v6 config system (as far as we need to) */ static struct cnfparamdescr modpdescr[] = {{"name", eCmdHdlrString, CNFPARAM_REQUIRED}, {"file", eCmdHdlrString, CNFPARAM_REQUIRED}, {"reloadOnHUP", eCmdHdlrBinary, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* internal data-types */ typedef struct uint32_index_val_s { uint32_t index; uchar *val; } uint32_index_val_t; const char *reloader_prefix = "lkp:"; static void *lookupTableReloader(void *self); static void lookupStopReloader(lookup_ref_t *pThis); #ifdef HAVE_PTHREAD_SETNAME_NP static void lookupSetReloaderThreadName(const lookup_ref_t *const pThis) { #if defined(__NetBSD__) || defined(__APPLE__) char *reloader_thd_name = NULL; int thd_name_len; #else char reloader_thd_name[16]; #endif int ret; #if defined(__NetBSD__) || defined(__APPLE__) thd_name_len = asprintf(&reloader_thd_name, "%s%s", reloader_prefix, (char *)pThis->name); if (thd_name_len < 0) { return; } #else snprintf(reloader_thd_name, sizeof(reloader_thd_name), "%s%s", reloader_prefix, (char *)pThis->name); #endif #if defined(__NetBSD__) ret = pthread_setname_np(pthread_self(), "%s", reloader_thd_name); #elif defined(__APPLE__) ret = pthread_setname_np(reloader_thd_name); #else ret = pthread_setname_np(pthread_self(), reloader_thd_name); #endif if (ret != 0) { DBGPRINTF("pthread_setname_np failed, not setting lookup reloader thread name for '%s'\n", reloader_thd_name); } #if defined(__NetBSD__) || defined(__APPLE__) free(reloader_thd_name); #endif } #endif static void lookupAppend(lookup_ref_t *pThis) { pThis->next = NULL; if (loadConf->lu_tabs.root == NULL) { loadConf->lu_tabs.root = pThis; } else { loadConf->lu_tabs.last->next = pThis; } loadConf->lu_tabs.last = pThis; } /* create a new lookup table object */ static rsRetVal lookupNew(lookup_ref_t **ppThis) { lookup_ref_t *pThis = NULL; lookup_t *t = NULL; DEFiRet; CHKmalloc(pThis = calloc(1, sizeof(lookup_ref_t))); CHKmalloc(t = calloc(1, sizeof(lookup_t))); pThis->do_reload = pThis->is_reloading = pThis->do_stop = 0; pThis->reload_on_hup = 1; /*DO reload on HUP (default)*/ pThis->next = NULL; pThis->self = t; *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { LogError(errno, iRet, "a lookup table could not be initialized"); free(t); free(pThis); } RETiRet; } /* activate a lookup table entry once rsyslog is ready to do so */ static rsRetVal lookupActivateTable(lookup_ref_t *pThis) { DEFiRet; int initialized = 0; DBGPRINTF("lookupActivateTable called\n"); CHKiConcCtrl(pthread_rwlock_init(&pThis->rwlock, NULL)); pThis->rwlock_initialized = 1; initialized++; /*1*/ CHKiConcCtrl(pthread_mutex_init(&pThis->reloader_mut, NULL)); pThis->reloader_mut_initialized = 1; initialized++; /*2*/ CHKiConcCtrl(pthread_cond_init(&pThis->run_reloader, NULL)); pThis->run_reloader_initialized = 1; initialized++; /*3*/ CHKiConcCtrl(pthread_attr_init(&pThis->reloader_thd_attr)); pThis->reloader_attr_initialized = 1; initialized++; /*4*/ pThis->do_reload = pThis->is_reloading = pThis->do_stop = 0; CHKiConcCtrl(pthread_create(&pThis->reloader, &pThis->reloader_thd_attr, lookupTableReloader, pThis)); pThis->reloader_started = 1; initialized++; /*5*/ finalize_it: if (iRet != RS_RET_OK) { LogError(errno, iRet, "a lookup table could not be activated: " "failed at init-step %d (please enable debug logs for details)", initialized); if (pThis->reloader_started) { lookupStopReloader(pThis); pThis->reloader_started = 0; } if (pThis->reloader_attr_initialized) { pthread_attr_destroy(&pThis->reloader_thd_attr); pThis->reloader_attr_initialized = 0; } if (pThis->run_reloader_initialized) { pthread_cond_destroy(&pThis->run_reloader); pThis->run_reloader_initialized = 0; } if (pThis->reloader_mut_initialized) { pthread_mutex_destroy(&pThis->reloader_mut); pThis->reloader_mut_initialized = 0; } if (pThis->rwlock_initialized) { pthread_rwlock_destroy(&pThis->rwlock); pThis->rwlock_initialized = 0; } } RETiRet; } /*must be called with reloader_mut acquired*/ static void ATTR_NONNULL() freeStubValueForReloadFailure(lookup_ref_t *const pThis) { if (pThis->stub_value_for_reload_failure != NULL) { free(pThis->stub_value_for_reload_failure); pThis->stub_value_for_reload_failure = NULL; } } static void lookupStopReloader(lookup_ref_t *pThis) { pthread_mutex_lock(&pThis->reloader_mut); freeStubValueForReloadFailure(pThis); pThis->do_reload = 0; pThis->is_reloading = 0; pThis->do_stop = 1; pthread_cond_signal(&pThis->run_reloader); pthread_mutex_unlock(&pThis->reloader_mut); pthread_join(pThis->reloader, NULL); } static void lookupRefDestruct(lookup_ref_t *pThis) { if (pThis->reloader_started) { lookupStopReloader(pThis); pThis->reloader_started = 0; } if (pThis->reloader_mut_initialized) pthread_mutex_destroy(&pThis->reloader_mut); if (pThis->run_reloader_initialized) pthread_cond_destroy(&pThis->run_reloader); if (pThis->reloader_attr_initialized) pthread_attr_destroy(&pThis->reloader_thd_attr); if (pThis->rwlock_initialized) pthread_rwlock_destroy(&pThis->rwlock); lookupDestruct(pThis->self); free(pThis->name); free(pThis->filename); free(pThis); } static void destructTable_str(lookup_t *pThis) { uint32_t i = 0; lookup_string_tab_entry_t *entries = pThis->table.str->entries; for (i = 0; i < pThis->nmemb; i++) { free(entries[i].key); } free(entries); free(pThis->table.str); } static void destructTable_arr(lookup_t *pThis) { free(pThis->table.arr->interned_val_refs); free(pThis->table.arr); } static void destructTable_sparseArr(lookup_t *pThis) { free(pThis->table.sprsArr->entries); free(pThis->table.sprsArr); } #ifdef FEATURE_REGEXP static void destructTable_regex(lookup_t *pThis) { uint32_t i; int regfree_available = 0; lookup_regex_tab_entry_t *entries; if (pThis == NULL || pThis->table.regex == NULL) return; entries = pThis->table.regex->entries; if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) regfree_available = 1; if (entries != NULL) { for (i = 0; i < pThis->nmemb; ++i) { if (entries[i].is_compiled) { if (regfree_available) { regexp.regfree(&entries[i].regex); } else { LogError(0, RS_RET_INTERNAL_ERROR, "regexp module missing; compiled regex cannot be freed"); } } free(entries[i].regex_str); entries[i].regex_str = NULL; } } free(entries); free(pThis->table.regex); } #endif static void lookupDestruct(lookup_t *pThis) { uint32_t i; if (pThis == NULL) return; if (pThis->type == STRING_LOOKUP_TABLE) { destructTable_str(pThis); } else if (pThis->type == ARRAY_LOOKUP_TABLE) { destructTable_arr(pThis); } else if (pThis->type == SPARSE_ARRAY_LOOKUP_TABLE) { destructTable_sparseArr(pThis); #ifdef FEATURE_REGEXP } else if (pThis->type == REGEX_LOOKUP_TABLE) { destructTable_regex(pThis); #endif } else if (pThis->type == STUBBED_LOOKUP_TABLE) { /*nothing to be done*/ } for (i = 0; i < pThis->interned_val_count; i++) { free(pThis->interned_vals[i]); } free(pThis->interned_vals); free(pThis->nomatch); free(pThis); } static void __attribute__((noinline)) lookupRefFreeUnlinked(lookup_ref_t *pThis) { if (pThis == NULL) return; lookupDestruct(pThis->self); free(pThis->name); free(pThis->filename); free(pThis); } static void __attribute__((noinline)) lookupRefDropTable(lookup_ref_t *pThis) { lookupDestruct(pThis->self); pThis->self = NULL; } void lookupInitCnf(lookup_tables_t *lu_tabs) { lu_tabs->root = NULL; lu_tabs->last = NULL; } void lookupDestroyCnf(void) { lookup_ref_t *luref, *luref_next; for (luref = runConf->lu_tabs.root; luref != NULL;) { luref_next = luref->next; lookupRefDestruct(luref); luref = luref_next; } } /* comparison function for qsort() */ static int qs_arrcmp_strtab(const void *s1, const void *s2) { return ustrcmp(((lookup_string_tab_entry_t *)s1)->key, ((lookup_string_tab_entry_t *)s2)->key); } static int qs_arrcmp_ustrs(const void *s1, const void *s2) { return ustrcmp(*(uchar **)s1, *(uchar **)s2); } static int qs_arrcmp_uint32_index_val(const void *s1, const void *s2) { uint32_t first_value = ((uint32_index_val_t *)s1)->index; uint32_t second_value = ((uint32_index_val_t *)s2)->index; if (first_value < second_value) { return -1; } if (first_value > second_value) { return 1; } return 0; } static int qs_arrcmp_sprsArrtab(const void *s1, const void *s2) { uint32_t first_value = ((lookup_sparseArray_tab_entry_t *)s1)->key; uint32_t second_value = ((lookup_sparseArray_tab_entry_t *)s2)->key; if (first_value < second_value) { return -1; } if (first_value > second_value) { return 1; } return 0; } /* comparison function for bsearch() and string array compare * this is for the string lookup table type */ static int bs_arrcmp_strtab(const void *s1, const void *s2) { return strcmp((char *)s1, (char *)((lookup_string_tab_entry_t *)s2)->key); } static int bs_arrcmp_str(const void *s1, const void *s2) { return ustrcmp((uchar *)s1, *(uchar **)s2); } static int bs_arrcmp_sprsArrtab(const void *s1, const void *s2) { uint32_t key = *(uint32_t *)s1; uint32_t array_member_value = ((lookup_sparseArray_tab_entry_t *)s2)->key; if (key < array_member_value) { return -1; } if (key > array_member_value) { return 1; } return 0; } static inline const char *defaultVal(lookup_t *pThis) { return (pThis->nomatch == NULL) ? "" : (const char *)pThis->nomatch; } /* lookup_fn for different types of tables */ static es_str_t *lookupKey_stub(lookup_t *pThis, lookup_key_t __attribute__((unused)) key) { return es_newStrFromCStr((char *)pThis->nomatch, ustrlen(pThis->nomatch)); } static es_str_t *lookupKey_str(lookup_t *pThis, lookup_key_t key) { lookup_string_tab_entry_t *entry; const char *r; if (pThis->nmemb == 0) { entry = NULL; } else { assert(pThis->table.str->entries); entry = bsearch(key.k_str, pThis->table.str->entries, pThis->nmemb, sizeof(lookup_string_tab_entry_t), bs_arrcmp_strtab); } if (entry == NULL) { r = defaultVal(pThis); } else { r = (const char *)entry->interned_val_ref; } return es_newStrFromCStr(r, strlen(r)); } static es_str_t *lookupKey_arr(lookup_t *pThis, lookup_key_t key) { const char *r; uint32_t uint_key = key.k_uint; if ((pThis->nmemb == 0) || (uint_key < pThis->table.arr->first_key)) { r = defaultVal(pThis); } else { uint32_t idx = uint_key - pThis->table.arr->first_key; if (idx >= pThis->nmemb) { r = defaultVal(pThis); } else { r = (char *)pThis->table.arr->interned_val_refs[idx]; } } return es_newStrFromCStr(r, strlen(r)); } typedef int(comp_fn_t)(const void *s1, const void *s2); static void *bsearch_lte(const void *key, const void *base, size_t nmemb, size_t size, comp_fn_t *comp_fn) { size_t l, u, idx; const void *p; int comparison; l = 0; u = nmemb; if (l == u) { return NULL; } while (l < u) { idx = (l + u) / 2; p = (void *)(((const char *)base) + (idx * size)); comparison = (*comp_fn)(key, p); if (comparison < 0) u = idx; else if (comparison > 0) l = idx + 1; else return (void *)p; } if (comparison < 0) { if (idx == 0) { return NULL; } idx--; } return (void *)(((const char *)base) + (idx * size)); } static es_str_t *lookupKey_sprsArr(lookup_t *pThis, lookup_key_t key) { lookup_sparseArray_tab_entry_t *entry; const char *r; if (pThis->nmemb == 0) { entry = NULL; } else { entry = bsearch_lte(&key.k_uint, pThis->table.sprsArr->entries, pThis->nmemb, sizeof(lookup_sparseArray_tab_entry_t), bs_arrcmp_sprsArrtab); } if (entry == NULL) { r = defaultVal(pThis); } else { r = (const char *)entry->interned_val_ref; } return es_newStrFromCStr(r, strlen(r)); } #ifdef FEATURE_REGEXP static es_str_t *lookupKey_regex(lookup_t *pThis, lookup_key_t key) { const char *r = defaultVal(pThis); for (uint32_t i = 0; i < pThis->nmemb; ++i) { if (regexp.regexec(&pThis->table.regex->entries[i].regex, (char *)key.k_str, 0, NULL, 0) == 0) { r = (const char *)pThis->table.regex->entries[i].interned_val_ref; break; } } return es_newStrFromCStr(r, strlen(r)); } #endif /* builders for different table-types */ #define NO_INDEX_ERROR(type, name) \ LogError(0, RS_RET_INVALID_VALUE, \ "'%s' lookup table named: '%s' has record(s) without 'index' " \ "field", \ type, name); \ ABORT_FINALIZE(RS_RET_INVALID_VALUE); static rsRetVal build_StringTable(lookup_t *pThis, struct json_object *jtab, const uchar *name) { uint32_t i; struct json_object *jrow, *jindex, *jvalue; uchar *value, *canonicalValueRef; DEFiRet; pThis->table.str = NULL; CHKmalloc(pThis->table.str = calloc(1, sizeof(lookup_string_tab_t))); if (pThis->nmemb > 0) { CHKmalloc(pThis->table.str->entries = calloc(pThis->nmemb, sizeof(lookup_string_tab_entry_t))); for (i = 0; i < pThis->nmemb; i++) { jrow = json_object_array_get_idx(jtab, i); fjson_object_object_get_ex(jrow, "index", &jindex); fjson_object_object_get_ex(jrow, "value", &jvalue); if (jindex == NULL || json_object_is_type(jindex, json_type_null)) { NO_INDEX_ERROR("string", name); } CHKmalloc(pThis->table.str->entries[i].key = ustrdup((uchar *)json_object_get_string(jindex))); value = (uchar *)json_object_get_string(jvalue); uchar **found = (uchar **)bsearch(value, pThis->interned_vals, pThis->interned_val_count, sizeof(uchar *), bs_arrcmp_str); if (found == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "lookup.c:build_StringTable(): " "internal error, bsearch returned NULL for '%s'", value); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } // I give up, I see no way to remove false positive -- rgerhards, 2017-10-24 #ifndef __clang_analyzer__ canonicalValueRef = *found; if (canonicalValueRef == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "lookup.c:build_StringTable(): " "internal error, canonicalValueRef returned from bsearch " "is NULL for '%s'", value); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } pThis->table.str->entries[i].interned_val_ref = canonicalValueRef; #endif } qsort(pThis->table.str->entries, pThis->nmemb, sizeof(lookup_string_tab_entry_t), qs_arrcmp_strtab); } pThis->lookup = lookupKey_str; pThis->key_type = LOOKUP_KEY_TYPE_STRING; finalize_it: RETiRet; } static rsRetVal build_ArrayTable(lookup_t *pThis, struct json_object *jtab, const uchar *name) { uint32_t i; struct json_object *jrow, *jindex, *jvalue; uchar *canonicalValueRef; uint32_t prev_index, _index; uint8_t prev_index_set; uint32_index_val_t *indexes = NULL; DEFiRet; prev_index_set = 0; pThis->table.arr = NULL; CHKmalloc(pThis->table.arr = calloc(1, sizeof(lookup_array_tab_t))); if (pThis->nmemb > 0) { CHKmalloc(indexes = calloc(pThis->nmemb, sizeof(uint32_index_val_t))); CHKmalloc(pThis->table.arr->interned_val_refs = calloc(pThis->nmemb, sizeof(uchar *))); for (i = 0; i < pThis->nmemb; i++) { jrow = json_object_array_get_idx(jtab, i); fjson_object_object_get_ex(jrow, "index", &jindex); fjson_object_object_get_ex(jrow, "value", &jvalue); if (jindex == NULL || json_object_is_type(jindex, json_type_null)) { NO_INDEX_ERROR("array", name); } int64_t index_val = json_object_get_int64(jindex); if (index_val < 0 || index_val > UINT32_MAX) { LogError(0, RS_RET_INVALID_VALUE, "'array' lookup table name: '%s' has index '%lld' outside uint32 range", name, (long long)index_val); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } indexes[i].index = (uint32_t)index_val; indexes[i].val = (uchar *)json_object_get_string(jvalue); } qsort(indexes, pThis->nmemb, sizeof(uint32_index_val_t), qs_arrcmp_uint32_index_val); for (i = 0; i < pThis->nmemb; i++) { _index = indexes[i].index; if (prev_index_set == 0) { prev_index = _index; prev_index_set = 1; pThis->table.arr->first_key = _index; } else { if (_index != ++prev_index) { LogError(0, RS_RET_INVALID_VALUE, "'array' lookup table name: '%s' " "has non-contiguous members between index '%d' and '%d'", name, prev_index, _index); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } } uchar *const *const canonicalValueRef_ptr = bsearch( indexes[i].val, pThis->interned_vals, pThis->interned_val_count, sizeof(uchar *), bs_arrcmp_str); if (canonicalValueRef_ptr == NULL) { LogError(0, RS_RET_ERR, "BUG: canonicalValueRef not found in " "build_ArrayTable(), %s:%d", __FILE__, __LINE__); ABORT_FINALIZE(RS_RET_ERR); } canonicalValueRef = *canonicalValueRef_ptr; assert(canonicalValueRef != NULL); pThis->table.arr->interned_val_refs[i] = canonicalValueRef; } } pThis->lookup = lookupKey_arr; pThis->key_type = LOOKUP_KEY_TYPE_UINT; finalize_it: free(indexes); RETiRet; } static rsRetVal build_SparseArrayTable(lookup_t *pThis, struct json_object *jtab, const uchar *name) { uint32_t i; struct json_object *jrow, *jindex, *jvalue; uchar *value, *canonicalValueRef; DEFiRet; pThis->table.str = NULL; CHKmalloc(pThis->table.sprsArr = calloc(1, sizeof(lookup_sparseArray_tab_t))); if (pThis->nmemb > 0) { CHKmalloc(pThis->table.sprsArr->entries = calloc(pThis->nmemb, sizeof(lookup_sparseArray_tab_entry_t))); for (i = 0; i < pThis->nmemb; i++) { jrow = json_object_array_get_idx(jtab, i); fjson_object_object_get_ex(jrow, "index", &jindex); fjson_object_object_get_ex(jrow, "value", &jvalue); if (jindex == NULL || json_object_is_type(jindex, json_type_null)) { NO_INDEX_ERROR("sparseArray", name); } int64_t index_val = json_object_get_int64(jindex); if (index_val < 0 || index_val > UINT32_MAX) { LogError(0, RS_RET_INVALID_VALUE, "'sparseArray' lookup table name: '%s' has index '%lld' outside uint32 range", name, (long long)index_val); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } pThis->table.sprsArr->entries[i].key = (uint32_t)index_val; value = (uchar *)json_object_get_string(jvalue); uchar *const *const canonicalValueRef_ptr = bsearch(value, pThis->interned_vals, pThis->interned_val_count, sizeof(uchar *), bs_arrcmp_str); if (canonicalValueRef_ptr == NULL) { LogError(0, RS_RET_ERR, "BUG: canonicalValueRef not found in " "build_SparseArrayTable(), %s:%d", __FILE__, __LINE__); ABORT_FINALIZE(RS_RET_ERR); } canonicalValueRef = *canonicalValueRef_ptr; assert(canonicalValueRef != NULL); pThis->table.sprsArr->entries[i].interned_val_ref = canonicalValueRef; } qsort(pThis->table.sprsArr->entries, pThis->nmemb, sizeof(lookup_sparseArray_tab_entry_t), qs_arrcmp_sprsArrtab); } pThis->lookup = lookupKey_sprsArr; pThis->key_type = LOOKUP_KEY_TYPE_UINT; finalize_it: RETiRet; } #ifdef FEATURE_REGEXP static rsRetVal build_RegexTable(lookup_t *pThis, struct json_object *jtab, const uchar *name) { uint32_t i; struct json_object *jrow, *jregex, *jtag; uchar *value, *canonicalValueRef; const char *regex_str; DEFiRet; pThis->table.regex = NULL; CHKmalloc(pThis->table.regex = calloc(1, sizeof(lookup_regex_tab_t))); if (pThis->nmemb > 0) { CHKmalloc(pThis->table.regex->entries = calloc(pThis->nmemb, sizeof(lookup_regex_tab_entry_t))); for (i = 0; i < pThis->nmemb; i++) { jrow = json_object_array_get_idx(jtab, i); fjson_object_object_get_ex(jrow, "regex", &jregex); fjson_object_object_get_ex(jrow, "tag", &jtag); if (jregex == NULL || jtag == NULL || json_object_is_type(jregex, json_type_null) || json_object_is_type(jtag, json_type_null)) { LogError(0, RS_RET_INVALID_VALUE, "'regex' lookup table named: '%s' has record(s) without required " "fields", name); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } regex_str = json_object_get_string(jregex); CHKmalloc(pThis->table.regex->entries[i].regex_str = ustrdup((const uchar *)regex_str)); value = (uchar *)json_object_get_string(jtag); uchar *const *const canonicalValueRef_ptr = bsearch(value, pThis->interned_vals, pThis->interned_val_count, sizeof(uchar *), bs_arrcmp_str); if (canonicalValueRef_ptr == NULL) { LogError(0, RS_RET_ERR, "BUG: canonicalValueRef not found in build_RegexTable(), %s:%d", __FILE__, __LINE__); ABORT_FINALIZE(RS_RET_ERR); } canonicalValueRef = *canonicalValueRef_ptr; assert(canonicalValueRef != NULL); pThis->table.regex->entries[i].interned_val_ref = canonicalValueRef; int err; if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { if ((err = regexp.regcomp(&pThis->table.regex->entries[i].regex, regex_str, REG_EXTENDED | REG_NOSUB)) != 0) { char errbuf[256]; regexp.regerror(err, &pThis->table.regex->entries[i].regex, errbuf, sizeof(errbuf)); LogError(0, RS_RET_INVALID_VALUE, "error compiling regex '%s' in lookup table '%s': %s", regex_str, name, errbuf); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } else { pThis->table.regex->entries[i].is_compiled = 1; } } else { LogError(0, RS_RET_INTERNAL_ERROR, "regex library could not be loaded"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } } } pThis->lookup = lookupKey_regex; pThis->key_type = LOOKUP_KEY_TYPE_STRING; finalize_it: RETiRet; } #endif static rsRetVal lookupBuildStubbedTable(lookup_t *pThis, const uchar *stub_val) { DEFiRet; CHKmalloc(pThis->nomatch = ustrdup(stub_val)); pThis->lookup = lookupKey_stub; pThis->type = STUBBED_LOOKUP_TABLE; pThis->key_type = LOOKUP_KEY_TYPE_NONE; finalize_it: RETiRet; } static rsRetVal lookupBuildTable_v1(lookup_t *pThis, struct json_object *jroot, const uchar *name) { struct json_object *jnomatch, *jtype, *jtab; struct json_object *jrow, *jvalue; const char *table_type, *nomatch_value; const char *value_key; const uchar **all_values; const uchar *curr, *prev; uint32_t i, j; uint32_t uniq_values; DEFiRet; all_values = NULL; fjson_object_object_get_ex(jroot, "nomatch", &jnomatch); fjson_object_object_get_ex(jroot, "type", &jtype); fjson_object_object_get_ex(jroot, "table", &jtab); if (jtab == NULL || !json_object_is_type(jtab, json_type_array)) { LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' has invalid table definition", name); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } pThis->nmemb = json_object_array_length(jtab); table_type = json_object_get_string(jtype); if (table_type == NULL) { table_type = "string"; } value_key = (strcmp(table_type, "regex") == 0) ? "tag" : "value"; CHKmalloc(all_values = malloc(pThis->nmemb * sizeof(uchar *))); /* before actual table can be loaded, prepare all-value list and remove duplicates*/ for (i = 0; i < pThis->nmemb; i++) { jrow = json_object_array_get_idx(jtab, i); fjson_object_object_get_ex(jrow, value_key, &jvalue); if (jvalue == NULL || json_object_is_type(jvalue, json_type_null)) { LogError(0, RS_RET_INVALID_VALUE, "'%s' lookup table named: '%s' has record(s) " "without '%s' field", table_type, name, value_key); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } all_values[i] = (const uchar *)json_object_get_string(jvalue); } qsort(all_values, pThis->nmemb, sizeof(uchar *), qs_arrcmp_ustrs); uniq_values = 1; for (i = 1; i < pThis->nmemb; i++) { curr = all_values[i]; prev = all_values[i - 1]; if (ustrcmp(prev, curr) != 0) { uniq_values++; } } if (pThis->nmemb > 0) { CHKmalloc(pThis->interned_vals = malloc(uniq_values * sizeof(uchar *))); j = 0; CHKmalloc(pThis->interned_vals[j++] = ustrdup(all_values[0])); for (i = 1; i < pThis->nmemb; ++i) { curr = all_values[i]; prev = all_values[i - 1]; if (ustrcmp(prev, curr) != 0) { CHKmalloc(pThis->interned_vals[j++] = ustrdup(all_values[i])); } } pThis->interned_val_count = uniq_values; } /* uniq values captured (sorted) */ nomatch_value = json_object_get_string(jnomatch); if (nomatch_value != NULL) { CHKmalloc(pThis->nomatch = (uchar *)strdup(nomatch_value)); } if (strcmp(table_type, "array") == 0) { pThis->type = ARRAY_LOOKUP_TABLE; CHKiRet(build_ArrayTable(pThis, jtab, name)); } else if (strcmp(table_type, "sparseArray") == 0) { pThis->type = SPARSE_ARRAY_LOOKUP_TABLE; CHKiRet(build_SparseArrayTable(pThis, jtab, name)); #ifdef FEATURE_REGEXP } else if (strcmp(table_type, "regex") == 0) { pThis->type = REGEX_LOOKUP_TABLE; CHKiRet(build_RegexTable(pThis, jtab, name)); #endif } else if (strcmp(table_type, "string") == 0) { pThis->type = STRING_LOOKUP_TABLE; CHKiRet(build_StringTable(pThis, jtab, name)); } else { LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' uses unupported " "type: '%s'", name, table_type); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } finalize_it: if (all_values != NULL) free(all_values); RETiRet; } static rsRetVal lookupBuildTable(lookup_t *pThis, struct json_object *jroot, const uchar *name) { struct json_object *jversion; int version = 1; DEFiRet; fjson_object_object_get_ex(jroot, "version", &jversion); if (jversion != NULL && !json_object_is_type(jversion, json_type_null)) { version = json_object_get_int(jversion); } else { LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' doesn't specify version " "(will use default value: %d)", name, version); } if (version == 1) { CHKiRet(lookupBuildTable_v1(pThis, jroot, name)); } else { LogError(0, RS_RET_INVALID_VALUE, "lookup table named: '%s' uses unsupported " "version: %d", name, version); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } finalize_it: RETiRet; } /* find a lookup table. This is a naive O(n) algo, but this really * doesn't matter as it is called only a few times during config * load. The function returns either a pointer to the requested * table or NULL, if not found. */ lookup_ref_t *ATTR_NONNULL() lookupFindTable(uchar *name) { lookup_ref_t *curr; for (curr = loadConf->lu_tabs.root; curr != NULL; curr = curr->next) { if (!ustrcmp(curr->name, name)) break; } return curr; } /* this reloads a lookup table. This is done while the engine is running, * as such the function must ensure proper locking and proper order of * operations (so that nothing can interfere). If the table cannot be loaded, * the old table is continued to be used. */ static rsRetVal lookupReloadOrStub(lookup_ref_t *pThis, const uchar *stub_val) { lookup_t *newlu, *oldlu; /* dummy to be able to use support functions without affecting current settings. */ DEFiRet; oldlu = pThis->self; newlu = NULL; DBGPRINTF("reload requested for lookup table '%s'\n", pThis->name); CHKmalloc(newlu = calloc(1, sizeof(lookup_t))); if (stub_val == NULL) { CHKiRet(lookupReadFile(newlu, pThis->name, pThis->filename)); } else { CHKiRet(lookupBuildStubbedTable(newlu, stub_val)); } /* all went well, copy over data members */ pthread_rwlock_wrlock(&pThis->rwlock); pThis->self = newlu; pthread_rwlock_unlock(&pThis->rwlock); finalize_it: if (iRet != RS_RET_OK) { if (stub_val == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "lookup table '%s' could not be reloaded from file '%s'", pThis->name, pThis->filename); } else { LogError(0, RS_RET_INTERNAL_ERROR, "lookup table '%s' could not be stubbed with value '%s'", pThis->name, stub_val); } lookupDestruct(newlu); } else { if (stub_val == NULL) { LogMsg(0, RS_RET_OK, LOG_INFO, "lookup table '%s' reloaded from file '%s'", pThis->name, pThis->filename); } else { LogError(0, RS_RET_OK, "lookup table '%s' stubbed with value '%s'", pThis->name, stub_val); } lookupDestruct(oldlu); } RETiRet; } static rsRetVal lookupDoStub(lookup_ref_t *pThis, const uchar *stub_val) { int already_stubbed = 0; DEFiRet; pthread_rwlock_rdlock(&pThis->rwlock); if (pThis->self->type == STUBBED_LOOKUP_TABLE && ustrcmp(pThis->self->nomatch, stub_val) == 0) already_stubbed = 1; pthread_rwlock_unlock(&pThis->rwlock); if (!already_stubbed) { LogError(0, RS_RET_OK, "stubbing lookup table '%s' with value '%s'", pThis->name, stub_val); CHKiRet(lookupReloadOrStub(pThis, stub_val)); } else { LogError(0, RS_RET_OK, "lookup table '%s' is already stubbed with value '%s'", pThis->name, stub_val); } finalize_it: RETiRet; } static uint8_t lookupIsReloadPending(lookup_ref_t *pThis) { uint8_t reload_pending; pthread_mutex_lock(&pThis->reloader_mut); reload_pending = pThis->do_reload || pThis->is_reloading; pthread_mutex_unlock(&pThis->reloader_mut); return reload_pending; } /* note: stub_val_if_reload_fails may or may not be NULL */ rsRetVal ATTR_NONNULL(1) lookupReload(lookup_ref_t *const pThis, const uchar *const stub_val_if_reload_fails) { uint8_t locked = 0; int lock_errno = 0; DEFiRet; assert(pThis != NULL); if ((lock_errno = pthread_mutex_trylock(&pThis->reloader_mut)) == 0) { locked = 1; /*so it doesn't leak memory in situation where 2 reload requests are issued back to back*/ freeStubValueForReloadFailure(pThis); if (stub_val_if_reload_fails != NULL) { CHKmalloc(pThis->stub_value_for_reload_failure = ustrdup(stub_val_if_reload_fails)); } pThis->do_reload = 1; pthread_cond_signal(&pThis->run_reloader); } else { LogError(lock_errno, RS_RET_INTERNAL_ERROR, "attempt to trigger " "reload of lookup table '%s' failed (not stubbing)", pThis->name); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); /* we can choose to stub the table here, but it'll hurt because the table reloader may take time to complete the reload and stubbing because of a concurrent reload message may not be desirable (except in very tightly controled environments where reload-triggering messages pushed are timed accurately and an idempotency-filter is used to reject re-deliveries) */ } finalize_it: if (locked) { pthread_mutex_unlock(&pThis->reloader_mut); } RETiRet; } static rsRetVal ATTR_NONNULL(1) lookupDoReload(lookup_ref_t *pThis, uchar *stub_val) { DEFiRet; iRet = lookupReloadOrStub(pThis, NULL); if ((iRet != RS_RET_OK) && (stub_val != NULL)) { iRet = lookupDoStub(pThis, stub_val); } free(stub_val); RETiRet; } void *lookupTableReloader(void *self) { lookup_ref_t *pThis = (lookup_ref_t *)self; #ifdef HAVE_PTHREAD_SETNAME_NP lookupSetReloaderThreadName(pThis); #endif pthread_mutex_lock(&pThis->reloader_mut); while (1) { if (pThis->do_stop) { break; } else if (pThis->do_reload) { uchar *stub_val = pThis->stub_value_for_reload_failure; pThis->stub_value_for_reload_failure = NULL; pThis->do_reload = 0; pThis->is_reloading = 1; pthread_mutex_unlock(&pThis->reloader_mut); lookupDoReload(pThis, stub_val); pthread_mutex_lock(&pThis->reloader_mut); pThis->is_reloading = 0; } else { pthread_cond_wait(&pThis->run_reloader, &pThis->reloader_mut); } } pthread_mutex_unlock(&pThis->reloader_mut); return NULL; } /* reload all lookup tables on HUP */ void lookupDoHUP(void) { lookup_ref_t *luref; for (luref = runConf->lu_tabs.root; luref != NULL; luref = luref->next) { if (luref->reload_on_hup) { lookupReload(luref, NULL); } } } /* activate lookup table system config * most importantly, this means tarting the lookup table reloader thread in the * right process space - it is a difference if we fork or not! */ void lookupActivateConf(void) { DBGPRINTF("lookup tables: activate config \n"); lookup_ref_t *luref; for (luref = runConf->lu_tabs.root; luref != NULL; luref = luref->next) { DBGPRINTF("lookup actiate: processing %p\n", luref); lookupActivateTable(luref); } DBGPRINTF("lookup tables: activate done\n"); } uint lookupPendingReloadCount(void) { uint pending_reload_count = 0; lookup_ref_t *luref; for (luref = runConf->lu_tabs.root; luref != NULL; luref = luref->next) { if (lookupIsReloadPending(luref)) { pending_reload_count++; } } return pending_reload_count; } /* returns either a pointer to the value (read only!) or NULL * if either the key could not be found or an error occurred. * Note that an estr_t object is returned. The caller is * responsible for freeing it. */ es_str_t *lookupKey(lookup_ref_t *pThis, lookup_key_t key) { es_str_t *estr; pthread_rwlock_rdlock(&pThis->rwlock); estr = lookupKeyLocked(pThis, key); pthread_rwlock_unlock(&pThis->rwlock); return estr; } /* caller must hold pThis->rwlock */ es_str_t *lookupKeyLocked(lookup_ref_t *pThis, lookup_key_t key) { lookup_t *t; t = pThis->self; return t->lookup(t, key); } /* note: widely-deployed json_c 0.9 does NOT support incremental * parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS, * we read the file into one big memory buffer and parse it at once. * While this is not very elegant, it will not pose any real issue * for "reasonable" lookup tables (and "unreasonably" large ones * will probably have other issues as well...). */ static rsRetVal ATTR_NONNULL() lookupReadFile(lookup_t *const pThis, const uchar *const name, const uchar *const filename) { struct json_tokener *tokener = NULL; struct json_object *json = NULL; char *iobuf = NULL; int fd = -1; ssize_t nread; struct stat sb; DEFiRet; if ((fd = open((const char *)filename, O_RDONLY)) == -1) { LogError(errno, RS_RET_FILE_NOT_FOUND, "lookup table file '%s' could not be opened", filename); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (fstat(fd, &sb) == -1) { LogError(errno, RS_RET_FILE_NOT_FOUND, "lookup table file '%s' stat failed", filename); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (sb.st_size == 0) { LogError(0, RS_RET_JSON_PARSE_ERR, "lookup table file '%s' is empty", filename); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } CHKmalloc(iobuf = malloc(sb.st_size)); tokener = json_tokener_new(); nread = read(fd, iobuf, sb.st_size); if (nread != (ssize_t)sb.st_size) { LogError(errno, RS_RET_READ_ERR, "lookup table file '%s' read error", filename); ABORT_FINALIZE(RS_RET_READ_ERR); } json = json_tokener_parse_ex(tokener, iobuf, sb.st_size); if (json == NULL) { LogError(0, RS_RET_JSON_PARSE_ERR, "lookup table file '%s' json parsing error", filename); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } free(iobuf); /* early free to sever resources*/ iobuf = NULL; /* make sure no double-free */ /* got json object, now populate our own in-memory structure */ CHKiRet(lookupBuildTable(pThis, json, name)); finalize_it: if (fd != -1) { close(fd); } free(iobuf); if (tokener != NULL) json_tokener_free(tokener); if (json != NULL) json_object_put(json); RETiRet; } rsRetVal lookupTableDefProcessCnf(struct cnfobj *o) { struct cnfparamvals *pvals; lookup_ref_t *lu; uchar *name = NULL; uchar *filename = NULL; int reload_on_hup = 1; int lu_linked = 0; short i; DEFiRet; lu = NULL; pvals = nvlstGetParams(o->nvlst, &modpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } DBGPRINTF("lookupTableDefProcessCnf params:\n"); cnfparamsPrint(&modpblk, pvals); for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "file")) { CHKmalloc(filename = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "name")) { CHKmalloc(name = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "reloadOnHUP")) { reload_on_hup = (pvals[i].val.d.n != 0); } else { dbgprintf( "lookup_table: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } if (name == NULL || filename == NULL) { iRet = RS_RET_INTERNAL_ERROR; LogError(0, iRet, "internal error: lookup table name or file not set albeit being mandatory"); ABORT_FINALIZE(iRet); } if (lookupFindTable(name) != NULL) { LogError(0, RS_RET_CONFIG_ERROR, "lookup_table: duplicate name '%s' in current config set", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKiRet(lookupNew(&lu)); lu->name = name; name = NULL; lu->filename = filename; filename = NULL; lu->reload_on_hup = reload_on_hup; const uchar *const lu_name = lu->name; /* we need a const to keep TSAN happy :-( */ const uchar *const lu_filename = lu->filename; /* we need a const to keep TSAN happy :-( */ lookupAppend(lu); lu_linked = 1; CHKiRet(lookupReadFile(lu->self, lu_name, lu_filename)); LogMsg(0, RS_RET_OK, LOG_INFO, "lookup table '%s' loaded from file '%s'", lu_name, lu->filename); finalize_it: free(name); free(filename); cnfparamvalsDestruct(pvals, &modpblk); if (iRet != RS_RET_OK && lu != NULL) { if (lu_linked) { lookupRefDropTable(lu); } else { lookupRefFreeUnlinked(lu); } } RETiRet; } void lookupClassExit(void) { objRelease(glbl, CORE_COMPONENT); } rsRetVal lookupClassInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(glbl, CORE_COMPONENT)); finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/stringbuf.c0000644000000000000000000000013115241075234016373 xustar0030 mtime=1787067036.611578407 29 atime=1787067036.75758114 30 ctime=1787067794.321723695 rsyslog-8.2608.0/runtime/stringbuf.c0000664000175000017500000006011515241075234016043 0ustar00rgerrger/* This is the byte-counted string class for rsyslog. * This object has a lot of legacy. Among others, it was started to * support embedded \0 bytes, which looked like they were needed to * be supported by RFC developments at that time. Later, this was * no longer a requirement, and we refactored the class in 2016 * to some simpler internals which make use of the fact that no * NUL can ever occur in rsyslog strings (they are escaped at the * input side of rsyslog). * It now serves primarily to a) dynamic string creation, b) keep * old interfaces supported, and c) some special functionality, * e.g. search. Further refactoring and simplificytin may make * sense. * * Copyright (C) 2005-2025 Adiscon GmbH * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include "rsyslog.h" #include "stringbuf.h" #include "srUtils.h" #include "regexp.h" #include "errmsg.h" #include "unicode-helper.h" #define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */ /* ################################################################# * * private members * * ################################################################# */ /* static data */ DEFobjCurrIf(obj) DEFobjCurrIf(regexp) /* ################################################################# * * public members * * ################################################################# */ rsRetVal cstrConstruct(cstr_t **const ppThis) { DEFiRet; cstr_t *pThis; CHKmalloc(pThis = (cstr_t *)malloc(sizeof(cstr_t))); rsSETOBJTYPE(pThis, OIDrsCStr); #ifndef NDEBUG pThis->isFinalized = 0; #endif pThis->pBuf = NULL; pThis->iBufSize = 0; pThis->iStrLen = 0; *ppThis = pThis; finalize_it: RETiRet; } /* construct from sz string * rgerhards 2005-09-15 */ rsRetVal rsCStrConstructFromszStr(cstr_t **const ppThis, const uchar *const sz) { DEFiRet; cstr_t *pThis; CHKiRet(rsCStrConstruct(&pThis)); pThis->iStrLen = strlen((char *)sz); pThis->iBufSize = strlen((char *)sz) + 1; if ((pThis->pBuf = (uchar *)malloc(pThis->iBufSize)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* we do NOT need to copy the \0! */ memcpy(pThis->pBuf, sz, pThis->iStrLen); *ppThis = pThis; finalize_it: RETiRet; } /* a helper function for rsCStr*Strf() */ static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); static rsRetVal rsCStrConstructFromszStrv(cstr_t **const ppThis, const char *const fmt, va_list ap) { DEFiRet; cstr_t *pThis; va_list ap2; int len; va_copy(ap2, ap); len = vsnprintf(NULL, 0, (char *)fmt, ap2); va_end(ap2); if (len < 0) ABORT_FINALIZE(RS_RET_ERR); CHKiRet(rsCStrConstruct(&pThis)); pThis->iStrLen = len; pThis->iBufSize = len + 1; len++; /* account for the \0 written by vsnprintf */ if ((pThis->pBuf = (uchar *)malloc(pThis->iBufSize)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } vsnprintf((char *)pThis->pBuf, len, (char *)fmt, ap); *ppThis = pThis; finalize_it: RETiRet; } /* construct from a printf-style formated string */ rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, const char *fmt, ...) { DEFiRet; va_list ap; va_start(ap, fmt); iRet = rsCStrConstructFromszStrv(ppThis, fmt, ap); va_end(ap); RETiRet; } /* construct from es_str_t string * rgerhards 2010-12-03 */ rsRetVal cstrConstructFromESStr(cstr_t **const ppThis, es_str_t *const str) { DEFiRet; cstr_t *pThis; CHKiRet(rsCStrConstruct(&pThis)); pThis->iStrLen = es_strlen(str); pThis->iBufSize = pThis->iStrLen + 1; if ((pThis->pBuf = (uchar *)malloc(pThis->iBufSize)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* we do NOT need to copy the \0! */ memcpy(pThis->pBuf, es_getBufAddr(str), pThis->iStrLen); *ppThis = pThis; finalize_it: RETiRet; } /* construct from CStr object. * rgerhards 2005-10-18 */ rsRetVal ATTR_NONNULL() rsCStrConstructFromCStr(cstr_t **const ppThis, const cstr_t *const pFrom) { DEFiRet; cstr_t *pThis; rsCHECKVALIDOBJECT(pFrom, OIDrsCStr); CHKiRet(rsCStrConstruct(&pThis)); if (pFrom->iStrLen > 0) { pThis->iStrLen = pFrom->iStrLen; pThis->iBufSize = pFrom->iStrLen + 1; if ((pThis->pBuf = (uchar *)malloc(pThis->iBufSize)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen); } *ppThis = pThis; finalize_it: RETiRet; } void rsCStrDestruct(cstr_t **const ppThis) { free((*ppThis)->pBuf); RSFREEOBJ(*ppThis); *ppThis = NULL; } /* extend the string buffer if its size is insufficient. * Param iMinNeeded is the minumum free space needed. If it is larger * than the default alloc increment, space for at least this amount is * allocated. In practice, a bit more is allocated because we envision that * some more characters may be added after these. * rgerhards, 2008-01-07 * changed to utilized realloc() -- rgerhards, 2009-06-16 */ static rsRetVal rsCStrExtendBuf(cstr_t *const __restrict__ pThis, const size_t iMinNeeded) { uchar *pNewBuf; size_t iNewSize; DEFiRet; /* first compute the new size needed */ if (iMinNeeded > RS_STRINGBUF_ALLOC_INCREMENT) { /* we allocate "n" ALLOC_INCREMENTs. Usually, that should * leave some room after the absolutely needed one. It also * reduces memory fragmentation. Note that all of this are * integer operations (very important to understand what is * going on)! Parenthesis are for better readibility. */ iNewSize = (iMinNeeded / RS_STRINGBUF_ALLOC_INCREMENT + 1) * RS_STRINGBUF_ALLOC_INCREMENT; } else { iNewSize = pThis->iBufSize + RS_STRINGBUF_ALLOC_INCREMENT; } iNewSize += pThis->iBufSize; /* add current size */ #if DEV_DEBUG == 1 dbgprintf("extending string buffer, old %d, new %d\n", pThis->iBufSize, iNewSize); #endif CHKmalloc(pNewBuf = (uchar *)realloc(pThis->pBuf, iNewSize)); pThis->iBufSize = iNewSize; pThis->pBuf = pNewBuf; finalize_it: RETiRet; } /* Append a character to the current string object. This may only be done until * cstrFinalize() is called. * rgerhards, 2009-06-16 */ rsRetVal cstrAppendChar(cstr_t *const __restrict__ pThis, const uchar c) { rsRetVal iRet = RS_RET_OK; if (pThis->iStrLen + 1 >= pThis->iBufSize) { CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */ } /* ok, when we reach this, we have sufficient memory */ *(pThis->pBuf + pThis->iStrLen++) = c; finalize_it: return iRet; } /* append a string of known length. In this case, we make sure we do at most * one additional memory allocation. */ rsRetVal rsCStrAppendStrWithLen(cstr_t *const pThis, const uchar *const psz, const size_t iStrLen) { DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(psz != NULL); /* Keep one spare byte for cstrFinalize(), which appends the trailing NUL. */ if (pThis->iStrLen + iStrLen + 1 > pThis->iBufSize) { CHKiRet(rsCStrExtendBuf(pThis, iStrLen + 1)); /* need more memory! */ } /* ok, now we always have sufficient continues memory to do a memcpy() */ memcpy(pThis->pBuf + pThis->iStrLen, psz, iStrLen); pThis->iStrLen += iStrLen; finalize_it: RETiRet; } rsRetVal rsCStrAppendParts(cstr_t *const pThis, const rs_cstr_part_t *const parts, const size_t count) { uchar *dst; size_t total_len = 0; size_t i; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(parts != NULL || count == 0); for (i = 0; i < count; ++i) { if (parts[i].len == 0) { continue; } assert(parts[i].ptr != NULL); total_len += parts[i].len; } if (total_len == 0) { FINALIZE; } if (pThis->iStrLen + total_len + 1 > pThis->iBufSize) { CHKiRet(rsCStrExtendBuf(pThis, total_len + 1)); } dst = pThis->pBuf + pThis->iStrLen; for (i = 0; i < count; ++i) { if (parts[i].len == 0) { continue; } memcpy(dst, parts[i].ptr, parts[i].len); dst += parts[i].len; } pThis->iStrLen += total_len; finalize_it: RETiRet; } /* changed to be a wrapper to rsCStrAppendStrWithLen() so that * we can save some time when we have the length but do not * need to change existing code. * rgerhards, 2007-07-03 */ rsRetVal rsCStrAppendStr(cstr_t *const pThis, const uchar *const psz) { return rsCStrAppendStrWithLen(pThis, psz, strlen((char *)psz)); } /* append the contents of one cstr_t object to another * rgerhards, 2008-02-25 */ rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend) { return rsCStrAppendStrWithLen(pThis, pstrAppend->pBuf, pstrAppend->iStrLen); } /* append a printf-style formated string */ rsRetVal rsCStrAppendStrf(cstr_t *pThis, const char *fmt, ...) { DEFiRet; va_list ap; cstr_t *pStr = NULL; va_start(ap, fmt); iRet = rsCStrConstructFromszStrv(&pStr, (char *)fmt, ap); va_end(ap); if (iRet != RS_RET_OK) goto finalize_it; iRet = cstrAppendCStr(pThis, pStr); rsCStrDestruct(&pStr); finalize_it: RETiRet; } rsRetVal rsCStrAppendInt(cstr_t *pThis, long i) { DEFiRet; uchar szBuf[32]; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), (number_t)i)); iRet = rsCStrAppendStr(pThis, szBuf); finalize_it: RETiRet; } /* Sets the string object to the classigal sz-string provided. * Any previously stored vlaue is discarded. If a NULL pointer * the the new value (pszNew) is provided, an empty string is * created (this is NOT an error!). * rgerhards, 2005-10-18 */ rsRetVal rsCStrSetSzStr(cstr_t *const __restrict__ pThis, uchar *const __restrict__ pszNew) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); if (pszNew == NULL) { free(pThis->pBuf); pThis->pBuf = NULL; pThis->iStrLen = 0; pThis->iBufSize = 0; } else { const size_t newlen = strlen((char *)pszNew); if (newlen > pThis->iBufSize) { uchar *const newbuf = (uchar *)realloc(pThis->pBuf, newlen + 1); if (newbuf == NULL) { /* we keep the old value, best we can do */ return RS_RET_OUT_OF_MEMORY; } pThis->pBuf = newbuf; pThis->iBufSize = newlen + 1; } pThis->iStrLen = newlen; if (pThis->iStrLen == 0) { if (pThis->pBuf != NULL) { pThis->pBuf[0] = '\0'; } } else { memcpy(pThis->pBuf, pszNew, pThis->iStrLen); } } return RS_RET_OK; } /* Converts the CStr object to a classical zero-terminated C string * and returns that string. The caller must not free it and must not * destroy the CStr object as long as the ascii string is used. */ uchar *cstrGetSzStrNoNULL(cstr_t *const __restrict__ pThis) { assert(pThis->isFinalized); return (pThis->pBuf == NULL) ? (uchar *)"" : pThis->pBuf; } /* Converts the CStr object to a classical zero-terminated C string, * returns that string and destroys the CStr object. The returned string * MUST be freed by the caller. The function might return NULL if * no memory can be allocated. * * This is the NEW replacement for rsCStrConvSzStrAndDestruct which does * no longer utilize a special buffer but soley works on pBuf (and also * assumes that cstrFinalize had been called). * * Parameters are as follows: * pointer to the object, pointer to string-pointer to receive string and * bRetNULL: 0 - must not return NULL on empty string, return "" in that * case, 1 - return NULL instead of an empty string. * PLEASE NOTE: the caller must free the memory returned in ppSz in any case * (except, of course, if it is NULL). */ rsRetVal cstrConvSzStrAndDestruct(cstr_t **ppThis, uchar **ppSz, int bRetNULL) { DEFiRet; uchar *pRetBuf; cstr_t *pThis; assert(ppThis != NULL); pThis = *ppThis; assert(pThis->isFinalized); rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(ppSz != NULL); assert(bRetNULL == 0 || bRetNULL == 1); if (pThis->pBuf == NULL) { if (bRetNULL == 0) { CHKmalloc(pRetBuf = malloc(1)); *pRetBuf = '\0'; } else { pRetBuf = NULL; } } else { pThis->pBuf[pThis->iStrLen] = '\0'; /* space for this is reserved */ pRetBuf = pThis->pBuf; } *ppSz = pRetBuf; finalize_it: /* We got it, now free the object ourselfs. Please note * that we can NOT use the rsCStrDestruct function as it would * also free the sz String buffer, which we pass on to the user. */ RSFREEOBJ(pThis); *ppThis = NULL; RETiRet; } /* return the length of the current string * 2005-09-09 rgerhards * Please note: this is only a function in a debug build. * For release builds, it is a macro defined in stringbuf.h. * This is due to performance reasons. */ #ifndef NDEBUG size_t cstrLen(cstr_t *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); return (pThis->iStrLen); } #endif /* Truncate characters from the end of the string. * rgerhards 2005-09-15 */ rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc) { rsCHECKVALIDOBJECT(pThis, OIDrsCStr); if (pThis->iStrLen < nTrunc) return RS_TRUNCAT_TOO_LARGE; pThis->iStrLen -= nTrunc; return RS_RET_OK; } /* Trim trailing whitespace from a given string */ void cstrTrimTrailingWhiteSpace(cstr_t *const __restrict__ pThis) { register int i; register uchar *pC; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); if (pThis->iStrLen == 0) goto done; /* empty string -> nothing to trim ;) */ i = pThis->iStrLen; pC = pThis->pBuf + i - 1; while (i > 0 && isspace((int)*pC)) { --pC; --i; } /* i now is the new string length! */ if (i != (int)pThis->iStrLen) { pThis->iStrLen = i; pThis->pBuf[pThis->iStrLen] = '\0'; /* we always have this space */ // TODO: can we remove this? } done: return; } /* compare two string objects - works like strcmp(), but operates * on CStr objects. Please note that this version here is * faster in the majority of cases, simply because it can * rely on StrLen. * rgerhards 2005-09-19 * fixed bug, in which only the last byte was actually compared * in equal-size strings. * rgerhards, 2005-09-26 */ int rsCStrCStrCmp(cstr_t *const __restrict__ pCS1, cstr_t *const __restrict__ pCS2) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); rsCHECKVALIDOBJECT(pCS2, OIDrsCStr); if (pCS1->iStrLen == pCS2->iStrLen) if (pCS1->iStrLen == 0) return 0; /* zero-sized string are equal ;) */ else return memcmp(pCS1->pBuf, pCS2->pBuf, pCS1->iStrLen); else return pCS1->iStrLen - pCS2->iStrLen; } /* check if a sz-type string starts with a CStr object. This function * is initially written to support the "startswith" property-filter * comparison operation. Maybe it also has other needs. * This functions is modelled after the strcmp() series, thus a * return value of 0 indicates that the string starts with the * sequence while -1 indicates it does not! * rgerhards 2005-10-19 */ int rsCStrSzStrStartsWithCStr(cstr_t *const __restrict__ pCS1, uchar *const __restrict__ psz, const size_t iLenSz) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(psz != NULL); assert(iLenSz == strlen((char *)psz)); /* just make sure during debugging! */ if (iLenSz >= pCS1->iStrLen) { if (pCS1->iStrLen == 0) return 0; /* yes, it starts with a zero-sized string ;) */ else return memcmp(psz, pCS1->pBuf, pCS1->iStrLen); } else { return -1; /* pCS1 is less then psz */ } } /* check if a sz-type string ends with a CStr object. This helper mirrors * rsCStrSzStrStartsWithCStr and is primarily intended for the new * "endswith" property-filter operation. * returns 0 if the string ends with the pattern, -1 otherwise. */ int rsCStrSzStrEndsWithCStr(cstr_t *const __restrict__ pCS1, uchar *const __restrict__ psz, const size_t iLenSz) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(psz != NULL); assert(iLenSz == strlen((char *)psz)); if (iLenSz >= pCS1->iStrLen) { if (pCS1->iStrLen == 0) { return 0; /* yes, it ends with a zero-sized string ;) */ } else { return memcmp(psz + iLenSz - pCS1->iStrLen, pCS1->pBuf, pCS1->iStrLen); } } else { return -1; } } /* check if a CStr object matches a regex. * msamia@redhat.com 2007-07-12 * @return returns 0 if matched * bug: doesn't work for CStr containing \0 * rgerhards, 2007-07-16: bug is no real bug, because rsyslogd ensures there * never is a \0 *inside* a property string. * Note that the function returns -1 if regexp functionality is not available. * rgerhards: 2009-03-04: ERE support added, via parameter iType: 0 - BRE, 1 - ERE * Arnaud Cornet/rgerhards: 2009-04-02: performance improvement by caching compiled regex * If a caller does not need the cached version, it must still provide memory for it * and must call rsCStrRegexDestruct() afterwards. */ rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *rc) { regex_t **cache = (regex_t **)rc; int ret; DEFiRet; assert(pCS1 != NULL); assert(psz != NULL); assert(cache != NULL); if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { if (*cache == NULL) { *cache = calloc(1, sizeof(regex_t)); int errcode; if ((errcode = regexp.regcomp(*cache, (char *)rsCStrGetSzStrNoNULL(pCS1), (iType == 1 ? REG_EXTENDED : 0) | REG_NOSUB))) { char errbuff[512]; regexp.regerror(errcode, *cache, errbuff, sizeof(errbuff)); LogError(0, NO_ERRCODE, "Error in regular expression: %s\n", errbuff); ABORT_FINALIZE(RS_RET_NOT_FOUND); } } ret = regexp.regexec(*cache, (char *)psz, 0, NULL, 0); if (ret != 0) ABORT_FINALIZE(RS_RET_NOT_FOUND); } else { ABORT_FINALIZE(RS_RET_NOT_FOUND); } finalize_it: RETiRet; } /* free a cached compiled regex * Caller must provide a pointer to a buffer that was created by * rsCStrSzStrMatchRegexCache() */ void rsCStrRegexDestruct(void *rc) { regex_t **cache = rc; assert(cache != NULL); assert(*cache != NULL); if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { regexp.regfree(*cache); free(*cache); *cache = NULL; } } /* compare a rsCStr object with a classical sz string. This function * is almost identical to rsCStrZsStrCmp(), but it also takes an offset * to the CStr object from where the comparison is to start. * I have thought quite a while if it really makes sense to more or * less duplicate the code. After all, if you call it with an offset of * zero, the functionality is exactly the same. So it looks natural to * just have a single function. However, supporting the offset requires * some (few) additional integer operations. While they are few, they * happen at places in the code that is run very frequently. All in all, * I have opted for performance and thus duplicated the code. I hope * this is a good, or at least acceptable, compromise. * rgerhards, 2005-09-26 * This function also has an offset-pointer which allows one to * specify *where* the compare operation should begin in * the CStr. If everything is to be compared, it must be set * to 0. If some leading bytes are to be skipped, it must be set * to the first index that is to be compared. It must not be * set higher than the string length (this is considered a * program bug and will lead to unpredictable results and program aborts). * rgerhards 2005-09-26 */ int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(iOffset < pCS1->iStrLen); assert(iLenSz == strlen((char *)psz)); /* just make sure during debugging! */ if ((pCS1->iStrLen - iOffset) == iLenSz) { /* we are using iLenSz below, because the lengths * are equal and iLenSz is faster to access */ if (iLenSz == 0) { return 0; /* zero-sized strings are equal ;) */ } else { /* we now have two non-empty strings of equal * length, so we need to actually check if they * are equal. */ return memcmp(pCS1->pBuf + iOffset, psz, iLenSz); } } else { return pCS1->iStrLen - iOffset - iLenSz; } } /* compare a rsCStr object with a classical sz string. * Just like rsCStrCStrCmp, just for a different data type. * There must not only the sz string but also its length be * provided. If the caller does not know the length he can * call with * rsCstrSzStrCmp(pCS, psz, strlen((char*)psz)); * we are not doing the strlen((char*)) ourselfs as the caller might * already know the length and in such cases we can save the * overhead of doing it one more time (strelen() is costly!). * The bottom line is that the provided length MUST be correct! * The to sz string pointer must not be NULL! * rgerhards 2005-09-26 */ int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz) { rsCHECKVALIDOBJECT(pCS1, OIDrsCStr); assert(psz != NULL); assert(iLenSz == strlen((char *)psz)); /* just make sure during debugging! */ if (pCS1->iStrLen == iLenSz) if (iLenSz == 0) return 0; /* zero-sized strings are equal ;) */ else return strncmp((char *)pCS1->pBuf, (char *)psz, iLenSz); else return (ssize_t)pCS1->iStrLen - (ssize_t)iLenSz; } /* Locate the first occurrence of this rsCStr object inside a standard sz string. * Returns the offset (0-bound) of this first occurrence. If not found, -1 is * returned. Both parameters MUST be given (NULL is not allowed). * rgerhards 2005-09-19 */ int ATTR_NONNULL(1, 2) rsCStrLocateInSzStr(cstr_t *const pThis, uchar *const sz) { size_t i; size_t iMax; size_t len_sz = ustrlen(sz); int bFound; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); assert(sz != NULL); if (pThis->iStrLen == 0) return 0; if (pThis->iStrLen > len_sz) return -1; /* compute the largest index where a match could occur - after all, * the to-be-located string must be able to be present in the * searched string (it needs its size ;)). */ iMax = len_sz - pThis->iStrLen; bFound = 0; i = 0; while (i <= iMax && !bFound) { size_t iCheck; uchar *pComp = sz + i; for (iCheck = 0; iCheck < pThis->iStrLen; ++iCheck) if (*(pComp + iCheck) != *(pThis->pBuf + iCheck)) break; if (iCheck == pThis->iStrLen) bFound = 1; /* found! - else it wouldn't be equal */ else ++i; /* on to the next try */ } return (bFound ? (int)i : -1); } /* our exit function. TODO: remove once converted to a class * rgerhards, 2008-03-11 */ rsRetVal strExit(void) { DEFiRet; objRelease(regexp, LM_REGEXP_FILENAME); RETiRet; } /* our init function. TODO: remove once converted to a class */ rsRetVal strInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/wtp.h0000644000000000000000000000013215241075234015210 xustar0030 mtime=1787067036.613578444 30 atime=1787067036.760581197 30 ctime=1787067794.389724962 rsyslog-8.2608.0/runtime/wtp.h0000664000175000017500000001241315241075234014655 0ustar00rgerrger/* Definition of the worker thread pool (wtp) object. * * Copyright 2008-2018 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef WTP_H_INCLUDED #define WTP_H_INCLUDED #include #include "obj.h" #include "atomic.h" /* states for worker threads. * important: they need to be increasing with all previous state bits * set. That is because we can only atomically or a value! */ #define WRKTHRD_STOPPED 0 #define WRKTHRD_INITIALIZING 1 #define WRKTHRD_RUNNING 3 #define WRKTHRD_WAIT_JOIN 7 /* possible states of a worker thread pool */ typedef enum { wtpState_RUNNING = 0, /* runs in regular mode */ wtpState_SHUTDOWN = 1, /* worker threads shall shutdown when idle */ wtpState_SHUTDOWN_IMMEDIATE = 2 /* worker threads shall shutdown ASAP, even if not idle */ } wtpState_t; /* the worker thread pool (wtp) object */ struct wtp_s { BEGINobjInstance ; wtpState_t wtpState; int iNumWorkerThreads; /* number of worker threads to use */ int iCurNumWrkThrd; /* current number of active worker threads */ struct wti_s **pWrkr; /* array with control structure for the worker thread(s) associated with this wtp */ int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */ int toFirstWrkShutdown; /* slot-zero override, -2 means use toWrkShutdown */ rsRetVal (*pConsumer)(void *); /* user-supplied consumer function for dewtpd messages */ /* synchronization variables */ pthread_mutex_t mutWtp; /* mutex for the wtp's thread management */ pthread_cond_t condThrdInitDone; /* signalled when a new thread is ready for work */ pthread_cond_t condThrdTrm; /* signalled when threads terminate */ /* end sync variables */ /* user objects */ void *pUsr; /* pointer to user object (in this case, the queue the wtp belongs to) */ pthread_attr_t attrThrd; /* attribute for new threads (created just once and cached here) */ pthread_mutex_t *pmutUsr; rsRetVal (*pfChkStopWrkr)(void *pUsr, int); rsRetVal (*pfGetDeqBatchSize)(void *pUsr, int *); /* obtains max dequeue count from queue config */ rsRetVal (*pfObjProcessed)(void *pUsr, wti_t *pWti); /* indicate user object is processed */ rsRetVal (*pfRateLimiter)(void *pUsr); rsRetVal (*pfDoWork)(void *pUsr, void *pWti); rsRetVal (*pfIdleTimeout)(void *pUsr); sbool bAllowFirstWorkerToTimeout; /* end user objects */ uchar *pszDbgHdr; /* header string for debug messages */ DEF_ATOMIC_HELPER_MUT(mutCurNumWrkThrd); DEF_ATOMIC_HELPER_MUT(mutWtpState); }; /* some symbolic constants for easier reference */ #define DENY_WORKER_START_DURING_SHUTDOWN 0 #define PERMIT_WORKER_START_DURING_SHUTDOWN 1 /* prototypes */ rsRetVal wtpConstruct(wtp_t **ppThis); rsRetVal wtpConstructFinalize(wtp_t *pThis); rsRetVal wtpDestruct(wtp_t **ppThis); rsRetVal wtpAdviseMaxWorkers(wtp_t *pThis, int nMaxWrkr, const int permit_during_shutdown); rsRetVal wtpProcessThrdChanges(wtp_t *pThis); rsRetVal wtpChkStopWrkr(wtp_t *pThis, int bLockUsrMutex); rsRetVal wtpSetState(wtp_t *pThis, wtpState_t iNewState); /** Wake every existing worker without creating a stopped worker. * * The caller must hold the pool's pmutUsr mutex so the queue predicate and * pthread condition signal cannot race. The helper serializes only the worker * table walk with mutWtp; it does not acquire pmutUsr itself. */ rsRetVal wtpWakeupAllWrkr(wtp_t *pThis); rsRetVal wtpCancelAll(wtp_t *pThis, const uchar *const cancelobj); rsRetVal wtpSetDbgHdr(wtp_t *pThis, uchar *pszMsg, size_t lenMsg); rsRetVal wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *ptTimeout); PROTOTYPEObjClassInit(wtp); PROTOTYPEObjClassExit(wtp); PROTOTYPEpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal (*pVal)(void *, int)); PROTOTYPEpropSetMethFP(wtp, pfRateLimiter, rsRetVal (*pVal)(void *)); PROTOTYPEpropSetMethFP(wtp, pfGetDeqBatchSize, rsRetVal (*pVal)(void *, int *)); PROTOTYPEpropSetMethFP(wtp, pfDoWork, rsRetVal (*pVal)(void *, void *)); PROTOTYPEpropSetMethFP(wtp, pfObjProcessed, rsRetVal (*pVal)(void *, wti_t *)); PROTOTYPEpropSetMethFP(wtp, pfIdleTimeout, rsRetVal (*pVal)(void *)); PROTOTYPEpropSetMeth(wtp, bAllowFirstWorkerToTimeout, sbool); PROTOTYPEpropSetMeth(wtp, toWrkShutdown, long); PROTOTYPEpropSetMeth(wtp, toFirstWrkShutdown, long); PROTOTYPEpropSetMeth(wtp, wtpState, wtpState_t); PROTOTYPEpropSetMeth(wtp, iMaxWorkerThreads, int); PROTOTYPEpropSetMeth(wtp, pUsr, void *); PROTOTYPEpropSetMeth(wtp, iNumWorkerThreads, int); PROTOTYPEpropSetMethPTR(wtp, pmutUsr, pthread_mutex_t); #endif /* #ifndef WTP_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/debug.c0000644000000000000000000000013215216464436015467 xustar0030 mtime=1782212894.020266087 30 atime=1787067618.055438106 30 ctime=1787067794.343724104 rsyslog-8.2608.0/runtime/debug.c0000664000175000017500000003706615216464436015147 0ustar00rgerrger/* debug.c * * This file proides debug support. * * File begun on 2008-01-22 by RGerhards * * Some functions are controlled by environment variables: * * RSYSLOG_DEBUGLOG if set, a debug log file is written to that location * RSYSLOG_DEBUG specific debug options * * For details, visit doc/debug.html * * Copyright 2008-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" /* autotools! */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SYSCALL_H #include #endif #if _POSIX_TIMERS <= 0 #include #endif #include "rsyslog.h" #include "debug.h" #include "cfsysline.h" #include "obj.h" /* static data (some time to be replaced) */ DEFobjCurrIf(obj) int Debug = DEBUG_OFF; /* debug flag - read-only after startup */ int debugging_on = 0; /* read-only, except on sig USR1 */ int dbgTimeoutToStderr = 0; static int bPrintTime = 1; /* print a timestamp together with debug message */ static int bOutputTidToStderr = 0; /* output TID to stderr on thread creation */ char *pszAltDbgFileName = NULL; /* if set, debug output is *also* sent to here */ int altdbg = -1; /* and the handle for alternate debug output */ int stddbg = 1; /* the handle for regular debug output, set to stdout if not forking, -1 otherwise */ static uint64_t dummy_errcount = 0; /* just to avoid some static analyzer complaints */ static pthread_key_t keyThrdName; /* output the current thread ID to "relevant" places * (what "relevant" means is determinded by various ways) */ void dbgOutputTID(char *name) { #if defined(__APPLE__) uint64_t tid; if (pthread_threadid_np(NULL, &tid) == 0) { if (bOutputTidToStderr) fprintf(stderr, "thread tid %llu, name '%s'\n", (unsigned long long)tid, name); DBGPRINTF("thread created, tid %llu, name '%s'\n", (unsigned long long)tid, name); } #elif defined(HAVE_SYSCALL) && defined(HAVE_SYS_gettid) if (bOutputTidToStderr) fprintf(stderr, "thread tid %u, name '%s'\n", (unsigned)syscall(SYS_gettid), name); DBGPRINTF("thread created, tid %u, name '%s'\n", (unsigned)syscall(SYS_gettid), name); #else const unsigned long tid = (unsigned long)pthread_self(); if (bOutputTidToStderr) fprintf(stderr, "thread pthread id %lu, name '%s'\n", tid, name); DBGPRINTF("thread created, pthread id %lu, name '%s'\n", tid, name); #endif } /* build a string with the thread name. If none is set, the thread ID is * used instead. Caller must provide buffer space. */ static void ATTR_NONNULL() dbgGetThrdName(char *const pszBuf, const size_t lenBuf, const pthread_t thrdID) { assert(pszBuf != NULL); const char *const thrdName = pthread_getspecific(keyThrdName); if (thrdName == NULL) { snprintf(pszBuf, lenBuf, "%lx", (long)thrdID); } else { snprintf(pszBuf, lenBuf, "%-15s", thrdName); } } /* set a name for the current thread */ void ATTR_NONNULL() dbgSetThrdName(const uchar *const pszName) { (void)pthread_setspecific(keyThrdName, strdup((char *)pszName)); } /* destructor for thread name (called by pthreads!) */ static void dbgThrdNameDestruct(void *arg) { free(arg); } /* write the debug message. This is a helper to dbgprintf and dbgoprint which * contains common code. added 2008-09-26 rgerhards * Note: We need to split the function due to the bad nature of POSIX * cancel cleanup handlers. */ static void DBGL_UNUSED dbgprint(obj_t *pObj, char *pszMsg, const char *pszFileName, const size_t lenMsg) { uchar *pszObjName = NULL; static pthread_t ptLastThrdID = 0; static int bWasNL = 0; char pszThrdName[64]; /* 64 is to be on the safe side, anything over 20 is bad... */ char pszWriteBuf[32 * 1024]; size_t lenCopy; size_t offsWriteBuf = 0; size_t lenWriteBuf; struct timespec t; #if _POSIX_TIMERS <= 0 struct timeval tv; #endif if (pObj != NULL) { pszObjName = obj.GetName(pObj); } /* The bWasNL handler does not really work. It works if no thread * switching occurs during non-NL messages. Else, things are messed * up. Anyhow, it works well enough to provide useful help during * getting this up and running. It is questionable if the extra effort * is worth fixing it, giving the limited appliability. -- rgerhards, 2005-10-25 * I have decided that it is not worth fixing it - especially as it works * pretty well. -- rgerhards, 2007-06-15 */ if (ptLastThrdID != pthread_self()) { if (!bWasNL) { pszWriteBuf[0] = '\n'; offsWriteBuf = 1; bWasNL = 1; } ptLastThrdID = pthread_self(); } dbgGetThrdName(pszThrdName, sizeof(pszThrdName), ptLastThrdID); if (bWasNL) { if (bPrintTime) { #if _POSIX_TIMERS > 0 /* this is the "regular" code */ clock_gettime(CLOCK_REALTIME, &t); #else gettimeofday(&tv, NULL); t.tv_sec = tv.tv_sec; t.tv_nsec = tv.tv_usec * 1000; #endif lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf, "%4.4ld.%9.9ld:", (long)(t.tv_sec % 10000), t.tv_nsec); offsWriteBuf += lenWriteBuf; } lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf, "%s: ", pszThrdName); offsWriteBuf += lenWriteBuf; /* print object name header if we have an object */ if (pszObjName != NULL) { lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf, "%s: ", pszObjName); offsWriteBuf += lenWriteBuf; } lenWriteBuf = snprintf(pszWriteBuf + offsWriteBuf, sizeof(pszWriteBuf) - offsWriteBuf, "%s: ", pszFileName); offsWriteBuf += lenWriteBuf; } if (lenMsg > sizeof(pszWriteBuf) - offsWriteBuf) lenCopy = sizeof(pszWriteBuf) - offsWriteBuf; else lenCopy = lenMsg; memcpy(pszWriteBuf + offsWriteBuf, pszMsg, lenCopy); offsWriteBuf += lenCopy; /* the write is included in an "if" just to silence compiler * warnings. Here, we really don't care if the write fails, we * have no good response to that in any case... -- rgerhards, 2012-11-28 */ if (stddbg != -1) { if (write(stddbg, pszWriteBuf, offsWriteBuf)) { ++dummy_errcount; } } if (altdbg != -1) { if (write(altdbg, pszWriteBuf, offsWriteBuf)) { ++dummy_errcount; } } bWasNL = (pszMsg[lenMsg - 1] == '\n') ? 1 : 0; } static int DBGL_UNUSED checkDbgFile(const char *srcname) { if (glblDbgFilesNum == 0) { return 1; } if (glblDbgWhitelist) { if (bsearch(srcname, glblDbgFiles, glblDbgFilesNum, sizeof(char *), bs_arrcmp_glblDbgFiles) == NULL) { return 0; } else { return 1; } } else { if (bsearch(srcname, glblDbgFiles, glblDbgFilesNum, sizeof(char *), bs_arrcmp_glblDbgFiles) != NULL) { return 0; } else { return 1; } } } /* print some debug output when an object is given * This is mostly a copy of dbgprintf, but I do not know how to combine it * into a single function as we have variable arguments and I don't know how to call * from one vararg function into another. I don't dig in this, it is OK for the * time being. -- rgerhards, 2008-01-29 */ #ifndef DEBUGLESS void r_dbgoprint(const char *srcname, obj_t *pObj, const char *fmt, ...) { va_list ap; char pszWriteBuf[32 * 1024]; size_t lenWriteBuf; if (!(Debug && debugging_on)) return; if (!checkDbgFile(srcname)) { return; } va_start(ap, fmt); lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap); va_end(ap); if (lenWriteBuf >= sizeof(pszWriteBuf)) { /* prevent buffer overrruns and garbagge display */ pszWriteBuf[sizeof(pszWriteBuf) - 5] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 4] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 3] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 2] = '\n'; pszWriteBuf[sizeof(pszWriteBuf) - 1] = '\0'; lenWriteBuf = sizeof(pszWriteBuf); } dbgprint(pObj, pszWriteBuf, srcname, lenWriteBuf); } #endif /* print some debug output when no object is given * WARNING: duplicate code, see dbgoprint above! */ #ifndef DEBUGLESS void r_dbgprintf(const char *srcname, const char *fmt, ...) { va_list ap; char pszWriteBuf[32 * 1024]; size_t lenWriteBuf; if (!(Debug && debugging_on)) { return; } if (!checkDbgFile(srcname)) { return; } va_start(ap, fmt); lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap); va_end(ap); if (lenWriteBuf >= sizeof(pszWriteBuf)) { /* prevent buffer overrruns and garbagge display */ pszWriteBuf[sizeof(pszWriteBuf) - 5] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 4] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 3] = '.'; pszWriteBuf[sizeof(pszWriteBuf) - 2] = '\n'; pszWriteBuf[sizeof(pszWriteBuf) - 1] = '\0'; lenWriteBuf = sizeof(pszWriteBuf); } dbgprint(NULL, pszWriteBuf, srcname, lenWriteBuf); } #endif /* support system to set debug options at runtime */ /* parse a param/value pair from the current location of the * option string. Returns 1 if an option was found, 0 * otherwise. 0 means there are NO MORE options to be * processed. -- rgerhards, 2008-02-28 */ static int ATTR_NONNULL() dbgGetRTOptNamVal(const uchar **const ppszOpt, uchar **const ppOptName) { assert(ppszOpt != NULL); assert(*ppszOpt != NULL); int bRet = 0; const uchar *p = *ppszOpt; size_t i; static uchar optname[128] = ""; /* skip whitespace */ while (*p && isspace(*p)) ++p; /* name: up until whitespace */ i = 0; while (i < (sizeof(optname) - 1) && *p && !isspace(*p)) { optname[i++] = *p++; } if (i > 0) { bRet = 1; optname[i] = '\0'; } /* done */ *ppszOpt = p; *ppOptName = optname; return bRet; } /* report fd used for debug log. This is needed in case of * auto-backgrounding, where the debug log shall not be closed. */ int dbgGetDbglogFd(void) { return altdbg; } /* read in the runtime options * rgerhards, 2008-02-28 */ static void dbgGetRuntimeOptions(void) { const uchar *pszOpts; uchar *optname; /* set some defaults */ if ((pszOpts = (uchar *)getenv("RSYSLOG_DEBUG")) != NULL) { /* we have options set, so let's process them */ while (dbgGetRTOptNamVal(&pszOpts, &optname)) { if (!strcasecmp((char *)optname, "help")) { fprintf(stderr, "rsyslogd " VERSION " runtime debug support - help requested, " "rsyslog terminates\n\nenvironment variables:\n" "additional logfile: export RSYSLOG_DEBUGFILE=\"/path/to/file\"\n" "to set: export RSYSLOG_DEBUG=\"cmd cmd cmd\"\n\n" "Commands are (all case-insensitive):\n" "help (this list, terminates rsyslogd)\n" "NoLogTimestamp\n" "Nostdout\n" "OutputTidToStderr\n" "DebugOnDemand - enables debugging on USR1, but does not turn on output\n" "\nSee debug.html in your doc set or https://www.rsyslog.com for details\n"); exit(1); } else if (!strcasecmp((char *)optname, "debug")) { /* this is earlier in the process than the -d option, as such it * allows us to spit out debug messages from the very beginning. */ Debug = DEBUG_FULL; debugging_on = 1; } else if (!strcasecmp((char *)optname, "debugondemand")) { /* Enables debugging, but turns off debug output */ Debug = DEBUG_ONDEMAND; debugging_on = 1; dbgprintf( "Note: debug on demand turned on via configuration file, " "use USR1 signal to activate.\n"); debugging_on = 0; } else if (!strcasecmp((char *)optname, "nologtimestamp")) { bPrintTime = 0; } else if (!strcasecmp((char *)optname, "nostdout")) { stddbg = -1; } else if (!strcasecmp((char *)optname, "outputtidtostderr")) { bOutputTidToStderr = 1; } else { fprintf(stderr, "rsyslogd " VERSION " error: invalid debug option '%s' " "- ignored\n", optname); } } } } void dbgSetDebugLevel(int level) { Debug = level; debugging_on = (level == DEBUG_FULL) ? 1 : 0; } void dbgSetDebugFile(uchar *fn) { if (altdbg != -1) { dbgprintf("switching to debug file %s\n", fn); close(altdbg); } if ((altdbg = open((char *)fn, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) { fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n", strerror(errno)); } } /* end support system to set debug options at runtime */ rsRetVal dbgClassInit(void) { rsRetVal iRet; /* do not use DEFiRet, as this makes calls into the debug system! */ (void)pthread_key_create(&keyThrdName, dbgThrdNameDestruct); /* while we try not to use any of the real rsyslog code (to avoid infinite loops), we * need to have the ability to query object names. Thus, we need to obtain a pointer to * the object interface. -- rgerhards, 2008-02-29 */ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ const char *dbgto2stderr; dbgto2stderr = getenv("RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR"); dbgTimeoutToStderr = (dbgto2stderr != NULL && !strcmp(dbgto2stderr, "on")) ? 1 : 0; if (dbgTimeoutToStderr) { fprintf(stderr, "rsyslogd: NOTE: RSYSLOG_DEBUG_TIMEOUTS_TO_STDERR activated\n"); } dbgGetRuntimeOptions(); /* init debug system from environment */ pszAltDbgFileName = getenv("RSYSLOG_DEBUGLOG"); if (pszAltDbgFileName != NULL) { /* we have a secondary file, so let's open it) */ if ((altdbg = open(pszAltDbgFileName, O_WRONLY | O_CREAT | O_TRUNC | O_NOCTTY | O_CLOEXEC, S_IRUSR | S_IWUSR)) == -1) { fprintf(stderr, "alternate debug file could not be opened, ignoring. Error: %s\n", strerror(errno)); } } dbgSetThrdName((uchar *)"main thread"); finalize_it: return (iRet); } rsRetVal dbgClassExit(void) { pthread_key_delete(keyThrdName); if (altdbg != -1) close(altdbg); return RS_RET_OK; } rsyslog-8.2608.0/runtime/PaxHeaders/statsobj.h0000644000000000000000000000013115241075234016226 xustar0030 mtime=1787067036.610578388 29 atime=1787067036.75758114 30 ctime=1787067794.359724403 rsyslog-8.2608.0/runtime/statsobj.h0000664000175000017500000003233415241075234015700 0ustar00rgerrger/* The statsobj object. * * Copyright 2010-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file statsobj.h * @brief Interface of the rsyslog statistics object * * A statistics object (statsobj_t) represents a set of counters that * describe activity within a subsystem. Each object keeps a doubly * linked list of counters and all objects are maintained in a global * list protected by a mutex. The counters are either 64 bit integers * (ctrType_IntCtr) or plain int values (ctrType_Int) and can be marked * resettable. Statistics are only gathered while the global * ::GatherStats flag is non-zero. * * Counters can be reported in multiple formats via the GetAllStatsLines() * interface: * - ::statsFmt_Legacy classic key=value pairs * - ::statsFmt_JSON valid JSON structures * - ::statsFmt_JSON_ES JSON with dot replacement for Elasticsearch * - ::statsFmt_CEE Project Lumberjack / CEE format * - ::statsFmt_Prometheus Prometheus text exposition format * * The caller supplies a callback that receives each generated line. * After emission counters flagged with CTR_FLAG_RESETTABLE may be * cleared if requested. */ #ifndef INCLUDED_STATSOBJ_H #define INCLUDED_STATSOBJ_H #include "atomic.h" /* The following data item is somewhat dirty, in that it does not follow * our usual object calling conventions. However, much like with "Debug", we * do this to gain speed. If we finally come to a platform that does not * provide resolution of names for dynamically loaded modules, we need to find * a work-around, but until then, we use the direct access. * If set to 0, statistics are not gathered, otherwise they are. */ extern int GatherStats; /* our basic counter type -- need 32 bit on 32 bit platform. * IMPORTANT: this type *MUST* be supported by atomic instructions! */ typedef uint64 intctr_t; /* counter types */ typedef enum statsCtrType_e { ctrType_IntCtr, ctrType_Int } statsCtrType_t; /* stats line format types */ typedef enum statsFmtType_e { statsFmt_Legacy, statsFmt_JSON, statsFmt_JSON_ES, statsFmt_CEE, /** * Prometheus text�exposition format: * For each counter, emit: * # HELP _ (optional generic text) * # TYPE _ counter * _ */ statsFmt_Prometheus } statsFmtType_t; /* counter flags */ #define CTR_FLAG_NONE 0 #define CTR_FLAG_RESETTABLE 1 #define CTR_FLAG_MUST_RESET 2 /* statsobj flags */ #define STATSOBJ_FLAG_NONE 0 #define STATSOBJ_FLAG_DO_PREPEND 1 /** * Callback type for native counter iteration via GetAllCounters(). * * @param ctx User context pointer passed to GetAllCounters() * @param obj_name Name of the statsobj instance (may be NULL/empty) * @param obj_origin Origin of the statsobj (e.g., "resource-usage", "core.queue") * @param ctr_name Name of the counter * @param ctr_type Type of counter (ctrType_IntCtr or ctrType_Int) * @param value Current counter value (read atomically for IntCtr, best-effort for Int) * @param flags Counter flags (CTR_FLAG_RESETTABLE, etc.) * @return RS_RET_OK to continue iteration, error code to abort * * THREAD SAFETY: * - ctrType_IntCtr: value is read atomically (uint64 on aligned address) * - ctrType_Int: value is read without application lock; may be stale but acceptable * for monitoring. These counters are typically gauges (queue size, open files) * protected by application-level mutexes that the stats system cannot acquire. * * LOCKING CONSTRAINT: * - The counter list mutex is HELD during callback invocation to prevent concurrent * list modification. Callbacks MUST complete quickly and MUST NOT call back into * statsobj or deadlock will occur. */ typedef rsRetVal (*statsobj_counter_cb_t)(void *ctx, const uchar *obj_name, const uchar *obj_origin, const uchar *ctr_name, statsCtrType_t ctr_type, uint64_t value, int8_t flags); /* helper entity, the counter */ typedef struct ctr_s { uchar *name; statsCtrType_t ctrType; union { intctr_t *pIntCtr; int *pInt; } val; int8_t flags; struct ctr_s *next, *prev; } ctr_t; /* the statsobj object */ struct statsobj_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ uchar *name; uchar *origin; uchar *reporting_ns; statsobj_read_notifier_t read_notifier; void *read_notifier_ctx; pthread_mutex_t mutCtr; /* to guard counter linked-list ops */ ctr_t *ctrRoot; /* doubly-linked list of statsobj counters */ ctr_t *ctrLast; int flags; /* used to link ourselves together */ statsobj_t *prev; statsobj_t *next; }; struct sender_stats { const uchar *sender; uint64_t nMsgs; time_t lastSeen; }; /* interfaces */ BEGINinterface(statsobj) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(statsobj); rsRetVal (*Construct)(statsobj_t **ppThis); rsRetVal (*ConstructFinalize)(statsobj_t *pThis); rsRetVal (*Destruct)(statsobj_t **ppThis); rsRetVal (*SetName)(statsobj_t *pThis, uchar *name); rsRetVal (*SetOrigin)(statsobj_t *pThis, uchar *name); /* added v12, 2014-09-08 */ rsRetVal (*SetReadNotifier)(statsobj_t *pThis, statsobj_read_notifier_t notifier, void *ctx); rsRetVal (*SetReportingNamespace)(statsobj_t *pThis, uchar *ns); void (*SetStatsObjFlags)(statsobj_t *pThis, int flags); rsRetVal (*GetAllStatsLines)(rsRetVal (*cb)(void *, const char *), void *usrptr, statsFmtType_t fmt, int8_t bResetCtr); rsRetVal (*GetAllCounters)(statsobj_counter_cb_t cb, void *ctx); /** * Encode a complete metric name for Prometheus text and Remote Write. * * @param raw_name non-NULL NUL-terminated metric name to encode * @param encoded_name non-NULL output location for the heap allocation * @return RS_RET_OK on success, RS_RET_PARAM_ERROR for NULL arguments, * or RS_RET_OUT_OF_MEMORY on allocation failure */ rsRetVal (*EncodePrometheusMetricName)(const uchar *raw_name, char **encoded_name); /** * @brief Register a counter value with a stats object. * * The counter name is duplicated internally; the caller retains ownership * of @p ctrName and may free/modify it after this call returns. * * @param pThis target stats object * @param ctrName counter name (copied internally) * @param ctrType counter type * @param flags counter flags * @param pCtr pointer to caller-owned counter storage * * @note The storage referenced by @p pCtr must remain valid for at least * the lifetime of the registered counter entry in @p pThis. */ rsRetVal (*AddCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr); /** * @brief Register a managed counter entry and optionally link it into * the stats object's counter list. * * The counter name is duplicated internally; the caller retains ownership * of @p ctrName and may free/modify it after this call returns. * * On success, @p ref receives the created entry handle, which can be used * with `DestructCounter()` (if linked) or `DestructUnlinkedCounter()` * (if not linked) according to the chosen lifecycle. * * @param pThis target stats object * @param ctrName counter name (copied internally) * @param ctrType counter type * @param flags counter flags * @param pCtr pointer to caller-owned counter storage * @param ref out: created counter entry handle * @param linked if non-zero, entry is linked into @p pThis and follows * object lifecycle unless explicitly destructed * * @note The storage referenced by @p pCtr must remain valid for at least * the lifetime of the created counter entry. */ rsRetVal (*AddManagedCounter)(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr, ctr_t **ref, int8_t linked); rsRetVal (*AddPreCreatedCtr)(statsobj_t *pThis, ctr_t *ctr); void (*DestructCounter)(statsobj_t *pThis, ctr_t *ref); void (*DestructUnlinkedCounter)(ctr_t *ctr); ctr_t *(*UnlinkAllCounters)(statsobj_t *pThis); rsRetVal (*EnableStats)(void); ENDinterface(statsobj) #define statsobjCURR_IF_VERSION 16 /* increment whenever you change the interface structure! */ /* Changes * v2-v9 rserved for future use in "older" version branches * v10, 2012-04-01: GetAllStatsLines got fmt parameter * v11, 2013-09-07: - add "flags" to AddCounter API * - GetAllStatsLines got parameter telling if ctrs shall be reset * v13, 2016-05-19: GetAllStatsLines cb data type changed (char* instead of cstr) * v14, 2026-02-01: Add GetAllCounters() native counter iteration API * v15, 2026-06-23: AddPreCreatedCtr returns rsRetVal for lock failure propagation * v16, 2026-07-15: add EncodePrometheusMetricName() for shared exporter name escaping */ /* prototypes */ PROTOTYPEObjFull(statsobj); PROTOTYPEObjDebugPrint(statsobj); rsRetVal statsRecordSender(const uchar *sender, unsigned nMsgs, time_t lastSeen); /* checkGoneAwaySenders() is part of this module because all it needs is * done by this module, so even though it's own processing is not directly * related to stats, it makes sense to do it here... -- rgerhards, 2016-02-01 */ void checkGoneAwaySenders(time_t); /* macros to handle stats counters * These are to be used by "counter providers". Note that we MUST * specify the mutex name, even though at first it looks like it * could be automatically be generated via e.g. "mut##ctr". * Unfortunately, this does not work if counter is e.g. "pThis->ctr". * So we decided, for clarity, to always insist on specifying the mutex * name (after all, it's just a few more keystrokes...). * -------------------------------------------------------------------- * NOTE WELL * -------------------------------------------------------------------- * There are actually two types of stats counters: "regular" counters, * which are only used for stats purposes and "dual" counters, which * are primarily used for other purposes but can be included in stats * as well. ALL regular counters MUST be initialized with * STATSCOUNTER_INIT and only be modified by STATSCOUNTER_* functions. * They MUST NOT be used for any other purpose (if this seems to make * sense, consider changing it to a dual counter). * Dual counters are somewhat dangerous in that a single variable is * used for two purposes: the actual application need and stats * counting. However, this is supported for performance reasons, as it * provides insight into the inner engine workings without need for * additional counters (and their maintenance code). Dual counters * MUST NOT be modified by STATSCOUNTER_* functions. Most importantly, * it is expected that the actua application code provides proper * (enough) synchronized access to these counters. Most importantly, * this means they have NO stats-system mutex associated to them. * * The interface function AddCounter() is a read-only function. It * only provides the stats subsystem with a reference to a counter. * It is irrelevant if the counter is a regular or dual one. For that * reason, AddCounter() must not modify the counter contents, as in * the case of a dual counter application code may be broken. */ #define STATSCOUNTER_DEF(ctr, mut) \ intctr_t ctr; \ DEF_ATOMIC_HELPER_MUT64(mut); #define STATSCOUNTER_INIT(ctr, mut) \ INIT_ATOMIC_HELPER_MUT64(mut); \ ctr = 0; #define STATSCOUNTER_ENABLED() (PREFER_FETCH_32BIT(GatherStats) != 0) #define STATSCOUNTER_INC(ctr, mut) \ if (STATSCOUNTER_ENABLED()) ATOMIC_INC_uint64_RELAXED(&ctr, &mut); #define STATSCOUNTER_ADD(ctr, mut, delta) \ if (STATSCOUNTER_ENABLED()) ATOMIC_ADD_uint64_RELAXED(&ctr, &mut, delta); #define STATSCOUNTER_DEC(ctr, mut) \ if (STATSCOUNTER_ENABLED()) ATOMIC_DEC_uint64_RELAXED(&ctr, &mut); /* the next macro works only if the variable is already guarded * by mutex (or the users risks a wrong result). It is assumed * that there are not concurrent operations that modify the counter. */ #define STATSCOUNTER_SETMAX_NOMUT(ctr, newmax) \ if (STATSCOUNTER_ENABLED() && ((newmax) > (ctr))) ctr = newmax; #endif /* #ifndef INCLUDED_STATSOBJ_H */rsyslog-8.2608.0/runtime/PaxHeaders/libossl.h0000644000000000000000000000013215132411300016030 xustar0030 mtime=1768559296.265885624 30 atime=1782715518.783788755 30 ctime=1787067794.236722111 rsyslog-8.2608.0/runtime/libossl.h0000666000175000017500000000526715132411300015510 0ustar00rgerrger/* libossl.h - rsyslog's ossl crypto provider support library * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LIBOSSL_H #define INCLUDED_LIBOSSL_H #include #include #include #include struct osslctx_s { uchar* key; size_t keyLen; const EVP_CIPHER* cipher; /* container for algorithm + mode */ }; typedef struct osslctx_s* osslctx; typedef struct osslfile_s* osslfile; /* this describes a file, as far as libgcry is concerned */ struct osslfile_s { // gcry_cipher_hd_t chd; /* cypher handle */ TODO EVP_CIPHER_CTX* chd; size_t blkLength; /* size of low-level crypto block */ uchar* eiName; /* name of .encinfo file */ int fd; /* descriptor of .encinfo file (-1 if not open) */ char openMode; /* 'r': read, 'w': write */ osslctx ctx; uchar* readBuf; int16_t readBufIdx; int16_t readBufMaxIdx; int8_t bDeleteOnClose; /* for queue support, similar to stream subsys */ ssize_t bytesToBlkEnd; /* number of bytes remaining in current crypto block -1 means -> no end (still being writen to, queue files), 0 means -> end of block, new one must be started. */ }; osslctx osslCtxNew(void); void rsosslCtxDel(osslctx ctx); rsRetVal rsosslSetAlgoMode(osslctx ctx, uchar* algorithm); int osslGetKeyFromFile(const char* const fn, char** const key, unsigned* const keylen); int rsosslSetKey(osslctx ctx, unsigned char* key, uint16_t keyLen); rsRetVal osslfileGetBytesLeftInBlock(osslfile gf, ssize_t* left); rsRetVal osslfileDeleteState(uchar* logfn); rsRetVal rsosslInitCrypt(osslctx ctx, osslfile* pgf, uchar* fname, char openMode); rsRetVal rsosslDecrypt(osslfile pF, uchar* buf, size_t* len); rsRetVal rsosslEncrypt(osslfile pF, uchar* buf, size_t* len); int osslfileDestruct(osslfile gf, off64_t offsLogfile); int rsosslInit(void); void rsosslExit(void); // FIXME refactor static inline void __attribute__((unused)) osslfileSetDeleteOnClose(osslfile gf, const int val) { if (gf != NULL) gf->bDeleteOnClose = val; } #endif /* #ifndef INCLUDED_LIBOSSL_H */ rsyslog-8.2608.0/runtime/PaxHeaders/unicode-helper.h0000644000000000000000000000013215216464436017311 xustar0030 mtime=1782212894.042266443 30 atime=1787067616.846415563 30 ctime=1787067794.250722371 rsyslog-8.2608.0/runtime/unicode-helper.h0000664000175000017500000001107115216464436016755 0ustar00rgerrger/* This is the header file for unicode support. * * Currently, this is a dummy module. * The following functions are wrappers which hopefully enable us to move * from 8-bit chars to unicode with relative ease when we finally attack this * * Begun 2009-05-21 RGerhards * * Copyright (C) 2009-2016 by Rainer Gerhards and Adiscon GmbH * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_UNICODE_HELPER_H #define INCLUDED_UNICODE_HELPER_H #include /** * @brief Copy into a fixed-size C-string buffer with bounded read and explicit termination. * * Contract: * - `dst` points to `dst_size` writable bytes. * - `src` points either to a NUL-terminated C string or to at least * `dst_size - 1` readable bytes. * - The helper reads at most `dst_size - 1` bytes from `src`. * - The helper writes at most `dst_size` bytes to `dst`. * - If `dst_size > 0`, `dst` is always NUL-terminated on return. * * Security note: * - This helper is intentionally written so both humans and automated review can * see the bound directly: it uses `memchr(src, '\0', dst_size - 1)` to cap the * source scan and then `memcpy()` only for that bounded length. * - Any claim of overflow is actionable only if the caller violates the pointer * and size contract stated above. * * Unlike `strncpy()`, this helper does not zero-pad the unused tail. Use * `u_memncpy()` when zero-padding semantics are required. * * @return Number of bytes copied, excluding the trailing NUL. */ static inline size_t rs_cstr_copy(char *dst, const char *src, size_t dst_size) { size_t copy_len; const char *const terminator = dst_size > 0 ? (const char *)memchr(src, '\0', dst_size - 1) : NULL; if (dst_size == 0) { return 0; } copy_len = terminator == NULL ? dst_size - 1 : (size_t)(terminator - src); if (copy_len > 0) { memcpy(dst, src, copy_len); } dst[copy_len] = '\0'; return copy_len; } /** * @brief Copy into a fixed-size unsigned-char C-string buffer with bounded read and explicit termination. * * Contract: * - `dst` points to `dst_size` writable bytes. * - `src` points either to a NUL-terminated string or to at least * `dst_size - 1` readable bytes. * - The helper reads at most `dst_size - 1` bytes from `src`. * - The helper writes at most `dst_size` bytes to `dst`. * - If `dst_size > 0`, `dst` is always NUL-terminated on return. * * This is the `unsigned char *` wrapper around `rs_cstr_copy()` and is the * preferred replacement for `strncpy()` when the destination is a fixed-size * `uchar`/byte buffer that is used as a C string. * * @return Number of bytes copied, excluding the trailing NUL. */ static inline size_t u_cstr_copy(unsigned char *dst, const unsigned char *src, size_t dst_size) { return rs_cstr_copy((char *)dst, (const char *)src, dst_size); } static inline void *u_memncpy(void *psz1, const void *psz2, size_t len) { size_t copy_len; const char *const src = (const char *)psz2; char *const dst = (char *)psz1; const void *const terminator = memchr(src, '\0', len); if (len == 0) { return psz1; } copy_len = terminator == NULL ? len : (size_t)((const char *)terminator - src); memcpy(dst, src, copy_len); if (copy_len < len) { memset(dst + copy_len, '\0', len - copy_len); } return psz1; } #define ustrncpy(psz1, psz2, len) u_memncpy((psz1), (psz2), (len)) #define ustrdup(psz) (uchar *)strdup((char *)(psz)) #define ustrcmp(psz1, psz2) (strcmp((const char *)(psz1), (const char *)(psz2))) #define ustrlen(psz) (strlen((const char *)(psz))) #define UCHAR_CONSTANT(x) ((uchar *)(x)) #define CHAR_CONVERT(x) ((char *)(x)) /* Compare values of two instances/configs/queues especially during dynamic config reload */ #define USTR_EQUALS(var) \ ((pOld->var == NULL) ? (pNew->var == NULL) : (pNew->var != NULL && !ustrcmp(pOld->var, pNew->var))) #define NUM_EQUALS(var) (pOld->var == pNew->var) #endif /* multi-include protection */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_ptcp.c0000644000000000000000000000013215241075234016203 xustar0030 mtime=1787067036.604578276 30 atime=1787067036.751581028 30 ctime=1787067794.568728297 rsyslog-8.2608.0/runtime/nsd_ptcp.c0000664000175000017500000012561615241075234015662 0ustar00rgerrger/* nsd_ptcp.c * * An implementation of the nsd interface for plain tcp sockets. * * Copyright 2007-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "parse.h" #include "srUtils.h" #include "obj.h" #include "errmsg.h" #include "net.h" #include "netstrms.h" #include "netstrm.h" #include "nsd_ptcp.h" #include "prop.h" #include "dnscache.h" #include "rsconf.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(netstrms) DEFobjCurrIf(netstrm) DEFobjCurrIf(prop) /* a few deinit helpers */ /* close socket if open (may always be called) */ static void sockClose(int *pSock) { if (*pSock >= 0) { close(*pSock); *pSock = -1; } } /* Standard-Constructor */ BEGINobjConstruct(nsd_ptcp) /* be sure to specify the object type also in END macro! */ pThis->sock = -1; ENDobjConstruct(nsd_ptcp) /* destructor for the nsd_ptcp object */ BEGINobjDestruct(nsd_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsd_ptcp); sockClose(&pThis->sock); if (pThis->remoteIP != NULL) prop.Destruct(&pThis->remoteIP); free(pThis->pRemHostName); ENDobjDestruct(nsd_ptcp) /* Provide access to the sockaddr_storage of the remote peer. This * is needed by the legacy ACL system. --- gerhards, 2008-12-01 */ static rsRetVal GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); assert(ppAddr != NULL); *ppAddr = &(pThis->remAddr); RETiRet; } /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_gtls) who utilize ourselfs * for some of their functionality. -- rgerhards, 2008-04-18 */ static rsRetVal GetSock(nsd_t *pNsd, int *pSock) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; NULL_CHECK(pSock); *pSock = pThis->sock; finalize_it: RETiRet; } /* Set the driver mode. We support no different modes, but allow mode * 0 to be set to be compatible with config file defaults and the other * drivers. * rgerhards, 2008-04-28 */ static rsRetVal SetMode(nsd_t __attribute__((unused)) * pNsd, int mode) { DEFiRet; if (mode != 0) { LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by " "ptcp netstream driver", mode); ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE); } finalize_it: RETiRet; } /* Set the driver cert extended key usage check setting, not supported in ptcp. * jvymazal, 2019-08-16 */ static rsRetVal SetCheckExtendedKeyUsage(nsd_t __attribute__((unused)) * pNsd, int ChkExtendedKeyUsage) { DEFiRet; if (ChkExtendedKeyUsage != 0) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " "not supported by ptcp netstream driver", ChkExtendedKeyUsage); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set the driver name checking strictness, not supported in ptcp. * jvymazal, 2019-08-16 */ static rsRetVal SetPrioritizeSAN(nsd_t __attribute__((unused)) * pNsd, int prioritizeSan) { DEFiRet; if (prioritizeSan != 0) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " "not supported by ptcp netstream driver", prioritizeSan); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set the tls verify depth, not supported in ptcp. * alorbach, 2019-12-20 */ static rsRetVal SetTlsVerifyDepth(nsd_t __attribute__((unused)) * pNsd, int verifyDepth) { nsd_ptcp_t __attribute__((unused)) *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); if (verifyDepth == 0) { FINALIZE; } finalize_it: RETiRet; } /* Set the authentication mode. For us, the following is supported: * anon - no certificate checks whatsoever (discouraged, but supported) * mode == NULL is valid and defaults to anon * Actually, we do not even record the mode right now, because we can * always work in anon mode, only. So there is no point in recording * something if that's the only choice. What the function does is * return an error if something is requested that we can not support. * rgerhards, 2008-05-17 */ static rsRetVal SetAuthMode(nsd_t __attribute__((unused)) * pNsd, uchar *mode) { DEFiRet; if (mode != NULL && strcasecmp((char *)mode, "anon")) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by " "ptcp netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set the PermitExpiredCerts mode. not supported in ptcp * alorbach, 2018-12-20 */ static rsRetVal SetPermitExpiredCerts(nsd_t __attribute__((unused)) * pNsd, uchar *mode) { DEFiRet; if (mode != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts setting not supported by " "ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsCAFile(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: CA File setting not supported by " "ptcp netstream driver - value %s", pszFile); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsCRLFile(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: CRL File setting not supported by " "ptcp netstream driver - value %s", pszFile); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsCAExtraFiles(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: extra CA Files setting not supported by " "ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsKeyFile(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS Key File setting not supported by " "ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsCertFile(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS Cert File setting not supported by " "ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetRemoteSNI(nsd_t __attribute__((unused)) * pNsd, uchar *pszRemoteSNI) { DEFiRet; if (pszRemoteSNI != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: remote SNI setting not supported by " "ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsRevocationCheck(nsd_t __attribute__((unused)) * pNsd, int enabled) { DEFiRet; if (enabled) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS revocation checking not supported by " "ptcp netstream driver (plain TCP has no TLS)"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set priorityString * PascalWithopf 2017-08-18 */ static rsRetVal SetGnutlsPriorityString(nsd_t __attribute__((unused)) * pNsd, uchar *iVal) { DEFiRet; if (iVal != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: " "gnutlsPriorityString '%s' not supported by ptcp netstream " "driver", iVal); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Set the permitted peers. This is a dummy, always returning an * error because we do not support fingerprint authentication. * rgerhards, 2008-05-17 */ static rsRetVal SetPermPeers(nsd_t __attribute__((unused)) * pNsd, permittedPeers_t __attribute__((unused)) * pPermPeers) { DEFiRet; if (pPermPeers != NULL) { LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by ptcp netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); } finalize_it: RETiRet; } /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_gtls) who utilize ourselfs * for some of their functionality. * This function sets the socket -- rgerhards, 2008-04-25 */ static rsRetVal SetSock(nsd_t *pNsd, int sock) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); assert(sock >= 0); pThis->sock = sock; RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); pThis->iKeepAliveIntvl = keepAliveIntvl; RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); pThis->iKeepAliveProbes = keepAliveProbes; RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); pThis->iKeepAliveTime = keepAliveTime; RETiRet; } /* TCP user timeout option */ static rsRetVal SetTcpUserTimeout(nsd_t *pNsd, int tcpUserTimeout) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); pThis->tcp_user_timeout_ms = tcpUserTimeout; RETiRet; } /* abort a connection. This is meant to be called immediately * before the Destruct call. -- rgerhards, 2008-03-24 */ static rsRetVal Abort(nsd_t *pNsd) { struct linger ling; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_ptcp); if ((pThis)->sock != -1) { ling.l_onoff = 1; ling.l_linger = 0; if (setsockopt((pThis)->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) < 0) { dbgprintf("could not set SO_LINGER, errno %d\n", errno); } } RETiRet; } /* Set pRemHost based on the address provided. This is to be called upon accept()ing * a connection request. It must be provided by the socket we received the * message on as well as a NI_MAXHOST size large character buffer for the FQDN. * Please see http://www.hmug.org/man/3/getnameinfo.php (under Caveats) * for some explanation of the code found below. If we detect a malicious * hostname, we return RS_RET_MALICIOUS_HNAME and let the caller decide * on how to deal with that. * rgerhards, 2008-03-31 */ static rsRetVal FillRemHost(nsd_ptcp_t *pThis, struct sockaddr_storage *pAddr) { prop_t *fqdn; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ptcp); assert(pAddr != NULL); CHKiRet(dnscacheLookup(pAddr, &fqdn, NULL, NULL, &pThis->remoteIP)); /* We now have the names, so now let's allocate memory and store them permanently. * (side note: we may hold on to these values for quite a while, thus we trim their * memory consumption) */ if ((pThis->pRemHostName = malloc(prop.GetStringLen(fqdn) + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pRemHostName, propGetSzStr(fqdn), prop.GetStringLen(fqdn) + 1); prop.Destruct(&fqdn); finalize_it: RETiRet; } /* obtain connection info as soon as we are connected */ static void get_socket_info(const int sockfd, char *const connInfo) { char local_ip_str[INET_ADDRSTRLEN]; // Buffer to hold the IP address string int local_port = -1; char local_port_str[8]; char remote_ip_str[INET_ADDRSTRLEN]; // Buffer to hold the IP address string int remote_port = -1; char remote_port_str[8]; struct sockaddr_in local_addr; socklen_t local_addr_len = sizeof(local_addr); struct sockaddr_in remote_addr; socklen_t remote_addr_len = sizeof(remote_addr); /* local system info */ local_addr.sin_port = 0; /* just to keep clang static analyzer happy */ if (getsockname(sockfd, (struct sockaddr *)&local_addr, &local_addr_len) == -1) { RS_COPY_LITERAL(local_ip_str, "?"); } else { if (inet_ntop(AF_INET, &local_addr.sin_addr, local_ip_str, INET_ADDRSTRLEN) == NULL) { RS_COPY_LITERAL(local_ip_str, "?"); } local_port = ntohs(local_addr.sin_port); } /* remote system info */ remote_addr.sin_port = 0; /* just to keep clang static analyzer happy */ if (getpeername(sockfd, (struct sockaddr *)&remote_addr, &remote_addr_len) == -1) { RS_COPY_LITERAL(remote_ip_str, "?"); } else { if (inet_ntop(AF_INET, &remote_addr.sin_addr, remote_ip_str, INET_ADDRSTRLEN) == NULL) { RS_COPY_LITERAL(remote_ip_str, "?"); } remote_port = ntohs(remote_addr.sin_port); } if (local_port == -1) { RS_COPY_LITERAL(local_port_str, "?"); } else { snprintf(local_port_str, 7, "%d", local_port); local_port_str[7] = '\0'; /* be on safe side */ } if (remote_port == -1) { RS_COPY_LITERAL(remote_port_str, "?"); } else { snprintf(remote_port_str, 7, "%d", remote_port); remote_port_str[7] = '\0'; /* be on safe side */ } snprintf(connInfo, TCPSRV_CONNINFO_SIZE, "from %s:%s to %s:%s", remote_ip_str, remote_port_str, local_ip_str, local_port_str); } /* accept an incoming connection request * rgerhards, 2008-04-22 */ static rsRetVal AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew, char *const connInfo) { int sockflags; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); nsd_ptcp_t *pNew = NULL; int iNewSock = -1; DEFiRet; assert(ppNew != NULL); ISOBJ_TYPE_assert(pThis, nsd_ptcp); iNewSock = accept(pThis->sock, (struct sockaddr *)&addr, &addrlen); if (iNewSock < 0) { if (errno == EINTR || errno == EAGAIN) { ABORT_FINALIZE(RS_RET_NO_MORE_DATA); } LogMsg(errno, RS_RET_ACCEPT_ERR, LOG_WARNING, "nds_ptcp: error accepting connection on socket %d", pThis->sock); ABORT_FINALIZE(RS_RET_ACCEPT_ERR); } get_socket_info(iNewSock, connInfo); /* construct our object so that we can use it... */ CHKiRet(nsd_ptcpConstruct(&pNew)); /* for the legacy ACL code, we need to preserve addr. While this is far from * begin perfect (from an abstract design perspective), we need this to prevent * breaking everything. */ memcpy(&pNew->remAddr, &addr, sizeof(struct sockaddr_storage)); CHKiRet(FillRemHost(pNew, &addr)); /* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */ if ((sockflags = fcntl(iNewSock, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* SETFL could fail too, so get it caught by the subsequent * error check. */ sockflags = fcntl(iNewSock, F_SETFL, sockflags); } if (sockflags == -1) { dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket %d", errno, iNewSock); ABORT_FINALIZE(RS_RET_IO_ERROR); } pNew->sock = iNewSock; *ppNew = (nsd_t *)pNew; finalize_it: if (iRet != RS_RET_OK) { if (pNew != NULL) nsd_ptcpDestruct(&pNew); /* the close may be redundant, but that doesn't hurt... */ sockClose(&iNewSock); } RETiRet; } /* initialize tcp sockets for a listner. The initialized sockets are passed to the * app-level caller via a callback. * pLstnPort must point to a port name or number. NULL is NOT permitted. pLstnIP * points to the port to listen to (NULL means "all"), iMaxSess has the maximum * number of sessions permitted. * rgerhards, 2008-04-22 */ static rsRetVal ATTR_NONNULL(1, 3, 5) LstnInit(netstrms_t *const pNS, void *pUsr, rsRetVal (*fAddLstn)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params) { DEFiRet; netstrm_t *pNewStrm = NULL; nsd_t *pNewNsd = NULL; int error, maxs, on = 1; int isIPv6 = 0; int sock = -1; int numSocks; int sockflags; int port_override = 0; /* if dyn port (0): use this for actually bound port */ struct addrinfo hints, *res = NULL, *r; union { struct sockaddr *sa; struct sockaddr_in *ipv4; struct sockaddr_in6 *ipv6; } savecast; ISOBJ_TYPE_assert(pNS, netstrms); assert(fAddLstn != NULL); assert(cnf_params->pszPort != NULL); assert(iSessMax >= 0); dbgprintf("creating tcp listen socket on port %s\n", cnf_params->pszPort); memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = glbl.GetDefPFFamily(runConf); hints.ai_socktype = SOCK_STREAM; error = getaddrinfo((const char *)cnf_params->pszAddr, (const char *)cnf_params->pszPort, &hints, &res); if (error) { LogError(0, RS_RET_INVALID_PORT, "error querying port '%s': %s", (cnf_params->pszAddr == NULL) ? "**UNSPECIFIED**" : (const char *)cnf_params->pszAddr, gai_strerror(error)); ABORT_FINALIZE(RS_RET_INVALID_PORT); } /* Count max number of sockets we may open */ for (maxs = 0, r = res; r != NULL; r = r->ai_next, maxs++) /* EMPTY */ ; numSocks = 0; /* num of sockets counter at start of array */ for (r = res; r != NULL; r = r->ai_next) { if (port_override != 0) { savecast.sa = (struct sockaddr *)r->ai_addr; if (r->ai_family == AF_INET6) { savecast.ipv6->sin6_port = port_override; } else { savecast.ipv4->sin_port = port_override; } } sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol); if (sock < 0) { if (!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) { dbgprintf("error %d creating tcp listen socket", errno); /* it is debatable if PF_INET with EAFNOSUPPORT should * also be ignored... */ } continue; } #ifdef IPV6_V6ONLY if (r->ai_family == AF_INET6) { isIPv6 = 1; int iOn = 1; if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&iOn, sizeof(iOn)) < 0) { close(sock); sock = -1; continue; } } #endif if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) { dbgprintf("error %d setting tcp socket option\n", errno); close(sock); sock = -1; continue; } /* We use non-blocking IO! */ if ((sockflags = fcntl(sock, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* SETFL could fail too, so get it caught by the subsequent * error check. */ sockflags = fcntl(sock, F_SETFL, sockflags); } if (sockflags == -1) { dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno); close(sock); sock = -1; continue; } /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ #if !defined(_AIX) && !defined(BSD) if (net.should_use_so_bsdcompat()) { if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT, (char *)&on, sizeof(on)) < 0) { LogError(errno, NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)"); close(sock); sock = -1; continue; } } #endif if ((bind(sock, r->ai_addr, r->ai_addrlen) < 0) #ifndef IPV6_V6ONLY && (errno != EADDRINUSE) #endif ) { /* TODO: check if *we* bound the socket - else we *have* an error! */ LogError(errno, NO_ERRCODE, "Error while binding tcp socket"); close(sock); sock = -1; continue; } /* if we bind to dynamic port (port 0 given), we will do so consistently. Thus * once we got a dynamic port, we will keep it and use it for other protocols * as well. As of my understanding, this should always work as the OS does not * pick a port that is used by some protocol (well, at least this looks very * unlikely...). If our asusmption is wrong, we should iterate until we find a * combination that works - it is very unusual to have the same service listen * on differnt ports on IPv4 and IPv6. */ savecast.sa = (struct sockaddr *)r->ai_addr; const int currport = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port; if (currport == 0) { socklen_t socklen_r = r->ai_addrlen; if (getsockname(sock, r->ai_addr, &socklen_r) == -1) { LogError(errno, NO_ERRCODE, "nsd_ptcp: ListenPortFileName: getsockname:" "error while trying to get socket"); } r->ai_addrlen = socklen_r; savecast.sa = (struct sockaddr *)r->ai_addr; port_override = (isIPv6) ? savecast.ipv6->sin6_port : savecast.ipv4->sin_port; if (cnf_params->pszLstnPortFileName != NULL) { FILE *fp; if ((fp = fopen((const char *)cnf_params->pszLstnPortFileName, "w+")) == NULL) { LogError(errno, RS_RET_IO_ERROR, "nsd_ptcp: ListenPortFileName: " "error while trying to open file"); ABORT_FINALIZE(RS_RET_IO_ERROR); } if (isIPv6) { fprintf(fp, "%d", ntohs(savecast.ipv6->sin6_port)); } else { fprintf(fp, "%d", ntohs(savecast.ipv4->sin_port)); } fclose(fp); } } const int iSynBacklog = (pNS->iSynBacklog == 0) ? iSessMax / 10 + 5 : pNS->iSynBacklog; if (listen(sock, iSynBacklog) < 0) { /* If the listen fails, it most probably fails because we ask * for a too-large backlog. So in this case we first set back * to a fixed, reasonable, limit that should work. Only if * that fails, too, we give up. */ dbgprintf("listen with a backlog of %d failed - retrying with default of 32.\n", iSessMax / 10 + 5); if (listen(sock, 32) < 0) { dbgprintf("tcp listen error %d, suspending\n", errno); close(sock); sock = -1; continue; } } /* if we reach this point, we were able to obtain a valid socket, so we can * construct a new netstrm obj and hand it over to the upper layers for inclusion * into their socket array. -- rgerhards, 2008-04-23 */ CHKiRet(pNS->Drvr.Construct(&pNewNsd)); CHKiRet(pNS->Drvr.SetSock(pNewNsd, sock)); CHKiRet(pNS->Drvr.SetMode(pNewNsd, netstrms.GetDrvrMode(pNS))); CHKiRet(pNS->Drvr.SetCheckExtendedKeyUsage(pNewNsd, netstrms.GetDrvrCheckExtendedKeyUsage(pNS))); CHKiRet(pNS->Drvr.SetPrioritizeSAN(pNewNsd, netstrms.GetDrvrPrioritizeSAN(pNS))); CHKiRet(pNS->Drvr.SetTlsCAFile(pNewNsd, netstrms.GetDrvrTlsCAFile(pNS))); CHKiRet(pNS->Drvr.SetTlsCRLFile(pNewNsd, netstrms.GetDrvrTlsCRLFile(pNS))); CHKiRet(pNS->Drvr.SetTlsCAExtraFiles(pNewNsd, NULL)); CHKiRet(pNS->Drvr.SetTlsKeyFile(pNewNsd, netstrms.GetDrvrTlsKeyFile(pNS))); CHKiRet(pNS->Drvr.SetTlsCertFile(pNewNsd, netstrms.GetDrvrTlsCertFile(pNS))); CHKiRet(pNS->Drvr.SetTlsVerifyDepth(pNewNsd, netstrms.GetDrvrTlsVerifyDepth(pNS))); CHKiRet(pNS->Drvr.SetTlsRevocationCheck(pNewNsd, netstrms.GetDrvrTlsRevocationCheck(pNS))); CHKiRet(pNS->Drvr.SetAuthMode(pNewNsd, netstrms.GetDrvrAuthMode(pNS))); CHKiRet(pNS->Drvr.SetPermitExpiredCerts(pNewNsd, netstrms.GetDrvrPermitExpiredCerts(pNS))); CHKiRet(pNS->Drvr.SetPermPeers(pNewNsd, netstrms.GetDrvrPermPeers(pNS))); CHKiRet(pNS->Drvr.SetGnutlsPriorityString(pNewNsd, netstrms.GetDrvrGnutlsPriorityString(pNS))); CHKiRet(netstrms.CreateStrm(pNS, &pNewStrm)); pNewStrm->pDrvrData = (nsd_t *)pNewNsd; if (pNS->fLstnInitDrvr != NULL) { CHKiRet(pNS->fLstnInitDrvr(pNewStrm)); } CHKiRet(fAddLstn(pUsr, pNewStrm)); pNewStrm = NULL; /* sock has been handed over by SetSock() above, so invalidate it here * coverity scan falsely identifies this as ressource leak */ sock = -1; ++numSocks; } if (numSocks != maxs) dbgprintf( "We could initialize %d TCP listen sockets out of %d we received " "- this may or may not be an error indication.\n", numSocks, maxs); if (numSocks == 0) { dbgprintf("No TCP listen sockets could successfully be initialized\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_BIND); } finalize_it: if (sock != -1) { close(sock); } if (res != NULL) freeaddrinfo(res); if (iRet != RS_RET_OK) { if (pNewStrm != NULL) netstrm.Destruct(&pNewStrm); else if (pNewNsd != NULL) pNS->Drvr.Destruct(&pNewNsd); } RETiRet; } /* receive data from a tcp socket * The lenBuf parameter must contain the max buffer size on entry and contains * the number of octets read (or -1 in case of error) on exit. This function * never blocks, not even when called on a blocking socket. That is important * for client sockets, which are set to block during send, but should not * block when trying to read data. If *pLenBuf is -1, an error occurred and * oserr holds the exact error cause. * rgerhards, 2008-03-17 */ static rsRetVal Rcv(nsd_t *pNsd, uchar *pRcvBuf, ssize_t *pLenBuf, int *const oserr, unsigned *const nextIODirection) { char errStr[1024]; DEFiRet; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ptcp); assert(oserr != NULL); /* AIXPORT : MSG_DONTWAIT not supported */ #if defined(_AIX) #define MSG_DONTWAIT MSG_NONBLOCK #endif *pLenBuf = recv(pThis->sock, pRcvBuf, *pLenBuf, MSG_DONTWAIT); *oserr = errno; *nextIODirection = NSDSEL_RD; if (*pLenBuf == 0) { ABORT_FINALIZE(RS_RET_CLOSED); } else if (*pLenBuf < 0) { if (*oserr == EINTR || *oserr == EAGAIN) { ABORT_FINALIZE(RS_RET_RETRY); } else { rs_strerror_r(errno, errStr, sizeof(errStr)); dbgprintf("error during recv on NSD %p: %s\n", pNsd, errStr); ABORT_FINALIZE(RS_RET_RCV_ERR); } } finalize_it: RETiRet; } /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has * been written. * rgerhards, 2008-03-19 */ static rsRetVal Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; ssize_t written; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ptcp); written = send(pThis->sock, pBuf, *pLenBuf, 0); if (written == -1) { switch (errno) { case EAGAIN: case EINTR: /* this is fine, just retry... */ written = 0; break; default: ABORT_FINALIZE(RS_RET_IO_ERROR); break; } } *pLenBuf = written; finalize_it: RETiRet; } /* Enable KEEPALIVE handling on the socket. * rgerhards, 2009-06-02 */ static rsRetVal EnableKeepAlive(nsd_t *pNsd) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; int ret; int optval; socklen_t optlen; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ptcp); optval = 1; optlen = sizeof(optval); ret = setsockopt(pThis->sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen); if (ret < 0) { dbgprintf("EnableKeepAlive socket call returns error %d\n", ret); ABORT_FINALIZE(RS_RET_ERR); } #if defined(IPPROTO_TCP) && defined(TCP_KEEPCNT) if (pThis->iKeepAliveProbes > 0) { optval = pThis->iKeepAliveProbes; optlen = sizeof(optval); ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen); } else { ret = 0; } #else ret = -1; #endif if (ret < 0) { LogError(ret, NO_ERRCODE, "nsd_ptcp cannot set keepalive probes - ignored"); } #if defined(IPPROTO_TCP) && defined(TCP_KEEPIDLE) if (pThis->iKeepAliveTime > 0) { optval = pThis->iKeepAliveTime; optlen = sizeof(optval); ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen); } else { ret = 0; } #else ret = -1; #endif if (ret < 0) { LogError(ret, NO_ERRCODE, "nsd_ptcp cannot set keepalive time - ignored"); } #if defined(IPPROTO_TCP) && defined(TCP_KEEPCNT) if (pThis->iKeepAliveIntvl > 0) { optval = pThis->iKeepAliveIntvl; optlen = sizeof(optval); ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen); } else { ret = 0; } #else ret = -1; #endif if (ret < 0) { LogError(errno, NO_ERRCODE, "nsd_ptcp cannot set keepalive intvl - ignored"); } dbgprintf("KEEPALIVE enabled for socket %d\n", pThis->sock); finalize_it: RETiRet; } /* Set TCP_USER_TIMEOUT on platforms that support it. */ static rsRetVal ApplyTcpUserTimeout(nsd_ptcp_t *pThis) { static int bWarned = 0; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ptcp); if (pThis->tcp_user_timeout_ms <= 0) { FINALIZE; } #if defined(IPPROTO_TCP) && defined(TCP_USER_TIMEOUT) int ret; int optval; socklen_t optlen; optval = pThis->tcp_user_timeout_ms; optlen = sizeof(optval); ret = setsockopt(pThis->sock, IPPROTO_TCP, TCP_USER_TIMEOUT, &optval, optlen); if (ret < 0 && !bWarned) { LogError(errno, NO_ERRCODE, "nsd_ptcp cannot set TCP_USER_TIMEOUT - ignored"); bWarned = 1; } #else if (!bWarned) { LogError(0, NO_ERRCODE, "nsd_ptcp cannot set TCP_USER_TIMEOUT on this platform - ignored"); bWarned = 1; } #endif finalize_it: RETiRet; } /* open a connection to a remote host (server). * rgerhards, 2008-03-19 */ static rsRetVal Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device) { nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; struct addrinfo *res = NULL; struct addrinfo *currAddr; struct addrinfo hints; int saved_errno = 0; struct timeval start, end; long seconds = 0, useconds = 0; int gai_rc; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_ptcp); assert(port != NULL); assert(host != NULL); assert(pThis->sock == -1); memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; gai_rc = getaddrinfo((char *)host, (char *)port, &hints, &res); if (gai_rc != 0) { LogError(0, RS_RET_IO_ERROR, "cannot resolve hostname '%s': %s", host, gai_strerror(gai_rc)); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* We need to copy Remote Hostname here for error logging purposes */ if ((pThis->pRemHostName = malloc(strlen((char *)host) + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pRemHostName, host, strlen((char *)host) + 1); if (device != NULL) { #if !defined(SO_BINDTODEVICE) LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "cannot use device '%s': SO_BINDTODEVICE is not supported on this platform", device); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); #endif } gettimeofday(&start, NULL); for (currAddr = res; currAddr != NULL; currAddr = currAddr->ai_next) { pThis->sock = socket(currAddr->ai_family, currAddr->ai_socktype, currAddr->ai_protocol); if (pThis->sock == -1) { saved_errno = errno; continue; } if (device) { #if defined(SO_BINDTODEVICE) if (setsockopt(pThis->sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1) < 0) { saved_errno = errno; dbgprintf("setsockopt(SO_BINDTODEVICE) failed\n"); sockClose(&pThis->sock); continue; } #endif } CHKiRet(ApplyTcpUserTimeout(pThis)); if (connect(pThis->sock, currAddr->ai_addr, currAddr->ai_addrlen) == 0) { break; } saved_errno = errno; sockClose(&pThis->sock); } if (currAddr == NULL) { gettimeofday(&end, NULL); seconds = end.tv_sec - start.tv_sec; useconds = end.tv_usec - start.tv_usec; if (useconds < 0) { useconds += 1000000; seconds -= 1; } if (seconds < 0) { seconds = 0; useconds = 0; } LogError(saved_errno, RS_RET_IO_ERROR, "cannot connect to %s:%s (took %ld.%02ld seconds)", host, port, seconds, useconds / 10000); ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: if (res != NULL) freeaddrinfo(res); if (iRet != RS_RET_OK) { sockClose(&pThis->sock); } RETiRet; } /* get the remote hostname. The returned hostname must be freed by the * caller. * rgerhards, 2008-04-24 */ static rsRetVal GetRemoteHName(nsd_t *pNsd, uchar **ppszHName) { DEFiRet; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ptcp); assert(ppszHName != NULL); // TODO: how can the RemHost be empty? CHKmalloc(*ppszHName = (uchar *)strdup(pThis->pRemHostName == NULL ? "" : (char *)pThis->pRemHostName)); finalize_it: RETiRet; } /** * getRemotePort - return peer TCP port number for improved diagnostics * @pThis: nsd_t object representing the network stream driver. * @port: Pointer to an integer where the port number will be stored. * It will be set to -1 on error or if no port information is available. * @return: standard rsRetVal error code */ static rsRetVal GetRemotePort(nsd_t *pNsd, int *port) { DEFiRet; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); assert(pThis != NULL); assert(port != NULL); *port = -1; /* Initialize port to -1, indicating no port found initially or on error */ memset(&addr, 0, sizeof(addr)); /* avoid potential garbage values */ if (getpeername(pThis->sock, (struct sockaddr *)&addr, &addrlen) == 0) { if (addr.ss_family == AF_INET6) { *port = ntohs(((struct sockaddr_in6 *)&addr)->sin6_port); } else if (addr.ss_family == AF_INET) { *port = ntohs(((struct sockaddr_in *)&addr)->sin_port); } else { /* Unsupported address family */ ABORT_FINALIZE(RS_RET_UNSUPP_SOCK_AF); } } else { /* getpeername failed */ ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: RETiRet; } static rsRetVal FmtRemotePortStr(const int port, uchar *const buf, const size_t len) { int r; if (len == 0) { return RS_RET_INVALID_PARAMS; /* can't do anything with zero-sized buffer */ } if (port == -1) { r = snprintf((char *)buf, len, "?"); } else { r = snprintf((char *)buf, len, "%d", port); } if (r < 0) { /* An encoding error occurred. */ return RS_RET_ERR; } else if ((size_t)r >= len) { /* The buffer was too small, truncation occurred. */ return RS_RET_PROVIDED_BUFFER_TOO_SMALL; } /* Ensure null termination, though snprintf usually does this unless truncated. */ buf[len - 1] = '\0'; return RS_RET_OK; } /* This function checks if the connection is still alive - well, kind of... It * is primarily being used for plain TCP syslog and it is quite a hack. However, * as it seems to work, it is worth supporting it. The bottom line is that it * should not be called by anything else but a plain tcp syslog sender. * In order for it to work, it must be called *immediately* *before* the send() * call. For details about what is done, see here: * http://blog.gerhards.net/2008/06/getting-bit-more-reliability-from-plain.html * rgerhards, 2008-06-09 */ static rsRetVal CheckConnection(nsd_t *pNsd) { DEFiRet; int rc; char msgbuf[1]; /* dummy */ nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ptcp); rc = recv(pThis->sock, msgbuf, 1, MSG_DONTWAIT | MSG_PEEK); if (rc == 0) { LogMsg(0, RS_RET_IO_ERROR, LOG_INFO, "ptcp network driver: CheckConnection detected that peer closed connection."); sockClose(&pThis->sock); ABORT_FINALIZE(RS_RET_PEER_CLOSED_CONN); } else if (rc < 0) { if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) { LogMsg(errno, RS_RET_IO_ERROR, LOG_ERR, "ptcp network driver: CheckConnection detected broken connection"); sockClose(&pThis->sock); ABORT_FINALIZE(RS_RET_IO_ERROR); } } finalize_it: RETiRet; } /* get the remote host's IP address. Caller must Destruct the object. */ static rsRetVal GetRemoteIP(nsd_t *pNsd, prop_t **ip) { DEFiRet; nsd_ptcp_t *pThis = (nsd_ptcp_t *)pNsd; ISOBJ_TYPE_assert(pThis, nsd_ptcp); prop.AddRef(pThis->remoteIP); *ip = pThis->remoteIP; RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(nsd_ptcp) CODESTARTobjQueryInterface(nsd_ptcp); if (pIf->ifVersion != nsdCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = (rsRetVal(*)(nsd_t **))nsd_ptcpConstruct; pIf->Destruct = (rsRetVal(*)(nsd_t **))nsd_ptcpDestruct; pIf->Abort = Abort; pIf->GetRemAddr = GetRemAddr; pIf->GetSock = GetSock; pIf->SetSock = SetSock; pIf->SetMode = SetMode; pIf->SetAuthMode = SetAuthMode; pIf->SetPermitExpiredCerts = SetPermitExpiredCerts; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetPermPeers = SetPermPeers; pIf->Rcv = Rcv; pIf->Send = Send; pIf->LstnInit = LstnInit; pIf->AcceptConnReq = AcceptConnReq; pIf->Connect = Connect; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->GetRemotePort = GetRemotePort; pIf->FmtRemotePortStr = FmtRemotePortStr; pIf->CheckConnection = CheckConnection; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetTcpUserTimeout = SetTcpUserTimeout; pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsCAExtraFiles = SetTlsCAExtraFiles; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; pIf->SetRemoteSNI = SetRemoteSNI; pIf->SetTlsRevocationCheck = SetTlsRevocationCheck; finalize_it: ENDobjQueryInterface(nsd_ptcp) /* exit our class */ BEGINObjClassExit(nsd_ptcp, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsd_ptcp); /* release objects we no longer need */ objRelease(net, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(netstrm, DONT_LOAD_LIB); objRelease(netstrms, LM_NETSTRMS_FILENAME); ENDObjClassExit(nsd_ptcp) /* Initialize the nsd_ptcp class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsd_ptcp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(net, CORE_COMPONENT)); CHKiRet(objUse(netstrms, LM_NETSTRMS_FILENAME)); CHKiRet(objUse(netstrm, DONT_LOAD_LIB)); /* set our own handlers */ ENDObjClassInit(nsd_ptcp) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; nsd_ptcpClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(nsd_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/datetime.c0000644000000000000000000000013215216464436016175 xustar0030 mtime=1782212894.020266087 30 atime=1787067617.855434377 30 ctime=1787067794.325723769 rsyslog-8.2608.0/runtime/datetime.c0000664000175000017500000014042615216464436015650 0ustar00rgerrger/* The datetime object. It contains date and time related functions. * * Module begun 2008-03-05 by Rainer Gerhards, based on some code * from syslogd.c. The main intension was to move code out of syslogd.c * in a useful manner. It is still undecided if all functions will continue * to stay here or some will be moved into parser modules (once we have them). * * Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include "rsyslog.h" #include "obj.h" #include "modules.h" #include "datetime.h" #include "srUtils.h" #include "stringbuf.h" #include "errmsg.h" #include "rsconf.h" #include "timezones.h" /* static data */ DEFobjStaticHelpers; /* the following table of ten powers saves us some computation */ static const int tenPowers[6] = {1, 10, 100, 1000, 10000, 100000}; /* the following table saves us from computing an additional date to get * the ordinal day of the year - at least from 1967-2099 * Note: non-2038+ compliant systems (Solaris) will generate compiler * warnings on the post 2038-rollover years. */ static const int yearInSec_startYear = 1967; /* for x in $(seq 1967 2099) ; do * printf %s', ' $(date --date="Dec 31 ${x} UTC 23:59:59" +%s) * done |fold -w 70 -s */ static const long long yearInSecs[] = { -63158401, -31536001, -1, 31535999, 63071999, 94694399, 126230399, 157766399, 189302399, 220924799, 252460799, 283996799, 315532799, 347155199, 378691199, 410227199, 441763199, 473385599, 504921599, 536457599, 567993599, 599615999, 631151999, 662687999, 694223999, 725846399, 757382399, 788918399, 820454399, 852076799, 883612799, 915148799, 946684799, 978307199, 1009843199, 1041379199, 1072915199, 1104537599, 1136073599, 1167609599, 1199145599, 1230767999, 1262303999, 1293839999, 1325375999, 1356998399, 1388534399, 1420070399, 1451606399, 1483228799, 1514764799, 1546300799, 1577836799, 1609459199, 1640995199, 1672531199, 1704067199, 1735689599, 1767225599, 1798761599, 1830297599, 1861919999, 1893455999, 1924991999, 1956527999, 1988150399, 2019686399, 2051222399, 2082758399, 2114380799, 2145916799, 2177452799, 2208988799, 2240611199, 2272147199, 2303683199, 2335219199, 2366841599, 2398377599, 2429913599, 2461449599, 2493071999, 2524607999, 2556143999, 2587679999, 2619302399, 2650838399, 2682374399, 2713910399, 2745532799, 2777068799, 2808604799, 2840140799, 2871763199, 2903299199, 2934835199, 2966371199, 2997993599, 3029529599, 3061065599, 3092601599, 3124223999, 3155759999, 3187295999, 3218831999, 3250454399, 3281990399, 3313526399, 3345062399, 3376684799, 3408220799, 3439756799, 3471292799, 3502915199, 3534451199, 3565987199, 3597523199, 3629145599, 3660681599, 3692217599, 3723753599, 3755375999, 3786911999, 3818447999, 3849983999, 3881606399, 3913142399, 3944678399, 3976214399, 4007836799, 4039372799, 4070908799, 4102444799}; /* note range is 1969 -> 2100 because it needs to access previous/next year */ /* for x in $(seq 1969 2100) ; do * printf %s', ' $(date --date="Dec 28 ${x} UTC 12:00:00" +%V) * done | fold -w 70 -s */ static const int weeksInYear[] = { 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, 52, 52, 52, 53, 52, 52, 52, 52, 52, 53, 52, }; static const char *monthNames[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; /* ------------------------------ methods ------------------------------ */ /** * Convert struct timeval to syslog_time */ static void timeval2syslogTime(struct timeval *tp, struct syslogTime *t, const int inUTC) { struct tm *tm; struct tm tmBuf; long lBias; time_t secs; #if defined(__hpux) struct timezone tz; #endif secs = tp->tv_sec; if (inUTC) tm = gmtime_r(&secs, &tmBuf); else tm = localtime_r(&secs, &tmBuf); t->year = tm->tm_year + 1900; t->month = tm->tm_mon + 1; t->day = tm->tm_mday; t->wday = tm->tm_wday; t->hour = tm->tm_hour; t->minute = tm->tm_min; t->second = tm->tm_sec; t->secfrac = tp->tv_usec; t->secfracPrecision = 6; if (inUTC) { t->OffsetMode = '+'; lBias = 0; } else { #if defined(__sun) /* Solaris uses a different method of exporting the time zone. * It is UTC - localtime, which is the opposite sign of mins east of GMT. */ lBias = -(tm->tm_isdst ? altzone : timezone); #elif defined(__hpux) lBias = tz.tz_dsttime ? -tz.tz_minuteswest : 0; #elif defined(_AIX) /* AIXPORT : IBM documentation notice that 'extern long timezone' * is setted after calling tzset. * Recent version of AIX, localtime_r call inside tzset. */ if (tm->tm_isdst) tzset(); lBias = -timezone; #else lBias = tm->tm_gmtoff; #endif if (lBias < 0) { t->OffsetMode = '-'; lBias *= -1; } else t->OffsetMode = '+'; } t->OffsetHour = lBias / 3600; t->OffsetMinute = (lBias % 3600) / 60; t->timeType = TIME_TYPE_RFC5424; /* we have a high precision timestamp */ t->inUTC = inUTC; } /** * Get the current date/time in the best resolution the operating * system has to offer (well, actually at most down to the milli- * second level. * * The date and time is returned in separate fields as this is * most portable and removes the need for additional structures * (but I have to admit it is somewhat "bulky";)). * * Obviously, *t must not be NULL... * * rgerhards, 2008-10-07: added ttSeconds to provide a way to * obtain the second-resolution UNIX timestamp. This is needed * in some situations to minimize time() calls (namely when doing * output processing). This can be left NULL if not needed. */ static void getCurrTime(struct syslogTime *t, time_t *ttSeconds, const int inUTC) { struct timeval tp; /* AIXPORT : fix build error : "tm_gmtoff" is not a member of "struct tm" * Choose the HPUX code path, only for this function. * This is achieved by adding a check to _AIX wherever _hpux is checked */ #if defined(__hpux) || defined(_AIX) struct timezone tz; #endif assert(t != NULL); #if defined(__hpux) || defined(_AIX) /* NOTE: under HP UX, the tz information might actually be * valid data. So we need to obtain and process it there. * As HP UX is not a supported platform, this is left to * explore by someone with interest in this platform. */ gettimeofday(&tp, &tz); #else gettimeofday(&tp, NULL); #endif if (ttSeconds != NULL) *ttSeconds = tp.tv_sec; timeval2syslogTime(&tp, t, inUTC); } /* A fast alternative to getCurrTime() and time() that only obtains * a timestamp like time() does. I was told that gettimeofday(), at * least under Linux, is much faster than time() and I could confirm * this testing. So I created that function as a replacement. * rgerhards, 2009-11-12 */ time_t getTime(time_t *ttSeconds) { struct timeval tp; if (gettimeofday(&tp, NULL) == -1) return -1; if (ttSeconds != NULL) *ttSeconds = tp.tv_sec; return tp.tv_sec; } dateTimeFormat_t getDateTimeFormatFromStr(const char *const __restrict__ s) { assert(s != NULL); if (strcmp(s, "date-rfc3164") == 0) return DATE_RFC3164; if (strcmp(s, "date-rfc3339") == 0) return DATE_RFC3339; if (strcmp(s, "date-unix") == 0) return DATE_UNIX; return DATE_INVALID; } /******************************************************************* * BEGIN CODE-LIBLOGGING * ******************************************************************* * Code in this section is borrowed from liblogging. This is an * interim solution. Once liblogging is fully integrated, this is * to be removed (see http://www.monitorware.com/liblogging for * more details. 2004-11-16 rgerhards * * Please note that the orginal liblogging code is modified so that * it fits into the context of the current version of syslogd.c. * * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!! */ /** * Parse a 32 bit integer number from a string. We do not permit * integer overruns, this the guard against INT_MAX. * * \param ppsz Pointer to the Pointer to the string being parsed. It * must be positioned at the first digit. Will be updated * so that on return it points to the first character AFTER * the integer parsed. * \param pLenStr pointer to string length, decremented on exit by * characters processed * Note that if an empty string (len < 1) is passed in, * the method always returns zero. * \retval The number parsed. */ static int srSLMGParseInt32(uchar **ppsz, int *pLenStr) { register int i; i = 0; while (*pLenStr > 0 && **ppsz >= '0' && **ppsz <= '9' && i < INT_MAX / 10 - 1) { i = i * 10 + **ppsz - '0'; ++(*ppsz); --(*pLenStr); } return i; } /** * Parse a TIMESTAMP-3339. * updates the parse pointer position. The pTime parameter * is guranteed to be updated only if a new valid timestamp * could be obtained (restriction added 2008-09-16 by rgerhards). * This method now also checks the maximum string length it is passed. * If a *valid* timestamp is found, the string length is decremented * by the number of characters processed. If it is not a valid timestamp, * the length is kept unmodified. -- rgerhards, 2009-09-23 */ static rsRetVal ParseTIMESTAMP3339(struct syslogTime *pTime, uchar **ppszTS, int *pLenStr) { uchar *pszTS = *ppszTS; /* variables to temporarily hold time information while we parse */ int year; int month; int day; int hour; /* 24 hour clock */ int minute; int second; int secfrac; /* fractional seconds (must be 32 bit!) */ int secfracPrecision; char OffsetMode; /* UTC offset + or - */ int OffsetHour; /* UTC offset in hours */ int OffsetMinute; /* UTC offset in minutes */ int lenStr; /* end variables to temporarily hold time information while we parse */ DEFiRet; assert(pTime != NULL); assert(ppszTS != NULL); assert(pszTS != NULL); lenStr = *pLenStr; year = srSLMGParseInt32(&pszTS, &lenStr); /* We take the liberty to accept slightly malformed timestamps e.g. in * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course, * with the current state of affairs, we would never run into this code * here because at postion 11, there is no "T" in such cases ;) */ if (lenStr == 0 || *pszTS++ != '-' || year < 0 || year >= 2100) { DBGPRINTF("ParseTIMESTAMP3339: invalid year: %d, pszTS: '%c'\n", year, *pszTS); ABORT_FINALIZE(RS_RET_INVLD_TIME); } --lenStr; month = srSLMGParseInt32(&pszTS, &lenStr); if (month < 1 || month > 12) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != '-') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; day = srSLMGParseInt32(&pszTS, &lenStr); if (day < 1 || day > 31) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != 'T') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; hour = srSLMGParseInt32(&pszTS, &lenStr); if (hour < 0 || hour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; minute = srSLMGParseInt32(&pszTS, &lenStr); if (minute < 0 || minute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; second = srSLMGParseInt32(&pszTS, &lenStr); if (second < 0 || second > 60) ABORT_FINALIZE(RS_RET_INVLD_TIME); /* Now let's see if we have secfrac */ if (lenStr > 0 && *pszTS == '.') { --lenStr; uchar *pszStart = ++pszTS; secfrac = srSLMGParseInt32(&pszTS, &lenStr); secfracPrecision = (int)(pszTS - pszStart); } else { secfracPrecision = 0; secfrac = 0; } /* check the timezone */ if (lenStr == 0) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (*pszTS == 'Z') { --lenStr; pszTS++; /* eat Z */ OffsetMode = 'Z'; OffsetHour = 0; OffsetMinute = 0; } else if ((*pszTS == '+') || (*pszTS == '-')) { OffsetMode = *pszTS; --lenStr; pszTS++; OffsetHour = srSLMGParseInt32(&pszTS, &lenStr); if (OffsetHour < 0 || OffsetHour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; pszTS++; OffsetMinute = srSLMGParseInt32(&pszTS, &lenStr); if (OffsetMinute < 0 || OffsetMinute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); } else { /* there MUST be TZ information */ ABORT_FINALIZE(RS_RET_INVLD_TIME); } /* OK, we actually have a 3339 timestamp, so let's indicated this */ if (lenStr > 0) { if (*pszTS != ' ') /* if it is not a space, it can not be a "good" time - 2010-02-22 rgerhards */ ABORT_FINALIZE(RS_RET_INVLD_TIME); ++pszTS; /* just skip past it */ --lenStr; } /* we had success, so update parse pointer and caller-provided timestamp */ *ppszTS = pszTS; pTime->timeType = 2; pTime->year = year; pTime->month = month; pTime->day = day; pTime->hour = hour; pTime->minute = minute; pTime->second = second; pTime->secfrac = secfrac; pTime->secfracPrecision = secfracPrecision; pTime->OffsetMode = OffsetMode; pTime->OffsetHour = OffsetHour; pTime->OffsetMinute = OffsetMinute; *pLenStr = lenStr; finalize_it: RETiRet; } /** * Parse a TIMESTAMP-3164. The pTime parameter * is guranteed to be updated only if a new valid timestamp * could be obtained (restriction added 2008-09-16 by rgerhards). This * also means the caller *must* provide a valid (probably current) * timstamp in pTime when calling this function. a 3164 timestamp contains * only partial information and only that partial information is updated. * So the "output timestamp" is a valid timestamp only if the "input * timestamp" was valid, too. The is actually an optimization, as it * permits us to use a pre-acquired timestamp and thus avoids to do * a (costly) time() call. Thanks to David Lang for insisting on * time() call reduction ;). * This method now also checks the maximum string length it is passed. * If a *valid* timestamp is found, the string length is decremented * by the number of characters processed. If it is not a valid timestamp, * the length is kept unmodified. -- rgerhards, 2009-09-23 * * We support this format: * [yyyy] Mon mm [yyyy] hh:mm:ss[.subsec][ [yyyy ]/[TZSTRING:]] * Note that [yyyy] and [.subsec] are non-standard but frequently occur. * Also [yyyy] can only occur once -- if it occurs twice, we flag the * timestamp as invalid. if bParseTZ is true, we try to obtain a * TZSTRING. Note that in this case it MUST be terminated by a colon * (Cisco format). This option is a bit dangerous, as it could already * by the tag. So it MUST only be enabled in specialised parsers. * subsec, [yyyy] in front, TZSTRING was added in 2014-07-08 rgerhards * Similarly, we try to detect a year after the timestamp if * bDetectYearAfterTime is set. This is mutally exclusive with bParseTZ. * Note: bDetectYearAfterTime will misdetect hostnames in the range * 2000..2100 as years, so this option should explicitly be turned on * and is not meant for general consumption. */ static rsRetVal ParseTIMESTAMP3164( struct syslogTime *pTime, uchar **ppszTS, int *pLenStr, const int bParseTZ, const int bDetectYearAfterTime) { /* variables to temporarily hold time information while we parse */ int month; int day; int year = 0; /* 0 means no year provided */ int hour; /* 24 hour clock */ int minute; int second; int secfrac; /* fractional seconds (must be 32 bit!) */ int secfracPrecision; char tzstring[16]; char OffsetMode = '\0'; /* UTC offset: \0 -> indicate no update */ char OffsetHour = '\0'; /* UTC offset in hours */ int OffsetMinute = 0; /* UTC offset in minutes */ /* end variables to temporarily hold time information while we parse */ int lenStr; uchar *pszTS; DEFiRet; assert(ppszTS != NULL); pszTS = *ppszTS; assert(pszTS != NULL); assert(pTime != NULL); assert(pLenStr != NULL); lenStr = *pLenStr; if (lenStr < 3) ABORT_FINALIZE(RS_RET_INVLD_TIME); /* first check if we have a year in front of the timestamp. some devices (e.g. Brocade) * do this. As it is pretty straightforward to detect and chance of misinterpretation * is low, we try to parse it. */ if (*pszTS >= '0' && *pszTS <= '9') { /* OK, either we have a prepended year or an invalid format! */ year = srSLMGParseInt32(&pszTS, &lenStr); if (year < 1970 || year > 2100 || *pszTS != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); ++pszTS; /* skip SP */ } /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec), * we may see the following character sequences occur: * * J(an/u(n/l)), Feb, Ma(r/y), A(pr/ug), Sep, Oct, Nov, Dec * * We will use this for parsing, as it probably is the * fastest way to parse it. * * 2009-08-17: we now do case-insensitive comparisons, as some devices obviously do not * obey to the RFC-specified case. As we need to guess in any case, we can ignore case * in the first place -- rgerhards * * 2005-07-18, well sometimes it pays to be a bit more verbose, even in C... * Fixed a bug that lead to invalid detection of the data. The issue was that * we had an if(++pszTS == 'x') inside of some of the consturcts below. However, * there were also some elseifs (doing the same ++), which than obviously did not * check the orginal character but the next one. Now removed the ++ and put it * into the statements below. Was a really nasty bug... I didn't detect it before * june, when it first manifested. This also lead to invalid parsing of the rest * of the message, as the time stamp was not detected to be correct. - rgerhards */ switch (*pszTS++) { case 'j': case 'J': if (*pszTS == 'a' || *pszTS == 'A') { ++pszTS; if (*pszTS == 'n' || *pszTS == 'N') { ++pszTS; month = 1; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else if (*pszTS == 'u' || *pszTS == 'U') { ++pszTS; if (*pszTS == 'n' || *pszTS == 'N') { ++pszTS; month = 6; } else if (*pszTS == 'l' || *pszTS == 'L') { ++pszTS; month = 7; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'f': case 'F': if (*pszTS == 'e' || *pszTS == 'E') { ++pszTS; if (*pszTS == 'b' || *pszTS == 'B') { ++pszTS; month = 2; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'm': case 'M': if (*pszTS == 'a' || *pszTS == 'A') { ++pszTS; if (*pszTS == 'r' || *pszTS == 'R') { ++pszTS; month = 3; } else if (*pszTS == 'y' || *pszTS == 'Y') { ++pszTS; month = 5; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'a': case 'A': if (*pszTS == 'p' || *pszTS == 'P') { ++pszTS; if (*pszTS == 'r' || *pszTS == 'R') { ++pszTS; month = 4; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else if (*pszTS == 'u' || *pszTS == 'U') { ++pszTS; if (*pszTS == 'g' || *pszTS == 'G') { ++pszTS; month = 8; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 's': case 'S': if (*pszTS == 'e' || *pszTS == 'E') { ++pszTS; if (*pszTS == 'p' || *pszTS == 'P') { ++pszTS; month = 9; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'o': case 'O': if (*pszTS == 'c' || *pszTS == 'C') { ++pszTS; if (*pszTS == 't' || *pszTS == 'T') { ++pszTS; month = 10; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'n': case 'N': if (*pszTS == 'o' || *pszTS == 'O') { ++pszTS; if (*pszTS == 'v' || *pszTS == 'V') { ++pszTS; month = 11; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; case 'd': case 'D': if (*pszTS == 'e' || *pszTS == 'E') { ++pszTS; if (*pszTS == 'c' || *pszTS == 'C') { ++pszTS; month = 12; } else ABORT_FINALIZE(RS_RET_INVLD_TIME); } else ABORT_FINALIZE(RS_RET_INVLD_TIME); break; default: ABORT_FINALIZE(RS_RET_INVLD_TIME); } lenStr -= 3; /* done month */ if (lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; /* we accept a slightly malformed timestamp when receiving. This is * we accept one-digit days */ if (*pszTS == ' ') { --lenStr; ++pszTS; } day = srSLMGParseInt32(&pszTS, &lenStr); if (day < 1 || day > 31) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; /* time part */ hour = srSLMGParseInt32(&pszTS, &lenStr); if (year == 0 && hour > 1970 && hour < 2100) { /* if so, we assume this actually is a year. This is a format found * e.g. in Cisco devices. * (if you read this 2100+ trying to fix a bug, congratulate me * to how long the code survived - me no longer ;)) -- rgerhards, 2008-11-18 */ year = hour; /* re-query the hour, this time it must be valid */ if (lenStr == 0 || *pszTS++ != ' ') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; hour = srSLMGParseInt32(&pszTS, &lenStr); } if (hour < 0 || hour > 23) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; minute = srSLMGParseInt32(&pszTS, &lenStr); if (minute < 0 || minute > 59) ABORT_FINALIZE(RS_RET_INVLD_TIME); if (lenStr == 0 || *pszTS++ != ':') ABORT_FINALIZE(RS_RET_INVLD_TIME); --lenStr; second = srSLMGParseInt32(&pszTS, &lenStr); if (second < 0 || second > 60) ABORT_FINALIZE(RS_RET_INVLD_TIME); /* as an extension e.g. found in CISCO IOS, we support sub-second resultion. * It's presence is indicated by a dot immediately following the second. */ if (lenStr > 0 && *pszTS == '.') { --lenStr; uchar *pszStart = ++pszTS; secfrac = srSLMGParseInt32(&pszTS, &lenStr); secfracPrecision = (int)(pszTS - pszStart); } else { secfracPrecision = 0; secfrac = 0; } /* try to parse the TZSTRING if we are instructed to do so */ if (bParseTZ && lenStr > 2 && *pszTS == ' ') { int i; for (++pszTS, --lenStr, i = 0; lenStr > 0 && i < (int)sizeof(tzstring) - 1 && *pszTS != ':' && *pszTS != ' '; --lenStr) tzstring[i++] = *pszTS++; if (i > 0) { /* found TZ, apply it */ tzinfo_t *tzinfo; tzstring[i] = '\0'; if ((tzinfo = glblFindTimezone(runConf, (char *)tzstring)) == NULL) { DBGPRINTF("ParseTIMESTAMP3164: invalid TZ string '%s' -- ignored\n", tzstring); } else { OffsetMode = tzinfo->offsMode; OffsetHour = tzinfo->offsHour; OffsetMinute = tzinfo->offsMin; } } } if (bDetectYearAfterTime && year == 0 && lenStr > 5 && *pszTS == ' ') { int j; int y = 0; for (j = 1; j < 5; ++j) { if (pszTS[j] < '0' || pszTS[j] > '9') break; y = 10 * y + pszTS[j] - '0'; } if (lenStr > 6 && pszTS[5] != ' ') y = 0; /* no year! */ if (2000 <= y && y < 2100) { year = y; pszTS += 5; /* we need to preserve the SP, checked below */ lenStr -= 5; } } /* we provide support for an extra ":" after the date. While this is an * invalid format, it occurs frequently enough (e.g. with Cisco devices) * to permit it as a valid case. -- rgerhards, 2008-09-12 */ if (lenStr > 0 && *pszTS == ':') { ++pszTS; /* just skip past it */ --lenStr; } if (lenStr > 0) { if (*pszTS != ' ') /* if it is not a space, it can not be a "good" time - 2010-02-22 rgerhards */ ABORT_FINALIZE(RS_RET_INVLD_TIME); ++pszTS; /* just skip past it */ --lenStr; } /* we had success, so update parse pointer and caller-provided timestamp * fields we do not have are not updated in the caller's timestamp. This * is the reason why the caller must pass in a correct timestamp. */ *ppszTS = pszTS; /* provide updated parse position back to caller */ pTime->timeType = 1; pTime->month = month; if (year > 0) pTime->year = year; /* persist year if detected */ pTime->day = day; pTime->hour = hour; pTime->minute = minute; pTime->second = second; pTime->secfrac = secfrac; pTime->secfracPrecision = secfracPrecision; if (OffsetMode != '\0') { /* need to update TZ info? */ pTime->OffsetMode = OffsetMode; pTime->OffsetHour = OffsetHour; pTime->OffsetMinute = OffsetMinute; } *pLenStr = lenStr; finalize_it: RETiRet; } void applyDfltTZ(struct syslogTime *pTime, char *tz) { pTime->OffsetMode = tz[0]; pTime->OffsetHour = (tz[1] - '0') * 10 + (tz[2] - '0'); pTime->OffsetMinute = (tz[4] - '0') * 10 + (tz[5] - '0'); } /******************************************************************* * END CODE-LIBLOGGING * *******************************************************************/ /** * Format a syslogTimestamp into format required by MySQL. * We are using the 14 digits format. For example 20041111122600 * is interpreted as '2004-11-11 12:26:00'. * The caller must provide the timestamp as well as a character * buffer that will receive the resulting string. The function * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occurred. */ static int formatTimestampToMySQL(struct syslogTime *ts, char *pBuf) { /* currently we do not consider localtime/utc. This may later be * added. If so, I recommend using a property replacer option * and/or a global configuration option. However, we should wait * on user requests for this feature before doing anything. * rgerhards, 2007-06-26 */ assert(ts != NULL); assert(pBuf != NULL); pBuf[0] = (ts->year / 1000) % 10 + '0'; pBuf[1] = (ts->year / 100) % 10 + '0'; pBuf[2] = (ts->year / 10) % 10 + '0'; pBuf[3] = ts->year % 10 + '0'; pBuf[4] = (ts->month / 10) % 10 + '0'; pBuf[5] = ts->month % 10 + '0'; pBuf[6] = (ts->day / 10) % 10 + '0'; pBuf[7] = ts->day % 10 + '0'; pBuf[8] = (ts->hour / 10) % 10 + '0'; pBuf[9] = ts->hour % 10 + '0'; pBuf[10] = (ts->minute / 10) % 10 + '0'; pBuf[11] = ts->minute % 10 + '0'; pBuf[12] = (ts->second / 10) % 10 + '0'; pBuf[13] = ts->second % 10 + '0'; pBuf[14] = '\0'; return 15; } static int formatTimestampToPgSQL(struct syslogTime *ts, char *pBuf) { /* see note in formatTimestampToMySQL, applies here as well */ assert(ts != NULL); assert(pBuf != NULL); pBuf[0] = (ts->year / 1000) % 10 + '0'; pBuf[1] = (ts->year / 100) % 10 + '0'; pBuf[2] = (ts->year / 10) % 10 + '0'; pBuf[3] = ts->year % 10 + '0'; pBuf[4] = '-'; pBuf[5] = (ts->month / 10) % 10 + '0'; pBuf[6] = ts->month % 10 + '0'; pBuf[7] = '-'; pBuf[8] = (ts->day / 10) % 10 + '0'; pBuf[9] = ts->day % 10 + '0'; pBuf[10] = ' '; pBuf[11] = (ts->hour / 10) % 10 + '0'; pBuf[12] = ts->hour % 10 + '0'; pBuf[13] = ':'; pBuf[14] = (ts->minute / 10) % 10 + '0'; pBuf[15] = ts->minute % 10 + '0'; pBuf[16] = ':'; pBuf[17] = (ts->second / 10) % 10 + '0'; pBuf[18] = ts->second % 10 + '0'; pBuf[19] = '\0'; return 19; } static int getNormalizedSecFracPower(const struct syslogTime *ts, int *secfrac) { int precision; assert(ts != NULL); assert(secfrac != NULL); assert(ts->secfracPrecision > 0); precision = ts->secfracPrecision; *secfrac = ts->secfrac; while (precision > 6) { *secfrac /= 10; --precision; } return tenPowers[precision - 1]; } /** * Format a syslogTimestamp to just the fractional seconds. * The caller must provide the timestamp as well as a character * buffer that will receive the resulting string. The function * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occurred. * The buffer must be at least 7 bytes large. * rgerhards, 2008-06-06 */ static int formatTimestampSecFrac(struct syslogTime *ts, char *pBuf) { int iBuf; int power; int secfrac; short digit; assert(ts != NULL); assert(pBuf != NULL); iBuf = 0; if (ts->secfracPrecision > 0) { power = getNormalizedSecFracPower(ts, &secfrac); while (power > 0) { digit = secfrac / power; secfrac -= digit * power; power /= 10; pBuf[iBuf++] = digit + '0'; } } else { pBuf[iBuf++] = '0'; } pBuf[iBuf] = '\0'; return iBuf; } /** * Format a syslogTimestamp to a RFC3339 timestamp string (as * specified in syslog-protocol). * The caller must provide the timestamp as well as a character * buffer that will receive the resulting string. The function * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occurred. */ static int formatTimestamp3339(struct syslogTime *ts, char *pBuf) { int iBuf; int power; int secfrac; short digit; assert(ts != NULL); assert(pBuf != NULL); /* start with fixed parts */ /* year yyyy */ pBuf[0] = (ts->year / 1000) % 10 + '0'; pBuf[1] = (ts->year / 100) % 10 + '0'; pBuf[2] = (ts->year / 10) % 10 + '0'; pBuf[3] = ts->year % 10 + '0'; pBuf[4] = '-'; /* month */ pBuf[5] = (ts->month / 10) % 10 + '0'; pBuf[6] = ts->month % 10 + '0'; pBuf[7] = '-'; /* day */ pBuf[8] = (ts->day / 10) % 10 + '0'; pBuf[9] = ts->day % 10 + '0'; pBuf[10] = 'T'; /* hour */ pBuf[11] = (ts->hour / 10) % 10 + '0'; pBuf[12] = ts->hour % 10 + '0'; pBuf[13] = ':'; /* minute */ pBuf[14] = (ts->minute / 10) % 10 + '0'; pBuf[15] = ts->minute % 10 + '0'; pBuf[16] = ':'; /* second */ pBuf[17] = (ts->second / 10) % 10 + '0'; pBuf[18] = ts->second % 10 + '0'; iBuf = 19; /* points to next free entry, now it becomes dynamic! */ if (ts->secfracPrecision > 0) { pBuf[iBuf++] = '.'; power = getNormalizedSecFracPower(ts, &secfrac); while (power > 0) { digit = secfrac / power; secfrac -= digit * power; power /= 10; pBuf[iBuf++] = digit + '0'; } } if (ts->OffsetMode == 'Z') { pBuf[iBuf++] = 'Z'; } else { pBuf[iBuf++] = ts->OffsetMode; pBuf[iBuf++] = (ts->OffsetHour / 10) % 10 + '0'; pBuf[iBuf++] = ts->OffsetHour % 10 + '0'; pBuf[iBuf++] = ':'; pBuf[iBuf++] = (ts->OffsetMinute / 10) % 10 + '0'; pBuf[iBuf++] = ts->OffsetMinute % 10 + '0'; } pBuf[iBuf] = '\0'; return iBuf; } /** * Format a syslogTimestamp to a RFC3164 timestamp string. * The caller must provide the timestamp as well as a character * buffer that will receive the resulting string. The function * returns the size of the timestamp written in bytes (without * the string terminator). If 0 is returend, an error occurred. * rgerhards, 2010-03-05: Added support to for buggy 3164 dates, * where a zero-digit is written instead of a space for the first * day character if day < 10. syslog-ng seems to do that, and some * parsing scripts (in migration cases) rely on that. */ static int formatTimestamp3164(struct syslogTime *ts, char *pBuf, int bBuggyDay) { int iDay; assert(ts != NULL); assert(pBuf != NULL); pBuf[0] = monthNames[(ts->month - 1) % 12][0]; pBuf[1] = monthNames[(ts->month - 1) % 12][1]; pBuf[2] = monthNames[(ts->month - 1) % 12][2]; pBuf[3] = ' '; iDay = (ts->day / 10) % 10; /* we need to write a space if the first digit is 0 */ pBuf[4] = (bBuggyDay || iDay > 0) ? iDay + '0' : ' '; pBuf[5] = ts->day % 10 + '0'; pBuf[6] = ' '; pBuf[7] = (ts->hour / 10) % 10 + '0'; pBuf[8] = ts->hour % 10 + '0'; pBuf[9] = ':'; pBuf[10] = (ts->minute / 10) % 10 + '0'; pBuf[11] = ts->minute % 10 + '0'; pBuf[12] = ':'; pBuf[13] = (ts->second / 10) % 10 + '0'; pBuf[14] = ts->second % 10 + '0'; pBuf[15] = '\0'; return 16; /* traditional: number of bytes written */ } /** * convert syslog timestamp to time_t * Note: it would be better to use something similar to mktime() here. * Unfortunately, mktime() semantics are problematic: first of all, it * works on local time, on the machine's time zone. In syslog, we have * to deal with multiple time zones at once, so we cannot plainly rely * on the local zone, and so we cannot rely on mktime(). One solution would * be to refactor all time-related functions so that they are all guarded * by a mutex to ensure TZ consistency (which would also enable us to * change the TZ at will for specific function calls). But that would * potentially mean a lot of overhead. * Also, mktime() has some side effects, at least setting of tzname. With * a refactoring as described above that should probably not be a problem, * but would also need more work. For some more thoughts on this topic, * have a look here: * http://stackoverflow.com/questions/18355101/is-standard-c-mktime-thread-safe-on-linux * In conclusion, we keep our own code for generating the unix timestamp. * rgerhards, 2016-03-02 */ static time_t syslogTime2time_t(const struct syslogTime *ts) { long MonthInDays, NumberOfYears, NumberOfDays; int utcOffset; time_t TimeInUnixFormat; if (ts->year < 1970 || ts->year > 2100) { TimeInUnixFormat = 0; LogError(0, RS_RET_ERR, "syslogTime2time_t: invalid year %d " "in timestamp - returning 1970-01-01 instead", ts->year); goto done; } /* Counting how many Days have passed since the 01.01 of the * selected Year (Month level), according to the selected Month*/ switch (ts->month) { case 1: MonthInDays = 0; // until 01 of January break; case 2: MonthInDays = 31; // until 01 of February - leap year handling down below! break; case 3: MonthInDays = 59; // until 01 of March break; case 4: MonthInDays = 90; // until 01 of April break; case 5: MonthInDays = 120; // until 01 of May break; case 6: MonthInDays = 151; // until 01 of June break; case 7: MonthInDays = 181; // until 01 of July break; case 8: MonthInDays = 212; // until 01 of August break; case 9: MonthInDays = 243; // until 01 of September break; case 10: MonthInDays = 273; // until 01 of October break; case 11: MonthInDays = 304; // until 01 of November break; case 12: MonthInDays = 334; // until 01 of December break; default: /* this cannot happen (and would be a program error) * but we need the code to keep the compiler silent. */ MonthInDays = 0; /* any value fits ;) */ break; } /* adjust for leap years */ if ((ts->year % 100 != 0 && ts->year % 4 == 0) || (ts->year == 2000)) { if (ts->month > 2) MonthInDays++; } /* 1) Counting how many Years have passed since 1970 2) Counting how many Days have passed since the 01.01 of the selected Year (Day level) according to the Selected Month and Day. Last day doesn't count, it should be until last day 3) Calculating this period (NumberOfDays) in seconds*/ NumberOfYears = ts->year - yearInSec_startYear - 1; NumberOfDays = MonthInDays + ts->day - 1; TimeInUnixFormat = (time_t)(yearInSecs[NumberOfYears] + 1) + NumberOfDays * 86400; /*Add Hours, minutes and seconds */ TimeInUnixFormat += ts->hour * 60 * 60; TimeInUnixFormat += ts->minute * 60; TimeInUnixFormat += ts->second; /* do UTC offset */ utcOffset = ts->OffsetHour * 3600 + ts->OffsetMinute * 60; if (ts->OffsetMode == '+') utcOffset *= -1; /* if timestamp is ahead, we need to "go back" to UTC */ TimeInUnixFormat += utcOffset; done: return TimeInUnixFormat; } /** * Same function as "syslogTime2time_t" * but return time_t value with offset of local TZ */ static time_t syslogTime2time_tLocalTZ(const struct syslogTime *ts) { struct tm tm_local; time_t currtime = time(NULL); long gmtoff = 0; /* Time without offset */ time_t timeWithoutLocalOffset = syslogTime2time_t(ts); if (ts->timeType == TIME_TYPE_RFC5424 || ts->OffsetMode == '+' || ts->OffsetMode == '-') { /* Offset TZ already done, and time is in UTC */ goto done; } if (localtime_r(&currtime, &tm_local) != NULL) { #if defined(_AIX) || defined(__sun) struct tm tm_utc; if (gmtime_r(&currtime, &tm_utc) != NULL) { /* Safely calculate total seconds elapsed in the day for both local and UTC */ long local_secs = tm_local.tm_sec + (tm_local.tm_min * 60) + (tm_local.tm_hour * 3600); long utc_secs = tm_utc.tm_sec + (tm_utc.tm_min * 60) + (tm_utc.tm_hour * 3600); gmtoff = local_secs - utc_secs; /* Account for day wrapping boundaries (including New Year thresholds) */ if (tm_local.tm_year == tm_utc.tm_year) { gmtoff += (tm_local.tm_yday - tm_utc.tm_yday) * 86400; } else if (tm_local.tm_year > tm_utc.tm_year) { gmtoff += 86400; /* Local time rolled into the next year first */ } else { gmtoff -= 86400; /* UTC rolled into the next year first */ } } #else gmtoff = tm_local.tm_gmtoff; #endif timeWithoutLocalOffset -= gmtoff; } done: return timeWithoutLocalOffset; } /** * format a timestamp as a UNIX timestamp; subsecond resolution is * discarded. * Note that this code can use some refactoring. I decided to use it * because mktime() requires an upfront TZ update as it works on local * time. In any case, it is worth reconsidering to move to mktime() or * some other method. * Important: pBuf must point to a buffer of at least 11 bytes. * rgerhards, 2012-03-29 */ static int formatTimestampUnix(struct syslogTime *ts, char *pBuf) { snprintf(pBuf, 11, "%u", (unsigned)syslogTime2time_t(ts)); return 11; } /* 0 - Sunday, 1, Monday, ... * Note that we cannot use strftime() and helpers as they rely on the TZ * variable (again, arghhhh). So we need to do it ourselves... * Note: in the year 2100, this algorithm does not work correctly (due to * leap time rules. To fix it then (*IF* this code really still exists then), * just use 2100 as new anchor year and adapt the initial day number. */ int getWeekdayNbr(struct syslogTime *ts) { int wday; int g, f; g = ts->year; if (ts->month < 3) { g--; f = ts->month + 13; } else { f = ts->month + 1; } wday = ((36525 * g) / 100) + ((306 * f) / 10) + ts->day - 621049; wday %= 7; return wday; } /* getOrdinal - 1-366 day of the year * I've given little thought to leap seconds here. */ int getOrdinal(struct syslogTime *ts) { int yday; time_t thistime; time_t previousyears; int utcOffset; time_t seconds_into_year; if (ts->year < 1970 || ts->year > 2100) { yday = 0; LogError(0, RS_RET_ERR, "getOrdinal: invalid year %d " "in timestamp - returning 1970-01-01 instead", ts->year); goto done; } thistime = syslogTime2time_t(ts); previousyears = (time_t)yearInSecs[ts->year - yearInSec_startYear - 1]; /* adjust previous years to match UTC offset */ utcOffset = ts->OffsetHour * 3600 + ts->OffsetMinute * 60; if (ts->OffsetMode == '+') utcOffset += -1; /* if timestamp is ahead, we need to "go back" to UTC */ previousyears += utcOffset; /* subtract seconds from previous years */ seconds_into_year = thistime - previousyears; /* divide by seconds in a day and truncate to int */ yday = seconds_into_year / 86400; done: return yday; } /* getWeek - 1-52 week of the year */ int getWeek(struct syslogTime *ts) { int weekNum; struct syslogTime yt; int curDow; int jan1Dow; int curYearDay; /* initialize a timestamp for january 1st of the current year */ yt.year = ts->year; yt.month = 1; yt.day = 1; yt.hour = 0; yt.minute = 0; yt.second = 0; yt.secfracPrecision = 0; yt.secfrac = 0; yt.OffsetMinute = ts->OffsetMinute; yt.OffsetHour = ts->OffsetHour; yt.OffsetMode = ts->OffsetMode; yt.timeType = TIME_TYPE_RFC3164; /* low-res time */ /* get current day in year, current day of week * and the day of week of 1/1 */ curYearDay = getOrdinal(ts); curDow = getWeekdayNbr(ts); jan1Dow = getWeekdayNbr(&yt); /* calculate week of year for given date by pinning 1/1 as start * of year, then going back and adjusting for the actual week day. */ weekNum = ((curYearDay + 6) / 7); if (curDow < jan1Dow) { ++weekNum; } return weekNum; } /* getISOWeek - 1-53 week of the year */ int getISOWeek(struct syslogTime *ts, int *year) { int weekNum; int curDow; int curYearDay; /* get current day in year, current day of week * and the day of week of 1/1 */ curYearDay = getOrdinal(ts); curDow = getWeekdayNbr(ts); /* map from 0 - Sunday, 1, Monday to 1, Monday, 7 - Sunday */ if (curDow == 0) { curDow = 7; } /* make ordinal in range 1-366 */ curYearDay++; weekNum = (10 + curYearDay - curDow) / 7; *year = ts->year; if (weekNum == 0) { /* this is actually W52 or W53 of previous year */ weekNum = weeksInYear[ts->year - 1 - 1969]; *year = ts->year - 1; } else if (weekNum > weeksInYear[ts->year - 1969]) { /* this is actually W01 of next year */ weekNum = 1; *year = ts->year + 1; } return weekNum; } void timeConvertToUTC(const struct syslogTime *const __restrict__ local, struct syslogTime *const __restrict__ utc) { struct timeval tp; tp.tv_sec = syslogTime2time_t(local); tp.tv_usec = local->secfrac; timeval2syslogTime(&tp, utc, 1); } /** * Format a UNIX timestamp. */ static int formatUnixTimeFromTime_t(time_t unixtime, const char *format, char *pBuf, __attribute__((unused)) uint pBufMax) { struct tm lt; assert(format != NULL); assert(pBuf != NULL); // Convert to struct tm if (gmtime_r(&unixtime, <) == NULL) { DBGPRINTF("Unexpected error calling gmtime_r().\n"); return -1; } // Do our conversions if (strcmp(format, "date-rfc3164") == 0) { assert(pBufMax >= 16); // Unlikely to run into this situation, but you never know... if (lt.tm_mon < 0 || lt.tm_mon > 11) { DBGPRINTF("lt.tm_mon is out of range. Value: %d\n", lt.tm_mon); return -1; } // MMM dd HH:mm:ss snprintf(pBuf, pBufMax, "%s %2d %.2d:%.2d:%.2d", monthNames[lt.tm_mon], lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec); } else if (strcmp(format, "date-rfc3339") == 0) { assert(pBufMax >= 26); // YYYY-MM-DDTHH:mm:ss+00:00 snprintf(pBuf, pBufMax, "%d-%.2d-%.2dT%.2d:%.2d:%.2dZ", lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec); } return strlen(pBuf); } /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(datetime) CODESTARTobjQueryInterface(datetime); if (pIf->ifVersion != datetimeCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->getCurrTime = getCurrTime; pIf->GetTime = getTime; pIf->timeval2syslogTime = timeval2syslogTime; pIf->ParseTIMESTAMP3339 = ParseTIMESTAMP3339; pIf->ParseTIMESTAMP3164 = ParseTIMESTAMP3164; pIf->formatTimestampToMySQL = formatTimestampToMySQL; pIf->formatTimestampToPgSQL = formatTimestampToPgSQL; pIf->formatTimestampSecFrac = formatTimestampSecFrac; pIf->formatTimestamp3339 = formatTimestamp3339; pIf->formatTimestamp3164 = formatTimestamp3164; pIf->formatTimestampUnix = formatTimestampUnix; pIf->syslogTime2time_t = syslogTime2time_t; pIf->syslogTime2time_tLocalTZ = syslogTime2time_tLocalTZ; pIf->formatUnixTimeFromTime_t = formatUnixTimeFromTime_t; finalize_it: ENDobjQueryInterface(datetime) /* Initialize the datetime class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(datetime, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ ENDObjClassInit(datetime) /* vi:set ai: */rsyslog-8.2608.0/runtime/PaxHeaders/queue.h0000644000000000000000000000013215241075234015522 xustar0030 mtime=1787067036.607578332 30 atime=1787067036.754581084 30 ctime=1787067794.397725111 rsyslog-8.2608.0/runtime/queue.h0000664000175000017500000004076115241075234015176 0ustar00rgerrger/* Definition of the queue support module. * * Copyright 2008-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ /** * @file queue.h * @brief Public interface and data structures for the rsyslog queue subsystem. * * This header defines the primary functions and data structures needed to * interact with rsyslog queues (in-memory, disk, and disk-assisted). It serves * as the main entry point for developers looking to understand how to use and * interact with the queueing mechanism. * * For a detailed discussion of the architectural principles, especially * concerning disk queues, their "Limited Duplication" guarantee, and a * comparison to Write-Ahead Logs (WALs), please see the extensive header * comment in queue.c. * * @see queue.c */ #ifndef QUEUE_H_INCLUDED #define QUEUE_H_INCLUDED #include #include "obj.h" #include "wtp.h" #include "batch.h" #include "stream.h" #include "statsobj.h" #include "cryprov.h" #include "queue_da.h" #include "segdisk_store.h" /* support for the toDelete list */ typedef struct toDeleteLst_s toDeleteLst_t; struct toDeleteLst_s { qDeqID deqID; int nElemDeq; /* numbe of elements that were dequeued and as such must now be discarded */ struct toDeleteLst_s *pNext; }; /* queue types */ typedef enum { QUEUETYPE_FIXED_ARRAY = 0, /* a simple queue made out of a fixed (initially malloced) array fast but memoryhog */ QUEUETYPE_LINKEDLIST = 1, /* linked list used as buffer, lower fixed memory overhead but slower */ QUEUETYPE_DISK = 2, /* disk files used as buffer */ QUEUETYPE_DIRECT = 3, /* no queuing happens, consumer is directly called */ QUEUETYPE_SEGMENTED_DISK = 4 /* log-structured segmented disk queue */ } queueType_t; /* queue recovery modes */ typedef enum { QUEUE_ON_CORRUPTION_SAFE_MODE = 0, QUEUE_ON_CORRUPTION_IN_MEMORY = 1, QUEUE_ON_CORRUPTION_IGNORE = 2 } queueOnCorruption_t; /* list member definition for linked list types of queues: */ typedef struct qLinkedList_S { struct qLinkedList_S *pNext; smsg_t *pMsg; } qLinkedList_t; /** * @brief The "queue object for the queueing subsystem". * * This structure holds the runtime state for a queue instance, especially a * disk-based one. It contains the core pointers that define the Bounded Queue. * * Note on naming: This is named `qqueue` due to historical symbol clashes with * system libraries on some platforms (e.g., AIX). See queue.c for details. */ struct queue_s { BEGINobjInstance ; queueType_t qType; int nLogDeq; /* number of elements currently logically dequeued */ int bShutdownImmediate; /* should all workers cease processing messages? */ DEF_ATOMIC_HELPER_MUT(mutShutdownImmediate); sbool bEnqOnly; /* does queue run in enqueue-only mode (1) or not (0)? */ sbool bSaveOnShutdown; /* persists everthing on shutdown (if DA!)? 1-yes, 0-no */ sbool bQueueStarted; /* has queueStart() been called on this queue? 1-yes, 0-no */ sbool takeFlowCtlFromMsg; /* override enq flow ctl by message property? */ int iQueueSize; /* Current number of elements in the queue */ int iMaxQueueSize; /* how large can the queue grow? */ int iNumWorkerThreads; /* number of worker threads to use */ int iCurNumWrkThrd; /* current number of active worker threads */ int iMinMsgsPerWrkr; /* minimum nbr of msgs per worker thread, if more, a new worker is started until max wrkrs */ wtp_t *pWtpDA; /* single-worker DA transfer pool, not the DA disk queue child consumer pool */ wtp_t *pWtpReg; action_t *pAction; /* for action queues, ptr to action object; for main queues unused */ int iUpdsSincePersist; /* nbr of queue updates since the last persist call */ int iPersistUpdCnt; /* persits queue info after this nbr of updates - 0 -> persist only on shutdown */ sbool bSyncQueueFiles; /* if working with files, sync them after each write? */ int iHighWtrMrk; /* high water mark for disk-assisted memory queues */ int iLowWtrMrk; /* low water mark for disk-assisted memory queues */ int iDiscardMrk; /* if the queue is above this mark, low-severity messages are discarded */ int iFullDlyMrk; /* if the queue is above this mark, FULL_DELAYable message are put on hold */ int iLightDlyMrk; /* if the queue is above this mark, LIGHT_DELAYable message are put on hold */ int iDiscardSeverity; /* messages of this severity above are discarded on too-full queue */ sbool bNeedDelQIF; /* does the QIF file need to be deleted when queue becomes empty? */ queueOnCorruption_t onCorruption; /* what to do on queue corruption */ int toQShutdown; /* timeout for regular queue shutdown in ms */ int toActShutdown; /* timeout for long-running action shutdown in ms */ int toWrkShutdown; /* timeout for idle workers in ms, -1 means indefinite (0 is immediate) */ toDeleteLst_t *toDeleteLst; /* this queue's to-delete list */ int toEnq; /* enqueue timeout */ int iDeqBatchSize; /* max number of elements that shall be dequeued at once */ int iMinDeqBatchSize; /* min number of elements that shall be dequeued at once */ int toMinDeqBatchSize; /* timeout for MinDeqBatchSize, in ms */ /* rate limiting settings (will be expanded) */ int iDeqSlowdown; /* slow down dequeue by specified nbr of microseconds */ /* end rate limiting */ /* dequeue time window settings (may also be expanded) */ int iDeqtWinFromHr; /* begin of dequeue time window (hour only) */ int iDeqtWinToHr; /* end of dequeue time window (hour only), set to 25 to disable deq window! */ /* note that begin and end have specific semantics. It is a big difference if we have * begin 4, end 22 or begin 22, end 4. In the later case, dequeuing will run from 10p, * throughout the night and stop at 4 in the morning. In the first case, it will start * at 4am, run throughout the day, and stop at 10 in the evening! So far, not logic is * applied to detect user configuration errors (and tell me how should we detect what * the user really wanted...). -- rgerhards, 2008-04-02 */ /* end dequeue time window */ rsRetVal (*pConsumer)(void *, batch_t *, wti_t *); /* user-supplied consumer function for dequeued messages */ /* calling interface for pConsumer: arg1 is the global user pointer from this structure, arg2 is the * user pointer array that was dequeued (actual sample: for actions, arg1 is the pAction and arg2 * is pointer to an array of message message pointers) */ /* type-specific handlers (set during construction) */ rsRetVal (*qConstruct)(struct queue_s *pThis); rsRetVal (*qDestruct)(struct queue_s *pThis); rsRetVal (*qAdd)(struct queue_s *pThis, smsg_t *pMsg); rsRetVal (*qDeq)(struct queue_s *pThis, smsg_t **ppMsg); rsRetVal (*qDel)(struct queue_s *pThis); rsRetVal (*qDeqBatch)(struct queue_s *pThis, batch_t *batch, int max, int *skipped); rsRetVal (*qCompleteBatch)(struct queue_s *pThis, batch_t *batch, int *committed, int *retried); /* end type-specific handler */ /* public entry points (set during construction, permit to set best algorithm for params selected) */ rsRetVal (*MultiEnq)(qqueue_t *pThis, multi_submit_t *pMultiSub); /* end public entry points */ /* synchronization variables */ pthread_mutex_t mutThrdMgmt; /* mutex for the queue's thread management */ pthread_mutex_t *mut; /* mutex for enqueing and dequeueing messages */ pthread_cond_t notFull; pthread_cond_t belowFullDlyWtrMrk; /* below eFLOWCTL_FULL_DELAY watermark */ pthread_cond_t belowLightDlyWtrMrk; /* below eFLOWCTL_FULL_DELAY watermark */ int bThrdStateChanged; /* at least one thread state has changed if 1 */ /* end sync variables */ /* the following variables are always present, because they * are not only used for the "disk" queueing mode but also for * any other queueing mode if it is set to "disk assisted". * rgerhards, 2008-01-09 */ uchar *pszSpoolDir; size_t lenSpoolDir; uchar *pszFilePrefix; size_t lenFilePrefix; uchar *pszQIFNam; /* full .qi file name, based on parts above */ size_t lenQIFNam; int iNumberFiles; /* how many files make up the queue? */ int64 iMaxFileSize; /* max size for a single queue file */ int64 sizeOnDiskMax; /* maximum size on disk allowed */ qDeqID deqIDAdd; /* next dequeue ID to use during add to queue store */ qDeqID deqIDDel; /* queue store delete position */ int bIsDA; /* is this queue disk assisted? */ qda_engine_mode_t diskQueueType; /* configured DA disk child selection */ qda_engine_mode_t effectiveDiskQueueType; /* selected DA disk child engine */ sbool diskQueueAutoUpgrade; /* move a drained auto-selected classic child to segmented */ int diskQueueIdleTimeout; /* segmented DA child idle dematerialization timeout */ sbool diskQueueTypeSet; sbool diskQueueAutoUpgradeSet; sbool diskQueueIdleTimeoutSet; sbool segdiskLazyCreate; /* create a fresh segmented store on first append */ sbool segdiskDAChild; /* segmented child of an in-memory DA parent */ sbool daEngineMarkerPending; /* publish the selected DA engine before first append */ uint64_t daActivityGeneration; /* parent enqueue generation for the idle grace period */ uint64_t segdiskIdleObservedActivity; struct queue_s *pqDA; /* queue for disk-assisted modes */ struct queue_s *pqParent; /* pointer to the parent (if this is a child queue) */ int bDAEnqOnly; /* EnqOnly setting for DA queue */ /* now follow queueing mode specific data elements */ // union { /* different data elements based on queue type (qType) */ struct { /* different data elements based on queue type (qType) */ struct { long deqhead, head, tail; void **pBuf; /* the queued user data structure */ } farray; struct { qLinkedList_t *pDeqRoot; qLinkedList_t *pDelRoot; qLinkedList_t *pLast; } linklist; struct { int64 sizeOnDisk; /* current amount of disk space used */ int64 deqOffs; /* offset after dequeue batch - used for file deleter */ int deqFileNumIn; /* same for the circular file numbers, mainly for */ int deqFileNumOut; /* deleting finished files */ strm_t *pWrite; /* current file to be written */ strm_t *pReadDeq; /* current file for dequeueing */ strm_t *pReadDel; /* current file for deleting */ int nForcePersist; /* force persist of .qi file the next "n" times */ int pendingCorruptRet; /* deferred dequeue-time corruption result to recover on next batch */ sbool runtimeCorruptionSkip; /* skipped messages in current batch due to runtime corruption */ } disk; segdisk_store_t *segdisk; } tVars; sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */ uchar *cryprovName; /* crypto provider to use */ cryprov_if_t cryprov; /* ptr to crypto provider interface */ void *cryprovData; /* opaque data ptr for provider use */ uchar *cryprovNameFull; /* full internal crypto provider name */ DEF_ATOMIC_HELPER_MUT(mutQueueSize); DEF_ATOMIC_HELPER_MUT(mutLogDeq); /* for statistics subsystem */ statsobj_t *statsobj; STATSCOUNTER_DEF(ctrEnqueued, mutCtrEnqueued) STATSCOUNTER_DEF(ctrSizeEnqueued, mutCtrSizeEnqueued) /* cumulative bytes enqueued */ STATSCOUNTER_DEF(ctrFull, mutCtrFull) STATSCOUNTER_DEF(ctrFDscrd, mutCtrFDscrd) STATSCOUNTER_DEF(ctrNFDscrd, mutCtrNFDscrd) int ctrMaxqsize; /* NOT guarded by a mutex */ int segdiskBytes; int segdiskSegments; int segdiskCheckpoints; int segdiskReplayed; int segdiskCorruptionEvents; int segdiskCorruptionBytes; int segdiskCorruptionRecords; int segdiskRetryOverageBytes; int segdiskRetryOverageMaxBytes; int segdiskStateWrites; int segdiskForcedStateWrites; int segdiskRecoveryPending; int segdiskRecoveryBytes; int segdiskRecoveryRecords; int segdiskStartupPayloadBytes; int segdiskStartupSegmentFilesProbed; int segdiskCorruptionSegments; int segdiskMaterializations; int segdiskDematerializations; int segdiskIdleCleanupFailures; int iSmpInterval; /* line interval of sampling logs */ int isRunning; }; /* the define below is an "eternal" timeout for the timeout settings which require a value. * It is one day, which is not really eternal, but comes close to it if we think about * rsyslog (e.g.: do you want to wait on shutdown for more than a day? ;)) * rgerhards, 2008-01-17 */ #define QUEUE_TIMEOUT_ETERNAL 24 * 60 * 60 * 1000 /* prototypes */ rsRetVal qqueueDestruct(qqueue_t **ppThis); rsRetVal qqueueEnqMsg(qqueue_t *pThis, flowControl_t flwCtlType, smsg_t *pMsg); rsRetVal qqueueStart(rsconf_t *cnf, qqueue_t *pThis); rsRetVal qqueueSetMaxFileSize(qqueue_t *pThis, size_t iMaxFileSize); rsRetVal qqueueSetFilePrefix(qqueue_t *pThis, uchar *pszPrefix, size_t iLenPrefix); rsRetVal qqueueConstruct(qqueue_t **ppThis, queueType_t qType, int iWorkerThreads, int iMaxQueueSize, rsRetVal (*pConsumer)(void *, batch_t *, wti_t *)); int queueCnfParamsSet(struct nvlst *lst); rsRetVal qqueueApplyCnfParam(qqueue_t *pThis, struct nvlst *lst); void qqueueSetDefaultsRulesetQueue(qqueue_t *pThis); void qqueueSetDefaultsActionQueue(qqueue_t *pThis); void qqueueDbgPrint(qqueue_t *pThis); rsRetVal qqueueShutdownWorkers(qqueue_t *pThis); void qqueueDoneLoadCnf(void); int queuesEqual(qqueue_t *pOld, qqueue_t *pNew); void qqueueCorrectParams(qqueue_t *pThis); PROTOTYPEObjClassInit(qqueue); PROTOTYPEpropSetMeth(qqueue, iPersistUpdCnt, int); PROTOTYPEpropSetMeth(qqueue, bSyncQueueFiles, int); PROTOTYPEpropSetMeth(qqueue, iDeqtWinFromHr, int); PROTOTYPEpropSetMeth(qqueue, iDeqtWinToHr, int); PROTOTYPEpropSetMeth(qqueue, toQShutdown, long); PROTOTYPEpropSetMeth(qqueue, toActShutdown, long); PROTOTYPEpropSetMeth(qqueue, toWrkShutdown, long); PROTOTYPEpropSetMeth(qqueue, toEnq, long); PROTOTYPEpropSetMeth(qqueue, iLightDlyMrk, int); PROTOTYPEpropSetMeth(qqueue, iHighWtrMrk, int); PROTOTYPEpropSetMeth(qqueue, iLowWtrMrk, int); PROTOTYPEpropSetMeth(qqueue, iDiscardMrk, int); PROTOTYPEpropSetMeth(qqueue, iDiscardSeverity, int); PROTOTYPEpropSetMeth(qqueue, iMinMsgsPerWrkr, int); PROTOTYPEpropSetMeth(qqueue, iNumWorkerThreads, int); PROTOTYPEpropSetMeth(qqueue, bSaveOnShutdown, int); PROTOTYPEpropSetMeth(qqueue, pAction, action_t *); PROTOTYPEpropSetMeth(qqueue, iDeqSlowdown, int); PROTOTYPEpropSetMeth(qqueue, sizeOnDiskMax, int64); PROTOTYPEpropSetMeth(qqueue, iDeqBatchSize, int); PROTOTYPEpropSetMeth(qqueue, iMinDeqBatchSize, int); PROTOTYPEpropSetMeth(qqueue, iSmpInterval, int); #define qqueueGetID(pThis) ((unsigned long)pThis) #ifdef ENABLE_IMDIAG extern unsigned int iOverallQueueSize; rsRetVal qqueueSetSegDiskTestFault(qqueue_t *pThis, const char *point, unsigned int hit_count); rsRetVal qqueueClearSegDiskTestFault(qqueue_t *pThis); #endif #endif /* #ifndef QUEUE_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/janitor.c0000644000000000000000000000013215132411300016022 xustar0030 mtime=1768559296.264885609 30 atime=1787067618.034437714 30 ctime=1787067794.286723042 rsyslog-8.2608.0/runtime/janitor.c0000666000175000017500000000574315132411300015501 0ustar00rgerrger/* janitor.c - rsyslog's janitor * * The rsyslog janitor can be used to periodically clean out * resources. It was initially developed to close files that * were not written to for some time (omfile plugin), but has * a generic interface that can be used for all similar tasks. * * Module begun 2014-05-15 by Rainer Gerhards * * Copyright (C) 2014-2015 by Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include "rsyslog.h" #include "janitor.h" static struct janitorEtry *janitorRoot = NULL; static pthread_mutex_t janitorMut = PTHREAD_MUTEX_INITIALIZER; rsRetVal janitorAddEtry(void (*cb)(void *), const char *id, void *pUsr) { struct janitorEtry *etry = NULL; DEFiRet; CHKmalloc(etry = malloc(sizeof(struct janitorEtry))); CHKmalloc(etry->id = strdup(id)); etry->pUsr = pUsr; etry->cb = cb; etry->next = janitorRoot; pthread_mutex_lock(&janitorMut); janitorRoot = etry; pthread_mutex_unlock(&janitorMut); DBGPRINTF("janitor: entry %p, id '%s' added\n", etry, id); finalize_it: if (iRet != RS_RET_OK && etry != NULL) free(etry); RETiRet; } rsRetVal janitorDelEtry(const char *__restrict__ const id) { struct janitorEtry *curr, *prev = NULL; DEFiRet; pthread_mutex_lock(&janitorMut); for (curr = janitorRoot; curr != NULL; curr = curr->next) { if (!strcmp(curr->id, id)) { if (prev == NULL) { janitorRoot = curr->next; } else { prev->next = curr->next; } free(curr->id); free(curr); DBGPRINTF("janitor: deleted entry '%s'\n", id); ABORT_FINALIZE(RS_RET_OK); } prev = curr; } DBGPRINTF("janitor: to be deleted entry '%s' not found\n", id); iRet = RS_RET_NOT_FOUND; finalize_it: pthread_mutex_unlock(&janitorMut); RETiRet; } /* run the janitor; all entries are processed */ void janitorRun(void) { struct janitorEtry *curr; dbgprintf("janitorRun() called\n"); pthread_mutex_lock(&janitorMut); for (curr = janitorRoot; curr != NULL; curr = curr->next) { DBGPRINTF("janitor: processing entry %p, id '%s'\n", curr, curr->id); curr->cb(curr->pUsr); } pthread_mutex_unlock(&janitorMut); } rsyslog-8.2608.0/runtime/PaxHeaders/datetime.h0000644000000000000000000000013115216464436016201 xustar0030 mtime=1782212894.020266087 29 atime=1787067616.84141547 30 ctime=1787067794.328723825 rsyslog-8.2608.0/runtime/datetime.h0000664000175000017500000001007515216464436015651 0ustar00rgerrger/* The datetime object. Contains time-related functions. * * Copyright 2008-2015 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_DATETIME_H #define INCLUDED_DATETIME_H /* TODO: define error codes */ #define NO_ERRCODE -1 /* the datetime object */ typedef struct datetime_s { char dummy; } datetime_t; typedef enum { DATE_INVALID = -1, DATE_RFC3164 = 0, DATE_RFC3339 = 1, DATE_UNIX = 2, } dateTimeFormat_t; /* interfaces */ BEGINinterface(datetime) /* name must also be changed in ENDinterface macro! */ void (*getCurrTime)(struct syslogTime *t, time_t *ttSeconds, const int inUTC); rsRetVal (*ParseTIMESTAMP3339)(struct syslogTime *pTime, uchar **ppszTS, int *); rsRetVal (*ParseTIMESTAMP3164)(struct syslogTime *pTime, uchar **pszTS, int *, const int bParseTZ, const int bDetectYearAfterTime); int (*formatTimestampToMySQL)(struct syslogTime *ts, char *pDst); int (*formatTimestampToPgSQL)(struct syslogTime *ts, char *pDst); int (*formatTimestamp3339)(struct syslogTime *ts, char *pBuf); int (*formatTimestamp3164)(struct syslogTime *ts, char *pBuf, int); int (*formatTimestampSecFrac)(struct syslogTime *ts, char *pBuf); /* v3, 2009-11-12 */ time_t (*GetTime)(time_t *ttSeconds); /* v6, 2011-06-20 , v10, 2016-01-12*/ void (*timeval2syslogTime)(struct timeval *tp, struct syslogTime *t, const int inUTC); /* v7, 2012-03-29 */ int (*formatTimestampUnix)(struct syslogTime *ts, char *pBuf); time_t (*syslogTime2time_t)(const struct syslogTime *ts); /* v11, 2017-10-05 */ int (*formatUnixTimeFromTime_t)(time_t time, const char *format, char *pBuf, uint pBufMax); /* v12, 2026-06-04 */ time_t (*syslogTime2time_tLocalTZ)(const struct syslogTime *ts); ENDinterface(datetime) #define datetimeCURR_IF_VERSION 11 /* increment whenever you change the interface structure! */ /* interface changes: * 1 - initial version * 2 - not compatible to 1 - bugfix required ParseTIMESTAMP3164 to accept char ** as * last parameter. Did not try to remain compatible as this is not something any * third-party module should call. -- rgerhards, 2008.-09-12 * 3 - taken by v5 branch! * 4 - formatTimestamp3164 takes a third int parameter * 5 - merge of versions 3 + 4 (2010-03-09) * 6 - see above * 8 - ParseTIMESTAMP3164 has addtl parameter to permit TZ string parsing * 9 - ParseTIMESTAMP3164 has addtl parameter to permit year parsing * 10 - functions having addtl paramater inUTC to emit time in UTC: * timeval2syslogTime, getCurrtime * 11 - Add formatUnixTimeFromTime_t */ #define PARSE3164_TZSTRING 1 #define NO_PARSE3164_TZSTRING 0 #define PERMIT_YEAR_AFTER_TIME 1 #define NO_PERMIT_YEAR_AFTER_TIME 0 /* two defines for functions that create timestamps either in local * time or UTC. */ #define TIME_IN_UTC 1 #define TIME_IN_LOCALTIME 0 /* prototypes */ PROTOTYPEObj(datetime); void applyDfltTZ(struct syslogTime *pTime, char *tz); int getWeekdayNbr(struct syslogTime *ts); int getOrdinal(struct syslogTime *ts); int getWeek(struct syslogTime *ts); int getISOWeek(struct syslogTime *ts, int *year); void timeConvertToUTC(const struct syslogTime *const __restrict__ local, struct syslogTime *const __restrict__ utc); time_t getTime(time_t *ttSeconds); dateTimeFormat_t getDateTimeFormatFromStr(const char *const __restrict__ s); #endif /* #ifndef INCLUDED_DATETIME_H */rsyslog-8.2608.0/runtime/PaxHeaders/janitor.h0000644000000000000000000000013215132411300016027 xustar0030 mtime=1768559296.264885609 30 atime=1787067618.420444912 30 ctime=1787067794.289723098 rsyslog-8.2608.0/runtime/janitor.h0000666000175000017500000000227715132411300015505 0ustar00rgerrger/* rsyslog's janitor * * Copyright (C) 2014 by Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_JANITOR_H #define INCLUDED_JANITOR_H struct janitorEtry { struct janitorEtry *next; char *id; /* ID used to remove entry */ void (*cb)(void *pUsr); void *pUsr; /* user-settable pointer (passed to callback) */ }; rsRetVal janitorAddEtry(void (*cb)(void *), const char *id, void *pUsr); rsRetVal janitorDelEtry(const char *__restrict__ const id); void janitorRun(void); #endif /* #ifndef INCLUDED_JANITOR_H */ rsyslog-8.2608.0/runtime/PaxHeaders/srutils.c0000644000000000000000000000013215241075234016076 xustar0030 mtime=1787067036.610578388 30 atime=1787067036.756581122 30 ctime=1787067794.330723862 rsyslog-8.2608.0/runtime/srutils.c0000664000175000017500000006703615241075234015556 0ustar00rgerrger/**\file srUtils.c * \brief General utilties that fit nowhere else. * * The namespace for this file is "srUtil". * * \author Rainer Gerhards * \date 2003-09-09 * Coding begun. * * Copyright 2003-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "obj.h" #include "errmsg.h" #include "glbl.h" #include "rsconf.h" #include "unicode-helper.h" #if _POSIX_TIMERS <= 0 #include #endif /* here we host some syslog specific names. There currently is no better place * to do it, but over here is also not ideal... -- rgerhards, 2008-02-14 * rgerhards, 2008-04-16: note in LGPL move: the code tables below exist in * the same way in BSD, so it is not a problem to move them from GPLv3 to LGPL. * And nobody modified them since it was under LGPL, so we can also move it * to ASL 2.0. */ syslogName_t syslogPriNames[] = { {"alert", LOG_ALERT}, {"crit", LOG_CRIT}, {"debug", LOG_DEBUG}, {"emerg", LOG_EMERG}, {"err", LOG_ERR}, {"error", LOG_ERR}, /* DEPRECATED */ {"info", LOG_INFO}, {"none", INTERNAL_NOPRI}, /* INTERNAL */ {"notice", LOG_NOTICE}, {"panic", LOG_EMERG}, /* DEPRECATED */ {"warn", LOG_WARNING}, /* DEPRECATED */ {"warning", LOG_WARNING}, {"*", TABLE_ALLPRI}, {NULL, -1}}; #ifndef LOG_AUTHPRIV #define LOG_AUTHPRIV LOG_AUTH #endif syslogName_t syslogFacNames[] = { {"auth", LOG_AUTH}, {"authpriv", LOG_AUTHPRIV}, {"cron", LOG_CRON}, {"daemon", LOG_DAEMON}, {"kern", LOG_KERN}, {"lpr", LOG_LPR}, {"mail", LOG_MAIL}, {"mark", LOG_MARK}, /* INTERNAL */ {"news", LOG_NEWS}, {"ntp", (12 << 3)}, /* NTP, perhaps BSD-specific? */ {"security", LOG_AUTH}, /* DEPRECATED */ {"bsd_security", (13 << 3)}, /* BSD-specific, unfortunatly with duplicate name... */ {"syslog", LOG_SYSLOG}, {"user", LOG_USER}, {"uucp", LOG_UUCP}, #if defined(_AIX) /* AIXPORT : These are necessary for AIX */ {"caa", LOG_CAA}, {"aso", LOG_ASO}, #endif #if defined(LOG_FTP) {"ftp", LOG_FTP}, #endif #if defined(LOG_AUDIT) {"audit", LOG_AUDIT}, #endif {"console", (14 << 3)}, /* BSD-specific priority */ {"local0", LOG_LOCAL0}, {"local1", LOG_LOCAL1}, {"local2", LOG_LOCAL2}, {"local3", LOG_LOCAL3}, {"local4", LOG_LOCAL4}, {"local5", LOG_LOCAL5}, {"local6", LOG_LOCAL6}, {"local7", LOG_LOCAL7}, {"invld", LOG_INVLD}, {NULL, -1}, }; /* ################################################################# * * private members * * ################################################################# */ /* As this is not a "real" object, there won't be any private * members in this file. */ /* ################################################################# * * public members * * ################################################################# */ rsRetVal srUtilItoA(char *pBuf, int iLenBuf, number_t iToConv) { int i; int bIsNegative; char szBuf[64]; /* sufficiently large for my lifespan and those of my children... ;) */ assert(pBuf != NULL); assert(iLenBuf > 1); /* This is actually an app error and as thus checked for... */ if (iToConv < 0) { bIsNegative = RSTRUE; iToConv *= -1; } else bIsNegative = RSFALSE; /* first generate a string with the digits in the reverse direction */ i = 0; do { szBuf[i++] = iToConv % 10 + '0'; iToConv /= 10; } while (iToConv > 0); /* warning: do...while()! */ --i; /* undo last increment - we were pointing at NEXT location */ /* make sure we are within bounds... */ if (i + 2 > iLenBuf) /* +2 because: a) i starts at zero! b) the \0 byte */ return RS_RET_PROVIDED_BUFFER_TOO_SMALL; /* then move it to the right direction... */ if (bIsNegative == RSTRUE) *pBuf++ = '-'; while (i >= 0) *pBuf++ = szBuf[i--]; *pBuf = '\0'; /* terminate it!!! */ return RS_RET_OK; } uchar *srUtilStrDup(uchar *pOld, size_t len) { uchar *pNew; assert(pOld != NULL); if ((pNew = malloc(len + 1)) != NULL) memcpy(pNew, pOld, len + 1); return pNew; } /* creates a path recursively * Return 0 on success, -1 otherwise. On failure, errno * hold the last OS error. * Param "mode" holds the mode that all non-existing directories are to be * created with. * Note that we have a potential race inside that code, a race that even exists * outside of the rsyslog process (if multiple instances run, or other programs * generate directories): If the directory does not exist, a context switch happens, * at that moment another process creates it, then our creation on the context * switch back fails. This actually happened in practice, and depending on the * configuration it is even likely to happen. We can not solve this situation * with a mutex, as that works only within out process space. So the solution * is that we take the optimistic approach, try the creation, and if it fails * with "already exists" we go back and do one retry of the check/create * sequence. That should then succeed. If the directory is still not found but * the creation fails in the similar way, we return an error on that second * try because otherwise we would potentially run into an endless loop. * loop. -- rgerhards, 2010-03-25 * The likeliest scenario for a prolonged contest of creating the parent directiories * is within our process space. This can happen with a high probability when two * threads, that want to start logging to files within same directory tree, are * started close to each other. We should fix what we can. -- nipakoo, 2017-11-25 */ static int real_makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode, const uid_t uid, const gid_t gid, const int bFailOnChownFail) { uchar *p; uchar *pszWork; size_t len; assert(szFile != NULL); assert(lenFile > 0); len = lenFile + 1; /* add one for '\0'-byte */ if ((pszWork = malloc(len)) == NULL) return -1; memcpy(pszWork, szFile, len); for (p = pszWork + 1; *p; p++) if (*p == '/') { /* temporarily terminate string, create dir and go on */ *p = '\0'; int bErr = 0; if (mkdir((char *)pszWork, mode) == 0) { if (uid != (uid_t)-1 || gid != (gid_t)-1) { /* we need to set owner/group */ if (chown((char *)pszWork, uid, gid) != 0) { LogError(errno, RS_RET_DIR_CHOWN_ERROR, "chown for directory '%s' failed", pszWork); if (bFailOnChownFail) { /* ignore if configured to do so */ bErr = 1; } } } } else if (errno != EEXIST) { /* EEXIST is ok, means this component exists */ bErr = 1; } if (bErr) { int eSave = errno; free(pszWork); errno = eSave; return -1; } *p = '/'; } free(pszWork); return 0; } /* note: this small function is the stub for the brain-dead POSIX cancel handling */ int makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode, const uid_t uid, const gid_t gid, const int bFailOnChownFail) { static pthread_mutex_t mutParentDir = PTHREAD_MUTEX_INITIALIZER; int r; /* needs to be declared OUTSIDE of pthread_cleanup... macros! */ pthread_mutex_lock(&mutParentDir); pthread_cleanup_push(mutexCancelCleanup, &mutParentDir); r = real_makeFileParentDirs(szFile, lenFile, mode, uid, gid, bFailOnChownFail); pthread_mutex_unlock(&mutParentDir); pthread_cleanup_pop(0); return r; } /** * @brief Execute a program with up to two optional arguments. * * This helper forks and then execs `program`. In the child process it resets * all signal handlers to defaults and clears any pending alarm before exec. * That behavior is intentional to avoid inheriting rsyslogd signal handling * into the external command. * * Arguments are optional and passed as-is (no shell parsing). If @p arg1 is * NULL and @p arg2 is non-NULL, @p arg2 is shifted into the first argument * position so callers can pass either only arg2 or both without extra logic. * * If bWait is set, the parent will wait for the child to exit and record * its status via glblReportChildProcessExit(). If not set, the child is * allowed to continue independently. * * @param program Executable name/path to run. * @param bWait If non-zero, wait for the child to exit before returning. * @param arg1 Optional first argument (may be NULL). * @param arg2 Optional second argument (may be NULL). * @return Child PID on success, 0 on fork failure (errno set). */ int execProg(uchar *program, int bWait, uchar *arg1, uchar *arg2) { int pid; int sig; struct sigaction sigAct; char *exec_argv[4]; int argc = 1; exec_argv[0] = (char *)program; if (arg1 == NULL && arg2 != NULL) { arg1 = arg2; arg2 = NULL; } if (arg1 != NULL) exec_argv[argc++] = (char *)arg1; if (arg2 != NULL) exec_argv[argc++] = (char *)arg2; exec_argv[argc] = NULL; dbgprintf("exec program '%s' with %d args\n", program, argc - 1); pid = fork(); if (pid < 0) { return 0; } if (pid) { /* Parent */ if (bWait) { /* waitpid will fail with errno == ECHILD if the child process has already been reaped by the rsyslogd main loop (see rsyslogd.c) */ int status; if (waitpid(pid, &status, 0) == pid) { glblReportChildProcessExit(runConf, program, pid, status); } else if (errno != ECHILD) { /* we do not use logerror(), because * that might bring us into an endless * loop. At some time, we may * reconsider this behaviour. */ dbgprintf("could not wait on child after executing '%s'", (char *)program); } } return pid; } /* Child */ alarm(0); /* create a clean environment before we exec the real child */ memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = SIG_DFL; for (sig = 1; sig < NSIG; ++sig) sigaction(sig, &sigAct, NULL); execvp((char *)program, exec_argv); /* In the long term, it's a good idea to implement some enhanced error * checking here. However, it can not easily be done. For starters, we * may run into endless loops if we log to syslog. The next problem is * that output is typically not seen by the user. For the time being, * we use no error reporting, which is quite consitent with the old * system() way of doing things. rgerhards, 2007-07-20 */ perror("exec"); fprintf(stderr, "exec program was '%s'\n", program); exit(1); /* not much we can do in this case */ } /* skip over whitespace in a standard C string. The * provided pointer is advanced to the first non-whitespace * charater or the \0 byte, if there is none. It is never * moved past the \0. */ void skipWhiteSpace(uchar **pp) { register uchar *p; assert(pp != NULL); assert(*pp != NULL); p = *pp; while (*p && isspace((int)*p)) ++p; *pp = p; } /* generate a file name from four parts: * /. * If number is negative, it is not used. If any of the strings is * NULL, an empty string is used instead. Length must be provided. * lNumDigits is the minimum number of digits that lNum should have. This * is to pretty-print the file name, e.g. lNum = 3, lNumDigits= 4 will * result in "0003" being used inside the file name. Set lNumDigits to 0 * to use as few space as possible. * rgerhards, 2008-01-03 */ PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wformat_nonliteral rsRetVal genFileName( uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName, size_t lenFName, int64_t lNum, int lNumDigits) { DEFiRet; uchar *pName; uchar *pNameWork; size_t lenName; uchar szBuf[128]; /* buffer for number */ char szFmtBuf[32]; /* buffer for snprintf format */ size_t lenBuf; if (lNum < 0) { szBuf[0] = '\0'; lenBuf = 0; } else { if (lNumDigits > 0) { snprintf(szFmtBuf, sizeof(szFmtBuf), ".%%0%d" PRId64, lNumDigits); lenBuf = snprintf((char *)szBuf, sizeof(szBuf), szFmtBuf, lNum); } else lenBuf = snprintf((char *)szBuf, sizeof(szBuf), ".%" PRId64, lNum); } lenName = lenDirName + 1 + lenFName + lenBuf + 1; /* last +1 for \0 char! */ if ((pName = malloc(lenName)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* got memory, now construct string */ memcpy(pName, pDirName, lenDirName); pNameWork = pName + lenDirName; *pNameWork++ = '/'; memcpy(pNameWork, pFName, lenFName); pNameWork += lenFName; if (lenBuf > 0) { memcpy(pNameWork, szBuf, lenBuf); pNameWork += lenBuf; } *pNameWork = '\0'; *ppName = pName; finalize_it: RETiRet; } PRAGMA_DIAGNOSTIC_POP /* get the number of digits required to represent a given number. We use an * iterative approach as we do not like to draw in the floating point * library just for log(). -- rgerhards, 2008-01-10 */ int getNumberDigits(long lNum) { int iDig; if (lNum == 0) iDig = 1; else for (iDig = 0; lNum != 0; ++iDig) lNum /= 10; return iDig; } /* compute an absolute time timeout suitable for calls to pthread_cond_timedwait() * iTimeout is in milliseconds * rgerhards, 2008-01-14 */ rsRetVal timeoutComp(struct timespec *pt, long iTimeout) { #if _POSIX_TIMERS <= 0 struct timeval tv; #endif assert(pt != NULL); /* compute timeout */ #if _POSIX_TIMERS > 0 /* this is the "regular" code */ clock_gettime(CLOCK_REALTIME, pt); #else gettimeofday(&tv, NULL); pt->tv_sec = tv.tv_sec; pt->tv_nsec = tv.tv_usec * 1000; #endif pt->tv_sec += iTimeout / 1000; pt->tv_nsec += (iTimeout % 1000) * 1000000; /* think INTEGER arithmetic! */ if (pt->tv_nsec > 999999999) { /* overrun? */ pt->tv_nsec -= 1000000000; ++pt->tv_sec; } return RS_RET_OK; /* so far, this is static... */ } long long currentTimeMills(void) { struct timespec tm; #if _POSIX_TIMERS <= 0 struct timeval tv; #endif #if _POSIX_TIMERS > 0 clock_gettime(CLOCK_REALTIME, &tm); #else gettimeofday(&tv, NULL); tm.tv_sec = tv.tv_sec; tm.tv_nsec = tv.tv_usec * 1000; #endif return ((long long)tm.tv_sec) * 1000 + (tm.tv_nsec / 1000000); } /* This function is kind of the reverse of timeoutComp() - it takes an absolute * timeout value and computes how far this is in the future. If the value is already * in the past, 0 is returned. The return value is in ms. * rgerhards, 2008-01-25 */ long timeoutVal(struct timespec *pt) { struct timespec t; long iTimeout; #if _POSIX_TIMERS <= 0 struct timeval tv; #endif assert(pt != NULL); /* compute timeout */ #if _POSIX_TIMERS > 0 /* this is the "regular" code */ clock_gettime(CLOCK_REALTIME, &t); #else gettimeofday(&tv, NULL); t.tv_sec = tv.tv_sec; t.tv_nsec = tv.tv_usec * 1000; #endif iTimeout = (pt->tv_nsec - t.tv_nsec) / 1000000; iTimeout += (pt->tv_sec - t.tv_sec) * 1000; if (iTimeout < 0) iTimeout = 0; return iTimeout; } /* cancellation cleanup handler - frees provided mutex * rgerhards, 2008-01-14 */ void mutexCancelCleanup(void *arg) { assert(arg != NULL); d_pthread_mutex_unlock((pthread_mutex_t *)arg); } /* rsSleep() - a fairly portable way to to sleep. It * will wake up when * a) the wake-time is over * rgerhards, 2008-01-28 */ void srSleep(int iSeconds, int iuSeconds) { struct timeval tvSelectTimeout; tvSelectTimeout.tv_sec = iSeconds; tvSelectTimeout.tv_usec = iuSeconds; /* micro seconds */ select(0, NULL, NULL, NULL, &tvSelectTimeout); } /* From varmojfekoj's mail on why he provided rs_strerror_r(): * There are two problems with strerror_r(): * I see you've rewritten some of the code which calls it to use only * the supplied buffer; unfortunately the GNU implementation sometimes * doesn't use the buffer at all and returns a pointer to some * immutable string instead, as noted in the man page. * * The other problem is that on some systems strerror_r() has a return * type of int. * * So I've written a wrapper function rs_strerror_r(), which should * take care of all this and be used instead. * * Added 2008-01-30 */ char *rs_strerror_r(int errnum, char *buf, size_t buflen) { #ifndef HAVE_STRERROR_R char *pszErr; pszErr = strerror(errnum); if (buflen > 0) { rs_cstr_copy(buf, pszErr, buflen); } #else #ifdef STRERROR_R_CHAR_P char *p = strerror_r(errnum, buf, buflen); if (p != buf) { if (buflen > 0) { rs_cstr_copy(buf, p, buflen); } } #else strerror_r(errnum, buf, buflen); #endif #endif /* #ifdef __hpux */ return buf; } /* Decode a symbolic name to a numeric value */ int decodeSyslogName(uchar *name, syslogName_t *codetab) { register syslogName_t *c; register uchar *p; char *end = NULL; long val; uchar buf[80]; assert(name != NULL); assert(codetab != NULL); DBGPRINTF("symbolic name: %s", name); if (isdigit((int)*name)) { DBGPRINTF("\n"); errno = 0; val = strtol((char *)name, &end, 10); if (errno != 0 || end == (char *)name || *end != '\0' || val < INT_MIN || val > INT_MAX) { return -1; } return (int)val; } u_cstr_copy(buf, name, sizeof(buf)); for (p = buf; *p; p++) { if (isupper((int)*p)) *p = tolower((int)*p); } for (c = codetab; c->c_name; c++) { if (!strcmp((char *)buf, (char *)c->c_name)) { DBGPRINTF(" ==> %d\n", c->c_val); return (c->c_val); } } DBGPRINTF("\n"); return (-1); } /** * getSubString * * Copy a string byte by byte until the occurrence * of a given separator. * * \param ppSrc Pointer to a pointer of the source array of characters. If a separator detected the Pointer points to the next char after the separator. Except if the end of the string is dedected ('\n'). Then it points to the terminator char. * \param pDst Pointer to the destination array of characters. Here the substing will be stored. * \param DstSize Maximum numbers of characters to store. * \param cSep Separator char. * \ret int Returns 0 if no error occurred. * * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time * so that it treats ' ' as a request for whitespace. But in general, the function and its callers * should be changed over time, this is not really very good code... */ int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep) { uchar *pSrc = *ppSrc; int iErr = 0; /* 0 = no error, >0 = error */ while ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize > 1) { *pDst++ = *(pSrc)++; DstSize--; } /* check if the Dst buffer was to small */ if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') { dbgprintf("in getSubString, error Src buffer > Dst buffer\n"); iErr = 1; } if (*pSrc == '\0' || *pSrc == '\n') /* this line was missing, causing ppSrc to be invalid when it * was returned in case of end-of-string. rgerhards 2005-07-29 */ *ppSrc = pSrc; else *ppSrc = pSrc + 1; *pDst = '\0'; return iErr; } /* get the size of a file or return appropriate error code. If an error is returned, * *pSize content is undefined. * rgerhards, 2009-06-12 */ rsRetVal getFileSize(uchar *pszName, off_t *pSize) { int ret; struct stat statBuf; DEFiRet; ret = stat((char *)pszName, &statBuf); if (ret == -1) { switch (errno) { case EACCES: ABORT_FINALIZE(RS_RET_NO_FILE_ACCESS); case ENOTDIR: case ENOENT: ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); default: ABORT_FINALIZE(RS_RET_FILE_NO_STAT); } } *pSize = statBuf.st_size; finalize_it: RETiRet; } /* Returns 1 if the given string contains a non-escaped glob(3) * wildcard character and 0 otherwise (or if the string is empty). */ int containsGlobWildcard(char *str) { char *p; if (!str) { return 0; } /* From Linux Programmer's Guide: * "A string is a wildcard pattern if it contains one of the characters '?', '*', '{' or '['" * "One can remove the special meaning of '?', '*', '{' and '[' by preceding them by a backslash" */ for (p = str; *p != '\0'; p++) { if ((*p == '?' || *p == '*' || *p == '[' || *p == '{') && (p == str || *(p - 1) != '\\')) { return 1; } } return 0; } static void seedRandomInsecureNumber(void) { struct timespec t; timeoutComp(&t, 0); long long x = t.tv_sec * 3 + t.tv_nsec * 2; srandom((unsigned int)x); } static long int randomInsecureNumber(void) { return random(); } #ifdef OS_LINUX static int fdURandom = -1; void seedRandomNumber(void) { if (fdURandom >= 0) { /* Already opened. */ return; } fdURandom = open("/dev/urandom", O_RDONLY); if (fdURandom == -1) { LogError(errno, RS_RET_IO_ERROR, "failed to seed random number generation," " will use fallback (open urandom failed)"); seedRandomInsecureNumber(); } } void seedRandomNumberForChild(void) { /* The file descriptor inherited from our parent will have been closed after * the fork. Discard this and call seedRandomNumber() to open /dev/urandom * again. */ fdURandom = -1; seedRandomNumber(); } long int randomNumber(void) { long int ret; if (fdURandom >= 0) { if (read(fdURandom, &ret, sizeof(long int)) == -1) { LogError(errno, RS_RET_IO_ERROR, "failed to generate random number, will" " use fallback (read urandom failed)"); ret = randomInsecureNumber(); } } else { ret = randomInsecureNumber(); } return ret; } #else void seedRandomNumber(void) { seedRandomInsecureNumber(); } void seedRandomNumberForChild(void) { seedRandomNumber(); } long int randomNumber(void) { return randomInsecureNumber(); } #endif /* process "binary" parameters where this is needed to execute * programs (namely mmexternal and omprog). * Most importantly, split them into argv[] and get the binary name */ rsRetVal ATTR_NONNULL() split_binary_parameters(uchar **const szBinary, char ***const __restrict__ aParams, int *const iParams, es_str_t *const param_binary) { es_size_t iCnt; es_size_t iStr; int iPrm; es_str_t *estrParams = NULL; es_str_t *estrBinary = param_binary; es_str_t *estrTmp = NULL; uchar *c; int bInQuotes; DEFiRet; assert(iParams != NULL); assert(param_binary != NULL); /* Search for end of binary name */ c = es_getBufAddr(param_binary); iCnt = 0; while (iCnt < es_strlen(param_binary)) { if (c[iCnt] == ' ') { /* Split binary name from parameters */ estrBinary = es_newStrFromSubStr(param_binary, 0, iCnt); estrParams = es_newStrFromSubStr(param_binary, iCnt + 1, es_strlen(param_binary)); break; } iCnt++; } *szBinary = (uchar *)es_str2cstr(estrBinary, NULL); DBGPRINTF("szBinary = '%s'\n", *szBinary); *iParams = 1; /* we always have argv[0] */ /* count size of argv[] */ if (estrParams != NULL) { (*iParams)++; /* last parameter is not counted in loop below! */ if (Debug) { char *params = es_str2cstr(estrParams, NULL); dbgprintf("szParams = '%s'\n", params); free(params); } c = es_getBufAddr(estrParams); for (iCnt = 0; iCnt < es_strlen(estrParams); ++iCnt) { if (c[iCnt] == ' ' && c[iCnt - 1] != '\\') (*iParams)++; } } DBGPRINTF("iParams %d (+1 for NULL terminator)\n", *iParams); /* create argv[] */ CHKmalloc(*aParams = calloc(*iParams + 1, sizeof(char *))); iPrm = 0; bInQuotes = FALSE; /* Set first parameter to binary */ (*aParams)[iPrm] = strdup((char *)*szBinary); iPrm++; if (estrParams != NULL) { iCnt = iStr = 0; c = es_getBufAddr(estrParams); /* Reset to beginning */ while (iCnt < es_strlen(estrParams)) { if (c[iCnt] == '"' && iCnt == iStr && !bInQuotes) { bInQuotes = TRUE; iStr++; } else { int bEOL = iCnt + 1 == es_strlen(estrParams); int bSpace = c[iCnt] == ' '; int bQuoteEnd = bInQuotes && ((bSpace && c[iCnt - 1] == '"') || (c[iCnt] == '"' && bEOL)); if (bEOL || bQuoteEnd || (bSpace && !bInQuotes)) { int iSubCnt = iCnt - iStr; if (bEOL) iSubCnt++; if (bQuoteEnd) iSubCnt--; estrTmp = es_newStrFromSubStr(estrParams, iStr, iSubCnt); } if (bQuoteEnd) bInQuotes = FALSE; } if (estrTmp != NULL) { (*aParams)[iPrm] = es_str2cstr(estrTmp, NULL); iStr = iCnt + 1; /* Set new start */ DBGPRINTF("Param (%d): '%s'\n", iPrm, (*aParams)[iPrm]); es_deleteStr(estrTmp); estrTmp = NULL; iPrm++; } iCnt++; } } (*aParams)[iPrm] = NULL; /* NULL per argv[] convention */ finalize_it: if (estrBinary != param_binary) { es_deleteStr(estrBinary); } if (estrParams != NULL) { es_deleteStr(estrParams); } RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/perctile_ringbuf.c0000644000000000000000000000013115132411300017676 xustar0030 mtime=1768559296.272885735 30 atime=1787067617.929435756 29 ctime=1787067794.36872457 rsyslog-8.2608.0/runtime/perctile_ringbuf.c0000666000175000017500000002311215132411300017344 0ustar00rgerrger/* * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "perctile_ringbuf.h" static uint64_t min(uint64_t a, uint64_t b) { return a < b ? a : b; } /* * circ buf macros derived from linux/circ_buf.h */ /* Return count in buffer. */ #define CIRC_CNT(head, tail, size) (((head) - (tail)) & ((size) - 1)) /* Return space available, 0..size-1. We always leave one free char as a completely full buffer has head == tail, which is the same as empty. */ #define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), ((head) + 1), (size)) /* Return count up to the end of the buffer. Carefully avoid accessing head and tail more than once, so they can change underneath us without returning inconsistent results. */ #define CIRC_CNT_TO_END(head, tail, size) \ ({ \ int end = (size) - (tail); \ int n = ((head) + end) & ((size) - 1); \ n < end ? n : end; \ }) /* Return space available up to the end of the buffer. */ #define CIRC_SPACE_TO_END(head, tail, size) \ ({ \ int end = (size) - 1 - (head); \ int n = (end + (tail)) & ((size) - 1); \ n <= end ? n : end + 1; \ }) /* Move head by size. */ #define CIRC_ADD(idx, size, offset) (((idx) + (offset)) & ((size) - 1)) // simple use of the linux defined circular buffer. ringbuf_t *ringbuf_new(size_t count) { // use nearest power of 2 double x = ceil(log2(count)); size_t bufsize = pow(2, x); ringbuf_t *rb = calloc(1, sizeof(ringbuf_t)); // Note: count needs to be a power of 2, otherwise our macros won't work. ITEM *pbuf = calloc(bufsize, sizeof(ITEM)); rb->cb.buf = pbuf; rb->cb.head = rb->cb.tail = 0; rb->size = bufsize; return rb; } void ringbuf_del(ringbuf_t *rb) { if (rb) { if (rb->cb.buf) { free(rb->cb.buf); } free(rb); } } int ringbuf_append(ringbuf_t *rb, ITEM item) { // lock it and add int head = rb->cb.head, tail = rb->cb.tail; if (!CIRC_SPACE(head, tail, rb->size)) { return -1; } else { /* insert item into buffer */ rb->cb.buf[head] = item; // move head rb->cb.head = CIRC_ADD(head, rb->size, 1); } return 0; } int ringbuf_append_with_overwrite(ringbuf_t *rb, ITEM item) { int head = rb->cb.head, tail = rb->cb.tail; int ret = 0; if (!CIRC_SPACE(head, tail, rb->size)) { rb->cb.tail = CIRC_ADD(tail, rb->size, 1); } ret = ringbuf_append(rb, item); assert(ret == 0); // we shouldn't fail due to no space. return ret; } int ringbuf_read(ringbuf_t *rb, ITEM *buf, size_t count) { int head = rb->cb.head, tail = rb->cb.tail; size_t copy_size = 0; if (!CIRC_CNT(head, tail, rb->size)) { return 0; } // copy to end of buffer copy_size = min((size_t)CIRC_CNT_TO_END(head, tail, rb->size), count); memcpy(buf, rb->cb.buf + tail, copy_size * sizeof(ITEM)); rb->cb.tail = CIRC_ADD(rb->cb.tail, rb->size, copy_size); return copy_size; } size_t ringbuf_read_to_end(ringbuf_t *rb, ITEM *buf, size_t count) { size_t nread = 0; nread += ringbuf_read(rb, buf, count); if (nread == 0) { return nread; } // read the rest if buf circled around nread += ringbuf_read(rb, buf + nread, count - nread); assert(nread <= count); return nread; } bool ringbuf_peek(ringbuf_t *rb, ITEM *item) { if (CIRC_CNT(rb->cb.head, rb->cb.tail, rb->size) == 0) { return false; } *item = rb->cb.buf[rb->cb.tail]; return true; } size_t ringbuf_capacity(ringbuf_t *rb) { return rb->size; } /* ---- RINGBUFFER TESTS ---- */ void ringbuf_init_test(void) { size_t count = 4; ringbuf_t *rb = ringbuf_new(count); // verify ringbuf empty state assert(rb->cb.head == 0); assert(rb->cb.tail == 0); assert(rb->size == 4); ringbuf_del(rb); } void ringbuf_simple_test(void) { size_t count = 3; ITEM item = 0; ringbuf_t *rb = ringbuf_new(count); assert(ringbuf_append(rb, 1) == 0); assert(ringbuf_append(rb, 2) == 0); assert(ringbuf_append(rb, 3) == 0); item = 0; assert(ringbuf_peek(rb, &item) == 0); assert(item == 1); } void ringbuf_append_test(void) { size_t count = 4; ringbuf_t *rb = ringbuf_new(count); assert(ringbuf_append(rb, 1) == 0); assert(ringbuf_append(rb, 2) == 0); assert(ringbuf_append(rb, 3) == 0); // check state of ringbuffer: // {1, 2, 3, X} // T H assert(rb->cb.buf[0] == 1); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.buf[3] == 0); assert(rb->cb.head == 3); assert(rb->cb.tail == 0); ringbuf_del(rb); } void ringbuf_append_wrap_test(void) { size_t count = 4; ITEM item = 0; ringbuf_t *rb = ringbuf_new(count); assert(ringbuf_append(rb, 1) == 0); assert(ringbuf_append(rb, 2) == 0); assert(ringbuf_append(rb, 3) == 0); assert(ringbuf_append(rb, 4) != 0); // check state of ringbuffer: // {1, 2, 3, X} // T H assert(rb->cb.buf[0] == 1); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.head == 3); assert(rb->cb.tail == 0); item = 0; assert(ringbuf_read(rb, &item, 1) == 1); assert(item == 1); assert(ringbuf_append(rb, 4) == 0); // state of ringbuffer: // {1, 2, 3, 4} // H T assert(rb->cb.buf[0] == 1); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.buf[3] == 4); assert(rb->cb.head == 0); assert(rb->cb.tail == 1); item = 0; assert(ringbuf_read(rb, &item, 1) == 1); assert(item == 2); // test wraparound assert(ringbuf_append(rb, 5) == 0); // state of ringbuffer: // {1, 2, 3, 4} // H T assert(rb->cb.buf[0] == 5); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.buf[3] == 4); assert(rb->cb.head == 1); assert(rb->cb.tail == 2); ringbuf_del(rb); } void ringbuf_append_overwrite_test(void) { size_t count = 4; ringbuf_t *rb = ringbuf_new(count); assert(ringbuf_append_with_overwrite(rb, 1) == 0); assert(ringbuf_append_with_overwrite(rb, 2) == 0); assert(ringbuf_append_with_overwrite(rb, 3) == 0); assert(ringbuf_append_with_overwrite(rb, 4) == 0); // check state of ringbuffer: // {1, 2, 3, 4} // H T assert(rb->cb.buf[0] == 1); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.buf[3] == 4); assert(rb->cb.head == 0); assert(rb->cb.tail == 1); assert(ringbuf_append_with_overwrite(rb, 5) == 0); // check state of ringbuffer: // {5, 2, 3, 4} // H T assert(rb->cb.buf[0] == 5); assert(rb->cb.buf[1] == 2); assert(rb->cb.buf[2] == 3); assert(rb->cb.buf[3] == 4); assert(rb->cb.head == 1); assert(rb->cb.tail == 2); ringbuf_del(rb); } void ringbuf_read_test(void) { size_t count = 4; ringbuf_t *rb = ringbuf_new(count); ITEM item_array[3]; ITEM expects[] = {1, 2, 3}; ITEM expects2[] = {4}; assert(ringbuf_append_with_overwrite(rb, 1) == 0); assert(ringbuf_append_with_overwrite(rb, 2) == 0); assert(ringbuf_append_with_overwrite(rb, 3) == 0); assert(ringbuf_read(rb, item_array, count) == 3); assert(memcmp(item_array, expects, 3) == 0); // check state of ringbuffer: // {X, X, X, X} // H // T assert(rb->cb.head == 3); assert(rb->cb.tail == 3); assert(ringbuf_append_with_overwrite(rb, 4) == 0); assert(ringbuf_read(rb, item_array, count) == 1); assert(memcmp(item_array, expects2, 1) == 0); assert(rb->cb.head == 0); assert(rb->cb.tail == 0); ringbuf_del(rb); } void ringbuf_read_to_end_test(void) { size_t count = 4; ringbuf_t *rb = ringbuf_new(count); ITEM item_array[3]; ITEM expects[] = {1, 2, 3}; ITEM expects2[] = {4}; assert(ringbuf_append_with_overwrite(rb, 1) == 0); assert(ringbuf_append_with_overwrite(rb, 2) == 0); assert(ringbuf_append_with_overwrite(rb, 3) == 0); // state of ringbuffer: // {1, 2, 3, X} // T H assert(ringbuf_read_to_end(rb, item_array, 3) == 3); assert(memcmp(item_array, expects, 3) == 0); // check state of ringbuffer: // {1, 2, 3, X} // H // T assert(rb->cb.head == 3); assert(rb->cb.tail == 3); assert(ringbuf_append_with_overwrite(rb, 4) == 0); // state of ringbuffer: // {1, 2, 3, 4} // H T assert(ringbuf_read_to_end(rb, item_array, count) == 1); // check state of ringbuffer (empty): // {1, 2, 3, 4} // H // T assert(memcmp(item_array, expects2, 1) == 0); assert(rb->cb.head == 0); assert(rb->cb.tail == 0); ringbuf_del(rb); } /* ---- END RINGBUFFER TESTS ---- */ rsyslog-8.2608.0/runtime/PaxHeaders/operatingstate.h0000644000000000000000000000013215132411300017412 xustar0030 mtime=1768559296.272885735 30 atime=1787067618.034437714 30 ctime=1787067794.341724067 rsyslog-8.2608.0/runtime/operatingstate.h0000666000175000017500000000212015132411300017053 0ustar00rgerrger/* OperatingStateFile interface. * * Copyright 2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_OPERATINGSTATEFILE_H #define INCLUDED_OPERATINGSTATEFILE_H /* supported TAGS */ #define OSF_TAG_STATE "STATE" #define OSF_TAG_MSG "MSG" void osf_open(void); void ATTR_NONNULL() osf_write(const char *const tag, const char *const line); void osf_close(void); #endif /* #ifndef INCLUDED_OPERATINGSTATEFILE_H */ rsyslog-8.2608.0/runtime/PaxHeaders/obj-types.h0000644000000000000000000000013215145046113016307 xustar0030 mtime=1771326539.004013717 30 atime=1787067616.803414761 30 ctime=1787067794.265722651 rsyslog-8.2608.0/runtime/obj-types.h0000664000175000017500000005270415145046113015763 0ustar00rgerrger/* Some type definitions and macros for the obj object. * I needed to move them out of the main obj.h, because obj.h's * prototypes use other data types. However, their .h's rely * on some of the obj.h data types and macros. So I needed to break * that loop somehow and I've done that by moving the typedefs * into this file here. * * Copyright 2008-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OBJ_TYPES_H_INCLUDED #define OBJ_TYPES_H_INCLUDED #include "stringbuf.h" #include "syslogd-types.h" #include "atomic.h" /* property types for obj[De]Serialize() */ typedef enum { PROPTYPE_NONE = 0, /* currently no value set */ PROPTYPE_PSZ = 1, PROPTYPE_SHORT = 2, PROPTYPE_INT = 3, PROPTYPE_LONG = 4, PROPTYPE_INT64 = 5, PROPTYPE_CSTR = 6, PROPTYPE_SYSLOGTIME = 7 } propType_t; typedef unsigned objID_t; typedef enum { /* IDs of base methods supported by all objects - used for jump table, so * they must start at zero and be incremented. -- rgerhards, 2008-01-04 */ objMethod_CONSTRUCT = 0, objMethod_DESTRUCT = 1, objMethod_SERIALIZE = 2, objMethod_DESERIALIZE = 3, objMethod_SETPROPERTY = 4, objMethod_CONSTRUCTION_FINALIZER = 5, objMethod_GETSEVERITY = 6, objMethod_DEBUGPRINT = 7 } objMethod_t; #define OBJ_NUM_METHODS 8 /* must be updated to contain the max number of methods supported */ /* the base data type for interfaces * This MUST be in sync with the ifBEGIN macro */ struct interface_s { int ifVersion; /* must be set to version requested */ int ifIsLoaded; /* is the interface loaded? (0-no, 1-yes, 2-load failed; if not 1, functions can NOT be called! */ }; struct objInfo_s { uchar *pszID; /* the object ID as a string */ size_t lenID; /* length of the ID string */ int iObjVers; uchar *pszName; rsRetVal (*objMethods[OBJ_NUM_METHODS])(void *, ...); rsRetVal (*QueryIF)(interface_t *); struct modInfo_s *pModInfo; }; struct obj_s { /* the dummy struct that each derived class can be casted to */ objInfo_t *pObjInfo; #ifndef NDEBUG /* this means if debug... */ unsigned int iObjCooCKiE; /* must always be 0xBADEFEE for a valid object */ #endif uchar *pszName; /* the name of *this* specific object instance */ }; /* macros which must be gloablly-visible (because they are used during definition of * other objects. */ #ifndef NDEBUG /* this means if debug... */ #include #define BEGINobjInstance obj_t objData #define ISOBJ_assert(pObj) \ do { \ assert((pObj) != NULL); \ assert((unsigned)((obj_t *)(pObj))->iObjCooCKiE == (unsigned)0xBADEFEE); \ } while (0); #define ISOBJ_TYPE_assert(pObj, objType) \ do { \ assert(pObj != NULL); \ if (strcmp((char *)(((obj_t *)pObj)->pObjInfo->pszID), #objType)) { \ dbgprintf( \ "%s:%d ISOBJ assert failure: invalid object type, expected '%s' " \ "actual '%s', cookie: %X\n", \ __FILE__, __LINE__, #objType, (((obj_t *)pObj)->pObjInfo->pszID), ((obj_t *)(pObj))->iObjCooCKiE); \ fprintf(stderr, \ "%s:%d ISOBJ assert failure: invalid object type, expected '%s' " \ "actual '%s', cookie: %X\n", \ __FILE__, __LINE__, #objType, (((obj_t *)pObj)->pObjInfo->pszID), \ ((obj_t *)(pObj))->iObjCooCKiE); \ fflush(stderr); \ assert(!strcmp((char *)(((obj_t *)pObj)->pObjInfo->pszID), #objType)); \ } \ assert((unsigned)((obj_t *)(pObj))->iObjCooCKiE == (unsigned)0xBADEFEE); \ } while (0) /* now the same for pointers to "regular" objects (like wrkrInstanceData) */ #define PTR_ASSERT_DEF unsigned int _Assert_type; #define PTR_ASSERT_SET_TYPE(_ptr, _type) _ptr->_Assert_type = _type #define PTR_ASSERT_CHK(_ptr, _type) \ do { \ assert(_ptr != NULL); \ if (_ptr->_Assert_type != _type) { \ dbgprintf( \ "%s:%d PTR_ASSERT_CHECK failure: invalid pointer type %x, " \ "expected %x\n", \ __FILE__, __LINE__, _ptr->_Assert_type, _type); \ fprintf(stderr, \ "%s:%d PTR_ASSERT_CHECK failure: invalid pointer type %x, " \ "expected %x\n", \ __FILE__, __LINE__, _ptr->_Assert_type, _type); \ assert(_ptr->_Assert_type == _type); \ } \ } while (0) #else /* non-debug mode, no checks but much faster */ #define BEGINobjInstance obj_t objData #define ISOBJ_TYPE_assert(pObj, objType) #define ISOBJ_assert(pObj) #define PTR_ASSERT_DEF #define PTR_ASSERT_SET_TYPE(_ptr, _type) #define PTR_ASSERT_CHK(_ptr, _type) #endif /* a set method for *very simple* object accesses. Note that this does * NOT conform to the standard calling conventions and should be * used only if actually nothing can go wrong! -- rgerhards, 2008-04-17 */ #define DEFpropGetMeth(obj, prop, dataType) \ dataType obj##Get##prop(void) { \ return pThis->prop = pVal; \ } #define DEFpropSetMethPTR(obj, prop, dataType) \ rsRetVal obj##Set##prop(obj##_t *pThis, dataType *pVal) { \ pThis->prop = pVal; \ return RS_RET_OK; \ } #define PROTOTYPEpropSetMethPTR(obj, prop, dataType) rsRetVal obj##Set##prop(obj##_t *pThis, dataType *) #define DEFpropSetMethFP(obj, prop, dataType) \ rsRetVal obj##Set##prop(obj##_t *pThis, dataType) { \ pThis->prop = pVal; \ return RS_RET_OK; \ } #define PROTOTYPEpropSetMethFP(obj, prop, dataType) rsRetVal obj##Set##prop(obj##_t *pThis, dataType) #define DEFpropSetMeth(obj, prop, dataType) \ rsRetVal obj##Set##prop(obj##_t *pThis, dataType pVal) { \ pThis->prop = pVal; \ return RS_RET_OK; \ } #define PROTOTYPEpropSetMeth(obj, prop, dataType) rsRetVal obj##Set##prop(obj##_t *pThis, dataType pVal) #define INTERFACEpropSetMeth(obj, prop, dataType) rsRetVal (*Set##prop)(obj##_t * pThis, dataType) /* class initializer */ #define PROTOTYPEObjClassInit(objName) rsRetVal objName##ClassInit(struct modInfo_s *) /* below: objName must be the object name (e.g. vm, strm, ...) and ISCORE must be * 1 if the module is a statically linked core module and 0 if it is a * dynamically loaded one. -- rgerhards, 2008-02-29 */ #define OBJ_IS_CORE_MODULE 1 /* This should better be renamed to something like "OBJ_IS_NOT_LIBHEAD" or so... ;) */ #define OBJ_IS_LOADABLE_MODULE 0 #define BEGINObjClassInit(objName, objVers, objType) \ rsRetVal objName##ClassInit(struct modInfo_s *pModInfo) { \ DEFiRet; \ if (objType == OBJ_IS_CORE_MODULE) { /* are we a core module? */ \ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ \ } \ CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, (uchar *)#objName, objVers, (rsRetVal(*)(void *))objName##Construct, \ (rsRetVal(*)(void *))objName##Destruct, \ (rsRetVal(*)(interface_t *))objName##QueryInterface, pModInfo)); #define ENDObjClassInit(objName) \ iRet = obj.RegisterObj((uchar *)#objName, pObjInfoOBJ); \ finalize_it: \ RETiRet; \ } /* ... and now the same for abstract classes. * TODO: consolidate the two -- rgerhards, 2008-02-29 */ #define BEGINAbstractObjClassInit(objName, objVers, objType) \ rsRetVal objName##ClassInit(struct modInfo_s *pModInfo) { \ DEFiRet; \ if (objType == OBJ_IS_CORE_MODULE) { /* are we a core module? */ \ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ \ } \ CHKiRet(obj.InfoConstruct(&pObjInfoOBJ, (uchar *)#objName, objVers, NULL, NULL, \ (rsRetVal(*)(interface_t *))objName##QueryInterface, pModInfo)); #define ENDObjClassInit(objName) \ iRet = obj.RegisterObj((uchar *)#objName, pObjInfoOBJ); \ finalize_it: \ RETiRet; \ } /* now come the class exit. This is to be called immediately before the class is * unloaded (actual unload for plugins, program termination for core modules) * gerhards, 2008-03-10 */ #define PROTOTYPEObjClassExit(objName) rsRetVal objName##ClassExit(void) #define BEGINObjClassExit(objName, objType) \ rsRetVal objName##ClassExit(void) { \ DEFiRet; #define CODESTARTObjClassExit(objName) #define ENDObjClassExit(objName) \ iRet = obj.UnregisterObj((uchar *)#objName); \ RETiRet; \ } /* this defines both the constructor and initializer * rgerhards, 2008-01-10 */ #define PROTOTYPEobjConstruct(obj) rsRetVal obj##Construct(obj##_t **ppThis) #define BEGINobjConstruct(obj) \ static rsRetVal obj##Initialize(obj##_t __attribute__((unused)) * pThis) { \ DEFiRet; #define ENDobjConstruct(obj) \ /* use finalize_it: before calling the macro (if you need it)! */ \ RETiRet; \ } \ rsRetVal obj##Construct(obj##_t **ppThis) { \ DEFiRet; \ obj##_t *pThis; \ \ assert(ppThis != NULL); \ \ if ((pThis = (obj##_t *)calloc(1, sizeof(obj##_t))) == NULL) { \ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); \ } \ objConstructSetObjInfo(pThis); \ \ obj##Initialize(pThis); \ \ finalize_it: \ OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \ RETiRet; \ } /* this defines the destructor. The important point is that the base object * destructor is called. The upper-level class shall destruct all of its * properties, but not the instance itself. This is freed here by the * framework (we need an intact pointer because we need to free the * obj_t structures inside it). A pointer to the object pointer must be * parse, because it is re-set to NULL (this, for example, is important in * cancellation handlers). The object pointer is always named pThis. * The object is always freed, even if there is some error while * Cancellation is blocked during destructors, as this could have fatal * side-effects. However, this also means the upper-level object should * not perform any lengthy processing. * IMPORTANT: if the upper level object requires some situations where the * object shall not be destructed (e.g. via reference counting), then * it shall set pThis to NULL, which prevents destruction of the * object. * processing. * rgerhards, 2008-01-30 */ #define PROTOTYPEobjDestruct(OBJ) rsRetVal OBJ##Destruct(OBJ##_t __attribute__((unused)) * *ppThis) /* note: we generate a prototype in any case, as this does not hurt but * many modules otherwise seem to miss one, which generates compiler * warnings. */ #define BEGINobjDestruct(OBJ) \ rsRetVal OBJ##Destruct(OBJ##_t __attribute__((unused)) * *ppThis) { \ DEFiRet; \ OBJ##_t *pThis; #define CODESTARTobjDestruct(OBJ) \ assert(ppThis != NULL); \ pThis = *ppThis; \ ISOBJ_TYPE_assert(pThis, OBJ); /* note: there was a long-time bug in the macro below that lead to *ppThis = NULL * only when the object was actually destructed. I discovered this issue during * introduction of the pRcvFrom property in smsg_t, but it potentially had other * effects, too. I am not sure if some experienced instability resulted from this * bug OR if its fix will cause harm to so-far "correctly" running code. The later * may very well be. Thus I will change it only for the current branch and also * the beta, but not in all old builds. Let's see how things evolve. * rgerhards, 2009-06-30 */ #define ENDobjDestruct(OBJ) \ goto finalize_it; /* prevent compiler warning ;) */ \ /* no more code here! */ \ finalize_it: \ if (pThis != NULL) { \ obj.DestructObjSelf((obj_t *)pThis); \ free(pThis); \ } \ *ppThis = NULL; \ RETiRet; \ } /* this defines the debug print entry point. DebugPrint is optional. If * it is provided, the object should output some meaningful information * via the debug system. * rgerhards, 2008-02-20 */ #define PROTOTYPEObjDebugPrint(obj) rsRetVal obj##DebugPrint(obj##_t *pThis) #define INTERFACEObjDebugPrint(obj) rsRetVal (*DebugPrint)(obj##_t * pThis) #define BEGINobjDebugPrint(obj) \ rsRetVal obj##DebugPrint(obj##_t __attribute__((unused)) * pThis) { \ DEFiRet; #define CODESTARTobjDebugPrint(obj) \ assert(pThis != NULL); \ ISOBJ_TYPE_assert(pThis, obj); #define ENDobjDebugPrint(obj) \ RETiRet; \ } /* ------------------------------ object loader system ------------------------------ * * The following code builds a dynamic object loader system. The * root idea is that all objects are dynamically loadable, * which is necessary to get a clean plug-in interface where every plugin can access * rsyslog's rich object model via simple and quite portable methods. * * To do so, each object defines one or more interfaces. They are essentially structures * with function (method) pointers. Anyone interested in calling an object must first * obtain the interface and can then call through it. * * The interface data type must always be called _if_t, as this is expected * by the macros. Having consitent naming is also easier for the programmer. By default, * macros create a static variable named like the object in each calling objects * static data block. * * rgerhards, 2008-02-21 (initial implementation), 2008-04-17 (update of this note) */ /* this defines the QueryInterface print entry point. Over time, it should be * present in all objects. */ #define BEGINobjQueryInterface(obj) \ rsRetVal obj##QueryInterface(obj##_if_t *pIf) { \ DEFiRet; #define CODESTARTobjQueryInterface(obj) assert(pIf != NULL); #define ENDobjQueryInterface(obj) \ RETiRet; \ } #define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pIf) /* the following macros should be used to define interfaces inside the * header files. */ #define BEGINinterface(obj) \ typedef struct obj##_if_s { \ ifBEGIN /* This MUST always be the first interface member */ #define ENDinterface(obj) \ } \ obj##_if_t; /* the following macro is used to get access to an object (not an instance, * just the class itself!). It must be called before any of the object's * methods can be accessed. The MYLIB part is the name of my library, or NULL if * the caller is a core module. Using the right value here is important to get * the reference counting correct (object accesses from the same library must * not be counted because that would cause a library plugin to never unload, as * its ClassExit() entry points are only called if no object is referenced, which * would never happen as the library references itself. * rgerhards, 2008-03-11 */ #define CORE_COMPONENT NULL /* use this to indicate this is a core component */ #define DONT_LOAD_LIB NULL /* do not load a library to obtain object interface (currently same as CORE_COMPONENT) */ #define objUse(objName, FILENAME) obj.UseObj(__FILE__, (uchar *)#objName, (uchar *)FILENAME, (void *)&objName) #define objRelease(objName, FILENAME) obj.ReleaseObj(__FILE__, (uchar *)#objName, (uchar *)FILENAME, (void *)&objName) /* defines data that must always be present at the very begin of the interface structure */ #define ifBEGIN \ int ifVersion; /* must be set to version requested */ \ int ifIsLoaded; /* is the interface loaded? (0-no, 1-yes; if no, functions can NOT be called! */ /* use the following define some place in your static data (suggested right at * the beginning */ #define DEFobjCurrIf(obj) static obj##_if_t obj = {.ifVersion = obj##CURR_IF_VERSION, .ifIsLoaded = 0}; /* define the prototypes for a class - keep signatures behind PROTOTYPE* * macros so interface changes are localized in this file. */ #define PROTOTYPEObjBasic(obj) \ PROTOTYPEObjClassInit(obj); \ PROTOTYPEObjClassExit(obj); \ PROTOTYPEObjQueryInterface(obj) /* use where typed object ctor/dtor declarations are valid in scope */ #define PROTOTYPEObjFull(obj) \ PROTOTYPEObjBasic(obj); \ PROTOTYPEobjConstruct(obj); \ PROTOTYPEobjDestruct(obj) /* legacy alias kept for broad in-tree compatibility */ #define PROTOTYPEObj(obj) PROTOTYPEObjBasic(obj) /* ------------------------------ end object loader system ------------------------------ */ #include "modules.h" #endif /* #ifndef OBJ_TYPES_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/parse.h0000644000000000000000000000013115216464436015517 xustar0030 mtime=1782212894.037266362 29 atime=1787067616.82641519 30 ctime=1787067794.477726601 rsyslog-8.2608.0/runtime/parse.h0000664000175000017500000000723615216464436015174 0ustar00rgerrger/* parsing routines for the counted string class. These * routines provide generic parsing aid as well some fairly * complex routines targeted toward specific needs. * * General information - read this: * All routines work on a single CStr object, which must be supplied * during construction. The parse class keeps an internal pointer of * where the next parse operation is to start (you could also say * this is where the last parse operation stopped). * * Each parse operation carried out by this package starts from the * parse pointer, parses the caller-requested element (e.g. an * integer or delemited string) and the update the parse pointer. If * the caller tries to parse beyond the end of the original string, * an error is returned. In general, all functions return a parsRet * error code and all require the parseObj to be the first parameter. * The to-be-parsed string provided to the parse object MUST NOT be * freed or modified by the caller during the lifetime of the parse * object. However, the caller must free it when it is no longer needed. * Optinally, the parse object can be instructed to do that. All objects * returned by the parse routines must be freed by the caller. For * simpler data types (like integers), the caller must provide the * necessary buffer space. * * begun 2005-09-09 rgerhards * * Copyright (C) 2005-2012 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _PARSE_H_INCLUDED__ #define _PARSE_H_INCLUDED__ 1 #include "stringbuf.h" /** * The parse object */ struct rsParsObject { #ifndef NDEBUG rsObjID OID; /**< object ID */ #endif cstr_t *pCStr; /**< pointer to the string object we are parsing */ size_t iCurrPos; /**< current parsing position (char offset) */ }; typedef struct rsParsObject rsParsObj; /* BEGIN "inline"-like functions */ /* END "inline"-like functions */ int rsParsGetParsePointer(rsParsObj *pThis); /** * Construct a rsPars object. */ rsRetVal rsParsConstruct(rsParsObj **ppThis); rsRetVal rsParsAssignString(rsParsObj *pThis, cstr_t *pCStr); /* parse an integer. The parse pointer is advanced */ rsRetVal parsInt(rsParsObj *pThis, int *pInt); /* Skip whitespace. Often used to trim parsable entries. */ rsRetVal parsSkipWhitespace(rsParsObj *pThis); /* Parse string up to a delimiter. * * Input: * cDelim - the delimiter * The following two are for whitespace stripping, * 0 means "no", 1 "yes" * - bTrimLeading * - bTrimTrailing * * Output: * ppCStr Pointer to the parsed string */ rsRetVal parsDelimCStr( rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower); rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c); rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr); rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz); rsRetVal rsParsDestruct(rsParsObj *pThis); int parsIsAtEndOfParseString(rsParsObj *pThis); int parsGetCurrentPosition(rsParsObj *pThis); char parsPeekAtCharAtParsPtr(rsParsObj *pThis); rsRetVal parsAddrWithBits(rsParsObj *pThis, netAddr_t **pIP, int *pBits); #endif rsyslog-8.2608.0/runtime/PaxHeaders/tcpsrv.h0000644000000000000000000000013215241075234015717 xustar0030 mtime=1787067036.612578425 30 atime=1787067036.759581178 30 ctime=1787067794.606729005 rsyslog-8.2608.0/runtime/tcpsrv.h0000664000175000017500000004331715241075234015373 0ustar00rgerrger/* Definitions for tcpsrv class. * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_TCPSRV_H #define INCLUDED_TCPSRV_H #if defined(ENABLE_IMTCP_EPOLL) && defined(HAVE_SYS_EPOLL_H) #include #endif #include "obj.h" #include "prop.h" #include "net.h" #include "tcps_sess.h" #include "statsobj.h" #include "regexp.h" /* support for framing anomalies */ typedef enum ETCPsyslogFramingAnomaly { frame_normal = 0, frame_NetScreen = 1, frame_CiscoIOS = 2 } eTCPsyslogFramingAnomaly; /** * Config parameters for TCP listeners. * * Ownership: the caller allocates and populates this struct, then hands it to * tcpsrv via `configureTCPListen()`. tcpsrv becomes the owner (including any * dynamically allocated fields) and will free it on error or when the listener * is torn down. */ struct tcpLstnParams_s { const uchar *pszPort; /**< the ports the listener shall listen on */ const uchar *pszAddr; /**< the addrs the listener shall listen on */ sbool bSuppOctetFram; /**< do we support octect-counted framing? (if no->legay only!)*/ sbool bSPFramingFix; /**< support work-around for broken Cisco ASA framing? */ sbool bPreserveCase; /**< preserve case in fromhost */ const uchar *pszLstnPortFileName; /**< File in which the dynamic port is written */ char *pszNetworkNamespace; /**< network namespace to use */ uchar *pszStrmDrvrName; /**< stream driver to use */ uchar *pszInputName; /**< value to be used as input name */ prop_t *pInputName; ruleset_t *pRuleset; /**< associated ruleset */ uchar dfltTZ[8]; /**< default TZ if none in timestamp; '\0' =No Default */ sbool bMultiLine; /**< support multi-line messages */ uchar *pszStartRegex; /**< regex that indicates start of frame */ uchar *pszRatelimitName; /**< name of rate limit configuration */ struct AllowedSenders *pAllowedSenderRoot; /**< source-address ACL list */ sbool bUseLegacyAllowedSender; /**< if true, use protocol-global legacy ACLs */ }; /* list of tcp listen ports */ struct tcpLstnPortList_s { tcpLstnParams_t *cnf_params; /**< listener config parameters */ tcpsrv_t *pSrv; /**< pointer to higher-level server instance */ statsobj_t *stats; /**< associated stats object */ ratelimit_t *ratelimiter; STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit) STATSCOUNTER_DEF(ctrBytesRcvd, mutCtrBytesRcvd) STATSCOUNTER_DEF(ctrBytesDecompressed, mutCtrBytesDecompressed) STATSCOUNTER_DEF(ctrDecompressErr, mutCtrDecompressErr) uint8_t compressionMode; uint8_t compressionDriver; uint64_t compressionMaxExpansionRatio; uint64_t compressionMaxDecompressedBytesPerReceive; uint64_t compressionMaxTotalZstdWindowBytes; /* Concurrency & Locking: sessions have independent decoder state and share * only this listener-wide zstd window counter. Native 64-bit atomics avoid * serialization; the helper mutex exists only on no-64-bit-atomics builds. */ uint64 compressionZstdWindowBytesInUse; DEF_ATOMIC_HELPER_MUT64(mutCompressionZstdWindow); #ifdef FEATURE_REGEXP regex_t start_preg; sbool bHasStartRegex; #endif tcpLstnPortList_t *pNext; /**< next port or NULL */ }; typedef struct tcpsrvWrkrData_s { statsobj_t *stats; STATSCOUNTER_DEF(ctrRuns, mutCtrRuns); STATSCOUNTER_DEF(ctrRead, mutCtrRead); STATSCOUNTER_DEF(ctrEmptyRead, mutCtrEmptyRead); STATSCOUNTER_DEF(ctrStarvation, mutCtrStarvation); STATSCOUNTER_DEF(ctrAccept, mutCtrAccept); } tcpsrvWrkrData_t; typedef struct workQueue_s { tcpsrv_io_descr_t *head; tcpsrv_io_descr_t *tail; pthread_mutex_t mut; pthread_cond_t workRdy; unsigned numWrkr; /* how many workers to spawn */ pthread_t *wrkr_tids; /* array of thread IDs */ tcpsrvWrkrData_t *wrkr_data; } workQueue_t; /** * The following structure is a descriptor for tcpsrv i/o. It is * primarily used together with epoll at the moment. */ struct tcpsrv_io_descr_s { int id; /* index into listener or session table, depending on ptrType */ int sock; /* socket descriptor we need to "monitor" */ unsigned ioDirection; enum { NSD_PTR_TYPE_LSTN, NSD_PTR_TYPE_SESS } ptrType; union { tcps_sess_t *pSess; netstrm_t **ppLstn; /**< accept listener's netstream */ } ptr; int isInError; /* boolean, if set, subsystem indicates we need to close because we had an * unrecoverable error at the network layer. */ tcpsrv_t *pSrv; /* our server object */ tcpsrv_io_descr_t *next; /* for use in workQueue_t */ #if defined(ENABLE_IMTCP_EPOLL) struct epoll_event event; /* to re-enable EPOLLONESHOT */ #endif DEF_ATOMIC_HELPER_MUT(mut_isInError); }; #define TCPSRV_NO_ADDTL_DELIMITER -1 /* specifies that no additional delimiter is to be used in TCP framing */ /* the tcpsrv object */ struct tcpsrv_s { BEGINobjInstance ; /**< Data to implement generic object - MUST be the first data element! */ int bUseKeepAlive; /**< use socket layer KEEPALIVE handling? */ int iKeepAliveIntvl; /**< socket layer KEEPALIVE interval */ int iKeepAliveProbes; /**< socket layer KEEPALIVE probes */ int iKeepAliveTime; /**< socket layer KEEPALIVE timeout */ netstrms_t *pNS; /**< pointer to network stream subsystem */ int iDrvrMode; /**< mode of the stream driver to use */ int DrvrChkExtendedKeyUsage; /**< if true, verify extended key usage in certs */ int DrvrPrioritizeSan; /**< if true, perform stricter checking of names in certs */ int DrvrTlsVerifyDepth; /**< Verify Depth for certificate chains */ int DrvrTlsRevocationCheck; /**< Enable TLS revocation checking (OCSP/CRL) */ uchar *gnutlsPriorityString; /**< priority string for gnutls */ uchar *pszLstnPortFileName; /**< File in which the dynamic port is written */ uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */ uchar *pszDrvrPermitExpiredCerts; /**< current driver setting for handlign expired certs */ uchar *pszDrvrCAFile; uchar *pszDrvrCRLFile; uchar *pszDrvrKeyFile; uchar *pszDrvrCertFile; uchar *pszDrvrName; /**< name of stream driver to use */ uchar *pszInputName; /**< value to be used as input name */ uchar *pszOrigin; /**< module to be used as "origin" (e.g. for pstats) */ ruleset_t *pRuleset; /**< ruleset to bind to */ permittedPeers_t *pPermPeers; /**< driver's permitted peers */ sbool bEmitMsgOnClose; /**< emit an informational message when the remote peer closes connection */ sbool bEmitMsgOnOpen; sbool bUseFlowControl; /**< use flow control (make light delayable) */ sbool bSPFramingFix; /**< support work-around for broken Cisco ASA framing? */ int iLstnCurr; /**< max nbr of listeners currently supported */ netstrm_t **ppLstn; /**< our netstream listeners */ /* We could use conditional compilation, but that causes more complexity and is (proofen causing errors) */ union { struct { int efd; } epoll; struct { uint32_t maxfds; uint32_t currfds; struct pollfd *fds; } poll; } evtdata; tcpLstnPortList_t **ppLstnPort; /**< pointer to relevant listen port description */ tcpsrv_io_descr_t **ppioDescrPtr; /**< pointer to i/o descriptor object */ int iLstnMax; /**< max number of listeners supported */ int iSessMax; /**< max number of sessions supported */ uchar dfltTZ[8]; /**< default TZ if none in timestamp; '\0' =No Default */ tcpLstnPortList_t *pLstnPorts; /**< head pointer for listen ports */ int addtlFrameDelim; /**< additional frame delimiter for plain TCP syslog framing (e.g. to handle NetScreen) */ int maxFrameSize; /**< max frame size for octet counted*/ uint8_t compressionMode; uint8_t compressionDriver; uint64_t compressionMaxExpansionRatio; uint64_t compressionMaxDecompressedBytesPerReceive; uint64_t compressionMaxTotalZstdWindowBytes; int bDisableLFDelim; /**< if 1, standard LF frame delimiter is disabled (*very dangerous*) */ int discardTruncatedMsg; /**< discard msg part that has been truncated*/ sbool bPreserveCase; /**< preserve case in fromhost */ int iSynBacklog; unsigned int ratelimitInterval; unsigned int ratelimitBurst; tcps_sess_t **pSessions; /**< session slots shared by accept and worker threads */ DEF_ATOMIC_HELPER_MUT(mut_sessions); unsigned int starvationMaxReads; void *pUsr; /**< a user-settable pointer (provides extensibility for "derived classes")*/ /* callbacks */ int (*pIsPermittedHost)(struct sockaddr *addr, char *fromHostFQDN, void *pUsrSrv, void *pUsrSess); rsRetVal (*pRcvData)(tcps_sess_t *, char *, size_t, ssize_t *, int *, unsigned *); rsRetVal (*OpenLstnSocks)(struct tcpsrv_s *); rsRetVal (*pOnListenDeinit)(void *); rsRetVal (*OnDestruct)(void *); rsRetVal (*pOnRegularClose)(tcps_sess_t *pSess); rsRetVal (*pOnErrClose)(tcps_sess_t *pSess); /* session specific callbacks */ rsRetVal (*pOnSessAccept)(tcpsrv_t *, tcps_sess_t *, char *connInfo); #define TCPSRV_CONNINFO_SIZE (2 * (INET_ADDRSTRLEN + 20)) rsRetVal (*OnSessConstructFinalize)(void *); rsRetVal (*pOnSessDestruct)(void *); rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *pszMsg, int iLenMsg); /* submit message callback */ /* work queue */ workQueue_t workQueue; int currWrkrs; }; /** */ struct tcpsrv_workset_s { int idx; /**< index into session table (or -1 if listener) */ void *pUsr; }; /* interfaces */ BEGINinterface(tcpsrv) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(tcpsrv); rsRetVal (*Construct)(tcpsrv_t **ppThis); rsRetVal (*ConstructFinalize)(tcpsrv_t __attribute__((unused)) * pThis); rsRetVal (*Destruct)(tcpsrv_t **ppThis); /** * Configure a TCP listener using the provided configuration parameters. * * Ownership of `cnf_params` is always transferred to tcpsrv. On success, * tcpsrv retains the configuration for the listener. On failure (including * invalid port), tcpsrv frees `cnf_params` and its owned fields. */ rsRetVal (*ATTR_NONNULL(1, 2) configureTCPListen)(tcpsrv_t *, tcpLstnParams_t *const cnf_params); rsRetVal (*create_tcp_socket)(tcpsrv_t *pThis); rsRetVal (*Run)(tcpsrv_t *pThis); /* set methods */ rsRetVal (*SetAddtlFrameDelim)(tcpsrv_t *, int); rsRetVal (*SetMaxFrameSize)(tcpsrv_t *, int); rsRetVal (*SetCompressionMode)(tcpsrv_t *, int); rsRetVal (*SetCompressionDriver)(tcpsrv_t *, int); rsRetVal (*SetCompressionMaxExpansionRatio)(tcpsrv_t *, uint64_t); rsRetVal (*SetCompressionMaxDecompressedBytesPerReceive)(tcpsrv_t *, uint64_t); /* added v32 */ rsRetVal (*SetCompressionMaxTotalZstdWindowBytes)(tcpsrv_t *, uint64_t); /** * Set the input name for a listener configuration. * * Ownership: the name is duplicated into `cnf_params` and managed by * tcpsrv along with the rest of `cnf_params` after ownership transfer. */ rsRetVal (*SetInputName)(tcpsrv_t *const pThis, tcpLstnParams_t *const cnf_params, const uchar *const name); rsRetVal (*SetUsrP)(tcpsrv_t *, void *); rsRetVal (*SetCBIsPermittedHost)(tcpsrv_t *, int (*)(struct sockaddr *addr, char *, void *, void *)); rsRetVal (*SetCBOpenLstnSocks)(tcpsrv_t *, rsRetVal (*)(tcpsrv_t *)); rsRetVal (*SetCBRcvData)(tcpsrv_t *pThis, rsRetVal (*pRcvData)(tcps_sess_t *, char *, size_t, ssize_t *, int *, unsigned *)); rsRetVal (*SetCBOnListenDeinit)(tcpsrv_t *, rsRetVal (*)(void *)); rsRetVal (*SetCBOnDestruct)(tcpsrv_t *, rsRetVal (*)(void *)); rsRetVal (*SetCBOnRegularClose)(tcpsrv_t *, rsRetVal (*)(tcps_sess_t *)); rsRetVal (*SetCBOnErrClose)(tcpsrv_t *, rsRetVal (*)(tcps_sess_t *)); rsRetVal (*SetDrvrMode)(tcpsrv_t *pThis, int iMode); rsRetVal (*SetDrvrAuthMode)(tcpsrv_t *pThis, uchar *pszMode); rsRetVal (*SetDrvrPermitExpiredCerts)(tcpsrv_t *pThis, uchar *pszMode); rsRetVal (*SetDrvrPermPeers)(tcpsrv_t *pThis, permittedPeers_t *); /* session specifics */ rsRetVal (*SetCBOnSessAccept)(tcpsrv_t *, rsRetVal (*)(tcpsrv_t *, tcps_sess_t *, char *)); rsRetVal (*SetCBOnSessDestruct)(tcpsrv_t *, rsRetVal (*)(void *)); rsRetVal (*SetCBOnSessConstructFinalize)(tcpsrv_t *, rsRetVal (*)(void *)); /* added v5 */ rsRetVal (*SetSessMax)(tcpsrv_t *pThis, int iMaxSess); /* 2009-04-09 */ /* added v6 */ rsRetVal (*SetOnMsgReceive)(tcpsrv_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *, int)); /* 2009-05-24 */ rsRetVal (*SetRuleset)(tcpsrv_t *pThis, ruleset_t *); /* 2009-06-12 */ /* added v7 (accidentally named v8!) */ rsRetVal (*SetLstnMax)(tcpsrv_t *pThis, int iMaxLstn); /* 2009-08-17 */ rsRetVal (*SetNotificationOnRemoteClose)(tcpsrv_t *pThis, int bNewVal); /* 2009-10-01 */ rsRetVal (*SetNotificationOnRemoteOpen)(tcpsrv_t *pThis, int bNewVal); /* 2022-08-23 */ /* added v9 -- rgerhards, 2010-03-01 */ rsRetVal (*SetbDisableLFDelim)(tcpsrv_t *, int); /* added v10 -- rgerhards, 2011-04-01 */ rsRetVal (*SetDiscardTruncatedMsg)(tcpsrv_t *, int); rsRetVal (*SetUseFlowControl)(tcpsrv_t *, int); /* added v11 -- rgerhards, 2011-05-09 */ rsRetVal (*SetKeepAlive)(tcpsrv_t *, int); /* added v13 -- rgerhards, 2012-10-15 */ rsRetVal (*SetLinuxLikeRatelimiters)(tcpsrv_t *pThis, unsigned int interval, unsigned int burst); /* added v14 -- rgerhards, 2013-07-28 */ rsRetVal (*SetDfltTZ)(tcpsrv_t *pThis, uchar *dfltTZ); /* added v15 -- rgerhards, 2013-09-17 */ rsRetVal (*SetDrvrName)(tcpsrv_t *pThis, uchar *pszName); /* added v16 -- rgerhards, 2014-09-08 */ rsRetVal (*SetOrigin)(tcpsrv_t *, uchar *); /* added v17 */ rsRetVal (*SetKeepAliveIntvl)(tcpsrv_t *, int); rsRetVal (*SetKeepAliveProbes)(tcpsrv_t *, int); rsRetVal (*SetKeepAliveTime)(tcpsrv_t *, int); /* added v18 */ rsRetVal (*SetbSPFramingFix)(tcpsrv_t *, sbool); /* added v19 -- PascalWithopf, 2017-08-08 */ rsRetVal (*SetGnutlsPriorityString)(tcpsrv_t *, uchar *); /* added v21 -- Preserve case in fromhost, 2018-08-16 */ rsRetVal (*SetPreserveCase)(tcpsrv_t *pThis, int bPreserveCase); /* added v23 -- Options for stricter driver behavior, 2019-08-16 */ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(tcpsrv_t *pThis, int ChkExtendedKeyUsage); rsRetVal (*SetDrvrPrioritizeSAN)(tcpsrv_t *pThis, int prioritizeSan); /* added v24 -- Options for TLS verify depth driver behavior, 2019-12-20 */ rsRetVal (*SetDrvrTlsVerifyDepth)(tcpsrv_t *pThis, int verifyDepth); rsRetVal (*SetDrvrTlsRevocationCheck)(tcpsrv_t *pThis, int enabled); /* added v25 -- Options for TLS certificates, 2021-07-19 */ rsRetVal (*SetDrvrCAFile)(tcpsrv_t *pThis, uchar *pszMode); rsRetVal (*SetDrvrKeyFile)(tcpsrv_t *pThis, uchar *pszMode); rsRetVal (*SetDrvrCertFile)(tcpsrv_t *pThis, uchar *pszMode); /* added v26 -- Options for TLS CRL file */ rsRetVal (*SetDrvrCRLFile)(tcpsrv_t *pThis, uchar *pszMode); /* added v27 -- sync backlog for listen() */ rsRetVal (*SetSynBacklog)(tcpsrv_t *pThis, int); /* added v28 */ rsRetVal (*SetNumWrkr)(tcpsrv_t *pThis, int); rsRetVal (*SetStarvationMaxReads)(tcpsrv_t *pThis, unsigned int); /* added v29 */ /* * @brief Set the Network Namespace into the listener parameters * @param pThis The associated TCP Server instance * @param cnf_params The listener parameters to configure * @param networkNamespace The namespace parameter to set into the * listener configuration parameters * @return RS_RET_OK on success, otherwise a failure code. * @details For platforms that do not support network namespaces, * this function should fail for any non-null and non-empty * namespace passed. Note that the empty string is treated * the same as a NULL, i.e. you are not allowed to actually * use a network namespace with the empty string. So both * a NULL and an empty string "" both mean to use the * original startup network namespace. */ rsRetVal (*SetNetworkNamespace)(tcpsrv_t *pThis, tcpLstnParams_t *const cnf_params, const char *const networkNamespace); ENDinterface(tcpsrv) #define tcpsrvCURR_IF_VERSION 32 /* increment whenever you change the interface structure! */ /* change for v4: * - SetAddtlFrameDelim() added -- rgerhards, 2008-12-10 * - SetInputName() added -- rgerhards, 2008-12-10 * change for v5 and up: see above * for v12: param bSuppOctetFram added to configureTCPListen * for v20: add oserr to setCBRcvData signature -- rgerhards, 2017-09-04 */ /* prototypes */ PROTOTYPEObjFull(tcpsrv); PROTOTYPEObjDebugPrint(tcpsrv); /* the name of our library binary */ #define LM_TCPSRV_FILENAME "lmtcpsrv" #endif /* #ifndef INCLUDED_TCPSRV_H */ rsyslog-8.2608.0/runtime/PaxHeaders/stream.c0000644000000000000000000000013115241075234015663 xustar0030 mtime=1787067036.610578388 29 atime=1787067036.75758114 30 ctime=1787067794.377724738 rsyslog-8.2608.0/runtime/stream.c0000664000175000017500000026336115241075234015343 0ustar00rgerrger/* The serial stream class. * * A serial stream provides serial data access. In theory, serial streams * can be implemented via a number of methods (e.g. files or in-memory * streams). In practice, there currently only exist the file type (aka * "driver"). * * File begun on 2008-01-09 by RGerhards * Large modifications in 2009-06 to support using it with omfile, including zip writer. * Note that this file obtains the zlib wrapper object is needed, but it never frees it * again. While this sounds like a leak (and one may argue it actually is), there is no * harm associated with that. The reason is that strm is a core object, so it is terminated * only when rsyslogd exists. As we could only release on termination (or else bear more * overhead for keeping track of how many users we have), not releasing zlibw is OK, because * it will be released when rsyslogd terminates. We may want to revisit this decision if * it turns out to be problematic. Then, we need to quasi-refcount the number of accesses * to the object. * * Copyright 2008-2022 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include /* required for HP UX */ #include #include #include #ifdef HAVE_SYS_PRCTL_H #include #endif #include "rsyslog.h" #include "stringbuf.h" #include "srUtils.h" #include "obj.h" #include "stream.h" #include "unicode-helper.h" #include "module-template.h" #include "errmsg.h" #include "zstdw.h" #include "cryprov.h" #include "datetime.h" #include "rsconf.h" /* some platforms do not have large file support :( */ #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif #ifndef HAVE_LSEEK64 #define lseek64(fd, offset, whence) lseek(fd, offset, whence) #endif /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(zlibw) DEFobjCurrIf(zstdw) /* forward definitions */ static rsRetVal strmFlushInternal(strm_t *pThis, int bFlushZip); static rsRetVal strmWrite(strm_t *__restrict__ const pThis, const uchar *__restrict__ const pBuf, const size_t lenBuf); static rsRetVal strmOpenFile(strm_t *pThis); static rsRetVal strmCloseFile(strm_t *pThis); static void *asyncWriterThread(void *pPtr); static rsRetVal doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, int bFlush); static rsRetVal doZipFinish(strm_t *pThis); static rsRetVal strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf); static rsRetVal strmSeekCurrOffs(strm_t *pThis); /* methods */ /* note: this may return NULL if not line segment is currently set */ // TODO: due to the cstrFinalize() this is not totally clean, albeit for our // current use case it does not hurt -- refactor! rgerhards, 2018-03-27 const uchar *ATTR_NONNULL() strmGetPrevLineSegment(strm_t *const pThis) { const uchar *ret = NULL; if (pThis->prevLineSegment != NULL) { cstrFinalize(pThis->prevLineSegment); ret = rsCStrGetSzStrNoNULL(pThis->prevLineSegment); } return ret; } /* note: this may return NULL if not line segment is currently set */ // TODO: due to the cstrFinalize() this is not totally clean, albeit for our // current use case it does not hurt -- refactor! rgerhards, 2018-03-27 const uchar *ATTR_NONNULL() strmGetPrevMsgSegment(strm_t *const pThis) { const uchar *ret = NULL; if (pThis->prevMsgSegment != NULL) { cstrFinalize(pThis->prevMsgSegment); ret = rsCStrGetSzStrNoNULL(pThis->prevMsgSegment); } return ret; } int ATTR_NONNULL() strmGetPrevWasNL(const strm_t *const pThis) { return pThis->bPrevWasNL; } /* output (current) file name for debug log purposes. Falls back to various * levels of impreciseness if more precise name is not known. */ static const char *getFileDebugName(const strm_t *const pThis) { return (pThis->pszCurrFName == NULL) ? ((pThis->pszFName == NULL) ? "N/A" : (char *)pThis->pszFName) : (const char *)pThis->pszCurrFName; } /* Try to resolve a size limit situation. This is used to support custom-file size handlers * for omfile. It first runs the command, and then checks if we are still above the size * treshold. Note that this works only with single file names, NOT with circular names. * Note that pszCurrFName can NOT be taken from pThis, because the stream is closed when * we are called (and that destroys pszCurrFName, as there is NO CURRENT file name!). So * we need to receive the name as a parameter. * initially wirtten 2005-06-21, moved to this class & updates 2009-06-01, both rgerhards */ static rsRetVal resolveFileSizeLimit(strm_t *pThis, uchar *pszCurrFName) { uchar *pParams; uchar *pCmd; uchar *p; off_t actualFileSize; rsRetVal localRet; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); assert(pszCurrFName != NULL); if (pThis->pszSizeLimitCmd == NULL) { ABORT_FINALIZE(RS_RET_NON_SIZELIMITCMD); /* nothing we can do in this case... */ } /* we first check if we have command line parameters. We assume this, * when we have a space in the program name. If we find it, everything after * the space is treated as a single argument. */ CHKmalloc(pCmd = ustrdup(pThis->pszSizeLimitCmd)); for (p = pCmd; *p && *p != ' '; ++p) { /* JUST SKIP */ } if (*p == ' ') { *p = '\0'; /* pretend string-end */ pParams = p + 1; } else pParams = NULL; /* the execProg() below is probably not great, but at least is is * fairly secure now. Once we change the way file size limits are * handled, we should also revisit how this command is run (and * with which parameters). rgerhards, 2007-07-20 */ execProg(pCmd, 1, pParams, pThis->bSizeLimitCmdPassFileName ? pszCurrFName : NULL); free(pCmd); localRet = getFileSize(pszCurrFName, &actualFileSize); if (localRet == RS_RET_OK && actualFileSize >= pThis->iSizeLimit) { ABORT_FINALIZE(RS_RET_SIZELIMITCMD_DIDNT_RESOLVE); /* OK, it didn't work out... */ } else if (localRet != RS_RET_FILE_NOT_FOUND) { /* file not found is OK, the command may have moved away the file */ ABORT_FINALIZE(localRet); } finalize_it: if (iRet != RS_RET_OK) { if (iRet == RS_RET_SIZELIMITCMD_DIDNT_RESOLVE) { LogError(0, RS_RET_ERR, "file size limit cmd for file '%s' " "did no resolve situation\n", pszCurrFName); } else { LogError(0, RS_RET_ERR, "file size limit cmd for file '%s' " "failed with code %d.\n", pszCurrFName, iRet); } pThis->bDisabled = 1; } RETiRet; } /* Check if the file has grown beyond the configured omfile iSizeLimit * and, if so, initiate processing. */ static rsRetVal doSizeLimitProcessing(strm_t *pThis) { uchar *pszCurrFName = NULL; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); assert(pThis->iSizeLimit != 0); assert(pThis->fd != -1); if (pThis->iCurrOffs >= pThis->iSizeLimit) { /* strmCloseFile() destroys the current file name, so we * need to preserve it. */ CHKmalloc(pszCurrFName = ustrdup(pThis->pszCurrFName)); CHKiRet(strmCloseFile(pThis)); CHKiRet(resolveFileSizeLimit(pThis, pszCurrFName)); } finalize_it: free(pszCurrFName); RETiRet; } /* now, we define type-specific handlers. The provide a generic functionality, * but for this specific type of strm. The mapping to these handlers happens during * strm construction. Later on, handlers are called by pointers present in the * strm instance object. */ /** * @brief Open the underlying file descriptor and initialize stream state. * * This performs the actual open(2), detects TTYs, and initializes the crypto * provider if configured. In async mode, a mutex protects the open/init sequence * from concurrent close/reopen operations. */ static rsRetVal doPhysOpen(strm_t *pThis) { int iFlags = 0; struct stat statOpen; const sbool bDoLock = (pThis->bAsyncWrite != 0); sbool bNeedOpenErrLog = 0; int openErrno = 0; rsRetVal openErrcode = RS_RET_OK; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); /* compute which flags we need to provide to open */ switch (pThis->tOperationsMode) { case STREAMMODE_READ: iFlags = O_CLOEXEC | O_NOCTTY | O_RDONLY; break; case STREAMMODE_WRITE: /* legacy mode used inside queue engine */ iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT; break; case STREAMMODE_WRITE_TRUNC: iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_TRUNC; break; case STREAMMODE_WRITE_APPEND: iFlags = O_CLOEXEC | O_NOCTTY | O_WRONLY | O_CREAT | O_APPEND; break; case STREAMMMODE_INVALID: default: assert(0); break; } if (pThis->sType == STREAMTYPE_NAMED_PIPE) { DBGPRINTF("Note: stream '%s' is a named pipe, open with O_NONBLOCK\n", pThis->pszCurrFName); iFlags |= O_NONBLOCK; } #ifdef O_NOFOLLOW if (pThis->bNoFollowFinal) { iFlags |= O_NOFOLLOW; } #endif /* Keep lock held through open + init to avoid async close/open races. */ if (bDoLock) d_pthread_mutex_lock(&pThis->mut); pThis->fd = open((char *)pThis->pszCurrFName, iFlags | O_LARGEFILE, pThis->tOpenMode); const int errno_save = errno; /* dbgprintf can mangle it! */ DBGPRINTF("file '%s' opened as #%d with mode %d\n", pThis->pszCurrFName, pThis->fd, (int)pThis->tOpenMode); if (pThis->fd == -1) { const rsRetVal errcode = (errno_save == ENOENT) ? RS_RET_FILE_NOT_FOUND : RS_RET_FILE_OPEN_ERROR; if (pThis->fileNotFoundError) { if (pThis->noRepeatedErrorOutput == 0) { /* Defer LogError until after mutex unlock to avoid lock-order inversion * with internal message logging paths. */ bNeedOpenErrLog = 1; openErrno = errno_save; openErrcode = errcode; pThis->noRepeatedErrorOutput = 1; } } else { DBGPRINTF("file '%s': open error", pThis->pszCurrFName); } ABORT_FINALIZE(errcode); } else { pThis->noRepeatedErrorOutput = 0; } if (pThis->tOperationsMode == STREAMMODE_READ) { if (fstat(pThis->fd, &statOpen) == -1) { DBGPRINTF("Error: cannot obtain inode# for file %s\n", pThis->pszCurrFName); ABORT_FINALIZE(RS_RET_IO_ERROR); } pThis->inode = statOpen.st_ino; } if (!ustrcmp(pThis->pszCurrFName, UCHAR_CONSTANT(_PATH_CONSOLE)) || isatty(pThis->fd)) { DBGPRINTF("file %d is a tty-type file\n", pThis->fd); pThis->bIsTTY = 1; } else { pThis->bIsTTY = 0; } if (pThis->cryprov != NULL) { CHKiRet(pThis->cryprov->OnFileOpen(pThis->cryprovData, pThis->pszCurrFName, &pThis->cryprovFileData, (pThis->tOperationsMode == STREAMMODE_READ) ? 'r' : 'w')); pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose); } finalize_it: if (bDoLock) d_pthread_mutex_unlock(&pThis->mut); if (bNeedOpenErrLog) { LogError(openErrno, openErrcode, "file '%s': open error", pThis->pszCurrFName); } RETiRet; } static rsRetVal strmSetCurrFName(strm_t *pThis) { DEFiRet; if (pThis->sType == STREAMTYPE_FILE_CIRCULAR) { CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir, pThis->pszFName, pThis->lenFName, pThis->iCurrFNum, pThis->iFileNumDigits)); } else { if (pThis->pszDir == NULL) { if ((pThis->pszCurrFName = ustrdup(pThis->pszFName)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else { CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir, pThis->pszFName, pThis->lenFName, -1, 0)); } } finalize_it: RETiRet; } /* This function checks if the actual file has changed and, if so, resets the * offset. This is support for monitoring files. It should be called after * deserializing the strm object and before doing any other operation on it * (most importantly not an open or seek!). */ static rsRetVal CheckFileChange(strm_t *pThis) { struct stat statName; DEFiRet; CHKiRet(strmSetCurrFName(pThis)); if (stat((char *)pThis->pszCurrFName, &statName) == -1) ABORT_FINALIZE(RS_RET_IO_ERROR); DBGPRINTF( "CheckFileChange: stream/after deserialize checking for file change " "on '%s', inode %u/%u, size/currOffs %llu/%llu\n", pThis->pszCurrFName, (unsigned)pThis->inode, (unsigned)statName.st_ino, (long long unsigned)statName.st_size, (long long unsigned)pThis->iCurrOffs); if (pThis->inode != statName.st_ino || statName.st_size < pThis->iCurrOffs) { DBGPRINTF("stream: file %s has changed\n", pThis->pszCurrFName); pThis->iCurrOffs = 0; } finalize_it: RETiRet; } /* open a strm file * It is OK to call this function when the stream is already open. In that * case, it returns immediately with RS_RET_OK */ static rsRetVal strmOpenFile(strm_t *pThis) { DEFiRet; off_t offset; assert(pThis != NULL); if (pThis->fd != -1) ABORT_FINALIZE(RS_RET_OK); free(pThis->pszCurrFName); pThis->pszCurrFName = NULL; /* used to prevent mem leak in case of error */ if (pThis->pszFName == NULL) ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING); CHKiRet(strmSetCurrFName(pThis)); CHKiRet(doPhysOpen(pThis)); pThis->iCurrOffs = 0; pThis->iBufPtrMax = 0; CHKiRet(getFileSize(pThis->pszCurrFName, &offset)); if (pThis->tOperationsMode == STREAMMODE_WRITE_APPEND) { pThis->iCurrOffs = offset; } else if (pThis->tOperationsMode == STREAMMODE_WRITE_TRUNC) { if (offset != 0) { LogError(0, 0, "file '%s' opened for truncate write, but " "already contains %zd bytes\n", pThis->pszCurrFName, (ssize_t)offset); } } DBGOPRINT((obj_t *)pThis, "opened file '%s' for %s as %d\n", pThis->pszCurrFName, (pThis->tOperationsMode == STREAMMODE_READ) ? "READ" : "WRITE", pThis->fd); finalize_it: if (iRet == RS_RET_OK) { assert(pThis->fd != -1); } else { if (pThis->pszCurrFName != NULL) { free(pThis->pszCurrFName); pThis->pszCurrFName = NULL; /* just to prevent mis-adressing down the road... */ } if (pThis->fd != -1) { close(pThis->fd); pThis->fd = -1; } } RETiRet; } /* wait for the output writer thread to be done. This must be called before actions * that require data to be persisted. May be called in non-async mode and is a null * operation than. Must be called with the mutex locked. */ static void strmWaitAsyncWriterDone(strm_t *pThis) { if (pThis->bAsyncWrite) { /* awake writer thread and make it write out everything */ while (pThis->iCnt > 0) { pthread_cond_signal(&pThis->notEmpty); d_pthread_cond_wait(&pThis->isEmpty, &pThis->mut); } } } /* stop the writer thread (we MUST be runnnig asynchronously when this method * is called!). Note that the mutex must be locked! -- rgerhards, 2009-07-06 */ static void stopWriter(strm_t *const pThis) { pThis->bStopWriter = 1; pthread_cond_signal(&pThis->notEmpty); d_pthread_mutex_unlock(&pThis->mut); pthread_join(pThis->writerThreadID, NULL); } /* close a strm file * Note that the bDeleteOnClose flag is honored. If it is set, the file will be * deleted after close. This is in support for the qRead thread. * Note: it is valid to call this function when the physical file is closed. If so, * strmCloseFile() will still check if there is any unwritten data inside buffers * (this may be the case) and, if so, will open the file, write the data, and then * close it again (this is done via strmFlushInternal and friends). */ static rsRetVal strmCloseFile(strm_t *pThis) { off64_t currOffs; DEFiRet; assert(pThis != NULL); DBGOPRINT((obj_t *)pThis, "file %d(%s) closing, bDeleteOnClose %d\n", pThis->fd, getFileDebugName(pThis), pThis->bDeleteOnClose); if (pThis->tOperationsMode != STREAMMODE_READ) { if (pThis->bAsyncWrite) { strmWaitAsyncWriterDone(pThis); } strmFlushInternal(pThis, 0); if (pThis->iZipLevel) { doZipFinish(pThis); } if (pThis->bAsyncWrite) { stopWriter(pThis); } } /* if we have a signature provider, we must make sure that the crypto * state files are opened and proper close processing happens. */ if (pThis->cryprov != NULL && pThis->fd == -1) { const rsRetVal localRet = strmOpenFile(pThis); if (localRet != RS_RET_OK) { LogError(0, localRet, "could not open file %s, this " "may result in problems with encryption - " "unfortunately, we cannot do anything against " "this.", pThis->pszCurrFName); } } /* the file may already be closed (or never have opened), so guard * against this. -- rgerhards, 2010-03-19 */ if (pThis->fd != -1) { DBGOPRINT((obj_t *)pThis, "file %d(%s) closing\n", pThis->fd, getFileDebugName(pThis)); currOffs = lseek64(pThis->fd, 0, SEEK_CUR); close(pThis->fd); pThis->fd = -1; pThis->inode = 0; if (pThis->cryprov != NULL) { pThis->cryprov->OnFileClose(pThis->cryprovFileData, currOffs); pThis->cryprovFileData = NULL; } } if (pThis->fdDir != -1) { /* close associated directory handle, if it is open */ close(pThis->fdDir); pThis->fdDir = -1; } if (pThis->bDeleteOnClose) { if (pThis->pszCurrFName == NULL) { CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir, pThis->pszFName, pThis->lenFName, pThis->iCurrFNum, pThis->iFileNumDigits)); } DBGPRINTF("strmCloseFile: deleting '%s'\n", pThis->pszCurrFName); if (unlink((char *)pThis->pszCurrFName) == -1) { char errStr[1024]; int err = errno; rs_strerror_r(err, errStr, sizeof(errStr)); DBGPRINTF("error %d unlinking '%s' - ignored: %s\n", errno, pThis->pszCurrFName, errStr); } } pThis->iCurrOffs = 0; /* we are back at begin of file */ finalize_it: free(pThis->pszCurrFName); pThis->pszCurrFName = NULL; RETiRet; } /* switch to next strm file * This method must only be called if we are in a multi-file mode! */ static rsRetVal strmNextFile(strm_t *pThis) { DEFiRet; assert(pThis != NULL); assert(pThis->sType == STREAMTYPE_FILE_CIRCULAR); assert(pThis->fd != -1); if (pThis->iMaxFiles <= 0) { LogError(0, RS_RET_CONF_PARAM_INVLD, "stream: circular file mode requires iMaxFiles > 0, but is %d", pThis->iMaxFiles); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(strmCloseFile(pThis)); /* we do modulo operation to ensure we obey the iMaxFile property. This will always * result in a file number lower than iMaxFile, so it if wraps, the name is back to * 0, which results in the first file being overwritten. Not desired for queues, so * make sure their iMaxFiles is large enough. But it is well-desired for other * use cases, e.g. a circular output log file. -- rgerhards, 2008-01-10 */ pThis->iCurrFNum = (pThis->iCurrFNum + 1) % pThis->iMaxFiles; finalize_it: RETiRet; } /* handle the EOF case of a stream * The EOF case is somewhat complicated, as the proper action depends on the * mode the stream is in. If there are multiple files (circular logs, most * important use case is queue files!), we need to close the current file and * try to open the next one. * rgerhards, 2008-02-13 */ static rsRetVal ATTR_NONNULL() strmHandleEOF(strm_t *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); switch (pThis->sType) { case STREAMTYPE_FILE_SINGLE: case STREAMTYPE_NAMED_PIPE: ABORT_FINALIZE(RS_RET_EOF); break; case STREAMTYPE_FILE_CIRCULAR: /* we have multiple files and need to switch to the next one */ /* TODO: think about emulating EOF in this case (not yet needed) */ DBGOPRINT((obj_t *)pThis, "file %d EOF\n", pThis->fd); CHKiRet(strmNextFile(pThis)); break; case STREAMTYPE_FILE_MONITOR: DBGOPRINT((obj_t *)pThis, "file '%s' (%d) EOF, rotationCheck %d\n", pThis->pszCurrFName, pThis->fd, pThis->rotationCheck); DBGPRINTF("RGER: EOF!\n"); ABORT_FINALIZE(RS_RET_EOF); break; default: // No action needed for other cases break; } finalize_it: RETiRet; } /* helper to checkTruncation */ static rsRetVal ATTR_NONNULL() rereadTruncated(strm_t *const pThis, const int err_no, const char *const reason, const long long data) { DEFiRet; LogMsg(err_no, RS_RET_FILE_TRUNCATED, LOG_WARNING, "file '%s': truncation detected, " "(%s) - re-start reading from beginning (data %lld)", pThis->pszCurrFName, reason, data); DBGPRINTF("checkTruncation, file %s last buffer CHANGED\n", pThis->pszCurrFName); CHKiRet(strmCloseFile(pThis)); CHKiRet(strmOpenFile(pThis)); iRet = RS_RET_FILE_TRUNCATED; finalize_it: RETiRet; } /* helper to read: * Check if file has been truncated since last read and, if so, re-set reading * to begin of file. To detect truncation, we try to re-read the last block. * If that does not succeed or different data than from the original read is * returned, truncation is assumed. * NOTE: this function must be called only if truncation is enabled AND * when the previous read buffer still is valid (aka "before the next read"). * It is ok to call with a 0-size buffer, which we than assume as begin of * reading. In that case, no truncation will be detected. * rgerhards, 2018-09-20 */ static rsRetVal ATTR_NONNULL() checkTruncation(strm_t *const pThis) { DEFiRet; off64_t ret; assert(pThis->bReopenOnTruncate); assert(pThis->fd != -1); DBGPRINTF("checkTruncation, file %s, iBufPtrMax %zd\n", pThis->pszCurrFName, pThis->iBufPtrMax); if (pThis->iBufPtrMax == 0) { FINALIZE; } const off64_t backseek = -1 * (off64_t)pThis->iBufPtrMax; ret = lseek64(pThis->fd, backseek, SEEK_CUR); if (ret < 0) { iRet = rereadTruncated(pThis, errno, "cannot seek backward to begin of last block", backseek); FINALIZE; } const ssize_t lenRead = read(pThis->fd, pThis->pIOBuf_truncation, pThis->iBufPtrMax); if (lenRead != (ssize_t)pThis->iBufPtrMax) { iRet = rereadTruncated(pThis, errno, "last block could not be re-read", lenRead); FINALIZE; } if (!memcmp(pThis->pIOBuf_truncation, pThis->pIOBuf, pThis->iBufPtrMax)) { DBGPRINTF("checkTruncation, file %s last buffer unchanged\n", pThis->pszCurrFName); } else { iRet = rereadTruncated(pThis, errno, "last block data different", 0); } finalize_it: RETiRet; } /* read the next buffer from disk * rgerhards, 2008-02-13 */ static rsRetVal strmReadBuf(strm_t *pThis, int *padBytes) { DEFiRet; int bRun; long iLenRead; size_t actualDataLen; size_t toRead; ssize_t bytesLeft; ISOBJ_TYPE_assert(pThis, strm); /* We need to try read at least twice because we may run into EOF and need to switch files. */ bRun = 1; while (bRun) { /* first check if we need to (re)open the file. We may have switched to a new one in * circular mode or it may have been rewritten (rotated) if we monitor a file * rgerhards, 2008-02-13 */ CHKiRet(strmOpenFile(pThis)); if (pThis->cryprov == NULL) { toRead = pThis->sIOBufSize; } else { CHKiRet(pThis->cryprov->GetBytesLeftInBlock(pThis->cryprovFileData, &bytesLeft)); if (bytesLeft == -1 || bytesLeft > (ssize_t)pThis->sIOBufSize) { toRead = pThis->sIOBufSize; } else { toRead = (size_t)bytesLeft; } } if (pThis->bReopenOnTruncate) { rsRetVal localRet = checkTruncation(pThis); if (localRet == RS_RET_FILE_TRUNCATED) { continue; } CHKiRet(localRet); } iLenRead = read(pThis->fd, pThis->pIOBuf, toRead); DBGOPRINT((obj_t *)pThis, "file %d read %ld bytes\n", pThis->fd, iLenRead); DBGOPRINT((obj_t *)pThis, "file %d read %*s\n", pThis->fd, (unsigned)iLenRead, (char *)pThis->pIOBuf); /* end crypto */ if (iLenRead == 0) { CHKiRet(strmHandleEOF(pThis)); } else if (iLenRead < 0) ABORT_FINALIZE(RS_RET_IO_ERROR); else { /* good read */ /* here we place our crypto interface */ if (pThis->cryprov != NULL) { actualDataLen = iLenRead; pThis->cryprov->Decrypt(pThis->cryprovFileData, pThis->pIOBuf, &actualDataLen); *padBytes = iLenRead - actualDataLen; iLenRead = actualDataLen; DBGOPRINT((obj_t *)pThis, "encrypted file %d pad bytes %d, actual " "data %ld\n", pThis->fd, *padBytes, iLenRead); } else { *padBytes = 0; } pThis->iBufPtrMax = iLenRead; bRun = 0; /* exit loop */ } } /* if we reach this point, we had a good read */ pThis->iBufPtr = 0; finalize_it: RETiRet; } /* debug output of current buffer */ void strmDebugOutBuf(const strm_t *const pThis) { int strtIdx = pThis->iBufPtr - 50; if (strtIdx < 0) strtIdx = 0; DBGOPRINT((obj_t *)pThis, "strmRead ungetc %d, index %zd, max %zd, buf '%.*s', CURR: '%.*s'\n", pThis->iUngetC, pThis->iBufPtr, pThis->iBufPtrMax, (int)pThis->iBufPtrMax - strtIdx, pThis->pIOBuf + strtIdx, (int)(pThis->iBufPtrMax - pThis->iBufPtr), pThis->pIOBuf + pThis->iBufPtr); } /* logically "read" a character from a file. What actually happens is that * data is taken from the buffer. Only if the buffer is full, data is read * directly from file. In that case, a read is performed blockwise. * rgerhards, 2008-01-07 * NOTE: needs to be enhanced to support sticking with a strm entry (if not * deleted). */ static rsRetVal strmReadChar(strm_t *pThis, uchar *pC) { int padBytes = 0; /* in crypto mode, we may have some padding (non-data) bytes */ DEFiRet; assert(pThis != NULL); assert(pC != NULL); /* DEV debug only: DBGOPRINT((obj_t*) pThis, "strmRead index %zd, max %zd\n", pThis->iBufPtr, pThis->iBufPtrMax); */ if (pThis->iUngetC != -1) { /* do we have an "unread" char that we need to provide? */ *pC = pThis->iUngetC; ++pThis->iCurrOffs; /* one more octet read */ pThis->iUngetC = -1; ABORT_FINALIZE(RS_RET_OK); } /* do we need to obtain a new buffer? */ if (pThis->iBufPtr >= pThis->iBufPtrMax) { CHKiRet(strmReadBuf(pThis, &padBytes)); } pThis->iCurrOffs += padBytes; /* if we reach this point, we have data available in the buffer */ *pC = pThis->pIOBuf[pThis->iBufPtr++]; ++pThis->iCurrOffs; /* one more octet read */ finalize_it: RETiRet; } /* unget a single character just like ungetc(). As with that call, there is only a single * character buffering capability. * rgerhards, 2008-01-07 */ static rsRetVal strmUnreadChar(strm_t *pThis, uchar c) { assert(pThis != NULL); assert(pThis->iUngetC == -1); pThis->iUngetC = c; --pThis->iCurrOffs; /* one less octet read - NOTE: this can cause problems if we got a file change and immediately do an unread and the file is on a buffer boundary and the stream is then persisted. With the queue, this can not happen as an Unread is only done on record begin, which is never split accross files. For other cases we accept the very remote risk. -- rgerhards, 2008-01-12 */ return RS_RET_OK; } /* read a 'paragraph' from a strm file. * A paragraph may be terminated by a LF, by a LFLF, or by LF depending on the option set. * The termination LF characters are read, but are * not returned in the buffer (it is discared). The caller is responsible for * destruction of the returned CStr object! -- dlang 2010-12-13 * * Parameter mode controls legacy multi-line processing: * mode = 0 single line mode (equivalent to ReadLine) * mode = 1 LFLF mode (paragraph, blank line between entries) * mode = 2 LF mode, a log line starts at the beginning of * a line, but following lines that are indented are part of the same log entry */ static rsRetVal ATTR_NONNULL(1, 2) strmReadLine(strm_t *const pThis, cstr_t **ppCStr, uint8_t mode, sbool bEscapeLF, const uchar *const escapeLFString, uint32_t trimLineOverBytes, int64 *const strtOffs) { uchar c; uchar finished; const int escapeLFString_len = (escapeLFString == NULL) ? 4 : strlen((char *)escapeLFString); DEFiRet; assert(pThis != NULL); assert(ppCStr != NULL); CHKiRet(cstrConstruct(ppCStr)); CHKiRet(strmReadChar(pThis, &c)); /* append previous message to current message if necessary */ if (pThis->prevLineSegment != NULL) { cstrFinalize(pThis->prevLineSegment); dbgprintf("readLine: have previous line segment: '%s'\n", rsCStrGetSzStrNoNULL(pThis->prevLineSegment)); CHKiRet(cstrAppendCStr(*ppCStr, pThis->prevLineSegment)); cstrDestruct(&pThis->prevLineSegment); } if (mode == 0) { while (c != '\n') { CHKiRet(cstrAppendChar(*ppCStr, c)); CHKiRet(strmReadChar(pThis, &c)); } if (trimLineOverBytes > 0 && (uint32_t)cstrLen(*ppCStr) > trimLineOverBytes) { /* Truncate long line at trimLineOverBytes position */ dbgprintf("Truncate long line at %u, mode %d\n", trimLineOverBytes, mode); rsCStrTruncate(*ppCStr, cstrLen(*ppCStr) - trimLineOverBytes); cstrAppendChar(*ppCStr, '\n'); } cstrFinalize(*ppCStr); } else if (mode == 1) { finished = 0; while (finished == 0) { if (c != '\n') { CHKiRet(cstrAppendChar(*ppCStr, c)); CHKiRet(strmReadChar(pThis, &c)); pThis->bPrevWasNL = 0; } else { if ((((*ppCStr)->iStrLen) > 0)) { if (pThis->bPrevWasNL && escapeLFString_len > 0) { rsCStrTruncate(*ppCStr, (bEscapeLF) ? escapeLFString_len : 1); /* remove the prior newline */ finished = 1; } else { if (bEscapeLF) { if (escapeLFString == NULL) { CHKiRet(rsCStrAppendStrWithLen(*ppCStr, (uchar *)"#012", sizeof("#012") - 1)); } else { CHKiRet(rsCStrAppendStrWithLen(*ppCStr, escapeLFString, escapeLFString_len)); } } else { CHKiRet(cstrAppendChar(*ppCStr, c)); } CHKiRet(strmReadChar(pThis, &c)); pThis->bPrevWasNL = 1; } } else { finished = 1; /* this is a blank line, a \n with nothing since the last complete record */ } } } cstrFinalize(*ppCStr); pThis->bPrevWasNL = 0; } else if (mode == 2) { /* indented follow-up lines */ finished = 0; while (finished == 0) { if ((*ppCStr)->iStrLen == 0) { if (c != '\n') { /* nothing in the buffer, and it's not a newline, add it to the buffer */ CHKiRet(cstrAppendChar(*ppCStr, c)); CHKiRet(strmReadChar(pThis, &c)); } else { finished = 1; /* this is a blank line, a \n with nothing since the last complete record */ } } else { if (pThis->bPrevWasNL) { if ((c == ' ') || (c == '\t')) { CHKiRet(cstrAppendChar(*ppCStr, c)); CHKiRet(strmReadChar(pThis, &c)); pThis->bPrevWasNL = 0; } else { /* clean things up by putting the character we just read back into * the input buffer and removing the LF character that is * currently at the * end of the output string */ CHKiRet(strmUnreadChar(pThis, c)); if (bEscapeLF && escapeLFString_len > 0) { rsCStrTruncate(*ppCStr, (bEscapeLF) ? escapeLFString_len : 1); } finished = 1; } } else { /* not the first character after a newline, add it to the buffer */ if (c == '\n') { pThis->bPrevWasNL = 1; if (bEscapeLF && escapeLFString_len > 0) { if (escapeLFString == NULL) { CHKiRet(rsCStrAppendStrWithLen(*ppCStr, (uchar *)"#012", sizeof("#012") - 1)); } else { CHKiRet(rsCStrAppendStrWithLen(*ppCStr, escapeLFString, escapeLFString_len)); } } else { CHKiRet(cstrAppendChar(*ppCStr, c)); } } else { CHKiRet(cstrAppendChar(*ppCStr, c)); } CHKiRet(strmReadChar(pThis, &c)); } } } if (trimLineOverBytes > 0 && (uint32_t)cstrLen(*ppCStr) > trimLineOverBytes) { /* Truncate long line at trimLineOverBytes position */ dbgprintf("Truncate long line at %u, mode %d\n", trimLineOverBytes, mode); rsCStrTruncate(*ppCStr, cstrLen(*ppCStr) - trimLineOverBytes); cstrAppendChar(*ppCStr, '\n'); } cstrFinalize(*ppCStr); pThis->bPrevWasNL = 0; } finalize_it: if (iRet == RS_RET_OK) { if (strtOffs != NULL) { *strtOffs = pThis->strtOffs; } pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */ } else { DBGPRINTF("RGER: strmReadLine iRet %d\n", iRet); if (*ppCStr != NULL) { if (cstrLen(*ppCStr) > 0) { /* we may have an empty string in an unsuccesfull poll or after restart! */ if (rsCStrConstructFromCStr(&pThis->prevLineSegment, *ppCStr) != RS_RET_OK) { /* we cannot do anything against this, but we can at least * ensure we do not have any follow-on errors. */ pThis->prevLineSegment = NULL; } } cstrDestruct(ppCStr); } } RETiRet; } /* check if the current multi line read is timed out * @return 0 - no timeout, something else - timeout */ int strmReadMultiLine_isTimedOut(const strm_t *const __restrict__ pThis) { /* note: order of evaluation is choosen so that the most inexpensive * processing flow is used. */ DBGPRINTF( "strmReadMultiline_isTimedOut: prevMsgSeg %p, readTimeout %d, " "lastRead %lld\n", pThis->prevMsgSegment, pThis->readTimeout, (long long)pThis->lastRead); return ((pThis->readTimeout) && (pThis->prevMsgSegment != NULL) && (getTime(NULL) > pThis->lastRead + pThis->readTimeout)); } /* read a multi-line message from a strm file. * The multi-line message is terminated based on the user-provided * startRegex or endRegex (Posix ERE). For performance reasons, the regex * must already have been compiled by the user. * added 2015-05-12 rgerhards */ rsRetVal ATTR_NONNULL(1, 2) strmReadMultiLine(strm_t *pThis, cstr_t **ppCStr, regex_t *start_preg, regex_t *end_preg, const sbool bEscapeLF, const uchar *const escapeLFString, const sbool discardTruncatedMsg, const sbool msgDiscardingError, int64 *const strtOffs) { uchar c; uchar finished = 0; cstr_t *thisLine = NULL; rsRetVal readCharRet; const time_t tCurr = pThis->readTimeout ? getTime(NULL) : 0; size_t maxMsgSize = glblGetMaxLine(runConf); DEFiRet; do { CHKiRet(strmReadChar(pThis, &c)); /* immediately exit on EOF */ pThis->lastRead = tCurr; CHKiRet(cstrConstruct(&thisLine)); /* append previous message to current message if necessary */ if (pThis->prevLineSegment != NULL) { CHKiRet(cstrAppendCStr(thisLine, pThis->prevLineSegment)); cstrDestruct(&pThis->prevLineSegment); } while (c != '\n') { CHKiRet(cstrAppendChar(thisLine, c)); readCharRet = strmReadChar(pThis, &c); if (readCharRet == RS_RET_EOF) { /* end of file reached without \n? */ CHKiRet(rsCStrConstructFromCStr(&pThis->prevLineSegment, thisLine)); } CHKiRet(readCharRet); } cstrFinalize(thisLine); /* we have a line, now let's assemble the message */ const int isStartMatch = start_preg ? !regexec(start_preg, (char *)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) : 0; const int isEndMatch = end_preg ? !regexec(end_preg, (char *)rsCStrGetSzStrNoNULL(thisLine), 0, NULL, 0) : 0; if (isStartMatch) { /* in this case, the *previous* message is complete and we are * at the start of a new one. */ if (pThis->ignoringMsg == 0) { if (pThis->prevMsgSegment != NULL) { /* may be NULL in initial poll! */ finished = 1; *ppCStr = pThis->prevMsgSegment; } } CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, thisLine)); pThis->ignoringMsg = 0; } else { if (pThis->ignoringMsg == 0) { if (pThis->prevMsgSegment == NULL) { /* may be NULL in initial poll or after timeout! */ CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, thisLine)); } else { if (bEscapeLF) { if (escapeLFString == NULL) { rsCStrAppendStrWithLen(pThis->prevMsgSegment, (uchar *)"\\n", 2); } else { rsCStrAppendStr(pThis->prevMsgSegment, escapeLFString); } } else { cstrAppendChar(pThis->prevMsgSegment, '\n'); } size_t currLineLen = cstrLen(thisLine); if (currLineLen > 0) { size_t len; if ((len = cstrLen(pThis->prevMsgSegment) + currLineLen) < maxMsgSize) { CHKiRet(cstrAppendCStr(pThis->prevMsgSegment, thisLine)); /* we could do this faster, but for now keep it simple */ } else { if (cstrLen(pThis->prevMsgSegment) > maxMsgSize) { len = 0; } else { len = currLineLen - (len - maxMsgSize); for (size_t z = 0; z < len; z++) { cstrAppendChar(pThis->prevMsgSegment, thisLine->pBuf[z]); } } finished = 1; *ppCStr = pThis->prevMsgSegment; CHKiRet(rsCStrConstructFromszStr(&pThis->prevMsgSegment, thisLine->pBuf + len)); if (discardTruncatedMsg == 1) { pThis->ignoringMsg = 1; } if (msgDiscardingError == 1) { if (discardTruncatedMsg == 1) { LogError(0, RS_RET_ERR, "imfile error: message received is " "larger than max msg size; " "rest of message will not be " "processed"); } else { LogError(0, RS_RET_ERR, "imfile error: message received is " "larger than max msg size; message " "will be split and processed as " "another message"); } } } } } } } if (isEndMatch) { /* in this case, the *current* message is complete and we are * at the end of it. */ if (pThis->ignoringMsg == 0) { if (pThis->prevMsgSegment != NULL) { finished = 1; *ppCStr = pThis->prevMsgSegment; pThis->prevMsgSegment = NULL; } } pThis->ignoringMsg = 0; } cstrDestruct(&thisLine); } while (finished == 0); finalize_it: *strtOffs = pThis->strtOffs; if (thisLine != NULL) { cstrDestruct(&thisLine); } if (iRet == RS_RET_OK) { pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */ cstrFinalize(*ppCStr); } else { if (pThis->readTimeout && (pThis->prevMsgSegment != NULL) && (tCurr > pThis->lastRead + pThis->readTimeout)) { if (rsCStrConstructFromCStr(ppCStr, pThis->prevMsgSegment) == RS_RET_OK) { cstrFinalize(*ppCStr); cstrDestruct(&pThis->prevMsgSegment); pThis->lastRead = tCurr; pThis->strtOffs = pThis->iCurrOffs; /* we are at begin of next line */ dbgprintf("stream: generated msg based on timeout: %s\n", cstrGetSzStrNoNULL(*ppCStr)); iRet = RS_RET_OK; } } } RETiRet; } /* Standard-Constructor for the strm object */ BEGINobjConstruct(strm) /* be sure to specify the object type also in END macro! */ pThis->iCurrFNum = 1; pThis->fd = -1; pThis->fdDir = -1; pThis->iUngetC = -1; pThis->bVeryReliableZip = 0; pThis->sType = STREAMTYPE_FILE_SINGLE; pThis->sIOBufSize = glblGetIOBufSize(); pThis->tOpenMode = 0600; pThis->compressionDriver = STRM_COMPRESS_ZIP; pThis->pszSizeLimitCmd = NULL; pThis->bSizeLimitCmdPassFileName = 1; pThis->prevLineSegment = NULL; pThis->prevMsgSegment = NULL; pThis->strtOffs = 0; pThis->ignoringMsg = 0; pThis->bPrevWasNL = 0; pThis->fileNotFoundError = 1; pThis->noRepeatedErrorOutput = 0; pThis->lastRead = getTime(NULL); ENDobjConstruct(strm) /* ConstructionFinalizer * rgerhards, 2008-01-09 */ static rsRetVal strmConstructFinalize(strm_t *pThis) { pthread_mutexattr_t mutAttr; rsRetVal localRet; int i; DEFiRet; assert(pThis != NULL); pThis->iBufPtrMax = 0; /* results in immediate read request */ if (pThis->iZipLevel) { /* do we need a zip buf? */ if (pThis->compressionDriver == STRM_COMPRESS_ZSTD) { localRet = objUse(zstdw, LM_ZSTDW_FILENAME); if (localRet != RS_RET_OK) { pThis->iZipLevel = 0; LogError(0, localRet, "stream was requested with zstd compression mode, " "but zstdw module unavailable - using without compression\n"); } } else { assert(pThis->compressionDriver == STRM_COMPRESS_ZIP); localRet = objUse(zlibw, LM_ZLIBW_FILENAME); if (localRet != RS_RET_OK) { pThis->iZipLevel = 0; LogError(0, localRet, "stream was requested with zip mode, but zlibw " "module unavailable - using without zip\n"); } } /* we use the same size as the original buf, as we would like * to make sure we can write out everything with a SINGLE api call! * We add another 128 bytes to take care of the gzip header and "all eventualities". */ CHKmalloc(pThis->pZipBuf = (Bytef *)malloc(pThis->sIOBufSize + 128)); } /* if we are set to sync, we must obtain a file handle to the directory for fsync() purposes */ if (pThis->bSync && !pThis->bIsTTY && pThis->pszDir != NULL) { pThis->fdDir = open((char *)pThis->pszDir, O_RDONLY | O_CLOEXEC | O_NOCTTY); if (pThis->fdDir == -1) { char errStr[1024]; int err = errno; rs_strerror_r(err, errStr, sizeof(errStr)); DBGPRINTF( "error %d opening directory file for fsync() use - fsync for directory " "disabled: %s\n", errno, errStr); } } /* if we have a flush interval, we need to do async writes in any case */ if (pThis->iFlushInterval != 0) { pThis->bAsyncWrite = 1; } DBGPRINTF("file stream %s params: flush interval %d, async write %d\n", getFileDebugName(pThis), pThis->iFlushInterval, pThis->bAsyncWrite); /* if we work asynchronously, we need a couple of synchronization objects */ if (pThis->bAsyncWrite) { /* the mutex must be recursive, because objects may call into other * object identifiers recursively. */ pthread_mutexattr_init(&mutAttr); pthread_mutexattr_settype(&mutAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&pThis->mut, &mutAttr); pthread_cond_init(&pThis->notFull, 0); pthread_cond_init(&pThis->notEmpty, 0); pthread_cond_init(&pThis->isEmpty, 0); pThis->iCnt = pThis->iEnq = pThis->iDeq = 0; for (i = 0; i < STREAM_ASYNC_NUMBUFS; ++i) { CHKmalloc(pThis->asyncBuf[i].pBuf = (uchar *)malloc(pThis->sIOBufSize)); } pThis->pIOBuf = pThis->asyncBuf[0].pBuf; pThis->bStopWriter = 0; if (pthread_create(&pThis->writerThreadID, &default_thread_attr, asyncWriterThread, pThis) != 0) DBGPRINTF("ERROR: stream %p cold not create writer thread\n", pThis); } else { /* we work synchronously, so we need to alloc a fixed pIOBuf */ CHKmalloc(pThis->pIOBuf = (uchar *)malloc(pThis->sIOBufSize)); CHKmalloc(pThis->pIOBuf_truncation = (char *)malloc(pThis->sIOBufSize)); } finalize_it: RETiRet; } /* destructor for the strm object */ BEGINobjDestruct(strm) /* be sure to specify the object type also in END and CODESTART macros! */ int i; CODESTARTobjDestruct(strm); /* we need to stop the ZIP writer */ if (pThis->bAsyncWrite) /* Note: mutex will be unlocked in strmCloseFile/stopWriter! */ d_pthread_mutex_lock(&pThis->mut); /* strmClose() will handle read-only files as well as need to open * files that have unwritten buffers. -- rgerhards, 2010-03-09 */ strmCloseFile(pThis); if (pThis->bAsyncWrite) { pthread_mutex_destroy(&pThis->mut); pthread_cond_destroy(&pThis->notFull); pthread_cond_destroy(&pThis->notEmpty); pthread_cond_destroy(&pThis->isEmpty); for (i = 0; i < STREAM_ASYNC_NUMBUFS; ++i) { free(pThis->asyncBuf[i].pBuf); } } else { free(pThis->pIOBuf); free(pThis->pIOBuf_truncation); } /* Finally, we can free the resources. * IMPORTANT: we MUST free this only AFTER the ansyncWriter has been stopped, else * we get random errors... */ if (pThis->compressionDriver == STRM_COMPRESS_ZSTD) { zstdw.Destruct(pThis); } if (pThis->prevLineSegment) cstrDestruct(&pThis->prevLineSegment); if (pThis->prevMsgSegment) cstrDestruct(&pThis->prevMsgSegment); free(pThis->pszDir); free(pThis->pZipBuf); free(pThis->pszCurrFName); free(pThis->pszFName); free(pThis->pszSizeLimitCmd); pThis->bStopWriter = 2; /* RG: use as flag for destruction */ ENDobjDestruct(strm) /* check if we need to open a new file (in output mode only). * The decision is based on file size AND record delimition state. * This method may also be called on a closed file, in which case * it immediately returns. */ static rsRetVal strmCheckNextOutputFile(strm_t *pThis) { DEFiRet; if (pThis->fd == -1 || pThis->sType != STREAMTYPE_FILE_CIRCULAR) FINALIZE; /* wait for output to be empty, so that our counts are correct */ strmWaitAsyncWriterDone(pThis); if (pThis->iCurrOffs >= pThis->iMaxFileSize) { DBGOPRINT((obj_t *)pThis, "max file size %ld reached for %d, now %ld - starting new file\n", (long)pThis->iMaxFileSize, pThis->fd, (long)pThis->iCurrOffs); CHKiRet(strmNextFile(pThis)); } finalize_it: RETiRet; } /* try to recover a tty after a write error. This may have happend * due to vhangup(), and, if so, we can simply re-open it. */ #ifdef linux #define ERR_TTYHUP EIO #else #define ERR_TTYHUP EBADF #endif static rsRetVal tryTTYRecover(strm_t *pThis, int err) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); #ifndef __FreeBSD__ if (err == ERR_TTYHUP) { #else /* Try to reopen our file descriptor even on errno 6, FreeBSD bug 200429 * Also try on errno 5, FreeBSD bug 211033 */ if (err == ERR_TTYHUP || err == ENXIO || err == EIO) { #endif /* __FreeBSD__ */ close(pThis->fd); pThis->fd = -1; CHKiRet(doPhysOpen(pThis)); } finalize_it: RETiRet; } #undef ER_TTYHUP /* issue write() api calls until either the buffer is completely * written or an error occurred (it may happen that multiple writes * are required, what is perfectly legal. On exit, *pLenBuf contains * the number of bytes actually written. * rgerhards, 2009-06-08 */ static rsRetVal ATTR_NONNULL(1, 2, 3) doWriteCall(strm_t *pThis, uchar *pBuf, size_t *pLenBuf) { ssize_t lenBuf; ssize_t iTotalWritten; ssize_t iWritten; char *pWriteBuf; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); #ifdef __FreeBSD__ sbool crnlNow = 0; #endif /* __FreeBSD__ */ lenBuf = *pLenBuf; pWriteBuf = (char *)pBuf; iTotalWritten = 0; do { #ifdef __FreeBSD__ if (pThis->bIsTTY && !pThis->iZipLevel && !pThis->cryprov) { char *pNl = NULL; if (crnlNow == 0) pNl = strchr(pWriteBuf, '\n'); else crnlNow = 0; if (pNl == pWriteBuf) { iWritten = write(pThis->fd, "\r", 1); if (iWritten > 0) { crnlNow = 1; iWritten = 0; } } else iWritten = write(pThis->fd, pWriteBuf, pNl ? pNl - pWriteBuf : lenBuf); } else #endif /* __FreeBSD__ */ iWritten = write(pThis->fd, pWriteBuf, lenBuf); if (iWritten < 0) { const int err = errno; iWritten = 0; /* we have written NO bytes! */ if (err == EBADF) { DBGPRINTF( "file %s: errno %d, fd %d no longer valid, recovery by " "reopen; if you see this, consider reporting at " "https://github.com/rsyslog/rsyslog/issues/3404 " "so that we know when it happens. Include output of uname -a. " "OS error reason", pThis->pszCurrFName, err, pThis->fd); pThis->fd = -1; CHKiRet(doPhysOpen(pThis)); } else { if (err != EINTR) { LogError(err, RS_RET_IO_ERROR, "file '%s'[%d] write error - see " "https://www.rsyslog.com/solving-rsyslog-write-errors/ for help " "OS error", pThis->pszCurrFName, pThis->fd); } if (err == EINTR) { /*NO ERROR, just continue */; } else if (!pThis->bIsTTY && (err == ENOTCONN || err == EIO)) { /* Failure for network file system, thus file needs to be closed * and reopened. */ close(pThis->fd); pThis->fd = -1; CHKiRet(doPhysOpen(pThis)); } else { if (pThis->bIsTTY) { CHKiRet(tryTTYRecover(pThis, err)); } else { ABORT_FINALIZE(RS_RET_IO_ERROR); /* Would it make sense to cover more error cases? So far, I * do not see good reason to do so. */ } } } } /* advance buffer to next write position */ iTotalWritten += iWritten; lenBuf -= iWritten; pWriteBuf += iWritten; } while (lenBuf > 0); /* Warning: do..while()! */ DBGOPRINT((obj_t *)pThis, "file %d write wrote %d bytes\n", pThis->fd, (int)iWritten); finalize_it: *pLenBuf = iTotalWritten; RETiRet; } /* write memory buffer to a stream object. */ static rsRetVal doWriteInternal(strm_t *pThis, uchar *pBuf, const size_t lenBuf, const int bFlush) { DEFiRet; DBGOPRINT((obj_t *)pThis, "file %d(%s) doWriteInternal: bFlush %d\n", pThis->fd, getFileDebugName(pThis), bFlush); if (pThis->iZipLevel) { CHKiRet(doZipWrite(pThis, pBuf, lenBuf, bFlush)); } else { /* write without zipping */ CHKiRet(strmPhysWrite(pThis, pBuf, lenBuf)); } finalize_it: RETiRet; } /* This function is called to "do" an async write call, what primarily means that * the data is handed over to the writer thread (which will then do the actual write * in parallel). Note that the stream mutex has already been locked by the * strmWrite...() calls. Also note that we always have only a single producer, * so we can simply serially assign the next free buffer to it and be sure that * the very some producer comes back in sequence to submit the then-filled buffers. * This also enables us to timout on partially written buffers. -- rgerhards, 2009-07-06 */ static rsRetVal doAsyncWriteInternal(strm_t *pThis, size_t lenBuf, const int bFlushZip) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); DBGOPRINT((obj_t *)pThis, "file %d(%s) doAsyncWriteInternal at begin: " "iCnt %d, iEnq %d, bFlushZip %d\n", pThis->fd, getFileDebugName(pThis), pThis->iCnt, pThis->iEnq, bFlushZip); /* the -1 below is important, because we need one buffer for the main thread! */ while (pThis->iCnt >= STREAM_ASYNC_NUMBUFS - 1) d_pthread_cond_wait(&pThis->notFull, &pThis->mut); pThis->asyncBuf[pThis->iEnq % STREAM_ASYNC_NUMBUFS].lenBuf = lenBuf; pThis->pIOBuf = pThis->asyncBuf[++pThis->iEnq % STREAM_ASYNC_NUMBUFS].pBuf; if (!pThis->bFlushNow) /* if we already need to flush, do not overwrite */ pThis->bFlushNow = bFlushZip; pThis->bDoTimedWait = 0; /* everything written, no need to timeout partial buffer writes */ if (++pThis->iCnt == 1) { pthread_cond_signal(&pThis->notEmpty); DBGOPRINT((obj_t *)pThis, "doAsyncWriteInternal signaled notEmpty\n"); } DBGOPRINT((obj_t *)pThis, "file %d(%s) doAsyncWriteInternal at exit: " "iCnt %d, iEnq %d, bFlushZip %d\n", pThis->fd, getFileDebugName(pThis), pThis->iCnt, pThis->iEnq, bFlushZip); RETiRet; } /* schedule writing to the stream. Depending on our concurrency settings, * this either directly writes to the stream or schedules writing via * the background thread. -- rgerhards, 2009-07-07 */ static rsRetVal strmSchedWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlushZip) { DEFiRet; assert(pThis != NULL); /* we need to reset the buffer pointer BEFORE calling the actual write * function. Otherwise, in circular mode, the write function will * potentially close the file, then close will flush and as the * buffer pointer is nonzero, will re-call into this code here. In * the end result, we than have a problem (and things are screwed * up). So we reset the buffer pointer first, and all this can * not happen. It is safe to do so, because that pointer is NOT * used inside the write functions. -- rgerhads, 2010-03-10 */ pThis->iBufPtr = 0; /* we are at the begin of a new buffer */ if (pThis->bAsyncWrite) { CHKiRet(doAsyncWriteInternal(pThis, lenBuf, bFlushZip)); } else { CHKiRet(doWriteInternal(pThis, pBuf, lenBuf, bFlushZip)); } finalize_it: RETiRet; } /* This is the writer thread for asynchronous mode. * -- rgerhards, 2009-07-06 */ static void *asyncWriterThread(void *pPtr) { int iDeq; struct timespec t; sbool bTimedOut = 0; strm_t *pThis = (strm_t *)pPtr; int err; uchar thrdName[256] = "rs:"; ISOBJ_TYPE_assert(pThis, strm); ustrncpy(thrdName + 3, pThis->pszFName, sizeof(thrdName) - 4); dbgOutputTID((char *)thrdName); #if defined(HAVE_PRCTL) && defined(PR_SET_NAME) if (prctl(PR_SET_NAME, (char *)thrdName, 0, 0, 0) != 0) { DBGPRINTF("prctl failed, not setting thread name for '%s'\n", "stream writer"); } #endif d_pthread_mutex_lock(&pThis->mut); while (1) { /* loop broken inside */ while (pThis->iCnt == 0) { DBGOPRINT((obj_t *)pThis, "file %d(%s) asyncWriterThread new iteration, " "iCnt %d, bTimedOut %d, iFlushInterval %d\n", pThis->fd, getFileDebugName(pThis), pThis->iCnt, bTimedOut, pThis->iFlushInterval); if (pThis->bStopWriter) { pthread_cond_broadcast(&pThis->isEmpty); d_pthread_mutex_unlock(&pThis->mut); goto finalize_it; /* break main loop */ } if (bTimedOut && pThis->iBufPtr > 0) { /* if we timed out, we need to flush pending data */ strmFlushInternal(pThis, 1); bTimedOut = 0; continue; } bTimedOut = 0; if (pThis->bDoTimedWait) { timeoutComp(&t, pThis->iFlushInterval * 1000); /* 1000 *millisconds* */ if ((err = pthread_cond_timedwait(&pThis->notEmpty, &pThis->mut, &t)) != 0) { DBGOPRINT((obj_t *)pThis, "file %d(%s) asyncWriterThread timed out\n", pThis->fd, getFileDebugName(pThis)); bTimedOut = 1; /* simulate in any case */ if (err != ETIMEDOUT) { char errStr[1024]; rs_strerror_r(err, errStr, sizeof(errStr)); DBGPRINTF( "stream async writer timeout with error (%d): %s - " "ignoring\n", err, errStr); } } } else { d_pthread_cond_wait(&pThis->notEmpty, &pThis->mut); } } DBGOPRINT((obj_t *)pThis, "file %d(%s) asyncWriterThread awoken, " "iCnt %d, bTimedOut %d\n", pThis->fd, getFileDebugName(pThis), pThis->iCnt, bTimedOut); bTimedOut = 0; /* we may have timed out, but there *is* work to do... */ iDeq = pThis->iDeq++ % STREAM_ASYNC_NUMBUFS; const int bFlush = (pThis->bFlushNow || bTimedOut) ? 1 : 0; pThis->bFlushNow = 0; /* now we can do the actual write in parallel */ d_pthread_mutex_unlock(&pThis->mut); doWriteInternal(pThis, pThis->asyncBuf[iDeq].pBuf, pThis->asyncBuf[iDeq].lenBuf, bFlush); // TODO: error check????? 2009-07-06 d_pthread_mutex_lock(&pThis->mut); --pThis->iCnt; if (pThis->iCnt < STREAM_ASYNC_NUMBUFS) { pthread_cond_signal(&pThis->notFull); if (pThis->iCnt == 0) pthread_cond_broadcast(&pThis->isEmpty); } } /* Not reached */ finalize_it: DBGOPRINT((obj_t *)pThis, "file %d(%s) asyncWriterThread terminated\n", pThis->fd, getFileDebugName(pThis)); return NULL; /* to keep pthreads happy */ } /* sync the file to disk, so that any unwritten data is persisted. This * also syncs the directory and thus makes sure that the file survives * fatal failure. Note that we do NOT return an error status if the * sync fails. Doing so would probably cause more trouble than it * is worth (read: data loss may occur where we otherwise might not * have it). -- rgerhards, 2009-06-08 */ #undef SYNCCALL #if defined(HAVE_FDATASYNC) && !defined(__APPLE__) #define SYNCCALL(x) fdatasync(x) #else #define SYNCCALL(x) fsync(x) #endif static rsRetVal syncFile(strm_t *pThis) { int ret; DEFiRet; if (pThis->bIsTTY) FINALIZE; /* TTYs can not be synced */ DBGPRINTF("syncing file %d\n", pThis->fd); ret = SYNCCALL(pThis->fd); if (ret != 0) { char errStr[1024]; int err = errno; rs_strerror_r(err, errStr, sizeof(errStr)); DBGPRINTF("sync failed for file %d with error (%d): %s - ignoring\n", pThis->fd, err, errStr); } if (pThis->fdDir != -1) { if (fsync(pThis->fdDir) != 0) DBGPRINTF("stream/syncFile: fsync returned error, ignoring\n"); } finalize_it: RETiRet; } #undef SYNCCALL /* physically write to the output file. the provided data is ready for * writing (e.g. zipped if we are requested to do that). * Note that if the write() API fails, we do not reset any pointers, but return * an error code. That means we may redo work in the next iteration. * rgerhards, 2009-06-04 */ static rsRetVal strmPhysWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf) { size_t iWritten; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); DBGPRINTF("strmPhysWrite, stream %p, len %u\n", pThis, (unsigned)lenBuf); if (pThis->fd == -1) CHKiRet(strmOpenFile(pThis)); /* here we place our crypto interface */ if (pThis->cryprov != NULL) { pThis->cryprov->Encrypt(pThis->cryprovFileData, pBuf, &lenBuf); } /* end crypto */ iWritten = lenBuf; CHKiRet(doWriteCall(pThis, pBuf, &iWritten)); pThis->iCurrOffs += iWritten; /* update user counter, if provided */ if (pThis->pUsrWCntr != NULL) *pThis->pUsrWCntr += iWritten; if (pThis->bSync) { CHKiRet(syncFile(pThis)); } if (pThis->sType == STREAMTYPE_FILE_CIRCULAR) { CHKiRet(strmCheckNextOutputFile(pThis)); } finalize_it: RETiRet; } /* write the output buffer in zip mode * This means we compress it first and then do a physical write. * Note that we always do a full deflateInit ... deflate ... deflateEnd * sequence. While this is not optimal, we need to do it because we need * to ensure that the file is readable even when we are aborted. Doing the * full sequence brings us as far towards this goal as possible (and not * doing it would be a total failure). It may be worth considering to * add a config switch so that the user can decide the risk he is ready * to take, but so far this is not yet implemented (not even requested ;)). * rgerhards, 2009-06-04 */ static rsRetVal doZipWrite(strm_t *pThis, uchar *pBuf, size_t lenBuf, const int bFlush) { if (pThis->compressionDriver == STRM_COMPRESS_ZSTD) { return zstdw.doStrmWrite(pThis, pBuf, lenBuf, bFlush, strmPhysWrite); } else { return zlibw.doStrmWrite(pThis, pBuf, lenBuf, bFlush, strmPhysWrite); } } /* finish zlib buffer, to be called before closing the ZIP file (if * running in stream mode). */ static rsRetVal doZipFinish(strm_t *pThis) { if (pThis->compressionDriver == STRM_COMPRESS_ZSTD) { return zstdw.doCompressFinish(pThis, strmPhysWrite); } else { return zlibw.doCompressFinish(pThis, strmPhysWrite); } } /* flush stream output buffer to persistent storage. This can be called at any time * and is automatically called when the output buffer is full. * rgerhards, 2008-01-10 */ static rsRetVal strmFlushInternal(strm_t *pThis, int bFlushZip) { DEFiRet; assert(pThis != NULL); DBGOPRINT((obj_t *)pThis, "strmFlushinternal: file %d(%s) flush, buflen %ld%s\n", pThis->fd, getFileDebugName(pThis), (long)pThis->iBufPtr, (pThis->iBufPtr == 0) ? " (no need to flush)" : ""); if (pThis->tOperationsMode != STREAMMODE_READ && pThis->iBufPtr > 0) { iRet = strmSchedWrite(pThis, pThis->pIOBuf, pThis->iBufPtr, bFlushZip); } RETiRet; } /* flush stream output buffer to persistent storage. This can be called at any time * and is automatically called when the output buffer is full. This function is for * use by EXTERNAL callers. Do NOT use it internally. It locks the async writer * mutex if ther is need to do so. * rgerhards, 2010-03-18 */ static rsRetVal strmFlush(strm_t *pThis) { DEFiRet; assert(pThis != NULL); DBGOPRINT((obj_t *)pThis, "file %d strmFlush\n", pThis->fd); if (pThis->bAsyncWrite) d_pthread_mutex_lock(&pThis->mut); CHKiRet(strmFlushInternal(pThis, 1)); finalize_it: if (pThis->bAsyncWrite) d_pthread_mutex_unlock(&pThis->mut); RETiRet; } /* seek a stream to a specific location. Pending writes are flushed, read data * is invalidated. * rgerhards, 2008-01-12 */ static rsRetVal ATTR_NONNULL() strmSeek(strm_t *pThis, const off64_t offs) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); if (pThis->fd == -1) { CHKiRet(strmOpenFile(pThis)); } else { CHKiRet(strmFlushInternal(pThis, 0)); } DBGOPRINT((obj_t *)pThis, "file %d seek, pos %llu\n", pThis->fd, (long long unsigned)offs); const off64_t i = lseek64(pThis->fd, offs, SEEK_SET); if (i != offs) { LogError(errno, RS_RET_IO_ERROR, "file %s: unexpected error seeking to " "offset %lld (ret %lld) - further malfunctions may happen", pThis->pszCurrFName, (long long)i, (long long)offs); ABORT_FINALIZE(RS_RET_IO_ERROR); } pThis->strtOffs = pThis->iCurrOffs = offs; /* we are now at *this* offset */ pThis->iBufPtr = 0; /* buffer invalidated */ finalize_it: RETiRet; } /* multi-file seek, seeks to file number & offset within file. This * is a support function for the queue, in circular mode. DO NOT USE * IT FOR OTHER NEEDS - it may not work as expected. It will * seek to the new position and delete interim files, as it skips them. * Note: this code can be removed when the queue gets a new disk store * handler (if and when it does ;)). * The output parameter bytesDel receives the number of bytes that have * been deleted (if a file is deleted) or 0 if nothing was deleted. * rgerhards, 2012-11-07 */ rsRetVal strmMultiFileSeek(strm_t *pThis, unsigned int FNum, off64_t offs, off64_t *bytesDel) { struct stat statBuf; int skipped_files; off64_t deletedBytes; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); if (FNum == 0 && offs == 0) { /* happens during queue init */ *bytesDel = 0; FINALIZE; } skipped_files = FNum - pThis->iCurrFNum; *bytesDel = 0; while (skipped_files > 0) { CHKiRet(genFileName(&pThis->pszCurrFName, pThis->pszDir, pThis->lenDir, pThis->pszFName, pThis->lenFName, pThis->iCurrFNum, pThis->iFileNumDigits)); dbgprintf("rger: processing file %s\n", pThis->pszCurrFName); memset(&statBuf, 0, sizeof(statBuf)); deletedBytes = 0; if (stat((char *)pThis->pszCurrFName, &statBuf) != 0) { LogError(errno, RS_RET_IO_ERROR, "unexpected error doing a stat() " "on file %s - further malfunctions may happen", pThis->pszCurrFName); /* we do NOT error-terminate here as this could worsen the * situation. As such, we just keep running and try to delete * as many files as possible. */ } else { deletedBytes = statBuf.st_size; *bytesDel += deletedBytes; } DBGPRINTF( "strmMultiFileSeek: detected new filenum, was %u, new %u, " "deleting '%s' (%lld bytes)\n", pThis->iCurrFNum, FNum, pThis->pszCurrFName, (long long)deletedBytes); unlink((char *)pThis->pszCurrFName); if (pThis->cryprov != NULL) pThis->cryprov->DeleteStateFiles(pThis->pszCurrFName); free(pThis->pszCurrFName); pThis->pszCurrFName = NULL; pThis->iCurrFNum++; --skipped_files; } DBGOPRINT((obj_t *)pThis, "strmMultiFileSeek: deleted %lld bytes in this run\n", (long long)*bytesDel); pThis->strtOffs = pThis->iCurrOffs = offs; finalize_it: RETiRet; } /* seek to current offset. This is primarily a helper to readjust the OS file * pointer after a strm object has been deserialized. */ static rsRetVal strmSeekCurrOffs(strm_t *pThis) { off64_t targetOffs; uchar c; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); if (pThis->cryprov == NULL || pThis->tOperationsMode != STREAMMODE_READ) { iRet = strmSeek(pThis, pThis->iCurrOffs); FINALIZE; } /* As the cryprov may use CBC or similiar things, we need to read skip data */ targetOffs = pThis->iCurrOffs; pThis->strtOffs = pThis->iCurrOffs = 0; DBGOPRINT((obj_t *)pThis, "encrypted, doing skip read of %lld bytes\n", (long long)targetOffs); while (targetOffs != pThis->iCurrOffs) { CHKiRet(strmReadChar(pThis, &c)); } finalize_it: RETiRet; } /* write a *single* character to a stream object -- rgerhards, 2008-01-10 */ static rsRetVal strmWriteChar(strm_t *__restrict__ const pThis, const uchar c) { DEFiRet; assert(pThis != NULL); if (pThis->bAsyncWrite) d_pthread_mutex_lock(&pThis->mut); if (pThis->bDisabled) ABORT_FINALIZE(RS_RET_STREAM_DISABLED); /* if the buffer is full, we need to flush before we can write */ if (pThis->iBufPtr == pThis->sIOBufSize) { CHKiRet(strmFlushInternal(pThis, 0)); } /* we now always have space for one character, so we simply copy it */ *(pThis->pIOBuf + pThis->iBufPtr) = c; pThis->iBufPtr++; finalize_it: if (pThis->bAsyncWrite) d_pthread_mutex_unlock(&pThis->mut); RETiRet; } /* write an integer value (actually a long) to a stream object * Note that we do not need to lock the mutex here, because we call * strmWrite(), which does the lock (aka: we must not lock it, else we * would run into a recursive lock, resulting in a deadlock!) */ static rsRetVal strmWriteLong(strm_t *__restrict__ const pThis, const long i) { DEFiRet; uchar szBuf[32]; assert(pThis != NULL); CHKiRet(srUtilItoA((char *)szBuf, sizeof(szBuf), (number_t)i)); CHKiRet(strmWrite(pThis, szBuf, strlen((char *)szBuf))); finalize_it: RETiRet; } /* write memory buffer to a stream object. * process the data in chunks and copy it over to our buffer. The caller-provided data * may theoritically be larger than our buffer. In that case, we do multiple copies. One * may argue if it were more efficient to write out the caller-provided buffer in that case * and earlier versions of rsyslog did this. However, this introduces a lot of complexity * inside the buffered writer and potential performance bottlenecks when trying to solve * it. Now keep in mind that we actually do (almost?) never have a case where the * caller-provided buffer is larger than our one. So instead of optimizing a case * which normally does not exist, we expect some degradation in its case but make us * perform better in the regular cases. -- rgerhards, 2009-07-07 * Note: the pThis->iBufPtr == pThis->sIOBufSize logic below looks a bit like an * on-off error. In fact, it is not, because iBufPtr always points to the next * *free* byte in the buffer. So if it is sIOBufSize - 1, there actually is one * free byte left. This came up during a code walkthrough and was considered * worth nothing. -- rgerhards, 2010-03-10 */ static rsRetVal ATTR_NONNULL(1, 2) strmWrite(strm_t *__restrict__ const pThis, const uchar *__restrict__ const pBuf, size_t lenBuf) { DEFiRet; size_t iWrite; size_t iOffset; assert(pThis != NULL); assert(pBuf != NULL); if (pThis->bDisabled) ABORT_FINALIZE(RS_RET_STREAM_DISABLED); if (pThis->bAsyncWrite) d_pthread_mutex_lock(&pThis->mut); iOffset = 0; do { if (pThis->iBufPtr == pThis->sIOBufSize) { CHKiRet(strmFlushInternal(pThis, 0)); /* get a new buffer for rest of data */ } iWrite = pThis->sIOBufSize - pThis->iBufPtr; /* this fits in current buf */ if (iWrite > lenBuf) iWrite = lenBuf; memcpy(pThis->pIOBuf + pThis->iBufPtr, pBuf + iOffset, iWrite); pThis->iBufPtr += iWrite; iOffset += iWrite; lenBuf -= iWrite; } while (lenBuf > 0); /* now check if the buffer right at the end of the write is full and, if so, * write it. This seems more natural than waiting (hours?) for the next message... */ if (pThis->iBufPtr == pThis->sIOBufSize) { CHKiRet(strmFlushInternal(pThis, 0)); /* get a new buffer for rest of data */ } if (pThis->fd != -1 && pThis->iSizeLimit != 0) { /* Only check if fd already set */ CHKiRet(doSizeLimitProcessing(pThis)); } finalize_it: if (pThis->bAsyncWrite) { if (pThis->bDoTimedWait == 0) { /* we potentially have a partial buffer, so re-activate the * writer thread that it can set and pick up timeouts. */ pThis->bDoTimedWait = 1; pthread_cond_signal(&pThis->notEmpty); } d_pthread_mutex_unlock(&pThis->mut); } RETiRet; } /* property set methods */ /* simple ones first */ DEFpropSetMeth(strm, iMaxFileSize, int64) DEFpropSetMeth(strm, iFileNumDigits, int) DEFpropSetMeth(strm, tOperationsMode, int) DEFpropSetMeth(strm, tOpenMode, mode_t) DEFpropSetMeth(strm, bNoFollowFinal, int) DEFpropSetMeth(strm, compressionDriver, strm_compressionDriver_t) DEFpropSetMeth(strm, sType, strmType_t) DEFpropSetMeth(strm, iZipLevel, int) DEFpropSetMeth(strm, bVeryReliableZip, int) DEFpropSetMeth(strm, bSync, int) DEFpropSetMeth(strm, bReopenOnTruncate, int) DEFpropSetMeth(strm, sIOBufSize, size_t) DEFpropSetMeth(strm, iSizeLimit, off_t) DEFpropSetMeth(strm, iFlushInterval, int) DEFpropSetMeth(strm, pszSizeLimitCmd, uchar *) DEFpropSetMeth(strm, bSizeLimitCmdPassFileName, int) DEFpropSetMeth(strm, cryprov, cryprov_if_t *) DEFpropSetMeth(strm, cryprovData, void *) /* sets timeout in seconds */ void ATTR_NONNULL() strmSetReadTimeout(strm_t *const __restrict__ pThis, const int val) { ISOBJ_TYPE_assert(pThis, strm); pThis->readTimeout = val; } static rsRetVal ATTR_NONNULL() strmSetbDeleteOnClose(strm_t *const pThis, const int val) { ISOBJ_TYPE_assert(pThis, strm); pThis->bDeleteOnClose = val; if (pThis->cryprov != NULL) { pThis->cryprov->SetDeleteOnClose(pThis->cryprovFileData, pThis->bDeleteOnClose); } return RS_RET_OK; } static rsRetVal ATTR_NONNULL() strmSetiMaxFiles(strm_t *const pThis, const int iNewVal) { ISOBJ_TYPE_assert(pThis, strm); pThis->iMaxFiles = iNewVal; pThis->iFileNumDigits = getNumberDigits(iNewVal); return RS_RET_OK; } static rsRetVal ATTR_NONNULL() strmSetFileNotFoundError(strm_t *const pThis, const int pFileNotFoundError) { ISOBJ_TYPE_assert(pThis, strm); pThis->fileNotFoundError = pFileNotFoundError; return RS_RET_OK; } /* set the stream's file prefix * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. * rgerhards, 2008-01-09 */ static rsRetVal strmSetFName(strm_t *pThis, uchar *pszName, size_t iLenName) { DEFiRet; assert(pThis != NULL); assert(pszName != NULL); if (iLenName < 1) ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING); if (pThis->pszFName != NULL) free(pThis->pszFName); if ((pThis->pszFName = malloc(iLenName + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pszFName, pszName, iLenName + 1); /* always think about the \0! */ pThis->lenFName = iLenName; finalize_it: RETiRet; } /* set the stream's directory * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. * rgerhards, 2008-01-09 */ static rsRetVal strmSetDir(strm_t *pThis, uchar *pszDir, size_t iLenDir) { DEFiRet; assert(pThis != NULL); assert(pszDir != NULL); if (iLenDir < 1) ABORT_FINALIZE(RS_RET_FILE_PREFIX_MISSING); CHKmalloc(pThis->pszDir = malloc(iLenDir + 1)); memcpy(pThis->pszDir, pszDir, iLenDir + 1); /* always think about the \0! */ pThis->lenDir = iLenDir; finalize_it: RETiRet; } /* support for data records * The stream class is able to write to multiple files. However, there are * situation (actually quite common), where a single data record should not * be split across files. This may be problematic if multiple stream write * calls are used to create the record. To support that, we provide the * bInRecord status variable. If it is set, no file spliting occurs. Once * it is set to 0, a check is done if a split is necessary and it then * happens. For a record-oriented caller, the proper sequence is: * * strmRecordBegin() * strmWrite...() * strmRecordEnd() * * Please note that records do not affect the writing of output buffers. They * are always written when full. The only thing affected is circular files * creation. So it is safe to write large records. * * IMPORTANT: RecordBegin() can not be nested! It is a programming error * if RecordBegin() is called while already in a record! * * rgerhards, 2008-01-10 */ static rsRetVal strmRecordBegin(strm_t *pThis) { assert(pThis != NULL); assert(pThis->bInRecord == 0); pThis->bInRecord = 1; return RS_RET_OK; } static rsRetVal strmRecordEnd(strm_t *pThis) { DEFiRet; assert(pThis != NULL); assert(pThis->bInRecord == 1); pThis->bInRecord = 0; iRet = strmCheckNextOutputFile(pThis); /* check if we need to switch files */ RETiRet; } /* end stream record support functions */ /* This method serializes a stream object. That means the whole * object is modified into text form. That text form is suitable for * later reconstruction of the object. * The most common use case for this method is the creation of an * on-disk representation of the message object. * We do not serialize the dynamic properties. * rgerhards, 2008-01-10 */ static rsRetVal strmSerialize(strm_t *pThis, strm_t *pStrm) { DEFiRet; int i; int64 l; ISOBJ_TYPE_assert(pThis, strm); ISOBJ_TYPE_assert(pStrm, strm); strmFlushInternal(pThis, 0); CHKiRet(obj.BeginSerialize(pStrm, (obj_t *)pThis)); objSerializeSCALAR(pStrm, iCurrFNum, INT); /* implicit cast is OK for persistance */ objSerializePTR(pStrm, pszFName, PSZ); objSerializeSCALAR(pStrm, iMaxFiles, INT); objSerializeSCALAR(pStrm, bDeleteOnClose, INT); i = pThis->sType; objSerializeSCALAR_VAR(pStrm, sType, INT, i); i = pThis->tOperationsMode; objSerializeSCALAR_VAR(pStrm, tOperationsMode, INT, i); i = pThis->tOpenMode; objSerializeSCALAR_VAR(pStrm, tOpenMode, INT, i); l = pThis->iCurrOffs; objSerializeSCALAR_VAR(pStrm, iCurrOffs, INT64, l); l = pThis->inode; objSerializeSCALAR_VAR(pStrm, inode, INT64, l); l = pThis->strtOffs; objSerializeSCALAR_VAR(pStrm, strtOffs, INT64, l); dbgprintf("strmSerialize: pThis->prevLineSegment %p\n", pThis->prevLineSegment); if (pThis->prevLineSegment != NULL) { cstrFinalize(pThis->prevLineSegment); objSerializePTR(pStrm, prevLineSegment, CSTR); } if (pThis->prevMsgSegment != NULL) { cstrFinalize(pThis->prevMsgSegment); objSerializePTR(pStrm, prevMsgSegment, CSTR); } i = pThis->bPrevWasNL; objSerializeSCALAR_VAR(pStrm, bPrevWasNL, INT, i); CHKiRet(obj.EndSerialize(pStrm)); finalize_it: RETiRet; } /* duplicate a stream object excluding dynamic properties. This function is * primarily meant to provide a duplicate that later on can be used to access * the data. This is needed, for example, for a restart of the disk queue. * Note that ConstructFinalize() is NOT called. So our caller may change some * properties before finalizing things. * rgerhards, 2009-05-26 */ static rsRetVal strmDup(strm_t *const pThis, strm_t **ppNew) { strm_t *pNew = NULL; DEFiRet; ISOBJ_TYPE_assert(pThis, strm); assert(ppNew != NULL); CHKiRet(strmConstruct(&pNew)); pNew->sType = pThis->sType; pNew->iCurrFNum = pThis->iCurrFNum; CHKmalloc(pNew->pszFName = ustrdup(pThis->pszFName)); pNew->lenFName = pThis->lenFName; CHKmalloc(pNew->pszDir = ustrdup(pThis->pszDir)); pNew->lenDir = pThis->lenDir; pNew->tOperationsMode = pThis->tOperationsMode; pNew->tOpenMode = pThis->tOpenMode; pNew->bNoFollowFinal = pThis->bNoFollowFinal; pNew->compressionDriver = pThis->compressionDriver; pNew->iMaxFileSize = pThis->iMaxFileSize; pNew->iMaxFiles = pThis->iMaxFiles; pNew->iFileNumDigits = pThis->iFileNumDigits; pNew->bDeleteOnClose = pThis->bDeleteOnClose; pNew->iCurrOffs = pThis->iCurrOffs; *ppNew = pNew; pNew = NULL; finalize_it: if (pNew != NULL) strmDestruct(&pNew); RETiRet; } static rsRetVal SetCompressionWorkers(strm_t *const pThis, int num_wrkrs) { ISOBJ_TYPE_assert(pThis, strm); if (num_wrkrs < 0) num_wrkrs = 1; pThis->zstd.num_wrkrs = num_wrkrs; return RS_RET_OK; } /* set a user write-counter. This counter is initialized to zero and * receives the number of bytes written. It is accurate only after a * flush(). This hook is provided as a means to control disk size usage. * The pointer must be valid at all times (so if it is on the stack, be sure * to remove it when you exit the function). Pointers are removed by * calling strmSetWCntr() with a NULL param. Only one pointer is settable, * any new set overwrites the previous one. * rgerhards, 2008-02-27 */ static rsRetVal strmSetWCntr(strm_t *pThis, number_t *pWCnt) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); if (pWCnt != NULL) *pWCnt = 0; pThis->pUsrWCntr = pWCnt; RETiRet; } #include "stringbuf.h" /* This function can be used as a generic way to set properties. * rgerhards, 2008-01-11 */ #define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, UCHAR_CONSTANT(name), sizeof(name) - 1) static rsRetVal strmSetProperty(strm_t *pThis, var_t *pProp) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); assert(pProp != NULL); if (isProp("sType")) { CHKiRet(strmSetsType(pThis, (strmType_t)pProp->val.num)); } else if (isProp("iCurrFNum")) { pThis->iCurrFNum = (unsigned)pProp->val.num; } else if (isProp("pszFName")) { CHKiRet(strmSetFName(pThis, rsCStrGetSzStrNoNULL(pProp->val.pStr), rsCStrLen(pProp->val.pStr))); } else if (isProp("tOperationsMode")) { CHKiRet(strmSettOperationsMode(pThis, pProp->val.num)); } else if (isProp("tOpenMode")) { CHKiRet(strmSettOpenMode(pThis, pProp->val.num)); } else if (isProp("iCurrOffs")) { pThis->iCurrOffs = pProp->val.num; } else if (isProp("inode")) { pThis->inode = (ino_t)pProp->val.num; } else if (isProp("strtOffs")) { pThis->strtOffs = pProp->val.num; } else if (isProp("iMaxFileSize")) { CHKiRet(strmSetiMaxFileSize(pThis, pProp->val.num)); } else if (isProp("fileNotFoundError")) { CHKiRet(strmSetFileNotFoundError(pThis, pProp->val.num)); } else if (isProp("iMaxFiles")) { CHKiRet(strmSetiMaxFiles(pThis, pProp->val.num)); } else if (isProp("iFileNumDigits")) { CHKiRet(strmSetiFileNumDigits(pThis, pProp->val.num)); } else if (isProp("bDeleteOnClose")) { CHKiRet(strmSetbDeleteOnClose(pThis, pProp->val.num)); } else if (isProp("prevLineSegment")) { CHKiRet(rsCStrConstructFromCStr(&pThis->prevLineSegment, pProp->val.pStr)); } else if (isProp("prevMsgSegment")) { CHKiRet(rsCStrConstructFromCStr(&pThis->prevMsgSegment, pProp->val.pStr)); } else if (isProp("bPrevWasNL")) { pThis->bPrevWasNL = (sbool)pProp->val.num; } finalize_it: RETiRet; } #undef isProp /* return the current offset inside the stream. Note that on two consequtive calls, the offset * reported on the second call may actually be lower than on the first call. This is due to * file circulation. A caller must deal with that. -- rgerhards, 2008-01-30 */ static rsRetVal strmGetCurrOffset(strm_t *pThis, int64 *pOffs) { DEFiRet; ISOBJ_TYPE_assert(pThis, strm); assert(pOffs != NULL); *pOffs = pThis->iCurrOffs; RETiRet; } static rsRetVal strmSync(strm_t *pStrmDest, const strm_t *pStrmSrc) { DEFiRet; ISOBJ_TYPE_assert(pStrmDest, strm); ISOBJ_TYPE_assert(pStrmSrc, strm); pStrmDest->iCurrFNum = pStrmSrc->iCurrFNum; pStrmDest->iCurrOffs = pStrmSrc->iCurrOffs; pStrmDest->strtOffs = pStrmSrc->strtOffs; RETiRet; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(strm) CODESTARTobjQueryInterface(strm); if (pIf->ifVersion != strmCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = strmConstruct; pIf->ConstructFinalize = strmConstructFinalize; pIf->Destruct = strmDestruct; pIf->ReadChar = strmReadChar; pIf->UnreadChar = strmUnreadChar; pIf->ReadLine = strmReadLine; pIf->SeekCurrOffs = strmSeekCurrOffs; pIf->Write = strmWrite; pIf->WriteChar = strmWriteChar; pIf->WriteLong = strmWriteLong; pIf->SetFName = strmSetFName; pIf->SetFileNotFoundError = strmSetFileNotFoundError; pIf->SetDir = strmSetDir; pIf->Flush = strmFlush; pIf->RecordBegin = strmRecordBegin; pIf->RecordEnd = strmRecordEnd; pIf->Serialize = strmSerialize; pIf->GetCurrOffset = strmGetCurrOffset; pIf->Dup = strmDup; pIf->Sync = strmSync; pIf->SetCompressionWorkers = SetCompressionWorkers; pIf->SetWCntr = strmSetWCntr; pIf->CheckFileChange = CheckFileChange; /* set methods */ pIf->SetbDeleteOnClose = strmSetbDeleteOnClose; pIf->SetiMaxFileSize = strmSetiMaxFileSize; pIf->SetiMaxFiles = strmSetiMaxFiles; pIf->SetiFileNumDigits = strmSetiFileNumDigits; pIf->SettOperationsMode = strmSettOperationsMode; pIf->SettOpenMode = strmSettOpenMode; pIf->SetbNoFollowFinal = strmSetbNoFollowFinal; pIf->SetcompressionDriver = strmSetcompressionDriver; pIf->SetsType = strmSetsType; pIf->SetiZipLevel = strmSetiZipLevel; pIf->SetbVeryReliableZip = strmSetbVeryReliableZip; pIf->SetbSync = strmSetbSync; pIf->SetbReopenOnTruncate = strmSetbReopenOnTruncate; pIf->SetsIOBufSize = strmSetsIOBufSize; pIf->SetiSizeLimit = strmSetiSizeLimit; pIf->SetiFlushInterval = strmSetiFlushInterval; pIf->SetpszSizeLimitCmd = strmSetpszSizeLimitCmd; pIf->SetbSizeLimitCmdPassFileName = strmSetbSizeLimitCmdPassFileName; pIf->Setcryprov = strmSetcryprov; pIf->SetcryprovData = strmSetcryprovData; finalize_it: ENDobjQueryInterface(strm) /* Initialize the stream class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-01-09 */ BEGINObjClassInit(strm, 1, OBJ_IS_CORE_MODULE) /* request objects we use */ OBJSetMethodHandler(objMethod_SERIALIZE, strmSerialize); OBJSetMethodHandler(objMethod_SETPROPERTY, strmSetProperty); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, strmConstructFinalize); ENDObjClassInit(strm) rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_state.c0000644000000000000000000000013215241075234017222 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.415725446 rsyslog-8.2608.0/runtime/segdisk_state.c0000664000175000017500000001231615241075234016671 0ustar00rgerrger/* Fixed-size durable state codec for queue.type="segmentedDisk". */ #include "config.h" #include #include #include "segdisk_crc.h" #include "segdisk_format.h" #include "segdisk_state.h" #define STATE_MAGIC "RSSEGST2" static void put16(unsigned char *p, uint16_t v) { p[0] = (unsigned char)(v >> 8); p[1] = (unsigned char)v; } static void put32(unsigned char *p, uint32_t v) { p[0] = (unsigned char)(v >> 24); p[1] = (unsigned char)(v >> 16); p[2] = (unsigned char)(v >> 8); p[3] = (unsigned char)v; } static void put64(unsigned char *p, uint64_t v) { put32(p, (uint32_t)(v >> 32)); put32(p + 4, (uint32_t)v); } static uint16_t get16(const unsigned char *p) { return (uint16_t)(((uint16_t)p[0] << 8) | p[1]); } static uint32_t get32(const unsigned char *p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3]; } static uint64_t get64(const unsigned char *p) { return ((uint64_t)get32(p) << 32) | get32(p + 4); } void segdiskStateEncode(const segdisk_state_image_t *s, const uint64_t generation, unsigned char b[SEGDISK_STATE_SLOT_LEN]) { memset(b, 0, SEGDISK_STATE_SLOT_LEN); memcpy(b, STATE_MAGIC, 8); put16(b + 8, SEGDISK_STATE_STORE_VERSION); put16(b + 10, SEGDISK_CODEC_VERSION); memcpy(b + 12, s->uuid, sizeof(s->uuid)); put64(b + 28, generation); put32(b + 36, s->flags); put64(b + 40, s->committed_segment); put64(b + 48, (uint64_t)s->committed_offset); put64(b + 56, s->committed_record_sequence); put64(b + 64, s->first_live_segment); put64(b + 72, s->last_data_segment); put64(b + 80, s->active_segment); put64(b + 88, s->recovery_first); put64(b + 96, s->recovery_last); put64(b + 104, s->next_segment); put64(b + 112, s->known_queue_size); put64(b + 120, (uint64_t)s->bytes); put64(b + 128, s->segments); put64(b + 136, s->writer_segment); put64(b + 144, (uint64_t)s->writer_end); put64(b + 152, s->writer_sequence); put64(b + 160, s->writer_count); put64(b + 168, s->delete_first); put64(b + 176, s->delete_last); put64(b + 184, (uint64_t)s->delete_bytes); put64(b + 192, s->delete_segments); put32(b + SEGDISK_STATE_SLOT_LEN - 4, segdiskCrc32c(b, SEGDISK_STATE_SLOT_LEN - 4)); } sbool segdiskStateValidate(const unsigned char b[SEGDISK_STATE_SLOT_LEN]) { return !memcmp(b, STATE_MAGIC, 8) && get16(b + 8) == SEGDISK_STATE_STORE_VERSION && get16(b + 10) == SEGDISK_CODEC_VERSION && get32(b + SEGDISK_STATE_SLOT_LEN - 4) == segdiskCrc32c(b, SEGDISK_STATE_SLOT_LEN - 4); } void segdiskStateDecode(const unsigned char b[SEGDISK_STATE_SLOT_LEN], segdisk_state_image_t *s) { memset(s, 0, sizeof(*s)); memcpy(s->uuid, b + 12, sizeof(s->uuid)); s->generation = get64(b + 28); s->flags = get32(b + 36); s->committed_segment = get64(b + 40); s->committed_offset = (int64_t)get64(b + 48); s->committed_record_sequence = get64(b + 56); s->first_live_segment = get64(b + 64); s->last_data_segment = get64(b + 72); s->active_segment = get64(b + 80); s->recovery_first = get64(b + 88); s->recovery_last = get64(b + 96); s->next_segment = get64(b + 104); s->known_queue_size = get64(b + 112); s->bytes = (int64_t)get64(b + 120); s->segments = get64(b + 128); s->writer_segment = get64(b + 136); s->writer_end = (int64_t)get64(b + 144); s->writer_sequence = get64(b + 152); s->writer_count = get64(b + 160); s->delete_first = get64(b + 168); s->delete_last = get64(b + 176); s->delete_bytes = (int64_t)get64(b + 184); s->delete_segments = get64(b + 192); } sbool segdiskStateGenerationNewer(const uint64_t candidate, const uint64_t reference) { if (candidate == reference) return 0; const uint64_t distance = candidate > reference ? candidate - reference : UINT64_MAX - reference + candidate + 1; return distance < (UINT64_C(1) << 63); } rsRetVal segdiskStateSelect(const unsigned char slot0[SEGDISK_STATE_SLOT_LEN], const sbool present0, const unsigned char slot1[SEGDISK_STATE_SLOT_LEN], const sbool present1, segdisk_state_image_t *state, int *selected_slot) { const sbool valid0 = present0 && segdiskStateValidate(slot0); const sbool valid1 = present1 && segdiskStateValidate(slot1); if (!valid0 && !valid1) return RS_RET_INVALID_VALUE; if (valid0 && valid1 && memcmp(slot0 + 12, slot1 + 12, 16) != 0) return RS_RET_INVALID_VALUE; if (valid0 && valid1) { const uint64_t generation0 = get64(slot0 + 28); const uint64_t generation1 = get64(slot1 + 28); if (generation0 != generation1 && !segdiskStateGenerationNewer(generation0, generation1) && !segdiskStateGenerationNewer(generation1, generation0)) return RS_RET_INVALID_VALUE; } const int selected = valid1 && (!valid0 || segdiskStateGenerationNewer(get64(slot1 + 28), get64(slot0 + 28))) ? 1 : 0; segdiskStateDecode(selected == 0 ? slot0 : slot1, state); if (selected_slot != NULL) *selected_slot = selected; return RS_RET_OK; } rsyslog-8.2608.0/runtime/PaxHeaders/ratelimit.h0000644000000000000000000000013115241075234016367 xustar0029 mtime=1787067036.60857835 30 atime=1787067036.755581103 30 ctime=1787067794.442725949 rsyslog-8.2608.0/runtime/ratelimit.h0000664000175000017500000001606115241075234016040 0ustar00rgerrger/* header for ratelimit.c * * Copyright 2012-2025 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_RATELIMIT_H #define INCLUDED_RATELIMIT_H #include #include "rsyslog.h" #include "rswatch.h" #include "statsobj.h" struct hashtable; struct ratelimit_ps_entry_s; struct template; typedef struct statsobj_s statsobj_t; #define RATELIMIT_PERSOURCE_SHARDS 32 typedef struct ratelimit_ps_bucket_s { struct hashtable *ht; struct ratelimit_ps_entry_s *lru_head; struct ratelimit_ps_entry_s *lru_tail; unsigned int active_states; unsigned int max_states; sbool lock_initialized; pthread_mutex_t mut; } ratelimit_ps_bucket_t; enum ratelimit_ps_key_mode { RL_PS_KEY_TPL = 0, RL_PS_KEY_FROMHOST_IP, RL_PS_KEY_FROMHOST, RL_PS_KEY_FROMHOST_PORT, RL_PS_KEY_FROMHOST_IP_PORT, RL_PS_KEY_FROMHOST_NAME_PORT }; typedef enum ratelimit_scope_e { RATELIMIT_SCOPE_INPUT = 0, RATELIMIT_SCOPE_OUTPUT } ratelimit_scope_t; typedef enum ratelimit_output_mode_e { RATELIMIT_OUTPUT_MODE_DROP = 0, RATELIMIT_OUTPUT_MODE_PACE } ratelimit_output_mode_t; typedef struct ratelimit_shared_s { char *name; ratelimit_scope_t scope; ratelimit_output_mode_t output_mode; sbool output_pace_forbidden; unsigned int interval; unsigned int burst; int severity; char *policy_file; sbool policy_watch; unsigned int policy_watch_debounce_ms; rswatch_handle_t *policy_watch_handle; rswatch_handle_t *per_source_policy_watch_handle; pthread_mutex_t ref_mut; pthread_cond_t ref_cond; unsigned int refcnt; sbool ref_initialized; pthread_mutex_t mut; unsigned int per_source_enabled; sbool per_source_policy_from_policy_file; char *per_source_policy_file; unsigned int per_source_default_max; unsigned int per_source_default_window; unsigned int per_source_max_states; unsigned int per_source_topn; char *per_source_key_tpl_name; unsigned int per_source_key_policy_seq; unsigned int per_source_key_policy_bits; struct template *per_source_key_tpl; pthread_mutex_t per_source_key_policy_mut; pthread_mutex_t per_source_policy_mut; ratelimit_ps_bucket_t per_source_shards[RATELIMIT_PERSOURCE_SHARDS]; sbool per_source_shards_initialized; statsobj_t *per_source_stats; STATSCOUNTER_DEF(ctrPerSourceAllowed, mutCtrPerSourceAllowed); STATSCOUNTER_DEF(ctrPerSourceDropped, mutCtrPerSourceDropped); STATSCOUNTER_DEF(ctrPerSourceEvicted, mutCtrPerSourceEvicted); STATSCOUNTER_DEF(ctrPerSourceKeyTplEvals, mutCtrPerSourceKeyTplEvals); STATSCOUNTER_DEF(ctrPerSourceKeyParseEvals, mutCtrPerSourceKeyParseEvals); ctr_t **per_source_top_ctrs; intctr_t *per_source_top_values; char **per_source_top_keys; } ratelimit_shared_t; struct ratelimit_s { char *name; /**< rate limiter name, e.g. for user messages */ ratelimit_shared_t *pShared; sbool bOwnsShared; /**< if we own pShared (and need to free it) */ unsigned done; unsigned missed; time_t begin; /* support for "last message repeated n times */ unsigned nsupp; /**< nbr of msgs suppressed */ smsg_t *pMsg; sbool bThreadSafe; /**< do we need to operate in Thread-Safe mode? */ sbool bNoTimeCache; /**< if we shall not used cached reception time */ sbool bMutInitialized; /**< if mut has been initialized */ pthread_mutex_t mut; /**< mutex if thread-safe operation desired */ }; #define RATELIMIT_CFG_SHARDS 32 typedef struct ratelimit_cfg_bucket_s { struct hashtable *ht; sbool lock_initialized; pthread_rwlock_t lock; } ratelimit_cfg_bucket_t; typedef struct ratelimit_cfgs_s { ratelimit_cfg_bucket_t shards[RATELIMIT_CFG_SHARDS]; } ratelimit_cfgs_t; /* prototypes */ typedef struct rsconf_s rsconf_t; rsRetVal ratelimitNew(ratelimit_t **ppThis, const char *modname, const char *dynname); rsRetVal ratelimitNewFromConfig( ratelimit_t **ppThis, rsconf_t *conf, const char *configname, const char *modname, const char *dynname); rsRetVal ratelimitNewFromConfigForScope(ratelimit_t **ppThis, rsconf_t *conf, const char *configname, const char *modname, const char *dynname, ratelimit_scope_t scope); rsRetVal ratelimitAddConfig(rsconf_t *conf, const char *name, unsigned int interval, unsigned int burst, int severity, const char *policy_file, sbool policy_watch, const char *policy_watch_debounce, sbool per_source_enabled, const char *per_source_policy_file, const char *per_source_key_tpl_name, unsigned int per_source_max_states, unsigned int per_source_topn, sbool has_inline_policy_params, sbool has_legacy_per_source_params); rsRetVal ratelimit_cfgsInit(ratelimit_cfgs_t *cfgs); void ratelimit_cfgsDestruct(ratelimit_cfgs_t *cfgs); void ratelimitSetThreadSafe(ratelimit_t *ratelimit); void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned int interval, unsigned int burst); void ratelimitSetNoTimeCache(ratelimit_t *ratelimit); void ratelimitSetSeverity(ratelimit_t *ratelimit, int severity); rsRetVal ratelimitMsgCount(ratelimit_t *ratelimit, time_t tt, const char *const appname); rsRetVal ratelimitMsgCountWait(ratelimit_t *ratelimit, time_t tt, const char *const appname, unsigned int *const wait_usec); ratelimit_scope_t ratelimitGetScope(const ratelimit_t *ratelimit); ratelimit_output_mode_t ratelimitGetOutputMode(const ratelimit_t *ratelimit); void ratelimitForbidOutputPace(ratelimit_t *ratelimit); rsRetVal ATTR_NONNULL(1, 2, 3) ratelimitMsg(ratelimit_t *ratelimit, smsg_t *pMsg, smsg_t **ppRep); rsRetVal ATTR_NONNULL(1, 3) ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, smsg_t *pMsg); void ratelimitDestruct(ratelimit_t *pThis); int ratelimitChecked(ratelimit_t *ratelimit); rsRetVal ratelimitModInit(void); void ratelimitModExit(void); void ratelimitDoHUP(void); #endif /* #ifndef INCLUDED_RATELIMIT_H */ rsyslog-8.2608.0/runtime/PaxHeaders/gss-misc.c0000644000000000000000000000013215216464436016126 xustar0030 mtime=1782212894.022266119 30 atime=1782715518.782788738 30 ctime=1787067794.517727347 rsyslog-8.2608.0/runtime/gss-misc.c0000664000175000017500000002274515216464436015604 0ustar00rgerrger/* gss-misc.c * This is a miscellaneous helper class for gss-api features. * * Copyright 2007-2017 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dirty.h" #include "syslogd-types.h" #include "srUtils.h" #include "net.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" #include "gss-misc.h" #include "gss-token-util.h" #include "debug.h" #include "glbl.h" #include "unlimited_select.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) static void display_status_(char *m, OM_uint32 code, int type) { OM_uint32 maj_stat, min_stat, msg_ctx = 0; gss_buffer_desc msg; do { maj_stat = gss_display_status(&min_stat, code, type, GSS_C_NO_OID, &msg_ctx, &msg); if (maj_stat != GSS_S_COMPLETE) { LogError(0, NO_ERRCODE, "GSS-API error in gss_display_status called from <%s>\n", m); break; } else { char buf[1024]; snprintf(buf, sizeof(buf), "GSS-API error %s: %s\n", m, (char *)msg.value); buf[sizeof(buf) - 1] = '\0'; LogError(0, NO_ERRCODE, "%s", buf); } if (msg.length != 0) gss_release_buffer(&min_stat, &msg); } while (msg_ctx); } static void display_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) { display_status_(m, maj_stat, GSS_C_GSS_CODE); display_status_(m, min_stat, GSS_C_MECH_CODE); } static void display_ctx_flags(OM_uint32 flags) { if (flags & GSS_C_DELEG_FLAG) dbgprintf("GSS_C_DELEG_FLAG\n"); if (flags & GSS_C_MUTUAL_FLAG) dbgprintf("GSS_C_MUTUAL_FLAG\n"); if (flags & GSS_C_REPLAY_FLAG) dbgprintf("GSS_C_REPLAY_FLAG\n"); if (flags & GSS_C_SEQUENCE_FLAG) dbgprintf("GSS_C_SEQUENCE_FLAG\n"); if (flags & GSS_C_CONF_FLAG) dbgprintf("GSS_C_CONF_FLAG\n"); if (flags & GSS_C_INTEG_FLAG) dbgprintf("GSS_C_INTEG_FLAG\n"); } static ssize_t read_all(int fd, char *buf, size_t nbyte, time_t deadline) { ssize_t ret; char *ptr; struct timeval tv; struct timeval *ptv; #ifdef USE_UNLIMITED_SELECT fd_set *pRfds = malloc(glbl.GetFdSetSize()); if (pRfds == NULL) return -1; #else fd_set rfds; fd_set *pRfds = &rfds; #endif for (ptr = buf; nbyte;) { if (deadline != 0) { const time_t now = time(NULL); if (now == (time_t)-1 || now >= deadline) { errno = ETIMEDOUT; freeFdSet(pRfds); return -1; } tv.tv_sec = 1; tv.tv_usec = 0; ptv = &tv; } else { ptv = NULL; } FD_ZERO(pRfds); FD_SET(fd, pRfds); ret = select(fd + 1, pRfds, NULL, NULL, ptv); if (ret < 0) { if (errno == EINTR) continue; freeFdSet(pRfds); return ret; } if (ret == 0) continue; if (!FD_ISSET(fd, pRfds)) { errno = EIO; freeFdSet(pRfds); return -1; } ret = recv(fd, ptr, nbyte, 0); if (ret < 0) { if (errno == EINTR) continue; freeFdSet(pRfds); return (ret); } else if (ret == 0) { freeFdSet(pRfds); return (ptr - buf); } ptr += ret; nbyte -= ret; } freeFdSet(pRfds); return (ptr - buf); } static int write_all(int fd, char *buf, unsigned int nbyte) { int ret; char *ptr; for (ptr = buf; nbyte;) { ret = send(fd, ptr, nbyte, 0); if (ret < 0) { if (errno == EINTR) continue; return (ret); } else if (ret == 0) { return (ptr - buf); } ptr += ret; nbyte -= ret; } return (ptr - buf); } static int recv_token(int s, gss_buffer_t tok, size_t max_tok_len, unsigned int timeout_secs) { ssize_t ret; unsigned char lenbuf[4] = "xxx"; // initialized to make clang static analyzer happy size_t len = 0; time_t deadline = 0; assert(tok != NULL); tok->length = 0; tok->value = NULL; if (timeout_secs > 0) { deadline = time(NULL); if (deadline == (time_t)-1) { errno = EIO; LogError(errno, NO_ERRCODE, "GSS-API error obtaining current time for token deadline"); return -1; } deadline += timeout_secs; } ret = read_all(s, (char *)lenbuf, 4, deadline); if (ret < 0) { LogError(0, NO_ERRCODE, "GSS-API error reading token length"); return -1; } else if (!ret) { return 0; } else if (ret != 4) { LogError(0, NO_ERRCODE, "GSS-API error reading token length"); return -1; } if (gssTokenDecodeLength(lenbuf, max_tok_len, &len) != RS_RET_OK) { LogError(0, NO_ERRCODE, "GSS-API rejecting token length %zu that exceeds limit %zu", len, max_tok_len); return -1; } tok->length = len; tok->value = (char *)malloc(tok->length ? tok->length : 1); if (tok->length && tok->value == NULL) { LogError(0, NO_ERRCODE, "Out of memory allocating token data\n"); return -1; } ret = read_all(s, (char *)tok->value, tok->length, deadline); if (ret < 0) { LogError(0, NO_ERRCODE, "GSS-API error reading token data"); free(tok->value); return -1; } else if ((size_t)ret != tok->length) { LogError(0, NO_ERRCODE, "GSS-API error reading token data"); free(tok->value); return -1; } return 1; } static int send_token(int s, gss_buffer_t tok) { int ret; unsigned char lenbuf[4]; uint32_t len; if (tok->length > 0xffffffffUL) { LogError(0, NO_ERRCODE, "GSS-API token length %lu exceeds wire format limit", (unsigned long)tok->length); return -1; } len = (uint32_t)tok->length; lenbuf[0] = (len >> 24) & 0xff; lenbuf[1] = (len >> 16) & 0xff; lenbuf[2] = (len >> 8) & 0xff; lenbuf[3] = len & 0xff; ret = write_all(s, (char *)lenbuf, 4); if (ret < 0) { LogError(0, NO_ERRCODE, "GSS-API error sending token length"); return -1; } else if (ret != 4) { LogError(0, NO_ERRCODE, "GSS-API error sending token length"); return -1; } ret = write_all(s, tok->value, tok->length); if (ret < 0) { LogError(0, NO_ERRCODE, "GSS-API error sending token data"); return -1; } else if (ret != (int)tok->length) { LogError(0, NO_ERRCODE, "GSS-API error sending token data"); return -1; } return 0; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(gssutil) CODESTARTobjQueryInterface(gssutil); if (pIf->ifVersion != gssutilCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->recv_token = recv_token; pIf->send_token = send_token; pIf->display_status = display_status; pIf->display_ctx_flags = display_ctx_flags; finalize_it: ENDobjQueryInterface(gssutil) /* exit our class * rgerhards, 2008-03-10 */ BEGINObjClassExit(gssutil, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(gssutil); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(gssutil) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINAbstractObjClassInit(gssutil, 1, OBJ_IS_LOADABLE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDObjClassInit(gssutil) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; gssutilClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(gssutilClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/libcry_common.c0000644000000000000000000000013015216464436017233 xustar0028 mtime=1782212894.0272662 30 atime=1783339707.699804203 30 ctime=1787067794.222721849 rsyslog-8.2608.0/runtime/libcry_common.c0000664000175000017500000001167415216464436016712 0ustar00rgerrger/* libgcry_common.c * This file hosts functions both being used by the rsyslog runtime as * well as tools who do not use the runtime (so we can maintain the * code at a single place). * * Copyright 2013 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "rsyslog.h" /* we need data typedefs */ #include "libcry_common.h" /* read a key from a key file * @param[out] key - key buffer, must be freed by caller * @param[out] keylen - length of buffer * @returns 0 if OK, something else otherwise (we do not use * iRet as this is also called from non-rsyslog w/o runtime) * on error, errno is set and can be queried * The key length is limited to 64KiB to prevent DoS. * Note well: key is a blob, not a C string (NUL may be present!) */ int cryGetKeyFromFile(const char *const fn, char **const key, unsigned *const keylen) { struct stat sb; int r = -1; const int fd = open(fn, O_RDONLY); if (fd < 0) goto done; if (fstat(fd, &sb) == -1) goto done; if (sb.st_size > 64 * 1024) { errno = EMSGSIZE; goto done; } if (sb.st_size == 0) { errno = EINVAL; goto done; } if ((*key = malloc(sb.st_size)) == NULL) goto done; if (read(fd, *key, sb.st_size) != sb.st_size) goto done; *keylen = sb.st_size; r = 0; done: if (fd >= 0) { close(fd); } return r; } /* execute the child process (must be called in child context * after fork). */ static void execKeyScript(char *cmd, int pipefd[]) { char *newargv[] = {NULL}; char *newenviron[] = {NULL}; dup2(pipefd[0], STDIN_FILENO); dup2(pipefd[1], STDOUT_FILENO); /* finally exec child */ fprintf(stderr, "pre execve: %s\n", cmd); execve(cmd, newargv, newenviron); /* switch to? execlp((char*)program, (char*) program, (char*)arg, NULL); */ /* we should never reach this point, but if we do, we terminate */ return; } static int openPipe(char *cmd, int *fd) { int pipefd[2]; pid_t cpid; int r; if (pipe(pipefd) == -1) { r = 1; goto done; } cpid = fork(); if (cpid == -1) { r = 1; goto done; } if (cpid == 0) { /* we are the child */ execKeyScript(cmd, pipefd); exit(1); } close(pipefd[1]); *fd = pipefd[0]; r = 0; done: return r; } /* Read a character from the program's output. */ static int readProgChar(int fd, char *c) { int r; if (read(fd, c, 1) != 1) { r = 1; goto done; } r = 0; done: return r; } /* Read a line from the script. Line is terminated by LF, which * is NOT put into the buffer. * buf must be 64KiB */ static int readProgLine(int fd, char *buf) { char c; int r; unsigned i; for (i = 0; i < 64 * 1024; ++i) { if ((r = readProgChar(fd, &c)) != 0) goto done; if (c == '\n') break; buf[i] = c; }; if (i >= 64 * 1024) { r = 1; goto done; } buf[i] = '\0'; r = 0; done: return r; } static int readProgKey(int fd, char *buf, unsigned keylen) { char c; int r; unsigned i; for (i = 0; i < keylen; ++i) { if ((r = readProgChar(fd, &c)) != 0) goto done; buf[i] = c; }; r = 0; done: return r; } int cryGetKeyFromProg(char *cmd, char **key, unsigned *keylen) { int r; int fd; char rcvBuf[64 * 1024]; if ((r = openPipe(cmd, &fd)) != 0) goto done; if ((r = readProgLine(fd, rcvBuf)) != 0) goto done; if (strcmp(rcvBuf, "RSYSLOG-KEY-PROVIDER:0")) { r = 2; goto done; } if ((r = readProgLine(fd, rcvBuf)) != 0) goto done; char *endptr = NULL; errno = 0; const long val = strtol(rcvBuf, &endptr, 10); if (errno == ERANGE || endptr == rcvBuf || *endptr != '\0' || val <= 0 || val > 64 * 1024L) { errno = (errno == ERANGE || val > 64 * 1024L) ? EMSGSIZE : EINVAL; r = 3; goto done; } *keylen = (unsigned)val; if ((*key = malloc(*keylen)) == NULL) { r = -1; goto done; } if ((r = readProgKey(fd, *key, *keylen)) != 0) goto done; done: return r; } rsyslog-8.2608.0/runtime/PaxHeaders/sigprov.h0000644000000000000000000000013215132411300016052 xustar0030 mtime=1768559296.275885783 30 atime=1787067622.181515038 30 ctime=1787067794.268722707 rsyslog-8.2608.0/runtime/sigprov.h0000666000175000017500000000300415132411300015515 0ustar00rgerrger/* The interface definition for (file) signature providers. * * This is just an abstract driver interface, which needs to be * implemented by concrete classes. * * Copyright 2013 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_SIGPROV_H #define INCLUDED_SIGPROV_H /* interface */ BEGINinterface(sigprov) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(void *ppThis); rsRetVal (*SetCnfParam)(void *ppThis, struct nvlst *lst); rsRetVal (*Destruct)(void *ppThis); rsRetVal (*OnFileOpen)(void *pThis, uchar *fn, void *pFileInstData); rsRetVal (*OnRecordWrite)(void *pFileInstData, uchar *rec, rs_size_t lenRec); rsRetVal (*OnFileClose)(void *pFileInstData); ENDinterface(sigprov) #define sigprovCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ #endif /* #ifndef INCLUDED_SIGPROV_H */ rsyslog-8.2608.0/runtime/PaxHeaders/module-template.h0000644000000000000000000000013215171370365017501 xustar0030 mtime=1776677109.437913017 30 atime=1787067618.157440008 30 ctime=1787067794.260722558 rsyslog-8.2608.0/runtime/module-template.h0000664000175000017500000014604415171370365017156 0ustar00rgerrger/* module-template.h * This header contains macros that can be used to implement the * plumbing of modules. * * File begun on 2007-07-25 by RGerhards * * Copyright 2007-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MODULE_TEMPLATE_H_INCLUDED #define MODULE_TEMPLATE_H_INCLUDED 1 #include "modules.h" #include "obj.h" #include "objomsr.h" #include "threads.h" /* macro to define standard output-module static data members */ #define DEF_MOD_STATIC_DATA \ static __attribute__((unused)) rsRetVal (*omsdRegCFSLineHdlr)(uchar * pCmdName, int bChainingPermitted, \ ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), \ void *pData, void *pOwnerCookie) #define DEF_OMOD_STATIC_DATA \ DEF_MOD_STATIC_DATA; \ DEFobjCurrIf(obj) static __attribute__((unused)) int bCoreSupportsBatching; #define DEF_IMOD_STATIC_DATA \ DEF_MOD_STATIC_DATA; \ DEFobjCurrIf(obj) #define DEF_LMOD_STATIC_DATA DEF_MOD_STATIC_DATA #define DEF_PMOD_STATIC_DATA \ DEFobjCurrIf(obj); \ DEF_MOD_STATIC_DATA #define DEF_SMOD_STATIC_DATA \ DEFobjCurrIf(obj); \ DEF_MOD_STATIC_DATA #define DEF_FMOD_STATIC_DATA \ DEFobjCurrIf(obj); \ DEF_MOD_STATIC_DATA /* Macro to define the module type. Each module can only have a single type. If * a module provides multiple types, several separate modules must be created which * then should share a single library containing the majority of code. This macro * must be present in each module. -- rgerhards, 2007-12-14 * Note that MODULE_TYPE_TESTBENCH is reserved for testbenches, but * declared in their own header files (because the rest does not need these * defines). -- rgerhards, 2008-06-13 */ #define MODULE_TYPE(x) \ static rsRetVal modGetType(eModType_t *modType) { \ *modType = x; \ return RS_RET_OK; \ } #define MODULE_TYPE_INPUT MODULE_TYPE(eMOD_IN) #define MODULE_TYPE_OUTPUT MODULE_TYPE(eMOD_OUT) #define MODULE_TYPE_PARSER MODULE_TYPE(eMOD_PARSER) #define MODULE_TYPE_STRGEN MODULE_TYPE(eMOD_STRGEN) #define MODULE_TYPE_FUNCTION MODULE_TYPE(eMOD_FUNCTION) #define MODULE_TYPE_LIB \ DEF_LMOD_STATIC_DATA; \ MODULE_TYPE(eMOD_LIB) /* Macro to define whether the module should be kept dynamically linked. */ #define MODULE_KEEP_TYPE(x) \ static rsRetVal modGetKeepType(eModKeepType_t *modKeepType) { \ *modKeepType = x; \ return RS_RET_OK; \ } #define MODULE_TYPE_NOKEEP MODULE_KEEP_TYPE(eMOD_NOKEEP) #define MODULE_TYPE_KEEP MODULE_KEEP_TYPE(eMOD_KEEP) /* macro to define a unique module id. This must be able to fit in a void*. The * module id must be unique inside a running rsyslogd application. It is used to * track ownership of several objects. Most importantly, when the module is * unloaded the module id value is used to find what needs to be destroyed. * We currently use a pointer to modExit() as the module id. This sounds to be * reasonable save, as each module must have this entry point AND there is no valid * reason for twice this entry point being in memory. * rgerhards, 2007-11-21 */ #define STD_LOADABLE_MODULE_ID ((void *)modExit) /* macro to implement the "modGetID()" interface function * rgerhards 2007-11-21 */ #define DEFmodGetID \ static rsRetVal modGetID(void **pID) { \ *pID = STD_LOADABLE_MODULE_ID; \ return RS_RET_OK; \ } /* macro to provide the v6 config system module name */ #define MODULE_CNFNAME(name) \ static rsRetVal modGetCnfName(uchar **cnfName) { \ *cnfName = (uchar *)name; \ return RS_RET_OK; \ } /* to following macros are used to generate function headers and standard * functionality. It works as follows (described on the sample case of * createInstance()): * * BEGINcreateInstance * ... custom variable definitions (on stack) ... (if any) * CODESTARTcreateInstance * ... custom code ... (if any) * ENDcreateInstance */ /* createInstance() */ #define BEGINcreateInstance \ static rsRetVal createInstance(instanceData **ppData) { \ DEFiRet; /* store error code here */ \ instanceData *pData; /* use this to point to data elements */ #define CODESTARTcreateInstance \ if ((pData = calloc(1, sizeof(instanceData))) == NULL) { \ *ppData = NULL; \ return RS_RET_OUT_OF_MEMORY; \ } #define ENDcreateInstance \ *ppData = pData; \ RETiRet; \ } /* freeInstance() * This is the cleanup function for the module instance. It is called immediately before * the module instance is destroyed (unloaded). The module should do any cleanup * here, e.g. close file, free instantance heap memory and the like. Control will * not be passed back to the module once this function is finished. Keep in mind, * however, that other instances may still be loaded and used. So do not destroy * anything that may be used by another instance. If you have such a ressource, you * currently need to do the instance counting yourself. */ #define BEGINfreeInstance \ static rsRetVal freeInstance(void *pModData) { \ DEFiRet; \ instanceData *pData; #define CODESTARTfreeInstance pData = (instanceData *)pModData; #define ENDfreeInstance \ if (pData != NULL) free(pData); /* we need to free this in any case */ \ RETiRet; \ } /* createWrkrInstance() */ #define BEGINcreateWrkrInstance \ static rsRetVal createWrkrInstance(wrkrInstanceData_t **ppWrkrData, instanceData *pData) { \ DEFiRet; /* store error code here */ \ wrkrInstanceData_t *pWrkrData; /* use this to point to data elements */ #define CODESTARTcreateWrkrInstance \ if ((pWrkrData = calloc(1, sizeof(wrkrInstanceData_t))) == NULL) { \ *ppWrkrData = NULL; \ return RS_RET_OUT_OF_MEMORY; \ } \ pWrkrData->pData = pData; #define ENDcreateWrkrInstance \ *ppWrkrData = pWrkrData; \ RETiRet; \ } /* freeWrkrInstance */ #define BEGINfreeWrkrInstance \ static rsRetVal freeWrkrInstance(void *pd) { \ DEFiRet; \ wrkrInstanceData_t *pWrkrData; #define CODESTARTfreeWrkrInstance pWrkrData = (wrkrInstanceData_t *)pd; #define ENDfreeWrkrInstance \ if (pWrkrData != NULL) free(pWrkrData); /* we need to free this in any case */ \ RETiRet; \ } /* isCompatibleWithFeature() */ #define BEGINisCompatibleWithFeature \ static rsRetVal isCompatibleWithFeature(syslogFeature __attribute__((unused)) eFeat) { \ rsRetVal iRet = RS_RET_INCOMPATIBLE; #define CODESTARTisCompatibleWithFeature #define ENDisCompatibleWithFeature \ RETiRet; \ } /* beginTransaction() * introduced in v4.3.3 -- rgerhards, 2009-04-27 */ #define BEGINbeginTransaction \ static rsRetVal beginTransaction(wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ DEFiRet; #define CODESTARTbeginTransaction /* currently empty, but may be extended */ #define ENDbeginTransaction \ RETiRet; \ } /* commitTransaction() * Commits a transaction. Note that beginTransaction() must have been * called before this entry point. It receives the full batch of messages * to be processed in pParam parameter. * introduced in v8.1.3 -- rgerhards, 2013-12-04 */ #define BEGINcommitTransaction \ static rsRetVal commitTransaction(wrkrInstanceData_t __attribute__((unused)) *const pWrkrData, \ actWrkrIParams_t *const pParams, const unsigned nParams) { \ DEFiRet; #define CODESTARTcommitTransaction /* currently empty, but may be extended */ #define ENDcommitTransaction \ RETiRet; \ } /* endTransaction() * introduced in v4.3.3 -- rgerhards, 2009-04-27 */ #define BEGINendTransaction \ static rsRetVal endTransaction(wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ DEFiRet; #define CODESTARTendTransaction /* currently empty, but may be extended */ #define ENDendTransaction \ RETiRet; \ } /* doAction() */ #define BEGINdoAction \ static rsRetVal doAction(void *pMsgData, wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ uchar **ppString = (uchar **)pMsgData; \ DEFiRet; #define CODESTARTdoAction /* ppString may be NULL if the output module requested no strings */ #define ENDdoAction \ RETiRet; \ } /* setActionInfo() * Optional callback to provide the action object after creation. */ #define BEGINsetActionInfo \ static rsRetVal setActionInfo(void *const pModData, action_t *const pAction) { \ DEFiRet; \ instanceData *pData; #define CODESTARTsetActionInfo \ pData = (instanceData *)pModData; \ (void)pAction; \ (void)pData; #define ENDsetActionInfo \ RETiRet; \ } /* below is a variant of doAction where the passed-in data is not the common * case of string. */ #define BEGINdoAction_NoStrings \ static rsRetVal doAction(void *pMsgData, wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ DEFiRet; /* dbgPrintInstInfo() * Extra comments: * Print debug information about this instance. */ #define BEGINdbgPrintInstInfo \ static rsRetVal dbgPrintInstInfo(void *pModData) { \ DEFiRet; \ instanceData *pData = NULL; #define CODESTARTdbgPrintInstInfo \ pData = (instanceData *)pModData; \ (void)pData; /* prevent compiler warning if unused! */ #define ENDdbgPrintInstInfo \ RETiRet; \ } /* parseSelectorAct() * Extra comments: * try to process a selector action line. Checks if the action * applies to this module and, if so, processed it. If not, it * is left untouched. The driver will then call another module. * On exit, ppModData must point to instance data. Also, a string * request object must be created and filled. A macro is defined * for that. * For the most usual case, we have defined a macro below. * If more than one string is requested, the macro can be used together * with own code that overwrites the entry count. In this case, the * macro must come before the own code. It is recommended to be * placed right after CODESTARTparseSelectorAct. */ #define BEGINparseSelectorAct \ static rsRetVal parseSelectorAct(uchar **pp, void **ppModData, omodStringRequest_t **ppOMSR) { \ DEFiRet; \ uchar *p; \ instanceData *pData = NULL; #define CODESTARTparseSelectorAct \ assert(pp != NULL); \ assert(ppModData != NULL); \ assert(ppOMSR != NULL); \ p = *pp; #define CODE_STD_STRING_REQUESTparseSelectorAct(NumStrReqEntries) CHKiRet(OMSRconstruct(ppOMSR, NumStrReqEntries)); #define CODE_STD_FINALIZERparseSelectorAct \ finalize_it : ATTR_UNUSED; /* semi-colon needed according to gcc doc! */ \ if (iRet == RS_RET_OK || iRet == RS_RET_OK_WARN || iRet == RS_RET_SUSPENDED) { \ *ppModData = pData; \ *pp = p; \ } else { \ /* cleanup, we failed */ \ if (*ppOMSR != NULL) { \ OMSRdestruct(*ppOMSR); \ *ppOMSR = NULL; \ } \ if (pData != NULL) { \ freeInstance(pData); \ } \ } #define ENDparseSelectorAct \ RETiRet; \ } /* a special replacement macro for modules that do not support legacy config at all */ #define NO_LEGACY_CONF_parseSelectorAct \ static rsRetVal parseSelectorAct(uchar **pp ATTR_UNUSED, void **ppModData ATTR_UNUSED, \ omodStringRequest_t **ppOMSR ATTR_UNUSED) { \ return RS_RET_LEGA_ACT_NOT_SUPPORTED; \ } /* newActInst() * Extra comments: * This creates a new instance of a the action that implements the call. * This is part of the conf2 (rsyslog v6) config system. It is called by * the core when an action object has been obtained. The output module * must then verify parameters and create a new action instance (if * parameters are acceptable) or return an error code. * On exit, ppModData must point to instance data. Also, a string * request object must be created and filled. A macro is defined * for that. * For the most usual case, we have defined a macro below. * If more than one string is requested, the macro can be used together * with own code that overwrites the entry count. In this case, the * macro must come before the own code. It is recommended to be * placed right after CODESTARTnewActInst. */ #define BEGINnewActInst \ static rsRetVal newActInst(uchar __attribute__((unused)) * modName, struct nvlst __attribute__((unused)) * lst, \ void **ppModData, omodStringRequest_t **ppOMSR) { \ DEFiRet; \ instanceData *pData = NULL; \ *ppOMSR = NULL; #define CODESTARTnewActInst #define CODE_STD_STRING_REQUESTnewActInst(NumStrReqEntries) CHKiRet(OMSRconstruct(ppOMSR, NumStrReqEntries)) #define CODE_STD_FINALIZERnewActInst \ finalize_it : if (iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) { \ *ppModData = pData; \ } else { \ /* cleanup, we failed */ \ if (*ppOMSR != NULL) { \ OMSRdestruct(*ppOMSR); \ *ppOMSR = NULL; \ } \ if (pData != NULL) { \ freeInstance(pData); \ } \ } #define ENDnewActInst \ RETiRet; \ } /* newInpInst() * This is basically the equivalent to newActInst() for creating input * module (listener) instances. */ #define BEGINnewInpInst \ static rsRetVal newInpInst(struct nvlst *lst) { \ DEFiRet; #define CODESTARTnewInpInst #define CODE_STD_FINALIZERnewInpInst #define ENDnewInpInst \ RETiRet; \ } /* newParserInst() * This is basically the equivalent to newActInst() for creating parser * module (listener) instances. */ #define BEGINnewParserInst \ static rsRetVal newParserInst(struct nvlst *lst, void *pinst) { \ instanceConf_t *inst; \ DEFiRet; #define CODESTARTnewParserInst #define CODE_STD_FINALIZERnewParserInst #define ENDnewParserInst \ if (iRet == RS_RET_OK) *((instanceConf_t **)pinst) = inst; \ RETiRet; \ } /* freeParserInst */ #define BEGINfreeParserInst \ static rsRetVal freeParserInst(void *pi) { \ DEFiRet; \ instanceConf_t *pInst; #define CODESTARTfreeParserInst pInst = (instanceConf_t *)pi; #define ENDfreeParserInst \ if (pInst != NULL) free(pInst); \ RETiRet; \ } /* tryResume() * This entry point is called to check if a module can resume operations. This * happens when a module requested that it be suspended. In suspended state, * the engine periodically tries to resume the module. If that succeeds, normal * processing continues. If not, the module will not be called unless a * tryResume() call succeeds. * Returns RS_RET_OK, if resumption succeeded, RS_RET_SUSPENDED otherwise * rgerhard, 2007-08-02 */ #define BEGINtryResume \ static rsRetVal tryResume(wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ DEFiRet; #define CODESTARTtryResume assert(pWrkrData != NULL); #define ENDtryResume \ RETiRet; \ } /* initConfVars() - initialize pre-v6.3-config variables */ #define BEGINinitConfVars \ static rsRetVal initConfVars(void) { \ DEFiRet; #define CODESTARTinitConfVars #define ENDinitConfVars \ RETiRet; \ } /* queryEtryPt() */ #define BEGINqueryEtryPt \ DEFmodGetID static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)()) { \ DEFiRet; #define CODESTARTqueryEtryPt \ if ((name == NULL) || (pEtryPoint == NULL)) { \ return RS_RET_PARAM_ERROR; \ } \ *pEtryPoint = NULL; #define ENDqueryEtryPt \ if (iRet == RS_RET_OK) \ if (*pEtryPoint == NULL) { \ dbgprintf("entry point '%s' not present in module\n", name); \ iRet = RS_RET_MODULE_ENTRY_POINT_NOT_FOUND; \ } \ RETiRet; \ } /** \addtogroup module_entrypoint_blocks * \{ * \brief Standard queryEtryPt block for all module types. * * Must be included in every module. This defines default queries * like `modExit`, `modGetID`, etc. */ #define CODEqueryEtryPt_STD_MOD_QUERIES \ if (!strcmp((char *)name, "modExit")) { \ *pEtryPoint = modExit; \ } \ if (!strcmp((char *)name, "modGetID")) { \ *pEtryPoint = modGetID; \ } \ if (!strcmp((char *)name, "getType")) { \ *pEtryPoint = modGetType; \ } \ if (!strcmp((char *)name, "getKeepType")) { \ *pEtryPoint = modGetKeepType; \ } /** * \brief Standard block for output modules without transaction support. */ #define CODEqueryEtryPt_STD_OMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "doAction")) { \ *pEtryPoint = doAction; \ } \ if (!strcmp((char *)name, "dbgPrintInstInfo")) { \ *pEtryPoint = dbgPrintInstInfo; \ } \ if (!strcmp((char *)name, "freeInstance")) { \ *pEtryPoint = freeInstance; \ } \ if (!strcmp((char *)name, "parseSelectorAct")) { \ *pEtryPoint = parseSelectorAct; \ } \ if (!strcmp((char *)name, "isCompatibleWithFeature")) { \ *pEtryPoint = isCompatibleWithFeature; \ } \ if (!strcmp((char *)name, "tryResume")) { \ *pEtryPoint = tryResume; \ } /** * \brief Standard block for output modules using the transaction interface. */ #define CODEqueryEtryPt_STD_OMODTX_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "beginTransaction")) { \ *pEtryPoint = beginTransaction; \ } \ if (!strcmp((char *)name, "commitTransaction")) { \ *pEtryPoint = commitTransaction; \ } \ if (!strcmp((char *)name, "dbgPrintInstInfo")) { \ *pEtryPoint = dbgPrintInstInfo; \ } \ if (!strcmp((char *)name, "freeInstance")) { \ *pEtryPoint = freeInstance; \ } \ if (!strcmp((char *)name, "parseSelectorAct")) { \ *pEtryPoint = parseSelectorAct; \ } \ if (!strcmp((char *)name, "isCompatibleWithFeature")) { \ *pEtryPoint = isCompatibleWithFeature; \ } \ if (!strcmp((char *)name, "tryResume")) { \ *pEtryPoint = tryResume; \ } /** * \brief Additional methods for output module v8+ support. */ #define CODEqueryEtryPt_STD_OMOD8_QUERIES \ if (!strcmp((char *)name, "createWrkrInstance")) { \ *pEtryPoint = createWrkrInstance; \ } \ if (!strcmp((char *)name, "freeWrkrInstance")) { \ *pEtryPoint = freeWrkrInstance; \ } /** * \brief For output modules with transaction interface extension. */ #define CODEqueryEtryPt_TXIF_OMOD_QUERIES \ if (!strcmp((char *)name, "beginTransaction")) { \ *pEtryPoint = beginTransaction; \ } \ if (!strcmp((char *)name, "endTransaction")) { \ *pEtryPoint = endTransaction; \ } /** * \brief Optional support for feature compatibility query. */ #define CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES \ if (!strcmp((char *)name, "isCompatibleWithFeature")) { \ *pEtryPoint = isCompatibleWithFeature; \ } #define CODEqueryEtryPt_SetActionInfo_IF_OMOD_QUERIES \ if (!strcmp((char *)name, "setActionInfo")) { \ *pEtryPoint = setActionInfo; \ } /** * \brief Standard block for input modules. */ #define CODEqueryEtryPt_STD_IMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "runInput")) { \ *pEtryPoint = runInput; \ } \ if (!strcmp((char *)name, "willRun")) { \ *pEtryPoint = willRun; \ } \ if (!strcmp((char *)name, "afterRun")) { \ *pEtryPoint = afterRun; \ } /** * \brief For modules using the config interface v2. */ #define CODEqueryEtryPt_STD_CONF2_QUERIES \ if (!strcmp((char *)name, "beginCnfLoad")) { \ *pEtryPoint = beginCnfLoad; \ } \ if (!strcmp((char *)name, "endCnfLoad")) { \ *pEtryPoint = endCnfLoad; \ } \ if (!strcmp((char *)name, "checkCnf")) { \ *pEtryPoint = checkCnf; \ } \ if (!strcmp((char *)name, "activateCnf")) { \ *pEtryPoint = activateCnf; \ } \ if (!strcmp((char *)name, "freeCnf")) { \ *pEtryPoint = freeCnf; \ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES #define CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES \ if (!strcmp((char *)name, "setModCnf")) { \ *pEtryPoint = setModCnf; \ } #define CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES \ if (!strcmp((char *)name, "newActInst")) { \ *pEtryPoint = newActInst; \ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES #define CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES \ if (!strcmp((char *)name, "newInpInst")) { \ *pEtryPoint = newInpInst; \ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES #define CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES \ if (!strcmp((char *)name, "activateCnfPrePrivDrop")) { \ *pEtryPoint = activateCnfPrePrivDrop; \ } /** * \brief Config interface v6 module name support. */ #define CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES \ if (!strcmp((char *)name, "getModCnfName")) { \ *pEtryPoint = modGetCnfName; \ } /** * \brief Standard block for library modules. */ #define CODEqueryEtryPt_STD_LIB_QUERIES CODEqueryEtryPt_STD_MOD_QUERIES /** * \brief Standard block for parser modules. */ #define CODEqueryEtryPt_STD_PMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "parse")) { \ *pEtryPoint = parse; \ } \ if (!strcmp((char *)name, "GetParserName")) { \ *pEtryPoint = GetParserName; \ } /** * \brief Standard block for parser modules using config v2. */ #define CODEqueryEtryPt_STD_PMOD2_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "parse2")) { \ *pEtryPoint = parse2; \ } \ if (!strcmp((char *)name, "GetParserName")) { \ *pEtryPoint = GetParserName; \ } \ if (!strcmp((char *)name, "newParserInst")) { \ *pEtryPoint = newParserInst; \ } \ if (!strcmp((char *)name, "checkParserInst")) { \ *pEtryPoint = checkParserInst; \ } \ if (!strcmp((char *)name, "freeParserInst")) { \ *pEtryPoint = freeParserInst; \ } \ CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES /** * \brief Standard block for rscript function modules. */ #define CODEqueryEtryPt_STD_FMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "getFunctArray")) { \ *pEtryPoint = getFunctArray; \ } /** * \brief Standard block for strgen modules. */ #define CODEqueryEtryPt_STD_SMOD_QUERIES \ CODEqueryEtryPt_STD_MOD_QUERIES if (!strcmp((char *)name, "strgen")) { \ *pEtryPoint = strgen; \ } \ if (!strcmp((char *)name, "GetName")) { \ *pEtryPoint = GetStrgenName; \ } /** \} */ // end of module_entrypoint_blocks /* modInit() * This has an extra parameter, which is the specific name of the modInit * function. That is needed for built-in modules, which must have unique * names in order to link statically. Please note that this is always only * the case with modInit() and NO other entry point. The reason is that only * modInit() is visible form a linker/loader point of view. All other entry * points are passed via rsyslog-internal query functions and are defined * static inside the modules source. This is an important concept, as it allows * us to support different interface versions within a single module. (Granted, * we do not currently have different interface versions, so we can not put * it to a test - but our firm believe is that we can do all abstraction needed...) * * Extra Comments: * initialize the module * * Later, much more must be done. So far, we only return a pointer * to the queryEtryPt() function * TODO: do interface version checking & handshaking * iIfVersRequetsed is the version of the interface specification that the * caller would like to see being used. ipIFVersProvided is what we * decide to provide. * rgerhards, 2007-11-21: see modExit() comment below for important information * on the need to initialize static data with code. modInit() may be called on a * cached, left-in-memory copy of a previous incarnation. */ #define BEGINmodInit(uniqName) \ rsRetVal __attribute__((unused)) modInit##uniqName( \ int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), \ rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal(**)()), modInfo_t __attribute__((unused)) * pModInfo); \ rsRetVal __attribute__((unused)) modInit##uniqName( \ int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), \ rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal(**)()), modInfo_t __attribute__((unused)) * pModInfo) { \ DEFiRet; \ rsRetVal (*pObjGetObjInterface)(obj_if_t * pIf); /* * Variant for modules that already publish modInit prototypes in headers. * This avoids duplicate declarations while preserving missing-prototype * coverage for modules that still rely on BEGINmodInit's local predecl. */ #define BEGINmodInitNoPredecl(uniqName) \ rsRetVal __attribute__((unused)) modInit##uniqName( \ int iIFVersRequested __attribute__((unused)), int *ipIFVersProvided, rsRetVal (**pQueryEtryPt)(), \ rsRetVal (*pHostQueryEtryPt)(uchar *, rsRetVal(**)()), modInfo_t __attribute__((unused)) * pModInfo) { \ DEFiRet; \ rsRetVal (*pObjGetObjInterface)(obj_if_t * pIf); #define CODESTARTmodInit \ assert(pHostQueryEtryPt != NULL); \ iRet = pHostQueryEtryPt((uchar *)"objGetObjInterface", &pObjGetObjInterface); \ if ((iRet != RS_RET_OK) || (pQueryEtryPt == NULL) || (ipIFVersProvided == NULL) || \ (pObjGetObjInterface == NULL)) { \ return (iRet == RS_RET_OK) ? RS_RET_PARAM_ERROR : iRet; \ } \ /* now get the obj interface so that we can access other objects */ \ CHKiRet(pObjGetObjInterface(&obj)) /* do those initializations necessary for legacy config variables */ #define INITLegCnfVars initConfVars() #define ENDmodInit \ finalize_it : *pQueryEtryPt = queryEtryPt; \ RETiRet; \ } /* now come some check functions, which enable a standard way of obtaining feature * information from the core. feat is the to-be-tested feature and featVar is a * variable that receives the result (0-not support, 1-supported). * This must be a macro, so that it is put into the output's code. Otherwise, we * would need to rely on a library entry point, which is what we intend to avoid ;) * rgerhards, 2009-04-27 */ #define INITChkCoreFeature(featVar, feat) \ { \ rsRetVal MACRO_Ret; \ rsRetVal (*pQueryCoreFeatureSupport)(int *, unsigned); \ int bSupportsIt; \ featVar = 0; \ MACRO_Ret = pHostQueryEtryPt((uchar *)"queryCoreFeatureSupport", &pQueryCoreFeatureSupport); \ if (MACRO_Ret == RS_RET_OK) { \ /* found entry point, so let's see if core supports it */ \ CHKiRet((*pQueryCoreFeatureSupport)(&bSupportsIt, feat)); \ if (bSupportsIt) featVar = 1; \ } else if (MACRO_Ret != RS_RET_ENTRY_POINT_NOT_FOUND) { \ ABORT_FINALIZE(MACRO_Ret); /* Something else went wrong, what is not acceptable */ \ } \ } /* definitions for host API queries */ #define CODEmodInit_QueryRegCFSLineHdlr CHKiRet(pHostQueryEtryPt((uchar *)"regCfSysLineHdlr", &omsdRegCFSLineHdlr)); /* modExit() * This is the counterpart to modInit(). It destroys a module and makes it ready for * unloading. It is similiar to freeInstance() for the instance data. Please note that * this entry point needs to free any module-global data structures and registrations. * For example, the CfSysLineHandlers a module has registered need to be unregistered * here. This entry point is only called immediately before unloading of the module. So * it is likely to be destroyed. HOWEVER, the caller may decide to keep the module cached. * So a module must never assume that it is actually destroyed. A call to modInit() may * happen immediately after modExit(). So a module can NOT assume that static data elements * are being re-initialized by the loader - this must always be done by module code itself. * It is suggested to do this in modInit(). - rgerhards, 2007-11-21 */ #define BEGINmodExit \ static rsRetVal modExit(void) { \ DEFiRet; #define CODESTARTmodExit #define ENDmodExit \ RETiRet; \ } /* beginCnfLoad() * This is a function tells an input module that a new config load begins. * The core passes in a handle to the new module-specific module conf to * the module. -- rgerards, 2011-05-03 */ #define BEGINbeginCnfLoad \ static rsRetVal beginCnfLoad(modConfData_t **ptr, __attribute__((unused)) rsconf_t *pConf) { \ modConfData_t *pModConf; \ DEFiRet; #define CODESTARTbeginCnfLoad \ if ((pModConf = calloc(1, sizeof(modConfData_t))) == NULL) { \ *ptr = NULL; \ return RS_RET_OUT_OF_MEMORY; \ } #define ENDbeginCnfLoad \ *ptr = pModConf; \ RETiRet; \ } /* setModCnf() * This function permits to set module global parameters via the v2 config * interface. It may be called multiple times, but parameters must not be * set in a conflicting way. The module must use its current config load * context when processing the directives. * Note that lst may be NULL, especially if the module is loaded via the * legacy config system. The module must check for this. * NOTE: This entry point must only be implemented if module global * parameters are actually required. */ #define BEGINsetModCnf \ static rsRetVal setModCnf(struct nvlst *lst) { \ DEFiRet; #define CODESTARTsetModCnf #define ENDsetModCnf \ RETiRet; \ } /* endCnfLoad() * This is a function tells an input module that the current config load ended. * It gets a last chance to make changes to its in-memory config object. After * this call, the config object must no longer be changed. * The pModConf pointer passed into the module must no longer be used. * rgerards, 2011-05-03 */ #define BEGINendCnfLoad \ static rsRetVal endCnfLoad(modConfData_t *ptr) { \ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t *)ptr; \ DEFiRet; #define CODESTARTendCnfLoad #define ENDendCnfLoad \ RETiRet; \ } /* checkCnf() * Check the provided config object for errors, inconsistencies and other things * that do not work out. * NOTE: no part of the config must be activated, so some checks that require * activation can not be done in this entry point. They must be done in the * activateConf() stage, where the caller must also be prepared for error * returns. * rgerhards, 2011-05-03 */ #define BEGINcheckCnf \ static rsRetVal checkCnf(modConfData_t *ptr) { \ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t *)ptr; \ DEFiRet; #define CODESTARTcheckCnf #define ENDcheckCnf \ RETiRet; \ } /* checkParserInst() - verifies a parser instance configuration */ #define BEGINcheckParserInst \ static rsRetVal checkParserInst(void *const ptr) { \ instanceConf_t __attribute__((unused)) *pInst = (instanceConf_t *)ptr; \ DEFiRet; #define CODESTARTcheckParserInst #define ENDcheckParserInst \ RETiRet; \ } /* activateCnfPrePrivDrop() * Initial config activation, before dropping privileges. This is an optional * entry points that should only be implemented by those module that really need * it. Processing should be limited to the minimum possible. Main activation * should happen in the normal activateCnf() call. * rgerhards, 2011-05-06 */ #define BEGINactivateCnfPrePrivDrop \ static rsRetVal activateCnfPrePrivDrop(modConfData_t *ptr) { \ modConfData_t *pModConf = (modConfData_t *)ptr; \ DEFiRet; #define CODESTARTactivateCnfPrePrivDrop #define ENDactivateCnfPrePrivDrop \ RETiRet; \ } /* activateCnf() * This activates the provided config, and may report errors if they are detected * during activation. * rgerhards, 2011-05-03 */ #define BEGINactivateCnf \ static rsRetVal activateCnf(modConfData_t *ptr) { \ modConfData_t __attribute__((unused)) *pModConf = (modConfData_t *)ptr; \ DEFiRet; #define CODESTARTactivateCnf #define ENDactivateCnf \ RETiRet; \ } /* freeCnf() * This is a function tells an input module that it must free all data * associated with the passed-in module config. * rgerhards, 2011-05-03 */ #define BEGINfreeCnf \ static rsRetVal freeCnf(void *ptr) { \ modConfData_t *pModConf = (modConfData_t *)ptr; \ DEFiRet; #define CODESTARTfreeCnf #define ENDfreeCnf \ if (pModConf != NULL) free(pModConf); /* we need to free this in any case */ \ RETiRet; \ } /* runInput() * This is the main function for input modules. It is used to gather data from the * input source and submit it to the message queue. Each runInput() instance has its own * thread. This is handled by the rsyslog engine. It needs to spawn off new threads only * if there is a module-internal need to do so. */ #define BEGINrunInput \ static rsRetVal runInput(thrdInfo_t __attribute__((unused)) * pThrd) { \ DEFiRet; #define CODESTARTrunInput dbgSetThrdName((uchar *)__FILE__); /* we need to provide something better later */ #define ENDrunInput \ RETiRet; \ } /* willRun() * This is a function that will be replaced in the longer term. It is used so * that a module can tell the caller if it will run or not. This is to be replaced * when we introduce input module instances. However, these require config syntax * changes and I may (or may not... ;)) hold that until another config file * format is available. -- rgerhards, 2007-12-17 * returns RS_RET_NO_RUN if it will not run (RS_RET_OK or error otherwise) */ #define BEGINwillRun \ static rsRetVal willRun(void) { \ DEFiRet; #define CODESTARTwillRun #define ENDwillRun \ RETiRet; \ } /* afterRun() * This function is called after an input module has been run and its thread has * been terminated. It shall do any necessary cleanup. * This is expected to evolve into a freeInstance type of call once the input module * interface evolves to support multiple instances. * rgerhards, 2007-12-17 */ #define BEGINafterRun \ static rsRetVal afterRun(void) { \ DEFiRet; #define CODESTARTafterRun #define ENDafterRun \ RETiRet; \ } /* doHUP() * This function is optional. Currently, it is available to output plugins * only, but may be made available to other types of plugins in the future. * A plugin does not need to define this entry point. If if does, it gets * called when a HUP at the action level is to be done. A plugin should register * this function so that it can close files, connection or other resources * on HUP - if it can be assume the user wanted to do this as a part of HUP * processing. Note that the name "HUP" has historical reasons, it stems back * to the infamous SIGHUP which was sent to restart a syslogd. We still retain * that legacy, but may move this to a different signal. * rgerhards, 2008-10-22 */ #define CODEqueryEtryPt_doHUP \ if (!strcmp((char *)name, "doHUP")) { \ *pEtryPoint = doHUP; \ } #define BEGINdoHUP \ static rsRetVal doHUP(instanceData __attribute__((unused)) * pData) { \ DEFiRet; #define CODESTARTdoHUP #define ENDdoHUP \ RETiRet; \ } /* doHUPParser() */ #define CODEqueryEtryPt_doHUPParser \ if (!strcmp((char *)name, "doHUP")) { \ *pEtryPoint = doHUP; \ } #define BEGINdoHUPParser \ static rsRetVal doHUP(instanceConf_t __attribute__((unused)) * pData) { \ DEFiRet; #define CODESTARTdoHUPParser #define ENDdoHUPParser \ RETiRet; \ } /* doHUPWrkr() * This is like doHUP(), but on an action worker level. * rgerhards, 2015-03-25 */ #define CODEqueryEtryPt_doHUPWrkr \ if (!strcmp((char *)name, "doHUPWrkr")) { \ *pEtryPoint = doHUPWrkr; \ } #define BEGINdoHUPWrkr \ static rsRetVal doHUPWrkr(wrkrInstanceData_t __attribute__((unused)) * pWrkrData) { \ DEFiRet; #define CODESTARTdoHUPWrkr #define ENDdoHUPWrkr \ RETiRet; \ } /* SetShutdownImmdtPtr() * This function is optional. If defined by an output plugin, it is called * each time the action is invoked to set the "ShutdownImmediate" pointer, * which is used during termination to indicate the action should shutdown * as quickly as possible. */ #define CODEqueryEtryPt_SetShutdownImmdtPtr \ else if (!strcmp((char *)name, "SetShutdownImmdtPtr")) { \ *pEtryPoint = SetShutdownImmdtPtr; \ } #define BEGINSetShutdownImmdtPtr \ static rsRetVal SetShutdownImmdtPtr(instanceData __attribute__((unused)) * pData, int *pPtr) { \ DEFiRet; #define CODESTARTSetShutdownImmdtPtr #define ENDSetShutdownImmdtPtr \ RETiRet; \ } /* parse() - main entry point of parser modules (v1 config interface) */ #define BEGINparse \ static rsRetVal parse(smsg_t *pMsg) { \ DEFiRet; #define CODESTARTparse assert(pMsg != NULL); #define ENDparse \ RETiRet; \ } /* parse2() - main entry point of parser modules (v2+ config interface) */ #define BEGINparse2 \ static rsRetVal parse2(instanceConf_t *const pInst, smsg_t *pMsg) { \ DEFiRet; #define CODESTARTparse2 \ assert(pInst != NULL); \ assert(pMsg != NULL); #define ENDparse2 \ RETiRet; \ } /* strgen() - main entry point of parser modules * Note that we do NOT use size_t as this permits us to store the * values directly into optimized heap structures. * ppBuf is the buffer pointer * pLenBuf is the current max size of this buffer * pStrLen is an output parameter that MUST hold the length * of the generated string on exit (this is cached) */ #define BEGINstrgen \ static rsRetVal strgen(smsg_t *const pMsg, actWrkrIParams_t *const iparam) { \ DEFiRet; #define CODESTARTstrgen assert(pMsg != NULL); #define ENDstrgen \ RETiRet; \ } /* getFunctArray() - main entry point of parser modules * Note that we do NOT use size_t as this permits us to store the * values directly into optimized heap structures. * ppBuf is the buffer pointer * pLenBuf is the current max size of this buffer * pStrLen is an output parameter that MUST hold the length * of the generated string on exit (this is cached) */ #define BEGINgetFunctArray \ static rsRetVal getFunctArray(int *const version, const struct scriptFunct **const functArray) { \ DEFiRet; #define CODESTARTgetFunctArray #define ENDgetFunctArray \ RETiRet; \ } /* function to specify the parser name. This is done via a single command which * receives a ANSI string as parameter. */ #define PARSER_NAME(x) \ static rsRetVal GetParserName(uchar **ppSz) { \ *ppSz = UCHAR_CONSTANT(x); \ return RS_RET_OK; \ } /* function to specify the strgen name. This is done via a single command which * receives a ANSI string as parameter. */ #define STRGEN_NAME(x) \ static rsRetVal GetStrgenName(uchar **ppSz) { \ *ppSz = UCHAR_CONSTANT(x); \ return RS_RET_OK; \ } #endif /* #ifndef MODULE_TEMPLATE_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/net_ossl_store.h0000644000000000000000000000013215241075234017440 xustar0030 mtime=1787067036.603578257 30 atime=1787067036.681579717 30 ctime=1787067794.561728167 rsyslog-8.2608.0/runtime/net_ossl_store.h0000664000175000017500000000607315241075234017112 0ustar00rgerrger/** * @file net_ossl_store.h * @brief Helper interfaces for loading TLS objects into the OpenSSL * netstream driver. * * The declarations in this header are private to the lmnsd_ossl runtime * module. They provide a single entry point for loading trust anchors, * certificates, and private keys from either traditional filesystem-backed * PEM files or provider-backed pkcs11: URIs. * * Copyright 2026 Cisco Systems, Inc., and/or its affiliates. * Copyright 2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NET_OSSL_STORE_H #define INCLUDED_NET_OSSL_STORE_H #include "rsyslog.h" #include "net_ossl.h" /** * @brief Load CA certificates into an SSL context. * @param ctx SSL context that receives the trust anchors. * @param caFile Path or pkcs11: URI describing the CA certificate source. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ rsRetVal net_ossl_load_ca_file(SSL_CTX *ctx, const char *caFile); /** * @brief Load an end-entity certificate chain into an SSL context. * @param ctx SSL context that receives the certificate chain. * @param certFile Path or pkcs11: URI describing the certificate source. * @return RS_RET_OK on success, or an rsyslog TLS certificate error code. */ rsRetVal net_ossl_load_cert_file(SSL_CTX *ctx, const char *certFile); /** * @brief Load a private key into an SSL context. * @param ctx SSL context that receives the private key. * @param keyFile Path or pkcs11: URI describing the private key source. * @return RS_RET_OK on success, or an rsyslog TLS key error code. */ rsRetVal net_ossl_load_key_file(SSL_CTX *ctx, const char *keyFile); /** * @brief Redact sensitive fields from a TLS object locator before logging it. * @param input Original path or URI to sanitize. * @param sanitized Allocated sanitized copy when redaction is required, or * NULL when the original input is safe to log as-is. * @return Either @p input when no redaction was needed, an allocated sanitized * copy stored in @p sanitized, or a constant fallback redaction string when * memory allocation fails. */ const char *ATTR_NONNULL() net_ossl_sanitize_log_value(const char *input, char **sanitized); /** * @brief Release a sanitized log value allocated by * net_ossl_sanitize_log_value(). * @param sanitized Pointer to the allocated sanitized string, or NULL when no * allocation was needed. */ void net_ossl_free_sanitized_log_value(char **sanitized); #endif /* INCLUDED_NET_OSSL_STORE_H */ rsyslog-8.2608.0/runtime/PaxHeaders/srUtils.h0000644000000000000000000000013115145046113016037 xustar0029 mtime=1771326539.01401388 30 atime=1787067616.838415414 30 ctime=1787067794.332723899 rsyslog-8.2608.0/runtime/srUtils.h0000664000175000017500000001026215145046113015505 0ustar00rgerrger/*! \file srUtils.h * \brief General, small utilities that fit nowhere else. * * \author Rainer Gerhards * \date 2003-09-09 * Coding begun. * * Copyright 2003-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __SRUTILS_H_INCLUDED__ #define __SRUTILS_H_INCLUDED__ 1 #include #include /* syslog names */ #ifndef LOG_MAKEPRI #define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) #endif #define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ #define TABLE_NOPRI 0 /* Value to indicate no priority in f_pmask */ #define TABLE_ALLPRI 0xFF /* Value to indicate all priorities in f_pmask */ #define LOG_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) /* mark "facility" */ typedef struct syslogName_s { const char *c_name; int c_val; } syslogName_t; extern syslogName_t syslogPriNames[]; extern syslogName_t syslogFacNames[]; /** * A reimplementation of itoa(), as this is not available * on all platforms. We used the chance to make an interface * that fits us well, so it is no longer plain itoa(). * * This method works with the US-ASCII alphabet. If you port this * to e.g. EBCDIC, you need to make a small adjustment. Keep in mind, * that on the wire it MUST be US-ASCII, so basically all you need * to do is replace the constant '0' with 0x30 ;). * * \param pBuf Caller-provided buffer that will receive the * generated ASCII string. * * \param iLenBuf Length of the caller-provided buffer. * * \param iToConv The integer to be converted. */ rsRetVal srUtilItoA(char *pBuf, int iLenBuf, number_t iToConv); /** * A method to duplicate a string for which the length is known. * Len must be the length in characters WITHOUT the trailing * '\0' byte. * rgerhards, 2007-07-10 */ unsigned char *srUtilStrDup(unsigned char *pOld, size_t len); /** * A method to create a directory and all its missing parents for * a given file name. Please not that the rightmost element is * considered to be a file name and thus NO directory is being created * for it. * added 2007-07-17 by rgerhards */ int makeFileParentDirs(const uchar *const szFile, const size_t lenFile, const mode_t mode, const uid_t uid, const gid_t gid, const int bFailOnChown); int execProg(uchar *program, int bWait, uchar *arg1, uchar *arg2); void skipWhiteSpace(uchar **pp); rsRetVal genFileName( uchar **ppName, uchar *pDirName, size_t lenDirName, uchar *pFName, size_t lenFName, int64_t lNum, int lNumDigits); int getNumberDigits(long lNum); rsRetVal timeoutComp(struct timespec *pt, long iTimeout); long timeoutVal(struct timespec *pt); void mutexCancelCleanup(void *arg); void srSleep(int iSeconds, int iuSeconds); char *rs_strerror_r(int errnum, char *buf, size_t buflen); int decodeSyslogName(uchar *name, syslogName_t *codetab); int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep); rsRetVal getFileSize(uchar *pszName, off_t *pSize); int containsGlobWildcard(char *str); void seedRandomNumber(void); void seedRandomNumberForChild(void); #define MAX_RANDOM_NUMBER RAND_MAX long int randomNumber(void); long long currentTimeMills(void); rsRetVal ATTR_NONNULL() split_binary_parameters(uchar **const szBinary, char ***const aParams, int *const iParams, es_str_t *const param_binary); #endif /* #ifndef __SRUTILS_H_INCLUDED__ */ rsyslog-8.2608.0/runtime/PaxHeaders/libossl.c0000644000000000000000000000013215171370365016045 xustar0030 mtime=1776677109.436913002 30 atime=1782715518.785788789 30 ctime=1787067794.234722073 rsyslog-8.2608.0/runtime/libossl.c0000664000175000017500000004622315171370365015520 0ustar00rgerrger/* libossl.c - rsyslog's openssl based crypto provider * * * We need to store some additional information in support of encryption. * For this, we create a side-file, which is named like the actual log * file, but with the suffix ".encinfo" appended. It contains the following * records: * IV: The initial vector used at block start. Also indicates start * start of block. * END: The end offset of the block, as uint64_t in decimal notation. * This is used during encryption to know when the current * encryption block ends. * For the current implementation, there must always be an IV record * followed by an END record. Each records is LF-terminated. Record * types can simply be extended in the future by specifying new * types (like "IV") before the colon. * To identify a file as rsyslog encryption info file, it must start with * the line "FILETYPE:rsyslog-enrcyption-info" * There are some size constraints: the recordtype must be 31 bytes at * most and the actual value (between : and LF) must be 1023 bytes at most. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "debug.h" #include "libossl.h" #include "libcry_common.h" #define READBUF_SIZE 4096 /* size of the read buffer */ static rsRetVal rsosslBlkBegin(osslfile gf); /* read a key from a key file * @param[out] key - key buffer, must be freed by caller * @param[out] keylen - length of buffer * @returns 0 if OK, something else otherwise (we do not use * iRet as this is also called from non-rsyslog w/o runtime) * on error, errno is set and can be queried * The key length is limited to 64KiB to prevent DoS. * Note well: key is a blob, not a C string (NUL may be present!) */ int osslGetKeyFromFile(const char* const fn, char** const key, unsigned* const keylen) { struct stat sb; int r = -1; const int fd = open(fn, O_RDONLY); if (fd < 0) goto done; if (fstat(fd, &sb) == -1) goto done; if (sb.st_size > 64 * 1024) { errno = EMSGSIZE; goto done; } if (sb.st_size == 0) { errno = EINVAL; goto done; } if ((*key = malloc(sb.st_size)) == NULL) goto done; if (read(fd, *key, sb.st_size) != sb.st_size) goto done; *keylen = sb.st_size; r = 0; done: if (fd >= 0) { close(fd); } return r; } static void addPadding(osslfile pF, uchar* buf, size_t* plen) { unsigned i; size_t nPad; nPad = (pF->blkLength - *plen % pF->blkLength) % pF->blkLength; DBGPRINTF("libgcry: addPadding %zd chars, blkLength %zd, mod %zd, pad %zd\n", *plen, pF->blkLength, *plen % pF->blkLength, nPad); for (i = 0; i < nPad; ++i) buf[(*plen) + i] = 0x00; (*plen) += nPad; } static void ATTR_NONNULL() removePadding(uchar* const buf, size_t* const plen) { const size_t len = *plen; size_t iSrc, iDst; iSrc = 0; /* skip to first NUL */ while (iSrc < len && buf[iSrc] == '\0') { ++iSrc; } iDst = iSrc; while (iSrc < len) { if (buf[iSrc] != 0x00) buf[iDst++] = buf[iSrc]; ++iSrc; } *plen = iDst; } static rsRetVal eiWriteRec(osslfile gf, const char* recHdr, size_t lenRecHdr, const char* buf, size_t lenBuf) { struct iovec iov[3]; ssize_t nwritten, towrite; DEFiRet; iov[0].iov_base = (void*)recHdr; iov[0].iov_len = lenRecHdr; iov[1].iov_base = (void*)buf; iov[1].iov_len = lenBuf; iov[2].iov_base = (void*)"\n"; iov[2].iov_len = 1; towrite = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; nwritten = writev(gf->fd, iov, sizeof(iov) / sizeof(struct iovec)); if (nwritten != towrite) { DBGPRINTF( "eiWrite%s: error writing file, towrite %d, " "nwritten %d\n", recHdr, (int)towrite, (int)nwritten); ABORT_FINALIZE(RS_RET_EI_WR_ERR); } DBGPRINTF("encryption info file %s: written %s, len %d\n", recHdr, gf->eiName, (int)nwritten); finalize_it: RETiRet; } static rsRetVal eiOpenRead(osslfile gf) { DEFiRet; gf->fd = open((char*)gf->eiName, O_RDONLY | O_NOCTTY | O_CLOEXEC); if (gf->fd == -1) { ABORT_FINALIZE(errno == ENOENT ? RS_RET_EI_NO_EXISTS : RS_RET_EI_OPN_ERR); } finalize_it: RETiRet; } static rsRetVal eiRead(osslfile gf) { ssize_t nRead; DEFiRet; if (gf->readBuf == NULL) { CHKmalloc(gf->readBuf = malloc(READBUF_SIZE)); } nRead = read(gf->fd, gf->readBuf, READBUF_SIZE); if (nRead <= 0) { ABORT_FINALIZE(RS_RET_ERR); } gf->readBufMaxIdx = (int16_t)nRead; gf->readBufIdx = 0; finalize_it: RETiRet; } /* returns EOF on any kind of error */ static int eiReadChar(osslfile gf) { int c; if (gf->readBufIdx >= gf->readBufMaxIdx) { if (eiRead(gf) != RS_RET_OK) { c = EOF; goto finalize_it; } } c = gf->readBuf[gf->readBufIdx++]; finalize_it: return c; } static rsRetVal eiCheckFiletype(osslfile gf) { char hdrBuf[128]; size_t toRead, didRead; sbool bNeedClose = 0; DEFiRet; if (gf->fd == -1) { CHKiRet(eiOpenRead(gf)); assert(gf->fd != -1); /* cannot happen after successful return */ bNeedClose = 1; } if (Debug) memset(hdrBuf, 0, sizeof(hdrBuf)); /* for dbgprintf below! */ toRead = sizeof("FILETYPE:") - 1 + sizeof(RSGCRY_FILETYPE_NAME) - 1 + 1; didRead = read(gf->fd, hdrBuf, toRead); if (bNeedClose) { close(gf->fd); gf->fd = -1; } DBGPRINTF("eiCheckFiletype read %zd bytes: '%s'\n", didRead, hdrBuf); if (didRead != toRead || strncmp(hdrBuf, "FILETYPE:" RSGCRY_FILETYPE_NAME "\n", toRead)) iRet = RS_RET_EI_INVLD_FILE; finalize_it: RETiRet; } /* rectype/value must be EIF_MAX_*_LEN+1 long! * returns 0 on success or something else on error/EOF */ static rsRetVal eiGetRecord(osslfile gf, char* rectype, char* value) { unsigned short i, j; int c; DEFiRet; c = eiReadChar(gf); if (c == EOF) { ABORT_FINALIZE(RS_RET_NO_DATA); } for (i = 0; i < EIF_MAX_RECTYPE_LEN; ++i) { if (c == ':' || c == EOF) break; rectype[i] = c; c = eiReadChar(gf); } if (c != ':') { ABORT_FINALIZE(RS_RET_ERR); } rectype[i] = '\0'; j = 0; for (++i; i < EIF_MAX_VALUE_LEN; ++i, ++j) { c = eiReadChar(gf); if (c == '\n' || c == EOF) break; value[j] = c; } if (c != '\n') { ABORT_FINALIZE(RS_RET_ERR); } value[j] = '\0'; finalize_it: RETiRet; } static rsRetVal eiGetIV(osslfile gf, uchar* iv, size_t leniv) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; size_t valueLen; unsigned short i, j; unsigned char nibble; DEFiRet; CHKiRet(eiGetRecord(gf, rectype, value)); const char* const cmp_IV = "IV"; // work-around for static analyzer if (strcmp(rectype, cmp_IV)) { DBGPRINTF( "no IV record found when expected, record type " "seen is '%s'\n", rectype); ABORT_FINALIZE(RS_RET_ERR); } valueLen = strlen(value); if (valueLen / 2 != leniv) { DBGPRINTF("length of IV is %zd, expected %zd\n", valueLen / 2, leniv); ABORT_FINALIZE(RS_RET_ERR); } for (i = j = 0; i < valueLen; ++i) { if (value[i] >= '0' && value[i] <= '9') nibble = value[i] - '0'; else if (value[i] >= 'a' && value[i] <= 'f') nibble = value[i] - 'a' + 10; else { DBGPRINTF("invalid IV '%s'\n", value); ABORT_FINALIZE(RS_RET_ERR); } if (i % 2 == 0) iv[j] = nibble << 4; else iv[j++] |= nibble; } finalize_it: RETiRet; } static rsRetVal eiGetEND(osslfile gf, off64_t* offs) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; DEFiRet; CHKiRet(eiGetRecord(gf, rectype, value)); const char* const const_END = "END"; // clang static analyzer work-around if (strcmp(rectype, const_END)) { DBGPRINTF( "no END record found when expected, record type " "seen is '%s'\n", rectype); ABORT_FINALIZE(RS_RET_ERR); } *offs = atoll(value); finalize_it: RETiRet; } static rsRetVal eiOpenAppend(osslfile gf) { rsRetVal localRet; DEFiRet; localRet = eiCheckFiletype(gf); if (localRet == RS_RET_OK) { gf->fd = open((char*)gf->eiName, O_WRONLY | O_APPEND | O_NOCTTY | O_CLOEXEC, 0600); if (gf->fd == -1) { ABORT_FINALIZE(RS_RET_EI_OPN_ERR); } } else if (localRet == RS_RET_EI_NO_EXISTS) { /* looks like we need to create a new file */ gf->fd = open((char*)gf->eiName, O_WRONLY | O_CREAT | O_NOCTTY | O_CLOEXEC, 0600); if (gf->fd == -1) { ABORT_FINALIZE(RS_RET_EI_OPN_ERR); } CHKiRet(eiWriteRec(gf, "FILETYPE:", 9, RSGCRY_FILETYPE_NAME, sizeof(RSGCRY_FILETYPE_NAME) - 1)); } else { gf->fd = -1; ABORT_FINALIZE(localRet); } DBGPRINTF("encryption info file %s: opened as #%d\n", gf->eiName, gf->fd); finalize_it: RETiRet; } static rsRetVal __attribute__((nonnull(2))) eiWriteIV(osslfile gf, const uchar* const iv) { static const char hexchars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; unsigned iSrc, iDst; char hex[4096]; DEFiRet; if (gf->blkLength > sizeof(hex) / 2) { DBGPRINTF( "eiWriteIV: crypto block len way too large, aborting " "write"); ABORT_FINALIZE(RS_RET_ERR); } for (iSrc = iDst = 0; iSrc < gf->blkLength; ++iSrc) { hex[iDst++] = hexchars[iv[iSrc] >> 4]; hex[iDst++] = hexchars[iv[iSrc] & 0x0f]; } iRet = eiWriteRec(gf, "IV:", 3, hex, gf->blkLength * 2); finalize_it: RETiRet; } /* we do not return an error state, as we MUST close the file, * no matter what happens. */ static void eiClose(osslfile gf, off64_t offsLogfile) { char offs[21]; size_t len; if (gf->fd == -1) return; if (gf->openMode == 'w') { /* 2^64 is 20 digits, so the snprintf buffer is large enough */ len = snprintf(offs, sizeof(offs), "%lld", (long long)offsLogfile); eiWriteRec(gf, "END:", 4, offs, len); } EVP_CIPHER_CTX_free(gf->chd); free(gf->readBuf); close(gf->fd); gf->fd = -1; DBGPRINTF("encryption info file %s: closed\n", gf->eiName); } /* this returns the number of bytes left inside the block or -1, if the block * size is unbounded. The function automatically handles end-of-block and begins * to read the next block in this case. */ rsRetVal osslfileGetBytesLeftInBlock(osslfile gf, ssize_t* left) { DEFiRet; if (gf->bytesToBlkEnd == 0) { DBGPRINTF("libossl: end of current crypto block\n"); EVP_CIPHER_CTX_free(gf->chd); CHKiRet(rsosslBlkBegin(gf)); } *left = gf->bytesToBlkEnd; finalize_it: RETiRet; } /* this is a special functon for use by the rsyslog disk queue subsystem. It * needs to have the capability to delete state when a queue file is rolled * over. This simply generates the file name and deletes it. It must take care * of "all" state files, which currently happens to be a single one. */ rsRetVal osslfileDeleteState(uchar* logfn) { char fn[MAXFNAME + 1]; DEFiRet; snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX); fn[MAXFNAME] = '\0'; /* be on save side */ DBGPRINTF("ossl crypto provider deletes state file '%s' on request\n", fn); unlink(fn); RETiRet; } static rsRetVal osslfileConstruct(osslctx ctx, osslfile* pgf, uchar* logfn) { char fn[MAXFNAME + 1]; osslfile gf; DEFiRet; CHKmalloc(gf = calloc(1, sizeof(struct osslfile_s))); CHKmalloc(gf->chd = EVP_CIPHER_CTX_new()); gf->ctx = ctx; gf->fd = -1; snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX); fn[MAXFNAME] = '\0'; /* be on save side */ gf->eiName = (uchar*)strdup(fn); *pgf = gf; finalize_it: RETiRet; } osslctx osslCtxNew(void) { osslctx ctx; ctx = calloc(1, sizeof(struct osslctx_s)); if (ctx != NULL) { ctx->cipher = EVP_aes_128_cbc(); ctx->key = NULL; ctx->keyLen = -1; } return ctx; } int osslfileDestruct(osslfile gf, off64_t offsLogfile) { int r = 0; if (gf == NULL) goto done; DBGPRINTF("libossl: close file %s\n", gf->eiName); eiClose(gf, offsLogfile); if (gf->bDeleteOnClose) { DBGPRINTF("unlink file '%s' due to bDeleteOnClose set\n", gf->eiName); unlink((char*)gf->eiName); } free(gf->eiName); free(gf); done: return r; } void rsosslCtxDel(osslctx ctx) { if (ctx != NULL) { free(ctx->key); free(ctx); } } /* returns 0 on succes, positive if key length does not match and key * of return value size is required. */ int rsosslSetKey(osslctx ctx, unsigned char* key, uint16_t keyLen) { uint16_t reqKeyLen; int r; reqKeyLen = EVP_CIPHER_get_key_length(ctx->cipher); if (keyLen != reqKeyLen) { r = reqKeyLen; goto done; } ctx->keyLen = keyLen; ctx->key = malloc(keyLen); memcpy(ctx->key, key, keyLen); r = 0; done: return r; } rsRetVal rsosslSetAlgoMode(osslctx ctx, uchar* algorithm) { EVP_CIPHER* cipher; DEFiRet; cipher = EVP_CIPHER_fetch(NULL, (char*)algorithm, NULL); if (cipher == NULL) { ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO); } ctx->cipher = cipher; finalize_it: RETiRet; } /* We use random numbers to initiate the IV. Rsyslog runtime will ensure * we get a sufficiently large number. */ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif static rsRetVal #if defined(__clang__) __attribute__((no_sanitize("shift"))) /* IV shift causes known overflow */ #endif seedIV(osslfile gf, uchar** iv) { long rndnum = 0; /* keep compiler happy -- this value is always overriden */ DEFiRet; CHKmalloc(*iv = calloc(1, gf->blkLength)); for (size_t i = 0; i < gf->blkLength; ++i) { const int shift = (i % 4) * 8; if (shift == 0) { /* need new random data? */ rndnum = randomNumber(); } (*iv)[i] = 0xff & ((rndnum & (255u << shift)) >> shift); } finalize_it: RETiRet; } static rsRetVal readIV(osslfile gf, uchar** iv) { rsRetVal localRet; DEFiRet; if (gf->fd == -1) { while (gf->fd == -1) { localRet = eiOpenRead(gf); if (localRet == RS_RET_EI_NO_EXISTS) { /* wait until it is created */ srSleep(0, 10000); } else { CHKiRet(localRet); } } CHKiRet(eiCheckFiletype(gf)); } *iv = malloc(gf->blkLength); /* do NOT zero-out! */ iRet = eiGetIV(gf, *iv, (size_t)gf->blkLength); finalize_it: RETiRet; } /* this tries to read the END record. HOWEVER, no such record may be * present, which is the case if we handle a currently-written to queue * file. On the other hand, the queue file may contain multiple blocks. So * what we do is try to see if there is a block end or not - and set the * status accordingly. Note that once we found no end-of-block, we will never * retry. This is because that case can never happen under current queue * implementations. -- gerhards, 2013-05-16 */ static rsRetVal readBlkEnd(osslfile gf) { off64_t blkEnd; DEFiRet; iRet = eiGetEND(gf, &blkEnd); if (iRet == RS_RET_OK) { gf->bytesToBlkEnd = (ssize_t)blkEnd; } else if (iRet == RS_RET_NO_DATA) { gf->bytesToBlkEnd = -1; } else { FINALIZE; } finalize_it: RETiRet; } /* module-init dummy for potential later use */ int rsosslInit(void) { return 0; } /* module-deinit dummy for potential later use */ void rsosslExit(void) { return; } /* Read the block begin metadata and set our state variables accordingly. * Can also be used to init the first block in write case. */ static rsRetVal rsosslBlkBegin(osslfile gf) { uchar* iv = NULL; DEFiRet; const char openMode = gf->openMode; // FIXME error handling if (openMode == 'r') { readIV(gf, &iv); readBlkEnd(gf); } else { CHKiRet(seedIV(gf, &iv)); } if (openMode == 'r') { if ((iRet = EVP_DecryptInit_ex(gf->chd, gf->ctx->cipher, NULL, gf->ctx->key, iv)) != 1) { DBGPRINTF("EVP_DecryptInit_ex failed: %d\n", iRet); ABORT_FINALIZE(RS_RET_ERR); } } else { if ((iRet = EVP_EncryptInit_ex(gf->chd, gf->ctx->cipher, NULL, gf->ctx->key, iv)) != 1) { DBGPRINTF("EVP_EncryptInit_ex failed: %d\n", iRet); ABORT_FINALIZE(RS_RET_ERR); } } if ((iRet = EVP_CIPHER_CTX_set_padding(gf->chd, 0)) != 1) { fprintf(stderr, "EVP_CIPHER_set_padding failed: %d\n", iRet); ABORT_FINALIZE(RS_RET_ERR); } if (openMode == 'w') { CHKiRet(eiOpenAppend(gf)); CHKiRet(eiWriteIV(gf, iv)); } finalize_it: free(iv); RETiRet; } rsRetVal rsosslInitCrypt(osslctx ctx, osslfile* pgf, uchar* fname, char openMode) { osslfile gf = NULL; DEFiRet; CHKiRet(osslfileConstruct(ctx, &gf, fname)); gf->openMode = openMode; gf->blkLength = EVP_CIPHER_get_block_size(ctx->cipher); CHKiRet(rsosslBlkBegin(gf)); *pgf = gf; finalize_it: if (iRet != RS_RET_OK && gf != NULL) osslfileDestruct(gf, -1); RETiRet; } rsRetVal rsosslDecrypt(osslfile pF, uchar* buf, size_t* len) { DEFiRet; int rc; if (pF->bytesToBlkEnd != -1) pF->bytesToBlkEnd -= *len; rc = EVP_DecryptUpdate(pF->chd, buf, (int*)len, buf, (int)*len); if (rc != 1) { DBGPRINTF("EVP_DecryptUpdate failed\n"); ABORT_FINALIZE(RS_RET_ERR); } removePadding(buf, len); dbgprintf("libossl: decrypted, bytesToBlkEnd %lld, buffer is now '%50.50s'\n", (long long)pF->bytesToBlkEnd, buf); finalize_it: RETiRet; } rsRetVal rsosslEncrypt(osslfile pF, uchar* buf, size_t* len) { DEFiRet; int tmplen; if (*len == 0) FINALIZE; addPadding(pF, buf, len); if (EVP_EncryptUpdate(pF->chd, buf, (int*)len, buf, (int)*len) != 1) { dbgprintf("EVP_EncryptUpdate failed\n"); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } if (EVP_EncryptFinal_ex(pF->chd, buf + *len, &tmplen) != 1) { dbgprintf("EVP_EncryptFinal_ex failed\n"); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } *len += tmplen; finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/queue_da.c0000644000000000000000000000013215241075234016161 xustar0030 mtime=1787067036.607578332 30 atime=1787067036.681579717 30 ctime=1787067794.400725167 rsyslog-8.2608.0/runtime/queue_da.c0000664000175000017500000003325015241075234015630 0ustar00rgerrger/* SPDX-License-Identifier: Apache-2.0 */ /* * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 */ /** * @file queue_da.c * @brief Resolves disk-assisted child engines and maintains their durable markers. * * This internal implementation selects the classic or segmented disk child for * a disk-assisted queue from its configuration, marker, and existing spool * contents. It also provides the crash-safe marker operations that preserve * the selected engine across restarts. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "queue_da.h" /* The marker format is intentionally independent of either queue payload * format. Its version identifies only the selection record, allowing future * engine-policy changes to reject rather than misinterpret an old marker. */ #define QDA_MARKER_MAGIC "RSYSLOG-DA-ENGINE-V1 " /** * @brief Allocate a path in a queue's persistent namespace. * * The caller owns *path on success and must free it. Keeping path assembly in * one helper makes all engine probes use the exact same prefix and suffix * convention. */ static rsRetVal make_path(char **path, const char *dir, const char *prefix, const char *suffix) { if (asprintf(path, "%s/%s%s", dir, prefix, suffix) < 0) { *path = NULL; return RS_RET_OUT_OF_MEMORY; } return RS_RET_OK; } /** @brief Test whether a named path exists without following a queue policy. */ static rsRetVal path_exists(const char *path, sbool *exists) { struct stat st; if (lstat(path, &st) == 0) { *exists = 1; return RS_RET_OK; } if (errno == ENOENT) { *exists = 0; return RS_RET_OK; } return RS_RET_IO_ERROR; } /** * @brief Recognize only legacy numeric segment names for the supplied prefix. * * A numeric segment is classic-engine evidence even when the .qi index is * gone. Non-numeric lookalikes must not make AUTO select classic. */ static sbool is_classic_segment_name(const char *name, const char *prefix) { const size_t prefix_len = strlen(prefix); if (strncmp(name, prefix, prefix_len) != 0 || name[prefix_len] != '.') return 0; const char *p = name + prefix_len + 1; if (*p == '\0') return 0; for (; *p != '\0'; ++p) { if (*p < '0' || *p > '9') return 0; } return 1; } /** * @brief Probe for classic numeric segments and fail closed on an incomplete scan. * * This is the one namespace enumeration in engine selection. A close or * readdir error is treated as an I/O failure rather than as an empty store: * choosing the wrong engine could otherwise strand persistent records. */ static rsRetVal find_classic_segments(const char *dir, const char *prefix, sbool *found) { DIR *d = opendir(dir); if (d == NULL) return errno == ENOENT ? RS_RET_FILE_NOT_FOUND : RS_RET_IO_ERROR; *found = 0; errno = 0; struct dirent *entry; while ((entry = readdir(d)) != NULL) { if (is_classic_segment_name(entry->d_name, prefix)) { *found = 1; break; } } const int saved_errno = errno; /* A close failure means the directory probe did not complete reliably, * even if a matching name was observed. Engine selection must fail * closed here: treating a partial/invalid probe as authoritative could * select an engine that conflicts with persistent data. */ if (closedir(d) != 0) return RS_RET_IO_ERROR; if (!*found && saved_errno != 0) return RS_RET_IO_ERROR; return RS_RET_OK; } const char *qdaEngineName(qda_engine_mode_t engine) { switch (engine) { case QDA_ENGINE_AUTO: return "auto"; case QDA_ENGINE_DISK: return "disk"; case QDA_ENGINE_SEGMENTED_DISK: return "segmentedDisk"; default: return "invalid"; } } sbool qdaLifecycleConfigEqual(const qda_lifecycle_config_t *left, const qda_lifecycle_config_t *right) { return left != NULL && right != NULL && left->engine == right->engine && left->auto_upgrade == right->auto_upgrade && left->idle_timeout == right->idle_timeout; } /** * @brief Read and validate a durable engine marker without following symlinks. * * Markers are deliberately tiny regular files with an exact versioned payload. * A malformed, truncated, oversized, or unsafe marker is rejected instead of * silently reverting to automatic detection, because it represents an * ambiguous persistent-engine decision. */ static rsRetVal read_marker(const char *path, sbool *present, qda_engine_mode_t *engine) { char buf[64]; *present = 0; const int fd = open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); if (fd < 0) return errno == ENOENT ? RS_RET_OK : RS_RET_IO_ERROR; struct stat st; if (fstat(fd, &st) != 0 || !S_ISREG(st.st_mode) || st.st_size <= 0 || st.st_size >= (off_t)sizeof(buf)) { close(fd); return RS_RET_INVALID_VALUE; } size_t off = 0; while (off < (size_t)st.st_size) { const ssize_t n = read(fd, buf + off, (size_t)st.st_size - off); if (n < 0) { if (errno == EINTR) continue; close(fd); return RS_RET_IO_ERROR; } if (n == 0) break; off += (size_t)n; } close(fd); if (off != (size_t)st.st_size) return RS_RET_IO_ERROR; buf[off] = '\0'; const size_t magic_len = sizeof(QDA_MARKER_MAGIC) - 1; if (off <= magic_len || memcmp(buf, QDA_MARKER_MAGIC, magic_len) != 0) return RS_RET_INVALID_VALUE; const char *value = buf + magic_len; if (!strcmp(value, "disk\n")) *engine = QDA_ENGINE_DISK; else if (!strcmp(value, "segmentedDisk\n")) *engine = QDA_ENGINE_SEGMENTED_DISK; else return RS_RET_INVALID_VALUE; *present = 1; return RS_RET_OK; } rsRetVal qdaEngineResolve(const qda_engine_config_t *config, qda_engine_result_t *result) { if (config == NULL || result == NULL || config->spool_dir == NULL || config->file_prefix == NULL) return RS_RET_PARAM_ERROR; memset(result, 0, sizeof(*result)); char *qi_path = NULL; char *seg_path = NULL; char *marker_path = NULL; rsRetVal r = make_path(&qi_path, config->spool_dir, config->file_prefix, ".qi"); if (r == RS_RET_OK) r = make_path(&seg_path, config->spool_dir, config->file_prefix, ".segq"); if (r == RS_RET_OK) r = make_path(&marker_path, config->spool_dir, config->file_prefix, ".da-engine"); if (r != RS_RET_OK) goto done; r = path_exists(qi_path, &result->classic_data); if (r == RS_RET_OK) r = path_exists(seg_path, &result->segmented_data); if (r == RS_RET_OK) r = read_marker(marker_path, &result->marker_present, &result->marker_engine); if (r != RS_RET_OK) goto done; sbool numeric_segments = 0; r = find_classic_segments(config->spool_dir, config->file_prefix, &numeric_segments); if (r == RS_RET_FILE_NOT_FOUND) r = RS_RET_OK; if (r != RS_RET_OK) goto done; result->classic_data = result->classic_data || numeric_segments; if (result->classic_data && result->segmented_data) { r = RS_RET_INVALID_VALUE; goto done; } if (result->marker_present && ((result->classic_data && result->marker_engine == QDA_ENGINE_SEGMENTED_DISK) || (result->segmented_data && result->marker_engine == QDA_ENGINE_DISK))) { r = RS_RET_INVALID_VALUE; goto done; } /* An explicit selector may replace an opposite marker only after the * probes above proved that the old engine has no state or segments. The * marker is intentionally not data: it is retained after a clean drain so * auto mode stays sticky, while an operator can explicitly choose the * engine for the next materialization. Opposite-engine data remains a * hard conflict in both branches. */ if (config->requested == QDA_ENGINE_DISK) { if (result->segmented_data) { r = RS_RET_INVALID_VALUE; goto done; } result->effective = QDA_ENGINE_DISK; result->reason = QDA_REASON_CONFIGURED; } else if (config->requested == QDA_ENGINE_SEGMENTED_DISK) { if (result->classic_data || config->requires_classic_features) { r = RS_RET_INVALID_VALUE; goto done; } result->effective = QDA_ENGINE_SEGMENTED_DISK; result->reason = QDA_REASON_CONFIGURED; } else if (config->requested != QDA_ENGINE_AUTO) { r = RS_RET_INVALID_VALUE; goto done; } else if (result->classic_data) { result->effective = QDA_ENGINE_DISK; result->reason = QDA_REASON_CLASSIC_DATA; } else if (result->segmented_data) { if (config->requires_classic_features) { r = RS_RET_INVALID_VALUE; goto done; } result->effective = QDA_ENGINE_SEGMENTED_DISK; result->reason = QDA_REASON_SEGMENTED_DATA; } else if (config->requires_classic_features) { /* Unsupported segmented features take precedence over an empty * segmented marker in auto mode. The data probes above proved that * changing the marker cannot strand records, and auto is required to * select the classic engine for these features. */ result->effective = QDA_ENGINE_DISK; result->reason = QDA_REASON_CLASSIC_FEATURE; } else if (result->marker_present && result->marker_engine == QDA_ENGINE_DISK && !config->auto_upgrade) { result->effective = QDA_ENGINE_DISK; result->reason = QDA_REASON_MARKER; } else if (result->marker_present && result->marker_engine == QDA_ENGINE_DISK && config->auto_upgrade) { /* This is the requested upgrade boundary: the durable marker proves * that the previous engine was classic, while the absence of .qi and * numeric segments proves that it drained. Selection changes only * during this restart; StartDA atomically replaces the marker before * constructing the new child, and no records are converted. */ result->effective = QDA_ENGINE_SEGMENTED_DISK; result->reason = QDA_REASON_AUTO_UPGRADE; } else if (result->marker_present) { result->effective = result->marker_engine; result->reason = QDA_REASON_MARKER; } else { result->effective = QDA_ENGINE_SEGMENTED_DISK; result->reason = QDA_REASON_FRESH_DEFAULT; } done: free(qi_path); free(seg_path); free(marker_path); return r; } /** @brief Write a complete marker payload, retrying only interrupted writes. */ static rsRetVal write_all(int fd, const char *buf, size_t len) { size_t off = 0; while (off < len) { const ssize_t n = write(fd, buf + off, len - off); if (n < 0) { if (errno == EINTR) continue; return RS_RET_IO_ERROR; } if (n == 0) return RS_RET_IO_ERROR; off += (size_t)n; } return RS_RET_OK; } /** * @brief Synchronize marker content before its atomic rename. * * fdatasync is sufficient where it is available because the marker's inode * metadata is established by the following rename and directory sync. macOS * falls back to fsync for portability. */ static int sync_file_data(const int fd) { #if defined(HAVE_FDATASYNC) && !defined(__APPLE__) return fdatasync(fd); #else return fsync(fd); #endif } /** * @brief Synchronize a marker rename while tolerating unsupported directory fsync. * * Some supported filesystems report EINVAL or ENOTSUP for directory fsync. * Treating only those responses as success preserves the strongest available * durability guarantee without making otherwise usable spool filesystems fail. */ static rsRetVal sync_directory(const int fd) { return fsync(fd) == 0 || errno == EINVAL || errno == ENOTSUP ? RS_RET_OK : RS_RET_IO_ERROR; } rsRetVal qdaEngineWriteMarker(const char *spool_dir, const char *file_prefix, qda_engine_mode_t engine) { if (spool_dir == NULL || file_prefix == NULL || (engine != QDA_ENGINE_DISK && engine != QDA_ENGINE_SEGMENTED_DISK)) return RS_RET_PARAM_ERROR; char *path = NULL; char *tmp = NULL; rsRetVal r = make_path(&path, spool_dir, file_prefix, ".da-engine"); if (r != RS_RET_OK) return r; const char *name = qdaEngineName(engine); char content[64]; const int content_len = snprintf(content, sizeof(content), "%s%s\n", QDA_MARKER_MAGIC, name); if (content_len < 0 || content_len >= (int)sizeof(content)) { free(path); return RS_RET_INTERNAL_ERROR; } if (asprintf(&tmp, "%s.tmp.%ld", path, (long)getpid()) < 0) { free(path); return RS_RET_OUT_OF_MEMORY; } int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW, 0600); if (fd < 0) { if (errno == EEXIST && unlink(tmp) == 0) fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC | O_NOFOLLOW, 0600); } if (fd < 0) { r = RS_RET_IO_ERROR; goto done; } r = write_all(fd, content, (size_t)content_len); if (r == RS_RET_OK && sync_file_data(fd) != 0) r = RS_RET_IO_ERROR; if (close(fd) != 0 && r == RS_RET_OK) r = RS_RET_IO_ERROR; if (r == RS_RET_OK && rename(tmp, path) != 0) r = RS_RET_IO_ERROR; if (r == RS_RET_OK) { const int dirfd = open(spool_dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); if (dirfd < 0 || sync_directory(dirfd) != RS_RET_OK) r = RS_RET_IO_ERROR; if (dirfd >= 0) close(dirfd); } if (r != RS_RET_OK) unlink(tmp); done: free(tmp); free(path); return r; } rsyslog-8.2608.0/runtime/PaxHeaders/obj.h0000644000000000000000000000013215132411300015133 xustar0030 mtime=1768559296.271885719 30 atime=1787067616.814414966 30 ctime=1787067794.350724235 rsyslog-8.2608.0/runtime/obj.h0000666000175000017500000001361615132411300014610 0ustar00rgerrger/* Definition of the generic obj class module. * * This module relies heavily on preprocessor macros in order to * provide fast execution time AND ease of use. * * Each object that uses this base class MUST provide a constructor with * the following interface: * * Destruct(pThis); * * A constructor is not necessary (except for some features, e.g. de-serialization). * If it is provided, it is a three-part constructor (to handle all cases with a * generic interface): * * Construct(&pThis); * SetProperty(pThis, property_t *); * ConstructFinalize(pThis); * * SetProperty() and ConstructFinalize() may also be called on an object * instance which has been Construct()'ed outside of this module. * * pThis always references to a pointer of the object. * * Copyright 2008-2025 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OBJ_H_INCLUDED #define OBJ_H_INCLUDED #include "obj-types.h" #include "var.h" #include "stream.h" /* macros */ /* the following one is a helper that prevents us from writing the * ever-same code at the end of Construct() */ #define OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP \ if (iRet == RS_RET_OK) { \ *ppThis = pThis; \ } else { \ if (pThis != NULL) free(pThis); \ } #define objSerializeSCALAR_VAR(strm, propName, propType, var) \ CHKiRet(obj.SerializeProp(strm, (uchar *)#propName, PROPTYPE_##propType, (void *)&var)) #define objSerializeSCALAR(strm, propName, propType) \ CHKiRet(obj.SerializeProp(strm, (uchar *)#propName, PROPTYPE_##propType, (void *)&pThis->propName)) #define objSerializePTR(strm, propName, propType) \ CHKiRet(obj.SerializeProp(strm, (uchar *)#propName, PROPTYPE_##propType, (void *)pThis->propName)) #define DEFobjStaticHelpers \ static objInfo_t __attribute__((unused)) *pObjInfoOBJ = NULL; \ DEFobjCurrIf(obj) #define objGetClassName(pThis) (((obj_t *)(pThis))->pObjInfo->pszID) #define objGetVersion(pThis) (((obj_t *)(pThis))->pObjInfo->iObjVers) /* the next macro MUST be called in Constructors: */ #ifndef NDEBUG /* this means if debug... */ #define objConstructSetObjInfo(pThis) \ ((obj_t *)(pThis))->pObjInfo = pObjInfoOBJ; \ ((obj_t *)(pThis))->pszName = NULL; \ ((obj_t *)(pThis))->iObjCooCKiE = 0xBADEFEE #else #define objConstructSetObjInfo(pThis) \ ((obj_t *)(pThis))->pObjInfo = pObjInfoOBJ; \ ((obj_t *)(pThis))->pszName = NULL #endif #define objSerialize(pThis) (((obj_t *)(pThis))->pObjInfo->objMethods[objMethod_SERIALIZE]) #define OBJSetMethodHandler(methodID, pHdlr) CHKiRet(obj.InfoSetMethod(pObjInfoOBJ, methodID, (rsRetVal(*)())pHdlr)) /* interfaces */ BEGINinterface(obj) /* name must also be changed in ENDinterface macro! */ rsRetVal (*UseObj)(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf); rsRetVal (*ReleaseObj)(const char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf); rsRetVal (*InfoConstruct)(objInfo_t **ppThis, uchar *pszID, int iObjVers, rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *), rsRetVal (*pQueryIF)(interface_t *), modInfo_t *); rsRetVal (*DestructObjSelf)(obj_t *pThis); rsRetVal (*BeginSerializePropBag)(strm_t *pStrm, obj_t *pObj); rsRetVal (*InfoSetMethod)(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void *)); rsRetVal (*BeginSerialize)(strm_t *pStrm, obj_t *pObj); rsRetVal (*SerializeProp)(strm_t *pStrm, uchar *pszPropName, propType_t propType, void *pUsr); rsRetVal (*EndSerialize)(strm_t *pStrm); rsRetVal (*RegisterObj)(uchar *pszObjName, objInfo_t *pInfo); rsRetVal (*UnregisterObj)(uchar *pszObjName); rsRetVal (*Deserialize)(void *ppObj, uchar *pszTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t *, void *), void *pUsr); rsRetVal (*DeserializePropBag)(obj_t *pObj, strm_t *pStrm); rsRetVal (*SetName)(obj_t *pThis, uchar *pszName); uchar *(*GetName)(obj_t *pThis); ENDinterface(obj) #define objCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ /* the following define *is* necessary, because it provides the root way of obtaining * interfaces (at some place we need to start our query... */ rsRetVal objGetObjInterface(obj_if_t *pIf); PROTOTYPEObjClassInit(obj); PROTOTYPEObjClassExit(obj); rsRetVal objDeserializeWithMethods(void *ppObj, uchar *pszTypeExpected, int lenTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t *, void *), void *pUsr, rsRetVal (*objConstruct)(void **), rsRetVal (*objConstructFinalize)(void *), rsRetVal (*objDeserialize)(void *, strm_t *)); rsRetVal objDeserializeProperty(var_t *pProp, strm_t *pStrm); uchar *objGetName(obj_t *pThis); /* the following definition is only for "friends" */ extern pthread_mutex_t mutObjGlobalOp; /* mutex to guard global operations of the object system */ #endif /* #ifndef OBJ_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/libgcry.h0000644000000000000000000000013215132411300016014 xustar0030 mtime=1768559296.265885624 30 atime=1783339707.658803469 30 ctime=1787067794.231722017 rsyslog-8.2608.0/runtime/libgcry.h0000666000175000017500000000532315132411300015465 0ustar00rgerrger/* libgcry.h - rsyslog's guardtime support library * * Copyright 2013 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LIBGCRY_H #define INCLUDED_LIBGCRY_H #include #include struct gcryctx_s { uchar *key; size_t keyLen; int algo; int mode; }; typedef struct gcryctx_s *gcryctx; typedef struct gcryfile_s *gcryfile; /* this describes a file, as far as libgcry is concerned */ struct gcryfile_s { gcry_cipher_hd_t chd; /* cypher handle */ size_t blkLength; /* size of low-level crypto block */ uchar *eiName; /* name of .encinfo file */ int fd; /* descriptor of .encinfo file (-1 if not open) */ char openMode; /* 'r': read, 'w': write */ gcryctx ctx; uchar *readBuf; int16_t readBufIdx; int16_t readBufMaxIdx; int8_t bDeleteOnClose; /* for queue support, similar to stream subsys */ ssize_t bytesToBlkEnd; /* number of bytes remaining in current crypto block -1 means -> no end (still being writen to, queue files), 0 means -> end of block, new one must be started. */ }; int rsgcryInit(void); void rsgcryExit(void); int rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen); rsRetVal rsgcrySetMode(gcryctx ctx, uchar *algoname); rsRetVal rsgcrySetAlgo(gcryctx ctx, uchar *modename); gcryctx gcryCtxNew(void); void rsgcryCtxDel(gcryctx ctx); int gcryfileDestruct(gcryfile gf, off64_t offsLogfile); rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname, char openMode); rsRetVal rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len); rsRetVal rsgcryDecrypt(gcryfile pF, uchar *buf, size_t *len); rsRetVal gcryfileDeleteState(uchar *fn); rsRetVal gcryfileGetBytesLeftInBlock(gcryfile gf, ssize_t *left); int rsgcryModename2Mode(char *const __restrict__ modename); int rsgcryAlgoname2Algo(char *const __restrict__ algoname); /* Note: gf may validly be NULL, e.g. if file has not yet been opened! */ static inline void __attribute__((unused)) gcryfileSetDeleteOnClose(gcryfile gf, const int val) { if (gf != NULL) gf->bDeleteOnClose = val; } #endif /* #ifndef INCLUDED_LIBGCRY_H */ rsyslog-8.2608.0/runtime/PaxHeaders/rsyslog.c0000644000000000000000000000013215171370365016100 xustar0030 mtime=1776677109.445913141 30 atime=1787067617.881434861 30 ctime=1787067794.239722166 rsyslog-8.2608.0/runtime/rsyslog.c0000664000175000017500000003016315171370365015547 0ustar00rgerrger/* rsyslog.c - the main entry point into rsyslog's runtime library (RTL) * * This module contains all function which work on a RTL global level. It's * name is abbreviated to "rsrt" (rsyslog runtime). * * Please note that the runtime library tends to be plugin-safe. That is, it must be * initialized by calling a global initialization function. However, that * function checks if the library is already initialized and, if so, does * nothing except incrementing a refeence count. Similarly, the deinit * function does nothing as long as there are still other users (which * is tracked via the refcount). As such, it is safe to call init and * exit multiple times, as long as this are always matching calls. This * capability is needed for a plugin system, where one plugin never * knows what the other did. HOWEVER, as of this writing, not all runtime * library objects may work cleanly without static global data (the * debug system is a very good example of this). So while we aim at the * ability to work well in a plugin environment, things may not really work * out. If you intend to use the rsyslog runtime library inside plugins, * you should investigate the situation in detail. Please note that the * rsyslog project itself does not yet need this functionality - thus you * can safely assume it is totally untested ;). * * rgerhards, 2008-04-17: I have now once again checked on the plugin-safety. * Unfortunately, there is currently no hook at all with which we could * abstract a global data instance class. As such, we can NOT make the * runtime plugin-safe in the above-described sense. As the rsyslog * project itself does not need this functionality (and it is quesationable * if someone else ever will), we do currently do not make an effort to * support it. So if you intend to use rsyslog runtime inside a non-rsyslog * plugin system, be careful! * * The rsyslog runtime library is in general reentrant and thread-safe. There * are some intentional exceptions (e.g. inside the msg object). These are * documented. Any other threading and reentrency issue can be considered a bug. * * Module begun 2008-04-16 by Rainer Gerhards * * Copyright 2008-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #ifdef ENABLE_LIBLOGGING_STDLOG #include #endif #include "rsyslog.h" #include "obj.h" #include "stringbuf.h" #include "wti.h" #include "wtp.h" #include "datetime.h" #include "queue.h" #include "conf.h" #include "rsconf.h" #include "glbl.h" #include "errmsg.h" #include "prop.h" #include "ruleset.h" #include "parser.h" #include "lookup.h" #include "rswatch.h" #include "strgen.h" #include "statsobj.h" #include "atomic.h" #include "srUtils.h" pthread_attr_t default_thread_attr; #ifdef HAVE_PTHREAD_SETSCHEDPARAM struct sched_param default_sched_param; int default_thr_sched_policy; #endif /* globally visible static data - see comment in rsyslog.h for details */ uchar *glblModPath; /* module load path */ void (*glblErrLogger)(const int, const int, const uchar *) = dfltErrLogger; /* the error logger to use by the errmsg module */ /* static data */ static int iRefCount = 0; /* our refcount - it MUST exist only once inside a process (not thread) thus it is perfectly OK to use a static. MUST be initialized to 0! */ /* This is the default instance of the error logger. It simply writes the message * to stderr. It is expected that this is replaced by the runtime user very early * during startup (at least if the default is unsuitable). However, we provide a * default so that we can log errors during the initial phase, most importantly * during initialization. -- rgerhards. 2008-04-17 */ void dfltErrLogger(const int severity, const int iErr, const uchar *errMsg) { fprintf(stderr, "rsyslog internal message (%d,%d): %s\n", severity, iErr, errMsg); } /* set the error log function * rgerhards, 2008-04-18 */ void rsrtSetErrLogger(void (*errLogger)(const int, const int, const uchar *)) { assert(errLogger != NULL); glblErrLogger = errLogger; } /* globally initialze the runtime system * NOTE: this is NOT thread safe and must not be called concurrently. If that * ever poses a problem, we may use proper mutex calls - not considered needed yet. * If ppErrObj is provided, it receives a char pointer to the name of the object that * caused the problem (if one occurred). The caller must never free this pointer. If * ppErrObj is NULL, no such information will be provided. pObjIF is the pointer to * the "obj" object interface, which may be used to query any other rsyslog objects. * rgerhards, 2008-04-16 */ rsRetVal rsrtInit(const char **ppErrObj, obj_if_t *pObjIF) { DEFiRet; int ret; char errstr[1024]; if (iRefCount == 0) { seedRandomNumber(); /* init runtime only if not yet done */ #ifdef ENABLE_LIBLOGGING_STDLOG stdlog_init(0); #endif ret = pthread_attr_init(&default_thread_attr); if (ret != 0) { rs_strerror_r(ret, errstr, sizeof(errstr)); fprintf(stderr, "rsyslogd: pthread_attr_init failed during " "startup - can not continue. Error was %s\n", errstr); exit(1); } pthread_attr_setstacksize(&default_thread_attr, 4096 * 1024); #ifdef HAVE_PTHREAD_SETSCHEDPARAM ret = pthread_getschedparam(pthread_self(), &default_thr_sched_policy, &default_sched_param); if (ret != 0) { rs_strerror_r(ret, errstr, sizeof(errstr)); fprintf(stderr, "rsyslogd: pthread_getschedparam failed during " "startup - ignoring. Error was %s\n", errstr); default_thr_sched_policy = 0; /* should be default on all platforms */ } #if defined(_AIX) pthread_attr_setstacksize(&default_thread_attr, 4096 * 512); #endif ret = pthread_attr_setschedpolicy(&default_thread_attr, default_thr_sched_policy); if (ret != 0) { rs_strerror_r(ret, errstr, sizeof(errstr)); fprintf(stderr, "rsyslogd: pthread_attr_setschedpolicy failed during " "startup - tried to set priority %d, now using default " "priority instead. Error was: %s\n", default_thr_sched_policy, errstr); } ret = pthread_attr_setschedparam(&default_thread_attr, &default_sched_param); if (ret != 0) { rs_strerror_r(ret, errstr, sizeof(errstr)); fprintf(stderr, "rsyslogd: pthread_attr_setschedparam failed during " "startup - ignored Error was: %s\n", errstr); } ret = pthread_attr_setinheritsched(&default_thread_attr, PTHREAD_EXPLICIT_SCHED); if (ret != 0) { rs_strerror_r(ret, errstr, sizeof(errstr)); fprintf(stderr, "rsyslogd: pthread_attr_setinheritsched failed during " "startup - ignoring. Error was: %s\n", errstr); } #endif if (ppErrObj != NULL) *ppErrObj = "obj"; CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */ CHKiRet(objGetObjInterface(pObjIF)); /* this provides the root pointer for all other queries */ /* initialize core classes. We must be very careful with the order of events. Some * classes use others and if we do not initialize them in the right order, we may end * up with an invalid call. The most important thing that can happen is that an error * is detected and needs to be logged, wich in turn requires a broader number of classes * to be available. The solution is that we take care in the order of calls AND use a * class immediately after it is initialized. And, of course, we load those classes * first that we use ourselfs... -- rgerhards, 2008-03-07 */ if (ppErrObj != NULL) *ppErrObj = "statsobj"; CHKiRet(statsobjClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "prop"; CHKiRet(propClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "glbl"; CHKiRet(glblClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "msg"; CHKiRet(msgClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "ruleset"; CHKiRet(rulesetClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "wti"; CHKiRet(wtiClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "wtp"; CHKiRet(wtpClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "queue"; CHKiRet(qqueueClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "conf"; CHKiRet(confClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "parser"; CHKiRet(parserClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "strgen"; CHKiRet(strgenClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "rsconf"; CHKiRet(rsconfClassInit(NULL)); if (ppErrObj != NULL) *ppErrObj = "lookup"; CHKiRet(lookupClassInit()); if (ppErrObj != NULL) *ppErrObj = "dynstats"; CHKiRet(dynstatsClassInit()); if (ppErrObj != NULL) *ppErrObj = "perctile_stats"; CHKiRet(perctileClassInit()); /* dummy "classes" */ if (ppErrObj != NULL) *ppErrObj = "str"; CHKiRet(strInit()); } ++iRefCount; dbgprintf("rsyslog runtime initialized, version %s, current users %d\n", VERSION, iRefCount); finalize_it: RETiRet; } /* globally de-initialze the runtime system * NOTE: this is NOT thread safe and must not be called concurrently. If that * ever poses a problem, we may use proper mutex calls - not considered needed yet. * This function must be provided with the caller's obj object pointer. This is * automatically deinitialized by the runtime system. * rgerhards, 2008-04-16 */ rsRetVal rsrtExit(void) { DEFiRet; if (iRefCount == 1) { /* do actual de-init only if we are the last runtime user */ rswatchExit(); confClassExit(); glblClassExit(); rulesetClassExit(); wtiClassExit(); wtpClassExit(); strgenClassExit(); propClassExit(); statsobjClassExit(); objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */ } --iRefCount; /* TODO we must deinit this pointer! pObjIF = NULL; / * no longer exists for this caller */ dbgprintf("rsyslog runtime de-initialized, current users %d\n", iRefCount); RETiRet; } /* returns 0 if the rsyslog runtime is not initialized and another value * if it is. This function is primarily meant to be used by runtime functions * itself. However, it is safe to call it before initializing the runtime. * Plugins should NOT rely on this function. The reason is that another caller * may have already initialized it but deinits it before this plugin is done. * So for plugins and like architectures, the right course of action is to * call rsrtInit() and rsrtExit(), which can be called by multiple callers. * rgerhards, 2008-04-16 */ int rsrtIsInit(void) { return iRefCount; } /* vim:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/parser.c0000644000000000000000000000013215241075234015665 xustar0030 mtime=1787067036.605578294 30 atime=1787067036.752581047 30 ctime=1787067794.298723266 rsyslog-8.2608.0/runtime/parser.c0000664000175000017500000006544115241075234015343 0ustar00rgerrger/* parser.c * This module contains functions for message parsers. It still needs to be * converted into an object (and much extended). * * Module begun 2008-10-09 by Rainer Gerhards (based on previous code from syslogd.c) * * Copyright 2008-2021 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "dirty.h" #include "msg.h" #include "obj.h" #include "datetime.h" #include "errmsg.h" #include "parser.h" #include "ruleset.h" #include "unicode-helper.h" #include "dirty.h" #include "cfsysline.h" /* some defines */ #define DEFUPRI (LOG_USER | LOG_NOTICE) /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(ruleset) /* static data */ static char hexdigit[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; BEGINobjDestruct(parser) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(parser); DBGPRINTF("destructing parser '%s'\n", pThis->pName); if (pThis->pInst != NULL) { pThis->pModule->mod.pm.freeParserInst(pThis->pInst); } free(pThis->pName); ENDobjDestruct(parser) /* destruct a parser list. The list elements are destroyed, but the parser objects * themselves are not modified. (That is done at a late stage during rsyslogd * shutdown and need not be considered here.) */ static rsRetVal DestructParserList(parserList_t **ppListRoot) { parserList_t *pParsLst; parserList_t *pParsLstDel; pParsLst = *ppListRoot; while (pParsLst != NULL) { pParsLstDel = pParsLst; pParsLst = pParsLst->pNext; free(pParsLstDel); } *ppListRoot = NULL; return RS_RET_OK; } /* Add a parser to the list. We use a VERY simple and ineffcient algorithm, * but it is employed only for a few milliseconds during config processing. So * I prefer to keep it very simple and with simple data structures. Unfortunately, * we need to preserve the order, but I don't like to add a tail pointer as that * would require a container object. So I do the extra work to skip to the tail * when adding elements... * rgerhards, 2009-11-03 */ static rsRetVal AddParserToList(parserList_t **ppListRoot, parser_t *pParser) { parserList_t *pThis; parserList_t *pTail; DEFiRet; CHKmalloc(pThis = malloc(sizeof(parserList_t))); pThis->pParser = pParser; pThis->pNext = NULL; if (*ppListRoot == NULL) { pThis->pNext = *ppListRoot; *ppListRoot = pThis; } else { /* find tail first */ for (pTail = *ppListRoot; pTail->pNext != NULL; pTail = pTail->pNext) /* just search, do nothing else */ ; /* add at tail */ pTail->pNext = pThis; } DBGPRINTF("DDDDD: added parser '%s' to list %p\n", pParser->pName, ppListRoot); finalize_it: RETiRet; } void printParserList(parserList_t *pList) { while (pList != NULL) { dbgprintf("parser: %s\n", pList->pParser->pName); pList = pList->pNext; } } /* find a parser based on the provided name */ static rsRetVal FindParser(parserList_t *pParserListRoot, parser_t **ppParser, uchar *pName) { parserList_t *pThis; DEFiRet; for (pThis = pParserListRoot; pThis != NULL; pThis = pThis->pNext) { if (ustrcmp(pThis->pParser->pName, pName) == 0) { *ppParser = pThis->pParser; FINALIZE; /* found it, iRet still eq. OK! */ } } iRet = RS_RET_PARSER_NOT_FOUND; finalize_it: RETiRet; } /* --- END helper functions for parser list handling --- */ /* Add a an already existing parser to the default list. As usual, order * of calls is important (most importantly, that means the legacy parser, * which can process everything, MUST be added last!). * rgerhards, 2009-11-04 */ static rsRetVal AddDfltParser(uchar *pName) { parser_t *pParser; DEFiRet; CHKiRet(FindParser(loadConf->parsers.pParsLstRoot, &pParser, pName)); CHKiRet(AddParserToList(&loadConf->parsers.pDfltParsLst, pParser)); DBGPRINTF("Parser '%s' added to default parser set.\n", pName); finalize_it: RETiRet; } /* set the parser name - string is copied over, call can continue to use it, * but must free it if desired. */ static rsRetVal SetName(parser_t *pThis, uchar *name) { DEFiRet; ISOBJ_TYPE_assert(pThis, parser); assert(name != NULL); if (pThis->pName != NULL) { free(pThis->pName); pThis->pName = NULL; } CHKmalloc(pThis->pName = ustrdup(name)); finalize_it: RETiRet; } /* set a pointer to "our" module. Note that no module * pointer must already be set. */ static rsRetVal SetModPtr(parser_t *pThis, modInfo_t *pMod) { ISOBJ_TYPE_assert(pThis, parser); assert(pMod != NULL); assert(pThis->pModule == NULL); pThis->pModule = pMod; return RS_RET_OK; } /* Specify if we should do standard PRI parsing before we pass the data * down to the parser module. */ static rsRetVal SetDoPRIParsing(parser_t *pThis, int bDoIt) { ISOBJ_TYPE_assert(pThis, parser); pThis->bDoPRIParsing = bDoIt; return RS_RET_OK; } BEGINobjConstruct(parser) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(parser) /* ConstructionFinalizer. The most important chore is to add the parser object * to our global list of available parsers. * rgerhards, 2009-11-03 */ static rsRetVal parserConstructFinalize(parser_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, parser); CHKiRet(AddParserToList(&loadConf->parsers.pParsLstRoot, pThis)); DBGPRINTF("Parser '%s' added to list of available parsers.\n", pThis->pName); finalize_it: RETiRet; } /* construct a parser object via a pointer to the parser module * and the name. This is a separate function because we need it * in multiple spots inside the code. */ rsRetVal parserConstructViaModAndName(modInfo_t *__restrict__ pMod, uchar *const __restrict__ pName, void *pInst) { rsRetVal localRet; parser_t *pParser = NULL; DEFiRet; if (pInst == NULL && pMod->mod.pm.newParserInst != NULL) { /* this happens for the default instance on ModLoad time */ CHKiRet(pMod->mod.pm.newParserInst(NULL, &pInst)); } CHKiRet(parserConstruct(&pParser)); /* check some features */ localRet = pMod->isCompatibleWithFeature(sFEATUREAutomaticSanitazion); if (localRet == RS_RET_OK) { pParser->bDoSanitazion = RSTRUE; } localRet = pMod->isCompatibleWithFeature(sFEATUREAutomaticPRIParsing); if (localRet == RS_RET_OK) { CHKiRet(SetDoPRIParsing(pParser, RSTRUE)); } CHKiRet(SetName(pParser, pName)); CHKiRet(SetModPtr(pParser, pMod)); pParser->pInst = pInst; CHKiRet(parserConstructFinalize(pParser)); finalize_it: if (iRet != RS_RET_OK) free(pParser); RETiRet; } /* uncompress a received message if it is compressed. * pMsg->pszRawMsg buffer is updated. * rgerhards, 2008-10-09 */ static rsRetVal uncompressMessage(smsg_t *pMsg) { DEFiRet; uchar *deflateBuf = NULL; uLongf iLenDefBuf; uchar *pszMsg; size_t lenMsg; assert(pMsg != NULL); pszMsg = pMsg->pszRawMsg; lenMsg = pMsg->iLenRawMsg; /* we first need to check if we have a compressed record. If so, * we must decompress it. */ if (lenMsg > 0 && *pszMsg == 'z' && runConf->globals.bSupportCompressionExtension && !(pMsg->msgFlags & NO_LEGACY_Z_DECOMPRESS)) { /* compressed data present? */ /* we have compressed data, so let's deflate it. We support a maximum * message size of iMaxLine. If it is larger, an error message is logged * and the message is dropped. We do NOT try to decompress larger messages * as such might be used for denial of service. It might happen to later * builds that such functionality be added as an optional, operator-configurable * feature. */ int ret; iLenDefBuf = glbl.GetMaxLine(runConf); CHKmalloc(deflateBuf = malloc(iLenDefBuf + 1)); ret = uncompress((uchar *)deflateBuf, &iLenDefBuf, (uchar *)pszMsg + 1, lenMsg - 1); DBGPRINTF("Compressed message uncompressed with status %d, length: new %ld, old %d.\n", ret, (long)iLenDefBuf, (int)(lenMsg - 1)); /* Now check if the uncompression worked. If not, there is not much we can do. In * that case, we log an error message but ignore the message itself. Storing the * compressed text is dangerous, as it contains control characters. So we do * not do this. If someone would like to have a copy, this code here could be * modified to do a hex-dump of the buffer in question. We do not include * this functionality right now. * rgerhards, 2006-12-07 */ if (ret != Z_OK) { LogError(0, NO_ERRCODE, "Uncompression of a message failed with return code %d " "- enable debug logging if you need further information. " "Message ignored.", ret); FINALIZE; /* unconditional exit, nothing left to do... */ } MsgSetRawMsg(pMsg, (char *)deflateBuf, iLenDefBuf); } finalize_it: if (deflateBuf != NULL) free(deflateBuf); RETiRet; } /* sanitize a received message * if a message gets to large during sanitization, it is truncated. This is * as specified in the upcoming syslog RFC series. * rgerhards, 2008-10-09 * We check if we have a NUL character at the very end of the * message. This seems to be a frequent problem with a number of senders. * So I have now decided to drop these NULs. However, if they are intentional, * that may cause us some problems, e.g. with syslog-sign. On the other hand, * current code always has problems with intentional NULs (as it needs to escape * them to prevent problems with the C string libraries), so that does not * really matter. Just to be on the save side, we'll log destruction of such * NULs in the debug log. * rgerhards, 2007-09-14 */ static rsRetVal SanitizeMsg(smsg_t *pMsg) { DEFiRet; uchar *pszMsg; uchar *pDst; /* destination for copy job */ size_t lenMsg; size_t iSrc; size_t iDst; size_t iMaxLine; size_t maxDest; size_t iFirstSanitize; uchar pc; sbool bUpdatedLen = RSFALSE; uchar szSanBuf[32 * 1024]; /* buffer used for sanitizing a string */ assert(pMsg != NULL); assert(pMsg->iLenRawMsg > 0); pszMsg = pMsg->pszRawMsg; lenMsg = pMsg->iLenRawMsg; /* remove NUL character at end of message (see comment in function header) * Note that we do not need to add a NUL character in this case, because it * is already present ;) */ if (pszMsg[lenMsg - 1] == '\0') { DBGPRINTF("dropped NUL at very end of message\n"); bUpdatedLen = RSTRUE; lenMsg--; } /* then we check if we need to drop trailing LFs, which often make * their way into syslog messages unintentionally. In order to remain * compatible to recent IETF developments, we allow the user to * turn on/off this handling. rgerhards, 2007-07-23 */ if (glbl.GetParserDropTrailingLFOnReception(runConf) && lenMsg > 0 && pszMsg[lenMsg - 1] == '\n') { DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n"); lenMsg--; pszMsg[lenMsg] = '\0'; bUpdatedLen = RSTRUE; } if (glbl.GetParserDropTrailingCROnReception(runConf) && lenMsg > 0 && pszMsg[lenMsg - 1] == '\r') { DBGPRINTF("dropped CR at very end of message (DropTrailingCR is set)\n"); lenMsg--; pszMsg[lenMsg] = '\0'; bUpdatedLen = RSTRUE; } /* it is much quicker to sweep over the message and see if it actually * needs sanitation than to do the sanitation in any case. So we first do * this and terminate when it is not needed - which is expectedly the case * for the vast majority of messages. -- rgerhards, 2009-06-15 * Note that we do NOT check here if tab characters are to be escaped or * not. I expect this functionality to be seldomly used and thus I do not * like to pay the performance penalty. So the penalty is only with those * that actually use it, because we may call the sanitizer without actual * need below (but it then still will work perfectly well!). -- rgerhards, 2009-11-27 */ int bNeedSanitize = 0; iFirstSanitize = lenMsg; for (iSrc = 0; iSrc < lenMsg; iSrc++) { if (pszMsg[iSrc] < 32) { if (glbl.GetParserSpaceLFOnReceive(runConf) && pszMsg[iSrc] == '\n') { pszMsg[iSrc] = ' '; } else if (pszMsg[iSrc] == '\0' || glbl.GetParserEscapeControlCharactersOnReceive(runConf)) { bNeedSanitize = 1; if (iFirstSanitize == lenMsg) iFirstSanitize = iSrc; if (!glbl.GetParserSpaceLFOnReceive(runConf)) { break; } } } else if (pszMsg[iSrc] > 127 && glbl.GetParserEscape8BitCharactersOnReceive(runConf)) { bNeedSanitize = 1; if (iFirstSanitize == lenMsg) iFirstSanitize = iSrc; if (!glbl.GetParserSpaceLFOnReceive(runConf)) { break; } } } if (!bNeedSanitize) { if (bUpdatedLen == RSTRUE) MsgSetRawMsgSize(pMsg, lenMsg); FINALIZE; } iSrc = iFirstSanitize; /* now copy over the message and sanitize it. Note that up to iSrc-1 there was * obviously no need to sanitize, so we can go over that quickly... */ iMaxLine = glbl.GetMaxLine(runConf); maxDest = lenMsg * 4; /* message can grow at most four-fold */ if (maxDest > iMaxLine) maxDest = iMaxLine; /* but not more than the max size! */ if (maxDest < sizeof(szSanBuf)) pDst = szSanBuf; else CHKmalloc(pDst = malloc(maxDest + 1)); if (iSrc > 0) { iSrc--; /* go back to where everything is OK */ if (iSrc > maxDest) { DBGPRINTF( "parser.Sanitize: have oversize index %zd, " "max %zd - corrected, but should not happen\n", iSrc, maxDest); iSrc = maxDest; } memcpy(pDst, pszMsg, iSrc); /* fast copy known good */ } iDst = iSrc; while (iSrc < lenMsg && iDst < maxDest - 3) { /* leave some space if last char must be escaped */ if ((pszMsg[iSrc] < 32) && (pszMsg[iSrc] != '\t' || glbl.GetParserEscapeControlCharacterTab(runConf))) { if (glbl.GetParserSpaceLFOnReceive(runConf) && pszMsg[iSrc] == '\n') { pDst[iDst++] = ' '; iSrc++; continue; } /* note: \0 must always be escaped, the rest of the code currently * can not handle it! -- rgerhards, 2009-08-26 */ if (pszMsg[iSrc] == '\0' || glbl.GetParserEscapeControlCharactersOnReceive(runConf)) { /* we are configured to escape control characters. Please note * that this most probably break non-western character sets like * Japanese, Korean or Chinese. rgerhards, 2007-07-17 */ if (glbl.GetParserEscapeControlCharactersCStyle(runConf)) { pDst[iDst++] = '\\'; switch (pszMsg[iSrc]) { case '\0': pDst[iDst++] = '0'; break; case '\a': pDst[iDst++] = 'a'; break; case '\b': pDst[iDst++] = 'b'; break; case '\x1b': /* equivalent to '\e' which is not accepted by XLC */ pDst[iDst++] = 'e'; break; case '\f': pDst[iDst++] = 'f'; break; case '\n': pDst[iDst++] = 'n'; break; case '\r': pDst[iDst++] = 'r'; break; case '\t': pDst[iDst++] = 't'; break; case '\v': pDst[iDst++] = 'v'; break; default: pDst[iDst++] = 'x'; pc = pszMsg[iSrc]; pDst[iDst++] = hexdigit[(pc & 0xF0) >> 4]; pDst[iDst++] = hexdigit[pc & 0xF]; break; } } else { pDst[iDst++] = glbl.GetParserControlCharacterEscapePrefix(runConf); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0300) >> 6); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0070) >> 3); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0007)); } } } else if (pszMsg[iSrc] > 127 && glbl.GetParserEscape8BitCharactersOnReceive(runConf)) { if (glbl.GetParserEscapeControlCharactersCStyle(runConf)) { pDst[iDst++] = '\\'; pDst[iDst++] = 'x'; pc = pszMsg[iSrc]; pDst[iDst++] = hexdigit[(pc & 0xF0) >> 4]; pDst[iDst++] = hexdigit[pc & 0xF]; } else { /* In this case, we also do the conversion. Note that this most * probably breaks European languages. -- rgerhards, 2010-01-27 */ pDst[iDst++] = glbl.GetParserControlCharacterEscapePrefix(runConf); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0300) >> 6); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0070) >> 3); pDst[iDst++] = '0' + ((pszMsg[iSrc] & 0007)); } } else { pDst[iDst++] = pszMsg[iSrc]; } ++iSrc; } pDst[iDst] = '\0'; MsgSetRawMsg(pMsg, (char *)pDst, iDst); /* save sanitized string */ if (pDst != szSanBuf) free(pDst); finalize_it: RETiRet; } /* Helper to compute the offset immediately after the initial PRI. * Returns the offset of the first byte after the closing '>' if a valid * PRI is found, or -1 if the message does not start with a valid PRI. * Valid PRI format is '<' followed by 1 to 3 decimal digits and '>'. * The PRI value must also be <= LOG_MAXPRI (191). */ static int compute_off_after_pri(const uchar *buf, size_t len, int *pri) { if (len < 3 || buf[0] != '<') { return -1; } if (isdigit(buf[1]) && buf[2] == '>') { if (pri != NULL) { *pri = buf[1] - '0'; } return 3; } if (len >= 4 && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { if (pri != NULL) { *pri = (buf[1] - '0') * 10 + (buf[2] - '0'); } return 4; } if (len >= 5 && isdigit(buf[1]) && isdigit(buf[2]) && isdigit(buf[3]) && buf[4] == '>') { int val = (buf[1] - '0') * 100 + (buf[2] - '0') * 10 + (buf[3] - '0'); if (val <= LOG_MAXPRI) { if (pri != NULL) { *pri = val; } return 5; } } return -1; } /* A standard parser to parse out the PRI. This is made available in * this module as it is expected that allmost all parsers will need * that functionality and so they do not need to implement it themsleves. */ rsRetVal parserParsePRI(smsg_t *pMsg) { syslog_pri_t pri; DEFiRet; /* pull PRI */ pri = DEFUPRI; if (pMsg->msgFlags & NO_PRI_IN_RAW) { /* In this case, simply do so as if the pri would be right at top */ msgSetPRI(pMsg, pri); MsgSetAfterPRIOffs(pMsg, 0); } else { if (pMsg->iLenRawMsg > 0 && pMsg->pszRawMsg[0] == '<') { int parsed_pri = 0; int offs = compute_off_after_pri(pMsg->pszRawMsg, pMsg->iLenRawMsg, &parsed_pri); if (offs != -1) { pri = parsed_pri; msgSetPRI(pMsg, pri); MsgSetAfterPRIOffs(pMsg, offs); } else { pri = LOG_PRI_INVLD; msgSetPRI(pMsg, pri); MsgSetAfterPRIOffs(pMsg, 0); } } else { pri = DEFUPRI; msgSetPRI(pMsg, pri); MsgSetAfterPRIOffs(pMsg, 0); } } RETiRet; } /* Parse a received message. The object's rawmsg property is taken and * parsed according to the relevant standards. This can later be * extended to support configured parsers. * rgerhards, 2008-10-09 */ static rsRetVal ParseMsg(smsg_t *pMsg) { rsRetVal localRet = RS_RET_ERR; parserList_t *pParserList; parser_t *pParser; sbool bIsSanitized; sbool bPRIisParsed; static int iErrMsgRateLimiter = 0; DEFiRet; if (pMsg->iLenRawMsg == 0) ABORT_FINALIZE(RS_RET_EMPTY_MSG); CHKiRet(uncompressMessage(pMsg)); /* we take the risk to print a non-sanitized string, because this is the best we can get * (and that functionality is too important for debugging to drop it...). */ DBGPRINTF("msg parser: flags %x, from '%s', msg '%.60s'\n", pMsg->msgFlags, (pMsg->msgFlags & NEEDS_DNSRESOL) ? UCHAR_CONSTANT("~NOTRESOLVED~") : getRcvFrom(pMsg), pMsg->pszRawMsg); /* we now need to go through our list of parsers and see which one is capable of * parsing the message. Note that the first parser that requires message sanitization * will cause it to happen. After that, access to the unsanitized message is no * loger possible. */ pParserList = ruleset.GetParserList(runConf, pMsg); if (pParserList == NULL) { pParserList = runConf->parsers.pDfltParsLst; } DBGPRINTF("parse using parser list %p%s.\n", pParserList, (pParserList == runConf->parsers.pDfltParsLst) ? " (the default list)" : ""); bIsSanitized = RSFALSE; bPRIisParsed = RSFALSE; while (pParserList != NULL) { pParser = pParserList->pParser; if (pParser->bDoSanitazion && bIsSanitized == RSFALSE) { CHKiRet(SanitizeMsg(pMsg)); if (pParser->bDoPRIParsing && bPRIisParsed == RSFALSE) { CHKiRet(parserParsePRI(pMsg)); bPRIisParsed = RSTRUE; } bIsSanitized = RSTRUE; } if (pParser->pModule->mod.pm.parse2 == NULL) localRet = pParser->pModule->mod.pm.parse(pMsg); else localRet = pParser->pModule->mod.pm.parse2(pParser->pInst, pMsg); DBGPRINTF("Parser '%s' returned %d\n", pParser->pName, localRet); if (localRet != RS_RET_COULD_NOT_PARSE) break; pParserList = pParserList->pNext; } /* We need to log a warning message and drop the message if we did not find a parser. * Note that we log at most the first 1000 message, as this may very well be a problem * that causes a message generation loop. We do not synchronize that counter, it doesn't * matter if we log a handful messages more than we should... */ if (localRet != RS_RET_OK) { if (++iErrMsgRateLimiter < 1000) { LogError(0, localRet, "Error: one message could not be processed by " "any parser, message is being discarded (start of raw msg: '%.60s')", pMsg->pszRawMsg); } DBGPRINTF("No parser could process the message (state %d), we need to discard it.\n", localRet); ABORT_FINALIZE(localRet); } /* "finalize" message object */ pMsg->msgFlags &= ~NEEDS_PARSING; /* this message is now parsed */ finalize_it: RETiRet; } /* This destroys the master parserlist and all of its parser entries. * Parser modules are NOT unloaded, rsyslog does that at a later stage * for all dynamically loaded modules. */ static rsRetVal destroyMasterParserList(parserList_t *pParserListRoot) { DEFiRet; parserList_t *pParsLst; parserList_t *pParsLstDel; pParsLst = pParserListRoot; while (pParsLst != NULL) { parserDestruct(&pParsLst->pParser); pParsLstDel = pParsLst; pParsLst = pParsLst->pNext; free(pParsLstDel); } RETiRet; } /* queryInterface function-- rgerhards, 2009-11-03 */ BEGINobjQueryInterface(parser) CODESTARTobjQueryInterface(parser); if (pIf->ifVersion != parserCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = parserConstruct; pIf->ConstructFinalize = parserConstructFinalize; pIf->Destruct = parserDestruct; pIf->SetName = SetName; pIf->SetModPtr = SetModPtr; pIf->SetDoPRIParsing = SetDoPRIParsing; pIf->ParseMsg = ParseMsg; pIf->SanitizeMsg = SanitizeMsg; pIf->DestructParserList = DestructParserList; pIf->AddParserToList = AddParserToList; pIf->AddDfltParser = AddDfltParser; pIf->FindParser = FindParser; pIf->destroyMasterParserList = destroyMasterParserList; finalize_it: ENDobjQueryInterface(parser) /* Exit our class. * rgerhards, 2009-11-04 */ BEGINObjClassExit(parser, OBJ_IS_CORE_MODULE) /* class, version */ objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDObjClassExit(parser) /* Initialize the parser class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2009-11-02 */ BEGINObjClassInit(parser, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); ENDObjClassInit(parser) rsyslog-8.2608.0/runtime/PaxHeaders/unlimited_select.h0000644000000000000000000000013015132411300017710 xustar0029 mtime=1768559296.27888583 29 atime=1787067620.23847881 30 ctime=1787067794.279722912 rsyslog-8.2608.0/runtime/unlimited_select.h0000666000175000017500000000244115132411300017361 0ustar00rgerrger/* unlimited_select.h * Tweak the macros for accessing fd_set so that the select() syscall * won't be limited to a particular number of file descriptors. * * Copyright 2009-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef UNLIMITED_SELECT_H_INCLUDED #define UNLIMITED_SELECT_H_INCLUDED #include #include #include #include "glbl.h" #ifdef USE_UNLIMITED_SELECT #undef FD_ZERO #define FD_ZERO(set) memset((set), 0, glbl.GetFdSetSize()); #endif #ifdef USE_UNLIMITED_SELECT static inline void freeFdSet(fd_set *p) { free(p); } #else #define freeFdSet(x) #endif #endif /* #ifndef UNLIMITED_SELECT_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/lmcry_gcry.h0000644000000000000000000000013215145046112016544 xustar0030 mtime=1771326538.991013504 30 atime=1783339708.101811397 30 ctime=1787067794.509727198 rsyslog-8.2608.0/runtime/lmcry_gcry.h0000664000175000017500000000247115145046112016214 0ustar00rgerrger/* An implementation of the cryprov interface for libgcrypt. * * Copyright 2013 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LMCRY_GCRY_H #define INCLUDED_LMCRY_GCRY_H #include "cryprov.h" /* interface is defined in cryprov.h, we just implement it! */ #define lmcry_gcryCURR_IF_VERSION cryprovCURR_IF_VERSION typedef cryprov_if_t lmcry_gcry_if_t; /* the lmcry_gcry object */ struct lmcry_gcry_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ gcryctx ctx; }; typedef struct lmcry_gcry_s lmcry_gcry_t; /* prototypes */ PROTOTYPEObjFull(lmcry_gcry); #endif /* #ifndef INCLUDED_LMCRY_GCRY_H */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_gtls.c0000644000000000000000000000013215241075234016206 xustar0030 mtime=1787067036.604578276 30 atime=1787067036.750581009 30 ctime=1787067794.543727831 rsyslog-8.2608.0/runtime/nsd_gtls.c0000664000175000017500000027774115241075234015674 0ustar00rgerrger/* nsd_gtls.c * * An implementation of the nsd interface for GnuTLS. * * Copyright (C) 2007-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include #if GNUTLS_VERSION_NUMBER <= 0x020b00 #include #endif #include #include #include #include #include #include #include "rsyslog.h" #include "syslogd-types.h" #include "module-template.h" #include "cfsysline.h" #include "obj.h" #include "stringbuf.h" #include "errmsg.h" #include "net.h" #include "datetime.h" #include "netstrm.h" #include "netstrms.h" #include "nsd_ptcp.h" #include "nsd_gtls.h" #include "prop.h" #include "unicode-helper.h" #include "rsconf.h" #if GNUTLS_VERSION_NUMBER <= 0x020b00 GCRY_THREAD_OPTION_PTHREAD_IMPL; #endif MODULE_TYPE_LIB MODULE_TYPE_KEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(net) DEFobjCurrIf(datetime) DEFobjCurrIf(nsd_ptcp) DEFobjCurrIf(prop) /* Static Helper variables for certless communication */ static gnutls_anon_client_credentials_t anoncred; /**< client anon credentials */ static gnutls_anon_server_credentials_t anoncredSrv; /**< server anon credentials */ static int dhBits = 2048; /**< number of bits for Diffie-Hellman key */ static int dhMinBits = 512; /**< minimum number of bits for Diffie-Hellman key */ static pthread_mutex_t mutGtlsStrerror; /*< a mutex protecting the potentially non-reentrant gtlStrerror() function */ static inline nsd_gtls_t *nsd_gtls_from_nsd(nsd_t *const pNsd) { return (nsd_gtls_t *)(void *)pNsd; } static gnutls_dh_params_t dh_params; /**< server DH parameters for anon mode */ /* Module-level bitfield for warnings that have been logged (shared across all instances) * NOTE: Intentionally NOT thread-safe. Occasional duplicate warnings (1-2) are acceptable * vs. thousands without this mechanism. Atomic ops/locks are overkill for startup warnings. */ static unsigned loggedWarnings = 0; /* bitfield for warnings that have been logged */ enum { GTLS_LOGGED_WARN_CERT_MISSING = 1 << 0, GTLS_LOGGED_WARN_KEY_MISSING = 1 << 1, GTLS_LOGGED_WARN_CA_MISSING = 1 << 2 }; /* a macro to abort if GnuTLS error is not acceptable. We split this off from * CHKgnutls() to avoid some Coverity report in cases where we know GnuTLS * failed. Note: gnuRet must already be set accordingly! */ #define ABORTgnutls \ { \ uchar *pErr = gtlsStrerror(gnuRet); \ LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); \ free(pErr); \ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \ } /* a macro to check GnuTLS calls against unexpected errors */ #define CHKgnutls(x) \ { \ gnuRet = (x); \ if (gnuRet == GNUTLS_E_FILE_ERROR) { \ LogError(0, RS_RET_GNUTLS_ERR, \ "error reading file - a common cause is that the " \ "file does not exist"); \ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); \ } else if (gnuRet != 0) { \ ABORTgnutls; \ } \ } /* ------------------------------ GnuTLS specifics ------------------------------ */ static rsRetVal doRetry(nsd_gtls_t *pNsd) { DEFiRet; int gnuRet; dbgprintf("doRetry: GnuTLS requested retry of operation %d - executing\n", pNsd->rtryCall); /* We follow a common scheme here: first, we do the systen call and * then we check the result. So far, the result is checked after the * switch, because the result check is the same for all calls. Note that * this may change once we deal with the read and write calls (but * probably this becomes an issue only when we begin to work on TLS * for relp). -- rgerhards, 2008-04-30 */ switch (pNsd->rtryCall) { case gtlsRtry_handshake: gnuRet = gnutls_handshake(pNsd->sess); if (gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) { dbgprintf( "doRetry: GnuTLS handshake retry did not finish - " "setting to retry (this is OK and can happen)\n"); FINALIZE; } else if (gnuRet == 0) { pNsd->rtryCall = gtlsRtry_None; /* we are done */ /* we got a handshake, now check authorization */ CHKiRet(gtlsChkPeerAuth(pNsd)); } else { uchar *pGnuErr = gtlsStrerror(gnuRet); uchar *fromHostIP = NULL; int remotePort; uchar remotePortStr[8]; nsd_ptcp.GetRemoteHName(pNsd->pTcp, &fromHostIP); nsd_ptcp.GetRemotePort(pNsd->pTcp, &remotePort); nsd_ptcp.FmtRemotePortStr(remotePort, remotePortStr, sizeof(remotePortStr)); LogError(0, RS_RET_TLS_HANDSHAKE_ERR, "nsd_gtls:TLS session terminated with remote client '%s:%s': " " GnuTLS handshake retry returned error: %s", fromHostIP, remotePortStr, pGnuErr); free(fromHostIP); free(pGnuErr); ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR); } break; case gtlsRtry_recv: case gtlsRtry_None: default: assert(0); /* this shall not happen! */ dbgprintf("ERROR: pNsd->rtryCall %d invalid in nsd_gtls.c:%d\n", pNsd->rtryCall, __LINE__); gnuRet = 0; /* if it happens, we have at least a defined behaviour... ;) */ break; } if (gnuRet == 0) { pNsd->rtryCall = gtlsRtry_None; /* we are done */ } else if (gnuRet != GNUTLS_E_AGAIN && gnuRet != GNUTLS_E_INTERRUPTED) { uchar *pErr = gtlsStrerror(gnuRet); LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); free(pErr); pNsd->rtryCall = gtlsRtry_None; /* we are also done... ;) */ ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } /* if we are interrupted once again (else case), we do not need to * change our status because we are already setup for retries. */ finalize_it: if (iRet != RS_RET_OK && iRet != RS_RET_CLOSED && iRet != RS_RET_RETRY) pNsd->bAbortConn = 1; /* request abort */ RETiRet; } /* This defines a log function to be provided to GnuTLS. It hopefully * helps us track down hard to find problems. * rgerhards, 2008-06-20 */ static void logFunction(int level, const char *msg) { dbgprintf("GnuTLS log msg, level %d: %s\n", level, msg); } /* read in the whole content of a file. The caller is responsible for * freeing the buffer. To prevent DOS, this function can NOT read * files larger than 1MB (which still is *very* large). * rgerhards, 2008-05-26 */ static rsRetVal readFile(const uchar *const pszFile, gnutls_datum_t *const pBuf) { int fd; struct stat stat_st; DEFiRet; assert(pszFile != NULL); assert(pBuf != NULL); pBuf->data = NULL; if ((fd = open((char *)pszFile, O_RDONLY)) == -1) { LogError(errno, RS_RET_FILE_NOT_FOUND, "can not read file '%s'", pszFile); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (fstat(fd, &stat_st) == -1) { LogError(errno, RS_RET_FILE_NO_STAT, "can not stat file '%s'", pszFile); ABORT_FINALIZE(RS_RET_FILE_NO_STAT); } /* 1MB limit */ if (stat_st.st_size > 1024 * 1024) { LogError(0, RS_RET_FILE_TOO_LARGE, "file '%s' too large, max 1MB", pszFile); ABORT_FINALIZE(RS_RET_FILE_TOO_LARGE); } CHKmalloc(pBuf->data = malloc(stat_st.st_size)); pBuf->size = stat_st.st_size; if (read(fd, pBuf->data, stat_st.st_size) != stat_st.st_size) { LogError(0, RS_RET_IO_ERROR, "error or incomplete read of file '%s'", pszFile); ABORT_FINALIZE(RS_RET_IO_ERROR); } finalize_it: if (fd != -1) close(fd); if (iRet != RS_RET_OK) { if (pBuf->data != NULL) { free(pBuf->data); pBuf->data = NULL; pBuf->size = 0; } } RETiRet; } /* Load the certificate and the private key into our own store. We need to do * this in the client case, to support fingerprint authentication. In that case, * we may be presented no matching root certificate, but we must provide ours. * The only way to do that is via the cert callback interface, but for it we * need to load certificates into our private store. * rgerhards, 2008-05-26 */ static rsRetVal gtlsLoadOurCertKey(nsd_gtls_t *pThis) { DEFiRet; int gnuRet; gnutls_datum_t data = {NULL, 0}; const uchar *keyFile; const uchar *certFile; ISOBJ_TYPE_assert(pThis, nsd_gtls); certFile = (pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile; keyFile = (pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile; if (certFile == NULL || keyFile == NULL) { /* in this case, we can not set our certificate. If we are * a client and the server is running in "anon" auth mode, this * may be well acceptable. In other cases, we will see some * more error messages down the road. -- rgerhards, 2008-07-02 */ dbgprintf("gtlsLoadOurCertKey our certificate is not set, file name values are cert: '%s', key: '%s'\n", certFile, keyFile); ABORT_FINALIZE(RS_RET_CERTLESS); } /* try load certificate */ CHKiRet(readFile(certFile, &data)); pThis->nOurCerts = sizeof(pThis->pOurCerts) / sizeof(gnutls_x509_crt_t); gnuRet = gnutls_x509_crt_list_import(pThis->pOurCerts, &pThis->nOurCerts, &data, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); if (gnuRet < 0) { ABORTgnutls; } pThis->bOurCertIsInit = 1; free(data.data); data.data = NULL; /* try load private key */ CHKiRet(readFile(keyFile, &data)); CHKgnutls(gnutls_x509_privkey_init(&pThis->ourKey)); pThis->bOurKeyIsInit = 1; CHKgnutls(gnutls_x509_privkey_import(pThis->ourKey, &data, GNUTLS_X509_FMT_PEM)); free(data.data); finalize_it: if (iRet == RS_RET_CERTLESS) { dbgprintf("gtlsLoadOurCertKey certless exit\n"); pThis->bOurCertIsInit = 0; pThis->bOurKeyIsInit = 0; } else if (iRet != RS_RET_OK) { dbgprintf("gtlsLoadOurCertKey error exit\n"); if (data.data != NULL) free(data.data); if (pThis->bOurCertIsInit) { for (unsigned i = 0; i < pThis->nOurCerts; ++i) { gnutls_x509_crt_deinit(pThis->pOurCerts[i]); } pThis->bOurCertIsInit = 0; } if (pThis->bOurKeyIsInit) { gnutls_x509_privkey_deinit(pThis->ourKey); pThis->bOurKeyIsInit = 0; } } else { dbgprintf("gtlsLoadOurCertKey Successfully Loaded cert '%s' and key: '%s'\n", certFile, keyFile); } RETiRet; } /* This callback must be associated with a session by calling * gnutls_certificate_client_set_retrieve_function(session, cert_callback), * before a handshake. We will always return the configured certificate, * even if it does not match the peer's trusted CAs. This is necessary * to use self-signed certs in fingerprint mode. And, yes, this usage * of the callback is quite a hack. But it seems the only way to * obey to the IETF -transport-tls I-D. * Note: GnuTLS requires the function to return 0 on success and * -1 on failure. * rgerhards, 2008-05-27 */ static int gtlsClientCertCallback(gnutls_session_t session, __attribute__((unused)) const gnutls_datum_t *req_ca_rdn, int __attribute__((unused)) nreqs, __attribute__((unused)) const gnutls_pk_algorithm_t *sign_algos, int __attribute__((unused)) sign_algos_length, #if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION gnutls_retr2_st *st #else gnutls_retr_st *st #endif ) { nsd_gtls_t *pThis; pThis = (nsd_gtls_t *)gnutls_session_get_ptr(session); #if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION st->cert_type = GNUTLS_CRT_X509; #else st->type = GNUTLS_CRT_X509; #endif st->ncerts = pThis->nOurCerts; st->cert.x509 = pThis->pOurCerts; st->key.x509 = pThis->ourKey; st->deinit_all = 0; return 0; } /* This function extracts some information about this session's peer * certificate. Works for X.509 certificates only. Adds all * of the info to a cstr_t, which is handed over to the caller. * Caller must destruct it when no longer needed. * rgerhards, 2008-05-21 */ static rsRetVal gtlsGetCertInfo(nsd_gtls_t *const pThis, cstr_t **ppStr) { uchar szBufA[1024]; uchar *szBuf = szBufA; size_t szBufLen = sizeof(szBufA), tmp; unsigned int algo, bits; time_t expiration_time, activation_time; const gnutls_datum_t *cert_list; unsigned cert_list_size = 0; gnutls_x509_crt_t cert; cstr_t *pStr = NULL; int gnuRet; DEFiRet; unsigned iAltName; assert(ppStr != NULL); ISOBJ_TYPE_assert(pThis, nsd_gtls); if (gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509) return RS_RET_TLS_CERT_ERR; cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size); CHKiRet(rsCStrConstructFromszStrf(&pStr, "peer provided %d certificate(s). ", cert_list_size)); if (cert_list_size > 0) { /* we only print information about the first certificate */ CHKgnutls(gnutls_x509_crt_init(&cert)); CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); expiration_time = gnutls_x509_crt_get_expiration_time(cert); activation_time = gnutls_x509_crt_get_activation_time(cert); ctime_r(&activation_time, (char *)szBuf); szBuf[ustrlen(szBuf) - 1] = '\0'; /* strip linefeed */ CHKiRet(rsCStrAppendStrf(pStr, "Certificate 1 info: " "certificate valid from %s ", szBuf)); ctime_r(&expiration_time, (char *)szBuf); szBuf[ustrlen(szBuf) - 1] = '\0'; /* strip linefeed */ CHKiRet(rsCStrAppendStrf(pStr, "to %s; ", szBuf)); /* Extract some of the public key algorithm's parameters */ algo = gnutls_x509_crt_get_pk_algorithm(cert, &bits); CHKiRet(rsCStrAppendStrf(pStr, "Certificate public key: %s; ", gnutls_pk_algorithm_get_name(algo))); /* names */ tmp = szBufLen; if (gnutls_x509_crt_get_dn(cert, (char *)szBuf, &tmp) == GNUTLS_E_SHORT_MEMORY_BUFFER) { szBufLen = tmp; szBuf = malloc(tmp); gnutls_x509_crt_get_dn(cert, (char *)szBuf, &tmp); } CHKiRet(rsCStrAppendStrf(pStr, "DN: %s; ", szBuf)); tmp = szBufLen; if (gnutls_x509_crt_get_issuer_dn(cert, (char *)szBuf, &tmp) == GNUTLS_E_SHORT_MEMORY_BUFFER) { szBufLen = tmp; szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp); gnutls_x509_crt_get_issuer_dn(cert, (char *)szBuf, &tmp); } CHKiRet(rsCStrAppendStrf(pStr, "Issuer DN: %s; ", szBuf)); /* dNSName alt name */ iAltName = 0; while (1) { /* loop broken below */ tmp = szBufLen; gnuRet = gnutls_x509_crt_get_subject_alt_name(cert, iAltName, szBuf, &tmp, NULL); if (gnuRet == GNUTLS_E_SHORT_MEMORY_BUFFER) { szBufLen = tmp; szBuf = realloc((szBuf == szBufA) ? NULL : szBuf, tmp); continue; } else if (gnuRet < 0) break; else if (gnuRet == GNUTLS_SAN_DNSNAME) { /* we found it! */ CHKiRet(rsCStrAppendStrf(pStr, "SAN:DNSname: %s; ", szBuf)); /* do NOT break, because there may be multiple dNSName's! */ } else if (gnuRet == GNUTLS_SAN_IPADDRESS) { char ipAddress[INET6_ADDRSTRLEN]; const int family = (tmp == sizeof(struct in6_addr)) ? AF_INET6 : ((tmp == sizeof(struct in_addr)) ? AF_INET : AF_UNSPEC); /* we found it! */ if (family != AF_UNSPEC && inet_ntop(family, szBuf, ipAddress, sizeof(ipAddress)) != NULL) { CHKiRet(rsCStrAppendStrf(pStr, "SAN:IPaddress: %s; ", ipAddress)); } /* do NOT break, because there may be multiple ipAddr's! */ } ++iAltName; } gnutls_x509_crt_deinit(cert); } cstrFinalize(pStr); *ppStr = pStr; finalize_it: if (iRet != RS_RET_OK) { if (pStr != NULL) rsCStrDestruct(&pStr); } if (szBuf != szBufA) free(szBuf); RETiRet; } #if 0 /* we may need this in the future - code needs to be looked at then! */ /* This function will print some details of the * given pThis->sess. */ static rsRetVal print_info(nsd_gtls_t *pThis) { const char *tmp; gnutls_credentials_type cred; gnutls_kx_algorithm kx; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); /* print the key exchange's algorithm name */ kx = gnutls_kx_get(pThis->sess); tmp = gnutls_kx_get_name(kx); dbgprintf("- Key Exchange: %s\n", tmp); /* Check the authentication type used and switch * to the appropriate. */ cred = gnutls_auth_get_type(pThis->sess); switch (cred) { case GNUTLS_CRD_ANON: /* anonymous authentication */ dbgprintf("- Anonymous DH using prime of %d bits\n", gnutls_dh_get_prime_bits(pThis->sess)); break; case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ /* Check if we have been using ephemeral Diffie Hellman. */ if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { dbgprintf("\n- Ephemeral DH using prime of %d bits\n", gnutls_dh_get_prime_bits(pThis->sess)); } /* if the certificate list is available, then * print some information about it. */ gtlsPrintCert(pThis); break; case GNUTLS_CRD_SRP: /* certificate authentication */ dbgprintf("GNUTLS_CRD_SRP/IA"); break; case GNUTLS_CRD_PSK: /* certificate authentication */ dbgprintf("GNUTLS_CRD_PSK"); break; case GNUTLS_CRD_IA: /* certificate authentication */ dbgprintf("GNUTLS_CRD_IA"); break; } /* switch */ /* print the protocol's name (ie TLS 1.0) */ tmp = gnutls_protocol_get_name(gnutls_protocol_get_version(pThis->sess)); dbgprintf("- Protocol: %s\n", tmp); /* print the certificate type of the peer. * ie X.509 */ tmp = gnutls_certificate_type_get_name( gnutls_certificate_type_get(pThis->sess)); dbgprintf("- Certificate Type: %s\n", tmp); /* print the compression algorithm (if any) */ tmp = gnutls_compression_get_name( gnutls_compression_get(pThis->sess)); dbgprintf("- Compression: %s\n", tmp); /* print the name of the cipher used. * ie 3DES. */ tmp = gnutls_cipher_get_name(gnutls_cipher_get(pThis->sess)); dbgprintf("- Cipher: %s\n", tmp); /* Print the MAC algorithms name. * ie SHA1 */ tmp = gnutls_mac_get_name(gnutls_mac_get(pThis->sess)); dbgprintf("- MAC: %s\n", tmp); RETiRet; } #endif /* Convert a fingerprint to printable data. The conversion is carried out * according IETF I-D syslog-transport-tls-12. The fingerprint string is * returned in a new cstr object. It is the caller's responsibility to * destruct that object. * rgerhards, 2008-05-08 */ static rsRetVal GenFingerprintStr(uchar *pFingerprint, size_t sizeFingerprint, cstr_t **ppStr, const char *prefix) { cstr_t *pStr = NULL; uchar buf[4]; size_t i; DEFiRet; CHKiRet(rsCStrConstruct(&pStr)); CHKiRet(rsCStrAppendStrWithLen(pStr, (uchar *)prefix, strlen(prefix))); for (i = 0; i < sizeFingerprint; ++i) { snprintf((char *)buf, sizeof(buf), ":%2.2X", pFingerprint[i]); CHKiRet(rsCStrAppendStrWithLen(pStr, buf, 3)); } cstrFinalize(pStr); *ppStr = pStr; finalize_it: if (iRet != RS_RET_OK) { if (pStr != NULL) rsCStrDestruct(&pStr); } RETiRet; } /* a thread-safe variant of gnutls_strerror * The caller must free the returned string. * rgerhards, 2008-04-30 */ uchar *gtlsStrerror(int error) { uchar *pErr; pthread_mutex_lock(&mutGtlsStrerror); pErr = (uchar *)strdup(gnutls_strerror(error)); pthread_mutex_unlock(&mutGtlsStrerror); return pErr; } /* try to receive a record from the remote peer. This works with * our own abstraction and handles local buffering and EAGAIN. * See details on local buffering in Rcv() header-comment. * This function MUST only be called when the local buffer is * empty. Calling it otherwise will cause losss of current buffer * data. * rgerhards, 2008-06-24 */ rsRetVal gtlsRecordRecv(nsd_gtls_t *const pThis, unsigned int *nextIODirection) { ssize_t lenRcvd; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); DBGPRINTF("gtlsRecordRecv: start (Pending Data: %zd | Wanted Direction: %s)\n", gnutls_record_check_pending(pThis->sess), (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ ? "READ" : "WRITE")); lenRcvd = gnutls_record_recv(pThis->sess, pThis->pszRcvBuf, NSD_GTLS_MAX_RCVBUF); if (lenRcvd >= 0) { DBGPRINTF("gtlsRecordRecv: gnutls_record_recv received %zd bytes\n", lenRcvd); pThis->lenRcvBuf = lenRcvd; pThis->ptrRcvBuf = 0; /* Check for additional data in SSL buffer */ size_t stBytesLeft = gnutls_record_check_pending(pThis->sess); if (stBytesLeft > 0) { DBGPRINTF("gtlsRecordRecv: %zd Bytes pending after gnutls_record_recv, expand buffer.\n", stBytesLeft); /* realloc buffer size and preserve char content */ char *const newbuf = realloc(pThis->pszRcvBuf, NSD_GTLS_MAX_RCVBUF + stBytesLeft); CHKmalloc(newbuf); pThis->pszRcvBuf = newbuf; /* 2nd read will read missing bytes from the current SSL Packet */ lenRcvd = gnutls_record_recv(pThis->sess, pThis->pszRcvBuf + NSD_GTLS_MAX_RCVBUF, stBytesLeft); if (lenRcvd > 0) { DBGPRINTF("gtlsRecordRecv: 2nd SSL_read received %zd bytes\n", (NSD_GTLS_MAX_RCVBUF + lenRcvd)); pThis->lenRcvBuf = NSD_GTLS_MAX_RCVBUF + lenRcvd; } else { if (lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) { goto sslerragain; /* Go to ERR AGAIN handling */ } else { /* Do all other error handling */ int gnuRet = lenRcvd; ABORTgnutls; } } } } else if (lenRcvd == GNUTLS_E_AGAIN || lenRcvd == GNUTLS_E_INTERRUPTED) { sslerragain: /* Check if the underlaying file descriptor needs to read or write data!*/ pThis->rtryCall = gtlsRtry_recv; /* _recv refers to the gnutls call, not socket layer! */ dbgprintf("GnuTLS receive requires a retry, this most probably is OK and no error condition\n"); *nextIODirection = (gnutls_record_get_direction(pThis->sess) == 0) ? NSDSEL_RD : NSDSEL_WR; ABORT_FINALIZE(RS_RET_RETRY); } else { int gnuRet = lenRcvd; ABORTgnutls; } finalize_it: dbgprintf("gtlsRecordRecv return. nsd %p, iRet %d, lenRcvd %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, (int)lenRcvd, pThis->lenRcvBuf, pThis->ptrRcvBuf); RETiRet; } static rsRetVal retrySendSideRecordRecv(nsd_gtls_t *const pThis) { DEFiRet; unsigned int nextIODirection; rsRetVal recvRet; if (pThis->pszRcvBuf == NULL) { CHKmalloc(pThis->pszRcvBuf = malloc(NSD_GTLS_MAX_RCVBUF)); pThis->lenRcvBuf = -1; } if (pThis->lenRcvBuf == -1) { recvRet = gtlsRecordRecv(pThis, &nextIODirection); if (recvRet != RS_RET_OK && recvRet != RS_RET_RETRY) ABORT_FINALIZE(recvRet); if (recvRet == RS_RET_RETRY) ABORT_FINALIZE(RS_RET_RETRY); pThis->rtryCall = gtlsRtry_None; if (pThis->lenRcvBuf == 0) ABORT_FINALIZE(RS_RET_CLOSED); } finalize_it: RETiRet; } /* add our own certificate to the certificate set, so that the peer * can identify us. Please note that we try to use mutual authentication, * so we always add a cert, even if we are in the client role (later, * this may be controlled by a config setting). * rgerhards, 2008-05-15 */ static rsRetVal gtlsAddOurCert(nsd_gtls_t *const pThis) { int gnuRet = 0; const uchar *keyFile; const uchar *certFile; uchar *pGnuErr; /* for GnuTLS error reporting */ DEFiRet; certFile = (pThis->pszCertFile == NULL) ? glbl.GetDfltNetstrmDrvrCertFile(runConf) : pThis->pszCertFile; keyFile = (pThis->pszKeyFile == NULL) ? glbl.GetDfltNetstrmDrvrKeyFile(runConf) : pThis->pszKeyFile; dbgprintf("GTLS certificate file: '%s'\n", certFile); dbgprintf("GTLS key file: '%s'\n", keyFile); if (certFile == NULL && !(loggedWarnings & GTLS_LOGGED_WARN_CERT_MISSING)) { LogError(0, RS_RET_CERT_MISSING, "warning: certificate file is not set"); loggedWarnings |= GTLS_LOGGED_WARN_CERT_MISSING; } if (keyFile == NULL && !(loggedWarnings & GTLS_LOGGED_WARN_KEY_MISSING)) { LogError(0, RS_RET_CERTKEY_MISSING, "warning: key file is not set"); loggedWarnings |= GTLS_LOGGED_WARN_KEY_MISSING; } /* set certificate in gnutls */ if (certFile != NULL && keyFile != NULL) { CHKgnutls( gnutls_certificate_set_x509_key_file(pThis->xcred, (char *)certFile, (char *)keyFile, GNUTLS_X509_FMT_PEM)); } finalize_it: if (iRet != RS_RET_OK && iRet != RS_RET_CERT_MISSING && iRet != RS_RET_CERTKEY_MISSING) { pGnuErr = gtlsStrerror(gnuRet); errno = 0; LogError(0, iRet, "error adding our certificate. GnuTLS error %d, message: '%s', " "key: '%s', cert: '%s'", gnuRet, pGnuErr, keyFile, certFile); free(pGnuErr); } RETiRet; } /* * removecomment ifdef out if needed */ #ifdef false static void print_cipher_suite_list(const char *priorities) { size_t i; int ret; unsigned int idx; const char *name; const char *err; unsigned char id[2]; gnutls_protocol_t version; gnutls_priority_t pcache; if (priorities != NULL) { printf("print_cipher_suite_list: Cipher suites for %s\n", priorities); ret = gnutls_priority_init(&pcache, priorities, &err); if (ret < 0) { fprintf(stderr, "print_cipher_suite_list: Syntax error at: %s\n", err); exit(1); } for (i = 0;; i++) { ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx); if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) continue; name = gnutls_cipher_suite_info(idx, id, NULL, NULL, NULL, &version); if (name != NULL) dbgprintf("print_cipher_suite_list: %-50s\t0x%02x, 0x%02x\t%s\n", name, (unsigned char)id[0], (unsigned char)id[1], gnutls_protocol_get_name(version)); } return; } } #endif /* initialize GnuTLS credential structure (certs etc) */ static rsRetVal gtlsInitCred(nsd_gtls_t *const pThis) { int gnuRet; const uchar *cafile, *crlfile; DEFiRet; /* X509 stuff */ if (pThis->xcred == NULL) { /* Allocate only ONCE */ CHKgnutls(gnutls_certificate_allocate_credentials(&pThis->xcred)); } /* sets the trusted cas file */ cafile = (pThis->pszCAFile == NULL) ? glbl.GetDfltNetstrmDrvrCAF(runConf) : pThis->pszCAFile; if (cafile == NULL && !(loggedWarnings & GTLS_LOGGED_WARN_CA_MISSING)) { LogError(0, RS_RET_CA_CERT_MISSING, "Warning: CA certificate is not set"); loggedWarnings |= GTLS_LOGGED_WARN_CA_MISSING; } if (cafile != NULL) { dbgprintf("GTLS CA file: '%s'\n", cafile); gnuRet = gnutls_certificate_set_x509_trust_file(pThis->xcred, (char *)cafile, GNUTLS_X509_FMT_PEM); if (gnuRet == GNUTLS_E_FILE_ERROR) { LogError(0, RS_RET_GNUTLS_ERR, "error reading certificate file '%s' - a common cause is that the " "file does not exist", cafile); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } else if (gnuRet < 0) { /* TODO; a more generic error-tracking function (this one based on CHKgnutls()) */ uchar *pErr = gtlsStrerror(gnuRet); LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error reading CA certificate file %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); free(pErr); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } } crlfile = (pThis->pszCRLFile == NULL) ? glbl.GetDfltNetstrmDrvrCRLF(runConf) : pThis->pszCRLFile; if (crlfile == NULL) { dbgprintf("Certificate revocation list (CRL) file not set."); } else { gnutls_datum_t crlData; gnutls_x509_crl_t crl; dbgprintf("GTLS CRL file: '%s'\n", crlfile); gnuRet = gnutls_load_file((char *)crlfile, &crlData); if (gnuRet < 0) { LogError(0, RS_RET_GNUTLS_ERR, "error reading Certificate revocation list (CRL) '%s' - a common cause is that the " "file does not exist", crlfile); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } gnuRet = gnutls_x509_crl_init(&crl); if (gnuRet < 0) { gnutls_free(crlData.data); uchar *pErr = gtlsStrerror(gnuRet); LogError(0, RS_RET_GNUTLS_ERR, "error initializing CRL object: %s", pErr); free(pErr); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } gnuRet = gnutls_x509_crl_import(crl, &crlData, GNUTLS_X509_FMT_PEM); if (gnuRet < 0) { gnutls_x509_crl_deinit(crl); gnutls_free(crlData.data); uchar *pErr = gtlsStrerror(gnuRet); LogError(0, RS_RET_GNUTLS_ERR, "error parsing Certificate revocation list (CRL) '%s': %s", crlfile, pErr); free(pErr); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } /* Check CRL validity period. GnuTLS does not do this automatically. */ time_t now = time(NULL); time_t thisUpdate = gnutls_x509_crl_get_this_update(crl); time_t nextUpdate = gnutls_x509_crl_get_next_update(crl); gnutls_x509_crl_deinit(crl); pThis->crlNextUpdate = nextUpdate; dbgprintf("GTLS CRL '%s': thisUpdate=%lld, nextUpdate=%lld, now=%lld\n", crlfile, (long long)thisUpdate, (long long)nextUpdate, (long long)now); if (thisUpdate > 0 && now < thisUpdate) { gnutls_free(crlData.data); LogError(0, RS_RET_CRL_INVALID, "CRL '%s' is not yet valid (thisUpdate is in the future)", crlfile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } if (nextUpdate > 0 && now > nextUpdate) { gnutls_free(crlData.data); LogError(0, RS_RET_CRL_INVALID, "CRL '%s' has expired", crlfile); ABORT_FINALIZE(RS_RET_CRL_INVALID); } dbgprintf("GTLS CRL '%s' validity check passed\n", crlfile); /* Load CRL into credentials (using already-loaded data) */ gnuRet = gnutls_certificate_set_x509_crl_mem(pThis->xcred, &crlData, GNUTLS_X509_FMT_PEM); gnutls_free(crlData.data); if (gnuRet < 0) { uchar *pErr = gtlsStrerror(gnuRet); LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error loading Certificate revocation list (CRL) %d in %s:%d: %s\n", gnuRet, __FILE__, __LINE__, pErr); free(pErr); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } } finalize_it: RETiRet; } /* globally initialize GnuTLS */ static rsRetVal gtlsGlblInit(void) { int gnuRet; DEFiRet; dbgprintf("gtlsGlblInit: Running Version: '%#010x'\n", GNUTLS_VERSION_NUMBER); /* gcry_control must be called first, so that the thread system is correctly set up */ #if GNUTLS_VERSION_NUMBER <= 0x020b00 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif CHKgnutls(gnutls_global_init()); if (GetGnuTLSLoglevel(runConf) > 0) { gnutls_global_set_log_function(logFunction); gnutls_global_set_log_level(GetGnuTLSLoglevel(runConf)); /* 0 (no) to 9 (most), 10 everything */ } /* Init Anon cipher helpers */ CHKgnutls(gnutls_dh_params_init(&dh_params)); CHKgnutls(gnutls_dh_params_generate2(dh_params, dhBits)); /* Allocate ANON Client Cred */ CHKgnutls(gnutls_anon_allocate_client_credentials(&anoncred)); /* Allocate ANON Server Cred */ CHKgnutls(gnutls_anon_allocate_server_credentials(&anoncredSrv)); gnutls_anon_set_server_dh_params(anoncredSrv, dh_params); finalize_it: RETiRet; } static rsRetVal gtlsInitSession(nsd_gtls_t *pThis) { DEFiRet; int gnuRet = 0; gnutls_session_t session; gnutls_init(&session, GNUTLS_SERVER); pThis->bHaveSess = 1; pThis->bIsInitiator = 0; pThis->sess = session; /* Moved CertKey Loading to top */ #if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION /* store a pointer to ourselfs (needed by callback) */ gnutls_session_set_ptr(pThis->sess, (void *)pThis); iRet = gtlsLoadOurCertKey(pThis); /* first load .pem files */ if (iRet == RS_RET_OK) { dbgprintf("gtlsInitSession: enable certificate checking (VerifyDepth=%d)\n", pThis->DrvrVerifyDepth); gnutls_certificate_set_retrieve_function(pThis->xcred, gtlsClientCertCallback); if (pThis->DrvrVerifyDepth != 0) { gnutls_certificate_set_verify_limits(pThis->xcred, 8200, pThis->DrvrVerifyDepth); } } else if (iRet == RS_RET_CERTLESS) { dbgprintf("gtlsInitSession: certificates not configured, not loaded.\n"); } else { ABORT_FINALIZE(iRet); /* we have an error case! */ } #endif /* avoid calling all the priority functions, since the defaults are adequate. */ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_CERTIFICATE, pThis->xcred)); /* check for anon authmode */ if (pThis->authMode == GTLS_AUTH_CERTANON) { dbgprintf("gtlsInitSession: anon authmode, gnutls_credentials_set GNUTLS_CRD_ANON\n"); CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_ANON, anoncredSrv)); gnutls_dh_set_prime_bits(pThis->sess, dhMinBits); } /* request client certificate if any. */ gnutls_certificate_server_set_request(pThis->sess, GNUTLS_CERT_REQUEST); finalize_it: if (iRet != RS_RET_OK && iRet != RS_RET_CERTLESS) { LogError(0, iRet, "gtlsInitSession failed to INIT Session %d", gnuRet); } RETiRet; } /* Obtain the CN from the DN field and hand it back to the caller * (which is responsible for destructing it). We try to follow * RFC2253 as far as it makes sense for our use-case. This function * is considered a compromise providing good-enough correctness while * limiting code size and complexity. If a problem occurs, we may enhance * this function. A (pointer to a) certificate must be caller-provided. * If no CN is contained in the cert, no string is returned * (*ppstrCN remains NULL). *ppstrCN MUST be NULL on entry! * rgerhards, 2008-05-22 */ static rsRetVal gtlsGetCN(gnutls_x509_crt_t *pCert, cstr_t **ppstrCN) { DEFiRet; int gnuRet; int i; int bFound; cstr_t *pstrCN = NULL; size_t size; /* big var the last, so we hope to have all we usually neeed within one mem cache line */ uchar szDN[1024]; /* this should really be large enough for any non-malicious case... */ assert(pCert != NULL); assert(ppstrCN != NULL); assert(*ppstrCN == NULL); size = sizeof(szDN); CHKgnutls(gnutls_x509_crt_get_dn(*pCert, (char *)szDN, &size)); /* now search for the CN part */ i = 0; bFound = 0; while (!bFound && szDN[i] != '\0') { /* note that we do not overrun our string due to boolean shortcut * operations. If we have '\0', the if does not match and evaluation * stops. Order of checks is obviously important! */ if (szDN[i] == 'C' && szDN[i + 1] == 'N' && szDN[i + 2] == '=') { bFound = 1; i += 2; } i++; } if (!bFound) { FINALIZE; /* we are done */ } /* we found a common name, now extract it */ CHKiRet(cstrConstruct(&pstrCN)); while (szDN[i] != '\0' && szDN[i] != ',') { if (szDN[i] == '\\') { /* hex escapes are not implemented */ ++i; /* escape char processed */ if (szDN[i] == '\0') ABORT_FINALIZE(RS_RET_CERT_INVALID_DN); CHKiRet(cstrAppendChar(pstrCN, szDN[i])); } else { CHKiRet(cstrAppendChar(pstrCN, szDN[i])); } ++i; /* char processed */ } cstrFinalize(pstrCN); /* we got it - we ignore the rest of the DN string (if any). So we may * not detect if it contains more than one CN */ *ppstrCN = pstrCN; finalize_it: if (iRet != RS_RET_OK) { if (pstrCN != NULL) cstrDestruct(&pstrCN); } RETiRet; } /* Check the peer's ID in fingerprint auth mode. * rgerhards, 2008-05-22 */ static rsRetVal gtlsChkPeerFingerprint(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert) { uchar fingerprint[20]; uchar fingerprintSha256[32]; size_t size; size_t sizeSha256; cstr_t *pstrFingerprint = NULL; cstr_t *pstrFingerprintSha256 = NULL; int bFoundPositiveMatch; permittedPeers_t *pPeer; int gnuRet; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); /* obtain the SHA1 fingerprint */ size = sizeof(fingerprint); sizeSha256 = sizeof(fingerprintSha256); CHKgnutls(gnutls_x509_crt_get_fingerprint(*pCert, GNUTLS_DIG_SHA1, fingerprint, &size)); CHKgnutls(gnutls_x509_crt_get_fingerprint(*pCert, GNUTLS_DIG_SHA256, fingerprintSha256, &sizeSha256)); CHKiRet(GenFingerprintStr(fingerprint, size, &pstrFingerprint, "SHA1")); CHKiRet(GenFingerprintStr(fingerprintSha256, sizeSha256, &pstrFingerprintSha256, "SHA256")); dbgprintf("peer's certificate SHA1 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprint)); dbgprintf("peer's certificate SHA256 fingerprint: %s\n", cstrGetSzStrNoNULL(pstrFingerprintSha256)); /* now search through the permitted peers to see if we can find a permitted one */ bFoundPositiveMatch = 0; pPeer = pThis->pPermPeers; while (pPeer != NULL && !bFoundPositiveMatch) { if (!rsCStrSzStrCmp(pstrFingerprint, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("gtlsChkPeerFingerprint: peer's certificate SHA1 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else if (!rsCStrSzStrCmp(pstrFingerprintSha256, pPeer->pszID, strlen((char *)pPeer->pszID))) { dbgprintf("gtlsChkPeerFingerprint: peer's certificate SHA256 MATCH found: %s\n", pPeer->pszID); bFoundPositiveMatch = 1; } else { pPeer = pPeer->pNext; } } if (!bFoundPositiveMatch) { dbgprintf("invalid peer fingerprint, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer fingerprint '%s' unknown - we are " "not permitted to talk to it", cstrGetSzStrNoNULL(pstrFingerprint)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } finalize_it: if (pstrFingerprint != NULL) cstrDestruct(&pstrFingerprint); if (pstrFingerprintSha256 != NULL) cstrDestruct(&pstrFingerprintSha256); RETiRet; } /* Perform a match on ONE peer name obtained from the certificate. This name * is checked against the set of configured credentials. *pbFoundPositiveMatch is * set to 1 if the ID matches. *pbFoundPositiveMatch must have been initialized * to 0 by the caller (this is a performance enhancement as we expect to be * called multiple times). * TODO: implemet wildcards? * rgerhards, 2008-05-26 */ static rsRetVal gtlsChkOnePeerName(nsd_gtls_t *pThis, uchar *pszPeerID, int *pbFoundPositiveMatch) { permittedPeers_t *pPeer; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); assert(pszPeerID != NULL); assert(pbFoundPositiveMatch != NULL); if (pThis->pPermPeers) { /* do we have configured peer IDs? */ pPeer = pThis->pPermPeers; while (pPeer != NULL) { CHKiRet(net.PermittedPeerWildcardMatch(pPeer, pszPeerID, pbFoundPositiveMatch)); if (*pbFoundPositiveMatch) break; pPeer = pPeer->pNext; } } else { /* we do not have configured peer IDs, so we use defaults */ if (pThis->pszConnectHost && !strcmp((char *)pszPeerID, (char *)pThis->pszConnectHost)) { *pbFoundPositiveMatch = 1; } } finalize_it: RETiRet; } /* Check the peer's ID in name auth mode. * rgerhards, 2008-05-22 */ static rsRetVal gtlsChkPeerName(nsd_gtls_t *pThis, gnutls_x509_crt_t *pCert) { uchar lnBuf[256]; char szAltName[1024]; /* this is sufficient for the DNSNAME and IPADDRESS... */ int iAltName; char *embeddedNul; size_t szAltNameLen; int bFoundPositiveMatch; int bHaveSAN = 0; cstr_t *pStr = NULL; cstr_t *pstrCN = NULL; int gnuRet; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); bFoundPositiveMatch = 0; CHKiRet(rsCStrConstruct(&pStr)); /* first search through the dNSName subject alt names */ iAltName = 0; while (!bFoundPositiveMatch) { /* loop broken below */ szAltNameLen = sizeof(szAltName); gnuRet = gnutls_x509_crt_get_subject_alt_name(*pCert, iAltName, szAltName, &szAltNameLen, NULL); if (gnuRet < 0) break; else if (gnuRet == GNUTLS_SAN_DNSNAME) { bHaveSAN = 1; if (szAltNameLen == 0 || szAltNameLen >= sizeof(szAltName)) { embeddedNul = NULL; } else { embeddedNul = memchr(szAltName, '\0', szAltNameLen); } if (szAltNameLen == 0 || szAltNameLen >= sizeof(szAltName) || embeddedNul != NULL) { /* GnuTLS returns DNS SAN as raw bytes. Do not let C-string * prefix semantics turn "name\\0.suffix" into authorized * peer "name". Treat malformed DNS SAN bytes as non-matching. */ dbgprintf("subject alt dnsName is malformed, ignoring for name match\n"); CHKiRet(rsCStrAppendStr(pStr, (uchar *)"DNSname: ; ")); ++iAltName; continue; } szAltName[szAltNameLen] = '\0'; dbgprintf("subject alt dnsName: '%s'\n", szAltName); snprintf((char *)lnBuf, sizeof(lnBuf), "DNSname: %s; ", szAltName); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(gtlsChkOnePeerName(pThis, (uchar *)szAltName, &bFoundPositiveMatch)); /* do NOT break, because there may be multiple dNSName's! */ } else if (gnuRet == GNUTLS_SAN_IPADDRESS) { bHaveSAN = 1; const int family = (szAltNameLen == sizeof(struct in6_addr)) ? AF_INET6 : ((szAltNameLen == sizeof(struct in_addr)) ? AF_INET : AF_UNSPEC); if (family != AF_UNSPEC) { char ipAddress[INET6_ADDRSTRLEN]; if (inet_ntop(family, szAltName, ipAddress, INET6_ADDRSTRLEN) != NULL) { dbgprintf("subject alt ipAddr: '%s'\n", ipAddress); snprintf((char *)lnBuf, sizeof(lnBuf), "IPaddress: %s; ", ipAddress); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(gtlsChkOnePeerName(pThis, (uchar *)ipAddress, &bFoundPositiveMatch)); } } /* do NOT break, because there may be multiple ipAddr's! */ } ++iAltName; } /* Check also CN only if not configured per stricter RFC 6125 or no SAN present*/ if (!bFoundPositiveMatch && (!pThis->bSANpriority || !bHaveSAN)) { CHKiRet(gtlsGetCN(pCert, &pstrCN)); if (pstrCN != NULL) { /* NULL if there was no CN present */ dbgprintf("gtls now checking auth for CN '%s'\n", cstrGetSzStrNoNULL(pstrCN)); snprintf((char *)lnBuf, sizeof(lnBuf), "CN: %s; ", cstrGetSzStrNoNULL(pstrCN)); CHKiRet(rsCStrAppendStr(pStr, lnBuf)); CHKiRet(gtlsChkOnePeerName(pThis, cstrGetSzStrNoNULL(pstrCN), &bFoundPositiveMatch)); } } if (!bFoundPositiveMatch) { dbgprintf("invalid peer name, not permitted to talk to it\n"); if (pThis->bReportAuthErr == 1) { cstrFinalize(pStr); errno = 0; LogError(0, RS_RET_INVALID_FINGERPRINT, "error: peer name not authorized - " "not permitted to talk to it. Names: %s", cstrGetSzStrNoNULL(pStr)); pThis->bReportAuthErr = 0; } ABORT_FINALIZE(RS_RET_INVALID_FINGERPRINT); } finalize_it: if (pStr != NULL) rsCStrDestruct(&pStr); if (pstrCN != NULL) rsCStrDestruct(&pstrCN); RETiRet; } static rsRetVal getRemotePeerLogName(nsd_gtls_t *const pThis, uchar **const peer) { prop_t *remoteIP = NULL; DEFiRet; *peer = NULL; if (!pThis->bIsInitiator && nsd_ptcp.GetRemoteIP((nsd_t *)pThis->pTcp, &remoteIP) == RS_RET_OK && remoteIP != NULL) { CHKmalloc(*peer = (uchar *)strdup((const char *)propGetSzStr(remoteIP))); FINALIZE; } CHKiRet(nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, peer)); finalize_it: if (remoteIP != NULL) prop.Destruct(&remoteIP); RETiRet; } /* check the ID of the remote peer - used for both fingerprint and * name authentication. This is common code. Will call into specific * drivers once the certificate has been obtained. * rgerhards, 2008-05-08 */ static rsRetVal gtlsChkPeerID(nsd_gtls_t *pThis) { const gnutls_datum_t *cert_list; unsigned int list_size = 0; gnutls_x509_crt_t cert; int bMustDeinitCert = 0; int gnuRet; DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); /* This function only works for X.509 certificates. */ if (gnutls_certificate_type_get(pThis->sess) != GNUTLS_CRT_X509) return RS_RET_TLS_CERT_ERR; cert_list = gnutls_certificate_get_peers(pThis->sess, &list_size); if (list_size < 1) { if (pThis->bReportAuthErr == 1) { uchar *peer = NULL; errno = 0; pThis->bReportAuthErr = 0; CHKiRet(getRemotePeerLogName(pThis, &peer)); LogError(0, RS_RET_TLS_NO_CERT, "error: peer %s did not provide a certificate, " "not permitted to talk to it", peer); free(peer); } ABORT_FINALIZE(RS_RET_TLS_NO_CERT); } /* If we reach this point, we have at least one valid certificate. * We always use only the first certificate. As of GnuTLS documentation, the * first certificate always contains the remote peer's own certificate. All other * certificates are issuer's certificates (up the chain). We are only interested * in the first certificate, which is our peer. -- rgerhards, 2008-05-08 */ CHKgnutls(gnutls_x509_crt_init(&cert)); bMustDeinitCert = 1; /* indicate cert is initialized and must be freed on exit */ CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER)); /* Now we see which actual authentication code we must call. */ if (pThis->authMode == GTLS_AUTH_CERTFINGERPRINT) { CHKiRet(gtlsChkPeerFingerprint(pThis, &cert)); } else { assert(pThis->authMode == GTLS_AUTH_CERTNAME); CHKiRet(gtlsChkPeerName(pThis, &cert)); } finalize_it: if (bMustDeinitCert) gnutls_x509_crt_deinit(cert); RETiRet; } /* Verify the validity of the remote peer's certificate. * rgerhards, 2008-05-21 */ static rsRetVal gtlsChkPeerCertValidity(nsd_gtls_t *pThis) { DEFiRet; const char *pszErrCause; int gnuRet; cstr_t *pStr = NULL; unsigned stateCert; const gnutls_datum_t *cert_list; unsigned cert_list_size = 0; gnutls_x509_crt_t cert; unsigned i; time_t ttCert; time_t ttNow; sbool bAbort = RSFALSE; int iAbortCode = RS_RET_OK; ISOBJ_TYPE_assert(pThis, nsd_gtls); /* check if we have at least one cert */ cert_list = gnutls_certificate_get_peers(pThis->sess, &cert_list_size); if (cert_list_size < 1) { errno = 0; uchar *peer = NULL; CHKiRet(getRemotePeerLogName(pThis, &peer)); LogError(0, RS_RET_TLS_NO_CERT, "peer %s did not provide a certificate, not permitted to talk to it", peer); free(peer); ABORT_FINALIZE(RS_RET_TLS_NO_CERT); } #ifdef EXTENDED_CERT_CHECK_AVAILABLE if (pThis->dataTypeCheck == GTLS_NONE) { #endif CHKgnutls(gnutls_certificate_verify_peers2(pThis->sess, &stateCert)); #ifdef EXTENDED_CERT_CHECK_AVAILABLE } else { /* we have configured data to check in addition to cert */ gnutls_typed_vdata_st data; data.type = GNUTLS_DT_KEY_PURPOSE_OID; if (pThis->bIsInitiator) { /* client mode */ data.data = (uchar *)GNUTLS_KP_TLS_WWW_SERVER; } else { /* server mode */ data.data = (uchar *)GNUTLS_KP_TLS_WWW_CLIENT; } data.size = ustrlen(data.data); CHKgnutls(gnutls_certificate_verify_peers(pThis->sess, &data, 1, &stateCert)); } #endif if (stateCert & GNUTLS_CERT_INVALID) { /* Default abort code */ iAbortCode = RS_RET_CERT_INVALID; /* provide error details if we have them */ if (stateCert & GNUTLS_CERT_EXPIRED) { dbgprintf("GnuTLS returned GNUTLS_CERT_EXPIRED, handling mode %d ...\n", pThis->permitExpiredCerts); /* Handle expired certs */ if (pThis->permitExpiredCerts == GTLS_EXPIRED_DENY) { bAbort = RSTRUE; iAbortCode = RS_RET_CERT_EXPIRED; } else if (pThis->permitExpiredCerts == GTLS_EXPIRED_WARN) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_WARNING, "Warning, certificate expired but expired certs are permitted"); } else { dbgprintf("GnuTLS returned GNUTLS_CERT_EXPIRED, but expired certs are permitted.\n"); } pszErrCause = "certificate expired"; } else if (stateCert & GNUTLS_CERT_SIGNER_NOT_FOUND) { pszErrCause = "signer not found"; bAbort = RSTRUE; } else if (stateCert & GNUTLS_CERT_SIGNER_NOT_CA) { pszErrCause = "signer is not a CA"; bAbort = RSTRUE; } else if (stateCert & GNUTLS_CERT_INSECURE_ALGORITHM) { pszErrCause = "insecure algorithm"; bAbort = RSTRUE; } else if (stateCert & GNUTLS_CERT_REVOKED) { pszErrCause = "certificate revoked"; bAbort = RSTRUE; iAbortCode = RS_RET_CERT_REVOKED; #ifdef EXTENDED_CERT_CHECK_AVAILABLE } else if (stateCert & GNUTLS_CERT_PURPOSE_MISMATCH) { pszErrCause = "key purpose OID does not match"; bAbort = RSTRUE; #endif } else { pszErrCause = "GnuTLS returned no specific reason"; dbgprintf( "GnuTLS returned no specific reason for GNUTLS_CERT_INVALID, certificate " "status is %d\n", stateCert); bAbort = RSTRUE; } } if (bAbort == RSTRUE) { uchar *fromHost = NULL; nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHost); LogError(0, NO_ERRCODE, "not permitted to talk to peer '%s', certificate invalid: %s", fromHost, pszErrCause); free(fromHost); gtlsGetCertInfo(pThis, &pStr); LogError(0, NO_ERRCODE, "invalid cert info: %s", cstrGetSzStrNoNULL(pStr)); cstrDestruct(&pStr); ABORT_FINALIZE(iAbortCode); } /* get current time for certificate validation */ if (datetime.GetTime(&ttNow) == -1) ABORT_FINALIZE(RS_RET_SYS_ERR); /* as it looks, we need to validate the expiration dates ourselves... * We need to loop through all certificates as we need to make sure the * interim certificates are also not expired. */ for (i = 0; i < cert_list_size; ++i) { CHKgnutls(gnutls_x509_crt_init(&cert)); CHKgnutls(gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER)); ttCert = gnutls_x509_crt_get_activation_time(cert); if (ttCert == -1) ABORT_FINALIZE(RS_RET_TLS_CERT_ERR); else if (ttCert > ttNow) { uchar *fromHost = NULL; nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHost); LogError(0, RS_RET_CERT_NOT_YET_ACTIVE, "not permitted to talk to peer '%s': " "certificate %d not yet active", fromHost, i); free(fromHost); gtlsGetCertInfo(pThis, &pStr); LogError(0, RS_RET_CERT_NOT_YET_ACTIVE, "invalid cert info: %s", cstrGetSzStrNoNULL(pStr)); cstrDestruct(&pStr); ABORT_FINALIZE(RS_RET_CERT_NOT_YET_ACTIVE); } gnutls_x509_crt_deinit(cert); } finalize_it: RETiRet; } /* Check if the cached CRL has expired since startup. * Called on each TLS handshake to match OpenSSL behavior. */ static rsRetVal gtlsChkCrlValidity(nsd_gtls_t *pThis) { DEFiRet; if (pThis->crlNextUpdate > 0 && time(NULL) > pThis->crlNextUpdate) { uchar *fromHost = NULL; nsd_ptcp.GetRemoteHName((nsd_t *)pThis->pTcp, &fromHost); LogError(0, RS_RET_CRL_INVALID, "CRL has expired (nextUpdate passed), rejecting peer '%s'", fromHost); free(fromHost); ABORT_FINALIZE(RS_RET_CRL_INVALID); } finalize_it: RETiRet; } /* check if it is OK to talk to the remote peer * rgerhards, 2008-05-21 */ rsRetVal gtlsChkPeerAuth(nsd_gtls_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); CHKiRet(gtlsChkCrlValidity(pThis)); /* call the actual function based on current auth mode */ switch (pThis->authMode) { case GTLS_AUTH_CERTNAME: /* if we check the name, we must ensure the cert is valid */ CHKiRet(gtlsChkPeerCertValidity(pThis)); CHKiRet(gtlsChkPeerID(pThis)); break; case GTLS_AUTH_CERTFINGERPRINT: CHKiRet(gtlsChkPeerID(pThis)); break; case GTLS_AUTH_CERTVALID: CHKiRet(gtlsChkPeerCertValidity(pThis)); break; case GTLS_AUTH_CERTANON: FINALIZE; break; default: // No action needed for other cases break; } finalize_it: RETiRet; } /* globally de-initialize GnuTLS */ static rsRetVal gtlsGlblExit(void) { DEFiRet; gnutls_anon_free_server_credentials(anoncredSrv); gnutls_dh_params_deinit(dh_params); gnutls_global_deinit(); RETiRet; } /* end a GnuTLS session * The function checks if we have a session and ends it only if so. So it can * always be called, even if there currently is no session. */ static rsRetVal gtlsEndSess(nsd_gtls_t *pThis) { int gnuRet; DEFiRet; if (pThis->bHaveSess) { if (pThis->bIsInitiator) { gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_WR); while (gnuRet == GNUTLS_E_INTERRUPTED || gnuRet == GNUTLS_E_AGAIN) { gnuRet = gnutls_bye(pThis->sess, GNUTLS_SHUT_WR); } } gnutls_deinit(pThis->sess); pThis->bHaveSess = 0; } RETiRet; } /* a small wrapper for gnutls_transport_set_ptr(). The main intension for * creating this wrapper is to get the annoying "cast to pointer from different * size" compiler warning just once. There seems to be no way around it, see: * http://lists.gnu.org/archive/html/help-gnutls/2008-05/msg00000.html * rgerhards, 2008.05-07 */ #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static inline void gtlsSetTransportPtr(nsd_gtls_t *pThis, int sock) { /* Note: the compiler warning for the next line is OK - see header comment! */ gnutls_transport_set_ptr(pThis->sess, (gnutls_transport_ptr_t)sock); } #pragma GCC diagnostic warning "-Wint-to-pointer-cast" /* ---------------------------- end GnuTLS specifics ---------------------------- */ /* Standard-Constructor */ BEGINobjConstruct(nsd_gtls) /* be sure to specify the object type also in END macro! */ iRet = nsd_ptcp.Construct(&pThis->pTcp); pThis->bReportAuthErr = 1; ENDobjConstruct(nsd_gtls) /* destructor for the nsd_gtls object */ BEGINobjDestruct(nsd_gtls) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(nsd_gtls); if (pThis->iMode == 1) { gtlsEndSess(pThis); } if (pThis->pTcp != NULL) { nsd_ptcp.Destruct(&pThis->pTcp); } free(pThis->pszConnectHost); free(pThis->pszRcvBuf); free((void *)pThis->pszCAFile); free((void *)pThis->pszCRLFile); free(pThis->remoteSNI); if (pThis->bOurCertIsInit) for (unsigned i = 0; i < pThis->nOurCerts; ++i) { gnutls_x509_crt_deinit(pThis->pOurCerts[i]); } if (pThis->bOurKeyIsInit) gnutls_x509_privkey_deinit(pThis->ourKey); if (pThis->bHaveSess) gnutls_deinit(pThis->sess); if (pThis->xcred != NULL && (pThis->bIsInitiator || (!pThis->xcred_is_copy && (!pThis->bIsInitiator || pThis->bHaveSess)))) { gnutls_certificate_free_credentials(pThis->xcred); free((void *)pThis->pszKeyFile); free((void *)pThis->pszCertFile); } ENDobjDestruct(nsd_gtls) /* Set the driver mode. For us, this has the following meaning: * 0 - work in plain tcp mode, without tls (e.g. before a STARTTLS) * 1 - work in TLS mode * rgerhards, 2008-04-28 */ static rsRetVal SetMode(nsd_t *const pNsd, const int mode) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); dbgprintf("(tls) mode: %d\n", mode); if (mode != 0 && mode != 1) { LogError(0, RS_RET_INVALID_DRVR_MODE, "error: driver mode %d not supported by " "gtls netstream driver", mode); ABORT_FINALIZE(RS_RET_INVALID_DRVR_MODE); } pThis->iMode = mode; finalize_it: RETiRet; } /* Set the authentication mode. For us, the following is supported: * anon - no certificate checks whatsoever (discouraged, but supported) * x509/certvalid - (just) check certificate validity * x509/fingerprint - certificate fingerprint * x509/name - cerfificate name check * mode == NULL is valid and defaults to x509/name * rgerhards, 2008-05-16 */ static rsRetVal SetAuthMode(nsd_t *pNsd, uchar *mode) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (mode == NULL || !strcasecmp((char *)mode, "x509/name")) { pThis->authMode = GTLS_AUTH_CERTNAME; } else if (!strcasecmp((char *)mode, "x509/fingerprint")) { pThis->authMode = GTLS_AUTH_CERTFINGERPRINT; } else if (!strcasecmp((char *)mode, "x509/certvalid")) { pThis->authMode = GTLS_AUTH_CERTVALID; } else if (!strcasecmp((char *)mode, "anon")) { pThis->authMode = GTLS_AUTH_CERTANON; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: authentication mode '%s' not supported by " "gtls netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetAuthMode to %s\n", (mode != NULL ? (char *)mode : "NULL")); /* TODO: clear stored IDs! */ finalize_it: RETiRet; } /* Set the PermitExpiredCerts mode. For us, the following is supported: * on - fail if certificate is expired * off - ignore expired certificates * warn - warn if certificate is expired * alorbach, 2018-12-20 */ static rsRetVal SetPermitExpiredCerts(nsd_t *pNsd, uchar *mode) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); /* default is set to off! */ if (mode == NULL || !strcasecmp((char *)mode, "off")) { pThis->permitExpiredCerts = GTLS_EXPIRED_DENY; } else if (!strcasecmp((char *)mode, "warn")) { pThis->permitExpiredCerts = GTLS_EXPIRED_WARN; } else if (!strcasecmp((char *)mode, "on")) { pThis->permitExpiredCerts = GTLS_EXPIRED_PERMIT; } else { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: permitexpiredcerts mode '%s' not supported by " "gtls netstream driver", mode); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } dbgprintf("SetPermitExpiredCerts: Set Mode %s/%d\n", (mode != NULL ? (char *)mode : "NULL"), pThis->permitExpiredCerts); /* TODO: clear stored IDs! */ finalize_it: RETiRet; } /* Set permitted peers. It is depending on the auth mode if this are * fingerprints or names. -- rgerhards, 2008-05-19 */ static rsRetVal SetPermPeers(nsd_t *pNsd, permittedPeers_t *pPermPeers) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (pPermPeers == NULL) FINALIZE; if (pThis->authMode != GTLS_AUTH_CERTFINGERPRINT && pThis->authMode != GTLS_AUTH_CERTNAME) { LogError(0, RS_RET_VALUE_NOT_IN_THIS_MODE, "authentication not supported by " "gtls netstream driver in the configured authentication mode - ignored"); ABORT_FINALIZE(RS_RET_VALUE_NOT_IN_THIS_MODE); } pThis->pPermPeers = pPermPeers; finalize_it: RETiRet; } /* gnutls priority string * PascalWithopf 2017-08-16 */ static rsRetVal SetGnutlsPriorityString(nsd_t *pNsd, uchar *gnutlsPriorityString) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); pThis->gnutlsPriorityString = gnutlsPriorityString; dbgprintf("gnutlsPriorityString: set to '%s'\n", (gnutlsPriorityString != NULL ? (char *)gnutlsPriorityString : "NULL")); RETiRet; } /* Set the driver cert extended key usage check setting * 0 - ignore contents of extended key usage * 1 - verify that cert contents is compatible with appropriate OID * jvymazal, 2019-08-16 */ static rsRetVal SetCheckExtendedKeyUsage(nsd_t *pNsd, int ChkExtendedKeyUsage) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (ChkExtendedKeyUsage != 0 && ChkExtendedKeyUsage != 1) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver ChkExtendedKeyUsage %d " "not supported by gtls netstream driver", ChkExtendedKeyUsage); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } pThis->dataTypeCheck = ChkExtendedKeyUsage; finalize_it: RETiRet; } /* Set the driver name checking strictness * 0 - less strict per RFC 5280, section 4.1.2.6 - either SAN or CN match is good * 1 - more strict per RFC 6125 - if any SAN present it must match (CN is ignored) * jvymazal, 2019-08-16 */ static rsRetVal SetPrioritizeSAN(nsd_t *pNsd, int prioritizeSan) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (prioritizeSan != 0 && prioritizeSan != 1) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: driver prioritizeSan %d " "not supported by gtls netstream driver", prioritizeSan); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } pThis->bSANpriority = prioritizeSan; finalize_it: RETiRet; } /* Set the driver tls verifyDepth * alorbach, 2019-12-20 */ static rsRetVal SetTlsVerifyDepth(nsd_t *pNsd, int verifyDepth) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (verifyDepth == 0) { FINALIZE; } assert(verifyDepth >= 2); pThis->DrvrVerifyDepth = verifyDepth; finalize_it: RETiRet; } static rsRetVal SetTlsCAFile(nsd_t *pNsd, const uchar *const caFile) { DEFiRet; nsd_gtls_t *const pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (caFile == NULL) { pThis->pszCAFile = NULL; } else { CHKmalloc(pThis->pszCAFile = (const uchar *)strdup((const char *)caFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCRLFile(nsd_t *pNsd, const uchar *const crlFile) { DEFiRet; nsd_gtls_t *const pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (crlFile == NULL) { pThis->pszCRLFile = NULL; } else { CHKmalloc(pThis->pszCRLFile = (const uchar *)strdup((const char *)crlFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCAExtraFiles(nsd_t __attribute__((unused)) * pNsd, const uchar *const pszFile) { DEFiRet; if (pszFile != NULL) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: extra CA Files setting not supported by " "gtls netstream driver"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } static rsRetVal SetTlsKeyFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_gtls_t *const pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (pszFile == NULL) { pThis->pszKeyFile = NULL; } else { CHKmalloc(pThis->pszKeyFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } static rsRetVal SetTlsCertFile(nsd_t *pNsd, const uchar *const pszFile) { DEFiRet; nsd_gtls_t *const pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); if (pszFile == NULL) { pThis->pszCertFile = NULL; } else { CHKmalloc(pThis->pszCertFile = (const uchar *)strdup((const char *)pszFile)); } finalize_it: RETiRet; } /* Set the TLS SNI of the remote server */ static rsRetVal SetRemoteSNI(nsd_t *pNsd, uchar *remoteSNI) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); free(pThis->remoteSNI); if (remoteSNI == NULL) { pThis->remoteSNI = NULL; } else { CHKmalloc(pThis->remoteSNI = (uchar *)strdup((char *)remoteSNI)); } finalize_it: RETiRet; } static rsRetVal SetTlsRevocationCheck(nsd_t *pNsd, int enabled) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); pThis->DrvrTlsRevocationCheck = (enabled != 0) ? 1 : 0; if (pThis->DrvrTlsRevocationCheck) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "error: TLS revocation checking not supported by " "gtls netstream driver (GnuTLS does not implement OCSP checking)"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: RETiRet; } /* Provide access to the underlying OS socket. This is primarily * useful for other drivers (like nsd_gtls) who utilize ourselfs * for some of their functionality. -- rgerhards, 2008-04-18 */ static rsRetVal SetSock(nsd_t *pNsd, int sock) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(sock >= 0); nsd_ptcp.SetSock(pThis->pTcp, sock); RETiRet; } static rsRetVal GetRemotePort(nsd_t *pNsd, int *port) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); return nsd_ptcp.GetRemotePort(pThis->pTcp, port); } static rsRetVal FmtRemotePortStr(const int port, uchar *const buf, const size_t len) { return nsd_ptcp.FmtRemotePortStr(port, buf, len); } /* Keep Alive Options */ static rsRetVal SetKeepAliveIntvl(nsd_t *pNsd, int keepAliveIntvl) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(keepAliveIntvl >= 0); nsd_ptcp.SetKeepAliveIntvl(pThis->pTcp, keepAliveIntvl); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveProbes(nsd_t *pNsd, int keepAliveProbes) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(keepAliveProbes >= 0); nsd_ptcp.SetKeepAliveProbes(pThis->pTcp, keepAliveProbes); RETiRet; } /* Keep Alive Options */ static rsRetVal SetKeepAliveTime(nsd_t *pNsd, int keepAliveTime) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(keepAliveTime >= 0); nsd_ptcp.SetKeepAliveTime(pThis->pTcp, keepAliveTime); RETiRet; } /* TCP user timeout option */ static rsRetVal SetTcpUserTimeout(nsd_t *pNsd, int tcpUserTimeout) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert((pThis), nsd_gtls); assert(tcpUserTimeout >= 0); nsd_ptcp.SetTcpUserTimeout(pThis->pTcp, tcpUserTimeout); RETiRet; } /* abort a connection. This is meant to be called immediately * before the Destruct call. -- rgerhards, 2008-03-24 */ static rsRetVal Abort(nsd_t *pNsd) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); DEFiRet; ISOBJ_TYPE_assert((pThis), nsd_gtls); if (pThis->iMode == 0) { nsd_ptcp.Abort(pThis->pTcp); } RETiRet; } /* Callback after netstrm obj init in nsd_ptcp - permits us to add some data */ static rsRetVal LstnInitDrvr(netstrm_t *const pThis) { DEFiRet; CHKiRet(gtlsInitCred(nsd_gtls_from_nsd(pThis->pDrvrData))); CHKiRet(gtlsAddOurCert(nsd_gtls_from_nsd(pThis->pDrvrData))); finalize_it: RETiRet; } /* initialize the tcp socket for a listner * Here, we use the ptcp driver - because there is nothing special * at this point with GnuTLS. Things become special once we accept * a session, but not during listener setup. * gerhards, 2008-04-25 */ static rsRetVal ATTR_NONNULL(1, 3, 5) LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal (*fAddLstn)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params) { DEFiRet; pNS->fLstnInitDrvr = LstnInitDrvr; iRet = nsd_ptcp.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params); // finalize_it: RETiRet; } /* This function checks if the connection is still alive - well, kind of... * This is a dummy here. For details, check function common in ptcp driver. * rgerhards, 2008-06-09 */ static rsRetVal CheckConnection(nsd_t __attribute__((unused)) * pNsd) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); dbgprintf("CheckConnection for %p\n", pNsd); return nsd_ptcp.CheckConnection(pThis->pTcp); } /* Provide access to the underlying OS socket. */ static rsRetVal GetSock(nsd_t *pNsd, int *pSock) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); return nsd_ptcp.GetSock(pThis->pTcp, pSock); } /* get the remote hostname. The returned hostname must be freed by the caller. * rgerhards, 2008-04-25 */ static rsRetVal GetRemoteHName(nsd_t *pNsd, uchar **ppszHName) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); iRet = nsd_ptcp.GetRemoteHName(pThis->pTcp, ppszHName); RETiRet; } /* Provide access to the sockaddr_storage of the remote peer. This * is needed by the legacy ACL system. --- gerhards, 2008-12-01 */ static rsRetVal GetRemAddr(nsd_t *pNsd, struct sockaddr_storage **ppAddr) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); iRet = nsd_ptcp.GetRemAddr(pThis->pTcp, ppAddr); RETiRet; } /* get the remote host's IP address. Caller must Destruct the object. */ static rsRetVal GetRemoteIP(nsd_t *pNsd, prop_t **ip) { DEFiRet; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); iRet = nsd_ptcp.GetRemoteIP(pThis->pTcp, ip); RETiRet; } /* accept an incoming connection request - here, we do the usual accept * handling. TLS specific handling is done thereafter (and if we run in TLS * mode at this time). * rgerhards, 2008-04-25 */ static rsRetVal AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew, char *const connInfo) { DEFiRet; int gnuRet; nsd_gtls_t *pNew = NULL; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); const char *error_position = NULL; ISOBJ_TYPE_assert((pThis), nsd_gtls); CHKiRet(nsd_gtlsConstruct(&pNew)); // TODO: prevent construct/destruct! CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp)); CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp, connInfo)); if (pThis->iMode == 0) { /* we are in non-TLS mode, so we are done */ *ppNew = (nsd_t *)pNew; FINALIZE; } /* copy Properties to pnew first */ pNew->authMode = pThis->authMode; pNew->permitExpiredCerts = pThis->permitExpiredCerts; pNew->pPermPeers = pThis->pPermPeers; pNew->gnutlsPriorityString = pThis->gnutlsPriorityString; pNew->DrvrVerifyDepth = pThis->DrvrVerifyDepth; pNew->DrvrTlsRevocationCheck = pThis->DrvrTlsRevocationCheck; pNew->crlNextUpdate = pThis->crlNextUpdate; pNew->dataTypeCheck = pThis->dataTypeCheck; pNew->bSANpriority = pThis->bSANpriority; pNew->pszCertFile = pThis->pszCertFile; pNew->pszKeyFile = pThis->pszKeyFile; pNew->xcred = pThis->xcred; // TODO: verify once again; xcred is read only at this stage pNew->xcred_is_copy = 1; // do not free on pNew Destruction /* if we reach this point, we are in TLS mode */ iRet = gtlsInitSession(pNew); if (iRet != RS_RET_OK) { if (iRet == RS_RET_CERTLESS) { dbgprintf("AcceptConnReq certless mode\n"); /* Set status to OK */ iRet = RS_RET_OK; } else { goto finalize_it; } } gtlsSetTransportPtr(pNew, ((nsd_ptcp_t *)(pNew->pTcp))->sock); dbgprintf("AcceptConnReq bOurCertIsInit=%hu bOurKeyIsInit=%hu \n", pNew->bOurCertIsInit, pNew->bOurKeyIsInit); /* here is the priorityString set */ if (pNew->gnutlsPriorityString != NULL) { dbgprintf("AcceptConnReq setting configured priority string (ciphers)\n"); if (gnutls_priority_set_direct(pNew->sess, (const char *)pNew->gnutlsPriorityString, &error_position) == GNUTLS_E_INVALID_REQUEST) { LogError(0, RS_RET_GNUTLS_ERR, "Syntax error or unsupported option in " "Priority String near: \"%s\"\n", error_position); } } else { if (pThis->authMode == GTLS_AUTH_CERTANON) { /* Allow ANON Ciphers */ dbgprintf("AcceptConnReq setting anon ciphers Try1: %s\n", GTLS_ANON_PRIO_NOTLSV13); if (gnutls_priority_set_direct(pNew->sess, (const char *)GTLS_ANON_PRIO_NOTLSV13, &error_position) == GNUTLS_E_INVALID_REQUEST) { dbgprintf("AcceptConnReq setting anon ciphers Try2 (TLS1.3 unknown): %s\n", GTLS_ANON_PRIO); CHKgnutls(gnutls_priority_set_direct(pNew->sess, GTLS_ANON_PRIO, &error_position)); } /* Uncomment for DEBUG print_cipher_suite_list("NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL"); */ } else { /* Use default priorities */ dbgprintf("AcceptConnReq setting default ciphers\n"); CHKgnutls(gnutls_set_default_priority(pNew->sess)); } } /* we now do the handshake. This is a bit complicated, because we are * on non-blocking sockets. Usually, the handshake will not complete * immediately, so that we need to retry it some time later. */ gnuRet = gnutls_handshake(pNew->sess); if (gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) { pNew->rtryCall = gtlsRtry_handshake; dbgprintf( "GnuTLS handshake does not complete immediately - " "setting to retry (this is OK and normal)\n"); } else if (gnuRet == 0) { /* we got a handshake, now check authorization */ CHKiRet(gtlsChkPeerAuth(pNew)); } else { uchar *pGnuErr = gtlsStrerror(gnuRet); uchar *fromHostIP = NULL; int remotePort; uchar remotePortStr[8]; nsd_ptcp.GetRemoteHName((nsd_t *)pNew->pTcp, &fromHostIP); nsd_ptcp.GetRemotePort((nsd_t *)pNew->pTcp, &remotePort); nsd_ptcp.FmtRemotePortStr(remotePort, remotePortStr, sizeof(remotePortStr)); LogError(0, RS_RET_TLS_HANDSHAKE_ERR, "nsd_gtls:TLS session terminated with remote client '%s:%s': " "gnutls returned error on handshake: %s", fromHostIP, remotePortStr, pGnuErr); free(fromHostIP); free(pGnuErr); ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR); } pNew->iMode = 1; /* this session is now in TLS mode! */ *ppNew = (nsd_t *)pNew; finalize_it: if (iRet != RS_RET_OK) { if (error_position != NULL) { dbgprintf("AcceptConnReq error_position=%s\n", error_position); } if (pNew != NULL) nsd_gtlsDestruct(&pNew); } RETiRet; } /* receive data from a tcp socket * The lenBuf parameter must contain the max buffer size on entry and contains * the number of octets read on exit. This function * never blocks, not even when called on a blocking socket. That is important * for client sockets, which are set to block during send, but should not * block when trying to read data. -- rgerhards, 2008-03-17 * The function now follows the usual iRet calling sequence. * With GnuTLS, we may need to restart a recv() system call. If so, we need * to supply the SAME buffer on the retry. We can not assure this, as the * caller is free to call us with any buffer location (and in current * implementation, it is on the stack and extremely likely to change). To * work-around this problem, we allocate a buffer ourselfs and always receive * into that buffer. We pass data on to the caller only after we have received it. * To save some space, we allocate that internal buffer only when it is actually * needed, which means when we reach this function for the first time. To keep * the algorithm simple, we always supply data only from the internal buffer, * even if it is a single byte. As we have a stream, the caller must be prepared * to accept messages in any order, so we do not need to take care about this. * Please note that the logic also forces us to do some "faking" in select(), as * we must provide a fake "is ready for readign" status if we have data inside our * buffer. -- rgerhards, 2008-06-23 */ static rsRetVal Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf, int *const oserr, unsigned *const nextIODirection) { DEFiRet; ssize_t iBytesCopy; /* how many bytes are to be copied to the client buffer? */ nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf, oserr, nextIODirection)); FINALIZE; } /* --- in TLS mode now --- */ if (pThis->rtryCall == gtlsRtry_handshake) { /* note: we are in receive, so we acually will retry receive in any case */ DBGPRINTF("need to do retry handshake\n"); CHKiRet(doRetry(pThis)); ABORT_FINALIZE(RS_RET_RETRY); } /* Buffer logic applies only if we are in TLS mode. Here we * assume that we will switch from plain to TLS, but never back. This * assumption may be unsafe, but it is the model for the time being and I * do not see any valid reason why we should switch back to plain TCP after * we were in TLS mode. However, in that case we may lose something that * is already in the receive buffer ... risk accepted. -- rgerhards, 2008-06-23 */ if (pThis->pszRcvBuf == NULL) { /* we have no buffer, so we need to malloc one */ CHKmalloc(pThis->pszRcvBuf = malloc(NSD_GTLS_MAX_RCVBUF)); pThis->lenRcvBuf = -1; } /* now check if we have something in our buffer. If so, we satisfy * the request from buffer contents. */ if (pThis->lenRcvBuf == -1) { /* no data present, must read */ CHKiRet(gtlsRecordRecv(pThis, nextIODirection)); } if (pThis->lenRcvBuf == 0) { /* EOS */ *oserr = errno; ABORT_FINALIZE(RS_RET_CLOSED); } /* if we reach this point, data is present in the buffer and must be copied */ iBytesCopy = pThis->lenRcvBuf - pThis->ptrRcvBuf; if (iBytesCopy > *pLenBuf) { iBytesCopy = *pLenBuf; } else { pThis->lenRcvBuf = -1; /* buffer will be emptied below */ } memcpy(pBuf, pThis->pszRcvBuf + pThis->ptrRcvBuf, iBytesCopy); pThis->ptrRcvBuf += iBytesCopy; *pLenBuf = iBytesCopy; finalize_it: if (iRet != RS_RET_OK && iRet != RS_RET_RETRY) { /* We need to free the receive buffer in error error case unless a retry is wanted. , if we * allocated one. -- rgerhards, 2008-12-03 -- moved here by alorbach, 2015-12-01 */ *pLenBuf = 0; free(pThis->pszRcvBuf); pThis->pszRcvBuf = NULL; } dbgprintf("gtlsRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf %d\n", pThis, iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf); RETiRet; } /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has * been written. * rgerhards, 2008-03-19 */ static rsRetVal Send(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf) { int iSent; int wantsWriteData = 0; nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); DEFiRet; ISOBJ_TYPE_assert(pThis, nsd_gtls); if (pThis->bAbortConn) ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ); if (pThis->iMode == 0) { CHKiRet(nsd_ptcp.Send(pThis->pTcp, pBuf, pLenBuf)); FINALIZE; } if (pThis->rtryCall == gtlsRtry_recv) { CHKiRet(retrySendSideRecordRecv(pThis)); } while (1) { /* loop broken inside */ iSent = gnutls_record_send(pThis->sess, pBuf, *pLenBuf); if (iSent >= 0) { *pLenBuf = iSent; break; } if (iSent == GNUTLS_E_AGAIN || iSent == GNUTLS_E_INTERRUPTED) { /* * GnuTLS may require us to read to make progress (e.g. KeyUpdate). */ if (gnutls_record_get_direction(pThis->sess) == gtlsDir_READ) { /* * Preserve any application data read while driving send-side TLS * control traffic. TLS 1.3 post-handshake messages can make * gnutls_record_send() need a read, and gnutls_record_recv() may * return application bytes after processing that control traffic. */ CHKiRet(retrySendSideRecordRecv(pThis)); } continue; /* retry send */ } else { /* Check if the underlaying file descriptor needs to read or write data!*/ wantsWriteData = gnutls_record_get_direction(pThis->sess); uchar *pErr = gtlsStrerror(iSent); LogError(0, RS_RET_GNUTLS_ERR, "unexpected GnuTLS error %d, wantsWriteData=%d - this " "could be caused by a broken connection. GnuTLS reports: %s\n", iSent, wantsWriteData, pErr); free(pErr); gnutls_perror(iSent); ABORT_FINALIZE(RS_RET_GNUTLS_ERR); } } finalize_it: RETiRet; } /* Enable KEEPALIVE handling on the socket. * rgerhards, 2009-06-02 */ static rsRetVal EnableKeepAlive(nsd_t *pNsd) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); ISOBJ_TYPE_assert(pThis, nsd_gtls); return nsd_ptcp.EnableKeepAlive(pThis->pTcp); } /* * SNI should not be used if the hostname is a bare IP address */ static int SetServerNameIfPresent(nsd_gtls_t *pThis, uchar *host) { struct sockaddr_in sa; struct sockaddr_in6 sa6; int inet_pton_ret; /* Always use the configured remote SNI if present */ if (pThis->remoteSNI != NULL) { return gnutls_server_name_set(pThis->sess, GNUTLS_NAME_DNS, pThis->remoteSNI, ustrlen(pThis->remoteSNI)); } inet_pton_ret = inet_pton(AF_INET, CHAR_CONVERT(host), &(sa.sin_addr)); if (inet_pton_ret == 0) { // host wasn't a bare IPv4 address: try IPv6 inet_pton_ret = inet_pton(AF_INET6, CHAR_CONVERT(host), &(sa6.sin6_addr)); } switch (inet_pton_ret) { case 1: // host is a valid IP address: don't use SNI return 0; case 0: // host isn't a valid IP address: assume it's a domain name, use SNI return gnutls_server_name_set(pThis->sess, GNUTLS_NAME_DNS, host, ustrlen(host)); default: // unexpected error return -1; } } /* open a connection to a remote host (server). With GnuTLS, we always * open a plain tcp socket and then, if in TLS mode, do a handshake on it. * rgerhards, 2008-03-19 */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" /* TODO: FIX Warnings! */ static rsRetVal Connect(nsd_t *pNsd, int family, uchar *port, uchar *host, char *device) { nsd_gtls_t *pThis = nsd_gtls_from_nsd(pNsd); int sock; int gnuRet; const char *error_position; #ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY static const int cert_type_priority[2] = {GNUTLS_CRT_X509, 0}; #endif DEFiRet; dbgprintf("Connect to %s:%s\n", host, port); ISOBJ_TYPE_assert(pThis, nsd_gtls); assert(port != NULL); assert(host != NULL); CHKiRet(gtlsInitCred(pThis)); CHKiRet(gtlsAddOurCert(pThis)); CHKiRet(nsd_ptcp.Connect(pThis->pTcp, family, port, host, device)); if (pThis->iMode == 0) FINALIZE; /* we reach this point if in TLS mode */ CHKgnutls(gnutls_init(&pThis->sess, GNUTLS_CLIENT)); pThis->bHaveSess = 1; pThis->bIsInitiator = 1; CHKgnutls(SetServerNameIfPresent(pThis, host)); /* in the client case, we need to set a callback that ensures our certificate * will be presented to the server even if it is not signed by one of the server's * trusted roots. This is necessary to support fingerprint authentication. */ /* store a pointer to ourselfs (needed by callback) */ gnutls_session_set_ptr(pThis->sess, (void *)pThis); iRet = gtlsLoadOurCertKey(pThis); /* first load .pem files */ if (iRet == RS_RET_OK) { #if HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION gnutls_certificate_set_retrieve_function(pThis->xcred, gtlsClientCertCallback); #else gnutls_certificate_client_set_retrieve_function(pThis->xcred, gtlsClientCertCallback); #endif dbgprintf("Connect: enable certificate checking (VerifyDepth=%d)\n", pThis->DrvrVerifyDepth); if (pThis->DrvrVerifyDepth != 0) { gnutls_certificate_set_verify_limits(pThis->xcred, 8200, pThis->DrvrVerifyDepth); } } else if (iRet == RS_RET_CERTLESS) { dbgprintf("Connect: certificates not configured, not loaded.\n"); } else { LogError(0, iRet, "Connect failed to INIT Session %d", gnuRet); ABORT_FINALIZE(iRet); ; /* we have an error case! */ } /*priority string setzen*/ if (pThis->gnutlsPriorityString != NULL) { dbgprintf("Connect: setting configured priority string (ciphers)\n"); if (gnutls_priority_set_direct(pThis->sess, (const char *)pThis->gnutlsPriorityString, &error_position) == GNUTLS_E_INVALID_REQUEST) { LogError(0, RS_RET_GNUTLS_ERR, "Syntax error or unsupported option in " "Priority String near: \"%s\"\n", error_position); } } else { if (pThis->authMode == GTLS_AUTH_CERTANON || pThis->bOurCertIsInit == 0) { /* Allow ANON Ciphers */ dbgprintf("Connect: setting anon ciphers Try1: %s\n", GTLS_ANON_PRIO_NOTLSV13); if (gnutls_priority_set_direct(pThis->sess, (const char *)GTLS_ANON_PRIO_NOTLSV13, &error_position) == GNUTLS_E_INVALID_REQUEST) { dbgprintf("Connect: setting anon ciphers Try2 (TLS1.3 unknown): %s\n", GTLS_ANON_PRIO); CHKgnutls(gnutls_priority_set_direct(pThis->sess, GTLS_ANON_PRIO, &error_position)); } /* Uncomment for DEBUG print_cipher_suite_list("NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL"); */ } else { /* Use default priorities */ dbgprintf("Connect: setting default ciphers\n"); CHKgnutls(gnutls_set_default_priority(pThis->sess)); } } #ifdef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY /* The gnutls_certificate_type_set_priority function is deprecated * and not available in recent GnuTLS versions. However, there is no * doc how to properly replace it with gnutls_priority_set_direct. * A lot of folks have simply removed it, when they also called * gnutls_set_default_priority. This is what we now also do. If * this causes problems or someone has an idea of how to replace * the deprecated function in a better way, please let us know! * In any case, we use it as long as it is available and let * not insult us by the deprecation warnings. * 2015-05-18 rgerhards */ CHKgnutls(gnutls_certificate_type_set_priority(pThis->sess, cert_type_priority)); #endif /* put the x509 credentials to the current session */ CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_CERTIFICATE, pThis->xcred)); /* check for anon authmode */ if (pThis->authMode == GTLS_AUTH_CERTANON) { dbgprintf("Connect: anon authmode, gnutls_credentials_set GNUTLS_CRD_ANON\n"); CHKgnutls(gnutls_credentials_set(pThis->sess, GNUTLS_CRD_ANON, anoncred)); gnutls_dh_set_prime_bits(pThis->sess, dhMinBits); } CHKiRet(nsd_ptcp.GetSock(pThis->pTcp, &sock)); /* assign the socket to GnuTls */ gtlsSetTransportPtr(pThis, sock); /* we need to store the hostname as an alternate mean of authentication if no * permitted peer names are given. Using the hostname is quite useful. It permits * auto-configuration of security if a commen root cert is present. -- rgerhards, 2008-05-26 */ CHKmalloc(pThis->pszConnectHost = (uchar *)strdup((char *)host)); /* and perform the handshake */ gnutls_handshake_set_timeout(pThis->sess, 3000); CHKgnutls(gnutls_handshake(pThis->sess)); dbgprintf("GnuTLS handshake succeeded\n"); /* now check if the remote peer is permitted to talk to us - ideally, we * should do this during the handshake, but GnuTLS does not yet provide * the necessary callbacks -- rgerhards, 2008-05-26 */ CHKiRet(gtlsChkPeerAuth(pThis)); finalize_it: if (iRet != RS_RET_OK) { if (pThis->bHaveSess) { gnutls_deinit(pThis->sess); pThis->bHaveSess = 0; /* Free memory using gnutls api first*/ gnutls_certificate_free_credentials(pThis->xcred); pThis->xcred = NULL; /* Free other memory */ free(pThis->pszConnectHost); pThis->pszConnectHost = NULL; } } RETiRet; } #pragma GCC diagnostic pop /* queryInterface function */ BEGINobjQueryInterface(nsd_gtls) CODESTARTobjQueryInterface(nsd_gtls); if (pIf->ifVersion != nsdCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = (rsRetVal(*)(nsd_t **))nsd_gtlsConstruct; pIf->Destruct = (rsRetVal(*)(nsd_t **))nsd_gtlsDestruct; pIf->Abort = Abort; pIf->LstnInit = LstnInit; pIf->AcceptConnReq = AcceptConnReq; pIf->Rcv = Rcv; pIf->Send = Send; pIf->Connect = Connect; pIf->GetSock = GetSock; pIf->SetSock = SetSock; pIf->SetMode = SetMode; pIf->SetAuthMode = SetAuthMode; pIf->SetPermitExpiredCerts = SetPermitExpiredCerts; pIf->SetPermPeers = SetPermPeers; pIf->CheckConnection = CheckConnection; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->GetRemAddr = GetRemAddr; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetTcpUserTimeout = SetTcpUserTimeout; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetCheckExtendedKeyUsage = SetCheckExtendedKeyUsage; pIf->SetPrioritizeSAN = SetPrioritizeSAN; pIf->SetTlsVerifyDepth = SetTlsVerifyDepth; pIf->SetTlsCAFile = SetTlsCAFile; pIf->SetTlsCRLFile = SetTlsCRLFile; pIf->SetTlsCAExtraFiles = SetTlsCAExtraFiles; pIf->SetTlsKeyFile = SetTlsKeyFile; pIf->SetTlsCertFile = SetTlsCertFile; pIf->GetRemotePort = GetRemotePort; pIf->FmtRemotePortStr = FmtRemotePortStr; pIf->SetRemoteSNI = SetRemoteSNI; pIf->SetTlsRevocationCheck = SetTlsRevocationCheck; finalize_it: ENDobjQueryInterface(nsd_gtls) /* exit our class */ BEGINObjClassExit(nsd_gtls, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(nsd_gtls); gtlsGlblExit(); /* shut down GnuTLS */ /* release objects we no longer need */ objRelease(prop, CORE_COMPONENT); objRelease(nsd_ptcp, LM_NSD_PTCP_FILENAME); objRelease(net, LM_NET_FILENAME); objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDObjClassExit(nsd_gtls) /* Initialize the nsd_gtls class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINObjClassInit(nsd_gtls, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(nsd_ptcp, LM_NSD_PTCP_FILENAME)); CHKiRet(objUse(prop, CORE_COMPONENT)); /* now do global TLS init stuff */ CHKiRet(gtlsGlblInit()); ENDObjClassInit(nsd_gtls) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; nsd_gtlsClassExit(); pthread_mutex_destroy(&mutGtlsStrerror); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(nsd_gtlsClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ pthread_mutex_init(&mutGtlsStrerror, NULL); ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/threads.h0000644000000000000000000000013215241075234016030 xustar0030 mtime=1787067036.612578425 30 atime=1787067036.760581197 30 ctime=1787067794.470726471 rsyslog-8.2608.0/runtime/threads.h0000664000175000017500000000416315241075234015500 0ustar00rgerrger/* Definition of the threading support module. * * Copyright 2007-2012 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef THREADS_H_INCLUDED #define THREADS_H_INCLUDED #include "atomic.h" /* the thread object */ struct thrdInfo { pthread_mutex_t mutThrd; /* mutex for handling long-running operations and shutdown */ pthread_cond_t condThrdTerm; /* condition: thread terminates (used just for shutdown loop) */ int bIsActive; /* Is thread running? */ int bShallStop; /* set to 1 if the thread should be stopped ? */ DEF_ATOMIC_HELPER_MUT(mutShallStop); rsRetVal (*pUsrThrdMain)(struct thrdInfo *); /* user thread main to be called in new thread */ rsRetVal (*pAfterRun)(struct thrdInfo *); /* cleanup function */ pthread_t thrdID; sbool bNeedsCancel; /* must input be terminated by pthread_cancel()? */ uchar *name; /* a thread name, mainly for user interaction */ }; static inline int thrdGetShallStop(thrdInfo_t *pThis) { return ATOMIC_LOAD_32BIT_RELAXED(&pThis->bShallStop, &pThis->mutShallStop); } static inline void thrdSetShallStop(thrdInfo_t *pThis) { ATOMIC_STORE_32BIT_RELAXED(&pThis->bShallStop, &pThis->mutShallStop, 1); } /* prototypes */ rsRetVal thrdExit(void); rsRetVal thrdInit(void); rsRetVal thrdTerminate(thrdInfo_t *pThis); rsRetVal thrdTerminateAll(void); rsRetVal thrdCreate(rsRetVal (*thrdMain)(thrdInfo_t *), rsRetVal (*afterRun)(thrdInfo_t *), sbool, uchar *); /* macros (replace inline functions) */ #endif /* #ifndef THREADS_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/rsyslog.h0000644000000000000000000000012715241066365016111 xustar0029 mtime=1787063541.60553321 28 atime=1787063541.6265336 30 ctime=1787067794.241722204 rsyslog-8.2608.0/runtime/rsyslog.h0000664000175000017500000015214315241066365015557 0ustar00rgerrger/** * @file rsyslog.h * @brief Public interface for the rsyslog runtime library. * * This header provides the public API and data structures required by * modules interacting with the rsyslog runtime. It is part of the * rsyslog runtime library, which is licensed under the GNU Lesser General * Public License version 3 or later. */ #ifndef INCLUDED_RSYSLOG_H #define INCLUDED_RSYSLOG_H #ifdef __GNUC__ /** * @brief Suppress -Wstrict-prototypes for plugin interface compatibility. * * This suppression is required because rsyslog's plugin interface API, * designed over 20 years ago, uses traditional C-style function declarations * like `int func()` instead of `int func(void)`. * * While this style triggers `-Wstrict-prototypes` in modern GCC, it remains * intentional and necessary: the plugin interface must stay ABI-compatible * with numerous out-of-tree and third-party plugins, many of which are * unknown and beyond our control. * * Internally, function declarations are correctly overridden and type-checked * where possible, and care is taken not to introduce mismatches. However, * the original form must be preserved to maintain binary compatibility. * * AI note: Do not "modernize" these declarations automatically. This is * legacy interface preservation, not an oversight. */ #pragma GCC diagnostic ignored "-Wstrict-prototypes" #pragma GCC diagnostic ignored "-Wdeclaration-after-statement" #if __GNUC__ >= 8 || defined(__clang__) #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-warning-option" #endif /* GCC, starting at least with version 8, is now really overdoing with it's * warning messages. We turn those off that either cause an enormous amount * of false positives or flag perfectly legal code as problematic. */ /* That one causes warnings when we use variable buffers for error * messages which may be truncated in the very unlikely case of all * vars using max value. If going over the max size, the engine will * most likely truncate due to max message size anyhow. Also, sizing * the buffers for max-max message size is a wast of (stack) memory. */ #pragma GCC diagnostic ignored "-Wformat-truncation" /* The next one flags variable initializations within out exception handling * (iRet system) as problematic, even though variables are not used in those * cases. This would be a good diagnostic if gcc would actually check that * a variable is used uninitialized. Unfortunately it does not do that. But * the static analyzers we use as part of CI do, so we are covered in any * case. * Unfortunately ignoring this diagnostic leads to two more info lines * being emitted where nobody knows what the mean and why they appear :-( */ #pragma GCC diagnostic ignored "-Wjump-misses-init" #pragma GCC diagnostic ignored "-Wincompatible-pointer-types" #pragma GCC diagnostic ignored "-Wcast-function-type" #endif #if defined(__clang__) #define ATTR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) #define ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread"))) #else #define ATTR_NO_SANITIZE_UNDEFINED #define ATTR_NO_SANITIZE_THREAD #endif /* define a couple of attributes to improve cross-platform builds */ #if __GNUC__ > 6 #define CASE_FALLTHROUGH __attribute__((fallthrough)); #else #define CASE_FALLTHROUGH #endif #define ATTR_NORETURN __attribute__((noreturn)) #define ATTR_UNUSED __attribute__((unused)) #define ATTR_NONNULL(...) __attribute__((nonnull(__VA_ARGS__))) #else /* ifdef __GNUC__ */ #define CASE_FALLTHROUGH #define ATTR_NORETURN #define ATTR_UNUSED #define ATTR_NONNULL(...) #define ATTR_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) #define ATTR_NO_SANITIZE_THREAD __attribute__((no_sanitize("thread"))) #endif /* ifdef __GNUC__ */ #if defined(_AIX) #include /* AIXPORT : start*/ #define SRC_FD 13 #define SRCMSG (sizeof(srcpacket)) #endif /* src end */ #include #include #include "compat/asprintf.h" #include "typedefs.h" #if defined(__GNUC__) #define PRAGMA_IGNORE_Wswitch_enum _Pragma("GCC diagnostic ignored \"-Wswitch-enum\"") #define PRAGMA_IGNORE_Wempty_body _Pragma("GCC diagnostic ignored \"-Wempty-body\"") #define PRAGMA_IGNORE_Wstrict_prototypes _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"") #define PRAGMA_IGNORE_Wold_style_definition _Pragma("GCC diagnostic ignored \"-Wold-style-definition\"") #if defined(__clang_major__) && __clang_major__ >= 14 #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast \ _Pragma("GCC diagnostic ignored \"-Wvoid-pointer-to-enum-cast\"") #else #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast #endif #define PRAGMA_IGNORE_Wsign_compare _Pragma("GCC diagnostic ignored \"-Wsign-compare\"") #define PRAGMA_IGNORE_Wpragmas _Pragma("GCC diagnostic ignored \"-Wpragmas\"") #define PRAGMA_IGNORE_Wmissing_noreturn _Pragma("GCC diagnostic ignored \"-Wmissing-noreturn\"") #define PRAGMA_IGNORE_Wexpansion_to_defined _Pragma("GCC diagnostic ignored \"-Wexpansion-to-defined\"") #define PRAGMA_IGNORE_Wunknown_warning_option _Pragma("GCC diagnostic ignored \"-Wunknown-warning-option\"") #define PRAGMA_IGNORE_Wjump_misses_init _Pragma("GCC diagnostic ignored \"-Wjump-misses-init\"") #if !defined(__clang__) #define PRAGMA_IGNORE_Wunknown_attribute _Pragma("GCC diagnostic ignored \"-Wunknown-attribute\"") #else #define PRAGMA_IGNORE_Wunknown_attribute #endif #define PRAGMA_IGNORE_Wformat_nonliteral _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || defined(__clang__) #define PRAGMA_IGNORE_Wdeprecated_declarations _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") #define PRAGMA_IGNORE_Wunused_parameter _Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") #define PRAGMA_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") #define PRAGMA_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") #else #define PRAGMA_IGNORE_Wdeprecated_declarations #define PRAGMA_IGNORE_Wunused_parameter #define PRAGMA_DIAGNOSTIC_PUSH #define PRAGMA_DIAGNOSTIC_POP #endif #else #define PRAGMA_IGNORE_Wswitch_enum #define PRAGMA_IGNORE_Wsign_compare #define PRAGMA_IGNORE_Wformat_nonliteral #define PRAGMA_IGNORE_Wpragmas #define PRAGMA_IGNORE_Wmissing_noreturn #define PRAGMA_IGNORE_Wempty_body #define PRAGMA_IGNORE_Wstrict_prototypes #define PRAGMA_IGNORE_Wold_style_definition #define PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast #define PRAGMA_IGNORE_Wdeprecated_declarations #define PRAGMA_IGNORE_Wexpansion_to_defined #define PRAGMA_IGNORE_Wunknown_attribute #define PRAGMA_IGNORE_Wunknown_warning_option #define PRAGMA_IGNORE_Wjump_misses_init #define PRAGMA_DIAGNOSTIC_PUSH #define PRAGMA_DIAGNOSTIC_POP #endif #define NULL_CHECK(ptr) \ do { \ if (unlikely(ptr == NULL)) { \ LogError(0, RS_RET_PROGRAM_ERROR, "%s:%d: prevented NULL pointer access", __FILE__, __LINE__); \ ABORT_FINALIZE(RS_RET_PROGRAM_ERROR); \ } \ } while (0); /* ############################################################# * * # Some constant values # * * ############################################################# */ /** * @brief Number of characters in an RFC 3164 timestamp (excluding the NUL terminator). */ #define CONST_LEN_TIMESTAMP_3164 15 /** * @brief Number of characters in an RFC 3339 timestamp (excluding the NUL terminator). */ #define CONST_LEN_TIMESTAMP_3339 32 #define CONST_LEN_CEE_COOKIE 5 #define CONST_CEE_COOKIE "@cee:" /* ############################################################# * * # Config Settings # * * ############################################################# */ #define RS_STRINGBUF_ALLOC_INCREMENT 128 /* MAXSIZE are absolute maxima, while BUFSIZE are just values after which * processing is more time-intense. The BUFSIZE params currently add their * value to the fixed size of the message object. */ /** * @brief Maximum permitted size for a syslog TAG field. * * This value is intentionally set far above any realistic tag length * to guard against malformed or excessive configurations. */ #define CONF_TAG_MAXSIZE 512 /** * @brief Maximum permitted size for a syslog HOSTNAME field. * * This value is intentionally set far above any realistic hostname length * to guard against malformed or excessive configurations. */ #define CONF_HOSTNAME_MAXSIZE 512 #define CONF_RAWMSG_BUFSIZE 101 #define CONF_TAG_BUFSIZE 32 #define CONF_PROGNAME_BUFSIZE 16 #define CONF_HOSTNAME_BUFSIZE 32 /** * @brief Suggested buffer size for config string properties. * * Should be close to the size of a pointer or slightly above it. * This may be used in unions with pointers. */ #define CONF_PROP_BUFSIZE 16 /** * @brief Initial size of iparams array in worker thread instances. * * This array is automatically extended as needed. */ #define CONF_IPARAMS_BUFSIZE 16 /** * @brief Minimum message size (in bytes) to attempt compression. * * Compression is skipped for smaller messages to avoid overhead. * Even though rsyslog checks for compression gain before submitting, * it still requires a (costly) compress() call. This threshold skips * the call entirely for very small messages. * * @note Some small messages may be sent uncompressed, trading a few * extra bytes for better performance. * * @remarks * Originally introduced to avoid pointless compression attempts that * save no bandwidth due to protocol padding (e.g. UDP). * - rgerhards, 2006-11-30 */ #define CONF_MIN_SIZE_FOR_COMPRESS 60 /** * @brief Maximum number of cached string buffer pointers in output modules. * * All rsyslog-provided plugins stay below this value. Recompile with a * higher value only if future or third-party plugins require it. * * Hardcoding this value reduces runtime and code complexity overhead. * Most modules require ≤ 3 buffers; 5 is considered safe. * * @remarks * - rgerhards, 2010-06-24 */ #define CONF_OMOD_NUMSTRINGS_MAXSIZE 5 /** * @brief Default number of messages per multisub structure. */ #define CONF_NUM_MULTISUB 1024 /* ############################################################# * * # End Config Settings # * * ############################################################# */ /* make sure we uses consistent macros, no matter what the * platform gives us. */ #undef LOG_EMERG #undef LOG_ALERT #undef LOG_CRIT #undef LOG_ERR #undef LOG_WARNING #undef LOG_NOTICE #undef LOG_INFO #undef LOG_DEBUG #undef LOG_KERN #undef LOG_USER #undef LOG_MAIL #undef LOG_DAEMON #undef LOG_AUTH #undef LOG_SYSLOG #undef LOG_LPR #undef LOG_NEWS #undef LOG_UUCP #undef LOG_CRON #undef LOG_AUTHPRIV #undef LOG_FTP #undef LOG_LOCAL0 #undef LOG_LOCAL1 #undef LOG_LOCAL2 #undef LOG_LOCAL3 #undef LOG_LOCAL4 #undef LOG_LOCAL5 #undef LOG_LOCAL6 #undef LOG_LOCAL7 #undef LOG_FAC_INVLD #undef LOG_INVLD #undef LOG_NFACILITIES /** * @brief Number of facility codes, including special invalid facility. * * This value covers the 24 standard syslog facilities plus * one extra slot for the special “invld� facility. */ #define LOG_NFACILITIES (24 + 1) /** * @brief Maximum supported PRI (priority) value. * * The highest valid PRI according to RFC 3164 and RFC 5424. */ #define LOG_MAXPRI 191 #undef LOG_MAKEPRI #define LOG_PRI_INVLD (LOG_INVLD | LOG_DEBUG) /* PRI is invalid --> special "invld.=debug" PRI code (rsyslog-specific) */ #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #define LOG_KERN (0 << 3) /* kernel messages */ #define LOG_USER (1 << 3) /* random user-level messages */ #define LOG_MAIL (2 << 3) /* mail system */ #define LOG_DAEMON (3 << 3) /* system daemons */ #define LOG_AUTH (4 << 3) /* security/authorization messages */ #define LOG_SYSLOG (5 << 3) /* messages generated internally by syslogd */ #define LOG_LPR (6 << 3) /* line printer subsystem */ #define LOG_NEWS (7 << 3) /* network news subsystem */ #define LOG_UUCP (8 << 3) /* UUCP subsystem */ #if !defined(LOG_CRON) #define LOG_CRON (9 << 3) /* clock daemon */ #endif #define LOG_AUTHPRIV (10 << 3) /* security/authorization messages (private) */ #define LOG_FTP (11 << 3) /* ftp daemon */ #if defined(_AIX) /* AIXPORT : These are necessary for AIX */ #define LOG_ASO (12 << 3) /* Active System Optimizer. Reserved for internal use */ #define LOG_CAA (15 << 3) /* Cluster aware AIX subsystem */ #endif #define LOG_LOCAL0 (16 << 3) /* reserved for local use */ #define LOG_LOCAL1 (17 << 3) /* reserved for local use */ #define LOG_LOCAL2 (18 << 3) /* reserved for local use */ #define LOG_LOCAL3 (19 << 3) /* reserved for local use */ #define LOG_LOCAL4 (20 << 3) /* reserved for local use */ #define LOG_LOCAL5 (21 << 3) /* reserved for local use */ #define LOG_LOCAL6 (22 << 3) /* reserved for local use */ #define LOG_LOCAL7 (23 << 3) /* reserved for local use */ #define LOG_FAC_INVLD 24 #define LOG_INVLD (LOG_FAC_INVLD << 3) /* invalid facility/PRI code */ /* we need to evaluate our argument only once, as otherwise we may * have side-effects (this was seen in some version). * Note: I know that "static inline" is not the right thing from a C99 * PoV, but some environments treat, even in C99 mode, compile * non-static inline into the source even if not defined as "extern". This * obviously results in linker errors. Using "static inline" as below together * with "__attribute__((unused))" works in all cases. Note also that we * cannot work around this in pri2fac, as we would otherwise need to evaluate * pri more than once. */ static inline syslog_pri_t __attribute__((unused)) pri2fac(const syslog_pri_t pri) { unsigned fac = pri >> 3; return (fac > 23) ? LOG_FAC_INVLD : fac; } #define pri2sev(pri) ((pri) & 0x07) /* the rsyslog core provides information about present feature to plugins * asking it. Below are feature-test macros which must be used to query * features. Note that this must be powers of two, so that multiple queries * can be combined. -- rgerhards, 2009-04-27 */ #define CORE_FEATURE_BATCHING 1 /* for additional features, define as powers of two (e.g. 'CORE_FEATURE_whatever 2', then 4, ...) */ #ifndef _PATH_CONSOLE #define _PATH_CONSOLE "/dev/console" #endif /** * @enum rsRetVal_ * @brief Return values used throughout the runtime API. * * The error codes below are originally borrowed from liblogging. Values up to * -2999 are reserved for future expansion. */ enum rsRetVal_ { /* the first two define are for errmsg.logError(), so that we can use the rsRetVal * as an rsyslog error code. -- rgerhards, 20080-06-27 */ RS_RET_NO_ERRCODE = -1, /**< RESERVED for NO_ERRCODE errmsg.logError status name */ RS_RET_INCLUDE_ERRNO = 1073741824, /* 2**30 - do NOT use error codes above this! */ /* begin regular error codes */ RS_RET_NOT_IMPLEMENTED = -7, /**< implementation is missing (probably internal error or lazyness ;)) */ RS_RET_OUT_OF_MEMORY = -6, /**< memory allocation failed */ RS_RET_PROVIDED_BUFFER_TOO_SMALL = -50, /*< the caller provided a buffer, but the called function sees the size of this buffer is too small - operation not carried out */ RS_RET_FILE_TRUNCATED = -51, /**< (input) file was truncated, not an error but a status */ RS_RET_TRUE = -3, /**< to indicate a true state (can be used as TRUE, legacy) */ RS_RET_FALSE = -2, /**< to indicate a false state (can be used as FALSE, legacy) */ RS_RET_NO_IRET = -8, /**< This is a trick for the debuging system - it means no iRet is provided */ RS_RET_VALIDATION_RUN = -9, /**< indicates a (config) validation run, processing not carried out */ RS_RET_ERR = -3000, /**< generic failure */ RS_TRUNCAT_TOO_LARGE = -3001, /**< truncation operation where too many chars should be truncated */ RS_RET_FOUND_AT_STRING_END = -3002, /**< some value found, but at the last pos of string */ RS_RET_NOT_FOUND = -3003, /**< some requested value not found */ RS_RET_MISSING_TRAIL_QUOTE = -3004, /**< an expected trailing quote is missing */ RS_RET_NO_DIGIT = -3005, /**< an digit was expected, but none found (mostly parsing) */ RS_RET_NO_MORE_DATA = -3006, /**< end of data, e.g. end of string during parsing or EAGAIN API state */ RS_RET_INVALID_IP = -3007, /**< invalid ip found where valid was expected */ RS_RET_OBJ_CREATION_FAILED = -3008, /**< the creation of an object failed (no details available) */ RS_RET_INOTIFY_INIT_FAILED = -3009, /**< the initialization of an inotify instance failed (no details available) */ RS_RET_FEN_INIT_FAILED = -3010, /**< the initialization of a fen instance failed (no details available) */ RS_RET_PARAM_ERROR = -1000, /**< invalid parameter in call to function */ RS_RET_MISSING_INTERFACE = -1001, /**< interface version mismatch, required missing */ RS_RET_INVALID_CORE_INTERFACE = -1002, /**< interface provided by host invalid, can not be used */ RS_RET_ENTRY_POINT_NOT_FOUND = -1003, /**< a requested entry point was not found */ RS_RET_MODULE_ENTRY_POINT_NOT_FOUND = -1004, /**< a entry point requested from a module was not present in it */ RS_RET_OBJ_NOT_AVAILABLE = -1005, /**< something could not be completed because the required object is not available*/ RS_RET_LOAD_ERROR = -1006, /**< we had an error loading the object/interface and can not continue */ RS_RET_MODULE_STILL_REFERENCED = -1007, /**< module could not be unloaded because it still is referenced by someone */ RS_RET_OBJ_UNKNOWN = -1008, /**< object is unknown where required */ RS_RET_OBJ_NOT_REGISTERED = -1009, /**< tried to unregister an object that is not registered */ /* return states for config file processing */ RS_RET_NONE = -2000, /**< some value is not available - not necessarily an error */ RS_RET_CONFLINE_UNPROCESSED = -2001, /**< config line was not processed, pass to other module */ RS_RET_DISCARDMSG = -2002, /**< discard message (no error state, processing request!) */ RS_RET_INCOMPATIBLE = -2003, /**< function not compatible with requested feature */ RS_RET_NOENTRY = -2004, /**< do not create an entry for (whatever) - not necessary an error */ RS_RET_NO_SQL_STRING = -2005, /**< string is not suitable for use as SQL */ RS_RET_DISABLE_ACTION = -2006, /**< action requests that it be disabled */ RS_RET_SUSPENDED = -2007, /**< something was suspended, not neccesarily an error */ RS_RET_RQD_TPLOPT_MISSING = -2008, /**< a required template option is missing */ RS_RET_INVALID_VALUE = -2009, /**< some value is invalid (e.g. user-supplied data) */ RS_RET_INVALID_INT = -2010, /**< invalid integer */ RS_RET_INVALID_CMD = -2011, /**< invalid command */ RS_RET_VAL_OUT_OF_RANGE = -2012, /**< value out of range */ RS_RET_FOPEN_FAILURE = -2013, /**< failure during fopen, for example file not found - see errno */ RS_RET_END_OF_LINKEDLIST = -2014, /**< end of linked list, not an error, but a status */ RS_RET_CHAIN_NOT_PERMITTED = -2015, /**< chaining (e.g. of config command handlers) not permitted */ RS_RET_INVALID_PARAMS = -2016, /**< supplied parameters are invalid */ RS_RET_EMPTY_LIST = -2017, /**< linked list is empty */ RS_RET_FINISHED = -2018, /**< some opertion is finished, not an error state */ RS_RET_INVALID_SOURCE = -2019, /**< source (address) invalid for some reason */ RS_RET_ADDRESS_UNKNOWN = -2020, /**< an address is unknown - not necessarily an error */ RS_RET_MALICIOUS_ENTITY = -2021, /**< there is an malicious entity involved */ RS_RET_NO_KERNEL_LOGSRC = -2022, /**< no source for kernel logs can be obtained */ RS_RET_TCP_SEND_ERROR = -2023, /**< error during TCP send process */ RS_RET_GSS_SEND_ERROR = -2024, /**< error during GSS (via TCP) send process */ RS_RET_TCP_SOCKCREATE_ERR = -2025, /**< error during creation of TCP socket */ RS_RET_GSS_SENDINIT_ERROR = -2024, /**< error during GSS (via TCP) send initialization process */ RS_RET_EOF = -2026, /**< end of file reached, not necessarily an error */ RS_RET_IO_ERROR = -2027, /**< some kind of IO error happened */ RS_RET_INVALID_OID = -2028, /**< invalid object ID */ RS_RET_INVALID_HEADER = -2029, /**< invalid header */ RS_RET_INVALID_HEADER_VERS = -2030, /**< invalid header version */ RS_RET_INVALID_DELIMITER = -2031, /**< invalid delimiter, e.g. between params */ RS_RET_INVALID_PROPFRAME = -2032, /**< invalid framing in serialized property */ RS_RET_NO_PROPLINE = -2033, /**< line is not a property line */ RS_RET_INVALID_TRAILER = -2034, /**< invalid trailer */ RS_RET_VALUE_TOO_LOW = -2035, /**< a provided value is too low */ RS_RET_FILE_PREFIX_MISSING = -2036, /**< a required file prefix (parameter?) is missing */ RS_RET_INVALID_HEADER_RECTYPE = -2037, /**< invalid record type in header or invalid header */ RS_RET_QTYPE_MISMATCH = -2038, /**< different qType when reading back a property type */ RS_RET_NO_FILE_ACCESS = -2039, /**< covers EACCES error on file open() */ RS_RET_FILE_NOT_FOUND = -2040, /**< file not found */ RS_RET_TIMED_OUT = -2041, /**< timeout occurred (not necessarily an error) */ RS_RET_QSIZE_ZERO = -2042, /**< queue size is zero where this is not supported */ RS_RET_ALREADY_STARTING = -2043, /**< something (a thread?) is already starting - not necessarily an error */ RS_RET_NO_MORE_THREADS = -2044, /**< no more threads available, not necessarily an error */ RS_RET_NO_FILEPREFIX = -2045, /**< file prefix is not specified where one is needed */ RS_RET_CONFIG_ERROR = -2046, /**< there is a problem with the user-provided config settigs */ RS_RET_OUT_OF_DESRIPTORS = -2047, /**< a descriptor table's space has been exhausted */ RS_RET_NO_DRIVERS = -2048, /**< a required drivers missing */ RS_RET_NO_DRIVERNAME = -2049, /**< driver name missing where one was required */ RS_RET_EOS = -2050, /**< end of stream (of whatever) */ RS_RET_SYNTAX_ERROR = -2051, /**< syntax error, eg. during parsing */ RS_RET_INVALID_OCTAL_DIGIT = -2052, /**< invalid octal digit during parsing */ RS_RET_INVALID_HEX_DIGIT = -2053, /**< invalid hex digit during parsing */ RS_RET_INTERFACE_NOT_SUPPORTED = -2054, /**< interface not supported */ RS_RET_OUT_OF_STACKSPACE = -2055, /**< a stack data structure is exhausted and can not be grown */ RS_RET_STACK_EMPTY = -2056, /**< a pop was requested on a stack, but the stack was already empty */ RS_RET_INVALID_VMOP = -2057, /**< invalid virtual machine instruction */ RS_RET_INVALID_VAR = -2058, /**< a var or its content is unsuitable, eg. VARTYPE_NONE */ RS_RET_INVALID_NUMBER = -2059, /**< number invalid during parsing */ RS_RET_NOT_A_NUMBER = -2060, /**< e.g. conversion impossible because the string is not a number */ RS_RET_OBJ_ALREADY_REGISTERED = -2061, /**< object (name) is already registered */ RS_RET_OBJ_REGISTRY_OUT_OF_SPACE = -2062, /**< the object registry has run out of space */ RS_RET_HOST_NOT_PERMITTED = -2063, /**< a host is not permitted to perform an action it requested */ RS_RET_MODULE_LOAD_ERR = -2064, /**< module could not be loaded */ RS_RET_MODULE_LOAD_ERR_PATHLEN = -2065, /**< module could not be loaded - path to long */ RS_RET_MODULE_LOAD_ERR_DLOPEN = -2066, /**< module could not be loaded - problem in dlopen() */ RS_RET_MODULE_LOAD_ERR_NO_INIT = -2067, /**< module could not be loaded - init() missing */ RS_RET_MODULE_LOAD_ERR_INIT_FAILED = -2068, /**< module could not be loaded - init() failed */ RS_RET_NO_SOCKET = -2069, /**< socket could not be obtained or was not provided */ RS_RET_SMTP_ERROR = -2070, /**< error during SMTP transation */ RS_RET_MAIL_NO_TO = -2071, /**< recipient for mail destination is missing */ RS_RET_MAIL_NO_FROM = -2072, /**< sender for mail destination is missing */ RS_RET_INVALID_PRI = -2073, /**< PRI value is invalid */ RS_RET_MALICIOUS_HNAME = -2074, /**< remote peer is trying malicious things with its hostname */ RS_RET_INVALID_HNAME = -2075, /**< remote peer's hostname invalid or unobtainable */ RS_RET_INVALID_PORT = -2076, /**< invalid port value */ RS_RET_COULD_NOT_BIND = -2077, /**< could not bind socket, defunct */ RS_RET_GNUTLS_ERR = -2078, /**< (unexpected) error in GnuTLS call */ RS_RET_MAX_SESS_REACHED = -2079, /**< max nbr of sessions reached, can not create more */ RS_RET_MAX_LSTN_REACHED = -2080, /**< max nbr of listeners reached, can not create more */ RS_RET_INVALID_DRVR_MODE = -2081, /**< tried to set mode not supported by driver */ RS_RET_DRVRNAME_TOO_LONG = -2082, /**< driver name too long - should never happen */ RS_RET_TLS_HANDSHAKE_ERR = -2083, /**< TLS handshake failed */ RS_RET_TLS_CERT_ERR = -2084, /**< generic TLS certificate error */ RS_RET_TLS_NO_CERT = -2085, /**< no TLS certificate available where one was expected */ RS_RET_VALUE_NOT_SUPPORTED = -2086, /**< a provided value is not supported */ RS_RET_VALUE_NOT_IN_THIS_MODE = -2087, /**< a provided value is invalid for the curret mode */ RS_RET_INVALID_FINGERPRINT = -2088, /**< a fingerprint is not valid for this use case */ RS_RET_CONNECTION_ABORTREQ = -2089, /**< connection was abort requested due to previous error */ RS_RET_CERT_INVALID = -2090, /**< a x509 certificate failed validation */ RS_RET_CERT_INVALID_DN = -2091, /**< distinguised name in x509 certificate is invalid (e.g. wrong escaping) */ RS_RET_CERT_EXPIRED = -2092, /**< we are past a x.509 cert's expiration time */ RS_RET_CERT_NOT_YET_ACTIVE = -2094, /**< x.509 cert's activation time not yet reached */ RS_RET_SYS_ERR = -2095, /**< system error occurred (e.g. time() returned -1, quite unexpected) */ RS_RET_FILE_NO_STAT = -2096, /**< can not stat() a file */ RS_RET_FILE_TOO_LARGE = -2097, /**< a file is larger than permitted */ RS_RET_INVALID_WILDCARD = -2098, /**< a wildcard entry is invalid */ RS_RET_CLOSED = -2099, /**< connection was closed */ RS_RET_RETRY = -2100, /**< call should be retried (e.g. EGAIN on recv) */ RS_RET_GSS_ERR = -2101, /**< generic error occurred in GSSAPI subsystem */ RS_RET_CERTLESS = -2102, /**< state: we run without machine cert (this may be OK) */ RS_RET_NO_ACTIONS = -2103, /**< no active actions are configured (no output will be created) */ RS_RET_CONF_FILE_NOT_FOUND = -2104, /**< config file or directory not found */ RS_RET_QUEUE_FULL = -2105, /**< queue is full, operation could not be completed */ RS_RET_ACCEPT_ERR = -2106, /**< error during accept() system call */ RS_RET_INVLD_TIME = -2107, /**< invalid timestamp (e.g. could not be parsed) */ RS_RET_NO_ZIP = -2108, /**< ZIP functionality is not present */ RS_RET_CODE_ERR = -2109, /**< program code (internal) error */ RS_RET_FUNC_NO_LPAREN = -2110, /**< left parenthesis missing after function call (rainerscript) */ RS_RET_FUNC_MISSING_EXPR = -2111, /**< no expression after comma in function call (rainerscript) */ RS_RET_INVLD_NBR_ARGUMENTS = -2112, /**< invalid number of arguments for function call (rainerscript) */ RS_RET_INVLD_FUNC = -2113, /**< invalid function name for function call (rainerscript) */ RS_RET_DUP_FUNC_NAME = -2114, /**< duplicate function name (rainerscript) */ RS_RET_UNKNW_FUNC = -2115, /**< unkown function name (rainerscript) */ RS_RET_ERR_RLIM_NOFILE = -2116, /**< error setting max. nbr open files process limit */ RS_RET_ERR_CREAT_PIPE = -2117, /**< error during pipe creation */ RS_RET_ERR_FORK = -2118, /**< error during fork() */ RS_RET_ERR_WRITE_PIPE = -2119, /**< error writing to pipe */ RS_RET_RSCORE_TOO_OLD = -2120, /**< rsyslog core is too old for ... (eg this plugin) */ RS_RET_DEFER_COMMIT = -2121, /**< output plugin status: not yet committed (an OK state!) */ RS_RET_PREVIOUS_COMMITTED = -2122, /**< output plugin status: previous record was committed (an OK state!) */ RS_RET_ACTION_FAILED = -2123, /**< action failed and is now suspended */ RS_RET_NON_SIZELIMITCMD = -2125, /**< size limit for file defined, but no size limit command given */ RS_RET_SIZELIMITCMD_DIDNT_RESOLVE = -2126, /**< size limit command did not resolve situation */ RS_RET_STREAM_DISABLED = -2127, /**< a file has been disabled (e.g. by size limit restriction) */ RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */ RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */ RS_RET_EMPTY_MSG = -2143, /**< provided (raw) MSG is empty */ RS_RET_PEER_CLOSED_CONN = -2144, /**< remote peer closed connection (information, no error) */ RS_RET_ERR_OPEN_KLOG = -2145, /**< error opening or reading the kernel log socket */ RS_RET_ERR_AQ_CONLOG = -2146, /**< error aquiring console log (on solaris) */ RS_RET_ERR_DOOR = -2147, /**< some problems with handling the Solaris door functionality */ RS_RET_NO_SRCNAME_TPL = -2150, /**< sourcename template was not specified where one was needed (omudpspoof spoof addr) */ RS_RET_HOST_NOT_SPECIFIED = -2151, /**< (target) host was not specified where it was needed */ RS_RET_ERR_LIBNET_INIT = -2152, /**< error initializing libnet, e.g. because not running as root */ RS_RET_FORCE_TERM = -2153, /**< thread was forced to terminate by bShallShutdown, a state, not an error */ RS_RET_RULES_QUEUE_EXISTS = -2154, /**< we were instructed to create a new ruleset queue, but one already exists */ RS_RET_NO_CURR_RULESET = -2155, /**< no current ruleset exists (but one is required) */ RS_RET_NO_MSG_PASSING = -2156, /*< output module interface parameter passing mode "MSG" is not available but required */ RS_RET_RULESET_NOT_FOUND = -2157, /**< a required ruleset could not be found */ RS_RET_NO_RULESET = -2158, /**< no ruleset name as specified where one was needed */ RS_RET_PARSER_NOT_FOUND = -2159, /**< parser with the specified name was not found */ RS_RET_COULD_NOT_PARSE = -2160, /**< (this) parser could not parse the message (no error, means try next one) */ RS_RET_EINTR = -2161, /**< EINTR occurred during a system call (not necessarily an error) */ RS_RET_ERR_EPOLL = -2162, /**< epoll() returned with an unexpected error code */ RS_RET_ERR_EPOLL_CTL = -2163, /**< epol_ctll() returned with an unexpected error code */ RS_RET_TIMEOUT = -2164, /**< timeout occurred during operation */ RS_RET_RCV_ERR = -2165, /**< error occurred during socket rcv operation */ RS_RET_NO_SOCK_CONFIGURED = -2166, /**< no socket (name) was configured where one is required */ RS_RET_CONF_NOT_GLBL = -2167, /**< $Begin not in global scope */ RS_RET_CONF_IN_GLBL = -2168, /**< $End when in global scope */ RS_RET_CONF_INVLD_END = -2169, /**< $End for wrong conf object (probably nesting error) */ RS_RET_CONF_INVLD_SCOPE = -2170, /*< config statement not valid in current scope (e.g. global stmt in action block) */ RS_RET_CONF_END_NO_ACT = -2171, /**< end of action block, but no actual action specified */ RS_RET_NO_LSTN_DEFINED = -2172, /**< no listener defined (e.g. inside an input module) */ RS_RET_EPOLL_CR_FAILED = -2173, /**< epoll_create() failed */ RS_RET_EPOLL_CTL_FAILED = -2174, /**< epoll_ctl() failed */ RS_RET_INTERNAL_ERROR = -2175, /**< rsyslogd internal error, unexpected code path reached */ RS_RET_ERR_CRE_AFUX = -2176, /**< error creating AF_UNIX socket (and binding it) */ RS_RET_RATE_LIMITED = -2177, /**< some messages discarded due to exceeding a rate limit */ RS_RET_ERR_HDFS_WRITE = -2178, /**< error writing to HDFS */ RS_RET_ERR_HDFS_OPEN = -2179, /**< error during hdfsOpen (e.g. file does not exist) */ RS_RET_FILE_NOT_SPECIFIED = -2180, /**< file name not configured where this was required */ RS_RET_ERR_WRKDIR = -2181, /**< problems with the rsyslog working directory */ RS_RET_WRN_WRKDIR = -2182, /**< correctable problems with the rsyslog working directory */ RS_RET_ERR_QUEUE_EMERGENCY = -2183, /**< some fatal error caused queue to switch to emergency mode */ RS_RET_OUTDATED_STMT = -2184, /**< some outdated statement/functionality is being used in conf file */ RS_RET_MISSING_WHITESPACE = -2185, /**< whitespace is missing in some config construct */ RS_RET_OK_WARN = -2186, /**< config part: everything was OK, but a warning message was emitted */ RS_RET_INVLD_CONF_OBJ = -2200, /**< invalid config object (e.g. $Begin conf statement) */ /* UNUSED, WAS; RS_RET_ERR_LIBEE_INIT = -2201, < cannot obtain libee ctx */ RS_RET_ERR_LIBLOGNORM_INIT = -2202, /**< cannot obtain liblognorm ctx */ RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD = -2203, /**< liblognorm sampledb load failed */ RS_RET_CMD_GONE_AWAY = -2204, /**< config directive existed, but no longer supported */ RS_RET_ERR_SCHED_PARAMS = -2205, /**< there is a problem with configured thread scheduling params */ RS_RET_SOCKNAME_MISSING = -2206, /**< no socket name configured where one is required */ RS_RET_CONF_PARSE_ERROR = -2207, /**< (fatal) error parsing config file */ RS_RET_CONF_RQRD_PARAM_MISSING = -2208, /**< required parameter in config object is missing */ RS_RET_MOD_UNKNOWN = -2209, /**< module (config name) is unknown */ RS_RET_CONFOBJ_UNSUPPORTED = -2210, /**< config objects (v6 conf) are not supported here */ RS_RET_MISSING_CNFPARAMS = -2211, /**< missing configuration parameters */ RS_RET_NO_LISTNERS = -2212, /**< module loaded, but no listeners are defined */ RS_RET_INVLD_PROTOCOL = -2213, /**< invalid protocol specified in config file */ RS_RET_CNF_INVLD_FRAMING = -2214, /**< invalid framing specified in config file */ RS_RET_LEGA_ACT_NOT_SUPPORTED = -2215, /**< the module (no longer) supports legacy action syntax */ RS_RET_MAX_OMSR_REACHED = -2216, /**< max nbr of string requests reached, not supported by core */ RS_RET_UID_MISSING = -2217, /**< a user id is missing (but e.g. a password provided) */ RS_RET_DATAFAIL = -2218, /**< data passed to action caused failure */ /* reserved for pre-v6.5 */ RS_RET_DUP_PARAM = -2220, /**< config parameter is given more than once */ RS_RET_MODULE_ALREADY_IN_CONF = -2221, /**< module already in current configuration */ RS_RET_PARAM_NOT_PERMITTED = -2222, /**< legacy parameter no longer permitted (usally already set by v2) */ RS_RET_NO_JSON_PASSING = -2223, /**< rsyslog core does not support JSON-passing plugin API */ RS_RET_MOD_NO_INPUT_STMT = -2224, /**< (input) module does not support input() statement */ RS_RET_NO_CEE_MSG = -2225, /**< the message being processed is NOT CEE-enhanced */ /**** up to 2290 is reserved for v6 use ****/ RS_RET_RELP_ERR = -2291, /**<< error in RELP processing */ /**** up to 3000 is reserved for c7 use ****/ RS_RET_JNAME_NO_ROOT = -2301, /**< root element is missing in JSON path */ RS_RET_JNAME_INVALID = -2302, /**< JSON path is invalid */ RS_RET_JSON_PARSE_ERR = -2303, /**< we had a problem parsing JSON (or extra data) */ RS_RET_BSD_BLOCKS_UNSUPPORTED = -2304, /**< BSD-style config blocks are no longer supported */ RS_RET_JNAME_NOTFOUND = -2305, /**< JSON name not found (does not exist) */ RS_RET_INVLD_SETOP = -2305, /**< invalid variable set operation, incompatible type */ RS_RET_RULESET_EXISTS = -2306, /**< ruleset already exists */ RS_RET_DEPRECATED = -2307, /**< deprecated functionality is used */ RS_RET_DS_PROP_SEQ_ERR = -2308, /**< property sequence error deserializing object */ RS_RET_INVLD_PROP = -2309, /**< property name error (unknown name) */ RS_RET_NO_RULEBASE = -2310, /**< mmnormalize: rulebase can not be found or otherwise invalid */ RS_RET_INVLD_MODE = -2311, /**< invalid mode specified in configuration */ RS_RET_INVLD_ANON_BITS = -2312, /**< mmanon: invalid number of bits to anonymize specified */ RS_RET_REPLCHAR_IGNORED = -2313, /**< mmanon: replacementChar parameter is ignored */ RS_RET_SIGPROV_ERR = -2320, /**< error in signature provider */ RS_RET_CRYPROV_ERR = -2321, /**< error in cryptography encryption provider */ RS_RET_EI_OPN_ERR = -2322, /**< error opening an .encinfo file */ RS_RET_EI_NO_EXISTS = -2323, /**< .encinfo file does not exist (status, not necessarily error!)*/ RS_RET_EI_WR_ERR = -2324, /**< error writing an .encinfo file */ RS_RET_EI_INVLD_FILE = -2325, /**< header indicates the file is no .encinfo file */ RS_RET_CRY_INVLD_ALGO = -2326, /**< user specified invalid (unkonwn) crypto algorithm */ RS_RET_CRY_INVLD_MODE = -2327, /**< user specified invalid (unkonwn) crypto mode */ RS_RET_QUEUE_DISK_NO_FN = -2328, /**< disk queue configured, but filename not set */ RS_RET_CA_CERT_MISSING = -2329, /**< a CA cert is missing where one is required (e.g. TLS) */ RS_RET_CERT_MISSING = -2330, /**< a cert is missing where one is required (e.g. TLS) */ RS_RET_CERTKEY_MISSING = -2331, /**< a cert (private) key is missing where one is required (e.g. TLS) */ RS_RET_CRL_MISSING = -2332, /**< a CRL file is missing but not required (e.g. TLS) */ RS_RET_CRL_INVALID = -2333, /**< a CRL file PEM file failed validation */ RS_RET_CERT_REVOKED = -2334, /**< a certificate has been revoked */ RS_RET_STRUC_DATA_INVLD = -2349, /**< structured data is malformed */ /* up to 2350 reserved for 7.4 */ RS_RET_QUEUE_CRY_DISK_ONLY = -2351, /**< crypto provider only supported for disk-associated queues */ RS_RET_NO_DATA = -2352, /**< file has no data; more a state than a real error */ RS_RET_RELP_AUTH_FAIL = -2353, /**< RELP peer authentication failed */ RS_RET_ERR_UDPSEND = -2354, /**< sending msg via UDP failed */ RS_RET_LAST_ERRREPORT = -2355, /**< module does not emit more error messages as limit is reached */ RS_RET_READ_ERR = -2356, /**< read error occurred (file i/o) */ RS_RET_CONF_PARSE_WARNING = -2357, /**< warning parsing config file */ RS_RET_CONF_WRN_FULLDLY_BELOW_HIGHWTR = -2358, /**< warning queue full delay mark below high wtr mark */ RS_RET_RESUMED = -2359, /**< status: action was resumed (used for reporting) */ RS_RET_RELP_NO_TLS = -2360, /**< librel does not support TLS (but TLS requested) */ RS_RET_STATEFILE_WRONG_FNAME = -2361, /**< state file is for wrong file */ RS_RET_NAME_INVALID = -2362, /**< invalid name (in RainerScript) */ /* up to 2400 reserved for 7.5 & 7.6 */ RS_RET_INVLD_OMOD = -2400, /**< invalid output module, does not provide proper interfaces */ RS_RET_INVLD_INTERFACE_INPUT = -2401, /**< invalid value for "interface.input" parameter (ext progs) */ RS_RET_PARSER_NAME_EXISTS = -2402, /**< parser name already exists */ RS_RET_MOD_NO_PARSER_STMT = -2403, /**< (parser) module does not support parser() statement */ /* up to 2419 reserved for 8.4.x */ RS_RET_IMFILE_WILDCARD = -2420, /**< imfile file name contains wildcard, which may be problematic */ RS_RET_RELP_NO_TLS_AUTH = -2421, /**< librel does not support TLS authentication (but was requested) */ RS_RET_KAFKA_ERROR = -2422, /**< error reported by Apache Kafka subsystem. See message for details. */ RS_RET_KAFKA_NO_VALID_BROKERS = -2423, /**< no valid Kafka brokers configured/available */ RS_RET_KAFKA_PRODUCE_ERR = -2424, /**< error during Kafka produce function */ RS_RET_CONF_PARAM_INVLD = -2425, /**< config parameter is invalid */ RS_RET_KSI_ERR = -2426, /**< error in KSI subsystem */ RS_RET_ERR_LIBLOGNORM = -2427, /**< cannot obtain liblognorm ctx */ RS_RET_CONC_CTRL_ERR = -2428, /**< error in lock/unlock/condition/concurrent-modification operation */ RS_RET_SENDER_GONE_AWAY = -2429, /**< warning: sender not seen for configured amount of time */ RS_RET_SENDER_APPEARED = -2430, /**< info: new sender appeared */ RS_RET_FILE_ALREADY_IN_TABLE = -2431, /**< in imfile: table already contains to be added file */ RS_RET_ERR_DROP_PRIV = -2432, /**< error droping privileges */ RS_RET_FILE_OPEN_ERROR = -2433, /**< error other than "not found" occurred during open() */ RS_RET_RENAME_TMP_QI_ERROR = -2435, /**< renaming temporary .qi file failed */ RS_RET_ERR_SETENV = -2436, /**< error setting an environment variable */ RS_RET_DIR_CHOWN_ERROR = -2437, /**< error during chown() */ RS_RET_JSON_UNUSABLE = -2438, /**< JSON object is NULL or otherwise unusable */ RS_RET_OPERATION_STATUS = -2439, /**< operational status (info) message, no error */ RS_RET_UDP_MSGSIZE_TOO_LARGE = -2440, /**< a message is too large to be sent via UDP */ RS_RET_NON_JSON_PROP = -2441, /**< a non-json property id is provided where a json one is requried */ RS_RET_NO_TZ_SET = -2442, /**< system env var TZ is not set (status msg) */ RS_RET_FS_ERR = -2443, /**< file-system error */ RS_RET_POLL_ERR = -2444, /**< error in poll() system call */ RS_RET_OVERSIZE_MSG = -2445, /**< message is too long (above configured max) */ RS_RET_TLS_KEY_ERR = -2446, /**< TLS KEY has problems */ RS_RET_RABBITMQ_CONN_ERR = -2447, /**< RabbitMQ Connection error */ RS_RET_RABBITMQ_LOGIN_ERR = -2448, /**< RabbitMQ Login error */ RS_RET_RABBITMQ_CHANNEL_ERR = -2449, /**< RabbitMQ Connection error */ RS_RET_NO_WRKDIR_SET = -2450, /**< working directory not set, but desired by functionality */ RS_RET_ERR_QUEUE_FN_DUP = -2451, /**< duplicate queue file name */ RS_RET_REDIS_ERROR = -2452, /**< redis-specific error. See message foe details. */ RS_RET_REDIS_AUTH_FAILED = -2453, /**< redis authentication failure */ RS_RET_FAUP_INIT_OPTIONS_FAILED = -2454, /**< could not initialize faup options */ RS_RET_LIBCAPNG_ERR = -2455, /**< error during dropping the capabilities */ RS_RET_NET_CONN_ABORTED = -2456, /**< error during dropping the capabilities */ RS_RET_PROGRAM_ERROR = -2457, /**< rsyslogd internal error, like tried NULL-ptr access */ RS_RET_DEBUG = -2458, /**< status messages primarily meant for debugging, no error */ RS_RET_TLS_BASEINIT_FAIL = -2459, /**< Basic TLS initialization step failed */ RS_RET_TLS_ERR_SYSCALL = -2460, /**< TLS lib had problem with syscall */ RS_RET_WARN_NO_SENDER_STATS = -2461, /**< TLS lib had problem with syscall */ RS_RET_UNSUPP_SOCK_AF = -2462, /**< unsupported socket address family, use if code cannot process address family or does not expect it (may be handled locally) */ RS_RET_SYSTEMD_VERSION_ERR = -2463, /**< systemd version doesn't support journal namespacing */ RS_RET_NO_TEMPLATE_SUPPORT_ERR = -2464, /**< journald namespace doesn't support template yet */ RS_RET_SERVER_NO_TLS = -2465, /**< server received TLS handshake but is not configured for TLS */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ RS_RET_FIELD_NOT_FOUND = 1002, /**< field() function did not find requested field */ /* some generic error/status codes */ RS_RET_OK = 0, /**< operation successful */ RS_RET_OK_DELETE_LISTENTRY = 1, /*< operation successful, but callee requested the deletion of an entry (special state) */ RS_RET_TERMINATE_NOW = 2, /**< operation successful, function is requested to terminate (mostly used with threads) */ RS_RET_NO_RUN = 3, /**< operation successful, but function does not like to be executed */ RS_RET_IDLE = 4, /**< operation successful, but callee is idle (e.g. because queue is empty) */ RS_RET_TERMINATE_WHEN_IDLE = 5 /**< operation successful, function is requested to terminate when idle */ }; /* some helpful macros to work with srRetVals. * Be sure to call the to-be-returned variable always "iRet" and * the function finalizer always "finalize_it". */ #ifdef HAVE_BUILTIN_EXCEPT #define CHKiRet(code) \ if (__builtin_expect(((iRet = code) != RS_RET_OK), 0)) goto finalize_it #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #else #define CHKiRet(code) \ if ((iRet = code) != RS_RET_OK) goto finalize_it #define likely(x) (x) #define unlikely(x) (x) #endif #define CHKiConcCtrl(code) \ { \ int tmp_CC; \ if ((tmp_CC = code) != 0) { \ iRet = RS_RET_CONC_CTRL_ERR; \ errno = tmp_CC; \ goto finalize_it; \ } \ } /* macro below is to be used if we need our own handling, eg for cleanup */ #define CHKiRet_Hdlr(code) if ((iRet = code) != RS_RET_OK) /* macro below is to handle failing malloc/calloc/strdup... which we almost always handle in the same way... */ #define CHKmalloc(operation) \ if ((operation) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY) /* macro below is used in conjunction with CHKiRet_Hdlr, else use ABORT_FINALIZE */ #define FINALIZE goto finalize_it; #define DEFiRet rsRetVal iRet = RS_RET_OK #define RETiRet return iRet #define RS_CONCAT_(a, b) a##b #define RS_CONCAT(a, b) RS_CONCAT_(a, b) /** * @brief Compile-time assertion with a pre-C11 fallback. * * Uses C11 `_Static_assert` when available and otherwise falls back * to a typedef-size check. */ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) #define RS_STATIC_ASSERT(condition, message) _Static_assert((condition), message) #else #define RS_STATIC_ASSERT(condition, message) \ typedef char RS_CONCAT(rs_static_assertion_line_, __LINE__)[(condition) ? 1 : -1] ATTR_UNUSED #endif /** * @brief Copy a string literal into a fixed-size destination buffer. * * The macro enforces at compile time that `dst` is large enough for * `lit` (including the trailing NUL) and then performs a `memcpy`. * * @note Intended for true fixed-size arrays, not pointer destinations. */ #define RS_COPY_LITERAL(dst, lit) \ do { \ RS_STATIC_ASSERT(sizeof(dst) >= sizeof(lit), "destination buffer too small"); \ memcpy((dst), (lit), sizeof(lit)); \ } while (0) #define ABORT_FINALIZE(errCode) \ do { \ iRet = errCode; \ goto finalize_it; \ } while (0) /** * @enum rsObjectID * @brief Internal object identifiers used for sanity checks. * * Each object carries one of these IDs to verify that pointers refer * to the expected type. */ enum rsObjectID { OIDrsFreed = -1, /**< assigned, when an object is freed. If this * is seen during a method call, this is an * invalid object pointer! */ OIDrsInvalid = 0, /**< value created by calloc(), so do not use ;) */ /* The 0x3412 is a debug aid. It helps us find object IDs in memory * dumps (on X86, this is 1234 in the dump ;) * If you are on an embedded device and you would like to save space * make them 1 byte only. */ OIDrsCStr = 0x34120001, OIDrsPars = 0x34120002 }; typedef enum rsObjectID rsObjID; /* support to set object types */ #ifdef NDEBUG #define rsSETOBJTYPE(pObj, type) #define rsCHECKVALIDOBJECT(x, type) #else #define rsSETOBJTYPE(pObj, type) pObj->OID = type; #define rsCHECKVALIDOBJECT(x, type) \ { \ assert(x != NULL); \ assert(x->OID == type); \ } #endif /** * This macro should be used to free objects. * It aids in interpreting dumps during debugging. */ #ifdef NDEBUG #define RSFREEOBJ(x) free(x) #else #define RSFREEOBJ(x) \ { \ (x)->OID = OIDrsFreed; \ free(x); \ } #endif /** Default thread attributes used for internal worker threads. */ extern pthread_attr_t default_thread_attr; #ifdef HAVE_PTHREAD_SETSCHEDPARAM /** Scheduling parameters for worker threads. */ extern struct sched_param default_sched_param; extern int default_thr_sched_policy; #endif /** * @struct actWrkrIParams * @brief Immutable parameters passed to output workers. * * Each output plugin may request multiple templates. The overall table * therefore holds one entry per template per message. Modifying this * structure requires adjusting all output modules. */ struct actWrkrIParams { uchar *param; uint32_t lenBuf; /* length of string buffer (if string ptr) */ uint32_t lenStr; /* length of current string (if string ptr) */ }; /* macro to access actWrkrIParams base object: * param is ptr to base address * nActTpls is the number of templates the action has requested * iMsg is the message index * iTpl is the template index * This macro can be used for read and write access. */ #define actParam(param, nActTpls, iMsg, iTpl) (param[(iMsg * nActTpls) + iTpl]) /* for the time being, we do our own portability handling here. It * looks like autotools either does not yet support checks for it, or * I wasn't smart enough to find them ;) rgerhards, 2007-07-18 */ #ifndef __GNUC__ #define __attribute__(x) /*NOTHING*/ #endif /* some constants */ #define MUTEX_ALREADY_LOCKED 0 #define LOCK_MUTEX 1 #include "debug.h" #include "obj.h" /* the variable below is a trick: before we can init the runtime, the caller * may want to set a module load path. We can not do this via the glbl class * because it needs an initialized runtime system (and may at some point in time * even be loaded itself). So this is a no-go. What we do is use a single global * variable which may be provided with a pointer by the caller. This variable * resides in rsyslog.c, the main runtime file. We have not seen any realy valule * in providing object access functions. If you don't like that, feel free to * add them. -- rgerhards, 2008-04-17 */ /** Path where modules are searched when loading dynamically. */ extern uchar *glblModPath; /** Optional callback used for runtime error logging. */ extern void (*glblErrLogger)(const int, const int, const uchar *); /* some runtime prototypes */ /** Process messages from iminternal. */ void processImInternal(void); /** Initialize the runtime environment. */ rsRetVal rsrtInit(const char **ppErrObj, obj_if_t *pObjIF); /** Shut down the runtime environment. */ rsRetVal rsrtExit(void); /** Check if the runtime system has been initialized. */ int rsrtIsInit(void); /** Specify an alternative error logger. */ void rsrtSetErrLogger(void (*errLogger)(const int, const int, const uchar *)); /** Default error logger used by the runtime. */ void dfltErrLogger(const int, const int, const uchar *errMsg); /** Determine the local host name and store it in the configuration. */ rsRetVal queryLocalHostname(rsconf_t *const); /** Configure the testbench-only termination marker file. * * This hook is used by imdiag so daemonized tests can prove how rsyslogd * terminated even when the shell cannot wait for the daemon child. The core * duplicates @p path because the normal marker is written after loadable * modules have already been unloaded. */ rsRetVal rsyslogdSetProperTerminationFile(const uchar *path); /** Write the configured testbench termination marker. * * @param status Short status string such as "ok" or "error". * @param reason Termination reason such as "normal" or "timeoutGuard". * @param phase Lifecycle phase that writes the marker. * @return 0 on success or if no marker is configured; non-zero on write error. */ int rsyslogdWriteTerminationMarker(const char *status, const char *reason, const char *phase); /* this define below is intended to be used to implement empty * structs on platforms where at least on struct member is. * absolutely necessary. We need to do this, as our runtime * expects several definitions to be present, even if in * rare cases the code in question does not really need it. */ #ifdef OS_SOLARIS #define EMPTY_STRUCT int remove_me_when_first_real_member_is_added; #else #define EMPTY_STRUCT #endif /** Global pointer to the active configuration object. */ extern rsconf_t *ourConf; /* defined by syslogd.c */ /** add compatibility layer for old platforms that miss essential functions */ #ifndef HAVE_STRNDUP char *strndup(const char *s, size_t n); #endif #if !defined(O_CLOEXEC) && !defined(_AIX) /* of course, this limits the functionality... */ #define O_CLOEXEC 0 #endif #endif /* multi-include protection */ rsyslog-8.2608.0/runtime/PaxHeaders/netstrms.c0000644000000000000000000000013215145046112016244 xustar0030 mtime=1771326538.999013635 30 atime=1787067618.176440362 30 ctime=1787067794.534727664 rsyslog-8.2608.0/runtime/netstrms.c0000664000175000017500000004046515145046112015721 0ustar00rgerrger/* netstrms.c * * Work on this module begun 2008-04-23 by Rainer Gerhards. * * Copyright 2008-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "nsd.h" #include "netstrm.h" #include "netstrms.h" #include "rsconf.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(netstrm) /* load our low-level driver. This must be done before any * driver-specific functions (allmost all...) can be carried * out. Note that the driver's .ifIsLoaded is correctly * initialized by calloc() and we depend on that. */ static rsRetVal loadDrvr(netstrms_t *pThis) { DEFiRet; uchar *pBaseDrvrName; uchar szDrvrName[48]; /* 48 shall be large enough */ pBaseDrvrName = pThis->pBaseDrvrName; if (pBaseDrvrName == NULL) /* if no drvr name is set, use system default */ pBaseDrvrName = glbl.GetDfltNetstrmDrvr(runConf); if (snprintf((char *)szDrvrName, sizeof(szDrvrName), "lmnsd_%s", pBaseDrvrName) == sizeof(szDrvrName)) ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG); CHKmalloc(pThis->pDrvrName = (uchar *)strdup((char *)szDrvrName)); pThis->Drvr.ifVersion = nsdCURR_IF_VERSION; /* The pDrvrName+2 below is a hack to obtain the object name. It * safes us to have yet another variable with the name without "lm" in * front of it. If we change the module load interface, we may re-think * about this hack, but for the time being it is efficient and clean * enough. -- rgerhards, 2008-04-18 */ CHKiRet(obj.UseObj(__FILE__, szDrvrName + 2, szDrvrName, (void *)&pThis->Drvr)); finalize_it: if (iRet != RS_RET_OK) { if (pThis->pDrvrName != NULL) { free(pThis->pDrvrName); pThis->pDrvrName = NULL; } } RETiRet; } /* Standard-Constructor */ BEGINobjConstruct(netstrms) /* be sure to specify the object type also in END macro! */ ENDobjConstruct(netstrms) /* destructor for the netstrms object */ BEGINobjDestruct(netstrms) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(netstrms); /* and now we must release our driver, if we got one. We use the presence of * a driver name string as load indicator (because we also need that string * to release the driver */ if (pThis->pDrvrName != NULL) { obj.ReleaseObj(__FILE__, pThis->pDrvrName + 2, pThis->pDrvrName, (void *)&pThis->Drvr); free(pThis->pDrvrName); } if (pThis->pszDrvrAuthMode != NULL) { free(pThis->pszDrvrAuthMode); pThis->pszDrvrAuthMode = NULL; } if (pThis->pszDrvrPermitExpiredCerts != NULL) { free(pThis->pszDrvrPermitExpiredCerts); pThis->pszDrvrPermitExpiredCerts = NULL; } free((void *)pThis->pszDrvrCAFile); pThis->pszDrvrCAFile = NULL; free((void *)pThis->pszDrvrCRLFile); pThis->pszDrvrCRLFile = NULL; free((void *)pThis->pszDrvrKeyFile); pThis->pszDrvrKeyFile = NULL; free((void *)pThis->pszDrvrCertFile); pThis->pszDrvrCertFile = NULL; if (pThis->pBaseDrvrName != NULL) { free(pThis->pBaseDrvrName); pThis->pBaseDrvrName = NULL; } if (pThis->gnutlsPriorityString != NULL) { free(pThis->gnutlsPriorityString); pThis->gnutlsPriorityString = NULL; } if (pThis->remoteSNI != NULL) { free(pThis->remoteSNI); pThis->remoteSNI = NULL; } ENDobjDestruct(netstrms) /* ConstructionFinalizer */ static rsRetVal netstrmsConstructFinalize(netstrms_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); iRet = loadDrvr(pThis); RETiRet; } static rsRetVal SetSynBacklog(netstrms_t *pThis, const int iSynBacklog) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->iSynBacklog = iSynBacklog; RETiRet; } /* set the base driver name. If the driver name * is set to NULL, the previously set name is deleted but * no name set again (which results in the system default being * used)-- rgerhards, 2008-05-05 */ static rsRetVal SetDrvrName(netstrms_t *pThis, uchar *pszName) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (pThis->pBaseDrvrName != NULL) { free(pThis->pBaseDrvrName); pThis->pBaseDrvrName = NULL; } if (pszName != NULL) { CHKmalloc(pThis->pBaseDrvrName = (uchar *)strdup((char *)pszName)); } finalize_it: RETiRet; } /* set the driver's permitted peers -- rgerhards, 2008-05-19 */ static rsRetVal SetDrvrPermPeers(netstrms_t *pThis, permittedPeers_t *pPermPeers) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->pPermPeers = pPermPeers; RETiRet; } /* return the driver's permitted peers * We use non-standard calling conventions because it makes an awful lot * of sense here. * rgerhards, 2008-05-19 */ static permittedPeers_t *GetDrvrPermPeers(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pPermPeers; } /* set the driver auth mode -- rgerhards, 2008-05-19 */ static rsRetVal SetDrvrAuthMode(netstrms_t *pThis, uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); CHKmalloc(pThis->pszDrvrAuthMode = (uchar *)strdup((char *)mode)); finalize_it: RETiRet; } /* return the driver auth mode * We use non-standard calling conventions because it makes an awful lot * of sense here. * rgerhards, 2008-05-19 */ static uchar *GetDrvrAuthMode(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrAuthMode; } /* return the driver permitexpiredcerts mode * We use non-standard calling conventions because it makes an awful lot * of sense here. * alorbach, 2018-12-21 */ static uchar *GetDrvrPermitExpiredCerts(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrPermitExpiredCerts; } /* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20 */ static rsRetVal SetDrvrPermitExpiredCerts(netstrms_t *pThis, uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (mode != NULL) { CHKmalloc(pThis->pszDrvrPermitExpiredCerts = (uchar *)strdup((char *)mode)); } finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCAFile(netstrms_t *pThis, const uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCAFile = (uchar *)strdup((char *)mode)); } finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCRLFile(netstrms_t *pThis, const uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCRLFile = (uchar *)strdup((char *)mode)); } finalize_it: RETiRet; } static rsRetVal SetDrvrTlsKeyFile(netstrms_t *pThis, const uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (mode != NULL) { CHKmalloc(pThis->pszDrvrKeyFile = (uchar *)strdup((char *)mode)); } finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCertFile(netstrms_t *pThis, const uchar *mode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); if (mode != NULL) { CHKmalloc(pThis->pszDrvrCertFile = (uchar *)strdup((char *)mode)); } finalize_it: RETiRet; } /* Set the priorityString * PascalWithopf 2017-08-16 */ static rsRetVal SetDrvrGnutlsPriorityString(netstrms_t *pThis, uchar *iVal) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); CHKmalloc(pThis->gnutlsPriorityString = (uchar *)strdup((char *)iVal)); finalize_it: RETiRet; } /* return the priorityString * PascalWithopf, 2017-08-16 */ static uchar *GetDrvrGnutlsPriorityString(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->gnutlsPriorityString; } /* set the driver mode -- rgerhards, 2008-04-30 */ static rsRetVal SetDrvrMode(netstrms_t *pThis, int iMode) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->iDrvrMode = iMode; RETiRet; } /* return the driver mode * We use non-standard calling conventions because it makes an awful lot * of sense here. * rgerhards, 2008-04-30 */ static int GetDrvrMode(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->iDrvrMode; } /* set the driver cert extended key usage check setting -- jvymazal, 2019-08-16 */ static rsRetVal SetDrvrCheckExtendedKeyUsage(netstrms_t *pThis, int ChkExtendedKeyUsage) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->DrvrChkExtendedKeyUsage = ChkExtendedKeyUsage; RETiRet; } /* return the driver cert extended key usage check setting * jvymazal, 2019-08-16 */ static int GetDrvrCheckExtendedKeyUsage(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->DrvrChkExtendedKeyUsage; } /* set the driver name checking policy -- jvymazal, 2019-08-16 */ static rsRetVal SetDrvrPrioritizeSAN(netstrms_t *pThis, int prioritizeSan) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->DrvrPrioritizeSan = prioritizeSan; RETiRet; } /* return the driver name checking policy * jvymazal, 2019-08-16 */ static int GetDrvrPrioritizeSAN(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->DrvrPrioritizeSan; } /* set the driver TlsVerifyDepth -- alorbach, 2019-12-20 */ /* set TLS revocation check */ static rsRetVal SetDrvrTlsRevocationCheck(netstrms_t *pThis, int enabled) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->DrvrTlsRevocationCheck = (enabled != 0) ? 1 : 0; RETiRet; } /* return TLS revocation check setting */ static int GetDrvrTlsRevocationCheck(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->DrvrTlsRevocationCheck; } static rsRetVal SetDrvrTlsVerifyDepth(netstrms_t *pThis, int verifyDepth) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); pThis->DrvrVerifyDepth = verifyDepth; RETiRet; } /* return the driver TlsVerifyDepth * alorbach, 2019-12-20 */ static int GetDrvrTlsVerifyDepth(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->DrvrVerifyDepth; } static const uchar *GetDrvrTlsCAFile(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrCAFile; } static const uchar *GetDrvrTlsCRLFile(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrCRLFile; } static const uchar *GetDrvrTlsKeyFile(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrKeyFile; } static const uchar *GetDrvrTlsCertFile(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->pszDrvrCertFile; } static rsRetVal SetDrvrRemoteSNI(netstrms_t *pThis, uchar *remoteSNI) { DEFiRet; ISOBJ_TYPE_assert(pThis, netstrms); CHKmalloc(pThis->remoteSNI = (uchar *)strdup((char *)remoteSNI)); finalize_it: RETiRet; } /* Return the remote server SNI */ static uchar *GetDrvrRemoteSNI(netstrms_t *pThis) { ISOBJ_TYPE_assert(pThis, netstrms); return pThis->remoteSNI; } /* create an instance of a netstrm object. It is initialized with default * values. The current driver is used. The caller may set netstrm properties * and must call ConstructFinalize(). */ static rsRetVal CreateStrm(netstrms_t *pThis, netstrm_t **ppStrm) { netstrm_t *pStrm = NULL; DEFiRet; CHKiRet(objUse(netstrm, DONT_LOAD_LIB)); CHKiRet(netstrm.Construct(&pStrm)); /* we copy over our driver structure. We could provide a pointer to * ourselves, but that costs some performance on each driver invocation. * As we already have hefty indirection (and thus performance toll), I * prefer to copy over the function pointers here. -- rgerhards, 2008-04-23 */ memcpy(&pStrm->Drvr, &pThis->Drvr, sizeof(pThis->Drvr)); pStrm->pNS = pThis; *ppStrm = pStrm; finalize_it: if (iRet != RS_RET_OK) { if (pStrm != NULL) netstrm.Destruct(&pStrm); } RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(netstrms) CODESTARTobjQueryInterface(netstrms); if (pIf->ifVersion != netstrmsCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = netstrmsConstruct; pIf->ConstructFinalize = netstrmsConstructFinalize; pIf->Destruct = netstrmsDestruct; pIf->CreateStrm = CreateStrm; pIf->SetSynBacklog = SetSynBacklog; pIf->SetDrvrName = SetDrvrName; pIf->SetDrvrMode = SetDrvrMode; pIf->GetDrvrMode = GetDrvrMode; pIf->SetDrvrAuthMode = SetDrvrAuthMode; pIf->GetDrvrAuthMode = GetDrvrAuthMode; pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts; pIf->GetDrvrPermitExpiredCerts = GetDrvrPermitExpiredCerts; pIf->SetDrvrGnutlsPriorityString = SetDrvrGnutlsPriorityString; pIf->GetDrvrGnutlsPriorityString = GetDrvrGnutlsPriorityString; pIf->SetDrvrPermPeers = SetDrvrPermPeers; pIf->GetDrvrPermPeers = GetDrvrPermPeers; pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; pIf->GetDrvrCheckExtendedKeyUsage = GetDrvrCheckExtendedKeyUsage; pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; pIf->GetDrvrPrioritizeSAN = GetDrvrPrioritizeSAN; pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth; pIf->SetDrvrTlsRevocationCheck = SetDrvrTlsRevocationCheck; pIf->GetDrvrTlsVerifyDepth = GetDrvrTlsVerifyDepth; pIf->GetDrvrTlsRevocationCheck = GetDrvrTlsRevocationCheck; pIf->SetDrvrRemoteSNI = SetDrvrRemoteSNI; pIf->GetDrvrRemoteSNI = GetDrvrRemoteSNI; pIf->GetDrvrTlsCAFile = GetDrvrTlsCAFile; pIf->GetDrvrTlsCRLFile = GetDrvrTlsCRLFile; pIf->GetDrvrTlsKeyFile = GetDrvrTlsKeyFile; pIf->GetDrvrTlsCertFile = GetDrvrTlsCertFile; pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile; pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile; pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile; pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile; finalize_it: ENDobjQueryInterface(netstrms) /* exit our class */ BEGINObjClassExit(netstrms, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(netstrms); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(netstrm, DONT_LOAD_LIB); ENDObjClassExit(netstrms) /* Initialize the netstrms class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(netstrms, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); /* set our own handlers */ ENDObjClassInit(netstrms) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; netstrmsClassExit(); netstrmClassExit(); /* we use this object, so we must exit it after we are finished */ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ /* Initialize all classes that are in our module - this includes ourselfs */ CHKiRet(netstrmClassInit(pModInfo)); CHKiRet(netstrmsClassInit(pModInfo)); ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/perctile_stats.c0000644000000000000000000000013215216464436017426 xustar0030 mtime=1782212894.037266362 30 atime=1787067617.929435756 30 ctime=1787067794.373724663 rsyslog-8.2608.0/runtime/perctile_stats.c0000664000175000017500000006457215216464436017110 0ustar00rgerrger/* * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include "unicode-helper.h" #include "rsyslog.h" #include "rsconf.h" #include "errmsg.h" #include "perctile_stats.h" #include "hashtable_itr.h" #include "perctile_ringbuf.h" #include "datetime.h" #include #include #include /* Use this macro to enable debug for this module */ #ifdef PERCTILE_STATS_DEBUG #define _DEBUG 1 #else #define _DEBUG 0 #endif #define PERCTILE_STATS_LOG(...) \ do { \ if (_DEBUG) fprintf(stderr, __VA_ARGS__); \ } while (0) /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(statsobj) DEFobjCurrIf(datetime) #define PERCTILE_CONF_PARAM_NAME "name" #define PERCTILE_CONF_PARAM_PERCENTILES "percentiles" #define PERCTILE_CONF_PARAM_WINDOW_SIZE "windowsize" #define PERCTILE_CONF_PARAM_DELIM "delimiter" #define PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH 128 #define PERCTILE_METRIC_NAME_SEPARATOR '.' static struct cnfparamdescr modpdescr[] = { {PERCTILE_CONF_PARAM_NAME, eCmdHdlrString, CNFPARAM_REQUIRED}, {PERCTILE_CONF_PARAM_DELIM, eCmdHdlrString, 0}, {PERCTILE_CONF_PARAM_PERCENTILES, eCmdHdlrArray, 0}, {PERCTILE_CONF_PARAM_WINDOW_SIZE, eCmdHdlrPositiveInt, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; rsRetVal perctileClassInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); finalize_it: RETiRet; } static void perctileDestroyCounter(statsobj_t *stats, ctr_t **ref) { if (*ref != NULL) { if (stats != NULL) { statsobj.DestructCounter(stats, *ref); } else { statsobj.DestructUnlinkedCounter(*ref); } *ref = NULL; } } static uint64_t min(uint64_t a, uint64_t b) { return a < b ? a : b; } static uint64_t max(uint64_t a, uint64_t b) { return a > b ? a : b; } static void perctileStatDestruct(perctile_bucket_t *b, perctile_stat_t *pstat) { if (pstat) { if (pstat->rb_observed_stats) { ringbuf_del(pstat->rb_observed_stats); } if (pstat->ctrs) { for (size_t i = 0; i < pstat->perctile_ctrs_count; ++i) { perctile_ctr_t *ctr = &pstat->ctrs[i]; perctileDestroyCounter(b->statsobj, &ctr->ref_ctr_percentile_stat); } free(pstat->ctrs); } perctileDestroyCounter(b->statsobj, &pstat->refCtrWindowCount); perctileDestroyCounter(b->statsobj, &pstat->refCtrWindowMin); perctileDestroyCounter(b->statsobj, &pstat->refCtrWindowMax); perctileDestroyCounter(b->statsobj, &pstat->refCtrWindowSum); pthread_rwlock_destroy(&pstat->stats_lock); free(pstat); } } static void perctileBucketDestruct(perctile_bucket_t *bkt) { PERCTILE_STATS_LOG("destructing perctile bucket\n"); if (bkt) { /* Drop stats registry visibility before taking bucket locks and * freeing counter backing storage; stats scrapes hold mutStats while * read notifiers take the bucket locks. */ if (bkt->statsobj != NULL) { statsobj.UnlinkAllCounters(bkt->statsobj); statsobj.Destruct(&bkt->statsobj); } pthread_rwlock_wrlock(&bkt->lock); // Delete all items in hashtable size_t count = hashtable_count(bkt->htable); if (count) { int ret = 0; struct hashtable_itr *itr = hashtable_iterator(bkt->htable); dbgprintf("%s() - All container instances, count=%zu...\n", __FUNCTION__, count); do { perctile_stat_t *pstat = hashtable_iterator_value(itr); perctileStatDestruct(bkt, pstat); ret = hashtable_iterator_advance(itr); } while (ret); free(itr); dbgprintf("End of container instances.\n"); } hashtable_destroy(bkt->htable, 0); pthread_rwlock_unlock(&bkt->lock); pthread_rwlock_destroy(&bkt->lock); perctileDestroyCounter(bkt->bkts != NULL ? bkt->bkts->global_stats : NULL, &bkt->pOpsOverflowCtr); perctileDestroyCounter(bkt->bkts != NULL ? bkt->bkts->global_stats : NULL, &bkt->pNewKeyAddCtr); free(bkt->perctile_values); free(bkt->delim); free(bkt->name); free(bkt); } } void perctileBucketsDestruct(void) { perctile_buckets_t *bkts = &runConf->perctile_buckets; if (bkts->initialized) { /* Global counters point into bucket storage, so detach the object * before buckets start releasing that storage. */ if (bkts->global_stats != NULL) { statsobj.UnlinkAllCounters(bkts->global_stats); statsobj.Destruct(&bkts->global_stats); } while (1) { perctile_bucket_t *pnode; pthread_rwlock_wrlock(&bkts->lock); pnode = bkts->listBuckets; if (pnode == NULL) { pthread_rwlock_unlock(&bkts->lock); break; } bkts->listBuckets = pnode->next; pnode->next = NULL; pthread_rwlock_unlock(&bkts->lock); perctileBucketDestruct(pnode); } // destroy any global stats we keep specifically for this. pthread_rwlock_destroy(&bkts->lock); } } static perctile_bucket_t *findBucket(perctile_bucket_t *head, const uchar *name) { perctile_bucket_t *pbkt_found = NULL; // walk the linked list until the name is found pthread_rwlock_rdlock(&head->lock); for (perctile_bucket_t *pnode = head; pnode != NULL; pnode = pnode->next) { if (ustrcmp(name, pnode->name) == 0) { // found. pbkt_found = pnode; } } pthread_rwlock_unlock(&head->lock); return pbkt_found; } #ifdef PERCTILE_STATS_DEBUG static void print_perctiles(perctile_bucket_t *bkt) { if (hashtable_count(bkt->htable)) { struct hashtable_itr *itr = hashtable_iterator(bkt->htable); do { uchar *key = hashtable_iterator_key(itr); perctile_stat_t *perc_stat = hashtable_iterator_value(itr); PERCTILE_STATS_LOG("print_perctile() - key: %s, perctile stat name: %s ", key, perc_stat->name); } while (hashtable_iterator_advance(itr)); PERCTILE_STATS_LOG("\n"); } } #endif // Assumes a fully created pstat and bkt, also initiliazes some values in pstat. static rsRetVal initAndAddPerctileMetrics(perctile_stat_t *pstat, perctile_bucket_t *bkt, uchar *key) { char stat_name[128]; int bytes = 0; int stat_name_len = sizeof(stat_name); DEFiRet; bytes = snprintf((char *)pstat->name, sizeof(pstat->name), "%s", key); if (bytes < 0 || bytes >= (int)sizeof(pstat->name)) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", key, bytes); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } int offset = snprintf(stat_name, stat_name_len, "%s%s", (char *)pstat->name, (char *)bkt->delim); if (offset < 0 || offset >= stat_name_len) { LogError(0, iRet, "statname '%s' delim '%s' truncated - too long for buffer size: %d\n", (char *)pstat->name, (char *)bkt->delim, offset); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } int remaining_size = stat_name_len - offset - 1; // initialize the counters array for (size_t i = 0; i < pstat->perctile_ctrs_count; ++i) { perctile_ctr_t *ctr = &pstat->ctrs[i]; // bucket contains the supported percentile values. ctr->percentile = bkt->perctile_values[i]; bytes = snprintf(stat_name + offset, remaining_size, "p%d", bkt->perctile_values[i]); if (bytes < 0 || bytes >= remaining_size) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr, CTR_FLAG_NONE, &ctr->ctr_perctile_stat, &ctr->ref_ctr_percentile_stat, 1)); } bytes = snprintf(stat_name + offset, remaining_size, "window_min"); if (bytes < 0 || bytes >= remaining_size) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr, CTR_FLAG_NONE, &pstat->ctrWindowMin, &pstat->refCtrWindowMin, 1)); bytes = snprintf(stat_name + offset, remaining_size, "window_max"); if (bytes < 0 || bytes >= remaining_size) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr, CTR_FLAG_NONE, &pstat->ctrWindowMax, &pstat->refCtrWindowMax, 1)); bytes = snprintf(stat_name + offset, remaining_size, "window_sum"); if (bytes < 0 || bytes >= remaining_size) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr, CTR_FLAG_NONE, &pstat->ctrWindowSum, &pstat->refCtrWindowSum, 1)); bytes = snprintf(stat_name + offset, remaining_size, "window_count"); if (bytes < 0 || bytes >= remaining_size) { LogError(0, iRet, "statname '%s' truncated - too long for buffer size: %d\n", stat_name, stat_name_len); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } CHKiRet(statsobj.AddManagedCounter(bkt->statsobj, (uchar *)stat_name, ctrType_IntCtr, CTR_FLAG_NONE, &pstat->ctrWindowCount, &pstat->refCtrWindowCount, 1)); finalize_it: if (iRet != RS_RET_OK) { LogError(0, iRet, "Could not initialize percentile stats."); } RETiRet; } static rsRetVal perctile_observe(perctile_bucket_t *bkt, uchar *key, int64_t value) { uint8_t lock_initialized = 0; uchar *hash_key = NULL; DEFiRet; time_t now; datetime.GetTime(&now); pthread_rwlock_wrlock(&bkt->lock); lock_initialized = 1; perctile_stat_t *pstat = (perctile_stat_t *)hashtable_search(bkt->htable, key); if (!pstat) { PERCTILE_STATS_LOG("perctile_observe(): key '%s' not found - creating new pstat", key); // create the pstat if not found CHKmalloc(pstat = calloc(1, sizeof(perctile_stat_t))); pstat->ctrs = calloc(bkt->perctile_values_count, sizeof(perctile_ctr_t)); if (!pstat->ctrs) { free(pstat); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pstat->perctile_ctrs_count = bkt->perctile_values_count; pstat->rb_observed_stats = ringbuf_new(bkt->window_size); if (!pstat->rb_observed_stats) { free(pstat->ctrs); free(pstat); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pstat->bReported = 0; pthread_rwlock_init(&pstat->stats_lock, NULL); // init all stat counters here pthread_rwlock_wrlock(&pstat->stats_lock); pstat->ctrWindowCount = pstat->ctrWindowMax = pstat->ctrWindowSum = 0; pstat->ctrWindowMin = value; pthread_rwlock_unlock(&pstat->stats_lock); iRet = initAndAddPerctileMetrics(pstat, bkt, key); if (iRet != RS_RET_OK) { perctileStatDestruct(bkt, pstat); ABORT_FINALIZE(iRet); } CHKmalloc(hash_key = ustrdup(key)); if (!hashtable_insert(bkt->htable, hash_key, pstat)) { perctileStatDestruct(bkt, pstat); free(hash_key); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } PERCTILE_STATS_LOG("perctile_observe - new pstat created - name: %s\n", pstat->name); STATSCOUNTER_INC(bkt->ctrNewKeyAdd, bkt->mutCtrNewKeyAdd); } // add this value into the ringbuffer assert(pstat->rb_observed_stats); if (ringbuf_append_with_overwrite(pstat->rb_observed_stats, value) != 0) { // ringbuffer is operating in overwrite mode, so should never see this. ABORT_FINALIZE(RS_RET_ERR); } // update perctile specific stats pthread_rwlock_wrlock(&pstat->stats_lock); { if (pstat->bReported) { // reset window values pstat->ctrWindowCount = pstat->ctrWindowSum = 0; pstat->ctrWindowMin = pstat->ctrWindowMax = value; pstat->bReported = 0; } ++(pstat->ctrWindowCount); pstat->ctrWindowSum += value; pstat->ctrWindowMin = min(pstat->ctrWindowMin, value); pstat->ctrWindowMax = max(pstat->ctrWindowMax, value); } pthread_rwlock_unlock(&pstat->stats_lock); #ifdef PERCTILE_STATS_DEBUG PERCTILE_STATS_LOG("perctile_observe - appended value: %lld to ringbuffer\n", value); PERCTILE_STATS_LOG("ringbuffer contents... \n"); for (size_t i = 0; i < pstat->rb_observed_stats->size; ++i) { PERCTILE_STATS_LOG("%lld ", pstat->rb_observed_stats->cb.buf[i]); } PERCTILE_STATS_LOG("\n"); print_perctiles(bkt); #endif finalize_it: if (lock_initialized) { pthread_rwlock_unlock(&bkt->lock); } if (iRet != RS_RET_OK) { // clean up if there was an error if (iRet == RS_RET_OUT_OF_MEMORY) { STATSCOUNTER_INC(bkt->ctrOpsOverflow, bkt->mutCtrOpsOverflow); } } RETiRet; } static int cmp(const void *p1, const void *p2) { return (*(ITEM *)p1) - (*(ITEM *)p2); } static rsRetVal report_perctile_stats(perctile_bucket_t *pbkt) { ITEM *buf = NULL; struct hashtable_itr *itr = NULL; DEFiRet; pthread_rwlock_rdlock(&pbkt->lock); if (hashtable_count(pbkt->htable)) { itr = hashtable_iterator(pbkt->htable); CHKmalloc(buf = malloc(pbkt->window_size * sizeof(ITEM))); do { memset(buf, 0, pbkt->window_size * sizeof(ITEM)); perctile_stat_t *perc_stat = hashtable_iterator_value(itr); // ringbuffer read size_t count = ringbuf_read_to_end(perc_stat->rb_observed_stats, buf, pbkt->window_size); if (!count) { continue; } PERCTILE_STATS_LOG("read %zu values\n", count); // calculate the p95 based on the #ifdef PERCTILE_STATS_DEBUG PERCTILE_STATS_LOG("ringbuffer contents... \n"); for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) { PERCTILE_STATS_LOG("%lld ", perc_stat->rb_observed_stats->cb.buf[i]); } PERCTILE_STATS_LOG("\n"); PERCTILE_STATS_LOG("buffer contents... \n"); for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) { PERCTILE_STATS_LOG("%lld ", buf[i]); } PERCTILE_STATS_LOG("\n"); #endif qsort(buf, count, sizeof(ITEM), cmp); #ifdef PERCTILE_STATS_DEBUG PERCTILE_STATS_LOG("buffer contents after sort... \n"); for (size_t i = 0; i < perc_stat->rb_observed_stats->size; ++i) { PERCTILE_STATS_LOG("%lld ", buf[i]); } PERCTILE_STATS_LOG("\n"); #endif PERCTILE_STATS_LOG("report_perctile_stats() - perctile stat has %zu counters.", perc_stat->perctile_ctrs_count); for (size_t i = 0; i < perc_stat->perctile_ctrs_count; ++i) { perctile_ctr_t *pctr = &perc_stat->ctrs[i]; // get percentile - this can be cached. int index = max(0, ((pctr->percentile / 100.0) * count) - 1); // look into if we need to lock this. pctr->ctr_perctile_stat = buf[index]; PERCTILE_STATS_LOG("report_perctile_stats() - index: %d, perctile stat [%s, %d, %llu]", index, perc_stat->name, pctr->percentile, pctr->ctr_perctile_stat); } perc_stat->bReported = 1; } while (hashtable_iterator_advance(itr)); } finalize_it: pthread_rwlock_unlock(&pbkt->lock); free(itr); free(buf); RETiRet; } static void perctile_readCallback(statsobj_t __attribute__((unused)) * ignore, void __attribute__((unused)) * b) { perctile_buckets_t *bkts = &runConf->perctile_buckets; pthread_rwlock_rdlock(&bkts->lock); for (perctile_bucket_t *pbkt = bkts->listBuckets; pbkt != NULL; pbkt = pbkt->next) { report_perctile_stats(pbkt); } pthread_rwlock_unlock(&bkts->lock); } static rsRetVal perctileInitNewBucketStats(perctile_bucket_t *b) { DEFiRet; CHKiRet(statsobj.Construct(&b->statsobj)); CHKiRet(statsobj.SetOrigin(b->statsobj, UCHAR_CONSTANT("percentile.bucket"))); CHKiRet(statsobj.SetName(b->statsobj, b->name)); CHKiRet(statsobj.SetReportingNamespace(b->statsobj, UCHAR_CONSTANT("values"))); statsobj.SetReadNotifier(b->statsobj, perctile_readCallback, b); CHKiRet(statsobj.ConstructFinalize(b->statsobj)); finalize_it: RETiRet; } static rsRetVal perctileAddBucketMetrics(perctile_buckets_t *bkts, perctile_bucket_t *b) { uchar *metric_name_buff, *metric_suffix; const uchar *suffix_litteral; const size_t name_len = ustrlen(b->name); DEFiRet; CHKmalloc(metric_name_buff = malloc((name_len + PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH + 1) * sizeof(uchar))); /* b->name is our owned duplicate created during bucket construction. */ memcpy(metric_name_buff, b->name, name_len + 1); metric_suffix = metric_name_buff + name_len; *metric_suffix = PERCTILE_METRIC_NAME_SEPARATOR; metric_suffix++; suffix_litteral = UCHAR_CONSTANT("new_metric_add"); ustrncpy(metric_suffix, suffix_litteral, PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrNewKeyAdd, b->mutCtrNewKeyAdd); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrNewKeyAdd), &b->pNewKeyAddCtr, 1)); suffix_litteral = UCHAR_CONSTANT("ops_overflow"); ustrncpy(metric_suffix, suffix_litteral, PERCTILE_MAX_BUCKET_NS_METRIC_LENGTH); STATSCOUNTER_INIT(b->ctrOpsOverflow, b->mutCtrOpsOverflow); CHKiRet(statsobj.AddManagedCounter(bkts->global_stats, metric_name_buff, ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(b->ctrOpsOverflow), &b->pOpsOverflowCtr, 1)); finalize_it: free(metric_name_buff); if (iRet != RS_RET_OK) { perctileDestroyCounter(bkts->global_stats, &b->pOpsOverflowCtr); perctileDestroyCounter(bkts->global_stats, &b->pNewKeyAddCtr); } RETiRet; } /* Create new perctile bucket, and add it to our list of perctile buckets. */ static rsRetVal perctile_newBucket( const uchar *name, const uchar *delim, uint8_t *perctiles, uint32_t perctilesCount, uint32_t windowSize) { perctile_buckets_t *bkts; perctile_bucket_t *b = NULL; pthread_rwlockattr_t bucket_lock_attr; DEFiRet; bkts = &loadConf->perctile_buckets; if (bkts->initialized) { CHKmalloc(b = calloc(1, sizeof(perctile_bucket_t))); // initialize b->bkts = bkts; pthread_rwlockattr_init(&bucket_lock_attr); pthread_rwlock_init(&b->lock, &bucket_lock_attr); CHKmalloc(b->htable = create_hashtable(7, hash_from_string, key_equals_string, NULL)); CHKmalloc(b->name = ustrdup(name)); if (delim) { CHKmalloc(b->delim = ustrdup(delim)); } else { CHKmalloc(b->delim = ustrdup(".")); } CHKmalloc(b->perctile_values = calloc(perctilesCount, sizeof(uint8_t))); b->perctile_values_count = perctilesCount; memcpy(b->perctile_values, perctiles, perctilesCount * sizeof(uint8_t)); b->window_size = windowSize; b->next = NULL; PERCTILE_STATS_LOG( "perctile_newBucket: create new bucket for %s," "with windowsize: %d, values_count: %zu\n", b->name, b->window_size, b->perctile_values_count); // create the statsobj for this bucket CHKiRet(perctileInitNewBucketStats(b)); CHKiRet(perctileAddBucketMetrics(bkts, b)); // add bucket to list of buckets pthread_rwlock_wrlock(&bkts->lock); if (!bkts->listBuckets) { // none yet bkts->listBuckets = b; PERCTILE_STATS_LOG("perctile_newBucket: Adding new bucket to empty list \n"); } else { b->next = bkts->listBuckets; bkts->listBuckets = b; PERCTILE_STATS_LOG("perctile_newBucket: prepended new bucket list \n"); } pthread_rwlock_unlock(&bkts->lock); } else { LogError(0, RS_RET_INTERNAL_ERROR, "perctile: bucket creation failed, as " "global-initialization of buckets was unsuccessful"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } finalize_it: if (iRet != RS_RET_OK) { if (b != NULL) { perctileBucketDestruct(b); } } RETiRet; } // Public functions rsRetVal perctile_processCnf(struct cnfobj *o) { struct cnfparamvals *pvals; uchar *name = NULL; uchar *delim = NULL; uint8_t *perctiles = NULL; uint32_t perctilesCount = 0; uint64_t windowSize = 0; DEFiRet; pvals = nvlstGetParams(o->nvlst, &modpblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } for (short i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_NAME)) { CHKmalloc(name = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_DELIM)) { CHKmalloc(delim = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_PERCENTILES)) { /* Only the first instance of this parameter will be accepted */ if (!perctiles) { perctilesCount = pvals[i].val.d.ar->nmemb; if (perctilesCount) { CHKmalloc(perctiles = calloc(perctilesCount, sizeof(uint8_t))); for (int j = 0; j < pvals[i].val.d.ar->nmemb; ++j) { char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); CHKmalloc(cstr); char *endptr = NULL; errno = 0; const long val = strtol(cstr, &endptr, 10); if (errno == ERANGE || endptr == cstr || *endptr != '\0' || val < 0 || val > 100) { LogError( 0, RS_RET_PARAM_ERROR, "perctile: percentile value '%s' is invalid - must be an integer between 0 and 100", cstr); free(cstr); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } perctiles[j] = (uint8_t)val; free(cstr); } } } } else if (!strcmp(modpblk.descr[i].name, PERCTILE_CONF_PARAM_WINDOW_SIZE)) { windowSize = pvals[i].val.d.n; } else { dbgprintf( "perctile: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } if (name != NULL && perctiles != NULL) { CHKiRet(perctile_newBucket(name, delim, perctiles, perctilesCount, windowSize)); } finalize_it: free(name); free(delim); free(perctiles); cnfparamvalsDestruct(pvals, &modpblk); RETiRet; } rsRetVal perctile_initCnf(perctile_buckets_t *bkts) { DEFiRet; bkts->initialized = 0; bkts->listBuckets = NULL; CHKiRet(statsobj.Construct(&bkts->global_stats)); CHKiRet(statsobj.SetOrigin(bkts->global_stats, UCHAR_CONSTANT("percentile"))); CHKiRet(statsobj.SetName(bkts->global_stats, UCHAR_CONSTANT("global"))); CHKiRet(statsobj.SetReportingNamespace(bkts->global_stats, UCHAR_CONSTANT("values"))); CHKiRet(statsobj.ConstructFinalize(bkts->global_stats)); pthread_rwlock_init(&bkts->lock, NULL); bkts->initialized = 1; finalize_it: if (iRet != RS_RET_OK) { statsobj.Destruct(&bkts->global_stats); } RETiRet; } perctile_bucket_t *perctile_findBucket(const uchar *name) { perctile_bucket_t *b = NULL; perctile_buckets_t *bkts = &loadConf->perctile_buckets; if (bkts->initialized) { pthread_rwlock_rdlock(&bkts->lock); if (bkts->listBuckets) { b = findBucket(bkts->listBuckets, name); } pthread_rwlock_unlock(&bkts->lock); } else { LogError(0, RS_RET_INTERNAL_ERROR, "perctile: bucket lookup failed, as global-initialization " "of buckets was unsuccessful"); } return b; } rsRetVal perctile_obs(perctile_bucket_t *perctile_bkt, uchar *key, int64_t value) { DEFiRet; if (!perctile_bkt) { LogError(0, RS_RET_INTERNAL_ERROR, "perctile() - perctile bkt not available"); FINALIZE; } PERCTILE_STATS_LOG("perctile_obs() - bucket name: %s, key: %s, val: %" PRId64 "\n", perctile_bkt->name, key, value); CHKiRet(perctile_observe(perctile_bkt, key, value)); finalize_it: if (iRet != RS_RET_OK) { LogError(0, RS_RET_INTERNAL_ERROR, "perctile_obs(): name: %s, key: %s, val: %" PRId64 "\n", perctile_bkt->name, key, value); } RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_crc.c0000644000000000000000000000013215241075234016651 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.409725334 rsyslog-8.2608.0/runtime/segdisk_crc.c0000664000175000017500000000774315241075234016330 0ustar00rgerrger#include "config.h" #include "segdisk_crc.h" uint32_t segdiskCrc32c(const void *vbuf, size_t len) { /* A portable byte table halves the dependent lookups of the compact * nibble implementation without relying on CPU-specific instructions. */ static const uint32_t table[256] = { 0x00000000u, 0xf26b8303u, 0xe13b70f7u, 0x1350f3f4u, 0xc79a971fu, 0x35f1141cu, 0x26a1e7e8u, 0xd4ca64ebu, 0x8ad958cfu, 0x78b2dbccu, 0x6be22838u, 0x9989ab3bu, 0x4d43cfd0u, 0xbf284cd3u, 0xac78bf27u, 0x5e133c24u, 0x105ec76fu, 0xe235446cu, 0xf165b798u, 0x030e349bu, 0xd7c45070u, 0x25afd373u, 0x36ff2087u, 0xc494a384u, 0x9a879fa0u, 0x68ec1ca3u, 0x7bbcef57u, 0x89d76c54u, 0x5d1d08bfu, 0xaf768bbcu, 0xbc267848u, 0x4e4dfb4bu, 0x20bd8edeu, 0xd2d60dddu, 0xc186fe29u, 0x33ed7d2au, 0xe72719c1u, 0x154c9ac2u, 0x061c6936u, 0xf477ea35u, 0xaa64d611u, 0x580f5512u, 0x4b5fa6e6u, 0xb93425e5u, 0x6dfe410eu, 0x9f95c20du, 0x8cc531f9u, 0x7eaeb2fau, 0x30e349b1u, 0xc288cab2u, 0xd1d83946u, 0x23b3ba45u, 0xf779deaeu, 0x05125dadu, 0x1642ae59u, 0xe4292d5au, 0xba3a117eu, 0x4851927du, 0x5b016189u, 0xa96ae28au, 0x7da08661u, 0x8fcb0562u, 0x9c9bf696u, 0x6ef07595u, 0x417b1dbcu, 0xb3109ebfu, 0xa0406d4bu, 0x522bee48u, 0x86e18aa3u, 0x748a09a0u, 0x67dafa54u, 0x95b17957u, 0xcba24573u, 0x39c9c670u, 0x2a993584u, 0xd8f2b687u, 0x0c38d26cu, 0xfe53516fu, 0xed03a29bu, 0x1f682198u, 0x5125dad3u, 0xa34e59d0u, 0xb01eaa24u, 0x42752927u, 0x96bf4dccu, 0x64d4cecfu, 0x77843d3bu, 0x85efbe38u, 0xdbfc821cu, 0x2997011fu, 0x3ac7f2ebu, 0xc8ac71e8u, 0x1c661503u, 0xee0d9600u, 0xfd5d65f4u, 0x0f36e6f7u, 0x61c69362u, 0x93ad1061u, 0x80fde395u, 0x72966096u, 0xa65c047du, 0x5437877eu, 0x4767748au, 0xb50cf789u, 0xeb1fcbadu, 0x197448aeu, 0x0a24bb5au, 0xf84f3859u, 0x2c855cb2u, 0xdeeedfb1u, 0xcdbe2c45u, 0x3fd5af46u, 0x7198540du, 0x83f3d70eu, 0x90a324fau, 0x62c8a7f9u, 0xb602c312u, 0x44694011u, 0x5739b3e5u, 0xa55230e6u, 0xfb410cc2u, 0x092a8fc1u, 0x1a7a7c35u, 0xe811ff36u, 0x3cdb9bddu, 0xceb018deu, 0xdde0eb2au, 0x2f8b6829u, 0x82f63b78u, 0x709db87bu, 0x63cd4b8fu, 0x91a6c88cu, 0x456cac67u, 0xb7072f64u, 0xa457dc90u, 0x563c5f93u, 0x082f63b7u, 0xfa44e0b4u, 0xe9141340u, 0x1b7f9043u, 0xcfb5f4a8u, 0x3dde77abu, 0x2e8e845fu, 0xdce5075cu, 0x92a8fc17u, 0x60c37f14u, 0x73938ce0u, 0x81f80fe3u, 0x55326b08u, 0xa759e80bu, 0xb4091bffu, 0x466298fcu, 0x1871a4d8u, 0xea1a27dbu, 0xf94ad42fu, 0x0b21572cu, 0xdfeb33c7u, 0x2d80b0c4u, 0x3ed04330u, 0xccbbc033u, 0xa24bb5a6u, 0x502036a5u, 0x4370c551u, 0xb11b4652u, 0x65d122b9u, 0x97baa1bau, 0x84ea524eu, 0x7681d14du, 0x2892ed69u, 0xdaf96e6au, 0xc9a99d9eu, 0x3bc21e9du, 0xef087a76u, 0x1d63f975u, 0x0e330a81u, 0xfc588982u, 0xb21572c9u, 0x407ef1cau, 0x532e023eu, 0xa145813du, 0x758fe5d6u, 0x87e466d5u, 0x94b49521u, 0x66df1622u, 0x38cc2a06u, 0xcaa7a905u, 0xd9f75af1u, 0x2b9cd9f2u, 0xff56bd19u, 0x0d3d3e1au, 0x1e6dcdeeu, 0xec064eedu, 0xc38d26c4u, 0x31e6a5c7u, 0x22b65633u, 0xd0ddd530u, 0x0417b1dbu, 0xf67c32d8u, 0xe52cc12cu, 0x1747422fu, 0x49547e0bu, 0xbb3ffd08u, 0xa86f0efcu, 0x5a048dffu, 0x8ecee914u, 0x7ca56a17u, 0x6ff599e3u, 0x9d9e1ae0u, 0xd3d3e1abu, 0x21b862a8u, 0x32e8915cu, 0xc083125fu, 0x144976b4u, 0xe622f5b7u, 0xf5720643u, 0x07198540u, 0x590ab964u, 0xab613a67u, 0xb831c993u, 0x4a5a4a90u, 0x9e902e7bu, 0x6cfbad78u, 0x7fab5e8cu, 0x8dc0dd8fu, 0xe330a81au, 0x115b2b19u, 0x020bd8edu, 0xf0605beeu, 0x24aa3f05u, 0xd6c1bc06u, 0xc5914ff2u, 0x37faccf1u, 0x69e9f0d5u, 0x9b8273d6u, 0x88d28022u, 0x7ab90321u, 0xae7367cau, 0x5c18e4c9u, 0x4f48173du, 0xbd23943eu, 0xf36e6f75u, 0x0105ec76u, 0x12551f82u, 0xe03e9c81u, 0x34f4f86au, 0xc69f7b69u, 0xd5cf889du, 0x27a40b9eu, 0x79b737bau, 0x8bdcb4b9u, 0x988c474du, 0x6ae7c44eu, 0xbe2da0a5u, 0x4c4623a6u, 0x5f16d052u, 0xad7d5351u, }; const unsigned char *buf = vbuf; uint32_t crc = ~0u; for (size_t i = 0; i < len; ++i) { crc = table[(crc ^ buf[i]) & 0xffu] ^ (crc >> 8); } return ~crc; } rsyslog-8.2608.0/runtime/PaxHeaders/lookup.h0000644000000000000000000000012715216464436015723 xustar0028 mtime=1782212894.0272662 30 atime=1787067616.831415283 29 ctime=1787067794.45672621 rsyslog-8.2608.0/runtime/lookup.h0000664000175000017500000000742215216464436015370 0ustar00rgerrger/* header for lookup.c * * Copyright 2013-2023 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LOOKUP_H #define INCLUDED_LOOKUP_H #include #include #define STRING_LOOKUP_TABLE 1 #define ARRAY_LOOKUP_TABLE 2 #define SPARSE_ARRAY_LOOKUP_TABLE 3 #define STUBBED_LOOKUP_TABLE 4 #define REGEX_LOOKUP_TABLE 5 #define LOOKUP_KEY_TYPE_STRING 1 #define LOOKUP_KEY_TYPE_UINT 2 #define LOOKUP_KEY_TYPE_NONE 3 struct lookup_tables_s { lookup_ref_t *root; /* the root of the template list */ lookup_ref_t *last; /* points to the last element of the template list */ }; struct lookup_array_tab_s { uint32_t first_key; uchar **interned_val_refs; }; struct lookup_sparseArray_tab_entry_s { uint32_t key; uchar *interned_val_ref; }; struct lookup_sparseArray_tab_s { lookup_sparseArray_tab_entry_t *entries; }; struct lookup_string_tab_entry_s { uchar *key; uchar *interned_val_ref; }; struct lookup_string_tab_s { lookup_string_tab_entry_t *entries; }; struct lookup_regex_tab_entry_s { regex_t regex; uchar *regex_str; uchar *interned_val_ref; uint8_t is_compiled; }; struct lookup_regex_tab_s { lookup_regex_tab_entry_t *entries; }; struct lookup_ref_s { pthread_rwlock_t rwlock; /* protect us in case of dynamic reloads */ uchar *name; uchar *filename; lookup_t *self; lookup_ref_t *next; /* reload specific attributes */ pthread_mutex_t reloader_mut; /* signaling + access to reload-flow variables*/ /* rwlock(above) may be acquired inside critical-section reloader_mut guards */ pthread_cond_t run_reloader; pthread_t reloader; pthread_attr_t reloader_thd_attr; uchar *stub_value_for_reload_failure; uint8_t rwlock_initialized; uint8_t reloader_mut_initialized; uint8_t run_reloader_initialized; uint8_t reloader_attr_initialized; uint8_t reloader_started; uint8_t do_reload; /* Set after do_reload is consumed until the table swap is complete. */ uint8_t is_reloading; uint8_t do_stop; uint8_t reload_on_hup; }; typedef es_str_t *(lookup_fn_t)(lookup_t *, lookup_key_t); /* a single lookup table */ struct lookup_s { uint32_t nmemb; uint8_t type; uint8_t key_type; union { lookup_string_tab_t *str; lookup_array_tab_t *arr; lookup_sparseArray_tab_t *sprsArr; lookup_regex_tab_t *regex; } table; uint32_t interned_val_count; uchar **interned_vals; uchar *nomatch; lookup_fn_t *lookup; }; union lookup_key_u { uchar *k_str; uint32_t k_uint; }; /* prototypes */ void lookupInitCnf(lookup_tables_t *lu_tabs); rsRetVal lookupTableDefProcessCnf(struct cnfobj *o); lookup_ref_t *lookupFindTable(uchar *name); es_str_t *lookupKey(lookup_ref_t *pThis, lookup_key_t key); es_str_t *lookupKeyLocked(lookup_ref_t *pThis, lookup_key_t key); void lookupDestroyCnf(void); void lookupClassExit(void); void lookupDoHUP(void); rsRetVal lookupReload(lookup_ref_t *pThis, const uchar *stub_value_if_reload_fails); uint lookupPendingReloadCount(void); rsRetVal lookupClassInit(void); void lookupActivateConf(void); #endif /* #ifndef INCLUDED_LOOKUP_H */ rsyslog-8.2608.0/runtime/PaxHeaders/parse.c0000644000000000000000000000013215216464436015513 xustar0030 mtime=1782212894.037266362 30 atime=1787067618.100438945 30 ctime=1787067794.475726564 rsyslog-8.2608.0/runtime/parse.c0000664000175000017500000003561115216464436015165 0ustar00rgerrger/* parsing routines for the counted string class. for generic * informaton see parse.h. * * begun 2005-09-15 rgerhards * * Copyright 2005-2017 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "net.h" /* struct NetAddr */ #include "parse.h" #include "debug.h" /* ################################################################# * * private members * * ################################################################# */ /* ################################################################# * * public members * * ################################################################# */ static void freeNetAddrContent(struct NetAddr *const pIP) { if (pIP == NULL) return; if (F_ISSET(pIP->flags, ADDR_NAME)) free(pIP->addr.HostWildcard); else free(pIP->addr.NetAddr); } /** * Destruct a rsPars object and its associated string. * rgerhards, 2005-09-26 */ rsRetVal rsParsDestruct(rsParsObj *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsPars); if (pThis->pCStr != NULL) rsCStrDestruct(&pThis->pCStr); RSFREEOBJ(pThis); return RS_RET_OK; } /** * Construct a rsPars object. */ rsRetVal rsParsConstruct(rsParsObj **ppThis) { rsParsObj *pThis; assert(ppThis != NULL); if ((pThis = (rsParsObj *)calloc(1, sizeof(rsParsObj))) == NULL) return RS_RET_OUT_OF_MEMORY; rsSETOBJTYPE(pThis, OIDrsPars); *ppThis = pThis; return RS_RET_OK; } /** * Construct a rsPars object and populate it with a * classical zero-terinated C-String. * rgerhards, 2005-09-27 */ rsRetVal rsParsConstructFromSz(rsParsObj **ppThis, unsigned char *psz) { DEFiRet; rsParsObj *pThis; cstr_t *pCS; assert(ppThis != NULL); assert(psz != NULL); /* create string for parser */ CHKiRet(rsCStrConstructFromszStr(&pCS, psz)); /* create parser */ if ((iRet = rsParsConstruct(&pThis)) != RS_RET_OK) { rsCStrDestruct(&pCS); FINALIZE; } /* assign string to parser */ if ((iRet = rsParsAssignString(pThis, pCS)) != RS_RET_OK) { rsParsDestruct(pThis); FINALIZE; } *ppThis = pThis; finalize_it: RETiRet; } /** * Assign the to-be-parsed string. */ rsRetVal rsParsAssignString(rsParsObj *pThis, cstr_t *pCStr) { rsCHECKVALIDOBJECT(pThis, OIDrsPars); rsCHECKVALIDOBJECT(pCStr, OIDrsCStr); pThis->pCStr = pCStr; pThis->iCurrPos = 0; return RS_RET_OK; } /* parse an integer. The parse pointer is advanced to the * position directly after the last digit. If no digit is * found at all, an error is returned and the parse pointer * is NOT advanced. * PORTABILITY WARNING: this function depends on the * continues representation of digits inside the character * set (as in ASCII). * rgerhards 2005-09-27 */ rsRetVal parsInt(rsParsObj *pThis, int *pInt) { unsigned char *pC; int iVal; rsCHECKVALIDOBJECT(pThis, OIDrsPars); assert(pInt != NULL); iVal = 0; pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* order of checks is important, else we might do * mis-addressing! (off by one) */ if (pThis->iCurrPos >= rsCStrLen(pThis->pCStr)) return RS_RET_NO_MORE_DATA; if (!isdigit((int)*pC)) return RS_RET_NO_DIGIT; while (pThis->iCurrPos < rsCStrLen(pThis->pCStr) && isdigit((int)*pC)) { iVal = iVal * 10 + *pC - '0'; ++pThis->iCurrPos; ++pC; } *pInt = iVal; return RS_RET_OK; } /* Skip everything up to a specified character. * Returns with ParsePointer set BEHIND this character. * Returns RS_RET_OK if found, RS_RET_NOT_FOUND if not * found. In that case, the ParsePointer is moved to the * last character of the string. * 2005-09-19 rgerhards */ rsRetVal parsSkipAfterChar(rsParsObj *pThis, char c) { register unsigned char *pC; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); pC = rsCStrGetBufBeg(pThis->pCStr); while (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) { if (pC[pThis->iCurrPos] == c) break; ++pThis->iCurrPos; } /* delimiter found? */ if (pC[pThis->iCurrPos] == c) { if (pThis->iCurrPos + 1 < rsCStrLen(pThis->pCStr)) { iRet = RS_RET_OK; pThis->iCurrPos++; /* 'eat' delimiter */ } else { iRet = RS_RET_FOUND_AT_STRING_END; } } else { iRet = RS_RET_NOT_FOUND; } RETiRet; } /* Skip whitespace. Often used to trim parsable entries. * Returns with ParsePointer set to first non-whitespace * character (or at end of string). */ rsRetVal parsSkipWhitespace(rsParsObj *pThis) { register unsigned char *pC; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); pC = rsCStrGetBufBeg(pThis->pCStr); while (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) { if (!isspace((int)*(pC + pThis->iCurrPos))) break; ++pThis->iCurrPos; } RETiRet; } /* Parse string up to a delimiter. * * Input: * cDelim - the delimiter. Note that SP within a value always is a delimiter, * so cDelim is actually an *additional* delimiter. * The following two are for whitespace stripping, * 0 means "no", 1 "yes" * - bTrimLeading * - bTrimTrailing * - bConvLower - convert string to lower case? * * Output: * ppCStr Pointer to the parsed string - must be freed by caller! */ rsRetVal parsDelimCStr( rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower) { DEFiRet; register unsigned char *pC; cstr_t *pCStr = NULL; rsCHECKVALIDOBJECT(pThis, OIDrsPars); CHKiRet(rsCStrConstruct(&pCStr)); if (bTrimLeading) parsSkipWhitespace(pThis); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; while (pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) { CHKiRet(cstrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC)); ++pThis->iCurrPos; ++pC; } if (pThis->iCurrPos < cstrLen(pThis->pCStr)) { // BUGFIX!! ++pThis->iCurrPos; /* eat delimiter */ } /* We got the string, now take it and see if we need to * remove anything at its end. */ cstrFinalize(pCStr); if (bTrimTrailing) { cstrTrimTrailingWhiteSpace(pCStr); } /* done! */ *ppCStr = pCStr; finalize_it: if (iRet != RS_RET_OK) { if (pCStr != NULL) rsCStrDestruct(&pCStr); } RETiRet; } /* Parse a quoted string ("-some-data") from the given position. * Leading whitespace before the first quote is skipped. During * parsing, escape sequences are detected and converted: * \\ - backslash character * \" - quote character * any other value \ is reserved for future use. * * After return, the parse pointer is paced after the trailing * quote. * * Output: * ppCStr Pointer to the parsed string - must be freed by caller and * does NOT include the quotes. * rgerhards, 2005-09-19 */ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr) { register unsigned char *pC; cstr_t *pCStr = NULL; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); CHKiRet(parsSkipAfterChar(pThis, '"')); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* OK, we most probably can obtain a value... */ CHKiRet(cstrConstruct(&pCStr)); while (pThis->iCurrPos < cstrLen(pThis->pCStr)) { if (*pC == '"') { break; /* we are done! */ } else if (*pC == '\\') { ++pThis->iCurrPos; ++pC; if (pThis->iCurrPos < cstrLen(pThis->pCStr)) { /* in this case, we copy the escaped character * to the output buffer (but do not rely on this, * we might later introduce other things, like \007! */ CHKiRet(cstrAppendChar(pCStr, *pC)); } } else { /* regular character */ CHKiRet(cstrAppendChar(pCStr, *pC)); } ++pThis->iCurrPos; ++pC; } if (*pC == '"') { ++pThis->iCurrPos; /* 'eat' trailing quote */ } else { /* error - improperly quoted string! */ cstrDestruct(&pCStr); ABORT_FINALIZE(RS_RET_MISSING_TRAIL_QUOTE); } cstrFinalize(pCStr); /* done! */ *ppCStr = pCStr; finalize_it: if (iRet != RS_RET_OK) { if (pCStr != NULL) cstrDestruct(&pCStr); } RETiRet; } /* * Parsing routine for IPv4, IPv6 and domain name wildcards. * * Parses string in the format [/bits] where * addr can be a IPv4 address (e.g.: 127.0.0.1), IPv6 address (e.g.: [::1]), * full hostname (e.g.: localhost.localdomain) or hostname wildcard * (e.g.: *.localdomain). */ rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits) { register uchar *pC; uchar *pszIP = NULL; uchar *pszTmp; struct addrinfo hints, *res = NULL; cstr_t *pCStr; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); assert(pIP != NULL); assert(pBits != NULL); CHKiRet(cstrConstruct(&pCStr)); parsSkipWhitespace(pThis); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* we parse everything until either '/', ',' or * whitespace. Validity will be checked down below. */ while (pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != '/' && *pC != ',' && !isspace((int)*pC)) { if ((iRet = cstrAppendChar(pCStr, *pC)) != RS_RET_OK) { cstrDestruct(&pCStr); FINALIZE; } ++pThis->iCurrPos; ++pC; } cstrFinalize(pCStr); /* now we have the string and must check/convert it to * an NetAddr structure. */ CHKiRet(cstrConvSzStrAndDestruct(&pCStr, &pszIP, 0)); if ((*pIP = calloc(1, sizeof(struct NetAddr))) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (*((char *)pszIP) == '[') { pszTmp = (uchar *)strchr((char *)pszIP, ']'); if (pszTmp == NULL) { free(*pIP); ABORT_FINALIZE(RS_RET_INVALID_IP); } *pszTmp = '\0'; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET6; hints.ai_flags = AI_NUMERICHOST; switch (getaddrinfo((char *)pszIP + 1, NULL, &hints, &res)) { case 0: (*pIP)->addr.NetAddr = malloc(res->ai_addrlen); memcpy((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); break; case EAI_NONAME: /* The "address" is not an IP prefix but a wildcard */ F_SET((*pIP)->flags, ADDR_NAME | ADDR_PRI6); (*pIP)->addr.HostWildcard = strdup((const char *)pszIP + 1); break; default: free(*pIP); ABORT_FINALIZE(RS_RET_ERR); } if (*pC == '/') { /* mask bits follow, let's parse them! */ ++pThis->iCurrPos; /* eat slash */ if ((iRet = parsInt(pThis, pBits)) != RS_RET_OK) { freeNetAddrContent(*pIP); free(*pIP); *pIP = NULL; FINALIZE; } /* we need to refresh pointer (changed by parsInt()) */ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; } else { /* no slash, so we assume a single host (/128) */ *pBits = 128; } } else { /* now parse IPv4 */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_flags = AI_NUMERICHOST; switch (getaddrinfo((char *)pszIP, NULL, &hints, &res)) { case 0: (*pIP)->addr.NetAddr = malloc(res->ai_addrlen); memcpy((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); break; case EAI_NONAME: /* The "address" is not an IP prefix but a wildcard */ F_SET((*pIP)->flags, ADDR_NAME); (*pIP)->addr.HostWildcard = strdup((const char *)pszIP); break; default: free(*pIP); ABORT_FINALIZE(RS_RET_ERR); } if (*pC == '/') { /* mask bits follow, let's parse them! */ ++pThis->iCurrPos; /* eat slash */ if ((iRet = parsInt(pThis, pBits)) != RS_RET_OK) { freeNetAddrContent(*pIP); free(*pIP); *pIP = NULL; FINALIZE; } /* we need to refresh pointer (changed by parsInt()) */ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; } else { /* no slash, so we assume a single host (/32) */ *pBits = 32; } } /* skip to next processable character */ while (pThis->iCurrPos < rsCStrLen(pThis->pCStr) && (*pC == ',' || isspace((int)*pC))) { ++pThis->iCurrPos; ++pC; } iRet = RS_RET_OK; finalize_it: free(pszIP); RETiRet; } /* tell if the parsepointer is at the end of the * to-be-parsed string. Returns 1, if so, 0 * otherwise. rgerhards, 2005-09-27 */ int parsIsAtEndOfParseString(rsParsObj *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsPars); return (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) ? 0 : 1; } /* return the position of the parse pointer */ int rsParsGetParsePointer(rsParsObj *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsPars); if (pThis->iCurrPos < rsCStrLen(pThis->pCStr)) return pThis->iCurrPos; else return rsCStrLen(pThis->pCStr) - 1; } /* peek at the character at the parse pointer * the caller must ensure that the parse pointer is not * at the end of the parse buffer (e.g. by first calling * parsIsAtEndOfParseString). * rgerhards, 2005-09-27 */ char parsPeekAtCharAtParsPtr(rsParsObj *pThis) { rsCHECKVALIDOBJECT(pThis, OIDrsPars); assert(pThis->iCurrPos < rsCStrLen(pThis->pCStr)); return (*(pThis->pCStr->pBuf + pThis->iCurrPos)); } /* return the current position inside the parse object. * rgerhards, 2007-07-04 */ int parsGetCurrentPosition(rsParsObj *pThis) { return pThis->iCurrPos; } /* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * tab-width: 8 * End: * vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/ratelimit.c0000644000000000000000000000013115241075234016362 xustar0029 mtime=1787067036.60857835 30 atime=1787067036.755581103 30 ctime=1787067794.440725912 rsyslog-8.2608.0/runtime/ratelimit.c0000664000175000017500000036126715241075234016046 0ustar00rgerrger/* ratelimit.c * support for rate-limiting sources, including "last message * repeated n times" processing. * * Copyright 2012-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_INOTIFY_H #include #endif #include "rsyslog.h" #include "errmsg.h" #include "ratelimit.h" #include "datetime.h" #include "atomic.h" #include "parser.h" #include "unicode-helper.h" #include "msg.h" #include "rsconf.h" #include "dirty.h" #include "hashtable.h" #include "statsobj.h" #include "template.h" #include "hashtable_itr.h" #include "srUtils.h" #ifdef HAVE_LIBYAML #include #endif /* definitions for objects we access */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) DEFobjCurrIf(parser) DEFobjCurrIf(statsobj) static inline unsigned int ratelimitSharedLoadUInt(unsigned int *value, pthread_mutex_t *mut) { (void)mut; return ATOMIC_LOAD_32BIT_unsigned(value, mut); } static inline void ratelimitSharedStoreUInt(unsigned int *value, pthread_mutex_t *mut, unsigned int newval) { (void)mut; ATOMIC_STORE_32BIT_unsigned(value, mut, newval); } static inline int ratelimitSharedLoadSeverity(int *value, pthread_mutex_t *mut) { (void)mut; return ATOMIC_LOAD_32BIT(value, mut); } static inline void ratelimitSharedStoreSeverity(int *value, pthread_mutex_t *mut, int newval) { (void)mut; ATOMIC_STORE_32BIT(value, mut, newval); } static inline unsigned int ratelimitPerSourceLoadEnabled(unsigned int *value, pthread_mutex_t *mut) { (void)mut; return ATOMIC_LOAD_32BIT_unsigned(value, mut); } static inline void ratelimitPerSourceStoreEnabled(unsigned int *value, pthread_mutex_t *mut, unsigned int newval) { (void)mut; ATOMIC_STORE_32BIT_unsigned(value, mut, newval); } static void ratelimitUnregisterSharedWatchers(ratelimit_shared_t *shared); static void ratelimitDestroyPerSourceShards(ratelimit_shared_t *shared); static rsRetVal ratelimitInitPerSourceShards(ratelimit_shared_t *shared, unsigned int max_states); static void ratelimitSetPerSourceShardCaps(ratelimit_shared_t *shared, unsigned int max_states); static void ratelimitFreePerSourceEntry(void *ptr); static void ratelimitSharedRefsInit(ratelimit_shared_t *const shared, const unsigned int refcnt) { pthread_mutex_init(&shared->ref_mut, NULL); pthread_cond_init(&shared->ref_cond, NULL); shared->refcnt = refcnt; shared->ref_initialized = 1; } static void ratelimitSharedAddRef(ratelimit_shared_t *const shared) { pthread_mutex_lock(&shared->ref_mut); assert(shared->refcnt > 0); assert(shared->refcnt < UINT_MAX); shared->refcnt++; pthread_mutex_unlock(&shared->ref_mut); } static void ratelimitSharedReleaseRef(ratelimit_shared_t *const shared) { pthread_mutex_lock(&shared->ref_mut); assert(shared->refcnt > 0); shared->refcnt--; if (shared->refcnt == 0) { pthread_cond_broadcast(&shared->ref_cond); } pthread_mutex_unlock(&shared->ref_mut); } static void ratelimitSharedDropRegistryRefAndWait(ratelimit_shared_t *const shared) { pthread_mutex_lock(&shared->ref_mut); assert(shared->refcnt > 0); shared->refcnt--; while (shared->refcnt != 0) { pthread_cond_wait(&shared->ref_cond, &shared->ref_mut); } pthread_mutex_unlock(&shared->ref_mut); } static void ratelimitSharedRefsDestroy(ratelimit_shared_t *const shared) { if (shared->ref_initialized) { pthread_cond_destroy(&shared->ref_cond); pthread_mutex_destroy(&shared->ref_mut); shared->ref_initialized = 0; } } static ratelimit_cfg_bucket_t *ratelimitCfgBucket(ratelimit_cfgs_t *const cfgs, const char *const name, unsigned int *const hashvalue) { unsigned int local_hash; assert(cfgs != NULL); assert(name != NULL); assert(cfgs->shards[0].ht != NULL); /* Every shard uses the same hashtable hash function; compute the mixed * hash once and reuse it for both shard selection and in-shard lookup. */ local_hash = hashtable_hash(cfgs->shards[0].ht, (void *)name); if (hashvalue != NULL) { *hashvalue = local_hash; } return &cfgs->shards[local_hash % RATELIMIT_CFG_SHARDS]; } /** * Classify the per-source key template for parsing requirements. * * Allowed exceptions (no parse): * - %fromhost-ip% * - %fromhost% * - %fromhost-port% * - %fromhost-ip%:%fromhost-port% * - %fromhost%:%fromhost-port% * * Everything else falls back to template evaluation and requires parsing. */ static enum ratelimit_ps_key_mode perSourceKeyModeFromTemplate(const struct template *const pTpl) { const struct templateEntry *entry; if (pTpl == NULL) { return RL_PS_KEY_TPL; } if (pTpl->pStrgen != NULL || pTpl->bHaveSubtree) { return RL_PS_KEY_TPL; } if (pTpl->pEntryRoot == NULL) { return RL_PS_KEY_TPL; } if (pTpl->tpenElements == 1) { entry = pTpl->pEntryRoot; if (entry->pNext != NULL) { return RL_PS_KEY_TPL; } if (entry->eEntryType != FIELD) { return RL_PS_KEY_TPL; } if (entry->bComplexProcessing) { return RL_PS_KEY_TPL; } if (entry->data.field.msgProp.id == PROP_FROMHOST_IP || entry->data.field.msgProp.id == PROP_FROMHOST || entry->data.field.msgProp.id == PROP_FROMHOST_PORT) { if (entry->data.field.msgProp.id == PROP_FROMHOST_IP) return RL_PS_KEY_FROMHOST_IP; if (entry->data.field.msgProp.id == PROP_FROMHOST_PORT) return RL_PS_KEY_FROMHOST_PORT; return RL_PS_KEY_FROMHOST; } return RL_PS_KEY_TPL; } if (pTpl->tpenElements == 3) { const struct templateEntry *const first = pTpl->pEntryRoot; const struct templateEntry *const second = first->pNext; const struct templateEntry *const third = second ? second->pNext : NULL; if (third == NULL || third->pNext != NULL) { return RL_PS_KEY_TPL; } if (first->eEntryType != FIELD || second->eEntryType != CONSTANT || third->eEntryType != FIELD) { return RL_PS_KEY_TPL; } if (first->bComplexProcessing || second->bComplexProcessing || third->bComplexProcessing) { return RL_PS_KEY_TPL; } if (second->data.constant.iLenConstant != 1 || second->data.constant.pConstant[0] != ':') { return RL_PS_KEY_TPL; } if ((first->data.field.msgProp.id == PROP_FROMHOST_IP || first->data.field.msgProp.id == PROP_FROMHOST) && third->data.field.msgProp.id == PROP_FROMHOST_PORT) { return (first->data.field.msgProp.id == PROP_FROMHOST_IP) ? RL_PS_KEY_FROMHOST_IP_PORT : RL_PS_KEY_FROMHOST_NAME_PORT; } return RL_PS_KEY_TPL; } return RL_PS_KEY_TPL; } static rsRetVal ratelimitLookupPerSourceTemplate(rsconf_t *conf, const char *tpl_name, struct template **tpl, sbool *is_default) { const char *lookup_name; DEFiRet; if (conf == NULL || tpl == NULL || is_default == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); lookup_name = (tpl_name == NULL) ? "RSYSLOG_PerSourceKey" : tpl_name; *tpl = tplFind(conf, (char *)lookup_name, (int)strlen(lookup_name)); if (*tpl == NULL) { ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } *is_default = (tpl_name == NULL); finalize_it: RETiRet; } static void ratelimitFreeShared(void *ptr) { ratelimit_shared_t *shared = (ratelimit_shared_t *)ptr; if (shared == NULL) return; ratelimitSharedDropRegistryRefAndWait(shared); ratelimitUnregisterSharedWatchers(shared); pthread_mutex_destroy(&shared->mut); free(shared->policy_file); ratelimitDestroyPerSourceShards(shared); if (shared->per_source_stats != NULL) { statsobj.Destruct(&shared->per_source_stats); } free(shared->per_source_top_ctrs); free(shared->per_source_top_values); if (shared->per_source_top_keys != NULL) { for (unsigned int i = 0; i < shared->per_source_topn; ++i) { free(shared->per_source_top_keys[i]); } } free(shared->per_source_top_keys); free(shared->per_source_key_tpl_name); pthread_mutex_destroy(&shared->per_source_key_policy_mut); pthread_mutex_destroy(&shared->per_source_policy_mut); free(shared->per_source_policy_file); ratelimitSharedRefsDestroy(shared); /* shared->name is the key, freed by hashtable_destroy via freekey(); do not free here */ free(shared); } rsRetVal ratelimit_cfgsInit(ratelimit_cfgs_t *cfgs) { DEFiRet; memset(cfgs, 0, sizeof(*cfgs)); for (unsigned int i = 0; i < RATELIMIT_CFG_SHARDS; ++i) { if (pthread_rwlock_init(&cfgs->shards[i].lock, NULL) != 0) { ABORT_FINALIZE(RS_RET_ERR); } cfgs->shards[i].lock_initialized = 1; CHKmalloc(cfgs->shards[i].ht = create_hashtable(16, hash_from_string, key_equals_string, ratelimitFreeShared)); } finalize_it: if (iRet != RS_RET_OK) { ratelimit_cfgsDestruct(cfgs); } RETiRet; } void ratelimit_cfgsDestruct(ratelimit_cfgs_t *cfgs) { for (unsigned int i = 0; i < RATELIMIT_CFG_SHARDS; ++i) { if (cfgs->shards[i].ht != NULL && hashtable_count(cfgs->shards[i].ht) > 0) { struct hashtable_itr *itr = hashtable_iterator(cfgs->shards[i].ht); if (itr != NULL) { do { ratelimit_shared_t *shared = (ratelimit_shared_t *)hashtable_iterator_value(itr); ratelimitUnregisterSharedWatchers(shared); } while (hashtable_iterator_advance(itr)); } free(itr); } if (cfgs->shards[i].ht != NULL) { hashtable_destroy(cfgs->shards[i].ht, 1); /* 1 = free values */ cfgs->shards[i].ht = NULL; } if (cfgs->shards[i].lock_initialized) { pthread_rwlock_destroy(&cfgs->shards[i].lock); cfgs->shards[i].lock_initialized = 0; } } } /* * Concurrency & Locking * - ratelimit_shared_t->mut guards shared policy updates for global limits. * - per-source limits use ratelimit_shared_t->per_source_policy_mut to guard * low-frequency policy metadata and fallback atomics. Versioned source-key * policy fields are atomically published; per_source_key_policy_mut is used * only as the no-atomics fallback. Message-time source accounting is * partitioned across ratelimit_shared_t->per_source_shards; each shard mutex * guards that shard's hashtable, LRU list, and counters. * - ratelimit_cfgs_t shards guard the named configuration registry. Config * lookup and insertion lock only the shard selected by the config name. * - ratelimit_t->mut guards per-instance counters when thread-safe mode is enabled. */ #define RATELIMIT_PERSOURCE_DEFAULT_MAX_STATES 10000U #define RATELIMIT_PERSOURCE_DEFAULT_TOPN 10U #define RATELIMIT_POLICY_WATCH_DEBOUNCE_DFLT_MS 5000U struct ratelimit_ps_override_s { char *key; unsigned int max; unsigned int window; sbool has_max; sbool has_window; }; typedef struct ratelimit_ps_override_s ratelimit_ps_override_t; struct ratelimit_ps_entry_s { char *key; unsigned int count; time_t window_start; uint64_t allowed; uint64_t dropped; time_t last_seen; sbool state_active; sbool has_override; unsigned int max; unsigned int window; sbool has_max; sbool has_window; struct ratelimit_ps_entry_s *lru_prev; struct ratelimit_ps_entry_s *lru_next; }; typedef struct ratelimit_ps_entry_s ratelimit_ps_entry_t; struct ratelimit_ps_policy_s { unsigned int default_max; unsigned int default_window; struct hashtable *overrides; }; typedef struct ratelimit_ps_policy_s ratelimit_ps_policy_t; typedef struct ratelimit_ps_key_policy_s { sbool key_tpl_default; sbool key_needs_parsing; enum ratelimit_ps_key_mode key_mode; struct template *key_tpl; } ratelimit_ps_key_policy_t; #define RL_PS_KEY_POLICY_MODE_MASK 0xffU #define RL_PS_KEY_POLICY_TPL_DEFAULT (1U << 8) #define RL_PS_KEY_POLICY_NEEDS_PARSING (1U << 9) typedef struct ratelimit_policy_file_s { sbool has_scope; sbool has_output_mode; sbool has_interval; sbool has_burst; sbool has_severity; ratelimit_scope_t scope; ratelimit_output_mode_t output_mode; unsigned int interval; unsigned int burst; int severity; sbool has_per_source; sbool per_source_enabled; char *per_source_key_tpl_name; unsigned int per_source_max_states; unsigned int per_source_topn; ratelimit_ps_policy_t *per_source_policy; } ratelimit_policy_file_t; enum ratelimit_watch_kind { RATELIMIT_WATCH_GLOBAL = 0, RATELIMIT_WATCH_PERSOURCE }; static rsRetVal parseDurationMillis(const char *value, unsigned int *out); #ifdef HAVE_LIBYAML static rsRetVal parseUnsignedInt(const char *value, unsigned int *out); static rsRetVal parseDurationSeconds(const char *value, unsigned int *out); static void ratelimitFreePerSourceOverrideValue(void *ptr); static void ratelimitFreePerSourceOverrideDirect(void *ptr); #endif static rsRetVal ratelimitReloadPolicyFile(ratelimit_shared_t *shared, const char *trigger); static rsRetVal ratelimitReloadPerSourcePolicyFile(ratelimit_shared_t *shared, const char *trigger); static rsRetVal ratelimitRegisterWatchTargets(ratelimit_shared_t *shared); /* The caller serializes publishers with per_source_policy_mut. The odd/even * sequence lets readers reject fields observed across an update. */ static void ratelimitPublishPerSourceKeyPolicy(ratelimit_shared_t *shared, struct template *key_tpl, const sbool key_tpl_default) { const enum ratelimit_ps_key_mode key_mode = perSourceKeyModeFromTemplate(key_tpl); unsigned int bits = (unsigned int)key_mode; if (key_tpl_default) bits |= RL_PS_KEY_POLICY_TPL_DEFAULT; if (key_mode == RL_PS_KEY_TPL) bits |= RL_PS_KEY_POLICY_NEEDS_PARSING; ATOMIC_INC(&shared->per_source_key_policy_seq, &shared->per_source_key_policy_mut); ATOMIC_STORE_PTR((void **)&shared->per_source_key_tpl, &shared->per_source_key_policy_mut, key_tpl); ATOMIC_STORE_32BIT_unsigned(&shared->per_source_key_policy_bits, &shared->per_source_key_policy_mut, bits); ATOMIC_INC(&shared->per_source_key_policy_seq, &shared->per_source_key_policy_mut); } static void ratelimitLoadPerSourceKeyPolicy(ratelimit_shared_t *shared, ratelimit_ps_key_policy_t *policy) { unsigned int seq_before; unsigned int seq_after; unsigned int bits; struct template *key_tpl; for (;;) { seq_before = ATOMIC_LOAD_32BIT_unsigned(&shared->per_source_key_policy_seq, &shared->per_source_key_policy_mut); if (seq_before & 1U) continue; bits = ATOMIC_LOAD_32BIT_unsigned(&shared->per_source_key_policy_bits, &shared->per_source_key_policy_mut); key_tpl = (struct template *)ATOMIC_LOAD_PTR((void **)&shared->per_source_key_tpl, &shared->per_source_key_policy_mut); seq_after = ATOMIC_LOAD_32BIT_unsigned(&shared->per_source_key_policy_seq, &shared->per_source_key_policy_mut); if (seq_before == seq_after && !(seq_after & 1U)) break; } policy->key_mode = (enum ratelimit_ps_key_mode)(bits & RL_PS_KEY_POLICY_MODE_MASK); policy->key_tpl_default = (bits & RL_PS_KEY_POLICY_TPL_DEFAULT) != 0; policy->key_needs_parsing = (bits & RL_PS_KEY_POLICY_NEEDS_PARSING) != 0; policy->key_tpl = key_tpl; } static rsRetVal parseDurationMillis(const char *value, unsigned int *out) { char *end = NULL; unsigned long val; unsigned long long multiplier = 1000ULL; unsigned long long total; DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); while (isspace((unsigned char)*value)) value++; if (*value == '-') ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); errno = 0; val = strtoul(value, &end, 10); if (errno != 0 || end == value) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } while (isspace((unsigned char)*end)) end++; if (*end == '\0' || (!strcmp(end, "s"))) { multiplier = 1000ULL; } else if (!strcmp(end, "ms")) { multiplier = 1ULL; } else if (!strcmp(end, "m")) { multiplier = 60ULL * 1000ULL; } else if (!strcmp(end, "h")) { multiplier = 60ULL * 60ULL * 1000ULL; } else { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if ((unsigned long long)val > ((unsigned long long)UINT_MAX / multiplier)) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } total = (unsigned long long)val * multiplier; if (total > UINT_MAX) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } *out = (unsigned int)total; finalize_it: RETiRet; } #ifdef HAVE_LIBYAML static rsRetVal parseDurationSeconds(const char *value, unsigned int *out) { unsigned int ms = 0; DEFiRet; CHKiRet(parseDurationMillis(value, &ms)); if (ms % 1000U != 0) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } *out = ms / 1000U; finalize_it: RETiRet; } #endif static const char *ratelimitWatchKindName(enum ratelimit_watch_kind kind) { return (kind == RATELIMIT_WATCH_PERSOURCE) ? "per-source policy" : "policy"; } static void ratelimitWatchReloadPolicyCb(void *ctx, const char *trigger) { ratelimitReloadPolicyFile((ratelimit_shared_t *)ctx, trigger); } static void ratelimitWatchReloadPerSourcePolicyCb(void *ctx, const char *trigger) { ratelimitReloadPerSourcePolicyFile((ratelimit_shared_t *)ctx, trigger); } static void ratelimitUnregisterSharedWatchers(ratelimit_shared_t *shared) { if (shared == NULL) { return; } if (shared->policy_watch_handle != NULL) { rswatchUnregister(shared->policy_watch_handle); shared->policy_watch_handle = NULL; } if (shared->per_source_policy_watch_handle != NULL) { rswatchUnregister(shared->per_source_policy_watch_handle); shared->per_source_policy_watch_handle = NULL; } } static rsRetVal ratelimitRegisterWatchTargets(ratelimit_shared_t *shared) { DEFiRet; rsRetVal localRet; rswatch_desc_t desc; const char *per_source_policy_file = NULL; sbool per_source_policy_from_policy_file; if (shared == NULL || !shared->policy_watch) { FINALIZE; } pthread_mutex_lock(&shared->per_source_policy_mut); per_source_policy_file = shared->per_source_policy_file; per_source_policy_from_policy_file = shared->per_source_policy_from_policy_file; pthread_mutex_unlock(&shared->per_source_policy_mut); if (shared->policy_file == NULL && per_source_policy_file == NULL) { LogMsg(0, RS_RET_OK, LOG_WARNING, "ratelimit: policyWatch enabled for '%s' but no policy file is configured; using HUP-only reload", shared->name); FINALIZE; } if (shared->policy_file != NULL) { memset(&desc, 0, sizeof(desc)); desc.id = shared->name; desc.path = shared->policy_file; desc.debounce_ms = shared->policy_watch_debounce_ms; desc.cb = ratelimitWatchReloadPolicyCb; desc.ctx = shared; localRet = rswatchRegister(&desc, &shared->policy_watch_handle); if (localRet != RS_RET_OK) { LogMsg(0, localRet, LOG_WARNING, "ratelimit: policyWatch requested for '%s' but automatic reload unavailable for %s '%s'; using " "HUP-only reload", shared->name, ratelimitWatchKindName(RATELIMIT_WATCH_GLOBAL), shared->policy_file); } } if (per_source_policy_file != NULL && !per_source_policy_from_policy_file) { memset(&desc, 0, sizeof(desc)); desc.id = shared->name; desc.path = per_source_policy_file; desc.debounce_ms = shared->policy_watch_debounce_ms; desc.cb = ratelimitWatchReloadPerSourcePolicyCb; desc.ctx = shared; localRet = rswatchRegister(&desc, &shared->per_source_policy_watch_handle); if (localRet != RS_RET_OK) { LogMsg(0, localRet, LOG_WARNING, "ratelimit: policyWatch requested for '%s' but automatic reload unavailable for %s '%s'; using " "HUP-only reload", shared->name, ratelimitWatchKindName(RATELIMIT_WATCH_PERSOURCE), per_source_policy_file); } } finalize_it: RETiRet; } static void ratelimitPolicyFileDestruct(ratelimit_policy_file_t *policy) { if (policy == NULL) return; free(policy->per_source_key_tpl_name); if (policy->per_source_policy != NULL) { if (policy->per_source_policy->overrides != NULL) hashtable_destroy(policy->per_source_policy->overrides, 1); free(policy->per_source_policy); } memset(policy, 0, sizeof(*policy)); } static rsRetVal parseBoolValue(const char *value, sbool *out) { DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (!strcasecmp(value, "on") || !strcasecmp(value, "yes") || !strcasecmp(value, "true") || !strcmp(value, "1")) { *out = 1; } else if (!strcasecmp(value, "off") || !strcasecmp(value, "no") || !strcasecmp(value, "false") || !strcmp(value, "0")) { *out = 0; } else { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } finalize_it: RETiRet; } static rsRetVal parsePolicyScopeValue(const char *value, ratelimit_scope_t *out) { DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (!strcasecmp(value, "input")) { *out = RATELIMIT_SCOPE_INPUT; } else if (!strcasecmp(value, "output")) { *out = RATELIMIT_SCOPE_OUTPUT; } else { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } finalize_it: RETiRet; } static rsRetVal parseOutputModeValue(const char *value, ratelimit_output_mode_t *out) { DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (!strcasecmp(value, "drop")) { *out = RATELIMIT_OUTPUT_MODE_DROP; } else if (!strcasecmp(value, "pace")) { *out = RATELIMIT_OUTPUT_MODE_PACE; } else { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } finalize_it: RETiRet; } static rsRetVal parseSeverityValue(const char *value, int *out) { char *end = NULL; long numeric; int severity; DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); while (isspace((unsigned char)*value)) value++; if (*value == '-' || isdigit((unsigned char)*value)) { errno = 0; numeric = strtol(value, &end, 10); if (errno != 0 || end == value || *end != '\0' || numeric < -1 || numeric > 127) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } severity = (int)numeric; } else { severity = decodeSyslogName((uchar *)value, syslogPriNames); if (severity < 0 || severity > 127) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } } *out = severity; finalize_it: RETiRet; } static rsRetVal parsePolicyFile(const char *policy_file, ratelimit_policy_file_t *policy) { DEFiRet; #ifdef HAVE_LIBYAML FILE *fh = NULL; yaml_parser_t yamlParser; int bParserInitialized = 0; yaml_event_t event; unsigned int depth = 0; enum policy_ctx { CTX_TOP = 0, CTX_PERSOURCE, CTX_PS_DEFAULT, CTX_PS_OVERRIDE_ITEM } ctxStack[8]; int expectKey[8] = {0}; char *last_key = NULL; sbool inOverridesSeq = 0; sbool default_max_seen = 0; sbool default_window_seen = 0; unsigned int override_count = 0; ratelimit_ps_override_t *current_override = NULL; if (policy == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); memset(policy, 0, sizeof(*policy)); fh = fopen(policy_file, "r"); if (fh == NULL) { LogError(errno, RS_RET_FILE_NOT_FOUND, "ratelimit: error opening policy file %s", policy_file); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (!yaml_parser_initialize(&yamlParser)) { LogError(0, RS_RET_INTERNAL_ERROR, "ratelimit: failed to initialize yaml parser"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } bParserInitialized = 1; yaml_parser_set_input_file(&yamlParser, fh); while (1) { if (!yaml_parser_parse(&yamlParser, &event)) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: yaml parser error in policy file %s: %s", policy_file, yamlParser.problem ? yamlParser.problem : "unknown error"); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wswitch_enum switch (event.type) { case YAML_NO_EVENT: case YAML_STREAM_START_EVENT: case YAML_DOCUMENT_START_EVENT: case YAML_DOCUMENT_END_EVENT: case YAML_ALIAS_EVENT: break; case YAML_MAPPING_START_EVENT: if (depth >= 8) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: yaml nesting too deep in %s", policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (depth == 0) { ctxStack[depth] = CTX_TOP; } else if (inOverridesSeq) { if (override_count >= 10000U) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: too many per-source overrides in %s (max %u)", policy_file, 10000U); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } ctxStack[depth] = CTX_PS_OVERRIDE_ITEM; CHKmalloc(current_override = calloc(1, sizeof(*current_override))); override_count++; } else if (last_key != NULL && !strcmp(last_key, "perSource")) { ctxStack[depth] = CTX_PERSOURCE; policy->has_per_source = 1; policy->per_source_enabled = 1; CHKmalloc(policy->per_source_policy = calloc(1, sizeof(*policy->per_source_policy))); policy->per_source_policy->overrides = create_hashtable(32, hash_from_string, key_equals_string, ratelimitFreePerSourceOverrideValue); if (policy->per_source_policy->overrides == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (depth > 0 && ctxStack[depth - 1] == CTX_PERSOURCE && last_key != NULL && !strcmp(last_key, "default")) { ctxStack[depth] = CTX_PS_DEFAULT; } else { ctxStack[depth] = CTX_TOP; } if (depth > 0 && last_key != NULL) { expectKey[depth - 1] = 1; } expectKey[depth] = 1; depth++; free(last_key); last_key = NULL; break; case YAML_MAPPING_END_EVENT: if (depth > 0) { depth--; if (ctxStack[depth] == CTX_PS_OVERRIDE_ITEM && current_override != NULL) { if (current_override->key == NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: per-source override missing key in %s", policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (hashtable_insert(policy->per_source_policy->overrides, current_override->key, current_override) == 0) { LogError(0, RS_RET_OUT_OF_MEMORY, "ratelimit: error inserting per-source override '%s'", current_override->key); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } current_override = NULL; } } free(last_key); last_key = NULL; break; case YAML_SEQUENCE_START_EVENT: if (depth > 0 && ctxStack[depth - 1] == CTX_PERSOURCE && last_key != NULL && !strcmp(last_key, "overrides")) { inOverridesSeq = 1; } if (depth > 0 && last_key != NULL) { expectKey[depth - 1] = 1; } free(last_key); last_key = NULL; break; case YAML_SEQUENCE_END_EVENT: inOverridesSeq = 0; free(last_key); last_key = NULL; break; case YAML_SCALAR_EVENT: if (depth == 0) break; if (expectKey[depth - 1]) { free(last_key); CHKmalloc(last_key = strdup((char *)event.data.scalar.value)); expectKey[depth - 1] = 0; } else { const char *val = (const char *)event.data.scalar.value; unsigned int uintval = 0; int severity = 0; sbool boolval = 0; if (ctxStack[depth - 1] == CTX_TOP) { if (last_key != NULL && !strcmp(last_key, "scope")) { if (parsePolicyScopeValue(val, &policy->scope) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid scope value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->has_scope = 1; } else if (last_key != NULL && !strcmp(last_key, "mode")) { if (parseOutputModeValue(val, &policy->output_mode) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid mode value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->has_output_mode = 1; } else if (last_key != NULL && !strcmp(last_key, "interval")) { if (parseUnsignedInt(val, &uintval) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid interval value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->interval = uintval; policy->has_interval = 1; } else if (last_key != NULL && !strcmp(last_key, "burst")) { if (parseUnsignedInt(val, &uintval) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid burst value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->burst = uintval; policy->has_burst = 1; } else if (last_key != NULL && !strcmp(last_key, "severity")) { if (parseSeverityValue(val, &severity) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid severity value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->severity = severity; policy->has_severity = 1; } } else if (ctxStack[depth - 1] == CTX_PERSOURCE) { if (last_key != NULL && !strcmp(last_key, "enabled")) { if (parseBoolValue(val, &boolval) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource.enabled value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->per_source_enabled = boolval; } else if (last_key != NULL && !strcmp(last_key, "keyTemplate")) { free(policy->per_source_key_tpl_name); CHKmalloc(policy->per_source_key_tpl_name = strdup(val)); } else if (last_key != NULL && !strcmp(last_key, "maxStates")) { if (parseUnsignedInt(val, &policy->per_source_max_states) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource.maxStates value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } } else if (last_key != NULL && !strcmp(last_key, "topN")) { if (parseUnsignedInt(val, &policy->per_source_topn) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource.topN value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } } } else if (ctxStack[depth - 1] == CTX_PS_DEFAULT && policy->per_source_policy != NULL) { if (last_key != NULL && !strcmp(last_key, "max")) { if (parseUnsignedInt(val, &policy->per_source_policy->default_max) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource.default.max value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } default_max_seen = 1; } else if (last_key != NULL && !strcmp(last_key, "window")) { if (parseDurationSeconds(val, &policy->per_source_policy->default_window) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource.default.window value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } default_window_seen = 1; } } else if (ctxStack[depth - 1] == CTX_PS_OVERRIDE_ITEM && current_override != NULL) { if (last_key != NULL && !strcmp(last_key, "key")) { free(current_override->key); CHKmalloc(current_override->key = strdup(val)); } else if (last_key != NULL && !strcmp(last_key, "max")) { if (parseUnsignedInt(val, ¤t_override->max) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource override.max value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } current_override->has_max = 1; } else if (last_key != NULL && !strcmp(last_key, "window")) { if (parseDurationSeconds(val, ¤t_override->window) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid perSource override.window value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } current_override->has_window = 1; } } expectKey[depth - 1] = 1; } break; case YAML_STREAM_END_EVENT: yaml_event_delete(&event); goto finalize_it; default: break; } PRAGMA_DIAGNOSTIC_POP yaml_event_delete(&event); } finalize_it: if (bParserInitialized) { yaml_parser_delete(&yamlParser); } free(last_key); if (current_override != NULL) ratelimitFreePerSourceOverrideDirect(current_override); if (fh) fclose(fh); if (iRet == RS_RET_OK && policy->has_per_source && policy->per_source_enabled && (!default_max_seen || !default_window_seen)) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: policy file %s perSource section missing default.max or default.window", policy_file); iRet = RS_RET_CONF_PARAM_INVLD; } if (iRet != RS_RET_OK) { ratelimitPolicyFileDestruct(policy); } #else LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: policy file '%s' specified but rsyslog " "was compiled without libyaml support. Policy settings ignored.", policy_file); iRet = RS_RET_CONF_PARAM_INVLD; #endif RETiRet; } static void ratelimitFreePerSourceEntry(void *ptr) { ratelimit_ps_entry_t *entry = (ratelimit_ps_entry_t *)ptr; if (entry == NULL) return; free(entry); } static unsigned int ratelimitPerSourceShardCap(const unsigned int max_states, const unsigned int shard) { if (max_states == 0) return 0; if (max_states <= RATELIMIT_PERSOURCE_SHARDS) return 1; return (max_states / RATELIMIT_PERSOURCE_SHARDS) + (shard < (max_states % RATELIMIT_PERSOURCE_SHARDS)); } static void ratelimitSetPerSourceShardCaps(ratelimit_shared_t *shared, unsigned int max_states) { if (shared == NULL) return; max_states = (max_states == 0) ? RATELIMIT_PERSOURCE_DEFAULT_MAX_STATES : max_states; shared->per_source_max_states = max_states; for (unsigned int i = 0; i < RATELIMIT_PERSOURCE_SHARDS; ++i) { if (shared->per_source_shards[i].lock_initialized) { pthread_mutex_lock(&shared->per_source_shards[i].mut); } shared->per_source_shards[i].max_states = ratelimitPerSourceShardCap(max_states, i); if (shared->per_source_shards[i].lock_initialized) { pthread_mutex_unlock(&shared->per_source_shards[i].mut); } } } static rsRetVal ratelimitInitPerSourceShards(ratelimit_shared_t *shared, unsigned int max_states) { DEFiRet; if (shared == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (shared->per_source_shards_initialized) { ratelimitSetPerSourceShardCaps(shared, max_states); FINALIZE; } for (unsigned int i = 0; i < RATELIMIT_PERSOURCE_SHARDS; ++i) { if (pthread_mutex_init(&shared->per_source_shards[i].mut, NULL) != 0) { ABORT_FINALIZE(RS_RET_ERR); } shared->per_source_shards[i].lock_initialized = 1; shared->per_source_shards[i].ht = create_hashtable(16, hash_from_string, key_equals_string, ratelimitFreePerSourceEntry); if (shared->per_source_shards[i].ht == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } shared->per_source_shards_initialized = 1; ratelimitSetPerSourceShardCaps(shared, max_states); finalize_it: if (iRet != RS_RET_OK) { ratelimitDestroyPerSourceShards(shared); } RETiRet; } static void ratelimitDestroyPerSourceShards(ratelimit_shared_t *shared) { if (shared == NULL) return; for (unsigned int i = 0; i < RATELIMIT_PERSOURCE_SHARDS; ++i) { if (shared->per_source_shards[i].ht != NULL) { hashtable_destroy(shared->per_source_shards[i].ht, 1); shared->per_source_shards[i].ht = NULL; } if (shared->per_source_shards[i].lock_initialized) { pthread_mutex_destroy(&shared->per_source_shards[i].mut); shared->per_source_shards[i].lock_initialized = 0; } shared->per_source_shards[i].lru_head = NULL; shared->per_source_shards[i].lru_tail = NULL; shared->per_source_shards[i].active_states = 0; shared->per_source_shards[i].max_states = 0; } shared->per_source_shards_initialized = 0; } static ratelimit_ps_bucket_t *ratelimitPerSourceBucket(ratelimit_shared_t *shared, const char *key, unsigned int *hashvalue) { unsigned int local_hash; assert(shared != NULL); assert(key != NULL); assert(shared->per_source_shards[0].ht != NULL); local_hash = hashtable_hash(shared->per_source_shards[0].ht, (void *)key); if (hashvalue != NULL) { *hashvalue = local_hash; } return &shared->per_source_shards[local_hash % RATELIMIT_PERSOURCE_SHARDS]; } static void ratelimitPerSourceLruRemove(ratelimit_ps_bucket_t *bucket, ratelimit_ps_entry_t *entry) { if (entry->lru_prev != NULL) entry->lru_prev->lru_next = entry->lru_next; if (entry->lru_next != NULL) entry->lru_next->lru_prev = entry->lru_prev; if (bucket->lru_head == entry) bucket->lru_head = entry->lru_next; if (bucket->lru_tail == entry) bucket->lru_tail = entry->lru_prev; entry->lru_prev = NULL; entry->lru_next = NULL; } static void ratelimitPerSourceLruTouch(ratelimit_ps_bucket_t *bucket, ratelimit_ps_entry_t *entry) { if (bucket->lru_tail == entry) return; if (entry->lru_prev != NULL || entry->lru_next != NULL || bucket->lru_head == entry) { ratelimitPerSourceLruRemove(bucket, entry); } entry->lru_prev = bucket->lru_tail; if (bucket->lru_tail != NULL) bucket->lru_tail->lru_next = entry; bucket->lru_tail = entry; if (bucket->lru_head == NULL) bucket->lru_head = entry; } static void ratelimitPerSourceEvictOne(ratelimit_shared_t *shared, ratelimit_ps_bucket_t *bucket) { ratelimit_ps_entry_t *evict = bucket->lru_head; ratelimit_ps_entry_t *removed; unsigned int hashvalue; if (evict == NULL) return; ratelimitPerSourceLruRemove(bucket, evict); if (bucket->active_states > 0) bucket->active_states--; evict->state_active = 0; STATSCOUNTER_INC(shared->ctrPerSourceEvicted, shared->mutCtrPerSourceEvicted); if (evict->has_override) return; hashvalue = hashtable_hash(bucket->ht, evict->key); removed = (ratelimit_ps_entry_t *)hashtable_remove_prehashed(bucket->ht, hashvalue, evict->key); ratelimitFreePerSourceEntry(removed); } #ifdef HAVE_LIBYAML static void ratelimitFreePerSourceOverrideValue(void *ptr) { ratelimit_ps_override_t *ovr = (ratelimit_ps_override_t *)ptr; if (ovr == NULL) return; free(ovr); } static void ratelimitFreePerSourceOverrideDirect(void *ptr) { ratelimit_ps_override_t *ovr = (ratelimit_ps_override_t *)ptr; if (ovr == NULL) return; free(ovr->key); free(ovr); } static rsRetVal parseUnsignedInt(const char *value, unsigned int *out) { char *end = NULL; unsigned long val; DEFiRet; if (value == NULL || out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); while (isspace((unsigned char)*value)) value++; if (*value == '-') ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); errno = 0; val = strtoul(value, &end, 10); if (errno != 0 || end == value || val > UINT_MAX) { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (*end != '\0') { ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } *out = (unsigned int)val; finalize_it: RETiRet; } #endif /* HAVE_LIBYAML */ static rsRetVal parsePerSourcePolicyFile(const char *policy_file, ratelimit_ps_policy_t **policy_out) { #ifndef HAVE_LIBYAML LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: per-source policy file '%s' specified but rsyslog " "was compiled without libyaml support.", policy_file); (void)policy_out; return RS_RET_CONF_PARAM_INVLD; #else ratelimit_ps_policy_t *policy = NULL; ratelimit_ps_override_t *current_override = NULL; FILE *fh = NULL; yaml_parser_t yamlParser; yaml_event_t event; int parserInitialized = 0; unsigned int depth = 0; int expectKey[8] = {0}; enum { CTX_TOP = 0, CTX_DEFAULT, CTX_OVERRIDE_ITEM } ctxStack[8]; sbool inOverridesSeq = 0; char *last_key = NULL; sbool default_max_seen = 0; sbool default_window_seen = 0; unsigned int override_count = 0; const unsigned int MAX_OVERRIDES = 10000; DEFiRet; if (policy_out == NULL || policy_file == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); CHKmalloc(policy = calloc(1, sizeof(*policy))); CHKmalloc(policy->overrides = create_hashtable(32, hash_from_string, key_equals_string, ratelimitFreePerSourceOverrideValue)); fh = fopen(policy_file, "r"); if (fh == NULL) { LogError(errno, RS_RET_FILE_NOT_FOUND, "ratelimit: error opening per-source policy file %s", policy_file); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (!yaml_parser_initialize(&yamlParser)) { LogError(0, RS_RET_INTERNAL_ERROR, "ratelimit: failed to initialize yaml parser"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } parserInitialized = 1; yaml_parser_set_input_file(&yamlParser, fh); while (1) { if (!yaml_parser_parse(&yamlParser, &event)) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: yaml parser error in policy file %s: %s", policy_file, yamlParser.problem ? yamlParser.problem : "unknown error"); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } switch (event.type) { case YAML_NO_EVENT: case YAML_STREAM_START_EVENT: case YAML_DOCUMENT_START_EVENT: case YAML_DOCUMENT_END_EVENT: case YAML_ALIAS_EVENT: break; case YAML_MAPPING_START_EVENT: if (depth >= 8) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: yaml nesting too deep in %s", policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (depth == 0) { ctxStack[depth] = CTX_TOP; } else if (inOverridesSeq) { if (override_count >= MAX_OVERRIDES) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: too many overrides in %s (max %u)", policy_file, MAX_OVERRIDES); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } ctxStack[depth] = CTX_OVERRIDE_ITEM; CHKmalloc(current_override = calloc(1, sizeof(*current_override))); override_count++; } else if (last_key != NULL && !strcmp(last_key, "default")) { ctxStack[depth] = CTX_DEFAULT; } else { ctxStack[depth] = CTX_TOP; } if (depth > 0 && last_key != NULL) { expectKey[depth - 1] = 1; } expectKey[depth] = 1; depth++; free(last_key); last_key = NULL; break; case YAML_MAPPING_END_EVENT: if (depth > 0) { depth--; if (ctxStack[depth] == CTX_OVERRIDE_ITEM && current_override != NULL) { if (current_override->key == NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: per-source override missing key in %s", policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (hashtable_insert(policy->overrides, current_override->key, current_override) == 0) { LogError(0, RS_RET_OUT_OF_MEMORY, "ratelimit: error inserting per-source override '%s'", current_override->key); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } current_override = NULL; } } free(last_key); last_key = NULL; break; case YAML_SEQUENCE_START_EVENT: if (last_key != NULL && !strcmp(last_key, "overrides")) { inOverridesSeq = 1; } if (depth > 0 && last_key != NULL) { expectKey[depth - 1] = 1; } free(last_key); last_key = NULL; break; case YAML_SEQUENCE_END_EVENT: inOverridesSeq = 0; free(last_key); last_key = NULL; break; case YAML_SCALAR_EVENT: if (depth == 0) break; if (expectKey[depth - 1]) { free(last_key); last_key = strdup((char *)event.data.scalar.value); expectKey[depth - 1] = 0; } else { const char *val = (const char *)event.data.scalar.value; if (ctxStack[depth - 1] == CTX_DEFAULT) { if (last_key != NULL && !strcmp(last_key, "max")) { unsigned int max = 0; if (parseUnsignedInt(val, &max) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid default.max value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->default_max = max; default_max_seen = 1; } else if (last_key != NULL && !strcmp(last_key, "window")) { unsigned int window = 0; if (parseDurationSeconds(val, &window) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid default.window value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } policy->default_window = window; default_window_seen = 1; } } else if (ctxStack[depth - 1] == CTX_OVERRIDE_ITEM && current_override != NULL) { if (last_key != NULL && !strcmp(last_key, "key")) { free(current_override->key); current_override->key = strdup(val); } else if (last_key != NULL && !strcmp(last_key, "max")) { unsigned int max = 0; if (parseUnsignedInt(val, &max) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid override.max value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } current_override->max = max; current_override->has_max = 1; } else if (last_key != NULL && !strcmp(last_key, "window")) { unsigned int window = 0; if (parseDurationSeconds(val, &window) != RS_RET_OK) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: invalid override.window value '%s' in %s", val, policy_file); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } current_override->window = window; current_override->has_window = 1; } } expectKey[depth - 1] = 1; } break; case YAML_STREAM_END_EVENT: yaml_event_delete(&event); goto finalize_it; default: break; } yaml_event_delete(&event); } finalize_it: if (parserInitialized) yaml_parser_delete(&yamlParser); if (fh) fclose(fh); free(last_key); if (iRet != RS_RET_OK) { if (current_override != NULL) ratelimitFreePerSourceOverrideDirect(current_override); if (policy != NULL) { if (policy->overrides != NULL) hashtable_destroy(policy->overrides, 1); free(policy); } return iRet; } if (!default_max_seen || !default_window_seen) { LogError(0, RS_RET_CONF_PARAM_INVLD, "ratelimit: per-source policy file %s missing default.max or default.window", policy_file); if (policy != NULL) { if (policy->overrides != NULL) hashtable_destroy(policy->overrides, 1); free(policy); } return RS_RET_CONF_PARAM_INVLD; } *policy_out = policy; return RS_RET_OK; #endif } static char *ratelimitSanitizeMetricName(const char *key) { size_t len = strlen(key); size_t maxLen = 128; size_t outLen = len > maxLen ? maxLen : len; char *out = malloc(outLen + 1); if (out == NULL) return NULL; for (size_t i = 0; i < outLen; ++i) { char c = key[i]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-') { out[i] = c; } else { out[i] = '_'; } } out[outLen] = '\0'; return out; } static void ratelimitPerSourceTopNAdd( uint64_t *values, char **keys, unsigned int topn, const char *key, uint64_t dropped) { if (dropped == 0) return; for (unsigned int i = 0; i < topn; ++i) { if (dropped > values[i]) { char *copy = strdup(key); if (copy == NULL) return; free(keys[topn - 1]); for (unsigned int j = topn - 1; j > i; --j) { values[j] = values[j - 1]; keys[j] = keys[j - 1]; } values[i] = dropped; keys[i] = copy; break; } } } static void ratelimitPerSourceUpdateTopN(ratelimit_shared_t *shared) { if (shared == NULL || shared->per_source_stats == NULL) return; pthread_mutex_lock(&shared->per_source_policy_mut); if (shared->per_source_topn == 0) { pthread_mutex_unlock(&shared->per_source_policy_mut); return; } unsigned int topn = shared->per_source_topn; pthread_mutex_unlock(&shared->per_source_policy_mut); uint64_t *values = calloc(topn, sizeof(uint64_t)); char **keys = calloc(topn, sizeof(char *)); if (values == NULL || keys == NULL) { free(values); free(keys); return; } for (unsigned int shard = 0; shard < RATELIMIT_PERSOURCE_SHARDS; ++shard) { ratelimit_ps_bucket_t *const bucket = &shared->per_source_shards[shard]; struct hashtable_itr *itr = NULL; if (bucket->ht == NULL) continue; pthread_mutex_lock(&bucket->mut); if (hashtable_count(bucket->ht) > 0) { itr = hashtable_iterator(bucket->ht); } if (itr != NULL) { do { ratelimit_ps_entry_t *entry = (ratelimit_ps_entry_t *)hashtable_iterator_value(itr); if (entry != NULL && entry->state_active) { ratelimitPerSourceTopNAdd(values, keys, topn, entry->key, entry->dropped); } } while (hashtable_iterator_advance(itr)); free(itr); } pthread_mutex_unlock(&bucket->mut); } pthread_mutex_lock(&shared->per_source_policy_mut); if (shared->per_source_topn != topn) { pthread_mutex_unlock(&shared->per_source_policy_mut); for (unsigned int i = 0; i < topn; ++i) free(keys[i]); free(values); free(keys); return; } if (shared->per_source_top_ctrs == NULL) { shared->per_source_top_ctrs = calloc(topn, sizeof(ctr_t *)); shared->per_source_top_values = calloc(topn, sizeof(intctr_t)); shared->per_source_top_keys = calloc(topn, sizeof(char *)); if (shared->per_source_top_ctrs == NULL || shared->per_source_top_values == NULL || shared->per_source_top_keys == NULL) { free(shared->per_source_top_ctrs); free(shared->per_source_top_values); free(shared->per_source_top_keys); shared->per_source_top_ctrs = NULL; shared->per_source_top_values = NULL; shared->per_source_top_keys = NULL; free(values); for (unsigned int i = 0; i < topn; ++i) free(keys[i]); free(keys); pthread_mutex_unlock(&shared->per_source_policy_mut); return; } } sbool rebuild = 0; for (unsigned int i = 0; i < topn; ++i) { const char *old_key = shared->per_source_top_keys[i]; const char *new_key = keys[i]; if ((old_key == NULL && new_key != NULL) || (old_key != NULL && new_key == NULL) || (old_key != NULL && new_key != NULL && strcmp(old_key, new_key) != 0)) { rebuild = 1; break; } } if (rebuild) { for (unsigned int i = 0; i < topn; ++i) { if (shared->per_source_top_ctrs[i] != NULL) { statsobj.DestructCounter(shared->per_source_stats, shared->per_source_top_ctrs[i]); shared->per_source_top_ctrs[i] = NULL; } free(shared->per_source_top_keys[i]); shared->per_source_top_keys[i] = NULL; } for (unsigned int i = 0; i < topn; ++i) { if (keys[i] == NULL) continue; char *sanitized = ratelimitSanitizeMetricName(keys[i]); if (sanitized == NULL) continue; char namebuf[256]; snprintf(namebuf, sizeof(namebuf), "per_source_drop_%u_%s", i + 1, sanitized); free(sanitized); shared->per_source_top_values[i] = values[i]; if (statsobj.AddManagedCounter(shared->per_source_stats, (uchar *)namebuf, ctrType_IntCtr, CTR_FLAG_NONE, &shared->per_source_top_values[i], &shared->per_source_top_ctrs[i], 1) == RS_RET_OK) { shared->per_source_top_keys[i] = strdup(keys[i]); } } } else { for (unsigned int i = 0; i < topn; ++i) { shared->per_source_top_values[i] = values[i]; } } pthread_mutex_unlock(&shared->per_source_policy_mut); free(values); for (unsigned int i = 0; i < topn; ++i) free(keys[i]); free(keys); } static void ratelimitPerSourceStatsRead(statsobj_t *stats, void *ctx) { ratelimit_shared_t *shared = (ratelimit_shared_t *)ctx; (void)stats; ratelimitPerSourceUpdateTopN(shared); } static rsRetVal ratelimitPerSourceCreateEntry(ratelimit_ps_bucket_t *bucket, const unsigned int hashvalue, const char *key, ratelimit_ps_entry_t **entry_out) { char *owned_key = NULL; ratelimit_ps_entry_t *entry = NULL; DEFiRet; if (bucket == NULL || key == NULL || entry_out == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); CHKmalloc(entry = calloc(1, sizeof(*entry))); CHKmalloc(owned_key = strdup(key)); entry->key = owned_key; if (hashtable_insert_prehashed(bucket->ht, hashvalue, owned_key, entry) == 0) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } owned_key = NULL; *entry_out = entry; entry = NULL; finalize_it: free(owned_key); free(entry); RETiRet; } static rsRetVal ratelimitPerSourceApplyOverrides(ratelimit_shared_t *shared, struct hashtable *overrides) { DEFiRet; if (shared == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); if (!shared->per_source_shards_initialized) FINALIZE; if (overrides != NULL && hashtable_count(overrides) > 0) { struct hashtable_itr *itr = hashtable_iterator(overrides); if (itr != NULL) { do { ratelimit_ps_override_t *override = (ratelimit_ps_override_t *)hashtable_iterator_value(itr); unsigned int hashvalue; ratelimit_ps_bucket_t *bucket; ratelimit_ps_entry_t *entry; if (override == NULL || override->key == NULL) continue; bucket = ratelimitPerSourceBucket(shared, override->key, &hashvalue); pthread_mutex_lock(&bucket->mut); entry = (ratelimit_ps_entry_t *)hashtable_search_prehashed(bucket->ht, hashvalue, override->key); if (entry == NULL) { iRet = ratelimitPerSourceCreateEntry(bucket, hashvalue, override->key, &entry); } pthread_mutex_unlock(&bucket->mut); if (iRet != RS_RET_OK) { free(itr); FINALIZE; } } while (hashtable_iterator_advance(itr)); free(itr); } } for (unsigned int shard = 0; shard < RATELIMIT_PERSOURCE_SHARDS; ++shard) { ratelimit_ps_bucket_t *const bucket = &shared->per_source_shards[shard]; struct hashtable_itr *itr; int more; pthread_mutex_lock(&bucket->mut); itr = hashtable_iterator(bucket->ht); if (itr != NULL) { more = (hashtable_count(bucket->ht) > 0); while (more) { ratelimit_ps_entry_t *entry = (ratelimit_ps_entry_t *)hashtable_iterator_value(itr); if (entry != NULL) { entry->has_override = 0; entry->has_max = 0; entry->has_window = 0; entry->max = 0; entry->window = 0; } more = hashtable_iterator_advance(itr); } free(itr); } if (overrides != NULL && hashtable_count(overrides) > 0) { itr = hashtable_iterator(overrides); if (itr != NULL) { do { ratelimit_ps_override_t *override = (ratelimit_ps_override_t *)hashtable_iterator_value(itr); unsigned int hashvalue; ratelimit_ps_bucket_t *override_bucket; ratelimit_ps_entry_t *entry; if (override == NULL || override->key == NULL) continue; override_bucket = ratelimitPerSourceBucket(shared, override->key, &hashvalue); if (override_bucket != bucket) continue; entry = (ratelimit_ps_entry_t *)hashtable_search_prehashed(bucket->ht, hashvalue, override->key); if (entry == NULL) continue; entry->has_override = 1; entry->has_max = override->has_max; entry->max = override->max; entry->has_window = override->has_window; entry->window = override->window; } while (hashtable_iterator_advance(itr)); free(itr); } } itr = hashtable_iterator(bucket->ht); if (itr != NULL) { more = (hashtable_count(bucket->ht) > 0); while (more) { ratelimit_ps_entry_t *entry = (ratelimit_ps_entry_t *)hashtable_iterator_value(itr); if (entry != NULL && !entry->state_active && !entry->has_override) { more = hashtable_iterator_remove(itr); ratelimitFreePerSourceEntry(entry); } else { more = hashtable_iterator_advance(itr); } } free(itr); } pthread_mutex_unlock(&bucket->mut); } finalize_it: RETiRet; } static rsRetVal ratelimitInitPerSourceShared(ratelimit_shared_t *shared, ratelimit_ps_policy_t *policy, const char *policy_file, unsigned int max_states, unsigned int topn) { char statname[256]; sbool bLocked = 0; DEFiRet; if (shared == NULL || policy == NULL || policy_file == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 0); pthread_mutex_lock(&shared->per_source_policy_mut); bLocked = 1; shared->per_source_policy_file = strdup(policy_file); if (shared->per_source_policy_file == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); ratelimitSharedStoreUInt(&shared->per_source_default_max, &shared->mut, policy->default_max); ratelimitSharedStoreUInt(&shared->per_source_default_window, &shared->mut, policy->default_window); shared->per_source_key_tpl_name = NULL; shared->per_source_topn = (topn == 0) ? RATELIMIT_PERSOURCE_DEFAULT_TOPN : topn; pthread_mutex_unlock(&shared->per_source_policy_mut); bLocked = 0; CHKiRet(ratelimitInitPerSourceShards(shared, max_states)); CHKiRet(ratelimitPerSourceApplyOverrides(shared, policy->overrides)); if (policy->overrides != NULL) { hashtable_destroy(policy->overrides, 1); policy->overrides = NULL; } STATSCOUNTER_INIT(shared->ctrPerSourceAllowed, shared->mutCtrPerSourceAllowed); STATSCOUNTER_INIT(shared->ctrPerSourceDropped, shared->mutCtrPerSourceDropped); STATSCOUNTER_INIT(shared->ctrPerSourceEvicted, shared->mutCtrPerSourceEvicted); STATSCOUNTER_INIT(shared->ctrPerSourceKeyTplEvals, shared->mutCtrPerSourceKeyTplEvals); STATSCOUNTER_INIT(shared->ctrPerSourceKeyParseEvals, shared->mutCtrPerSourceKeyParseEvals); CHKiRet(statsobj.Construct(&shared->per_source_stats)); snprintf(statname, sizeof(statname), "ratelimit.%s.per_source", shared->name); statname[sizeof(statname) - 1] = '\0'; CHKiRet(statsobj.SetName(shared->per_source_stats, (uchar *)statname)); CHKiRet(statsobj.SetOrigin(shared->per_source_stats, (uchar *)"ratelimit")); CHKiRet(statsobj.AddCounter(shared->per_source_stats, UCHAR_CONSTANT("per_source_allowed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &shared->ctrPerSourceAllowed)); CHKiRet(statsobj.AddCounter(shared->per_source_stats, UCHAR_CONSTANT("per_source_dropped"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &shared->ctrPerSourceDropped)); CHKiRet(statsobj.AddCounter(shared->per_source_stats, UCHAR_CONSTANT("per_source_evicted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &shared->ctrPerSourceEvicted)); CHKiRet(statsobj.AddCounter(shared->per_source_stats, UCHAR_CONSTANT("per_source_key_tpl_evals"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &shared->ctrPerSourceKeyTplEvals)); CHKiRet(statsobj.AddCounter(shared->per_source_stats, UCHAR_CONSTANT("per_source_key_parse_evals"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &shared->ctrPerSourceKeyParseEvals)); CHKiRet(statsobj.SetReadNotifier(shared->per_source_stats, ratelimitPerSourceStatsRead, shared)); CHKiRet(statsobj.ConstructFinalize(shared->per_source_stats)); finalize_it: if (iRet != RS_RET_OK) { if (bLocked) { pthread_mutex_unlock(&shared->per_source_policy_mut); } if (shared->per_source_stats != NULL) statsobj.Destruct(&shared->per_source_stats); ratelimitDestroyPerSourceShards(shared); free(shared->per_source_policy_file); shared->per_source_policy_file = NULL; ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 0); } return iRet; } static rsRetVal ratelimitSwapPerSourcePolicy(ratelimit_shared_t *shared, ratelimit_ps_policy_t *policy) { DEFiRet; if (shared == NULL || policy == NULL) FINALIZE; CHKiRet(ratelimitPerSourceApplyOverrides(shared, policy->overrides)); ratelimitSharedStoreUInt(&shared->per_source_default_max, &shared->mut, policy->default_max); ratelimitSharedStoreUInt(&shared->per_source_default_window, &shared->mut, policy->default_window); if (policy->overrides != NULL) { hashtable_destroy(policy->overrides, 1); policy->overrides = NULL; } finalize_it: RETiRet; } static void ratelimitResetPerSourceTopN(ratelimit_shared_t *shared) { ctr_t **top_ctrs = NULL; intctr_t *top_values = NULL; char **top_keys = NULL; unsigned int topn; if (shared == NULL) return; pthread_mutex_lock(&shared->per_source_policy_mut); if (shared->per_source_top_ctrs == NULL) { pthread_mutex_unlock(&shared->per_source_policy_mut); return; } topn = shared->per_source_topn; top_ctrs = shared->per_source_top_ctrs; top_values = shared->per_source_top_values; top_keys = shared->per_source_top_keys; shared->per_source_top_ctrs = NULL; shared->per_source_top_values = NULL; shared->per_source_top_keys = NULL; pthread_mutex_unlock(&shared->per_source_policy_mut); for (unsigned int i = 0; i < topn; ++i) { if (top_ctrs[i] != NULL && shared->per_source_stats != NULL) { statsobj.DestructCounter(shared->per_source_stats, top_ctrs[i]); } free(top_keys[i]); } free(top_ctrs); free(top_values); free(top_keys); } static rsRetVal ratelimitApplyPolicyPerSource(ratelimit_shared_t *shared, ratelimit_policy_file_t *policy, rsconf_t *conf, const char *policy_file) { struct template *key_tpl = NULL; sbool key_tpl_default = 0; char *key_tpl_name = NULL; char *new_policy_file = NULL; unsigned int effective_topn; sbool have_per_source_policy_file; sbool have_per_source_shards; DEFiRet; if (shared == NULL || policy == NULL || !policy->has_per_source) FINALIZE; if (!policy->per_source_enabled) { ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 0); pthread_mutex_lock(&shared->per_source_policy_mut); shared->per_source_policy_from_policy_file = 1; pthread_mutex_unlock(&shared->per_source_policy_mut); FINALIZE; } CHKiRet(ratelimitLookupPerSourceTemplate(conf, policy->per_source_key_tpl_name, &key_tpl, &key_tpl_default)); if (policy->per_source_key_tpl_name != NULL) { CHKmalloc(key_tpl_name = strdup(policy->per_source_key_tpl_name)); } pthread_mutex_lock(&shared->per_source_policy_mut); have_per_source_shards = shared->per_source_shards_initialized; pthread_mutex_unlock(&shared->per_source_policy_mut); if (!have_per_source_shards) { CHKiRet(ratelimitInitPerSourceShared(shared, policy->per_source_policy, policy_file, policy->per_source_max_states, policy->per_source_topn)); } else { CHKiRet(ratelimitSwapPerSourcePolicy(shared, policy->per_source_policy)); } if (policy_file != NULL) { pthread_mutex_lock(&shared->per_source_policy_mut); have_per_source_policy_file = (shared->per_source_policy_file != NULL); pthread_mutex_unlock(&shared->per_source_policy_mut); if (!have_per_source_policy_file) { CHKmalloc(new_policy_file = strdup(policy_file)); } } pthread_mutex_lock(&shared->per_source_policy_mut); if (shared->per_source_policy_file == NULL && new_policy_file != NULL) { shared->per_source_policy_file = new_policy_file; new_policy_file = NULL; } free(shared->per_source_key_tpl_name); shared->per_source_key_tpl_name = key_tpl_name; key_tpl_name = NULL; shared->per_source_policy_from_policy_file = 1; ratelimitSetPerSourceShardCaps(shared, policy->per_source_max_states); effective_topn = (policy->per_source_topn == 0) ? RATELIMIT_PERSOURCE_DEFAULT_TOPN : policy->per_source_topn; if (shared->per_source_topn != effective_topn) { pthread_mutex_unlock(&shared->per_source_policy_mut); ratelimitResetPerSourceTopN(shared); pthread_mutex_lock(&shared->per_source_policy_mut); shared->per_source_topn = effective_topn; } ratelimitPublishPerSourceKeyPolicy(shared, key_tpl, key_tpl_default); pthread_mutex_unlock(&shared->per_source_policy_mut); ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 1); finalize_it: free(new_policy_file); free(key_tpl_name); RETiRet; } static rsRetVal ratelimitReloadPolicyFile(ratelimit_shared_t *shared, const char *trigger) { unsigned int interval; unsigned int burst; int severity; ratelimit_scope_t scope; ratelimit_output_mode_t output_mode; ratelimit_policy_file_t policy = {0}; DEFiRet; if (shared == NULL || shared->policy_file == NULL) { FINALIZE; } interval = ratelimitSharedLoadUInt(&shared->interval, &shared->mut); burst = ratelimitSharedLoadUInt(&shared->burst, &shared->mut); severity = ratelimitSharedLoadSeverity(&shared->severity, &shared->mut); pthread_mutex_lock(&shared->mut); output_mode = shared->output_mode; pthread_mutex_unlock(&shared->mut); CHKiRet(parsePolicyFile(shared->policy_file, &policy)); scope = policy.has_scope ? policy.scope : RATELIMIT_SCOPE_INPUT; if (scope != shared->scope) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of policy '%s' from file '%s' rejected because scope changed", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (shared->scope == RATELIMIT_SCOPE_OUTPUT) { if (!policy.has_output_mode) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of output policy '%s' from file '%s' rejected because mode is missing", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (!policy.has_interval || !policy.has_burst) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of output policy '%s' from file '%s' rejected because interval or burst " "is missing", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (policy.has_severity || policy.has_per_source) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of output policy '%s' from file '%s' rejected due to unsupported fields", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } output_mode = policy.output_mode; } else if (policy.has_output_mode) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of input policy '%s' from file '%s' rejected because output mode is set", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (policy.has_interval) interval = policy.interval; if (policy.has_burst) burst = policy.burst; if (policy.has_severity) severity = policy.severity; if (shared->scope == RATELIMIT_SCOPE_OUTPUT && output_mode == RATELIMIT_OUTPUT_MODE_PACE) { sbool output_pace_forbidden; if (burst == 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of output policy '%s' from file '%s' rejected because pace mode requires " "burst greater than zero", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } pthread_mutex_lock(&shared->mut); output_pace_forbidden = shared->output_pace_forbidden; pthread_mutex_unlock(&shared->mut); if (output_pace_forbidden) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: %s reload of output policy '%s' from file '%s' rejected because a direct action uses " "this policy", trigger, shared->name, shared->policy_file); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } if (policy.has_per_source) { CHKiRet(ratelimitApplyPolicyPerSource(shared, &policy, runConf, shared->policy_file)); } else { pthread_mutex_lock(&shared->per_source_policy_mut); const sbool disable_per_source = shared->per_source_policy_from_policy_file; pthread_mutex_unlock(&shared->per_source_policy_mut); if (disable_per_source) { ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 0); } } ratelimitSharedStoreUInt(&shared->interval, &shared->mut, interval); ratelimitSharedStoreUInt(&shared->burst, &shared->mut, burst); ratelimitSharedStoreSeverity(&shared->severity, &shared->mut, severity); pthread_mutex_lock(&shared->mut); shared->output_mode = output_mode; pthread_mutex_unlock(&shared->mut); LogMsg(0, RS_RET_OK, LOG_INFO, "ratelimit: %s reloaded policy '%s' from file '%s'", trigger, shared->name, shared->policy_file); finalize_it: ratelimitPolicyFileDestruct(&policy); if (iRet != RS_RET_OK && shared != NULL && shared->policy_file != NULL) { LogError(0, iRet, "ratelimit: %s failed to reload policy '%s' from file '%s', keeping old values", trigger, shared->name, shared->policy_file); } RETiRet; } static rsRetVal ratelimitReloadPerSourcePolicyFile(ratelimit_shared_t *shared, const char *trigger) { ratelimit_ps_policy_t *policy = NULL; DEFiRet; if (shared == NULL || shared->per_source_policy_file == NULL) { FINALIZE; } CHKiRet(parsePerSourcePolicyFile(shared->per_source_policy_file, &policy)); if (policy != NULL) { CHKiRet(ratelimitSwapPerSourcePolicy(shared, policy)); if (policy->overrides != NULL) { policy->overrides = NULL; } free(policy); policy = NULL; } LogMsg(0, RS_RET_OK, LOG_INFO, "ratelimit: %s reloaded per-source policy '%s' from file '%s'", trigger, shared->name, shared->per_source_policy_file); finalize_it: if (policy != NULL) { if (policy->overrides != NULL) { hashtable_destroy(policy->overrides, 1); } free(policy); } if (iRet != RS_RET_OK && shared != NULL && shared->per_source_policy_file != NULL) { LogError(0, iRet, "ratelimit: %s failed to reload per-source policy '%s' from file '%s', keeping old values", trigger, shared->name, shared->per_source_policy_file); } RETiRet; } static rsRetVal ratelimitPerSourceCheck(ratelimit_t *ratelimit, const char *key, size_t key_len, time_t tt) { ratelimit_shared_t *shared; ratelimit_ps_bucket_t *bucket; ratelimit_ps_entry_t *entry; unsigned int hashvalue; unsigned int max; unsigned int window; sbool must_drop = 0; DEFiRet; if (ratelimit == NULL || ratelimit->pShared == NULL || key == NULL || key_len == 0) { FINALIZE; } shared = ratelimit->pShared; if (tt == 0) tt = time(NULL); if (!ratelimitPerSourceLoadEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut)) FINALIZE; bucket = ratelimitPerSourceBucket(shared, key, &hashvalue); pthread_mutex_lock(&bucket->mut); entry = (ratelimit_ps_entry_t *)hashtable_search_prehashed(bucket->ht, hashvalue, (void *)key); if (entry == NULL) { iRet = ratelimitPerSourceCreateEntry(bucket, hashvalue, key, &entry); if (iRet != RS_RET_OK) { pthread_mutex_unlock(&bucket->mut); FINALIZE; } } if (!entry->state_active) { while (bucket->max_states > 0 && bucket->active_states >= bucket->max_states) { if (bucket->lru_head == NULL) break; ratelimitPerSourceEvictOne(shared, bucket); } entry->state_active = 1; entry->window_start = tt; entry->last_seen = tt; bucket->active_states++; } ratelimitPerSourceLruTouch(bucket, entry); max = (entry->has_override && entry->has_max) ? entry->max : ratelimitSharedLoadUInt(&shared->per_source_default_max, &shared->mut); window = (entry->has_override && entry->has_window) ? entry->window : ratelimitSharedLoadUInt(&shared->per_source_default_window, &shared->mut); if (max == 0 || window == 0) { entry->allowed++; } else { if (entry->window_start == 0 || (tt - entry->window_start) >= (time_t)window || tt < entry->window_start) { entry->window_start = tt; entry->count = 0; } if (entry->count < max) { entry->count++; entry->allowed++; } else { entry->dropped++; must_drop = 1; } } entry->last_seen = tt; if (must_drop) { STATSCOUNTER_INC(shared->ctrPerSourceDropped, shared->mutCtrPerSourceDropped); } else { STATSCOUNTER_INC(shared->ctrPerSourceAllowed, shared->mutCtrPerSourceAllowed); } pthread_mutex_unlock(&bucket->mut); if (must_drop) { ABORT_FINALIZE(RS_RET_DISCARDMSG); } finalize_it: RETiRet; } rsRetVal ratelimitAddConfig(rsconf_t *conf, const char *name, unsigned int interval, unsigned int burst, int severity, const char *policy_file, sbool policy_watch, const char *policy_watch_debounce, sbool per_source_enabled, const char *per_source_policy_file, const char *per_source_key_tpl_name, unsigned int per_source_max_states, unsigned int per_source_topn, sbool has_inline_policy_params, sbool has_legacy_per_source_params) { DEFiRet; ratelimit_shared_t *shared = NULL; ratelimit_shared_t *existing_shared = NULL; struct template *per_source_key_tpl = NULL; sbool per_source_key_tpl_default = 0; char *key = NULL; ratelimit_ps_policy_t *per_source_policy = NULL; ratelimit_policy_file_t file_policy = {0}; unsigned int debounce_ms = RATELIMIT_POLICY_WATCH_DEBOUNCE_DFLT_MS; sbool per_source_from_policy_file = 0; sbool bLocked = 0; ratelimit_cfg_bucket_t *bucket = NULL; unsigned int hashvalue = 0; ratelimit_scope_t scope = RATELIMIT_SCOPE_INPUT; ratelimit_output_mode_t output_mode = RATELIMIT_OUTPUT_MODE_DROP; if (name == NULL) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (policy_watch_debounce != NULL) { CHKiRet(parseDurationMillis(policy_watch_debounce, &debounce_ms)); } if (policy_file != NULL) { CHKiRet(parsePolicyFile(policy_file, &file_policy)); if (file_policy.has_scope) scope = file_policy.scope; if (file_policy.has_output_mode) output_mode = file_policy.output_mode; if (file_policy.has_interval) interval = file_policy.interval; if (file_policy.has_burst) burst = file_policy.burst; if (file_policy.has_severity) severity = file_policy.severity; if (file_policy.has_per_source) { if (per_source_enabled || per_source_policy_file != NULL || per_source_key_tpl_name != NULL || per_source_max_states != 0 || per_source_topn != 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: policy file '%s' contains perSource for '%s'; do not mix it with legacy " "perSource/perSourcePolicy/perSourceKeyTpl/maxStates/topN parameters", policy_file, name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } per_source_from_policy_file = 1; per_source_enabled = file_policy.per_source_enabled; if (per_source_enabled) { per_source_policy = file_policy.per_source_policy; file_policy.per_source_policy = NULL; per_source_policy_file = policy_file; per_source_key_tpl_name = file_policy.per_source_key_tpl_name; file_policy.per_source_key_tpl_name = NULL; per_source_max_states = file_policy.per_source_max_states; per_source_topn = file_policy.per_source_topn; } } } if (scope == RATELIMIT_SCOPE_OUTPUT) { if (policy_file == NULL) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' must use a YAML policy file", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (has_inline_policy_params || has_legacy_per_source_params) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' must define limits only in the YAML policy file", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (!file_policy.has_output_mode) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' must define mode in the YAML policy file", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (!file_policy.has_interval || !file_policy.has_burst) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' must define interval and burst in the YAML policy file", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (file_policy.has_severity || file_policy.has_per_source) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' does not support severity or perSource in this version", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (output_mode == RATELIMIT_OUTPUT_MODE_PACE && burst == 0) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: output policy '%s' pace mode requires burst greater than zero", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } else if (file_policy.has_output_mode) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: input policy '%s' must not define output mode", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (per_source_enabled && per_source_policy == NULL) { if (per_source_policy_file == NULL) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: per-source rate limiting enabled but perSourcePolicy is missing for '%s'", name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKiRet(parsePerSourcePolicyFile(per_source_policy_file, &per_source_policy)); } /* Logic: * 1. Search for existing shared object * 2. If exists: * a. If policy_file != NULL, update it (lock, update, unlock) * b. If policy_file == NULL, do nothing (read-only, keep existing) * 3. If not exists: * a. Create new, fill values, insert into hashtable */ bucket = ratelimitCfgBucket(&conf->ratelimit_cfgs, name, &hashvalue); pthread_rwlock_wrlock(&bucket->lock); bLocked = 1; existing_shared = (ratelimit_shared_t *)hashtable_search_prehashed(bucket->ht, hashvalue, (void *)name); if (existing_shared != NULL) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: duplicate name '%s' in current config set", name); pthread_rwlock_unlock(&bucket->lock); bLocked = 0; ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* Not found - Create New */ CHKmalloc(shared = calloc(1, sizeof(ratelimit_shared_t))); ratelimitSharedRefsInit(shared, 1); pthread_mutex_init(&shared->mut, NULL); pthread_mutex_init(&shared->per_source_policy_mut, NULL); pthread_mutex_init(&shared->per_source_key_policy_mut, NULL); CHKmalloc(key = strdup(name)); shared->name = key; shared->scope = scope; shared->output_mode = output_mode; shared->interval = interval; shared->burst = burst; shared->severity = severity; shared->policy_watch = policy_watch; shared->policy_watch_debounce_ms = debounce_ms; if (policy_file) { CHKmalloc(shared->policy_file = strdup(policy_file)); } if (per_source_enabled) { iRet = ratelimitInitPerSourceShared(shared, per_source_policy, per_source_policy_file, per_source_max_states, per_source_topn); free(per_source_policy); per_source_policy = NULL; CHKiRet(iRet); if (ratelimitLookupPerSourceTemplate(conf, per_source_key_tpl_name, &per_source_key_tpl, &per_source_key_tpl_default) != RS_RET_OK) { if (per_source_key_tpl_name != NULL) { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: perSourceKeyTpl '%s' not found for '%s'", per_source_key_tpl_name, name); } else { LogError(0, RS_RET_CONFIG_ERROR, "ratelimit: default perSourceKeyTpl 'RSYSLOG_PerSourceKey' not found for '%s'", name); } pthread_rwlock_unlock(&bucket->lock); bLocked = 0; ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (per_source_key_tpl_name != NULL) { CHKmalloc(shared->per_source_key_tpl_name = strdup(per_source_key_tpl_name)); } pthread_mutex_lock(&shared->per_source_policy_mut); shared->per_source_policy_from_policy_file = per_source_from_policy_file; ratelimitPublishPerSourceKeyPolicy(shared, per_source_key_tpl, per_source_key_tpl_default); pthread_mutex_unlock(&shared->per_source_policy_mut); ratelimitPerSourceStoreEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut, 1); } if (hashtable_insert_prehashed(bucket->ht, hashvalue, key, shared) == 0) { pthread_rwlock_unlock(&bucket->lock); bLocked = 0; LogError(0, RS_RET_OUT_OF_MEMORY, "ratelimit: error inserting config into hashtable"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* shared ownership now in hashtable */ existing_shared = shared; shared = NULL; pthread_rwlock_unlock(&bucket->lock); bLocked = 0; CHKiRet(ratelimitRegisterWatchTargets(existing_shared)); finalize_it: if (bLocked) { pthread_rwlock_unlock(&bucket->lock); } if (shared != NULL) { /* If we are here, shared was allocated but NOT inserted (error case before insert) */ free(shared->name); /* key was assigned to name */ free(shared->policy_file); ratelimitDestroyPerSourceShards(shared); if (shared->per_source_stats != NULL) { statsobj.Destruct(&shared->per_source_stats); } free(shared->per_source_top_ctrs); free(shared->per_source_top_values); if (shared->per_source_top_keys != NULL) { for (unsigned int i = 0; i < shared->per_source_topn; ++i) { free(shared->per_source_top_keys[i]); } } free(shared->per_source_top_keys); free(shared->per_source_key_tpl_name); pthread_mutex_destroy(&shared->per_source_key_policy_mut); pthread_mutex_destroy(&shared->per_source_policy_mut); free(shared->per_source_policy_file); pthread_mutex_destroy(&shared->mut); ratelimitSharedRefsDestroy(shared); free(shared); } if (per_source_policy != NULL) { if (per_source_policy->overrides != NULL) hashtable_destroy(per_source_policy->overrides, 1); free(per_source_policy); } ratelimitPolicyFileDestruct(&file_policy); RETiRet; } rsRetVal ratelimitNewFromConfigForScope(ratelimit_t **ppThis, rsconf_t *conf, const char *configname, const char *modname, const char *dynname, ratelimit_scope_t scope) { DEFiRet; ratelimit_shared_t *shared; ratelimit_cfg_bucket_t *bucket; unsigned int hashvalue; sbool shared_ref = 0; if (configname == NULL || conf == NULL) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } bucket = ratelimitCfgBucket(&conf->ratelimit_cfgs, configname, &hashvalue); pthread_rwlock_rdlock(&bucket->lock); shared = (ratelimit_shared_t *)hashtable_search_prehashed(bucket->ht, hashvalue, (void *)configname); if (shared == NULL) { pthread_rwlock_unlock(&bucket->lock); LogError(0, RS_RET_NOT_FOUND, "ratelimit config '%s' not found", configname); ABORT_FINALIZE(RS_RET_NOT_FOUND); } if (shared->scope != scope) { pthread_rwlock_unlock(&bucket->lock); LogError(0, RS_RET_CONFIG_ERROR, "ratelimit config '%s' has incompatible scope for %s", configname, modname); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } ratelimitSharedAddRef(shared); shared_ref = 1; pthread_rwlock_unlock(&bucket->lock); /* We use ratelimitNew to allocate the instance, but we override the shared ptr */ CHKiRet(ratelimitNew(ppThis, modname, dynname)); /* Re-pointing to the global shared object */ /* First, free the default one created by ratelimitNew */ if ((*ppThis)->bOwnsShared) { pthread_mutex_destroy(&(*ppThis)->pShared->mut); ratelimitDestroyPerSourceShards((*ppThis)->pShared); pthread_mutex_destroy(&(*ppThis)->pShared->per_source_key_policy_mut); pthread_mutex_destroy(&(*ppThis)->pShared->per_source_policy_mut); free((*ppThis)->pShared); } (*ppThis)->pShared = shared; (*ppThis)->bOwnsShared = 0; shared_ref = 0; finalize_it: if (shared_ref) { ratelimitSharedReleaseRef(shared); } RETiRet; } rsRetVal ratelimitNewFromConfig( ratelimit_t **ppThis, rsconf_t *conf, const char *configname, const char *modname, const char *dynname) { return ratelimitNewFromConfigForScope(ppThis, conf, configname, modname, dynname, RATELIMIT_SCOPE_INPUT); } /* generate a "repeated n times" message */ static smsg_t *ratelimitGenRepMsg(ratelimit_t *ratelimit) { smsg_t *repMsg; size_t lenRepMsg; uchar szRepMsg[1024]; if (ratelimit->nsupp == 1) { /* we simply use the original message! */ repMsg = MsgAddRef(ratelimit->pMsg); } else { /* we need to duplicate, original message may still be in use in other * parts of the system! */ if ((repMsg = MsgDup(ratelimit->pMsg)) == NULL) { DBGPRINTF("Message duplication failed, dropping repeat message.\n"); goto done; } lenRepMsg = snprintf((char *)szRepMsg, sizeof(szRepMsg), " message repeated %d times: [%.800s]", ratelimit->nsupp, getMSG(ratelimit->pMsg)); MsgReplaceMSG(repMsg, szRepMsg, lenRepMsg); } done: return repMsg; } static rsRetVal doLastMessageRepeatedNTimes(ratelimit_t *ratelimit, smsg_t *pMsg, smsg_t **ppRepMsg) { int bNeedUnlockMutex = 0; DEFiRet; if (ratelimit->bThreadSafe) { pthread_mutex_lock(&ratelimit->mut); bNeedUnlockMutex = 1; } if (ratelimit->pMsg != NULL && getMSGLen(pMsg) == getMSGLen(ratelimit->pMsg) && !ustrcmp(getMSG(pMsg), getMSG(ratelimit->pMsg)) && !strcmp(getHOSTNAME(pMsg), getHOSTNAME(ratelimit->pMsg)) && !strcmp(getPROCID(pMsg, LOCK_MUTEX), getPROCID(ratelimit->pMsg, LOCK_MUTEX)) && !strcmp(getAPPNAME(pMsg, LOCK_MUTEX), getAPPNAME(ratelimit->pMsg, LOCK_MUTEX))) { ratelimit->nsupp++; DBGPRINTF("msg repeated %d times\n", ratelimit->nsupp); /* use current message, so we have the new timestamp * (means we need to discard previous one) */ msgDestruct(&ratelimit->pMsg); ratelimit->pMsg = pMsg; ABORT_FINALIZE(RS_RET_DISCARDMSG); } else { /* new message, do "repeat processing" & save it */ if (ratelimit->pMsg != NULL) { if (ratelimit->nsupp > 0) { *ppRepMsg = ratelimitGenRepMsg(ratelimit); ratelimit->nsupp = 0; } msgDestruct(&ratelimit->pMsg); } ratelimit->pMsg = MsgAddRef(pMsg); } finalize_it: if (bNeedUnlockMutex) pthread_mutex_unlock(&ratelimit->mut); RETiRet; } /* helper: tell how many messages we lost due to linux-like ratelimiting */ static void tellLostCnt(ratelimit_t *ratelimit) { uchar msgbuf[1024]; if (ratelimit->missed) { snprintf((char *)msgbuf, sizeof(msgbuf), "%s: %u messages lost due to rate-limiting (%u allowed within %u seconds)", ratelimit->name, ratelimit->missed, ratelimitSharedLoadUInt(&ratelimit->pShared->burst, &ratelimit->pShared->mut), ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut)); ratelimit->missed = 0; logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG | LOG_INFO, msgbuf, 0); } } /* Linux-like ratelimiting, modelled after the linux kernel * returns 1 if message is within rate limit and shall be * processed, 0 otherwise. * This implementation is NOT THREAD-SAFE and must not * be called concurrently. */ static int ATTR_NONNULL() withinRatelimit(ratelimit_t *__restrict__ const ratelimit, time_t tt, const char *const appname) { int ret; uchar msgbuf[1024]; if (ratelimit->bThreadSafe) { pthread_mutex_lock(&ratelimit->mut); } unsigned int interval = ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut); unsigned int burst = ratelimitSharedLoadUInt(&ratelimit->pShared->burst, &ratelimit->pShared->mut); if (interval == 0) { ret = 1; goto finalize_it; } /* we primarily need "NoTimeCache" mode for imjournal, as it * sets the message generation time to the journal timestamp. * As such, we do not get a proper indication of the actual * message rate. To prevent this, we need to query local * system time ourselvs. */ if (ratelimit->bNoTimeCache) tt = time(NULL); /* assert(burst != 0); -- burst can be 0 for block-all policy */ if (ratelimit->begin == 0) ratelimit->begin = tt; /* resume if we go out of time window or if time has gone backwards */ if ((tt > (time_t)(ratelimit->begin + interval)) || (tt < ratelimit->begin)) { ratelimit->begin = 0; ratelimit->done = 0; tellLostCnt(ratelimit); } /* do actual limit check */ if (burst > ratelimit->done) { ratelimit->done++; ret = 1; } else { ratelimit->missed++; if (ratelimit->missed == 1) { snprintf((char *)msgbuf, sizeof(msgbuf), "%s from <%s>: begin to drop messages due to rate-limiting", ratelimit->name, appname); logmsgInternal(RS_RET_RATE_LIMITED, LOG_SYSLOG | LOG_INFO, msgbuf, 0); } ret = 0; } finalize_it: if (ratelimit->bThreadSafe) { pthread_mutex_unlock(&ratelimit->mut); } return ret; } /* ratelimit a message based on message count * - handles only rate-limiting * This function returns RS_RET_OK, if the caller shall process * the message regularly and RS_RET_DISCARD if the caller must * discard the message. The caller should also discard the message * if another return status occurs. */ rsRetVal ratelimitMsgCount(ratelimit_t *__restrict__ const ratelimit, time_t tt, const char *const appname) { DEFiRet; if (ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut)) { if (withinRatelimit(ratelimit, tt, appname) == 0) { ABORT_FINALIZE(RS_RET_DISCARDMSG); } } finalize_it: if (Debug) { if (iRet == RS_RET_DISCARDMSG) DBGPRINTF("message discarded by ratelimiting\n"); } RETiRet; } rsRetVal ratelimitMsgCountWait(ratelimit_t *__restrict__ const ratelimit, time_t tt, const char *const appname, unsigned int *const wait_usec) { unsigned int interval; unsigned int burst; time_t resume_time; time_t wait_sec; DEFiRet; if (ratelimit == NULL || wait_usec == NULL) return RS_RET_PARAM_ERROR; (void)appname; *wait_usec = 0; if (ratelimit->bThreadSafe) { pthread_mutex_lock(&ratelimit->mut); } interval = ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut); burst = ratelimitSharedLoadUInt(&ratelimit->pShared->burst, &ratelimit->pShared->mut); if (interval == 0) goto finalize_it; if (ratelimit->bNoTimeCache || tt == 0) tt = time(NULL); if (ratelimit->begin == 0) ratelimit->begin = tt; if ((tt >= (time_t)(ratelimit->begin + interval)) || (tt < ratelimit->begin)) { ratelimit->begin = tt; ratelimit->done = 0; tellLostCnt(ratelimit); } if (burst > ratelimit->done) { ratelimit->done++; } else { resume_time = ratelimit->begin + interval; wait_sec = (resume_time > tt) ? resume_time - tt : 1; if (wait_sec > (time_t)(UINT_MAX / 1000000U)) { *wait_usec = UINT_MAX; } else { *wait_usec = (unsigned int)wait_sec * 1000000U; } ABORT_FINALIZE(RS_RET_DISCARDMSG); } finalize_it: if (ratelimit->bThreadSafe) { pthread_mutex_unlock(&ratelimit->mut); } RETiRet; } ratelimit_scope_t ratelimitGetScope(const ratelimit_t *ratelimit) { if (ratelimit == NULL || ratelimit->pShared == NULL) return RATELIMIT_SCOPE_INPUT; return ratelimit->pShared->scope; } ratelimit_output_mode_t ratelimitGetOutputMode(const ratelimit_t *ratelimit) { ratelimit_output_mode_t mode; if (ratelimit == NULL || ratelimit->pShared == NULL) return RATELIMIT_OUTPUT_MODE_DROP; pthread_mutex_lock(&ratelimit->pShared->mut); mode = ratelimit->pShared->output_mode; pthread_mutex_unlock(&ratelimit->pShared->mut); return mode; } void ratelimitForbidOutputPace(ratelimit_t *ratelimit) { if (ratelimit == NULL || ratelimit->pShared == NULL) return; pthread_mutex_lock(&ratelimit->pShared->mut); ratelimit->pShared->output_pace_forbidden = 1; pthread_mutex_unlock(&ratelimit->pShared->mut); } /* ratelimit a message, that means: * - handle "last message repeated n times" logic * - handle actual (discarding) rate-limiting * This function returns RS_RET_OK, if the caller shall process * the message regularly and RS_RET_DISCARD if the caller must * discard the message. The caller should also discard the message * if another return status occurs. This places some burden on the * caller logic, but provides best performance. Demanding this * cooperative mode can enable a faulty caller to thrash up part * of the system, but we accept that risk (a faulty caller can * always do all sorts of evil, so...) * If *ppRepMsg != NULL on return, the caller must enqueue that * message before the original message. */ rsRetVal ATTR_NONNULL(1, 2, 3) ratelimitMsg(ratelimit_t *__restrict__ const ratelimit, smsg_t *pMsg, smsg_t **ppRepMsg) { DEFiRet; rsRetVal localRet; int severity = 0; unsigned int interval; int threshold; assert(ratelimit != NULL); assert(pMsg != NULL); assert(ppRepMsg != NULL); *ppRepMsg = NULL; interval = ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut); threshold = ratelimitSharedLoadSeverity(&ratelimit->pShared->severity, &ratelimit->pShared->mut); if (runConf->globals.bReduceRepeatMsgs || threshold > 0) { /* consider early parsing only if really needed */ if ((pMsg->msgFlags & NEEDS_PARSING) != 0) { if ((localRet = parser.ParseMsg(pMsg)) != RS_RET_OK) { DBGPRINTF("Message discarded, parsing error %d\n", localRet); ABORT_FINALIZE(RS_RET_DISCARDMSG); } } severity = pMsg->iSeverity; } /* Only the messages having severity level at or below the * treshold (the value is >=) are subject to ratelimiting. */ if (interval && (severity >= threshold)) { char namebuf[512]; /* 256 for FGDN adn 256 for APPNAME should be enough */ snprintf(namebuf, sizeof namebuf, "%s:%s", getHOSTNAME(pMsg), getAPPNAME(pMsg, 0)); if (withinRatelimit(ratelimit, pMsg->ttGenTime, namebuf) == 0) { msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_DISCARDMSG); } } if (runConf->globals.bReduceRepeatMsgs) { CHKiRet(doLastMessageRepeatedNTimes(ratelimit, pMsg, ppRepMsg)); } finalize_it: if (Debug) { if (iRet == RS_RET_DISCARDMSG) DBGPRINTF("message discarded by ratelimiting\n"); } RETiRet; } /* returns 1, if the ratelimiter performs any checks and 0 otherwise */ int ratelimitChecked(ratelimit_t *ratelimit) { const unsigned int per_source_enabled = ratelimitPerSourceLoadEnabled(&ratelimit->pShared->per_source_enabled, &ratelimit->pShared->per_source_policy_mut); return ratelimitSharedLoadUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut) || per_source_enabled || runConf->globals.bReduceRepeatMsgs; } /* add a message to a ratelimiter/multisubmit structure. * ratelimiting is automatically handled according to the ratelimit * settings. * if pMultiSub == NULL, a single-message enqueue happens (under reconsideration) */ typedef struct per_source_key_ctx_s { const char *key; size_t key_len; actWrkrIParams_t tpl_param; char *combined; uchar *free_host; uchar *free_port; } per_source_key_ctx_t; static void ratelimitPerSourceKeyCtxFree(per_source_key_ctx_t *ctx) { if (ctx == NULL) return; free(ctx->tpl_param.param); free(ctx->combined); free(ctx->free_host); free(ctx->free_port); memset(ctx, 0, sizeof(*ctx)); } static rsRetVal ratelimitGetRcvFromString( smsg_t *pMsg, propid_t propid, const char **value, size_t *len, uchar **to_free) { uchar *prop_value; int prop_len; DEFiRet; if (pMsg == NULL || value == NULL || len == NULL || to_free == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); *to_free = NULL; MsgGetRcvFromProp(pMsg, propid, &prop_value, &prop_len); *value = (const char *)prop_value; *len = (size_t)prop_len; finalize_it: RETiRet; } static rsRetVal ratelimitComposePerSourceHostPort( per_source_key_ctx_t *ctx, const char *host, size_t host_len, const char *port, size_t port_len) { DEFiRet; if (ctx == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); CHKmalloc(ctx->combined = malloc(host_len + 1 + port_len + 1)); if (host_len > 0) memcpy(ctx->combined, host, host_len); ctx->combined[host_len] = ':'; if (port_len > 0) memcpy(ctx->combined + host_len + 1, port, port_len); ctx->combined[host_len + 1 + port_len] = '\0'; ctx->key = ctx->combined; ctx->key_len = host_len + 1 + port_len; finalize_it: RETiRet; } static rsRetVal ratelimitComputePerSourceKey(ratelimit_t *ratelimit, smsg_t *pMsg, per_source_key_ctx_t *ctx) { ratelimit_shared_t *shared; ratelimit_ps_key_policy_t policy; const char *host = ""; const char *port = ""; size_t host_len = 0; size_t port_len = 0; DEFiRet; if (ratelimit == NULL || pMsg == NULL || ctx == NULL || ratelimit->pShared == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); memset(ctx, 0, sizeof(*ctx)); shared = ratelimit->pShared; if (!ratelimitPerSourceLoadEnabled(&shared->per_source_enabled, &shared->per_source_policy_mut)) FINALIZE; ratelimitLoadPerSourceKeyPolicy(shared, &policy); switch (policy.key_mode) { case RL_PS_KEY_FROMHOST_IP: CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST_IP, &ctx->key, &ctx->key_len, &ctx->free_host)); break; case RL_PS_KEY_FROMHOST: CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST, &ctx->key, &ctx->key_len, &ctx->free_host)); break; case RL_PS_KEY_FROMHOST_PORT: CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST_PORT, &ctx->key, &ctx->key_len, &ctx->free_port)); break; case RL_PS_KEY_FROMHOST_IP_PORT: CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST_IP, &host, &host_len, &ctx->free_host)); CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST_PORT, &port, &port_len, &ctx->free_port)); CHKiRet(ratelimitComposePerSourceHostPort(ctx, host, host_len, port, port_len)); break; case RL_PS_KEY_FROMHOST_NAME_PORT: CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST, &host, &host_len, &ctx->free_host)); CHKiRet(ratelimitGetRcvFromString(pMsg, PROP_FROMHOST_PORT, &port, &port_len, &ctx->free_port)); CHKiRet(ratelimitComposePerSourceHostPort(ctx, host, host_len, port, port_len)); break; case RL_PS_KEY_TPL: default: if (policy.key_needs_parsing && (pMsg->msgFlags & NEEDS_PARSING) != 0) { STATSCOUNTER_INC(shared->ctrPerSourceKeyParseEvals, shared->mutCtrPerSourceKeyParseEvals); if (parser.ParseMsg(pMsg) != RS_RET_OK) { FINALIZE; } } if (policy.key_tpl == NULL || policy.key_tpl_default) { ctx->key = getHOSTNAME(pMsg); ctx->key_len = getHOSTNAMELen(pMsg); break; } STATSCOUNTER_INC(shared->ctrPerSourceKeyTplEvals, shared->mutCtrPerSourceKeyTplEvals); if (tplToString(policy.key_tpl, pMsg, &ctx->tpl_param, NULL) == RS_RET_OK) { ctx->key = (const char *)ctx->tpl_param.param; ctx->key_len = ctx->tpl_param.lenStr; } break; } finalize_it: RETiRet; } static rsRetVal ratelimitSubmitCheckedMsg(multi_submit_t *pMultiSub, smsg_t **ppMsg) { DEFiRet; if (ppMsg == NULL || *ppMsg == NULL) FINALIZE; if (pMultiSub == NULL) { CHKiRet(submitMsg2(*ppMsg)); *ppMsg = NULL; } else { if ((*ppMsg)->iLenRawMsg > glblGetMaxLine(runConf)) { if (pMultiSub->nElem > 0) { CHKiRet(multiSubmitMsg2(pMultiSub)); } CHKiRet(submitMsg2(*ppMsg)); *ppMsg = NULL; FINALIZE; } pMultiSub->ppMsgs[pMultiSub->nElem++] = *ppMsg; *ppMsg = NULL; if (pMultiSub->nElem == pMultiSub->maxElem) CHKiRet(multiSubmitMsg2(pMultiSub)); } finalize_it: RETiRet; } static rsRetVal ratelimitSubmitReportMsg(multi_submit_t *pMultiSub, smsg_t **ppRepMsg) { DEFiRet; if (ppRepMsg == NULL || *ppRepMsg == NULL) FINALIZE; if (pMultiSub == NULL) { CHKiRet(submitMsg2(*ppRepMsg)); *ppRepMsg = NULL; } else { pMultiSub->ppMsgs[pMultiSub->nElem++] = *ppRepMsg; *ppRepMsg = NULL; if (pMultiSub->nElem == pMultiSub->maxElem) CHKiRet(multiSubmitMsg2(pMultiSub)); } finalize_it: RETiRet; } rsRetVal ATTR_NONNULL(1, 3) ratelimitAddMsg(ratelimit_t *ratelimit, multi_submit_t *pMultiSub, smsg_t *pMsg) { rsRetVal localRet; smsg_t *repMsg = NULL; sbool msg_owned = 0; sbool per_source_dropped = 0; per_source_key_ctx_t per_source_key = {0}; DEFiRet; assert(ratelimit != NULL); assert(pMsg != NULL); localRet = ratelimitMsg(ratelimit, pMsg, &repMsg); CHKiRet(localRet); msg_owned = 1; CHKiRet(ratelimitSubmitReportMsg(pMultiSub, &repMsg)); CHKiRet(ratelimitComputePerSourceKey(ratelimit, pMsg, &per_source_key)); if (per_source_key.key != NULL && per_source_key.key_len > 0) { if ((iRet = ratelimitPerSourceCheck(ratelimit, per_source_key.key, per_source_key.key_len, pMsg->ttGenTime)) != RS_RET_OK) { per_source_dropped = 1; ABORT_FINALIZE(iRet); } } CHKiRet(ratelimitSubmitCheckedMsg(pMultiSub, &pMsg)); finalize_it: ratelimitPerSourceKeyCtxFree(&per_source_key); if (repMsg != NULL) { msgDestruct(&repMsg); } if (pMsg != NULL && (msg_owned || per_source_dropped)) { msgDestruct(&pMsg); } RETiRet; } /* modname must be a static name (usually expected to be the module * name and MUST be present. dynname may be NULL and can be used for * dynamic information, e.g. PID or listener IP, ... * Both values should be kept brief. */ rsRetVal ratelimitNew(ratelimit_t **ppThis, const char *modname, const char *dynname) { ratelimit_t *pThis = NULL; char namebuf[256]; DEFiRet; CHKmalloc(pThis = calloc(1, sizeof(ratelimit_t))); if (modname == NULL) modname = "*ERROR:MODULE NAME MISSING*"; if (dynname == NULL) { pThis->name = strdup(modname); } else { snprintf(namebuf, sizeof(namebuf), "%s[%s]", modname, dynname); namebuf[sizeof(namebuf) - 1] = '\0'; /* to be on safe side */ pThis->name = strdup(namebuf); } /* Allocate default shared structure for standalone instance */ CHKmalloc(pThis->pShared = calloc(1, sizeof(ratelimit_shared_t))); pThis->bOwnsShared = 1; pThis->pShared->scope = RATELIMIT_SCOPE_INPUT; pThis->pShared->output_mode = RATELIMIT_OUTPUT_MODE_DROP; pthread_mutex_init(&pThis->pShared->mut, NULL); pthread_mutex_init(&pThis->pShared->per_source_policy_mut, NULL); pthread_mutex_init(&pThis->pShared->per_source_key_policy_mut, NULL); DBGPRINTF("ratelimit:%s:new ratelimiter\n", pThis->name); *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { if (pThis != NULL) { free(pThis->name); free(pThis); } } RETiRet; } /* enable linux-like ratelimiting */ void ratelimitSetLinuxLike(ratelimit_t *ratelimit, unsigned int interval, unsigned int burst) { ratelimitSharedStoreUInt(&ratelimit->pShared->interval, &ratelimit->pShared->mut, interval); ratelimitSharedStoreUInt(&ratelimit->pShared->burst, &ratelimit->pShared->mut, burst); ratelimit->done = 0; ratelimit->missed = 0; ratelimit->begin = 0; } static void ratelimitEnsureMutexInitialized(ratelimit_t *ratelimit) { if (!ratelimit->bMutInitialized) { pthread_mutex_init(&ratelimit->mut, NULL); ratelimit->bMutInitialized = 1; } } /* enable thread-safe operations mode. This make sure that * a single ratelimiter can be called from multiple threads. As * this causes some overhead and is not always required, it needs * to be explicitely enabled. This operation cannot be undone * (think: why should one do that???) */ void ratelimitSetThreadSafe(ratelimit_t *ratelimit) { ratelimit->bThreadSafe = 1; ratelimitEnsureMutexInitialized(ratelimit); } void ratelimitSetNoTimeCache(ratelimit_t *ratelimit) { ratelimit->bNoTimeCache = 1; ratelimitEnsureMutexInitialized(ratelimit); } /* Severity level determines which messages are subject to * ratelimiting. Default (no value set) is all messages. */ void ratelimitSetSeverity(ratelimit_t *ratelimit, int severity) { ratelimitSharedStoreSeverity(&ratelimit->pShared->severity, &ratelimit->pShared->mut, severity); } void ratelimitDestruct(ratelimit_t *ratelimit) { smsg_t *pMsg; if (ratelimit->pMsg != NULL) { if (ratelimit->nsupp > 0) { pMsg = ratelimitGenRepMsg(ratelimit); if (pMsg != NULL) submitMsg2(pMsg); } msgDestruct(&ratelimit->pMsg); } tellLostCnt(ratelimit); if (ratelimit->bMutInitialized) pthread_mutex_destroy(&ratelimit->mut); if (ratelimit->bOwnsShared && ratelimit->pShared != NULL) { pthread_mutex_destroy(&ratelimit->pShared->mut); ratelimitDestroyPerSourceShards(ratelimit->pShared); pthread_mutex_destroy(&ratelimit->pShared->per_source_key_policy_mut); pthread_mutex_destroy(&ratelimit->pShared->per_source_policy_mut); free(ratelimit->pShared); } else if (ratelimit->pShared != NULL) { ratelimitSharedReleaseRef(ratelimit->pShared); } free(ratelimit->name); free(ratelimit); } void ratelimitModExit(void) { objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); } rsRetVal ratelimitModInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); finalize_it: RETiRet; } static void ratelimitDoHUPShared(ratelimit_shared_t *const shared) { sbool reload_per_source; if (shared->policy_file) { ratelimitReloadPolicyFile(shared, "HUP"); } pthread_mutex_lock(&shared->per_source_policy_mut); reload_per_source = (shared->per_source_policy_file != NULL && !shared->per_source_policy_from_policy_file); pthread_mutex_unlock(&shared->per_source_policy_mut); if (reload_per_source) { ratelimitReloadPerSourcePolicyFile(shared, "HUP"); } } static rsRetVal ratelimitCfgsAppendSnapshot(ratelimit_shared_t ***const snapshot, size_t *const count, size_t *const capacity, ratelimit_shared_t *const shared) { ratelimit_shared_t **new_snapshot; size_t new_capacity; DEFiRet; if (*count == *capacity) { new_capacity = (*capacity == 0) ? 16 : (*capacity * 2); if (new_capacity < *capacity || new_capacity > ((size_t)-1 / sizeof(ratelimit_shared_t *))) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(new_snapshot = realloc(*snapshot, new_capacity * sizeof(ratelimit_shared_t *))); *snapshot = new_snapshot; *capacity = new_capacity; } (*snapshot)[(*count)++] = shared; finalize_it: RETiRet; } static void ratelimitCfgsReleaseSnapshot(ratelimit_shared_t **const snapshot, const size_t count) { if (snapshot != NULL) { for (size_t i = 0; i < count; ++i) { if (snapshot[i] != NULL) { ratelimitSharedReleaseRef(snapshot[i]); } } free(snapshot); } } static rsRetVal ratelimitCfgsSnapshot(ratelimit_cfgs_t *const cfgs, ratelimit_shared_t ***const snapshot, size_t *const count) { struct hashtable_itr *itr = NULL; size_t capacity = 0; unsigned int locked_shard = RATELIMIT_CFG_SHARDS; DEFiRet; *snapshot = NULL; *count = 0; for (unsigned int i = 0; i < RATELIMIT_CFG_SHARDS; ++i) { pthread_rwlock_rdlock(&cfgs->shards[i].lock); locked_shard = i; if (cfgs->shards[i].ht != NULL && hashtable_count(cfgs->shards[i].ht) > 0) { CHKmalloc(itr = hashtable_iterator(cfgs->shards[i].ht)); do { ratelimit_shared_t *const shared = (ratelimit_shared_t *)hashtable_iterator_value(itr); if (shared != NULL) { CHKiRet(ratelimitCfgsAppendSnapshot(snapshot, count, &capacity, shared)); ratelimitSharedAddRef(shared); } } while (hashtable_iterator_advance(itr)); free(itr); itr = NULL; } pthread_rwlock_unlock(&cfgs->shards[i].lock); locked_shard = RATELIMIT_CFG_SHARDS; } finalize_it: free(itr); if (locked_shard < RATELIMIT_CFG_SHARDS) { pthread_rwlock_unlock(&cfgs->shards[locked_shard].lock); } if (iRet != RS_RET_OK) { ratelimitCfgsReleaseSnapshot(*snapshot, *count); *snapshot = NULL; *count = 0; } RETiRet; } void ratelimitDoHUP(void) { ratelimit_shared_t **snapshot = NULL; size_t count = 0; if (runConf == NULL) { return; } if (ratelimitCfgsSnapshot(&runConf->ratelimit_cfgs, &snapshot, &count) != RS_RET_OK) { LogError(0, RS_RET_OUT_OF_MEMORY, "ratelimit: cannot snapshot configs for HUP reload"); return; } for (size_t i = 0; i < count; ++i) { if (snapshot[i] != NULL) { ratelimitDoHUPShared(snapshot[i]); } } ratelimitCfgsReleaseSnapshot(snapshot, count); } rsyslog-8.2608.0/runtime/PaxHeaders/statsobj.c0000644000000000000000000000013115241075234016221 xustar0030 mtime=1787067036.610578388 29 atime=1787067036.75758114 30 ctime=1787067794.357724365 rsyslog-8.2608.0/runtime/statsobj.c0000664000175000017500000011425715241075234015700 0ustar00rgerrger/* The statsobj object. * * This object provides a statistics-gathering facility inside rsyslog. This * functionality will be pragmatically implemented and extended. * * Copyright 2010-2021 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file statsobj.c * @brief Implementation of the rsyslog statistics object * * Each statsobj_t instance maintains a name, origin and a set of counters. * All instances are linked together so that GetAllStatsLines() can iterate * through them and emit their values. Counters may be 64 bit integers or * plain ints and are modified with atomic helpers when required. * * The module can output collected counters in several formats: * - legacy key=value lines * - JSON or JSON-ES (Elasticsearch compatible) * - CEE / lumberjack records * - Prometheus text exposition * * Statistics gathering is controlled by the ::GatherStats flag and can be * enabled via EnableStats(). */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "unicode-helper.h" #include "obj.h" #include "statsobj.h" #include "srUtils.h" #include "stringbuf.h" #include "errmsg.h" #include "hashtable.h" #include "hashtable_itr.h" #include "rsconf.h" /* externally-visiable data (see statsobj.h for explanation) */ int GatherStats = 0; /* static data */ DEFobjStaticHelpers; /* doubly linked list of stats objects. Object is automatically linked to it * upon construction. Enqueue always happens at the front (simplifies logic). */ static statsobj_t *objRoot = NULL; static statsobj_t *objLast = NULL; static pthread_mutex_t mutStats; static pthread_mutex_t mutSenders; static struct hashtable *stats_senders = NULL; /* ------------------------------ statsobj linked list maintenance ------------------------------ */ static rsRetVal statsobjLock(pthread_mutex_t *mutex, const char *lockName) { const int ret = pthread_mutex_lock(mutex); if (ret != 0) { LogError(ret, RS_RET_CONC_CTRL_ERR, "statsobj: error locking %s mutex", lockName); return RS_RET_CONC_CTRL_ERR; } return RS_RET_OK; } static void statsobjUnlock(pthread_mutex_t *mutex, const char *lockName) { const int ret = pthread_mutex_unlock(mutex); if (ret != 0) { LogError(ret, RS_RET_CONC_CTRL_ERR, "statsobj: error unlocking %s mutex", lockName); abort(); } } static rsRetVal addToObjList(statsobj_t *pThis) { DEFiRet; CHKiRet(statsobjLock(&mutStats, "stats object list")); if (pThis->flags & STATSOBJ_FLAG_DO_PREPEND) { pThis->next = objRoot; if (objRoot != NULL) { objRoot->prev = pThis; } objRoot = pThis; if (objLast == NULL) objLast = pThis; } else { pThis->prev = objLast; if (objLast != NULL) objLast->next = pThis; objLast = pThis; if (objRoot == NULL) objRoot = pThis; } /* Unlock failures happen after shared state was already updated. Log them, * but do not make callers roll back objects that are now visible. */ statsobjUnlock(&mutStats, "stats object list"); finalize_it: RETiRet; } static rsRetVal removeFromObjList(statsobj_t *pThis) { DEFiRet; CHKiRet(statsobjLock(&mutStats, "stats object list")); if (pThis->prev != NULL) pThis->prev->next = pThis->next; if (pThis->next != NULL) pThis->next->prev = pThis->prev; if (objLast == pThis) objLast = pThis->prev; if (objRoot == pThis) objRoot = pThis->next; statsobjUnlock(&mutStats, "stats object list"); finalize_it: RETiRet; } static rsRetVal addCtrToList(statsobj_t *pThis, ctr_t *pCtr) { DEFiRet; CHKiRet(statsobjLock(&pThis->mutCtr, "counter list")); pCtr->prev = pThis->ctrLast; if (pThis->ctrLast != NULL) pThis->ctrLast->next = pCtr; pThis->ctrLast = pCtr; if (pThis->ctrRoot == NULL) pThis->ctrRoot = pCtr; /* See addToObjList(): rollback after successful list mutation is unsafe. */ statsobjUnlock(&pThis->mutCtr, "counter list"); finalize_it: RETiRet; } /* ------------------------------ methods ------------------------------ */ /* Standard-Constructor */ BEGINobjConstruct(statsobj) /* be sure to specify the object type also in END macro! */ CHKiConcCtrl(pthread_mutex_init(&pThis->mutCtr, NULL)); pThis->ctrLast = NULL; pThis->ctrRoot = NULL; pThis->read_notifier = NULL; pThis->flags = 0; finalize_it: ENDobjConstruct(statsobj) /* ConstructionFinalizer */ static rsRetVal statsobjConstructFinalize(statsobj_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, statsobj); CHKiRet(addToObjList(pThis)); finalize_it: RETiRet; } /* set read_notifier (a function which is invoked after stats are read). */ static rsRetVal setReadNotifier(statsobj_t *pThis, statsobj_read_notifier_t notifier, void *ctx) { DEFiRet; pThis->read_notifier = notifier; pThis->read_notifier_ctx = ctx; RETiRet; } /* set origin (module name, etc). * Note that we make our own copy of the memory, caller is * responsible to free up name it passes in (if required). */ static rsRetVal setOrigin(statsobj_t *pThis, uchar *origin) { DEFiRet; CHKmalloc(pThis->origin = ustrdup(origin)); finalize_it: RETiRet; } /* set name. Note that we make our own copy of the memory, caller is * responsible to free up name it passes in (if required). */ static rsRetVal setName(statsobj_t *pThis, uchar *name) { DEFiRet; CHKmalloc(pThis->name = ustrdup(name)); finalize_it: RETiRet; } static void setStatsObjFlags(statsobj_t *pThis, int flags) { pThis->flags = flags; } static rsRetVal setReportingNamespace(statsobj_t *pThis, uchar *ns) { DEFiRet; CHKmalloc(pThis->reporting_ns = ustrdup(ns)); finalize_it: RETiRet; } /* add a counter to an object * ctrName is duplicated, caller must free it if requried * NOTE: The counter is READ-ONLY and MUST NOT be modified (most * importantly, it must not be initialized, so the caller must * ensure the counter is properly initialized before AddCounter() * is called. */ static rsRetVal addManagedCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr, ctr_t **entryRef, int8_t linked) { ctr_t *ctr; DEFiRet; *entryRef = NULL; CHKmalloc(ctr = calloc(1, sizeof(ctr_t))); ctr->next = NULL; ctr->prev = NULL; if ((ctr->name = ustrdup(ctrName)) == NULL) { DBGPRINTF("addCounter: OOM in strdup()\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } ctr->flags = flags; ctr->ctrType = ctrType; switch (ctrType) { case ctrType_IntCtr: ctr->val.pIntCtr = (intctr_t *)pCtr; break; case ctrType_Int: ctr->val.pInt = (int *)pCtr; break; default: // No action needed for other cases break; } if (linked) { CHKiRet(addCtrToList(pThis, ctr)); } *entryRef = ctr; finalize_it: if (iRet != RS_RET_OK) { if (ctr != NULL) { free(ctr->name); free(ctr); } } RETiRet; } static rsRetVal addPreCreatedCounter(statsobj_t *pThis, ctr_t *pCtr) { pCtr->next = NULL; pCtr->prev = NULL; return addCtrToList(pThis, pCtr); } static rsRetVal addCounter(statsobj_t *pThis, const uchar *ctrName, statsCtrType_t ctrType, int8_t flags, void *pCtr) { ctr_t *ctr; DEFiRet; iRet = addManagedCounter(pThis, ctrName, ctrType, flags, pCtr, &ctr, 1); RETiRet; } static void destructUnlinkedCounter(ctr_t *ctr) { free(ctr->name); free(ctr); } static void destructCounter(statsobj_t *pThis, ctr_t *pCtr) { pthread_mutex_lock(&pThis->mutCtr); if (pCtr->prev != NULL) { pCtr->prev->next = pCtr->next; } if (pCtr->next != NULL) { pCtr->next->prev = pCtr->prev; } if (pThis->ctrLast == pCtr) { pThis->ctrLast = pCtr->prev; } if (pThis->ctrRoot == pCtr) { pThis->ctrRoot = pCtr->next; } pthread_mutex_unlock(&pThis->mutCtr); destructUnlinkedCounter(pCtr); } static intctr_t getIntCtrValue(const intctr_t *const ctr) { return PREFER_LOAD_uint64(ctr); } static void resetIntCtrValue(intctr_t *const ctr) { PREFER_STORE_uint64(ctr, 0); } static int getIntValue(const int *const ctr) { return PREFER_LOAD_INT(ctr); } static void resetIntValue(int *const ctr) { PREFER_STORE_INT(ctr, 0); } static void resetResettableCtr(ctr_t *pCtr, int8_t bResetCtrs) { if ((bResetCtrs && (pCtr->flags & CTR_FLAG_RESETTABLE)) || (pCtr->flags & CTR_FLAG_MUST_RESET)) { switch (pCtr->ctrType) { case ctrType_IntCtr: resetIntCtrValue(pCtr->val.pIntCtr); break; case ctrType_Int: resetIntValue(pCtr->val.pInt); break; default: // No action needed for other cases break; } } } static rsRetVal addCtrForReporting(json_object *to, const uchar *field_name, intctr_t value) { json_object *v; DEFiRet; /*We should migrate libfastjson to support uint64_t in addition to int64_t. Although no counter is likely to grow to int64 max-value, this is theoritically incorrect (as intctr_t is uint64)*/ CHKmalloc(v = json_object_new_int64((int64_t)value)); json_object_object_add(to, (const char *)field_name, v); finalize_it: /* v cannot be NULL in error case, as this would only happen during malloc fail, * which itself sets it to NULL -- so not doing cleanup here. */ RETiRet; } static rsRetVal addContextForReporting(json_object *to, const uchar *field_name, const uchar *value) { json_object *v; DEFiRet; CHKmalloc(v = json_object_new_string((const char *)value)); json_object_object_add(to, (const char *)field_name, v); finalize_it: RETiRet; } static intctr_t accumulatedValue(ctr_t *pCtr) { switch (pCtr->ctrType) { case ctrType_IntCtr: return getIntCtrValue(pCtr->val.pIntCtr); case ctrType_Int: return (intctr_t)getIntValue(pCtr->val.pInt); default: // No action needed for other cases break; } return -1; } /* get all the object's countes together as CEE. */ static rsRetVal getStatsLineCEE(statsobj_t *pThis, cstr_t **ppcstr, const statsFmtType_t fmt, const int8_t bResetCtrs) { cstr_t *pcstr = NULL; ctr_t *pCtr; json_object *root, *values; int locked = 0; DEFiRet; root = values = NULL; CHKiRet(cstrConstruct(&pcstr)); if (fmt == statsFmt_CEE) CHKiRet(rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT(CONST_CEE_COOKIE " "), CONST_LEN_CEE_COOKIE + 1)); CHKmalloc(root = json_object_new_object()); CHKiRet(addContextForReporting(root, UCHAR_CONSTANT("name"), pThis->name)); if (pThis->origin != NULL) { CHKiRet(addContextForReporting(root, UCHAR_CONSTANT("origin"), pThis->origin)); } if (pThis->reporting_ns == NULL) { values = json_object_get(root); } else { CHKmalloc(values = json_object_new_object()); json_object_object_add(root, (const char *)pThis->reporting_ns, json_object_get(values)); } /* now add all counters to this line */ pthread_mutex_lock(&pThis->mutCtr); locked = 1; for (pCtr = pThis->ctrRoot; pCtr != NULL; pCtr = pCtr->next) { if (fmt == statsFmt_JSON_ES) { /* work-around for broken Elasticsearch JSON implementation: * we need to replace dots by a different char, we use bang. * Note: ES 2.0 does not longer accept dot in name */ uchar esbuf[256]; const size_t ctr_name_len = strlen((char *)pCtr->name); const size_t esbuf_len = ctr_name_len < sizeof(esbuf) - 1 ? ctr_name_len : sizeof(esbuf) - 1; memcpy(esbuf, pCtr->name, esbuf_len); esbuf[esbuf_len] = '\0'; for (uchar *c = esbuf; *c; ++c) { if (*c == '.') *c = '!'; } CHKiRet(addCtrForReporting(values, esbuf, accumulatedValue(pCtr))); } else { CHKiRet(addCtrForReporting(values, pCtr->name, accumulatedValue(pCtr))); } resetResettableCtr(pCtr, bResetCtrs); } pthread_mutex_unlock(&pThis->mutCtr); locked = 0; CHKiRet(rsCStrAppendStr(pcstr, (const uchar *)json_object_to_json_string(root))); cstrFinalize(pcstr); *ppcstr = pcstr; pcstr = NULL; finalize_it: if (locked) { pthread_mutex_unlock(&pThis->mutCtr); } if (pcstr != NULL) { cstrDestruct(&pcstr); } if (root != NULL) { json_object_put(root); } if (values != NULL) { json_object_put(values); } RETiRet; } /* get all the object's countes together with object name as one line. */ static rsRetVal getStatsLine(statsobj_t *pThis, cstr_t **ppcstr, int8_t bResetCtrs) { cstr_t *pcstr; ctr_t *pCtr; DEFiRet; CHKiRet(cstrConstruct(&pcstr)); rsCStrAppendStr(pcstr, pThis->name); rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT(": "), 2); if (pThis->origin != NULL) { rsCStrAppendStrWithLen(pcstr, UCHAR_CONSTANT("origin="), 7); rsCStrAppendStr(pcstr, pThis->origin); cstrAppendChar(pcstr, ' '); } /* now add all counters to this line */ pthread_mutex_lock(&pThis->mutCtr); for (pCtr = pThis->ctrRoot; pCtr != NULL; pCtr = pCtr->next) { rsCStrAppendStr(pcstr, pCtr->name); cstrAppendChar(pcstr, '='); switch (pCtr->ctrType) { case ctrType_IntCtr: rsCStrAppendInt(pcstr, getIntCtrValue(pCtr->val.pIntCtr)); break; case ctrType_Int: rsCStrAppendInt(pcstr, getIntValue(pCtr->val.pInt)); break; default: // No action needed for other cases break; } cstrAppendChar(pcstr, ' '); resetResettableCtr(pCtr, bResetCtrs); } pthread_mutex_unlock(&pThis->mutCtr); cstrFinalize(pcstr); *ppcstr = pcstr; finalize_it: RETiRet; } /* this function obtains all sender stats. hlper to getAllStatsLines() * We need to keep this looked to avoid resizing of the hash table * (what could otherwise cause a segfault). */ static void getSenderStats(rsRetVal (*cb)(void *, const char *), void *usrptr, statsFmtType_t fmt, const int8_t bResetCtrs) { struct hashtable_itr *itr = NULL; struct sender_stats *stat; char fmtbuf[2048]; pthread_mutex_lock(&mutSenders); /* Iterator constructor only returns a valid iterator if * the hashtable is not empty */ if (hashtable_count(stats_senders) > 0) { itr = hashtable_iterator(stats_senders); do { stat = (struct sender_stats *)hashtable_iterator_value(itr); if (fmt == statsFmt_Legacy) { snprintf(fmtbuf, sizeof(fmtbuf), "_sender_stat: sender=%s messages=%" PRIu64, stat->sender, stat->nMsgs); } else { snprintf(fmtbuf, sizeof(fmtbuf), "{ \"name\":\"_sender_stat\", " "\"origin\":\"impstats\", " "\"sender\":\"%s\", \"messages\":%" PRIu64 "}", stat->sender, stat->nMsgs); } fmtbuf[sizeof(fmtbuf) - 1] = '\0'; cb(usrptr, fmtbuf); if (bResetCtrs) stat->nMsgs = 0; } while (hashtable_iterator_advance(itr)); } free(itr); pthread_mutex_unlock(&mutSenders); } /* * Prometheus values escaping reserves the U__ prefix. Ordinary legacy-safe * names remain unchanged; all other names use a reversible U__ encoding. */ static int prometheusLegacySafeName(const uchar *name) { const uchar *p; if (name == NULL || name[0] == '\0') return 0; if (!((name[0] >= 'a' && name[0] <= 'z') || (name[0] >= 'A' && name[0] <= 'Z') || name[0] == '_' || name[0] == ':')) { return 0; } if (name[0] == 'U' && strncmp((const char *)name, "U__", 3) == 0) return 0; for (p = name + 1; *p != '\0'; ++p) { if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_' || *p == ':')) { return 0; } } return 1; } static int decodeUtf8Codepoint(const uchar *input, size_t len, size_t *consumed, uint32_t *codepoint) { const uint32_t b0 = input[0]; if (b0 < 0x80) { *consumed = 1; *codepoint = b0; return 1; } if (b0 >= 0xc2 && b0 <= 0xdf && len >= 2 && (input[1] & 0xc0) == 0x80) { *consumed = 2; *codepoint = ((b0 & 0x1f) << 6) | (input[1] & 0x3f); return 1; } if (b0 >= 0xe0 && b0 <= 0xef && len >= 3 && (input[1] & 0xc0) == 0x80 && (input[2] & 0xc0) == 0x80) { *codepoint = ((b0 & 0x0f) << 12) | ((input[1] & 0x3f) << 6) | (input[2] & 0x3f); if (*codepoint >= 0x800 && !(*codepoint >= 0xd800 && *codepoint <= 0xdfff)) { *consumed = 3; return 1; } } if (b0 >= 0xf0 && b0 <= 0xf4 && len >= 4 && (input[1] & 0xc0) == 0x80 && (input[2] & 0xc0) == 0x80 && (input[3] & 0xc0) == 0x80) { *codepoint = ((b0 & 0x07) << 18) | ((input[1] & 0x3f) << 12) | ((input[2] & 0x3f) << 6) | (input[3] & 0x3f); if (*codepoint >= 0x10000 && *codepoint <= 0x10ffff) { *consumed = 4; return 1; } } *consumed = 1; *codepoint = b0; return 0; } static rsRetVal encodePrometheusMetricName(const uchar *raw_name, char **encoded_name) { const size_t raw_len = raw_name == NULL ? 0 : strlen((const char *)raw_name); size_t offset = 0; size_t out_len = 0; size_t remaining; int written; char *out = NULL; DEFiRet; if (encoded_name == NULL || raw_name == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); *encoded_name = NULL; if (prometheusLegacySafeName(raw_name)) { CHKmalloc(out = strdup((const char *)raw_name)); *encoded_name = out; out = NULL; FINALIZE; } if (raw_len > (SIZE_MAX - 4) / 10) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); CHKmalloc(out = malloc(raw_len * 10 + 4)); memcpy(out, "U__", 3); out_len = 3; while (offset < raw_len) { size_t consumed; uint32_t codepoint; const int valid = decodeUtf8Codepoint(raw_name + offset, raw_len - offset, &consumed, &codepoint); if (valid && ((codepoint >= 'a' && codepoint <= 'z') || (codepoint >= 'A' && codepoint <= 'Z') || (codepoint >= '0' && codepoint <= '9') || codepoint == ':')) { out[out_len++] = (char)codepoint; } else if (valid && codepoint == '_') { out[out_len++] = '_'; out[out_len++] = '_'; } else if (valid) { remaining = raw_len * 10 + 4 - out_len; written = snprintf(out + out_len, remaining, "_%X_", codepoint); if (written < 0 || (size_t)written >= remaining) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); out_len += (size_t)written; } else { remaining = raw_len * 10 + 4 - out_len; written = snprintf(out + out_len, remaining, "_x%02X_", codepoint); if (written < 0 || (size_t)written >= remaining) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); out_len += (size_t)written; } offset += consumed; } out[out_len] = '\0'; *encoded_name = out; out = NULL; finalize_it: free(out); RETiRet; } static rsRetVal escapePrometheusHelp(const char *input, const char **escaped, char **allocated) { size_t i; size_t len; size_t out_len = 0; char *out = NULL; DEFiRet; if (input == NULL || escaped == NULL || allocated == NULL) ABORT_FINALIZE(RS_RET_PARAM_ERROR); *escaped = input; *allocated = NULL; len = strlen(input); for (i = 0; i < len; ++i) { if (input[i] == '\\' || input[i] == '"' || input[i] == '\n') break; } if (i == len) FINALIZE; if (len > (SIZE_MAX - 1) / 2) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); CHKmalloc(out = malloc(len * 2 + 1)); for (i = 0; i < len; ++i) { if (input[i] == '\\' || input[i] == '"') { out[out_len++] = '\\'; out[out_len++] = input[i]; } else if (input[i] == '\n') { out[out_len++] = '\\'; out[out_len++] = 'n'; } else { out[out_len++] = input[i]; } } out[out_len] = '\0'; *escaped = out; *allocated = out; out = NULL; finalize_it: free(out); RETiRet; } /** * Helper: For a single statsobj_t (named o->name), iterate its counters * and emit Prometheus lines via cb. We generate, for each counter: * # HELP _ Generic help: " object, counter " * # TYPE _ counter * _ * * If bResetCtrs=TRUE and the counter has CTR_FLAG_RESETTABLE, zero it after reading. * * Note: by rsyslog stats subsystem design decision, read and write counters is racy * because we need the performance. It is OK that the counters in question are * not 100% precise. */ static ATTR_NO_SANITIZE_THREAD rsRetVal emitPrometheusForObject(statsobj_t *o, rsRetVal (*cb)(void *, const char *), void *usrptr, int8_t bResetCtrs) { ctr_t *pCtr; char *raw_name = NULL; char *metric_name = NULL; const char *escaped_origin; const char *escaped_object; const char *escaped_counter; char *escaped_origin_alloc = NULL; char *escaped_object_alloc = NULL; char *escaped_counter_alloc = NULL; char *line = NULL; rsRetVal iRet; uint64_t value; const char *objName = (const char *)o->name; const char *origin = o->origin ? (const char *)o->origin : ""; /* Iterate each counter in o->ctrRoot. Lock while walking the linked list. */ pthread_mutex_lock(&o->mutCtr); for (pCtr = o->ctrRoot; pCtr != NULL; pCtr = pCtr->next) { /* 1) Read the current accumulated value. Might be IntCtr or Int. */ switch (pCtr->ctrType) { case ctrType_IntCtr: value = getIntCtrValue(pCtr->val.pIntCtr); break; case ctrType_Int: value = (uint64_t)getIntValue(pCtr->val.pInt); break; default: value = 0; break; } /* 2) Optionally reset if requested and allowed. */ if ((bResetCtrs && (pCtr->flags & CTR_FLAG_RESETTABLE)) || (pCtr->flags & CTR_FLAG_MUST_RESET)) { switch (pCtr->ctrType) { case ctrType_IntCtr: resetIntCtrValue(pCtr->val.pIntCtr); break; case ctrType_Int: resetIntValue(pCtr->val.pInt); break; default: break; } } pthread_mutex_unlock(&o->mutCtr); /* 3) Build the metric name: "__total". */ if (asprintf(&raw_name, "%s_%s_total", objName, pCtr->name) < 0) { raw_name = NULL; return RS_RET_OUT_OF_MEMORY; } if (raw_name == NULL || encodePrometheusMetricName((const uchar *)raw_name, &metric_name) != RS_RET_OK || escapePrometheusHelp(origin, &escaped_origin, &escaped_origin_alloc) != RS_RET_OK || escapePrometheusHelp(objName, &escaped_object, &escaped_object_alloc) != RS_RET_OK || escapePrometheusHelp((const char *)pCtr->name, &escaped_counter, &escaped_counter_alloc) != RS_RET_OK) { free(raw_name); free(metric_name); free(escaped_origin_alloc); free(escaped_object_alloc); free(escaped_counter_alloc); return RS_RET_OUT_OF_MEMORY; } if (asprintf(&line, "# HELP %s rsyslog stats: origin=\"%s\" object=\"%s\", counter=\"%s\"\n" "# TYPE %s counter\n" "%s %llu\n", metric_name, escaped_origin, escaped_object, escaped_counter, metric_name, metric_name, (unsigned long long)value) < 0) { line = NULL; free(raw_name); free(metric_name); free(escaped_origin_alloc); free(escaped_object_alloc); free(escaped_counter_alloc); return RS_RET_OUT_OF_MEMORY; } iRet = cb(usrptr, line); free(raw_name); free(metric_name); free(escaped_origin_alloc); free(escaped_object_alloc); free(escaped_counter_alloc); free(line); raw_name = metric_name = escaped_origin_alloc = escaped_object_alloc = escaped_counter_alloc = line = NULL; if (iRet != RS_RET_OK) return iRet; /* Acquire the lock again before advancing to the next counter */ pthread_mutex_lock(&o->mutCtr); } pthread_mutex_unlock(&o->mutCtr); return RS_RET_OK; } static rsRetVal generatePrometheusStats(rsRetVal (*cb)(void *, const char *), void *usrptr, int8_t bResetCtrs) { statsobj_t *o; int listLocked = 0; DEFiRet; /* For each statsobj in our linked list, emit Prometheus lines. */ pthread_mutex_lock(&mutStats); listLocked = 1; for (o = objRoot; o != NULL; o = o->next) { CHKiRet(emitPrometheusForObject(o, cb, usrptr, bResetCtrs)); /* If the object has a read_notifier, call it now */ if (o->read_notifier != NULL) { o->read_notifier(o, o->read_notifier_ctx); } } pthread_mutex_unlock(&mutStats); listLocked = 0; /* Optionally, handle sender stats as additional metrics: * e.g. emit "rsyslog_sender_ " lines. * For simplicity, we skip this, or you can extend similarly. */ finalize_it: if (listLocked) { pthread_mutex_unlock(&mutStats); } RETiRet; } /* this function can be used to obtain all stats lines. In this case, * a callback must be provided. This module than iterates over all objects and * submits each stats line to the callback. The callback has two parameters: * the first one is a caller-provided void*, the second one the cstr_t with the * line. If the callback reports an error, processing is stopped. */ static rsRetVal getAllStatsLines(rsRetVal (*cb)(void *, const char *), void *const usrptr, statsFmtType_t fmt, const int8_t bResetCtrs) { statsobj_t *o; cstr_t *cstr = NULL; int listLocked = 0; DEFiRet; if (fmt == statsFmt_Prometheus) { CHKiRet(generatePrometheusStats(cb, usrptr, bResetCtrs)); FINALIZE; } pthread_mutex_lock(&mutStats); listLocked = 1; for (o = objRoot; o != NULL; o = o->next) { switch (fmt) { case statsFmt_Legacy: CHKiRet(getStatsLine(o, &cstr, bResetCtrs)); break; case statsFmt_CEE: case statsFmt_JSON: case statsFmt_JSON_ES: CHKiRet(getStatsLineCEE(o, &cstr, fmt, bResetCtrs)); break; case statsFmt_Prometheus: /* already handled above */ break; default: // No action needed for other cases break; } CHKiRet(cb(usrptr, (const char *)cstrGetSzStrNoNULL(cstr))); rsCStrDestruct(&cstr); if (o->read_notifier != NULL) { o->read_notifier(o, o->read_notifier_ctx); } } pthread_mutex_unlock(&mutStats); listLocked = 0; getSenderStats(cb, usrptr, fmt, bResetCtrs); finalize_it: if (listLocked) { pthread_mutex_unlock(&mutStats); } if (cstr != NULL) { rsCStrDestruct(&cstr); } RETiRet; } /** * getAllCounters() - Native counter iteration API * * Iterates through all statsobj instances and their counters, invoking the callback * with raw counter values. This eliminates text serialization/parsing overhead. * * @param cb Callback function invoked for each counter * @param ctx User context passed to callback * @return RS_RET_OK on success, error code on failure */ static rsRetVal getAllCounters(statsobj_counter_cb_t cb, void *ctx) { DEFiRet; statsobj_t *o; ctr_t *ctr; int listLocked = 0; if (cb == NULL) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } /* Iterate through all statsobj instances */ pthread_mutex_lock(&mutStats); listLocked = 1; for (o = objRoot; o != NULL; o = o->next) { /* Iterate through all counters in this object */ pthread_mutex_lock(&o->mutCtr); for (ctr = o->ctrRoot; ctr != NULL; ctr = ctr->next) { uint64_t value; /* Read counter value based on type */ switch (ctr->ctrType) { case ctrType_IntCtr: value = getIntCtrValue(ctr->val.pIntCtr); break; case ctrType_Int: /* Plain int - read without lock. This matches GetAllStatsLines() * behavior. Value may be stale but acceptable for monitoring. * Most ctrType_Int counters are gauges (queue size, open files) * protected by application-level mutexes. */ value = (uint64_t)getIntValue(ctr->val.pInt); break; default: value = 0; break; } /* Invoke callback with counter metadata and value. * Keep mutCtr locked to prevent list modification during iteration. * Callback must not call back into statsobj or deadlock may occur. */ rsRetVal localRet = cb(ctx, o->name, o->origin, ctr->name, ctr->ctrType, value, ctr->flags); if (localRet != RS_RET_OK) { pthread_mutex_unlock(&o->mutCtr); ABORT_FINALIZE(localRet); } } pthread_mutex_unlock(&o->mutCtr); /* Call read notifier after counters are read (e.g., for percentile stats) */ if (o->read_notifier != NULL) { o->read_notifier(o, o->read_notifier_ctx); } } pthread_mutex_unlock(&mutStats); listLocked = 0; finalize_it: if (listLocked) { pthread_mutex_unlock(&mutStats); } RETiRet; } /* Enable statistics gathering. currently there is no function to disable it * again, as this is right now not needed. */ static rsRetVal enableStats(void) { PREFER_STORE_1_TO_INT(&GatherStats); return RS_RET_OK; } rsRetVal statsRecordSender(const uchar *sender, unsigned nMsgs, time_t lastSeen) { struct sender_stats *stat; int mustUnlock = 0; DEFiRet; if (stats_senders == NULL) FINALIZE; /* unlikely: we could not init our hash table */ pthread_mutex_lock(&mutSenders); mustUnlock = 1; stat = hashtable_search(stats_senders, (void *)sender); if (stat == NULL) { DBGPRINTF("statsRecordSender: sender '%s' not found, adding\n", sender); CHKmalloc(stat = calloc(1, sizeof(struct sender_stats))); stat->sender = (const uchar *)strdup((const char *)sender); stat->nMsgs = 0; if (runConf->globals.reportNewSenders) { LogMsg(0, RS_RET_SENDER_APPEARED, LOG_INFO, "new sender '%s'", stat->sender); } if (hashtable_insert(stats_senders, (void *)stat->sender, (void *)stat) == 0) { LogError(errno, RS_RET_INTERNAL_ERROR, "error inserting sender '%s' into sender " "hash table", sender); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } } stat->nMsgs += nMsgs; stat->lastSeen = lastSeen; DBGPRINTF("DDDDD: statsRecordSender: '%s', nmsgs %u [%llu], lastSeen %llu\n", sender, nMsgs, (long long unsigned)stat->nMsgs, (long long unsigned)lastSeen); finalize_it: if (mustUnlock) pthread_mutex_unlock(&mutSenders); RETiRet; } static ctr_t *unlinkAllCounters(statsobj_t *pThis) { ctr_t *ctr; pthread_mutex_lock(&pThis->mutCtr); ctr = pThis->ctrRoot; pThis->ctrLast = NULL; pThis->ctrRoot = NULL; pthread_mutex_unlock(&pThis->mutCtr); return ctr; } static void destructUnlinkedCounters(ctr_t *ctr) { ctr_t *ctrToDel; while (ctr != NULL) { ctrToDel = ctr; ctr = ctr->next; destructUnlinkedCounter(ctrToDel); } } /* check if a sender has not sent info to us for an extended period * of time. */ void checkGoneAwaySenders(const time_t tCurr) { struct hashtable_itr *itr = NULL; struct sender_stats *stat; const time_t rqdLast = tCurr - runConf->globals.senderStatsTimeout; struct tm tm; pthread_mutex_lock(&mutSenders); /* Iterator constructor only returns a valid iterator if * the hashtable is not empty */ if (hashtable_count(stats_senders) > 0) { itr = hashtable_iterator(stats_senders); do { stat = (struct sender_stats *)hashtable_iterator_value(itr); if (stat->lastSeen < rqdLast) { if (runConf->globals.reportGoneAwaySenders) { localtime_r(&stat->lastSeen, &tm); LogMsg(0, RS_RET_SENDER_GONE_AWAY, LOG_WARNING, "removing sender '%s' from connection " "table, last seen at " "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", stat->sender, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } hashtable_remove(stats_senders, (void *)stat->sender); } } while (hashtable_iterator_advance(itr)); } pthread_mutex_unlock(&mutSenders); free(itr); } /* destructor for the statsobj object */ BEGINobjDestruct(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(statsobj); iRet = removeFromObjList(pThis); /* Do not enter ENDobjDestruct on unlink failure: that macro frees pThis * and would leave objRoot/objLast pointing at released memory. There is no * safe recovery path once we cannot lock the global list for destruction. */ if (iRet != RS_RET_OK) abort(); /* destruct counters */ destructUnlinkedCounters(unlinkAllCounters(pThis)); pthread_mutex_destroy(&pThis->mutCtr); free(pThis->name); free(pThis->origin); free(pThis->reporting_ns); ENDobjDestruct(statsobj) /* debugprint for the statsobj object */ BEGINobjDebugPrint(statsobj) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDebugPrint(statsobj); dbgoprint((obj_t *)pThis, "statsobj object, currently no state info available\n"); ENDobjDebugPrint(statsobj) /* queryInterface function */ BEGINobjQueryInterface(statsobj) CODESTARTobjQueryInterface(statsobj); if (pIf->ifVersion != statsobjCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = statsobjConstruct; pIf->ConstructFinalize = statsobjConstructFinalize; pIf->Destruct = statsobjDestruct; pIf->DebugPrint = statsobjDebugPrint; pIf->SetName = setName; pIf->SetOrigin = setOrigin; pIf->SetReadNotifier = setReadNotifier; pIf->SetReportingNamespace = setReportingNamespace; pIf->SetStatsObjFlags = setStatsObjFlags; pIf->GetAllStatsLines = getAllStatsLines; pIf->GetAllCounters = getAllCounters; pIf->EncodePrometheusMetricName = encodePrometheusMetricName; pIf->AddCounter = addCounter; pIf->AddManagedCounter = addManagedCounter; pIf->AddPreCreatedCtr = addPreCreatedCounter; pIf->DestructCounter = destructCounter; pIf->DestructUnlinkedCounter = destructUnlinkedCounter; pIf->UnlinkAllCounters = unlinkAllCounters; pIf->EnableStats = enableStats; finalize_it: ENDobjQueryInterface(statsobj) /* Initialize the statsobj class. Must be called as the very first method * before anything else is called inside this class. */ BEGINAbstractObjClassInit(statsobj, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, statsobjDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, statsobjConstructFinalize); /* init other data items */ CHKiConcCtrl(pthread_mutex_init(&mutStats, NULL)); CHKiConcCtrl(pthread_mutex_init(&mutSenders, NULL)); if ((stats_senders = create_hashtable(100, hash_from_string, key_equals_string, NULL)) == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table " "for sender table. Sender statistics and warnings are disabled."); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } ENDObjClassInit(statsobj) /* Exit the class. */ BEGINObjClassExit(statsobj, OBJ_IS_CORE_MODULE) /* class, version */ /* release objects we no longer need */ pthread_mutex_destroy(&mutStats); pthread_mutex_destroy(&mutSenders); hashtable_destroy(stats_senders, 1); ENDObjClassExit(statsobj) rsyslog-8.2608.0/runtime/PaxHeaders/stringbuf.h0000644000000000000000000000013115216464436016410 xustar0029 mtime=1782212894.04026641 30 atime=1787067616.806414817 30 ctime=1787067794.323723732 rsyslog-8.2608.0/runtime/stringbuf.h0000664000175000017500000001636215216464436016065 0ustar00rgerrger/* stringbuf.h * The counted string object * * \author Rainer Gerhards * \date 2005-09-07 * Initial version begun. * * Copyright 2005-2016 Adiscon GmbH. All Rights Reserved. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _STRINGBUF_H_INCLUDED__ #define _STRINGBUF_H_INCLUDED__ 1 #include #include /** * The dynamic string buffer object. * * Contract notes: * - The buffer stores counted bytes and may keep `pBuf == NULL` for empty * strings. * - Constructors and mutating helpers do not guarantee a trailing NUL. * Callers must invoke `cstrFinalize()` before using any API that exposes the * buffer as a classic C string. * - `cstrFinalize()` writes the trailing NUL but is not a hard state change in * release builds; appending after finalize remains invalid API usage even if * some call paths appear to tolerate it. */ typedef struct cstr_s { #ifndef NDEBUG rsObjID OID; /**< object ID */ sbool isFinalized; #endif uchar *pBuf; /**< pointer to the string buffer, may be NULL if string is empty */ size_t iBufSize; /**< current maximum size of the string buffer */ size_t iStrLen; /**< length of the string in characters. */ } cstr_t; typedef struct rs_cstr_part_s { const uchar *ptr; size_t len; } rs_cstr_part_t; /** * Construct an empty counted string. * * The resulting object is not finalized. Call `cstrFinalize()` before passing * it to any consumer that expects a NUL-terminated string view. */ rsRetVal cstrConstruct(cstr_t **ppThis); #define rsCStrConstruct(x) cstrConstruct((x)) rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str); rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, const uchar *sz); rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, const cstr_t *pFrom); rsRetVal rsCStrConstructFromszStrf(cstr_t **ppThis, const char *fmt, ...) __attribute__((format(printf, 2, 3))); /** * Destruct the string buffer object. */ void rsCStrDestruct(cstr_t **ppThis); #define cstrDestruct(x) rsCStrDestruct((x)) /* Append a character to the current string object. This may only be done until * cstrFinalize() is called. * rgerhards, 2009-06-16 */ rsRetVal cstrAppendChar(cstr_t *pThis, const uchar c); /* Finalize the string object. * * This writes the trailing NUL expected by `cstrGetSzStrNoNULL()`, regex * matching, and other C-string consumers. Call it after the last mutation and * before any read that depends on classic NUL-terminated semantics. * rgerhards, 2009-06-16 */ #ifdef NDEBUG #define cstrFinalize(pThis) \ { \ if ((pThis)->iStrLen > 0) (pThis)->pBuf[(pThis)->iStrLen] = '\0'; /* space is always reserved for this */ \ } #else #define cstrFinalize(pThis) \ { \ if ((pThis)->iStrLen > 0) (pThis)->pBuf[(pThis)->iStrLen] = '\0'; /* space is always reserved for this */ \ (pThis)->isFinalized = 1; \ } #endif /** * Truncate "n" number of characters from the end of the * string. The buffer remains unchanged, just the * string length is manipulated. This is for performance * reasons. */ rsRetVal rsCStrTruncate(cstr_t *pThis, size_t nTrunc); void cstrTrimTrailingWhiteSpace(cstr_t *pThis); /** * Append a string to the buffer. For performance reasons, * use rsCStrAppenStrWithLen() if you know the length. * * \param psz pointer to string to be appended. Must not be NULL. * * The object remains non-finalized after this call. */ rsRetVal rsCStrAppendStr(cstr_t *pThis, const uchar *psz); /** * Append a string to the buffer. * * \param psz pointer to string to be appended. Must not be NULL. * \param iStrLen the length of the string pointed to by psz * * The object remains non-finalized after this call. */ rsRetVal rsCStrAppendStrWithLen(cstr_t *pThis, const uchar *psz, size_t iStrLen); rsRetVal rsCStrAppendParts(cstr_t *pThis, const rs_cstr_part_t *parts, size_t count); /** * Append a printf-style formated string to the buffer. * * \param fmt pointer to the format string (see man 3 printf for details). Must not be NULL. * * The object remains non-finalized after this call. */ rsRetVal rsCStrAppendStrf(cstr_t *pThis, const char *fmt, ...) __attribute__((format(printf, 2, 3))); /** * Append an integer to the string. No special formatting is * done. */ rsRetVal rsCStrAppendInt(cstr_t *pThis, long i); rsRetVal strExit(void); /* Return a borrowed NUL-terminated view of the internal buffer. * * The object must already be finalized. The returned pointer is owned by the * cstr object and remains valid only until the next mutation or destruction. * Empty strings are returned as `""`, never as NULL. */ uchar *cstrGetSzStrNoNULL(cstr_t *pThis); #define rsCStrGetSzStrNoNULL(x) cstrGetSzStrNoNULL(x) /* Replace the current contents from a classic NUL-terminated string. * * Passing `NULL` resets the object to an empty string and may leave * `pBuf == NULL`. The setter does not finalize the object. */ rsRetVal rsCStrSetSzStr(cstr_t *pThis, uchar *pszNew); int rsCStrCStrCmp(cstr_t *pCS1, cstr_t *pCS2); int rsCStrSzStrCmp(cstr_t *pCS1, uchar *psz, size_t iLenSz); int rsCStrOffsetSzStrCmp(cstr_t *pCS1, size_t iOffset, uchar *psz, size_t iLenSz); int rsCStrLocateSzStr(cstr_t *pCStr, uchar *sz); int rsCStrLocateInSzStr(cstr_t *pThis, uchar *sz); int rsCStrSzStrStartsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz); int rsCStrSzStrEndsWithCStr(cstr_t *pCS1, uchar *psz, size_t iLenSz); rsRetVal rsCStrSzStrMatchRegex(cstr_t *pCS1, uchar *psz, int iType, void *cache); void rsCStrRegexDestruct(void *rc); /* Convert to an owned C string and destroy the counted-string object. * * Ownership of the returned buffer transfers to the caller, which must * `free()` it unless `bRetNULL == 1` and the string was empty. `*ppThis` is * always cleared on return. */ rsRetVal cstrConvSzStrAndDestruct(cstr_t **pThis, uchar **ppSz, int bRetNULL); rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend); /* now come inline-like functions */ #ifdef NDEBUG #define cstrLen(x) ((size_t)((x)->iStrLen)) #else size_t cstrLen(cstr_t *pThis); #endif #define rsCStrLen(s) cstrLen((s)) #define rsCStrGetBufBeg(x) ((x)->pBuf) rsRetVal strInit(void); #endif /* single include */ rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_codec.h0000644000000000000000000000013215241075234017164 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.407725297 rsyslog-8.2608.0/runtime/segdisk_codec.h0000664000175000017500000000063215241075234016631 0ustar00rgerrger/* Queue-private binary message codec for the segmented disk store. */ #ifndef INCLUDED_SEGDISK_CODEC_H #define INCLUDED_SEGDISK_CODEC_H #include #include #include "rsyslog.h" #include "msg.h" #include "segdisk_format.h" rsRetVal segdiskCodecEncode(smsg_t *msg, unsigned char **buf, size_t *len); rsRetVal segdiskCodecDecode(const unsigned char *buf, size_t len, smsg_t **msg); #endif rsyslog-8.2608.0/runtime/PaxHeaders/net_ossl.h0000644000000000000000000000013215216464436016234 xustar0030 mtime=1782212894.034266313 30 atime=1787067618.293442543 30 ctime=1787067794.556728074 rsyslog-8.2608.0/runtime/net_ossl.h0000664000175000017500000001702315216464436015703 0ustar00rgerrger/* Definitions for generic OpenSSL include stuff. * * Copyright 2023-2026 Andre Lorbach and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_NET_OSSL_H #define INCLUDED_NET_OSSL_H /* Needed OpenSSL Includes */ #ifdef ENABLE_WOLFSSL #include #include #include #include #include #include #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) #include #endif #ifndef OPENSSL_NO_ENGINE #include #endif #else #include #include #include #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) #include #endif #ifndef OPENSSL_NO_ENGINE #include #endif #include #include #endif /* Internal OpenSSL defined ENUMS */ typedef enum { OSSL_AUTH_CERTNAME = 0, OSSL_AUTH_CERTFINGERPRINT = 1, OSSL_AUTH_CERTVALID = 2, OSSL_AUTH_CERTANON = 3 } AuthMode; typedef enum { OSSL_EXPIRED_PERMIT = 0, OSSL_EXPIRED_DENY = 1, OSSL_EXPIRED_WARN = 2 } PermitExpiredCerts; typedef enum { osslServer = 0, /**< Server SSL Object */ osslClient = 1 /**< Client SSL Object */ } osslSslState_t; /* the net_ossl object */ struct net_ossl_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ /* Config Cert vars */ const uchar *pszCAFile; const uchar *pszCRLFile; const uchar *pszExtraCAFiles; const uchar *pszKeyFile; const uchar *pszCertFile; AuthMode authMode; permittedPeers_t *pPermPeers; /* permitted peers */ int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is * set to 1 and changed to 0 after the first report. It is changed back to 1 after * one successful authentication. */ int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not check CN) */ int bTlsRevocationCheck; /* Open SSL objects */ BIO *bio; /* OpenSSL main BIO obj */ int ctx_is_copy; SSL_CTX *ctx; /* credentials, ciphers, ... */ SSL *ssl; /* OpenSSL main SSL obj */ osslSslState_t sslState; /**< what must we retry? */ }; /* interface */ BEGINinterface(net_ossl) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(net_ossl_t **ppThis); rsRetVal (*Destruct)(net_ossl_t **ppThis); rsRetVal (*osslCtxInit)(net_ossl_t *pThis, const SSL_METHOD *method); #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(ENABLE_WOLFSSL) rsRetVal (*osslCtxInitCookie)(net_ossl_t *pThis); #endif // OPENSSL_VERSION_NUMBER >= 0x10100000L rsRetVal (*osslInitEngine)(net_ossl_t *pThis); // OpenSSL Helper function exports rsRetVal (*osslChkpeername)(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP); rsRetVal (*osslPeerfingerprint)(net_ossl_t *pThis, X509 *certpeer, uchar *fromHostIP); X509 *(*osslGetpeercert)(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP); rsRetVal (*osslChkpeercertvalidity)(net_ossl_t *pThis, SSL *ssl, uchar *fromHostIP); #if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)) || defined(ENABLE_WOLFSSL) rsRetVal (*osslApplyTlscgfcmd)(net_ossl_t *pThis, uchar *tlscfgcmd); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L void (*osslSetBioCallback)(BIO *conn); void (*osslSetCtxVerifyCallback)(SSL_CTX *pCtx, int flags); void (*osslSetSslVerifyCallback)(SSL *pSsl, int flags); void (*osslLastOpenSSLErrorMsg)(uchar *fromHost, const int ret, SSL *ssl, int severity, const char *pszCallSource, const char *pszOsslApi); ENDinterface(net_ossl) #define net_osslCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ // ------------------------------------------------------ /* OpenSSL API differences */ #ifdef ENABLE_WOLFSSL #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT) #else #if OPENSSL_VERSION_NUMBER >= 0x10100000L #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT) #define RSYSLOG_BIO_method_name(SSLBIO) BIO_method_name(SSLBIO) #define RSYSLOG_BIO_number_read(SSLBIO) BIO_number_read(SSLBIO) #define RSYSLOG_BIO_number_written(SSLBIO) BIO_number_written(SSLBIO) #else #define RSYSLOG_X509_NAME_oneline(X509CERT) (X509CERT != NULL ? X509CERT->cert_info->subject : NULL) #define RSYSLOG_BIO_method_name(SSLBIO) SSLBIO->method->name #define RSYSLOG_BIO_number_read(SSLBIO) SSLBIO->num #define RSYSLOG_BIO_number_written(SSLBIO) SSLBIO->num #endif #endif /*-----------------------------------------------------------------------------*/ /* OpenSSL Global Helper functions prototypes */ #define MUTEX_TYPE pthread_mutex_t #define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) #define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) #define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) #define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) #define THREAD_ID pthread_self() /* This array will store all of the mutexes available to OpenSSL. */ struct CRYPTO_dynlock_value { MUTEX_TYPE mutex; }; void dyn_destroy_function(struct CRYPTO_dynlock_value *l, __attribute__((unused)) const char *file, __attribute__((unused)) int line); void dyn_lock_function(int mode, struct CRYPTO_dynlock_value *l, __attribute__((unused)) const char *file, __attribute__((unused)) int line); struct CRYPTO_dynlock_value *dyn_create_function(__attribute__((unused)) const char *file, __attribute__((unused)) int line); unsigned long id_function(void); void locking_function(int mode, int n, __attribute__((unused)) const char *file, __attribute__((unused)) int line); int opensslh_THREAD_setup(void); int opensslh_THREAD_cleanup(void); void osslGlblInit(void); void osslGlblExit(void); /*-----------------------------------------------------------------------------*/ /* prototypes */ PROTOTYPEObjFull(net_ossl); /* the name of our library binary */ // #define LM_NET_OSSL_FILENAME "lmnet_ossl" #define LM_NET_OSSL_FILENAME "lmnsd_ossl" #endif /* #ifndef INCLUDED_NET_OSSL_H */ rsyslog-8.2608.0/runtime/PaxHeaders/libgcry.c0000644000000000000000000000013015216464436016032 xustar0028 mtime=1782212894.0272662 30 atime=1783339707.613802663 30 ctime=1787067794.219721794 rsyslog-8.2608.0/runtime/libgcry.c0000664000175000017500000005050015216464436015500 0ustar00rgerrger/* gcry.c - rsyslog's libgcrypt based crypto provider * * Copyright 2013-2018 Adiscon GmbH. * * We need to store some additional information in support of encryption. * For this, we create a side-file, which is named like the actual log * file, but with the suffix ".encinfo" appended. It contains the following * records: * IV: The initial vector used at block start. Also indicates start * start of block. * END: The end offset of the block, as uint64_t in decimal notation. * This is used during encryption to know when the current * encryption block ends. * For the current implementation, there must always be an IV record * followed by an END record. Each records is LF-terminated. Record * types can simply be extended in the future by specifying new * types (like "IV") before the colon. * To identify a file as rsyslog encryption info file, it must start with * the line "FILETYPE:rsyslog-enrcyption-info" * There are some size constraints: the recordtype must be 31 bytes at * most and the actual value (between : and LF) must be 1023 bytes at most. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #if HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "debug.h" #include "libgcry.h" #include "libcry_common.h" #define READBUF_SIZE 4096 /* size of the read buffer */ static rsRetVal rsgcryBlkBegin(gcryfile gf); int rsgcryAlgoname2Algo(char *const __restrict__ algoname) { if (!strcmp((char *)algoname, "3DES")) return GCRY_CIPHER_3DES; if (!strcmp((char *)algoname, "CAST5")) return GCRY_CIPHER_CAST5; if (!strcmp((char *)algoname, "BLOWFISH")) return GCRY_CIPHER_BLOWFISH; if (!strcmp((char *)algoname, "AES128")) return GCRY_CIPHER_AES128; if (!strcmp((char *)algoname, "AES192")) return GCRY_CIPHER_AES192; if (!strcmp((char *)algoname, "AES256")) return GCRY_CIPHER_AES256; if (!strcmp((char *)algoname, "TWOFISH")) return GCRY_CIPHER_TWOFISH; if (!strcmp((char *)algoname, "TWOFISH128")) return GCRY_CIPHER_TWOFISH128; if (!strcmp((char *)algoname, "ARCFOUR")) return GCRY_CIPHER_ARCFOUR; if (!strcmp((char *)algoname, "DES")) return GCRY_CIPHER_DES; if (!strcmp((char *)algoname, "SERPENT128")) return GCRY_CIPHER_SERPENT128; if (!strcmp((char *)algoname, "SERPENT192")) return GCRY_CIPHER_SERPENT192; if (!strcmp((char *)algoname, "SERPENT256")) return GCRY_CIPHER_SERPENT256; if (!strcmp((char *)algoname, "RFC2268_40")) return GCRY_CIPHER_RFC2268_40; if (!strcmp((char *)algoname, "SEED")) return GCRY_CIPHER_SEED; if (!strcmp((char *)algoname, "CAMELLIA128")) return GCRY_CIPHER_CAMELLIA128; if (!strcmp((char *)algoname, "CAMELLIA192")) return GCRY_CIPHER_CAMELLIA192; if (!strcmp((char *)algoname, "CAMELLIA256")) return GCRY_CIPHER_CAMELLIA256; return GCRY_CIPHER_NONE; } int rsgcryModename2Mode(char *const __restrict__ modename) { if (!strcmp((char *)modename, "ECB")) return GCRY_CIPHER_MODE_ECB; if (!strcmp((char *)modename, "CFB")) return GCRY_CIPHER_MODE_CFB; if (!strcmp((char *)modename, "CBC")) return GCRY_CIPHER_MODE_CBC; if (!strcmp((char *)modename, "STREAM")) return GCRY_CIPHER_MODE_STREAM; if (!strcmp((char *)modename, "OFB")) return GCRY_CIPHER_MODE_OFB; if (!strcmp((char *)modename, "CTR")) return GCRY_CIPHER_MODE_CTR; #ifdef GCRY_CIPHER_MODE_AESWRAP if (!strcmp((char *)modename, "AESWRAP")) return GCRY_CIPHER_MODE_AESWRAP; #endif return GCRY_CIPHER_MODE_NONE; } static rsRetVal eiWriteRec(gcryfile gf, const char *recHdr, size_t lenRecHdr, const char *buf, size_t lenBuf) { struct iovec iov[3]; ssize_t nwritten, towrite; DEFiRet; iov[0].iov_base = (void *)recHdr; iov[0].iov_len = lenRecHdr; iov[1].iov_base = (void *)buf; iov[1].iov_len = lenBuf; iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1; towrite = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len; nwritten = writev(gf->fd, iov, sizeof(iov) / sizeof(struct iovec)); if (nwritten != towrite) { DBGPRINTF( "eiWrite%s: error writing file, towrite %d, " "nwritten %d\n", recHdr, (int)towrite, (int)nwritten); ABORT_FINALIZE(RS_RET_EI_WR_ERR); } DBGPRINTF("encryption info file %s: written %s, len %d\n", recHdr, gf->eiName, (int)nwritten); finalize_it: RETiRet; } static rsRetVal eiOpenRead(gcryfile gf) { DEFiRet; gf->fd = open((char *)gf->eiName, O_RDONLY | O_NOCTTY | O_CLOEXEC); if (gf->fd == -1) { ABORT_FINALIZE(errno == ENOENT ? RS_RET_EI_NO_EXISTS : RS_RET_EI_OPN_ERR); } finalize_it: RETiRet; } static rsRetVal eiRead(gcryfile gf) { ssize_t nRead; DEFiRet; if (gf->readBuf == NULL) { CHKmalloc(gf->readBuf = malloc(READBUF_SIZE)); } nRead = read(gf->fd, gf->readBuf, READBUF_SIZE); if (nRead <= 0) { ABORT_FINALIZE(RS_RET_ERR); } gf->readBufMaxIdx = (int16_t)nRead; gf->readBufIdx = 0; finalize_it: RETiRet; } /* returns EOF on any kind of error */ static int eiReadChar(gcryfile gf) { int c; if (gf->readBufIdx >= gf->readBufMaxIdx) { if (eiRead(gf) != RS_RET_OK) { c = EOF; goto finalize_it; } } c = gf->readBuf[gf->readBufIdx++]; finalize_it: return c; } static rsRetVal eiCheckFiletype(gcryfile gf) { char hdrBuf[128]; size_t toRead, didRead; sbool bNeedClose = 0; DEFiRet; if (gf->fd == -1) { CHKiRet(eiOpenRead(gf)); assert(gf->fd != -1); /* cannot happen after successful return */ bNeedClose = 1; } if (Debug) memset(hdrBuf, 0, sizeof(hdrBuf)); /* for dbgprintf below! */ toRead = sizeof("FILETYPE:") - 1 + sizeof(RSGCRY_FILETYPE_NAME) - 1 + 1; didRead = read(gf->fd, hdrBuf, toRead); if (bNeedClose) { close(gf->fd); gf->fd = -1; } DBGPRINTF("eiCheckFiletype read %zd bytes: '%s'\n", didRead, hdrBuf); if (didRead != toRead || strncmp(hdrBuf, "FILETYPE:" RSGCRY_FILETYPE_NAME "\n", toRead)) iRet = RS_RET_EI_INVLD_FILE; finalize_it: RETiRet; } /* rectype/value must be EIF_MAX_*_LEN+1 long! * returns 0 on success or something else on error/EOF */ static rsRetVal eiGetRecord(gcryfile gf, char *rectype, char *value) { unsigned short i, j; int c; DEFiRet; c = eiReadChar(gf); if (c == EOF) { ABORT_FINALIZE(RS_RET_NO_DATA); } for (i = 0; i < EIF_MAX_RECTYPE_LEN; ++i) { if (c == ':' || c == EOF) break; rectype[i] = c; c = eiReadChar(gf); } if (c != ':') { ABORT_FINALIZE(RS_RET_ERR); } rectype[i] = '\0'; j = 0; for (++i; i < EIF_MAX_VALUE_LEN; ++i, ++j) { c = eiReadChar(gf); if (c == '\n' || c == EOF) break; value[j] = c; } if (c != '\n') { ABORT_FINALIZE(RS_RET_ERR); } value[j] = '\0'; finalize_it: RETiRet; } static rsRetVal eiGetIV(gcryfile gf, uchar *iv, size_t leniv) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; size_t valueLen; unsigned short i, j; unsigned char nibble; DEFiRet; CHKiRet(eiGetRecord(gf, rectype, value)); const char *const cmp_IV = "IV"; // work-around for static analyzer if (strcmp(rectype, cmp_IV)) { DBGPRINTF( "no IV record found when expected, record type " "seen is '%s'\n", rectype); ABORT_FINALIZE(RS_RET_ERR); } valueLen = strlen(value); if (valueLen / 2 != leniv) { DBGPRINTF("length of IV is %zd, expected %zd\n", valueLen / 2, leniv); ABORT_FINALIZE(RS_RET_ERR); } for (i = j = 0; i < valueLen; ++i) { if (value[i] >= '0' && value[i] <= '9') nibble = value[i] - '0'; else if (value[i] >= 'a' && value[i] <= 'f') nibble = value[i] - 'a' + 10; else { DBGPRINTF("invalid IV '%s'\n", value); ABORT_FINALIZE(RS_RET_ERR); } if (i % 2 == 0) iv[j] = nibble << 4; else iv[j++] |= nibble; } finalize_it: RETiRet; } static rsRetVal eiGetEND(gcryfile gf, off64_t *offs) { char rectype[EIF_MAX_RECTYPE_LEN + 1]; char value[EIF_MAX_VALUE_LEN + 1]; DEFiRet; CHKiRet(eiGetRecord(gf, rectype, value)); const char *const const_END = "END"; // clang static analyzer work-around if (strcmp(rectype, const_END)) { DBGPRINTF( "no END record found when expected, record type " "seen is '%s'\n", rectype); ABORT_FINALIZE(RS_RET_ERR); } *offs = atoll(value); finalize_it: RETiRet; } static rsRetVal eiOpenAppend(gcryfile gf) { rsRetVal localRet; DEFiRet; localRet = eiCheckFiletype(gf); if (localRet == RS_RET_OK) { gf->fd = open((char *)gf->eiName, O_WRONLY | O_APPEND | O_NOCTTY | O_CLOEXEC, 0600); if (gf->fd == -1) { ABORT_FINALIZE(RS_RET_EI_OPN_ERR); } } else if (localRet == RS_RET_EI_NO_EXISTS) { /* looks like we need to create a new file */ gf->fd = open((char *)gf->eiName, O_WRONLY | O_CREAT | O_NOCTTY | O_CLOEXEC, 0600); if (gf->fd == -1) { ABORT_FINALIZE(RS_RET_EI_OPN_ERR); } CHKiRet(eiWriteRec(gf, "FILETYPE:", 9, RSGCRY_FILETYPE_NAME, sizeof(RSGCRY_FILETYPE_NAME) - 1)); } else { gf->fd = -1; ABORT_FINALIZE(localRet); } DBGPRINTF("encryption info file %s: opened as #%d\n", gf->eiName, gf->fd); finalize_it: RETiRet; } static rsRetVal __attribute__((nonnull(2))) eiWriteIV(gcryfile gf, const uchar *const iv) { static const char hexchars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; unsigned iSrc, iDst; char hex[4096]; DEFiRet; if (gf->blkLength > sizeof(hex) / 2) { DBGPRINTF( "eiWriteIV: crypto block len way too large, aborting " "write"); ABORT_FINALIZE(RS_RET_ERR); } for (iSrc = iDst = 0; iSrc < gf->blkLength; ++iSrc) { hex[iDst++] = hexchars[iv[iSrc] >> 4]; hex[iDst++] = hexchars[iv[iSrc] & 0x0f]; } iRet = eiWriteRec(gf, "IV:", 3, hex, gf->blkLength * 2); finalize_it: RETiRet; } /* we do not return an error state, as we MUST close the file, * no matter what happens. */ static void eiClose(gcryfile gf, off64_t offsLogfile) { char offs[21]; size_t len; if (gf->fd == -1) return; if (gf->openMode == 'w') { /* 2^64 is 20 digits, so the snprintf buffer is large enough */ len = snprintf(offs, sizeof(offs), "%lld", (long long)offsLogfile); eiWriteRec(gf, "END:", 4, offs, len); } gcry_cipher_close(gf->chd); free(gf->readBuf); close(gf->fd); gf->fd = -1; DBGPRINTF("encryption info file %s: closed\n", gf->eiName); } /* this returns the number of bytes left inside the block or -1, if the block * size is unbounded. The function automatically handles end-of-block and begins * to read the next block in this case. */ rsRetVal gcryfileGetBytesLeftInBlock(gcryfile gf, ssize_t *left) { DEFiRet; if (gf->bytesToBlkEnd == 0) { DBGPRINTF("libgcry: end of current crypto block\n"); gcry_cipher_close(gf->chd); CHKiRet(rsgcryBlkBegin(gf)); } *left = gf->bytesToBlkEnd; finalize_it: RETiRet; } /* this is a special functon for use by the rsyslog disk queue subsystem. It * needs to have the capability to delete state when a queue file is rolled * over. This simply generates the file name and deletes it. It must take care * of "all" state files, which currently happens to be a single one. */ rsRetVal gcryfileDeleteState(uchar *logfn) { char fn[MAXFNAME + 1]; DEFiRet; snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX); fn[MAXFNAME] = '\0'; /* be on save side */ DBGPRINTF("crypto provider deletes state file '%s' on request\n", fn); unlink(fn); RETiRet; } static rsRetVal gcryfileConstruct(gcryctx ctx, gcryfile *pgf, uchar *logfn) { char fn[MAXFNAME + 1]; gcryfile gf; DEFiRet; CHKmalloc(gf = calloc(1, sizeof(struct gcryfile_s))); gf->ctx = ctx; gf->fd = -1; snprintf(fn, sizeof(fn), "%s%s", logfn, ENCINFO_SUFFIX); fn[MAXFNAME] = '\0'; /* be on save side */ gf->eiName = (uchar *)strdup(fn); *pgf = gf; finalize_it: RETiRet; } gcryctx gcryCtxNew(void) { gcryctx ctx; ctx = calloc(1, sizeof(struct gcryctx_s)); if (ctx != NULL) { ctx->algo = GCRY_CIPHER_AES128; ctx->mode = GCRY_CIPHER_MODE_CBC; } return ctx; } int gcryfileDestruct(gcryfile gf, off64_t offsLogfile) { int r = 0; if (gf == NULL) goto done; DBGPRINTF("libgcry: close file %s\n", gf->eiName); eiClose(gf, offsLogfile); if (gf->bDeleteOnClose) { DBGPRINTF("unlink file '%s' due to bDeleteOnClose set\n", gf->eiName); unlink((char *)gf->eiName); } free(gf->eiName); free(gf); done: return r; } void rsgcryCtxDel(gcryctx ctx) { if (ctx != NULL) { free(ctx->key); free(ctx); } } static void addPadding(gcryfile pF, uchar *buf, size_t *plen) { unsigned i; size_t nPad; nPad = (pF->blkLength - *plen % pF->blkLength) % pF->blkLength; DBGPRINTF("libgcry: addPadding %zd chars, blkLength %zd, mod %zd, pad %zd\n", *plen, pF->blkLength, *plen % pF->blkLength, nPad); for (i = 0; i < nPad; ++i) buf[(*plen) + i] = 0x00; (*plen) += nPad; } static void ATTR_NONNULL() removePadding(uchar *const buf, size_t *const plen) { const size_t len = *plen; size_t iSrc, iDst; iSrc = 0; /* skip to first NUL */ while (iSrc < len && buf[iSrc] == '\0') { ++iSrc; } iDst = iSrc; while (iSrc < len) { if (buf[iSrc] != 0x00) buf[iDst++] = buf[iSrc]; ++iSrc; } *plen = iDst; } /* returns 0 on succes, positive if key length does not match and key * of return value size is required. */ int rsgcrySetKey(gcryctx ctx, unsigned char *key, uint16_t keyLen) { uint16_t reqKeyLen; int r; reqKeyLen = gcry_cipher_get_algo_keylen(ctx->algo); if (keyLen != reqKeyLen) { r = reqKeyLen; goto done; } ctx->keyLen = keyLen; ctx->key = malloc(keyLen); memcpy(ctx->key, key, keyLen); r = 0; done: return r; } rsRetVal rsgcrySetMode(gcryctx ctx, uchar *modename) { int mode; DEFiRet; mode = rsgcryModename2Mode((char *)modename); if (mode == GCRY_CIPHER_MODE_NONE) { ABORT_FINALIZE(RS_RET_CRY_INVLD_MODE); } ctx->mode = mode; finalize_it: RETiRet; } rsRetVal rsgcrySetAlgo(gcryctx ctx, uchar *algoname) { int algo; DEFiRet; algo = rsgcryAlgoname2Algo((char *)algoname); if (algo == GCRY_CIPHER_NONE) { ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO); } ctx->algo = algo; finalize_it: RETiRet; } /* We use random numbers to initiate the IV. Rsyslog runtime will ensure * we get a sufficiently large number. */ static rsRetVal seedIV(gcryfile gf, uchar **iv) { unsigned long rndnum = 0; /* keep compiler happy -- this value is always overriden */ DEFiRet; CHKmalloc(*iv = calloc(1, gf->blkLength)); for (size_t i = 0; i < gf->blkLength; ++i) { const int shift = (i % 4) * 8; if (shift == 0) { /* need new random data? */ rndnum = (unsigned long)randomNumber(); } (*iv)[i] = (uchar)((rndnum >> shift) & 0xffu); } finalize_it: RETiRet; } static rsRetVal readIV(gcryfile gf, uchar **iv) { rsRetVal localRet; DEFiRet; if (gf->fd == -1) { while (gf->fd == -1) { localRet = eiOpenRead(gf); if (localRet == RS_RET_EI_NO_EXISTS) { /* wait until it is created */ srSleep(0, 10000); } else { CHKiRet(localRet); } } CHKiRet(eiCheckFiletype(gf)); } *iv = malloc(gf->blkLength); /* do NOT zero-out! */ iRet = eiGetIV(gf, *iv, (size_t)gf->blkLength); finalize_it: RETiRet; } /* this tries to read the END record. HOWEVER, no such record may be * present, which is the case if we handle a currently-written to queue * file. On the other hand, the queue file may contain multiple blocks. So * what we do is try to see if there is a block end or not - and set the * status accordingly. Note that once we found no end-of-block, we will never * retry. This is because that case can never happen under current queue * implementations. -- gerhards, 2013-05-16 */ static rsRetVal readBlkEnd(gcryfile gf) { off64_t blkEnd; DEFiRet; iRet = eiGetEND(gf, &blkEnd); if (iRet == RS_RET_OK) { gf->bytesToBlkEnd = (ssize_t)blkEnd; } else if (iRet == RS_RET_NO_DATA) { gf->bytesToBlkEnd = -1; } else { FINALIZE; } finalize_it: RETiRet; } /* Read the block begin metadata and set our state variables accordingly. Can also * be used to init the first block in write case. */ static rsRetVal rsgcryBlkBegin(gcryfile gf) { gcry_error_t gcryError; uchar *iv = NULL; DEFiRet; const char openMode = gf->openMode; gcryError = gcry_cipher_open(&gf->chd, gf->ctx->algo, gf->ctx->mode, 0); if (gcryError) { DBGPRINTF("gcry_cipher_open failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); ABORT_FINALIZE(RS_RET_ERR); } gcryError = gcry_cipher_setkey(gf->chd, gf->ctx->key, gf->ctx->keyLen); if (gcryError) { DBGPRINTF("gcry_cipher_setkey failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); ABORT_FINALIZE(RS_RET_ERR); } if (openMode == 'r') { readIV(gf, &iv); readBlkEnd(gf); } else { CHKiRet(seedIV(gf, &iv)); } gcryError = gcry_cipher_setiv(gf->chd, iv, gf->blkLength); if (gcryError) { DBGPRINTF("gcry_cipher_setiv failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); ABORT_FINALIZE(RS_RET_ERR); } if (openMode == 'w') { CHKiRet(eiOpenAppend(gf)); CHKiRet(eiWriteIV(gf, iv)); } finalize_it: free(iv); RETiRet; } rsRetVal rsgcryInitCrypt(gcryctx ctx, gcryfile *pgf, uchar *fname, char openMode) { gcryfile gf = NULL; DEFiRet; CHKiRet(gcryfileConstruct(ctx, &gf, fname)); gf->openMode = openMode; gf->blkLength = gcry_cipher_get_algo_blklen(ctx->algo); CHKiRet(rsgcryBlkBegin(gf)); *pgf = gf; finalize_it: if (iRet != RS_RET_OK && gf != NULL) gcryfileDestruct(gf, -1); RETiRet; } rsRetVal rsgcryEncrypt(gcryfile pF, uchar *buf, size_t *len) { int gcryError; DEFiRet; if (*len == 0) FINALIZE; addPadding(pF, buf, len); gcryError = gcry_cipher_encrypt(pF->chd, buf, *len, NULL, 0); if (gcryError) { dbgprintf("gcry_cipher_encrypt failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: RETiRet; } /* test-read END record; if present, store offset, else unbounded (current active block) * when decrypting, check if bound is reached. If yes, split into two blocks, get new IV for * second one. */ rsRetVal rsgcryDecrypt(gcryfile pF, uchar *buf, size_t *len) { gcry_error_t gcryError; DEFiRet; if (pF->bytesToBlkEnd != -1) pF->bytesToBlkEnd -= *len; gcryError = gcry_cipher_decrypt(pF->chd, buf, *len, NULL, 0); if (gcryError) { DBGPRINTF("gcry_cipher_decrypt failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError)); ABORT_FINALIZE(RS_RET_ERR); } removePadding(buf, len); finalize_it: RETiRet; } /* module-init dummy for potential later use */ int rsgcryInit(void) { return 0; } /* module-deinit dummy for potential later use */ void rsgcryExit(void) { return; } rsyslog-8.2608.0/runtime/PaxHeaders/netstrm.h0000644000000000000000000000013215241075234016072 xustar0030 mtime=1787067036.603578257 30 atime=1787067036.750581009 30 ctime=1787067794.541727794 rsyslog-8.2608.0/runtime/netstrm.h0000664000175000017500000001504715241075234015545 0ustar00rgerrger/* Definitions for the stream-based netstrmworking class. * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_NETSTRM_H #define INCLUDED_NETSTRM_H #include "tcpsrv.h" #include "netstrms.h" /* the netstrm object */ struct netstrm_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pDrvrData; /**< the driver's data elements (at most other places, this is called pNsd) */ nsd_if_t Drvr; /**< our stream driver */ uchar *pszDrvrAuthMode; /**< auth mode of the stream driver to use */ void *pUsr; /**< pointer to user-provided data structure */ netstrms_t *pNS; /**< pointer to our netstream subsystem object */ }; /* interface */ BEGINinterface(netstrm) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(netstrm_t **ppThis); rsRetVal (*ConstructFinalize)(netstrm_t *pThis); rsRetVal (*Destruct)(netstrm_t **ppThis); rsRetVal (*AbortDestruct)(netstrm_t **ppThis); rsRetVal (*AcceptConnReq)(netstrm_t *pThis, netstrm_t **ppNew, char *connInfo); rsRetVal (*Rcv)(netstrm_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf, int *oserr, unsigned *nextIODirection); rsRetVal (*Send)(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf); rsRetVal (*Connect)(netstrm_t *pThis, int family, unsigned char *port, unsigned char *host, char *device); rsRetVal (*GetRemoteHName)(netstrm_t *pThis, uchar **pszName); rsRetVal (*GetRemoteIP)(netstrm_t *pThis, prop_t **ip); rsRetVal (*SetDrvrMode)(netstrm_t *pThis, int iMode); rsRetVal (*SetDrvrAuthMode)(netstrm_t *pThis, uchar *); rsRetVal (*SetDrvrPermitExpiredCerts)(netstrm_t *pThis, uchar *); rsRetVal (*SetDrvrPermPeers)(netstrm_t *pThis, permittedPeers_t *); rsRetVal (*CheckConnection)(netstrm_t *pThis); /* This is a trick mostly for plain tcp syslog */ /* the GetSock() below is a hack to make imgssapi work. In the long term, * we should migrate imgssapi to a stream driver, which will relieve us of * this problem. Please note that nobody else should use GetSock(). Using it * will also tie the caller to nsd_ptcp, because other drivers may not support * it at all. Once the imgssapi problem is solved, GetSock should be removed from * this interface. -- rgerhards, 2008-05-05 */ rsRetVal (*GetSock)(netstrm_t *pThis, int *pSock); rsRetVal (*GetRemAddr)(netstrm_t *pThis, struct sockaddr_storage **ppAddr); /* getRemAddr() is an aid needed by the legacy ACL system. It exposes the remote * peer's socket addr structure, so that the legacy matching functions can work on * it. Note that this ties netstream drivers to things that can be implemented over * sockets - not really desirable, but not the end of the world... */ /* v4 */ rsRetVal (*EnableKeepAlive)(netstrm_t *pThis); /* v7 */ rsRetVal (*SetKeepAliveProbes)(netstrm_t *pThis, int keepAliveProbes); rsRetVal (*SetKeepAliveTime)(netstrm_t *pThis, int keepAliveTime); rsRetVal (*SetKeepAliveIntvl)(netstrm_t *pThis, int keepAliveIntvl); rsRetVal (*SetTcpUserTimeout)(netstrm_t *pThis, int tcpUserTimeout); rsRetVal (*SetGnutlsPriorityString)(netstrm_t *pThis, uchar *priorityString); /* v11 -- Parameter pszLstnFileName added to LstnInit*/ rsRetVal(ATTR_NONNULL(1, 3, 5) * LstnInit)(netstrms_t * pNS, void *pUsr, rsRetVal (*)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params); /* v12 -- two new binary flags added to gtls driver enabling stricter operation */ rsRetVal (*SetDrvrCheckExtendedKeyUsage)(netstrm_t *pThis, int ChkExtendedKeyUsage); rsRetVal (*SetDrvrPrioritizeSAN)(netstrm_t *pThis, int prioritizeSan); /* v14 -- Tls functions */ rsRetVal (*SetDrvrTlsVerifyDepth)(netstrm_t *pThis, int verifyDepth); rsRetVal (*SetDrvrTlsRevocationCheck)(netstrm_t *pThis, int enabled); /* v15 -- Tls cert functions */ rsRetVal (*SetDrvrTlsCAFile)(netstrm_t *pThis, const uchar *file); rsRetVal (*SetDrvrTlsCRLFile)(netstrm_t *pThis, const uchar *file); rsRetVal (*SetDrvrTlsCAExtraFiles)(netstrm_t *pThis, const uchar *file); rsRetVal (*SetDrvrTlsKeyFile)(netstrm_t *pThis, const uchar *file); rsRetVal (*SetDrvrTlsCertFile)(netstrm_t *pThis, const uchar *file); /* v18 -- allow remote server's TLS SNI to be set manually */ rsRetVal (*SetDrvrRemoteSNI)(netstrm_t *pThis, uchar *pszRemoteSNI); ENDinterface(netstrm) #define netstrmCURR_IF_VERSION 20 /* increment whenever you change the interface structure! */ /* interface version 3 added GetRemAddr() * interface version 4 added EnableKeepAlive() -- rgerhards, 2009-06-02 * interface version 5 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06 * interface version 6 changed signature of GetRemoteIP() -- rgerhards, 2013-01-21 * interface version 7 added KeepAlive parameter set functions * interface version 8 changed signature of Connect() -- dsa, 2016-11-14 * interface version 9 added SetGnutlsPriorityString -- PascalWithopf, 2017-08-08 * interface version 10 added oserr parameter to Rcv() -- rgerhards, 2017-09-04 * interface version 16 CRL file -- Oracle, 2022-01-16 * interface version 17 added nextIODirection parameter to Rcv() -- rgehards, 2025-04-17 * interface version 18 added SetDrvrRemoteSNI -- jfcantu, 2020-01-15 * interface version 19 added SetTcpUserTimeout * interface version 20 added SetDrvrTlsCAExtraFiles * */ /* prototypes */ PROTOTYPEObjFull(netstrm); /* the name of our library binary */ #define LM_NETSTRM_FILENAME LM_NETSTRMS_FILENAME #endif /* #ifndef INCLUDED_NETSTRM_H */ rsyslog-8.2608.0/runtime/PaxHeaders/im-helper.h0000644000000000000000000000013215241075234016260 xustar0030 mtime=1787067036.601578219 30 atime=1787067036.746580934 30 ctime=1787067794.263722614 rsyslog-8.2608.0/runtime/im-helper.h0000664000175000017500000000504515241075234015730 0ustar00rgerrger/* im-helper.h * This file contains helper constructs that save time writing input modules. It * assumes some common field names and plumbing. It is intended to be used together * with module-template.h * * File begun on 2011-05-04 by RGerhards * * Copyright 2011-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef IM_HELPER_H_INCLUDED #define IM_HELPER_H_INCLUDED 1 #include "parserif.h" #include "ruleset.h" /* The following function provides a complete implementation to check a * ruleset and set the actual ruleset pointer. The macro assumes that * standard field names are used. A functon std_checkRuleset_genErrMsg() * must be defined to generate error messages in case the ruleset cannot * be found. */ static inline void std_checkRuleset_genErrMsg(modConfData_t *modConf, instanceConf_t *inst); static inline rsRetVal std_checkRuleset(modConfData_t *modConf, instanceConf_t *inst) { ruleset_t *pRuleset; rsRetVal localRet; DEFiRet; inst->pBindRuleset = NULL; /* assume default ruleset */ if (inst->pszBindRuleset == NULL) FINALIZE; localRet = ruleset.GetRuleset(modConf->pConf, &pRuleset, inst->pszBindRuleset); if (localRet == RS_RET_NOT_FOUND) { std_checkRuleset_genErrMsg(modConf, inst); } CHKiRet(localRet); inst->pBindRuleset = pRuleset; if (!rulesetHasQueue(pRuleset)) { parser_warnmsg( "input-bound ruleset '%s' has no dedicated non-direct queue; " "input processing will share the main queue or run synchronously", (const char *)inst->pszBindRuleset); } finalize_it: RETiRet; } #endif /* #ifndef IM_HELPER_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/prop.h0000644000000000000000000000013215145046113015353 xustar0030 mtime=1771326539.005013733 30 atime=1787067616.815414985 30 ctime=1787067794.437725856 rsyslog-8.2608.0/runtime/prop.h0000664000175000017500000000616415145046113015026 0ustar00rgerrger/* The prop object. * * This implements props within rsyslog. * * Copyright 2009-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_PROP_H #define INCLUDED_PROP_H #include "atomic.h" /* the prop object */ struct prop_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ int iRefCount; /* reference counter */ union { uchar *psz; /* stored string */ uchar sz[CONF_PROP_BUFSIZE]; } szVal; int len; /* we use int intentionally, otherwise we may get some troubles... */ DEF_ATOMIC_HELPER_MUT(mutRefCount); }; /* interfaces */ BEGINinterface(prop) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(prop); rsRetVal (*Construct)(prop_t **ppThis); rsRetVal (*ConstructFinalize)(prop_t *pThis); rsRetVal (*Destruct)(prop_t **ppThis); rsRetVal (*SetString)(prop_t *pThis, const uchar *psz, const int len); rsRetVal (*GetString)(prop_t *pThis, uchar **ppsz, int *plen); int (*GetStringLen)(prop_t *pThis); rsRetVal (*AddRef)(prop_t *pThis); rsRetVal (*CreateStringProp)(prop_t **ppThis, const uchar *psz, const int len); rsRetVal (*CreateOrReuseStringProp)(prop_t **ppThis, const uchar *psz, const int len); ENDinterface(prop) #define propCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ /* get classic c-style string */ /* Note: I know that "static inline" is not the right thing from a C99 * PoV, but some environments treat, even in C99 mode, compile * non-static inline into the source even if not defined as "extern". This * obviously results in linker errors. Using "static inline" as below together * with "__attribute__((unused))" works in all cases. Note also that we * cannot work around this as we would otherwise need to evaluate * pThis more than once. */ static inline uchar *__attribute__((unused)) ATTR_NONNULL(1) propGetSzStr(prop_t *pThis) { return (pThis->len < CONF_PROP_BUFSIZE) ? pThis->szVal.sz : pThis->szVal.psz; } static inline const char *__attribute__((unused)) propGetSzStrOrDefault(prop_t *pThis, const char *dflt) { return (pThis != NULL) ? (const char *)propGetSzStr(pThis) : dflt; } static inline const char *__attribute__((unused)) szStrOrDefault(const uchar *psz, const char *dflt) { return (psz != NULL) ? (const char *)psz : dflt; } /* prototypes */ PROTOTYPEObjFull(prop); PROTOTYPEObjDebugPrint(prop); #endif /* #ifndef INCLUDED_PROP_H */ rsyslog-8.2608.0/runtime/PaxHeaders/operatingstate.c0000644000000000000000000000013115132411300017404 xustar0030 mtime=1768559296.272885735 30 atime=1787067617.863434526 29 ctime=1787067794.33972403 rsyslog-8.2608.0/runtime/operatingstate.c0000666000175000017500000001273715132411300017065 0ustar00rgerrger/* OperatingStateFile Handler. * * Copyright 2018 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "errmsg.h" #include "operatingstate.h" #include "rsconf.h" #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif #ifndef HAVE_LSEEK64 #define lseek64(fd, offset, whence) lseek(fd, offset, whence) #endif /* some important standard states */ #define STATE_INITIALIZING "INITIALIZING" #define STATE_CLEAN_CLOSE "CLEAN CLOSE" static int fd_osf = -1; /* check if old osf points to a problem and, if so, report */ static void osf_checkOnStartup(void) { int do_rename = 1; const char *fn_osf = (const char *)glblGetOperatingStateFile(loadConf); char iobuf[sizeof(STATE_CLEAN_CLOSE)]; const int len_clean_close = sizeof(STATE_CLEAN_CLOSE) - 1; assert(fn_osf != NULL); const int fd = open(fn_osf, O_RDONLY | O_LARGEFILE | O_CLOEXEC, 0); if (fd == -1) { if (errno != ENOENT) { LogError(errno, RS_RET_ERR, "error opening existing operatingStateFile '%s' - " "this may be an indication of a problem; ignoring", fn_osf); } do_rename = 0; goto done; } assert(fd != -1); int offs = lseek64(fd, -(len_clean_close + 1), SEEK_END); if (offs == -1) { LogError(errno, RS_RET_IO_ERROR, "error seeking to end of existing operatingStateFile " "'%s' - this may be an indication of a problem, e.g. empty file", fn_osf); goto done; } int rd = read(fd, iobuf, len_clean_close); if (rd == -1) { LogError(errno, RS_RET_IO_ERROR, "error reading existing operatingStateFile " "'%s' - this probably indicates an improper shutdown", fn_osf); goto done; } else { assert(rd <= len_clean_close); iobuf[rd] = '\0'; if (rd != len_clean_close || strcmp(iobuf, STATE_CLEAN_CLOSE) != 0) { LogError(errno, RS_RET_IO_ERROR, "existing operatingStateFile '%s' does not end " "with '%s, instead it has '%s' - this probably indicates an " "improper shutdown", fn_osf, STATE_CLEAN_CLOSE, iobuf); goto done; } } /* all ok! */ do_rename = 0; done: if (fd != -1) { close(fd); } if (do_rename) { char newname[MAXFNAME]; snprintf(newname, sizeof(newname) - 1, "%s.previous", fn_osf); newname[MAXFNAME - 1] = '\0'; if (rename(fn_osf, newname) != 0) { LogError(errno, RS_RET_IO_ERROR, "could not rename existing operatingStateFile " "'%s' to '%s' - ignored, but will probably be overwritten now", fn_osf, newname); } else { LogMsg(errno, RS_RET_OK, LOG_INFO, "existing state file '%s' renamed " "to '%s' - you may want to review it", fn_osf, newname); } } return; } void osf_open(void) { assert(fd_osf == -1); const char *fn_osf = (const char *)glblGetOperatingStateFile(loadConf); assert(fn_osf != NULL); osf_checkOnStartup(); fd_osf = open(fn_osf, O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fd_osf == -1) { LogError(errno, RS_RET_ERR, "error opening operatingStateFile '%s' for write - " "ignoring it", fn_osf); goto done; } assert(fd_osf != -1); osf_write(OSF_TAG_STATE, STATE_INITIALIZING " " VERSION); done: return; } void ATTR_NONNULL() osf_write(const char *const tag, const char *const line) { char buf[1024]; /* intentionally small */ time_t tt; ssize_t wr; size_t len; struct tm tm; DBGPRINTF("osf: %s %s: ", tag, line); /* ensure everything is inside the debug log */ if (fd_osf == -1) return; time(&tt); localtime_r(&tt, &tm); len = snprintf(buf, sizeof(buf) - 1, "%d%2.2d%2.2d-%2.2d%2.2d%2.2d: %-5.5s %s\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tag, line); if (len > sizeof(buf) - 1) { len = sizeof(buf) - 1; /* overflow, truncate */ } wr = write(fd_osf, buf, len); // TODO: handle EINTR if (wr != (ssize_t)len) { LogError(errno, RS_RET_IO_ERROR, "error writing operating state file - line lost"); } } void osf_close(void) { if (fd_osf == -1) return; osf_write(OSF_TAG_STATE, STATE_CLEAN_CLOSE); close(fd_osf); } rsyslog-8.2608.0/runtime/PaxHeaders/timezones.c0000644000000000000000000000013115216464436016415 xustar0030 mtime=1782212894.042266443 30 atime=1787067618.224441257 29 ctime=1787067794.50072703 rsyslog-8.2608.0/runtime/timezones.c0000664000175000017500000001455515216464436016074 0ustar00rgerrger/* timezones.c * Support for timezones in RainerScript. * * Copyright 2022 Attila Lakatos and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include "rsyslog.h" #include "unicode-helper.h" #include "errmsg.h" #include "parserif.h" #include "rainerscript.h" #include "srUtils.h" #include "rsconf.h" static struct cnfparamdescr timezonecnfparamdescr[] = {{"id", eCmdHdlrString, CNFPARAM_REQUIRED}, {"offset", eCmdHdlrGetWord, CNFPARAM_REQUIRED}}; static struct cnfparamblk timezonepblk = { CNFPARAMBLK_VERSION, sizeof(timezonecnfparamdescr) / sizeof(struct cnfparamdescr), timezonecnfparamdescr}; /* Note: this function is NOT thread-safe! * This is currently not needed as used only during * initialization. */ static rsRetVal addTimezoneInfo(rsconf_t *cnf, uchar *tzid, char offsMode, int8_t offsHour, int8_t offsMin) { DEFiRet; tzinfo_t *newti; CHKmalloc(newti = realloc(cnf->timezones.tzinfos, (cnf->timezones.ntzinfos + 1) * sizeof(tzinfo_t))); if ((newti[cnf->timezones.ntzinfos].id = strdup((char *)tzid)) == NULL) { free(newti); DBGPRINTF("addTimezoneInfo: strdup failed with OOM\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } newti[cnf->timezones.ntzinfos].offsMode = offsMode; newti[cnf->timezones.ntzinfos].offsHour = offsHour; newti[cnf->timezones.ntzinfos].offsMin = offsMin; ++cnf->timezones.ntzinfos, cnf->timezones.tzinfos = newti; finalize_it: RETiRet; } void glblProcessTimezone(struct cnfobj *o) { struct cnfparamvals *pvals; uchar *id = NULL; uchar *offset = NULL; char offsMode; int8_t offsHour; int8_t offsMin; int i; pvals = nvlstGetParams(o->nvlst, &timezonepblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing timezone " "config parameters"); goto done; } if (Debug) { dbgprintf("timezone param blk after glblProcessTimezone:\n"); cnfparamsPrint(&timezonepblk, pvals); } for (i = 0; i < timezonepblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(timezonepblk.descr[i].name, "id")) { id = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL); if (id == NULL) { parser_errmsg("timezone: failed to convert id parameter due to out of memory"); goto done; } } else if (!strcmp(timezonepblk.descr[i].name, "offset")) { offset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL); if (offset == NULL) { parser_errmsg("timezone: failed to convert offset parameter due to out of memory"); goto done; } } else { dbgprintf( "glblProcessTimezone: program error, non-handled " "param '%s'\n", timezonepblk.descr[i].name); } } /* note: the following two checks for NULL are not strictly necessary * as these are required parameters for the config block. But we keep * them to make the clang static analyzer happy, which also helps * guard against logic errors. */ if (offset == NULL) { parser_errmsg("offset parameter missing (logic error?), timezone config ignored"); goto done; } if (id == NULL) { parser_errmsg("id parameter missing (logic error?), timezone config ignored"); goto done; } if (strlen((char *)offset) != 6 || !(offset[0] == '-' || offset[0] == '+') || !(isdigit(offset[1]) && isdigit(offset[2])) || offset[3] != ':' || !(isdigit(offset[4]) && isdigit(offset[5]))) { parser_errmsg("timezone offset has invalid format. Must be +/-hh:mm, e.g. \"-07:00\"."); goto done; } offsHour = (offset[1] - '0') * 10 + offset[2] - '0'; offsMin = (offset[4] - '0') * 10 + offset[5] - '0'; offsMode = offset[0]; if (offsHour > 12 || offsMin > 59) { parser_errmsg("timezone offset outside of supported range (hours 0..12, minutes 0..59)"); goto done; } addTimezoneInfo(loadConf, id, offsMode, offsHour, offsMin); done: cnfparamvalsDestruct(pvals, &timezonepblk); free(id); free(offset); } /* comparison function for qsort() and string array compare * this is for the string lookup table type */ static int qs_arrcmp_tzinfo(const void *s1, const void *s2) { return strcmp(((tzinfo_t *)s1)->id, ((tzinfo_t *)s2)->id); } void sortTimezones(rsconf_t *cnf) { if (cnf->timezones.ntzinfos > 0) { qsort(cnf->timezones.tzinfos, cnf->timezones.ntzinfos, sizeof(tzinfo_t), qs_arrcmp_tzinfo); } } void displayTimezones(rsconf_t *cnf) { if (!Debug) return; for (int i = 0; i < cnf->timezones.ntzinfos; ++i) dbgprintf("tzinfo: '%s':%c%2.2d:%2.2d\n", cnf->timezones.tzinfos[i].id, cnf->timezones.tzinfos[i].offsMode, cnf->timezones.tzinfos[i].offsHour, cnf->timezones.tzinfos[i].offsMin); } static int bs_arrcmp_tzinfo(const void *s1, const void *s2) { return strcmp((char *)s1, (char *)((tzinfo_t *)s2)->id); } /* returns matching timezone info or NULL if no entry exists */ tzinfo_t *glblFindTimezone(rsconf_t *cnf, char *id) { return (tzinfo_t *)bsearch(id, cnf->timezones.tzinfos, cnf->timezones.ntzinfos, sizeof(tzinfo_t), bs_arrcmp_tzinfo); } static void freeTimezone(tzinfo_t *tzinfo) { free(tzinfo->id); } void freeTimezones(rsconf_t *cnf) { for (int i = 0; i < cnf->timezones.ntzinfos; ++i) freeTimezone(&cnf->timezones.tzinfos[i]); if (cnf->timezones.ntzinfos > 0) free(cnf->timezones.tzinfos); cnf->timezones.tzinfos = NULL; } rsyslog-8.2608.0/runtime/PaxHeaders/lib_ksi_queue.h0000644000000000000000000000013215132411300017201 xustar0030 mtime=1768559296.264885609 30 atime=1782715518.784788772 30 ctime=1787067794.592728745 rsyslog-8.2608.0/runtime/lib_ksi_queue.h0000666000175000017500000000325615132411300016655 0ustar00rgerrger#ifndef INCLUDED_LIBRSKSI_QUEUE_H #define INCLUDED_LIBRSKSI_QUEUE_H #include #include #include #define RB_GROW_FACTOR 2 typedef struct RingBuffer_st { void** buffer; size_t size; size_t count; size_t head; size_t tail; } RingBuffer; RingBuffer* RingBuffer_new(size_t size); void RingBuffer_free(RingBuffer* this); bool RingBuffer_pushBack(RingBuffer* this, void* item); bool RingBuffer_popFront(RingBuffer* this, void** item); bool RingBuffer_peekFront(RingBuffer* this, void** item); bool RingBuffer_getItem(RingBuffer* this, size_t index, void** item); size_t RingBuffer_count(RingBuffer* this); typedef struct ProtectedQueue_st { bool bStop; RingBuffer* workItems; pthread_mutex_t mutex; pthread_cond_t condition; } ProtectedQueue; ProtectedQueue* ProtectedQueue_new(size_t queueSize); void ProtectedQueue_free(ProtectedQueue* this); void ProtectedQueue_stop(ProtectedQueue* this); bool ProtectedQueue_addItem(ProtectedQueue* this, void* item); bool ProtectedQueue_peekFront(ProtectedQueue* this, void** item); bool ProtectedQueue_popFront(ProtectedQueue* this, void** item); size_t ProtectedQueue_popFrontBatch(ProtectedQueue* this, void** items, size_t bufSize); int ProtectedQueue_waitForItem(ProtectedQueue* this, void** item, uint64_t timeout); size_t ProtectedQueue_count(ProtectedQueue* this); bool ProtectedQueue_getItem(ProtectedQueue* this, size_t index, void** item); typedef struct WorkerThreadContext_st { bool (*workerFunc)(void*); bool (*timeoutFunc)(void); ProtectedQueue* queue; unsigned timeout; } WorkerThreadContext; void* worker_thread_main(void* arg); #endif // INCLUDED_LIBRSKSI_QUEUE_H rsyslog-8.2608.0/runtime/PaxHeaders/translate.c0000644000000000000000000000013215216464436016376 xustar0030 mtime=1782212894.042266443 30 atime=1787067618.092438796 30 ctime=1787067794.444725987 rsyslog-8.2608.0/runtime/translate.c0000664000175000017500000020015115216464436016041 0ustar00rgerrger/** @file translate.c * @brief Canonical config translation support for rsyslog. * * Captures config objects and script bodies during config load so rsyslogd * can emit canonical RainerScript or YAML during validation runs. * * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include "rsyslog.h" #include "translate.h" #include "action.h" #include "errmsg.h" #include "msg.h" #include "grammar/grammar.h" static char *translateVasprintf(const char *fmt, va_list ap); static void cnfarrayCloneDestruct(struct cnfarray *ar); static int preferredKeyRank(const struct nvlst *n); static int nvlstSortComesBefore(const struct nvlst *a, const struct nvlst *b); static int estrAppendCstr(es_str_t **s, const char *buf); static int estrAppendChar(es_str_t **s, char c); static int estrAppendQuoted(es_str_t **s, const char *buf); static int nvlstValueToRs(es_str_t **out, const struct nvlst *node); struct rsconfTranslateWarning_s { char *msg; struct rsconfTranslateWarning_s *next; }; static void addWarning(struct rsconfTranslateWarning_s **head, const char *fmt, ...); struct rsconfTranslateYamlAction_s { struct nvlst *nvlst; struct rsconfTranslateYamlAction_s *next; }; struct rsconfTranslateYamlStatement_s { char *if_expr; struct rsconfTranslateYamlAction_s *actions; struct rsconfTranslateYamlStatement_s *next; }; enum rsconfTranslateYamlRulesetKind_e { RS_TRANSLATE_YAML_RULESET_NONE = 0, RS_TRANSLATE_YAML_RULESET_ACTIONS, RS_TRANSLATE_YAML_RULESET_FILTER_ACTIONS, RS_TRANSLATE_YAML_RULESET_STATEMENTS, }; struct rsconfTranslateItem_s { enum cnfobjType objType; struct nvlst *nvlst; struct objlst *subobjs; char *script; char *source; int line; struct rsconfTranslateWarning_s *warnings; enum rsconfTranslateYamlRulesetKind_e yaml_ruleset_kind; char *yaml_filter; struct rsconfTranslateYamlAction_s *yaml_actions; struct rsconfTranslateYamlStatement_s *yaml_statements; struct rsconfTranslateItem_s *next; }; struct rsconfTranslateState_s { enum rsconfTranslateFormat fmt; int fatal; struct rsconfTranslateWarning_s *globalWarnings; struct rsconfTranslateItem_s *globals; struct rsconfTranslateItem_s *mainqueue; struct rsconfTranslateItem_s *modules; struct rsconfTranslateItem_s *inputs; struct rsconfTranslateItem_s *templates; struct rsconfTranslateItem_s *rulesets; struct rsconfTranslateItem_s *lookups; struct rsconfTranslateItem_s *parsers; struct rsconfTranslateItem_s *timezones; struct rsconfTranslateItem_s *dynstats; struct rsconfTranslateItem_s *perctilestats; struct rsconfTranslateItem_s *ratelimits; }; /* Concurrency & Locking: * Translation capture is only active during single-threaded config load and * validation. g_tx is process-global mutable state with no locking because it * is not accessed concurrently; runtime worker threads are not started while * translation state is being built or emitted. */ static struct rsconfTranslateState_s g_tx = { RSCONF_TRANSLATE_NONE, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; static void cnfarrayCloneDestruct(struct cnfarray *ar) { if (ar == NULL) return; cnfarrayContentDestruct(ar); free(ar); } static void warningsDestruct(struct rsconfTranslateWarning_s *w) { struct rsconfTranslateWarning_s *n; while (w != NULL) { n = w->next; free(w->msg); free(w); w = n; } } static void yamlActionDestruct(struct rsconfTranslateYamlAction_s *act) { while (act != NULL) { struct rsconfTranslateYamlAction_s *n = act->next; nvlstDestruct(act->nvlst); free(act); act = n; } } static void yamlStatementDestruct(struct rsconfTranslateYamlStatement_s *stmt) { while (stmt != NULL) { struct rsconfTranslateYamlStatement_s *n = stmt->next; free(stmt->if_expr); yamlActionDestruct(stmt->actions); free(stmt); stmt = n; } } static void itemDestruct(struct rsconfTranslateItem_s *it) { while (it != NULL) { struct rsconfTranslateItem_s *n = it->next; nvlstDestruct(it->nvlst); objlstDestruct(it->subobjs); free(it->script); free(it->source); warningsDestruct(it->warnings); free(it->yaml_filter); yamlActionDestruct(it->yaml_actions); yamlStatementDestruct(it->yaml_statements); free(it); it = n; } } void rsconfTranslateCleanup(void) { warningsDestruct(g_tx.globalWarnings); itemDestruct(g_tx.globals); itemDestruct(g_tx.mainqueue); itemDestruct(g_tx.modules); itemDestruct(g_tx.inputs); itemDestruct(g_tx.templates); itemDestruct(g_tx.rulesets); itemDestruct(g_tx.lookups); itemDestruct(g_tx.parsers); itemDestruct(g_tx.timezones); itemDestruct(g_tx.dynstats); itemDestruct(g_tx.perctilestats); itemDestruct(g_tx.ratelimits); memset(&g_tx, 0, sizeof(g_tx)); } void rsconfTranslateConfigure(enum rsconfTranslateFormat fmt) { rsconfTranslateCleanup(); g_tx.fmt = fmt; } int rsconfTranslateEnabled(void) { return g_tx.fmt != RSCONF_TRANSLATE_NONE; } int rsconfTranslateHasFatal(void) { return g_tx.fatal; } PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wformat_nonliteral static char *translateVasprintf(const char *fmt, va_list ap) { va_list ap_copy; char *buf; int len; va_copy(ap_copy, ap); len = vsnprintf(NULL, 0, fmt, ap_copy); va_end(ap_copy); if (len < 0) return NULL; buf = malloc((size_t)len + 1); if (buf == NULL) return NULL; va_copy(ap_copy, ap); if (vsnprintf(buf, (size_t)len + 1, fmt, ap_copy) != len) { va_end(ap_copy); free(buf); return NULL; } va_end(ap_copy); return buf; } PRAGMA_IGNORE_Wformat_nonliteral static void addWarning(struct rsconfTranslateWarning_s **head, const char *fmt, ...) { va_list ap; char *buf; struct rsconfTranslateWarning_s *w; va_start(ap, fmt); buf = translateVasprintf(fmt, ap); va_end(ap); if (buf == NULL) return; w = calloc(1, sizeof(*w)); if (w == NULL) { free(buf); return; } w->msg = buf; if (*head == NULL) { *head = w; } else { struct rsconfTranslateWarning_s *cur = *head; while (cur->next != NULL) cur = cur->next; cur->next = w; } } void rsconfTranslateAddUnsupported(const char *source, int line, const char *fmt, ...) { va_list ap; char *buf; va_start(ap, fmt); buf = translateVasprintf(fmt, ap); va_end(ap); g_tx.fatal = 1; addWarning(&g_tx.globalWarnings, "%s:%d: %s", source == NULL ? "" : source, line, buf == NULL ? "translator: failed to format error message" : buf); free(buf); } PRAGMA_DIAGNOSTIC_POP static es_str_t *cloneEstr(const es_str_t *in) { if (in == NULL) return NULL; return es_newStrFromCStr((char *)es_getBufAddr((es_str_t *)in), es_strlen((es_str_t *)in)); } static struct cnfarray *cloneArray(const struct cnfarray *ar) { int i; struct cnfarray *out; if (ar == NULL) return NULL; out = calloc(1, sizeof(*out)); if (out == NULL) return NULL; out->nodetype = ar->nodetype; out->nmemb = ar->nmemb; if (ar->nmemb > 0) { out->arr = calloc(ar->nmemb, sizeof(es_str_t *)); if (out->arr == NULL) { free(out); return NULL; } for (i = 0; i < ar->nmemb; ++i) { out->arr[i] = cloneEstr(ar->arr[i]); if (out->arr[i] == NULL && ar->arr[i] != NULL) { cnfarrayCloneDestruct(out); return NULL; } } } return out; } static struct nvlst *cloneNvlstNode(const struct nvlst *node) { struct nvlst *out; if (node == NULL) return NULL; out = calloc(1, sizeof(*out)); if (out == NULL) return NULL; out->name = cloneEstr(node->name); if (out->name == NULL && node->name != NULL) { nvlstDestruct(out); return NULL; } out->val.datatype = node->val.datatype; switch (node->val.datatype) { case 'S': out->val.d.estr = cloneEstr(node->val.d.estr); if (out->val.d.estr == NULL && node->val.d.estr != NULL) { nvlstDestruct(out); return NULL; } break; case 'A': out->val.d.ar = cloneArray(node->val.d.ar); if (out->val.d.ar == NULL && node->val.d.ar != NULL) { nvlstDestruct(out); return NULL; } break; case 'N': out->val.d.n = node->val.d.n; break; default: break; } return out; } struct nvlst *rsconfTranslateCloneNvlst(const struct nvlst *lst) { struct nvlst *head = NULL, *n; while (lst != NULL) { struct nvlst *prev = NULL, *cur = head; n = cloneNvlstNode(lst); if (n == NULL) { nvlstDestruct(head); return NULL; } while (cur != NULL && !nvlstSortComesBefore(n, cur)) { prev = cur; cur = cur->next; } n->next = cur; if (prev == NULL) { head = n; } else { prev->next = n; } lst = lst->next; } return head; } static struct objlst *cloneObjlst(const struct objlst *lst) { struct objlst *head = NULL, *tail = NULL, *n; while (lst != NULL) { struct cnfobj *obj = calloc(1, sizeof(*obj)); if (obj == NULL) { objlstDestruct(head); return NULL; } obj->objType = lst->obj->objType; obj->nvlst = rsconfTranslateCloneNvlst(lst->obj->nvlst); if (obj->nvlst == NULL && lst->obj->nvlst != NULL) { cnfobjDestruct(obj); objlstDestruct(head); return NULL; } n = objlstNew(obj); if (n == NULL) { cnfobjDestruct(obj); objlstDestruct(head); return NULL; } if (head == NULL) { head = tail = n; } else { tail->next = n; tail = n; } lst = lst->next; } return head; } static int stmtListIsStructuredActionsOnly(const struct cnfstmt *stmt) { while (stmt != NULL) { if (stmt->nodetype != S_ACT) return 0; if (stmt->d.act != NULL && stmt->d.act->pSyntaxLst != NULL) { stmt = stmt->next; continue; } if (stmt->printable != NULL) { const char *s = (const char *)stmt->printable; while (*s == ' ' || *s == '\t') ++s; if (*s == '/' || (*s == '-' && s[1] == '/') || !strncmp(s, ":omusrmsg:", 10)) { stmt = stmt->next; continue; } } return 0; } return 1; } static struct nvlst *newStringNode(const char *name, const char *value) { es_str_t *nm = NULL; es_str_t *val = NULL; struct nvlst *node = NULL; nm = es_newStrFromCStr(name, strlen(name)); if (nm == NULL) goto done; val = es_newStrFromCStr(value, strlen(value)); if (val == NULL) { es_deleteStr(nm); goto done; } node = nvlstNewStr(val); if (node == NULL) { es_deleteStr(val); es_deleteStr(nm); goto done; } node = nvlstSetName(node, nm); if (node == NULL) { es_deleteStr(val); es_deleteStr(nm); } done: return node; } static void yamlActionNodeAppend(struct nvlst **head, struct nvlst *node) { struct nvlst *cur; if (node == NULL) return; node->next = NULL; if (*head == NULL) { *head = node; return; } cur = *head; while (cur->next != NULL) cur = cur->next; cur->next = node; } static struct nvlst *legacyActionToNvlst(const char *printable, int *oom) { const char *s = printable; struct nvlst *lst = NULL; struct nvlst *node; if (printable == NULL) return NULL; while (*s == ' ' || *s == '\t') ++s; if (*s == '/' || (*s == '-' && s[1] == '/')) { if (*s == '-') ++s; node = newStringNode("type", "omfile"); if (node == NULL) goto oom_fail; yamlActionNodeAppend(&lst, node); node = newStringNode("file", s); if (node == NULL) goto oom_fail; yamlActionNodeAppend(&lst, node); return lst; } if (!strncmp(s, ":omusrmsg:", 10)) { node = newStringNode("type", "omusrmsg"); if (node == NULL) goto oom_fail; yamlActionNodeAppend(&lst, node); node = newStringNode("users", s + 10); if (node == NULL) goto oom_fail; yamlActionNodeAppend(&lst, node); return lst; } return NULL; oom_fail: *oom = 1; nvlstDestruct(lst); return NULL; } static char *buildPriFilterExpr(const char *selector) { es_str_t *estr; char *out; const char *p; int use_single = 1; estr = es_newStr(64); if (estr == NULL) return NULL; for (p = selector; *p != '\0'; ++p) { if (*p == '\'') { use_single = 0; break; } } if (use_single) { if (estrAppendCstr(&estr, "prifilt('") != 0) { es_deleteStr(estr); return NULL; } } else if (estrAppendCstr(&estr, "prifilt(") != 0 || estrAppendQuoted(&estr, selector) != 0 || estrAppendChar(&estr, ')') != 0) { es_deleteStr(estr); return NULL; } if (!use_single) { out = es_str2cstr(estr, NULL); es_deleteStr(estr); return out; } for (p = selector; *p != '\0'; ++p) { if (estrAppendChar(&estr, *p) != 0) { es_deleteStr(estr); return NULL; } } if (estrAppendCstr(&estr, "')") != 0) { es_deleteStr(estr); return NULL; } out = es_str2cstr(estr, NULL); es_deleteStr(estr); return out; } static int appendActionNvlstSingleline(es_str_t **out, const struct nvlst *lst) { const struct nvlst *n; char *name; int first = 1; int rank; if (estrAppendCstr(out, "action(") != 0) return -1; for (rank = 0; rank < 4; ++rank) { for (n = lst; n != NULL; n = n->next) { if (preferredKeyRank(n) != rank) continue; name = es_str2cstr(n->name, NULL); if (name == NULL) return -1; if (!first && estrAppendCstr(out, " ") != 0) { free(name); return -1; } first = 0; if (estrAppendCstr(out, name) != 0 || estrAppendChar(out, '=') != 0 || nvlstValueToRs(out, n) != 0) { free(name); return -1; } free(name); } } return estrAppendChar(out, ')'); } static struct rsconfTranslateYamlAction_s *cloneYamlActions(const struct cnfstmt *stmt, int *oom) { struct rsconfTranslateYamlAction_s *head = NULL, *tail = NULL, *node; while (stmt != NULL) { int legacy_oom = 0; node = calloc(1, sizeof(*node)); if (node == NULL) { *oom = 1; yamlActionDestruct(head); return NULL; } if (stmt->d.act != NULL && stmt->d.act->pSyntaxLst != NULL) { node->nvlst = rsconfTranslateCloneNvlst(stmt->d.act->pSyntaxLst); } else { node->nvlst = legacyActionToNvlst((const char *)stmt->printable, &legacy_oom); } if (node->nvlst == NULL) { *oom = legacy_oom; free(node); yamlActionDestruct(head); return NULL; } if (head == NULL) { head = tail = node; } else { tail->next = node; tail = node; } stmt = stmt->next; } return head; } static void yamlActionsAppend(struct rsconfTranslateYamlAction_s **dst, struct rsconfTranslateYamlAction_s *src) { struct rsconfTranslateYamlAction_s *tail; if (*dst == NULL) { *dst = src; return; } tail = *dst; while (tail->next != NULL) tail = tail->next; tail->next = src; } static struct rsconfTranslateYamlStatement_s *cloneYamlLegacyStatements(const struct cnfstmt *stmt, int *oom) { struct rsconfTranslateYamlStatement_s *head = NULL, *tail = NULL, *node; while (stmt != NULL) { const struct cnfstmt *then_branch = NULL; char *if_expr; if (stmt->nodetype != S_PRIFILT || stmt->d.s_prifilt.t_else != NULL || stmt->printable == NULL) { yamlStatementDestruct(head); return NULL; } then_branch = stmt->d.s_prifilt.t_then; if (!stmtListIsStructuredActionsOnly(then_branch)) { yamlStatementDestruct(head); return NULL; } if_expr = buildPriFilterExpr((const char *)stmt->printable); if (if_expr == NULL) { *oom = 1; yamlStatementDestruct(head); return NULL; } node = calloc(1, sizeof(*node)); if (node == NULL) { free(if_expr); *oom = 1; yamlStatementDestruct(head); return NULL; } node->if_expr = if_expr; node->actions = cloneYamlActions(then_branch, oom); if (node->actions == NULL) { yamlStatementDestruct(node); yamlStatementDestruct(head); return NULL; } if (head == NULL) { head = tail = node; } else { tail->next = node; tail = node; } stmt = stmt->next; } return head; } static struct rsconfTranslateYamlStatement_s *newYamlStatement(char *if_expr, struct rsconfTranslateYamlAction_s *actions, int *oom) { struct rsconfTranslateYamlStatement_s *node = calloc(1, sizeof(*node)); if (node == NULL) { *oom = 1; free(if_expr); yamlActionDestruct(actions); return NULL; } node->if_expr = if_expr; node->actions = actions; return node; } static void yamlStatementsAppend(struct rsconfTranslateYamlStatement_s **dst, struct rsconfTranslateYamlStatement_s *src) { struct rsconfTranslateYamlStatement_s *tail; if (*dst == NULL) { *dst = src; return; } tail = *dst; while (tail->next != NULL) tail = tail->next; tail->next = src; } static int promoteSimpleYamlToStatements(struct rsconfTranslateItem_s *it, int *oom) { char *if_expr; struct rsconfTranslateYamlAction_s *actions; struct rsconfTranslateYamlStatement_s *stmt; if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_STATEMENTS) return 1; if (it->yaml_ruleset_kind != RS_TRANSLATE_YAML_RULESET_FILTER_ACTIONS || it->yaml_filter == NULL || it->yaml_actions == NULL) return 0; if_expr = buildPriFilterExpr(it->yaml_filter); if (if_expr == NULL) { *oom = 1; return 0; } actions = it->yaml_actions; it->yaml_actions = NULL; stmt = newYamlStatement(if_expr, actions, oom); if (stmt == NULL) return 0; free(it->yaml_filter); it->yaml_filter = NULL; it->yaml_statements = stmt; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_STATEMENTS; return 1; } static int appendYamlLegacyStatement(struct rsconfTranslateItem_s *it, const struct cnfstmt *script, int *oom) { const struct cnfstmt *then_branch = NULL; char *if_expr; struct rsconfTranslateYamlAction_s *actions; struct rsconfTranslateYamlStatement_s *stmt; if (script == NULL || script->next != NULL || script->nodetype != S_PRIFILT || script->d.s_prifilt.t_else != NULL || script->printable == NULL) return 0; then_branch = script->d.s_prifilt.t_then; if (!stmtListIsStructuredActionsOnly(then_branch)) return 0; if (!promoteSimpleYamlToStatements(it, oom) || it->yaml_ruleset_kind != RS_TRANSLATE_YAML_RULESET_STATEMENTS) { return 0; } if_expr = buildPriFilterExpr((const char *)script->printable); if (if_expr == NULL) { *oom = 1; return 0; } actions = cloneYamlActions(then_branch, oom); if (actions == NULL) { free(if_expr); return 0; } stmt = newYamlStatement(if_expr, actions, oom); if (stmt == NULL) return 0; yamlStatementsAppend(&it->yaml_statements, stmt); return 1; } static void captureYamlRulesetBody(struct rsconfTranslateItem_s *it, const struct cnfstmt *script) { int oom = 0; if (it == NULL || script == NULL) return; if (stmtListIsStructuredActionsOnly(script)) { struct rsconfTranslateYamlAction_s *actions = cloneYamlActions(script, &oom); if (oom) { addWarning(&it->warnings, "translator: out of memory when capturing YAML action list"); g_tx.fatal = 1; return; } if (actions == NULL) { /* Unsupported legacy action shorthand, fall back below. */ } else if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_NONE) { yamlStatementDestruct(it->yaml_statements); it->yaml_statements = NULL; it->yaml_actions = actions; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_ACTIONS; return; } else if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_ACTIONS && it->yaml_filter == NULL) { yamlActionsAppend(&it->yaml_actions, actions); return; } else { yamlActionDestruct(actions); free(it->yaml_filter); it->yaml_filter = NULL; yamlActionDestruct(it->yaml_actions); it->yaml_actions = NULL; yamlStatementDestruct(it->yaml_statements); it->yaml_statements = NULL; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_NONE; } } if (script->next == NULL && script->printable != NULL) { const struct cnfstmt *then_branch = NULL; if (script->nodetype == S_PRIFILT && script->d.s_prifilt.t_else == NULL) { then_branch = script->d.s_prifilt.t_then; } else if (script->nodetype == S_PROPFILT && script->d.s_propfilt.t_else == NULL) { then_branch = script->d.s_propfilt.t_then; } if (then_branch != NULL && stmtListIsStructuredActionsOnly(then_branch) && it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_NONE) { it->yaml_filter = strdup((char *)script->printable); if (it->yaml_filter == NULL) { addWarning(&it->warnings, "translator: out of memory when capturing YAML filter"); g_tx.fatal = 1; return; } it->yaml_actions = cloneYamlActions(then_branch, &oom); if (oom) { addWarning(&it->warnings, "translator: out of memory when capturing YAML action list"); g_tx.fatal = 1; return; } if (it->yaml_actions != NULL) { yamlStatementDestruct(it->yaml_statements); it->yaml_statements = NULL; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_FILTER_ACTIONS; return; } free(it->yaml_filter); it->yaml_filter = NULL; } } if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_NONE) { it->yaml_statements = cloneYamlLegacyStatements(script, &oom); if (oom) { addWarning(&it->warnings, "translator: out of memory when capturing YAML statements"); g_tx.fatal = 1; return; } if (it->yaml_statements != NULL) { it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_STATEMENTS; return; } } free(it->yaml_filter); it->yaml_filter = NULL; yamlActionDestruct(it->yaml_actions); it->yaml_actions = NULL; yamlStatementDestruct(it->yaml_statements); it->yaml_statements = NULL; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_NONE; } static int stmtListIsSelectorCompatible(const struct cnfstmt *stmt) { while (stmt != NULL) { switch (stmt->nodetype) { case S_ACT: case S_STOP: case S_CALL: case S_CALL_INDIRECT: case S_NOP: break; default: return 0; } stmt = stmt->next; } return 1; } static int estrAppendCstr(es_str_t **s, const char *buf) { return es_addBuf(s, buf, strlen(buf)); } static int estrAppendChar(es_str_t **s, char c) { return es_addChar(s, (unsigned char)c); } static int estrAppendVarName(es_str_t **s, const char *name) { if (name == NULL || name[0] == '\0') return -1; if (name[0] != '$' && estrAppendChar(s, '$') != 0) return -1; return estrAppendCstr(s, name); } static int estrAppendQuoted(es_str_t **s, const char *buf) { size_t i; if (estrAppendChar(s, '"') != 0) return -1; for (i = 0; buf[i] != '\0'; ++i) { switch (buf[i]) { case '"': case '\\': if (estrAppendChar(s, '\\') != 0 || estrAppendChar(s, buf[i]) != 0) return -1; break; case '\n': if (estrAppendCstr(s, "\\n") != 0) return -1; break; case '\r': if (estrAppendCstr(s, "\\r") != 0) return -1; break; case '\t': if (estrAppendCstr(s, "\\t") != 0) return -1; break; default: if (estrAppendChar(s, buf[i]) != 0) return -1; break; } } return estrAppendChar(s, '"'); } static const char *exprOpToStr(unsigned nodetype) { switch (nodetype) { case CMP_EQ: return "=="; case CMP_NE: return "!="; case CMP_LE: return "<="; case CMP_GE: return ">="; case CMP_LT: return "<"; case CMP_GT: return ">"; case CMP_CONTAINS: return "contains"; case CMP_CONTAINSI: return "contains_i"; case CMP_STARTSWITH: return "startswith"; case CMP_STARTSWITHI: return "startswith_i"; case CMP_ENDSWITH: return "endswith"; case OR: return "or"; case AND: return "and"; default: return NULL; } } static int exprToString(es_str_t **out, const struct cnfexpr *expr, struct rsconfTranslateWarning_s **warnings); static int exprListToString(es_str_t **out, unsigned short nParams, const struct cnfexpr *const *exprs, struct rsconfTranslateWarning_s **warnings) { unsigned short i; for (i = 0; i < nParams; ++i) { if (i > 0 && estrAppendCstr(out, ", ") != 0) return -1; if (exprToString(out, exprs[i], warnings) != 0) return -1; } return 0; } static int exprToString(es_str_t **out, const struct cnfexpr *expr, struct rsconfTranslateWarning_s **warnings) { const char *op; char nbuf[64]; int i; char *cstr; const struct cnffunc *func; const struct cnfarray *ar; if (expr == NULL) return -1; op = exprOpToStr(expr->nodetype); if (op != NULL) { if (estrAppendChar(out, '(') != 0) return -1; if (exprToString(out, expr->l, warnings) != 0) return -1; if (estrAppendCstr(out, " ") != 0 || estrAppendCstr(out, op) != 0 || estrAppendCstr(out, " ") != 0) return -1; if (exprToString(out, expr->r, warnings) != 0) return -1; return estrAppendChar(out, ')'); } switch (expr->nodetype) { case NOT: if (estrAppendCstr(out, "not ") != 0) return -1; return exprToString(out, expr->r, warnings); case 'N': { int len = snprintf(nbuf, sizeof(nbuf), "%lld", ((const struct cnfnumval *)expr)->val); if (len < 0 || len >= (int)sizeof(nbuf)) return -1; return estrAppendCstr(out, nbuf); } case 'S': cstr = es_str2cstr(((const struct cnfstringval *)expr)->estr, NULL); if (cstr == NULL) return -1; i = estrAppendQuoted(out, cstr); free(cstr); return i; case 'V': return estrAppendVarName(out, ((const struct cnfvar *)expr)->name); case 'A': ar = (const struct cnfarray *)expr; if (estrAppendChar(out, '[') != 0) return -1; for (i = 0; i < ar->nmemb; ++i) { char *aval = es_str2cstr(ar->arr[i], NULL); if (i > 0 && estrAppendCstr(out, ", ") != 0) { free(aval); return -1; } if (aval == NULL || estrAppendQuoted(out, aval) != 0) { free(aval); return -1; } free(aval); } return estrAppendChar(out, ']'); case 'F': func = (const struct cnffunc *)expr; cstr = es_str2cstr(func->fname, NULL); if (cstr == NULL) return -1; if (estrAppendCstr(out, cstr) != 0 || estrAppendChar(out, '(') != 0) { free(cstr); return -1; } free(cstr); if (exprListToString(out, func->nParams, (const struct cnfexpr *const *)func->expr, warnings) != 0 || estrAppendChar(out, ')') != 0) return -1; return 0; case S_FUNC_EXISTS: if (estrAppendCstr(out, "exists(") != 0) return -1; if (estrAppendVarName(out, ((const struct cnffuncexists *)expr)->varname) != 0) return -1; return estrAppendChar(out, ')'); case '&': case '+': case '-': case '*': case '/': case '%': case 'M': if (expr->nodetype == 'M') { if (estrAppendChar(out, '-') != 0) return -1; return exprToString(out, expr->r, warnings); } if (estrAppendChar(out, '(') != 0) return -1; if (exprToString(out, expr->l, warnings) != 0) return -1; if (estrAppendCstr(out, " ") != 0 || estrAppendChar(out, (char)expr->nodetype) != 0 || estrAppendCstr(out, " ") != 0) return -1; if (exprToString(out, expr->r, warnings) != 0) return -1; return estrAppendChar(out, ')'); default: addWarning(warnings, "translator: unsupported expression node %u", expr->nodetype); return -1; } } static int nvlstValueToRs(es_str_t **out, const struct nvlst *node) { char *cstr; int i; struct cnfarray *ar; char nbuf[64]; switch (node->val.datatype) { case 'S': cstr = es_str2cstr(node->val.d.estr, NULL); if (cstr == NULL) return -1; i = estrAppendQuoted(out, cstr); free(cstr); return i; case 'A': ar = node->val.d.ar; if (estrAppendChar(out, '[') != 0) return -1; for (i = 0; i < ar->nmemb; ++i) { cstr = es_str2cstr(ar->arr[i], NULL); if (cstr == NULL) return -1; if ((i > 0 && estrAppendCstr(out, ", ") != 0) || estrAppendQuoted(out, cstr) != 0) { free(cstr); return -1; } free(cstr); } return estrAppendChar(out, ']'); case 'N': { int len = snprintf(nbuf, sizeof(nbuf), "%lld", node->val.d.n); if (len < 0 || len >= (int)sizeof(nbuf)) return -1; return estrAppendCstr(out, nbuf); } default: return -1; } } static int emitActionSingleline(es_str_t **out, const struct cnfstmt *stmt, struct rsconfTranslateWarning_s **warnings) { char *name; switch (stmt->nodetype) { case S_ACT: if (stmt->d.act != NULL && stmt->d.act->pSyntaxLst != NULL) { return appendActionNvlstSingleline(out, stmt->d.act->pSyntaxLst); } if (stmt->printable != NULL) { int oom = 0; struct nvlst *legacy = legacyActionToNvlst((char *)stmt->printable, &oom); if (legacy != NULL) { int ret = appendActionNvlstSingleline(out, legacy); nvlstDestruct(legacy); return ret; } if (oom) { addWarning(warnings, "translator: out of memory when converting legacy action syntax"); return -1; } addWarning(warnings, "legacy action syntax preserved as script text"); return estrAppendCstr(out, (char *)stmt->printable); } addWarning(warnings, "translator: action statement lost original syntax"); return -1; case S_STOP: return estrAppendCstr(out, "stop"); case S_CALL: { int ret; if (estrAppendCstr(out, "call ") != 0) return -1; name = es_str2cstr(stmt->d.s_call.name, NULL); if (name == NULL) return -1; ret = estrAppendCstr(out, name); free(name); return ret; } case S_CALL_INDIRECT: if (estrAppendCstr(out, "call_indirect ") != 0) return -1; if (exprToString(out, stmt->d.s_call_ind.expr, warnings) != 0) return -1; return estrAppendChar(out, ';'); case S_NOP: if (stmt->printable != NULL && !strcmp((char *)stmt->printable, "continue")) { return estrAppendCstr(out, "continue"); } addWarning(warnings, "translator: omitted internal NOP statement"); return -1; default: return -1; } } static int stmtListToString(es_str_t **out, const struct cnfstmt *stmt, int indent, struct rsconfTranslateWarning_s **warnings); static int appendIndent(es_str_t **out, int indent) { while (indent-- > 0) { if (estrAppendCstr(out, " ") != 0) return -1; } return 0; } static int emitSelectorBlock(es_str_t **out, const struct cnfstmt *stmt, int indent, const char *selector, struct rsconfTranslateWarning_s **warnings) { const struct cnfstmt *cur = stmt; int first = 1; while (cur != NULL) { if (appendIndent(out, indent) != 0) return -1; if (!first && estrAppendCstr(out, "& ") != 0) return -1; if (first) { if (estrAppendCstr(out, selector) != 0 || estrAppendCstr(out, " ") != 0) return -1; } first = 0; if (emitActionSingleline(out, cur, warnings) != 0 || estrAppendChar(out, '\n') != 0) return -1; cur = cur->next; } return 0; } static int stmtListToString(es_str_t **out, const struct cnfstmt *stmt, int indent, struct rsconfTranslateWarning_s **warnings) { while (stmt != NULL) { switch (stmt->nodetype) { case S_ACT: case S_STOP: case S_CALL: case S_CALL_INDIRECT: case S_NOP: if (appendIndent(out, indent) != 0 || emitActionSingleline(out, stmt, warnings) != 0 || estrAppendChar(out, '\n') != 0) return -1; break; case S_SET: if (appendIndent(out, indent) != 0) return -1; if (estrAppendCstr(out, stmt->d.s_set.force_reset ? "reset " : "set ") != 0 || estrAppendVarName(out, (char *)stmt->d.s_set.varname) != 0 || estrAppendCstr(out, " = ") != 0 || exprToString(out, stmt->d.s_set.expr, warnings) != 0 || estrAppendCstr(out, ";\n") != 0) return -1; break; case S_UNSET: if (appendIndent(out, indent) != 0 || estrAppendCstr(out, "unset ") != 0 || estrAppendVarName(out, (char *)stmt->d.s_unset.varname) != 0 || estrAppendCstr(out, ";\n") != 0) return -1; break; case S_IF: if (appendIndent(out, indent) != 0 || estrAppendCstr(out, "if ") != 0 || exprToString(out, stmt->d.s_if.expr, warnings) != 0 || estrAppendCstr(out, " then {\n") != 0 || stmtListToString(out, stmt->d.s_if.t_then, indent + 1, warnings) != 0) return -1; if (appendIndent(out, indent) != 0) return -1; if (stmt->d.s_if.t_else != NULL) { if (estrAppendCstr(out, "} else {\n") != 0 || stmtListToString(out, stmt->d.s_if.t_else, indent + 1, warnings) != 0 || appendIndent(out, indent) != 0 || estrAppendCstr(out, "}\n") != 0) return -1; } else if (estrAppendCstr(out, "}\n") != 0) { return -1; } break; case S_FOREACH: if (appendIndent(out, indent) != 0 || estrAppendCstr(out, "foreach (") != 0 || estrAppendVarName(out, stmt->d.s_foreach.iter->var) != 0 || estrAppendCstr(out, " in ") != 0 || exprToString(out, stmt->d.s_foreach.iter->collection, warnings) != 0 || estrAppendCstr(out, ") do {\n") != 0 || stmtListToString(out, stmt->d.s_foreach.body, indent + 1, warnings) != 0 || appendIndent(out, indent) != 0 || estrAppendCstr(out, "}\n") != 0) return -1; break; case S_PRIFILT: if (stmt->d.s_prifilt.t_else == NULL && stmtListIsSelectorCompatible(stmt->d.s_prifilt.t_then)) { if (emitSelectorBlock(out, stmt->d.s_prifilt.t_then, indent, (char *)stmt->printable, warnings) != 0) return -1; } else { addWarning(warnings, "PRI selector normalized into if/prifilt() form"); if (appendIndent(out, indent) != 0 || estrAppendCstr(out, "if prifilt(") != 0 || estrAppendQuoted(out, (char *)stmt->printable) != 0 || estrAppendCstr(out, ") then {\n") != 0 || stmtListToString(out, stmt->d.s_prifilt.t_then, indent + 1, warnings) != 0 || appendIndent(out, indent) != 0) return -1; if (stmt->d.s_prifilt.t_else != NULL) { if (estrAppendCstr(out, "} else {\n") != 0 || stmtListToString(out, stmt->d.s_prifilt.t_else, indent + 1, warnings) != 0 || appendIndent(out, indent) != 0 || estrAppendCstr(out, "}\n") != 0) return -1; } else if (estrAppendCstr(out, "}\n") != 0) { return -1; } } break; case S_PROPFILT: if (stmt->d.s_propfilt.t_else == NULL && stmtListIsSelectorCompatible(stmt->d.s_propfilt.t_then)) { if (emitSelectorBlock(out, stmt->d.s_propfilt.t_then, indent, (char *)stmt->printable, warnings) != 0) return -1; } else { addWarning(warnings, "property selector with else/complex body is not safely translatable"); return -1; } break; case S_RELOAD_LOOKUP_TABLE: if (appendIndent(out, indent) != 0 || estrAppendCstr(out, "reload_lookup_table(") != 0 || estrAppendQuoted(out, (char *)stmt->d.s_reload_lookup_table.table_name) != 0 || estrAppendCstr(out, ", stub_value=") != 0 || estrAppendQuoted(out, (char *)stmt->d.s_reload_lookup_table.stub_value) != 0 || estrAppendCstr(out, ")\n") != 0) return -1; break; default: addWarning(warnings, "translator: unsupported statement node %u", stmt->nodetype); return -1; } stmt = stmt->next; } return 0; } static struct rsconfTranslateItem_s **selectList(enum cnfobjType t) { switch (t) { case CNFOBJ_GLOBAL: return &g_tx.globals; case CNFOBJ_MAINQ: return &g_tx.mainqueue; case CNFOBJ_MODULE: return &g_tx.modules; case CNFOBJ_INPUT: return &g_tx.inputs; case CNFOBJ_TPL: return &g_tx.templates; case CNFOBJ_RULESET: return &g_tx.rulesets; case CNFOBJ_LOOKUP_TABLE: return &g_tx.lookups; case CNFOBJ_PARSER: return &g_tx.parsers; case CNFOBJ_TIMEZONE: return &g_tx.timezones; case CNFOBJ_DYN_STATS: return &g_tx.dynstats; case CNFOBJ_PERCTILE_STATS: return &g_tx.perctilestats; case CNFOBJ_RATELIMIT: return &g_tx.ratelimits; case CNFOBJ_ACTION: case CNFOBJ_PROPERTY: case CNFOBJ_CONSTANT: default: return NULL; } } static void mergeSingleton(struct rsconfTranslateItem_s *dst, const struct nvlst *lst) { const struct nvlst *src; for (src = lst; src != NULL; src = src->next) { struct nvlst *prev = NULL; struct nvlst *cur = dst->nvlst; while (cur != NULL) { char *lhs = es_str2cstr(cur->name, NULL); char *rhs = es_str2cstr(src->name, NULL); int eq = lhs != NULL && rhs != NULL && !strcasecmp(lhs, rhs); free(lhs); free(rhs); if (eq) break; prev = cur; cur = cur->next; } if (cur != NULL) { struct nvlst *rep = cloneNvlstNode(src); if (rep == NULL) continue; rep->next = cur->next; if (prev == NULL) dst->nvlst = rep; else prev->next = rep; cur->next = NULL; nvlstDestruct(cur); } else { struct nvlst *rep = cloneNvlstNode(src); struct nvlst *tail; if (rep == NULL) continue; rep->next = NULL; if (dst->nvlst == NULL) { dst->nvlst = rep; } else { tail = dst->nvlst; while (tail->next != NULL) tail = tail->next; tail->next = rep; } } } } void rsconfTranslateCaptureObj(const struct cnfobj *o, const char *source, int line) { struct rsconfTranslateItem_s **list; struct rsconfTranslateItem_s *it; es_str_t *estr; if (!rsconfTranslateEnabled() || o == NULL) return; list = selectList(o->objType); if (list == NULL) return; if ((o->objType == CNFOBJ_GLOBAL || o->objType == CNFOBJ_MAINQ) && *list != NULL) { mergeSingleton(*list, o->nvlst); return; } it = calloc(1, sizeof(*it)); if (it == NULL) { g_tx.fatal = 1; return; } it->objType = o->objType; it->nvlst = rsconfTranslateCloneNvlst(o->nvlst); if (it->nvlst == NULL && o->nvlst != NULL) { g_tx.fatal = 1; itemDestruct(it); return; } it->subobjs = cloneObjlst(o->subobjs); if (it->subobjs == NULL && o->subobjs != NULL) { g_tx.fatal = 1; itemDestruct(it); return; } it->source = source ? strdup(source) : NULL; if (source != NULL && it->source == NULL) { g_tx.fatal = 1; itemDestruct(it); return; } it->line = line; if (o->objType == CNFOBJ_RULESET && o->script != NULL) { estr = es_newStr(256); if (estr == NULL || stmtListToString(&estr, o->script, 1, &it->warnings) != 0) { addWarning(&it->warnings, "translator: failed to serialize ruleset body"); g_tx.fatal = 1; if (estr != NULL) es_deleteStr(estr); } else { it->script = es_str2cstr(estr, NULL); es_deleteStr(estr); if (it->script == NULL) { addWarning(&it->warnings, "translator: out of memory when capturing ruleset body"); g_tx.fatal = 1; } } captureYamlRulesetBody(it, o->script); } if (*list == NULL) { *list = it; } else { struct rsconfTranslateItem_s *tail = *list; while (tail->next != NULL) tail = tail->next; tail->next = it; } } void rsconfTranslateCaptureScript(const struct cnfstmt *script, const char *source, int line) { struct rsconfTranslateItem_s *it = g_tx.rulesets; es_str_t *estr; struct nvlst *nameNode; int had_script; if (!rsconfTranslateEnabled() || script == NULL) return; while (it != NULL) { struct nvlst *cur; for (cur = it->nvlst; cur != NULL; cur = cur->next) { char *k = es_str2cstr(cur->name, NULL); int match = k != NULL && !strcasecmp(k, "name"); free(k); if (match) break; } if (cur != NULL) { char *v = es_str2cstr(cur->val.d.estr, NULL); int match = v != NULL && !strcmp(v, "RSYSLOG_DefaultRuleset"); free(v); if (match) break; } it = it->next; } if (it == NULL) { es_str_t *nm = es_newStrFromCStr("name", 4); es_str_t *val = es_newStrFromCStr("RSYSLOG_DefaultRuleset", strlen("RSYSLOG_DefaultRuleset")); if (nm == NULL || val == NULL) { es_deleteStr(nm); es_deleteStr(val); g_tx.fatal = 1; return; } nameNode = nvlstNewStr(val); if (nameNode == NULL) { es_deleteStr(val); es_deleteStr(nm); g_tx.fatal = 1; return; } nameNode = nvlstSetName(nameNode, nm); it = calloc(1, sizeof(*it)); if (it == NULL) { nvlstDestruct(nameNode); g_tx.fatal = 1; return; } it->objType = CNFOBJ_RULESET; it->nvlst = nameNode; it->source = source ? strdup(source) : NULL; it->line = line; addWarning(&it->warnings, "top-level statements normalized into explicit RSYSLOG_DefaultRuleset"); if (g_tx.rulesets == NULL) { g_tx.rulesets = it; } else { struct rsconfTranslateItem_s *tail = g_tx.rulesets; while (tail->next != NULL) tail = tail->next; tail->next = it; } } had_script = it->script != NULL; estr = es_newStr(256); if (estr == NULL || stmtListToString(&estr, script, 1, &it->warnings) != 0) { addWarning(&it->warnings, "translator: failed to serialize top-level script"); g_tx.fatal = 1; if (estr != NULL) es_deleteStr(estr); return; } if (it->script == NULL) { it->script = es_str2cstr(estr, NULL); if (it->script == NULL) { addWarning(&it->warnings, "translator: out of memory when capturing script"); g_tx.fatal = 1; } } else { char *more = es_str2cstr(estr, NULL); if (more == NULL) { addWarning(&it->warnings, "translator: out of memory when capturing script"); g_tx.fatal = 1; es_deleteStr(estr); return; } size_t oldlen = strlen(it->script); size_t addlen = strlen(more); char *merged = realloc(it->script, oldlen + addlen + 1); if (merged == NULL) { addWarning(&it->warnings, "translator: out of memory when merging script parts"); g_tx.fatal = 1; } else { memcpy(merged + oldlen, more, addlen + 1); it->script = merged; } free(more); } es_deleteStr(estr); if (had_script) { int oom = 0; if (!appendYamlLegacyStatement(it, script, &oom)) { if (oom) { addWarning(&it->warnings, "translator: out of memory when capturing YAML statements"); g_tx.fatal = 1; } else { free(it->yaml_filter); it->yaml_filter = NULL; yamlActionDestruct(it->yaml_actions); it->yaml_actions = NULL; yamlStatementDestruct(it->yaml_statements); it->yaml_statements = NULL; it->yaml_ruleset_kind = RS_TRANSLATE_YAML_RULESET_NONE; } } } else { captureYamlRulesetBody(it, script); } } static void writeWarningComments(FILE *fp, const struct rsconfTranslateWarning_s *w, int indent) { while (w != NULL) { int i; for (i = 0; i < indent; ++i) fputs(" ", fp); fprintf(fp, "# TRANSLATION WARNING: %s\n", w->msg); w = w->next; } } static void logWarnings(const struct rsconfTranslateWarning_s *w) { while (w != NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "%s", w->msg); w = w->next; } } static void logItemWarnings(const struct rsconfTranslateItem_s *items) { while (items != NULL) { logWarnings(items->warnings); items = items->next; } } static void logAllWarnings(void) { logWarnings(g_tx.globalWarnings); logItemWarnings(g_tx.globals); logItemWarnings(g_tx.mainqueue); logItemWarnings(g_tx.modules); logItemWarnings(g_tx.inputs); logItemWarnings(g_tx.templates); logItemWarnings(g_tx.rulesets); logItemWarnings(g_tx.lookups); logItemWarnings(g_tx.parsers); logItemWarnings(g_tx.timezones); logItemWarnings(g_tx.dynstats); logItemWarnings(g_tx.perctilestats); logItemWarnings(g_tx.ratelimits); } static void writeYamlQuoted(FILE *fp, const char *s) { fputc('"', fp); while (*s != '\0') { switch (*s) { case '"': fputs("\\\"", fp); break; case '\\': fputs("\\\\", fp); break; case '\n': fputs("\\n", fp); break; case '\r': fputs("\\r", fp); break; case '\t': fputs("\\t", fp); break; default: fputc(*s, fp); break; } ++s; } fputc('"', fp); } static void writeYamlValue(FILE *fp, const struct nvlst *n) { int i; char *s; switch (n->val.datatype) { case 'N': fprintf(fp, "%lld", n->val.d.n); break; case 'A': fputc('[', fp); for (i = 0; i < n->val.d.ar->nmemb; ++i) { s = es_str2cstr(n->val.d.ar->arr[i], NULL); if (i > 0) fputs(", ", fp); writeYamlQuoted(fp, s == NULL ? "" : s); free(s); } fputc(']', fp); break; case 'S': default: s = es_str2cstr(n->val.d.estr, NULL); writeYamlQuoted(fp, s == NULL ? "" : s); free(s); break; } } static int preferredKeyRank(const struct nvlst *n) { char *name; int rank = 3; if (n == NULL) return rank; name = es_str2cstr(n->name, NULL); if (name != NULL) { if (!strcmp(name, "name")) { rank = 0; } else if (!strcmp(name, "type")) { rank = 1; } else if (!strcmp(name, "load")) { rank = 2; } } free(name); return rank; } static int nvlstSortComesBefore(const struct nvlst *a, const struct nvlst *b) { char *nameA; char *nameB; int rankA; int rankB; int cmp; if (b == NULL) return 1; if (a == NULL) return 0; rankA = preferredKeyRank(a); rankB = preferredKeyRank(b); if (rankA != rankB) return rankA < rankB; nameA = es_str2cstr(a->name, NULL); nameB = es_str2cstr(b->name, NULL); if (nameA == NULL || nameB == NULL) { free(nameA); free(nameB); return 0; } cmp = strcmp(nameA, nameB); free(nameA); free(nameB); return cmp < 0; } static void writeYamlEntry(FILE *fp, const struct nvlst *n, int indent, int list_prefix) { char *name; int i; for (i = 0; i < indent; ++i) fputs(" ", fp); if (list_prefix) fputs("- ", fp); name = es_str2cstr(n->name, NULL); fprintf(fp, "%s: ", name == NULL ? "" : name); free(name); writeYamlValue(fp, n); fputc('\n', fp); } static void writeYamlMappingExcept(FILE *fp, const struct nvlst *lst, int indent, const struct nvlst *skip) { const struct nvlst *n; int rank; for (rank = 0; rank < 4; ++rank) { for (n = lst; n != NULL; n = n->next) { if (n == skip || preferredKeyRank(n) != rank) continue; writeYamlEntry(fp, n, indent, 0); } } } static void writeYamlMapping(FILE *fp, const struct nvlst *lst, int indent) { writeYamlMappingExcept(fp, lst, indent, NULL); } static void writeYamlBlockScalar(FILE *fp, const char *content, int indent) { const char *cur = content; int i; while (cur != NULL && *cur != '\0') { for (i = 0; i < indent; ++i) fputs(" ", fp); while (*cur != '\0' && *cur != '\n') { fputc(*cur++, fp); } fputc('\n', fp); if (*cur == '\n') ++cur; } } static void writeYamlActions(FILE *fp, const struct rsconfTranslateYamlAction_s *actions, int indent) { const struct rsconfTranslateYamlAction_s *act; int i; for (i = 0; i < indent; ++i) fputs(" ", fp); fputs("actions:\n", fp); for (act = actions; act != NULL; act = act->next) { const struct nvlst *n; const struct nvlst *firstNode = NULL; int firstRank = 4; for (n = act->nvlst; n != NULL; n = n->next) { int rank = preferredKeyRank(n); if (rank < firstRank) { firstNode = n; firstRank = rank; } } if (firstNode != NULL) { writeYamlEntry(fp, firstNode, indent + 1, 1); } else { for (i = 0; i < indent + 1; ++i) fputs(" ", fp); fputs("-\n", fp); } writeYamlMappingExcept(fp, act->nvlst, indent + 2, firstNode); } } static int yamlActionCount(const struct rsconfTranslateYamlAction_s *actions) { int n = 0; while (actions != NULL) { ++n; actions = actions->next; } return n; } static void writeYamlActionList(FILE *fp, const struct rsconfTranslateYamlAction_s *actions, int indent) { const struct rsconfTranslateYamlAction_s *act; int i; for (act = actions; act != NULL; act = act->next) { const struct nvlst *n; const struct nvlst *firstNode = NULL; int firstRank = 4; for (n = act->nvlst; n != NULL; n = n->next) { int rank = preferredKeyRank(n); if (rank < firstRank) { firstNode = n; firstRank = rank; } } if (firstNode != NULL) { writeYamlEntry(fp, firstNode, indent, 1); } else { for (i = 0; i < indent; ++i) fputs(" ", fp); fputs("-\n", fp); } writeYamlMappingExcept(fp, act->nvlst, indent + 1, firstNode); } } static void writeYamlActionMapping(FILE *fp, const struct nvlst *lst, int indent) { const struct nvlst *n; const struct nvlst *firstNode = NULL; int firstRank = 4; for (n = lst; n != NULL; n = n->next) { int rank = preferredKeyRank(n); if (rank < firstRank) { firstNode = n; firstRank = rank; } } if (firstNode != NULL) { writeYamlEntry(fp, firstNode, indent, 0); } writeYamlMappingExcept(fp, lst, indent, firstNode); } static void writeYamlStatements(FILE *fp, const struct rsconfTranslateYamlStatement_s *stmts, int indent) { const struct rsconfTranslateYamlStatement_s *stmt; int i; for (i = 0; i < indent; ++i) fputs(" ", fp); fputs("statements:\n", fp); for (stmt = stmts; stmt != NULL; stmt = stmt->next) { for (i = 0; i < indent + 1; ++i) fputs(" ", fp); fputs("- if: ", fp); writeYamlQuoted(fp, stmt->if_expr == NULL ? "" : stmt->if_expr); fputc('\n', fp); if (yamlActionCount(stmt->actions) == 1) { for (i = 0; i < indent + 2; ++i) fputs(" ", fp); fputs("action:\n", fp); writeYamlActionMapping(fp, stmt->actions->nvlst, indent + 3); } else { for (i = 0; i < indent + 2; ++i) fputs(" ", fp); fputs("then:\n", fp); writeYamlActionList(fp, stmt->actions, indent + 3); } } } static void writeYamlListSection(FILE *fp, const char *name, const struct rsconfTranslateItem_s *items) { const struct rsconfTranslateItem_s *it; if (items == NULL) return; fprintf(fp, "%s:\n", name); for (it = items; it != NULL; it = it->next) { const struct nvlst *n; const struct nvlst *firstNode = NULL; int firstRank = 4; writeWarningComments(fp, it->warnings, 1); for (n = it->nvlst; n != NULL; n = n->next) { int rank = preferredKeyRank(n); if (rank < firstRank) { firstNode = n; firstRank = rank; } } if (it->nvlst == NULL && it->script == NULL) { fputs(" -\n", fp); continue; } if (firstNode != NULL) { writeYamlEntry(fp, firstNode, 1, 1); } else { fputs(" -\n", fp); } writeYamlMappingExcept(fp, it->nvlst, 2, firstNode); if (it->subobjs != NULL) { fputs(" elements:\n", fp); for (const struct objlst *obj = it->subobjs; obj != NULL; obj = obj->next) { fprintf(fp, " - %s:\n", obj->obj->objType == CNFOBJ_PROPERTY ? "property" : "constant"); writeYamlMapping(fp, obj->obj->nvlst, 4); } } if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_FILTER_ACTIONS && it->yaml_filter != NULL) { fputs(" filter: ", fp); writeYamlQuoted(fp, it->yaml_filter); fputc('\n', fp); writeYamlActions(fp, it->yaml_actions, 2); } else if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_ACTIONS) { writeYamlActions(fp, it->yaml_actions, 2); } else if (it->yaml_ruleset_kind == RS_TRANSLATE_YAML_RULESET_STATEMENTS) { writeYamlStatements(fp, it->yaml_statements, 2); } else if (it->script != NULL) { fputs(" script: |\n", fp); writeYamlBlockScalar(fp, it->script, 3); } } } static void writeRsParams(FILE *fp, const struct nvlst *lst) { const struct nvlst *n; char *name; int first = 1, i, rank; for (rank = 0; rank < 4; ++rank) { for (n = lst; n != NULL; n = n->next) { if (preferredKeyRank(n) != rank) continue; if (!first) fputc(' ', fp); first = 0; name = es_str2cstr(n->name, NULL); fprintf(fp, "%s=", name == NULL ? "" : name); free(name); switch (n->val.datatype) { case 'N': fprintf(fp, "%lld", n->val.d.n); break; case 'A': fputc('[', fp); for (i = 0; i < n->val.d.ar->nmemb; ++i) { char *aval = es_str2cstr(n->val.d.ar->arr[i], NULL); if (i > 0) fputs(", ", fp); writeYamlQuoted(fp, aval == NULL ? "" : aval); free(aval); } fputc(']', fp); break; case 'S': default: { char *val = es_str2cstr(n->val.d.estr, NULL); writeYamlQuoted(fp, val == NULL ? "" : val); free(val); break; } } } } } static void writeRsTemplate(FILE *fp, const struct rsconfTranslateItem_s *it) { fprintf(fp, "template("); writeRsParams(fp, it->nvlst); if (it->subobjs == NULL) { fprintf(fp, ")\n\n"); return; } fprintf(fp, ") {\n"); for (const struct objlst *obj = it->subobjs; obj != NULL; obj = obj->next) { fprintf(fp, " %s(", obj->obj->objType == CNFOBJ_PROPERTY ? "property" : "constant"); writeRsParams(fp, obj->obj->nvlst); fprintf(fp, ")\n"); } fprintf(fp, "}\n\n"); } static void writeRsList(FILE *fp, const char *keyword, const struct rsconfTranslateItem_s *items) { const struct rsconfTranslateItem_s *it; for (it = items; it != NULL; it = it->next) { writeWarningComments(fp, it->warnings, 0); if (it->objType == CNFOBJ_TPL) { writeRsTemplate(fp, it); continue; } if (it->objType == CNFOBJ_RULESET) { fprintf(fp, "ruleset("); writeRsParams(fp, it->nvlst); if (it->script != NULL) { fprintf(fp, ") {\n%s}\n\n", it->script); } else { fprintf(fp, ") {}\n\n"); } continue; } fprintf(fp, "%s(", keyword); writeRsParams(fp, it->nvlst); fprintf(fp, ")\n\n"); } } rsRetVal rsconfTranslateWriteFile(const char *path) { FILE *fp = NULL; DEFiRet; if (!rsconfTranslateEnabled()) { FINALIZE; } if (g_tx.fatal) { logAllWarnings(); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (path == NULL || !strcmp(path, "-")) { fp = stdout; } else { fp = fopen(path, "w"); } if (fp == NULL) { ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } if (g_tx.fmt == RSCONF_TRANSLATE_YAML) { fputs("version: 2\n\n", fp); writeWarningComments(fp, g_tx.globalWarnings, 0); if (g_tx.globals != NULL) { writeWarningComments(fp, g_tx.globals->warnings, 0); fputs("global:\n", fp); writeYamlMapping(fp, g_tx.globals->nvlst, 1); fputc('\n', fp); } if (g_tx.mainqueue != NULL) { writeWarningComments(fp, g_tx.mainqueue->warnings, 0); fputs("mainqueue:\n", fp); writeYamlMapping(fp, g_tx.mainqueue->nvlst, 1); fputc('\n', fp); } writeYamlListSection(fp, "modules", g_tx.modules); writeYamlListSection(fp, "inputs", g_tx.inputs); writeYamlListSection(fp, "templates", g_tx.templates); writeYamlListSection(fp, "rulesets", g_tx.rulesets); writeYamlListSection(fp, "lookup_tables", g_tx.lookups); writeYamlListSection(fp, "parsers", g_tx.parsers); writeYamlListSection(fp, "timezones", g_tx.timezones); writeYamlListSection(fp, "dyn_stats", g_tx.dynstats); writeYamlListSection(fp, "perctile_stats", g_tx.perctilestats); writeYamlListSection(fp, "ratelimits", g_tx.ratelimits); } else { writeWarningComments(fp, g_tx.globalWarnings, 0); writeRsList(fp, "global", g_tx.globals); writeRsList(fp, "main_queue", g_tx.mainqueue); writeRsList(fp, "module", g_tx.modules); writeRsList(fp, "input", g_tx.inputs); writeRsList(fp, "template", g_tx.templates); writeRsList(fp, "lookup_table", g_tx.lookups); writeRsList(fp, "parser", g_tx.parsers); writeRsList(fp, "timezone", g_tx.timezones); writeRsList(fp, "dyn_stats", g_tx.dynstats); writeRsList(fp, "perctile_stats", g_tx.perctilestats); writeRsList(fp, "ratelimit", g_tx.ratelimits); writeRsList(fp, "ruleset", g_tx.rulesets); } finalize_it: if (fp != NULL && fp != stdout) fclose(fp); RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/glbl.h0000644000000000000000000000013215241075234015316 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.274722819 rsyslog-8.2608.0/runtime/glbl.h0000664000175000017500000001707115241075234014770 0ustar00rgerrger/* Definition of globally-accessible data items. * * This module provides access methods to items of global scope. Most often, * these globals serve as defaults to initialize local settings. Currently, * many of them are either constants or global variable references. However, * this module provides the necessary hooks to change that at any time. * * Please note that there currently is no glbl.c file as we do not yet * have any implementations. * * Copyright 2008-2024 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef GLBL_H_INCLUDED #define GLBL_H_INCLUDED #include #include #ifdef ENABLE_LIBLOGGING_STDLOG #include #endif #include "rainerscript.h" #include "prop.h" #define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */ #define glblOversizeMsgInputMode_Truncate 0 #define glblOversizeMsgInputMode_Split 1 #define glblOversizeMsgInputMode_Accept 2 extern pid_t glbl_ourpid; /* interfaces */ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */ uchar *(*GetWorkDir)(rsconf_t *cnf); int (*GetMaxLine)(rsconf_t *cnf); #define SIMP_PROP(name, dataType) \ dataType (*Get##name)(void); \ rsRetVal (*Set##name)(dataType) SIMP_PROP(OptimizeUniProc, int); SIMP_PROP(PreserveFQDN, int); SIMP_PROP(LocalFQDNName, uchar *); SIMP_PROP(mainqCnfObj, struct cnfobj *); SIMP_PROP(LocalHostName, uchar *); SIMP_PROP(LocalDomain, uchar *); /* added v3, 2009-06-30 */ rsRetVal (*GenerateLocalHostNameProperty)(void); prop_t *(*GetLocalHostNameProp)(void); /* added v4, 2009-07-20 */ int (*GetGlobalInputTermState)(void); void (*SetGlobalInputTermination)(void); /* added v5, 2009-11-03 */ /* note: v4, v5 are already used by more recent versions, so we need to skip them! */ /* added v6, 2009-11-16 as part of varmojfekoj's "unlimited select()" patch * Note that it must be always present, otherwise the interface would have different * versions depending on compile settings, what is not acceptable. * Use this property with care, it is only truly available if UNLIMITED_SELECT is enabled * (I did not yet further investigate the details, because that code hopefully can be removed * at some later stage). */ SIMP_PROP(FdSetSize, int); /* v7: was neeeded to mean v5+v6 - do NOT add anything else for that version! */ /* next change is v9! */ /* v8 - 2012-03-21 */ prop_t *(*GetLocalHostIP)(void); uchar *(*GetSourceIPofLocalClient)(void); /* [ar] */ rsRetVal (*SetSourceIPofLocalClient)(uchar *); /* [ar] */ /* v9 - 2015-01-12 SetMaxLine method removed */ /* v10 - global variables should be moved to the rsconf_t data structure, so * dynamic configuration reload can be introduced. This is why each getter needs additional * parameter specifying a configuration it belongs to(either loadConf or runConf) */ #undef SIMP_PROP #define SIMP_PROP(name, dataType) \ dataType (*Get##name)(rsconf_t * cnf); \ rsRetVal (*Set##name)(dataType) SIMP_PROP(DropMalPTRMsgs, int); SIMP_PROP(DfltNetstrmDrvrCAF, uchar *); SIMP_PROP(DfltNetstrmDrvrCRLF, uchar *); SIMP_PROP(DfltNetstrmDrvrCertFile, uchar *); SIMP_PROP(DfltNetstrmDrvrKeyFile, uchar *); SIMP_PROP(DfltNetstrmDrvr, uchar *); SIMP_PROP(DfltOpensslEngine, uchar *); SIMP_PROP(DefPFFamily, int); SIMP_PROP(DisableDNS, int); SIMP_PROP(NetstrmDrvrCAExtraFiles, uchar *); SIMP_PROP(ParserControlCharacterEscapePrefix, uchar); SIMP_PROP(ParserDropTrailingLFOnReception, int); SIMP_PROP(ParserDropTrailingCROnReception, int); SIMP_PROP(ParserEscapeControlCharactersOnReceive, int); SIMP_PROP(ParserSpaceLFOnReceive, int); SIMP_PROP(ParserEscape8BitCharactersOnReceive, int); SIMP_PROP(ParserEscapeControlCharacterTab, int); SIMP_PROP(ParserEscapeControlCharactersCStyle, int); SIMP_PROP(ParseHOSTNAMEandTAG, int); SIMP_PROP(OptionDisallowWarning, int); #undef SIMP_PROP ENDinterface(glbl) #define glblCURR_IF_VERSION 11 /* increment whenever you change the interface structure! */ /* version 2 had PreserveFQDN added - rgerhards, 2008-12-08 */ /* the remaining prototypes */ PROTOTYPEObj(glbl); extern int glblJsonFormatOpt; extern int glblUnloadModules; extern short janitorInterval; extern char **glblDbgFiles; extern size_t glblDbgFilesNum; extern int glblDbgWhitelist; extern int glblPermitCtlC; extern int glblAbortOnProgramError; extern int bTerminateInputs; extern volatile sig_atomic_t bTerminateInputsSigSafe; #ifndef HAVE_ATOMIC_BUILTINS extern DEF_ATOMIC_HELPER_MUT(mutTerminateInputs); #endif /* Developer options enable some strange things for developer-only testing. * These should never be enabled in a user build, except if explicitly told * by a developer. The options are acutally flags, so they should be powers * of two. Flag assignment may change between versions, **backward * compatibility is NOT necessary**. * rgerhards, 2018-04-28 */ #define DEV_OPTION_KEEP_RUNNING_ON_HARD_CONF_ERROR 1 #define DEV_OPTION_8_1905_HANG_TEST 2 // TODO: remove - temporary for bughunt #define glblGetOurPid() glbl_ourpid #define glblSetOurPid(pid) \ { glbl_ourpid = (pid); } void glblPrepCnf(void); void glblProcessCnf(struct cnfobj *o); void glblProcessMainQCnf(struct cnfobj *o); void glblDestructMainqCnfObj(void); rsRetVal glblDoneLoadCnf(void); const uchar *glblGetWorkDirRaw(rsconf_t *cnf); int GetGnuTLSLoglevel(rsconf_t *cnf); int glblGetMaxLine(rsconf_t *cnf); int bs_arrcmp_glblDbgFiles(const void *s1, const void *s2); uchar *glblGetOversizeMsgErrorFile(rsconf_t *cnf); const uchar *glblGetOperatingStateFile(rsconf_t *cnf); int glblGetOversizeMsgInputMode(rsconf_t *cnf); int glblReportOversizeMessage(rsconf_t *cnf); void glblReportChildProcessExit(rsconf_t *cnf, const uchar *name, pid_t pid, int status); uchar *glblGetLocalHostName(void); rsRetVal glblSetMaxOpenFiles(void *pVal, int iFiles); /** Check whether a legacy $-directive may be processed under the active compatibility policy. */ int glblPermitLegacyConfigDirective(rsconf_t *cnf, const char *directive); /** Check whether a classic syslogd PRI selector may be processed under the active compatibility policy. */ int glblPermitSyslogdConfigFilter(rsconf_t *cnf, const char *filter); /** Check whether a classic property-based selector filter may be processed under the active compatibility policy. */ int glblPermitPropertyConfigFilter(rsconf_t *cnf, const char *filter); /** Emit an insecure-default warning when compatibility.defaults.secure is set to warn. */ void glblWarnIfInsecureDefault(rsconf_t *cnf, const char *detail); /** Return local stream driver name or the configured global default. */ const uchar *glblGetEffectiveNetstrmDrvr(rsconf_t *cnf, const uchar *localDrvr); /** Check whether a netstream driver name selects a TLS-capable driver. */ int glblIsTlsCapableNetstrmDrvr(const uchar *drvr); #endif /* #ifndef GLBL_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/lmsig_ksi-ls12.h0000644000000000000000000000013215145046112017132 xustar0030 mtime=1771326538.992013521 30 atime=1782715518.784788772 30 ctime=1787067794.580728521 rsyslog-8.2608.0/runtime/lmsig_ksi-ls12.h0000664000175000017500000000267315145046112016606 0ustar00rgerrger/* An implementation of the sigprov interface for KSI-LS12. * * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LMSIG_LS12_KSI_H #define INCLUDED_LMSIG_LS12_KSI_H #include "sigprov.h" #include "lib_ksils12.h" /* interface is defined in sigprov.h, we just implement it! */ #define lmsig_ksi_ls12CURR_IF_VERSION sigprovCURR_IF_VERSION typedef sigprov_if_t lmsig_ksi_ls12_if_t; /* the lmsig_ksi object */ struct lmsig_ksi_ls12_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ rsksictx ctx; /* librsksi context - contains all we need */ }; typedef struct lmsig_ksi_ls12_s lmsig_ksi_ls12_t; /* prototypes */ PROTOTYPEObjFull(lmsig_ksi_ls12); #endif /* #ifndef INCLUDED_LMSIG_LS12_KSI_H */ rsyslog-8.2608.0/runtime/PaxHeaders/hashtable.h0000644000000000000000000000013215241075234016331 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.482726695 rsyslog-8.2608.0/runtime/hashtable.h0000664000175000017500000002016415241075234016000 0ustar00rgerrger/* Copyright (C) 2002 Christopher Clark */ #ifndef __HASHTABLE_CWC22_H__ #define __HASHTABLE_CWC22_H__ struct hashtable; /* Example of use: * * struct hashtable *h; * struct some_key *k; * struct some_value *v; * * static unsigned int hash_from_key_fn( void *k ); * static int keys_equal_fn ( void *key1, void *key2 ); * * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); * k = (struct some_key *) malloc(sizeof(struct some_key)); * v = (struct some_value *) malloc(sizeof(struct some_value)); * * (initialise k and v to suitable values) * * if (! hashtable_insert(h,k,v) ) * { exit(-1); } * * if (NULL == (found = hashtable_search(h,k) )) * { printf("not found!"); } * * if (NULL == (found = hashtable_remove(h,k) )) * { printf("Not found\n"); } * */ /* Macros may be used to define type-safe(r) hashtable access functions, with * methods specialized to take known key and value types as parameters. * * Example: * * Insert this at the start of your file: * * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); * * This defines the functions 'insert_some', 'search_some' and 'remove_some'. * These operate just like hashtable_insert etc., with the same parameters, * but their function signatures have 'struct some_key *' rather than * 'void *', and hence can generate compile time errors if your program is * supplying incorrect data as a key (and similarly for value). * * Note that the hash and key equality functions passed to create_hashtable * still take 'void *' parameters instead of 'some key *'. This shouldn't be * a difficult issue as they're only defined and passed once, and the other * functions will ensure that only valid keys are supplied to them. * * The cost for this checking is increased code size and runtime overhead * - if performance is important, it may be worth switching back to the * unsafe methods once your program has been debugged with the safe methods. * This just requires switching to some simple alternative defines - eg: * #define insert_some hashtable_insert * */ /***************************************************************************** * create_hashtable * @name create_hashtable * @param minsize minimum initial size of hashtable * @param hashfunction function for hashing keys * @param key_eq_fn function for determining key equality * @param dest destructor for value entries (NULL -> use free()) * @return newly created hashtable or NULL on failure */ struct hashtable *create_hashtable(unsigned int minsize, unsigned int (*hashfunction)(void *), int (*key_eq_fn)(void *, void *), void (*dest)(void *)); /***************************************************************************** * hashtable_insert * @name hashtable_insert * @param h the hashtable to insert into * @param k the key - hashtable claims ownership and will free on removal * @param v the value - does not claim ownership * @return non-zero for successful insertion * * This function will cause the table to expand if the insertion would take * the ratio of entries to table size over the maximum load factor. * * This function does not check for repeated insertions with a duplicate key. * The value returned when using a duplicate key is undefined -- when * the hashtable changes size, the order of retrieval of duplicate key * entries is reversed. * If in doubt, remove before insert. */ int hashtable_insert(struct hashtable *h, void *k, void *v); /* Return the internal, mixed hash value used by this hashtable. The * prehashed APIs below require a value returned by this function for a table * with the same hash function; callers must not pass raw hashfn output. */ unsigned int hashtable_hash(struct hashtable *h, void *k); int hashtable_insert_prehashed(struct hashtable *h, unsigned int hashvalue, void *k, void *v); #define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ int fnname(struct hashtable *h, keytype *k, valuetype *v) { \ return hashtable_insert(h, k, v); \ } /***************************************************************************** * hashtable_search * @name hashtable_search * @param h the hashtable to search * @param k the key to search for - does not claim ownership * @return the value associated with the key, or NULL if none found */ void *hashtable_search(struct hashtable *h, void *k); void *hashtable_search_prehashed(struct hashtable *h, unsigned int hashvalue, void *k); #define DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ valuetype *fnname(struct hashtable *h, keytype *k) { \ return (valuetype *)(hashtable_search(h, k)); \ } /***************************************************************************** * hashtable_remove * @name hashtable_remove * @param h the hashtable to remove the item from * @param k the key to search for - does not claim ownership * @return the value associated with the key, or NULL if none found */ void * /* returns value */ hashtable_remove(struct hashtable *h, void *k); void * /* returns value */ hashtable_remove_prehashed(struct hashtable *h, unsigned int hashvalue, void *k); #define DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ valuetype *fnname(struct hashtable *h, keytype *k) { \ return (valuetype *)(hashtable_remove(h, k)); \ } /***************************************************************************** * hashtable_count * @name hashtable_count * @param h the hashtable * @return the number of items stored in the hashtable */ unsigned int hashtable_count(struct hashtable *h); /***************************************************************************** * hashtable_destroy * @name hashtable_destroy * @param h the hashtable * @param free_values whether to call 'free' on the remaining values */ void hashtable_destroy(struct hashtable *h, int free_values); /* * Copyright (c) 2002, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ unsigned __attribute__((nonnull(1))) int hash_from_string(void *k); int key_equals_string(void *key1, void *key2); #endif /* __HASHTABLE_CWC22_H__ */ rsyslog-8.2608.0/runtime/PaxHeaders/lmsig_ksi-ls12.c0000644000000000000000000000013015216464436017137 xustar0028 mtime=1782212894.0272662 30 atime=1782715518.783788755 30 ctime=1787067794.578728484 rsyslog-8.2608.0/runtime/lmsig_ksi-ls12.c0000664000175000017500000003225415216464436016613 0ustar00rgerrger/* lmsig_ksi-ls12.c * * An implementation of the sigprov interface for KSI-LS12. * * Copyright 2013-2017 Adiscon GmbH and Guardtime, Inc. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "sigprov.h" #include "lmsig_ksi-ls12.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfpdescr[] = { {"sig.hashfunction", eCmdHdlrGetWord, 0}, {"sig.aggregator.url", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"sig.aggregator.user", eCmdHdlrGetWord, 0}, {"sig.aggregator.key", eCmdHdlrGetWord, 0}, {"sig.aggregator.hmacAlg", eCmdHdlrGetWord, 0}, {"sig.block.levelLimit", eCmdHdlrSize, CNFPARAM_REQUIRED}, {"sig.block.timeLimit", eCmdHdlrInt, 0}, {"sig.block.signtimeout", eCmdHdlrInt, 0}, {"sig.confinterval", eCmdHdlrInt, 0}, {"sig.keeprecordhashes", eCmdHdlrBinary, 0}, {"sig.keeptreehashes", eCmdHdlrBinary, 0}, {"sig.fileformat", eCmdHdlrString, 0}, {"sig.syncmode", eCmdHdlrString, 0}, {"sig.randomsource", eCmdHdlrString, 0}, {"sig.debugfile", eCmdHdlrString, 0}, {"sig.debuglevel", eCmdHdlrInt, 0}, {"dirowner", eCmdHdlrUID, 0}, /* legacy: dirowner */ {"dirownernum", eCmdHdlrInt, 0}, /* legacy: dirownernum */ {"dirgroup", eCmdHdlrGID, 0}, /* legacy: dirgroup */ {"dirgroupnum", eCmdHdlrInt, 0}, /* legacy: dirgroupnum */ {"fileowner", eCmdHdlrUID, 0}, /* legacy: fileowner */ {"fileownernum", eCmdHdlrInt, 0}, /* legacy: fileownernum */ {"filegroup", eCmdHdlrGID, 0}, /* legacy: filegroup */ {"filegroupnum", eCmdHdlrInt, 0}, /* legacy: filegroupnum */ {"dircreatemode", eCmdHdlrFileCreateMode, 0}, /* legacy: dircreatemode */ {"filecreatemode", eCmdHdlrFileCreateMode, 0} /* legacy: filecreatemode */ }; static struct cnfparamblk pblk = {CNFPARAMBLK_VERSION, sizeof(cnfpdescr) / sizeof(struct cnfparamdescr), cnfpdescr}; static void errfunc(__attribute__((unused)) void *usrptr, uchar *emsg) { LogError(0, RS_RET_SIGPROV_ERR, "KSI Signature Provider" "Error: %s", emsg); } static void logfunc(__attribute__((unused)) void *usrptr, uchar *emsg) { LogMsg(0, RS_RET_NO_ERRCODE, LOG_INFO, "KSI/LS12 Signature Provider: %s", emsg); } /* Standard-Constructor */ BEGINobjConstruct(lmsig_ksi_ls12) pThis->ctx = rsksiCtxNew(); rsksisetErrFunc(pThis->ctx, errfunc, NULL); rsksisetLogFunc(pThis->ctx, logfunc, NULL); ENDobjConstruct(lmsig_ksi_ls12) /* destructor for the lmsig_ksi object */ BEGINobjDestruct(lmsig_ksi_ls12) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(lmsig_ksi_ls12); rsksiCtxDel(pThis->ctx); ENDobjDestruct(lmsig_ksi_ls12) /* apply all params from param block to us. This must be called * after construction, but before the OnFileOpen() entry point. * Defaults are expected to have been set during construction. */ static rsRetVal SetCnfParam(void *pT, struct nvlst *lst) { char *ag_uri = NULL, *ag_loginid = NULL, *ag_key = NULL; char *hash = NULL, *hmac = NULL; lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t *)pT; int i; uchar *cstr; struct cnfparamvals *pvals; DEFiRet; pvals = nvlstGetParams(lst, &pblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_ERR, "Failed to load configuration - signing disabled"); pThis->ctx->disabled = true; ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("sig param blk in lmsig_ksi:\n"); cnfparamsPrint(&pblk, pvals); } for (i = 0; i < pblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblk.descr[i].name, "sig.hashfunction")) { CHKmalloc(hash = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.url")) { CHKmalloc(ag_uri = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.user")) { CHKmalloc(ag_loginid = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.key")) { CHKmalloc(ag_key = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "sig.aggregator.hmacAlg")) { CHKmalloc(hmac = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "sig.block.levelLimit")) { if (pvals[i].val.d.n < 2) { LogError(0, RS_RET_ERR, "sig.block.levelLimit " "%llu invalid - signing disabled", pvals[i].val.d.n); pThis->ctx->disabled = true; } else { rsksiSetBlockLevelLimit(pThis->ctx, pvals[i].val.d.n); } } else if (!strcmp(pblk.descr[i].name, "sig.block.timeLimit")) { if (pvals[i].val.d.n < 0) { LogError(0, RS_RET_ERR, "sig.block.timeLimit " "%llu invalid - signing disabled", pvals[i].val.d.n); pThis->ctx->disabled = true; } else { rsksiSetBlockTimeLimit(pThis->ctx, pvals[i].val.d.n); } } else if (!strcmp(pblk.descr[i].name, "sig.confinterval")) { if (pvals[i].val.d.n < 0) { LogError(0, RS_RET_ERR, "sig.confinterval " "%llu invalid - signing disabled", pvals[i].val.d.n); pThis->ctx->disabled = true; } else { rsksiSetConfInterval(pThis->ctx, pvals[i].val.d.n); } } else if (!strcmp(pblk.descr[i].name, "sig.keeprecordhashes")) { rsksiSetKeepRecordHashes(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "sig.block.signtimeout")) { if (pvals[i].val.d.n < 0) { LogError(0, RS_RET_ERR, "sig.block.signtimeout " "%llu invalid - signing disabled", pvals[i].val.d.n); pThis->ctx->disabled = true; } else { rsksiSetBlockSigTimeout(pThis->ctx, pvals[i].val.d.n); } } else if (!strcmp(pblk.descr[i].name, "sig.keeptreehashes")) { rsksiSetKeepTreeHashes(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "sig.syncmode")) { CHKmalloc(cstr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcasecmp((char *)cstr, "sync")) rsksiSetSyncMode(pThis->ctx, LOGSIG_SYNCHRONOUS); else if (!strcasecmp((char *)cstr, "async")) rsksiSetSyncMode(pThis->ctx, LOGSIG_ASYNCHRONOUS); else LogError(0, RS_RET_ERR, "sig.syncmode '%s' unknown - using default", cstr); free(cstr); } else if (!strcmp(pblk.descr[i].name, "sig.randomsource")) { CHKmalloc(cstr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); rsksiSetRandomSource(pThis->ctx, (char *)cstr); free(cstr); } else if (!strcmp(pblk.descr[i].name, "sig.debugfile")) { CHKmalloc(cstr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); rsksiSetDebugFile(pThis->ctx, (char *)cstr); free(cstr); } else if (!strcmp(pblk.descr[i].name, "sig.debuglevel")) { rsksiSetDebugLevel(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "dirowner")) { rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "dirownernum")) { rsksiSetDirUID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "dirgroup")) { rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "dirgroupnum")) { rsksiSetDirGID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "fileowner")) { rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "fileownernum")) { rsksiSetFileUID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "filegroup")) { rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "filegroupnum")) { rsksiSetFileGID(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "dircreatemode")) { rsksiSetDirCreateMode(pThis->ctx, pvals[i].val.d.n); } else if (!strcmp(pblk.descr[i].name, "filecreatemode")) { rsksiSetCreateMode(pThis->ctx, pvals[i].val.d.n); } else { DBGPRINTF( "lmsig_ksi: program error, non-handled " "param '%s'\n", pblk.descr[i].name); } } if (rsksiSetHashFunction(pThis->ctx, hash ? hash : (char *)"default") != KSI_OK) { ABORT_FINALIZE(RS_RET_KSI_ERR); } if (rsksiSetHmacFunction(pThis->ctx, hmac ? hmac : (char *)"default") != KSI_OK) { ABORT_FINALIZE(RS_RET_KSI_ERR); } if (rsksiSetAggregator(pThis->ctx, ag_uri, ag_loginid, ag_key) != KSI_OK) { ABORT_FINALIZE(RS_RET_KSI_ERR); } finalize_it: free(ag_uri); free(ag_loginid); free(ag_key); free(hash); free(hmac); if (pvals != NULL) cnfparamvalsDestruct(pvals, &pblk); RETiRet; } static rsRetVal OnFileOpen(void *pT, uchar *fn, void *pGF) { lmsig_ksi_ls12_t *pThis = (lmsig_ksi_ls12_t *)pT; ksifile *pgf = (ksifile *)pGF; DEFiRet; /* note: if *pgf is set to NULL, this auto-disables GT functions */ *pgf = rsksiCtxOpenFile(pThis->ctx, fn); sigblkInitKSI(*pgf); RETiRet; } /* Note: we assume that the record is terminated by a \n. * As of the GuardTime paper, \n is not part of the signed * message, so we subtract one from the record size. This * may cause issues with non-standard formats, but let's * see how things evolve (the verifier will not work in * any case when the records are not \n delimited...). * rgerhards, 2013-03-17 */ static rsRetVal OnRecordWrite(void *pF, uchar *rec, rs_size_t lenRec) { const rs_size_t payloadLen = (lenRec > 0) ? (lenRec - 1) : 0; const int printLen = (payloadLen > (rs_size_t)INT_MAX) ? INT_MAX : (int)payloadLen; DEFiRet; if (rec == NULL) { DBGPRINTF("lmsig_ksi-ls12: onRecordWrite (%lu): (null)\n", (unsigned long)payloadLen); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } DBGPRINTF("lmsig_ksi-ls12: onRecordWrite (%lu): %.*s\n", (unsigned long)payloadLen, printLen, rec); sigblkAddRecordKSI(pF, rec, payloadLen); finalize_it: RETiRet; } static rsRetVal OnFileClose(void *pF) { DEFiRet; DBGPRINTF("lmsig_ksi_ls12: onFileClose\n"); rsksifileDestruct(pF); RETiRet; } BEGINobjQueryInterface(lmsig_ksi_ls12) CODESTARTobjQueryInterface(lmsig_ksi_ls12); if (pIf->ifVersion != sigprovCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } pIf->Construct = (rsRetVal(*)(void *))lmsig_ksi_ls12Construct; pIf->SetCnfParam = SetCnfParam; pIf->Destruct = (rsRetVal(*)(void *))lmsig_ksi_ls12Destruct; pIf->OnFileOpen = OnFileOpen; pIf->OnRecordWrite = OnRecordWrite; pIf->OnFileClose = OnFileClose; finalize_it: ENDobjQueryInterface(lmsig_ksi_ls12) BEGINObjClassExit(lmsig_ksi_ls12, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(lmsig_ksi_ls12); /* release objects we no longer need */ objRelease(glbl, CORE_COMPONENT); ENDObjClassExit(lmsig_ksi_ls12) BEGINObjClassInit(lmsig_ksi_ls12, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDObjClassInit(lmsig_ksi_ls12) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; lmsig_ksi_ls12ClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CHKiRet(lmsig_ksi_ls12ClassInit(pModInfo)); ENDmodInit rsyslog-8.2608.0/runtime/PaxHeaders/tcps_sess.h0000644000000000000000000000013215241075234016404 xustar0030 mtime=1787067036.611578407 30 atime=1787067036.758581159 30 ctime=1787067794.602728931 rsyslog-8.2608.0/runtime/tcps_sess.h0000664000175000017500000001256415241075234016060 0ustar00rgerrger/* Definitions for tcps_sess class. This implements a session of the * plain TCP server. * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_TCPS_SESS_H #define INCLUDED_TCPS_SESS_H #include "rsyslog.h" #include "obj.h" #include "prop.h" #include /* a forward-definition, we are somewhat cyclic */ struct tcpsrv_s; #define TCPSRV_COMPRESS_NEVER 0 #define TCPSRV_COMPRESS_STREAM_ALWAYS 2 #define TCPSRV_COMPRESS_DRIVER_ZLIB 0 #define TCPSRV_COMPRESS_DRIVER_ZSTD 1 #define TCPSRV_COMPRESS_MAX_EXPANSION_RATIO_DEFAULT 1024 #define TCPSRV_COMPRESS_MAX_DECOMPRESSED_BYTES_PER_RECEIVE_DEFAULT (64ULL * 1024ULL * 1024ULL) #define TCPSRV_COMPRESS_MAX_TOTAL_ZSTD_WINDOW_BYTES_DEFAULT 0 #define TCPSRV_ZSTD_FRAME_HEADER_MAX 18 /* the tcps_sess object */ struct tcps_sess_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ tcpsrv_t *pSrv; /* pointer back to my server (e.g. for callbacks) */ tcpLstnPortList_t *pLstnInfo; /* pointer back to listener info */ netstrm_t *pStrm; int iMsg; /* index of next char to store in msg */ sbool bSuppOctetFram; /**< copy from listener, to speed up access */ sbool bSPFramingFix; enum { eAtStrtFram, eInOctetCnt, eInMsg, eInMsgTruncating, eInMsgCheckMultiLine } inputState; /* our current state */ sbool bFrameOversize; /* current frame exceeded maxMessageSize before submit */ int iOctetsRemain; /* Number of Octets remaining in message */ TCPFRAMINGMODE eFraming; uchar *pMsg; /* message (fragment) received */ prop_t *fromHost; /* host name we received messages from */ prop_t *fromHostIP; prop_t *fromHostPort; int iCurrLine; /* 2nd char of current line in regex framing mode */ uchar *pMsg_save; /* message (fragment) save area in regex framing mode */ void *pUsr; /* a user-pointer */ rsRetVal (*DoSubmitMessage)(tcps_sess_t *, uchar *, int); /* submit message callback */ int iMaxLine; /* fast lookup buffer for config property */ pthread_mutex_t mut; unsigned tlsProbeBytes; /**< number of bytes collected for TLS client detection */ uchar tlsProbeBuf[5]; /**< first bytes received for TLS client detection */ sbool tlsProbeDone; /**< indicates TLS client detection has been completed */ sbool tlsMismatchWarned; /**< avoids logging the same TLS mismatch twice */ uint8_t compressionMode; uint8_t compressionDriver; uint64_t compressionMaxExpansionRatio; uint64_t compressionMaxDecompressedBytesPerReceive; uint64_t compressionMaxTotalZstdWindowBytes; uint64_t compressionTotalBytesIn; uint64_t compressionTotalBytesOut; sbool zipInitDone; sbool compressedStreamEnded; sbool compressedStreamFailed; sbool streamDecompressed; z_stream zstrm; void *zstdDctx; uchar zstd_frame_header[TCPSRV_ZSTD_FRAME_HEADER_MAX]; size_t zstd_frame_header_len; sbool zstd_frame_header_processed; uint64_t zstd_window_reservation; }; /* interfaces */ BEGINinterface(tcps_sess) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(tcps_sess); rsRetVal (*Construct)(tcps_sess_t **ppThis); rsRetVal (*ConstructFinalize)(tcps_sess_t __attribute__((unused)) * pThis); rsRetVal (*Destruct)(tcps_sess_t **ppThis); rsRetVal (*PrepareClose)(tcps_sess_t *pThis); rsRetVal (*Close)(tcps_sess_t *pThis); rsRetVal (*DataRcvd)(tcps_sess_t *pThis, char *pData, size_t iLen); /* set methods */ rsRetVal (*SetTcpsrv)(tcps_sess_t *pThis, struct tcpsrv_s *pSrv); rsRetVal (*SetLstnInfo)(tcps_sess_t *pThis, tcpLstnPortList_t *pLstnInfo); rsRetVal (*SetUsrP)(tcps_sess_t *, void *); rsRetVal (*SetHost)(tcps_sess_t *pThis, uchar *); rsRetVal (*SetHostIP)(tcps_sess_t *pThis, prop_t *); rsRetVal (*SetHostPort)(tcps_sess_t *pThis, prop_t *); rsRetVal (*SetStrm)(tcps_sess_t *pThis, netstrm_t *); rsRetVal (*SetMsgIdx)(tcps_sess_t *pThis, int); rsRetVal (*SetOnMsgReceive)(tcps_sess_t *pThis, rsRetVal (*OnMsgReceive)(tcps_sess_t *, uchar *, int)); ENDinterface(tcps_sess) #define tcps_sessCURR_IF_VERSION 4 /* increment whenever you change the interface structure! */ /* interface changes * to version v2, rgerhards, 2009-05-22 * - Data structures changed * - SetLstnInfo entry point added * version 3, rgerhards, 2013-01-21: * - signature of SetHostIP() changed * version 4, 2025-01-??: * - SetHostPort() entry point added */ /* prototypes */ PROTOTYPEObjFull(tcps_sess); PROTOTYPEObjDebugPrint(tcps_sess); #endif /* #ifndef INCLUDED_TCPS_SESS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/template.h0000644000000000000000000000013215241075234016211 xustar0030 mtime=1787067036.612578425 30 atime=1787067036.759581178 30 ctime=1787067794.498726993 rsyslog-8.2608.0/runtime/template.h0000664000175000017500000002304015241075234015654 0ustar00rgerrger/* This is the header for template processing code of rsyslog. * begun 2004-11-17 rgerhards * * Copyright (C) 2004-2013 by Rainer Gerhards and Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Note: there is a tiny bit of code left where I could not get any response * from the author if this code can be placed under ASL2.0. I have guarded this * with #ifdef STRICT_GPLV3. Only if that macro is defined, the code will be * compiled. Otherwise this feature is not present. The plan is to do a * different implementation in the future to get rid of this problem. * rgerhards, 2012-08-25 */ #ifndef TEMPLATE_H_INCLUDED #define TEMPLATE_H_INCLUDED 1 #include #include #include "regexp.h" #include "stringbuf.h" struct tplJsonNode; struct template { struct template *pNext; char *pszName; int iLenName; rsRetVal (*pStrgen)(const smsg_t *const, actWrkrIParams_t *const iparam); sbool bHaveSubtree; msgPropDescr_t subtree; /* subtree property name for subtree-type templates */ int tpenElements; /* number of elements in templateEntry list */ struct templateEntry *pEntryRoot; struct templateEntry *pEntryLast; char optFormatEscape; /* in text fields, */ #define NO_ESCAPE 0 /* 0 - do not escape, */ #define SQL_ESCAPE 1 /* 1 - escape "the MySQL way" */ #define STDSQL_ESCAPE 2 /* 2 - escape quotes by double quotes, */ #define JSON_ESCAPE 3 /* 3 - escape double quotes for JSON. */ #define JSONF 4 /* 4 - not a real escape - template contains json fields only */ /* following are options. All are 0/1 defined (either on or off). * we use chars because they are faster than bit fields and smaller * than short... */ char optCaseSensitive; /* case-sensitive variable property references, default False, 0 */ char bJsonTreeEnabled; struct tplJsonNode *pJsonRoot; char bJsonTreeBuilt; unsigned bUsedAsDynafile : 1; /**< template renders an omfile dynamic file name */ unsigned bUsedAsNonDynafile : 1; /**< template also has a non-dynafile use */ unsigned bWarnedDynafileMixedUse : 1; /**< mixed-use warning was already emitted */ unsigned bWarnedDynafileSecureDefault : 1; /**< warn-mode notice was already emitted */ unsigned bAppliedDynafileSecureDefault : 1; /**< strict-mode default was already applied */ }; enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 }; enum tplFormatTypes { tplFmtDefault = 0, tplFmtMySQLDate = 1, tplFmtRFC3164Date = 2, tplFmtRFC3339Date = 3, tplFmtPgSQLDate = 4, tplFmtSecFrac = 5, tplFmtRFC3164BuggyDate = 6, tplFmtUnixDate = 7, tplFmtWDayName = 8, tplFmtYear = 9, tplFmtMonth = 10, tplFmtDay = 11, tplFmtHour = 12, tplFmtMinute = 13, tplFmtSecond = 14, tplFmtTZOffsHour = 15, tplFmtTZOffsMin = 16, tplFmtTZOffsDirection = 17, tplFmtWDay = 18, tplFmtOrdinal = 19, tplFmtWeek = 20, tplFmtISOWeek = 21, tplFmtISOWeekYear = 22 }; enum tplFormatCaseConvTypes { tplCaseConvNo = 0, tplCaseConvUpper = 1, tplCaseConvLower = 2 }; enum tplRegexType { TPL_REGEX_BRE = 0, /* posix BRE */ TPL_REGEX_ERE = 1 /* posix ERE */ }; #define TPL_REGEX_MAX_MATCHES 10 #include "msg.h" /* a specific parse entry */ struct templateEntry { struct templateEntry *pNext; enum EntryTypes eEntryType; uchar *fieldName; /**< field name to be used for structured output */ int lenFieldName; sbool bComplexProcessing; /**< set if complex processing (options, etc) is required */ union { struct { uchar *pConstant; /* pointer to constant value */ int iLenConstant; /* its length */ unsigned bJSONf : 1; /* constant uses jsonf formatting */ } constant; struct { msgPropDescr_t msgProp; /* property to be used */ unsigned iFromPos; /* for partial strings only chars from this position ... */ unsigned iToPos; /* up to that one... */ unsigned iFieldNr; /* for field extraction: field to extract */ #ifdef FEATURE_REGEXP regex_t re; /* APR: this is the regular expression */ short has_regex; short iMatchToUse; /* which match should be obtained (TPL_REGEX_MAX_MATCHES max) */ short iSubMatchToUse; /* which submatch should be obtained (TPL_REGEX_MAX_MATCHES max) */ enum tplRegexType typeRegex; enum tlpRegexNoMatchType { TPL_REGEX_NOMATCH_USE_DFLTSTR = 0, /* use the (old style) default "**NO MATCH**" string */ TPL_REGEX_NOMATCH_USE_BLANK = 1, /* use a blank string */ TPL_REGEX_NOMATCH_USE_WHOLE_FIELD = 2, /* use the full field contents that we were searching in*/ TPL_REGEX_NOMATCH_USE_ZERO = 3 /* use 0 (useful for numerical values) */ } nomatchAction; /**< what to do if we do not have a match? */ #endif unsigned has_fields; /* support for field-counting: field to extract */ unsigned char field_delim; /* support for field-counting: field delimiter char */ #ifdef STRICT_GPLV3 int field_expand; /* use multiple instances of the field delimiter as a single one? */ #endif enum tplFormatTypes eDateFormat; enum tplFormatCaseConvTypes eCaseConv; struct { /* bit fields! */ unsigned bDropCC : 1; /* drop control characters? */ unsigned bSpaceCC : 1; /* change control characters to spaceescape? */ unsigned bEscapeCC : 1; /* escape control characters? */ unsigned bEscapeCCOctal : 1; /* escape control characters as octal values? */ unsigned bCompressSP : 1; /* compress multiple spaces to a single one? */ unsigned bDropLastLF : 1; /* drop last LF char in msg (PIX!) */ unsigned bSecPathDrop : 1; /* drop slashes, replace dots, empty string */ unsigned bSecPathReplace : 1; /* replace slashes, replace dots, empty string */ unsigned bSPIffNo1stSP : 1; /* be a space if 1st pos if field is no space*/ unsigned bCSV : 1; /* format field in CSV (RFC 4180) format */ unsigned bJSON : 1; /* format field JSON escaped */ unsigned bJSONf : 1; /* format field JSON *field* (n/v pair) */ unsigned bJSONr : 1; /* format field JSON non escaped */ unsigned bJSONfr : 1; /* format field JSON *field* non escaped (n/v pair) */ unsigned bMandatory : 1; /* mandatory field - emit even if empty */ unsigned bOmitIfZero : 1; /* omit field if value is 0 */ unsigned bFromPosEndRelative : 1; /* is From/To-Pos relative to end of string? */ unsigned bFixedWidth : 1; /* space pad to toChar if string is shorter */ unsigned bDateInUTC : 1; /* should date be expressed in UTC? */ #define TPE_DATATYPE_STRING 0 #define TPE_DATATYPE_NUMBER 1 #define TPE_DATATYPE_BOOL 2 #define TPE_DATATYPE_AUTO 3 /* NOTE: bit field values exhausted! */ unsigned dataType : 2; #define TPE_DATAEMPTY_KEEP 0 #define TPE_DATAEMPTY_SKIP 1 #define TPE_DATAEMPTY_NULL 2 unsigned onEmpty : 2; } options; /* options as bit fields */ } field; } data; }; /* interfaces */ BEGINinterface(tpl) /* name must also be changed in ENDinterface macro! */ ENDinterface(tpl) #define tplCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(tpl); struct template *tplAddLine(rsconf_t *conf, const char *pName, unsigned char **pRestOfConfLine); struct template *tplFind(rsconf_t *conf, char *pName, int iLenName); int tplGetEntryCount(struct template *pTpl); void tplDeleteAll(rsconf_t *conf); void tplDeleteNew(rsconf_t *conf); void tplPrintList(rsconf_t *conf); void tplLastStaticInit(rsconf_t *conf, struct template *tpl); rsRetVal ExtendBuf(actWrkrIParams_t *const iparam, const size_t iMinSize); int tplRequiresDateCall(struct template *pTpl); void tplNoteUse(struct template *pTpl, int bDynafile); /* note: if a compiler warning for undefined type tells you to look at this * code line below, the actual cause is that you currently MUST include template.h * BEFORE msg.h, even if your code file does not actually need it. * rgerhards, 2007-08-06 */ rsRetVal tplToJSON(struct template *pTpl, smsg_t *pMsg, struct json_object **, struct syslogTime *ttNow); rsRetVal doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode); rsRetVal tplToString(struct template *__restrict__ const pTpl, smsg_t *__restrict__ const pMsg, actWrkrIParams_t *__restrict__ const iparam, struct syslogTime *const ttNow); rsRetVal templateInit(void); rsRetVal tplProcessCnf(struct cnfobj *o); #endif /* #ifndef TEMPLATE_H_INCLUDED */ /* vim:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_mbedtls.h0000644000000000000000000000013215145046113016671 xustar0030 mtime=1771326539.002013684 30 atime=1782715518.783788755 30 ctime=1787067794.551727981 rsyslog-8.2608.0/runtime/nsd_mbedtls.h0000664000175000017500000000706515145046113016345 0ustar00rgerrger/* An implementation of the nsd interface for Mbed TLS. * * Copyright 2008-2021 Adiscon GmbH. * Copyright (C) 2023 CS Group. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NSD_MBEDTLS_H #define INCLUDED_NSD_MBEDTLS_H #include #include #include #include #include #include "nsd.h" typedef nsd_if_t nsd_mbedtls_if_t; /* we just *implement* this interface */ /* the nsd_mbedtls object */ struct nsd_mbedtls_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */ uchar *pszConnectHost; /**< hostname used for connect - may be used to authenticate peer if no other name given */ const uchar *pszCAFile; const uchar *pszCRLFile; const uchar *pszKeyFile; const uchar *pszCertFile; int iMode; /* 0 - plain tcp, 1 - TLS */ int bAbortConn; /* if set, abort conncection (fatal error had happened) */ enum { MBEDTLS_AUTH_CERTNAME = 0, MBEDTLS_AUTH_CERTFINGERPRINT = 1, MBEDTLS_AUTH_CERTVALID = 2, MBEDTLS_AUTH_CERTANON = 3 } authMode; enum { MBEDTLS_EXPIRED_PERMIT = 0, MBEDTLS_EXPIRED_DENY = 1, MBEDTLS_EXPIRED_WARN = 2, } permitExpiredCerts; enum { MBEDTLS_NONE = 0, MBEDTLS_PURPOSE = 1 } dataTypeCheck; int bHaveSess; /* true if a tls session is active */ int DrvrVerifyDepth; /* Verify Depth for certificate chains */ int DrvrTlsRevocationCheck; /**< Enable TLS revocation checking (OCSP/CRL) */ permittedPeers_t *pPermPeers; /* permitted peers */ int *anzCipherSuites; /* array of cipher suites (IANA ids) in decreasing priority order (0-terminated) */ int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not check CN) */ int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is * set to 1 and changed to 0 after the first report. It is changed back to 1 after * one successful authentication. */ int sock; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; int bHaveCaCert; mbedtls_x509_crt cacert; int bHaveCrl; mbedtls_x509_crl crl; int bHaveKey; mbedtls_pk_context pkey; int bHaveCert; mbedtls_x509_crt srvcert; }; /* interface is defined in nsd.h, we just implement it! */ #define nsd_mbedtlsCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObjFull(nsd_mbedtls); /* the name of our library binary */ #define LM_NSD_MBEDTLS_FILENAME "lmnsd_mbedtls" #endif /* #ifndef INCLUDED_NSD_MBEDTLS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/typedefs.h0000644000000000000000000000013215171370365016226 xustar0030 mtime=1776677109.449913202 30 atime=1787067616.791414537 30 ctime=1787067794.243722241 rsyslog-8.2608.0/runtime/typedefs.h0000664000175000017500000002553015171370365015677 0ustar00rgerrger/* This defines some types commonly used. Do NOT include any other * rsyslog runtime file. * * Begun 2010-11-25 RGerhards * * Copyright (C) 2005-2020 by Rainer Gerhards and Adiscon GmbH * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #ifndef INCLUDED_TYPEDEFS_H #define INCLUDED_TYPEDEFS_H #include #if defined(__FreeBSD__) || !defined(HAVE_LSEEK64) #include #endif /* some universal fixed size integer defines ... */ #ifndef _AIX typedef long long int64; #endif typedef long long unsigned uint64; typedef int64 number_t; /* type to use for numbers - TODO: maybe an autoconf option? */ typedef char intTiny; /* 0..127! */ typedef unsigned char uintTiny; /* 0..255! */ /* define some base data types */ typedef uint16_t syslog_pri_t; /* to be used for syslog PRI values */ typedef unsigned char uchar; /* get rid of the unhandy "unsigned char" */ typedef struct aUsrp_s aUsrp_t; typedef struct thrdInfo thrdInfo_t; typedef struct obj_s obj_t; typedef struct ruleset_s ruleset_t; typedef struct rule_s rule_t; typedef struct NetAddr netAddr_t; typedef struct netstrms_s netstrms_t; typedef struct netstrm_s netstrm_t; typedef struct nssel_s nssel_t; typedef enum nsdsel_waitOp_e nsdsel_waitOp_t; typedef struct net_ossl_s net_ossl_t; typedef struct nsd_ptcp_s nsd_ptcp_t; typedef struct nsd_gtls_s nsd_gtls_t; typedef struct nsd_ossl_s nsd_ossl_t; typedef struct nsd_mbedtls_s nsd_mbedtls_t; typedef struct nsd_gsspi_s nsd_gsspi_t; typedef struct nsd_nss_s nsd_nss_t; typedef struct wti_s wti_t; typedef struct msgPropDescr_s msgPropDescr_t; typedef struct msg smsg_t; typedef struct queue_s qqueue_t; typedef struct prop_s prop_t; typedef struct interface_s interface_t; typedef struct objInfo_s objInfo_t; typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */ typedef rsRetVal (*errLogFunc_t)(uchar *); /* this is a trick to store a function ptr to a function returning a function ptr... */ typedef struct permittedPeers_s permittedPeers_t; /* this should go away in the long term -- rgerhards, 2008-05-19 */ typedef struct permittedPeerWildcard_s permittedPeerWildcard_t; /* this should go away in the long term -- rgerhards, 2008-05-19 */ typedef struct tcpsrv_s tcpsrv_t; typedef struct tcps_sess_s tcps_sess_t; typedef struct strmsrv_s strmsrv_t; typedef struct strms_sess_s strms_sess_t; typedef struct vmstk_s vmstk_t; typedef struct batch_obj_s batch_obj_t; typedef struct batch_s batch_t; typedef struct wtp_s wtp_t; typedef struct modInfo_s modInfo_t; typedef struct parser_s parser_t; typedef struct parserList_s parserList_t; typedef struct strgen_s strgen_t; typedef struct strgenList_s strgenList_t; typedef struct statsobj_s statsobj_t; typedef void (*statsobj_read_notifier_t)(statsobj_t *, void *); // typedef struct nsd_epworkset_s nsd_epworkset_t; // TODO: REMOVE typedef struct tcpsrv_io_descr_s tcpsrv_io_descr_t; // i/o descriptor used for tcpsrv network i/o typedef struct templates_s templates_t; typedef struct parsers_s parsers_t; typedef struct queuecnf_s queuecnf_t; typedef struct parsercnf_s parsercnf_t; typedef struct rulesets_s rulesets_t; typedef struct globals_s globals_t; typedef struct defaults_s defaults_t; typedef struct actions_s actions_t; typedef struct timezones_s timezones_t; typedef struct rsconf_s rsconf_t; typedef struct cfgmodules_s cfgmodules_t; typedef struct cfgmodules_etry_s cfgmodules_etry_t; typedef struct outchannels_s outchannels_t; typedef struct modConfData_s modConfData_t; typedef struct instanceConf_s instanceConf_t; typedef struct ratelimit_s ratelimit_t; typedef struct lookup_string_tab_entry_s lookup_string_tab_entry_t; typedef struct lookup_string_tab_s lookup_string_tab_t; typedef struct lookup_array_tab_s lookup_array_tab_t; typedef struct lookup_sparseArray_tab_s lookup_sparseArray_tab_t; typedef struct lookup_sparseArray_tab_entry_s lookup_sparseArray_tab_entry_t; typedef struct lookup_regex_tab_entry_s lookup_regex_tab_entry_t; typedef struct lookup_tables_s lookup_tables_t; typedef struct lookup_regex_tab_s lookup_regex_tab_t; typedef union lookup_key_u lookup_key_t; typedef struct lookup_s lookup_t; typedef struct lookup_ref_s lookup_ref_t; typedef struct action_s action_t; typedef int rs_size_t; /* we do never need more than 2Gig strings, signed permits to * use -1 as a special flag. */ typedef rsRetVal (*prsf_t)(struct vmstk_s *, int); /* pointer to a RainerScript function */ typedef uint64 qDeqID; /* queue Dequeue order ID. 32 bits is considered dangerously few */ typedef struct tcpLstnParams_s tcpLstnParams_t; typedef struct tcpLstnPortList_s tcpLstnPortList_t; // TODO: rename? typedef struct strmLstnPortList_s strmLstnPortList_t; // TODO: rename? typedef struct actWrkrIParams actWrkrIParams_t; typedef struct dynstats_bucket_s dynstats_bucket_t; typedef struct dynstats_buckets_s dynstats_buckets_t; typedef struct perctile_buckets_s perctile_buckets_t; typedef struct dynstats_ctr_s dynstats_ctr_t; /* under Solaris (actually only SPARC), we need to redefine some types * to be void, so that we get void* pointers. Otherwise, we will see * alignment errors. */ #ifdef OS_SOLARIS typedef void *obj_t_ptr; typedef void nsd_t; #else typedef obj_t *obj_t_ptr; typedef obj_t nsd_t; #endif #ifdef __hpux typedef unsigned int u_int32_t; /* TODO: is this correct? */ typedef int socklen_t; #endif typedef struct epoll_event epoll_event_t; typedef signed char sbool; /* (small bool) I intentionally use char, to keep it slim so that many fit into the CPU cache! */ /* settings for flow control * TODO: is there a better place for them? -- rgerhards, 2008-03-14 */ typedef enum { eFLOWCTL_NO_DELAY = 0, /**< UDP and other non-delayable sources */ eFLOWCTL_LIGHT_DELAY = 1, /**< some light delay possible, but no extended period of time */ eFLOWCTL_FULL_DELAY = 2 /**< delay possible for extended period of time */ } flowControl_t; /* filter operations */ typedef enum { FIOP_NOP = 0, /* do not use - No Operation */ FIOP_CONTAINS = 1, /* contains string? */ FIOP_ISEQUAL = 2, /* is (exactly) equal? */ FIOP_STARTSWITH = 3, /* starts with a string? */ FIOP_ENDSWITH = 4, /* ends with a string? */ FIOP_REGEX = 5, /* matches a (BRE) regular expression? */ FIOP_EREREGEX = 6, /* matches a ERE regular expression? */ FIOP_ISEMPTY = 7 /* string empty <=> strlen(s) == 0 ?*/ } fiop_t; #ifndef HAVE_LSEEK64 #ifndef HAVE_OFF64_T typedef off_t off64_t; #endif #endif /* properties are now encoded as (tiny) integers. I do not use an enum as I would like * to keep the memory footprint small (and thus cache hits high). * rgerhards, 2009-06-26 */ typedef uintTiny propid_t; #define PROP_INVALID 0 #define PROP_MSG 1 #define PROP_TIMESTAMP 2 #define PROP_HOSTNAME 3 #define PROP_SYSLOGTAG 4 #define PROP_RAWMSG 5 #define PROP_INPUTNAME 6 #define PROP_FROMHOST 7 #define PROP_FROMHOST_IP 8 #define PROP_PRI 9 #define PROP_PRI_TEXT 10 #define PROP_IUT 11 #define PROP_SYSLOGFACILITY 12 #define PROP_SYSLOGFACILITY_TEXT 13 #define PROP_SYSLOGSEVERITY 14 #define PROP_SYSLOGSEVERITY_TEXT 15 #define PROP_TIMEGENERATED 16 #define PROP_PROGRAMNAME 17 #define PROP_PROTOCOL_VERSION 18 #define PROP_STRUCTURED_DATA 19 #define PROP_APP_NAME 20 #define PROP_PROCID 21 #define PROP_MSGID 22 #define PROP_PARSESUCCESS 23 #define PROP_JSONMESG 24 #define PROP_RAWMSG_AFTER_PRI 25 #define PROP_FROMHOST_PORT 26 #define PROP_SYS_NOW 150 #define PROP_SYS_YEAR 151 #define PROP_SYS_MONTH 152 #define PROP_SYS_DAY 153 #define PROP_SYS_HOUR 154 #define PROP_SYS_HHOUR 155 #define PROP_SYS_QHOUR 156 #define PROP_SYS_MINUTE 157 #define PROP_SYS_MYHOSTNAME 158 #define PROP_SYS_BOM 159 #define PROP_SYS_UPTIME 160 #define PROP_UUID 161 #define PROP_SYS_NOW_UTC 162 #define PROP_SYS_YEAR_UTC 163 #define PROP_SYS_MONTH_UTC 164 #define PROP_SYS_DAY_UTC 165 #define PROP_SYS_HOUR_UTC 166 #define PROP_SYS_HHOUR_UTC 167 #define PROP_SYS_QHOUR_UTC 168 #define PROP_SYS_MINUTE_UTC 169 #define PROP_SYS_WDAY 170 #define PROP_SYS_WDAY_UTC 171 #define PROP_SYS_NOW_UXTIMESTAMP 173 #define PROP_CEE 200 #define PROP_CEE_ALL_JSON 201 #define PROP_LOCAL_VAR 202 #define PROP_GLOBAL_VAR 203 #define PROP_CEE_ALL_JSON_PLAIN 204 /* types of configuration handlers. These are used in rainerscript.h */ typedef enum cslCmdHdlrType { eCmdHdlrInvalid = 0, /* invalid handler type - indicates a coding error */ eCmdHdlrCustomHandler, /* custom handler, just call handler function */ eCmdHdlrUID, eCmdHdlrGID, eCmdHdlrBinary, eCmdHdlrFileCreateMode, eCmdHdlrInt, eCmdHdlrNonNegInt, eCmdHdlrPositiveInt, eCmdHdlrSize, eCmdHdlrGetChar, eCmdHdlrFacility, eCmdHdlrSeverity, eCmdHdlrGetWord, eCmdHdlrString, eCmdHdlrArray, eCmdHdlrQueueType, eCmdHdlrGoneAway /* statement existed, but is no longer supported */ } ecslCmdHdrlType; /* the next type describes $Begin .. $End block object types */ typedef enum cslConfObjType { eConfObjGlobal = 0, /* global directives */ eConfObjAction, /* action-specific directives */ /* now come states that indicate that we wait for a block-end. These are * states that permit us to do some safety checks and they hopefully ease * migration to a "real" parser/grammar. */ eConfObjActionWaitEnd, eConfObjAlways /* always valid, very special case (guess $End only!) */ } ecslConfObjType; /* multi-submit support. * This is done via a simple data structure, which holds the number of elements * as well as an array of to-be-submitted messages. * rgerhards, 2009-06-16 */ typedef struct multi_submit_s multi_submit_t; struct multi_submit_s { short maxElem; /* maximum number of Elements */ short nElem; /* current number of Elements, points to the next one FREE */ smsg_t **ppMsgs; }; /* the following structure is a helper to describe a message property */ struct msgPropDescr_s { propid_t id; uchar *name; /* name and lenName are only set for dynamic */ int nameLen; /* properties (JSON) */ }; /* some forward-definitions from the grammar */ struct nvlst; struct cnfobj; #endif /* multi-include protection */ rsyslog-8.2608.0/runtime/PaxHeaders/parser.h0000644000000000000000000000013215241075234015672 xustar0030 mtime=1787067036.605578294 30 atime=1787067036.752581047 30 ctime=1787067794.296723229 rsyslog-8.2608.0/runtime/parser.h0000664000175000017500000000611315241075234015337 0ustar00rgerrger/* header for parser.c * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_PARSER_H #define INCLUDED_PARSER_H /* we create a small helper object, a list of parsers, that we can use to * build a chain of them whereever this is needed (initially thought to be * used in ruleset.c as well as ourselvs). */ struct parserList_s { parser_t *pParser; parserList_t *pNext; }; /* the parser object, a dummy because we have only static methods */ struct parser_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ uchar *pName; /* name of this parser */ modInfo_t *pModule; /* pointer to parser's module */ void *pInst; /* instance data for the parser (v2+ module interface) */ sbool bDoSanitazion; /* do standard message sanitazion before calling parser? */ sbool bDoPRIParsing; /* do standard PRI parsing before calling parser? */ }; /* interfaces */ BEGINinterface(parser) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(var); rsRetVal (*Construct)(parser_t **ppThis); rsRetVal (*ConstructFinalize)(parser_t *pThis); rsRetVal (*Destruct)(parser_t **ppThis); rsRetVal (*SetName)(parser_t *pThis, uchar *name); rsRetVal (*SetModPtr)(parser_t *pThis, modInfo_t *pMod); rsRetVal (*SetDoPRIParsing)(parser_t *pThis, int); rsRetVal (*FindParser)(parserList_t *pParserListRoot, parser_t **ppThis, uchar *name); rsRetVal (*DestructParserList)(parserList_t **pListRoot); rsRetVal (*AddParserToList)(parserList_t **pListRoot, parser_t *pParser); rsRetVal (*destroyMasterParserList)(parserList_t *pParserListRoot); /* static functions */ rsRetVal (*ParseMsg)(smsg_t *pMsg); rsRetVal (*SanitizeMsg)(smsg_t *pMsg); rsRetVal (*AddDfltParser)(uchar *); ENDinterface(parser) #define parserCURR_IF_VERSION 3 /* increment whenever you change the interface above! */ /* version changes 2 SetDoSanitization removed, no longer needed 3 InitParserList removed, no longer needed destroyMasterParserList added findParser extended with new parameter specifying the parser list */ void printParserList(parserList_t *pList); /* prototypes */ PROTOTYPEObjFull(parser); rsRetVal parserConstructViaModAndName(modInfo_t *pMod, uchar *const pName, void *parserInst); rsRetVal parserParsePRI(smsg_t *pMsg); #endif /* #ifndef INCLUDED_PARSER_H */ rsyslog-8.2608.0/runtime/PaxHeaders/dirty.h0000644000000000000000000000013215216464436015541 xustar0030 mtime=1782212894.020266087 30 atime=1787067618.026437565 30 ctime=1787067794.472726508 rsyslog-8.2608.0/runtime/dirty.h0000664000175000017500000000533715216464436015215 0ustar00rgerrger/* This file is an aid to support non-modular object accesses * while we do not have fully modularized everything. Once this is * done, this file can (and should) be deleted. Presence of it * also somewhat indicates that the runtime library is not really * yet a runtime library, because it depends on some functionality * residing somewhere else. * * Copyright 2007-2023 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DIRTY_H_INCLUDED #define DIRTY_H_INCLUDED 1 rsRetVal __attribute__((deprecated)) multiSubmitMsg(multi_submit_t *pMultiSub); rsRetVal ATTR_NONNULL() multiSubmitMsg2(multi_submit_t *const pMultiSub); /* friends only! */ rsRetVal submitMsg2(smsg_t *pMsg); rsRetVal __attribute__((deprecated)) submitMsg(smsg_t *pMsg); rsRetVal multiSubmitFlush(multi_submit_t *pMultiSub); rsRetVal logmsgInternal(const int iErr, const syslog_pri_t pri, const uchar *const msg, int flags); rsRetVal __attribute__((deprecated)) parseAndSubmitMessage(const uchar *hname, const uchar *hnameIP, const uchar *msg, const int len, const int flags, const flowControl_t flowCtlType, prop_t *pInputName, const struct syslogTime *stTime, const time_t ttGenTime, ruleset_t *pRuleset); rsRetVal createMainQueue(qqueue_t **ppQueue, uchar *pszQueueName, struct nvlst *lst); rsRetVal startMainQueue(rsconf_t *cnf, qqueue_t *pQueue); int get_bHadHUP(void); extern int MarkInterval; #define CONF_VERIFY_PARTIAL_CONF 0x02 /* bit: partial configuration to be checked */ extern int iConfigVerify; /* is this just a config verify run? */ extern int bHaveMainQueue; #endif /* #ifndef DIRTY_H_INCLUDED */ rsyslog-8.2608.0/runtime/PaxHeaders/cfsysline.c0000644000000000000000000000013215171370365016375 xustar0030 mtime=1776677109.434912971 30 atime=1787067618.108439094 30 ctime=1787067794.459726266 rsyslog-8.2608.0/runtime/cfsysline.c0000664000175000017500000010145115171370365016043 0ustar00rgerrger/* cfsysline.c * Implementation of the configuration system line object. * * File begun on 2007-07-30 by RGerhards * * Copyright (C) 2007-2020 Adiscon GmbH. * * This file is part of rsyslog. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "cfsysline.h" #include "obj.h" #include "conf.h" #include "errmsg.h" #include "srUtils.h" #include "unicode-helper.h" #include "rsconf.h" #include "parserif.h" /* static data */ DEFobjCurrIf(obj) linkedList_t llCmdList; /* this is NOT a pointer - no typo here ;) */ /* --------------- START functions for handling canned syntaxes --------------- */ /* parse a character from the config line * added 2007-07-17 by rgerhards * TODO: enhance this function to handle different classes of characters * HINT: check if char is ' and, if so, use 'c' where c may also be things * like \t etc. */ static rsRetVal doGetChar(uchar **pp, rsRetVal (*pSetHdlr)(void *, uchar *), void *pVal) { DEFiRet; assert(pp != NULL); assert(*pp != NULL); skipWhiteSpace(pp); /* skip over any whitespace */ /* if we are not at a '\0', we have our new char - no validity checks here... */ if (**pp == '\0') { LogError(0, RS_RET_NOT_FOUND, "No character available"); iRet = RS_RET_NOT_FOUND; } else { if (pSetHdlr == NULL) { /* we should set value directly to var */ *((uchar *)pVal) = **pp; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, *pp)); } ++(*pp); /* eat processed char */ } finalize_it: RETiRet; } /* Parse a number from the configuration line. This is more or less * a shell to call the custom handler. * rgerhards, 2007-07-31 */ static rsRetVal doCustomHdlr(uchar **pp, rsRetVal (*pSetHdlr)(uchar **, void *), void *pVal) { DEFiRet; assert(pp != NULL); assert(*pp != NULL); CHKiRet(pSetHdlr(pp, pVal)); finalize_it: RETiRet; } /* Parse a number from the configuration line. This functions just parses * the number and does NOT call any handlers or set any values. It is just * for INTERNAL USE by other parse functions! * rgerhards, 2008-01-08 */ static rsRetVal parseIntVal(uchar **pp, int64 *pVal) { DEFiRet; uchar *p; int64 i; int bWasNegative; assert(pp != NULL); assert(*pp != NULL); assert(pVal != NULL); skipWhiteSpace(pp); /* skip over any whitespace */ p = *pp; if (*p == '-') { bWasNegative = 1; ++p; /* eat it */ } else { bWasNegative = 0; } if (!isdigit((int)*p)) { errno = 0; LogError(0, RS_RET_INVALID_INT, "invalid number"); ABORT_FINALIZE(RS_RET_INVALID_INT); } /* pull value */ for (i = 0; *p && (isdigit((int)*p) || *p == '.' || *p == ','); ++p) { if (isdigit((int)*p)) { i = i * 10 + *p - '0'; } } if (bWasNegative) i *= -1; *pVal = i; *pp = p; finalize_it: RETiRet; } /* Parse a size from the configuration line. This is basically an integer * syntax, but modifiers may be added after the integer (e.g. 1k to mean * 1024). The size must immediately follow the number. Note that the * param value must be int64! * rgerhards, 2008-01-09 */ static rsRetVal doGetSize(uchar **pp, rsRetVal (*pSetHdlr)(void *, int64), void *pVal) { DEFiRet; int64 i; assert(pp != NULL); assert(*pp != NULL); CHKiRet(parseIntVal(pp, &i)); /* we now check if the next character is one of our known modifiers. * If so, we accept it as such. If not, we leave it alone. tera and * above does not make any sense as that is above a 32-bit int value. */ switch (**pp) { /* traditional binary-based definitions */ case 'k': i *= 1024; ++(*pp); break; case 'm': i *= 1024 * 1024; ++(*pp); break; case 'g': i *= 1024 * 1024 * 1024; ++(*pp); break; case 't': i *= (int64)1024 * 1024 * 1024 * 1024; ++(*pp); break; /* tera */ case 'p': i *= (int64)1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* peta */ case 'e': i *= (int64)1024 * 1024 * 1024 * 1024 * 1024 * 1024; ++(*pp); break; /* exa */ /* and now the "new" 1000-based definitions */ case 'K': i *= 1000; ++(*pp); break; case 'M': i *= 1000000; ++(*pp); break; case 'G': i *= 1000000000; ++(*pp); break; /* we need to use the multiplication below because otherwise * the compiler gets an error during constant parsing */ case 'T': i *= (int64)1000 * 1000000000; ++(*pp); break; /* tera */ case 'P': i *= (int64)1000000 * 1000000000; ++(*pp); break; /* peta */ case 'E': i *= (int64)1000000000 * 1000000000; ++(*pp); break; /* exa */ default: // No action needed for other cases break; } /* done */ if (pSetHdlr == NULL) { /* we should set value directly to var */ *((int64 *)pVal) = i; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, i)); } finalize_it: RETiRet; } /* Parse a number from the configuration line. * rgerhards, 2007-07-31 */ static rsRetVal doGetInt(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { uchar *p; DEFiRet; int64 i; assert(pp != NULL); assert(*pp != NULL); CHKiRet(doGetSize(pp, NULL, &i)); p = *pp; if (i > 2147483648ll) { /*2^31*/ LogError(0, RS_RET_INVALID_VALUE, "value %lld too large for integer argument.", i); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } if (pSetHdlr == NULL) { /* we should set value directly to var */ *((int *)pVal) = (int)i; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, (int)i)); } *pp = p; finalize_it: RETiRet; } static rsRetVal doGetNonNegInt(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { int val; DEFiRet; CHKiRet(doGetInt(pp, NULL, &val)); if (val < 0) { LogError(0, RS_RET_INVALID_VALUE, "value %d must not be less than zero.", val); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } if (pSetHdlr == NULL) { *((int *)pVal) = val; } else { CHKiRet(pSetHdlr(pVal, val)); } finalize_it: RETiRet; } static rsRetVal doGetPositiveInt(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { int val; DEFiRet; CHKiRet(doGetInt(pp, NULL, &val)); if (val < 1) { LogError(0, RS_RET_INVALID_VALUE, "value %d must be greater than zero.", val); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } if (pSetHdlr == NULL) { *((int *)pVal) = val; } else { CHKiRet(pSetHdlr(pVal, val)); } finalize_it: RETiRet; } /* Parse and interpret a $FileCreateMode and $umask line. This function * pulls the creation mode and, if successful, stores it * into the global variable so that the rest of rsyslogd * opens files with that mode. Any previous value will be * overwritten. * HINT: if we store the creation mode in selector_t, we * can even specify multiple modes simply be virtue of * being placed in the right section of rsyslog.conf * rgerhards, 2007-07-4 (happy independence day to my US friends!) * Parameter **pp has a pointer to the current config line. * On exit, it will be updated to the processed position. */ static rsRetVal doFileCreateMode(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { uchar *p; DEFiRet; int iVal; assert(pp != NULL); assert(*pp != NULL); skipWhiteSpace(pp); /* skip over any whitespace */ p = *pp; /* for now, we parse and accept only octal numbers * Sequence of tests is important, we are using boolean shortcuts * to avoid addressing invalid memory! */ if (!((*p == '0') && (*(p + 1) && *(p + 1) >= '0' && *(p + 1) <= '7') && (*(p + 2) && *(p + 2) >= '0' && *(p + 2) <= '7') && (*(p + 3) && *(p + 3) >= '0' && *(p + 3) <= '7'))) { LogError(0, RS_RET_INVALID_VALUE, "value must be octal (e.g 0644)."); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } /* we reach this code only if the octal number is ok - so we can now * compute the value. */ iVal = (*(p + 1) - '0') * 64 + (*(p + 2) - '0') * 8 + (*(p + 3) - '0'); if (pSetHdlr == NULL) { /* we should set value directly to var */ *((int *)pVal) = iVal; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, iVal)); } p += 4; /* eat the octal number */ *pp = p; finalize_it: RETiRet; } /* Parse and interpret an on/off inside a config file line. This is most * often used for boolean options, but of course it may also be used * for other things. The passed-in pointer is updated to point to * the first unparsed character on exit. Function emits error messages * if the value is neither on or off. It returns 0 if the option is off, * 1 if it is on and another value if there was an error. * rgerhards, 2007-07-15 */ static int doParseOnOffOption(uchar **pp) { uchar *pOptStart; uchar szOpt[32]; assert(pp != NULL); assert(*pp != NULL); pOptStart = *pp; skipWhiteSpace(pp); /* skip over any whitespace */ if (getSubString(pp, (char *)szOpt, sizeof(szOpt), ' ') != 0) { LogError(0, NO_ERRCODE, "Invalid $-configline - could not extract on/off option"); return -1; } if (!strcmp((char *)szOpt, "on")) { return 1; } else if (!strcmp((char *)szOpt, "off")) { return 0; } else { LogError(0, NO_ERRCODE, "Option value must be on or off, but is '%s'", (char *)pOptStart); return -1; } } /* extract a groupname and return its gid. * rgerhards, 2007-07-17 */ static rsRetVal doGetGID(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { struct group *pgBuf = NULL; struct group gBuf; DEFiRet; uchar szName[256]; int bufSize = 1024; char *stringBuf = NULL; int err; assert(pp != NULL); assert(*pp != NULL); if (getSubString(pp, (char *)szName, sizeof(szName), ' ') != 0) { if (loadConf->globals.abortOnIDResolutionFail) { fprintf(stderr, "could not extract group name: %s\n", (char *)szName); exit(1); /* good exit */ } else { LogError(0, RS_RET_NOT_FOUND, "could not extract group name"); ABORT_FINALIZE(RS_RET_NOT_FOUND); } } do { char *p; /* Increase bufsize and try again.*/ bufSize *= 2; CHKmalloc(p = realloc(stringBuf, bufSize)); stringBuf = p; err = getgrnam_r((char *)szName, &gBuf, stringBuf, bufSize, &pgBuf); } while ((pgBuf == NULL) && (err == ERANGE)); if (pgBuf == NULL) { if (err != 0) { LogError(err, RS_RET_NOT_FOUND, "Query for group '%s' resulted in an error", szName); } else { LogError(0, RS_RET_NOT_FOUND, "ID for group '%s' could not be found", szName); } iRet = RS_RET_NOT_FOUND; if (loadConf->globals.abortOnIDResolutionFail) { fprintf(stderr, "ID for group '%s' could not be found or error\n", szName); exit(1); /* good exit */ } } else { if (pSetHdlr == NULL) { /* we should set value directly to var */ *((gid_t *)pVal) = pgBuf->gr_gid; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, pgBuf->gr_gid)); } dbgprintf("gid %d obtained for group '%s'\n", (int)pgBuf->gr_gid, szName); } skipWhiteSpace(pp); /* skip over any whitespace */ finalize_it: free(stringBuf); RETiRet; } /* extract a username and return its uid. * rgerhards, 2007-07-17 */ static rsRetVal doGetUID(uchar **pp, rsRetVal (*pSetHdlr)(void *, uid_t), void *pVal) { struct passwd *ppwBuf; struct passwd pwBuf; DEFiRet; uchar szName[256]; char stringBuf[2048]; /* I hope this is large enough... */ assert(pp != NULL); assert(*pp != NULL); if (getSubString(pp, (char *)szName, sizeof(szName), ' ') != 0) { if (loadConf->globals.abortOnIDResolutionFail) { fprintf(stderr, "could not extract user name: %s\n", (char *)szName); exit(1); /* good exit */ } else { LogError(0, RS_RET_NOT_FOUND, "could not extract user name"); ABORT_FINALIZE(RS_RET_NOT_FOUND); } } getpwnam_r((char *)szName, &pwBuf, stringBuf, sizeof(stringBuf), &ppwBuf); if (ppwBuf == NULL) { if (loadConf->globals.abortOnIDResolutionFail) { fprintf(stderr, "ID for user '%s' could not be found or error\n", (char *)szName); exit(1); /* good exit */ } else { LogError(0, RS_RET_NOT_FOUND, "ID for user '%s' could not be found or error", (char *)szName); iRet = RS_RET_NOT_FOUND; } } else { if (pSetHdlr == NULL) { /* we should set value directly to var */ *((uid_t *)pVal) = ppwBuf->pw_uid; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, ppwBuf->pw_uid)); } dbgprintf("uid %d obtained for user '%s'\n", (int)ppwBuf->pw_uid, szName); } skipWhiteSpace(pp); /* skip over any whitespace */ finalize_it: RETiRet; } /* Parse and process an binary cofig option. pVal must be * a pointer to an integer which is to receive the option * value. * rgerhards, 2007-07-15 */ static rsRetVal doBinaryOptionLine(uchar **pp, rsRetVal (*pSetHdlr)(void *, int), void *pVal) { int iOption; DEFiRet; assert(pp != NULL); assert(*pp != NULL); if ((iOption = doParseOnOffOption(pp)) == -1) return RS_RET_ERR; /* nothing left to do */ if (pSetHdlr == NULL) { /* we should set value directly to var */ *((int *)pVal) = iOption; } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, iOption)); } skipWhiteSpace(pp); /* skip over any whitespace */ finalize_it: RETiRet; } /* parse a whitespace-delimited word from the provided string. This is a * helper function for a number of syntaxes. The parsed value is returned * in ppStrB (which must be provided by caller). * rgerhards, 2008-02-14 */ static rsRetVal getWord(uchar **pp, cstr_t **ppStrB) { DEFiRet; uchar *p; assert(pp != NULL); assert(*pp != NULL); assert(ppStrB != NULL); CHKiRet(cstrConstruct(ppStrB)); skipWhiteSpace(pp); /* skip over any whitespace */ /* parse out the word */ p = *pp; while (*p && !isspace((int)*p)) { CHKiRet(cstrAppendChar(*ppStrB, *p++)); } cstrFinalize(*ppStrB); *pp = p; finalize_it: RETiRet; } /* Parse and a word config line option. A word is a consequtive * sequence of non-whitespace characters. pVal must be * a pointer to a string which is to receive the option * value. The returned string must be freed by the caller. * rgerhards, 2007-09-07 * To facilitate multiple instances of the same command line * directive, doGetWord() now checks if pVal is already a * non-NULL pointer. If so, we assume it was created by a previous * incarnation and is automatically freed. This happens only when * no custom handler is defined. If it is, the customer handler * must do the cleanup. I have checked and this was al also memory * leak with some code. Obviously, not a large one. -- rgerhards, 2007-12-20 * Just to clarify: if pVal is parsed to a custom handler, this handler * is responsible for freeing pVal. -- rgerhards, 2008-03-20 */ static rsRetVal doGetWord(uchar **pp, rsRetVal (*pSetHdlr)(void *, uchar *), void *pVal) { DEFiRet; cstr_t *pStrB = NULL; uchar *pNewVal; assert(pp != NULL); assert(*pp != NULL); CHKiRet(getWord(pp, &pStrB)); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pNewVal, 0)); DBGPRINTF("doGetWord: get newval '%s' (len %d), hdlr %p\n", pNewVal, (int)ustrlen(pNewVal), pSetHdlr); /* we got the word, now set it */ if (pSetHdlr == NULL) { /* we should set value directly to var */ if (*((uchar **)pVal) != NULL) free(*((uchar **)pVal)); /* free previous entry */ *((uchar **)pVal) = pNewVal; /* set new one */ } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, pNewVal)); } skipWhiteSpace(pp); /* skip over any whitespace */ finalize_it: if (iRet != RS_RET_OK) { if (pStrB != NULL) cstrDestruct(&pStrB); } RETiRet; } /* parse a syslog name from the string. This is the generic code that is * called by the facility/severity functions. Note that we do not check the * validity of numerical values, something that should probably change over * time (TODO). -- rgerhards, 2008-02-14 */ static rsRetVal doSyslogName(uchar **pp, rsRetVal (*pSetHdlr)(void *, int), void *pVal, syslogName_t *pNameTable) { DEFiRet; cstr_t *pStrB; int iNewVal; assert(pp != NULL); assert(*pp != NULL); CHKiRet(getWord(pp, &pStrB)); /* get word */ iNewVal = decodeSyslogName(cstrGetSzStrNoNULL(pStrB), pNameTable); if (pSetHdlr == NULL) { /* we should set value directly to var */ *((int *)pVal) = iNewVal; /* set new one */ } else { /* we set value via a set function */ CHKiRet(pSetHdlr(pVal, iNewVal)); } skipWhiteSpace(pp); /* skip over any whitespace */ finalize_it: if (pStrB != NULL) rsCStrDestruct(&pStrB); RETiRet; } /* Implements the facility syntax. * rgerhards, 2008-02-14 */ static rsRetVal doFacility(uchar **pp, rsRetVal (*pSetHdlr)(void *, int), void *pVal) { DEFiRet; iRet = doSyslogName(pp, pSetHdlr, pVal, syslogFacNames); RETiRet; } static rsRetVal doGoneAway(__attribute__((unused)) uchar **pp, __attribute__((unused)) rsRetVal (*pSetHdlr)(void *, int), __attribute__((unused)) void *pVal) { parser_warnmsg("config directive is no longer supported -- ignored"); return RS_RET_CMD_GONE_AWAY; } /* Implements the severity syntax. * rgerhards, 2008-02-14 */ static rsRetVal doSeverity(uchar **pp, rsRetVal (*pSetHdlr)(void *, int), void *pVal) { DEFiRet; iRet = doSyslogName(pp, pSetHdlr, pVal, syslogPriNames); RETiRet; } /* --------------- END functions for handling canned syntaxes --------------- */ /* destructor for cslCmdHdlr * pThis is actually a cslCmdHdlr_t, but we do not cast it as all we currently * need to do is free it. */ static rsRetVal cslchDestruct(void *pThis) { assert(pThis != NULL); free(pThis); return RS_RET_OK; } /* constructor for cslCmdHdlr */ static rsRetVal cslchConstruct(cslCmdHdlr_t **ppThis) { cslCmdHdlr_t *pThis; DEFiRet; assert(ppThis != NULL); if ((pThis = calloc(1, sizeof(cslCmdHdlr_t))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } finalize_it: *ppThis = pThis; RETiRet; } /* destructor for linked list keys. As we do not use any dynamic memory, * we simply return. However, this entry point must be defined for the * linkedList class to make sure we have not forgotten a destructor. * rgerhards, 2007-11-21 */ static rsRetVal cslchKeyDestruct(void __attribute__((unused)) * pData) { return RS_RET_OK; } /* Key compare operation for linked list class. This compares two * owner cookies (void *). * rgerhards, 2007-11-21 */ static int cslchKeyCompare(void *pKey1, void *pKey2) { if (pKey1 == pKey2) return 0; else if (pKey1 < pKey2) return -1; else return 1; } /* set data members for this object */ static rsRetVal cslchSetEntry( cslCmdHdlr_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, int *permitted) { assert(pThis != NULL); assert(eType != eCmdHdlrInvalid); pThis->eType = eType; pThis->cslCmdHdlr = pHdlr; pThis->pData = pData; pThis->permitted = permitted; return RS_RET_OK; } /* call the specified handler */ static rsRetVal cslchCallHdlr(cslCmdHdlr_t *pThis, uchar **ppConfLine) { DEFiRet; assert(pThis != NULL); assert(ppConfLine != NULL); switch (pThis->eType) { case eCmdHdlrCustomHandler: CHKiRet(doCustomHdlr(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrUID: CHKiRet(doGetUID(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrGID: CHKiRet(doGetGID(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrBinary: CHKiRet(doBinaryOptionLine(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrFileCreateMode: CHKiRet(doFileCreateMode(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrInt: CHKiRet(doGetInt(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrNonNegInt: CHKiRet(doGetNonNegInt(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrPositiveInt: CHKiRet(doGetPositiveInt(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrSize: CHKiRet(doGetSize(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrGetChar: CHKiRet(doGetChar(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrFacility: CHKiRet(doFacility(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrSeverity: CHKiRet(doSeverity(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrGetWord: CHKiRet(doGetWord(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; case eCmdHdlrGoneAway: CHKiRet(doGoneAway(ppConfLine, pThis->cslCmdHdlr, pThis->pData)); break; /* some non-legacy handler (used in v6+ solely) */ case eCmdHdlrInvalid: case eCmdHdlrString: case eCmdHdlrArray: case eCmdHdlrQueueType: default: dbgprintf("error: command handler type %d not implemented in legacy system\n", pThis->eType); iRet = RS_RET_NOT_IMPLEMENTED; goto finalize_it; } finalize_it: RETiRet; } /* ---------------------------------------------------------------------- * * now come the handlers for cslCmd_t * ---------------------------------------------------------------------- */ /* destructor for a cslCmd list key (a string as of now) */ static rsRetVal cslcKeyDestruct(void *pData) { free(pData); /* we do not need to cast as all we do is free it anyway... */ return RS_RET_OK; } /* destructor for cslCmd */ static rsRetVal cslcDestruct(void *pData) { cslCmd_t *pThis = (cslCmd_t *)pData; assert(pThis != NULL); llDestroy(&pThis->llCmdHdlrs); free(pThis); return RS_RET_OK; } /* constructor for cslCmd */ static rsRetVal cslcConstruct(cslCmd_t **ppThis, int bChainingPermitted) { cslCmd_t *pThis; DEFiRet; assert(ppThis != NULL); if ((pThis = calloc(1, sizeof(cslCmd_t))) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pThis->bChainingPermitted = bChainingPermitted; CHKiRet(llInit(&pThis->llCmdHdlrs, cslchDestruct, cslchKeyDestruct, (int (*)(void *, void *))cslchKeyCompare)); finalize_it: *ppThis = pThis; RETiRet; } /* add a handler entry to a known command */ static rsRetVal cslcAddHdlr( cslCmd_t *pThis, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie, int *permitted) { DEFiRet; cslCmdHdlr_t *pCmdHdlr = NULL; assert(pThis != NULL); CHKiRet(cslchConstruct(&pCmdHdlr)); CHKiRet(cslchSetEntry(pCmdHdlr, eType, pHdlr, pData, permitted)); CHKiRet(llAppend(&pThis->llCmdHdlrs, pOwnerCookie, pCmdHdlr)); finalize_it: if (iRet != RS_RET_OK) { if (pHdlr != NULL) cslchDestruct(pCmdHdlr); } RETiRet; } /* function that registers cfsysline handlers. * The supplied pCmdName is copied and a new buffer is allocated. This * buffer is automatically destroyed when the element is freed, the * caller does not need to take care of that. The caller must, however, * free pCmdName if he allocated it dynamically! -- rgerhards, 2007-08-09 * Parameter permitted has been added to support the v2 config system. With it, * we can tell the legacy system (us here!) to check if a config directive is * still permitted. For example, the v2 system will disable module global * parameters if the are supplied via the native v2 callbacks. In order not * to break exisiting modules, we have renamed the rgCfSysLinHdlr routine to * version 2 and added a new one with the original name. It just calls the * v2 function and supplies a "don't care (NULL)" pointer as this argument. * rgerhards, 2012-06-26 */ rsRetVal regCfSysLineHdlr2(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie, int *permitted) { DEFiRet; cslCmd_t *pThis; uchar *pMyCmdName; iRet = llFind(&llCmdList, (void *)pCmdName, (void *)&pThis); if (iRet == RS_RET_NOT_FOUND) { /* new command */ CHKiRet(cslcConstruct(&pThis, bChainingPermitted)); CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, permitted)) { cslcDestruct(pThis); FINALIZE; } /* important: add to list, AFTER everything else is OK. Else * we mess up things in the error case. */ if ((pMyCmdName = (uchar *)strdup((char *)pCmdName)) == NULL) { cslcDestruct(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKiRet_Hdlr(llAppend(&llCmdList, pMyCmdName, (void *)pThis)) { cslcDestruct(pThis); FINALIZE; } } else { /* command already exists, are we allowed to chain? */ if (pThis->bChainingPermitted == 0 || bChainingPermitted == 0) { ABORT_FINALIZE(RS_RET_CHAIN_NOT_PERMITTED); } CHKiRet_Hdlr(cslcAddHdlr(pThis, eType, pHdlr, pData, pOwnerCookie, permitted)) { cslcDestruct(pThis); FINALIZE; } } finalize_it: RETiRet; } rsRetVal regCfSysLineHdlr(const uchar *pCmdName, int bChainingPermitted, ecslCmdHdrlType eType, rsRetVal (*pHdlr)(), void *pData, void *pOwnerCookie) { DEFiRet; iRet = regCfSysLineHdlr2(pCmdName, bChainingPermitted, eType, pHdlr, pData, pOwnerCookie, NULL); RETiRet; } rsRetVal unregCfSysLineHdlrs(void) { return llDestroy(&llCmdList); } /* helper function for unregCfSysLineHdlrs4Owner(). This is used to see if there is * a handler of this owner inside the element and, if so, remove it. Please note that * it keeps track of a pointer to the last linked list entry, as this is needed to * remove an entry from the list. * rgerhards, 2007-11-21 */ DEFFUNC_llExecFunc(unregHdlrsHeadExec) { DEFiRet; cslCmd_t *pListHdr = (cslCmd_t *)pData; int iNumElts; /* first find element */ CHKiRet(llFindAndDelete(&(pListHdr->llCmdHdlrs), pParam)); /* now go back and check how many elements are left */ CHKiRet(llGetNumElts(&(pListHdr->llCmdHdlrs), &iNumElts)); if (iNumElts == 0) { /* nothing left in header, so request to delete it */ iRet = RS_RET_OK_DELETE_LISTENTRY; } finalize_it: RETiRet; } /* unregister and destroy cfSysLineHandlers for a specific owner. This method is * most importantly used before unloading a loadable module providing some handlers. * The full list of handlers is searched. If the to-be removed handler was the only * handler for a directive name, the directive header, too, is deleted. * rgerhards, 2007-11-21 */ rsRetVal unregCfSysLineHdlrs4Owner(void *pOwnerCookie) { DEFiRet; /* we need to walk through all directive names, as the linked list * class does not provide a way to just search the lower-level handlers. */ iRet = llExecFunc(&llCmdList, unregHdlrsHeadExec, pOwnerCookie); if (iRet == RS_RET_NOT_FOUND) { /* It is not considered an error if a module had no hanlers registered. */ iRet = RS_RET_OK; } RETiRet; } /* process a cfsysline command (based on handler structure) * param "p" is a pointer to the command line after the command. Should be * updated. */ rsRetVal processCfSysLineCommand(uchar *pCmdName, uchar **p) { DEFiRet; rsRetVal iRetLL; /* for linked list handling */ cslCmd_t *pCmd; cslCmdHdlr_t *pCmdHdlr; linkedListCookie_t llCookieCmdHdlr; uchar *pHdlrP; /* the handler's private p (else we could only call one handler) */ int bWasOnceOK; /* was the result of an handler at least once RS_RET_OK? */ uchar *pOKp = NULL; /* returned conf line pointer when it was OK */ iRet = llFind(&llCmdList, (void *)pCmdName, (void *)&pCmd); if (iRet == RS_RET_NOT_FOUND) { LogError(0, RS_RET_NOT_FOUND, "invalid or yet-unknown config file command '%s' - " "have you forgotten to load a module?", pCmdName); } if (iRet != RS_RET_OK) goto finalize_it; llCookieCmdHdlr = NULL; bWasOnceOK = 0; while ((iRetLL = llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void *)&pCmdHdlr)) == RS_RET_OK) { /* for the time being, we ignore errors during handlers. The * reason is that handlers are independent. An error in one * handler does not necessarily mean that another one will * fail, too. Later, we might add a config variable to control * this behaviour (but I am not sure if that is really * necessary). -- rgerhards, 2007-07-31 */ pHdlrP = *p; if (pCmdHdlr->permitted != NULL && !*(pCmdHdlr->permitted)) { LogError(0, RS_RET_PARAM_NOT_PERMITTED, "command '%s' is currently not " "permitted - did you already set it via a RainerScript command (v6+ config)?", pCmdName); ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED); } else if ((iRet = cslchCallHdlr(pCmdHdlr, &pHdlrP)) == RS_RET_OK) { bWasOnceOK = 1; pOKp = pHdlrP; } } if (bWasOnceOK == 1) { *p = pOKp; iRet = RS_RET_OK; } if (iRetLL != RS_RET_END_OF_LINKEDLIST) iRet = iRetLL; finalize_it: RETiRet; } /* debug print the command handler structure */ void dbgPrintCfSysLineHandlers(void) { cslCmd_t *pCmd; cslCmdHdlr_t *pCmdHdlr; linkedListCookie_t llCookieCmd; linkedListCookie_t llCookieCmdHdlr; uchar *pKey; dbgprintf("System Line Configuration Commands:\n"); llCookieCmd = NULL; while (llGetNextElt(&llCmdList, &llCookieCmd, (void *)&pCmd) == RS_RET_OK) { llGetKey(llCookieCmd, (void *)&pKey); /* TODO: using the cookie is NOT clean! */ dbgprintf("\tCommand '%s':\n", pKey); llCookieCmdHdlr = NULL; while (llGetNextElt(&pCmd->llCmdHdlrs, &llCookieCmdHdlr, (void *)&pCmdHdlr) == RS_RET_OK) { dbgprintf("\t\ttype : %d\n", pCmdHdlr->eType); dbgprintf("\t\tpData: 0x%lx\n", (unsigned long)pCmdHdlr->pData); dbgprintf("\t\tHdlr : 0x%lx\n", (unsigned long)pCmdHdlr->cslCmdHdlr); dbgprintf("\t\tOwner: 0x%lx\n", (unsigned long)llCookieCmdHdlr->pKey); dbgprintf("\n"); } } dbgprintf("\n"); } rsRetVal cfsyslineInit(void) { DEFiRet; CHKiRet(objGetObjInterface(&obj)); CHKiRet(llInit(&llCmdList, cslcDestruct, cslcKeyDestruct, (int (*)(void *, void *))strcasecmp)); finalize_it: RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/ruleset.h0000644000000000000000000000013015145046113016054 xustar0030 mtime=1771326539.013013864 29 atime=1787067616.84141547 29 ctime=1787067794.42772567 rsyslog-8.2608.0/runtime/ruleset.h0000664000175000017500000001026515145046113015526 0ustar00rgerrger/* The ruleset object. * * This implements rulesets within rsyslog. * * Copyright 2009-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_RULESET_H #define INCLUDED_RULESET_H #include "queue.h" #include "linkedlist.h" #include "rsconf.h" /* the ruleset object */ struct ruleset_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ uchar *pszName; /* name of our ruleset */ qqueue_t *pQueue; /* "main" message queue, if the ruleset has its own (else NULL) */ struct cnfstmt *root; struct cnfstmt *last; parserList_t *pParserLst; /* list of parsers to use for this ruleset */ }; /* interfaces */ BEGINinterface(ruleset) /* name must also be changed in ENDinterface macro! */ INTERFACEObjDebugPrint(ruleset); rsRetVal (*DebugPrintAll)(rsconf_t *conf); rsRetVal (*Construct)(ruleset_t **ppThis); rsRetVal (*ConstructFinalize)(rsconf_t *conf, ruleset_t __attribute__((unused)) * pThis); rsRetVal (*Destruct)(ruleset_t **ppThis); rsRetVal (*DestructAllActions)(rsconf_t *conf); rsRetVal (*SetName)(ruleset_t *pThis, uchar *pszName); rsRetVal (*ProcessBatch)(batch_t *, wti_t *); rsRetVal (*GetRuleset)(rsconf_t *conf, ruleset_t **ppThis, uchar *); rsRetVal (*SetDefaultRuleset)(rsconf_t *conf, uchar *); rsRetVal (*SetCurrRuleset)(rsconf_t *conf, uchar *); ruleset_t *(*GetCurrent)(rsconf_t *conf); qqueue_t *(*GetRulesetQueue)(ruleset_t *); /* v3, 2009-11-04 */ parserList_t *(*GetParserList)(rsconf_t *conf, smsg_t *); /* v5, 2011-04-19 * added support for the rsconf object -- fundamental change * v6, 2011-07-15 * removed conf ptr from SetName, AddRule as the flex/bison based * system uses globals in any case. */ /* v7, 2012-09-04 */ /* AddRule() removed */ /*TODO:REMOVE*/ rsRetVal (*IterateAllActions)(rsconf_t *conf, rsRetVal (*pFunc)(void *, void *), void *pParam); void (*AddScript)(ruleset_t *pThis, struct cnfstmt *script); /* v8: changed processBatch interface */ ENDinterface(ruleset) #define rulesetCURR_IF_VERSION 8 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObjFull(ruleset); PROTOTYPEObjDebugPrint(ruleset); /* TODO: remove these -- currently done dirty for config file * redo -- rgerhards, 2011-04-19 * rgerhards, 2012-04-19: actually, it may be way cooler not to remove * them and use plain c-style conventions at least inside core objects. */ rsRetVal rulesetDestructForLinkedList(void *pData); rsRetVal rulesetKeyDestruct(void __attribute__((unused)) * pData); /* Get name associated to ruleset. This function cannot fail (except, * of course, if previously something went really wrong). Returned * pointer is read-only. * rgerhards, 2012-04-18 */ #define rulesetGetName(pRuleset) ((pRuleset)->pszName) /* returns 1 if the ruleset has a queue associated, 0 if not */ #define rulesetHasQueue(pRuleset) \ (((pRuleset)->pQueue != NULL) && ((pRuleset)->pQueue->qType != QUEUETYPE_DIRECT) ? 1 : 0) /* we will most probably convert this module back to traditional C * calling sequence, so here we go... */ rsRetVal rulesetGetRuleset(rsconf_t *conf, ruleset_t **ppRuleset, uchar *pszName); rsRetVal rulesetOptimizeAll(rsconf_t *conf); rsRetVal rulesetProcessCnf(struct cnfobj *o); rsRetVal activateRulesetQueues(void); /* Set a current rule set to already-known pointer */ #define rulesetSetCurrRulesetPtr(pRuleset) (loadConf->rulesets.pCurr = (pRuleset)) #endif /* #ifndef INCLUDED_RULESET_H */ rsyslog-8.2608.0/runtime/PaxHeaders/action.c0000644000000000000000000000013215241075234015646 xustar0030 mtime=1787067036.599578182 30 atime=1787067036.744580897 30 ctime=1787067794.466726397 rsyslog-8.2608.0/runtime/action.c0000664000175000017500000034427215241075234015326 0ustar00rgerrger/** * @file action.c * @brief Implementation of the action object. * * This module contains the core implementation of output actions. An * action can operate in direct or queued mode and may maintain * per-worker state. Several message submission paths exist and are * chosen at runtime depending on configuration. All filtering is * performed before a message is enqueued so that queued and direct * modes behave identically. * * Some output modules offer transactional behavior. In this context a * transaction simply groups the current batch of messages. Rollback * is not guaranteed, so message delivery follows an at-least-once model. * * The legacy comments below outline the call sequences used for the * various execution modes. They are retained for reference. * * File begun on 2007-08-06 by Rainer Gerhards (extracted from syslogd.c). * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * * @section action_flow Action Execution Flow * The submission path depends on rate limiting and mark handling: * - If @c iExecEveryNthOccur or @c iSecsExecOnceInterval is set, * doSubmitToActionQComplex() -> actionWriteToAction() -> doSubmitToActionQ() * -> queue processing. * - If @c bWriteAllMarkMsgs is false, * doSubmitToActionQNotAllMark() -> doSubmitToActionQ() -> queue processing. * - Otherwise, * doSubmitToActionQ() -> qqueueEnqObj() -> queue processing. * When mark messages are not written immediately, doSubmitToActionQNotAllMark() * filters out those that are not yet due. * After dequeue, processBatchMain() invokes processMsgMain() for each message. * Direct queues enter at processMsgMain(). * All filtering happens before enqueue so direct and queued modes behave identically. * Historically some filters ran after the queue, leading to inconsistent * results. Since version 5.8.2 all checks occur before enqueue so * queued and direct modes process the same set of messages. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "dirty.h" #include "template.h" #include "action.h" #include "modules.h" #include "cfsysline.h" #include "srUtils.h" #include "errmsg.h" #include "batch.h" #include "wti.h" #include "rsconf.h" #include "datetime.h" #include "unicode-helper.h" #include "atomic.h" #include "ruleset.h" #include "parserif.h" #include "statsobj.h" #include "runtime/translate.h" #include "ratelimit.h" /* AIXPORT : cs renamed to legacy_cs as clashes with libpthreads variable in complete file*/ #ifdef _AIX #define cs legacy_cs #endif PRAGMA_IGNORE_Wswitch_enum #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif #define NO_TIME_PROVIDED 0 /* indicate we do not provide any cached time */ /* forward definitions */ static rsRetVal ATTR_NONNULL() processBatchMain(void *pVoid, batch_t *pBatch, wti_t *const pWti); static rsRetVal doSubmitToActionQ(action_t *const pAction, wti_t *const pWti, smsg_t *); static rsRetVal doSubmitToActionQComplex(action_t *const pAction, wti_t *const pWti, smsg_t *); static rsRetVal doSubmitToActionQNotAllMark(action_t *const pAction, wti_t *const pWti, smsg_t *); static void ATTR_NONNULL() actionSuspend(action_t *const pThis, wti_t *const pWti); static void ATTR_NONNULL() actionRetry(action_t *const pThis, wti_t *const pWti); /* object static data (once for all instances) */ DEFobjCurrIf(obj) DEFobjCurrIf(datetime) DEFobjCurrIf(module) DEFobjCurrIf(statsobj) DEFobjCurrIf(ruleset) typedef struct configSettings_s { int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */ int bActionWriteAllMarkMsgs; /* should all mark messages be unconditionally written? */ int iActExecOnceInterval; /* execute action once every nn seconds */ int iActExecEveryNthOccur; /* execute action every n-th occurrence (0,1=always) */ time_t iActExecEveryNthOccurTO; /* timeout for n-occurrence setting (in seconds, 0=never) */ int glbliActionResumeInterval; int glbliActionResumeRetryCount; /* how often should suspended actions be retried? */ int bActionRepMsgHasMsg; /* last messsage repeated... has msg fragment in it */ uchar *pszActionName; /* short name for the action */ /* action queue and its configuration parameters */ queueType_t ActionQueType; /* type of the main message queue above */ int iActionQueueSize; /* size of the main message queue above */ int iActionQueueDeqBatchSize; /* batch size for action queues */ int iActionQHighWtrMark; /* high water mark for disk-assisted queues */ int iActionQLowWtrMark; /* low water mark for disk-assisted queues */ int iActionQDiscardMark; /* begin to discard messages */ int iActionQDiscardSeverity; /* by default, discard nothing to prevent unintentional loss */ int iActionQueueNumWorkers; /* number of worker threads for the mm queue above */ uchar *pszActionQFName; /* prefix for the main message queue file */ int64 iActionQueMaxFileSize; int iActionQPersistUpdCnt; /* persist queue info every n updates */ int bActionQSyncQeueFiles; /* sync queue files */ int iActionQtoQShutdown; /* queue shutdown */ int iActionQtoActShutdown; /* action shutdown (in phase 2) */ int iActionQtoEnq; /* timeout for queue enque */ int iActionQtoWrkShutdown; /* timeout for worker thread shutdown */ int iActionQWrkMinMsgs; /* minimum messages per worker needed to start a new one */ int bActionQSaveOnShutdown; /* save queue on shutdown (when DA enabled)? */ int64 iActionQueMaxDiskSpace; /* max disk space allocated 0 ==> unlimited */ int iActionQueueDeqSlowdown; /* dequeue slowdown (simple rate limiting) */ int iActionQueueDeqtWinFromHr; /* hour begin of time frame when queue is to be dequeued */ int iActionQueueDeqtWinToHr; /* hour begin of time frame when queue is to be dequeued */ } configSettings_t; static configSettings_t cs; /* our current config settings */ /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfparamdescr[] = { {"name", eCmdHdlrGetWord, 0}, /* legacy: actionname */ {"type", eCmdHdlrString, CNFPARAM_REQUIRED}, /* legacy: actionname */ {"action.errorfile", eCmdHdlrString, 0}, {"action.errorfile.maxsize", eCmdHdlrInt, 0}, {"action.writeallmarkmessages", eCmdHdlrBinary, 0}, /* legacy: actionwriteallmarkmessages */ {"action.execonlyeverynthtime", eCmdHdlrInt, 0}, /* legacy: actionexeconlyeverynthtime */ {"action.execonlyeverynthtimetimeout", eCmdHdlrInt, 0}, /* legacy: actionexeconlyeverynthtimetimeout */ {"action.execonlyonceeveryinterval", eCmdHdlrInt, 0}, /* legacy: actionexeconlyonceeveryinterval */ {"action.execonlywhenpreviousissuspended", eCmdHdlrBinary, 0}, /* legacy: actionexeconlywhenpreviousissuspended */ {"action.repeatedmsgcontainsoriginalmsg", eCmdHdlrBinary, 0}, /* legacy: repeatedmsgcontainsoriginalmsg */ {"action.resumeretrycount", eCmdHdlrInt, 0}, /* legacy: actionresumeretrycount */ {"action.reportsuspension", eCmdHdlrBinary, 0}, {"action.reportsuspensioncontinuation", eCmdHdlrBinary, 0}, {"action.resumeintervalmax", eCmdHdlrPositiveInt, 0}, {"action.resumeinterval", eCmdHdlrInt, 0}, {"action.externalstate.file", eCmdHdlrString, 0}, {"action.ratelimit.name", eCmdHdlrString, 0}, {"action.copymsg", eCmdHdlrBinary, 0}}; static struct cnfparamblk pblk = {CNFPARAMBLK_VERSION, sizeof(cnfparamdescr) / sizeof(struct cnfparamdescr), cnfparamdescr}; /* primarily a helper for debug purposes, get human-readble name of state */ /* currently not needed, but may be useful in the future! */ #if 0 static const char * batchState2String(const batch_state_t state) { switch(state) { case BATCH_STATE_RDY: return "BATCH_STATE_RDY"; case BATCH_STATE_BAD: return "BATCH_STATE_BAD"; case BATCH_STATE_SUB: return "BATCH_STATE_SUB"; case BATCH_STATE_COMM: return "BATCH_STATE_COMM"; case BATCH_STATE_DISC: return "BATCH_STATE_DISC"; default: return "ERROR, batch state not known!"; } } #endif // #if 0 /* ------------------------------ methods ------------------------------ */ /* This function returns the "current" time for this action. Current time * is not necessarily real-time. In order to enhance performance, current * system time is obtained the first time an action needs to know the time * and then kept cached inside the action structure. Later requests will * always return that very same time. Wile not totally accurate, it is far * accurate in most cases and considered "acurate enough" for all cases. * When changing the threading model, please keep in mind that this * logic needs to be changed should we once allow more than one parallel * call into the same action (object). As this is currently not supported, * we simply cache the time inside the action object itself, after it * is under mutex protection. * Side-note: the value -1 is used as tActNow, because it also is the * error return value of time(). So we would do a retry with the next * invocation if time() failed. Then, of course, we would probably already * be in trouble, but for the sake of performance we accept this very, * very slight risk. * This logic has been added as part of an overall performance improvment * effort inspired by David Lang. -- rgerhards, 2008-09-16 * Note: this function does not use the usual iRet call conventions * because that would provide little to no benefit but complicate things * a lot. So we simply return the system time. */ static time_t getActNow(action_t *const pThis) { assert(pThis != NULL); if (pThis->tActNow == -1) { pThis->tActNow = datetime.GetTime(NULL); /* good time call - the only one done */ if (pThis->tLastExec > pThis->tActNow) { /* if we are traveling back in time, reset tLastExec */ pThis->tLastExec = (time_t)0; } } return pThis->tActNow; } /* resets action queue parameters to their default values. This happens * after each action has been created in order to prevent any wild defaults * to be used. It is somewhat against the original spirit of the config file * reader, but I think it is a good thing to do. * rgerhards, 2008-01-29 */ static rsRetVal actionResetQueueParams(void) { DEFiRet; cs.ActionQueType = QUEUETYPE_DIRECT; /* type of the main message queue above */ cs.iActionQueueSize = 1000; /* size of the main message queue above */ cs.iActionQueueDeqBatchSize = 128; /* default batch size */ cs.iActionQHighWtrMark = -1; /* high water mark for disk-assisted queues */ cs.iActionQLowWtrMark = -1; /* low water mark for disk-assisted queues */ cs.iActionQDiscardMark = -1; /* begin to discard messages */ cs.iActionQDiscardSeverity = 8; /* discard warning and above */ cs.iActionQueueNumWorkers = 1; /* number of worker threads for the mm queue above */ cs.iActionQueMaxFileSize = 1024 * 1024; cs.iActionQPersistUpdCnt = 0; /* persist queue info every n updates */ cs.bActionQSyncQeueFiles = 0; cs.iActionQtoQShutdown = 0; /* queue shutdown */ cs.iActionQtoActShutdown = 1000; /* action shutdown (in phase 2) */ cs.iActionQtoEnq = 50; /* timeout for queue enque */ cs.iActionQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */ cs.iActionQWrkMinMsgs = -1; /* minimum messages per worker needed to start a new one */ cs.bActionQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ cs.iActionQueMaxDiskSpace = 0; cs.iActionQueueDeqSlowdown = 0; cs.iActionQueueDeqtWinFromHr = 0; cs.iActionQueueDeqtWinToHr = 25; /* 25 disables time windowed dequeuing */ cs.glbliActionResumeRetryCount = 0; /* I guess it is smart to reset this one, too */ free(cs.pszActionQFName); cs.pszActionQFName = NULL; /* prefix for the main message queue file */ RETiRet; } /* free action worker data table */ static void freeWrkrDataTable(action_t *const pThis) { int freeSpot; for (freeSpot = 0; freeSpot < pThis->wrkrDataTableSize; ++freeSpot) { if (pThis->wrkrDataTable[freeSpot] != NULL) { pThis->pMod->mod.om.freeWrkrInstance(pThis->wrkrDataTable[freeSpot]); pThis->wrkrDataTable[freeSpot] = NULL; } } free(pThis->wrkrDataTable); return; } /* destructs an action descriptor object * rgerhards, 2007-08-01 */ rsRetVal actionDestruct(action_t *const pThis) { DEFiRet; assert(pThis != NULL); if (!strcmp((char *)modGetName(pThis->pMod), "builtin:omdiscard")) { /* discard actions will be optimized out */ nvlstDestruct(pThis->pSyntaxLst); pThis->pSyntaxLst = NULL; FINALIZE; } if (pThis->pQueue != NULL) { qqueueDestruct(&pThis->pQueue); } /* destroy stats object, if we have one (may not always be * be the case, e.g. if turned off) */ if (pThis->statsobj != NULL) statsobj.Destruct(&pThis->statsobj); if (pThis->ratelimiter != NULL) ratelimitDestruct(pThis->ratelimiter); if (pThis->fdErrFile != -1) close(pThis->fdErrFile); pthread_mutex_destroy(&pThis->mutErrFile); pthread_mutex_destroy(&pThis->mutAction); pthread_mutex_destroy(&pThis->mutWrkrDataTable); free((void *)pThis->pszErrFile); free((void *)pThis->pszExternalStateFile); free(pThis->pszRatelimitName); free(pThis->pszName); nvlstDestruct(pThis->pSyntaxLst); free(pThis->ppTpl); free(pThis->peParamPassing); freeWrkrDataTable(pThis); /* The module's instance data must be freed after the worker data table, * as workers may need to access the shared module data during their * cleanup. */ if (pThis->pModData != NULL) pThis->pMod->freeInstance(pThis->pModData); finalize_it: free(pThis); RETiRet; } /* Disable action, this means it will never again be usable * until rsyslog is reloaded. Use only as a last resort, but * depends on output module. * rgerhards, 2007-08-02 */ static inline void actionDisable(action_t *__restrict__ const pThis) { actionStoreDisabled(pThis, 1); } /* create a new action descriptor object * rgerhards, 2007-08-01 * Note that it is vital to set proper initial values as the v6 config * system depends on these! */ rsRetVal actionConstruct(action_t **ppThis) { DEFiRet; action_t *pThis; assert(ppThis != NULL); CHKmalloc(pThis = (action_t *)calloc(1, sizeof(action_t))); pThis->iResumeInterval = 30; pThis->iResumeIntervalMax = 1800; /* max interval default is half an hour */ pThis->iResumeRetryCount = 0; pThis->pszName = NULL; pThis->pszErrFile = NULL; pThis->maxErrFileSize = 0; pThis->currentErrFileSize = 0; pThis->pszExternalStateFile = NULL; pThis->pszRatelimitName = NULL; pThis->ratelimiter = NULL; pThis->fdErrFile = -1; pThis->bWriteAllMarkMsgs = 1; pThis->iExecEveryNthOccur = 0; pThis->iExecEveryNthOccurTO = 0; pThis->iSecsExecOnceInterval = 0; pThis->bExecWhenPrevSusp = 0; pThis->bRepMsgHasMsg = 0; pThis->bDisabled = 0; pThis->isTransactional = 0; pThis->bReportSuspension = -1; /* indicate "not yet set" */ pThis->bReportSuspensionCont = -1; /* indicate "not yet set" */ pThis->bCopyMsg = 0; pThis->tLastOccur = datetime.GetTime(NULL); /* done once per action on startup only */ pThis->iActionNbr = loadConf->actions.iActionNbr; pthread_mutex_init(&pThis->mutErrFile, NULL); pthread_mutex_init(&pThis->mutAction, NULL); pthread_mutex_init(&pThis->mutWrkrDataTable, NULL); INIT_ATOMIC_HELPER_MUT(pThis->mutCAS); /* indicate we have a new action */ loadConf->actions.iActionNbr++; finalize_it: *ppThis = pThis; RETiRet; } static rsRetVal actionRegisterName(action_t *const pThis) { DEFiRet; size_t i; char *name = NULL; char **names = NULL; struct actions_s *const actions = &loadConf->actions; if (pThis->pszName == NULL) { FINALIZE; } for (i = 0; i < actions->n_action_names; ++i) { if (!strcmp(actions->action_names[i], (char *)pThis->pszName)) { LogMsg(0, RS_RET_OK, LOG_WARNING, "action: duplicate name '%s' in current config set; impstats counters may be ambiguous", pThis->pszName); FINALIZE; } } CHKmalloc(name = strdup((char *)pThis->pszName)); if (actions->n_action_names == actions->n_action_names_alloc) { const size_t newAlloc = (actions->n_action_names_alloc == 0) ? 8 : actions->n_action_names_alloc * 2; CHKmalloc(names = realloc(actions->action_names, newAlloc * sizeof(char *))); actions->action_names = names; actions->n_action_names_alloc = newAlloc; } actions->action_names[actions->n_action_names++] = name; name = NULL; finalize_it: free(name); RETiRet; } /* action construction finalizer */ rsRetVal actionConstructFinalize(action_t *__restrict__ const pThis, struct nvlst *lst) { DEFiRet; uchar pszAName[64]; /* friendly name of our action */ if (!strcmp((char *)modGetName(pThis->pMod), "builtin:omdiscard")) { /* discard actions will be optimized out */ FINALIZE; } /* generate a friendly name for us action stats */ if (pThis->pszName == NULL) { snprintf((char *)pszAName, sizeof(pszAName), "action-%d-%s", pThis->iActionNbr, pThis->pMod->pszName); pThis->pszName = ustrdup(pszAName); } /* cache transactional attribute */ pThis->isTransactional = pThis->pMod->mod.om.supportsTX; if (pThis->isTransactional) { int i; for (i = 0; i < pThis->iNumTpls; ++i) { if (pThis->peParamPassing[i] != ACT_STRING_PASSING) { LogError(0, RS_RET_INVLD_OMOD, "action '%s'(%d) is transactional but " "parameter %d " "uses invalid parameter passing mode -- disabling " "action. This is probably caused by a pre-v7 " "output module that needs upgrade.", pThis->pszName, pThis->iActionNbr, i); actionDisable(pThis); ABORT_FINALIZE(RS_RET_INVLD_OMOD); } } } /* support statistics gathering */ CHKiRet(statsobj.Construct(&pThis->statsobj)); CHKiRet(statsobj.SetName(pThis->statsobj, pThis->pszName)); CHKiRet(statsobj.SetOrigin(pThis->statsobj, (uchar *)"core.action")); STATSCOUNTER_INIT(pThis->ctrProcessed, pThis->mutCtrProcessed); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("processed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrProcessed)); STATSCOUNTER_INIT(pThis->ctrBatchesProcessed, pThis->mutCtrBatchesProcessed); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("batchesprocessed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrBatchesProcessed)); STATSCOUNTER_INIT(pThis->ctrFail, pThis->mutCtrFail); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("failed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFail)); STATSCOUNTER_INIT(pThis->ctrSuspend, pThis->mutCtrSuspend); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("suspended"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrSuspend)); STATSCOUNTER_INIT(pThis->ctrSuspendDuration, pThis->mutCtrSuspendDuration); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("suspended.duration"), ctrType_IntCtr, 0, &pThis->ctrSuspendDuration)); STATSCOUNTER_INIT(pThis->ctrResume, pThis->mutCtrResume); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("resumed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrResume)); STATSCOUNTER_INIT(pThis->ctrRateLimitAllowed, pThis->mutCtrRateLimitAllowed); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("ratelimit.allowed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrRateLimitAllowed)); STATSCOUNTER_INIT(pThis->ctrRateLimitDropped, pThis->mutCtrRateLimitDropped); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("ratelimit.dropped"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrRateLimitDropped)); STATSCOUNTER_INIT(pThis->ctrRateLimitPaced, pThis->mutCtrRateLimitPaced); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("ratelimit.paced"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrRateLimitPaced)); STATSCOUNTER_INIT(pThis->ctrRateLimitPacedUsec, pThis->mutCtrRateLimitPacedUsec); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("ratelimit.paced_usec"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrRateLimitPacedUsec)); CHKiRet(statsobj.ConstructFinalize(pThis->statsobj)); /* create our queue */ /* generate a friendly name for the queue */ snprintf((char *)pszAName, sizeof(pszAName), "%s queue", pThis->pszName); /* now check if we can run the action in "firehose mode" during stage one of * its processing (that is before messages are enqueued into the action q). * This is only possible if some features, which require strict sequence, are * not used. Thankfully, that is usually the case. The benefit of firehose * mode is much faster processing (and simpler code) -- rgerhards, 2010-06-08 */ if (pThis->iExecEveryNthOccur > 1 || pThis->iSecsExecOnceInterval) { DBGPRINTF( "info: firehose mode disabled for action because " "iExecEveryNthOccur=%d, iSecsExecOnceInterval=%d\n", pThis->iExecEveryNthOccur, pThis->iSecsExecOnceInterval); pThis->submitToActQ = doSubmitToActionQComplex; } else if (pThis->bWriteAllMarkMsgs) { /* full firehose submission mode, default case*/ pThis->submitToActQ = doSubmitToActionQ; } else { /* nearly full-speed submission mode */ pThis->submitToActQ = doSubmitToActionQNotAllMark; } /* create queue */ /* action queues always (for now) have just one worker. This may change when * we begin to implement an interface the enable output modules to request * to be run on multiple threads. So far, this is forbidden by the interface * spec. -- rgerhards, 2008-01-30 */ CHKiRet(qqueueConstruct(&pThis->pQueue, cs.ActionQueType, 1, cs.iActionQueueSize, processBatchMain)); obj.SetName((obj_t *)pThis->pQueue, pszAName); qqueueSetpAction(pThis->pQueue, pThis); if (lst == NULL) { /* use legacy params? */ /* ... set some properties ... */ #define setQPROP(func, directive, data) \ CHKiRet_Hdlr(func(pThis->pQueue, data)) { \ LogError(0, NO_ERRCODE, \ "Invalid " #directive \ ", \ error %d. Ignored, running with default setting", \ iRet); \ } #define setQPROPstr(func, directive, data) \ CHKiRet_Hdlr(func(pThis->pQueue, data, (data == NULL) ? 0 : strlen((char *)data))) { \ LogError(0, NO_ERRCODE, \ "Invalid " #directive \ ", \ error %d. Ignored, running with default setting", \ iRet); \ } setQPROP(qqueueSetsizeOnDiskMax, "$ActionQueueMaxDiskSpace", cs.iActionQueMaxDiskSpace); setQPROP(qqueueSetiDeqBatchSize, "$ActionQueueDequeueBatchSize", cs.iActionQueueDeqBatchSize); setQPROP(qqueueSetMaxFileSize, "$ActionQueueFileSize", cs.iActionQueMaxFileSize); setQPROPstr(qqueueSetFilePrefix, "$ActionQueueFileName", cs.pszActionQFName); setQPROP(qqueueSetiPersistUpdCnt, "$ActionQueueCheckpointInterval", cs.iActionQPersistUpdCnt); setQPROP(qqueueSetbSyncQueueFiles, "$ActionQueueSyncQueueFiles", cs.bActionQSyncQeueFiles); setQPROP(qqueueSettoQShutdown, "$ActionQueueTimeoutShutdown", cs.iActionQtoQShutdown); setQPROP(qqueueSettoActShutdown, "$ActionQueueTimeoutActionCompletion", cs.iActionQtoActShutdown); setQPROP(qqueueSettoWrkShutdown, "$ActionQueueWorkerTimeoutThreadShutdown", cs.iActionQtoWrkShutdown); setQPROP(qqueueSettoEnq, "$ActionQueueTimeoutEnqueue", cs.iActionQtoEnq); setQPROP(qqueueSetiHighWtrMrk, "$ActionQueueHighWaterMark", cs.iActionQHighWtrMark); setQPROP(qqueueSetiLowWtrMrk, "$ActionQueueLowWaterMark", cs.iActionQLowWtrMark); setQPROP(qqueueSetiDiscardMrk, "$ActionQueueDiscardMark", cs.iActionQDiscardMark); setQPROP(qqueueSetiDiscardSeverity, "$ActionQueueDiscardSeverity", cs.iActionQDiscardSeverity); setQPROP(qqueueSetiMinMsgsPerWrkr, "$ActionQueueWorkerThreadMinimumMessages", cs.iActionQWrkMinMsgs); setQPROP(qqueueSetiNumWorkerThreads, "$ActionQueueWorkerThreads", cs.iActionQueueNumWorkers); setQPROP(qqueueSetbSaveOnShutdown, "$ActionQueueSaveOnShutdown", cs.bActionQSaveOnShutdown); setQPROP(qqueueSetiDeqSlowdown, "$ActionQueueDequeueSlowdown", cs.iActionQueueDeqSlowdown); setQPROP(qqueueSetiDeqtWinFromHr, "$ActionQueueDequeueTimeBegin", cs.iActionQueueDeqtWinFromHr); setQPROP(qqueueSetiDeqtWinToHr, "$ActionQueueDequeueTimeEnd", cs.iActionQueueDeqtWinToHr); } else { /* we have v6-style config params */ qqueueSetDefaultsActionQueue(pThis->pQueue); qqueueApplyCnfParam(pThis->pQueue, lst); } qqueueCorrectParams(pThis->pQueue); if (pThis->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfigForScope(&pThis->ratelimiter, loadConf, (char *)pThis->pszRatelimitName, "action", (char *)pThis->pszName, RATELIMIT_SCOPE_OUTPUT)); ratelimitSetNoTimeCache(pThis->ratelimiter); ratelimitSetThreadSafe(pThis->ratelimiter); if (pThis->pQueue->qType == QUEUETYPE_DIRECT) { ratelimitForbidOutputPace(pThis->ratelimiter); } if (ratelimitGetOutputMode(pThis->ratelimiter) == RATELIMIT_OUTPUT_MODE_PACE && pThis->pQueue->qType == QUEUETYPE_DIRECT) { LogError(0, RS_RET_CONFIG_ERROR, "action '%s': action.ratelimit.name='%s' uses pace mode, which requires a non-direct action " "queue", pThis->pszName, pThis->pszRatelimitName); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } #undef setQPROP #undef setQPROPstr qqueueDbgPrint(pThis->pQueue); DBGPRINTF("Action %p: queue %p created\n", pThis, pThis->pQueue); if (pThis->bUsesMsgPassingMode && pThis->pQueue->qType != QUEUETYPE_DIRECT) { parser_warnmsg( "module %s with message passing mode uses " "non-direct queue. This most probably leads to undesired " "results. For message modificaton modules (mm*), this means " "that they will have no effect - " "see https://www.rsyslog.com/mm-no-queue/", (char *)modGetName(pThis->pMod)); } /* and now reset the queue params (see comment in its function header!) */ actionResetQueueParams(); CHKiRet(actionRegisterName(pThis)); finalize_it: RETiRet; } /* set the global resume interval */ rsRetVal actionSetGlobalResumeInterval(int iNewVal) { cs.glbliActionResumeInterval = iNewVal; return RS_RET_OK; } /* returns the action state name in human-readable form * returned string must not be modified. * rgerhards, 2009-05-07 */ static uchar *getActStateName(action_t *const pThis, wti_t *const pWti) { switch (getActionState(pWti, pThis)) { case ACT_STATE_RDY: return (uchar *)"rdy"; case ACT_STATE_ITX: return (uchar *)"itx"; case ACT_STATE_RTRY: return (uchar *)"rtry"; case ACT_STATE_SUSP: return (uchar *)"susp"; case ACT_STATE_DATAFAIL: return (uchar *)"datafail"; case ACT_STATE_DISABLED: return (uchar *)"disabled"; default: return (uchar *)"ERROR/UNKNWON"; } } /* returns a suitable return code based on action state * rgerhards, 2009-05-07 */ static rsRetVal getReturnCode(action_t *const pThis, wti_t *const pWti) { DEFiRet; switch (getActionState(pWti, pThis)) { case ACT_STATE_RDY: iRet = RS_RET_OK; break; case ACT_STATE_ITX: if (pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit) { pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 0; /* auto-reset */ iRet = RS_RET_PREVIOUS_COMMITTED; } else { iRet = RS_RET_DEFER_COMMIT; } break; case ACT_STATE_RTRY: iRet = RS_RET_SUSPENDED; break; case ACT_STATE_SUSP: iRet = RS_RET_ACTION_FAILED; break; case ACT_STATE_DATAFAIL: iRet = RS_RET_DATAFAIL; break; case ACT_STATE_DISABLED: iRet = RS_RET_DISABLE_ACTION; break; default: DBGPRINTF("Invalid action engine state %u, program error\n", getActionState(pWti, pThis)); iRet = RS_RET_ERR; break; } RETiRet; } /* set the action to a new state * rgerhards, 2007-08-02 */ static void actionSetState(action_t *const pThis, const char *const callerName, wti_t *const pWti, uint8_t newState) { setActionState(pWti, pThis, newState); DBGPRINTF("action[%s] transitioned to state: %s (caller %s)\n", pThis->pszName, getActStateName(pThis, pWti), callerName); } static void actionDisableForWorker(action_t *const pThis, wti_t *const pWti) { actionDisable(pThis); if (pWti != NULL && getActionState(pWti, pThis) != ACT_STATE_DISABLED) { actionSetState(pThis, __func__, pWti, ACT_STATE_DISABLED); } } /* Handles the transient commit state. So far, this is * mostly a dummy... * rgerhards, 2007-08-02 */ static void actionCommitted(action_t *const pThis, wti_t *const pWti) { actionSetState(pThis, __func__, pWti, ACT_STATE_RDY); } static rsRetVal ATTR_NONNULL() actionCheckOutputRatelimit(action_t *const pAction, wti_t *const pWti) { unsigned int wait_usec; unsigned int sleep_usec; ratelimit_output_mode_t mode; DEFiRet; if (pAction->ratelimiter == NULL) FINALIZE; mode = ratelimitGetOutputMode(pAction->ratelimiter); if (mode == RATELIMIT_OUTPUT_MODE_DROP) { iRet = ratelimitMsgCount(pAction->ratelimiter, NO_TIME_PROVIDED, (char *)pAction->pszName); if (iRet == RS_RET_OK) { STATSCOUNTER_INC(pAction->ctrRateLimitAllowed, pAction->mutCtrRateLimitAllowed); } else if (iRet == RS_RET_DISCARDMSG) { STATSCOUNTER_INC(pAction->ctrRateLimitDropped, pAction->mutCtrRateLimitDropped); } FINALIZE; } for (;;) { wait_usec = 0; iRet = ratelimitMsgCountWait(pAction->ratelimiter, NO_TIME_PROVIDED, (char *)pAction->pszName, &wait_usec); if (iRet == RS_RET_OK) { STATSCOUNTER_INC(pAction->ctrRateLimitAllowed, pAction->mutCtrRateLimitAllowed); FINALIZE; } if (iRet != RS_RET_DISCARDMSG) FINALIZE; if (wtiIsShutdownImmediate(pWti)) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } sleep_usec = wait_usec > 1000000U ? 1000000U : wait_usec; STATSCOUNTER_INC(pAction->ctrRateLimitPaced, pAction->mutCtrRateLimitPaced); STATSCOUNTER_ADD(pAction->ctrRateLimitPacedUsec, pAction->mutCtrRateLimitPacedUsec, sleep_usec); srSleep(sleep_usec / 1000000U, sleep_usec % 1000000U); } finalize_it: RETiRet; } /* set action state according to external state file (if configured) */ static rsRetVal ATTR_NONNULL() checkExternalStateFile(action_t *const pThis, wti_t *const pWti) { char filebuf[1024]; int fd = -1; int r; DEFiRet; DBGPRINTF("checking external state file\n"); if (pThis->pszExternalStateFile == NULL) { FINALIZE; } fd = open(pThis->pszExternalStateFile, O_RDONLY | O_CLOEXEC); if (fd == -1) { dbgprintf("could not read external state file\n"); FINALIZE; } r = read(fd, filebuf, sizeof(filebuf) - 1); if (r < 1) { dbgprintf("checkExternalStateFile read() returned %d\n", r); FINALIZE; } filebuf[r] = '\0'; dbgprintf("external state file content: '%s'\n", filebuf); /* trim trailing whitespace */ for (int j = r - 1; j > 0; --j) { if (filebuf[j] == '\n' || filebuf[j] == '\t' || filebuf[j] == ' ') { filebuf[j] = '\0'; } else { break; } } if (!strcmp(filebuf, "SUSPENDED")) { LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "action '%s' suspended (module '%s') by external state file", pThis->pszName, pThis->pMod->pszName); actionRetry(pThis, pWti); ABORT_FINALIZE(RS_RET_SUSPENDED); } finalize_it: if (fd != -1) { close(fd); } DBGPRINTF("done checking external state file, iRet=%d\n", iRet); RETiRet; } /* we need to defer setting the action's own bReportSuspension state until * after the full config has been processed. So the most simple case to do * that is here. It's not a performance problem, as it happens infrequently. * it's not a threading race problem, as always the same value will be written. * As we need to do this in several places, we have moved the code to its own * helper function. */ static void setSuspendMessageConfVars(action_t *__restrict__ const pThis) { if (pThis->bReportSuspension == -1) pThis->bReportSuspension = runConf->globals.bActionReportSuspension; if (pThis->bReportSuspensionCont == -1) { pThis->bReportSuspensionCont = runConf->globals.bActionReportSuspensionCont; if (pThis->bReportSuspensionCont == -1) pThis->bReportSuspensionCont = 1; } } /* set action to "rtry" state. * rgerhards, 2007-08-02 */ static void ATTR_NONNULL() actionRetry(action_t *const pThis, wti_t *const pWti) { if (actionIsDisabled(pThis)) { actionDisableForWorker(pThis, pWti); return; } setSuspendMessageConfVars(pThis); actionSetState(pThis, __func__, pWti, ACT_STATE_RTRY); if (pThis->bReportSuspension) { LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "action '%s' suspended (module '%s'), retry %d. There should " "be messages before this one giving the reason for suspension.", pThis->pszName, pThis->pMod->pszName, getActionNbrResRtry(pWti, pThis)); } incActionResumeInRow(pWti, pThis); } static time_t actionGetResumeRetryTime(const action_t *const pThis) { return PREFER_LOAD_time_t(&pThis->ttResumeRtry); } static void actionSetResumeRetryTime(action_t *const pThis, const time_t ttResumeRtry) { PREFER_STORE_time_t(&pThis->ttResumeRtry, ttResumeRtry); } /* Suspend action, this involves changing the action state as well * as setting the next retry time. * if we have more than 10 retries, we prolong the * retry interval. If something is really stalled, it will * get re-tried only very, very seldom - but that saves * CPU time. * rgerhards, 2007-08-02 */ static void ATTR_NONNULL() actionSuspend(action_t *const pThis, wti_t *const pWti) { time_t ttNow; time_t ttResumeRtry; int suspendDuration; char timebuf[32]; DBGPRINTF("actionSuspend: enter\n"); setSuspendMessageConfVars(pThis); /* note: we can NOT use a cached timestamp, as time may have evolved * since caching, and this would break logic (and it actually did so!) */ datetime.GetTime(&ttNow); suspendDuration = pThis->iResumeInterval * (getActionNbrResRtry(pWti, pThis) / 10 + 1); if (pThis->iResumeIntervalMax > 0 && suspendDuration > pThis->iResumeIntervalMax) { suspendDuration = pThis->iResumeIntervalMax; } ttResumeRtry = ttNow + suspendDuration; actionSetResumeRetryTime(pThis, ttResumeRtry); actionSetState(pThis, __func__, pWti, ACT_STATE_SUSP); STATSCOUNTER_ADD(pThis->ctrSuspendDuration, pThis->mutCtrSuspendDuration, suspendDuration); if (getActionNbrResRtry(pWti, pThis) == 0) { STATSCOUNTER_INC(pThis->ctrSuspend, pThis->mutCtrSuspend); } if (pThis->bReportSuspensionCont || (pThis->bReportSuspension && getActionNbrResRtry(pWti, pThis) == 0)) { ctime_r(&ttResumeRtry, timebuf); timebuf[strlen(timebuf) - 1] = '\0'; /* strip LF */ LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "action '%s' suspended (module '%s'), next retry is %s, retry nbr %d. " "There should be messages before this one giving the reason for suspension.", pThis->pszName, pThis->pMod->pszName, timebuf, getActionNbrResRtry(pWti, pThis)); } DBGPRINTF( "action '%s' suspended, earliest retry=%lld (now %lld), iNbrResRtry %d, " "duration %d\n", pThis->pszName, (long long)ttResumeRtry, (long long)ttNow, getActionNbrResRtry(pWti, pThis), suspendDuration); } /* actually do retry processing. Note that the function receives a timestamp so * that we do not need to call the (expensive) time() API. * Note that we do the full retry processing here, doing the configured number of * iterations. -- rgerhards, 2009-05-07 * We need to guard against module which always return RS_RET_OK from their tryResume() * entry point. This is invalid, but has harsh consequences: it will cause the rsyslog * engine to go into a tight loop. That obviously is not acceptable. As such, we track the * count of iterations that a tryResume returning RS_RET_OK is immediately followed by * an unsuccessful call to doAction(). If that happens more than 10 times, we assume * the return acutally is a RS_RET_SUSPENDED. In order to go through the various * resumption stages, we do this for every 10 requests. This magic number 10 may * not be the most appropriate, but it should be thought of a "if nothing else helps" * kind of facility: in the first place, the module should return a proper indication * of its inability to recover. -- rgerhards, 2010-04-26. */ static rsRetVal actionDoRetryInternal( action_t *const pThis, wti_t *const pWti, int *const slept, const int permitSleep, int *const deferredSleepNeeded) { int iRetries; int bTreatOKasSusp; time_t ttTemp; DEFiRet; assert(pThis != NULL); if (slept != NULL) { *slept = 0; } if (deferredSleepNeeded != NULL) { *deferredSleepNeeded = 0; } iRetries = 0; while (!wtiIsShutdownImmediate(pWti) && getActionState(pWti, pThis) == ACT_STATE_RTRY) { if (actionIsDisabled(pThis)) { break; } DBGPRINTF("actionDoRetry: %s enter loop, iRetries=%d, ResumeInRow %d\n", pThis->pszName, iRetries, getActionResumeInRow(pWti, pThis)); iRet = pThis->pMod->tryResume(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData); DBGPRINTF("actionDoRetry: %s action->tryResume returned %d\n", pThis->pszName, iRet); if ((getActionResumeInRow(pWti, pThis) > 9) && (getActionResumeInRow(pWti, pThis) % 10 == 0)) { bTreatOKasSusp = 1; setActionResumeInRow(pWti, pThis, 0); iRet = RS_RET_SUSPENDED; } else { bTreatOKasSusp = 0; } if ((iRet == RS_RET_OK) && (!bTreatOKasSusp)) { DBGPRINTF("actionDoRetry: %s had success RDY again (iRet=%d)\n", pThis->pszName, iRet); STATSCOUNTER_INC(pThis->ctrResume, pThis->mutCtrResume); if (pThis->bReportSuspension) { LogMsg(0, RS_RET_RESUMED, LOG_INFO, "action '%s' " "resumed (module '%s')", pThis->pszName, pThis->pMod->pszName); } actionSetState(pThis, __func__, pWti, ACT_STATE_RDY); } else if (iRet == RS_RET_SUSPENDED || bTreatOKasSusp) { /* max retries reached? */ DBGPRINTF( "actionDoRetry: %s check for max retries, iResumeRetryCount " "%d, iRetries %d\n", pThis->pszName, pThis->iResumeRetryCount, iRetries); if ((pThis->iResumeRetryCount != -1 && iRetries >= pThis->iResumeRetryCount)) { actionSuspend(pThis, pWti); if (getActionNbrResRtry(pWti, pThis) < 20) incActionNbrResRtry(pWti, pThis); } else { if (!permitSleep) { DBGPRINTF("actionDoRetry: %s needs resumeInterval sleep; deferring to caller\n", pThis->pszName); if (deferredSleepNeeded != NULL) { *deferredSleepNeeded = 1; } iRet = RS_RET_SUSPENDED; FINALIZE; } ++iRetries; datetime.GetTime(&ttTemp); DBGPRINTF( "actionDoRetry: %s, controlled by resumeInterval, may miss the next try." "Will sleep %d seconds. ResumeRtry=%lld (now %lld), iRetries %d\n", pThis->pszName, pThis->iResumeInterval, (long long)actionGetResumeRetryTime(pThis), (long long)ttTemp, iRetries); if (slept != NULL) { *slept = 1; } srSleep(pThis->iResumeInterval, 0); if (wtiIsShutdownImmediate(pWti)) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } } } else if (iRet == RS_RET_DISABLE_ACTION) { actionDisableForWorker(pThis, pWti); break; } } if (getActionState(pWti, pThis) == ACT_STATE_RDY) { setActionNbrResRtry(pWti, pThis, 0); } finalize_it: RETiRet; } /* special retry handling if disabled via file: simply wait for the file * to indicate whether or not it is ready again */ static rsRetVal ATTR_NONNULL() actionDoRetry_extFile(action_t *const pThis, wti_t *const pWti) { int iRetries; DEFiRet; assert(pThis != NULL); DBGPRINTF("actionDoRetry_extFile: enter, actionState: %d\n", getActionState(pWti, pThis)); iRetries = 0; while (!wtiIsShutdownImmediate(pWti) && getActionState(pWti, pThis) == ACT_STATE_RTRY) { if (actionIsDisabled(pThis)) { break; } DBGPRINTF("actionDoRetry_extFile: %s enter loop, iRetries=%d, ResumeInRow %d\n", pThis->pszName, iRetries, getActionResumeInRow(pWti, pThis)); iRet = checkExternalStateFile(pThis, pWti); DBGPRINTF("actionDoRetry_extFile: %s checkExternalStateFile returned %d\n", pThis->pszName, iRet); if (iRet == RS_RET_OK) { DBGPRINTF("actionDoRetry_extFile: %s had success RDY again (iRet=%d)\n", pThis->pszName, iRet); if (pThis->bReportSuspension) { LogMsg(0, RS_RET_RESUMED, LOG_INFO, "action '%s' " "resumed (module '%s') via external state file", pThis->pszName, pThis->pMod->pszName); } actionSetState(pThis, __func__, pWti, ACT_STATE_RDY); } else if (iRet == RS_RET_SUSPENDED) { /* max retries reached? */ DBGPRINTF( "actionDoRetry_extFile: %s check for max retries, iResumeRetryCount " "%d, iRetries %d\n", pThis->pszName, pThis->iResumeRetryCount, iRetries); if ((pThis->iResumeRetryCount != -1 && iRetries >= pThis->iResumeRetryCount)) { DBGPRINTF("actionDoRetry_extFile: did not work out, suspending\n"); actionSuspend(pThis, pWti); pWti->execState.bPrevWasSuspended = 1; if (getActionNbrResRtry(pWti, pThis) < 20) incActionNbrResRtry(pWti, pThis); } else { ++iRetries; srSleep(pThis->iResumeInterval, 0); if (wtiIsShutdownImmediate(pWti)) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } } } else if (iRet == RS_RET_DISABLE_ACTION) { actionDisableForWorker(pThis, pWti); break; } } if (getActionState(pWti, pThis) == ACT_STATE_RDY) { setActionNbrResRtry(pWti, pThis, 0); } finalize_it: RETiRet; } static rsRetVal actionCheckAndCreateWrkrInstance(action_t *const pThis, const wti_t *const pWti) { int locked = 0; void *existingInstance; DEFiRet; if (actionIsDisabled(pThis)) { FINALIZE; } /* Fast path: atomic read to check if instance already exists. * This optimization avoids mutex contention in the common case where * the worker instance has already been created. Uses atomic operations * to ensure proper memory ordering and visibility across threads. */ #ifdef HAVE_ATOMIC_BUILTINS existingInstance = ATOMIC_LOAD_PTR(&pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData, &pThis->mutWrkrDataTable); if (existingInstance != NULL) { FINALIZE; /* Common case: instance exists, return immediately */ } #endif /* Worker instance does not exist. Acquire lock to prevent race condition * where multiple threads might try to create instances simultaneously. * We use double-checked locking when atomic reads are available to * confirm another thread did not create the instance between checks. * On platforms without atomic builtins, we perform the full check under * a single mutex to avoid nested locking in the fallback path. */ pthread_mutex_lock(&pThis->mutWrkrDataTable); locked = 1; #ifdef HAVE_ATOMIC_BUILTINS /* Recheck under lock (double-checked locking pattern with atomics) */ existingInstance = ATOMIC_LOAD_PTR(&pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData, &pThis->mutWrkrDataTable); #else existingInstance = pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData; #endif if (existingInstance == NULL) { DBGPRINTF( "wti %p: we need to create a new action worker instance for " "action %d\n", pWti, pThis->iActionNbr); CHKiRet(pThis->pMod->mod.om.createWrkrInstance(&(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData), pThis->pModData)); pWti->actWrkrInfo[pThis->iActionNbr].pAction = pThis; setActionState(pWti, pThis, ACT_STATE_RDY); /* action is enabled */ /* maintain worker data table -- only needed if wrkrHUP is requested! */ int freeSpot; for (freeSpot = 0; freeSpot < pThis->wrkrDataTableSize; ++freeSpot) if (pThis->wrkrDataTable[freeSpot] == NULL) break; if (pThis->nWrkr == pThis->wrkrDataTableSize) { void *const newTable = realloc(pThis->wrkrDataTable, (pThis->wrkrDataTableSize + 1) * sizeof(void *)); if (newTable == NULL) { DBGPRINTF( "actionCheckAndCreateWrkrInstance: out of " "memory realloc wrkrDataTable\n") ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pThis->wrkrDataTable = newTable; pThis->wrkrDataTableSize++; } pThis->wrkrDataTable[freeSpot] = pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData; pThis->nWrkr++; DBGPRINTF( "wti %p: created action worker instance %d for " "action %d\n", pWti, pThis->nWrkr, pThis->iActionNbr); } finalize_it: if (locked) { pthread_mutex_unlock(&pThis->mutWrkrDataTable); } RETiRet; } /* try to resume an action -- rgerhards, 2007-08-02 * changed to new action state engine -- rgerhards, 2009-05-07 */ static rsRetVal actionTryResumeInternal(action_t *const pThis, wti_t *const pWti, int *const slept, const int permitRetrySleep, int *const deferredSleepNeeded) { DEFiRet; time_t ttNow = NO_TIME_PROVIDED; DBGPRINTF("actionTryResume: enter\n"); if (actionIsDisabled(pThis)) { actionDisableForWorker(pThis, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } if (getActionState(pWti, pThis) == ACT_STATE_SUSP) { /* if we are suspended, we need to check if the timeout expired. * for this handling, we must always obtain a fresh timestamp. We used * to use the action timestamp, but in this case we will never reach a * point where a resumption is actually tried, because the action timestamp * is always in the past. So we can not avoid doing a fresh time() call * here. -- rgerhards, 2009-03-18 */ datetime.GetTime(&ttNow); /* cache "now" */ if (ttNow >= actionGetResumeRetryTime(pThis)) { actionSetState(pThis, __func__, pWti, ACT_STATE_RTRY); /* back to retries */ } } if (getActionState(pWti, pThis) == ACT_STATE_RTRY) { DBGPRINTF("actionTryResume calls actionDoRetry\n"); CHKiRet(actionDoRetryInternal(pThis, pWti, slept, permitRetrySleep, deferredSleepNeeded)); } if (Debug && (getActionState(pWti, pThis) == ACT_STATE_RTRY || getActionState(pWti, pThis) == ACT_STATE_SUSP)) { if (ttNow == NO_TIME_PROVIDED) /* use cached result if we have it */ datetime.GetTime(&ttNow); dbgprintf("actionTryResume: action[%s] state: %s, next retry (if applicable): %u [now %u]\n", pThis->pszName, getActStateName(pThis, pWti), (unsigned)actionGetResumeRetryTime(pThis), (unsigned)ttNow); } finalize_it: RETiRet; } /** * @brief Prepare an action for message processing. * * This helper ensures a worker instance exists and attempts to * resume a suspended action. If the action becomes ready a new * transaction is started via the output module's beginTransaction() * hook, transitioning the internal state to @c ACT_STATE_ITX. */ static rsRetVal actionPrepareInternal(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, int *const slept, const int permitRetrySleep, int *const deferredSleepNeeded) { DEFiRet; DBGPRINTF("actionPrepare[%s]: enter\n", pThis->pszName); if (actionIsDisabled(pThis)) { actionDisableForWorker(pThis, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } CHKiRet(actionCheckAndCreateWrkrInstance(pThis, pWti)); CHKiRet(actionTryResumeInternal(pThis, pWti, slept, permitRetrySleep, deferredSleepNeeded)); DBGPRINTF("actionPrepare[%s]: after calling actionTryResume\n", pThis->pszName); /* if we are now ready, we initialize the transaction and advance * action state accordingly */ if (getActionState(pWti, pThis) == ACT_STATE_RDY) { iRet = checkExternalStateFile(pThis, pWti); if (iRet == RS_RET_SUSPENDED) { DBGPRINTF( "actionPrepare[%s]: SUSPENDED via external state file, " "doing retry processing\n", pThis->pszName); CHKiRet(actionDoRetry_extFile(pThis, pWti)); } iRet = pThis->pMod->mod.om.beginTransaction(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData); switch (iRet) { case RS_RET_OK: actionSetState(pThis, __func__, pWti, ACT_STATE_ITX); break; case RS_RET_SUSPENDED: actionRetry(pThis, pWti); break; case RS_RET_DISABLE_ACTION: actionDisableForWorker(pThis, pWti); break; default: FINALIZE; } } finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() actionPrepare(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti) { return actionPrepareInternal(pThis, pWti, NULL, 1, NULL); } /* prepare the calling parameters for doAction() * rgerhards, 2009-05-07 */ static rsRetVal prepareDoActionParams(action_t *__restrict__ const pAction, wti_t *__restrict__ const pWti, smsg_t *__restrict__ const pMsg, struct syslogTime *ttNow) { int i; struct json_object *json; actWrkrIParams_t *iparams; actWrkrInfo_t *__restrict__ pWrkrInfo; DEFiRet; pWrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]); if (pAction->isTransactional) { CHKiRet(wtiNewIParam(pWti, pAction, &iparams)); for (i = 0; i < pAction->iNumTpls; ++i) { CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &actParam(iparams, pAction->iNumTpls, 0, i), ttNow)); } } else { for (i = 0; i < pAction->iNumTpls; ++i) { switch (pAction->peParamPassing[i]) { case ACT_STRING_PASSING: CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &(pWrkrInfo->p.nontx.actParams[i]), ttNow)); break; /* note: ARRAY_PASSING mode has been removed in 8.26.0; if it * is ever needed again, it can be found in 8.25.0. * rgerhards 2017-03-06 */ case ACT_MSG_PASSING: pWrkrInfo->p.nontx.actParams[i].param = (void *)pMsg; break; case ACT_JSON_PASSING: CHKiRet(tplToJSON(pAction->ppTpl[i], pMsg, &json, ttNow)); pWrkrInfo->p.nontx.actParams[i].param = (void *)json; break; default: dbgprintf( "software bug/error: unknown " "pAction->peParamPassing[%d] %d in prepareDoActionParams\n", i, (int)pAction->peParamPassing[i]); break; } } } finalize_it: RETiRet; } /** * @brief Release memory allocated for action parameters. * * Parameters are prepared by prepareDoActionParams() before the * output module is invoked. Depending on the parameter passing mode * temporary buffers or JSON objects may need explicit cleanup. * * @param[in] pAction action whose parameters are released * @param[in] pWti worker thread context * @param[in] action_destruct non-zero if called during action teardown */ void releaseDoActionParams(action_t *__restrict__ const pAction, wti_t *__restrict__ const pWti, int action_destruct) { int j; actWrkrInfo_t *__restrict__ pWrkrInfo; pWrkrInfo = &(pWti->actWrkrInfo[pAction->iActionNbr]); for (j = 0; j < pAction->iNumTpls; ++j) { if (action_destruct) { if (ACT_STRING_PASSING == pAction->peParamPassing[j]) { free(pWrkrInfo->p.nontx.actParams[j].param); pWrkrInfo->p.nontx.actParams[j].param = NULL; pWrkrInfo->p.nontx.actParams[j].lenBuf = 0; pWrkrInfo->p.nontx.actParams[j].lenStr = 0; } } else { switch (pAction->peParamPassing[j]) { case ACT_ARRAY_PASSING: LogError(0, RS_RET_ERR, "plugin error: no longer supported " "ARRAY_PASSING mode is used (see action.c)"); return; case ACT_JSON_PASSING: json_object_put((struct json_object *)pWrkrInfo->p.nontx.actParams[j].param); pWrkrInfo->p.nontx.actParams[j].param = NULL; pWrkrInfo->p.nontx.actParams[j].lenBuf = 0; pWrkrInfo->p.nontx.actParams[j].lenStr = 0; break; default: /* no need to do anything with these */ break; } } } return; } /** * @brief Mark that an action successfully processed a message. * * This helper resets the consecutive resume counter so that the * retry backoff is cleared once a message passes through the action * after a suspension. */ static void actionSetActionWorked(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti) { setActionResumeInRow(pWti, pThis, 0); } /** * @brief Translate the result of an output module call into action state. * * Depending on @a ret the action's state machine is advanced and a * suitable return code for higher layers is produced. This function * centralizes the logic for commit, retry and suspend transitions. */ static rsRetVal handleActionExecResult(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, const rsRetVal ret) { DEFiRet; switch (ret) { case RS_RET_OK: actionCommitted(pThis, pWti); actionSetActionWorked(pThis, pWti); /* we had a successful call! */ break; case RS_RET_DEFER_COMMIT: actionSetActionWorked(pThis, pWti); /* we had a successful call! */ /* we are done, action state remains the same */ break; case RS_RET_PREVIOUS_COMMITTED: /* action state remains the same, but we had a commit. */ pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 1; actionSetActionWorked(pThis, pWti); /* we had a successful call! */ break; case RS_RET_DISABLE_ACTION: actionDisableForWorker(pThis, pWti); break; case RS_RET_SUSPENDED: actionRetry(pThis, pWti); break; default: /* error happened - if it hits us here, we assume the message cannot * be processed but an retry makes no sense. Usually, this should be * return code RS_RET_DATAFAIL. -- rgerhards, 2017-10-06 */ LogError(0, ret, "action '%s' (module '%s') " "message lost, could not be processed. Check for " "additional error messages before this one.", pThis->pszName, pThis->pMod->pszName); actionSetState(pThis, __func__, pWti, ACT_STATE_DATAFAIL); break; } iRet = getReturnCode(pThis, pWti); RETiRet; } /* call the DoAction output plugin entry point * rgerhards, 2008-01-28 */ static rsRetVal actionCallDoAction(action_t *__restrict__ const pThis, actWrkrIParams_t *__restrict__ const iparams, wti_t *__restrict__ const pWti) { void *param[CONF_OMOD_NUMSTRINGS_MAXSIZE]; int i; DEFiRet; DBGPRINTF("entering actionCalldoAction(), state: %s, actionNbr %d\n", getActStateName(pThis, pWti), pThis->iActionNbr); pWti->actWrkrInfo[pThis->iActionNbr].bHadAutoCommit = 0; /* for this interface, we need to emulate the old style way * of parameter passing. */ for (i = 0; i < pThis->iNumTpls; ++i) { param[i] = actParam(iparams, pThis->iNumTpls, 0, i).param; } iRet = pThis->pMod->mod.om.doAction(param, pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData); iRet = handleActionExecResult(pThis, pWti, iRet); RETiRet; } /* call the commitTransaction output plugin entry point */ static rsRetVal ATTR_NONNULL() actionCallCommitTransaction(action_t *const pThis, wti_t *const pWti, actWrkrIParams_t *__restrict__ const iparams, const int nparams) { DEFiRet; DBGPRINTF("entering actionCallCommitTransaction[%s], state: %s, nMsgs %u\n", pThis->pszName, getActStateName(pThis, pWti), nparams); iRet = pThis->pMod->mod.om.commitTransaction(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData, iparams, nparams); DBGPRINTF( "actionCallCommitTransaction[%s] state: %s " "mod commitTransaction returned %d\n", pThis->pszName, getActStateName(pThis, pWti), iRet); iRet = handleActionExecResult(pThis, pWti, iRet); RETiRet; } /* process a message * this readies the action and then calls doAction() * rgerhards, 2008-01-28 */ static rsRetVal actionProcessMessage(action_t *const pThis, void *actParams, wti_t *const pWti) { DEFiRet; CHKiRet(actionPrepare(pThis, pWti)); if (pThis->pMod->mod.om.SetShutdownImmdtPtr != NULL) pThis->pMod->mod.om.SetShutdownImmdtPtr(pThis->pModData, pWti->pbShutdownImmediate); if (getActionState(pWti, pThis) == ACT_STATE_ITX) CHKiRet(actionCallDoAction(pThis, actParams, pWti)); iRet = getReturnCode(pThis, pWti); finalize_it: RETiRet; } /** * Execute a transactional batch for an action. * * Depending on the output module capabilities the batch is either * handed to commitTransaction() or processed message by message for * legacy modules. Rollback is best effort only; if a commit fails some * messages may have already been delivered. * * @param[in] pThis action to execute * @param[in] pWti worker thread instance * @param[in] iparams parameter array for all messages * @param[in] nparams number of messages in the batch * * @retval RS_RET_OK batch processed successfully * @retval RS_RET_SUSPENDED action entered retry state */ static rsRetVal doTransaction(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, actWrkrIParams_t *__restrict__ const iparams, const int nparams) { actWrkrInfo_t *wrkrInfo; int i; sbool bSuspended = 0; DEFiRet; DBGPRINTF("doTransaction[%s] enter\n", pThis->pszName); wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]); if (pThis->pMod->mod.om.commitTransaction != NULL) { DBGPRINTF("doTransaction: have commitTransaction IF, using that, pWrkrInfo %p\n", wrkrInfo); CHKiRet(actionCallCommitTransaction(pThis, pWti, iparams, nparams)); } else { /* note: this branch is for compatibility with old TX modules */ DBGPRINTF("doTransaction: action '%s', currIParam %d\n", pThis->pszName, wrkrInfo->p.tx.currIParam); for (i = 0; i < nparams; ++i) { /* Note: we provide the message's base iparam - actionProcessMessage() * uses this as *base* address. */ iRet = actionProcessMessage(pThis, &actParam(iparams, pThis->iNumTpls, i, 0), pWti); DBGPRINTF("doTransaction: action %d, processing msg %d, result %d\n", pThis->iActionNbr, i, iRet); if (iRet == RS_RET_SUSPENDED) { if (!bSuspended) { /* First suspension for this message: * - Avoid busy-spin: wait 1 second, then try the same message once more. * - Decrement the loop index so the current message is processed again * on the next iteration. * - Set the flag so we do not perform repeated local retries. * If suspension persists, the next hit takes the RS_RET_SUSPENDED path * and the rsyslog core’s standard retry logic takes over. */ --i; /* reprocess this message on the next loop iteration */ srSleep(1, 0); /* sleep 1 second */ bSuspended = 1; /* mark that the one local retry has been done */ continue; } else { /* Already retried locally: delegate to core retry handling. */ ABORT_FINALIZE(RS_RET_SUSPENDED); } } else if (iRet != RS_RET_DEFER_COMMIT && iRet != RS_RET_PREVIOUS_COMMITTED && iRet != RS_RET_OK) { FINALIZE; /* let upper peer handle the error condition! */ } bSuspended = 0; } } finalize_it: if (iRet == RS_RET_DEFER_COMMIT || iRet == RS_RET_PREVIOUS_COMMITTED) iRet = RS_RET_OK; /* this is expected for transactional action! */ RETiRet; } /** * @brief Attempt to commit a batch without invoking retry logic. * * The action is prepared and the transaction executed. If the * action remains in transactional state @c endTransaction() is * invoked to finalize the batch. The return value reflects the * resulting action state but no retries are performed here. */ static rsRetVal actionTryCommitInternal(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, actWrkrIParams_t *__restrict__ const iparams, const int nparams, int *const slept, const int permitRetrySleep, int *const deferredSleepNeeded) { DEFiRet; DBGPRINTF("actionTryCommit[%s] enter\n", pThis->pszName); CHKiRet(actionPrepareInternal(pThis, pWti, slept, permitRetrySleep, deferredSleepNeeded)); if (getActionState(pWti, pThis) == ACT_STATE_RTRY || getActionState(pWti, pThis) == ACT_STATE_SUSP || getActionState(pWti, pThis) == ACT_STATE_DISABLED) { DBGPRINTF("actionTryCommit[%s]: skip transaction while state is %s\n", pThis->pszName, getActStateName(pThis, pWti)); ABORT_FINALIZE(getReturnCode(pThis, pWti)); } CHKiRet(doTransaction(pThis, pWti, iparams, nparams)); if (getActionState(pWti, pThis) == ACT_STATE_ITX) { iRet = pThis->pMod->mod.om.endTransaction(pWti->actWrkrInfo[pThis->iActionNbr].actWrkrData); switch (iRet) { case RS_RET_OK: actionCommitted(pThis, pWti); break; case RS_RET_SUSPENDED: actionRetry(pThis, pWti); break; case RS_RET_DISABLE_ACTION: actionDisableForWorker(pThis, pWti); break; case RS_RET_DEFER_COMMIT: DBGPRINTF( "output plugin error: endTransaction() returns RS_RET_DEFER_COMMIT " "- ignored\n"); actionCommitted(pThis, pWti); break; case RS_RET_PREVIOUS_COMMITTED: DBGPRINTF( "output plugin error: endTransaction() returns RS_RET_PREVIOUS_COMMITTED " "- ignored\n"); actionCommitted(pThis, pWti); break; default: /* permanent failure of this message - no sense in retrying. This is * not yet handled (but easy TODO) */ DBGPRINTF("action[%s]: actionTryCommit receveived iRet %d\n", pThis->pszName, iRet); FINALIZE; } } iRet = getReturnCode(pThis, pWti); finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() actionTryCommit(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, actWrkrIParams_t *__restrict__ const iparams, const int nparams) { return actionTryCommitInternal(pThis, pWti, iparams, nparams, NULL, 1, NULL); } /** * Write details about failed messages to the configured error file. * * @param[in] pThis action that failed * @param[in] ret return code from the failed commit * @param[in] iparams parameter array describing the failed messages * @param[in] nparams number of messages contained in @a iparams */ static void ATTR_NONNULL() actionWriteErrorFile(action_t *__restrict__ const pThis, const rsRetVal ret, actWrkrIParams_t *__restrict__ const iparams, const int nparams) { fjson_object *etry = NULL; int bNeedUnlock = 0; STATSCOUNTER_INC(pThis->ctrFail, pThis->mutCtrFail); if (pThis->pszErrFile == NULL) { DBGPRINTF( "action %s: commit failed, no error file set, silently " "discarding %d messages\n", pThis->pszName, nparams); goto done; } DBGPRINTF("action %d commit failed, writing %u messages (%d tpls) to error file\n", pThis->iActionNbr, nparams, pThis->iNumTpls); pthread_mutex_lock(&pThis->mutErrFile); bNeedUnlock = 1; if (pThis->fdErrFile == -1) { pThis->fdErrFile = open(pThis->pszErrFile, O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (pThis->fdErrFile == -1) { LogError(errno, RS_RET_ERR, "action %s: error opening error file %s", pThis->pszName, pThis->pszErrFile); goto done; } if (pThis->maxErrFileSize > 0) { struct stat statbuf; if (fstat(pThis->fdErrFile, &statbuf) == -1) { LogError(errno, RS_RET_ERR, "failed to fstat %s", pThis->pszErrFile); goto done; } pThis->currentErrFileSize = statbuf.st_size; } } for (int i = 0; i < nparams; ++i) { if ((etry = fjson_object_new_object()) == NULL) goto done; fjson_object_object_add(etry, "action", fjson_object_new_string((char *)pThis->pszName)); fjson_object_object_add(etry, "status", fjson_object_new_int(ret)); for (int j = 0; j < pThis->iNumTpls; ++j) { char tplname[20]; snprintf(tplname, sizeof(tplname), "template%d", j); tplname[sizeof(tplname) - 1] = '\0'; fjson_object_object_add(etry, tplname, fjson_object_new_string((char *)actParam(iparams, 1, i, j).param)); } char *const rendered = strdup((char *)fjson_object_to_json_string(etry)); if (rendered == NULL) goto done; size_t toWrite = strlen(rendered) + 1; // Check if need to truncate the amount of bytes to write if (pThis->maxErrFileSize > 0) { if (pThis->currentErrFileSize + toWrite > pThis->maxErrFileSize) { // Truncate to the pending available toWrite = pThis->maxErrFileSize - pThis->currentErrFileSize; } pThis->currentErrFileSize += toWrite; } if (toWrite > 0) { /* note: we use the '\0' inside the string to store a LF - we do not * otherwise need it and it safes us a copy/realloc. */ rendered[toWrite - 1] = '\n'; /* NO LONGER A STRING! */ const ssize_t wrRet = write(pThis->fdErrFile, rendered, toWrite); if (wrRet != (ssize_t)toWrite) { LogError(errno, RS_RET_IO_ERROR, "action %s: error writing errorFile %s, write returned %lld", pThis->pszName, pThis->pszErrFile, (long long)wrRet); } } free(rendered); fjson_object_put(etry); etry = NULL; } done: if (bNeedUnlock) { pthread_mutex_unlock(&pThis->mutErrFile); } fjson_object_put(etry); return; } static rsRetVal ATTR_NONNULL() actionSleepBeforeRetryingTransaction(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti) { DEFiRet; if (pThis->iResumeRetryCount == 0) { FINALIZE; } if (pThis->iResumeInterval > 0) { DBGPRINTF("actionCommit[%s]: sleeping %d seconds before retrying suspended transaction\n", pThis->pszName, pThis->iResumeInterval); srSleep(pThis->iResumeInterval, 0); if (wtiIsShutdownImmediate(pWti)) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } } finalize_it: RETiRet; } static rsRetVal actionTryRemoveHardErrorsFromBatch(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti, actWrkrIParams_t *const new_iparams, unsigned *new_nMsgs, int *const allSuspendedSlept) { actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]); const unsigned nMsgs = wrkrInfo->p.tx.currIParam; actWrkrIParams_t oneParamSet[CONF_OMOD_NUMSTRINGS_MAXSIZE]; rsRetVal ret; DEFiRet; *new_nMsgs = 0; if (allSuspendedSlept != NULL) { *allSuspendedSlept = 1; } for (unsigned i = 0; i < nMsgs; ++i) { setActionResumeInRow(pWti, pThis, 0); // make sure we do not trigger OK-as-SUSPEND handling memcpy(&oneParamSet, &actParam(wrkrInfo->p.tx.iparams, pThis->iNumTpls, i, 0), sizeof(actWrkrIParams_t) * pThis->iNumTpls); int retrySlept = 0; int deferredSleepNeeded = 0; ret = actionTryCommitInternal(pThis, pWti, oneParamSet, 1, &retrySlept, 0, &deferredSleepNeeded); if (deferredSleepNeeded) { CHKiRet(actionSleepBeforeRetryingTransaction(pThis, pWti)); retrySlept = 1; deferredSleepNeeded = 0; ret = actionTryCommitInternal(pThis, pWti, oneParamSet, 1, &retrySlept, 0, &deferredSleepNeeded); if (deferredSleepNeeded) { memcpy(new_iparams + (*new_nMsgs * pThis->iNumTpls), &oneParamSet, sizeof(actWrkrIParams_t) * pThis->iNumTpls); ++(*new_nMsgs); for (++i; i < nMsgs; ++i) { memcpy(new_iparams + (*new_nMsgs * pThis->iNumTpls), &actParam(wrkrInfo->p.tx.iparams, pThis->iNumTpls, i, 0), sizeof(actWrkrIParams_t) * pThis->iNumTpls); ++(*new_nMsgs); } if (allSuspendedSlept != NULL) { *allSuspendedSlept = 1; } ABORT_FINALIZE(RS_RET_OK); } } if (ret == RS_RET_FORCE_TERM) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } else if (ret == RS_RET_SUSPENDED) { if (!retrySlept && allSuspendedSlept != NULL) { *allSuspendedSlept = 0; } memcpy(new_iparams + (*new_nMsgs * pThis->iNumTpls), &oneParamSet, sizeof(actWrkrIParams_t) * pThis->iNumTpls); ++(*new_nMsgs); } else if (ret != RS_RET_OK) { actionWriteErrorFile(pThis, ret, oneParamSet, 1); } } finalize_it: RETiRet; } /** * Commit all messages currently buffered for an action. * * The function first tries to commit the whole batch. On failure each * message is retried individually so that permanent errors can be * written to the action's error file while temporary errors trigger the * usual retry handling. * * @param[in] pThis action being committed * @param[in] pWti worker thread instance * * The return value is propagated via qqueueAdd() when the action queue * operates in direct mode so that callers can react immediately. * @return Status code from the final commit attempt. * The result is propagated back through direct-mode queues so * higher levels can act on suspend or failure states. */ static rsRetVal ATTR_NONNULL() actionCommit(action_t *__restrict__ const pThis, wti_t *__restrict__ const pWti) { actWrkrInfo_t *const wrkrInfo = &(pWti->actWrkrInfo[pThis->iActionNbr]); /* Variables that permit us to override the batch of messages */ unsigned nMsgs = 0; actWrkrIParams_t *iparams = NULL; int needfree_iparams = 0; // work-around for clang static analyzer false positive int sleepBeforeRetry = 0; DEFiRet; DBGPRINTF("actionCommit[%s]: enter, %d msgs\n", pThis->pszName, wrkrInfo->p.tx.currIParam); if (actionIsDisabled(pThis)) { actionDisableForWorker(pThis, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } else if (!pThis->isTransactional || pWti->actWrkrInfo[pThis->iActionNbr].p.tx.currIParam == 0) { FINALIZE; } else if (getActionState(pWti, pThis) == ACT_STATE_SUSP) { /* if we are suspended, we already tried everything to recover the * action - and failed. So all we can do here is write the error file. */ actionWriteErrorFile(pThis, iRet, wrkrInfo->p.tx.iparams, wrkrInfo->p.tx.currIParam); FINALIZE; } DBGPRINTF("actionCommit[%s]: processing...\n", pThis->pszName); /* we now do one try at commiting the whole batch. Usually, this will * succeed. If so, we are happy and done. If not, we dig into the details * of finding out if we have a non-temporary error and try to handle this * as well as retry processing. Due to this logic we do a bit more retries * than configured (if temporary failure), but this unavoidable and should * do no real harm. - rgerhards, 2017-10-06 */ iRet = actionTryCommit(pThis, pWti, wrkrInfo->p.tx.iparams, wrkrInfo->p.tx.currIParam); DBGPRINTF("actionCommit[%s]: return actionTryCommit %d\n", pThis->pszName, iRet); if (iRet == RS_RET_OK) { FINALIZE; } /* check if this was a single-message batch. If it had a datafail error, we * are done. If it is a multi-message batch, we need to sort out the individual * message states. */ if (wrkrInfo->p.tx.currIParam == 1) { needfree_iparams = 0; iparams = wrkrInfo->p.tx.iparams; nMsgs = wrkrInfo->p.tx.currIParam; if (iRet == RS_RET_DATAFAIL) { FINALIZE; } else if (iRet == RS_RET_SUSPENDED) { sleepBeforeRetry = 1; } } else { DBGPRINTF( "actionCommit[%s]: somewhat unhappy, full batch of %d msgs returned " "status %d. Trying messages as individual actions.\n", pThis->pszName, wrkrInfo->p.tx.currIParam, iRet); CHKmalloc(iparams = malloc(sizeof(actWrkrIParams_t) * pThis->iNumTpls * wrkrInfo->p.tx.currIParam)); needfree_iparams = 1; int splitSuspendedSlept = 1; CHKiRet(actionTryRemoveHardErrorsFromBatch(pThis, pWti, iparams, &nMsgs, &splitSuspendedSlept)); if (nMsgs > 0) { sleepBeforeRetry = !splitSuspendedSlept; } } if (nMsgs == 0) { ABORT_FINALIZE(RS_RET_OK); // here, we consider everyting OK } /* We still have some messages with suspend error. So now let's do our * "regular" retry and suspend processing. */ DBGPRINTF("actionCommit[%s]: unhappy, we still have %d uncommitted messages.\n", pThis->pszName, nMsgs); int bDone = 0; do { if (wtiIsShutdownImmediate(pWti)) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } if (sleepBeforeRetry) { CHKiRet(actionSleepBeforeRetryingTransaction(pThis, pWti)); sleepBeforeRetry = 0; } iRet = actionTryCommit(pThis, pWti, iparams, nMsgs); DBGPRINTF("actionCommit[%s]: in retry loop, iRet %d\n", pThis->pszName, iRet); if (iRet == RS_RET_FORCE_TERM) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } else if (iRet == RS_RET_SUSPENDED) { int retrySlept = 0; iRet = actionDoRetryInternal(pThis, pWti, &retrySlept, 1, NULL); DBGPRINTF("actionCommit[%s]: actionDoRetry returned %d\n", pThis->pszName, iRet); if (iRet == RS_RET_FORCE_TERM) { ABORT_FINALIZE(RS_RET_FORCE_TERM); } else if (iRet != RS_RET_OK) { actionWriteErrorFile(pThis, iRet, iparams, nMsgs); bDone = 1; } else { sleepBeforeRetry = !retrySlept; } continue; } else if (iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED || iRet == RS_RET_ACTION_FAILED || iRet == RS_RET_DISABLE_ACTION) { bDone = 1; } if (getActionState(pWti, pThis) == ACT_STATE_RDY || getActionState(pWti, pThis) == ACT_STATE_SUSP || getActionState(pWti, pThis) == ACT_STATE_DISABLED || actionIsDisabled(pThis)) { bDone = 1; } } while (!bDone); finalize_it: DBGPRINTF("actionCommit[%s]: done, iRet %d\n", pThis->pszName, iRet); if (needfree_iparams) { free(iparams); } wrkrInfo->p.tx.currIParam = 0; /* reset to beginning */ RETiRet; } /* Commit all active transactions in *DIRECT mode* */ void ATTR_NONNULL() actionCommitAllDirect(wti_t *__restrict__ const pWti) { int i; action_t *pAction; for (i = 0; i < runConf->actions.iActionNbr; ++i) { pAction = pWti->actWrkrInfo[i].pAction; if (pAction == NULL) continue; DBGPRINTF( "actionCommitAllDirect: action %d, state %u, nbr to commit %d " "isTransactional %d\n", i, getActionStateByNbr(pWti, i), pWti->actWrkrInfo->p.tx.currIParam, pAction->isTransactional); if (pAction->pQueue->qType == QUEUETYPE_DIRECT && !actionIsDisabled(pAction)) actionCommit(pAction, pWti); } } /* process a single message. This is both called if we run from the * consumer side of an action queue as well as directly from the main * queue thread if the action queue is set to "direct". */ static rsRetVal processMsgMain(action_t *__restrict__ const pAction, wti_t *__restrict__ const pWti, smsg_t *__restrict__ const pMsg, struct syslogTime *ttNow) { DEFiRet; if (actionIsDisabled(pAction)) { actionDisableForWorker(pAction, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } iRet = actionCheckOutputRatelimit(pAction, pWti); if (iRet == RS_RET_DISCARDMSG) { iRet = RS_RET_OK; FINALIZE; } CHKiRet(iRet); CHKiRet(prepareDoActionParams(pAction, pWti, pMsg, ttNow)); if (pAction->isTransactional) { pWti->actWrkrInfo[pAction->iActionNbr].pAction = pAction; DBGPRINTF("action '%s': is transactional - executing in commit phase\n", pAction->pszName); CHKiRet(actionPrepare(pAction, pWti)); iRet = getReturnCode(pAction, pWti); FINALIZE; } iRet = actionProcessMessage(pAction, pWti->actWrkrInfo[pAction->iActionNbr].p.nontx.actParams, pWti); if (pAction->bNeedReleaseBatch) releaseDoActionParams(pAction, pWti, 0); if (iRet == RS_RET_OK) { if (pWti->execState.bDoAutoCommit) iRet = actionCommit(pAction, pWti); } finalize_it: RETiRet; } static void markBatchCommittedFrom(batch_t *const pBatch, const int firstElem) { for (int i = firstElem; i < batchNumMsgs(pBatch); ++i) { if (batchIsValidElem(pBatch, i)) { batchSetElemState(pBatch, i, BATCH_STATE_COMM); } } } static void markBatchReadyFrom(batch_t *const pBatch, const int firstElem) { for (int i = firstElem; i < batchNumMsgs(pBatch); ++i) { if (batchIsValidElem(pBatch, i)) { batchSetElemState(pBatch, i, BATCH_STATE_RDY); } } } /** * @brief Worker callback for action queues. * * Called by the action's queue to process a batch of messages. Each * message is executed via processMsgMain() so that transactional * actions collect parameters before a final call to actionCommit(). * * @param[in] pVoid pointer to the action instance * @param[in] pBatch batch of messages from the queue * @param[in] pWti worker thread state */ static rsRetVal ATTR_NONNULL() processBatchMain(void *__restrict__ const pVoid, batch_t *__restrict__ const pBatch, wti_t *__restrict__ const pWti) { action_t *__restrict__ const pAction = (action_t *__restrict__ const)pVoid; int i; struct syslogTime ttNow; DEFiRet; wtiResetExecState(pWti, pBatch); /* indicate we have not yet read the date */ ttNow.year = 0; if (actionIsDisabled(pAction)) { actionDisableForWorker(pAction, pWti); markBatchCommittedFrom(pBatch, 0); FINALIZE; } for (i = 0; i < batchNumMsgs(pBatch) && !wtiIsShutdownImmediate(pWti); ++i) { if (batchIsValidElem(pBatch, i)) { /* we do not check error state below, because aborting would be * more harmful than continuing. */ rsRetVal localRet = processMsgMain(pAction, pWti, pBatch->pElem[i].pMsg, &ttNow); DBGPRINTF("processBatchMain: i %d, processMsgMain iRet %d\n", i, localRet); if (localRet == RS_RET_OK || localRet == RS_RET_DEFER_COMMIT || localRet == RS_RET_ACTION_FAILED || localRet == RS_RET_PREVIOUS_COMMITTED) { batchSetElemState(pBatch, i, BATCH_STATE_COMM); DBGPRINTF("processBatchMain: i %d, COMM state set\n", i); } else if (localRet == RS_RET_DISABLE_ACTION) { actionDisableForWorker(pAction, pWti); markBatchCommittedFrom(pBatch, i); FINALIZE; } } } if (batchNumMsgs(pBatch) > 0) { STATSCOUNTER_INC(pAction->ctrBatchesProcessed, pAction->mutCtrBatchesProcessed); } iRet = actionCommit(pAction, pWti); /* Transactional messages are tentatively marked committed when queued for * the commit call. If shutdown interrupts retry handling, keep them on the * queue so disk queues can persist and retry them after restart. */ if (iRet == RS_RET_FORCE_TERM && pAction->isTransactional) { markBatchReadyFrom(pBatch, 0); } finalize_it: RETiRet; } /** * @brief Remove a worker instance from an action. * * Called by worker threads during shutdown to remove their private * data pointer from the action's worker table. */ void actionRemoveWorker(action_t *const __restrict__ pAction, void *const __restrict__ actWrkrData) { pthread_mutex_lock(&pAction->mutWrkrDataTable); pAction->nWrkr--; for (int w = 0; w < pAction->wrkrDataTableSize; ++w) { if (pAction->wrkrDataTable[w] == actWrkrData) { pAction->wrkrDataTable[w] = NULL; break; /* done */ } } pthread_mutex_unlock(&pAction->mutWrkrDataTable); } /** * @brief Invoke the configured HUP handlers for an action. * * Both action-level and per-worker callbacks may be registered by the * output module. The worker table is locked while iterating to avoid * races with worker removal. */ rsRetVal actionCallHUPHdlr(action_t *const pAction) { DEFiRet; assert(pAction != NULL); DBGPRINTF("Action %p checks HUP hdlr, act level: %p, wrkr level %p\n", pAction, pAction->pMod->doHUP, pAction->pMod->doHUPWrkr); if (pAction->pMod->doHUP != NULL) { CHKiRet(pAction->pMod->doHUP(pAction->pModData)); } if (pAction->pMod->doHUPWrkr != NULL) { pthread_mutex_lock(&pAction->mutWrkrDataTable); for (int i = 0; i < pAction->wrkrDataTableSize; ++i) { dbgprintf("HUP: table entry %d: %p %s\n", i, pAction->wrkrDataTable[i], pAction->wrkrDataTable[i] == NULL ? "[unused]" : ""); if (pAction->wrkrDataTable[i] != NULL) { const rsRetVal localRet = pAction->pMod->doHUPWrkr(pAction->wrkrDataTable[i]); if (localRet != RS_RET_OK) { DBGPRINTF( "HUP handler returned error state %d - " "ignored\n", localRet); } } } pthread_mutex_unlock(&pAction->mutWrkrDataTable); } finalize_it: RETiRet; } /* set the action message queue mode * TODO: probably move this into queue object, merge with MainMsgQueue! * rgerhards, 2008-01-28 */ static rsRetVal setActionQueType(void __attribute__((unused)) * pVal, uchar *pszType) { DEFiRet; if (!strcasecmp((char *)pszType, "fixedarray")) { cs.ActionQueType = QUEUETYPE_FIXED_ARRAY; DBGPRINTF("action queue type set to FIXED_ARRAY\n"); } else if (!strcasecmp((char *)pszType, "linkedlist")) { cs.ActionQueType = QUEUETYPE_LINKEDLIST; DBGPRINTF("action queue type set to LINKEDLIST\n"); } else if (!strcasecmp((char *)pszType, "disk")) { cs.ActionQueType = QUEUETYPE_DISK; DBGPRINTF("action queue type set to DISK\n"); } else if (!strcasecmp((char *)pszType, "segmenteddisk")) { LogError(0, RS_RET_INVALID_PARAMS, "$ActionQueueType does not support the experimental segmentedDisk backend; use action() object " "parameters instead"); iRet = RS_RET_INVALID_PARAMS; } else if (!strcasecmp((char *)pszType, "direct")) { cs.ActionQueType = QUEUETYPE_DIRECT; DBGPRINTF("action queue type set to DIRECT (no queueing at all)\n"); } else { LogError(0, RS_RET_INVALID_PARAMS, "unknown actionqueue parameter: %s", (char *)pszType); iRet = RS_RET_INVALID_PARAMS; } free(pszType); /* no longer needed */ RETiRet; } /* This submits the message to the action queue in case we do NOT need to handle repeat * message processing. That case permits us to gain lots of freedom during processing * and thus speed. This is also utilized to submit messages in more complex cases once * the complex logic has been applied ;) * rgerhards, 2010-06-08 */ static rsRetVal ATTR_NONNULL() doSubmitToActionQ(action_t *const pAction, wti_t *const pWti, smsg_t *pMsg) { struct syslogTime ttNow; // TODO: think if we can buffer this in pWti DEFiRet; DBGPRINTF("action '%s': called, logging to %s (susp %d/%d, direct q %d)\n", pAction->pszName, module.GetStateName(pAction->pMod), pAction->bExecWhenPrevSusp, pWti->execState.bPrevWasSuspended, pAction->pQueue->qType == QUEUETYPE_DIRECT); if (actionIsDisabled(pAction)) { actionDisableForWorker(pAction, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } if (pAction->bExecWhenPrevSusp && !pWti->execState.bPrevWasSuspended) { DBGPRINTF( "action '%s': NOT executing, as previous action was " "not suspended\n", pAction->pszName); FINALIZE; } STATSCOUNTER_INC(pAction->ctrProcessed, pAction->mutCtrProcessed); if (pAction->pQueue->qType == QUEUETYPE_DIRECT) { STATSCOUNTER_INC(pAction->ctrBatchesProcessed, pAction->mutCtrBatchesProcessed); ttNow.year = 0; iRet = processMsgMain(pAction, pWti, pMsg, &ttNow); } else { /* in this case, we do single submits to the queue. * TODO: optimize this, we may do at least a multi-submit! */ iRet = qqueueEnqMsg(pAction->pQueue, eFLOWCTL_NO_DELAY, pAction->bCopyMsg ? MsgDup(pMsg) : MsgAddRef(pMsg)); } pWti->execState.bPrevWasSuspended = (iRet == RS_RET_SUSPENDED || iRet == RS_RET_ACTION_FAILED); if (iRet == RS_RET_ACTION_FAILED) /* Increment failed counter */ STATSCOUNTER_INC(pAction->ctrFail, pAction->mutCtrFail); DBGPRINTF("action '%s': set suspended state to %d\n", pAction->pszName, pWti->execState.bPrevWasSuspended); finalize_it: RETiRet; } /** * Enqueue a single message for later processing by an action. * * The caller is responsible for filtering messages that should be * discarded due to previous suspension state; this function always * enqueues the provided message when the rate and interval checks pass. */ rsRetVal actionWriteToAction(action_t *const pAction, smsg_t *pMsg, wti_t *const pWti) { DEFiRet; if (actionIsDisabled(pAction)) { actionDisableForWorker(pAction, pWti); ABORT_FINALIZE(RS_RET_DISABLE_ACTION); } /* first, we check if the action should actually be called. The action-specific * $ActionExecOnlyEveryNthTime permits us to execute an action only every Nth * time. So we need to check if we need to drop the (otherwise perfectly executable) * action for this reason. Note that in case we need to drop it, we return RS_RET_OK * as the action was properly "passed to execution" from the upper layer's point * of view. -- rgerhards, 2008-08-07. */ if (pAction->iExecEveryNthOccur > 1) { /* we need to care about multiple occurrences */ if (pAction->iExecEveryNthOccurTO > 0 && (getActNow(pAction) - pAction->tLastOccur) > pAction->iExecEveryNthOccurTO) { DBGPRINTF("n-th occurrence handling timed out (%d sec), restarting from 0\n", (int)(getActNow(pAction) - pAction->tLastOccur)); pAction->iNbrNoExec = 0; pAction->tLastOccur = getActNow(pAction); } if (pAction->iNbrNoExec < pAction->iExecEveryNthOccur - 1) { ++pAction->iNbrNoExec; DBGPRINTF("action %p passed %d times to execution - less than configured - discarding\n", pAction, pAction->iNbrNoExec); FINALIZE; } else { pAction->iNbrNoExec = 0; /* we execute the action now, so the number of no execs is down to */ } } DBGPRINTF("Called action(complex case), logging to %s\n", module.GetStateName(pAction->pMod)); /* now check if we need to drop the message because otherwise the action would be too * frequently called. -- rgerhards, 2008-04-08 * Note that the check for "pAction->iSecsExecOnceInterval > 0" is not necessary from * a purely logical point of view. However, if safes us to check the system time in * (those common) cases where ExecOnceInterval is not used. -- rgerhards, 2008-09-16 */ if (pAction->iSecsExecOnceInterval > 0 && pAction->iSecsExecOnceInterval + pAction->tLastExec > getActNow(pAction)) { /* in this case we need to discard the message - its not yet time to exec the action */ DBGPRINTF("action not yet ready again to be executed, onceInterval %d, tCurr %d, tNext %d\n", (int)pAction->iSecsExecOnceInterval, (int)getActNow(pAction), (int)(pAction->iSecsExecOnceInterval + pAction->tLastExec)); FINALIZE; } /* we use reception time, not dequeue time - this is considered more appropriate and also faster ;) * rgerhards, 2008-09-17 */ pAction->tLastExec = getActNow(pAction); /* re-init time flags */ pAction->f_time = pMsg->ttGenTime; /* When we reach this point, we have a valid, non-disabled action. * So let's enqueue our message for execution. -- rgerhards, 2007-07-24 */ iRet = doSubmitToActionQ(pAction, pWti, pMsg); finalize_it: RETiRet; } /* Call configured action, most complex case with all features supported (and thus slow). * rgerhards, 2010-06-08 */ PRAGMA_DIAGNOSTIC_PUSH; PRAGMA_IGNORE_Wempty_body; static rsRetVal doSubmitToActionQComplex(action_t *const pAction, wti_t *const pWti, smsg_t *pMsg) { DEFiRet; d_pthread_mutex_lock(&pAction->mutAction); pthread_cleanup_push(mutexCancelCleanup, &pAction->mutAction); DBGPRINTF("Called action %p (complex case), logging to %s\n", pAction, module.GetStateName(pAction->pMod)); pAction->tActNow = -1; /* we do not yet know our current time (clear prev. value) */ // TODO: can we optimize the "now" handling again (was batch, I guess...)? /* don't output marks to recently written outputs */ if (pAction->bWriteAllMarkMsgs == 0 && (pMsg->msgFlags & MARK) && (getActNow(pAction) - pAction->f_time) < MarkInterval / 2) { ABORT_FINALIZE(RS_RET_OK); } /* call the output driver */ iRet = actionWriteToAction(pAction, pMsg, pWti); finalize_it: d_pthread_mutex_unlock(&pAction->mutAction); pthread_cleanup_pop(0); /* remove mutex cleanup handler */ RETiRet; } PRAGMA_DIAGNOSTIC_POP /* helper to activateActions, it activates a specific action. */ DEFFUNC_llExecFunc(doActivateActions) { rsRetVal localRet; action_t *const pThis = (action_t *)pData; localRet = qqueueStart(runConf, pThis->pQueue); if (localRet != RS_RET_OK) { if (runConf->globals.bAbortOnFailedQueueStartup) { fprintf(stderr, "rsyslogd: error %d starting up action queue, " "abortOnFailedQueueStartup is set, so we abort rsyslog now.", localRet); fflush(stderr); exit(1); /* "good" exit, this is intended here */ } LogError(0, localRet, "error starting up action queue"); if (localRet == RS_RET_FILE_PREFIX_MISSING) { LogError(0, localRet, "file prefix (work directory?) " "is missing"); } actionDisable(pThis); } DBGPRINTF("Action %s[%p]: queue %p started\n", modGetName(pThis->pMod), pThis, pThis->pQueue); return RS_RET_OK; /* we ignore errors, we can not do anything either way */ } /* This function "activates" the action after privileges have been dropped. Currently, * this means that the queues are started. * rgerhards, 2011-05-02 */ rsRetVal activateActions(void) { DEFiRet; iRet = ruleset.IterateAllActions(runConf, doActivateActions, NULL); RETiRet; } /* This submits the message to the action queue in case where we need to handle * bWriteAllMarkMessage == RSFALSE only. Note that we use a non-blocking CAS loop * for the synchronization. Here, we just modify the filter condition to be false when * a mark message must not be written. However, in this case we must save the previous * filter as we may need it in the next action (potential future optimization: check if this is * the last action TODO). * rgerhards, 2010-06-08 */ static rsRetVal doSubmitToActionQNotAllMark(action_t *const pAction, wti_t *const pWti, smsg_t *const pMsg) { int doProcess = 1; time_t lastAct; DEFiRet; /* TODO: think about the whole logic. If messages come in out of order, things * tend to become a bit unreliable. On the other hand, this only happens if we have * very high traffic, in which this use case here is not really affected (as the * MarkInterval is pretty corase). */ /* CAS loop, we write back a bit early, but that's OK... */ /* we use reception time, not dequeue time - this is considered more appropriate and * also faster ;) -- rgerhards, 2008-09-17 */ do { lastAct = pAction->f_time; if (pMsg->msgFlags & MARK) { if ((pMsg->ttGenTime - lastAct) < MarkInterval / 2) { doProcess = 0; DBGPRINTF("action was recently called, ignoring mark message\n"); break; /* do not update timestamp for non-written mark messages */ } } } while (ATOMIC_CAS_time_t(&pAction->f_time, lastAct, pMsg->ttGenTime, &pAction->mutCAS) == 0); if (doProcess) { DBGPRINTF("Called action(NotAllMark), processing via '%s'\n", module.GetStateName(pAction->pMod)); iRet = doSubmitToActionQ(pAction, pWti, pMsg); } RETiRet; } /* apply all params from param block to action. This supports the v6 config system. * Defaults must have been set appropriately during action construct! * rgerhards, 2011-08-01 */ static rsRetVal actionApplyCnfParam(action_t *const pAction, struct cnfparamvals *const pvals) { int i; DEFiRet; for (i = 0; i < pblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(pblk.descr[i].name, "name")) { pAction->pszName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(pblk.descr[i].name, "type")) { continue; /* this is handled seperately during module select! */ } else if (!strcmp(pblk.descr[i].name, "action.errorfile")) { pAction->pszErrFile = es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(pblk.descr[i].name, "action.errorfile.maxsize")) { pAction->maxErrFileSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.externalstate.file")) { pAction->pszExternalStateFile = es_str2cstr(pvals[i].val.d.estr, NULL); } else if (!strcmp(pblk.descr[i].name, "action.writeallmarkmessages")) { pAction->bWriteAllMarkMsgs = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.execonlyeverynthtime")) { pAction->iExecEveryNthOccur = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.execonlyeverynthtimetimeout")) { pAction->iExecEveryNthOccurTO = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.execonlyonceeveryinterval")) { pAction->iSecsExecOnceInterval = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.execonlywhenpreviousissuspended")) { pAction->bExecWhenPrevSusp = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.repeatedmsgcontainsoriginalmsg")) { pAction->bRepMsgHasMsg = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.resumeretrycount")) { pAction->iResumeRetryCount = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.reportsuspension")) { pAction->bReportSuspension = (int)pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.reportsuspensioncontinuation")) { pAction->bReportSuspensionCont = (int)pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.copymsg")) { pAction->bCopyMsg = (int)pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.resumeinterval")) { pAction->iResumeInterval = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.resumeintervalmax")) { pAction->iResumeIntervalMax = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "action.ratelimit.name")) { CHKmalloc(pAction->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { dbgprintf( "action: program error, non-handled " "param '%s'\n", pblk.descr[i].name); } } finalize_it: RETiRet; } /* add an Action to the current selector * The pOMSR is freed, as it is not needed after this function. * Note: this function pulls global data that specifies action config state. * rgerhards, 2007-07-27 */ rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, struct cnfparamvals *actParams, struct nvlst *const lst) { DEFiRet; int i; int iTplOpts; uchar *pTplName; action_t *pAction; char errMsg[512]; assert(ppAction != NULL); assert(pMod != NULL); assert(pOMSR != NULL); DBGPRINTF("Module %s processes this action.\n", module.GetName(pMod)); CHKiRet(actionConstruct(&pAction)); /* create action object first */ pAction->pMod = pMod; pAction->pModData = pModData; if (rsconfTranslateEnabled() && lst != NULL && pAction->pSyntaxLst == NULL) { pAction->pSyntaxLst = rsconfTranslateCloneNvlst(lst); } if (actParams == NULL) { /* use legacy systemn */ pAction->pszName = cs.pszActionName; pAction->iResumeInterval = cs.glbliActionResumeInterval; pAction->iResumeRetryCount = cs.glbliActionResumeRetryCount; pAction->bWriteAllMarkMsgs = cs.bActionWriteAllMarkMsgs; pAction->bExecWhenPrevSusp = cs.bActExecWhenPrevSusp; pAction->iSecsExecOnceInterval = cs.iActExecOnceInterval; pAction->iExecEveryNthOccur = cs.iActExecEveryNthOccur; pAction->iExecEveryNthOccurTO = cs.iActExecEveryNthOccurTO; pAction->bRepMsgHasMsg = cs.bActionRepMsgHasMsg; cs.iActExecEveryNthOccur = 0; /* auto-reset */ cs.iActExecEveryNthOccurTO = 0; /* auto-reset */ cs.bActionWriteAllMarkMsgs = 1; /* auto-reset */ cs.pszActionName = NULL; /* free again! */ } else { actionApplyCnfParam(pAction, actParams); } /* check if we can obtain the template pointers - TODO: move to separate function? */ pAction->iNumTpls = OMSRgetEntryCount(pOMSR); assert(pAction->iNumTpls >= 0); /* only debug check because this "can not happen" */ /* please note: iNumTpls may validly be zero. This is the case if the module * does not request any templates. This sounds unlikely, but an actual example is * the discard action, which does not require a string. -- rgerhards, 2007-07-30 */ if (pAction->iNumTpls > 0) { /* we first need to create the template arrays */ CHKmalloc(pAction->ppTpl = (struct template **)calloc(pAction->iNumTpls, sizeof(struct template *))); CHKmalloc(pAction->peParamPassing = (paramPassing_t *)calloc(pAction->iNumTpls, sizeof(paramPassing_t))); } pAction->bUsesMsgPassingMode = 0; pAction->bNeedReleaseBatch = 0; for (i = 0; i < pAction->iNumTpls; ++i) { CHKiRet(OMSRgetEntry(pOMSR, i, &pTplName, &iTplOpts)); /* Ok, we got everything, so it now is time to look up the template * (Hint: templates MUST be defined before they are used!) */ if (!(iTplOpts & OMSR_TPL_AS_MSG)) { if ((pAction->ppTpl[i] = tplFind(loadConf, (char *)pTplName, strlen((char *)pTplName))) == NULL) { snprintf(errMsg, sizeof(errMsg), " Could not find template %d '%s' - action disabled", i, pTplName); errno = 0; LogError(0, RS_RET_NOT_FOUND, "%s", errMsg); ABORT_FINALIZE(RS_RET_NOT_FOUND); } /* check required template options */ if ((iTplOpts & OMSR_RQD_TPL_OPT_SQL) && (pAction->ppTpl[i]->optFormatEscape == 0)) { errno = 0; LogError(0, RS_RET_RQD_TPLOPT_MISSING, "Action disabled." " To use this action, you have to specify " "the SQL or stdSQL option in your template!\n"); ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING); } tplNoteUse(pAction->ppTpl[i], iTplOpts & OMSR_TPL_AS_DYNAFILE); } /* set parameter-passing mode */ if (iTplOpts & OMSR_TPL_AS_ARRAY) { ABORT_FINALIZE(RS_RET_ERR); } else if (iTplOpts & OMSR_TPL_AS_MSG) { pAction->peParamPassing[i] = ACT_MSG_PASSING; pAction->bUsesMsgPassingMode = 1; } else if (iTplOpts & OMSR_TPL_AS_JSON) { pAction->peParamPassing[i] = ACT_JSON_PASSING; pAction->bNeedReleaseBatch = 1; } else { pAction->peParamPassing[i] = ACT_STRING_PASSING; } DBGPRINTF("template: '%s' assigned\n", pTplName); } pAction->pMod = pMod; pAction->pModData = pModData; CHKiRet(actionConstructFinalize(pAction, lst)); if (pAction->pMod->mod.om.setActionInfo != NULL) { CHKiRet(pAction->pMod->mod.om.setActionInfo(pAction->pModData, pAction)); } *ppAction = pAction; /* finally store the action pointer */ finalize_it: if (iRet == RS_RET_OK) iRet = OMSRdestruct(pOMSR); else { /* do not overwrite error state! */ OMSRdestruct(pOMSR); if (pAction != NULL) actionDestruct(pAction); } RETiRet; } const uchar *actionGetName(const action_t *const pAction) { static const uchar fallbackName[] = "[action]"; if (pAction == NULL) { assert(pAction != NULL); /* should not happen, but we are robust */ return fallbackName; } if (pAction->pszName == NULL) { return fallbackName; } return pAction->pszName; } /* Reset config variables to default values. * rgerhards, 2009-11-12 */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { cs.iActExecOnceInterval = 0; cs.bActExecWhenPrevSusp = 0; return RS_RET_OK; } /* initialize (current) config variables. * Used at program start and when a new scope is created. */ static void initConfigVariables(void) { cs.bActionWriteAllMarkMsgs = 1; cs.glbliActionResumeRetryCount = 0; cs.bActExecWhenPrevSusp = 0; cs.iActExecOnceInterval = 0; cs.iActExecEveryNthOccur = 0; cs.iActExecEveryNthOccurTO = 0; cs.glbliActionResumeInterval = 30; cs.glbliActionResumeRetryCount = 0; cs.bActionRepMsgHasMsg = 0; if (cs.pszActionName != NULL) { free(cs.pszActionName); cs.pszActionName = NULL; } actionResetQueueParams(); } rsRetVal actionNewInst(struct nvlst *lst, action_t **ppAction) { struct cnfparamvals *paramvals; modInfo_t *pMod; uchar *cnfModName = NULL; omodStringRequest_t *pOMSR; void *pModData; action_t *pAction; DEFiRet; paramvals = nvlstGetParams(lst, &pblk, NULL); if (paramvals == NULL) { ABORT_FINALIZE(RS_RET_PARAM_ERROR); } dbgprintf("action param blk after actionNewInst:\n"); cnfparamsPrint(&pblk, paramvals); cnfModName = (uchar *)es_str2cstr(paramvals[cnfparamGetIdx(&pblk, ("type"))].val.d.estr, NULL); if ((pMod = module.FindWithCnfName(loadConf, cnfModName, eMOD_OUT)) == NULL) { LogError(0, RS_RET_MOD_UNKNOWN, "module name '%s' is unknown", cnfModName); ABORT_FINALIZE(RS_RET_MOD_UNKNOWN); } CHKiRet(pMod->mod.om.newActInst(cnfModName, lst, &pModData, &pOMSR)); if ((iRet = addAction(&pAction, pMod, pModData, pOMSR, paramvals, lst)) == RS_RET_OK) { /* check if the module is compatible with select features * (currently no such features exist) */ loadConf->actions.nbrActions++; /* one more active action! */ *ppAction = pAction; } else { // TODO: cleanup } finalize_it: free(cnfModName); cnfparamvalsDestruct(paramvals, &pblk); RETiRet; } rsRetVal actionClassInit(void) { DEFiRet; /* request objects we use */ CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */ CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(regCfSysLineHdlr((uchar *)"actionname", 0, eCmdHdlrGetWord, NULL, &cs.pszActionName, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuefilename", 0, eCmdHdlrGetWord, NULL, &cs.pszActionQFName, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesize", 0, eCmdHdlrInt, NULL, &cs.iActionQueueSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionwriteallmarkmessages", 0, eCmdHdlrBinary, NULL, &cs.bActionWriteAllMarkMsgs, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuebatchsize", 0, eCmdHdlrInt, NULL, &cs.iActionQueueDeqBatchSize, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &cs.iActionQueMaxDiskSpace, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuehighwatermark", 0, eCmdHdlrInt, NULL, &cs.iActionQHighWtrMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuelowwatermark", 0, eCmdHdlrInt, NULL, &cs.iActionQLowWtrMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuediscardmark", 0, eCmdHdlrInt, NULL, &cs.iActionQDiscardMark, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuediscardseverity", 0, eCmdHdlrInt, NULL, &cs.iActionQDiscardSeverity, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuecheckpointinterval", 0, eCmdHdlrInt, NULL, &cs.iActionQPersistUpdCnt, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesyncqueuefiles", 0, eCmdHdlrBinary, NULL, &cs.bActionQSyncQeueFiles, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetype", 0, eCmdHdlrGetWord, setActionQueType, NULL, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkerthreads", 0, eCmdHdlrPositiveInt, NULL, &cs.iActionQueueNumWorkers, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL, &cs.iActionQtoQShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL, &cs.iActionQtoActShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL, &cs.iActionQtoEnq, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkertimeoutthreadshutdown", 0, eCmdHdlrInt, NULL, &cs.iActionQtoWrkShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL, &cs.iActionQWrkMinMsgs, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &cs.iActionQueMaxFileSize, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &cs.bActionQSaveOnShutdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &cs.iActionQueueDeqSlowdown, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimebegin", 0, eCmdHdlrInt, NULL, &cs.iActionQueueDeqtWinFromHr, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionqueuedequeuetimeend", 0, eCmdHdlrInt, NULL, &cs.iActionQueueDeqtWinToHr, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"actionexeconlyeverynthtime", 0, eCmdHdlrInt, NULL, &cs.iActExecEveryNthOccur, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyeverynthtimetimeout", 0, eCmdHdlrInt, NULL, &cs.iActExecEveryNthOccurTO, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlyonceeveryinterval", 0, eCmdHdlrInt, NULL, &cs.iActExecOnceInterval, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgcontainsoriginalmsg", 0, eCmdHdlrBinary, NULL, &cs.bActionRepMsgHasMsg, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &cs.bActExecWhenPrevSusp, NULL)); CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &cs.glbliActionResumeRetryCount, NULL)); CHKiRet( regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); initConfigVariables(); /* first-time init of config setings */ finalize_it: RETiRet; } /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_gtls.h0000644000000000000000000000013215171370365016220 xustar0030 mtime=1776677109.439913048 30 atime=1787067618.314442935 30 ctime=1787067794.546727887 rsyslog-8.2608.0/runtime/nsd_gtls.h0000664000175000017500000001266315171370365015674 0ustar00rgerrger/* An implementation of the nsd interface for GnuTLS. * * Copyright 2008-2026 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NSD_GTLS_H #define INCLUDED_NSD_GTLS_H #include "nsd.h" #define NSD_GTLS_MAX_RCVBUF 16 * 1024 + 1 /* TLS RFC 8449: max size of buffer for message reception */ #define NSD_GTLS_MAX_CERT 10 /* max number of certs in our chain */ typedef enum { gtlsRtry_None = 0, /**< no call needs to be retried */ gtlsRtry_handshake = 1, gtlsRtry_recv = 2 } gtlsRtryCall_t; /**< IDs of calls that needs to be retried */ typedef enum { gtlsDir_READ = 0, /**< GNUTLS wants READ */ gtlsDir_WRITE = 1 /**< GNUTLS wants WRITE */ } gtlsDirection_t; typedef nsd_if_t nsd_gtls_if_t; /* we just *implement* this interface */ /* the nsd_gtls object */ struct nsd_gtls_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */ uchar *pszConnectHost; /**< hostname used for connect - may be used to authenticate peer if no other name given */ const uchar *pszCAFile; const uchar *pszCRLFile; const uchar *pszKeyFile; const uchar *pszCertFile; gnutls_certificate_credentials_t xcred; int xcred_is_copy; int iMode; /* 0 - plain tcp, 1 - TLS */ int bAbortConn; /* if set, abort conncection (fatal error had happened) */ enum { GTLS_AUTH_CERTNAME = 0, GTLS_AUTH_CERTFINGERPRINT = 1, GTLS_AUTH_CERTVALID = 2, GTLS_AUTH_CERTANON = 3 } authMode; enum { GTLS_EXPIRED_PERMIT = 0, GTLS_EXPIRED_DENY = 1, GTLS_EXPIRED_WARN = 2 } permitExpiredCerts; enum { GTLS_NONE = 0, GTLS_PURPOSE = 1 } dataTypeCheck; int bSANpriority; /* if true, we do stricter checking (if any SAN present we do not cehck CN) */ gtlsRtryCall_t rtryCall; /**< what must we retry? */ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */ gnutls_session_t sess; int bHaveSess; /* as we don't know exactly which gnutls_session values are invalid, we use this one to flag whether or not we are in a session (same as -1 for a socket meaning no sess) */ int bReportAuthErr; /* only the first auth error is to be reported, this var triggers it. Initially, it is * set to 1 and changed to 0 after the first report. It is changed back to 1 after * one successful authentication. */ permittedPeers_t *pPermPeers; /* permitted peers */ uchar *gnutlsPriorityString; /* gnutls priority string */ uchar *remoteSNI; /**< Remote SNI to use instead of the server hostname */ int DrvrVerifyDepth; /* Verify Depth for certificate chains */ int DrvrTlsRevocationCheck; /**< Enable TLS revocation checking (OCSP/CRL) */ time_t crlNextUpdate; /**< cached CRL nextUpdate for per-connection expiration check (0 = not set) */ gnutls_x509_crt_t pOurCerts[NSD_GTLS_MAX_CERT]; /**< our certificate, if in client mode (unused in server mode) */ unsigned int nOurCerts; /* number of certificates in our chain */ gnutls_x509_privkey_t ourKey; /**< our private key, if in client mode (unused in server mode) */ short bOurCertIsInit; /**< 1 if our certificate is initialized and must be deinit on destruction */ short bOurKeyIsInit; /**< 1 if our private key is initialized and must be deinit on destruction */ char *pszRcvBuf; int lenRcvBuf; /**< -1: empty, 0: connection closed, 1..NSD_GTLS_MAX_RCVBUF-1: data of that size present */ int ptrRcvBuf; /**< offset for next recv operation if 0 < lenRcvBuf < NSD_GTLS_MAX_RCVBUF */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsd_gtlsCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObjFull(nsd_gtls); /* some prototypes for things used by our nsdsel_gtls helper class */ uchar *gtlsStrerror(int error); rsRetVal gtlsChkPeerAuth(nsd_gtls_t *pThis); rsRetVal gtlsRecordRecv(nsd_gtls_t *pThis, unsigned *); /* the name of our library binary */ #define LM_NSD_GTLS_FILENAME "lmnsd_gtls" #if GNUTLS_VERSION_NUMBER <= 0x00030000 #define GTLS_ANON_PRIO_NOTLSV13 "NORMAL:-VERS-TLS1.3:+ANON-DH:+COMP-ALL" #define GTLS_ANON_PRIO "NORMAL:+ANON-DH:+COMP-ALL" #else #define GTLS_ANON_PRIO_NOTLSV13 "NORMAL:-VERS-TLS1.3:+ANON-DH:+ANON-ECDH:+COMP-ALL" #define GTLS_ANON_PRIO "NORMAL:+ANON-DH:+ANON-ECDH:+COMP-ALL" #endif #if GNUTLS_VERSION_MAJOR > 3 || (GNUTLS_VERSION_MAJOR == 3 && GNUTLS_VERSION_MINOR >= 4) #define EXTENDED_CERT_CHECK_AVAILABLE #endif #endif /* #ifndef INCLUDED_NSD_GTLS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/nsd_ossl.h0000644000000000000000000000013115145046113016216 xustar0030 mtime=1771326539.003013701 30 atime=1787067618.653449256 29 ctime=1787067794.56672826 rsyslog-8.2608.0/runtime/nsd_ossl.h0000664000175000017500000000756715145046113015702 0ustar00rgerrger/* An implementation of the nsd interface for OpenSSL. * * Copyright 2018-2026 Adiscon GmbH. * Author: Andre Lorbach * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NSD_OSSL_H #define INCLUDED_NSD_OSSL_H #include "nsd.h" #define NSD_OSSL_MAX_RCVBUF 16 * 1024 + 1 /* TLS RFC 8449: max size of buffer for message reception */ typedef enum { osslRtry_None = 0, /**< no call needs to be retried */ osslRtry_handshake = 1, osslRtry_recv = 2 } osslRtryCall_t; /**< IDs of calls that needs to be retried */ typedef nsd_if_t nsd_ossl_if_t; /* we just *implement* this interface */ /* the nsd_ossl object */ struct nsd_ossl_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ nsd_t *pTcp; /**< our aggregated nsd_ptcp data */ uchar *pszConnectHost; /**< hostname used for connect - may be used to authenticate peer if no other name given */ int iMode; /* 0 - plain tcp, 1 - TLS */ int bAbortConn; /* if set, abort conncection (fatal error had happened) */ PermitExpiredCerts permitExpiredCerts; osslRtryCall_t rtryCall; /**< what must we retry? */ int rtryOsslErr; /**< store ssl error code into like SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE */ int bIsInitiator; /**< 0 if socket is the server end (listener), 1 if it is the initiator */ int bHaveSess; /* as we don't know exactly which gnutls_session values are invalid, we use this one to flag whether or not we are in a session (same as -1 for a socket meaning no sess) */ uchar *gnutlsPriorityString; /* gnutls priority string */ int DrvrVerifyDepth; /* Verify Depth for certificate chains */ int DrvrTlsRevocationCheck; /* Enable TLS revocation checking (OCSP/CRL) */ uchar *remoteSNI; /**< Remote SNI to use instead of the server hostname */ short bOurCertIsInit; /**< 1 if our certificate is initialized and must be deinit on destruction */ short bOurKeyIsInit; /**< 1 if our private key is initialized and must be deinit on destruction */ char *pszRcvBuf; int lenRcvBuf; /**< -1: empty, 0: connection closed, 1..NSD_OSSL_MAX_RCVBUF-1: data of that size present */ int ptrRcvBuf; /**< offset for next recv operation if 0 < lenRcvBuf < NSD_OSSL_MAX_RCVBUF */ /* OpenSSL and Config Cert vars inside net_ossl_t now */ net_ossl_t *pNetOssl; /* OSSL shared Config and object vars are here */ }; /* interface is defined in nsd.h, we just implement it! */ #define nsd_osslCURR_IF_VERSION nsdCURR_IF_VERSION /* prototypes */ PROTOTYPEObjFull(nsd_ossl); /* some prototypes for things used by our nsdsel_ossl helper class */ uchar *osslStrerror(int error); rsRetVal osslChkPeerAuth(nsd_ossl_t *pThis); rsRetVal osslRecordRecv(nsd_ossl_t *pThis, unsigned *); rsRetVal osslHandshakeCheck(nsd_ossl_t *pNsd); void nsd_ossl_lastOpenSSLErrorMsg( nsd_ossl_t const *pThis, const int ret, SSL *ssl, int severity, const char *pszCallSource, const char *pszOsslApi); rsRetVal osslPostHandshakeCheck(nsd_ossl_t *pNsd); /* the name of our library binary */ #define LM_NSD_OSSL_FILENAME "lmnsd_ossl" #endif /* #ifndef INCLUDED_NSD_OSSL_H */ rsyslog-8.2608.0/runtime/PaxHeaders/Makefile.in0000644000000000000000000000013215241076163016274 xustar0030 mtime=1787067507.714380269 30 atime=1787067576.752667934 30 ctime=1787067794.215721719 rsyslog-8.2608.0/runtime/Makefile.in0000664000175000017500000045267315241076163015761 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = ${LIBLOGGING_STDLOG_CFLAGS} @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS) # # regular expression support # @ENABLE_REGEXP_TRUE@am__append_3 = lmregexp.la @ENABLE_LIBLOGGING_STDLOG_TRUE@@ENABLE_REGEXP_TRUE@am__append_4 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@@ENABLE_REGEXP_TRUE@am__append_5 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_6 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_7 = $(LIBLOGGING_STDLOG_LIBS) # netstream drivers # plain tcp driver - main driver @ENABLE_INET_TRUE@am__append_8 = lmnetstrms.la lmnsd_ptcp.la @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_9 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_10 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_11 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_12 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_13 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_INET_TRUE@@ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_14 = $(LIBLOGGING_STDLOG_LIBS) # # openssl base and netstream driver # # noinst_LTLIBRARIES += lmnsd_ossl.la @ENABLE_OSSL_TRUE@am__append_15 = lmnsd_ossl.la # # GnuTLS netstream driver # @ENABLE_GNUTLS_TRUE@am__append_16 = lmnsd_gtls.la # # Mbed TLS netstream driver # @ENABLE_MBEDTLS_TRUE@am__append_17 = lmnsd_mbedtls.la # # support library for libgcrypt # @ENABLE_LIBGCRYPT_TRUE@am__append_18 = libgcry.la @ENABLE_LIBGCRYPT_TRUE@am__append_19 = lmcry_gcry.la @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am__append_20 = libossl.la @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am__append_21 = lmcry_ossl.la # # support library for zstd # @ENABLE_LIBZSTD_TRUE@am__append_22 = lmzstdw.la # # gssapi support # @ENABLE_GSSAPI_TRUE@am__append_23 = lmgssutil.la @ENABLE_LIBZSTD_TRUE@am__append_24 = $(ZSTD_CFLAGS) @ENABLE_LIBZSTD_TRUE@am__append_25 = $(ZSTD_LIBS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_26 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_27 = $(LIBLOGGING_STDLOG_LIBS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_28 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_29 = $(LIBLOGGING_STDLOG_LIBS) # # support library for Guardtime KSI-LS12 # @ENABLE_KSI_LS12_TRUE@am__append_30 = lmsig_ksi_ls12.la subdir = runtime ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)" PROGRAMS = $(sbin_PROGRAMS) LIBRARIES = $(noinst_LIBRARIES) 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; }; \ } LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES) libgcry_la_LIBADD = am__libgcry_la_SOURCES_DIST = libgcry.c libcry_common.c \ libcry_common.h libgcry.h @ENABLE_LIBGCRYPT_TRUE@am_libgcry_la_OBJECTS = libgcry_la-libgcry.lo \ @ENABLE_LIBGCRYPT_TRUE@ libgcry_la-libcry_common.lo libgcry_la_OBJECTS = $(am_libgcry_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 = @ENABLE_LIBGCRYPT_TRUE@am_libgcry_la_rpath = libossl_la_LIBADD = am__libossl_la_SOURCES_DIST = libossl.c libossl.h libcry_common.c \ libcry_common.h @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am_libossl_la_OBJECTS = \ @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@ libossl_la-libossl.lo \ @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@ libossl_la-libcry_common.lo libossl_la_OBJECTS = $(am_libossl_la_OBJECTS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am_libossl_la_rpath = am__DEPENDENCIES_1 = @ENABLE_LIBLOGGING_STDLOG_TRUE@am__DEPENDENCIES_2 = \ @ENABLE_LIBLOGGING_STDLOG_TRUE@ $(am__DEPENDENCIES_1) librsyslog_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am_librsyslog_la_OBJECTS = librsyslog_la-rsyslog.lo \ librsyslog_la-dnscache.lo librsyslog_la-glbl.lo \ librsyslog_la-conf.lo librsyslog_la-janitor.lo \ librsyslog_la-rsconf.lo librsyslog_la-parser.lo \ librsyslog_la-strgen.lo librsyslog_la-msg.lo \ librsyslog_la-linkedlist.lo librsyslog_la-objomsr.lo \ librsyslog_la-stringbuf.lo librsyslog_la-datetime.lo \ librsyslog_la-srutils.lo librsyslog_la-errmsg.lo \ librsyslog_la-operatingstate.lo librsyslog_la-debug.lo \ librsyslog_la-obj.lo librsyslog_la-modules.lo \ librsyslog_la-statsobj.lo librsyslog_la-dynstats.lo \ librsyslog_la-perctile_ringbuf.lo \ librsyslog_la-perctile_stats.lo librsyslog_la-stream.lo \ librsyslog_la-var.lo librsyslog_la-wtp.lo librsyslog_la-wti.lo \ librsyslog_la-queue.lo librsyslog_la-queue_da.lo \ librsyslog_la-segdisk_codec.lo librsyslog_la-segdisk_crc.lo \ librsyslog_la-segdisk_state.lo librsyslog_la-segdisk_store.lo \ librsyslog_la-ruleset.lo librsyslog_la-rswatch.lo \ librsyslog_la-prop.lo librsyslog_la-ratelimit.lo \ librsyslog_la-translate.lo librsyslog_la-yamlconf.lo \ librsyslog_la-lookup.lo librsyslog_la-cfsysline.lo \ librsyslog_la-action.lo librsyslog_la-threads.lo \ librsyslog_la-parse.lo librsyslog_la-hashtable.lo \ librsyslog_la-hashtable_itr.lo librsyslog_la-outchannel.lo \ librsyslog_la-template.lo librsyslog_la-timezones.lo librsyslog_la_OBJECTS = $(am_librsyslog_la_OBJECTS) am__lmcry_gcry_la_SOURCES_DIST = lmcry_gcry.c lmcry_gcry.h @ENABLE_LIBGCRYPT_TRUE@am_lmcry_gcry_la_OBJECTS = \ @ENABLE_LIBGCRYPT_TRUE@ lmcry_gcry_la-lmcry_gcry.lo lmcry_gcry_la_OBJECTS = $(am_lmcry_gcry_la_OBJECTS) lmcry_gcry_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmcry_gcry_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_LIBGCRYPT_TRUE@am_lmcry_gcry_la_rpath = -rpath $(pkglibdir) am__lmcry_ossl_la_SOURCES_DIST = lmcry_ossl.c lmcry_ossl.h @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am_lmcry_ossl_la_OBJECTS = lmcry_ossl_la-lmcry_ossl.lo lmcry_ossl_la_OBJECTS = $(am_lmcry_ossl_la_OBJECTS) lmcry_ossl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmcry_ossl_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@am_lmcry_ossl_la_rpath = -rpath \ @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@ $(pkglibdir) @ENABLE_GSSAPI_TRUE@lmgssutil_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am__lmgssutil_la_SOURCES_DIST = gss-misc.c gss-misc.h gss-token-util.h @ENABLE_GSSAPI_TRUE@am_lmgssutil_la_OBJECTS = \ @ENABLE_GSSAPI_TRUE@ lmgssutil_la-gss-misc.lo lmgssutil_la_OBJECTS = $(am_lmgssutil_la_OBJECTS) lmgssutil_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmgssutil_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_GSSAPI_TRUE@am_lmgssutil_la_rpath = -rpath $(pkglibdir) lmnet_la_DEPENDENCIES = am_lmnet_la_OBJECTS = lmnet_la-net.lo lmnet_la-netns_socket.lo lmnet_la_OBJECTS = $(am_lmnet_la_OBJECTS) lmnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmnet_la_LDFLAGS) $(LDFLAGS) -o $@ lmnetstrms_la_DEPENDENCIES = am__lmnetstrms_la_SOURCES_DIST = netstrms.c netstrms.h netstrm.c \ netstrm.h @ENABLE_INET_TRUE@am_lmnetstrms_la_OBJECTS = \ @ENABLE_INET_TRUE@ lmnetstrms_la-netstrms.lo \ @ENABLE_INET_TRUE@ lmnetstrms_la-netstrm.lo lmnetstrms_la_OBJECTS = $(am_lmnetstrms_la_OBJECTS) lmnetstrms_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmnetstrms_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_INET_TRUE@am_lmnetstrms_la_rpath = -rpath $(pkglibdir) @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_DEPENDENCIES = \ @ENABLE_GNUTLS_TRUE@ $(am__DEPENDENCIES_1) am__lmnsd_gtls_la_SOURCES_DIST = nsd_gtls.c nsd_gtls.h @ENABLE_GNUTLS_TRUE@am_lmnsd_gtls_la_OBJECTS = \ @ENABLE_GNUTLS_TRUE@ lmnsd_gtls_la-nsd_gtls.lo lmnsd_gtls_la_OBJECTS = $(am_lmnsd_gtls_la_OBJECTS) lmnsd_gtls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmnsd_gtls_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_GNUTLS_TRUE@am_lmnsd_gtls_la_rpath = -rpath $(pkglibdir) @ENABLE_MBEDTLS_TRUE@lmnsd_mbedtls_la_DEPENDENCIES = \ @ENABLE_MBEDTLS_TRUE@ $(am__DEPENDENCIES_1) am__lmnsd_mbedtls_la_SOURCES_DIST = nsd_mbedtls.c nsd_mbedtls.h @ENABLE_MBEDTLS_TRUE@am_lmnsd_mbedtls_la_OBJECTS = \ @ENABLE_MBEDTLS_TRUE@ lmnsd_mbedtls_la-nsd_mbedtls.lo lmnsd_mbedtls_la_OBJECTS = $(am_lmnsd_mbedtls_la_OBJECTS) lmnsd_mbedtls_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(lmnsd_mbedtls_la_LDFLAGS) $(LDFLAGS) \ -o $@ @ENABLE_MBEDTLS_TRUE@am_lmnsd_mbedtls_la_rpath = -rpath $(pkglibdir) @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_FALSE@lmnsd_ossl_la_DEPENDENCIES = \ @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_FALSE@ $(am__DEPENDENCIES_1) \ @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_FALSE@ $(am__DEPENDENCIES_1) @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_TRUE@lmnsd_ossl_la_DEPENDENCIES = \ @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_TRUE@ $(am__DEPENDENCIES_1) \ @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_TRUE@ $(am__DEPENDENCIES_1) am__lmnsd_ossl_la_SOURCES_DIST = net_ossl.c net_ossl.h \ net_ossl_store.c net_ossl_store.h nsd_ossl.c nsd_ossl.h @ENABLE_OSSL_TRUE@am_lmnsd_ossl_la_OBJECTS = \ @ENABLE_OSSL_TRUE@ lmnsd_ossl_la-net_ossl.lo \ @ENABLE_OSSL_TRUE@ lmnsd_ossl_la-net_ossl_store.lo \ @ENABLE_OSSL_TRUE@ lmnsd_ossl_la-nsd_ossl.lo lmnsd_ossl_la_OBJECTS = $(am_lmnsd_ossl_la_OBJECTS) lmnsd_ossl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmnsd_ossl_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_OSSL_TRUE@am_lmnsd_ossl_la_rpath = -rpath $(pkglibdir) lmnsd_ptcp_la_DEPENDENCIES = am__lmnsd_ptcp_la_SOURCES_DIST = nsd_ptcp.c nsd_ptcp.h @ENABLE_INET_TRUE@am_lmnsd_ptcp_la_OBJECTS = \ @ENABLE_INET_TRUE@ lmnsd_ptcp_la-nsd_ptcp.lo lmnsd_ptcp_la_OBJECTS = $(am_lmnsd_ptcp_la_OBJECTS) lmnsd_ptcp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmnsd_ptcp_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_INET_TRUE@am_lmnsd_ptcp_la_rpath = -rpath $(pkglibdir) lmregexp_la_DEPENDENCIES = am__lmregexp_la_SOURCES_DIST = regexp.c regexp.h @ENABLE_REGEXP_TRUE@am_lmregexp_la_OBJECTS = lmregexp_la-regexp.lo lmregexp_la_OBJECTS = $(am_lmregexp_la_OBJECTS) lmregexp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmregexp_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_REGEXP_TRUE@am_lmregexp_la_rpath = -rpath $(pkglibdir) lmsig_ksi_ls12_la_LIBADD = am__lmsig_ksi_ls12_la_SOURCES_DIST = lmsig_ksi-ls12.c lmsig_ksi-ls12.h \ lib_ksils12.c lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h @ENABLE_KSI_LS12_TRUE@am_lmsig_ksi_ls12_la_OBJECTS = \ @ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo \ @ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lib_ksils12.lo \ @ENABLE_KSI_LS12_TRUE@ lmsig_ksi_ls12_la-lib_ksi_queue.lo lmsig_ksi_ls12_la_OBJECTS = $(am_lmsig_ksi_ls12_la_OBJECTS) lmsig_ksi_ls12_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(lmsig_ksi_ls12_la_LDFLAGS) $(LDFLAGS) \ -o $@ @ENABLE_KSI_LS12_TRUE@am_lmsig_ksi_ls12_la_rpath = -rpath $(pkglibdir) lmtcpclt_la_DEPENDENCIES = am_lmtcpclt_la_OBJECTS = lmtcpclt_la-tcpclt.lo lmtcpclt_la_OBJECTS = $(am_lmtcpclt_la_OBJECTS) lmtcpclt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmtcpclt_la_LDFLAGS) $(LDFLAGS) -o $@ lmtcpsrv_la_DEPENDENCIES = am_lmtcpsrv_la_OBJECTS = lmtcpsrv_la-tcps_sess.lo \ lmtcpsrv_la-tcpsrv.lo lmtcpsrv_la_OBJECTS = $(am_lmtcpsrv_la_OBJECTS) lmtcpsrv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmtcpsrv_la_LDFLAGS) $(LDFLAGS) -o $@ lmzlibw_la_DEPENDENCIES = am_lmzlibw_la_OBJECTS = lmzlibw_la-zlibw.lo lmzlibw_la_OBJECTS = $(am_lmzlibw_la_OBJECTS) lmzlibw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmzlibw_la_LDFLAGS) $(LDFLAGS) -o $@ lmzstdw_la_DEPENDENCIES = am__lmzstdw_la_SOURCES_DIST = zstdw.c zstdw.h @ENABLE_LIBZSTD_TRUE@am_lmzstdw_la_OBJECTS = lmzstdw_la-zstdw.lo lmzstdw_la_OBJECTS = $(am_lmzstdw_la_OBJECTS) lmzstdw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(lmzstdw_la_LDFLAGS) $(LDFLAGS) -o $@ @ENABLE_LIBZSTD_TRUE@am_lmzstdw_la_rpath = -rpath $(pkglibdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/libgcry_la-libcry_common.Plo \ ./$(DEPDIR)/libgcry_la-libgcry.Plo \ ./$(DEPDIR)/libossl_la-libcry_common.Plo \ ./$(DEPDIR)/libossl_la-libossl.Plo \ ./$(DEPDIR)/librsyslog_la-action.Plo \ ./$(DEPDIR)/librsyslog_la-cfsysline.Plo \ ./$(DEPDIR)/librsyslog_la-conf.Plo \ ./$(DEPDIR)/librsyslog_la-datetime.Plo \ ./$(DEPDIR)/librsyslog_la-debug.Plo \ ./$(DEPDIR)/librsyslog_la-dnscache.Plo \ ./$(DEPDIR)/librsyslog_la-dynstats.Plo \ ./$(DEPDIR)/librsyslog_la-errmsg.Plo \ ./$(DEPDIR)/librsyslog_la-glbl.Plo \ ./$(DEPDIR)/librsyslog_la-hashtable.Plo \ ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo \ ./$(DEPDIR)/librsyslog_la-janitor.Plo \ ./$(DEPDIR)/librsyslog_la-linkedlist.Plo \ ./$(DEPDIR)/librsyslog_la-lookup.Plo \ ./$(DEPDIR)/librsyslog_la-modules.Plo \ ./$(DEPDIR)/librsyslog_la-msg.Plo \ ./$(DEPDIR)/librsyslog_la-obj.Plo \ ./$(DEPDIR)/librsyslog_la-objomsr.Plo \ ./$(DEPDIR)/librsyslog_la-operatingstate.Plo \ ./$(DEPDIR)/librsyslog_la-outchannel.Plo \ ./$(DEPDIR)/librsyslog_la-parse.Plo \ ./$(DEPDIR)/librsyslog_la-parser.Plo \ ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo \ ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo \ ./$(DEPDIR)/librsyslog_la-prop.Plo \ ./$(DEPDIR)/librsyslog_la-queue.Plo \ ./$(DEPDIR)/librsyslog_la-queue_da.Plo \ ./$(DEPDIR)/librsyslog_la-ratelimit.Plo \ ./$(DEPDIR)/librsyslog_la-rsconf.Plo \ ./$(DEPDIR)/librsyslog_la-rswatch.Plo \ ./$(DEPDIR)/librsyslog_la-rsyslog.Plo \ ./$(DEPDIR)/librsyslog_la-ruleset.Plo \ ./$(DEPDIR)/librsyslog_la-segdisk_codec.Plo \ ./$(DEPDIR)/librsyslog_la-segdisk_crc.Plo \ ./$(DEPDIR)/librsyslog_la-segdisk_state.Plo \ ./$(DEPDIR)/librsyslog_la-segdisk_store.Plo \ ./$(DEPDIR)/librsyslog_la-srutils.Plo \ ./$(DEPDIR)/librsyslog_la-statsobj.Plo \ ./$(DEPDIR)/librsyslog_la-stream.Plo \ ./$(DEPDIR)/librsyslog_la-strgen.Plo \ ./$(DEPDIR)/librsyslog_la-stringbuf.Plo \ ./$(DEPDIR)/librsyslog_la-template.Plo \ ./$(DEPDIR)/librsyslog_la-threads.Plo \ ./$(DEPDIR)/librsyslog_la-timezones.Plo \ ./$(DEPDIR)/librsyslog_la-translate.Plo \ ./$(DEPDIR)/librsyslog_la-var.Plo \ ./$(DEPDIR)/librsyslog_la-wti.Plo \ ./$(DEPDIR)/librsyslog_la-wtp.Plo \ ./$(DEPDIR)/librsyslog_la-yamlconf.Plo \ ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo \ ./$(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Plo \ ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo \ ./$(DEPDIR)/lmnet_la-net.Plo \ ./$(DEPDIR)/lmnet_la-netns_socket.Plo \ ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo \ ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo \ ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo \ ./$(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Plo \ ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo \ ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo \ ./$(DEPDIR)/lmregexp_la-regexp.Plo \ ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo \ ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo \ ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo \ ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo \ ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo \ ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo \ ./$(DEPDIR)/lmzlibw_la-zlibw.Plo \ ./$(DEPDIR)/lmzstdw_la-zstdw.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libgcry_la_SOURCES) $(libossl_la_SOURCES) \ $(librsyslog_la_SOURCES) $(lmcry_gcry_la_SOURCES) \ $(lmcry_ossl_la_SOURCES) $(lmgssutil_la_SOURCES) \ $(lmnet_la_SOURCES) $(lmnetstrms_la_SOURCES) \ $(lmnsd_gtls_la_SOURCES) $(lmnsd_mbedtls_la_SOURCES) \ $(lmnsd_ossl_la_SOURCES) $(lmnsd_ptcp_la_SOURCES) \ $(lmregexp_la_SOURCES) $(lmsig_ksi_ls12_la_SOURCES) \ $(lmtcpclt_la_SOURCES) $(lmtcpsrv_la_SOURCES) \ $(lmzlibw_la_SOURCES) $(lmzstdw_la_SOURCES) DIST_SOURCES = $(am__libgcry_la_SOURCES_DIST) \ $(am__libossl_la_SOURCES_DIST) $(librsyslog_la_SOURCES) \ $(am__lmcry_gcry_la_SOURCES_DIST) \ $(am__lmcry_ossl_la_SOURCES_DIST) \ $(am__lmgssutil_la_SOURCES_DIST) $(lmnet_la_SOURCES) \ $(am__lmnetstrms_la_SOURCES_DIST) \ $(am__lmnsd_gtls_la_SOURCES_DIST) \ $(am__lmnsd_mbedtls_la_SOURCES_DIST) \ $(am__lmnsd_ossl_la_SOURCES_DIST) \ $(am__lmnsd_ptcp_la_SOURCES_DIST) \ $(am__lmregexp_la_SOURCES_DIST) \ $(am__lmsig_ksi_ls12_la_SOURCES_DIST) $(lmtcpclt_la_SOURCES) \ $(lmtcpsrv_la_SOURCES) $(lmzlibw_la_SOURCES) \ $(am__lmzstdw_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 am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ man_MANS = noinst_LIBRARIES = noinst_LTLIBRARIES = librsyslog.la $(am__append_18) $(am__append_20) # # zlib support # # # basic network support, needed for rsyslog startup (e.g. our own system name) # pkglib_LTLIBRARIES = $(am__append_3) lmzlibw.la lmnet.la \ $(am__append_8) $(am__append_15) $(am__append_16) \ $(am__append_17) $(am__append_19) $(am__append_21) \ $(am__append_22) $(am__append_23) lmtcpsrv.la lmtcpclt.la \ $(am__append_30) #pkglib_LTLIBRARIES = librsyslog.la librsyslog_la_SOURCES = \ rsyslog.c \ rsyslog.h \ typedefs.h \ dnscache.c \ dnscache.h \ unicode-helper.h \ atomic.h \ batch.h \ syslogd-types.h \ module-template.h \ im-helper.h \ obj-types.h \ sigprov.h \ cryprov.h \ nsd.h \ glbl.h \ glbl.c \ unlimited_select.h \ conf.c \ conf.h \ janitor.c \ janitor.h \ rsconf.c \ rsconf.h \ parser.h \ parser.c \ strgen.h \ strgen.c \ msg.c \ msg.h \ msg_replace_helper.h \ linkedlist.c \ linkedlist.h \ objomsr.c \ objomsr.h \ stringbuf.c \ stringbuf.h \ datetime.c \ datetime.h \ srutils.c \ srUtils.h \ errmsg.c \ errmsg.h \ operatingstate.c \ operatingstate.h \ debug.c \ debug.h \ obj.c \ obj.h \ modules.c \ modules.h \ statsobj.c \ statsobj.h \ compat_queue.h \ dynstats.c \ dynstats.h \ perctile_ringbuf.c \ perctile_ringbuf.h \ perctile_stats.c \ perctile_stats.h \ statsobj.h \ stream.c \ stream.h \ var.c \ var.h \ wtp.c \ wtp.h \ wti.c \ wti.h \ queue.c \ queue.h \ queue_da.c \ queue_da.h \ segdisk_codec.c \ segdisk_codec.h \ segdisk_crc.c \ segdisk_crc.h \ segdisk_format.h \ segdisk_state.c \ segdisk_state.h \ segdisk_store.c \ segdisk_store.h \ ruleset.c \ ruleset.h \ rswatch.c \ rswatch.h \ prop.c \ prop.h \ ratelimit.c \ ratelimit.h \ translate.c \ translate.h \ yamlconf.c \ yamlconf.h \ lookup.c \ lookup.h \ cfsysline.c \ cfsysline.h \ \ action.h \ action.c \ threads.c \ threads.h \ dirty.h \ \ parse.c \ parse.h \ \ hashtable.c \ hashtable.h \ hashtable_itr.c \ hashtable_itr.h \ hashtable_private.h \ \ outchannel.c \ outchannel.h \ template.c \ template.h \ timezones.c \ timezones.h #librsyslog_la_LDFLAGS = -module -avoid-version @WITH_MODDIRS_FALSE@librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS \ @WITH_MODDIRS_FALSE@ -D_PATH_MODDIR=\"$(pkglibdir)/\" \ @WITH_MODDIRS_FALSE@ -I\$(top_srcdir) -I\$(top_srcdir)/grammar \ @WITH_MODDIRS_FALSE@ -I\$(top_builddir)/grammar \ @WITH_MODDIRS_FALSE@ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ @WITH_MODDIRS_FALSE@ $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) \ @WITH_MODDIRS_FALSE@ ${LIBESTR_CFLAGS} $(LIBYAML_CFLAGS) \ @WITH_MODDIRS_FALSE@ $(am__append_1) -I\$(top_srcdir)/tools #if OS_LINUX #librsyslog_la_SOURCES += \ #endif #librsyslog_la_LDFLAGS = -module -avoid-version @WITH_MODDIRS_TRUE@librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS \ @WITH_MODDIRS_TRUE@ -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\" \ @WITH_MODDIRS_TRUE@ $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ @WITH_MODDIRS_TRUE@ $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) \ @WITH_MODDIRS_TRUE@ ${LIBESTR_CFLAGS} $(LIBYAML_CFLAGS) \ @WITH_MODDIRS_TRUE@ $(am__append_1) -I\$(top_srcdir)/tools librsyslog_la_LIBADD = $(DL_LIBS) $(RT_LIBS) $(LIBUUID_LIBS) \ $(LIBFASTJSON_LIBS) ${LIBESTR_LIBS} $(LIBYAML_LIBS) -lm \ $(am__append_2) @ENABLE_REGEXP_TRUE@lmregexp_la_SOURCES = regexp.c regexp.h @ENABLE_REGEXP_TRUE@lmregexp_la_CPPFLAGS = $(PTHREADS_CFLAGS) \ @ENABLE_REGEXP_TRUE@ $(RSRT_CFLAGS) $(am__append_4) @ENABLE_REGEXP_TRUE@lmregexp_la_LDFLAGS = -module -avoid-version \ @ENABLE_REGEXP_TRUE@ $(am__append_5) @ENABLE_REGEXP_TRUE@lmregexp_la_LIBADD = lmzlibw_la_SOURCES = zlibw.c zlibw.h lmzlibw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ $(am__append_6) lmzlibw_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS) \ $(am__append_7) lmzlibw_la_LIBADD = lmnet_la_SOURCES = net.c net.h netns_socket.c netns_socket.h lmnet_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(am__append_9) lmnet_la_LDFLAGS = -module -avoid-version \ ../compat/compat_la-getifaddrs.lo $(am__append_10) lmnet_la_LIBADD = # network stream master class and stream factory @ENABLE_INET_TRUE@lmnetstrms_la_SOURCES = netstrms.c netstrms.h \ @ENABLE_INET_TRUE@ netstrm.c netstrm.h @ENABLE_INET_TRUE@lmnetstrms_la_CPPFLAGS = $(PTHREADS_CFLAGS) \ @ENABLE_INET_TRUE@ $(RSRT_CFLAGS) $(am__append_11) @ENABLE_INET_TRUE@lmnetstrms_la_LDFLAGS = -module -avoid-version \ @ENABLE_INET_TRUE@ $(am__append_12) @ENABLE_INET_TRUE@lmnetstrms_la_LIBADD = @ENABLE_INET_TRUE@lmnsd_ptcp_la_SOURCES = nsd_ptcp.c nsd_ptcp.h @ENABLE_INET_TRUE@lmnsd_ptcp_la_CPPFLAGS = $(PTHREADS_CFLAGS) \ @ENABLE_INET_TRUE@ $(RSRT_CFLAGS) $(am__append_13) @ENABLE_INET_TRUE@lmnsd_ptcp_la_LDFLAGS = -module -avoid-version \ @ENABLE_INET_TRUE@ $(am__append_14) @ENABLE_INET_TRUE@lmnsd_ptcp_la_LIBADD = @ENABLE_OSSL_TRUE@lmnsd_ossl_la_SOURCES = net_ossl.c net_ossl.h net_ossl_store.c net_ossl_store.h nsd_ossl.c nsd_ossl.h @ENABLE_OSSL_TRUE@lmnsd_ossl_la_LDFLAGS = -module -avoid-version @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_FALSE@lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_TRUE@lmnsd_ossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(WOLFSSL_CFLAGS) @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_FALSE@lmnsd_ossl_la_LIBADD = $(OPENSSL_LIBS) $(GAI_LIBS) @ENABLE_OSSL_TRUE@@ENABLE_WOLFSSL_TRUE@lmnsd_ossl_la_LIBADD = $(WOLFSSL_LIBS) $(GAI_LIBS) @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_SOURCES = nsd_gtls.c nsd_gtls.h @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GNUTLS_CFLAGS) @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_LDFLAGS = -module -avoid-version @ENABLE_GNUTLS_TRUE@lmnsd_gtls_la_LIBADD = $(GNUTLS_LIBS) @ENABLE_MBEDTLS_TRUE@lmnsd_mbedtls_la_SOURCES = nsd_mbedtls.c nsd_mbedtls.h @ENABLE_MBEDTLS_TRUE@lmnsd_mbedtls_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(MBEDTLS_CFLAGS) @ENABLE_MBEDTLS_TRUE@lmnsd_mbedtls_la_LDFLAGS = -module -avoid-version @ENABLE_MBEDTLS_TRUE@lmnsd_mbedtls_la_LIBADD = $(MBEDTLS_LIBS) @ENABLE_LIBGCRYPT_TRUE@libgcry_la_SOURCES = libgcry.c libcry_common.c libcry_common.h libgcry.h @ENABLE_LIBGCRYPT_TRUE@libgcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS) @ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_DEPENDENCIES = libgcry.la @ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_SOURCES = lmcry_gcry.c lmcry_gcry.h @ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_CPPFLAGS = $(RSRT_CFLAGS) $(LIBGCRYPT_CFLAGS) @ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_LDFLAGS = -module -avoid-version @ENABLE_LIBGCRYPT_TRUE@lmcry_gcry_la_LIBADD = libgcry.la $(LIBGCRYPT_LIBS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@libossl_la_SOURCES = libossl.c libossl.h libcry_common.c libcry_common.h @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@libossl_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(OPENSSL_CFLAGS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@lmcry_ossl_la_DEPENDENCIES = libossl.la @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@lmcry_ossl_la_SOURCES = lmcry_ossl.c lmcry_ossl.h @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@lmcry_ossl_la_CPPFLAGS = $(RSRT_CFLAGS) $(OPENSSL_FLAGS) @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@lmcry_ossl_la_LDFLAGS = -module -avoid-version @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@lmcry_ossl_la_LIBADD = libossl.la $(OPENSSL_LIBS) @ENABLE_LIBZSTD_TRUE@lmzstdw_la_SOURCES = zstdw.c zstdw.h @ENABLE_LIBZSTD_TRUE@lmzstdw_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) @ENABLE_LIBZSTD_TRUE@lmzstdw_la_LDFLAGS = -module -avoid-version $(ZSTD_LIBS) @ENABLE_LIBZSTD_TRUE@lmzstdw_la_LIBADD = -lzstd @ENABLE_GSSAPI_TRUE@lmgssutil_la_SOURCES = gss-misc.c gss-misc.h gss-token-util.h @ENABLE_GSSAPI_TRUE@lmgssutil_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(GSS_CFLAGS) @ENABLE_GSSAPI_TRUE@lmgssutil_la_LDFLAGS = -module -avoid-version @ENABLE_GSSAPI_TRUE@lmgssutil_la_LIBADD = $(GSS_LIBS) # # # TCP (stream) server support # lmtcpsrv_la_SOURCES = \ tcps_sess.c \ tcps_sess.h \ tcpsrv.c \ tcpsrv.h lmtcpsrv_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ $(am__append_24) $(am__append_26) lmtcpsrv_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS) \ $(am__append_25) $(am__append_27) lmtcpsrv_la_LIBADD = # # TCP (stream) client support # lmtcpclt_la_SOURCES = \ tcpclt.c \ tcpclt.h lmtcpclt_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ $(am__append_28) lmtcpclt_la_LDFLAGS = -module -avoid-version $(am__append_29) lmtcpclt_la_LIBADD = @ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_SOURCES = lmsig_ksi-ls12.c lmsig_ksi-ls12.h lib_ksils12.c \ @ENABLE_KSI_LS12_TRUE@ lib_ksils12.h lib_ksi_queue.c lib_ksi_queue.h @ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_CPPFLAGS = $(RSRT_CFLAGS) $(GT_KSI_LS12_CFLAGS) @ENABLE_KSI_LS12_TRUE@lmsig_ksi_ls12_la_LDFLAGS = -module -avoid-version $(GT_KSI_LS12_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 runtime/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu runtime/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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 clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } libgcry.la: $(libgcry_la_OBJECTS) $(libgcry_la_DEPENDENCIES) $(EXTRA_libgcry_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libgcry_la_rpath) $(libgcry_la_OBJECTS) $(libgcry_la_LIBADD) $(LIBS) libossl.la: $(libossl_la_OBJECTS) $(libossl_la_DEPENDENCIES) $(EXTRA_libossl_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libossl_la_rpath) $(libossl_la_OBJECTS) $(libossl_la_LIBADD) $(LIBS) librsyslog.la: $(librsyslog_la_OBJECTS) $(librsyslog_la_DEPENDENCIES) $(EXTRA_librsyslog_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(librsyslog_la_OBJECTS) $(librsyslog_la_LIBADD) $(LIBS) lmcry_gcry.la: $(lmcry_gcry_la_OBJECTS) $(lmcry_gcry_la_DEPENDENCIES) $(EXTRA_lmcry_gcry_la_DEPENDENCIES) $(AM_V_CCLD)$(lmcry_gcry_la_LINK) $(am_lmcry_gcry_la_rpath) $(lmcry_gcry_la_OBJECTS) $(lmcry_gcry_la_LIBADD) $(LIBS) lmcry_ossl.la: $(lmcry_ossl_la_OBJECTS) $(lmcry_ossl_la_DEPENDENCIES) $(EXTRA_lmcry_ossl_la_DEPENDENCIES) $(AM_V_CCLD)$(lmcry_ossl_la_LINK) $(am_lmcry_ossl_la_rpath) $(lmcry_ossl_la_OBJECTS) $(lmcry_ossl_la_LIBADD) $(LIBS) lmgssutil.la: $(lmgssutil_la_OBJECTS) $(lmgssutil_la_DEPENDENCIES) $(EXTRA_lmgssutil_la_DEPENDENCIES) $(AM_V_CCLD)$(lmgssutil_la_LINK) $(am_lmgssutil_la_rpath) $(lmgssutil_la_OBJECTS) $(lmgssutil_la_LIBADD) $(LIBS) lmnet.la: $(lmnet_la_OBJECTS) $(lmnet_la_DEPENDENCIES) $(EXTRA_lmnet_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnet_la_LINK) -rpath $(pkglibdir) $(lmnet_la_OBJECTS) $(lmnet_la_LIBADD) $(LIBS) lmnetstrms.la: $(lmnetstrms_la_OBJECTS) $(lmnetstrms_la_DEPENDENCIES) $(EXTRA_lmnetstrms_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnetstrms_la_LINK) $(am_lmnetstrms_la_rpath) $(lmnetstrms_la_OBJECTS) $(lmnetstrms_la_LIBADD) $(LIBS) lmnsd_gtls.la: $(lmnsd_gtls_la_OBJECTS) $(lmnsd_gtls_la_DEPENDENCIES) $(EXTRA_lmnsd_gtls_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnsd_gtls_la_LINK) $(am_lmnsd_gtls_la_rpath) $(lmnsd_gtls_la_OBJECTS) $(lmnsd_gtls_la_LIBADD) $(LIBS) lmnsd_mbedtls.la: $(lmnsd_mbedtls_la_OBJECTS) $(lmnsd_mbedtls_la_DEPENDENCIES) $(EXTRA_lmnsd_mbedtls_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnsd_mbedtls_la_LINK) $(am_lmnsd_mbedtls_la_rpath) $(lmnsd_mbedtls_la_OBJECTS) $(lmnsd_mbedtls_la_LIBADD) $(LIBS) lmnsd_ossl.la: $(lmnsd_ossl_la_OBJECTS) $(lmnsd_ossl_la_DEPENDENCIES) $(EXTRA_lmnsd_ossl_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnsd_ossl_la_LINK) $(am_lmnsd_ossl_la_rpath) $(lmnsd_ossl_la_OBJECTS) $(lmnsd_ossl_la_LIBADD) $(LIBS) lmnsd_ptcp.la: $(lmnsd_ptcp_la_OBJECTS) $(lmnsd_ptcp_la_DEPENDENCIES) $(EXTRA_lmnsd_ptcp_la_DEPENDENCIES) $(AM_V_CCLD)$(lmnsd_ptcp_la_LINK) $(am_lmnsd_ptcp_la_rpath) $(lmnsd_ptcp_la_OBJECTS) $(lmnsd_ptcp_la_LIBADD) $(LIBS) lmregexp.la: $(lmregexp_la_OBJECTS) $(lmregexp_la_DEPENDENCIES) $(EXTRA_lmregexp_la_DEPENDENCIES) $(AM_V_CCLD)$(lmregexp_la_LINK) $(am_lmregexp_la_rpath) $(lmregexp_la_OBJECTS) $(lmregexp_la_LIBADD) $(LIBS) lmsig_ksi_ls12.la: $(lmsig_ksi_ls12_la_OBJECTS) $(lmsig_ksi_ls12_la_DEPENDENCIES) $(EXTRA_lmsig_ksi_ls12_la_DEPENDENCIES) $(AM_V_CCLD)$(lmsig_ksi_ls12_la_LINK) $(am_lmsig_ksi_ls12_la_rpath) $(lmsig_ksi_ls12_la_OBJECTS) $(lmsig_ksi_ls12_la_LIBADD) $(LIBS) lmtcpclt.la: $(lmtcpclt_la_OBJECTS) $(lmtcpclt_la_DEPENDENCIES) $(EXTRA_lmtcpclt_la_DEPENDENCIES) $(AM_V_CCLD)$(lmtcpclt_la_LINK) -rpath $(pkglibdir) $(lmtcpclt_la_OBJECTS) $(lmtcpclt_la_LIBADD) $(LIBS) lmtcpsrv.la: $(lmtcpsrv_la_OBJECTS) $(lmtcpsrv_la_DEPENDENCIES) $(EXTRA_lmtcpsrv_la_DEPENDENCIES) $(AM_V_CCLD)$(lmtcpsrv_la_LINK) -rpath $(pkglibdir) $(lmtcpsrv_la_OBJECTS) $(lmtcpsrv_la_LIBADD) $(LIBS) lmzlibw.la: $(lmzlibw_la_OBJECTS) $(lmzlibw_la_DEPENDENCIES) $(EXTRA_lmzlibw_la_DEPENDENCIES) $(AM_V_CCLD)$(lmzlibw_la_LINK) -rpath $(pkglibdir) $(lmzlibw_la_OBJECTS) $(lmzlibw_la_LIBADD) $(LIBS) lmzstdw.la: $(lmzstdw_la_OBJECTS) $(lmzstdw_la_DEPENDENCIES) $(EXTRA_lmzstdw_la_DEPENDENCIES) $(AM_V_CCLD)$(lmzstdw_la_LINK) $(am_lmzstdw_la_rpath) $(lmzstdw_la_OBJECTS) $(lmzstdw_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcry_la-libcry_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgcry_la-libgcry.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libossl_la-libcry_common.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libossl_la-libossl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-action.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-cfsysline.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-conf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-datetime.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-debug.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-dnscache.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-dynstats.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-errmsg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-glbl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-janitor.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-linkedlist.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-lookup.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-modules.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-msg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-obj.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-objomsr.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-operatingstate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-outchannel.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-parse.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-perctile_stats.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-prop.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-queue_da.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-ratelimit.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-rsconf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-rswatch.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-rsyslog.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-ruleset.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-segdisk_codec.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-segdisk_crc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-segdisk_state.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-segdisk_store.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-srutils.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-statsobj.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-stream.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-strgen.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-stringbuf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-template.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-threads.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-timezones.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-translate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-var.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-wti.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-wtp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/librsyslog_la-yamlconf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmgssutil_la-gss-misc.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnet_la-net.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnet_la-netns_socket.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-netstrm.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnetstrms_la-netstrms.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmregexp_la-regexp.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmzlibw_la-zlibw.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lmzstdw_la-zstdw.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< libgcry_la-libgcry.lo: libgcry.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgcry_la-libgcry.lo -MD -MP -MF $(DEPDIR)/libgcry_la-libgcry.Tpo -c -o libgcry_la-libgcry.lo `test -f 'libgcry.c' || echo '$(srcdir)/'`libgcry.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgcry_la-libgcry.Tpo $(DEPDIR)/libgcry_la-libgcry.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libgcry.c' object='libgcry_la-libgcry.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgcry_la-libgcry.lo `test -f 'libgcry.c' || echo '$(srcdir)/'`libgcry.c libgcry_la-libcry_common.lo: libcry_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libgcry_la-libcry_common.lo -MD -MP -MF $(DEPDIR)/libgcry_la-libcry_common.Tpo -c -o libgcry_la-libcry_common.lo `test -f 'libcry_common.c' || echo '$(srcdir)/'`libcry_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgcry_la-libcry_common.Tpo $(DEPDIR)/libgcry_la-libcry_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcry_common.c' object='libgcry_la-libcry_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libgcry_la-libcry_common.lo `test -f 'libcry_common.c' || echo '$(srcdir)/'`libcry_common.c libossl_la-libossl.lo: libossl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libossl_la-libossl.lo -MD -MP -MF $(DEPDIR)/libossl_la-libossl.Tpo -c -o libossl_la-libossl.lo `test -f 'libossl.c' || echo '$(srcdir)/'`libossl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libossl_la-libossl.Tpo $(DEPDIR)/libossl_la-libossl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libossl.c' object='libossl_la-libossl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libossl_la-libossl.lo `test -f 'libossl.c' || echo '$(srcdir)/'`libossl.c libossl_la-libcry_common.lo: libcry_common.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libossl_la-libcry_common.lo -MD -MP -MF $(DEPDIR)/libossl_la-libcry_common.Tpo -c -o libossl_la-libcry_common.lo `test -f 'libcry_common.c' || echo '$(srcdir)/'`libcry_common.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libossl_la-libcry_common.Tpo $(DEPDIR)/libossl_la-libcry_common.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libcry_common.c' object='libossl_la-libcry_common.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libossl_la-libcry_common.lo `test -f 'libcry_common.c' || echo '$(srcdir)/'`libcry_common.c librsyslog_la-rsyslog.lo: rsyslog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-rsyslog.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-rsyslog.Tpo -c -o librsyslog_la-rsyslog.lo `test -f 'rsyslog.c' || echo '$(srcdir)/'`rsyslog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-rsyslog.Tpo $(DEPDIR)/librsyslog_la-rsyslog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsyslog.c' object='librsyslog_la-rsyslog.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-rsyslog.lo `test -f 'rsyslog.c' || echo '$(srcdir)/'`rsyslog.c librsyslog_la-dnscache.lo: dnscache.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-dnscache.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-dnscache.Tpo -c -o librsyslog_la-dnscache.lo `test -f 'dnscache.c' || echo '$(srcdir)/'`dnscache.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-dnscache.Tpo $(DEPDIR)/librsyslog_la-dnscache.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dnscache.c' object='librsyslog_la-dnscache.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-dnscache.lo `test -f 'dnscache.c' || echo '$(srcdir)/'`dnscache.c librsyslog_la-glbl.lo: glbl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-glbl.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-glbl.Tpo -c -o librsyslog_la-glbl.lo `test -f 'glbl.c' || echo '$(srcdir)/'`glbl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-glbl.Tpo $(DEPDIR)/librsyslog_la-glbl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='glbl.c' object='librsyslog_la-glbl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-glbl.lo `test -f 'glbl.c' || echo '$(srcdir)/'`glbl.c librsyslog_la-conf.lo: conf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-conf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-conf.Tpo -c -o librsyslog_la-conf.lo `test -f 'conf.c' || echo '$(srcdir)/'`conf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-conf.Tpo $(DEPDIR)/librsyslog_la-conf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='conf.c' object='librsyslog_la-conf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-conf.lo `test -f 'conf.c' || echo '$(srcdir)/'`conf.c librsyslog_la-janitor.lo: janitor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-janitor.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-janitor.Tpo -c -o librsyslog_la-janitor.lo `test -f 'janitor.c' || echo '$(srcdir)/'`janitor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-janitor.Tpo $(DEPDIR)/librsyslog_la-janitor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='janitor.c' object='librsyslog_la-janitor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-janitor.lo `test -f 'janitor.c' || echo '$(srcdir)/'`janitor.c librsyslog_la-rsconf.lo: rsconf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-rsconf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-rsconf.Tpo -c -o librsyslog_la-rsconf.lo `test -f 'rsconf.c' || echo '$(srcdir)/'`rsconf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-rsconf.Tpo $(DEPDIR)/librsyslog_la-rsconf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rsconf.c' object='librsyslog_la-rsconf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-rsconf.lo `test -f 'rsconf.c' || echo '$(srcdir)/'`rsconf.c librsyslog_la-parser.lo: parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-parser.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-parser.Tpo -c -o librsyslog_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-parser.Tpo $(DEPDIR)/librsyslog_la-parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parser.c' object='librsyslog_la-parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-parser.lo `test -f 'parser.c' || echo '$(srcdir)/'`parser.c librsyslog_la-strgen.lo: strgen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-strgen.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-strgen.Tpo -c -o librsyslog_la-strgen.lo `test -f 'strgen.c' || echo '$(srcdir)/'`strgen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-strgen.Tpo $(DEPDIR)/librsyslog_la-strgen.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strgen.c' object='librsyslog_la-strgen.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-strgen.lo `test -f 'strgen.c' || echo '$(srcdir)/'`strgen.c librsyslog_la-msg.lo: msg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-msg.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-msg.Tpo -c -o librsyslog_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-msg.Tpo $(DEPDIR)/librsyslog_la-msg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msg.c' object='librsyslog_la-msg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c librsyslog_la-linkedlist.lo: linkedlist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-linkedlist.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-linkedlist.Tpo -c -o librsyslog_la-linkedlist.lo `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-linkedlist.Tpo $(DEPDIR)/librsyslog_la-linkedlist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linkedlist.c' object='librsyslog_la-linkedlist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-linkedlist.lo `test -f 'linkedlist.c' || echo '$(srcdir)/'`linkedlist.c librsyslog_la-objomsr.lo: objomsr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-objomsr.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-objomsr.Tpo -c -o librsyslog_la-objomsr.lo `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-objomsr.Tpo $(DEPDIR)/librsyslog_la-objomsr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='objomsr.c' object='librsyslog_la-objomsr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-objomsr.lo `test -f 'objomsr.c' || echo '$(srcdir)/'`objomsr.c librsyslog_la-stringbuf.lo: stringbuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-stringbuf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-stringbuf.Tpo -c -o librsyslog_la-stringbuf.lo `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-stringbuf.Tpo $(DEPDIR)/librsyslog_la-stringbuf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stringbuf.c' object='librsyslog_la-stringbuf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-stringbuf.lo `test -f 'stringbuf.c' || echo '$(srcdir)/'`stringbuf.c librsyslog_la-datetime.lo: datetime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-datetime.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-datetime.Tpo -c -o librsyslog_la-datetime.lo `test -f 'datetime.c' || echo '$(srcdir)/'`datetime.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-datetime.Tpo $(DEPDIR)/librsyslog_la-datetime.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='datetime.c' object='librsyslog_la-datetime.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-datetime.lo `test -f 'datetime.c' || echo '$(srcdir)/'`datetime.c librsyslog_la-srutils.lo: srutils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-srutils.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-srutils.Tpo -c -o librsyslog_la-srutils.lo `test -f 'srutils.c' || echo '$(srcdir)/'`srutils.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-srutils.Tpo $(DEPDIR)/librsyslog_la-srutils.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='srutils.c' object='librsyslog_la-srutils.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-srutils.lo `test -f 'srutils.c' || echo '$(srcdir)/'`srutils.c librsyslog_la-errmsg.lo: errmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-errmsg.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-errmsg.Tpo -c -o librsyslog_la-errmsg.lo `test -f 'errmsg.c' || echo '$(srcdir)/'`errmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-errmsg.Tpo $(DEPDIR)/librsyslog_la-errmsg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='errmsg.c' object='librsyslog_la-errmsg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-errmsg.lo `test -f 'errmsg.c' || echo '$(srcdir)/'`errmsg.c librsyslog_la-operatingstate.lo: operatingstate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-operatingstate.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-operatingstate.Tpo -c -o librsyslog_la-operatingstate.lo `test -f 'operatingstate.c' || echo '$(srcdir)/'`operatingstate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-operatingstate.Tpo $(DEPDIR)/librsyslog_la-operatingstate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='operatingstate.c' object='librsyslog_la-operatingstate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-operatingstate.lo `test -f 'operatingstate.c' || echo '$(srcdir)/'`operatingstate.c librsyslog_la-debug.lo: debug.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-debug.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-debug.Tpo -c -o librsyslog_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-debug.Tpo $(DEPDIR)/librsyslog_la-debug.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='debug.c' object='librsyslog_la-debug.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-debug.lo `test -f 'debug.c' || echo '$(srcdir)/'`debug.c librsyslog_la-obj.lo: obj.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-obj.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-obj.Tpo -c -o librsyslog_la-obj.lo `test -f 'obj.c' || echo '$(srcdir)/'`obj.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-obj.Tpo $(DEPDIR)/librsyslog_la-obj.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='obj.c' object='librsyslog_la-obj.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-obj.lo `test -f 'obj.c' || echo '$(srcdir)/'`obj.c librsyslog_la-modules.lo: modules.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-modules.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-modules.Tpo -c -o librsyslog_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-modules.Tpo $(DEPDIR)/librsyslog_la-modules.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='modules.c' object='librsyslog_la-modules.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c librsyslog_la-statsobj.lo: statsobj.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-statsobj.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-statsobj.Tpo -c -o librsyslog_la-statsobj.lo `test -f 'statsobj.c' || echo '$(srcdir)/'`statsobj.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-statsobj.Tpo $(DEPDIR)/librsyslog_la-statsobj.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='statsobj.c' object='librsyslog_la-statsobj.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-statsobj.lo `test -f 'statsobj.c' || echo '$(srcdir)/'`statsobj.c librsyslog_la-dynstats.lo: dynstats.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-dynstats.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-dynstats.Tpo -c -o librsyslog_la-dynstats.lo `test -f 'dynstats.c' || echo '$(srcdir)/'`dynstats.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-dynstats.Tpo $(DEPDIR)/librsyslog_la-dynstats.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dynstats.c' object='librsyslog_la-dynstats.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-dynstats.lo `test -f 'dynstats.c' || echo '$(srcdir)/'`dynstats.c librsyslog_la-perctile_ringbuf.lo: perctile_ringbuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-perctile_ringbuf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-perctile_ringbuf.Tpo -c -o librsyslog_la-perctile_ringbuf.lo `test -f 'perctile_ringbuf.c' || echo '$(srcdir)/'`perctile_ringbuf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-perctile_ringbuf.Tpo $(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='perctile_ringbuf.c' object='librsyslog_la-perctile_ringbuf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-perctile_ringbuf.lo `test -f 'perctile_ringbuf.c' || echo '$(srcdir)/'`perctile_ringbuf.c librsyslog_la-perctile_stats.lo: perctile_stats.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-perctile_stats.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-perctile_stats.Tpo -c -o librsyslog_la-perctile_stats.lo `test -f 'perctile_stats.c' || echo '$(srcdir)/'`perctile_stats.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-perctile_stats.Tpo $(DEPDIR)/librsyslog_la-perctile_stats.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='perctile_stats.c' object='librsyslog_la-perctile_stats.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-perctile_stats.lo `test -f 'perctile_stats.c' || echo '$(srcdir)/'`perctile_stats.c librsyslog_la-stream.lo: stream.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-stream.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-stream.Tpo -c -o librsyslog_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-stream.Tpo $(DEPDIR)/librsyslog_la-stream.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='stream.c' object='librsyslog_la-stream.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c librsyslog_la-var.lo: var.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-var.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-var.Tpo -c -o librsyslog_la-var.lo `test -f 'var.c' || echo '$(srcdir)/'`var.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-var.Tpo $(DEPDIR)/librsyslog_la-var.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='var.c' object='librsyslog_la-var.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-var.lo `test -f 'var.c' || echo '$(srcdir)/'`var.c librsyslog_la-wtp.lo: wtp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-wtp.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-wtp.Tpo -c -o librsyslog_la-wtp.lo `test -f 'wtp.c' || echo '$(srcdir)/'`wtp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-wtp.Tpo $(DEPDIR)/librsyslog_la-wtp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wtp.c' object='librsyslog_la-wtp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-wtp.lo `test -f 'wtp.c' || echo '$(srcdir)/'`wtp.c librsyslog_la-wti.lo: wti.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-wti.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-wti.Tpo -c -o librsyslog_la-wti.lo `test -f 'wti.c' || echo '$(srcdir)/'`wti.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-wti.Tpo $(DEPDIR)/librsyslog_la-wti.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wti.c' object='librsyslog_la-wti.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-wti.lo `test -f 'wti.c' || echo '$(srcdir)/'`wti.c librsyslog_la-queue.lo: queue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-queue.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-queue.Tpo -c -o librsyslog_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-queue.Tpo $(DEPDIR)/librsyslog_la-queue.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue.c' object='librsyslog_la-queue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-queue.lo `test -f 'queue.c' || echo '$(srcdir)/'`queue.c librsyslog_la-queue_da.lo: queue_da.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-queue_da.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-queue_da.Tpo -c -o librsyslog_la-queue_da.lo `test -f 'queue_da.c' || echo '$(srcdir)/'`queue_da.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-queue_da.Tpo $(DEPDIR)/librsyslog_la-queue_da.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='queue_da.c' object='librsyslog_la-queue_da.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-queue_da.lo `test -f 'queue_da.c' || echo '$(srcdir)/'`queue_da.c librsyslog_la-segdisk_codec.lo: segdisk_codec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-segdisk_codec.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-segdisk_codec.Tpo -c -o librsyslog_la-segdisk_codec.lo `test -f 'segdisk_codec.c' || echo '$(srcdir)/'`segdisk_codec.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-segdisk_codec.Tpo $(DEPDIR)/librsyslog_la-segdisk_codec.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='segdisk_codec.c' object='librsyslog_la-segdisk_codec.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-segdisk_codec.lo `test -f 'segdisk_codec.c' || echo '$(srcdir)/'`segdisk_codec.c librsyslog_la-segdisk_crc.lo: segdisk_crc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-segdisk_crc.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-segdisk_crc.Tpo -c -o librsyslog_la-segdisk_crc.lo `test -f 'segdisk_crc.c' || echo '$(srcdir)/'`segdisk_crc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-segdisk_crc.Tpo $(DEPDIR)/librsyslog_la-segdisk_crc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='segdisk_crc.c' object='librsyslog_la-segdisk_crc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-segdisk_crc.lo `test -f 'segdisk_crc.c' || echo '$(srcdir)/'`segdisk_crc.c librsyslog_la-segdisk_state.lo: segdisk_state.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-segdisk_state.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-segdisk_state.Tpo -c -o librsyslog_la-segdisk_state.lo `test -f 'segdisk_state.c' || echo '$(srcdir)/'`segdisk_state.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-segdisk_state.Tpo $(DEPDIR)/librsyslog_la-segdisk_state.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='segdisk_state.c' object='librsyslog_la-segdisk_state.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-segdisk_state.lo `test -f 'segdisk_state.c' || echo '$(srcdir)/'`segdisk_state.c librsyslog_la-segdisk_store.lo: segdisk_store.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-segdisk_store.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-segdisk_store.Tpo -c -o librsyslog_la-segdisk_store.lo `test -f 'segdisk_store.c' || echo '$(srcdir)/'`segdisk_store.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-segdisk_store.Tpo $(DEPDIR)/librsyslog_la-segdisk_store.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='segdisk_store.c' object='librsyslog_la-segdisk_store.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-segdisk_store.lo `test -f 'segdisk_store.c' || echo '$(srcdir)/'`segdisk_store.c librsyslog_la-ruleset.lo: ruleset.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-ruleset.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-ruleset.Tpo -c -o librsyslog_la-ruleset.lo `test -f 'ruleset.c' || echo '$(srcdir)/'`ruleset.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-ruleset.Tpo $(DEPDIR)/librsyslog_la-ruleset.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ruleset.c' object='librsyslog_la-ruleset.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-ruleset.lo `test -f 'ruleset.c' || echo '$(srcdir)/'`ruleset.c librsyslog_la-rswatch.lo: rswatch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-rswatch.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-rswatch.Tpo -c -o librsyslog_la-rswatch.lo `test -f 'rswatch.c' || echo '$(srcdir)/'`rswatch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-rswatch.Tpo $(DEPDIR)/librsyslog_la-rswatch.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rswatch.c' object='librsyslog_la-rswatch.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-rswatch.lo `test -f 'rswatch.c' || echo '$(srcdir)/'`rswatch.c librsyslog_la-prop.lo: prop.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-prop.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-prop.Tpo -c -o librsyslog_la-prop.lo `test -f 'prop.c' || echo '$(srcdir)/'`prop.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-prop.Tpo $(DEPDIR)/librsyslog_la-prop.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='prop.c' object='librsyslog_la-prop.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-prop.lo `test -f 'prop.c' || echo '$(srcdir)/'`prop.c librsyslog_la-ratelimit.lo: ratelimit.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-ratelimit.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-ratelimit.Tpo -c -o librsyslog_la-ratelimit.lo `test -f 'ratelimit.c' || echo '$(srcdir)/'`ratelimit.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-ratelimit.Tpo $(DEPDIR)/librsyslog_la-ratelimit.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ratelimit.c' object='librsyslog_la-ratelimit.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-ratelimit.lo `test -f 'ratelimit.c' || echo '$(srcdir)/'`ratelimit.c librsyslog_la-translate.lo: translate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-translate.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-translate.Tpo -c -o librsyslog_la-translate.lo `test -f 'translate.c' || echo '$(srcdir)/'`translate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-translate.Tpo $(DEPDIR)/librsyslog_la-translate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='translate.c' object='librsyslog_la-translate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-translate.lo `test -f 'translate.c' || echo '$(srcdir)/'`translate.c librsyslog_la-yamlconf.lo: yamlconf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-yamlconf.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-yamlconf.Tpo -c -o librsyslog_la-yamlconf.lo `test -f 'yamlconf.c' || echo '$(srcdir)/'`yamlconf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-yamlconf.Tpo $(DEPDIR)/librsyslog_la-yamlconf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yamlconf.c' object='librsyslog_la-yamlconf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-yamlconf.lo `test -f 'yamlconf.c' || echo '$(srcdir)/'`yamlconf.c librsyslog_la-lookup.lo: lookup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-lookup.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-lookup.Tpo -c -o librsyslog_la-lookup.lo `test -f 'lookup.c' || echo '$(srcdir)/'`lookup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-lookup.Tpo $(DEPDIR)/librsyslog_la-lookup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lookup.c' object='librsyslog_la-lookup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-lookup.lo `test -f 'lookup.c' || echo '$(srcdir)/'`lookup.c librsyslog_la-cfsysline.lo: cfsysline.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-cfsysline.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-cfsysline.Tpo -c -o librsyslog_la-cfsysline.lo `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-cfsysline.Tpo $(DEPDIR)/librsyslog_la-cfsysline.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cfsysline.c' object='librsyslog_la-cfsysline.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-cfsysline.lo `test -f 'cfsysline.c' || echo '$(srcdir)/'`cfsysline.c librsyslog_la-action.lo: action.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-action.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-action.Tpo -c -o librsyslog_la-action.lo `test -f 'action.c' || echo '$(srcdir)/'`action.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-action.Tpo $(DEPDIR)/librsyslog_la-action.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='action.c' object='librsyslog_la-action.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-action.lo `test -f 'action.c' || echo '$(srcdir)/'`action.c librsyslog_la-threads.lo: threads.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-threads.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-threads.Tpo -c -o librsyslog_la-threads.lo `test -f 'threads.c' || echo '$(srcdir)/'`threads.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-threads.Tpo $(DEPDIR)/librsyslog_la-threads.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='threads.c' object='librsyslog_la-threads.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-threads.lo `test -f 'threads.c' || echo '$(srcdir)/'`threads.c librsyslog_la-parse.lo: parse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-parse.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-parse.Tpo -c -o librsyslog_la-parse.lo `test -f 'parse.c' || echo '$(srcdir)/'`parse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-parse.Tpo $(DEPDIR)/librsyslog_la-parse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='parse.c' object='librsyslog_la-parse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-parse.lo `test -f 'parse.c' || echo '$(srcdir)/'`parse.c librsyslog_la-hashtable.lo: hashtable.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-hashtable.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-hashtable.Tpo -c -o librsyslog_la-hashtable.lo `test -f 'hashtable.c' || echo '$(srcdir)/'`hashtable.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-hashtable.Tpo $(DEPDIR)/librsyslog_la-hashtable.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hashtable.c' object='librsyslog_la-hashtable.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-hashtable.lo `test -f 'hashtable.c' || echo '$(srcdir)/'`hashtable.c librsyslog_la-hashtable_itr.lo: hashtable_itr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-hashtable_itr.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-hashtable_itr.Tpo -c -o librsyslog_la-hashtable_itr.lo `test -f 'hashtable_itr.c' || echo '$(srcdir)/'`hashtable_itr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-hashtable_itr.Tpo $(DEPDIR)/librsyslog_la-hashtable_itr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='hashtable_itr.c' object='librsyslog_la-hashtable_itr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-hashtable_itr.lo `test -f 'hashtable_itr.c' || echo '$(srcdir)/'`hashtable_itr.c librsyslog_la-outchannel.lo: outchannel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-outchannel.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-outchannel.Tpo -c -o librsyslog_la-outchannel.lo `test -f 'outchannel.c' || echo '$(srcdir)/'`outchannel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-outchannel.Tpo $(DEPDIR)/librsyslog_la-outchannel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='outchannel.c' object='librsyslog_la-outchannel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-outchannel.lo `test -f 'outchannel.c' || echo '$(srcdir)/'`outchannel.c librsyslog_la-template.lo: template.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-template.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-template.Tpo -c -o librsyslog_la-template.lo `test -f 'template.c' || echo '$(srcdir)/'`template.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-template.Tpo $(DEPDIR)/librsyslog_la-template.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='template.c' object='librsyslog_la-template.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-template.lo `test -f 'template.c' || echo '$(srcdir)/'`template.c librsyslog_la-timezones.lo: timezones.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT librsyslog_la-timezones.lo -MD -MP -MF $(DEPDIR)/librsyslog_la-timezones.Tpo -c -o librsyslog_la-timezones.lo `test -f 'timezones.c' || echo '$(srcdir)/'`timezones.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/librsyslog_la-timezones.Tpo $(DEPDIR)/librsyslog_la-timezones.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='timezones.c' object='librsyslog_la-timezones.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(librsyslog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o librsyslog_la-timezones.lo `test -f 'timezones.c' || echo '$(srcdir)/'`timezones.c lmcry_gcry_la-lmcry_gcry.lo: lmcry_gcry.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmcry_gcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmcry_gcry_la-lmcry_gcry.lo -MD -MP -MF $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Tpo -c -o lmcry_gcry_la-lmcry_gcry.lo `test -f 'lmcry_gcry.c' || echo '$(srcdir)/'`lmcry_gcry.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Tpo $(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lmcry_gcry.c' object='lmcry_gcry_la-lmcry_gcry.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmcry_gcry_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmcry_gcry_la-lmcry_gcry.lo `test -f 'lmcry_gcry.c' || echo '$(srcdir)/'`lmcry_gcry.c lmcry_ossl_la-lmcry_ossl.lo: lmcry_ossl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmcry_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmcry_ossl_la-lmcry_ossl.lo -MD -MP -MF $(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Tpo -c -o lmcry_ossl_la-lmcry_ossl.lo `test -f 'lmcry_ossl.c' || echo '$(srcdir)/'`lmcry_ossl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Tpo $(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lmcry_ossl.c' object='lmcry_ossl_la-lmcry_ossl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmcry_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmcry_ossl_la-lmcry_ossl.lo `test -f 'lmcry_ossl.c' || echo '$(srcdir)/'`lmcry_ossl.c lmgssutil_la-gss-misc.lo: gss-misc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmgssutil_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmgssutil_la-gss-misc.lo -MD -MP -MF $(DEPDIR)/lmgssutil_la-gss-misc.Tpo -c -o lmgssutil_la-gss-misc.lo `test -f 'gss-misc.c' || echo '$(srcdir)/'`gss-misc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmgssutil_la-gss-misc.Tpo $(DEPDIR)/lmgssutil_la-gss-misc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gss-misc.c' object='lmgssutil_la-gss-misc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmgssutil_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmgssutil_la-gss-misc.lo `test -f 'gss-misc.c' || echo '$(srcdir)/'`gss-misc.c lmnet_la-net.lo: net.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnet_la-net.lo -MD -MP -MF $(DEPDIR)/lmnet_la-net.Tpo -c -o lmnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnet_la-net.Tpo $(DEPDIR)/lmnet_la-net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net.c' object='lmnet_la-net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnet_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c lmnet_la-netns_socket.lo: netns_socket.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnet_la-netns_socket.lo -MD -MP -MF $(DEPDIR)/lmnet_la-netns_socket.Tpo -c -o lmnet_la-netns_socket.lo `test -f 'netns_socket.c' || echo '$(srcdir)/'`netns_socket.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnet_la-netns_socket.Tpo $(DEPDIR)/lmnet_la-netns_socket.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netns_socket.c' object='lmnet_la-netns_socket.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnet_la-netns_socket.lo `test -f 'netns_socket.c' || echo '$(srcdir)/'`netns_socket.c lmnetstrms_la-netstrms.lo: netstrms.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-netstrms.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-netstrms.Tpo -c -o lmnetstrms_la-netstrms.lo `test -f 'netstrms.c' || echo '$(srcdir)/'`netstrms.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-netstrms.Tpo $(DEPDIR)/lmnetstrms_la-netstrms.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netstrms.c' object='lmnetstrms_la-netstrms.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-netstrms.lo `test -f 'netstrms.c' || echo '$(srcdir)/'`netstrms.c lmnetstrms_la-netstrm.lo: netstrm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnetstrms_la-netstrm.lo -MD -MP -MF $(DEPDIR)/lmnetstrms_la-netstrm.Tpo -c -o lmnetstrms_la-netstrm.lo `test -f 'netstrm.c' || echo '$(srcdir)/'`netstrm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnetstrms_la-netstrm.Tpo $(DEPDIR)/lmnetstrms_la-netstrm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='netstrm.c' object='lmnetstrms_la-netstrm.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnetstrms_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnetstrms_la-netstrm.lo `test -f 'netstrm.c' || echo '$(srcdir)/'`netstrm.c lmnsd_gtls_la-nsd_gtls.lo: nsd_gtls.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_gtls_la-nsd_gtls.lo -MD -MP -MF $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Tpo -c -o lmnsd_gtls_la-nsd_gtls.lo `test -f 'nsd_gtls.c' || echo '$(srcdir)/'`nsd_gtls.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Tpo $(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_gtls.c' object='lmnsd_gtls_la-nsd_gtls.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_gtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_gtls_la-nsd_gtls.lo `test -f 'nsd_gtls.c' || echo '$(srcdir)/'`nsd_gtls.c lmnsd_mbedtls_la-nsd_mbedtls.lo: nsd_mbedtls.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_mbedtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_mbedtls_la-nsd_mbedtls.lo -MD -MP -MF $(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Tpo -c -o lmnsd_mbedtls_la-nsd_mbedtls.lo `test -f 'nsd_mbedtls.c' || echo '$(srcdir)/'`nsd_mbedtls.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Tpo $(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_mbedtls.c' object='lmnsd_mbedtls_la-nsd_mbedtls.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_mbedtls_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_mbedtls_la-nsd_mbedtls.lo `test -f 'nsd_mbedtls.c' || echo '$(srcdir)/'`nsd_mbedtls.c lmnsd_ossl_la-net_ossl.lo: net_ossl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-net_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-net_ossl.Tpo -c -o lmnsd_ossl_la-net_ossl.lo `test -f 'net_ossl.c' || echo '$(srcdir)/'`net_ossl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-net_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net_ossl.c' object='lmnsd_ossl_la-net_ossl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-net_ossl.lo `test -f 'net_ossl.c' || echo '$(srcdir)/'`net_ossl.c lmnsd_ossl_la-net_ossl_store.lo: net_ossl_store.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-net_ossl_store.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Tpo -c -o lmnsd_ossl_la-net_ossl_store.lo `test -f 'net_ossl_store.c' || echo '$(srcdir)/'`net_ossl_store.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Tpo $(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='net_ossl_store.c' object='lmnsd_ossl_la-net_ossl_store.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-net_ossl_store.lo `test -f 'net_ossl_store.c' || echo '$(srcdir)/'`net_ossl_store.c lmnsd_ossl_la-nsd_ossl.lo: nsd_ossl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ossl_la-nsd_ossl.lo -MD -MP -MF $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Tpo -c -o lmnsd_ossl_la-nsd_ossl.lo `test -f 'nsd_ossl.c' || echo '$(srcdir)/'`nsd_ossl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Tpo $(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_ossl.c' object='lmnsd_ossl_la-nsd_ossl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ossl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ossl_la-nsd_ossl.lo `test -f 'nsd_ossl.c' || echo '$(srcdir)/'`nsd_ossl.c lmnsd_ptcp_la-nsd_ptcp.lo: nsd_ptcp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmnsd_ptcp_la-nsd_ptcp.lo -MD -MP -MF $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Tpo -c -o lmnsd_ptcp_la-nsd_ptcp.lo `test -f 'nsd_ptcp.c' || echo '$(srcdir)/'`nsd_ptcp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Tpo $(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nsd_ptcp.c' object='lmnsd_ptcp_la-nsd_ptcp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmnsd_ptcp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmnsd_ptcp_la-nsd_ptcp.lo `test -f 'nsd_ptcp.c' || echo '$(srcdir)/'`nsd_ptcp.c lmregexp_la-regexp.lo: regexp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmregexp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmregexp_la-regexp.lo -MD -MP -MF $(DEPDIR)/lmregexp_la-regexp.Tpo -c -o lmregexp_la-regexp.lo `test -f 'regexp.c' || echo '$(srcdir)/'`regexp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmregexp_la-regexp.Tpo $(DEPDIR)/lmregexp_la-regexp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='regexp.c' object='lmregexp_la-regexp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmregexp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmregexp_la-regexp.lo `test -f 'regexp.c' || echo '$(srcdir)/'`regexp.c lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo: lmsig_ksi-ls12.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Tpo -c -o lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo `test -f 'lmsig_ksi-ls12.c' || echo '$(srcdir)/'`lmsig_ksi-ls12.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lmsig_ksi-ls12.c' object='lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lmsig_ksi-ls12.lo `test -f 'lmsig_ksi-ls12.c' || echo '$(srcdir)/'`lmsig_ksi-ls12.c lmsig_ksi_ls12_la-lib_ksils12.lo: lib_ksils12.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lib_ksils12.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Tpo -c -o lmsig_ksi_ls12_la-lib_ksils12.lo `test -f 'lib_ksils12.c' || echo '$(srcdir)/'`lib_ksils12.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib_ksils12.c' object='lmsig_ksi_ls12_la-lib_ksils12.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lib_ksils12.lo `test -f 'lib_ksils12.c' || echo '$(srcdir)/'`lib_ksils12.c lmsig_ksi_ls12_la-lib_ksi_queue.lo: lib_ksi_queue.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmsig_ksi_ls12_la-lib_ksi_queue.lo -MD -MP -MF $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Tpo -c -o lmsig_ksi_ls12_la-lib_ksi_queue.lo `test -f 'lib_ksi_queue.c' || echo '$(srcdir)/'`lib_ksi_queue.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Tpo $(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib_ksi_queue.c' object='lmsig_ksi_ls12_la-lib_ksi_queue.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmsig_ksi_ls12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmsig_ksi_ls12_la-lib_ksi_queue.lo `test -f 'lib_ksi_queue.c' || echo '$(srcdir)/'`lib_ksi_queue.c lmtcpclt_la-tcpclt.lo: tcpclt.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpclt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpclt_la-tcpclt.lo -MD -MP -MF $(DEPDIR)/lmtcpclt_la-tcpclt.Tpo -c -o lmtcpclt_la-tcpclt.lo `test -f 'tcpclt.c' || echo '$(srcdir)/'`tcpclt.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpclt_la-tcpclt.Tpo $(DEPDIR)/lmtcpclt_la-tcpclt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpclt.c' object='lmtcpclt_la-tcpclt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpclt_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpclt_la-tcpclt.lo `test -f 'tcpclt.c' || echo '$(srcdir)/'`tcpclt.c lmtcpsrv_la-tcps_sess.lo: tcps_sess.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpsrv_la-tcps_sess.lo -MD -MP -MF $(DEPDIR)/lmtcpsrv_la-tcps_sess.Tpo -c -o lmtcpsrv_la-tcps_sess.lo `test -f 'tcps_sess.c' || echo '$(srcdir)/'`tcps_sess.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpsrv_la-tcps_sess.Tpo $(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcps_sess.c' object='lmtcpsrv_la-tcps_sess.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpsrv_la-tcps_sess.lo `test -f 'tcps_sess.c' || echo '$(srcdir)/'`tcps_sess.c lmtcpsrv_la-tcpsrv.lo: tcpsrv.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmtcpsrv_la-tcpsrv.lo -MD -MP -MF $(DEPDIR)/lmtcpsrv_la-tcpsrv.Tpo -c -o lmtcpsrv_la-tcpsrv.lo `test -f 'tcpsrv.c' || echo '$(srcdir)/'`tcpsrv.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmtcpsrv_la-tcpsrv.Tpo $(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcpsrv.c' object='lmtcpsrv_la-tcpsrv.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmtcpsrv_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmtcpsrv_la-tcpsrv.lo `test -f 'tcpsrv.c' || echo '$(srcdir)/'`tcpsrv.c lmzlibw_la-zlibw.lo: zlibw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzlibw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmzlibw_la-zlibw.lo -MD -MP -MF $(DEPDIR)/lmzlibw_la-zlibw.Tpo -c -o lmzlibw_la-zlibw.lo `test -f 'zlibw.c' || echo '$(srcdir)/'`zlibw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmzlibw_la-zlibw.Tpo $(DEPDIR)/lmzlibw_la-zlibw.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zlibw.c' object='lmzlibw_la-zlibw.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzlibw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmzlibw_la-zlibw.lo `test -f 'zlibw.c' || echo '$(srcdir)/'`zlibw.c lmzstdw_la-zstdw.lo: zstdw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzstdw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lmzstdw_la-zstdw.lo -MD -MP -MF $(DEPDIR)/lmzstdw_la-zstdw.Tpo -c -o lmzstdw_la-zstdw.lo `test -f 'zstdw.c' || echo '$(srcdir)/'`zstdw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lmzstdw_la-zstdw.Tpo $(DEPDIR)/lmzstdw_la-zstdw.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zstdw.c' object='lmzstdw_la-zstdw.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lmzstdw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lmzstdw_la-zstdw.lo `test -f 'zstdw.c' || echo '$(srcdir)/'`zstdw.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(LIBRARIES) $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(pkglibdir)"; 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-noinstLIBRARIES \ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES \ clean-sbinPROGRAMS mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/libgcry_la-libcry_common.Plo -rm -f ./$(DEPDIR)/libgcry_la-libgcry.Plo -rm -f ./$(DEPDIR)/libossl_la-libcry_common.Plo -rm -f ./$(DEPDIR)/libossl_la-libossl.Plo -rm -f ./$(DEPDIR)/librsyslog_la-action.Plo -rm -f ./$(DEPDIR)/librsyslog_la-cfsysline.Plo -rm -f ./$(DEPDIR)/librsyslog_la-conf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-datetime.Plo -rm -f ./$(DEPDIR)/librsyslog_la-debug.Plo -rm -f ./$(DEPDIR)/librsyslog_la-dnscache.Plo -rm -f ./$(DEPDIR)/librsyslog_la-dynstats.Plo -rm -f ./$(DEPDIR)/librsyslog_la-errmsg.Plo -rm -f ./$(DEPDIR)/librsyslog_la-glbl.Plo -rm -f ./$(DEPDIR)/librsyslog_la-hashtable.Plo -rm -f ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo -rm -f ./$(DEPDIR)/librsyslog_la-janitor.Plo -rm -f ./$(DEPDIR)/librsyslog_la-linkedlist.Plo -rm -f ./$(DEPDIR)/librsyslog_la-lookup.Plo -rm -f ./$(DEPDIR)/librsyslog_la-modules.Plo -rm -f ./$(DEPDIR)/librsyslog_la-msg.Plo -rm -f ./$(DEPDIR)/librsyslog_la-obj.Plo -rm -f ./$(DEPDIR)/librsyslog_la-objomsr.Plo -rm -f ./$(DEPDIR)/librsyslog_la-operatingstate.Plo -rm -f ./$(DEPDIR)/librsyslog_la-outchannel.Plo -rm -f ./$(DEPDIR)/librsyslog_la-parse.Plo -rm -f ./$(DEPDIR)/librsyslog_la-parser.Plo -rm -f ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo -rm -f ./$(DEPDIR)/librsyslog_la-prop.Plo -rm -f ./$(DEPDIR)/librsyslog_la-queue.Plo -rm -f ./$(DEPDIR)/librsyslog_la-queue_da.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ratelimit.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rswatch.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_codec.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_crc.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_state.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_store.Plo -rm -f ./$(DEPDIR)/librsyslog_la-srutils.Plo -rm -f ./$(DEPDIR)/librsyslog_la-statsobj.Plo -rm -f ./$(DEPDIR)/librsyslog_la-stream.Plo -rm -f ./$(DEPDIR)/librsyslog_la-strgen.Plo -rm -f ./$(DEPDIR)/librsyslog_la-stringbuf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-template.Plo -rm -f ./$(DEPDIR)/librsyslog_la-threads.Plo -rm -f ./$(DEPDIR)/librsyslog_la-timezones.Plo -rm -f ./$(DEPDIR)/librsyslog_la-translate.Plo -rm -f ./$(DEPDIR)/librsyslog_la-var.Plo -rm -f ./$(DEPDIR)/librsyslog_la-wti.Plo -rm -f ./$(DEPDIR)/librsyslog_la-wtp.Plo -rm -f ./$(DEPDIR)/librsyslog_la-yamlconf.Plo -rm -f ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo -rm -f ./$(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Plo -rm -f ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo -rm -f ./$(DEPDIR)/lmnet_la-net.Plo -rm -f ./$(DEPDIR)/lmnet_la-netns_socket.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo -rm -f ./$(DEPDIR)/lmregexp_la-regexp.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo -rm -f ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo -rm -f ./$(DEPDIR)/lmzlibw_la-zlibw.Plo -rm -f ./$(DEPDIR)/lmzstdw_la-zstdw.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES 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 -f ./$(DEPDIR)/libgcry_la-libcry_common.Plo -rm -f ./$(DEPDIR)/libgcry_la-libgcry.Plo -rm -f ./$(DEPDIR)/libossl_la-libcry_common.Plo -rm -f ./$(DEPDIR)/libossl_la-libossl.Plo -rm -f ./$(DEPDIR)/librsyslog_la-action.Plo -rm -f ./$(DEPDIR)/librsyslog_la-cfsysline.Plo -rm -f ./$(DEPDIR)/librsyslog_la-conf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-datetime.Plo -rm -f ./$(DEPDIR)/librsyslog_la-debug.Plo -rm -f ./$(DEPDIR)/librsyslog_la-dnscache.Plo -rm -f ./$(DEPDIR)/librsyslog_la-dynstats.Plo -rm -f ./$(DEPDIR)/librsyslog_la-errmsg.Plo -rm -f ./$(DEPDIR)/librsyslog_la-glbl.Plo -rm -f ./$(DEPDIR)/librsyslog_la-hashtable.Plo -rm -f ./$(DEPDIR)/librsyslog_la-hashtable_itr.Plo -rm -f ./$(DEPDIR)/librsyslog_la-janitor.Plo -rm -f ./$(DEPDIR)/librsyslog_la-linkedlist.Plo -rm -f ./$(DEPDIR)/librsyslog_la-lookup.Plo -rm -f ./$(DEPDIR)/librsyslog_la-modules.Plo -rm -f ./$(DEPDIR)/librsyslog_la-msg.Plo -rm -f ./$(DEPDIR)/librsyslog_la-obj.Plo -rm -f ./$(DEPDIR)/librsyslog_la-objomsr.Plo -rm -f ./$(DEPDIR)/librsyslog_la-operatingstate.Plo -rm -f ./$(DEPDIR)/librsyslog_la-outchannel.Plo -rm -f ./$(DEPDIR)/librsyslog_la-parse.Plo -rm -f ./$(DEPDIR)/librsyslog_la-parser.Plo -rm -f ./$(DEPDIR)/librsyslog_la-perctile_ringbuf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-perctile_stats.Plo -rm -f ./$(DEPDIR)/librsyslog_la-prop.Plo -rm -f ./$(DEPDIR)/librsyslog_la-queue.Plo -rm -f ./$(DEPDIR)/librsyslog_la-queue_da.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ratelimit.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsconf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rswatch.Plo -rm -f ./$(DEPDIR)/librsyslog_la-rsyslog.Plo -rm -f ./$(DEPDIR)/librsyslog_la-ruleset.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_codec.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_crc.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_state.Plo -rm -f ./$(DEPDIR)/librsyslog_la-segdisk_store.Plo -rm -f ./$(DEPDIR)/librsyslog_la-srutils.Plo -rm -f ./$(DEPDIR)/librsyslog_la-statsobj.Plo -rm -f ./$(DEPDIR)/librsyslog_la-stream.Plo -rm -f ./$(DEPDIR)/librsyslog_la-strgen.Plo -rm -f ./$(DEPDIR)/librsyslog_la-stringbuf.Plo -rm -f ./$(DEPDIR)/librsyslog_la-template.Plo -rm -f ./$(DEPDIR)/librsyslog_la-threads.Plo -rm -f ./$(DEPDIR)/librsyslog_la-timezones.Plo -rm -f ./$(DEPDIR)/librsyslog_la-translate.Plo -rm -f ./$(DEPDIR)/librsyslog_la-var.Plo -rm -f ./$(DEPDIR)/librsyslog_la-wti.Plo -rm -f ./$(DEPDIR)/librsyslog_la-wtp.Plo -rm -f ./$(DEPDIR)/librsyslog_la-yamlconf.Plo -rm -f ./$(DEPDIR)/lmcry_gcry_la-lmcry_gcry.Plo -rm -f ./$(DEPDIR)/lmcry_ossl_la-lmcry_ossl.Plo -rm -f ./$(DEPDIR)/lmgssutil_la-gss-misc.Plo -rm -f ./$(DEPDIR)/lmnet_la-net.Plo -rm -f ./$(DEPDIR)/lmnet_la-netns_socket.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrm.Plo -rm -f ./$(DEPDIR)/lmnetstrms_la-netstrms.Plo -rm -f ./$(DEPDIR)/lmnsd_gtls_la-nsd_gtls.Plo -rm -f ./$(DEPDIR)/lmnsd_mbedtls_la-nsd_mbedtls.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-net_ossl_store.Plo -rm -f ./$(DEPDIR)/lmnsd_ossl_la-nsd_ossl.Plo -rm -f ./$(DEPDIR)/lmnsd_ptcp_la-nsd_ptcp.Plo -rm -f ./$(DEPDIR)/lmregexp_la-regexp.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksi_queue.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lib_ksils12.Plo -rm -f ./$(DEPDIR)/lmsig_ksi_ls12_la-lmsig_ksi-ls12.Plo -rm -f ./$(DEPDIR)/lmtcpclt_la-tcpclt.Plo -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcps_sess.Plo -rm -f ./$(DEPDIR)/lmtcpsrv_la-tcpsrv.Plo -rm -f ./$(DEPDIR)/lmzlibw_la-zlibw.Plo -rm -f ./$(DEPDIR)/lmzstdw_la-zstdw.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-noinstLIBRARIES clean-noinstLTLIBRARIES \ clean-pkglibLTLIBRARIES clean-sbinPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES uninstall-sbinPROGRAMS .PRECIOUS: Makefile # # support library for openssl crypto provider # @ENABLE_OPENSSL_CRYPTO_PROVIDER_TRUE@ # Helper # 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: rsyslog-8.2608.0/runtime/PaxHeaders/lib_ksi_queue.c0000644000000000000000000000013215132411300017174 xustar0030 mtime=1768559296.264885609 30 atime=1782715518.784788772 30 ctime=1787067794.589728689 rsyslog-8.2608.0/runtime/lib_ksi_queue.c0000666000175000017500000001321015132411300016637 0ustar00rgerrger#define _POSIX_C_SOURCE 199309L #include #include #include #include "lib_ksi_queue.h" RingBuffer* RingBuffer_new(size_t size) { RingBuffer* p = calloc(1, sizeof(RingBuffer)); if (!p) return NULL; p->buffer = calloc(size, sizeof(void*)); p->size = size; return p; } void RingBuffer_free(RingBuffer* this) { if (this->buffer != NULL) free(this->buffer); free(this); } static bool RingBuffer_grow(RingBuffer* this) { void** pTmp = calloc(this->size * RB_GROW_FACTOR, sizeof(void*)); void* pTmpItem = NULL; if (!pTmp) return false; for (size_t i = 0; i < this->size; ++i) { RingBuffer_popFront(this, &pTmpItem); pTmp[i] = pTmpItem; } free(this->buffer); this->buffer = pTmp; this->head = 0; this->tail = this->size; this->count = this->size; this->size = this->size * RB_GROW_FACTOR; return true; } bool RingBuffer_pushBack(RingBuffer* this, void* item) { if (this->size == this->count && !RingBuffer_grow(this)) return false; if (this->size == 0) return false; this->buffer[this->tail] = item; this->tail = (this->tail + 1) % this->size; this->count += 1; return true; } bool RingBuffer_popFront(RingBuffer* this, void** item) { if (this->count == 0) return false; *item = this->buffer[this->head]; this->buffer[this->head] = NULL; this->count -= 1; this->head = (this->head + 1) % this->size; return true; } bool RingBuffer_peekFront(RingBuffer* this, void** item) { if (this->count == 0) return false; *item = this->buffer[this->head]; return true; } size_t RingBuffer_count(RingBuffer* this) { return this->count; } bool RingBuffer_getItem(RingBuffer* this, size_t index, void** item) { if (this->count == 0 || index >= this->count) return false; *item = this->buffer[(this->head + index) % this->size]; return true; } ProtectedQueue* ProtectedQueue_new(size_t queueSize) { ProtectedQueue* p = calloc(1, sizeof(ProtectedQueue)); if (!p) return NULL; pthread_mutex_init(&p->mutex, 0); p->bStop = false; p->workItems = RingBuffer_new(queueSize); return p; } void ProtectedQueue_free(ProtectedQueue* this) { pthread_mutex_destroy(&this->mutex); pthread_cond_destroy(&this->condition); this->bStop = true; RingBuffer_free(this->workItems); free(this); } /// Signal stop. All threads waiting in FetchItme will be returned false from FetchItem void ProtectedQueue_stop(ProtectedQueue* this) { this->bStop = true; pthread_cond_broadcast(&this->condition); } /// Atomically adds an item into work item queue and releases a thread waiting /// in FetchItem bool ProtectedQueue_addItem(ProtectedQueue* this, void* item) { bool ret = false; if (this->bStop) return false; pthread_mutex_lock(&this->mutex); if ((ret = RingBuffer_pushBack(this->workItems, item)) == true) pthread_cond_signal(&this->condition); pthread_mutex_unlock(&this->mutex); return ret; } bool ProtectedQueue_peekFront(ProtectedQueue* this, void** item) { bool ret; pthread_mutex_lock(&this->mutex); ret = RingBuffer_peekFront(this->workItems, item); pthread_mutex_unlock(&this->mutex); return ret; } bool ProtectedQueue_popFront(ProtectedQueue* this, void** item) { bool ret; pthread_mutex_lock(&this->mutex); ret = RingBuffer_popFront(this->workItems, item); pthread_mutex_unlock(&this->mutex); return ret; } size_t ProtectedQueue_popFrontBatch(ProtectedQueue* this, void** items, size_t bufSize) { size_t i; pthread_mutex_lock(&this->mutex); for (i = 0; RingBuffer_count(this->workItems) > 0 && i < bufSize; ++i) RingBuffer_popFront(this->workItems, items[i]); pthread_mutex_unlock(&this->mutex); return i; } bool ProtectedQueue_getItem(ProtectedQueue* this, size_t index, void** item) { bool ret = false; pthread_mutex_lock(&this->mutex); ret = RingBuffer_getItem(this->workItems, index, item); pthread_mutex_unlock(&this->mutex); return ret; } /* Waits for a new work item or timeout (if specified). Returns 0 in case of exit * condition, 1 if item became available and ETIMEDOUT in case of timeout. */ int ProtectedQueue_waitForItem(ProtectedQueue* this, void** item, uint64_t timeout) { struct timespec ts; pthread_mutex_lock(&this->mutex); if (timeout > 0) { clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += timeout / 1000LL; ts.tv_nsec += (timeout % 1000LL) * 1000LL; } if (timeout) { if (pthread_cond_timedwait(&this->condition, &this->mutex, &ts) == ETIMEDOUT) { pthread_mutex_unlock(&this->mutex); return ETIMEDOUT; } } else pthread_cond_wait(&this->condition, &this->mutex); if (this->bStop) { pthread_mutex_unlock(&this->mutex); return 0; } if (RingBuffer_count(this->workItems) != 0 && item != NULL) RingBuffer_popFront(this->workItems, item); pthread_mutex_unlock(&this->mutex); return 1; } size_t ProtectedQueue_count(ProtectedQueue* this) { size_t nCount; pthread_mutex_lock(&this->mutex); nCount = RingBuffer_count(this->workItems); pthread_mutex_unlock(&this->mutex); return nCount; } void* worker_thread_main(void* arg) { int res; void* item; WorkerThreadContext* tc = (WorkerThreadContext*)arg; while (1) { item = NULL; res = ProtectedQueue_waitForItem(tc->queue, &item, tc->timeout); if (tc->queue->bStop) return NULL; if (res == ETIMEDOUT) { if (!tc->timeoutFunc()) return NULL; } else if (item != NULL && !tc->workerFunc(item)) return NULL; } } rsyslog-8.2608.0/runtime/PaxHeaders/hashtable_itr.c0000644000000000000000000000013215132411300017165 xustar0030 mtime=1768559296.264885609 30 atime=1787067618.106439057 30 ctime=1787067794.484726732 rsyslog-8.2608.0/runtime/hashtable_itr.c0000666000175000017500000001315715132411300016642 0ustar00rgerrger/* Copyright (C) 2002, 2004 Christopher Clark */ #include "hashtable_private.h" #include "hashtable_itr.h" #include /* defines NULL */ /*****************************************************************************/ /* hashtable_iterator - iterator constructor */ struct hashtable_itr *hashtable_iterator(struct hashtable *h) { unsigned int i, tablelength; struct hashtable_itr *itr = (struct hashtable_itr *)malloc(sizeof(struct hashtable_itr)); if (NULL == itr) return NULL; itr->h = h; itr->e = NULL; itr->parent = NULL; tablelength = h->tablelength; itr->index = tablelength; if (0 == h->entrycount) return itr; for (i = 0; i < tablelength; i++) { if (NULL != h->table[i]) { itr->e = h->table[i]; itr->index = i; break; } } return itr; } /*****************************************************************************/ /* key - return the key of the (key,value) pair at the current position */ /* value - return the value of the (key,value) pair at the current position */ #if 0 /* these are now inline functions! */ void * hashtable_iterator_key(struct hashtable_itr *i) { return i->e->k; } void * hashtable_iterator_value(struct hashtable_itr *i) { return i->e->v; } #endif /*****************************************************************************/ /* advance - advance the iterator to the next element * returns zero if advanced to end of table */ int hashtable_iterator_advance(struct hashtable_itr *itr) { unsigned int j, tablelength; struct entry **table; struct entry *next; if (NULL == itr->e) return 0; /* stupidity check */ next = itr->e->next; if (NULL != next) { itr->parent = itr->e; itr->e = next; return -1; } tablelength = itr->h->tablelength; itr->parent = NULL; if (tablelength <= (j = ++(itr->index))) { itr->e = NULL; return 0; } table = itr->h->table; while (NULL == (next = table[j])) { if (++j >= tablelength) { itr->index = tablelength; itr->e = NULL; return 0; } } itr->index = j; itr->e = next; return -1; } /*****************************************************************************/ /* remove - remove the entry at the current iterator position * and advance the iterator, if there is a successive * element. * If you want the value, read it before you remove: * beware memory leaks if you don't. * Returns zero if end of iteration. */ int hashtable_iterator_remove(struct hashtable_itr *itr) { struct entry *remember_e, *remember_parent; int ret; /* Do the removal */ if (NULL == (itr->parent)) { /* element is head of a chain */ itr->h->table[itr->index] = itr->e->next; } else { /* element is mid-chain */ itr->parent->next = itr->e->next; } /* itr->e is now outside the hashtable */ remember_e = itr->e; itr->h->entrycount--; freekey(remember_e->k); /* Advance the iterator, correcting the parent */ remember_parent = itr->parent; ret = hashtable_iterator_advance(itr); if (itr->parent == remember_e) { itr->parent = remember_parent; } free(remember_e); return ret; } /*****************************************************************************/ int /* returns zero if not found */ hashtable_iterator_search(struct hashtable_itr *itr, struct hashtable *h, void *k) { struct entry *e, *parent; unsigned int hashvalue, index; hashvalue = hash(h, k); index = indexFor(h->tablelength, hashvalue); e = h->table[index]; parent = NULL; while (NULL != e) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { itr->index = index; itr->e = e; itr->parent = parent; itr->h = h; return -1; } parent = e; e = e->next; } return 0; } /* * Copyright (c) 2002, 2004, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ rsyslog-8.2608.0/runtime/PaxHeaders/libcry_common.h0000644000000000000000000000013215132411300017215 xustar0030 mtime=1768559296.265885624 30 atime=1783339707.659803487 30 ctime=1787067794.228721961 rsyslog-8.2608.0/runtime/libcry_common.h0000666000175000017500000000250015132411300016660 0ustar00rgerrger/* libgcry.h - rsyslog's guardtime support library * * Copyright 2013 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LIBCRY_COMMON_H #define INCLUDED_LIBCRY_COMMON_H #include /* error states */ #define RSGCRYE_EI_OPEN 1 /* error opening .encinfo file */ #define RSGCRYE_OOM 4 /* ran out of memory */ #define EIF_MAX_RECTYPE_LEN 31 /* max length of record types */ #define EIF_MAX_VALUE_LEN 1023 /* max length of value types */ #define RSGCRY_FILETYPE_NAME "rsyslog-enrcyption-info" #define ENCINFO_SUFFIX ".encinfo" int cryGetKeyFromFile(const char* const fn, char** const key, unsigned* const keylen); int cryGetKeyFromProg(char* cmd, char** key, unsigned* keylen); #endif rsyslog-8.2608.0/runtime/PaxHeaders/regexp.c0000644000000000000000000000013215216464436015673 xustar0030 mtime=1782212894.039266394 30 atime=1787067618.087438702 30 ctime=1787067794.573728391 rsyslog-8.2608.0/runtime/regexp.c0000664000175000017500000003111515216464436015340 0ustar00rgerrger/* The regexp object. * * Module begun 2008-03-05 by Rainer Gerhards, based on some code * from syslogd.c * * Copyright 2008-2012 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "module-template.h" #include "obj.h" #include "regexp.h" #include "errmsg.h" #include "hashtable.h" #include "hashtable_itr.h" MODULE_TYPE_LIB MODULE_TYPE_NOKEEP; /* static data */ DEFobjStaticHelpers; /* When using glibc, we enable per-thread regex to avoid lock contention. * See: * - https://github.com/rsyslog/rsyslog/issues/2759 * - https://github.com/rsyslog/rsyslog/pull/2786 * - https://sourceware.org/bugzilla/show_bug.cgi?id=11159 * * This should not affect BSD as they don't seem to take a lock in regexec. */ #ifdef __GLIBC__ #define USE_PERTHREAD_REGEX 1 #else #define USE_PERTHREAD_REGEX 0 #endif static pthread_mutex_t mut_regexp; // Map a regex_t to its associated uncompiled parameters. static struct hashtable *regex_to_uncomp = NULL; // Map a (regexp_t, pthead_t) to a perthread_regex. static struct hashtable *perthread_regexs = NULL; /* * This stores un-compiled regex to allow further * call to regexec to re-compile a new regex dedicated * to the calling thread. */ typedef struct uncomp_regex { char *regex; int cflags; regex_t *preg; } uncomp_regex_t; /* * This stores a regex dedicated to a single thread. */ typedef struct perthread_regex { const regex_t *original_preg; regex_t preg; int ret; pthread_mutex_t lock; pthread_t thread; } perthread_regex_t; static unsigned __attribute__((nonnull(1))) int hash_from_regex(void *k) { return (uintptr_t) * (regex_t **)k; } static int key_equals_regex(void *key1, void *key2) { return *(regex_t **)key1 == *(regex_t **)key2; } static unsigned __attribute__((nonnull(1))) int hash_from_tregex(void *k) { perthread_regex_t *entry = k; // Cast to (void*) is ok here because already used in other parts of the code. uintptr_t thread_id = (uintptr_t)(void *)entry->thread; return thread_id ^ (uintptr_t)entry->original_preg; } static int key_equals_tregex(void *key1, void *key2) { perthread_regex_t *entry1 = key1; perthread_regex_t *entry2 = key2; return (pthread_equal(entry1->thread, entry2->thread) && entry1->original_preg == entry2->original_preg); } /* ------------------------------ methods ------------------------------ */ // Create a copy of preg to be used by this thread only. static perthread_regex_t *create_perthread_regex(const regex_t *preg, uncomp_regex_t *uncomp) { perthread_regex_t *entry = NULL; if (Debug) { DBGPRINTF("Creating new regex_t for thread %p original regexp_t %p (pattern: %s, cflags: %x)\n", (void *)pthread_self(), preg, uncomp->regex, uncomp->cflags); } entry = calloc(1, sizeof(*entry)); if (!entry) return entry; entry->original_preg = preg; DBGPRINTF("regexp: regcomp %p %p\n", entry, &entry->preg); entry->ret = regcomp(&entry->preg, uncomp->regex, uncomp->cflags); pthread_mutex_init(&entry->lock, NULL); entry->thread = pthread_self(); return entry; } // Get (or create) a regex_t to be used by the current thread. static perthread_regex_t *get_perthread_regex(const regex_t *preg) { perthread_regex_t *entry = NULL; perthread_regex_t key = {.original_preg = preg, .thread = pthread_self()}; pthread_mutex_lock(&mut_regexp); entry = hashtable_search(perthread_regexs, (void *)&key); if (!entry) { uncomp_regex_t *uncomp = hashtable_search(regex_to_uncomp, (void *)&preg); if (uncomp) { entry = create_perthread_regex(preg, uncomp); if (!hashtable_insert(perthread_regexs, (void *)entry, entry)) { LogError(0, RS_RET_INTERNAL_ERROR, "error trying to insert thread-regexp into hash-table - things " "will not work 100%% correctly (mostly probably out of memory issue)"); } } } if (entry) { pthread_mutex_lock(&entry->lock); } pthread_mutex_unlock(&mut_regexp); return entry; } static void remove_uncomp_regexp(regex_t *preg) { uncomp_regex_t *uncomp = NULL; pthread_mutex_lock(&mut_regexp); uncomp = hashtable_remove(regex_to_uncomp, (void *)&preg); if (uncomp) { if (Debug) { DBGPRINTF("Removing everything linked to regexp_t %p (pattern: %s, cflags: %x)\n", preg, uncomp->regex, uncomp->cflags); } free(uncomp->regex); free(uncomp); } pthread_mutex_unlock(&mut_regexp); } static void _regfree(regex_t *preg) { int ret = 0; struct hashtable_itr *itr = NULL; if (!preg) return; regfree(preg); remove_uncomp_regexp(preg); pthread_mutex_lock(&mut_regexp); if (!hashtable_count(perthread_regexs)) { pthread_mutex_unlock(&mut_regexp); return; } // This can be long to iterate other all regexps, but regfree doesn't get called // a lot during processing. itr = hashtable_iterator(perthread_regexs); do { perthread_regex_t *entry = (perthread_regex_t *)hashtable_iterator_value(itr); // Do it before freeing the entry. ret = hashtable_iterator_advance(itr); if (entry->original_preg == preg) { // This allows us to avoid freeing this while somebody is still using it. pthread_mutex_lock(&entry->lock); // We can unlock immediately after because mut_regexp is locked. pthread_mutex_unlock(&entry->lock); pthread_mutex_destroy(&entry->lock); regfree(&entry->preg); // Do it last because it will free entry. hashtable_remove(perthread_regexs, (void *)entry); } } while (ret); free(itr); pthread_mutex_unlock(&mut_regexp); } static void destroy_perthread_regexs(void) { struct hashtable_itr *itr = NULL; int ret = 0; if (perthread_regexs == NULL) return; pthread_mutex_lock(&mut_regexp); if (hashtable_count(perthread_regexs)) { itr = hashtable_iterator(perthread_regexs); if (itr == NULL) { hashtable_destroy(perthread_regexs, 0); perthread_regexs = NULL; pthread_mutex_unlock(&mut_regexp); LogError(0, RS_RET_OUT_OF_MEMORY, "error creating per-thread regexp iterator during regexp class unload"); return; } do { perthread_regex_t *entry = (perthread_regex_t *)hashtable_iterator_value(itr); ret = hashtable_iterator_advance(itr); pthread_mutex_lock(&entry->lock); pthread_mutex_unlock(&entry->lock); pthread_mutex_destroy(&entry->lock); regfree(&entry->preg); /* * perthread_regexs uses the perthread_regex_t object as both * key and value. hashtable_destroy() always frees keys, so leave * the entry allocation owned by the hash table after cleaning the * resources embedded in it. */ } while (ret); free(itr); } hashtable_destroy(perthread_regexs, 0); perthread_regexs = NULL; pthread_mutex_unlock(&mut_regexp); } static int _regcomp(regex_t *preg, const char *regex, int cflags) { int ret = 0; regex_t **ppreg = NULL; uncomp_regex_t *uncomp; // Remove previous data if caller forgot to call regfree(). remove_uncomp_regexp(preg); // Make sure preg itself it correctly initalized. ret = regcomp(preg, regex, cflags); if (ret != 0) return ret; uncomp = calloc(1, sizeof(*uncomp)); if (!uncomp) return REG_ESPACE; uncomp->preg = preg; uncomp->regex = strdup(regex); uncomp->cflags = cflags; pthread_mutex_lock(&mut_regexp); // We need to allocate the key because hashtable will free it on remove. ppreg = malloc(sizeof(regex_t *)); *ppreg = preg; ret = hashtable_insert(regex_to_uncomp, (void *)ppreg, uncomp); pthread_mutex_unlock(&mut_regexp); if (ret == 0) { free(uncomp->regex); free(uncomp); return REG_ESPACE; } perthread_regex_t *entry = get_perthread_regex(preg); if (entry) { ret = entry->ret; pthread_mutex_unlock(&entry->lock); } else { ret = REG_ESPACE; } return ret; } static int _regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { perthread_regex_t *entry = get_perthread_regex(preg); int ret = REG_NOMATCH; if (entry != NULL) { ret = regexec(&entry->preg, string, nmatch, pmatch, eflags); pthread_mutex_unlock(&entry->lock); } return ret; } static size_t _regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) { perthread_regex_t *entry = get_perthread_regex(preg); if (entry) preg = &entry->preg; size_t ret = regerror(errcode, preg, errbuf, errbuf_size); if (entry) pthread_mutex_unlock(&entry->lock); return ret; } /* queryInterface function * rgerhards, 2008-03-05 */ BEGINobjQueryInterface(regexp) CODESTARTobjQueryInterface(regexp); if (pIf->ifVersion != regexpCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ if (USE_PERTHREAD_REGEX) { pIf->regcomp = _regcomp; pIf->regexec = _regexec; pIf->regerror = _regerror; pIf->regfree = _regfree; } else { pIf->regcomp = regcomp; pIf->regexec = regexec; pIf->regerror = regerror; pIf->regfree = regfree; } finalize_it: ENDobjQueryInterface(regexp) /* Initialize the regexp class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(regexp, 1, OBJ_IS_LOADABLE_MODULE) /* class, version */ /* request objects we use */ if (USE_PERTHREAD_REGEX) { pthread_mutex_init(&mut_regexp, NULL); regex_to_uncomp = create_hashtable(100, hash_from_regex, key_equals_regex, NULL); perthread_regexs = create_hashtable(100, hash_from_tregex, key_equals_tregex, NULL); if (regex_to_uncomp == NULL || perthread_regexs == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "error trying to initialize hash-table " "for regexp table. regexp will be disabled."); if (regex_to_uncomp) hashtable_destroy(regex_to_uncomp, 1); if (perthread_regexs) hashtable_destroy(perthread_regexs, 1); regex_to_uncomp = NULL; perthread_regexs = NULL; ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } } ENDObjClassInit(regexp) /* Exit the class. */ BEGINObjClassExit(regexp, OBJ_IS_LOADABLE_MODULE) /* class, version */ if (USE_PERTHREAD_REGEX) { /* release objects we no longer need */ destroy_perthread_regexs(); if (regex_to_uncomp) hashtable_destroy(regex_to_uncomp, 1); regex_to_uncomp = NULL; pthread_mutex_destroy(&mut_regexp); } ENDObjClassExit(regexp) /* --------------- here now comes the plumbing that makes as a library module --------------- */ BEGINmodExit CODESTARTmodExit; regexpClassExit(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_LIB_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CHKiRet(regexpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */ /* Initialize all classes that are in our module - this includes ourselfs */ ENDmodInit /* vi:set ai: */ rsyslog-8.2608.0/runtime/PaxHeaders/netns_socket.c0000644000000000000000000000013215216464436017100 xustar0030 mtime=1782212894.034266313 30 atime=1787067618.279442282 30 ctime=1787067794.530727589 rsyslog-8.2608.0/runtime/netns_socket.c0000664000175000017500000001204515216464436016546 0ustar00rgerrger/* Implementation for netns_socket API * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include "rsyslog.h" #include "debug.h" #include "errmsg.h" #include "netns_socket.h" /* Change to the given network namespace. * This function based on previous implementation * of tools/omfwd.c function changeToNs. */ rsRetVal netns_switch(const char *ns) { DEFiRet; #ifdef HAVE_SETNS int ns_fd = -1; char *nsPath = NULL; if (ns && *ns) { /* Build network namespace path */ if (asprintf(&nsPath, "/var/run/netns/%s", ns) == -1) { // Some implementations say nsPath would be undefined on failure nsPath = NULL; LogError(0, RS_RET_OUT_OF_MEMORY, "%s: asprintf failed", __func__); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* Open file descriptor of destination network namespace */ ns_fd = open(nsPath, O_RDONLY); if (ns_fd < 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not open namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_IO_ERROR); } /* Change to the destination network namespace */ if (setns(ns_fd, CLONE_NEWNET) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not change to namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: changed to network namespace '%s'\n", __func__, ns); } finalize_it: free(nsPath); if ((ns_fd >= 0) && (close(ns_fd) != 0)) { LogError(errno, RS_RET_IO_ERROR, "%s: failed to close namespace '%s'", __func__, ns); } #else // ndef HAVE_SETNS if (ns && *ns) { LogError(ENOSYS, RS_RET_VALUE_NOT_SUPPORTED, "%s: could not change to namespace '%s'", __func__, ns); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } finalize_it: #endif // ndef HAVE_SETNS RETiRet; } /* Return to the startup network namespace. * This function based on code in tools/omfwd.c */ rsRetVal ATTR_NONNULL() netns_restore(int *fd) { DEFiRet; #ifdef HAVE_SETNS if (*fd >= 0) { if (setns(*fd, CLONE_NEWNET) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not return to startup namespace", __func__); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: returned to startup network namespace\n", __func__); } finalize_it: #endif // def HAVE_SETNS if (*fd >= 0 && close(*fd) != 0) { LogError(errno, RS_RET_IO_ERROR, "%s: could not close startup namespace fd", __func__); } *fd = -1; RETiRet; } /* Save the current network namespace fd */ rsRetVal ATTR_NONNULL() netns_save(int *fd) { DEFiRet; /* * The fd must always point to either a valid fd * or to -1. We expect it to be -1 on entry here. * To avoid bugs, or possible descriptor leaks, * check that it is always -1 on entry. */ if (*fd != -1) { LogError(0, RS_RET_CODE_ERR, "%s: called with uninitialized descriptor", __func__); ABORT_FINALIZE(RS_RET_CODE_ERR); } #ifdef HAVE_SETNS *fd = open("/proc/self/ns/net", O_RDONLY); if (*fd == -1) { LogError(errno, RS_RET_IO_ERROR, "%s: could not access startup namespace", __func__); ABORT_FINALIZE(RS_RET_IO_ERROR); } dbgprintf("%s: saved startup network namespace\n", __func__); #endif finalize_it: RETiRet; } rsRetVal netns_socket(int *fdp, int domain, int type, int protocol, const char *ns) { DEFiRet; int fd = -1; #ifndef HAVE_SETNS if (ns && *ns) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "Network namespaces are not supported"); ABORT_FINALIZE(RS_RET_VALUE_NOT_SUPPORTED); } #else /* def HAVE_SETNS */ rsRetVal iRet_restore; int ns_fd = -1; if (ns && *ns) { CHKiRet(netns_save(&ns_fd)); CHKiRet(netns_switch(ns)); } #endif /* def HAVE_SETNS */ *fdp = fd = socket(domain, type, protocol); if (fd == -1) { LogError(errno, RS_RET_NO_SOCKET, "%s: socket(%d, %d, %d) failed", __func__, domain, type, protocol); ABORT_FINALIZE(RS_RET_NO_SOCKET); } finalize_it: #ifdef HAVE_SETNS iRet_restore = netns_restore(&ns_fd); if (iRet == RS_RET_OK) iRet = iRet_restore; #endif /* def HAVE_SETNS */ if (iRet != RS_RET_OK && fd != -1) { (void)close(fd); *fdp = -1; } RETiRet; } rsyslog-8.2608.0/runtime/PaxHeaders/dynstats.h0000644000000000000000000000013215241075234016247 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.745580916 30 ctime=1787067794.366724533 rsyslog-8.2608.0/runtime/dynstats.h0000664000175000017500000001007215241075234015713 0ustar00rgerrger/* * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_DYNSTATS_H #define INCLUDED_DYNSTATS_H #include "compat_queue.h" #include "hashtable.h" typedef struct hashtable htable; typedef struct rsconf_s rsconf_t; struct dynstats_buckets_s; struct dynstats_ctr_s { STATSCOUNTER_DEF(ctr, mutCtr); ctr_t *pCtr; uchar *metric; /* linked list ptr */ struct dynstats_ctr_s *next; struct dynstats_ctr_s *prev; }; struct dynstats_bucket_s { struct dynstats_buckets_s *bkts; htable *table; uchar *name; pthread_rwlock_t lock; statsobj_t *stats; STATSCOUNTER_DEF(ctrOpsOverflow, mutCtrOpsOverflow); ctr_t *pOpsOverflowCtr; STATSCOUNTER_DEF(ctrNewMetricAdd, mutCtrNewMetricAdd); ctr_t *pNewMetricAddCtr; STATSCOUNTER_DEF(ctrNoMetric, mutCtrNoMetric); ctr_t *pNoMetricCtr; STATSCOUNTER_DEF(ctrMetricsPurged, mutCtrMetricsPurged); ctr_t *pMetricsPurgedCtr; STATSCOUNTER_DEF(ctrOpsIgnored, mutCtrOpsIgnored); ctr_t *pOpsIgnoredCtr; STATSCOUNTER_DEF(ctrPurgeTriggered, mutCtrPurgeTriggered); ctr_t *pPurgeTriggeredCtr; /* file writer thread updates these counters - currently takes the bucket lock */ STATSCOUNTER_DEF(ctrFlushedBytes, mutCtrFlushedBytes); ctr_t *pCtrFlushedBytes; STATSCOUNTER_DEF(ctrFlushed, mutCtrFlushed); ctr_t *pCtrFlushed; STATSCOUNTER_DEF(ctrFlushedErrors, mutCtrFlushedErrors); ctr_t *pCtrFlushedErrors; struct dynstats_bucket_s *next; /* linked list ptr */ struct dynstats_ctr_s *ctrs; /*survivor objects are used to keep counter values around for upto unused-ttl duration, so in case it is accessed within (ttl - 2 * ttl) time-period we can re-store the accumulator value from this */ struct dynstats_ctr_s *survivor_ctrs; htable *survivor_table; uint32_t maxCardinality; uint32_t metricCount; pthread_mutex_t mutMetricCount; uint32_t unusedMetricLife; uint32_t lastResetTs; struct timespec metricCleanupTimeout; uint8_t resettable; uchar *state_file_directory; uint32_t persist_state_write_count_interval; /* count of bucket updates before persisting */ uint32_t persist_state_interval_secs; /* interval in secs bucket before persisting bucket state */ time_t persist_expiration_time; DEF_ATOMIC_HELPER_MUT64(mutPersistExpirationTime); uint32_t n_updates; /* number of bucket updates before persisting the stream */ }; struct dynstats_file_write_queue_s { STAILQ_HEAD(head, file_write_entry_s) q; STATSCOUNTER_DEF(ctrEnq, mutCtrEnq); int size; int ctrMaxSz; statsobj_t *stats; pthread_mutex_t mut; pthread_cond_t wakeup_worker; }; struct dynstats_wrkrInfo_s { pthread_t tid; /* the worker's thread ID */ }; struct dynstats_buckets_s { struct dynstats_bucket_s *list; statsobj_t *global_stats; pthread_rwlock_t lock; uint8_t initialized; /* background file write worker data */ struct dynstats_file_write_queue_s work_q; uint8_t wrkrRunning; uint8_t wrkrTermState; uint8_t wrkrStarted; struct dynstats_wrkrInfo_s wrkrInfo; }; rsRetVal dynstats_initCnf(dynstats_buckets_t *b); rsRetVal dynstats_processCnf(struct cnfobj *o); dynstats_bucket_t *dynstats_findBucket(const uchar *name); rsRetVal dynstats_inc(dynstats_bucket_t *bucket, uchar *metric); void dynstats_destroyAllBuckets(rsconf_t *cnf); void dynstats_resetExpired(void); rsRetVal dynstatsClassInit(void); #endif /* #ifndef INCLUDED_DYNSTATS_H */ rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_codec.c0000644000000000000000000000013215241075234017157 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.404725241 rsyslog-8.2608.0/runtime/segdisk_codec.c0000664000175000017500000003727415241075234016640 0ustar00rgerrger/* * Queue-private binary codec used by segmentedDisk. * * The format is a sequence of network-byte-order TLVs. Unknown optional * fields can be skipped; field ids with the critical flag must be understood. */ #include "config.h" #include #include #include #include #include #include "segdisk_codec.h" #include "segdisk_crc.h" #include "ruleset.h" #define TLV_HDR_LEN 8u #define TLV_CRITICAL 0x01u #define TLV_MAX_PAYLOAD (128u * 1024u * 1024u) enum tlv_type { TLV_U8 = 1, TLV_U16 = 2, TLV_U32 = 3, TLV_U64 = 4, TLV_BYTES = 5, TLV_TIME = 6 }; enum tlv_field { F_PROTOCOL = 1, F_SEVERITY = 2, F_FACILITY = 3, F_FLAGS = 4, F_GENTIME = 5, F_RECEIVED = 6, F_TIMESTAMP = 7, F_TAG = 8, F_RAWMSG = 9, F_HOSTNAME = 10, F_INPUTNAME = 11, F_RCVFROM = 12, F_RCVFROMIP = 13, F_RCVFROMPORT = 14, F_STRUCTURED_DATA = 15, F_JSON = 16, F_LOCALVARS = 17, F_APPNAME = 18, F_PROCID = 19, F_MSGID = 20, F_UUID = 21, F_RULESET = 22, F_MSG_OFFSET = 23, F_AFTER_PRI_OFFSET = 24, F_PARSE_SUCCESS = 25 }; typedef struct encbuf_s { unsigned char *data; size_t len; size_t cap; } encbuf_t; static void put16(unsigned char *p, uint16_t v) { p[0] = (unsigned char)(v >> 8); p[1] = (unsigned char)v; } static void put32(unsigned char *p, uint32_t v) { p[0] = (unsigned char)(v >> 24); p[1] = (unsigned char)(v >> 16); p[2] = (unsigned char)(v >> 8); p[3] = (unsigned char)v; } static void put64(unsigned char *p, uint64_t v) { put32(p, (uint32_t)(v >> 32)); put32(p + 4, (uint32_t)v); } static uint16_t get16(const unsigned char *p) { return (uint16_t)(((uint16_t)p[0] << 8) | p[1]); } static uint32_t get32(const unsigned char *p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3]; } static uint64_t get64(const unsigned char *p) { return ((uint64_t)get32(p) << 32) | get32(p + 4); } static rsRetVal reserve(encbuf_t *b, size_t add) { if (add > TLV_MAX_PAYLOAD || b->len > TLV_MAX_PAYLOAD - add) return RS_RET_FILE_TOO_LARGE; const size_t need = b->len + add; if (need <= b->cap) return RS_RET_OK; size_t cap = b->cap == 0 ? 1024 : b->cap; while (cap < need) { if (cap > TLV_MAX_PAYLOAD / 2) { cap = TLV_MAX_PAYLOAD; break; } cap *= 2; } unsigned char *next = realloc(b->data, cap); if (next == NULL) return RS_RET_OUT_OF_MEMORY; b->data = next; b->cap = cap; return RS_RET_OK; } static rsRetVal add_tlv( encbuf_t *b, uint16_t field, unsigned char type, unsigned char flags, const void *data, size_t len) { if (len > UINT32_MAX) return RS_RET_FILE_TOO_LARGE; rsRetVal r = reserve(b, TLV_HDR_LEN + len); if (r != RS_RET_OK) return r; put16(b->data + b->len, field); b->data[b->len + 2] = type; b->data[b->len + 3] = flags; put32(b->data + b->len + 4, (uint32_t)len); if (len != 0) memcpy(b->data + b->len + TLV_HDR_LEN, data, len); b->len += TLV_HDR_LEN + len; return RS_RET_OK; } static rsRetVal add_u8(encbuf_t *b, uint16_t f, uint8_t v) { return add_tlv(b, f, TLV_U8, 0, &v, 1); } static rsRetVal add_u16(encbuf_t *b, uint16_t f, uint16_t v) { unsigned char d[2]; put16(d, v); return add_tlv(b, f, TLV_U16, 0, d, sizeof(d)); } static rsRetVal add_u32(encbuf_t *b, uint16_t f, uint32_t v) { unsigned char d[4]; put32(d, v); return add_tlv(b, f, TLV_U32, 0, d, sizeof(d)); } static rsRetVal add_u64(encbuf_t *b, uint16_t f, uint64_t v) { unsigned char d[8]; put64(d, v); return add_tlv(b, f, TLV_U64, 0, d, sizeof(d)); } static rsRetVal add_bytes(encbuf_t *b, uint16_t f, const void *p, size_t len) { return p == NULL ? RS_RET_OK : add_tlv(b, f, TLV_BYTES, 0, p, len); } static rsRetVal add_time(encbuf_t *b, uint16_t f, const struct syslogTime *t) { unsigned char d[20] = {0}; d[0] = t->timeType; d[1] = t->month; d[2] = t->day; d[3] = t->wday; d[4] = t->hour; d[5] = t->minute; d[6] = t->second; d[7] = t->secfracPrecision; d[8] = t->OffsetMinute; d[9] = t->OffsetHour; d[10] = (unsigned char)t->OffsetMode; d[11] = t->inUTC; put16(d + 12, (uint16_t)t->year); put32(d + 14, (uint32_t)t->secfrac); return add_tlv(b, f, TLV_TIME, 0, d, sizeof(d)); } static rsRetVal add_json(encbuf_t *b, uint16_t f, smsg_t *msg, struct json_object *json) { char *copy = NULL; if (json == NULL) return RS_RET_OK; MsgLock(msg); const char *text = json_object_to_json_string_ext(json, JSON_C_TO_STRING_PLAIN); if (text != NULL) copy = strdup(text); MsgUnlock(msg); if (copy == NULL) return RS_RET_OUT_OF_MEMORY; const rsRetVal r = add_bytes(b, f, copy, strlen(copy)); free(copy); return r; } static rsRetVal add_cstr(encbuf_t *b, uint16_t f, smsg_t *msg, cstr_t *text) { if (text == NULL) return RS_RET_OK; MsgLock(msg); const rsRetVal r = add_bytes(b, f, text->pBuf, text->iStrLen); MsgUnlock(msg); return r; } rsRetVal segdiskCodecEncode(smsg_t *msg, unsigned char **buf, size_t *len) { encbuf_t b = {0}; uchar *text; int textlen; rsRetVal r; #define ADD(call) \ do { \ if ((r = (call)) != RS_RET_OK) goto fail; \ } while (0) if (msg == NULL || buf == NULL || len == NULL) return RS_RET_PARAM_ERROR; ADD(add_u16(&b, F_PROTOCOL, (uint16_t)msg->iProtocolVersion)); ADD(add_u16(&b, F_SEVERITY, msg->iSeverity)); ADD(add_u16(&b, F_FACILITY, msg->iFacility)); ADD(add_u32(&b, F_FLAGS, (uint32_t)msg->msgFlags)); ADD(add_u64(&b, F_GENTIME, (uint64_t)(int64_t)msg->ttGenTime)); ADD(add_time(&b, F_RECEIVED, &msg->tRcvdAt)); ADD(add_time(&b, F_TIMESTAMP, &msg->tTIMESTAMP)); getTAG(msg, &text, &textlen, LOCK_MUTEX); ADD(add_bytes(&b, F_TAG, text, (size_t)textlen)); getRawMsg(msg, &text, &textlen); ADD(add_bytes(&b, F_RAWMSG, text, (size_t)textlen)); ADD(add_bytes(&b, F_HOSTNAME, msg->pszHOSTNAME, (size_t)msg->iLenHOSTNAME)); getInputName(msg, &text, &textlen); ADD(add_bytes(&b, F_INPUTNAME, text, (size_t)textlen)); text = getRcvFrom(msg); ADD(add_bytes(&b, F_RCVFROM, text, strlen((char *)text))); text = getRcvFromIP(msg); ADD(add_bytes(&b, F_RCVFROMIP, text, strlen((char *)text))); text = getRcvFromPort(msg); ADD(add_bytes(&b, F_RCVFROMPORT, text, strlen((char *)text))); if (msg->pszStrucData != NULL) ADD(add_bytes(&b, F_STRUCTURED_DATA, msg->pszStrucData, msg->lenStrucData)); ADD(add_json(&b, F_JSON, msg, msg->json)); ADD(add_json(&b, F_LOCALVARS, msg, msg->localvars)); ADD(add_cstr(&b, F_APPNAME, msg, msg->pCSAPPNAME)); ADD(add_cstr(&b, F_PROCID, msg, msg->pCSPROCID)); ADD(add_cstr(&b, F_MSGID, msg, msg->pCSMSGID)); if (msg->pszUUID != NULL) ADD(add_bytes(&b, F_UUID, msg->pszUUID, strlen((char *)msg->pszUUID))); if (msg->pRuleset != NULL) { text = rulesetGetName(msg->pRuleset); ADD(add_bytes(&b, F_RULESET, text, strlen((char *)text))); } ADD(add_u32(&b, F_MSG_OFFSET, (uint32_t)msg->offMSG)); ADD(add_u32(&b, F_AFTER_PRI_OFFSET, (uint32_t)msg->offAfterPRI)); ADD(add_u8(&b, F_PARSE_SUCCESS, (uint8_t)msg->bParseSuccess)); *buf = b.data; *len = b.len; return RS_RET_OK; fail: free(b.data); return r; #undef ADD } static rsRetVal dup_text(const unsigned char *p, uint32_t len, char **out) { char *s; if ((s = malloc((size_t)len + 1)) == NULL) return RS_RET_OUT_OF_MEMORY; memcpy(s, p, len); s[len] = '\0'; *out = s; return RS_RET_OK; } static rsRetVal decode_time(const unsigned char *p, uint32_t len, struct syslogTime *t) { if (len != 20) return RS_RET_INVALID_VALUE; memset(t, 0, sizeof(*t)); t->timeType = p[0]; t->month = p[1]; t->day = p[2]; t->wday = p[3]; t->hour = p[4]; t->minute = p[5]; t->second = p[6]; t->secfracPrecision = p[7]; t->OffsetMinute = p[8]; t->OffsetHour = p[9]; t->OffsetMode = (char)p[10]; t->inUTC = p[11]; t->year = (short)get16(p + 12); t->secfrac = (int)get32(p + 14); return RS_RET_OK; } rsRetVal segdiskCodecDecode(const unsigned char *buf, size_t len, smsg_t **out) { smsg_t *msg = NULL; uint32_t seen = 0; size_t pos = 0; rsRetVal r = msgConstructForDeserializer(&msg); if (r != RS_RET_OK) return r; while (pos < len) { if (len - pos < TLV_HDR_LEN) { r = RS_RET_INVALID_VALUE; goto fail; } const uint16_t field = get16(buf + pos); const unsigned char type = buf[pos + 2]; const unsigned char flags = buf[pos + 3]; const uint32_t n = get32(buf + pos + 4); pos += TLV_HDR_LEN; if (n > TLV_MAX_PAYLOAD || n > len - pos) { r = RS_RET_INVALID_VALUE; goto fail; } const unsigned char *p = buf + pos; char *s = NULL; if (field >= 1 && field <= 31) { const uint32_t mask = 1u << (field - 1); if ((seen & mask) != 0) { r = RS_RET_INVALID_VALUE; goto fail; } seen |= mask; } #define NEED(t, nbytes) \ do { \ if (type != (t) || n != (nbytes)) { \ r = RS_RET_INVALID_VALUE; \ goto fail; \ } \ } while (0) #define NEED_TYPE(t) \ do { \ if (type != (t)) { \ r = RS_RET_INVALID_VALUE; \ goto fail; \ } \ } while (0) #define TEXT_CALL(call) \ do { \ NEED_TYPE(TLV_BYTES); \ if ((r = dup_text(p, n, &s)) != RS_RET_OK) goto fail; \ r = (call); \ free(s); \ s = NULL; \ if (r != RS_RET_OK) goto fail; \ } while (0) switch (field) { case F_PROTOCOL: NEED(TLV_U16, 2); setProtocolVersion(msg, get16(p)); break; case F_SEVERITY: NEED(TLV_U16, 2); msg->iSeverity = get16(p); break; case F_FACILITY: NEED(TLV_U16, 2); msg->iFacility = get16(p); break; case F_FLAGS: NEED(TLV_U32, 4); msg->msgFlags = (int)get32(p); break; case F_GENTIME: NEED(TLV_U64, 8); msg->ttGenTime = (time_t)(int64_t)get64(p); break; case F_RECEIVED: NEED(TLV_TIME, 20); if ((r = decode_time(p, n, &msg->tRcvdAt)) != RS_RET_OK) goto fail; break; case F_TIMESTAMP: NEED(TLV_TIME, 20); if ((r = decode_time(p, n, &msg->tTIMESTAMP)) != RS_RET_OK) goto fail; break; case F_TAG: if (type != TLV_BYTES) { r = RS_RET_INVALID_VALUE; goto fail; } MsgSetTAG(msg, p, n); break; case F_RAWMSG: if (type != TLV_BYTES) { r = RS_RET_INVALID_VALUE; goto fail; } MsgSetRawMsg(msg, (const char *)p, n); break; case F_HOSTNAME: if (type != TLV_BYTES) { r = RS_RET_INVALID_VALUE; goto fail; } MsgSetHOSTNAME(msg, p, n); break; case F_INPUTNAME: NEED_TYPE(TLV_BYTES); if ((r = MsgSetInputNameStr(msg, p, n)) != RS_RET_OK) goto fail; break; case F_RCVFROM: NEED_TYPE(TLV_BYTES); if ((r = MsgSetRcvFromText(msg, p, n)) != RS_RET_OK) goto fail; break; case F_RCVFROMIP: NEED_TYPE(TLV_BYTES); if ((r = MsgSetRcvFromIPText(msg, p, n)) != RS_RET_OK) goto fail; break; case F_RCVFROMPORT: NEED_TYPE(TLV_BYTES); if ((r = MsgSetRcvFromPortText(msg, p, n)) != RS_RET_OK) goto fail; break; case F_STRUCTURED_DATA: TEXT_CALL(MsgSetStructuredData(msg, s)); break; case F_JSON: case F_LOCALVARS: { NEED_TYPE(TLV_BYTES); if ((r = dup_text(p, n, &s)) != RS_RET_OK) goto fail; struct json_object *j = json_tokener_parse(s); free(s); s = NULL; if (j == NULL) { r = RS_RET_INVALID_VALUE; goto fail; } if (field == F_JSON) msg->json = j; else msg->localvars = j; break; } case F_APPNAME: TEXT_CALL(MsgSetAPPNAME(msg, s)); break; case F_PROCID: TEXT_CALL(MsgSetPROCID(msg, s)); break; case F_MSGID: TEXT_CALL(MsgSetMSGID(msg, s)); break; case F_UUID: NEED_TYPE(TLV_BYTES); if ((r = dup_text(p, n, &s)) != RS_RET_OK) goto fail; msg->pszUUID = (uchar *)s; s = NULL; break; case F_RULESET: NEED_TYPE(TLV_BYTES); if ((r = dup_text(p, n, &s)) != RS_RET_OK) goto fail; { cstr_t *cs = NULL; if (rsCStrConstructFromszStr(&cs, (uchar *)s) != RS_RET_OK) { free(s); r = RS_RET_OUT_OF_MEMORY; goto fail; } cstrFinalize(cs); r = MsgSetRulesetByName(msg, cs); rsCStrDestruct(&cs); free(s); s = NULL; /* A queued event may outlive the ruleset named by its * original input. Preserve the event and let a NULL * pRuleset select the current default ruleset. */ if (r != RS_RET_OK && r != RS_RET_NOT_FOUND) goto fail; } break; case F_MSG_OFFSET: NEED(TLV_U32, 4); MsgSetMSGoffs(msg, (int)get32(p)); break; case F_AFTER_PRI_OFFSET: NEED(TLV_U32, 4); if ((r = MsgSetAfterPRIOffs(msg, (int)get32(p))) != RS_RET_OK) goto fail; break; case F_PARSE_SUCCESS: NEED(TLV_U8, 1); MsgSetParseSuccess(msg, p[0]); break; default: if ((flags & TLV_CRITICAL) != 0) { r = RS_RET_INVALID_VALUE; goto fail; } break; } #undef NEED #undef NEED_TYPE #undef TEXT_CALL pos += n; } if ((seen & ((1u << (F_RAWMSG - 1)) | (1u << (F_MSG_OFFSET - 1)))) != ((1u << (F_RAWMSG - 1)) | (1u << (F_MSG_OFFSET - 1)))) { r = RS_RET_INVALID_VALUE; goto fail; } *out = msg; return RS_RET_OK; fail: if (msg != NULL) msgDestruct(&msg); return r; } rsyslog-8.2608.0/runtime/PaxHeaders/queue.c0000644000000000000000000000013215241075234015515 xustar0030 mtime=1787067036.607578332 30 atime=1787067036.752581047 30 ctime=1787067794.395725073 rsyslog-8.2608.0/runtime/queue.c0000664000175000017500000070165415241075234015176 0ustar00rgerrger/* queue.c * * This file implements the queue object and its several queueing methods. * * File begun on 2008-01-03 by RGerhards * * There is some in-depth documentation available in doc/dev_queue.html * (and in the web doc set on https://www.rsyslog.com/doc/). Be sure to read it * if you are getting acquainted to the object. * * NOTE: as of 2009-04-22, I have begin to remove the qqueue* prefix from static * function names - this makes it really hard to read and does not provide much * benefit, at least I (now) think so... * * Copyright 2008-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ /** * @file queue.c * @brief This file implements the rsyslog queueing subsystem. * * @section queue_maintenance Important Note on Maintenance * * This header comment contains critical information on the system's * architecture and design philosophy. It is essential that this comment, and * all other relevant documentation, be **updated whenever architectural or * other significant changes are made to the queueing subsystem.** * * Maintaining synchronization between code and documentation is vital for * long-term project health, developer onboarding, and to enable automated * tools and AI agents to accurately analyze the codebase and detect potential * issues arising from undocumented changes. This documentation reflects the * state of the system as of mid-2025, based on a battle-proven design that * originated circa 2004. * * @section queue_architecture Architectural Overview and Design Philosophy * * The rsyslog queueing system is a fundamental component for providing both * performance and reliability. It is built on a powerful abstraction: a queue * can be placed at two key points in the message processing pipeline: * * 1. **Ruleset Queue (Main Message Queue):** Each ruleset has a single queue * that buffers messages received from inputs *before* they are processed * by the ruleset's filters. This decouples message ingestion from filter * processing, allowing rsyslog to handle massive input bursts without * losing messages. The queue for the default ruleset is often referred * to by its historical name, the "main message queue". * * 2. **Action Queue:** Each action within a ruleset can have its own dedicated * queue. This decouples the filter engine from the output action (e.g., * writing to a file or sending over the network). * * This system's design is a testament to operator-centric control, providing * a sophisticated toolkit of compromises. This contrasts sharply with modern * "WAL-only" log shippers, making rsyslog uniquely versatile. * * * @subsection queue_types Queue Types * * Rsyslog offers multiple queue types, each with a specific performance and * reliability profile. They are listed here from most lightweight to most * robust. * * 1. **Direct (The "No-Queue" Queue)** * - **Behavior:** The default for all **action queues**. No buffering occurs. The * worker thread from the parent queue (usually the ruleset's queue) * executes the action's logic directly. * - **Use Case:** For fast, non-blocking, local actions (e.g., `omfile`). * - **Warning:** If a Direct-queued action blocks, it stalls the worker * thread, potentially halting all processing for that worker. * * 2. **In-Memory (LinkedList and FixedArray)** * - **Behavior:** Buffers messages in RAM. Extremely fast but offers no * persistence across restarts. * - **Sub-Types:** * - `LinkedList`: The recommended default for most in-memory queues. It is * memory-efficient, allocating space only for messages it holds. * - `FixedArray`: A legacy option that pre-allocates a static array of * pointers. It can be slightly faster under constant load but is * less memory-efficient. It remains the default for ruleset queues. * - **Use Case:** High-performance buffering where a potential loss of * in-flight messages on crash is acceptable. * * 3. **Disk (The "Pure-Disk" Queue)** * - **Behavior:** Writes every single message to a disk-based queue structure * before acknowledging the enqueue operation. This queue provides a * **"Limited Duplication"** guarantee, not a simple "at-least-once". * - **The `.qi` Checkpoint File:** The queue's state (read/write pointers) * is persisted in a `.qi` file. The `queue.checkpointInterval` parameter * dictates how often this file is updated, allowing the user to tune * the trade-off between I/O performance and duplication risk. A value * of `1` provides near-exactly-once delivery, essential for "dumb" * (non-deduplicating) receivers. * - **Use Case:** For audit-grade logging chains where no message loss can * be tolerated, even in the case of a power failure or ungraceful shutdown. * * 4. **Disk-Assisted (DA) (The Hybrid "Best-of-Both-Worlds" Queue)** * - **Behavior:** This is the most sophisticated queue type. It acts as a * multi-stage defense system against data loss. * - **Stage 1: In-Memory First:** By default, it operates as a high-speed * `LinkedList` queue with zero disk I/O. * - **Stage 2: Disk Spooling:** If the in-memory queue exceeds its * `highwatermark` (e.g., due to downstream backpressure), it seamlessly * activates its internal **Disk Queue** and begins spooling messages * to disk. This provides resilience to transient failures without the * constant performance penalty of a pure Disk queue. The disk portion * operates with its own "Limited Duplication" guarantee. * - **Stage 3: Load Shedding:** If all buffers (memory and disk) are full, * the queue hits the `queue.discardMark`. It can then begin to discard * messages based on severity (`queue.discardSeverity`), preserving * critical logs during a total system overload. * - **Use Case:** The recommended choice for any potentially unreliable or * slow action, or for a ruleset queue that needs to survive downstream * outages. * * 5. **Segmented Disk** * - **Behavior:** A pure-disk queue backed by a log-structured segmented * store. It uses one serial writer, sealed segment files, and durable * per-segment commit offsets. It can be selected as the disk store used by * disk-assisted (DA) queues via DA engine/store selection. * - **Use Case:** Durable queueing with segmented-store mechanics, including * DA deployments that use the segmented disk store. * * * @subsection comparison_to_wal Rsyslog's "Bounded Queue" vs. a WAL's "Unbounded Stream" * * It is critical to understand that rsyslog's disk-based queues implement a * **Bounded FIFO Queue**, which is architecturally different from the * **Unbounded Stream** model of a Write-Ahead Log (WAL) found in tools like * Fluent Bit or Vector. * * - **Rsyslog's Model:** The `.qi` file checkpoints the queue's *structure*, * containing two primary tuples: `write_ptr = (segment, offset)` and * `read_ptr = (segment, offset)`. This defines the queue's boundaries. * Consumption is a destructive action that advances the `read_ptr`. On a * graceful restart (e.g., K8s `SIGTERM`), DA queues flush memory to disk, * ensuring **zero data loss**. On a crash, only the `checkpointInterval`-worth * of messages are at risk of replay. This fine-grained control makes it safe * for both smart and dumb receivers. **Note:** A known operational risk is * that the current implementation does not gracefully handle a missing or * corrupt `.qi` file in conjunction with pre-existing queue segment files. * This can lead to startup failures or inconsistent state and is a top * priority for future reliability enhancements. * * * - **WAL Model:** A WAL is a simple, append-only log. The checkpoint is just * a consumer's *offset*. On restart, a WAL-based shipper replays *all data* * from the last offset, which can be massive. This model mandates a smart, * idempotent receiver and is fundamentally unsafe for dumb endpoints.* * @subsection naming_convention Historical Naming: queue vs. qqueue * * Throughout the code, you will see types and variables prefixed with `qqueue` * (e.g., `qqueue_t`). This is the result of a historical name change. * Originally, these were named `queue`, but this caused symbol clashes on some * platforms (e.g., AIX) where `queue` is a reserved name in system libraries. * The name was changed to `qqueue` ("queue object for the queueing subsystem") * to ensure portability. * * * @section conclusion Summary for Developers * * When working with this code, remember that you are not dealing with a simple * log appender. You are maintaining a transactional, persistent FIFO queue. * The logic surrounding the `.qi` file, segment files, and the read/write * pointers is designed to provide robust, tunable delivery guarantees that are * a core feature of rsyslog. This makes it more versatile than pure WAL-based * log shippers. * */ #include "config.h" #include #include #include #include #include #include #include #include #include /* required for HP UX */ #include #include #include #include #include #include #include "rsyslog.h" #include "queue.h" #include "stringbuf.h" #include "srUtils.h" #include "obj.h" #include "wtp.h" #include "wti.h" #include "msg.h" #include "obj.h" #include "atomic.h" #include "errmsg.h" #include "datetime.h" #include "unicode-helper.h" #include "statsobj.h" #include "parserif.h" #include "rsconf.h" #ifdef OS_SOLARIS #include #endif /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(glbl) DEFobjCurrIf(strm) DEFobjCurrIf(datetime) DEFobjCurrIf(statsobj) #if __GNUC__ >= 8 #pragma GCC diagnostic ignored "-Wcast-function-type" // TODO: investigate further! #endif /* if __GNUC__ >= 8 */ #ifdef ENABLE_IMDIAG unsigned int iOverallQueueSize = 0; #endif #define OVERSIZE_QUEUE_WATERMARK 500000 /* when is a queue considered to be "overly large"? */ #define MAX_DISK_QUEUE_FILES 10000000 /* maximum file number for disk queues */ #define DISKQUEUE_CORRUPTION_RESYNC_MAX_BYTES (1024 * 1024) /* forward-definitions */ static rsRetVal doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg); static rsRetVal qqueueChkPersist(qqueue_t *pThis, int nUpdates); static rsRetVal RateLimiter(qqueue_t *pThis); static rsRetVal qqueueChkStopWrkrDA(qqueue_t *pThis); static rsRetVal GetDeqBatchSize(qqueue_t *pThis, int *pVal); static rsRetVal ConsumerDA(qqueue_t *pThis, wti_t *pWti); static rsRetVal batchProcessed(qqueue_t *pThis, wti_t *pWti); static rsRetVal qqueueMultiEnqObjNonDirect(qqueue_t *pThis, multi_submit_t *pMultiSub); static rsRetVal qqueueMultiEnqObjDirect(qqueue_t *pThis, multi_submit_t *pMultiSub); static rsRetVal qAddDirect(qqueue_t *pThis, smsg_t *pMsg); static rsRetVal qDestructDirect(qqueue_t __attribute__((unused)) * pThis); static rsRetVal qConstructDirect(qqueue_t __attribute__((unused)) * pThis); static rsRetVal qConstructDisk(qqueue_t *pThis); static rsRetVal qDestructDisk(qqueue_t *pThis); static rsRetVal qConstructSegDisk(qqueue_t *pThis); static rsRetVal qDestructSegDisk(qqueue_t *pThis); static rsRetVal qAddSegDisk(qqueue_t *pThis, smsg_t *pMsg); static rsRetVal qDeqBatchSegDisk(qqueue_t *pThis, batch_t *batch, int max, int *skipped); static rsRetVal qCompleteBatchSegDisk(qqueue_t *pThis, batch_t *batch, int *committed, int *retried); rsRetVal qqueueSetSpoolDir(qqueue_t *pThis, uchar *pszSpoolDir, int lenSpoolDir); static rsRetVal handleReadSeekError(rsRetVal seekRet, qqueue_t *pThis, const char *streamName, sbool *pReadSeekFailed); static void alignReadDeqToWrite(qqueue_t *pThis); static void recoverFromInvalidQi(qqueue_t *pThis, int wr_fd, int64_t wr_offs); static void qqueueDestroyDiskStreams(qqueue_t *pThis); static rsRetVal qqueueSwitchToInMemoryEmergency(qqueue_t *pThis); static rsRetVal qqueueResetDiskQueueAfterCorruption(qqueue_t *pThis); static rsRetVal msgConstructFromVoid(void **ppThis); static rsRetVal msgDeserializeFromVoid(void *pObj, strm_t *pStrm); /* some constants for queuePersist () */ #define QUEUE_CHECKPOINT 1 #define QUEUE_NO_CHECKPOINT 0 /* tables for interfacing with the v6 config system */ static struct cnfparamdescr cnfpdescr[] = {{"queue.filename", eCmdHdlrGetWord, 0}, {"queue.spooldirectory", eCmdHdlrGetWord, 0}, {"queue.size", eCmdHdlrSize, 0}, {"queue.dequeuebatchsize", eCmdHdlrInt, 0}, {"queue.mindequeuebatchsize", eCmdHdlrInt, 0}, {"queue.mindequeuebatchsize.timeout", eCmdHdlrInt, 0}, {"queue.maxdiskspace", eCmdHdlrSize, 0}, {"queue.highwatermark", eCmdHdlrInt, 0}, {"queue.lowwatermark", eCmdHdlrInt, 0}, {"queue.fulldelaymark", eCmdHdlrInt, 0}, {"queue.lightdelaymark", eCmdHdlrInt, 0}, {"queue.discardmark", eCmdHdlrInt, 0}, {"queue.discardseverity", eCmdHdlrFacility, 0}, {"queue.checkpointinterval", eCmdHdlrInt, 0}, {"queue.syncqueuefiles", eCmdHdlrBinary, 0}, {"queue.type", eCmdHdlrQueueType, 0}, {"queue.diskqueuetype", eCmdHdlrGetWord, 0}, {"queue.diskqueueautoupgrade", eCmdHdlrBinary, 0}, {"queue.diskqueueidletimeout", eCmdHdlrInt, 0}, {"queue.workerthreads", eCmdHdlrPositiveInt, 0}, {"queue.timeoutshutdown", eCmdHdlrInt, 0}, {"queue.timeoutactioncompletion", eCmdHdlrInt, 0}, {"queue.timeoutenqueue", eCmdHdlrInt, 0}, {"queue.timeoutworkerthreadshutdown", eCmdHdlrInt, 0}, {"queue.workerthreadminimummessages", eCmdHdlrInt, 0}, {"queue.maxfilesize", eCmdHdlrSize, 0}, {"queue.saveonshutdown", eCmdHdlrBinary, 0}, {"queue.dequeueslowdown", eCmdHdlrInt, 0}, {"queue.dequeuetimebegin", eCmdHdlrInt, 0}, {"queue.dequeuetimeend", eCmdHdlrInt, 0}, {"queue.cry.provider", eCmdHdlrGetWord, 0}, {"queue.samplinginterval", eCmdHdlrInt, 0}, {"queue.takeflowctlfrommsg", eCmdHdlrBinary, 0}, {"queue.oncorruption", eCmdHdlrGetWord, 0}}; static struct cnfparamblk pblk = {CNFPARAMBLK_VERSION, sizeof(cnfpdescr) / sizeof(struct cnfparamdescr), cnfpdescr}; /* support to detect duplicate queue file names */ struct queue_filename { struct queue_filename *next; const char *dirname; const char *filename; }; struct queue_filename *queue_filename_root = NULL; /* debug aid */ #if 0 static inline void displayBatchState(batch_t *pBatch) { int i; for(i = 0 ; i < pBatch->nElem ; ++i) { DBGPRINTF("displayBatchState %p[%d]: %d\n", pBatch, i, pBatch->eltState[i]); } } #endif static rsRetVal qqueuePersist(qqueue_t *pThis, int bIsCheckpoint); /* do cleanup when config is loaded */ void qqueueDoneLoadCnf(void) { struct queue_filename *next, *del; next = queue_filename_root; while (next != NULL) { del = next; next = next->next; free((void *)del->filename); free((void *)del->dirname); free((void *)del); } queue_filename_root = NULL; } /*********************************************************************** * we need a private data structure, the "to-delete" list. As C does * not provide any partly private data structures, we implement this * structure right here inside the module. * Note that this list must always be kept sorted based on a unique * dequeue ID (which is monotonically increasing). * rgerhards, 2009-05-18 ***********************************************************************/ /* generate next uniqueue dequeue ID. Note that uniqueness is only required * on a per-queue basis and while this instance runs. So a stricly monotonically * increasing counter is sufficient (if enough bits are used). */ static inline qDeqID getNextDeqID(qqueue_t *pQueue) { ISOBJ_TYPE_assert(pQueue, qqueue); return pQueue->deqIDAdd++; } /* return the top element of the to-delete list or NULL, if the * list is empty. */ static toDeleteLst_t *tdlPeek(qqueue_t *pQueue) { ISOBJ_TYPE_assert(pQueue, qqueue); return pQueue->toDeleteLst; } /* remove the top element of the to-delete list. Nothing but the * element itself is destroyed. Must not be called when the list * is empty. */ static rsRetVal tdlPop(qqueue_t *pQueue) { toDeleteLst_t *pRemove; DEFiRet; ISOBJ_TYPE_assert(pQueue, qqueue); assert(pQueue->toDeleteLst != NULL); pRemove = pQueue->toDeleteLst; pQueue->toDeleteLst = pQueue->toDeleteLst->pNext; free(pRemove); RETiRet; } /* Add a new to-delete list entry. The function allocates the data * structure, populates it with the values provided and links the new * element into the correct place inside the list. */ static rsRetVal tdlAdd(qqueue_t *pQueue, qDeqID deqID, int nElemDeq) { toDeleteLst_t *pNew; toDeleteLst_t *pPrev; toDeleteLst_t *pCur; DEFiRet; ISOBJ_TYPE_assert(pQueue, qqueue); assert(pQueue->toDeleteLst != NULL); CHKmalloc(pNew = malloc(sizeof(toDeleteLst_t))); pNew->deqID = deqID; pNew->nElemDeq = nElemDeq; /* now find right spot */ pPrev = NULL; for (pCur = pQueue->toDeleteLst; pCur != NULL && deqID > pCur->deqID; pCur = pCur->pNext) { pPrev = pCur; /*JUST SEARCH*/; } if (pPrev == NULL) { pNew->pNext = pCur; pQueue->toDeleteLst = pNew; } else { pNew->pNext = pCur; pPrev->pNext = pNew; } finalize_it: RETiRet; } static rsRetVal validateQueueSpoolDir(qqueue_t *pThis) { DEFiRet; if (pThis->pszSpoolDir != NULL && pThis->lenSpoolDir == 0) { parser_errmsg("queue.spooldirectory must not be empty"); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } finalize_it: RETiRet; } /* methods */ static const char *getQueueTypeName(queueType_t t) { const char *r; switch (t) { case QUEUETYPE_FIXED_ARRAY: r = "FixedArray"; break; case QUEUETYPE_LINKEDLIST: r = "LinkedList"; break; case QUEUETYPE_DISK: r = "Disk"; break; case QUEUETYPE_DIRECT: r = "Direct"; break; case QUEUETYPE_SEGMENTED_DISK: r = "segmentedDisk"; break; default: r = "invalid/unknown queue mode"; break; } return r; } void qqueueDbgPrint(qqueue_t *pThis) { dbgoprint((obj_t *)pThis, "parameter dump:\n"); dbgoprint((obj_t *)pThis, "queue.filename '%s'\n", (pThis->pszFilePrefix == NULL) ? "[NONE]" : (char *)pThis->pszFilePrefix); dbgoprint((obj_t *)pThis, "queue.size: %d\n", pThis->iMaxQueueSize); dbgoprint((obj_t *)pThis, "queue.dequeuebatchsize: %d\n", pThis->iDeqBatchSize); dbgoprint((obj_t *)pThis, "queue.mindequeuebatchsize: %d\n", pThis->iMinDeqBatchSize); dbgoprint((obj_t *)pThis, "queue.mindequeuebatchsize.timeout: %d\n", pThis->toMinDeqBatchSize); dbgoprint((obj_t *)pThis, "queue.maxdiskspace: %lld\n", pThis->sizeOnDiskMax); dbgoprint((obj_t *)pThis, "queue.highwatermark: %d\n", pThis->iHighWtrMrk); dbgoprint((obj_t *)pThis, "queue.lowwatermark: %d\n", pThis->iLowWtrMrk); dbgoprint((obj_t *)pThis, "queue.fulldelaymark: %d\n", pThis->iFullDlyMrk); dbgoprint((obj_t *)pThis, "queue.lightdelaymark: %d\n", pThis->iLightDlyMrk); dbgoprint((obj_t *)pThis, "queue.takeflowctlfrommsg: %d\n", pThis->takeFlowCtlFromMsg); dbgoprint((obj_t *)pThis, "queue.discardmark: %d\n", pThis->iDiscardMrk); dbgoprint((obj_t *)pThis, "queue.discardseverity: %d\n", pThis->iDiscardSeverity); dbgoprint((obj_t *)pThis, "queue.checkpointinterval: %d\n", pThis->iPersistUpdCnt); dbgoprint((obj_t *)pThis, "queue.syncqueuefiles: %d\n", pThis->bSyncQueueFiles); dbgoprint((obj_t *)pThis, "queue.type: %d [%s]\n", pThis->qType, getQueueTypeName(pThis->qType)); dbgoprint((obj_t *)pThis, "queue.workerthreads: %d\n", pThis->iNumWorkerThreads); dbgoprint((obj_t *)pThis, "queue.timeoutshutdown: %d\n", pThis->toQShutdown); dbgoprint((obj_t *)pThis, "queue.timeoutactioncompletion: %d\n", pThis->toActShutdown); dbgoprint((obj_t *)pThis, "queue.timeoutenqueue: %d\n", pThis->toEnq); dbgoprint((obj_t *)pThis, "queue.timeoutworkerthreadshutdown: %d\n", pThis->toWrkShutdown); dbgoprint((obj_t *)pThis, "queue.workerthreadminimummessages: %d\n", pThis->iMinMsgsPerWrkr); dbgoprint((obj_t *)pThis, "queue.maxfilesize: %lld\n", pThis->iMaxFileSize); dbgoprint((obj_t *)pThis, "queue.saveonshutdown: %d\n", pThis->bSaveOnShutdown); dbgoprint((obj_t *)pThis, "queue.dequeueslowdown: %d\n", pThis->iDeqSlowdown); dbgoprint((obj_t *)pThis, "queue.dequeuetimebegin: %d\n", pThis->iDeqtWinFromHr); dbgoprint((obj_t *)pThis, "queue.dequeuetimeend: %d\n", pThis->iDeqtWinToHr); } /* get the physical queue size. Must only be called * while mutex is locked! * rgerhards, 2008-01-29 */ static int getPhysicalQueueSize(qqueue_t *pThis) { const int size = (int)PREFER_FETCH_32BIT(pThis->iQueueSize); if (size == 0 && pThis->qType == QUEUETYPE_SEGMENTED_DISK && pThis->tVars.segdisk != NULL && segdiskStoreMayHaveData(pThis->tVars.segdisk)) return 1; return size; } /* get the logical queue size (that is store size minus logically dequeued elements). * Must only be called while mutex is locked! * rgerhards, 2009-05-19 */ static int getLogicalQueueSize(qqueue_t *pThis) { const int size = pThis->iQueueSize - pThis->nLogDeq; if (size == 0 && pThis->qType == QUEUETYPE_SEGMENTED_DISK && pThis->tVars.segdisk != NULL && segdiskStoreMayHaveData(pThis->tVars.segdisk)) return 1; return size; } static int64 getQueueDiskBytes(qqueue_t *pThis) { if (pThis->qType == QUEUETYPE_SEGMENTED_DISK && pThis->tVars.segdisk != NULL) { segdisk_store_stats_t stats; segdiskStoreGetStats(pThis->tVars.segdisk, &stats); return stats.bytes; } return pThis->tVars.disk.sizeOnDisk; } static int segdiskStatsInt(const uint64_t value) { return value > INT_MAX ? INT_MAX : (int)value; } static void qqueueUpdateSegDiskStats(qqueue_t *pThis) { if (pThis->qType != QUEUETYPE_SEGMENTED_DISK || pThis->tVars.segdisk == NULL) return; segdisk_store_stats_t stats; segdiskStoreGetStats(pThis->tVars.segdisk, &stats); pThis->segdiskBytes = stats.bytes > INT_MAX ? INT_MAX : (stats.bytes < 0 ? 0 : (int)stats.bytes); pThis->segdiskSegments = stats.segments; pThis->segdiskCheckpoints = segdiskStatsInt(stats.checkpoints); pThis->segdiskReplayed = segdiskStatsInt(stats.replayed); pThis->segdiskCorruptionEvents = segdiskStatsInt(stats.corruption_events); pThis->segdiskCorruptionBytes = segdiskStatsInt(stats.corruption_bytes); pThis->segdiskCorruptionRecords = segdiskStatsInt(stats.corruption_records); pThis->segdiskRetryOverageBytes = stats.retry_overage_bytes > INT_MAX ? INT_MAX : (int)stats.retry_overage_bytes; pThis->segdiskRetryOverageMaxBytes = stats.retry_overage_max_bytes > INT_MAX ? INT_MAX : (int)stats.retry_overage_max_bytes; pThis->segdiskStateWrites = segdiskStatsInt(stats.state_writes); pThis->segdiskForcedStateWrites = segdiskStatsInt(stats.forced_state_writes); pThis->segdiskRecoveryBytes = segdiskStatsInt(stats.recovery_bytes); pThis->segdiskRecoveryRecords = segdiskStatsInt(stats.recovery_records); pThis->segdiskStartupPayloadBytes = segdiskStatsInt(stats.startup_payload_bytes_read); pThis->segdiskStartupSegmentFilesProbed = segdiskStatsInt(stats.startup_segment_files_probed); pThis->segdiskRecoveryPending = segdiskStatsInt(stats.recovery_pending); pThis->segdiskCorruptionSegments = segdiskStatsInt(stats.corruption_segments); pThis->segdiskMaterializations = segdiskStatsInt(stats.materializations); pThis->segdiskDematerializations = segdiskStatsInt(stats.dematerializations); pThis->segdiskIdleCleanupFailures = segdiskStatsInt(stats.idle_cleanup_failures); } static rsRetVal qqueueSegDiskIdleTimeout(qqueue_t *pThis) { if (!pThis->segdiskDAChild || pThis->qType != QUEUETYPE_SEGMENTED_DISK || pThis->tVars.segdisk == NULL) return RS_RET_RETRY; if (getLogicalQueueSize(pThis) != 0 || getPhysicalQueueSize(pThis) != 0 || !segdiskStoreCanDematerialize(pThis->tVars.segdisk)) return RS_RET_RETRY; /* A DA child shares its parent queue mutex. The child can become empty * while ConsumerDA still owns a parent batch that has not reached the * child store. The parent physical count includes those logically * dequeued batches until ConsumerDA commits them, so it is the required * transfer-in-flight barrier. Without it, an immediate idle timeout can * remove the child store and a crash can lose the parent-only batch. */ if (pThis->pqParent == NULL || getPhysicalQueueSize(pThis->pqParent) != 0) { return RS_RET_RETRY; } if (pThis->segdiskIdleObservedActivity != pThis->pqParent->daActivityGeneration) { pThis->segdiskIdleObservedActivity = pThis->pqParent->daActivityGeneration; return RS_RET_RETRY; } const rsRetVal r = segdiskStoreDematerialize(pThis->tVars.segdisk); qqueueUpdateSegDiskStats(pThis); if (r != RS_RET_OK) { LogError(0, r, "%s: segmented disk-assisted idle store cleanup failed; will retry", obj.GetName((obj_t *)pThis)); return RS_RET_RETRY; } return RS_RET_OK; } #ifdef ENABLE_IMDIAG rsRetVal qqueueSetSegDiskTestFault(qqueue_t *pThis, const char *point, unsigned int hit_count) { if (pThis == NULL || point == NULL || hit_count == 0) return RS_RET_PARAM_ERROR; qqueue_t *target = pThis->qType == QUEUETYPE_SEGMENTED_DISK ? pThis : pThis->pqDA; if (target == NULL || target->qType != QUEUETYPE_SEGMENTED_DISK || target->tVars.segdisk == NULL) return RS_RET_INVALID_VALUE; d_pthread_mutex_lock(target->mut); const rsRetVal r = segdiskStoreSetTestFault(target->tVars.segdisk, point, hit_count); d_pthread_mutex_unlock(target->mut); return r; } rsRetVal qqueueClearSegDiskTestFault(qqueue_t *pThis) { if (pThis == NULL) return RS_RET_PARAM_ERROR; qqueue_t *target = pThis->qType == QUEUETYPE_SEGMENTED_DISK ? pThis : pThis->pqDA; if (target == NULL || target->qType != QUEUETYPE_SEGMENTED_DISK || target->tVars.segdisk == NULL) return RS_RET_INVALID_VALUE; d_pthread_mutex_lock(target->mut); segdiskStoreClearTestFault(target->tVars.segdisk); d_pthread_mutex_unlock(target->mut); return RS_RET_OK; } #endif static int qqueueIsShutdownImmediate(qqueue_t *const pThis) { return ATOMIC_LOAD_32BIT(&pThis->bShutdownImmediate, &pThis->mutShutdownImmediate); } static void qqueueSetShutdownImmediate(qqueue_t *const pThis, const int value) { ATOMIC_STORE_32BIT(&pThis->bShutdownImmediate, &pThis->mutShutdownImmediate, value); } static void qqueueSetWtiShutdownImmediate(qqueue_t *const pThis, wti_t *const pWti) { pWti->pbShutdownImmediate = &pThis->bShutdownImmediate; #ifndef HAVE_ATOMIC_BUILTINS pWti->pmutShutdownImmediate = &pThis->mutShutdownImmediate; #endif } /* This function drains the queue in cases where this needs to be done. The most probable * reason is a HUP which needs to discard data (because the queue is configured to be lossy). * During a shutdown, this is typically not needed, as the OS frees up resources and does * this much quicker than when we clean up ourselves. -- rgerhards, 2008-10-21 * This function returns void, as it makes no sense to communicate an error back, even if * it happens. * This functions works "around" the regular deque mechanism, because it is only used to * clean up (in cases where message loss is acceptable). */ static void queueDrain(qqueue_t *pThis) { smsg_t *pMsg; assert(pThis != NULL); DBGOPRINT((obj_t *)pThis, "queue (type %d) will lose %d messages, destroying...\n", pThis->qType, pThis->iQueueSize); /* iQueueSize is not decremented by qDel(), so we need to do it ourselves */ while (ATOMIC_DEC_AND_FETCH(&pThis->iQueueSize, &pThis->mutQueueSize) > 0) { pThis->qDeq(pThis, &pMsg); if (pMsg != NULL) { msgDestruct(&pMsg); } pThis->qDel(pThis); } } /* --------------- code for disk-assisted (DA) queue modes -------------------- */ /* returns the number of workers that should be advised at * this point in time. The mutex must be locked when * ths function is called. -- rgerhards, 2008-01-25 */ static rsRetVal qqueueAdviseMaxWorkers(qqueue_t *pThis) { DEFiRet; int iMaxWorkers; ISOBJ_TYPE_assert(pThis, qqueue); if (!pThis->bEnqOnly) { if (pThis->bIsDA && getLogicalQueueSize(pThis) >= pThis->iHighWtrMrk) { DBGOPRINT((obj_t *)pThis, "(re)activating DA worker\n"); wtpAdviseMaxWorkers(pThis->pWtpDA, 1, DENY_WORKER_START_DURING_SHUTDOWN); /* The DA transfer pool intentionally has one worker. */ } if (getLogicalQueueSize(pThis) == 0) { iMaxWorkers = 0; } else if (pThis->iMinMsgsPerWrkr == 0) { iMaxWorkers = 1; } else { iMaxWorkers = getLogicalQueueSize(pThis) / pThis->iMinMsgsPerWrkr + 1; } wtpAdviseMaxWorkers(pThis->pWtpReg, iMaxWorkers, DENY_WORKER_START_DURING_SHUTDOWN); } RETiRet; } /* check if we run in disk-assisted mode and record that * setting for easy (and quick!) access in the future. This * function must only be called from constructors and only * from those that support disk-assisted modes (aka memory- * based queue drivers). * rgerhards, 2008-01-14 */ static rsRetVal qqueueChkIsDA(qqueue_t *pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); if (pThis->pszFilePrefix != NULL) { pThis->bIsDA = 1; DBGOPRINT((obj_t *)pThis, "is disk-assisted, disk will be used on demand\n"); } else { DBGOPRINT((obj_t *)pThis, "is NOT disk-assisted\n"); } RETiRet; } /** * @brief Construct and configure the persistent child of a memory-first DA queue. * * Disk-assisted queues have an in-memory parent and a separate child that * receives overflow. The resolver chooses the child's concrete store before * construction, preserving legacy backlogs and rejecting mixed stores rather * than attempting in-place conversion. For a fresh segmented child, this * routine deliberately leaves the store unmaterialized: the marker, .segq * directory, state file, and disk worker are created only on the first spill. * * The durable marker is published before opening existing data or replacing a * drained classic selection. A fresh child instead carries marker-pending * state until its first append, which keeps normal memory-only operation free * of disk artifacts while still preventing a later engine ambiguity. */ static rsRetVal StartDA(qqueue_t *pThis) { DEFiRet; uchar pszDAQName[128]; ISOBJ_TYPE_assert(pThis, qqueue); const qda_engine_config_t engine_config = { .spool_dir = (const char *)pThis->pszSpoolDir, .file_prefix = (const char *)pThis->pszFilePrefix, .requested = pThis->diskQueueType, .auto_upgrade = pThis->diskQueueAutoUpgrade, .requires_classic_features = pThis->useCryprov || pThis->onCorruption != QUEUE_ON_CORRUPTION_SAFE_MODE, }; qda_engine_result_t engine_result; iRet = qdaEngineResolve(&engine_config, &engine_result); if (iRet != RS_RET_OK) { LogError(0, iRet, "%s: cannot select disk-assisted queue engine for prefix '%s'; classic and segmented data, " "an explicit engine conflict, a malformed engine marker, or unsupported segmented options " "require operator intervention", obj.GetName((obj_t *)pThis), pThis->pszFilePrefix); FINALIZE; } pThis->effectiveDiskQueueType = engine_result.effective; if (pThis->diskQueueType == QDA_ENGINE_AUTO && engine_result.effective == QDA_ENGINE_DISK) { if (engine_result.reason == QDA_REASON_CLASSIC_FEATURE) LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "%s: disk-assisted queue automatically selected the classic disk engine for prefix '%s' " "because classic-only queue options are configured", obj.GetName((obj_t *)pThis), pThis->pszFilePrefix); else LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "%s: disk-assisted queue automatically selected the classic disk engine for prefix '%s' " "because classic queue state is present or retained; set queue.diskQueueAutoUpgrade=\"on\" " "to use segmentedDisk after the classic backlog drains", obj.GetName((obj_t *)pThis), pThis->pszFilePrefix); } /* A marker mismatch is the intentional auto-upgrade case. The resolver * permits it only after proving that the old classic store is empty, so * publish the new selection durably at this restart boundary. */ if (engine_result.classic_data || engine_result.segmented_data || (engine_result.marker_present && engine_result.marker_engine != engine_result.effective)) { CHKiRet(qdaEngineWriteMarker((const char *)pThis->pszSpoolDir, (const char *)pThis->pszFilePrefix, engine_result.effective)); } const queueType_t child_type = engine_result.effective == QDA_ENGINE_SEGMENTED_DISK ? QUEUETYPE_SEGMENTED_DISK : QUEUETYPE_DISK; /* create message queue */ CHKiRet(qqueueConstruct(&pThis->pqDA, child_type, pThis->iNumWorkerThreads, 0, pThis->pConsumer)); /* give it a name */ snprintf((char *)pszDAQName, sizeof(pszDAQName), "%s[DA]", obj.GetName((obj_t *)pThis)); obj.SetName((obj_t *)pThis->pqDA, pszDAQName); /* as the created queue is the same object class, we take the * liberty to access its properties directly. */ pThis->pqDA->pqParent = pThis; pThis->pqDA->segdiskDAChild = child_type == QUEUETYPE_SEGMENTED_DISK; pThis->pqDA->segdiskLazyCreate = pThis->pqDA->segdiskDAChild && !engine_result.segmented_data; pThis->pqDA->daEngineMarkerPending = !engine_result.marker_present && !engine_result.classic_data && !engine_result.segmented_data; pThis->pqDA->diskQueueIdleTimeout = pThis->diskQueueIdleTimeout; CHKiRet(qqueueSetpAction(pThis->pqDA, pThis->pAction)); CHKiRet(qqueueSetsizeOnDiskMax(pThis->pqDA, pThis->sizeOnDiskMax)); CHKiRet(qqueueSetiDeqSlowdown(pThis->pqDA, pThis->iDeqSlowdown)); CHKiRet(qqueueSetMaxFileSize(pThis->pqDA, pThis->iMaxFileSize)); CHKiRet(qqueueSetFilePrefix(pThis->pqDA, pThis->pszFilePrefix, pThis->lenFilePrefix)); CHKiRet(qqueueSetSpoolDir(pThis->pqDA, pThis->pszSpoolDir, pThis->lenSpoolDir)); CHKiRet(qqueueSetiPersistUpdCnt(pThis->pqDA, pThis->iPersistUpdCnt)); CHKiRet(qqueueSetbSyncQueueFiles(pThis->pqDA, pThis->bSyncQueueFiles)); CHKiRet(qqueueSettoActShutdown(pThis->pqDA, pThis->toActShutdown)); CHKiRet(qqueueSettoEnq(pThis->pqDA, pThis->toEnq)); CHKiRet(qqueueSetiDeqtWinFromHr(pThis->pqDA, pThis->iDeqtWinFromHr)); CHKiRet(qqueueSetiDeqtWinToHr(pThis->pqDA, pThis->iDeqtWinToHr)); CHKiRet(qqueueSettoQShutdown(pThis->pqDA, pThis->toQShutdown)); CHKiRet(qqueueSetiHighWtrMrk(pThis->pqDA, 0)); CHKiRet(qqueueSetiDiscardMrk(pThis->pqDA, 0)); pThis->pqDA->iDeqBatchSize = pThis->iDeqBatchSize; pThis->pqDA->iMinDeqBatchSize = pThis->iMinDeqBatchSize; pThis->pqDA->iMinMsgsPerWrkr = pThis->iMinMsgsPerWrkr; pThis->pqDA->iLowWtrMrk = pThis->iLowWtrMrk; pThis->pqDA->onCorruption = pThis->onCorruption; if (pThis->useCryprov && child_type == QUEUETYPE_DISK) { /* hand over cryprov to DA queue - in-mem queue does no longer need it * and DA queue will be kept active from now on until termination. */ pThis->pqDA->useCryprov = pThis->useCryprov; pThis->pqDA->cryprov = pThis->cryprov; pThis->pqDA->cryprovData = pThis->cryprovData; pThis->pqDA->cryprovName = pThis->cryprovName; pThis->pqDA->cryprovNameFull = pThis->cryprovNameFull; /* reset memory queue parameters */ pThis->useCryprov = 0; /* pThis->cryprov cannot and need not be reset, is structure */ pThis->cryprovData = NULL; pThis->cryprovName = NULL; pThis->cryprovNameFull = NULL; } iRet = qqueueStart(runConf, pThis->pqDA); /* file not found is expected, that means it is no previous QIF available */ if (iRet != RS_RET_OK && iRet != RS_RET_FILE_NOT_FOUND) { errno = 0; /* else an errno is shown in errmsg! */ LogError(errno, iRet, "error starting up disk queue, using pure in-memory mode"); pThis->bIsDA = 0; /* disable memory mode */ FINALIZE; /* something is wrong */ } DBGOPRINT((obj_t *)pThis, "DA queue initialized, disk queue 0x%lx\n", qqueueGetID(pThis->pqDA)); finalize_it: if (iRet != RS_RET_OK) { const rsRetVal startup_error = iRet; if (pThis->pqDA != NULL) { qqueueDestruct(&pThis->pqDA); } pThis->bIsDA = 0; LogError(0, startup_error, "%s: error creating disk queue - giving up.", obj.GetName((obj_t *)pThis)); } RETiRet; } /* initiate DA mode * param bEnqOnly tells if the disk queue is to be run in enqueue-only mode. This may * be needed during shutdown of memory queues which need to be persisted to disk. * If this function fails (should not happen), DA mode is not turned on. * rgerhards, 2008-01-16 */ static rsRetVal ATTR_NONNULL() InitDA(qqueue_t *const pThis, const int bLockMutex) { DEFiRet; uchar pszBuf[64]; size_t lenBuf; ISOBJ_TYPE_assert(pThis, qqueue); if (bLockMutex == LOCK_MUTEX) { d_pthread_mutex_lock(pThis->mut); } /* check if we already have a DA worker pool. If not, initiate one. Please note that the * pool is created on first need but never again destructed (until the queue is). This * is intentional. We assume that when we need it once, we may also need it on another * occasion. Resources used are quite minimal when no worker is running. * rgerhards, 2008-01-24 * NOTE: this is the DA worker *pool*, not the DA queue! */ lenBuf = snprintf((char *)pszBuf, sizeof(pszBuf), "%s:DAwpool", obj.GetName((obj_t *)pThis)); CHKiRet(wtpConstruct(&pThis->pWtpDA)); CHKiRet(wtpSetDbgHdr(pThis->pWtpDA, pszBuf, lenBuf)); CHKiRet(wtpSetpfChkStopWrkr(pThis->pWtpDA, (rsRetVal(*)(void *pUsr, int))qqueueChkStopWrkrDA)); CHKiRet(wtpSetpfGetDeqBatchSize(pThis->pWtpDA, (rsRetVal(*)(void *pUsr, int *))GetDeqBatchSize)); CHKiRet(wtpSetpfDoWork(pThis->pWtpDA, (rsRetVal(*)(void *pUsr, void *pWti))ConsumerDA)); CHKiRet(wtpSetpfObjProcessed(pThis->pWtpDA, (rsRetVal(*)(void *pUsr, wti_t *pWti))batchProcessed)); CHKiRet(wtpSetpmutUsr(pThis->pWtpDA, pThis->mut)); CHKiRet(wtpSetiNumWorkerThreads(pThis->pWtpDA, 1)); CHKiRet(wtpSettoWrkShutdown(pThis->pWtpDA, pThis->toWrkShutdown)); CHKiRet(wtpSetpUsr(pThis->pWtpDA, pThis)); CHKiRet(wtpConstructFinalize(pThis->pWtpDA)); /* if we reach this point, we have a "good" DA worker pool */ /* now construct the actual queue (if it does not already exist) */ if (pThis->pqDA == NULL) { CHKiRet(StartDA(pThis)); } finalize_it: if (iRet != RS_RET_OK) pThis->bIsDA = 0; if (bLockMutex == LOCK_MUTEX) { d_pthread_mutex_unlock(pThis->mut); } RETiRet; } /* --------------- end code for disk-assisted queue modes -------------------- */ /* Now, we define type-specific handlers. The provide a generic functionality, * but for this specific type of queue. The mapping to these handlers happens during * queue construction. Later on, handlers are called by pointers present in the * queue instance object. */ /* -------------------- fixed array -------------------- */ static rsRetVal qConstructFixedArray(qqueue_t *pThis) { DEFiRet; assert(pThis != NULL); if (pThis->iMaxQueueSize == 0) ABORT_FINALIZE(RS_RET_QSIZE_ZERO); if ((pThis->tVars.farray.pBuf = malloc(sizeof(void *) * pThis->iMaxQueueSize)) == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pThis->tVars.farray.deqhead = 0; pThis->tVars.farray.head = 0; pThis->tVars.farray.tail = 0; qqueueChkIsDA(pThis); finalize_it: RETiRet; } static rsRetVal qDestructFixedArray(qqueue_t *pThis) { DEFiRet; assert(pThis != NULL); queueDrain(pThis); /* discard any remaining queue entries */ free(pThis->tVars.farray.pBuf); RETiRet; } static rsRetVal qAddFixedArray(qqueue_t *pThis, smsg_t *in) { DEFiRet; assert(pThis != NULL); pThis->tVars.farray.pBuf[pThis->tVars.farray.tail] = in; pThis->tVars.farray.tail++; if (pThis->tVars.farray.tail == pThis->iMaxQueueSize) pThis->tVars.farray.tail = 0; RETiRet; } static rsRetVal qDeqFixedArray(qqueue_t *pThis, smsg_t **out) { DEFiRet; assert(pThis != NULL); *out = (void *)pThis->tVars.farray.pBuf[pThis->tVars.farray.deqhead]; pThis->tVars.farray.deqhead++; if (pThis->tVars.farray.deqhead == pThis->iMaxQueueSize) pThis->tVars.farray.deqhead = 0; RETiRet; } static rsRetVal qDelFixedArray(qqueue_t *pThis) { DEFiRet; assert(pThis != NULL); pThis->tVars.farray.head++; if (pThis->tVars.farray.head == pThis->iMaxQueueSize) pThis->tVars.farray.head = 0; RETiRet; } /* -------------------- linked list -------------------- */ static rsRetVal qConstructLinkedList(qqueue_t *pThis) { DEFiRet; assert(pThis != NULL); pThis->tVars.linklist.pDeqRoot = NULL; pThis->tVars.linklist.pDelRoot = NULL; pThis->tVars.linklist.pLast = NULL; qqueueChkIsDA(pThis); RETiRet; } static rsRetVal qDestructLinkedList(qqueue_t __attribute__((unused)) * pThis) { DEFiRet; queueDrain(pThis); /* discard any remaining queue entries */ /* with the linked list type, there is nothing left to do here. The * reason is that there are no dynamic elements for the list itself. */ RETiRet; } static rsRetVal qAddLinkedList(qqueue_t *pThis, smsg_t *pMsg) { qLinkedList_t *pEntry; DEFiRet; CHKmalloc((pEntry = (qLinkedList_t *)malloc(sizeof(qLinkedList_t)))); pEntry->pNext = NULL; pEntry->pMsg = pMsg; if (pThis->tVars.linklist.pDelRoot == NULL) { pThis->tVars.linklist.pDelRoot = pThis->tVars.linklist.pDeqRoot = pThis->tVars.linklist.pLast = pEntry; } else { pThis->tVars.linklist.pLast->pNext = pEntry; pThis->tVars.linklist.pLast = pEntry; } if (pThis->tVars.linklist.pDeqRoot == NULL) { pThis->tVars.linklist.pDeqRoot = pEntry; } finalize_it: RETiRet; } static rsRetVal qDeqLinkedList(qqueue_t *pThis, smsg_t **ppMsg) { qLinkedList_t *pEntry; DEFiRet; pEntry = pThis->tVars.linklist.pDeqRoot; if (pEntry != NULL) { *ppMsg = pEntry->pMsg; pThis->tVars.linklist.pDeqRoot = pEntry->pNext; } else { /* Check and return NULL for linklist.pDeqRoot */ dbgprintf("qDeqLinkedList: pDeqRoot is NULL!\n"); *ppMsg = NULL; pThis->tVars.linklist.pDeqRoot = NULL; } RETiRet; } static rsRetVal qDelLinkedList(qqueue_t *pThis) { qLinkedList_t *pEntry; DEFiRet; pEntry = pThis->tVars.linklist.pDelRoot; if (pThis->tVars.linklist.pDelRoot == pThis->tVars.linklist.pLast) { pThis->tVars.linklist.pDelRoot = pThis->tVars.linklist.pDeqRoot = pThis->tVars.linklist.pLast = NULL; } else { pThis->tVars.linklist.pDelRoot = pEntry->pNext; } free(pEntry); RETiRet; } /* -------------------- disk -------------------- */ /* Helper to switch queue to LinkedList mode */ static void qqueueSetupLinkedList(qqueue_t *pThis) { pThis->qConstruct = qConstructLinkedList; pThis->qDestruct = qDestructLinkedList; pThis->qAdd = qAddLinkedList; pThis->qDeq = qDeqLinkedList; pThis->qDel = qDelLinkedList; pThis->MultiEnq = qqueueMultiEnqObjNonDirect; } static void qqueueDestroyDiskStreams(qqueue_t *pThis) { /* Emergency recovery must not delete queue files while switching modes. */ if (pThis->tVars.disk.pWrite != NULL) strm.SetbDeleteOnClose(pThis->tVars.disk.pWrite, 0); if (pThis->tVars.disk.pReadDeq != NULL) strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDeq, 0); if (pThis->tVars.disk.pReadDel != NULL) strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 0); if (pThis->tVars.disk.pWrite != NULL) strm.Destruct(&pThis->tVars.disk.pWrite); if (pThis->tVars.disk.pReadDeq != NULL) strm.Destruct(&pThis->tVars.disk.pReadDeq); if (pThis->tVars.disk.pReadDel != NULL) strm.Destruct(&pThis->tVars.disk.pReadDel); } static void qqueueResetRecoveredQueueSize(qqueue_t *pThis, const sbool adjustOverallQueueSize) { #ifndef ENABLE_IMDIAG (void)adjustOverallQueueSize; #endif if (pThis->iQueueSize > 0) { #ifdef ENABLE_IMDIAG if (adjustOverallQueueSize) { #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_SUB(&iOverallQueueSize, pThis->iQueueSize, &NULL); #else iOverallQueueSize -= pThis->iQueueSize; /* racy, but we can't wait for a mutex! */ #endif } #endif pThis->iQueueSize = 0; } pThis->nLogDeq = 0; if (pThis->qType == QUEUETYPE_DISK || pThis->bIsDA) { pThis->tVars.disk.sizeOnDisk = 0; } } static void qqueueSubtractOverallQueueSize(const int nElem) { if (nElem <= 0) { return; } #ifdef ENABLE_IMDIAG #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_SUB(&iOverallQueueSize, nElem, &NULL); #else iOverallQueueSize -= nElem; /* racy, but we can't wait for a mutex! */ #endif #endif } static void qqueueAddOverallQueueSize(const int nElem) { if (nElem <= 0) { return; } #ifdef ENABLE_IMDIAG #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_ADD(iOverallQueueSize, nElem); #else iOverallQueueSize += nElem; /* racy, but we can't wait for a mutex! */ #endif #endif } static void qqueueAddLogDeq(qqueue_t *pThis, const int nElem) { #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_ADD(pThis->nLogDeq, nElem); #else pthread_mutex_lock(&pThis->mutLogDeq); pThis->nLogDeq += nElem; pthread_mutex_unlock(&pThis->mutLogDeq); #endif } static void qqueueAddPhysicalQueueSize(qqueue_t *pThis, const int nElem) { #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_ADD(pThis->iQueueSize, nElem); #else pthread_mutex_lock(&pThis->mutQueueSize); pThis->iQueueSize += nElem; pthread_mutex_unlock(&pThis->mutQueueSize); #endif } /** * @brief Open the segmented store backing a pure or disk-assisted queue. * * The same store implementation backs eager pure segmentedDisk queues and * lazy DA children. For the latter, lazy_create allows open to succeed without * creating files; qAddSegDisk() materializes them when overflow actually * occurs. Recovered logical count is reflected in both child and overall queue * accounting before workers are advised. */ static rsRetVal qConstructSegDisk(qqueue_t *pThis) { segdisk_store_config_t cfg = { .work_dir = (const char *)pThis->pszSpoolDir, .file_prefix = (const char *)pThis->pszFilePrefix, .queue_name = (const char *)obj.GetName((obj_t *)pThis), .max_file_size = pThis->iMaxFileSize, .max_disk_space = pThis->sizeOnDiskMax, .checkpoint_interval = (unsigned int)pThis->iPersistUpdCnt, .sync_files = pThis->bSyncQueueFiles, .lazy_create = pThis->segdiskLazyCreate, }; int recovered = 0; DEFiRet; CHKiRet(segdiskStoreOpen(&pThis->tVars.segdisk, &cfg, &recovered)); pThis->iQueueSize = recovered; qqueueAddOverallQueueSize(recovered); qqueueUpdateSegDiskStats(pThis); finalize_it: if (iRet != RS_RET_OK) LogError(0, iRet, "%s: segmentedDisk store initialization failed", obj.GetName((obj_t *)pThis)); RETiRet; } static rsRetVal qDestructSegDisk(qqueue_t *pThis) { return segdiskStoreClose(&pThis->tVars.segdisk, getPhysicalQueueSize(pThis) == 0); } /** * @brief Serialize one message into a segmented store and account for DA activity. * * A lazy DA child must durably claim segmentedDisk before its first append can * create .segq. The marker write therefore precedes serialization and remains * pending after a failure. A successful DA append increments the parent * activity generation, invalidating any in-progress idle-dematerialization * grace period. The store consumes no message reference, so this function * always destroys the queue-owned reference before returning. */ static rsRetVal qAddSegDisk(qqueue_t *pThis, smsg_t *pMsg) { DEFiRet; if (pThis->daEngineMarkerPending) { /* The marker lives in workDirectory beside .segq, not inside * that lazy store directory. StartDA has already validated the * parent spool directory, so publishing the engine choice here can * and must precede segdiskStoreAppend() materializing .segq. */ CHKiRet(qdaEngineWriteMarker((const char *)pThis->pszSpoolDir, (const char *)pThis->pszFilePrefix, QDA_ENGINE_SEGMENTED_DISK)); pThis->daEngineMarkerPending = 0; } CHKiRet(segdiskStoreAppend(pThis->tVars.segdisk, pMsg, 0, NULL)); if (pThis->segdiskDAChild) ++pThis->pqParent->daActivityGeneration; qqueueUpdateSegDiskStats(pThis); finalize_it: /* The store serializes synchronously and never retains the message. The * queue owns the reference even when serialization or I/O fails. */ msgDestruct(&pMsg); RETiRet; } static rsRetVal qDeqBatchSegDisk(qqueue_t *pThis, batch_t *batch, int max, int *skipped) { int discovered = 0; const rsRetVal store_ret = segdiskStoreDequeueBatch(pThis->tVars.segdisk, batch, max, skipped, &discovered); if (discovered > 0) { qqueueAddPhysicalQueueSize(pThis, discovered); qqueueAddOverallQueueSize(discovered); } qqueueUpdateSegDiskStats(pThis); return store_ret == RS_RET_RETRY ? RS_RET_NO_DATA : store_ret; } static rsRetVal qCompleteBatchSegDisk(qqueue_t *pThis, batch_t *batch, int *committed, int *retried) { const rsRetVal r = segdiskStoreCompleteBatch(pThis->tVars.segdisk, batch, committed, retried); if (r == RS_RET_OK && pThis->segdiskDAChild && segdiskStoreCanDematerialize(pThis->tVars.segdisk)) pThis->segdiskIdleObservedActivity = pThis->pqParent->daActivityGeneration; qqueueUpdateSegDiskStats(pThis); return r; } static rsRetVal qqueueSwitchToInMemoryEmergency(qqueue_t *pThis) { DEFiRet; qqueueResetRecoveredQueueSize(pThis, 1); qqueueDestroyDiskStreams(pThis); free(pThis->pszFilePrefix); pThis->pszFilePrefix = NULL; pThis->lenFilePrefix = 0; pThis->bIsDA = 0; free(pThis->pszQIFNam); pThis->pszQIFNam = NULL; pThis->lenQIFNam = 0; pThis->bNeedDelQIF = 0; pThis->qType = QUEUETYPE_LINKEDLIST; qqueueSetupLinkedList(pThis); CHKiRet(pThis->qConstruct(pThis)); LogMsg(0, RS_RET_ERR, LOG_ALERT, "Queue now runs in pure in-memory emergency mode. Data is not persistent and can be lost " "on restart or crash."); finalize_it: RETiRet; } typedef struct fileEntry_s { int number; char *name; } fileEntry_t; static int fileEntryCmpByNumber(const void *a, const void *b) { const fileEntry_t *e1 = (const fileEntry_t *)a; const fileEntry_t *e2 = (const fileEntry_t *)b; if (e1->number < e2->number) return -1; if (e1->number > e2->number) return 1; return 0; } static sbool fileEntryExistsByNumber(const fileEntry_t *files, int nFiles, int number) { fileEntry_t key; if (nFiles <= 0 || files == NULL) { return 0; } key.number = number; key.name = NULL; return bsearch(&key, files, (size_t)nFiles, sizeof(fileEntry_t), fileEntryCmpByNumber) != NULL; } static sbool qqueueLoadRetIsStructuralCorruption(rsRetVal loadRet) { /* This classifier is used only by qConstructDisk() after parsing classic * .qi state. Segmented state and DA engine markers have separate fail-fast * validation paths and never reach it. Do not classify the generic * RS_RET_INVALID_VALUE here: it is not a classic deserializer framing * result and may represent a non-corruption startup/configuration error. */ static const rsRetVal structural_errors[] = { RS_RET_FILE_TRUNCATED, RS_RET_EOF, RS_RET_INVALID_OID, RS_RET_INVALID_HEADER, RS_RET_INVALID_HEADER_VERS, RS_RET_INVALID_DELIMITER, RS_RET_INVALID_PROPFRAME, RS_RET_NO_PROPLINE, RS_RET_INVALID_TRAILER, RS_RET_INVALID_HEADER_RECTYPE, RS_RET_QTYPE_MISMATCH, RS_RET_SYNTAX_ERROR, RS_RET_DS_PROP_SEQ_ERR, RS_RET_INVLD_PROP, }; for (size_t i = 0; i < sizeof(structural_errors) / sizeof(structural_errors[0]); ++i) { if (loadRet == structural_errors[i]) return 1; } return 0; } static rsRetVal qqueueVerifyAndRecover(qqueue_t *pThis, rsRetVal loadRet) { DEFiRet; DIR *d = NULL; struct dirent *dir; fileEntry_t *files = NULL; int nFiles = 0; int capFiles = 0; int fileNum; int corruptionDetected = 0; int canScanDir = 1; int i; if (pThis->onCorruption == QUEUE_ON_CORRUPTION_IGNORE) { return loadRet; } if (pThis->pszSpoolDir == NULL || pThis->pszSpoolDir[0] == '\0' || pThis->pszFilePrefix == NULL) { iRet = loadRet; FINALIZE; } if (strchr((char *)pThis->pszFilePrefix, '/') != NULL || strchr((char *)pThis->pszFilePrefix, '\\') != NULL) { LogError(0, RS_RET_ERR, "queue corruption: queue file prefix contains path separators; switching to emergency in-memory mode"); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } /* 1. Directory Scan */ d = opendir((char *)pThis->pszSpoolDir); if (d) { while (1) { errno = 0; dir = readdir(d); if (dir == NULL) { break; } size_t nameLen = strlen(dir->d_name); size_t prefixLen = pThis->lenFilePrefix; if (nameLen > prefixLen + 1 && strncmp(dir->d_name, (char *)pThis->pszFilePrefix, prefixLen) == 0 && dir->d_name[prefixLen] == '.') { char *suffix = dir->d_name + prefixLen + 1; if (strcmp(suffix, "qi") == 0) continue; char *endptr; long parsedNum; errno = 0; parsedNum = strtol(suffix, &endptr, 10); if (*endptr == '\0') { if (errno == ERANGE || parsedNum < 0 || parsedNum > INT_MAX) { LogError(0, RS_RET_ERR, "queue corruption: found file with invalid sequence number %s", suffix); corruptionDetected = 1; continue; } if (parsedNum >= MAX_DISK_QUEUE_FILES) { LogError(0, RS_RET_ERR, "queue corruption: found file with out-of-range sequence number %ld", parsedNum); corruptionDetected = 1; continue; } fileNum = (int)parsedNum; if (nFiles == capFiles) { fileEntry_t *newFiles; int newCapFiles = capFiles ? capFiles * 2 : 16; if ((size_t)newCapFiles > SIZE_MAX / sizeof(fileEntry_t)) { LogError(0, RS_RET_OUT_OF_MEMORY, "queue corruption: too many queue files while scanning spool directory"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(newFiles = realloc(files, (size_t)newCapFiles * sizeof(fileEntry_t))); files = newFiles; capFiles = newCapFiles; } char *dupName = strdup(dir->d_name); if (dupName == NULL) { iRet = RS_RET_OUT_OF_MEMORY; FINALIZE; } files[nFiles].number = fileNum; files[nFiles].name = dupName; nFiles++; } } } if (errno != 0) { canScanDir = 0; LogError(errno, RS_RET_ERR, "queue corruption: unable to fully scan spool directory %s; skipping corruption scan", pThis->pszSpoolDir); } closedir(d); d = NULL; } else { canScanDir = 0; if (errno != ENOENT && errno != ENOTDIR) { LogError(errno, RS_RET_ERR, "queue corruption: unable to scan spool directory %s; skipping corruption scan", pThis->pszSpoolDir); } } /* If we cannot scan spool files, we cannot safely validate file continuity. */ if (!canScanDir) { iRet = loadRet; FINALIZE; } if (nFiles > 1) { qsort(files, (size_t)nFiles, sizeof(fileEntry_t), fileEntryCmpByNumber); } /* 2. State Validation */ if (loadRet == RS_RET_OK) { int deqNum = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); int enqNum = strmGetCurrFileNum(pThis->tVars.disk.pWrite); if (deqNum < 0 || deqNum >= MAX_DISK_QUEUE_FILES) { LogError(0, RS_RET_ERR, "queue corruption: .qi file contains invalid dequeue number %d", deqNum); corruptionDetected = 1; } if (enqNum < 0 || enqNum >= MAX_DISK_QUEUE_FILES) { LogError(0, RS_RET_ERR, "queue corruption: .qi file contains invalid enqueue number %d", enqNum); corruptionDetected = 1; } if (!corruptionDetected) { int curr = deqNum; int limit = 0; /* Verify chain from deqNum to enqNum */ while (curr != enqNum) { if (!fileEntryExistsByNumber(files, nFiles, curr)) { LogError(0, RS_RET_ERR, "queue corruption: missing file in sequence: %d", curr); corruptionDetected = 1; break; } curr = (curr + 1) % MAX_DISK_QUEUE_FILES; limit++; if (limit > MAX_DISK_QUEUE_FILES) { /* Should theoretically not happen unless strm logic is broken */ LogError(0, RS_RET_ERR, "queue corruption: infinite loop detected verifying sequence"); corruptionDetected = 1; break; } } /* Check enqueue file itself */ if (!corruptionDetected && !fileEntryExistsByNumber(files, nFiles, enqNum)) { LogError(0, RS_RET_ERR, "queue corruption: missing enqueue file: %d", enqNum); corruptionDetected = 1; } } /* Check for orphaned files (files on disk not in the active range) */ if (!corruptionDetected) { int isWrapped = (enqNum < deqNum); for (i = 0; i < nFiles; i++) { int fNum = files[i].number; int isOrphan = 0; if (fNum < 0 || fNum >= MAX_DISK_QUEUE_FILES) continue; /* Defensive only; should be filtered above */ if (!isWrapped) { if (fNum < deqNum || fNum > enqNum) isOrphan = 1; } else { if (fNum > enqNum && fNum < deqNum) isOrphan = 1; } if (isOrphan) { LogError(0, RS_RET_ERR, "queue corruption: orphaned file found: %s (seq %d not in range [%d, %d]%s)", files[i].name, fNum, deqNum, enqNum, isWrapped ? " wrapped" : ""); corruptionDetected = 1; } } } } else { /* If .qi is missing/corrupt but we have segment files */ if (nFiles > 0) { corruptionDetected = 1; LogError(0, RS_RET_ERR, "queue corruption: .qi file missing or inaccessible but %d segment files exist", nFiles); } else if (qqueueLoadRetIsStructuralCorruption(loadRet)) { /* Only deterministic parser/framing failures prove that the .qi * contents are corrupt. I/O, access, allocation, and other * operational failures retain loadRet and fail startup so a * transient storage problem can never quarantine healthy state. */ corruptionDetected = 1; LogError(0, RS_RET_ERR, "queue corruption: .qi file is invalid and contains no usable queue state"); } } /* 3. Recovery */ if (corruptionDetected) { if (pThis->onCorruption == QUEUE_ON_CORRUPTION_IN_MEMORY) { LogMsg(0, RS_RET_ERR, LOG_ALERT, "Queue corruption detected. Entering emergency in-memory mode (non-persistent queue)."); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; } else { /* SAFE_MODE */ LogMsg(0, RS_RET_ERR, LOG_ALERT, "Queue corruption detected! Moving queue files to .bad directory and starting fresh."); char timebuf[64]; struct tm tm_buf; time_t now = time(NULL); if (now == (time_t)-1) { LogError(errno, RS_RET_ERR, "queue corruption: time() failed during recovery directory generation, using PID fallback"); struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { snprintf(timebuf, sizeof(timebuf), "timeerr-%ld-%ld", (long)getpid(), (long)ts.tv_nsec); } else { snprintf(timebuf, sizeof(timebuf), "timeerr-%ld", (long)getpid()); } } else { localtime_r(&now, &tm_buf); strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%S", &tm_buf); } char badDir[MAXFNAME]; int badDirLen = snprintf(badDir, sizeof(badDir), "%s/%s.bad.%s", pThis->pszSpoolDir, pThis->pszFilePrefix, timebuf); if (badDirLen < 0 || badDirLen >= (int)sizeof(badDir)) { LogError(0, RS_RET_ERR, "queue corruption: recovery directory path too long, switching to emergency in-memory mode"); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } if (mkdir(badDir, 0755) != 0) { if (errno == EEXIST) { struct stat badDirStat; if (stat(badDir, &badDirStat) != 0 || !S_ISDIR(badDirStat.st_mode)) { LogError(errno, RS_RET_ERR, "queue corruption: recovery directory path exists but is unusable %s; switching to " "emergency in-memory mode", badDir); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } } else { LogError(errno, RS_RET_ERR, "queue corruption: failed to create recovery directory %s; switching to emergency " "in-memory mode", badDir); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } } qqueueDestroyDiskStreams(pThis); char oldPath[MAXFNAME]; char newPath[MAXFNAME]; int pathLen1 = snprintf(oldPath, sizeof(oldPath), "%s/%s.qi", pThis->pszSpoolDir, pThis->pszFilePrefix); int pathLen2 = snprintf(newPath, sizeof(newPath), "%s/%s.qi", badDir, pThis->pszFilePrefix); if (pathLen1 < 0 || pathLen1 >= (int)sizeof(oldPath) || pathLen2 < 0 || pathLen2 >= (int)sizeof(newPath)) { LogError(0, RS_RET_ERR, "queue corruption: .qi recovery path too long; switching to emergency in-memory mode"); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } struct stat sb; if (stat(oldPath, &sb) == 0) { if (rename(oldPath, newPath) != 0) { LogError(errno, RS_RET_ERR, "queue corruption: could not move .qi file to recovery directory; switching to emergency " "in-memory mode"); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } } for (i = 0; i < nFiles; i++) { char oldSegPath[MAXFNAME]; char newSegPath[MAXFNAME]; int segPathLen1 = snprintf(oldSegPath, sizeof(oldSegPath), "%s/%s", pThis->pszSpoolDir, files[i].name); int segPathLen2 = snprintf(newSegPath, sizeof(newSegPath), "%s/%s", badDir, files[i].name); if (segPathLen1 < 0 || segPathLen1 >= (int)sizeof(oldSegPath) || segPathLen2 < 0 || segPathLen2 >= (int)sizeof(newSegPath)) { LogError(0, RS_RET_ERR, "queue corruption: queue file recovery path too long; switching to emergency " "in-memory mode"); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } if (rename(oldSegPath, newSegPath) != 0) { LogError(errno, RS_RET_ERR, "queue corruption: could not move queue file %s to recovery directory; switching to " "emergency in-memory mode", files[i].name); CHKiRet(qqueueSwitchToInMemoryEmergency(pThis)); iRet = RS_RET_OK; FINALIZE; } } qqueueResetRecoveredQueueSize(pThis, 1); iRet = RS_RET_FILE_NOT_FOUND; } } else { iRet = loadRet; } finalize_it: if (d != NULL) { closedir(d); } if (files) { for (i = 0; i < nFiles; i++) free(files[i].name); free(files); } RETiRet; } static rsRetVal makeDiskQueueBadDir(qqueue_t *pThis, char *badDir, const size_t badDirLen) { char timebuf[96]; struct tm tm_buf; time_t now = time(NULL); DEFiRet; if (now == (time_t)-1) { struct timespec ts; if (clock_gettime(CLOCK_REALTIME, &ts) == 0) { snprintf(timebuf, sizeof(timebuf), "timeerr-%ld-%ld", (long)getpid(), (long)ts.tv_nsec); } else { snprintf(timebuf, sizeof(timebuf), "timeerr-%ld", (long)getpid()); } } else { localtime_r(&now, &tm_buf); strftime(timebuf, sizeof(timebuf), "%Y%m%d%H%M%S", &tm_buf); } const int len = snprintf(badDir, badDirLen, "%s/%s.bad.%s.%ld", pThis->pszSpoolDir, pThis->pszFilePrefix, timebuf, (long)getpid()); if (len < 0 || len >= (int)badDirLen) { ABORT_FINALIZE(RS_RET_ERR); } if (mkdir(badDir, 0755) != 0) { if (errno != EEXIST) { LogError(errno, RS_RET_ERR, "queue corruption: failed to create quarantine directory %s", badDir); ABORT_FINALIZE(RS_RET_ERR); } struct stat badDirStat; if (stat(badDir, &badDirStat) != 0 || !S_ISDIR(badDirStat.st_mode)) { LogError(errno, RS_RET_ERR, "queue corruption: quarantine path exists but is unusable %s", badDir); ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: RETiRet; } static rsRetVal moveQueueFileToBadDir(qqueue_t *pThis, const char *badDir, const char *fileName) { char oldPath[MAXFNAME]; char newPath[MAXFNAME]; DEFiRet; const int oldLen = snprintf(oldPath, sizeof(oldPath), "%s/%s", pThis->pszSpoolDir, fileName); const int newLen = snprintf(newPath, sizeof(newPath), "%s/%s", badDir, fileName); if (oldLen < 0 || oldLen >= (int)sizeof(oldPath) || newLen < 0 || newLen >= (int)sizeof(newPath)) { ABORT_FINALIZE(RS_RET_ERR); } if (rename(oldPath, newPath) != 0 && errno != ENOENT) { LogError(errno, RS_RET_ERR, "queue corruption: could not move queue file %s to quarantine directory %s", fileName, badDir); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: RETiRet; } static rsRetVal qqueueQuarantineCurrentDiskFiles(qqueue_t *pThis, char *badDir, const size_t badDirLen) { DIR *d = NULL; struct dirent *dir; fileEntry_t *files = NULL; int nFiles = 0; int capFiles = 0; int i; DEFiRet; CHKiRet(makeDiskQueueBadDir(pThis, badDir, badDirLen)); d = opendir((char *)pThis->pszSpoolDir); if (d == NULL) { LogError(errno, RS_RET_ERR, "queue corruption: unable to scan spool directory %s for quarantine", pThis->pszSpoolDir); ABORT_FINALIZE(RS_RET_ERR); } errno = 0; while ((dir = readdir(d)) != NULL) { const size_t nameLen = strlen(dir->d_name); const size_t prefixLen = pThis->lenFilePrefix; if (nameLen <= prefixLen + 1 || strncmp(dir->d_name, (char *)pThis->pszFilePrefix, prefixLen) != 0 || dir->d_name[prefixLen] != '.') { continue; } const char *suffix = dir->d_name + prefixLen + 1; if (strcmp(suffix, "qi") == 0) { continue; } char *endptr; errno = 0; const long parsedNum = strtol(suffix, &endptr, 10); if (*endptr != '\0' || errno == ERANGE || parsedNum < 0 || parsedNum > INT_MAX) { continue; } if (nFiles == capFiles) { fileEntry_t *newFiles; const int newCapFiles = capFiles ? capFiles * 2 : 16; if ((size_t)newCapFiles > SIZE_MAX / sizeof(fileEntry_t)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(newFiles = realloc(files, (size_t)newCapFiles * sizeof(fileEntry_t))); files = newFiles; capFiles = newCapFiles; } CHKmalloc(files[nFiles].name = strdup(dir->d_name)); files[nFiles].number = (int)parsedNum; ++nFiles; } if (errno != 0) { LogError(errno, RS_RET_ERR, "queue corruption: unable to fully scan spool directory %s for quarantine", pThis->pszSpoolDir); ABORT_FINALIZE(RS_RET_ERR); } closedir(d); d = NULL; qqueueDestroyDiskStreams(pThis); char qiName[MAXFNAME]; const int qiLen = snprintf(qiName, sizeof(qiName), "%s.qi", pThis->pszFilePrefix); if (qiLen < 0 || qiLen >= (int)sizeof(qiName)) { ABORT_FINALIZE(RS_RET_ERR); } CHKiRet(moveQueueFileToBadDir(pThis, badDir, qiName)); for (i = 0; i < nFiles; ++i) { CHKiRet(moveQueueFileToBadDir(pThis, badDir, files[i].name)); } finalize_it: if (d != NULL) { closedir(d); } if (files != NULL) { for (i = 0; i < nFiles; ++i) free(files[i].name); free(files); } RETiRet; } static rsRetVal qqueueResetDiskQueueAfterCorruption(qqueue_t *pThis) { char badDir[MAXFNAME]; DEFiRet; CHKiRet(qqueueQuarantineCurrentDiskFiles(pThis, badDir, sizeof(badDir))); LogMsg(0, RS_RET_ERR, LOG_ALERT, "%s: disk queue corruption could not be resynchronized; quarantined unread queue tail into %s", obj.GetName((obj_t *)pThis), badDir); qqueueResetRecoveredQueueSize(pThis, 0); pThis->tVars.disk.sizeOnDisk = 0; pThis->tVars.disk.deqFileNumIn = 0; pThis->tVars.disk.deqFileNumOut = 0; pThis->tVars.disk.deqOffs = 0; pThis->tVars.disk.nForcePersist = 0; pThis->tVars.disk.pendingCorruptRet = RS_RET_OK; pThis->bNeedDelQIF = 0; pThis->iUpdsSincePersist = 0; CHKiRet(qConstructDisk(pThis)); LogMsg(0, RS_RET_OK, LOG_WARNING, "%s: disk queue active state reset after corruption quarantine", obj.GetName((obj_t *)pThis)); finalize_it: if (iRet != RS_RET_OK) { LogError(0, iRet, "%s: disk queue corruption quarantine failed; switching to emergency in-memory mode", obj.GetName((obj_t *)pThis)); const rsRetVal localRet = qqueueSwitchToInMemoryEmergency(pThis); if (localRet != RS_RET_OK) { LogError(0, localRet, "%s: emergency in-memory mode switch failed after disk queue corruption", obj.GetName((obj_t *)pThis)); } iRet = RS_RET_OK; } RETiRet; } /* The following function is used to "save" ourself from being killed by * a fatally failed disk queue. A fatal failure is, for example, if no * data can be read or written. In that case, the disk support is disabled, * with all on-disk structures kept as-is as much as possible. However, * we do not really stop or destruct the in-memory disk queue object. * Practice has shown that this may cause races during destruction which * themselves can lead to segfault. So we prefer to was some resources by * keeping the queue active. * Instead, the queue is switched to direct mode, so that at least * some processing can happen. Of course, this may still have lots of * undesired side-effects, but is probably better than aborting the * syslogd. Note that this function *must* succeed in one way or another, as * we can not recover from failure here. But it may emit different return * states, which can trigger different processing in the higher layers. * rgerhards, 2011-05-03 */ static rsRetVal queueSwitchToEmergencyMode(qqueue_t *pThis, rsRetVal initiatingError) { pThis->iQueueSize = 0; pThis->nLogDeq = 0; pThis->qType = QUEUETYPE_DIRECT; pThis->qConstruct = qConstructDirect; pThis->qDestruct = qDestructDirect; /* these entry points shall not be used in direct mode * To catch program errors, make us abort if that happens! * rgerhards, 2013-11-05 */ pThis->qAdd = qAddDirect; pThis->MultiEnq = qqueueMultiEnqObjDirect; pThis->qDel = NULL; if (pThis->pqParent != NULL) { DBGOPRINT((obj_t *)pThis, "DA queue is in emergency mode, disabling DA in parent\n"); pThis->pqParent->bIsDA = 0; pThis->pqParent->pqDA = NULL; /* This may have undesired side effects, not sure if I really evaluated * all. So you know where to look at if you come to this point during * troubleshooting ;) -- rgerhards, 2011-05-03 */ } LogError(0, initiatingError, "fatal error on disk queue '%s', " "emergency switch to direct mode", obj.GetName((obj_t *)pThis)); return RS_RET_ERR_QUEUE_EMERGENCY; } static rsRetVal qqueueLoadPersStrmInfoFixup(strm_t *pStrm, qqueue_t __attribute__((unused)) * pThis) { DEFiRet; ISOBJ_TYPE_assert(pStrm, strm); ISOBJ_TYPE_assert(pThis, qqueue); CHKiRet(strm.SetDir(pStrm, pThis->pszSpoolDir, pThis->lenSpoolDir)); CHKiRet(strm.SetbSync(pStrm, pThis->bSyncQueueFiles)); CHKiRet(strm.SetbNoFollowFinal(pStrm, 1)); finalize_it: RETiRet; } /* The method loads the persistent queue information. * rgerhards, 2008-01-11 */ static rsRetVal qqueueTryLoadPersistedInfo(qqueue_t *pThis) { DEFiRet; strm_t *psQIF = NULL; struct stat stat_buf; ISOBJ_TYPE_assert(pThis, qqueue); /* check if the file exists */ if (stat((char *)pThis->pszQIFNam, &stat_buf) == -1) { if (errno == ENOENT) { DBGOPRINT((obj_t *)pThis, "clean startup, no .qi file found\n"); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } else { LogError(errno, RS_RET_IO_ERROR, "queue: %s: error %d could not access .qi file", obj.GetName((obj_t *)pThis), errno); ABORT_FINALIZE(RS_RET_IO_ERROR); } } /* If we reach this point, we have a .qi file */ CHKiRet(strm.Construct(&psQIF)); CHKiRet(strm.SettOperationsMode(psQIF, STREAMMODE_READ)); CHKiRet(strm.SetsType(psQIF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetbNoFollowFinal(psQIF, 1)); CHKiRet(strm.SetFName(psQIF, pThis->pszQIFNam, pThis->lenQIFNam)); CHKiRet(strm.ConstructFinalize(psQIF)); /* first, we try to read the property bag for ourselfs */ CHKiRet(obj.DeserializePropBag((obj_t *)pThis, psQIF)); /* then the stream objects (same order as when persisted!) */ CHKiRet(obj.Deserialize(&pThis->tVars.disk.pWrite, (uchar *)"strm", psQIF, (rsRetVal(*)(obj_t *, void *))qqueueLoadPersStrmInfoFixup, pThis)); CHKiRet(obj.Deserialize(&pThis->tVars.disk.pReadDel, (uchar *)"strm", psQIF, (rsRetVal(*)(obj_t *, void *))qqueueLoadPersStrmInfoFixup, pThis)); /* create a duplicate for the read "pointer". */ CHKiRet(strm.Dup(pThis->tVars.disk.pReadDel, &pThis->tVars.disk.pReadDeq)); CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDeq, 0)); /* deq must NOT delete the files! */ CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDeq)); /* if we use a crypto provider, we need to amend the objects with it's info */ if (pThis->useCryprov) { CHKiRet(strm.Setcryprov(pThis->tVars.disk.pWrite, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pWrite, pThis->cryprovData)); CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDeq, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDeq, pThis->cryprovData)); CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDel, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDel, pThis->cryprovData)); } CHKiRet(strm.SeekCurrOffs(pThis->tVars.disk.pWrite)); rsRetVal seekRet = strm.SeekCurrOffs(pThis->tVars.disk.pReadDel); sbool read_seek_failed = 0; CHKiRet(handleReadSeekError(seekRet, pThis, "read/delete", &read_seek_failed)); seekRet = strm.SeekCurrOffs(pThis->tVars.disk.pReadDeq); CHKiRet(handleReadSeekError(seekRet, pThis, "read", &read_seek_failed)); if (read_seek_failed) { /* Align read pointer to write pointer to trigger recovery later. */ alignReadDeqToWrite(pThis); } /* OK, we could successfully read the file, so we now can request that it be * deleted when we are done with the persisted information. */ pThis->bNeedDelQIF = 1; LogMsg(0, RS_RET_OK, LOG_INFO, "%s: queue files exist on disk, re-starting with " "%d messages. This will keep the disk queue file open, details: " "https://rainer.gerhards.net/2013/07/rsyslog-why-disk-assisted-queues-keep-a-file-open.html", objGetName((obj_t *)pThis), getLogicalQueueSize(pThis)); finalize_it: if (psQIF != NULL) strm.Destruct(&psQIF); if (iRet != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "state %d reading .qi file - can not read persisted info (if any)\n", iRet); } RETiRet; } /* disk queue constructor. * Note that we use a file limit of 10,000,000 files. That number should never pose a * problem. If so, I guess the user has a design issue... But of course, the code can * always be changed (though it would probably be more appropriate to increase the * allowed file size at this point - that should be a config setting... * rgerhards, 2008-01-10 */ static rsRetVal qConstructDisk(qqueue_t *pThis) { DEFiRet; int bRestarted = 0; assert(pThis != NULL); pThis->tVars.disk.pendingCorruptRet = RS_RET_OK; pThis->tVars.disk.runtimeCorruptionSkip = 0; /* and now check if there is some persistent information that needs to be read in */ iRet = qqueueTryLoadPersistedInfo(pThis); iRet = qqueueVerifyAndRecover(pThis, iRet); if (iRet == RS_RET_OK && pThis->qType == QUEUETYPE_LINKEDLIST) { /* we switched to in-memory mode, so we are done */ FINALIZE; } if (iRet == RS_RET_OK) bRestarted = 1; else if (iRet != RS_RET_FILE_NOT_FOUND) FINALIZE; if (bRestarted == 1) { ; } else { CHKiRet(strm.Construct(&pThis->tVars.disk.pWrite)); CHKiRet(strm.SetbSync(pThis->tVars.disk.pWrite, pThis->bSyncQueueFiles)); CHKiRet(strm.SetDir(pThis->tVars.disk.pWrite, pThis->pszSpoolDir, pThis->lenSpoolDir)); CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pWrite, MAX_DISK_QUEUE_FILES)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pWrite, STREAMMODE_WRITE)); CHKiRet(strm.SetsType(pThis->tVars.disk.pWrite, STREAMTYPE_FILE_CIRCULAR)); CHKiRet(strm.SetbNoFollowFinal(pThis->tVars.disk.pWrite, 1)); if (pThis->useCryprov) { CHKiRet(strm.Setcryprov(pThis->tVars.disk.pWrite, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pWrite, pThis->cryprovData)); } CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pWrite)); CHKiRet(strm.Construct(&pThis->tVars.disk.pReadDeq)); CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDeq, 0)); CHKiRet(strm.SetDir(pThis->tVars.disk.pReadDeq, pThis->pszSpoolDir, pThis->lenSpoolDir)); CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pReadDeq, MAX_DISK_QUEUE_FILES)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDeq, STREAMMODE_READ)); CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDeq, STREAMTYPE_FILE_CIRCULAR)); CHKiRet(strm.SetbNoFollowFinal(pThis->tVars.disk.pReadDeq, 1)); if (pThis->useCryprov) { CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDeq, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDeq, pThis->cryprovData)); } CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDeq)); CHKiRet(strm.Construct(&pThis->tVars.disk.pReadDel)); CHKiRet(strm.SetbSync(pThis->tVars.disk.pReadDel, pThis->bSyncQueueFiles)); CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 1)); CHKiRet(strm.SetDir(pThis->tVars.disk.pReadDel, pThis->pszSpoolDir, pThis->lenSpoolDir)); CHKiRet(strm.SetiMaxFiles(pThis->tVars.disk.pReadDel, MAX_DISK_QUEUE_FILES)); CHKiRet(strm.SettOperationsMode(pThis->tVars.disk.pReadDel, STREAMMODE_READ)); CHKiRet(strm.SetsType(pThis->tVars.disk.pReadDel, STREAMTYPE_FILE_CIRCULAR)); CHKiRet(strm.SetbNoFollowFinal(pThis->tVars.disk.pReadDel, 1)); if (pThis->useCryprov) { CHKiRet(strm.Setcryprov(pThis->tVars.disk.pReadDel, &pThis->cryprov)); CHKiRet(strm.SetcryprovData(pThis->tVars.disk.pReadDel, pThis->cryprovData)); } CHKiRet(strm.ConstructFinalize(pThis->tVars.disk.pReadDel)); CHKiRet(strm.SetFName(pThis->tVars.disk.pWrite, pThis->pszFilePrefix, pThis->lenFilePrefix)); CHKiRet(strm.SetFName(pThis->tVars.disk.pReadDeq, pThis->pszFilePrefix, pThis->lenFilePrefix)); CHKiRet(strm.SetFName(pThis->tVars.disk.pReadDel, pThis->pszFilePrefix, pThis->lenFilePrefix)); } /* now we set (and overwrite in case of a persisted restart) some parameters which * should always reflect the current configuration variables. Be careful by doing so, * for example file name generation must not be changed as that would break the * ability to read existing queue files. -- rgerhards, 2008-01-12 */ CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pWrite, pThis->iMaxFileSize)); CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pReadDeq, pThis->iMaxFileSize)); CHKiRet(strm.SetiMaxFileSize(pThis->tVars.disk.pReadDel, pThis->iMaxFileSize)); finalize_it: RETiRet; } static rsRetVal qDestructDisk(qqueue_t *pThis) { DEFiRet; assert(pThis != NULL); free(pThis->pszQIFNam); if (pThis->tVars.disk.pWrite != NULL) { if (getPhysicalQueueSize(pThis) == 0) { /* Once the disk queue is logically empty, any remaining active write * file only contains untracked tail data, typically late internal * messages emitted during shutdown. Keep teardown from leaving that * orphaned file behind. */ strm.SetbDeleteOnClose(pThis->tVars.disk.pWrite, 1); } strm.Destruct(&pThis->tVars.disk.pWrite); } if (pThis->tVars.disk.pReadDeq != NULL) strm.Destruct(&pThis->tVars.disk.pReadDeq); if (pThis->tVars.disk.pReadDel != NULL) strm.Destruct(&pThis->tVars.disk.pReadDel); RETiRet; } static rsRetVal ATTR_NONNULL(1, 2) qAddDisk(qqueue_t *const pThis, smsg_t *pMsg) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); ISOBJ_TYPE_assert(pMsg, msg); if (pThis->daEngineMarkerPending) { CHKiRet(qdaEngineWriteMarker((const char *)pThis->pszSpoolDir, (const char *)pThis->pszFilePrefix, QDA_ENGINE_DISK)); pThis->daEngineMarkerPending = 0; } number_t nWriteCount; const int oldfile = strmGetCurrFileNum(pThis->tVars.disk.pWrite); CHKiRet(strm.SetWCntr(pThis->tVars.disk.pWrite, &nWriteCount)); CHKiRet((objSerialize(pMsg))(pMsg, pThis->tVars.disk.pWrite)); CHKiRet(strm.Flush(pThis->tVars.disk.pWrite)); CHKiRet(strm.SetWCntr(pThis->tVars.disk.pWrite, NULL)); /* no more counting for now... */ pThis->tVars.disk.sizeOnDisk += nWriteCount; /* we have enqueued the user element to disk. So we now need to destruct * the in-memory representation. The instance will be re-created upon * dequeue. -- rgerhards, 2008-07-09 */ msgDestruct(&pMsg); DBGOPRINT((obj_t *)pThis, "write wrote %lld octets to disk, queue disk size now %lld octets, EnqOnly:%d\n", nWriteCount, pThis->tVars.disk.sizeOnDisk, pThis->bEnqOnly); /* Did we have a change in the on-disk file? If so, we * should do a "robustness sync" of the .qi file to guard * against the most harsh consequences of kill -9 and power off. */ int newfile; newfile = strmGetCurrFileNum(pThis->tVars.disk.pWrite); if (newfile != oldfile) { DBGOPRINT((obj_t *)pThis, "current to-be-written-to file has changed from " "number %d to number %d - requiring a .qi write for robustness\n", oldfile, newfile); pThis->tVars.disk.nForcePersist = 2; } finalize_it: RETiRet; } static rsRetVal msgConstructFromVoid(void **ppThis) { return msgConstructForDeserializer((smsg_t **)ppThis); } static rsRetVal msgDeserializeFromVoid(void *pObj, strm_t *pStrm) { return MsgDeserialize((smsg_t *)pObj, pStrm); } static rsRetVal qDeqDisk(qqueue_t *pThis, smsg_t **ppMsg) { DEFiRet; iRet = objDeserializeWithMethods(ppMsg, (uchar *)"msg", sizeof("msg") - 1, pThis->tVars.disk.pReadDeq, NULL, NULL, msgConstructFromVoid, NULL, msgDeserializeFromVoid); if (iRet != RS_RET_OK) { LogError(0, iRet, "%s: qDeqDisk error happened at around offset %lld", obj.GetName((obj_t *)pThis), (long long)pThis->tVars.disk.pReadDeq->iCurrOffs); } RETiRet; } static rsRetVal qDeqDiskRecoverAfterCorruption(qqueue_t *pThis, smsg_t **ppMsg, const rsRetVal corruptRet, int *const pSkippedMsgs) { uchar c; int64_t startOffs; int startFile; unsigned int scanned = 0; DEFiRet; assert(ppMsg != NULL); assert(pSkippedMsgs != NULL); *ppMsg = NULL; *pSkippedMsgs = 0; if (pThis->onCorruption != QUEUE_ON_CORRUPTION_SAFE_MODE || pThis->tVars.disk.pReadDeq == NULL) { ABORT_FINALIZE(corruptRet); } if (pThis->tVars.disk.pWrite != NULL && strmGetCurrFileNum(pThis->tVars.disk.pReadDeq) == strmGetCurrFileNum(pThis->tVars.disk.pWrite) && pThis->tVars.disk.pReadDeq->iCurrOffs >= pThis->tVars.disk.pWrite->iCurrOffs) { ABORT_FINALIZE(corruptRet); } startFile = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); startOffs = pThis->tVars.disk.pReadDeq->iCurrOffs; LogMsg(0, corruptRet, LOG_ALERT, "%s: disk queue corruption detected while dequeuing at file %d offset %lld; attempting bounded resync", obj.GetName((obj_t *)pThis), startFile, (long long)startOffs); while (scanned < DISKQUEUE_CORRUPTION_RESYNC_MAX_BYTES) { if (pThis->tVars.disk.pWrite != NULL && strmGetCurrFileNum(pThis->tVars.disk.pReadDeq) == strmGetCurrFileNum(pThis->tVars.disk.pWrite) && pThis->tVars.disk.pReadDeq->iCurrOffs >= pThis->tVars.disk.pWrite->iCurrOffs) { break; } iRet = strm.ReadChar(pThis->tVars.disk.pReadDeq, &c); if (iRet != RS_RET_OK) { break; } ++scanned; if (c != '<') { continue; } CHKiRet(strm.UnreadChar(pThis->tVars.disk.pReadDeq, c)); iRet = objDeserializeWithMethods(ppMsg, (uchar *)"msg", sizeof("msg") - 1, pThis->tVars.disk.pReadDeq, NULL, NULL, msgConstructFromVoid, NULL, msgDeserializeFromVoid); if (iRet == RS_RET_OK) { *pSkippedMsgs = 1; LogMsg(0, RS_RET_OK, LOG_WARNING, "%s: disk queue corruption recovery resumed after skipping a damaged record; " "resynchronized at file %d offset %lld after scanning %u bytes", obj.GetName((obj_t *)pThis), strmGetCurrFileNum(pThis->tVars.disk.pReadDeq), (long long)pThis->tVars.disk.pReadDeq->iCurrOffs, scanned); FINALIZE; } if (iRet == RS_RET_OUT_OF_MEMORY) { ABORT_FINALIZE(iRet); } *ppMsg = NULL; } LogMsg(0, corruptRet, LOG_ALERT, "%s: disk queue corruption recovery failed after bounded scan of %u bytes; quarantining unread tail", obj.GetName((obj_t *)pThis), scanned); const int skippedTail = getLogicalQueueSize(pThis); CHKiRet(qqueueResetDiskQueueAfterCorruption(pThis)); *pSkippedMsgs = skippedTail; iRet = RS_RET_NO_DATA; finalize_it: RETiRet; } /* -------------------- direct (no queueing) -------------------- */ static rsRetVal qConstructDirect(qqueue_t __attribute__((unused)) * pThis) { return RS_RET_OK; } static rsRetVal qDestructDirect(qqueue_t __attribute__((unused)) * pThis) { return RS_RET_OK; } static rsRetVal qAddDirectWithWti(qqueue_t *pThis, smsg_t *pMsg, wti_t *pWti) { batch_t singleBatch; batch_obj_t batchObj; batch_state_t batchState = BATCH_STATE_RDY; DEFiRet; // TODO: init batchObj (states _OK and new fields -- CHECK) assert(pThis != NULL); /* calling the consumer is quite different here than it is from a worker thread */ /* we need to provide the consumer's return value back to the caller because in direct * mode the consumer probably has a lot to convey (which get's lost in the other modes * because they are asynchronous. But direct mode is deliberately synchronous. * rgerhards, 2008-02-12 * We use our knowledge about the batch_t structure below, but without that, we * pay a too-large performance toll... -- rgerhards, 2009-04-22 */ memset(&batchObj, 0, sizeof(batch_obj_t)); memset(&singleBatch, 0, sizeof(batch_t)); batchObj.pMsg = pMsg; singleBatch.nElem = 1; /* there always is only one in direct mode */ singleBatch.pElem = &batchObj; singleBatch.eltState = &batchState; iRet = pThis->pConsumer(pThis->pAction, &singleBatch, pWti); msgDestruct(&pMsg); RETiRet; } /* this is called if we do not have a pWti. This currently only happens * when we are called from a main queue in direct mode. If so, we need * to obtain a dummy pWti. */ static rsRetVal qAddDirect(qqueue_t *pThis, smsg_t *pMsg) { wti_t *pWti; DEFiRet; pWti = wtiGetDummy(); qqueueSetWtiShutdownImmediate(pThis, pWti); iRet = qAddDirectWithWti(pThis, pMsg, pWti); RETiRet; } /* --------------- end type-specific handlers -------------------- */ /* generic code to add a queue entry * We use some specific code to most efficiently support direct mode * queues. This is justified in spite of the gain and the need to do some * things truely different. -- rgerhards, 2008-02-12 */ static rsRetVal qqueueAdd(qqueue_t *pThis, smsg_t *pMsg) { DEFiRet; assert(pThis != NULL); static int msgCnt = 0; if (pThis->iSmpInterval > 0) { msgCnt = (msgCnt + 1) % (pThis->iSmpInterval); if (msgCnt != 0) { msgDestruct(&pMsg); goto finalize_it; } } CHKiRet(pThis->qAdd(pThis, pMsg)); if (pThis->bIsDA && pThis->pqDA != NULL && pThis->pqDA->segdiskDAChild) { /* Parent and DA child intentionally share this queue mutex. The idle * callback therefore observes this activity generation atomically * with both producer enqueue and child store operations. */ ++pThis->daActivityGeneration; if (pThis->pqDA->pWtpReg != NULL) wtpWakeupAllWrkr(pThis->pqDA->pWtpReg); } if (pThis->qType != QUEUETYPE_DIRECT) { ATOMIC_INC(&pThis->iQueueSize, &pThis->mutQueueSize); #ifdef ENABLE_IMDIAG #ifdef HAVE_ATOMIC_BUILTINS /* mutex is never used due to conditional compilation */ ATOMIC_INC(&iOverallQueueSize, &NULL); #else ++iOverallQueueSize; /* racy, but we can't wait for a mutex! */ #endif #endif } finalize_it: RETiRet; } /* Try to shut down regular and DA queue workers, within the queue timeout * period. That means processing continues as usual. This is the expected * usual case, where during shutdown those messages remaining are being * processed. At this point, it is acceptable that the queue can not be * fully depleted, that case is handled in the next step. During this phase, * we first shut down the main queue DA worker to prevent new data to arrive * at the DA queue, and then we ask the regular workers of both the Regular * and DA queue to try complete processing. * rgerhards, 2009-10-14 */ static rsRetVal ATTR_NONNULL(1) tryShutdownWorkersWithinQueueTimeout(qqueue_t *const pThis) { struct timespec tTimeout; rsRetVal iRetLocal; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pThis->pqParent == NULL); /* detect invalid calling sequence */ if (pThis->bIsDA) { /* We need to lock the mutex, as otherwise we may have a race that prevents * us from awaking the DA worker. */ d_pthread_mutex_lock(pThis->mut); /* tell regular queue DA worker to stop shuffling messages to DA queue... */ DBGOPRINT((obj_t *)pThis, "setting EnqOnly mode for DA worker\n"); pThis->pqDA->bEnqOnly = 1; wtpSetState(pThis->pWtpDA, wtpState_SHUTDOWN_IMMEDIATE); wtpAdviseMaxWorkers(pThis->pWtpDA, 1, DENY_WORKER_START_DURING_SHUTDOWN); DBGOPRINT((obj_t *)pThis, "awoke DA worker, told it to shut down.\n"); /* also tell the DA queue worker to shut down, so that it already knows... */ wtpSetState(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN); wtpAdviseMaxWorkers(pThis->pqDA->pWtpReg, 1, DENY_WORKER_START_DURING_SHUTDOWN); /* awake its lone worker */ DBGOPRINT((obj_t *)pThis, "awoke DA queue regular worker, told it to shut down when done.\n"); d_pthread_mutex_unlock(pThis->mut); } /* first calculate absolute timeout - we need the absolute value here, because we need to coordinate * shutdown of both the regular and DA queue on *the same* timeout. */ timeoutComp(&tTimeout, pThis->toQShutdown); DBGOPRINT((obj_t *)pThis, "trying shutdown of regular workers\n"); iRetLocal = wtpShutdownAll(pThis->pWtpReg, wtpState_SHUTDOWN, &tTimeout); if (iRetLocal == RS_RET_TIMED_OUT) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "%s: regular queue shutdown timed out on primary queue " "(this is OK, timeout was %d)", objGetName((obj_t *)pThis), pThis->toQShutdown); } else { DBGOPRINT((obj_t *)pThis, "regular queue workers shut down.\n"); } /* OK, the worker for the regular queue is processed, on the the DA queue regular worker. */ if (pThis->pqDA != NULL) { DBGOPRINT((obj_t *)pThis, "we have a DA queue (0x%lx), requesting its shutdown.\n", qqueueGetID(pThis->pqDA)); /* we use the same absolute timeout as above, so we do not use more than the configured * timeout interval! */ DBGOPRINT((obj_t *)pThis, "trying shutdown of regular worker of DA queue\n"); iRetLocal = wtpShutdownAll(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN, &tTimeout); if (iRetLocal == RS_RET_TIMED_OUT) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "%s: regular queue shutdown timed out on DA queue (this is OK, " "timeout was %d)", objGetName((obj_t *)pThis), pThis->toQShutdown); } else { DBGOPRINT((obj_t *)pThis, "DA queue worker shut down.\n"); } } RETiRet; } /* Try to shut down regular and DA queue workers, within the action timeout * period. This aborts processing, but at the end of the current action, in * a well-defined manner. During this phase, we terminate all three worker * pools, including the regular queue DA worker if it not yet has terminated. * Not finishing processing all messages is OK (and expected) at this stage * (they may be preserved later, depending * on bSaveOnShutdown setting). * rgerhards, 2009-10-14 */ static rsRetVal tryShutdownWorkersWithinActionTimeout(qqueue_t *pThis) { struct timespec tTimeout; rsRetVal iRetLocal; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pThis->pqParent == NULL); /* detect invalid calling sequence */ /* instruct workers to finish ASAP, even if still work exists */ DBGOPRINT((obj_t *)pThis, "trying to shutdown workers within Action Timeout"); DBGOPRINT((obj_t *)pThis, "setting EnqOnly mode\n"); pThis->bEnqOnly = 1; qqueueSetShutdownImmediate(pThis, 1); /* now DA queue */ if (pThis->bIsDA) { pThis->pqDA->bEnqOnly = 1; qqueueSetShutdownImmediate(pThis->pqDA, 1); } /* now give the queue workers a last chance to gracefully shut down (based on action timeout setting) */ timeoutComp(&tTimeout, pThis->toActShutdown); DBGOPRINT((obj_t *)pThis, "trying immediate shutdown of regular workers (if any)\n"); iRetLocal = wtpShutdownAll(pThis->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal == RS_RET_TIMED_OUT) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "%s: immediate shutdown timed out on primary queue (this is acceptable and " "triggers cancellation)", objGetName((obj_t *)pThis)); } else if (iRetLocal != RS_RET_OK) { LogMsg(0, iRetLocal, LOG_WARNING, "%s: potential internal error: unexpected return state after trying " "immediate shutdown of the primary queue in disk save mode. " "Continuing, but results are unpredictable", objGetName((obj_t *)pThis)); } if (pThis->pqDA != NULL) { /* and now the same for the DA queue */ DBGOPRINT((obj_t *)pThis, "trying immediate shutdown of DA queue workers\n"); iRetLocal = wtpShutdownAll(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal == RS_RET_TIMED_OUT) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "%s: immediate shutdown timed out on DA queue (this is acceptable and " "triggers cancellation)", objGetName((obj_t *)pThis)); } else if (iRetLocal != RS_RET_OK) { LogMsg(0, iRetLocal, LOG_WARNING, "%s: potential internal error: unexpected return state after trying " "immediate shutdown of the DA queue in disk save mode. " "Continuing, but results are unpredictable", objGetName((obj_t *)pThis)); } /* and now we need to terminate the DA worker itself. We always grant it a 100ms timeout, * which should be sufficient and usually not be required (it is expected to have finished * long before while we were processing the queue timeout in shutdown phase 1). * rgerhards, 2009-10-14 */ timeoutComp(&tTimeout, 100); DBGOPRINT((obj_t *)pThis, "trying regular shutdown of main queue DA worker pool\n"); iRetLocal = wtpShutdownAll(pThis->pWtpDA, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal == RS_RET_TIMED_OUT) { LogMsg(0, iRetLocal, LOG_WARNING, "%s: shutdown timed out on main queue DA worker pool " "(this is not good, but possibly OK)", objGetName((obj_t *)pThis)); } else { DBGOPRINT((obj_t *)pThis, "main queue DA worker pool shut down.\n"); } } RETiRet; } /* This function cancels all remaining regular workers for both the main and the DA * queue. * rgerhards, 2009-05-29 */ static rsRetVal cancelWorkers(qqueue_t *pThis) { rsRetVal iRetLocal; struct timespec tTimeout; DEFiRet; assert(pThis->qType != QUEUETYPE_DIRECT); /* Now queue workers should have terminated. If not, we need to cancel them as we have applied * all timeout setting. If any worker in any queue still executes, its consumer is possibly * long-running and cancelling is the only way to get rid of it. */ DBGOPRINT((obj_t *)pThis, "checking to see if we need to cancel any worker threads of the primary queue\n"); iRetLocal = wtpCancelAll(pThis->pWtpReg, objGetName((obj_t *)pThis)); /* ^-- returns immediately if all threads already have terminated */ if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected iRet state %d trying to cancel primary queue worker " "threads, continuing, but results are unpredictable\n", iRetLocal); } timeoutComp(&tTimeout, QUEUE_TIMEOUT_ETERNAL); iRetLocal = wtpShutdownAll(pThis->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected state %d joining cancelled primary workers\n", iRetLocal); } /* ... and now the DA queue, if it exists (should always be after the primary one) */ if (pThis->pqDA != NULL) { DBGOPRINT((obj_t *)pThis, "checking to see if we need to cancel any worker threads of " "the DA queue\n"); iRetLocal = wtpCancelAll(pThis->pqDA->pWtpReg, objGetName((obj_t *)pThis)); /* returns immediately if all threads already have terminated */ if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected iRet state %d trying to cancel DA queue worker " "threads, continuing, but results are unpredictable\n", iRetLocal); } timeoutComp(&tTimeout, QUEUE_TIMEOUT_ETERNAL); iRetLocal = wtpShutdownAll(pThis->pqDA->pWtpReg, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected state %d joining cancelled DA child workers\n", iRetLocal); } /* finally, we cancel the main queue's DA worker pool, if it still is running. It may be * restarted later to persist the queue. But we stop it, because otherwise we get into * big trouble when resetting the logical dequeue pointer. This operation can only be * done when *no* worker is running. So time for a shutdown... -- rgerhards, 2009-05-28 */ DBGOPRINT((obj_t *)pThis, "checking to see if main queue DA worker pool needs to be cancelled\n"); wtpCancelAll(pThis->pWtpDA, objGetName((obj_t *)pThis)); /* returns immediately if all threads already have terminated */ timeoutComp(&tTimeout, QUEUE_TIMEOUT_ETERNAL); iRetLocal = wtpShutdownAll(pThis->pWtpDA, wtpState_SHUTDOWN_IMMEDIATE, &tTimeout); if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected state %d joining cancelled DA transfer workers\n", iRetLocal); } } RETiRet; } /* This function shuts down all worker threads and waits until they * have terminated. If they timeout, they are cancelled. * rgerhards, 2008-01-24 * Please note that this function shuts down BOTH the parent AND the child queue * in DA case. This is necessary because their timeouts are tightly coupled. Most * importantly, the timeouts would be applied twice (or logic be extremely * complex) if each would have its own shutdown. The function does not self check * this condition - the caller must make sure it is not called with a parent. * rgerhards, 2009-05-26: we do NO longer persist the queue here if bSaveOnShutdown * is set. This must be handled by the caller. Not doing that cleans up the queue * shutdown considerably. Also, older engines had a potential hang condition when * the DA queue was already started and the DA worker configured for infinite * retries and the action was during retry processing. This was a design issue, * which is solved as of now. Note that the shutdown now may take a little bit * longer, because we no longer can persist the queue in parallel to waiting * on worker timeouts. */ rsRetVal ATTR_NONNULL(1) qqueueShutdownWorkers(qqueue_t *const pThis) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); if (pThis->qType == QUEUETYPE_DIRECT) { FINALIZE; } assert(pThis->pqParent == NULL); /* detect invalid calling sequence */ DBGOPRINT((obj_t *)pThis, "initiating worker thread shutdown sequence %p\n", pThis); CHKiRet(tryShutdownWorkersWithinQueueTimeout(pThis)); pthread_mutex_lock(pThis->mut); const int parent_phys_queue_size = getPhysicalQueueSize(pThis); const int child_phys_queue_size = pThis->pqDA == NULL ? 0 : getPhysicalQueueSize(pThis->pqDA); pthread_mutex_unlock(pThis->mut); /* The DA transfer worker can empty the memory parent while the disk child * still owns queued or in-flight work. Skipping the action-completion * phase in that state sends the child directly to cancellation, which can * discard an action at the cancellation boundary. Parent and child share * the queue mutex, so inspect both at one stable point. */ if (parent_phys_queue_size > 0 || child_phys_queue_size > 0) { CHKiRet(tryShutdownWorkersWithinActionTimeout(pThis)); } CHKiRet(cancelWorkers(pThis)); /* All worker threads have terminated and been joined. This stable point is * required before save-on-shutdown may restart the DA transfer pool. */ DBGOPRINT((obj_t *)pThis, "worker threads terminated, remaining queue size log %d, phys %d.\n", getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); finalize_it: RETiRet; } /* Constructor for the queue object * This constructs the data structure, but does not yet start the queue. That * is done by queueStart(). The reason is that we want to give the caller a chance * to modify some parameters before the queue is actually started. */ rsRetVal qqueueConstruct(qqueue_t **ppThis, queueType_t qType, int iWorkerThreads, int iMaxQueueSize, rsRetVal (*pConsumer)(void *, batch_t *, wti_t *)) { DEFiRet; qqueue_t *pThis; const uchar *const workDir = glblGetWorkDirRaw(ourConf); assert(ppThis != NULL); assert(pConsumer != NULL); assert(iWorkerThreads > 0); CHKmalloc(pThis = (qqueue_t *)calloc(1, sizeof(qqueue_t))); /* we have an object, so let's fill the properties */ objConstructSetObjInfo(pThis); if (workDir != NULL) { if ((pThis->pszSpoolDir = ustrdup(workDir)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); pThis->lenSpoolDir = ustrlen(pThis->pszSpoolDir); } /* set some water marks so that we have useful defaults if none are set specifically */ pThis->iFullDlyMrk = -1; pThis->iLightDlyMrk = -1; pThis->iMaxFileSize = 1024 * 1024; /* default is 1 MiB */ pThis->iQueueSize = 0; pThis->nLogDeq = 0; pThis->useCryprov = 0; pThis->takeFlowCtlFromMsg = 0; pThis->iMaxQueueSize = iMaxQueueSize; pThis->pConsumer = pConsumer; pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */ pThis->iDeqBatchSize = 8; /* conservative default, should still provide good performance */ pThis->iMinDeqBatchSize = 0; /* conservative default, should still provide good performance */ pThis->isRunning = 0; pThis->onCorruption = QUEUE_ON_CORRUPTION_SAFE_MODE; pThis->diskQueueType = QDA_ENGINE_AUTO; pThis->effectiveDiskQueueType = QDA_ENGINE_AUTO; pThis->diskQueueIdleTimeout = 60000; pThis->pszFilePrefix = NULL; pThis->qType = qType; INIT_ATOMIC_HELPER_MUT(pThis->mutQueueSize); INIT_ATOMIC_HELPER_MUT(pThis->mutLogDeq); INIT_ATOMIC_HELPER_MUT(pThis->mutShutdownImmediate); CHKiRet(qqueueSetiNumWorkerThreads(pThis, iWorkerThreads)); finalize_it: OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP RETiRet; } /* set default inside queue object suitable for action queues. * This shall be called directly after queue construction. This functions has * been added in support of the new v6 config system. It expect properly pre-initialized * objects, but we need to differentiate between ruleset main and action queues. * In order to avoid unnecessary complexity, we provide the necessary defaults * via specific function calls. */ void qqueueSetDefaultsActionQueue(qqueue_t *pThis) { pThis->qType = QUEUETYPE_DIRECT; /* type of the main message queue above */ pThis->iMaxQueueSize = 1000; /* size of the main message queue above */ pThis->iDeqBatchSize = 128; /* default batch size */ pThis->iMinDeqBatchSize = 0; pThis->toMinDeqBatchSize = 1000; pThis->iHighWtrMrk = -1; /* high water mark for disk-assisted queues */ pThis->iLowWtrMrk = -1; /* low water mark for disk-assisted queues */ pThis->iDiscardMrk = -1; /* begin to discard messages */ pThis->iDiscardSeverity = 8; /* turn off */ pThis->iNumWorkerThreads = 1; /* number of worker threads for the mm queue above */ pThis->iMaxFileSize = 1024 * 1024; pThis->iPersistUpdCnt = 0; /* persist queue info every n updates */ pThis->bSyncQueueFiles = 0; pThis->toQShutdown = loadConf->globals.actq_dflt_toQShutdown; /* queue shutdown */ pThis->toActShutdown = loadConf->globals.actq_dflt_toActShutdown; /* action shutdown (in phase 2) */ pThis->toEnq = loadConf->globals.actq_dflt_toEnq; /* timeout for queue enque */ pThis->toWrkShutdown = loadConf->globals.actq_dflt_toWrkShutdown; /* timeout for worker thread shutdown */ pThis->iMinMsgsPerWrkr = -1; /* minimum messages per worker needed to start a new one */ pThis->bSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ pThis->sizeOnDiskMax = 0; /* unlimited */ pThis->iDeqSlowdown = 0; pThis->iDeqtWinFromHr = 0; pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */ pThis->iSmpInterval = 0; /* disable sampling */ pThis->onCorruption = QUEUE_ON_CORRUPTION_SAFE_MODE; } /* set defaults inside queue object suitable for main/ruleset queues. * See queueSetDefaultsActionQueue() for more details and background. */ void qqueueSetDefaultsRulesetQueue(qqueue_t *pThis) { pThis->qType = QUEUETYPE_FIXED_ARRAY; /* type of the main message queue above */ pThis->iMaxQueueSize = 50000; /* size of the main message queue above */ pThis->iDeqBatchSize = 1024; /* default batch size */ pThis->iMinDeqBatchSize = 0; pThis->toMinDeqBatchSize = 1000; pThis->iHighWtrMrk = -1; /* high water mark for disk-assisted queues */ pThis->iLowWtrMrk = -1; /* low water mark for disk-assisted queues */ pThis->iDiscardMrk = -1; /* begin to discard messages */ pThis->iDiscardSeverity = 8; /* turn off */ pThis->iNumWorkerThreads = 1; /* number of worker threads for the mm queue above */ pThis->iMaxFileSize = 16 * 1024 * 1024; pThis->iPersistUpdCnt = 0; /* persist queue info every n updates */ pThis->bSyncQueueFiles = 0; pThis->toQShutdown = ourConf->globals.ruleset_dflt_toQShutdown; pThis->toActShutdown = ourConf->globals.ruleset_dflt_toActShutdown; pThis->toEnq = ourConf->globals.ruleset_dflt_toEnq; pThis->toWrkShutdown = ourConf->globals.ruleset_dflt_toWrkShutdown; pThis->iMinMsgsPerWrkr = -1; /* minimum messages per worker needed to start a new one */ pThis->bSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */ pThis->sizeOnDiskMax = 0; /* unlimited */ pThis->iDeqSlowdown = 0; pThis->iDeqtWinFromHr = 0; pThis->iDeqtWinToHr = 25; /* disable time-windowed dequeuing by default */ pThis->iSmpInterval = 0; /* disable sampling */ pThis->onCorruption = QUEUE_ON_CORRUPTION_SAFE_MODE; } /* This function checks if the provided message shall be discarded and does so, if needed. * In DA mode, we do not discard any messages as we assume the disk subsystem is fast enough to * provide real-time creation of spool files. * Note: cached copies of iQueueSize is provided so that no mutex locks are required. * The caller must have obtained them while the mutex was locked. Of course, these values may no * longer be current, but that is OK for the discard check. At worst, the message is either processed * or discarded when it should not have been. As discarding is in itself somewhat racy and erratic, * that is no problems for us. This function MUST NOT lock the queue mutex, it could result in * deadlocks! * If the message is discarded, it can no longer be processed by the caller. So be sure to check * the return state! * rgerhards, 2008-01-24 */ static int qqueueChkDiscardMsg(qqueue_t *pThis, int iQueueSize, smsg_t *pMsg) { DEFiRet; rsRetVal iRetLocal; int iSeverity; ISOBJ_TYPE_assert(pThis, qqueue); if (pThis->iDiscardMrk > 0 && iQueueSize >= pThis->iDiscardMrk) { iRetLocal = MsgGetSeverity(pMsg, &iSeverity); if (iRetLocal == RS_RET_OK && iSeverity >= pThis->iDiscardSeverity) { DBGOPRINT((obj_t *)pThis, "queue nearly full (%d entries), discarded severity %d message\n", iQueueSize, iSeverity); STATSCOUNTER_INC(pThis->ctrNFDscrd, pThis->mutCtrNFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } else { DBGOPRINT((obj_t *)pThis, "queue nearly full (%d entries), but could not drop msg " "(iRet: %d, severity %d)\n", iQueueSize, iRetLocal, iSeverity); } } finalize_it: RETiRet; } static rsRetVal handleReadSeekError(rsRetVal seekRet, qqueue_t *pThis, const char *streamName, sbool *const pReadSeekFailed) { assert(pReadSeekFailed != NULL); if (seekRet == RS_RET_OK) { return RS_RET_OK; } if (seekRet == RS_RET_FILE_NOT_FOUND) { LogError(0, seekRet, "%s: disk queue %s file missing on startup", obj.GetName((obj_t *)pThis), streamName); *pReadSeekFailed = 1; return RS_RET_OK; } return seekRet; } static void alignReadDeqToWrite(qqueue_t *pThis) { if (pThis->tVars.disk.pReadDeq == NULL || pThis->tVars.disk.pWrite == NULL) { return; } const rsRetVal syncRet = strm.Sync(pThis->tVars.disk.pReadDeq, pThis->tVars.disk.pWrite); if (syncRet != RS_RET_OK) { LogError(0, syncRet, "%s: could not sync disk queue read pointer to write pointer", obj.GetName((obj_t *)pThis)); } const rsRetVal seekRet = strm.SeekCurrOffs(pThis->tVars.disk.pReadDeq); if (seekRet != RS_RET_OK) { LogError(0, seekRet, "%s: could not seek disk queue read pointer after startup recovery hint", obj.GetName((obj_t *)pThis)); } } static void recoverFromInvalidQi(qqueue_t *pThis, const int wr_fd, const int64_t wr_offs) { pThis->tVars.disk.runtimeCorruptionSkip = 0; if (pThis->tVars.disk.pReadDel == NULL || pThis->tVars.disk.pWrite == NULL || wr_fd < 0 || wr_offs < 0) { return; } off64_t bytesDel = 0; int reset_done = 0; const unsigned int del_fnum = pThis->tVars.disk.pReadDel->iCurrFNum; if (del_fnum > (unsigned int)wr_fd) { LogError(0, RS_RET_ERR, "%s: invalid .qi file; delete stream ahead of write stream " "(del_fnum=%u, wr_fd=%d); keeping delete pointer", obj.GetName((obj_t *)pThis), del_fnum, wr_fd); reset_done = 1; } else { const rsRetVal delRet = strmMultiFileSeek(pThis->tVars.disk.pReadDel, (unsigned int)wr_fd, wr_offs, &bytesDel); if (delRet != RS_RET_OK) { LogError(0, delRet, "%s: could not reset disk queue pointers after invalid .qi file", obj.GetName((obj_t *)pThis)); } else { if (bytesDel != 0) { if (pThis->tVars.disk.sizeOnDisk >= bytesDel) { pThis->tVars.disk.sizeOnDisk -= bytesDel; } else { pThis->tVars.disk.sizeOnDisk = 0; } } reset_done = 1; } } if (reset_done && pThis->tVars.disk.pReadDeq != NULL) { const rsRetVal syncRet = strm.Sync(pThis->tVars.disk.pReadDeq, pThis->tVars.disk.pReadDel); if (syncRet != RS_RET_OK) { LogError(0, syncRet, "%s: could not sync disk queue read pointer after invalid .qi file", obj.GetName((obj_t *)pThis)); } /* Non-fatal: queue already reset; keep draining if seek fails. */ const rsRetVal seekRet = strm.SeekCurrOffs(pThis->tVars.disk.pReadDeq); if (seekRet != RS_RET_OK) { LogError(0, seekRet, "%s: could not seek disk queue read pointer after invalid .qi file", obj.GetName((obj_t *)pThis)); } } if (reset_done) { const rsRetVal persistRet = qqueuePersist(pThis, QUEUE_CHECKPOINT); if (persistRet != RS_RET_OK) { LogError(0, persistRet, "%s: could not persist disk queue after invalid .qi reset", obj.GetName((obj_t *)pThis)); } else { pThis->iUpdsSincePersist = 0; } } } /* Finally remove n elements from the queue store. */ static rsRetVal ATTR_NONNULL(1) DoDeleteBatchFromQStore(qqueue_t *const pThis, const int nElem) { int i; off64_t bytesDel = 0; /* keep CLANG static analyzer happy */ DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); /* now send delete request to storage driver */ if (pThis->qType == QUEUETYPE_DISK) { strmMultiFileSeek(pThis->tVars.disk.pReadDel, pThis->tVars.disk.deqFileNumOut, pThis->tVars.disk.deqOffs, &bytesDel); /* We need to correct the on-disk file size. This time it is a bit tricky: * we free disk space only upon file deletion. So we need to keep track of what we * have read until we get an out-offset that is lower than the in-offset (which * indicates file change). Then, we can subtract the whole thing from the on-disk * size. -- rgerhards, 2008-01-30 */ if (bytesDel != 0) { if (pThis->tVars.disk.sizeOnDisk >= bytesDel) { pThis->tVars.disk.sizeOnDisk -= bytesDel; } else { pThis->tVars.disk.sizeOnDisk = 0; } DBGOPRINT((obj_t *)pThis, "doDeleteBatch: a %lld octet file has been deleted, now %lld " "octets disk space used\n", (long long)bytesDel, pThis->tVars.disk.sizeOnDisk); /* awake possibly waiting enq process */ pthread_cond_signal(&pThis->notFull); /* we hold the mutex while we are in here! */ } } else { /* memory queue */ for (i = 0; i < nElem; ++i) { pThis->qDel(pThis); } } /* iQueueSize is not decremented by qDel(), so we need to do it ourselves */ ATOMIC_SUB(&pThis->iQueueSize, nElem, &pThis->mutQueueSize); #ifdef ENABLE_IMDIAG #ifdef HAVE_ATOMIC_BUILTINS /* mutex is never used due to conditional compilation */ ATOMIC_SUB(&iOverallQueueSize, nElem, &NULL); #else iOverallQueueSize -= nElem; /* racy, but we can't wait for a mutex! */ #endif #endif ATOMIC_SUB(&pThis->nLogDeq, nElem, &pThis->mutLogDeq); DBGPRINTF("doDeleteBatch: delete batch from store, new sizes: log %d, phys %d\n", getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); ++pThis->deqIDDel; /* one more batch dequeued */ if ((pThis->qType == QUEUETYPE_DISK) && (bytesDel != 0)) { qqueuePersist(pThis, QUEUE_CHECKPOINT); /* robustness persist .qi file */ } RETiRet; } typedef enum tdlPhase_e { TDL_EMPTY, TDL_PROCESS_HEAD, TDL_QUEUE } tdlPhase_t; /** * Remove messages from the physical queue store that are fully processed. * * Deletion proceeds through a small state machine governed by the * to-delete list: * - TDL_EMPTY: list is empty, delete the current batch directly. * - TDL_PROCESS_HEAD: pending head elements are removed first, then the * current batch. * - TDL_QUEUE: current batch cannot be deleted and is queued for later. * * The dequeue identifier advances strictly monotonically, ensuring * deterministic order and proper resource release for both disk and * memory queue implementations. */ static rsRetVal DeleteBatchFromQStore(qqueue_t *pThis, batch_t *pBatch) { toDeleteLst_t *pTdl; qDeqID nextID; tdlPhase_t phase; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pBatch != NULL); dbgprintf("rger: deleteBatchFromQStore, nElem %d\n", (int)pBatch->nElem); pTdl = tdlPeek(pThis); /* get current head element */ if (pTdl == NULL) { phase = TDL_EMPTY; } else if (pBatch->deqID == pThis->deqIDDel) { phase = TDL_PROCESS_HEAD; } else { phase = TDL_QUEUE; } switch (phase) { case TDL_EMPTY: DoDeleteBatchFromQStore(pThis, pBatch->nElemDeq); break; case TDL_PROCESS_HEAD: nextID = pThis->deqIDDel; while ((pTdl = tdlPeek(pThis)) != NULL && pTdl->deqID == nextID) { DoDeleteBatchFromQStore(pThis, pTdl->nElemDeq); tdlPop(pThis); ++nextID; } assert(pThis->deqIDDel == nextID); /* old entries deleted, now delete current ones... */ DoDeleteBatchFromQStore(pThis, pBatch->nElemDeq); break; case TDL_QUEUE: /* cannot delete, insert into to-delete list */ DBGPRINTF("not at head of to-delete list, enqueue %d\n", (int)pBatch->deqID); CHKiRet(tdlAdd(pThis, pBatch->deqID, pBatch->nElemDeq)); break; default: /* all phases should be handled above. */ assert(0 && "unhandled tdlPhase_t"); break; } finalize_it: RETiRet; } /* Delete a batch of processed user objects from the queue, which includes * destructing the objects themself. Any entries not marked as finally * processed are enqueued again. The new enqueue is necessary because we have a * rgerhards, 2009-05-13 */ static rsRetVal DeleteProcessedBatch(qqueue_t *pThis, batch_t *pBatch) { int i; smsg_t *pMsg; int nEnqueued = 0; rsRetVal localRet; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pBatch != NULL); if (pThis->qCompleteBatch != NULL && pBatch->storeData != NULL) { int committed = 0; int retried = 0; iRet = pThis->qCompleteBatch(pThis, pBatch, &committed, &retried); if (iRet != RS_RET_OK) RETiRet; for (i = 0; i < pBatch->nElem; ++i) { pMsg = pBatch->pElem[i].pMsg; msgDestruct(&pMsg); pBatch->pElem[i].pMsg = NULL; } /* committed is the physical-record count. It intentionally includes * salvaged corrupt records because recovery included those records in * iQueueSize; retried counts only decoded messages appended again. */ if (committed > retried) { const int removed = committed - retried; ATOMIC_SUB(&pThis->iQueueSize, removed, &pThis->mutQueueSize); qqueueSubtractOverallQueueSize(removed); /* A producer may be waiting on either the logical queue limit or * segmented-store disk space released by this completion. */ pthread_cond_signal(&pThis->notFull); } else if (retried > committed) { const int added = retried - committed; qqueueAddPhysicalQueueSize(pThis, added); qqueueAddOverallQueueSize(added); } ATOMIC_SUB(&pThis->nLogDeq, committed, &pThis->mutLogDeq); pBatch->nElem = pBatch->nElemDeq = 0; pBatch->storeData = NULL; RETiRet; } for (i = 0; i < pBatch->nElem; ++i) { pMsg = pBatch->pElem[i].pMsg; DBGPRINTF("DeleteProcessedBatch: etry %d state %d\n", i, pBatch->eltState[i]); if (pBatch->eltState[i] == BATCH_STATE_RDY || pBatch->eltState[i] == BATCH_STATE_SUB) { localRet = doEnqSingleObj(pThis, eFLOWCTL_NO_DELAY, MsgAddRef(pMsg)); ++nEnqueued; if (localRet != RS_RET_OK) { DBGPRINTF( "DeleteProcessedBatch: error %d re-enqueuing unprocessed " "data element - discarded\n", localRet); } } msgDestruct(&pMsg); } DBGPRINTF("DeleteProcessedBatch: we deleted %d objects and enqueued %d objects\n", i - nEnqueued, nEnqueued); if (nEnqueued > 0) qqueueChkPersist(pThis, nEnqueued); iRet = DeleteBatchFromQStore(pThis, pBatch); pBatch->nElem = pBatch->nElemDeq = 0; /* reset batch */ // TODO: more fine init, new fields! 2010-06-14 RETiRet; } /* dequeue as many user pointers as are available, until we hit the configured * upper limit of pointers. Note that this function also deletes all processed * objects from the previous batch. However, it is perfectly valid that the * previous batch contained NO objects at all. For example, this happens * immediately after system startup or when a queue was exhausted and the queue * worker needed to wait for new data. * This must only be called when the queue mutex is LOOKED, otherwise serious * malfunction will happen. */ static rsRetVal ATTR_NONNULL() DequeueConsumableElements(qqueue_t *const pThis, wti_t *const pWti, int *const piRemainingQueueSize, int *const pSkippedMsgs) { int nDequeued; int nDiscarded; int nDeleted; int iQueueSize; int keep_running = 1; int deferredDiskCorruption = 0; rsRetVal pendingCorruptRet = RS_RET_OK; struct timespec timeout; smsg_t *pMsg; rsRetVal localRet; DEFiRet; nDeleted = pWti->batch.nElemDeq; localRet = DeleteProcessedBatch(pThis, &pWti->batch); if (pThis->qCompleteBatch != NULL) CHKiRet(localRet); nDequeued = nDiscarded = 0; if (pThis->qDeqBatch != NULL) { localRet = pThis->qDeqBatch(pThis, &pWti->batch, pThis->iDeqBatchSize, pSkippedMsgs); if (localRet == RS_RET_NO_DATA) { /* With a returned batch, framed corrupt records are included in * nElemDeq and retired by qCompleteBatch. Only an all-corrupt * result has no batch context, so retire those records here. */ if (*pSkippedMsgs > 0) { ATOMIC_SUB(&pThis->iQueueSize, *pSkippedMsgs, &pThis->mutQueueSize); qqueueSubtractOverallQueueSize(*pSkippedMsgs); } pWti->batch.nElem = pWti->batch.nElemDeq = 0; *piRemainingQueueSize = getLogicalQueueSize(pThis); iRet = RS_RET_OK; FINALIZE; } CHKiRet(localRet); for (int i = 0; i < pWti->batch.nElem; ++i) { localRet = qqueueChkDiscardMsg(pThis, pThis->iQueueSize, pWti->batch.pElem[i].pMsg); if (localRet == RS_RET_QUEUE_FULL) { pWti->batch.eltState[i] = BATCH_STATE_DISC; ++nDiscarded; } else { CHKiRet(localRet); } } qqueueAddLogDeq(pThis, pWti->batch.nElemDeq); pWti->batch.deqID = getNextDeqID(pThis); *piRemainingQueueSize = getLogicalQueueSize(pThis); FINALIZE; } if (pThis->qType == QUEUETYPE_DISK) { pThis->tVars.disk.deqFileNumIn = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); pThis->tVars.disk.runtimeCorruptionSkip = 0; if (pThis->tVars.disk.pendingCorruptRet != RS_RET_OK) { pendingCorruptRet = pThis->tVars.disk.pendingCorruptRet; pThis->tVars.disk.pendingCorruptRet = RS_RET_OK; } } /* work-around clang static analyzer false positive, we need a const value */ const int iMinDeqBatchSize = pThis->iMinDeqBatchSize; if (iMinDeqBatchSize > 0) { timeoutComp(&timeout, pThis->toMinDeqBatchSize); /* get absolute timeout */ } while ((iQueueSize = getLogicalQueueSize(pThis)) > 0 && nDequeued < pThis->iDeqBatchSize) { int rd_fd = -1; int64_t rd_offs = 0; int wr_fd = -1; int64_t wr_offs = 0; if (pThis->tVars.disk.pReadDeq != NULL) { rd_fd = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); rd_offs = pThis->tVars.disk.pReadDeq->iCurrOffs; } if (pThis->tVars.disk.pWrite != NULL) { wr_fd = strmGetCurrFileNum(pThis->tVars.disk.pWrite); wr_offs = pThis->tVars.disk.pWrite->iCurrOffs; } pMsg = NULL; if (pendingCorruptRet != RS_RET_OK) { localRet = pendingCorruptRet; pendingCorruptRet = RS_RET_OK; } else { if (rd_fd != -1 && rd_fd == wr_fd && rd_offs == wr_offs) { DBGPRINTF( "problem on disk queue '%s': " //"queue size log %d, phys %d, but rd_fd=wr_rd=%d and offs=%lld\n", "queue size log %d, phys %d, but rd_fd=wr_rd=%d and offs=%" PRId64 "\n", obj.GetName((obj_t *)pThis), iQueueSize, pThis->iQueueSize, rd_fd, rd_offs); if (pThis->onCorruption == QUEUE_ON_CORRUPTION_SAFE_MODE && iQueueSize > 1) { LogMsg(0, RS_RET_ERR, LOG_ALERT, "%s: disk queue corruption reached the write pointer with %d logical records remaining; " "quarantining unread tail", obj.GetName((obj_t *)pThis), iQueueSize); pThis->tVars.disk.runtimeCorruptionSkip = 1; *pSkippedMsgs += iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize); pThis->iQueueSize -= iQueueSize; CHKiRet(qqueueResetDiskQueueAfterCorruption(pThis)); pThis->tVars.disk.runtimeCorruptionSkip = 1; nDiscarded = 0; iQueueSize = 0; break; } *pSkippedMsgs = iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize - nDiscarded); pThis->iQueueSize -= iQueueSize; recoverFromInvalidQi(pThis, wr_fd, wr_offs); iQueueSize = 0; break; } localRet = pThis->qDeq(pThis, &pMsg); if (localRet == RS_RET_FILE_NOT_FOUND) { DBGPRINTF( "fatal error on disk queue '%s': file '%s' " "not found, queue size said to be %d", obj.GetName((obj_t *)pThis), "...", iQueueSize); if (pThis->qType == QUEUETYPE_DISK) { if (pThis->onCorruption == QUEUE_ON_CORRUPTION_SAFE_MODE && iQueueSize > 1) { LogMsg(0, localRet, LOG_ALERT, "%s: disk queue corruption reached a missing file with %d logical records remaining; " "quarantining unread tail", obj.GetName((obj_t *)pThis), iQueueSize); pThis->tVars.disk.runtimeCorruptionSkip = 1; *pSkippedMsgs += iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize); pThis->iQueueSize -= iQueueSize; CHKiRet(qqueueResetDiskQueueAfterCorruption(pThis)); pThis->tVars.disk.runtimeCorruptionSkip = 1; nDiscarded = 0; iQueueSize = 0; break; } *pSkippedMsgs = iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize - nDiscarded); pThis->iQueueSize -= iQueueSize; recoverFromInvalidQi(pThis, wr_fd, wr_offs); iQueueSize = 0; break; } } if (localRet != RS_RET_OK && pThis->qType == QUEUETYPE_DISK && pThis->tVars.disk.pReadDeq != NULL && pThis->tVars.disk.pWrite != NULL && strmGetCurrFileNum(pThis->tVars.disk.pReadDeq) == strmGetCurrFileNum(pThis->tVars.disk.pWrite) && pThis->tVars.disk.pReadDeq->iCurrOffs >= pThis->tVars.disk.pWrite->iCurrOffs) { if (pThis->onCorruption == QUEUE_ON_CORRUPTION_SAFE_MODE && iQueueSize > 1) { LogMsg(0, localRet, LOG_ALERT, "%s: disk queue corruption reached the write pointer with %d logical records remaining; " "quarantining unread tail", obj.GetName((obj_t *)pThis), iQueueSize); pThis->tVars.disk.runtimeCorruptionSkip = 1; *pSkippedMsgs += iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize); pThis->iQueueSize -= iQueueSize; CHKiRet(qqueueResetDiskQueueAfterCorruption(pThis)); pThis->tVars.disk.runtimeCorruptionSkip = 1; nDiscarded = 0; iQueueSize = 0; break; } *pSkippedMsgs = iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize - nDiscarded); pThis->iQueueSize -= iQueueSize; recoverFromInvalidQi(pThis, strmGetCurrFileNum(pThis->tVars.disk.pWrite), pThis->tVars.disk.pWrite->iCurrOffs); iQueueSize = 0; break; } } if (localRet != RS_RET_OK && pThis->qType == QUEUETYPE_DISK && pThis->onCorruption == QUEUE_ON_CORRUPTION_SAFE_MODE) { int nSkippedCorrupt = 0; if (nDequeued > 0) { LogMsg(0, localRet, LOG_WARNING, "%s: disk queue corruption detected after %d valid records; deferring recovery until " "the current batch is committed", obj.GetName((obj_t *)pThis), nDequeued); deferredDiskCorruption = 1; pThis->tVars.disk.pendingCorruptRet = localRet; iRet = RS_RET_OK; break; } localRet = qDeqDiskRecoverAfterCorruption(pThis, &pMsg, localRet, &nSkippedCorrupt); if (localRet != RS_RET_OK && pThis->tVars.disk.pReadDeq != NULL && pThis->tVars.disk.pWrite != NULL && strmGetCurrFileNum(pThis->tVars.disk.pReadDeq) == strmGetCurrFileNum(pThis->tVars.disk.pWrite) && pThis->tVars.disk.pReadDeq->iCurrOffs >= pThis->tVars.disk.pWrite->iCurrOffs) { if (iQueueSize > 1) { LogMsg(0, localRet, LOG_ALERT, "%s: disk queue corruption reached the write pointer with %d logical records remaining; " "quarantining unread tail", obj.GetName((obj_t *)pThis), iQueueSize); pThis->tVars.disk.runtimeCorruptionSkip = 1; *pSkippedMsgs += iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize); pThis->iQueueSize -= iQueueSize; CHKiRet(qqueueResetDiskQueueAfterCorruption(pThis)); pThis->tVars.disk.runtimeCorruptionSkip = 1; nDiscarded = 0; iQueueSize = 0; break; } *pSkippedMsgs = iQueueSize; qqueueSubtractOverallQueueSize(iQueueSize - nDiscarded); pThis->iQueueSize -= iQueueSize; recoverFromInvalidQi(pThis, strmGetCurrFileNum(pThis->tVars.disk.pWrite), pThis->tVars.disk.pWrite->iCurrOffs); iQueueSize = 0; break; } if (localRet == RS_RET_NO_DATA) { pThis->tVars.disk.runtimeCorruptionSkip = 1; *pSkippedMsgs += nSkippedCorrupt; qqueueSubtractOverallQueueSize(nSkippedCorrupt); iQueueSize = 0; break; } if (nSkippedCorrupt > 0) { pThis->tVars.disk.runtimeCorruptionSkip = 1; nDiscarded += nSkippedCorrupt; *pSkippedMsgs += nSkippedCorrupt; } if (localRet == RS_RET_OK) { qqueueAddLogDeq(pThis, nSkippedCorrupt + 1); } } else if (localRet == RS_RET_OK) { qqueueAddLogDeq(pThis, 1); } CHKiRet(localRet); if (pThis->qType == QUEUETYPE_DISK) { strm.GetCurrOffset(pThis->tVars.disk.pReadDeq, &pThis->tVars.disk.deqOffs); pThis->tVars.disk.deqFileNumOut = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); } /* check if we should discard this element */ localRet = qqueueChkDiscardMsg(pThis, pThis->iQueueSize, pMsg); if (localRet == RS_RET_QUEUE_FULL) { ++nDiscarded; continue; } else if (localRet != RS_RET_OK) { ABORT_FINALIZE(localRet); } /* all well, use this element */ pWti->batch.pElem[nDequeued].pMsg = pMsg; pWti->batch.eltState[nDequeued] = BATCH_STATE_RDY; ++nDequeued; if (nDequeued < iMinDeqBatchSize && getLogicalQueueSize(pThis) == 0) { while (!qqueueIsShutdownImmediate(pThis) && keep_running && nDequeued < iMinDeqBatchSize && getLogicalQueueSize(pThis) == 0) { dbgprintf( "%s minDeqBatchSize doing wait, batch is %d messages, " "queue size %d\n", obj.GetName((obj_t *)pThis), nDequeued, getLogicalQueueSize(pThis)); if (wtiWaitNonEmpty(pWti, timeout) == 0) { /* timeout? */ DBGPRINTF("%s minDeqBatchSize timeout, batch is %d messages\n", obj.GetName((obj_t *)pThis), nDequeued); keep_running = 0; } } } if (keep_running) { keep_running = (getLogicalQueueSize(pThis) > 0) && (nDequeued < pThis->iDeqBatchSize); } } if (pThis->qType == QUEUETYPE_DISK && !deferredDiskCorruption) { strm.GetCurrOffset(pThis->tVars.disk.pReadDeq, &pThis->tVars.disk.deqOffs); pThis->tVars.disk.deqFileNumOut = strmGetCurrFileNum(pThis->tVars.disk.pReadDeq); } /* it is sufficient to persist only when the bulk of work is done */ qqueueChkPersist(pThis, nDequeued + nDiscarded + nDeleted); /* If messages where DISCARDED, we need to substract them from the OverallQueueSize */ #ifdef ENABLE_IMDIAG #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_SUB(&iOverallQueueSize, nDiscarded, &NULL); #else iOverallQueueSize -= nDiscarded; /* racy, but we can't wait for a mutex! */ #endif DBGOPRINT((obj_t *)pThis, "dequeued %d discarded %d QueueSize %d consumable elements, szlog %d sz phys %d\n", nDequeued, nDiscarded, iOverallQueueSize, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); #else DBGOPRINT((obj_t *)pThis, "dequeued %d discarded %d consumable elements, szlog %d sz phys %d\n", nDequeued, nDiscarded, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); #endif pWti->batch.nElem = nDequeued; pWti->batch.nElemDeq = nDequeued + nDiscarded; pWti->batch.deqID = getNextDeqID(pThis); *piRemainingQueueSize = iQueueSize; finalize_it: RETiRet; } /* dequeue the queued object for the queue consumers. * rgerhards, 2008-10-21 * I made a radical change - we now dequeue multiple elements, and store these objects in * an array of user pointers. We expect that this increases performance. * rgerhards, 2009-04-22 */ static rsRetVal DequeueConsumable(qqueue_t *pThis, wti_t *pWti, int *const pSkippedMsgs) { DEFiRet; int iQueueSize = 0; /* keep the compiler happy... */ *pSkippedMsgs = 0; /* dequeue element batch (still protected from mutex) */ iRet = DequeueConsumableElements(pThis, pWti, &iQueueSize, pSkippedMsgs); if (*pSkippedMsgs > 0) { if (pThis->qType == QUEUETYPE_SEGMENTED_DISK) { LogMsg(0, RS_RET_ERR, LOG_ERR, "%s: segmentedDisk salvage skipped %d corrupt records", obj.GetName((obj_t *)pThis), *pSkippedMsgs); } else if (pThis->qType == QUEUETYPE_DISK && pThis->tVars.disk.runtimeCorruptionSkip) { LogMsg(0, RS_RET_ERR, LOG_ERR, "%s: skipped %d messages from diskqueue during runtime corruption handling", obj.GetName((obj_t *)pThis), *pSkippedMsgs); } else { LogError(0, RS_RET_ERR, "%s: lost %d messages from diskqueue (invalid .qi file)", obj.GetName((obj_t *)pThis), *pSkippedMsgs); } } /* awake some flow-controlled sources if we can do this right now */ /* TODO: this could be done better from a performance point of view -- do it only if * we have someone waiting for the condition (or only when we hit the watermark right * on the nail [exact value]) -- rgerhards, 2008-03-14 * now that we dequeue batches of pointers, this is much less an issue... * rgerhards, 2009-04-22 */ if (iQueueSize < pThis->iFullDlyMrk / 2 || glbl.GetGlobalInputTermState() == 1) { pthread_cond_broadcast(&pThis->belowFullDlyWtrMrk); } if (iQueueSize < pThis->iLightDlyMrk / 2) { pthread_cond_broadcast(&pThis->belowLightDlyWtrMrk); } pthread_cond_signal(&pThis->notFull); /* WE ARE NO LONGER PROTECTED BY THE MUTEX */ if (iRet != RS_RET_OK && iRet != RS_RET_DISCARDMSG) { LogError(0, iRet, "%s: error dequeueing element - ignoring, " "but strange things may happen", obj.GetName((obj_t *)pThis)); } RETiRet; } /* The rate limiter * * IMPORTANT: the rate-limiter MUST unlock and re-lock the queue when * it actually delays processing. Otherwise inputs are stalled. * * Here we may wait if a dequeue time window is defined or if we are * rate-limited. TODO: If we do so, we should also look into the * way new worker threads are spawned. Obviously, it doesn't make much * sense to spawn additional worker threads when none of them can do any * processing. However, it is deemed acceptable to allow this for an initial * implementation of the timeframe/rate limiting feature. * Please also note that these feature could also be implemented at the action * level. However, that would limit them to be used together with actions. We have * taken the broader approach, moving it right into the queue. This is even * necessary if we want to prevent spawning of multiple unnecessary worker * threads as described above. -- rgerhards, 2008-04-02 * * * time window: tCurr is current time; tFrom is start time, tTo is end time (in mil 24h format). * We may have tFrom = 4, tTo = 10 --> run from 4 to 10 hrs. nice and happy * we may also have tFrom= 22, tTo = 4 -> run from 10pm to 4am, which is actually two * windows: 0-4; 22-23:59 * so when to run? Let's assume we have 3am * * if(tTo < tFrom) { * if(tCurr < tTo [3 < 4] || tCurr > tFrom [3 > 22]) * do work * else * sleep for tFrom - tCurr "hours" [22 - 5 --> 17] * } else { * if(tCurr >= tFrom [3 >= 4] && tCurr < tTo [3 < 10]) * do work * else * sleep for tTo - tCurr "hours" [4 - 3 --> 1] * } * * Bottom line: we need to check which type of window we have and need to adjust our * logic accordingly. Of course, sleep calculations need to be done up to the minute, * but you get the idea from the code above. */ static rsRetVal RateLimiter(qqueue_t *pThis) { DEFiRet; int iDelay; int iHrCurr; time_t tCurr; struct tm m; ISOBJ_TYPE_assert(pThis, qqueue); iDelay = 0; if (pThis->iDeqtWinToHr != 25) { /* 25 means disabled */ /* time calls are expensive, so only do them when needed */ datetime.GetTime(&tCurr); localtime_r(&tCurr, &m); iHrCurr = m.tm_hour; if (pThis->iDeqtWinToHr < pThis->iDeqtWinFromHr) { if (iHrCurr < pThis->iDeqtWinToHr || iHrCurr > pThis->iDeqtWinFromHr) { ; /* do not delay */ } else { iDelay = (pThis->iDeqtWinFromHr - iHrCurr) * 3600; /* this time, we are already into the next hour, so we need * to subtract our current minute and seconds. */ iDelay -= m.tm_min * 60; iDelay -= m.tm_sec; } } else { if (iHrCurr >= pThis->iDeqtWinFromHr && iHrCurr < pThis->iDeqtWinToHr) { ; /* do not delay */ } else { if (iHrCurr < pThis->iDeqtWinFromHr) { iDelay = (pThis->iDeqtWinFromHr - iHrCurr - 1) * 3600; /* -1 as we are already in the hour */ iDelay += (60 - m.tm_min) * 60; iDelay += 60 - m.tm_sec; } else { iDelay = (24 - iHrCurr + pThis->iDeqtWinFromHr) * 3600; /* this time, we are already into the next hour, so we need * to subtract our current minute and seconds. */ iDelay -= m.tm_min * 60; iDelay -= m.tm_sec; } } } } if (iDelay > 0) { pthread_mutex_unlock(pThis->mut); DBGOPRINT((obj_t *)pThis, "outside dequeue time window, delaying %d seconds\n", iDelay); srSleep(iDelay, 0); pthread_mutex_lock(pThis->mut); } RETiRet; } /* This dequeues the next batch. Note that this function must not be * cancelled, else it will leave back an inconsistent state. * rgerhards, 2009-05-20 */ static rsRetVal DequeueForConsumer(qqueue_t *pThis, wti_t *pWti, int *const pSkippedMsgs) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); ISOBJ_TYPE_assert(pWti, wti); CHKiRet(DequeueConsumable(pThis, pWti, pSkippedMsgs)); if (pWti->batch.nElem == 0) ABORT_FINALIZE(RS_RET_IDLE); finalize_it: RETiRet; } /* This is called when a batch is processed and the worker does not * ask for another batch (e.g. because it is to be terminated) * Note that we must not be terminated while we delete a processed * batch. Otherwise, we may not complete it, and then the cancel * handler also tries to delete the batch. But then it finds some of * the messages already destructed. This was a bug we have seen, especially * with disk mode, where a delete takes rather long. Anyhow, the coneptual * problem exists in all queue modes. * rgerhards, 2009-05-27 */ static rsRetVal batchProcessed(qqueue_t *pThis, wti_t *pWti) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); ISOBJ_TYPE_assert(pWti, wti); int iCancelStateSave; /* at this spot, we must not be cancelled */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); DeleteProcessedBatch(pThis, &pWti->batch); qqueueChkPersist(pThis, pWti->batch.nElemDeq); pthread_setcancelstate(iCancelStateSave, NULL); RETiRet; } /* This is the queue consumer in the regular (non-DA) case. It is * protected by the queue mutex, but MUST release it as soon as possible. * rgerhards, 2008-01-21 */ static rsRetVal ConsumerReg(qqueue_t *pThis, wti_t *pWti) { int iCancelStateSave; int bNeedReLock = 0; /**< do we need to lock the mutex again? */ int skippedMsgs = 0; /**< did the queue loose any messages (can happen with ** disk queue if .qi file is corrupt */ DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); ISOBJ_TYPE_assert(pWti, wti); iRet = DequeueForConsumer(pThis, pWti, &skippedMsgs); if (iRet == RS_RET_FILE_NOT_FOUND) { /* This is a fatal condition and means the queue is almost unusable */ d_pthread_mutex_unlock(pThis->mut); DBGOPRINT((obj_t *)pThis, "got 'file not found' error %d, queue defunct\n", iRet); iRet = queueSwitchToEmergencyMode(pThis, iRet); // TODO: think about what to return as iRet -- keep RS_RET_FILE_NOT_FOUND? d_pthread_mutex_lock(pThis->mut); } if (iRet != RS_RET_OK) { FINALIZE; } /* we now have a non-idle batch of work, so we can release the queue mutex and process it */ d_pthread_mutex_unlock(pThis->mut); bNeedReLock = 1; /* report errors, now that we are outside of queue lock */ if (skippedMsgs > 0) { if (pThis->qType != QUEUETYPE_SEGMENTED_DISK) LogError(0, 0, "problem on disk queue '%s': " "queue files contain %d messages fewer than specified " "in .qi file -- we lost those messages. That's all we know.", obj.GetName((obj_t *)pThis), skippedMsgs); } /* at this spot, we may be cancelled */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &iCancelStateSave); qqueueSetWtiShutdownImmediate(pThis, pWti); CHKiRet(pThis->pConsumer(pThis->pAction, &pWti->batch, pWti)); /* we now need to check if we should deliberately delay processing a bit * and, if so, do that. -- rgerhards, 2008-01-30 */ if (pThis->iDeqSlowdown) { DBGOPRINT((obj_t *)pThis, "sleeping %d microseconds as requested by config params\n", pThis->iDeqSlowdown); srSleep(pThis->iDeqSlowdown / 1000000, pThis->iDeqSlowdown % 1000000); } /* but now cancellation is no longer permitted */ pthread_setcancelstate(iCancelStateSave, NULL); finalize_it: DBGPRINTF("regular consumer finished, iret=%d, szlog %d sz phys %d\n", iRet, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); /* now we are done, but potentially need to re-acquire the mutex */ if (bNeedReLock) d_pthread_mutex_lock(pThis->mut); RETiRet; } /* This is a special consumer to feed the disk-queue in disk-assisted mode. * When active, our own queue more or less acts as a memory buffer to the disk. * So this consumer just needs to drain the memory queue and submit entries * to the disk queue. The disk queue will then call the actual consumer from * the app point of view (we chain two queues here). * When this method is entered, the mutex is always locked and needs to be unlocked * as part of the processing. * rgerhards, 2008-01-14 */ static rsRetVal ConsumerDA(qqueue_t *pThis, wti_t *pWti) { int i; int iCancelStateSave; int bNeedReLock = 0; /**< do we need to lock the mutex again? */ int skippedMsgs = 0; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); ISOBJ_TYPE_assert(pWti, wti); CHKiRet(DequeueForConsumer(pThis, pWti, &skippedMsgs)); /* we now have a non-idle batch of work, so we can release the queue mutex and process it */ d_pthread_mutex_unlock(pThis->mut); bNeedReLock = 1; /* at this spot, we may be cancelled */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &iCancelStateSave); /* iterate over returned results and enqueue them in DA queue */ for (i = 0; i < pWti->batch.nElem && !qqueueIsShutdownImmediate(pThis); i++) { iRet = qqueueEnqMsg(pThis->pqDA, eFLOWCTL_NO_DELAY, MsgAddRef(pWti->batch.pElem[i].pMsg)); if (iRet != RS_RET_OK) { if (iRet == RS_RET_ERR_QUEUE_EMERGENCY) { /* Queue emergency error occurred */ DBGOPRINT((obj_t *)pThis, "ConsumerDA:qqueueEnqMsg caught RS_RET_ERR_QUEUE_EMERGENCY," "aborting loop.\n"); FINALIZE; } else { DBGOPRINT((obj_t *)pThis, "ConsumerDA:qqueueEnqMsg item (%d) returned " "with error state: '%d'\n", i, iRet); if (pThis->pqDA->qType == QUEUETYPE_SEGMENTED_DISK) { /* The segmented child may fail before the event becomes * durable (for example while publishing its engine marker * or materializing the store). Leave this and the * remaining batch elements uncommitted so normal parent * retry handling preserves them. Classic DA behavior is * intentionally unchanged. */ break; } } } pWti->batch.eltState[i] = BATCH_STATE_COMM; /* commited to other queue! */ } /* but now cancellation is no longer permitted */ pthread_setcancelstate(iCancelStateSave, NULL); finalize_it: /* Check the last return state of qqueueEnqMsg. If an error was returned, we acknowledge it only. * Unless the error code is RS_RET_ERR_QUEUE_EMERGENCY, we reset the return state to RS_RET_OK. * Otherwise the Caller functions would run into an infinite Loop trying to enqueue the * same messages over and over again. * * However we do NOT overwrite positive return states like * RS_RET_TERMINATE_NOW, * RS_RET_NO_RUN, * RS_RET_IDLE, * RS_RET_TERMINATE_WHEN_IDLE * These return states are important for Queue handling of the upper laying functions. * RGer: Note that checking for iRet < 0 is a bit bold. In theory, positive iRet * values are "OK" states, and things that the caller shall deal with. However, * this has not been done so consistently. Andre convinced me that the current * code is an elegant solution. However, if problems with queue workers and/or * shutdown come up, this code here should be looked at suspiciously. In those * cases it may work out to check all status codes explicitely, just to avoid * a pitfall due to unexpected states being passed on to the caller. */ if (iRet != RS_RET_OK && iRet != RS_RET_ERR_QUEUE_EMERGENCY && iRet < 0) { DBGOPRINT((obj_t *)pThis, "ConsumerDA:qqueueEnqMsg Resetting iRet from %d back to RS_RET_OK\n", iRet); iRet = RS_RET_OK; } else { DBGOPRINT((obj_t *)pThis, "ConsumerDA:qqueueEnqMsg returns with iRet %d\n", iRet); } /* now we are done, but potentially need to re-acquire the mutex */ if (bNeedReLock) d_pthread_mutex_lock(pThis->mut); RETiRet; } /* must only be called when the queue mutex is locked, else results * are not stable! */ static rsRetVal qqueueChkStopWrkrDA(qqueue_t *pThis) { DEFiRet; DBGPRINTF("rger: chkStopWrkrDA called, low watermark %d, log Size %d, phys Size %d, bEnqOnly %d\n", pThis->iLowWtrMrk, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->bEnqOnly); if (pThis->bEnqOnly) { iRet = RS_RET_TERMINATE_WHEN_IDLE; } if (getPhysicalQueueSize(pThis) <= pThis->iLowWtrMrk) { iRet = RS_RET_TERMINATE_NOW; } RETiRet; } /* must only be called when the queue mutex is locked, else results * are not stable! * Version for the regular worker thread. DA child queues intentionally keep * their regular worker alive while idle so worker-instance state, such as * output connections, survives short refill gaps. */ static rsRetVal ChkStopWrkrReg(qqueue_t *pThis) { DEFiRet; /*DBGPRINTF("XXXX: chkStopWrkrReg called, low watermark %d, log Size %d, phys Size %d, bEnqOnly %d\n", pThis->iLowWtrMrk, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->bEnqOnly);*/ if (pThis->bEnqOnly) { iRet = RS_RET_TERMINATE_NOW; } RETiRet; } /* return the configured "deq max at once" interval * rgerhards, 2009-04-22 */ static rsRetVal GetDeqBatchSize(qqueue_t *pThis, int *pVal) { DEFiRet; assert(pVal != NULL); *pVal = pThis->iDeqBatchSize; RETiRet; } /* start up the queue - it must have been constructed and parameters defined * before. */ rsRetVal qqueueStart(rsconf_t *cnf, qqueue_t *pThis) /* this is the ConstructionFinalizer */ { DEFiRet; uchar pszBuf[64]; uchar pszQIFNam[MAXFNAME]; int wrk; uchar *qName; size_t lenBuf; assert(pThis != NULL); /* do not modify the queue if it's already running(happens when dynamic config reload is invoked * and the queue is used in the new config as well) */ if (pThis->isRunning) FINALIZE; dbgoprint((obj_t *)pThis, "starting queue\n"); if (pThis->pszSpoolDir == NULL) { /* note: we need to pick the path so late as we do not have * the workdir during early config load */ if ((pThis->pszSpoolDir = (uchar *)strdup((char *)glbl.GetWorkDir(cnf))) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); pThis->lenSpoolDir = ustrlen(pThis->pszSpoolDir); } if (pThis->qType == QUEUETYPE_SEGMENTED_DISK && pThis->pszSpoolDir[0] == '\0') { LogError(0, RS_RET_CONF_PARAM_INVLD, "error on queue '%s': segmentedDisk requires queue.spoolDirectory or a global workDirectory", obj.GetName((obj_t *)pThis)); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } /* set type-specific handlers and other very type-specific things * (we can not totally hide it...) */ pThis->qDeqBatch = NULL; pThis->qCompleteBatch = NULL; switch (pThis->qType) { case QUEUETYPE_FIXED_ARRAY: pThis->qConstruct = qConstructFixedArray; pThis->qDestruct = qDestructFixedArray; pThis->qAdd = qAddFixedArray; pThis->qDeq = qDeqFixedArray; pThis->qDel = qDelFixedArray; pThis->MultiEnq = qqueueMultiEnqObjNonDirect; break; case QUEUETYPE_LINKEDLIST: pThis->qConstruct = qConstructLinkedList; pThis->qDestruct = qDestructLinkedList; pThis->qAdd = qAddLinkedList; pThis->qDeq = qDeqLinkedList; pThis->qDel = qDelLinkedList; pThis->MultiEnq = qqueueMultiEnqObjNonDirect; break; case QUEUETYPE_DISK: pThis->qConstruct = qConstructDisk; pThis->qDestruct = qDestructDisk; pThis->qAdd = qAddDisk; pThis->qDeq = qDeqDisk; pThis->qDel = NULL; /* delete for disk handled via special code! */ pThis->MultiEnq = qqueueMultiEnqObjNonDirect; /* pre-construct file name for .qi file */ pThis->lenQIFNam = snprintf((char *)pszQIFNam, sizeof(pszQIFNam), "%s/%s.qi", (char *)pThis->pszSpoolDir, (char *)pThis->pszFilePrefix); pThis->pszQIFNam = ustrdup(pszQIFNam); DBGOPRINT((obj_t *)pThis, ".qi file name is '%s', len %d\n", pThis->pszQIFNam, (int)pThis->lenQIFNam); break; case QUEUETYPE_SEGMENTED_DISK: pThis->qConstruct = qConstructSegDisk; pThis->qDestruct = qDestructSegDisk; pThis->qAdd = qAddSegDisk; pThis->qDeq = NULL; pThis->qDel = NULL; pThis->qDeqBatch = qDeqBatchSegDisk; pThis->qCompleteBatch = qCompleteBatchSegDisk; pThis->MultiEnq = qqueueMultiEnqObjNonDirect; break; case QUEUETYPE_DIRECT: pThis->qConstruct = qConstructDirect; pThis->qDestruct = qDestructDirect; /* these entry points shall not be used in direct mode * To catch program errors, make us abort if that happens! * rgerhards, 2013-11-05 */ pThis->qAdd = qAddDirect; pThis->MultiEnq = qqueueMultiEnqObjDirect; pThis->qDel = NULL; break; default: // We need to satisfy compiler which does not properly handle enum break; } /* finalize some initializations that could not yet be done because it is * influenced by properties which might have been set after queueConstruct () */ if (pThis->pqParent == NULL) { CHKmalloc(pThis->mut = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t))); pthread_mutex_init(pThis->mut, NULL); } else { /* child queue, we need to use parent's mutex */ DBGOPRINT((obj_t *)pThis, "I am a child\n"); pThis->mut = pThis->pqParent->mut; } pthread_mutex_init(&pThis->mutThrdMgmt, NULL); pthread_cond_init(&pThis->notFull, NULL); pthread_cond_init(&pThis->belowFullDlyWtrMrk, NULL); pthread_cond_init(&pThis->belowLightDlyWtrMrk, NULL); /* call type-specific constructor */ CHKiRet(pThis->qConstruct(pThis)); /* this also sets bIsDA */ /* re-adjust some params if required */ if (pThis->bIsDA) { /* if we are in DA mode, we must make sure full delayable messages do not * initiate going to disk! */ wrk = pThis->iHighWtrMrk - (pThis->iHighWtrMrk / 100) * 50; /* 50% of high water mark */ if (wrk < pThis->iFullDlyMrk) pThis->iFullDlyMrk = wrk; } DBGOPRINT((obj_t *)pThis, "params: type %d, enq-only %d, disk assisted %d, spoolDir '%s', maxFileSz %lld, " "maxQSize %d, lqsize %d, pqsize %d, child %d, full delay %d, " "light delay %d, deq batch size %d, min deq batch size %d, " "high wtrmrk %d, low wtrmrk %d, " "discardmrk %d, max wrkr %d, min msgs f. wrkr %d " "takeFlowCtlFromMsg %d\n", pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->pszSpoolDir, pThis->iMaxFileSize, pThis->iMaxQueueSize, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis), pThis->pqParent == NULL ? 0 : 1, pThis->iFullDlyMrk, pThis->iLightDlyMrk, pThis->iDeqBatchSize, pThis->iMinDeqBatchSize, pThis->iHighWtrMrk, pThis->iLowWtrMrk, pThis->iDiscardMrk, (int)pThis->iNumWorkerThreads, (int)pThis->iMinMsgsPerWrkr, pThis->takeFlowCtlFromMsg); pThis->bQueueStarted = 1; if (pThis->qType == QUEUETYPE_DIRECT) FINALIZE; /* with direct queues, we are already finished... */ /* create worker thread pools for regular and DA operation. */ lenBuf = snprintf((char *)pszBuf, sizeof(pszBuf), "%.*s:Reg", (int)(sizeof(pszBuf) - 16), obj.GetName((obj_t *)pThis)); /* leave some room inside the name for suffixes */ if (lenBuf >= sizeof(pszBuf)) { LogError(0, RS_RET_INTERNAL_ERROR, "%s:%d debug header too long: %zd - in " "thory this cannot happen - truncating", __FILE__, __LINE__, lenBuf); lenBuf = sizeof(pszBuf) - 1; pszBuf[lenBuf] = '\0'; } CHKiRet(wtpConstruct(&pThis->pWtpReg)); CHKiRet(wtpSetDbgHdr(pThis->pWtpReg, pszBuf, lenBuf)); CHKiRet(wtpSetpfRateLimiter(pThis->pWtpReg, (rsRetVal(*)(void *pUsr))RateLimiter)); CHKiRet(wtpSetpfChkStopWrkr(pThis->pWtpReg, (rsRetVal(*)(void *pUsr, int))ChkStopWrkrReg)); CHKiRet(wtpSetpfGetDeqBatchSize(pThis->pWtpReg, (rsRetVal(*)(void *pUsr, int *))GetDeqBatchSize)); CHKiRet(wtpSetpfDoWork(pThis->pWtpReg, (rsRetVal(*)(void *pUsr, void *pWti))ConsumerReg)); CHKiRet(wtpSetpfObjProcessed(pThis->pWtpReg, (rsRetVal(*)(void *pUsr, wti_t *pWti))batchProcessed)); CHKiRet(wtpSetpmutUsr(pThis->pWtpReg, pThis->mut)); CHKiRet(wtpSetiNumWorkerThreads(pThis->pWtpReg, pThis->iNumWorkerThreads)); CHKiRet(wtpSettoWrkShutdown(pThis->pWtpReg, pThis->toWrkShutdown)); /* This callback implements runtime idle dematerialization only. Process * shutdown deliberately stops and joins the workers without waiting for * this timer; qDestructSegDisk() then closes the store and, when empty, * removes its segments, state file, and directory synchronously. */ if (pThis->segdiskDAChild && pThis->diskQueueIdleTimeout != -1) { CHKiRet(wtpSetbAllowFirstWorkerToTimeout(pThis->pWtpReg, 1)); CHKiRet(wtpSetpfIdleTimeout(pThis->pWtpReg, (rsRetVal(*)(void *pUsr))qqueueSegDiskIdleTimeout)); CHKiRet(wtpSettoFirstWrkShutdown(pThis->pWtpReg, pThis->diskQueueIdleTimeout)); } else if (pThis->segdiskDAChild) { /* An idle timeout of -1 disables dematerialization without disabling * the normal shutdown timeout for additional workers. Explicitly * keep slot zero non-timeout-capable: wtpStartWrkr() consequently * marks that slot always-running, so the generic worker timeout can * never terminate the segmented DA child's final worker. */ CHKiRet(wtpSetbAllowFirstWorkerToTimeout(pThis->pWtpReg, 0)); } CHKiRet(wtpSetpUsr(pThis->pWtpReg, pThis)); CHKiRet(wtpConstructFinalize(pThis->pWtpReg)); /* Validate queue configuration before starting */ if (pThis->qType == QUEUETYPE_DISK || pThis->qType == QUEUETYPE_SEGMENTED_DISK || pThis->bIsDA) { /* Check that maxDiskSpace is not smaller than maxFileSize */ if (pThis->sizeOnDiskMax > 0 && pThis->iMaxFileSize > 0 && pThis->sizeOnDiskMax < pThis->iMaxFileSize) { LogError(0, RS_RET_CONF_PARAM_INVLD, "queue.maxDiskSpace (%lld) must be larger than queue.maxFileSize (%lld) - " "setting queue.maxDiskSpace to %lld", pThis->sizeOnDiskMax, pThis->iMaxFileSize, pThis->iMaxFileSize); pThis->sizeOnDiskMax = pThis->iMaxFileSize; } } /* set up DA system if we have a disk-assisted queue */ if (pThis->bIsDA) CHKiRet(InitDA(pThis, LOCK_MUTEX)); /* initiate DA mode */ DBGOPRINT((obj_t *)pThis, "queue finished initialization\n"); /* if the queue already contains data, we need to start the correct number of worker threads. This can be * the case when a disk queue has been loaded. If we did not start it here, it would never start. */ qqueueAdviseMaxWorkers(pThis); /* support statistics gathering */ qName = obj.GetName((obj_t *)pThis); CHKiRet(statsobj.Construct(&pThis->statsobj)); CHKiRet(statsobj.SetName(pThis->statsobj, qName)); CHKiRet(statsobj.SetOrigin(pThis->statsobj, (uchar *)"core.queue")); /* we need to save the queue size, as the stats module initializes it to 0! */ /* iQueueSize is a dual-use counter: no init, no mutex! */ CHKiRet( statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("size"), ctrType_Int, CTR_FLAG_NONE, &pThis->iQueueSize)); STATSCOUNTER_INIT(pThis->ctrEnqueued, pThis->mutCtrEnqueued); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("enqueued"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrEnqueued)); STATSCOUNTER_INIT(pThis->ctrSizeEnqueued, pThis->mutCtrSizeEnqueued); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("size.enqueued"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrSizeEnqueued)); STATSCOUNTER_INIT(pThis->ctrFull, pThis->mutCtrFull); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("full"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFull)); STATSCOUNTER_INIT(pThis->ctrFDscrd, pThis->mutCtrFDscrd); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("discarded.full"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrFDscrd)); STATSCOUNTER_INIT(pThis->ctrNFDscrd, pThis->mutCtrNFDscrd); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("discarded.nf"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &pThis->ctrNFDscrd)); pThis->ctrMaxqsize = 0; /* no mutex needed, thus no init call */ CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("maxqsize"), ctrType_Int, CTR_FLAG_NONE, &pThis->ctrMaxqsize)); if (pThis->qType == QUEUETYPE_SEGMENTED_DISK) { CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("disk.usage"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("segments"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskSegments)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("checkpoints"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskCheckpoints)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("replayed"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskReplayed)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("corruption.events"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskCorruptionEvents)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("corruption.bytes"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskCorruptionBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("corruption.records"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskCorruptionRecords)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("corruption.segments"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskCorruptionSegments)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("retry.overage.bytes"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskRetryOverageBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("retry.overage.maxbytes"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskRetryOverageMaxBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("state.writes"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskStateWrites)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("state.forcedWrites"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskForcedStateWrites)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("recovery.pending"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskRecoveryPending)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("recovery.bytes"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskRecoveryBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("recovery.records"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskRecoveryRecords)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("startup.payloadBytesRead"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskStartupPayloadBytes)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("startup.segmentFilesProbed"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskStartupSegmentFilesProbed)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("store.materializations"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskMaterializations)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("store.idleDematerializations"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskDematerializations)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("store.idleCleanupFailures"), ctrType_Int, CTR_FLAG_NONE, &pThis->segdiskIdleCleanupFailures)); CHKiRet(statsobj.AddCounter(pThis->statsobj, UCHAR_CONSTANT("workers.current"), ctrType_Int, CTR_FLAG_NONE, &pThis->pWtpReg->iCurNumWrkThrd)); } CHKiRet(statsobj.ConstructFinalize(pThis->statsobj)); finalize_it: if (iRet != RS_RET_OK) { /* note: a child uses it's parent mutex, so do not delete it! */ if (pThis->pqParent == NULL && pThis->mut != NULL) free(pThis->mut); } else { pThis->isRunning = 1; } RETiRet; } /* persist the queue to disk (write the .qi file). If we have something to persist, we first * save the information on the queue properties itself and then we call * the queue-type specific drivers. * Variable bIsCheckpoint is set to 1 if the persist is for a checkpoint, * and 0 otherwise. * rgerhards, 2008-01-10 */ static rsRetVal qqueuePersist(qqueue_t *pThis, int bIsCheckpoint) { DEFiRet; char *tmpQIFName = NULL; strm_t *psQIF = NULL; /* Queue Info File */ char errStr[1024]; assert(pThis != NULL); if (pThis->qType == QUEUETYPE_SEGMENTED_DISK) { CHKiRet(segdiskStoreCheckpoint(pThis->tVars.segdisk, bIsCheckpoint != QUEUE_CHECKPOINT)); qqueueUpdateSegDiskStats(pThis); FINALIZE; } if (pThis->qType != QUEUETYPE_DISK) { if (getPhysicalQueueSize(pThis) > 0) { /* This error code is OK, but we will probably not implement this any time * The reason is that persistence happens via DA queues. But I would like to * leave the code as is, as we so have a hook in case we need one. * -- rgerhards, 2008-01-28 */ ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED); } else FINALIZE; /* if the queue is empty, we are happy and done... */ } DBGOPRINT((obj_t *)pThis, "persisting queue to disk, %d entries...\n", getPhysicalQueueSize(pThis)); if ((bIsCheckpoint != QUEUE_CHECKPOINT) && (getPhysicalQueueSize(pThis) == 0)) { if (pThis->bNeedDelQIF) { unlink((char *)pThis->pszQIFNam); pThis->bNeedDelQIF = 0; } /* indicate spool file needs to be deleted */ if (pThis->tVars.disk.pReadDel != NULL) /* may be NULL if we had a startup failure! */ CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 1)); FINALIZE; /* nothing left to do, so be happy */ } int lentmpQIFName; lentmpQIFName = asprintf((char **)&tmpQIFName, "%s.tmp", pThis->pszQIFNam); if (tmpQIFName == NULL) tmpQIFName = (char *)pThis->pszQIFNam; CHKiRet(strm.Construct(&psQIF)); CHKiRet(strm.SettOperationsMode(psQIF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetbSync(psQIF, pThis->bSyncQueueFiles)); CHKiRet(strm.SetsType(psQIF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetbNoFollowFinal(psQIF, 1)); CHKiRet(strm.SetFName(psQIF, (uchar *)tmpQIFName, lentmpQIFName)); CHKiRet(strm.ConstructFinalize(psQIF)); /* first, write the property bag for ourselfs * And, surprisingly enough, we currently need to persist only the size of the * queue. All the rest is re-created with then-current config parameters when the * queue is re-created. Well, we'll also save the current queue type, just so that * we know when somebody has changed the queue type... -- rgerhards, 2008-01-11 */ CHKiRet(obj.BeginSerializePropBag(psQIF, (obj_t *)pThis)); objSerializeSCALAR(psQIF, iQueueSize, INT); objSerializeSCALAR(psQIF, tVars.disk.sizeOnDisk, INT64); CHKiRet(obj.EndSerialize(psQIF)); /* now persist the stream info */ if (pThis->tVars.disk.pWrite != NULL) CHKiRet(strm.Serialize(pThis->tVars.disk.pWrite, psQIF)); if (pThis->tVars.disk.pReadDel != NULL) CHKiRet(strm.Serialize(pThis->tVars.disk.pReadDel, psQIF)); strm.Destruct(&psQIF); if (tmpQIFName != (char *)pThis->pszQIFNam) { /* pointer, not string comparison! */ if (rename(tmpQIFName, (char *)pThis->pszQIFNam) != 0) { rs_strerror_r(errno, errStr, sizeof(errStr)); DBGOPRINT((obj_t *)pThis, "FATAL error: renaming temporary .qi file failed: %s\n", errStr); ABORT_FINALIZE(RS_RET_RENAME_TMP_QI_ERROR); } } /* tell the input file object that it must not delete the file on close if the queue * is non-empty - but only if we are not during a simple checkpoint */ if (bIsCheckpoint != QUEUE_CHECKPOINT && pThis->tVars.disk.pReadDel != NULL) { CHKiRet(strm.SetbDeleteOnClose(pThis->tVars.disk.pReadDel, 0)); } /* we have persisted the queue object. So whenever it comes to an empty queue, * we need to delete the QIF. Thus, we indicte that need. */ pThis->bNeedDelQIF = 1; finalize_it: if (tmpQIFName != (char *)pThis->pszQIFNam) /* pointer, not string comparison! */ free(tmpQIFName); if (psQIF != NULL) strm.Destruct(&psQIF); RETiRet; } static rsRetVal qqueueChkPersist(qqueue_t *const pThis, const int nUpdates) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(nUpdates >= 0); if (nUpdates == 0) FINALIZE; /* segmentedDisk checkpoints completed dequeue batches in its store. Enqueue * activity must not turn checkpointInterval=1 into one checkpoint per write. */ if (pThis->qType == QUEUETYPE_SEGMENTED_DISK) FINALIZE; pThis->iUpdsSincePersist += nUpdates; if (pThis->iPersistUpdCnt && pThis->iUpdsSincePersist >= pThis->iPersistUpdCnt) { qqueuePersist(pThis, QUEUE_CHECKPOINT); pThis->iUpdsSincePersist = 0; } finalize_it: RETiRet; } /* persist a queue with all data elements to disk - this is used to handle * bSaveOnShutdown. We utilize the DA worker to do this. This must only * be called after all workers have been shut down and if bSaveOnShutdown * is actually set. Note that this function may potentially run long, * depending on the queue configuration (e.g. store on remote machine). * rgerhards, 2009-05-26 */ static rsRetVal DoSaveOnShutdown(qqueue_t *pThis) { struct timespec tTimeout; rsRetVal iRetLocal; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); /* we reduce the low water mark, otherwise the DA worker would terminate when * it is reached. */ DBGOPRINT((obj_t *)pThis, "bSaveOnShutdown set, restarting DA worker...\n"); qqueueSetShutdownImmediate(pThis, 0); /* would terminate the DA worker! */ pThis->iLowWtrMrk = 0; wtpSetState(pThis->pWtpDA, wtpState_SHUTDOWN); /* shutdown worker (only) when done (was _IMMEDIATE!) */ wtpAdviseMaxWorkers(pThis->pWtpDA, 1, PERMIT_WORKER_START_DURING_SHUTDOWN); /* restart DA worker */ DBGOPRINT((obj_t *)pThis, "waiting for DA worker to terminate...\n"); timeoutComp(&tTimeout, QUEUE_TIMEOUT_ETERNAL); /* and run the primary queue's DA worker to drain the queue */ iRetLocal = wtpShutdownAll(pThis->pWtpDA, wtpState_SHUTDOWN, &tTimeout); DBGOPRINT((obj_t *)pThis, "end queue persistence run, iRet %d, queue size log %d, phys %d\n", iRetLocal, getLogicalQueueSize(pThis), getPhysicalQueueSize(pThis)); if (iRetLocal != RS_RET_OK) { DBGOPRINT((obj_t *)pThis, "unexpected iRet state %d after trying to shut down primary " "queue in disk save mode, continuing, but results are unpredictable\n", iRetLocal); } RETiRet; } /* destructor for the queue object */ BEGINobjDestruct(qqueue) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(qqueue); DBGOPRINT((obj_t *)pThis, "shutdown: begin to destruct queue\n"); if (ourConf->globals.shutdownQueueDoubleSize) { pThis->iHighWtrMrk *= 2; pThis->iMaxQueueSize *= 2; } if (pThis->bQueueStarted) { /* shut down all workers * We do not need to shutdown workers when we are in enqueue-only mode or we are a * direct queue - because in both cases we have none... ;) * with a child! -- rgerhards, 2008-01-28 */ if (pThis->qType != QUEUETYPE_DIRECT && !pThis->bEnqOnly && pThis->pqParent == NULL && pThis->pWtpReg != NULL) qqueueShutdownWorkers(pThis); /* Destroy the now-joined regular pool before inspecting the remaining * size or starting save-on-shutdown. It is no longer needed, and this * keeps the persistence phase's worker ownership explicit. */ if (pThis->qType != QUEUETYPE_DIRECT && pThis->pWtpReg != NULL) { wtpDestruct(&pThis->pWtpReg); } if (pThis->bIsDA && getPhysicalQueueSize(pThis) > 0) { if (pThis->bSaveOnShutdown) { LogMsg(0, RS_RET_TIMED_OUT, LOG_INFO, "%s: queue holds %d messages after shutdown of workers. " "queue.saveonshutdown is set, so data will now be spooled to disk", objGetName((obj_t *)pThis), getPhysicalQueueSize(pThis)); CHKiRet(DoSaveOnShutdown(pThis)); } else { LogMsg(0, RS_RET_TIMED_OUT, LOG_WARNING, "%s: queue holds %d messages after shutdown of workers. " "queue.saveonshutdown is NOT set, so data will be discarded.", objGetName((obj_t *)pThis), getPhysicalQueueSize(pThis)); } } /* finally destruct our (regular) worker thread pool * Note: currently pWtpReg is never NULL, but if we optimize our logic, this may happen, * e.g. when they are not created in enqueue-only mode. We already check the condition * as this may otherwise be very hard to find once we optimize (and have long forgotten * about this condition here ;) * rgerhards, 2008-01-25 */ /* Now check if we actually have a DA queue and, if so, destruct it. * The wtp must be destructed before the child queue. Shutdown has already * joined its workers, so destruction now releases only pool resources. * Please note that this also generates a situation * where it is possible that the DA queue has a parent pointer but the parent has * no WtpDA associated with it - which is perfectly legal thanks to this code here. */ if (pThis->pWtpDA != NULL) { wtpDestruct(&pThis->pWtpDA); } if (pThis->pqDA != NULL) { qqueueDestruct(&pThis->pqDA); } /* persist the queue (we always do that - queuePersits() does cleanup if the queue is empty) * This handler is most important for disk queues, it will finally persist the necessary * on-disk structures. In theory, other queueing modes may implement their other (non-DA) * methods of persisting a queue between runs, but in practice all of this is done via * disk queues and DA mode. Anyhow, it doesn't hurt to know that we could extend it here * if need arises (what I doubt...) -- rgerhards, 2008-01-25 */ CHKiRet_Hdlr(qqueuePersist(pThis, QUEUE_NO_CHECKPOINT)) { DBGOPRINT((obj_t *)pThis, "error %d persisting queue - data lost!\n", iRet); } /* finally, clean up some simple things... */ if (pThis->pqParent == NULL) { /* if we are not a child, we allocated our own mutex, which we now need to destroy */ pthread_mutex_destroy(pThis->mut); free(pThis->mut); } pthread_mutex_destroy(&pThis->mutThrdMgmt); pthread_cond_destroy(&pThis->notFull); pthread_cond_destroy(&pThis->belowFullDlyWtrMrk); pthread_cond_destroy(&pThis->belowLightDlyWtrMrk); DESTROY_ATOMIC_HELPER_MUT(pThis->mutQueueSize); DESTROY_ATOMIC_HELPER_MUT(pThis->mutLogDeq); DESTROY_ATOMIC_HELPER_MUT(pThis->mutShutdownImmediate); /* type-specific destructor */ iRet = pThis->qDestruct(pThis); } free(pThis->pszFilePrefix); free(pThis->pszSpoolDir); if (pThis->useCryprov) { pThis->cryprov.Destruct(&pThis->cryprovData); obj.ReleaseObj(__FILE__, pThis->cryprovNameFull + 2, pThis->cryprovNameFull, (void *)&pThis->cryprov); free(pThis->cryprovName); free(pThis->cryprovNameFull); } /* some queues do not provide stats and thus have no statsobj! */ if (pThis->statsobj != NULL) statsobj.Destruct(&pThis->statsobj); ENDobjDestruct(qqueue) /* set the queue's spool directory. The directory MUST NOT be NULL. * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. */ rsRetVal qqueueSetSpoolDir(qqueue_t *pThis, uchar *pszSpoolDir, int lenSpoolDir) { DEFiRet; free(pThis->pszSpoolDir); CHKmalloc(pThis->pszSpoolDir = ustrdup(pszSpoolDir)); pThis->lenSpoolDir = lenSpoolDir; finalize_it: RETiRet; } /* set the queue's file prefix * The passed-in string is duplicated. So if the caller does not need * it any longer, it must free it. * rgerhards, 2008-01-09 */ rsRetVal qqueueSetFilePrefix(qqueue_t *pThis, uchar *pszPrefix, size_t iLenPrefix) { DEFiRet; free(pThis->pszFilePrefix); pThis->pszFilePrefix = NULL; if (pszPrefix == NULL) /* just unset the prefix! */ ABORT_FINALIZE(RS_RET_OK); if ((pThis->pszFilePrefix = malloc(iLenPrefix + 1)) == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); memcpy(pThis->pszFilePrefix, pszPrefix, iLenPrefix + 1); pThis->lenFilePrefix = iLenPrefix; finalize_it: RETiRet; } /* set the queue's maximum file size * rgerhards, 2008-01-09 */ rsRetVal qqueueSetMaxFileSize(qqueue_t *pThis, size_t iMaxFileSize) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); if (iMaxFileSize < 1024) { ABORT_FINALIZE(RS_RET_VALUE_TOO_LOW); } pThis->iMaxFileSize = iMaxFileSize; finalize_it: RETiRet; } /* enqueue a single data object. * Note that the queue mutex MUST already be locked when this function is called. * rgerhards, 2009-06-16 */ static rsRetVal doEnqSingleObj(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg) { DEFiRet; int err; struct timespec t; STATSCOUNTER_INC(pThis->ctrEnqueued, pThis->mutCtrEnqueued); /* size.enqueued mirrors enqueued: counted on arrival, before discard checks, * so it represents inbound byte volume (rejected slice tracked by ctrFDscrd). */ STATSCOUNTER_ADD(pThis->ctrSizeEnqueued, pThis->mutCtrSizeEnqueued, (uint64_t)pMsg->iLenRawMsg); /* first check if we need to discard this message (which will cause CHKiRet() to exit) */ CHKiRet(qqueueChkDiscardMsg(pThis, pThis->iQueueSize, pMsg)); /* handle flow control * There are two different flow control mechanisms: basic and advanced flow control. * Basic flow control has always been implemented and protects the queue structures * in that it makes sure no more data is enqueued than the queue is configured to * support. Enhanced flow control is being added today. There are some sources which * can easily be stopped, e.g. a file reader. This is the case because it is unlikely * that blocking those sources will have negative effects (after all, the file is * continued to be written). Other sources can somewhat be blocked (e.g. the kernel * log reader or the local log stream reader): in general, nothing is lost if messages * from these sources are not picked up immediately. HOWEVER, they can not block for * an extended period of time, as this either causes message loss or - even worse - some * other bad effects (e.g. unresponsive system in respect to the main system log socket). * Finally, there are some (few) sources which can not be blocked at all. UDP syslog is * a prime example. If a UDP message is not received, it is simply lost. So we can't * do anything against UDP sockets that come in too fast. The core idea of advanced * flow control is that we take into account the different natures of the sources and * select flow control mechanisms that fit these needs. This also means, in the end * result, that non-blockable sources like UDP syslog receive priority in the system. * It's a side effect, but a good one ;) -- rgerhards, 2008-03-14 */ if (unlikely(pThis->takeFlowCtlFromMsg)) { /* recommendation is NOT to use this option */ flowCtlType = pMsg->flowCtlType; } if (flowCtlType == eFLOWCTL_FULL_DELAY) { while (pThis->iQueueSize >= pThis->iFullDlyMrk && !glbl.GetGlobalInputTermState()) { /* We have a problem during shutdown if we block eternally. In that * case, the the input thread cannot be terminated. So we wake up * from time to time to check for termination. * TODO/v6(at earliest): check if we could signal the condition during * shutdown. However, this requires new queue registries and thus is * far to much change for a stable version (and I am still not sure it * is worth the effort, given how seldom this situation occurs and how * few resources the wakeups need). -- rgerhards, 2012-05-03 * In any case, this was the old code (if we do the TODO): * pthread_cond_wait(&pThis->belowFullDlyWtrMrk, pThis->mut); */ DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: FullDelay mark reached for full " "delayable message - blocking, queue size is %d.\n", pThis->iQueueSize); timeoutComp(&t, 1000); err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t); if (err != 0 && err != ETIMEDOUT) { /* Something is really wrong now. Report to debug log and abort the * wait. That keeps us running, even though we may lose messages. */ DBGOPRINT((obj_t *)pThis, "potential program bug: pthread_cond_timedwait()" "/fulldelay returned %d\n", err); break; } DBGPRINTF("wti worker in full delay timed out, checking termination...\n"); } } else if (flowCtlType == eFLOWCTL_LIGHT_DELAY && !glbl.GetGlobalInputTermState()) { if (pThis->iQueueSize >= pThis->iLightDlyMrk) { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: LightDelay mark reached for light " "delayable message - blocking a bit.\n"); timeoutComp(&t, 1000); /* 1000 millisconds = 1 second TODO: make configurable */ err = pthread_cond_timedwait(&pThis->belowLightDlyWtrMrk, pThis->mut, &t); if (err != 0 && err != ETIMEDOUT) { /* Something is really wrong now. Report to debug log */ DBGOPRINT((obj_t *)pThis, "potential program bug: pthread_cond_timedwait()" "/lightdelay returned %d\n", err); } } } /* from our regular flow control settings, we are now ready to enqueue the object. * However, we now need to do a check if the queue permits to add more data. If that * is not the case, basic flow control enters the field, which means we wait for * the queue to become ready or drop the new message. -- rgerhards, 2008-03-14 */ while ((pThis->iMaxQueueSize > 0 && pThis->iQueueSize >= pThis->iMaxQueueSize) || ((pThis->qType == QUEUETYPE_DISK || pThis->bIsDA) && pThis->sizeOnDiskMax != 0 && pThis->tVars.disk.sizeOnDisk > pThis->sizeOnDiskMax) || (pThis->qType == QUEUETYPE_SEGMENTED_DISK && pThis->sizeOnDiskMax != 0 && getQueueDiskBytes(pThis) >= pThis->sizeOnDiskMax)) { STATSCOUNTER_INC(pThis->ctrFull, pThis->mutCtrFull); if (pThis->toEnq == 0 || pThis->bEnqOnly) { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: queue FULL - configured for immediate " "discarding QueueSize=%d MaxQueueSize=%d sizeOnDisk=%lld " "sizeOnDiskMax=%lld\n", pThis->iQueueSize, pThis->iMaxQueueSize, getQueueDiskBytes(pThis), pThis->sizeOnDiskMax); STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } else { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: queue FULL - waiting %dms to drain.\n", pThis->toEnq); /* Multi-submit and single-message enqueue normally advise workers * only after doEnqSingleObj() returns. If this call blocks first, * an already-idle worker would never be awakened to make room. */ qqueueAdviseMaxWorkers(pThis); if (glbl.GetGlobalInputTermState()) { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: queue FULL, discard due to " "FORCE_TERM.\n"); ABORT_FINALIZE(RS_RET_FORCE_TERM); } timeoutComp(&t, pThis->toEnq); const int r = pthread_cond_timedwait(&pThis->notFull, pThis->mut, &t); if (dbgTimeoutToStderr && r != 0) { fprintf(stderr, "%lld: queue timeout(%dms), error %d%s, " "lost message %s\n", (long long)time(NULL), pThis->toEnq, r, (r == ETIMEDOUT) ? "[ETIMEDOUT]" : "", pMsg->pszRawMsg); } if (r == ETIMEDOUT) { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: cond timeout, dropping message!\n"); STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } else if (r != 0) { DBGOPRINT((obj_t *)pThis, "doEnqSingleObject: cond error %d, dropping message!\n", r); STATSCOUNTER_INC(pThis->ctrFDscrd, pThis->mutCtrFDscrd); msgDestruct(&pMsg); ABORT_FINALIZE(RS_RET_QUEUE_FULL); } dbgoprint((obj_t *)pThis, "doEnqSingleObject: wait solved queue full condition, enqueing\n"); } } /* and finally enqueue the message */ CHKiRet(qqueueAdd(pThis, pMsg)); STATSCOUNTER_SETMAX_NOMUT(pThis->ctrMaxqsize, pThis->iQueueSize); /* check if we had a file rollover and need to persist * the .qi file for robustness reasons. * Note: the n=2 write is required for closing the old file and * the n=1 write is required after opening and writing to the new * file. */ if (pThis->tVars.disk.nForcePersist > 0) { DBGOPRINT((obj_t *)pThis, ".qi file write required for robustness reasons (n=%d)\n", pThis->tVars.disk.nForcePersist); pThis->tVars.disk.nForcePersist--; qqueuePersist(pThis, QUEUE_CHECKPOINT); } finalize_it: RETiRet; } /* ------------------------------ multi-enqueue functions ------------------------------ */ /* enqueue multiple user data elements at once. The aim is to provide a faster interface * for object submission. Uses the multi_submit_t helper object. * Please note that this function is not cancel-safe and consequently * sets the calling thread's cancelibility state to PTHREAD_CANCEL_DISABLE * during its execution. If that is not done, race conditions occur if the * thread is canceled (most important use case is input module termination). * rgerhards, 2009-06-16 * Note: there now exists multiple different functions implementing specially * optimized algorithms for different config cases. -- rgerhards, 2010-06-09 */ /* now the function for all modes but direct */ static rsRetVal qqueueMultiEnqObjNonDirect(qqueue_t *pThis, multi_submit_t *pMultiSub) { int iCancelStateSave; int i; rsRetVal localRet; DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pMultiSub != NULL); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); d_pthread_mutex_lock(pThis->mut); for (i = 0; i < pMultiSub->nElem; ++i) { localRet = doEnqSingleObj(pThis, pMultiSub->ppMsgs[i]->flowCtlType, (void *)pMultiSub->ppMsgs[i]); if (localRet != RS_RET_OK && localRet != RS_RET_QUEUE_FULL) ABORT_FINALIZE(localRet); } qqueueChkPersist(pThis, pMultiSub->nElem); finalize_it: /* make sure at least one worker is running. */ qqueueAdviseMaxWorkers(pThis); /* and release the mutex */ d_pthread_mutex_unlock(pThis->mut); pthread_setcancelstate(iCancelStateSave, NULL); DBGOPRINT((obj_t *)pThis, "MultiEnqObj advised worker start\n"); RETiRet; } /* now, the same function, but for direct mode */ static rsRetVal qqueueMultiEnqObjDirect(qqueue_t *pThis, multi_submit_t *pMultiSub) { int i; wti_t *pWti; DEFiRet; pWti = wtiGetDummy(); qqueueSetWtiShutdownImmediate(pThis, pWti); for (i = 0; i < pMultiSub->nElem; ++i) { CHKiRet(qAddDirectWithWti(pThis, (void *)pMultiSub->ppMsgs[i], pWti)); } finalize_it: RETiRet; } /* ------------------------------ END multi-enqueue functions ------------------------------ */ /* enqueue a new user data element * Enqueues the new element and awakes worker thread. */ rsRetVal qqueueEnqMsg(qqueue_t *pThis, flowControl_t flowCtlType, smsg_t *pMsg) { DEFiRet; int iCancelStateSave; ISOBJ_TYPE_assert(pThis, qqueue); const int isNonDirectQ = pThis->qType != QUEUETYPE_DIRECT; if (isNonDirectQ) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); d_pthread_mutex_lock(pThis->mut); } CHKiRet(doEnqSingleObj(pThis, flowCtlType, pMsg)); qqueueChkPersist(pThis, 1); finalize_it: if (isNonDirectQ) { /* make sure at least one worker is running. */ qqueueAdviseMaxWorkers(pThis); /* and release the mutex */ d_pthread_mutex_unlock(pThis->mut); pthread_setcancelstate(iCancelStateSave, NULL); DBGOPRINT((obj_t *)pThis, "EnqueueMsg advised worker start\n"); } RETiRet; } /* are any queue params set at all? 1 - yes, 0 - no * We need to evaluate the param block for this function, which is somewhat * inefficient. HOWEVER, this is only done during config load, so we really * don't care... -- rgerhards, 2013-05-10 */ int queueCnfParamsSet(struct nvlst *lst) { int r; struct cnfparamvals *pvals; pvals = nvlstGetParams(lst, &pblk, NULL); r = cnfparamvalsIsSet(&pblk, pvals); cnfparamvalsDestruct(pvals, &pblk); return r; } static rsRetVal initCryprov(qqueue_t *pThis, struct nvlst *lst) { uchar szDrvrName[1024]; DEFiRet; if (snprintf((char *)szDrvrName, sizeof(szDrvrName), "lmcry_%s", pThis->cryprovName) == sizeof(szDrvrName)) { LogError(0, RS_RET_ERR, "queue: crypto provider " "name is too long: '%s' - encryption disabled", pThis->cryprovName); ABORT_FINALIZE(RS_RET_ERR); } pThis->cryprovNameFull = ustrdup(szDrvrName); pThis->cryprov.ifVersion = cryprovCURR_IF_VERSION; /* The pDrvrName+2 below is a hack to obtain the object name. It * safes us to have yet another variable with the name without "lm" in * front of it. If we change the module load interface, we may re-think * about this hack, but for the time being it is efficient and clean enough. */ if (obj.UseObj(__FILE__, szDrvrName, szDrvrName, (void *)&pThis->cryprov) != RS_RET_OK) { LogError(0, RS_RET_LOAD_ERROR, "queue: could not load " "crypto provider '%s' - encryption disabled", szDrvrName); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } if (pThis->cryprov.Construct(&pThis->cryprovData) != RS_RET_OK) { LogError(0, RS_RET_CRYPROV_ERR, "queue: error constructing " "crypto provider %s dataset - encryption disabled", szDrvrName); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } CHKiRet(pThis->cryprov.SetCnfParam(pThis->cryprovData, lst, CRYPROV_PARAMTYPE_DISK)); dbgprintf("loaded crypto provider %s, data instance at %p\n", szDrvrName, pThis->cryprovData); pThis->useCryprov = 1; finalize_it: RETiRet; } /* check the queue file name is unique. */ static rsRetVal ATTR_NONNULL() checkUniqueDiskFile(qqueue_t *const pThis) { DEFiRet; struct queue_filename *queue_fn_curr = queue_filename_root; struct queue_filename *newetry = NULL; const char *const curr_dirname = (pThis->pszSpoolDir == NULL) ? "" : (char *)pThis->pszSpoolDir; if (pThis->pszFilePrefix == NULL) { FINALIZE; /* no disk queue! */ } while (queue_fn_curr != NULL) { if (!strcmp((const char *)pThis->pszFilePrefix, queue_fn_curr->filename) && !strcmp(curr_dirname, queue_fn_curr->dirname)) { parser_errmsg( "queue directory '%s' and file name prefix '%s' already used. " "This is not possible. Please make it unique.", curr_dirname, pThis->pszFilePrefix); ABORT_FINALIZE(RS_RET_ERR_QUEUE_FN_DUP); } queue_fn_curr = queue_fn_curr->next; } /* name ok, so let's add it to the list */ CHKmalloc(newetry = calloc(1, sizeof(struct queue_filename))); CHKmalloc(newetry->filename = strdup((char *)pThis->pszFilePrefix)); CHKmalloc(newetry->dirname = strdup(curr_dirname)); newetry->next = queue_filename_root; queue_filename_root = newetry; finalize_it: if (iRet != RS_RET_OK) { if (newetry != NULL) { free((void *)newetry->filename); free((void *)newetry->dirname); free((void *)newetry); } } RETiRet; } void qqueueCorrectParams(qqueue_t *pThis) { int goodval; /* a "good value" to use for comparisons (different objects) */ int needWarnHigh = 0, needWarnLow = 0; if (pThis->iMaxQueueSize < 100 && (pThis->qType == QUEUETYPE_LINKEDLIST || pThis->qType == QUEUETYPE_FIXED_ARRAY)) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "Note: queue.size=\"%d\" is very " "low and can lead to unpredictable results. See also " "https://www.rsyslog.com/lower-bound-for-queue-sizes/", pThis->iMaxQueueSize); } /* we need to do a quick check if our water marks are set plausible. If not, * we correct the most important shortcomings. */ goodval = (pThis->iMaxQueueSize / 100) * 60; if (pThis->iHighWtrMrk != -1 && pThis->iHighWtrMrk < goodval) { LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": high water mark " "is set quite low at %d. You should only set it below " "60%% (%d) if you have a good reason for this.", obj.GetName((obj_t *)pThis), pThis->iHighWtrMrk, goodval); } if (pThis->iNumWorkerThreads > 1) { goodval = (pThis->iMaxQueueSize / 100) * 10; if (pThis->iMinMsgsPerWrkr != -1 && pThis->iMinMsgsPerWrkr < goodval) { LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": " "queue.workerThreadMinimumMessage " "is set quite low at %d. You should only set it below " "10%% (%d) if you have a good reason for this.", obj.GetName((obj_t *)pThis), pThis->iMinMsgsPerWrkr, goodval); } } if (pThis->iDiscardMrk > pThis->iMaxQueueSize) { LogError(0, RS_RET_PARAM_ERROR, "error: queue \"%s\": " "queue.discardMark %d is set larger than queue.size", obj.GetName((obj_t *)pThis), pThis->iDiscardMrk); } goodval = (pThis->iMaxQueueSize / 100) * 80; if (pThis->iDiscardMrk != -1 && pThis->iDiscardMrk < goodval) { LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": queue.discardMark " "is set quite low at %d. You should only set it below " "80%% (%d) if you have a good reason for this.", obj.GetName((obj_t *)pThis), pThis->iDiscardMrk, goodval); } if (pThis->pszFilePrefix != NULL) { /* This means we have a potential DA queue */ if (pThis->iFullDlyMrk != -1 && pThis->iFullDlyMrk < pThis->iHighWtrMrk) { LogMsg(0, RS_RET_CONF_WRN_FULLDLY_BELOW_HIGHWTR, LOG_WARNING, "queue \"%s\": queue.fullDelayMark " "is set below high water mark. This will result in DA mode " " NOT being activated for full delayable messages: In many " "cases this is a configuration error, please check if this " "is really what you want", obj.GetName((obj_t *)pThis)); } } /* now come parameter corrections and defaults */ if (pThis->iHighWtrMrk != -1 && (pThis->iHighWtrMrk < 2 || pThis->iHighWtrMrk > pThis->iMaxQueueSize)) { needWarnHigh = 1; } if (pThis->iHighWtrMrk == -1 || needWarnHigh) { pThis->iHighWtrMrk = (pThis->iMaxQueueSize / 100) * 90; if (pThis->iHighWtrMrk == 0) { /* guard against very low max queue sizes! */ pThis->iHighWtrMrk = pThis->iMaxQueueSize; } if (needWarnHigh) { LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": queue.highWaterMark " "is invalid (must be between 2 and queue size). It has been automatically " "adjusted to %d. In any case, we strongly recommend to review the " "queue definition and resolve inconsistencies to guarantee " "the config really matches your intent.", obj.GetName((obj_t *)pThis), pThis->iHighWtrMrk); } } if (pThis->iLowWtrMrk != -1 && (pThis->iLowWtrMrk < 2 || pThis->iLowWtrMrk > pThis->iHighWtrMrk)) { needWarnLow = 1; } if (pThis->iLowWtrMrk == -1 || needWarnLow) { pThis->iLowWtrMrk = (pThis->iHighWtrMrk * 7ll / 10); if (pThis->iLowWtrMrk == 0) { pThis->iLowWtrMrk = 1; } if (needWarnLow) { LogMsg(0, RS_RET_CONF_PARSE_WARNING, LOG_WARNING, "queue \"%s\": queue.lowWaterMark " "is invalid (must be between 2 and highWaterMark). It has been automatically " "adjusted to %d. In any case, we strongly recommend to review the " "queue definition and resolve inconsistencies to guarantee " "the config really matches your intent.", obj.GetName((obj_t *)pThis), pThis->iLowWtrMrk); } } if ((pThis->iMinMsgsPerWrkr < 1 || pThis->iMinMsgsPerWrkr > pThis->iMaxQueueSize)) { pThis->iMinMsgsPerWrkr = pThis->iMaxQueueSize / pThis->iNumWorkerThreads; } if (pThis->iFullDlyMrk == -1 || pThis->iFullDlyMrk > pThis->iMaxQueueSize) { pThis->iFullDlyMrk = (pThis->iMaxQueueSize / 100) * 97; if (pThis->iFullDlyMrk == 0) { pThis->iFullDlyMrk = (pThis->iMaxQueueSize == 1) ? 1 : pThis->iMaxQueueSize - 1; } } if (pThis->iLightDlyMrk == 0) { pThis->iLightDlyMrk = pThis->iMaxQueueSize; } if (pThis->iLightDlyMrk == -1 || pThis->iLightDlyMrk > pThis->iMaxQueueSize) { pThis->iLightDlyMrk = (pThis->iMaxQueueSize / 100) * 70; if (pThis->iLightDlyMrk == 0) { pThis->iLightDlyMrk = (pThis->iMaxQueueSize == 1) ? 1 : pThis->iMaxQueueSize - 1; } } if (pThis->iDiscardMrk < 1 || pThis->iDiscardMrk > pThis->iMaxQueueSize) { pThis->iDiscardMrk = (pThis->iMaxQueueSize / 100) * 98; if (pThis->iDiscardMrk == 0) { /* for very small queues, we disable this by default */ pThis->iDiscardMrk = pThis->iMaxQueueSize; } } if (pThis->iMaxQueueSize > 0 && pThis->iDeqBatchSize > pThis->iMaxQueueSize) { pThis->iDeqBatchSize = pThis->iMaxQueueSize; } } /* apply all params from param block to queue. Must be called before * finalizing. This supports the v6 config system. Defaults were already * set during queue creation. The pvals object is destructed by this * function. */ rsRetVal qqueueApplyCnfParam(qqueue_t *pThis, struct nvlst *lst) { int i; struct cnfparamvals *pvals; int n_params_set = 0; DEFiRet; pvals = nvlstGetParams(lst, &pblk, NULL); if (pvals == NULL) { parser_errmsg("error processing queue config parameters"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("queue param blk:\n"); cnfparamsPrint(&pblk, pvals); } for (i = 0; i < pblk.nParams; ++i) { if (!pvals[i].bUsed) continue; n_params_set++; if (!strcmp(pblk.descr[i].name, "queue.filename")) { CHKmalloc(pThis->pszFilePrefix = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); pThis->lenFilePrefix = es_strlen(pvals[i].val.d.estr); } else if (!strcmp(pblk.descr[i].name, "queue.cry.provider")) { CHKmalloc(pThis->cryprovName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(pblk.descr[i].name, "queue.spooldirectory")) { free(pThis->pszSpoolDir); CHKmalloc(pThis->pszSpoolDir = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); pThis->lenSpoolDir = es_strlen(pvals[i].val.d.estr); CHKiRet(validateQueueSpoolDir(pThis)); if (pThis->lenSpoolDir > 0 && pThis->pszSpoolDir[pThis->lenSpoolDir - 1] == '/') { pThis->pszSpoolDir[pThis->lenSpoolDir - 1] = '\0'; --pThis->lenSpoolDir; parser_errmsg( "queue.spooldirectory must not end with '/', " "corrected to '%s'", pThis->pszSpoolDir); } } else if (!strcmp(pblk.descr[i].name, "queue.size")) { if (pvals[i].val.d.n > 0x7fffffff) { parser_warnmsg( "queue.size higher than maximum (2147483647) - " "corrected to maximum"); pvals[i].val.d.n = 0x7fffffff; } else if (pvals[i].val.d.n > OVERSIZE_QUEUE_WATERMARK) { parser_warnmsg( "queue.size=%d is very large - is this " "really intended? More info at " "https://www.rsyslog.com/avoid-overly-large-in-memory-queues/", (int)pvals[i].val.d.n); } pThis->iMaxQueueSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.dequeuebatchsize")) { pThis->iDeqBatchSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.mindequeuebatchsize")) { pThis->iMinDeqBatchSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.mindequeuebatchsize.timeout")) { pThis->toMinDeqBatchSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.maxdiskspace")) { pThis->sizeOnDiskMax = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.highwatermark")) { pThis->iHighWtrMrk = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.lowwatermark")) { pThis->iLowWtrMrk = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.fulldelaymark")) { pThis->iFullDlyMrk = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.lightdelaymark")) { pThis->iLightDlyMrk = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.discardmark")) { pThis->iDiscardMrk = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.discardseverity")) { pThis->iDiscardSeverity = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.checkpointinterval")) { pThis->iPersistUpdCnt = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.syncqueuefiles")) { pThis->bSyncQueueFiles = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.type")) { pThis->qType = (queueType_t)pvals[i].val.d.n; if (pThis->qType == QUEUETYPE_DIRECT) { /* if we have a direct queue, we mimic this param was not set. * Our prime intent is to make sure we detect when "real" params * are set on a direct queue, and the type setting is obviously * not relevant here. */ n_params_set--; } } else if (!strcmp(pblk.descr[i].name, "queue.diskqueuetype")) { char *mode; CHKmalloc(mode = es_str2cstr(pvals[i].val.d.estr, NULL)); pThis->diskQueueTypeSet = 1; if (!strcasecmp(mode, "auto")) pThis->diskQueueType = QDA_ENGINE_AUTO; else if (!strcasecmp(mode, "disk")) pThis->diskQueueType = QDA_ENGINE_DISK; else if (!strcasecmp(mode, "segmentedDisk")) pThis->diskQueueType = QDA_ENGINE_SEGMENTED_DISK; else { parser_errmsg("queue.diskQueueType: invalid value '%s'; using 'auto'", mode); pThis->diskQueueType = QDA_ENGINE_AUTO; } free(mode); } else if (!strcmp(pblk.descr[i].name, "queue.diskqueueautoupgrade")) { pThis->diskQueueAutoUpgrade = pvals[i].val.d.n; pThis->diskQueueAutoUpgradeSet = 1; } else if (!strcmp(pblk.descr[i].name, "queue.diskqueueidletimeout")) { pThis->diskQueueIdleTimeout = pvals[i].val.d.n; pThis->diskQueueIdleTimeoutSet = 1; if (pThis->diskQueueIdleTimeout < -1) { parser_errmsg("queue.diskQueueIdleTimeout must be -1 or greater; using 60000"); pThis->diskQueueIdleTimeout = 60000; } } else if (!strcmp(pblk.descr[i].name, "queue.workerthreads")) { CHKiRet(qqueueSetiNumWorkerThreads(pThis, pvals[i].val.d.n)); } else if (!strcmp(pblk.descr[i].name, "queue.timeoutshutdown")) { pThis->toQShutdown = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.timeoutactioncompletion")) { pThis->toActShutdown = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.timeoutenqueue")) { pThis->toEnq = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.timeoutworkerthreadshutdown")) { pThis->toWrkShutdown = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.workerthreadminimummessages")) { pThis->iMinMsgsPerWrkr = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.maxfilesize")) { pThis->iMaxFileSize = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.saveonshutdown")) { pThis->bSaveOnShutdown = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.dequeueslowdown")) { pThis->iDeqSlowdown = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.dequeuetimebegin")) { pThis->iDeqtWinFromHr = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.dequeuetimeend")) { pThis->iDeqtWinToHr = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.samplinginterval")) { pThis->iSmpInterval = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.takeflowctlfrommsg")) { pThis->takeFlowCtlFromMsg = pvals[i].val.d.n; } else if (!strcmp(pblk.descr[i].name, "queue.oncorruption")) { char *mode; CHKmalloc(mode = es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcasecmp(mode, "ignore")) { pThis->onCorruption = QUEUE_ON_CORRUPTION_IGNORE; } else if (!strcasecmp(mode, "safe")) { pThis->onCorruption = QUEUE_ON_CORRUPTION_SAFE_MODE; } else if (!strcasecmp(mode, "inMemory")) { pThis->onCorruption = QUEUE_ON_CORRUPTION_IN_MEMORY; } else { LogError(0, RS_RET_CONF_PARAM_INVLD, "queue.oncorruption: invalid value '%s', using 'safe'", mode); pThis->onCorruption = QUEUE_ON_CORRUPTION_SAFE_MODE; } free(mode); } else { DBGPRINTF( "queue: program error, non-handled " "param '%s'\n", pblk.descr[i].name); } } const sbool is_da_memory_queue = (pThis->qType == QUEUETYPE_FIXED_ARRAY || pThis->qType == QUEUETYPE_LINKEDLIST) && pThis->pszFilePrefix != NULL; /* These are deliberately parser_errmsg(), not advisory warnings: * parser_errmsg marks the configuration dirty. Permissive startup keeps * running after the unusable value is ignored, while * abortOnUncleanConfig="on" rejects the same configuration. */ if ((pThis->diskQueueTypeSet || pThis->diskQueueAutoUpgradeSet || pThis->diskQueueIdleTimeoutSet) && !is_da_memory_queue) { parser_errmsg( "queue.diskQueueType, queue.diskQueueAutoUpgrade, and queue.diskQueueIdleTimeout apply only to " "FixedArray or LinkedList disk-assisted queues; ignoring these parameters"); pThis->diskQueueType = QDA_ENGINE_AUTO; pThis->diskQueueAutoUpgrade = 0; pThis->diskQueueIdleTimeout = 60000; } if (is_da_memory_queue && pThis->diskQueueAutoUpgradeSet && pThis->diskQueueType != QDA_ENGINE_AUTO) { parser_errmsg("queue.diskQueueAutoUpgrade applies only when queue.diskQueueType='auto'; ignoring it"); pThis->diskQueueAutoUpgrade = 0; } if (is_da_memory_queue && pThis->diskQueueType == QDA_ENGINE_DISK && pThis->diskQueueIdleTimeoutSet && pThis->diskQueueIdleTimeout != 60000) { parser_errmsg("queue.diskQueueIdleTimeout does not apply to the classic disk engine; using 60000"); pThis->diskQueueIdleTimeout = 60000; } checkUniqueDiskFile(pThis); if (pThis->qType == QUEUETYPE_DIRECT) { if (n_params_set > 0) { LogMsg(0, RS_RET_OK, LOG_WARNING, "warning on queue '%s': " "queue is in direct mode, but parameters have been set. " "These PARAMETERS cannot be applied and WILL BE IGNORED.", obj.GetName((obj_t *)pThis)); } } else if (pThis->qType == QUEUETYPE_DISK) { if (pThis->pszFilePrefix == NULL) { LogError(0, RS_RET_QUEUE_DISK_NO_FN, "error on queue '%s', disk mode selected, but " "no queue file name given; queue type changed to 'linkedList'", obj.GetName((obj_t *)pThis)); pThis->qType = QUEUETYPE_LINKEDLIST; } } else if (pThis->qType == QUEUETYPE_SEGMENTED_DISK) { if (pThis->pszFilePrefix == NULL) { LogError(0, RS_RET_QUEUE_DISK_NO_FN, "error on queue '%s', segmentedDisk mode selected, but " "no queue file name given", obj.GetName((obj_t *)pThis)); ABORT_FINALIZE(RS_RET_QUEUE_DISK_NO_FN); } if (pThis->onCorruption != QUEUE_ON_CORRUPTION_SAFE_MODE) { LogError(0, RS_RET_CONF_PARAM_INVLD, "error on queue '%s': segmentedDisk currently supports only queue.onCorruption=\"safe\"", obj.GetName((obj_t *)pThis)); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } if (pThis->cryprovName != NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "error on queue '%s': queue.cry.provider is not yet supported by segmentedDisk", obj.GetName((obj_t *)pThis)); ABORT_FINALIZE(RS_RET_CONF_PARAM_INVLD); } } if (pThis->pszFilePrefix == NULL && pThis->cryprovName != NULL) { LogError(0, RS_RET_QUEUE_CRY_DISK_ONLY, "error on queue '%s', crypto provider can " "only be set for disk or disk assisted queue - ignored", obj.GetName((obj_t *)pThis)); free(pThis->cryprovName); pThis->cryprovName = NULL; } if (pThis->cryprovName != NULL) { CHKiRet(initCryprov(pThis, lst)); } cnfparamvalsDestruct(pvals, &pblk); finalize_it: RETiRet; } /* return 1 if the content of two qqueue_t structs equal */ int queuesEqual(qqueue_t *pOld, qqueue_t *pNew) { const qda_lifecycle_config_t old_da = { .engine = pOld->diskQueueType, .auto_upgrade = pOld->diskQueueAutoUpgrade, .idle_timeout = pOld->diskQueueIdleTimeout, }; const qda_lifecycle_config_t new_da = { .engine = pNew->diskQueueType, .auto_upgrade = pNew->diskQueueAutoUpgrade, .idle_timeout = pNew->diskQueueIdleTimeout, }; return (NUM_EQUALS(qType) && NUM_EQUALS(iMaxQueueSize) && NUM_EQUALS(iDeqBatchSize) && NUM_EQUALS(iMinDeqBatchSize) && NUM_EQUALS(toMinDeqBatchSize) && NUM_EQUALS(sizeOnDiskMax) && NUM_EQUALS(iHighWtrMrk) && NUM_EQUALS(iLowWtrMrk) && NUM_EQUALS(iFullDlyMrk) && NUM_EQUALS(iLightDlyMrk) && NUM_EQUALS(iDiscardMrk) && NUM_EQUALS(iDiscardSeverity) && NUM_EQUALS(iPersistUpdCnt) && NUM_EQUALS(bSyncQueueFiles) && NUM_EQUALS(iNumWorkerThreads) && NUM_EQUALS(toQShutdown) && NUM_EQUALS(toActShutdown) && NUM_EQUALS(toEnq) && NUM_EQUALS(toWrkShutdown) && NUM_EQUALS(iMinMsgsPerWrkr) && NUM_EQUALS(iMaxFileSize) && NUM_EQUALS(bSaveOnShutdown) && NUM_EQUALS(iDeqSlowdown) && NUM_EQUALS(iDeqtWinFromHr) && NUM_EQUALS(iDeqtWinToHr) && NUM_EQUALS(iSmpInterval) && NUM_EQUALS(takeFlowCtlFromMsg) && qdaLifecycleConfigEqual(&old_da, &new_da) && USTR_EQUALS(pszFilePrefix) && USTR_EQUALS(cryprovName)); } /* some simple object access methods * Note: the semicolons behind the macros are actually empty declarations. This is * a work-around for clang-format's missing understanding of generative macros. * Some compilers may flag this empty declarations by a warning. If so, we need * to disable this warning. Alternatively, we could exclude this code from being * reformatted by clang-format; */ DEFpropSetMeth(qqueue, bSyncQueueFiles, int); DEFpropSetMeth(qqueue, iPersistUpdCnt, int); DEFpropSetMeth(qqueue, iDeqtWinFromHr, int); DEFpropSetMeth(qqueue, iDeqtWinToHr, int); DEFpropSetMeth(qqueue, toQShutdown, long); DEFpropSetMeth(qqueue, toActShutdown, long); DEFpropSetMeth(qqueue, toWrkShutdown, long); DEFpropSetMeth(qqueue, toEnq, long); DEFpropSetMeth(qqueue, iHighWtrMrk, int); DEFpropSetMeth(qqueue, iLowWtrMrk, int); DEFpropSetMeth(qqueue, iDiscardMrk, int); DEFpropSetMeth(qqueue, iDiscardSeverity, int); DEFpropSetMeth(qqueue, iLightDlyMrk, int); DEFpropSetMeth(qqueue, iMinMsgsPerWrkr, int); DEFpropSetMeth(qqueue, bSaveOnShutdown, int); DEFpropSetMeth(qqueue, pAction, action_t *); DEFpropSetMeth(qqueue, iDeqSlowdown, int); DEFpropSetMeth(qqueue, iDeqBatchSize, int); DEFpropSetMeth(qqueue, iMinDeqBatchSize, int); DEFpropSetMeth(qqueue, sizeOnDiskMax, int64); DEFpropSetMeth(qqueue, iSmpInterval, int); rsRetVal qqueueSetiNumWorkerThreads(qqueue_t *pThis, int pVal) { if (pVal <= 0) { LogError(0, RS_RET_CONF_PARAM_INVLD, "queue.workerthreads must be greater than 0, but is %d", pVal); return RS_RET_CONF_PARAM_INVLD; } pThis->iNumWorkerThreads = pVal; return RS_RET_OK; } /* This function can be used as a generic way to set properties. Only the subset * of properties required to read persisted property bags is supported. This * functions shall only be called by the property bag reader, thus it is static. * rgerhards, 2008-01-11 */ #define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, (uchar *)name, sizeof(name) - 1) static rsRetVal qqueueSetProperty(qqueue_t *pThis, var_t *pProp) { DEFiRet; ISOBJ_TYPE_assert(pThis, qqueue); assert(pProp != NULL); if (isProp("iQueueSize")) { pThis->iQueueSize = pProp->val.num; #ifdef ENABLE_IMDIAG iOverallQueueSize += pThis->iQueueSize; #endif } else if (isProp("tVars.disk.sizeOnDisk")) { pThis->tVars.disk.sizeOnDisk = pProp->val.num; } else if (isProp("qType")) { if (pThis->qType != pProp->val.num) ABORT_FINALIZE(RS_RET_QTYPE_MISMATCH); } finalize_it: RETiRet; } #undef isProp /* dummy */ static rsRetVal qqueueQueryInterface(interface_t __attribute__((unused)) * i) { return RS_RET_NOT_IMPLEMENTED; } /* Initialize the stream class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-01-09 */ BEGINObjClassInit(qqueue, 1, OBJ_IS_CORE_MODULE) /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); /* now set our own handlers */ OBJSetMethodHandler(objMethod_SETPROPERTY, qqueueSetProperty); ENDObjClassInit(qqueue) rsyslog-8.2608.0/runtime/PaxHeaders/yamlconf.c0000644000000000000000000000013115216464436016210 xustar0030 mtime=1782212894.043266459 30 atime=1787067618.084438646 29 ctime=1787067794.44972608 rsyslog-8.2608.0/runtime/yamlconf.c0000664000175000017500000024656615216464436015700 0ustar00rgerrger/** @file yamlconf.c * @brief YAML configuration file loader for rsyslog. * * Parses a .yaml/.yml rsyslog config file and drives the same processing * pipeline that the RainerScript lex/bison parser uses: * - builds struct cnfobj + struct nvlst for each declarative block * - calls cnfDoObj() to let rsconf.c dispatch to the right processor * - feeds ruleset script: strings back into the existing parser via * cnfAddConfigBuffer() so RainerScript logic is fully supported * * The YAML schema mirrors the RainerScript object model: * * global: { key: value, ... } * modules: [ { load: name, param: val, ... }, ... ] * inputs: [ { type: name, param: val, ... }, ... ] * templates: [ { name: n, type: t, string: s, ... }, ... ] * rulesets: [ { name: n, script: |rainerscript..., ... }, ... ] * or [ { name: n, statements: [{if:...,action:...}, ...] }, ... ] * mainqueue: { type: linkedlist, size: 100000, ... } * include: [ { path: glob, optional: on }, ... ] * parser: [ { name: n, type: t, ... }, ... ] * lookup_table: [ { name: n, file: f, ... }, ... ] * dyn_stats: [ { name: n, ... }, ... ] * timezone: [ { id: z, offset: o }, ... ] * ratelimit: [ { name: n, interval: i, burst: b }, ... ] * * Parameter names within each block are identical to their RainerScript * counterparts; all type conversion and validation happens downstream in * nvlstGetParams() as usual. * * Concurrency & Locking: this code runs only during config load, which is * single-threaded. No synchronisation primitives are needed. * * Copyright 2025 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #ifdef HAVE_LIBYAML #include #include #include #include #include #include #include #include "rsyslog.h" #include "errmsg.h" #include "yamlconf.h" #include "grammar/rainerscript.h" #include "grammar/parserif.h" /* Maximum nesting depth tracked during YAML node skipping. * rsyslog config objects are inherently shallow (2-3 levels); 16 guards * against malformed or adversarial YAML without needing a full DFS. */ /** @brief Maximum YAML nesting depth allowed when skipping unknown nodes. */ #define YAMLCONF_MAX_DEPTH 16 /* -------------------------------------------------------------------------- * Forward declarations * -------------------------------------------------------------------------- */ static rsRetVal process_top_level(yaml_parser_t *parser, const char *key, const char *fname); static rsRetVal parse_singleton_obj(yaml_parser_t *parser, enum cnfobjType objType, const char *fname); static rsRetVal parse_obj_sequence(yaml_parser_t *parser, enum cnfobjType objType, const char *fname); static rsRetVal parse_template_sequence(yaml_parser_t *parser, const char *fname); static rsRetVal parse_elements_sequence(yaml_parser_t *parser, struct objlst **out, const char *fname); static rsRetVal parse_ruleset_sequence(yaml_parser_t *parser, const char *fname); static rsRetVal parse_actions_sequence(yaml_parser_t *parser, struct cnfstmt **head_out, const char *fname); static rsRetVal parse_include_sequence(yaml_parser_t *parser, const char *fname); static rsRetVal build_nvlst_from_mapping(yaml_parser_t *parser, struct nvlst **out, const char *fname); static rsRetVal build_array_from_sequence(yaml_parser_t *parser, struct cnfarray **out, const char *fname); static rsRetVal yaml_value_to_nvlst_node( yaml_parser_t *parser, const char *fname, yaml_event_t *ev, const char *key, struct nvlst **out); static rsRetVal build_stmts_rs(yaml_parser_t *parser, es_str_t **s, const char *fname); static rsRetVal expect_event( yaml_parser_t *parser, yaml_event_t *ev, yaml_event_type_t expected, const char *ctx, const char *fname); static void skip_node(yaml_parser_t *parser); typedef struct yamlIncludeFrame_s { char *path; struct yamlIncludeFrame_s *prev; } yamlIncludeFrame_t; static yamlIncludeFrame_t *yamlIncludeStack = NULL; static char *yamlconf_canonical_path(const char *fname) { char *resolved = realpath(fname, NULL); if (resolved != NULL) return resolved; return strdup(fname); } /* -------------------------------------------------------------------------- * Helpers * -------------------------------------------------------------------------- */ /* Convert a YAML scalar value (C string) into a heap-allocated es_str_t. * The caller owns the returned pointer. */ static es_str_t *scalar_to_estr(const char *val) { return es_newStrFromCStr(val, strlen(val)); } /* Append a C string to an es_str_t, growing as needed. * Returns 0 on success, -1 on error. */ static int estr_append_cstr(es_str_t **s, const char *buf, size_t len) { if (len > (size_t)INT_MAX) { LogError(0, RS_RET_OUT_OF_MEMORY, "yamlconf: string length %zu exceeds maximum supported size", len); return -1; } return es_addBuf(s, buf, (es_size_t)len); } /* Append a single character to an es_str_t. */ static int estr_append_char(es_str_t **s, char c) { return es_addChar(s, (unsigned char)c); } /* Append a string value enclosed in double-quotes, escaping backslash and * double-quote characters with a preceding backslash. This produces valid * RainerScript string literals. */ static int estr_append_quoted(es_str_t **s, const char *val, size_t len) { if (estr_append_char(s, '"') != 0) return -1; for (size_t i = 0; i < len; i++) { char c = val[i]; if (c == '"' || c == '\\') { if (estr_append_char(s, '\\') != 0) return -1; } if (estr_append_char(s, c) != 0) return -1; } return estr_append_char(s, '"'); } /* Synthesise a complete RainerScript ruleset block: * * ruleset(name="" [key="val" ...]) { * * } * * All entries from 'lst' (the nvlst collected from the YAML mapping) are * serialised as key="value" pairs inside the parentheses. String values are * double-quoted and escaped. Array values use ["v1","v2"] syntax. * * The resulting es_str_t has two trailing NUL bytes appended so it is safe * to pass directly to cnfAddConfigBuffer() / yy_scan_buffer(). * * Returns RS_RET_OK on success, RS_RET_OUT_OF_MEMORY on allocation failure. */ static rsRetVal build_ruleset_rainerscript(struct nvlst *lst, const char *script_str, es_str_t **out) { es_str_t *s = es_newStr(256); DEFiRet; if (s == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (estr_append_cstr(&s, "ruleset(", 8) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); for (struct nvlst *n = lst; n != NULL; n = n->next) { if (n != lst) { if (estr_append_char(&s, ' ') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* key name */ size_t klen = es_strlen(n->name); if (estr_append_cstr(&s, (char *)es_getBufAddr(n->name), klen) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (estr_append_char(&s, '=') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (n->val.datatype == 'S') { /* String value → "escaped" */ size_t vlen = es_strlen(n->val.d.estr); if (estr_append_quoted(&s, (char *)es_getBufAddr(n->val.d.estr), vlen) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (n->val.datatype == 'A') { /* Array value → ["v1","v2",...] */ struct cnfarray *ar = n->val.d.ar; if (estr_append_char(&s, '[') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); for (int i = 0; i < ar->nmemb; i++) { if (i > 0 && estr_append_char(&s, ',') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); size_t elen = es_strlen(ar->arr[i]); if (estr_append_quoted(&s, (char *)es_getBufAddr(ar->arr[i]), elen) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_char(&s, ']') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else { /* Unexpected type; skip with a warning (should not happen for rulesets) */ LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: unexpected nvlst value datatype '%c' in ruleset " "parameter serialisation, skipping", n->val.datatype); if (estr_append_cstr(&s, "\"\"", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } /* Close parameter list, open script body */ if (estr_append_cstr(&s, ") {\n", 4) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* Script body */ size_t slen = strlen(script_str); if (estr_append_cstr(&s, script_str, slen) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* Ensure the script ends with a newline before the closing brace */ if (slen == 0 || script_str[slen - 1] != '\n') { if (estr_append_char(&s, '\n') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_cstr(&s, "}\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* Two trailing NUL bytes required by yy_scan_buffer() */ if (estr_append_char(&s, '\0') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (estr_append_char(&s, '\0') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); *out = s; s = NULL; /* caller owns it */ iRet = RS_RET_OK; finalize_it: if (s != NULL) es_deleteStr(s); RETiRet; } /* Emit a parse-error message that includes the YAML source location. */ static void yaml_errmsg(yaml_parser_t *parser, const char *fname, const char *extra) { if (parser->problem != NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: %s (line %lu col %lu)%s%s", fname, parser->problem, (unsigned long)parser->problem_mark.line + 1, (unsigned long)parser->problem_mark.column + 1, extra ? " " : "", extra ? extra : ""); } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: parse error%s%s", fname, extra ? " " : "", extra ? extra : ""); } } /* Pull the next event from the parser; on error log and return RS_RET_CONF_PARSE_ERROR. */ static rsRetVal next_event(yaml_parser_t *parser, yaml_event_t *ev, const char *fname) { DEFiRet; if (!yaml_parser_parse(parser, ev)) { yaml_errmsg(parser, fname, NULL); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } finalize_it: RETiRet; } /* Pull the next event and assert it has the expected type. */ static rsRetVal expect_event( yaml_parser_t *parser, yaml_event_t *ev, yaml_event_type_t expected, const char *ctx, const char *fname) { DEFiRet; CHKiRet(next_event(parser, ev, fname)); if (ev->type != expected) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected event %d got %d in %s", fname, (int)expected, (int)ev->type, ctx); yaml_event_delete(ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } finalize_it: RETiRet; } /* Skip over the current node (scalar, sequence, or mapping) and all its * children. Assumes the opening event for this node has already been consumed * (i.e. the caller has just read MAPPING_START or SEQUENCE_START; for a * scalar the caller passes the scalar event and we do nothing). */ static void skip_node(yaml_parser_t *parser) { yaml_event_t ev; int depth = 1; while (depth > 0) { if (!yaml_parser_parse(parser, &ev)) break; PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wswitch_enum switch (ev.type) { case YAML_MAPPING_START_EVENT: case YAML_SEQUENCE_START_EVENT: depth++; if (depth > YAMLCONF_MAX_DEPTH) { yaml_event_delete(&ev); LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: YAML nesting exceeds maximum depth %d; " "skipping remainder", YAMLCONF_MAX_DEPTH); return; } break; case YAML_MAPPING_END_EVENT: case YAML_SEQUENCE_END_EVENT: depth--; break; default: break; } PRAGMA_DIAGNOSTIC_POP yaml_event_delete(&ev); } } /* -------------------------------------------------------------------------- * nvlst / cnfarray builders * -------------------------------------------------------------------------- */ /* Build a struct cnfarray* from the remaining items of a YAML sequence. * The SEQUENCE_START event must already have been consumed by the caller. * Consumes up to and including the matching SEQUENCE_END event. */ static rsRetVal build_array_from_sequence(yaml_parser_t *parser, struct cnfarray **out, const char *fname) { yaml_event_t ev; struct cnfarray *arr = NULL; es_str_t *estr; DEFiRet; *out = NULL; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: array elements must be scalars", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } estr = scalar_to_estr((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (estr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (arr == NULL) arr = cnfarrayNew(estr); else arr = cnfarrayAdd(arr, estr); if (arr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } *out = arr; finalize_it: if (iRet != RS_RET_OK && arr != NULL) { cnfarrayContentDestruct(arr); free(arr); } RETiRet; } /** * @brief Converts one YAML value event into a named nvlst node. * * The event @p ev must already have been pulled from the parser by the * caller (the value event following a key scalar). The event is always * consumed before returning, regardless of success or failure. * * Callers that need to handle YAML_MAPPING_START_EVENT specially (e.g. to * skip nested mappings with a warning) should check ev->type before calling * and only invoke this function for SCALAR and SEQUENCE_START events. * * @param parser libyaml parser; read-from only when ev is SEQUENCE_START. * @param fname Config file name used in diagnostic messages. * @param ev Pre-read value event; always consumed. * @param key Parameter key (C string); copied into the node's name field. * @param out Set to the new nvlst node on success; NULL on any error. * @return RS_RET_OK, RS_RET_OUT_OF_MEMORY, or RS_RET_CONF_PARSE_ERROR. */ static rsRetVal yaml_value_to_nvlst_node( yaml_parser_t *parser, const char *fname, yaml_event_t *ev, const char *key, struct nvlst **out) { es_str_t *keyestr = NULL; struct nvlst *node = NULL; DEFiRet; *out = NULL; keyestr = scalar_to_estr(key); if (keyestr == NULL) { yaml_event_delete(ev); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (ev->type == YAML_SCALAR_EVENT) { es_str_t *val = scalar_to_estr((char *)ev->data.scalar.value); yaml_event_delete(ev); if (val == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); node = nvlstNewStr(val); if (node == NULL) { es_deleteStr(val); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } else if (ev->type == YAML_SEQUENCE_START_EVENT) { struct cnfarray *arr = NULL; yaml_event_delete(ev); CHKiRet(build_array_from_sequence(parser, &arr, fname)); node = nvlstNewArray(arr); if (node == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else { yaml_event_delete(ev); LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: unsupported value type for parameter '%s'", fname, key); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } nvlstSetName(node, keyestr); keyestr = NULL; /* owned by node */ *out = node; node = NULL; finalize_it: es_deleteStr(keyestr); if (node != NULL) nvlstDestruct(node); RETiRet; } /* Build a struct nvlst* from a YAML mapping. * The MAPPING_START event must already have been consumed by the caller. * Consumes up to and including the matching MAPPING_END event. * * Each key/value pair becomes one nvlst node: * scalar value → nvlstNewStr(estr) * sequence → nvlstNewArray(cnfarray) * nested mapping → logged as unsupported and skipped (rsyslog params are flat) */ static rsRetVal build_nvlst_from_mapping(yaml_parser_t *parser, struct nvlst **out, const char *fname) { yaml_event_t ev; struct nvlst *lst = NULL; struct nvlst *node; char *key = NULL; DEFiRet; *out = NULL; while (1) { /* Expect: key scalar or mapping end */ CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected scalar key in mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(key); key = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (key == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* Now read the value */ CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_START_EVENT) { /* Nested mappings are not part of the rsyslog parameter model. * Skip and warn so the user knows the key was ignored. */ yaml_event_delete(&ev); LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: nested mapping for key '%s' is not supported – ignoring", fname, key); skip_node(parser); continue; } CHKiRet(yaml_value_to_nvlst_node(parser, fname, &ev, key, &node)); /* Prepend; cnfDoObj() does not depend on order */ node->next = lst; lst = node; } *out = lst; finalize_it: free(key); if (iRet != RS_RET_OK && lst != NULL) { nvlstDestruct(lst); } RETiRet; } /* -------------------------------------------------------------------------- * Object section parsers * -------------------------------------------------------------------------- */ /* Parse a singleton mapping section (e.g. global:, mainqueue:) and emit one * cnfobj of the given type. * The MAPPING_START event for the section body must already be consumed. */ static rsRetVal parse_singleton_obj(yaml_parser_t *parser, enum cnfobjType objType, const char *fname) { struct nvlst *lst = NULL; struct cnfobj *obj = NULL; DEFiRet; CHKiRet(build_nvlst_from_mapping(parser, &lst, fname)); obj = cnfobjNew(objType, lst); if (obj == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); lst = NULL; /* owned by obj now */ cnfDoObj(obj); finalize_it: if (lst != NULL) nvlstDestruct(lst); RETiRet; } /* Parse a sequence of mapping items, each becoming one cnfobj. * The SEQUENCE_START event for the list must already be consumed. * * Used for: modules, inputs, templates, parser, lookup_table, dyn_stats, * ratelimit, timezone. */ static rsRetVal parse_obj_sequence(yaml_parser_t *parser, enum cnfobjType objType, const char *fname) { yaml_event_t ev; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: sequence item must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); struct nvlst *lst = NULL; CHKiRet(build_nvlst_from_mapping(parser, &lst, fname)); struct cnfobj *obj = cnfobjNew(objType, lst); if (obj == NULL) { nvlstDestruct(lst); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } cnfDoObj(obj); } finalize_it: RETiRet; } /* Parse the elements: sequence of a list template. * * Each item is a mapping with exactly one key, "property" or "constant", * whose value is a mapping of parameters: * * elements: * - property: * name: msg * - constant: * value: "\n" * * Builds a struct objlst of CNFOBJ_PROPERTY / CNFOBJ_CONSTANT nodes that * mirrors what the bison grammar constructs for: * template(name="t" type="list") { property(name="msg") constant(value="\n") } * * The SEQUENCE_START event must already have been consumed by the caller. * Ownership of the returned objlst passes to the caller. */ static rsRetVal parse_elements_sequence(yaml_parser_t *parser, struct objlst **out, const char *fname) { yaml_event_t ev; struct objlst *subobjs = NULL; char *elemtype = NULL; DEFiRet; *out = NULL; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: each elements: item must be a mapping with a " "'property' or 'constant' key", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); /* Read the element type key: "property" or "constant" */ CHKiRet(next_event(parser, &ev, fname)); if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: elements: item key must be 'property' or 'constant'", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(elemtype); elemtype = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (elemtype == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); enum cnfobjType etype; if (!strcmp(elemtype, "property")) { etype = CNFOBJ_PROPERTY; } else if (!strcmp(elemtype, "constant")) { etype = CNFOBJ_CONSTANT; } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: elements: item key must be 'property' or 'constant', got '%s'", fname, elemtype); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } /* Read MAPPING_START for the element parameters */ CHKiRet(expect_event(parser, &ev, YAML_MAPPING_START_EVENT, "element params mapping", fname)); yaml_event_delete(&ev); struct nvlst *elst = NULL; CHKiRet(build_nvlst_from_mapping(parser, &elst, fname)); struct cnfobj *eobj = cnfobjNew(etype, elst); elst = NULL; /* owned by eobj */ if (eobj == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); subobjs = objlstAdd(subobjs, eobj); /* Consume the MAPPING_END of the outer element item mapping */ CHKiRet(expect_event(parser, &ev, YAML_MAPPING_END_EVENT, "element item end", fname)); yaml_event_delete(&ev); } *out = subobjs; subobjs = NULL; finalize_it: free(elemtype); if (subobjs != NULL) objlstDestruct(subobjs); RETiRet; } /* Parse the templates: sequence. * * Simple templates (type=string/subtree/plugin) use the flat nvlst path * identical to other object sequences. * * List templates (type=list) need sub-objects: the "elements:" key takes * a sequence of property:/constant: items that are built as * CNFOBJ_PROPERTY/CNFOBJ_CONSTANT nodes and attached to the template * cnfobj->subobjs — exactly what the bison grammar does for: * template(name="t" type="list") { property(...) constant(...) } * * YAML schema summary: * # string template * - name: t1 * type: string * string: "%msg%\n" * * # subtree template * - name: t2 * type: subtree * subtree: "$!all-json" * * # list template * - name: t3 * type: list * elements: * - property: * name: msg * - constant: * value: "\n" * * SEQUENCE_START must already be consumed by the caller. */ static rsRetVal parse_template_sequence(yaml_parser_t *parser, const char *fname) { yaml_event_t ev; struct nvlst *lst = NULL; struct objlst *subobjs = NULL; char *kname = NULL; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: templates sequence item must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); /* Reset per-template state */ lst = NULL; subobjs = NULL; /* Walk the template mapping manually to intercept "elements:" */ while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected scalar key in template mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(kname); kname = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (kname == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); CHKiRet(next_event(parser, &ev, fname)); if (!strcmp(kname, "elements")) { /* elements: [...] – sub-objects for list template */ if (ev.type != YAML_SEQUENCE_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'elements' value must be a sequence of " "property/constant items", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); if (subobjs != NULL) objlstDestruct(subobjs); subobjs = NULL; CHKiRet(parse_elements_sequence(parser, &subobjs, fname)); } else { /* Regular template param: add to nvlst */ struct nvlst *node = NULL; CHKiRet(yaml_value_to_nvlst_node(parser, fname, &ev, kname, &node)); node->next = lst; lst = node; } } /* end per-template key loop */ struct cnfobj *obj = cnfobjNew(CNFOBJ_TPL, lst); lst = NULL; /* owned by obj */ if (obj == NULL) { if (subobjs != NULL) objlstDestruct(subobjs); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } obj->subobjs = subobjs; /* NULL for non-list templates */ subobjs = NULL; cnfDoObj(obj); } /* end template sequence loop */ finalize_it: free(kname); nvlstDestruct(lst); if (subobjs != NULL) objlstDestruct(subobjs); RETiRet; } /* Parse the actions: sequence. * * Each item is a YAML mapping that mirrors an action() object: the "type" * key names the output module and all other keys are passed as parameters. * We build an nvlst for each item and call cnfstmtNewAct() directly, then * chain the resulting cnfstmt nodes via ->next. * * The SEQUENCE_START event must already have been consumed by the caller. * On success *head_out points to the first node of the chain (possibly NULL * if the sequence was empty). Ownership passes to the caller. */ static rsRetVal parse_actions_sequence(yaml_parser_t *parser, struct cnfstmt **head_out, const char *fname) { yaml_event_t ev; struct cnfstmt *head = NULL, *tail = NULL; DEFiRet; *head_out = NULL; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: actions: item must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); struct nvlst *alst = NULL; CHKiRet(build_nvlst_from_mapping(parser, &alst, fname)); /* cnfstmtNewAct() takes ownership of alst and frees it internally. */ struct cnfstmt *act = cnfstmtNewAct(alst); if (act == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (head == NULL) { head = tail = act; } else { tail->next = act; tail = act; } } *head_out = head; head = NULL; finalize_it: if (head != NULL) cnfstmtDestructLst(head); RETiRet; } /* -------------------------------------------------------------------------- * YAML-native statements: block * * Converts a YAML statements: sequence into a RainerScript body string that * is then injected via cnfAddConfigBuffer(), following the same proven path * as the raw script: key. * * Supported statement types in a statements: sequence item: * * Unconditional action (same schema as actions: items): * - type: omfile * file: /path * template: outfmt * * Conditional (single-action shorthand): * - if: '$msg contains "msgnum:"' * action: * type: omfile * file: /path * else: # optional * - stop: true * * Conditional (multi-statement then/else): * - if: '$msg contains "msgnum:"' * then: * - type: omfile * file: /path * else: # optional * - stop: true * * Control flow: * - stop: true # or stop: * - continue: true # or continue: * - call: rulesetname * * Variable assignment: * - set: * var: "$.nbr" * expr: 'field($msg, 58, 2)' * - unset: "$.var" * * foreach loop: * - foreach: * var: "$.item" * in: "$!array" * do: * - type: omfile * file: /tmp/out * * Indirect ruleset call: * - call_indirect: "$!rulesetname" * * Reload a lookup table (triggers an asynchronous reload of a previously * loaded lookup table). Unlike action() parameters, reload_lookup_table * takes positional string arguments in RainerScript, so the YAML keys * "table" and "stub_value" are extracted and emitted as quoted literals: * - reload_lookup_table: * table: myLookupTable * stub_value: unknown # optional; returned on reload failure * * -------------------------------------------------------------------------- */ /* Append all entries of 'lst' as key="val" pairs to the RainerScript * string *s. Used to serialise action() parameter lists. * Reuses the same quoting logic as build_ruleset_rainerscript(). * Returns 0 on success, -1 on allocation failure (int, not rsRetVal). */ static int append_nvlst_as_rs_params(es_str_t **s, struct nvlst *lst) { for (struct nvlst *n = lst; n != NULL; n = n->next) { if (n != lst) { if (estr_append_char(s, ' ') != 0) return -1; } size_t klen = es_strlen(n->name); if (estr_append_cstr(s, (char *)es_getBufAddr(n->name), klen) != 0) return -1; if (estr_append_char(s, '=') != 0) return -1; if (n->val.datatype == 'S') { size_t vlen = es_strlen(n->val.d.estr); if (estr_append_quoted(s, (char *)es_getBufAddr(n->val.d.estr), vlen) != 0) return -1; } else if (n->val.datatype == 'A') { struct cnfarray *ar = n->val.d.ar; if (estr_append_char(s, '[') != 0) return -1; for (int i = 0; i < ar->nmemb; i++) { if (i > 0 && estr_append_char(s, ',') != 0) return -1; size_t elen = es_strlen(ar->arr[i]); if (estr_append_quoted(s, (char *)es_getBufAddr(ar->arr[i]), elen) != 0) return -1; } if (estr_append_char(s, ']') != 0) return -1; } else { if (estr_append_cstr(s, "\"\"", 2) != 0) return -1; } } return 0; } /* Parse the sub-mapping for a foreach: statement. * MAPPING_START already consumed. Fills *p_var, *p_in, *p_body (all * owned by caller; freed via the finalize_it: of build_one_stmt_rs). */ static rsRetVal parse_foreach_mapping( yaml_parser_t *parser, const char *fname, char **p_var, char **p_in, es_str_t **p_body) { yaml_event_t ev; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } char *fk = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (fk == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (!strcmp(fk, "var") || !strcmp(fk, "in")) { yaml_event_t fv; rsRetVal fret = next_event(parser, &fv, fname); if (fret != RS_RET_OK) { free(fk); ABORT_FINALIZE(fret); } if (fv.type == YAML_SCALAR_EVENT) { char **dst = !strcmp(fk, "var") ? p_var : p_in; free(*dst); *dst = strdup((char *)fv.data.scalar.value); if (*dst == NULL) { yaml_event_delete(&fv); free(fk); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } yaml_event_delete(&fv); } else if (!strcmp(fk, "do")) { yaml_event_t sev; rsRetVal sret = next_event(parser, &sev, fname); if (sret != RS_RET_OK) { free(fk); ABORT_FINALIZE(sret); } if (sev.type != YAML_SEQUENCE_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: foreach 'do' must be a sequence of statements", fname); yaml_event_delete(&sev); free(fk); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&sev); es_deleteStr(*p_body); *p_body = es_newStr(64); if (*p_body == NULL) { free(fk); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } rsRetVal bret = build_stmts_rs(parser, p_body, fname); if (bret != RS_RET_OK) { free(fk); ABORT_FINALIZE(bret); } } else { /* skip unknown foreach sub-key */ yaml_event_t fv; rsRetVal fret = next_event(parser, &fv, fname); if (fret == RS_RET_OK) yaml_event_delete(&fv); } free(fk); } finalize_it: RETiRet; } /* Parse the sub-mapping for a set: statement. * MAPPING_START already consumed. Fills *p_var and *p_expr. */ static rsRetVal parse_set_subkeys(yaml_parser_t *parser, const char *fname, char **p_var, char **p_expr) { yaml_event_t ev; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } char *sk = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (sk == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); yaml_event_t sv; rsRetVal sret = next_event(parser, &sv, fname); if (sret != RS_RET_OK) { free(sk); ABORT_FINALIZE(sret); } if (sv.type == YAML_SCALAR_EVENT) { char **dst = !strcmp(sk, "var") ? p_var : (!strcmp(sk, "expr") ? p_expr : NULL); if (dst != NULL) { free(*dst); *dst = strdup((char *)sv.data.scalar.value); if (*dst == NULL) { yaml_event_delete(&sv); free(sk); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } } yaml_event_delete(&sv); free(sk); } finalize_it: RETiRet; } /* Build RainerScript for one statement mapping. MAPPING_START already consumed. * Appends to *s. * * Design note: this function intentionally uses a two-phase collect-then-emit * pattern rather than being split further. The statement type cannot be * determined until all keys in the YAML mapping have been read (e.g. an * item with only 'type:' is a flat action, but one with 'if:' and 'action:' * is an if/action shorthand). Splitting collect from emit would require a * ~15-field context struct with its own cleanup, adding boilerplate without * clarity. The foreach and set sub-mapping parsers are extracted into * parse_foreach_mapping() and parse_set_subkeys() to keep nesting shallow. */ static rsRetVal build_one_stmt_rs(yaml_parser_t *parser, es_str_t **s, const char *fname) { yaml_event_t ev; DEFiRet; /* Collect all top-level keys from this mapping so we can determine the * statement type. Some values (then:/else:/action:/set:) are nested * sequences or mappings that we handle inline. */ char *if_expr = NULL; /* value of if: */ char *call_name = NULL; /* value of call: */ char *call_indirect_expr = NULL; /* value of call_indirect: */ char *set_var = NULL; /* value of set.var */ char *set_expr = NULL; /* value of set.expr */ char *unset_var = NULL; /* value of unset: */ char *foreach_var = NULL; /* value of foreach.var */ char *foreach_in = NULL; /* value of foreach.in */ es_str_t *foreach_body = NULL; /* compiled body of foreach.do */ es_str_t *then_rs = NULL; es_str_t *else_rs = NULL; es_str_t *action_rs = NULL; /* action: nested mapping → serialised RS */ struct nvlst *act_lst = NULL; /* for flat action (type: key at top level) */ int has_stop = 0; int has_continue = 0; int has_if = 0; int has_call = 0; int has_call_indirect = 0; int has_set = 0; int has_unset = 0; int has_foreach = 0; int has_type = 0; /* flat action form */ /* reload_lookup_table: uses positional args: ("tableName"[, "stubValue"]) */ char *rlt_table = NULL; char *rlt_stub = NULL; int has_rlt = 0; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected scalar key in statements item", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } char *kname = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (kname == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (!strcmp(kname, "if")) { /* value: scalar expression string */ yaml_event_t vev; CHKiRet_Hdlr(next_event(parser, &vev, fname)) { free(kname); FINALIZE; } if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'if' value must be a scalar expression", fname); yaml_event_delete(&vev); free(kname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(if_expr); if_expr = strdup((char *)vev.data.scalar.value); yaml_event_delete(&vev); has_if = 1; free(kname); if (if_expr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "then") || !strcmp(kname, "else")) { /* value: sequence of statement items */ int is_else = (kname[0] == 'e'); free(kname); yaml_event_t sev; CHKiRet(next_event(parser, &sev, fname)); if (sev.type != YAML_SEQUENCE_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'then'/'else' value must be a sequence of statements", fname); yaml_event_delete(&sev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&sev); es_str_t *branch_rs = es_newStr(64); if (branch_rs == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); rsRetVal bret = build_stmts_rs(parser, &branch_rs, fname); if (bret != RS_RET_OK) { es_deleteStr(branch_rs); ABORT_FINALIZE(bret); } if (is_else) { es_deleteStr(else_rs); else_rs = branch_rs; } else { es_deleteStr(then_rs); then_rs = branch_rs; } } else if (!strcmp(kname, "action")) { /* value: mapping with action params (type: + others) */ free(kname); yaml_event_t mev; CHKiRet(next_event(parser, &mev, fname)); if (mev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'action' value must be a mapping of action parameters", fname); yaml_event_delete(&mev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&mev); struct nvlst *alst = NULL; rsRetVal aret = build_nvlst_from_mapping(parser, &alst, fname); if (aret != RS_RET_OK) ABORT_FINALIZE(aret); /* serialise to action(...) string */ es_deleteStr(action_rs); action_rs = es_newStr(128); if (action_rs == NULL) { nvlstDestruct(alst); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_cstr(&action_rs, "action(", 7) != 0 || append_nvlst_as_rs_params(&action_rs, alst) != 0 || estr_append_cstr(&action_rs, ")\n", 2) != 0) { nvlstDestruct(alst); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } nvlstDestruct(alst); } else if (!strcmp(kname, "stop")) { free(kname); /* Only emit stop if value is truthy. Canonical YAML falsy values * (false/no/off/0) must NOT trigger the statement — stop: false is * a valid way to conditionally disable a stop. Non-scalar values * are a config error. */ yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'stop' value must be a scalar (true/false)", fname); yaml_event_delete(&vev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (strcasecmp((char *)vev.data.scalar.value, "false") != 0 && strcasecmp((char *)vev.data.scalar.value, "no") != 0 && strcasecmp((char *)vev.data.scalar.value, "off") != 0 && strcmp((char *)vev.data.scalar.value, "0") != 0) { has_stop = 1; } yaml_event_delete(&vev); } else if (!strcmp(kname, "continue")) { free(kname); yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'continue' value must be a scalar (true/false)", fname); yaml_event_delete(&vev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (strcasecmp((char *)vev.data.scalar.value, "false") != 0 && strcasecmp((char *)vev.data.scalar.value, "no") != 0 && strcasecmp((char *)vev.data.scalar.value, "off") != 0 && strcmp((char *)vev.data.scalar.value, "0") != 0) { has_continue = 1; } yaml_event_delete(&vev); } else if (!strcmp(kname, "call")) { free(kname); yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'call' value must be a ruleset name", fname); yaml_event_delete(&vev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(call_name); call_name = strdup((char *)vev.data.scalar.value); yaml_event_delete(&vev); has_call = 1; if (call_name == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "call_indirect")) { free(kname); yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'call_indirect' value must be a variable expression", fname); yaml_event_delete(&vev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(call_indirect_expr); call_indirect_expr = strdup((char *)vev.data.scalar.value); yaml_event_delete(&vev); has_call_indirect = 1; if (call_indirect_expr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "unset")) { free(kname); yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'unset' value must be a variable name", fname); yaml_event_delete(&vev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(unset_var); unset_var = strdup((char *)vev.data.scalar.value); yaml_event_delete(&vev); has_unset = 1; if (unset_var == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "foreach")) { free(kname); has_foreach = 1; yaml_event_t mev; CHKiRet(next_event(parser, &mev, fname)); if (mev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'foreach' value must be a mapping with var:, in:, and do: keys", fname); yaml_event_delete(&mev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&mev); CHKiRet(parse_foreach_mapping(parser, fname, &foreach_var, &foreach_in, &foreach_body)); } else if (!strcmp(kname, "set")) { free(kname); has_set = 1; yaml_event_t mev; CHKiRet(next_event(parser, &mev, fname)); if (mev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'set' value must be a mapping with var: and expr: keys", fname); yaml_event_delete(&mev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&mev); CHKiRet(parse_set_subkeys(parser, fname, &set_var, &set_expr)); } else if (!strcmp(kname, "reload_lookup_table")) { free(kname); has_rlt = 1; yaml_event_t mev; CHKiRet(next_event(parser, &mev, fname)); if (mev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'reload_lookup_table' value must be a mapping with at " "least a 'table' key", fname); yaml_event_delete(&mev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&mev); /* Extract positional args: table (required) and stub_value (optional). * The RainerScript syntax is reload_lookup_table("name"[, "stub"]) * so we cannot use append_nvlst_as_rs_params(). */ struct nvlst *rlt_nl = NULL; rsRetVal rlt_r = build_nvlst_from_mapping(parser, &rlt_nl, fname); if (rlt_r != RS_RET_OK) ABORT_FINALIZE(rlt_r); for (struct nvlst *n = rlt_nl; n != NULL; n = n->next) { if (n->val.datatype != 'S') continue; /* es_getBufAddr() is NOT null-terminated; use es_str2cstr() */ char *nkey = es_str2cstr(n->name, NULL); char *nval = es_str2cstr(n->val.d.estr, NULL); if (nkey != NULL && nval != NULL) { if (!strcmp(nkey, "table")) { free(rlt_table); rlt_table = strdup(nval); } else if (!strcmp(nkey, "stub_value")) { free(rlt_stub); rlt_stub = strdup(nval); } } free(nkey); free(nval); } nvlstDestruct(rlt_nl); if (rlt_table == NULL && has_rlt) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: reload_lookup_table: 'table' key is required", fname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } } else { /* Unknown key at statement level: treat as action param (flat action form). * Collect into act_lst so we can emit action(...) at the end. */ has_type = has_type || (!strcmp(kname, "type") ? 1 : 0); yaml_event_t vev; rsRetVal next_ret = next_event(parser, &vev, fname); if (next_ret != RS_RET_OK) { free(kname); ABORT_FINALIZE(next_ret); } struct nvlst *node = NULL; rsRetVal nret = yaml_value_to_nvlst_node(parser, fname, &vev, kname, &node); free(kname); kname = NULL; if (nret != RS_RET_OK) ABORT_FINALIZE(nret); node->next = act_lst; act_lst = node; } } /* end mapping loop */ /* ---- Generate RainerScript from collected fields ---- */ if (has_if) { /* if () then { ... } [else { ... }] */ if (estr_append_cstr(s, "if (", 4) != 0 || estr_append_cstr(s, if_expr, strlen(if_expr)) != 0 || estr_append_cstr(s, ") then {\n", 9) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* then branch: either action_rs (from action: key) or then_rs (from then: key) */ if (action_rs != NULL) { if (es_addStr(s, action_rs) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (then_rs != NULL) { if (es_addStr(s, then_rs) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_char(s, '}') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (else_rs != NULL) { if (estr_append_cstr(s, " else {\n", 8) != 0 || es_addStr(s, else_rs) != 0 || estr_append_char(s, '}') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_char(s, '\n') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_stop) { if (estr_append_cstr(s, "stop\n", 5) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_continue) { if (estr_append_cstr(s, "continue\n", 9) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_call) { if (estr_append_cstr(s, "call ", 5) != 0 || estr_append_cstr(s, call_name, strlen(call_name)) != 0 || estr_append_char(s, '\n') != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_call_indirect) { if (estr_append_cstr(s, "call_indirect ", 14) != 0 || estr_append_cstr(s, call_indirect_expr, strlen(call_indirect_expr)) != 0 || estr_append_cstr(s, ";\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_unset) { if (estr_append_cstr(s, "unset ", 6) != 0 || estr_append_cstr(s, unset_var, strlen(unset_var)) != 0 || estr_append_cstr(s, ";\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_foreach) { if (foreach_var == NULL || foreach_in == NULL || foreach_body == NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: foreach: requires 'var', 'in', and 'do' keys", fname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (estr_append_cstr(s, "foreach (", 9) != 0 || estr_append_cstr(s, foreach_var, strlen(foreach_var)) != 0 || estr_append_cstr(s, " in ", 4) != 0 || estr_append_cstr(s, foreach_in, strlen(foreach_in)) != 0 || estr_append_cstr(s, ") do {\n", 7) != 0 || es_addStr(s, foreach_body) != 0 || estr_append_cstr(s, "}\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_set) { if (set_var == NULL || set_expr == NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: set: requires both 'var' and 'expr' keys", fname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (estr_append_cstr(s, "set ", 4) != 0 || estr_append_cstr(s, set_var, strlen(set_var)) != 0 || estr_append_cstr(s, " = ", 3) != 0 || estr_append_cstr(s, set_expr, strlen(set_expr)) != 0 || estr_append_cstr(s, ";\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_type || act_lst != NULL) { /* Flat action: item with type: key directly at statement level */ if (estr_append_cstr(s, "action(", 7) != 0 || append_nvlst_as_rs_params(s, act_lst) != 0 || estr_append_cstr(s, ")\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (has_rlt) { /* Emit: reload_lookup_table("tableName"[, "stubValue"]) */ if (estr_append_cstr(s, "reload_lookup_table(", 20) != 0 || estr_append_quoted(s, rlt_table, strlen(rlt_table)) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (rlt_stub != NULL) { if (estr_append_cstr(s, ", ", 2) != 0 || estr_append_quoted(s, rlt_stub, strlen(rlt_stub)) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (estr_append_cstr(s, ")\n", 2) != 0) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: unrecognised statement item in statements: " "(expected if/type/stop/continue/call/call_indirect/unset/set/foreach/reload_lookup_table)", fname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } finalize_it: free(if_expr); free(call_name); free(call_indirect_expr); free(unset_var); free(foreach_var); free(foreach_in); free(set_var); free(set_expr); es_deleteStr(then_rs); es_deleteStr(else_rs); es_deleteStr(action_rs); es_deleteStr(foreach_body); nvlstDestruct(act_lst); free(rlt_table); free(rlt_stub); RETiRet; } /* Parse a statements: sequence and append the equivalent RainerScript to *s. * SEQUENCE_START must already be consumed by the caller. * * This function is RECURSIVE: build_one_stmt_rs() calls build_stmts_rs() for * then:/else: branch bodies, and parse_foreach_mapping() calls it for do: * bodies. Recursion depth is bounded by YAML nesting depth which is shallow * in practice (foreach inside if is the deepest realistic case). */ static rsRetVal build_stmts_rs(yaml_parser_t *parser, es_str_t **s, const char *fname) { yaml_event_t ev; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: each item in a statements: sequence must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); CHKiRet(build_one_stmt_rs(parser, s, fname)); } finalize_it: RETiRet; } /* Parse the rulesets: sequence. * * Each item is a mapping with at least a "name" key. The special "script" * key causes a complete ruleset(params) { script } RainerScript block to * be synthesised and pushed onto the flex buffer stack via * cnfAddConfigBuffer(); the ongoing yyparse() then processes it naturally. * * The "statements" key is the YAML-native alternative to "script". It takes * a sequence of statement mappings (if/action/stop/continue/call/set) that are * translated to an equivalent RainerScript body and then processed via the * same cnfAddConfigBuffer() path. Only the filter expression in "if:" remains * as a RainerScript expression string; action parameters and control-flow are * expressed as YAML keys. script:/statements: and filter:/actions: are all * mutually exclusive. * * ORDERING NOTE: The synthesised ruleset buffer is pushed AFTER any .conf * files that were included via the include: section (which are also pushed * via cnfAddConfigBuffer / cnfSetLexFile). Because the flex buffer stack is * LIFO, the ruleset script is processed BEFORE those included .conf files. * Consequently, any templates or objects that a ruleset script references * must be defined in the YAML file's own templates:/global:/etc. sections * (processed immediately via cnfDoObj()), not in included .conf fragments. * * Structured filter shortcut (Phase 2): * filter: "" # optional; "*.info" (PRI) or ":prop,op,val" (property) * actions: # mutually exclusive with script: * - type: omfile * file: /var/log/messages * When filter: + actions: are used, cnfstmt nodes are built directly via * cnfstmtNewPRIFILT / cnfstmtNewPROPFILT / cnfstmtNewAct and set on the * cnfobj->script field before calling cnfDoObj() — no text buffer needed. */ static rsRetVal parse_ruleset_sequence(yaml_parser_t *parser, const char *fname) { yaml_event_t ev; /* Hoisted to function scope so finalize_it: can clean up on error */ struct nvlst *lst = NULL; char *script_str = NULL; char *filter_str = NULL; struct cnfstmt *actions = NULL; char *kname = NULL; DEFiRet; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: rulesets sequence item must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); /* Reset per-ruleset state (all NULL at function entry or after prior iteration) */ lst = NULL; script_str = NULL; filter_str = NULL; actions = NULL; /* We parse the mapping manually here so we can intercept special keys */ while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected scalar key in ruleset mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(kname); kname = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (kname == NULL) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKiRet(next_event(parser, &ev, fname)); if (!strcmp(kname, "script")) { /* script: must be a scalar (RainerScript text) */ if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'script' value must be a scalar" " (use a YAML block scalar '|' for multi-line)", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(script_str); script_str = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (script_str == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "statements")) { /* statements: sequence — YAML-native scripting. * Translates to RainerScript and stored in script_str. */ if (ev.type != YAML_SEQUENCE_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'statements' value must be a sequence", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); es_str_t *stmts_estr = es_newStr(256); if (stmts_estr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); rsRetVal sret = build_stmts_rs(parser, &stmts_estr, fname); if (sret != RS_RET_OK) { es_deleteStr(stmts_estr); ABORT_FINALIZE(sret); } free(script_str); script_str = es_str2cstr(stmts_estr, NULL); es_deleteStr(stmts_estr); if (script_str == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "filter")) { /* filter: "" or ":" */ if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'filter' value must be a scalar string", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(filter_str); filter_str = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (filter_str == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } else if (!strcmp(kname, "actions")) { /* actions: [ {type: ..., ...}, ... ] */ if (ev.type != YAML_SEQUENCE_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: 'actions' value must be a sequence", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); if (actions) { cnfstmtDestructLst(actions); actions = NULL; } CHKiRet(parse_actions_sequence(parser, &actions, fname)); } else { /* All other keys go into the header nvlst */ struct nvlst *node = NULL; CHKiRet(yaml_value_to_nvlst_node(parser, fname, &ev, kname, &node)); node->next = lst; lst = node; } } /* end per-ruleset key loop */ /* Sanity: script:/statements: and actions: are mutually exclusive */ if (script_str != NULL && actions != NULL) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: ruleset cannot have both 'script'/'statements' and 'actions';" " use one or the other", fname); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } if (script_str != NULL && *script_str != '\0') { /* Synthesise a complete RainerScript ruleset(...) { script } * block and push it onto the flex buffer stack. The bison parser * will call cnfDoObj() itself after parsing the whole block, * setting cnfobj->script correctly via rulesetProcessCnf(). */ free(filter_str); filter_str = NULL; es_str_t *estr = NULL; rsRetVal br = build_ruleset_rainerscript(lst, script_str, &estr); nvlstDestruct(lst); lst = NULL; free(script_str); script_str = NULL; if (br != RS_RET_OK) ABORT_FINALIZE(br); /* cnfAddConfigBuffer() takes ownership of estr */ cnfAddConfigBuffer(estr, fname); } else if (actions != NULL) { /* Phase 2 structured shortcut: build cnfstmt chain directly. * If filter: was given, wrap the action chain in a filter node. * Otherwise the actions run unconditionally (equivalent to *.*). */ struct cnfstmt *body = actions; actions = NULL; if (filter_str != NULL && *filter_str != '\0') { struct cnfstmt *filt; /* Property filters start with ':', PRI filters do not */ if (filter_str[0] == ':') { filt = cnfstmtNewPROPFILT(filter_str, body); } else { filt = cnfstmtNewPRIFILT(filter_str, body); } if (filt == NULL) { cnfstmtDestructLst(body); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* filter_str ownership taken by cnfstmt (printable field) */ filter_str = NULL; body = filt; } free(filter_str); filter_str = NULL; struct cnfobj *obj = cnfobjNew(CNFOBJ_RULESET, lst); lst = NULL; if (obj == NULL) { cnfstmtDestructLst(body); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } obj->script = body; cnfDoObj(obj); } else { /* No script or actions — emit just the ruleset header. */ free(script_str); script_str = NULL; free(filter_str); filter_str = NULL; struct cnfobj *obj = cnfobjNew(CNFOBJ_RULESET, lst); lst = NULL; /* cnfobjNew takes ownership */ if (obj == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); cnfDoObj(obj); } } /* end ruleset sequence loop */ finalize_it: free(kname); free(script_str); free(filter_str); if (actions != NULL) cnfstmtDestructLst(actions); nvlstDestruct(lst); RETiRet; } /* Parse the include: sequence and trigger file inclusion. * Each item is a mapping with "path" (required) and "optional" (optional). * * Processing order matters because the flex buffer stack is LIFO: * - .yaml/.yml paths: cnfDoInclude() → yamlconf_load() immediately and * recursively, so they must be processed in forward (document) order. * - .conf / other paths: cnfDoInclude() → cnfSetLexFile() which pushes * onto the LIFO flex buffer stack. To ensure the bison parser later * sees them in document order (A then B then C), we must push them in * REVERSE order (C, B, A → stack top to bottom A, B, C → pop A first). * * We therefore collect all items first, then do a forward pass for YAML * files and a reverse pass for non-YAML files. * * ORDERING LIMITATION: when the include: list mixes .yaml and non-YAML files * (e.g. [a.conf, b.yaml, c.conf]), YAML files are always processed before * non-YAML files, regardless of their relative position in the document. * This is a fundamental architectural constraint — the LIFO flex buffer stack * cannot interleave with synchronous YAML loads. A warning is emitted when * such a mixed list is detected. If strict order is required, use separate * include: blocks or consolidate to a single file type. */ static rsRetVal parse_include_sequence(yaml_parser_t *parser, const char *fname) { yaml_event_t ev; char *k = NULL; char *path = NULL; /* current item path; function-scope so finalize_it can free it */ /* Dynamic array of collected items */ struct inc_item { char *path; int optional; } *items = NULL; int nitems = 0, cap = 0; DEFiRet; /* ---- Phase 1: collect all (path, optional) pairs ---- */ while (1) { free(path); /* free any leftover from previous iteration */ path = NULL; CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_SEQUENCE_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_MAPPING_START_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: include sequence item must be a mapping", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } yaml_event_delete(&ev); int optional = 0; while (1) { CHKiRet(next_event(parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } k = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (k == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); yaml_event_t vev; CHKiRet(next_event(parser, &vev, fname)); if (vev.type == YAML_SCALAR_EVENT) { const char *v = (char *)vev.data.scalar.value; if (!strcmp(k, "path")) { free(path); path = strdup(v); } else if (!strcmp(k, "optional")) { optional = (!strcasecmp(v, "on") || !strcasecmp(v, "yes") || !strcmp(v, "1")) ? 1 : 0; } yaml_event_delete(&vev); } else { /* Non-scalar value for an include key is a config error. * Consume the nested structure so the parser stays in sync. */ LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: include item key '%s' must have a scalar value, skipping", fname, k); if (vev.type == YAML_MAPPING_START_EVENT || vev.type == YAML_SEQUENCE_START_EVENT) { yaml_event_delete(&vev); skip_node(parser); } else { yaml_event_delete(&vev); } } free(k); k = NULL; } if (path != NULL) { if (nitems >= cap) { int newcap = cap == 0 ? 8 : cap * 2; struct inc_item *tmp = realloc(items, newcap * sizeof(*items)); if (tmp == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); items = tmp; cap = newcap; } items[nitems].path = path; path = NULL; /* ownership transferred to items[]; finalize_it must not free */ items[nitems].optional = optional; nitems++; } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: include item missing required 'path' key", fname); /* non-fatal: skip this item */ } } /* ---- Phase 2: warn on mixed list, then forward pass for YAML files ---- */ /* Detect mixed .yaml / non-YAML to warn about ordering limitation. */ int has_yaml_item = 0, has_conf_item = 0; for (int i = 0; i < nitems; i++) { const char *ext = strrchr(items[i].path, '.'); if (ext != NULL && (!strcmp(ext, ".yaml") || !strcmp(ext, ".yml"))) has_yaml_item = 1; else has_conf_item = 1; } if (has_yaml_item && has_conf_item) { LogError(0, RS_RET_OK, "yamlconf: %s: include: list mixes .yaml and non-YAML files; " "YAML files are loaded first regardless of document order — " "use separate include: blocks if strict ordering is required", fname); } for (int i = 0; i < nitems; i++) { const char *ext = strrchr(items[i].path, '.'); int is_yaml = (ext != NULL && (!strcmp(ext, ".yaml") || !strcmp(ext, ".yml"))); if (!is_yaml) continue; int iret = cnfDoInclude(items[i].path, items[i].optional); if (iret != 0 && !items[i].optional) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: include of '%s' failed (non-optional)", fname, items[i].path); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } } /* ---- Phase 3: reverse pass — non-YAML files → LIFO stack ---- */ /* Pushing in reverse order ensures the bison parser processes them in * the same forward (document) order as they appear in the YAML list. */ for (int i = nitems - 1; i >= 0; i--) { const char *ext = strrchr(items[i].path, '.'); int is_yaml = (ext != NULL && (!strcmp(ext, ".yaml") || !strcmp(ext, ".yml"))); if (is_yaml) continue; int iret = cnfDoInclude(items[i].path, items[i].optional); if (iret != 0 && !items[i].optional) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: include of '%s' failed (non-optional)", fname, items[i].path); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } } finalize_it: free(k); free(path); /* NULL-safe; only non-NULL if ABORT_FINALIZE before item was stored */ for (int i = 0; i < nitems; i++) free(items[i].path); free(items); RETiRet; } /* -------------------------------------------------------------------------- * Top-level dispatcher * -------------------------------------------------------------------------- */ /* Map a top-level YAML key to its cnfobjType and call the right parser. * The opening event for the section value (MAPPING_START or SEQUENCE_START) * has already been consumed when this function is called. */ static rsRetVal process_top_level(yaml_parser_t *parser, const char *key, const char *fname) { DEFiRet; if (!strcmp(key, "global")) { CHKiRet(parse_singleton_obj(parser, CNFOBJ_GLOBAL, fname)); } else if (!strcmp(key, "mainqueue") || !strcmp(key, "main_queue")) { CHKiRet(parse_singleton_obj(parser, CNFOBJ_MAINQ, fname)); } else if (!strcmp(key, "modules") || !strcmp(key, "testbench_modules")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_MODULE, fname)); } else if (!strcmp(key, "inputs")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_INPUT, fname)); } else if (!strcmp(key, "templates")) { CHKiRet(parse_template_sequence(parser, fname)); } else if (!strcmp(key, "rulesets")) { CHKiRet(parse_ruleset_sequence(parser, fname)); } else if (!strcmp(key, "parsers")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_PARSER, fname)); } else if (!strcmp(key, "lookup_tables")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_LOOKUP_TABLE, fname)); } else if (!strcmp(key, "dyn_stats")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_DYN_STATS, fname)); } else if (!strcmp(key, "perctile_stats")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_PERCTILE_STATS, fname)); } else if (!strcmp(key, "ratelimits")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_RATELIMIT, fname)); } else if (!strcmp(key, "timezones")) { CHKiRet(parse_obj_sequence(parser, CNFOBJ_TIMEZONE, fname)); } else if (!strcmp(key, "include")) { CHKiRet(parse_include_sequence(parser, fname)); } else if (!strcmp(key, "version")) { /* Informational; skip the scalar value */ yaml_event_t ev; if (next_event(parser, &ev, fname) == RS_RET_OK) yaml_event_delete(&ev); } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: unknown top-level key '%s' – ignoring", fname, key); /* Skip the value node so the parser stays in sync */ yaml_event_t ev; if (next_event(parser, &ev, fname) == RS_RET_OK) { if (ev.type == YAML_MAPPING_START_EVENT || ev.type == YAML_SEQUENCE_START_EVENT) { yaml_event_delete(&ev); skip_node(parser); } else { yaml_event_delete(&ev); } } } finalize_it: RETiRet; } /* -------------------------------------------------------------------------- * Public entry point * -------------------------------------------------------------------------- */ /** * @brief Load and process a YAML rsyslog configuration file. * * Opens @p fname, drives the libyaml event parser over the top-level * mapping, and dispatches each section to the appropriate handler. * All resulting config objects are committed to rsconf via cnfDoObj() or * cnfAddConfigBuffer() before this function returns. * * @param fname Absolute or relative path to the .yaml/.yml config file. * @return RS_RET_OK on success; RS_RET_FILE_NOT_FOUND if @p fname cannot * be opened; RS_RET_CONF_PARSE_ERROR on any YAML or semantic error. */ rsRetVal yamlconf_load(const char *fname) { yaml_parser_t parser; yaml_event_t ev; int parserInit = 0; FILE *fh = NULL; #define YAMLCONF_MAX_TOPKEYS 32 char *seen_keys[YAMLCONF_MAX_TOPKEYS]; int seen_count = 0; DEFiRet; char *prev_cnfcurrfn = cnfcurrfn; yamlIncludeFrame_t frame = {0}; frame.path = yamlconf_canonical_path(fname); if (frame.path == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); for (yamlIncludeFrame_t *it = yamlIncludeStack; it != NULL; it = it->prev) { if (!strcmp(it->path, frame.path)) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: trying to include file '%s', which is already included - ignored", fname); iRet = RS_RET_OK; goto finalize_it; } } frame.prev = yamlIncludeStack; yamlIncludeStack = &frame; cnfcurrfn = (char *)fname; fh = fopen(fname, "r"); if (fh == NULL) { LogError(errno, RS_RET_CONF_FILE_NOT_FOUND, "yamlconf: cannot open config file '%s'", fname); ABORT_FINALIZE(RS_RET_CONF_FILE_NOT_FOUND); } if (!yaml_parser_initialize(&parser)) { LogError(0, RS_RET_INTERNAL_ERROR, "yamlconf: failed to initialize YAML parser"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } parserInit = 1; yaml_parser_set_input_file(&parser, fh); /* Consume stream/document start */ CHKiRet(expect_event(&parser, &ev, YAML_STREAM_START_EVENT, "stream start", fname)); yaml_event_delete(&ev); CHKiRet(expect_event(&parser, &ev, YAML_DOCUMENT_START_EVENT, "document start", fname)); yaml_event_delete(&ev); /* The top-level node must be a mapping */ CHKiRet(expect_event(&parser, &ev, YAML_MAPPING_START_EVENT, "top-level mapping", fname)); yaml_event_delete(&ev); /* Track seen top-level keys to warn on duplicates. Duplicate keys are * undefined behaviour in the YAML spec and unsupported by rsyslog; use * sequences for multiple items or include: for file-level composition. */ /* Walk the top-level key/value pairs */ while (1) { CHKiRet(next_event(&parser, &ev, fname)); if (ev.type == YAML_MAPPING_END_EVENT) { yaml_event_delete(&ev); break; } if (ev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: expected scalar key at top level", fname); yaml_event_delete(&ev); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } char *topkey = strdup((char *)ev.data.scalar.value); yaml_event_delete(&ev); if (topkey == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); /* Warn on duplicate top-level key. */ for (int ki = 0; ki < seen_count; ++ki) { if (!strcmp(seen_keys[ki], topkey)) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: duplicate top-level key '%s' - " "this is unsupported; use sequences for multiple items " "or include: for file-level composition", fname, topkey); break; } } int topkey_owned = 0; /* 1 if seen_keys owns topkey, 0 if we must free it */ if (seen_count < YAMLCONF_MAX_TOPKEYS) { seen_keys[seen_count++] = topkey; /* ownership transferred to seen_keys */ topkey_owned = 1; } /* else: array full (>32 distinct top-level keys — highly unusual); * duplicate detection skipped for this key; topkey freed below. */ /* Consume the opening event of the value node before dispatching */ yaml_event_t vev; rsRetVal vret = next_event(&parser, &vev, fname); if (vret != RS_RET_OK) { if (!topkey_owned) free(topkey); ABORT_FINALIZE(vret); } /* For sections that expect a sequence we need SEQUENCE_START; * for singleton sections we need MAPPING_START. * process_top_level() takes responsibility from here, but we already * consumed the opening event – so verify it makes sense. */ if (vev.type != YAML_MAPPING_START_EVENT && vev.type != YAML_SEQUENCE_START_EVENT && vev.type != YAML_SCALAR_EVENT) { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: unexpected value type for key '%s'", fname, topkey); yaml_event_delete(&vev); if (!topkey_owned) free(topkey); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } /* For scalar values (e.g. version: 2) put the event back via a small * detour: handle scalars inline here before calling process_top_level. */ if (vev.type == YAML_SCALAR_EVENT) { if (!strcmp(topkey, "version")) { /* silently accept */ } else { LogError(0, RS_RET_CONF_PARSE_ERROR, "yamlconf: %s: key '%s' has a scalar value but expects" " a mapping or sequence", fname, topkey); /* non-fatal */ } yaml_event_delete(&vev); if (!topkey_owned) free(topkey); continue; } yaml_event_delete(&vev); /* process_top_level() will now call the right parser which will consume * the rest of the value node (up to and including its END event). */ rsRetVal pret = process_top_level(&parser, topkey, fname); if (!topkey_owned) free(topkey); if (pret != RS_RET_OK) ABORT_FINALIZE(pret); } finalize_it: for (int ki = 0; ki < seen_count; ++ki) free(seen_keys[ki]); if (parserInit) yaml_parser_delete(&parser); if (fh) fclose(fh); if (yamlIncludeStack == &frame) yamlIncludeStack = frame.prev; free(frame.path); cnfcurrfn = prev_cnfcurrfn; RETiRet; } #endif /* HAVE_LIBYAML */ rsyslog-8.2608.0/runtime/PaxHeaders/netstrm.c0000644000000000000000000000013115241075234016064 xustar0030 mtime=1787067036.603578257 29 atime=1787067036.74958099 30 ctime=1787067794.538727738 rsyslog-8.2608.0/runtime/netstrm.c0000664000175000017500000004200515241075234015532 0ustar00rgerrger/* netstrm.c * * This class implements a generic netstrmwork stream class. It supports * sending and receiving data streams over a netstrmwork. The class abstracts * the transport, though it is a safe assumption that TCP is being used. * The class has a number of properties, among which are also ones to * select privacy settings, eg by enabling TLS and/or GSSAPI. In the * long run, this class shall provide all stream-oriented netstrmwork * functionality inside rsyslog. * * It is a high-level class, which uses a number of helper objects * to carry out its work (including, and most importantly, transport * drivers). * * Note on processing: * - Initiating a listener may be driver-specific, but in regard to TLS/non-TLS * it actually is not. This is because TLS is negotiated after a connection * has been established. So it is the "acceptConnReq" driver entry where TLS * params need to be applied. * * Work on this module begun 2008-04-17 by Rainer Gerhards. This code * borrows from librelp's tcp.c/.h code. librelp is dual licensed and * Rainer Gerhards and Adiscon GmbH have agreed to permit using the code * under the terms of the GNU Lesser General Public License. * * Copyright 2007-2020 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ #include "config.h" #include #include #include #include "rsyslog.h" #include "net.h" #include "module-template.h" #include "obj.h" #include "errmsg.h" #include "netstrms.h" #include "netstrm.h" /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(net) DEFobjCurrIf(netstrms) /* Standard-Constructor */ BEGINobjConstruct(netstrm) /* be sure to specify the object type also in END macro! */ ENDobjConstruct (netstrm) /* destructor for the netstrm object */ BEGINobjDestruct(netstrm) /* be sure to specify the object type also in END and CODESTART macros! */ CODESTARTobjDestruct(netstrm); if (pThis->pDrvrData != NULL) iRet = pThis->Drvr.Destruct(&pThis->pDrvrData); ENDobjDestruct (netstrm) /* ConstructionFinalizer */ static rsRetVal netstrmConstructFinalize(netstrm_t *pThis) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.Construct(&pThis->pDrvrData); finalize_it: RETiRet; } /* abort a connection. This is much like Destruct(), but tries * to discard any unsent data. -- rgerhards, 2008-03-24 */ static rsRetVal AbortDestruct(netstrm_t **ppThis) { DEFiRet; NULL_CHECK(ppThis); NULL_CHECK(*ppThis); /* we do NOT exit on error, because that would make things worse */ (*ppThis)->Drvr.Abort((*ppThis)->pDrvrData); iRet = netstrmDestruct(ppThis); finalize_it: RETiRet; } /* accept an incoming connection request * The netstrm instance that had the incoming request must be provided. If * the connection request succeeds, a new netstrm object is created and * passed back to the caller. The caller is responsible for destructing it. * pReq is the nsd_t obj that has the accept request. * rgerhards, 2008-04-21 */ static rsRetVal AcceptConnReq(netstrm_t *pThis, netstrm_t **ppNew, char *const connInfo) { nsd_t *pNewNsd = NULL; DEFiRet; NULL_CHECK(pThis); assert(ppNew != NULL); /* accept the new connection */ CHKiRet(pThis->Drvr.AcceptConnReq(pThis->pDrvrData, &pNewNsd, connInfo)); /* construct our object so that we can use it... */ CHKiRet(objUse(netstrms, DONT_LOAD_LIB)); /* use netstrms obj if not already done so */ CHKiRet(netstrms.CreateStrm(pThis->pNS, ppNew)); (*ppNew)->pDrvrData = pNewNsd; finalize_it: if (iRet != RS_RET_OK) { /* the close may be redundant, but that doesn't hurt... */ if (pNewNsd != NULL) pThis->Drvr.Destruct(&pNewNsd); } RETiRet; } /* make the netstrm listen to specified port and IP. * pLstnIP points to the port to listen to (NULL means "all"), * iMaxSess has the maximum number of sessions permitted (this ist just a hint). * pLstnPort must point to a port name or number. NULL is NOT permitted. * rgerhards, 2008-04-22 */ static rsRetVal ATTR_NONNULL(1, 3, 5) LstnInit(netstrms_t *pNS, void *pUsr, rsRetVal (*fAddLstn)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params) { DEFiRet; ISOBJ_TYPE_assert(pNS, netstrms); assert(fAddLstn != NULL); assert(cnf_params->pszPort != NULL); #ifdef HAVE_SETNS const char *ns = cnf_params->pszNetworkNamespace; int netns_fd = -1; if (ns) { CHKiRet(net.netns_save(&netns_fd)); CHKiRet(net.netns_switch(ns)); } #endif // ndef HAVE_SETNS CHKiRet(pNS->Drvr.LstnInit(pNS, pUsr, fAddLstn, iSessMax, cnf_params)); finalize_it: #ifdef HAVE_SETNS if (ns) { // netns_restore will log a message on failure // but there's really nothing we can do about it (void)net.netns_restore(&netns_fd); } #endif // ndef HAVE_SETNS RETiRet; } /* receive data from a tcp socket * The lenBuf parameter must contain the max buffer size on entry and contains * the number of octets read (or -1 in case of error) on exit. This function * never blocks, not even when called on a blocking socket. That is important * for client sockets, which are set to block during send, but should not * block when trying to read data. If *pLenBuf is -1, an error occurred and * oserr holds the exact error cause. * rgerhards, 2008-03-17 */ static rsRetVal Rcv(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf, int *const oserr, unsigned *nextIODirection) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.Rcv(pThis->pDrvrData, pBuf, pLenBuf, oserr, nextIODirection); finalize_it: RETiRet; } /* here follows a number of methods that shuffle authentication settings down * to the drivers. Drivers not supporting these settings may return an error * state. * -------------------------------------------------------------------------- */ /* set the driver mode * rgerhards, 2008-04-28 */ static rsRetVal SetDrvrMode(netstrm_t *pThis, int iMode) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetMode(pThis->pDrvrData, iMode); finalize_it: RETiRet; } /* set the driver authentication mode -- rgerhards, 2008-05-16 */ static rsRetVal SetDrvrAuthMode(netstrm_t *pThis, uchar *mode) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetAuthMode(pThis->pDrvrData, mode); finalize_it: RETiRet; } /* set the driver permitexpiredcerts mode -- alorbach, 2018-12-20 */ static rsRetVal SetDrvrPermitExpiredCerts(netstrm_t *pThis, uchar *mode) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetPermitExpiredCerts(pThis->pDrvrData, mode); finalize_it: RETiRet; } /* set the driver's permitted peers -- rgerhards, 2008-05-19 */ static rsRetVal SetDrvrPermPeers(netstrm_t *pThis, permittedPeers_t *pPermPeers) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetPermPeers(pThis->pDrvrData, pPermPeers); finalize_it: RETiRet; } /* Mandate also verification of Extended key usage / purpose field */ static rsRetVal SetDrvrCheckExtendedKeyUsage(netstrm_t *pThis, int ChkExtendedKeyUsage) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetCheckExtendedKeyUsage(pThis->pDrvrData, ChkExtendedKeyUsage); finalize_it: RETiRet; } /* Mandate stricter name checking per RFC 6125 - ignoce CN if any SAN present */ static rsRetVal SetDrvrPrioritizeSAN(netstrm_t *pThis, int prioritizeSan) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetPrioritizeSAN(pThis->pDrvrData, prioritizeSan); finalize_it: RETiRet; } /* tls verify depth */ static rsRetVal SetDrvrTlsRevocationCheck(netstrm_t *pThis, int enabled) { DEFiRet; iRet = pThis->Drvr.SetTlsRevocationCheck(pThis->pDrvrData, enabled); RETiRet; } static rsRetVal SetDrvrTlsVerifyDepth(netstrm_t *pThis, int verifyDepth) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsVerifyDepth(pThis->pDrvrData, verifyDepth); finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCAFile(netstrm_t *const pThis, const uchar *const file) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsCAFile(pThis->pDrvrData, file); finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCRLFile(netstrm_t *const pThis, const uchar *const file) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsCRLFile(pThis->pDrvrData, file); finalize_it: RETiRet; } /** * @brief Set additional CA certificate sources on the active netstream * driver. * @param pThis Netstream instance whose driver should receive the setting. * @param file Comma-separated file list or strict ``pkcs11:`` URI list to * forward to the driver. * @return RS_RET_OK on success or a driver-specific error code. */ static rsRetVal SetDrvrTlsCAExtraFiles(netstrm_t *const pThis, const uchar *const file) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsCAExtraFiles(pThis->pDrvrData, file); finalize_it: RETiRet; } static rsRetVal SetDrvrTlsKeyFile(netstrm_t *const pThis, const uchar *const file) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsKeyFile(pThis->pDrvrData, file); finalize_it: RETiRet; } static rsRetVal SetDrvrTlsCertFile(netstrm_t *const pThis, const uchar *const file) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTlsCertFile(pThis->pDrvrData, file); finalize_it: RETiRet; } /* Set remote host's TLS SNI */ static rsRetVal SetDrvrRemoteSNI(netstrm_t *pThis, uchar *remoteSNI) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetRemoteSNI(pThis->pDrvrData, remoteSNI); finalize_it: RETiRet; } /* End of methods to shuffle autentication settings to the driver. * -------------------------------------------------------------------------- */ /* send a buffer. On entry, pLenBuf contains the number of octets to * write. On exit, it contains the number of octets actually written. * If this number is lower than on entry, only a partial buffer has * been written. * rgerhards, 2008-03-19 */ static rsRetVal Send(netstrm_t *pThis, uchar *pBuf, ssize_t *pLenBuf) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.Send(pThis->pDrvrData, pBuf, pLenBuf); finalize_it: RETiRet; } /* Enable Keep-Alive handling for those drivers that support it. * rgerhards, 2009-06-02 */ static rsRetVal EnableKeepAlive(netstrm_t *pThis) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.EnableKeepAlive(pThis->pDrvrData); finalize_it: RETiRet; } /* Keep-Alive options */ static rsRetVal SetKeepAliveProbes(netstrm_t *pThis, int keepAliveProbes) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetKeepAliveProbes(pThis->pDrvrData, keepAliveProbes); finalize_it: RETiRet; } /* Keep-Alive options */ static rsRetVal SetKeepAliveTime(netstrm_t *pThis, int keepAliveTime) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetKeepAliveTime(pThis->pDrvrData, keepAliveTime); finalize_it: RETiRet; } /* Keep-Alive options */ static rsRetVal SetKeepAliveIntvl(netstrm_t *pThis, int keepAliveIntvl) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetKeepAliveIntvl(pThis->pDrvrData, keepAliveIntvl); finalize_it: RETiRet; } /* TCP user timeout option */ static rsRetVal SetTcpUserTimeout(netstrm_t *pThis, int tcpUserTimeout) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetTcpUserTimeout(pThis->pDrvrData, tcpUserTimeout); finalize_it: RETiRet; } /* gnutls priority string */ static rsRetVal SetGnutlsPriorityString(netstrm_t *pThis, uchar *gnutlsPriorityString) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.SetGnutlsPriorityString(pThis->pDrvrData, gnutlsPriorityString); finalize_it: RETiRet; } /* check connection - slim wrapper for NSD driver function */ static rsRetVal CheckConnection(netstrm_t *pThis) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.CheckConnection(pThis->pDrvrData); finalize_it: RETiRet; } /* get remote hname - slim wrapper for NSD driver function */ static rsRetVal GetRemoteHName(netstrm_t *pThis, uchar **ppsz) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.GetRemoteHName(pThis->pDrvrData, ppsz); finalize_it: RETiRet; } /* get remote IP - slim wrapper for NSD driver function */ static rsRetVal GetRemoteIP(netstrm_t *pThis, prop_t **ip) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.GetRemoteIP(pThis->pDrvrData, ip); finalize_it: RETiRet; } /* get remote addr - slim wrapper for NSD driver function */ static rsRetVal GetRemAddr(netstrm_t *pThis, struct sockaddr_storage **ppAddr) { DEFiRet; NULL_CHECK(pThis); iRet = pThis->Drvr.GetRemAddr(pThis->pDrvrData, ppAddr); finalize_it: RETiRet; } /* open a connection to a remote host (server). * rgerhards, 2008-03-19 */ static rsRetVal Connect(netstrm_t *pThis, int family, uchar *port, uchar *host, char *device) { DEFiRet; NULL_CHECK(pThis); assert(port != NULL); assert(host != NULL); iRet = pThis->Drvr.Connect(pThis->pDrvrData, family, port, host, device); finalize_it: RETiRet; } /* Provide access to the underlying OS socket. This is dirty * and scheduled to be removed. Does not work with all nsd drivers. * See comment in netstrm interface for details. * rgerhards, 2008-05-05 */ static rsRetVal GetSock(netstrm_t *pThis, int *pSock) { DEFiRet; NULL_CHECK(pThis); NULL_CHECK(pSock); iRet = pThis->Drvr.GetSock(pThis->pDrvrData, pSock); finalize_it: RETiRet; } /* queryInterface function */ BEGINobjQueryInterface(netstrm) CODESTARTobjQueryInterface(netstrm); if (pIf->ifVersion != netstrmCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->Construct = netstrmConstruct; pIf->ConstructFinalize = netstrmConstructFinalize; pIf->Destruct = netstrmDestruct; pIf->AbortDestruct = AbortDestruct; pIf->Rcv = Rcv; pIf->Send = Send; pIf->Connect = Connect; pIf->LstnInit = LstnInit; pIf->AcceptConnReq = AcceptConnReq; pIf->GetRemoteHName = GetRemoteHName; pIf->GetRemoteIP = GetRemoteIP; pIf->GetRemAddr = GetRemAddr; pIf->SetDrvrMode = SetDrvrMode; pIf->SetDrvrAuthMode = SetDrvrAuthMode; pIf->SetDrvrPermitExpiredCerts = SetDrvrPermitExpiredCerts; pIf->SetDrvrPermPeers = SetDrvrPermPeers; pIf->CheckConnection = CheckConnection; pIf->GetSock = GetSock; pIf->EnableKeepAlive = EnableKeepAlive; pIf->SetKeepAliveProbes = SetKeepAliveProbes; pIf->SetKeepAliveTime = SetKeepAliveTime; pIf->SetKeepAliveIntvl = SetKeepAliveIntvl; pIf->SetTcpUserTimeout = SetTcpUserTimeout; pIf->SetGnutlsPriorityString = SetGnutlsPriorityString; pIf->SetDrvrCheckExtendedKeyUsage = SetDrvrCheckExtendedKeyUsage; pIf->SetDrvrPrioritizeSAN = SetDrvrPrioritizeSAN; pIf->SetDrvrTlsVerifyDepth = SetDrvrTlsVerifyDepth; pIf->SetDrvrTlsRevocationCheck = SetDrvrTlsRevocationCheck; pIf->SetDrvrTlsCAFile = SetDrvrTlsCAFile; pIf->SetDrvrTlsCRLFile = SetDrvrTlsCRLFile; pIf->SetDrvrTlsCAExtraFiles = SetDrvrTlsCAExtraFiles; pIf->SetDrvrTlsKeyFile = SetDrvrTlsKeyFile; pIf->SetDrvrTlsCertFile = SetDrvrTlsCertFile; pIf->SetDrvrRemoteSNI = SetDrvrRemoteSNI; finalize_it: ENDobjQueryInterface(netstrm) /* exit our class */ BEGINObjClassExit(netstrm, OBJ_IS_LOADABLE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(netstrm); /* release objects we no longer need */ objRelease(netstrms, DONT_LOAD_LIB); objRelease(net, LM_NET_FILENAME); ENDObjClassExit(netstrm) /* Initialize the netstrm class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 */ BEGINAbstractObjClassInit(netstrm, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(net, LM_NET_FILENAME)); /* set our own handlers */ ENDObjClassInit(netstrm) rsyslog-8.2608.0/runtime/PaxHeaders/nsd.h0000644000000000000000000000013215241075234015162 xustar0030 mtime=1787067036.603578257 30 atime=1787067036.750581009 30 ctime=1787067794.272722781 rsyslog-8.2608.0/runtime/nsd.h0000664000175000017500000001357415241075234014640 0ustar00rgerrger/* The interface definition for "NetStream Drivers" (nsd). * * This is just an abstract driver interface, which needs to be * implemented by concrete classes. As such, no nsd data type itself * is defined. * * Copyright 2008-2025 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_NSD_H #define INCLUDED_NSD_H #include enum nsdsel_waitOp_e { NSDSEL_RD = 1, NSDSEL_WR = 2, NSDSEL_RDWR = 3 }; /**< the operation we wait for */ /* nsd_t is actually obj_t (which is somewhat better than void* but in essence * much the same). */ /* interface */ BEGINinterface(nsd) /* name must also be changed in ENDinterface macro! */ rsRetVal (*Construct)(nsd_t **ppThis); rsRetVal (*Destruct)(nsd_t **ppThis); rsRetVal (*Abort)(nsd_t *pThis); rsRetVal (*Rcv)(nsd_t *pThis, uchar *pRcvBuf, ssize_t *pLenBuf, int *oserr, unsigned *nextIODirection); rsRetVal (*Send)(nsd_t *pThis, uchar *pBuf, ssize_t *pLenBuf); rsRetVal (*Connect)(nsd_t *pThis, int family, unsigned char *port, unsigned char *host, char *device); rsRetVal (*AcceptConnReq)(nsd_t *pThis, nsd_t **ppThis, char *connInfo); rsRetVal (*GetRemoteHName)(nsd_t *pThis, uchar **pszName); rsRetVal (*GetRemoteIP)(nsd_t *pThis, prop_t **ip); rsRetVal (*SetMode)(nsd_t *pThis, int mode); /* sets a driver specific mode - see driver doc for details */ rsRetVal (*SetAuthMode)(nsd_t *pThis, uchar *); /* sets a driver specific mode - see driver doc for details */ rsRetVal (*SetPermitExpiredCerts)(nsd_t *pThis, uchar *); /* sets a driver specific permitexpiredcerts mode */ rsRetVal (*SetPermPeers)(nsd_t *pThis, permittedPeers_t *); /* sets driver permitted peers for auth needs */ rsRetVal (*CheckConnection)(nsd_t *pThis); /* This is a trick mostly for plain tcp syslog */ rsRetVal (*GetSock)(nsd_t *pThis, int *pSock); rsRetVal (*SetSock)(nsd_t *pThis, int sock); /* GetSock() and SetSock() return an error if the driver does not use plain * OS sockets. This interface is primarily meant as an internal aid for * those drivers that utilize the nsd_ptcp to do some of their work. */ rsRetVal (*GetRemAddr)(nsd_t *pThis, struct sockaddr_storage **ppAddr); /* getRemAddr() is an aid needed by the legacy ACL system. It exposes the remote * peer's socket addr structure, so that the legacy matching functions can work on * it. Note that this ties netstream drivers to things that can be implemented over * sockets - not really desirable, but not the end of the world... */ /* v5 */ rsRetVal (*EnableKeepAlive)(nsd_t *pThis); /* v8 */ rsRetVal (*SetKeepAliveIntvl)(nsd_t *pThis, int keepAliveIntvl); rsRetVal (*SetKeepAliveProbes)(nsd_t *pThis, int keepAliveProbes); rsRetVal (*SetKeepAliveTime)(nsd_t *pThis, int keepAliveTime); rsRetVal (*SetTcpUserTimeout)(nsd_t *pThis, int tcpUserTimeout); rsRetVal (*SetGnutlsPriorityString)(nsd_t *pThis, uchar *gnutlsPriorityString); /* v12 -- parameter pszLstnPortFileName added to LstnInit()*/ rsRetVal(ATTR_NONNULL(1, 3, 5) * LstnInit)(netstrms_t * pNS, void *pUsr, rsRetVal (*)(void *, netstrm_t *), const int iSessMax, const tcpLstnParams_t *const cnf_params); /* v13 -- two new binary flags added to gtls driver enabling stricter operation */ rsRetVal (*SetCheckExtendedKeyUsage)(nsd_t *pThis, int ChkExtendedKeyUsage); rsRetVal (*SetPrioritizeSAN)(nsd_t *pThis, int prioritizeSan); /* v14 -- Tls functions */ rsRetVal (*SetTlsVerifyDepth)(nsd_t *pThis, int verifyDepth); /* v15 -- Tls functions */ rsRetVal (*SetTlsCAFile)(nsd_t *pThis, const uchar *); rsRetVal (*SetTlsKeyFile)(nsd_t *pThis, const uchar *); rsRetVal (*SetTlsCertFile)(nsd_t *pThis, const uchar *); /* v16 - Tls CRL */ rsRetVal (*SetTlsCRLFile)(nsd_t *pThis, const uchar *); rsRetVal (*SetTlsCAExtraFiles)(nsd_t *pThis, const uchar *); /* v17 - Remote Port */ rsRetVal (*GetRemotePort)(nsd_t *pThis, int *); rsRetVal (*FmtRemotePortStr)(const int port, uchar *const buf, const size_t len); /* v18 -- allow remote server's TLS SNI to be set manually */ rsRetVal (*SetRemoteSNI)(nsd_t *pThis, uchar *pszRemoteSNI); /* v19 -- TLS revocation checking (OCSP/CRL) */ rsRetVal (*SetTlsRevocationCheck)(nsd_t *pThis, int enabled); ENDinterface(nsd) #define nsdCURR_IF_VERSION 21 /* increment whenever you change the interface structure! */ /* interface version 4 added GetRemAddr() * interface version 5 added EnableKeepAlive() -- rgerhards, 2009-06-02 * interface version 6 changed return of CheckConnection from void to rsRetVal -- alorbach, 2012-09-06 * interface version 7 changed signature ofGetRempoteIP() -- rgerhards, 2013-01-21 * interface version 8 added keep alive parameter set functions * interface version 9 changed signature of Connect() -- dsa, 2016-11-14 * interface version 10 added SetGnutlsPriorityString() -- PascalWithopf, 2017-08-08 * interface version 11 added oserr to Rcv() signature -- rgerhards, 2017-09-04 * interface version 18 added SetRemoteSNI -- jfcantu, 2020-01-15 * interface version 20 added SetTcpUserTimeout * interface version 21 added SetTlsCAExtraFiles */ #endif /* #ifndef INCLUDED_NSD_H */ rsyslog-8.2608.0/runtime/PaxHeaders/zlibw.h0000644000000000000000000000013215132411300015510 xustar0030 mtime=1768559296.279885846 30 atime=1787067616.816415003 30 ctime=1787067794.611729099 rsyslog-8.2608.0/runtime/zlibw.h0000666000175000017500000000362215132411300015161 0ustar00rgerrger/* The zlibw object. It encapsulates the zlib functionality. The primary * purpose of this wrapper class is to enable rsyslogd core to be build without * zlib libraries. * * Copyright 2009-2022 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_ZLIBW_H #define INCLUDED_ZLIBW_H #include #include "errmsg.h" /* interfaces */ BEGINinterface(zlibw) /* name must also be changed in ENDinterface macro! */ int (*DeflateInit)(z_streamp strm, int); int (*DeflateInit2)(z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy); int (*Deflate)(z_streamp strm, int); int (*DeflateEnd)(z_streamp strm); rsRetVal (*doStrmWrite)(strm_t *pThis, uchar *const pBuf, const size_t lenBuf, const int bFlush, rsRetVal (*strmPhysWrite)(strm_t *pThis, uchar *pBuf, size_t lenBuf)); rsRetVal (*doCompressFinish)(strm_t *pThis, rsRetVal (*Destruct)(strm_t *pThis, uchar *pBuf, size_t lenBuf)); rsRetVal (*Destruct)(strm_t *pThis); ENDinterface(zlibw) #define zlibwCURR_IF_VERSION 2 /* increment whenever you change the interface structure! */ /* prototypes */ PROTOTYPEObj(zlibw); /* the name of our library binary */ #define LM_ZLIBW_FILENAME "lmzlibw" #endif /* #ifndef INCLUDED_ZLIBW_H */ rsyslog-8.2608.0/runtime/PaxHeaders/msg.c0000644000000000000000000000013215241075234015157 xustar0030 mtime=1787067036.602578238 30 atime=1787067036.747580953 30 ctime=1787067794.305723396 rsyslog-8.2608.0/runtime/msg.c0000664000175000017500000062614515241075234014641 0ustar00rgerrger/* msg.c * The msg object. Implementation of all msg-related functions * * File begun on 2007-07-13 by RGerhards (extracted from syslogd.c) * This file is under development and has not yet arrived at being fully * self-contained and a real object. So far, it is mostly an excerpt * of the "old" message code without any modifications. However, it * helps to have things at the right place one we go to the meat of it. * * Copyright 2007-2026 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * The rsyslog runtime library is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The rsyslog runtime library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the rsyslog runtime library. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. * A copy of the LGPL can be found in the file "COPYING.LESSER" in this distribution. */ /* Concurrency & Locking * * A message's mut mutex protects its mutable JSON trees and turbo snapshot * slots. MsgDup() holds the source mutex while it takes a coherent copy of * JSON state and establishes shared snapshot ownership. Lazy snapshot * materialization also runs under that mutex. * * Turbo snapshots are immutable after publication. Separate MsgDup() copies * may therefore read one snapshot concurrently; turbo_result_refs tracks * their shared ownership with atomic increments and decrements. Each message * releases its reference exactly once through MsgReleaseTurboResult(). */ #include "config.h" #include #include #include #define SYSLOG_NAMES #include #include #include #include #include #include #include #ifdef HAVE_SYSINFO_UPTIME #include #endif #include #include #include #ifdef HAVE_MALLOC_H #include #endif #ifdef USE_LIBUUID #include #endif #include #include "rsyslog.h" #include "srUtils.h" #include "stringbuf.h" #include "template.h" #include "msg.h" #include "datetime.h" #include "glbl.h" #include "regexp.h" #include "atomic.h" #include "unicode-helper.h" #include "ruleset.h" #include "prop.h" #include "msg_replace_helper.h" #include "net.h" #include "var.h" #include "rsconf.h" #include "parserif.h" #include "errmsg.h" #define DEV_DEBUG 0 /* set to 1 to enable very verbose developer debugging messages */ /* TODO: move the global variable root to the config object - had no time to to it * right now before vacation -- rgerhards, 2013-07-22 */ static pthread_mutex_t glblVars_lock; struct json_object *global_var_root = NULL; #ifdef HAVE_LOGNORM_TURBO static int msgMaterializeTurboJSON(smsg_t *pMsg); #endif /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) DEFobjCurrIf(regexp) DEFobjCurrIf(prop) DEFobjCurrIf(net) DEFobjCurrIf(var) static const char *one_digit[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; static const char *two_digits[100] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99"}; static const char *wdayNames[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; /* Table of days in a year, needed for getYearDay */ static const char *daysInYear[366] = { "001", "002", "003", "004", "005", "006", "007", "008", "009", "010", "011", "012", "013", "014", "015", "016", "017", "018", "019", "020", "021", "022", "023", "024", "025", "026", "027", "028", "029", "030", "031", "032", "033", "034", "035", "036", "037", "038", "039", "040", "041", "042", "043", "044", "045", "046", "047", "048", "049", "050", "051", "052", "053", "054", "055", "056", "057", "058", "059", "060", "061", "062", "063", "064", "065", "066", "067", "068", "069", "070", "071", "072", "073", "074", "075", "076", "077", "078", "079", "080", "081", "082", "083", "084", "085", "086", "087", "088", "089", "090", "091", "092", "093", "094", "095", "096", "097", "098", "099", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", "360", "361", "362", "363", "364", "365", "366"}; /* The following is a table of supported years. This permits us * to avoid dynamic memory allocation. Note that the time-based * algos need to be upgraded after the year 2099 in any case. * Quite honestly, I don't expect that this is a real problem ;) */ static const char *years[] = { "1967", "1968", "1969", "1970", "1971", "1972", "1973", "1974", "1975", "1976", "1977", "1978", "1979", "1980", "1981", "1982", "1983", "1984", "1985", "1986", "1987", "1988", "1989", "1990", "1991", "1992", "1993", "1994", "1995", "1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026", "2027", "2028", "2029", "2030", "2031", "2032", "2033", "2034", "2035", "2036", "2037", "2038", "2039", "2040", "2041", "2042", "2043", "2044", "2045", "2046", "2047", "2048", "2049", "2050", "2051", "2052", "2053", "2054", "2055", "2056", "2057", "2058", "2059", "2060", "2061", "2062", "2063", "2064", "2065", "2066", "2067", "2068", "2069", "2070", "2071", "2072", "2073", "2074", "2075", "2076", "2077", "2078", "2079", "2080", "2081", "2082", "2083", "2084", "2085", "2086", "2087", "2088", "2089", "2090", "2091", "2092", "2093", "2094", "2095", "2096", "2097", "2098", "2099"}; static struct { uchar *pszName; } syslog_pri_names[200] = { {UCHAR_CONSTANT("0")}, {UCHAR_CONSTANT("1")}, {UCHAR_CONSTANT("2")}, {UCHAR_CONSTANT("3")}, {UCHAR_CONSTANT("4")}, {UCHAR_CONSTANT("5")}, {UCHAR_CONSTANT("6")}, {UCHAR_CONSTANT("7")}, {UCHAR_CONSTANT("8")}, {UCHAR_CONSTANT("9")}, {UCHAR_CONSTANT("10")}, {UCHAR_CONSTANT("11")}, {UCHAR_CONSTANT("12")}, {UCHAR_CONSTANT("13")}, {UCHAR_CONSTANT("14")}, {UCHAR_CONSTANT("15")}, {UCHAR_CONSTANT("16")}, {UCHAR_CONSTANT("17")}, {UCHAR_CONSTANT("18")}, {UCHAR_CONSTANT("19")}, {UCHAR_CONSTANT("20")}, {UCHAR_CONSTANT("21")}, {UCHAR_CONSTANT("22")}, {UCHAR_CONSTANT("23")}, {UCHAR_CONSTANT("24")}, {UCHAR_CONSTANT("25")}, {UCHAR_CONSTANT("26")}, {UCHAR_CONSTANT("27")}, {UCHAR_CONSTANT("28")}, {UCHAR_CONSTANT("29")}, {UCHAR_CONSTANT("30")}, {UCHAR_CONSTANT("31")}, {UCHAR_CONSTANT("32")}, {UCHAR_CONSTANT("33")}, {UCHAR_CONSTANT("34")}, {UCHAR_CONSTANT("35")}, {UCHAR_CONSTANT("36")}, {UCHAR_CONSTANT("37")}, {UCHAR_CONSTANT("38")}, {UCHAR_CONSTANT("39")}, {UCHAR_CONSTANT("40")}, {UCHAR_CONSTANT("41")}, {UCHAR_CONSTANT("42")}, {UCHAR_CONSTANT("43")}, {UCHAR_CONSTANT("44")}, {UCHAR_CONSTANT("45")}, {UCHAR_CONSTANT("46")}, {UCHAR_CONSTANT("47")}, {UCHAR_CONSTANT("48")}, {UCHAR_CONSTANT("49")}, {UCHAR_CONSTANT("50")}, {UCHAR_CONSTANT("51")}, {UCHAR_CONSTANT("52")}, {UCHAR_CONSTANT("53")}, {UCHAR_CONSTANT("54")}, {UCHAR_CONSTANT("55")}, {UCHAR_CONSTANT("56")}, {UCHAR_CONSTANT("57")}, {UCHAR_CONSTANT("58")}, {UCHAR_CONSTANT("59")}, {UCHAR_CONSTANT("60")}, {UCHAR_CONSTANT("61")}, {UCHAR_CONSTANT("62")}, {UCHAR_CONSTANT("63")}, {UCHAR_CONSTANT("64")}, {UCHAR_CONSTANT("65")}, {UCHAR_CONSTANT("66")}, {UCHAR_CONSTANT("67")}, {UCHAR_CONSTANT("68")}, {UCHAR_CONSTANT("69")}, {UCHAR_CONSTANT("70")}, {UCHAR_CONSTANT("71")}, {UCHAR_CONSTANT("72")}, {UCHAR_CONSTANT("73")}, {UCHAR_CONSTANT("74")}, {UCHAR_CONSTANT("75")}, {UCHAR_CONSTANT("76")}, {UCHAR_CONSTANT("77")}, {UCHAR_CONSTANT("78")}, {UCHAR_CONSTANT("79")}, {UCHAR_CONSTANT("80")}, {UCHAR_CONSTANT("81")}, {UCHAR_CONSTANT("82")}, {UCHAR_CONSTANT("83")}, {UCHAR_CONSTANT("84")}, {UCHAR_CONSTANT("85")}, {UCHAR_CONSTANT("86")}, {UCHAR_CONSTANT("87")}, {UCHAR_CONSTANT("88")}, {UCHAR_CONSTANT("89")}, {UCHAR_CONSTANT("90")}, {UCHAR_CONSTANT("91")}, {UCHAR_CONSTANT("92")}, {UCHAR_CONSTANT("93")}, {UCHAR_CONSTANT("94")}, {UCHAR_CONSTANT("95")}, {UCHAR_CONSTANT("96")}, {UCHAR_CONSTANT("97")}, {UCHAR_CONSTANT("98")}, {UCHAR_CONSTANT("99")}, {UCHAR_CONSTANT("100")}, {UCHAR_CONSTANT("101")}, {UCHAR_CONSTANT("102")}, {UCHAR_CONSTANT("103")}, {UCHAR_CONSTANT("104")}, {UCHAR_CONSTANT("105")}, {UCHAR_CONSTANT("106")}, {UCHAR_CONSTANT("107")}, {UCHAR_CONSTANT("108")}, {UCHAR_CONSTANT("109")}, {UCHAR_CONSTANT("110")}, {UCHAR_CONSTANT("111")}, {UCHAR_CONSTANT("112")}, {UCHAR_CONSTANT("113")}, {UCHAR_CONSTANT("114")}, {UCHAR_CONSTANT("115")}, {UCHAR_CONSTANT("116")}, {UCHAR_CONSTANT("117")}, {UCHAR_CONSTANT("118")}, {UCHAR_CONSTANT("119")}, {UCHAR_CONSTANT("120")}, {UCHAR_CONSTANT("121")}, {UCHAR_CONSTANT("122")}, {UCHAR_CONSTANT("123")}, {UCHAR_CONSTANT("124")}, {UCHAR_CONSTANT("125")}, {UCHAR_CONSTANT("126")}, {UCHAR_CONSTANT("127")}, {UCHAR_CONSTANT("128")}, {UCHAR_CONSTANT("129")}, {UCHAR_CONSTANT("130")}, {UCHAR_CONSTANT("131")}, {UCHAR_CONSTANT("132")}, {UCHAR_CONSTANT("133")}, {UCHAR_CONSTANT("134")}, {UCHAR_CONSTANT("135")}, {UCHAR_CONSTANT("136")}, {UCHAR_CONSTANT("137")}, {UCHAR_CONSTANT("138")}, {UCHAR_CONSTANT("139")}, {UCHAR_CONSTANT("140")}, {UCHAR_CONSTANT("141")}, {UCHAR_CONSTANT("142")}, {UCHAR_CONSTANT("143")}, {UCHAR_CONSTANT("144")}, {UCHAR_CONSTANT("145")}, {UCHAR_CONSTANT("146")}, {UCHAR_CONSTANT("147")}, {UCHAR_CONSTANT("148")}, {UCHAR_CONSTANT("149")}, {UCHAR_CONSTANT("150")}, {UCHAR_CONSTANT("151")}, {UCHAR_CONSTANT("152")}, {UCHAR_CONSTANT("153")}, {UCHAR_CONSTANT("154")}, {UCHAR_CONSTANT("155")}, {UCHAR_CONSTANT("156")}, {UCHAR_CONSTANT("157")}, {UCHAR_CONSTANT("158")}, {UCHAR_CONSTANT("159")}, {UCHAR_CONSTANT("160")}, {UCHAR_CONSTANT("161")}, {UCHAR_CONSTANT("162")}, {UCHAR_CONSTANT("163")}, {UCHAR_CONSTANT("164")}, {UCHAR_CONSTANT("165")}, {UCHAR_CONSTANT("166")}, {UCHAR_CONSTANT("167")}, {UCHAR_CONSTANT("168")}, {UCHAR_CONSTANT("169")}, {UCHAR_CONSTANT("170")}, {UCHAR_CONSTANT("171")}, {UCHAR_CONSTANT("172")}, {UCHAR_CONSTANT("173")}, {UCHAR_CONSTANT("174")}, {UCHAR_CONSTANT("175")}, {UCHAR_CONSTANT("176")}, {UCHAR_CONSTANT("177")}, {UCHAR_CONSTANT("178")}, {UCHAR_CONSTANT("179")}, {UCHAR_CONSTANT("180")}, {UCHAR_CONSTANT("181")}, {UCHAR_CONSTANT("182")}, {UCHAR_CONSTANT("183")}, {UCHAR_CONSTANT("184")}, {UCHAR_CONSTANT("185")}, {UCHAR_CONSTANT("186")}, {UCHAR_CONSTANT("187")}, {UCHAR_CONSTANT("188")}, {UCHAR_CONSTANT("189")}, {UCHAR_CONSTANT("190")}, {UCHAR_CONSTANT("191")}, {UCHAR_CONSTANT("192")}, {UCHAR_CONSTANT("193")}, {UCHAR_CONSTANT("194")}, {UCHAR_CONSTANT("195")}, {UCHAR_CONSTANT("196")}, {UCHAR_CONSTANT("197")}, {UCHAR_CONSTANT("198")}, {UCHAR_CONSTANT("199")}}; static char hexdigit[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; #if defined(_AIX) /* AIXPORT : replace facility names with aso and caa only for AIX */ static const char *syslog_fac_names[LOG_NFACILITIES] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp", "aso", "audit", "alert", "caa", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7", "invld"}; /* length of the facility names string (for optimizatiions) */ static short len_syslog_fac_names[LOG_NFACILITIES] = {4, 4, 4, 6, 4, 6, 3, 4, 4, 4, 8, 3, 3, 5, 5, 3, 6, 6, 6, 6, 6, 6, 6, 6, 5}; #else /*syslog facility names (as of RFC5424) */ static const char *syslog_fac_names[LOG_NFACILITIES] = { "kern", "user", "mail", "daemon", "auth", "syslog", "lpr", "news", "uucp", "cron", "authpriv", "ftp", "ntp", "audit", "alert", "clock", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7", "invld"}; /* length of the facility names string (for optimizatiions) */ static short len_syslog_fac_names[LOG_NFACILITIES] = {4, 4, 4, 6, 4, 6, 3, 4, 4, 4, 8, 3, 3, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 5}; #endif /* table of severity names (in numerical order)*/ static const char *syslog_severity_names[8] = {"emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"}; static short len_syslog_severity_names[8] = {5, 5, 4, 3, 7, 6, 4, 5}; /* numerical values as string - this is the most efficient approach to convert severity * and facility values to a numerical string... -- rgerhars, 2009-06-17 */ static const char *syslog_number_names[LOG_NFACILITIES] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24"}; /* global variables */ #if defined(HAVE_MALLOC_TRIM) && !defined(HAVE_ATOMIC_BUILTINS) static pthread_mutex_t mutTrimCtr; /* mutex to handle malloc trim */ #endif /* some forward declarations */ static int getAPPNAMELen(smsg_t *const pM, sbool bLockMutex); static rsRetVal jsonPathFindParent( struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, int bCreate); static uchar *jsonPathGetLeaf(uchar *name, int lenName); static json_bool jsonVarExtract(struct json_object *root, const char *key, struct json_object **value); void getRawMsgAfterPRI(smsg_t *const pM, uchar **pBuf, int *piLen); /* the locking and unlocking implementations: */ void MsgLock(smsg_t *pThis) { #if DEV_DEBUG == 1 dbgprintf("MsgLock(0x%lx)\n", (unsigned long)pThis); #endif pthread_mutex_lock(&pThis->mut); } void MsgUnlock(smsg_t *pThis) { #if DEV_DEBUG == 1 dbgprintf("MsgUnlock(0x%lx)\n", (unsigned long)pThis); #endif pthread_mutex_unlock(&pThis->mut); } /* set RcvFromIP name in msg object WITHOUT calling AddRef. * rgerhards, 2013-01-22 */ static inline void MsgSetRcvFromIPWithoutAddRef(smsg_t *pThis, prop_t *new) { if (pThis->pRcvFromIP != NULL) prop.Destruct(&pThis->pRcvFromIP); pThis->pRcvFromIP = new; } static inline void MsgSetRcvFromPortWithoutAddRef(smsg_t *pThis, prop_t *new) { if (pThis->pRcvFromPort != NULL) prop.Destruct(&pThis->pRcvFromPort); pThis->pRcvFromPort = new; } /* set RcvFrom name in msg object WITHOUT calling AddRef. * rgerhards, 2013-01-22 */ static void MsgSetRcvFromWithoutAddRef(smsg_t *pThis, prop_t *new) { assert(pThis != NULL); if (pThis->msgFlags & NEEDS_DNSRESOL) { if (pThis->rcvFrom.pfrominet != NULL) free(pThis->rcvFrom.pfrominet); pThis->msgFlags &= ~NEEDS_DNSRESOL; } else { if (pThis->rcvFrom.pRcvFrom != NULL) prop.Destruct(&pThis->rcvFrom.pRcvFrom); } pThis->rcvFrom.pRcvFrom = new; } /* rgerhards 2012-04-18: set associated ruleset (by ruleset name) * pRuleset pointer inside msg is updated. If ruleset cannot be found, * no update is done and an error message emitted. */ rsRetVal ATTR_NONNULL() MsgSetRulesetByName(smsg_t *const pMsg, cstr_t *const rulesetName) { uchar *const rs_name = rsCStrGetSzStrNoNULL(rulesetName); const rsRetVal localRet = rulesetGetRuleset(runConf, &(pMsg->pRuleset), rs_name); if (localRet != RS_RET_OK) { LogError(0, localRet, "msg: ruleset '%s' could not be found and could not " "be assigned to message object. This possibly leads to the message " "being processed incorrectly. We cannot do anything against this, but " "wanted to let you know.", rs_name); } return localRet; } /* do a DNS reverse resolution, if not already done, reflect status * rgerhards, 2009-11-16 */ static rsRetVal resolveDNS(smsg_t *const pMsg) { rsRetVal localRet; prop_t *propFromHost = NULL; prop_t *ip = NULL; prop_t *localName = NULL; prop_t *port = NULL; char portbuf[8]; uint16_t pnum; const struct sockaddr_storage *pfrominet; DEFiRet; MsgLock(pMsg); CHKiRet(objUse(net, CORE_COMPONENT)); if (pMsg->msgFlags & NEEDS_DNSRESOL) { if (pMsg->msgFlags & PRESERVE_CASE) { localRet = net.cvthname(pMsg->rcvFrom.pfrominet, NULL, &localName, &ip); } else { localRet = net.cvthname(pMsg->rcvFrom.pfrominet, &localName, NULL, &ip); } if (localRet == RS_RET_OK) { pfrominet = pMsg->rcvFrom.pfrominet; if (pMsg->pRcvFromPort == NULL) { if (pfrominet != NULL && pfrominet->ss_family == AF_INET) pnum = ntohs(((const struct sockaddr_in *)pfrominet)->sin_port); else if (pfrominet != NULL && pfrominet->ss_family == AF_INET6) pnum = ntohs(((const struct sockaddr_in6 *)pfrominet)->sin6_port); else pnum = 0; snprintf(portbuf, sizeof(portbuf), "%u", pnum); CHKiRet(prop.CreateStringProp(&port, (uchar *)portbuf, strlen(portbuf))); MsgSetRcvFromPortWithoutAddRef(pMsg, port); port = NULL; } /* we pass down the props, so no need for AddRef */ MsgSetRcvFromWithoutAddRef(pMsg, localName); localName = NULL; MsgSetRcvFromIPWithoutAddRef(pMsg, ip); ip = NULL; } } finalize_it: if (iRet != RS_RET_OK) { /* best we can do: remove property */ MsgSetRcvFromStr(pMsg, UCHAR_CONSTANT(""), 0, &propFromHost); prop.Destruct(&propFromHost); } MsgUnlock(pMsg); if (propFromHost != NULL) prop.Destruct(&propFromHost); if (localName != NULL) prop.Destruct(&localName); if (ip != NULL) prop.Destruct(&ip); if (port != NULL) prop.Destruct(&port); RETiRet; } void getInputName(const smsg_t *const pM, uchar **ppsz, int *const plen) { if (pM == NULL || pM->pInputName == NULL) { *ppsz = UCHAR_CONSTANT(""); *plen = 0; } else { prop.GetString(pM->pInputName, ppsz, plen); } } uchar *getRcvFromIP(smsg_t *const pM) { uchar *psz; int len; if (pM == NULL) { psz = UCHAR_CONSTANT(""); } else { resolveDNS(pM); /* make sure we have a resolved entry */ if (pM->pRcvFromIP == NULL) psz = UCHAR_CONSTANT(""); else prop.GetString(pM->pRcvFromIP, &psz, &len); } return psz; } uchar *getRcvFromPort(smsg_t *const pM) { uchar *psz; int len; if (pM == NULL) { psz = UCHAR_CONSTANT(""); } else { resolveDNS(pM); if (pM->pRcvFromPort == NULL) psz = UCHAR_CONSTANT(""); else prop.GetString(pM->pRcvFromPort, &psz, &len); } return psz; } /* map a property name (string) to a property ID */ rsRetVal propNameToID(const uchar *const pName, propid_t *const pPropID) { DEFiRet; /* sometimes there are aliases to the original MonitoWare * property names. These come after || in the ifs below. */ if (!strcasecmp((char *)pName, "msg")) { *pPropID = PROP_MSG; } else if (!strcasecmp((char *)pName, "timestamp") || !strcasecmp((char *)pName, "timereported")) { *pPropID = PROP_TIMESTAMP; } else if (!strcasecmp((char *)pName, "hostname") || !strcasecmp((char *)pName, "source")) { *pPropID = PROP_HOSTNAME; } else if (!strcasecmp((char *)pName, "syslogtag")) { *pPropID = PROP_SYSLOGTAG; } else if (!strcasecmp((char *)pName, "rawmsg")) { *pPropID = PROP_RAWMSG; } else if (!strcasecmp((char *)pName, "rawmsg-after-pri")) { *pPropID = PROP_RAWMSG_AFTER_PRI; } else if (!strcasecmp((char *)pName, "inputname")) { *pPropID = PROP_INPUTNAME; } else if (!strcasecmp((char *)pName, "fromhost")) { *pPropID = PROP_FROMHOST; } else if (!strcasecmp((char *)pName, "fromhost-ip")) { *pPropID = PROP_FROMHOST_IP; } else if (!strcasecmp((char *)pName, "fromhost-port")) { *pPropID = PROP_FROMHOST_PORT; } else if (!strcasecmp((char *)pName, "pri")) { *pPropID = PROP_PRI; } else if (!strcasecmp((char *)pName, "pri-text")) { *pPropID = PROP_PRI_TEXT; } else if (!strcasecmp((char *)pName, "iut")) { *pPropID = PROP_IUT; } else if (!strcasecmp((char *)pName, "syslogfacility")) { *pPropID = PROP_SYSLOGFACILITY; } else if (!strcasecmp((char *)pName, "syslogfacility-text")) { *pPropID = PROP_SYSLOGFACILITY_TEXT; } else if (!strcasecmp((char *)pName, "syslogseverity") || !strcasecmp((char *)pName, "syslogpriority")) { *pPropID = PROP_SYSLOGSEVERITY; } else if (!strcasecmp((char *)pName, "syslogseverity-text") || !strcasecmp((char *)pName, "syslogpriority-text")) { *pPropID = PROP_SYSLOGSEVERITY_TEXT; } else if (!strcasecmp((char *)pName, "timegenerated") || !strcasecmp((char *)pName, "timereceived")) { *pPropID = PROP_TIMEGENERATED; } else if (!strcasecmp((char *)pName, "programname")) { *pPropID = PROP_PROGRAMNAME; } else if (!strcasecmp((char *)pName, "protocol-version")) { *pPropID = PROP_PROTOCOL_VERSION; } else if (!strcasecmp((char *)pName, "structured-data")) { *pPropID = PROP_STRUCTURED_DATA; } else if (!strcasecmp((char *)pName, "app-name")) { *pPropID = PROP_APP_NAME; } else if (!strcasecmp((char *)pName, "procid")) { *pPropID = PROP_PROCID; } else if (!strcasecmp((char *)pName, "msgid")) { *pPropID = PROP_MSGID; } else if (!strcasecmp((char *)pName, "jsonmesg")) { *pPropID = PROP_JSONMESG; } else if (!strcasecmp((char *)pName, "parsesuccess")) { *pPropID = PROP_PARSESUCCESS; #ifdef USE_LIBUUID } else if (!strcasecmp((char *)pName, "uuid")) { *pPropID = PROP_UUID; #endif /* here start system properties (those, that do not relate to the message itself */ } else if (!strcasecmp((char *)pName, "$NOW")) { *pPropID = PROP_SYS_NOW; } else if (!strcasecmp((char *)pName, "$YEAR")) { *pPropID = PROP_SYS_YEAR; } else if (!strcasecmp((char *)pName, "$MONTH")) { *pPropID = PROP_SYS_MONTH; } else if (!strcasecmp((char *)pName, "$DAY")) { *pPropID = PROP_SYS_DAY; } else if (!strcasecmp((char *)pName, "$HOUR")) { *pPropID = PROP_SYS_HOUR; } else if (!strcasecmp((char *)pName, "$HHOUR")) { *pPropID = PROP_SYS_HHOUR; } else if (!strcasecmp((char *)pName, "$QHOUR")) { *pPropID = PROP_SYS_QHOUR; } else if (!strcasecmp((char *)pName, "$MINUTE")) { *pPropID = PROP_SYS_MINUTE; } else if (!strcasecmp((char *)pName, "$WDAY")) { *pPropID = PROP_SYS_WDAY; } else if (!strcasecmp((char *)pName, "$now-utc")) { *pPropID = PROP_SYS_NOW_UTC; } else if (!strcasecmp((char *)pName, "$year-utc")) { *pPropID = PROP_SYS_YEAR_UTC; } else if (!strcasecmp((char *)pName, "$month-utc")) { *pPropID = PROP_SYS_MONTH_UTC; } else if (!strcasecmp((char *)pName, "$day-utc")) { *pPropID = PROP_SYS_DAY_UTC; } else if (!strcasecmp((char *)pName, "$hour-utc")) { *pPropID = PROP_SYS_HOUR_UTC; } else if (!strcasecmp((char *)pName, "$hhour-utc")) { *pPropID = PROP_SYS_HHOUR_UTC; } else if (!strcasecmp((char *)pName, "$qhour-utc")) { *pPropID = PROP_SYS_QHOUR_UTC; } else if (!strcasecmp((char *)pName, "$minute-utc")) { *pPropID = PROP_SYS_MINUTE_UTC; } else if (!strcasecmp((char *)pName, "$wday-utc")) { *pPropID = PROP_SYS_WDAY_UTC; } else if (!strcasecmp((char *)pName, "$now-unixtimestamp")) { *pPropID = PROP_SYS_NOW_UXTIMESTAMP; } else if (!strcasecmp((char *)pName, "$MYHOSTNAME")) { *pPropID = PROP_SYS_MYHOSTNAME; } else if (!strcasecmp((char *)pName, "$!all-json")) { *pPropID = PROP_CEE_ALL_JSON; } else if (!strcasecmp((char *)pName, "$!all-json-plain")) { *pPropID = PROP_CEE_ALL_JSON_PLAIN; } else if (!strcasecmp((char *)pName, "$BOM")) { *pPropID = PROP_SYS_BOM; } else if (!strcasecmp((char *)pName, "$UPTIME")) { *pPropID = PROP_SYS_UPTIME; } else if (!strncmp((char *)pName, "$!", 2) || pName[0] == '!') { *pPropID = PROP_CEE; } else if (!strncmp((char *)pName, "$.", 2) || pName[0] == '.') { *pPropID = PROP_LOCAL_VAR; } else if (!strncmp((char *)pName, "$/", 2) || pName[0] == '/') { *pPropID = PROP_GLOBAL_VAR; } else { DBGPRINTF("PROP_INVALID for name '%s'\n", pName); *pPropID = PROP_INVALID; iRet = RS_RET_VAR_NOT_FOUND; } RETiRet; } /* map a property ID to a name string (useful for displaying) */ uchar *propIDToName(propid_t propID) { switch (propID) { case PROP_MSG: return UCHAR_CONSTANT("msg"); case PROP_TIMESTAMP: return UCHAR_CONSTANT("timestamp"); case PROP_HOSTNAME: return UCHAR_CONSTANT("hostname"); case PROP_SYSLOGTAG: return UCHAR_CONSTANT("syslogtag"); case PROP_RAWMSG: return UCHAR_CONSTANT("rawmsg"); case PROP_RAWMSG_AFTER_PRI: return UCHAR_CONSTANT("rawmsg-after-pri"); case PROP_INPUTNAME: return UCHAR_CONSTANT("inputname"); case PROP_FROMHOST: return UCHAR_CONSTANT("fromhost"); case PROP_FROMHOST_IP: return UCHAR_CONSTANT("fromhost-ip"); case PROP_FROMHOST_PORT: return UCHAR_CONSTANT("fromhost-port"); case PROP_PRI: return UCHAR_CONSTANT("pri"); case PROP_PRI_TEXT: return UCHAR_CONSTANT("pri-text"); case PROP_IUT: return UCHAR_CONSTANT("iut"); case PROP_SYSLOGFACILITY: return UCHAR_CONSTANT("syslogfacility"); case PROP_SYSLOGFACILITY_TEXT: return UCHAR_CONSTANT("syslogfacility-text"); case PROP_SYSLOGSEVERITY: return UCHAR_CONSTANT("syslogseverity"); case PROP_SYSLOGSEVERITY_TEXT: return UCHAR_CONSTANT("syslogseverity-text"); case PROP_TIMEGENERATED: return UCHAR_CONSTANT("timegenerated"); case PROP_PROGRAMNAME: return UCHAR_CONSTANT("programname"); case PROP_PROTOCOL_VERSION: return UCHAR_CONSTANT("protocol-version"); case PROP_STRUCTURED_DATA: return UCHAR_CONSTANT("structured-data"); case PROP_APP_NAME: return UCHAR_CONSTANT("app-name"); case PROP_PROCID: return UCHAR_CONSTANT("procid"); case PROP_MSGID: return UCHAR_CONSTANT("msgid"); case PROP_JSONMESG: return UCHAR_CONSTANT("jsonmesg"); case PROP_PARSESUCCESS: return UCHAR_CONSTANT("parsesuccess"); #ifdef USE_LIBUUID case PROP_UUID: return UCHAR_CONSTANT("uuid"); #endif case PROP_SYS_NOW: return UCHAR_CONSTANT("$NOW"); case PROP_SYS_YEAR: return UCHAR_CONSTANT("$YEAR"); case PROP_SYS_MONTH: return UCHAR_CONSTANT("$MONTH"); case PROP_SYS_DAY: return UCHAR_CONSTANT("$DAY"); case PROP_SYS_HOUR: return UCHAR_CONSTANT("$HOUR"); case PROP_SYS_HHOUR: return UCHAR_CONSTANT("$HHOUR"); case PROP_SYS_QHOUR: return UCHAR_CONSTANT("$QHOUR"); case PROP_SYS_MINUTE: return UCHAR_CONSTANT("$MINUTE"); case PROP_SYS_NOW_UTC: return UCHAR_CONSTANT("$NOW-UTC"); case PROP_SYS_YEAR_UTC: return UCHAR_CONSTANT("$YEAR-UTC"); case PROP_SYS_MONTH_UTC: return UCHAR_CONSTANT("$MONTH-UTC"); case PROP_SYS_DAY_UTC: return UCHAR_CONSTANT("$DAY-UTC"); case PROP_SYS_HOUR_UTC: return UCHAR_CONSTANT("$HOUR-UTC"); case PROP_SYS_HHOUR_UTC: return UCHAR_CONSTANT("$HHOUR-UTC"); case PROP_SYS_QHOUR_UTC: return UCHAR_CONSTANT("$QHOUR-UTC"); case PROP_SYS_MINUTE_UTC: return UCHAR_CONSTANT("$MINUTE-UTC"); case PROP_SYS_WDAY: return UCHAR_CONSTANT("$WDAY"); case PROP_SYS_WDAY_UTC: return UCHAR_CONSTANT("$WDAY-UTC"); case PROP_SYS_NOW_UXTIMESTAMP: return UCHAR_CONSTANT("$NOW-UNIXTIMESTAMP"); case PROP_SYS_MYHOSTNAME: return UCHAR_CONSTANT("$MYHOSTNAME"); case PROP_CEE_ALL_JSON: return UCHAR_CONSTANT("$!all-json"); case PROP_CEE_ALL_JSON_PLAIN: return UCHAR_CONSTANT("$!all-json-plain"); case PROP_SYS_BOM: return UCHAR_CONSTANT("$BOM"); case PROP_SYS_UPTIME: return UCHAR_CONSTANT("$UPTIME"); case PROP_CEE: return UCHAR_CONSTANT("*CEE-based property*"); case PROP_LOCAL_VAR: return UCHAR_CONSTANT("*LOCAL_VARIABLE*"); case PROP_GLOBAL_VAR: return UCHAR_CONSTANT("*GLOBAL_VARIABLE*"); default: return UCHAR_CONSTANT("*invalid property id*"); } } /* This is common code for all Constructors. It is defined in an * inline'able function so that we can save a function call in the * actual constructors (otherwise, the msgConstruct would need * to call msgConstructWithTime(), which would require a * function call). Now, both can use this inline function. This * enables us to be optimal, but still have the code just once. * the new object or NULL if no such object could be allocated. * An object constructed via this function should only be destroyed * via "msgDestruct()". This constructor does not query system time * itself but rather uses a user-supplied value. This enables the caller * to do some tricks to save processing time (done, for example, in the * udp input). * NOTE: this constructor does NOT call calloc(), as we have many bytes * inside the structure which do not need to be cleared. bzero() will * heavily thrash the cache, so we do the init manually (which also * is the right thing to do with pointers, as they are not neccessarily * a binary 0 on all machines [but today almost always...]). * rgerhards, 2008-10-06 */ static rsRetVal msgBaseConstruct(smsg_t **ppThis) { DEFiRet; smsg_t *pM; assert(ppThis != NULL); CHKmalloc(pM = malloc(sizeof(smsg_t))); objConstructSetObjInfo(pM); /* initialize object helper entities */ /* initialize members in ORDER they appear in structure (think "cache line"!) */ pM->flowCtlType = 0; pM->bParseSuccess = 0; pM->iRefCount = 1; pM->iSeverity = LOG_DEBUG; pM->iFacility = LOG_INVLD; pM->iLenPROGNAME = -1; pM->offAfterPRI = 0; pM->offMSG = -1; pM->iProtocolVersion = 0; pM->msgFlags = 0; pM->iLenRawMsg = 0; pM->iLenMSG = 0; pM->iLenTAG = 0; pM->iLenHOSTNAME = 0; pM->pszRawMsg = NULL; pM->pszHOSTNAME = NULL; pM->pszRcvdAt3164 = NULL; pM->pszRcvdAt3339 = NULL; pM->pszRcvdAt_MySQL = NULL; pM->pszRcvdAt_PgSQL = NULL; pM->pszTIMESTAMP3164 = NULL; pM->pszTIMESTAMP3339 = NULL; pM->pszTIMESTAMP_MySQL = NULL; pM->pszTIMESTAMP_PgSQL = NULL; pM->pszStrucData = NULL; pM->lenStrucData = 0; pM->pCSAPPNAME = NULL; pM->pCSPROCID = NULL; pM->pCSMSGID = NULL; pM->pInputName = NULL; pM->pRcvFromIP = NULL; pM->pRcvFromPort = NULL; pM->rcvFrom.pRcvFrom = NULL; pM->pRuleset = NULL; pM->json = NULL; pM->localvars = NULL; #ifdef HAVE_LOGNORM_TURBO pM->turbo_result = NULL; pM->turbo_result_free = NULL; pM->turbo_result_to_json = NULL; pM->turbo_result_get_str = NULL; pM->turbo_result_refs = NULL; #endif pM->dfltTZ[0] = '\0'; memset(&pM->tRcvdAt, 0, sizeof(pM->tRcvdAt)); memset(&pM->tTIMESTAMP, 0, sizeof(pM->tTIMESTAMP)); pM->TAG.pszTAG = NULL; pM->pszTimestamp3164[0] = '\0'; pM->pszTimestamp3339[0] = '\0'; pM->pszTIMESTAMP_SecFrac[0] = '\0'; pM->pszRcvdAt_SecFrac[0] = '\0'; pM->pszTIMESTAMP_Unix[0] = '\0'; pM->pszRcvdAt_Unix[0] = '\0'; pM->pszUUID = NULL; pthread_mutex_init(&pM->mut, NULL); #if DEV_DEBUG == 1 dbgprintf("msgConstruct\t0x%x, ref 1\n", (int)pM); #endif *ppThis = pM; finalize_it: RETiRet; } /* "Constructor" for a msg "object". Returns a pointer to * the new object or NULL if no such object could be allocated. * An object constructed via this function should only be destroyed * via "msgDestruct()". This constructor does not query system time * itself but rather uses a user-supplied value. This enables the caller * to do some tricks to save processing time (done, for example, in the * udp input). * rgerhards, 2008-10-06 */ rsRetVal msgConstructWithTime(smsg_t **ppThis, const struct syslogTime *stTime, const time_t ttGenTime) { DEFiRet; CHKiRet(msgBaseConstruct(ppThis)); (*ppThis)->ttGenTime = ttGenTime; memcpy(&(*ppThis)->tRcvdAt, stTime, sizeof(struct syslogTime)); memcpy(&(*ppThis)->tTIMESTAMP, stTime, sizeof(struct syslogTime)); finalize_it: RETiRet; } /* "Constructor" for a msg "object". Returns a pointer to * the new object or NULL if no such object could be allocated. * An object constructed via this function should only be destroyed * via "msgDestruct()". This constructor, for historical reasons, * also sets the two timestamps to the current time. */ rsRetVal msgConstruct(smsg_t **ppThis) { DEFiRet; CHKiRet(msgBaseConstruct(ppThis)); /* we initialize both timestamps to contain the current time, so that they * are consistent. Also, this saves us from doing any further time calls just * to obtain a timestamp. The memcpy() should not really make a difference, * especially as I think there is no codepath currently where it would not be * required (after I have cleaned up the pathes ;)). -- rgerhards, 2008-10-02 */ datetime.getCurrTime(&((*ppThis)->tRcvdAt), &((*ppThis)->ttGenTime), TIME_IN_LOCALTIME); memcpy(&(*ppThis)->tTIMESTAMP, &(*ppThis)->tRcvdAt, sizeof(struct syslogTime)); finalize_it: RETiRet; } /* Special msg constructor, to be used when an object is deserialized. * we do only the base init as we know the properties will be set in * any case by the deserializer. We still do the "inexpensive" inits * just to be on the safe side. The whole process needs to be * refactored together with the msg serialization subsystem. */ rsRetVal msgConstructForDeserializer(smsg_t **ppThis) { return msgBaseConstruct(ppThis); } /* some free handlers for (slightly) complicated cases... All of them may be called * with an empty element. */ static inline void freeTAG(smsg_t *pThis) { if (pThis->iLenTAG >= CONF_TAG_BUFSIZE) free(pThis->TAG.pszTAG); } static inline void freeHOSTNAME(smsg_t *pThis) { if (pThis->iLenHOSTNAME >= CONF_HOSTNAME_BUFSIZE) free(pThis->pszHOSTNAME); } #ifdef HAVE_LOGNORM_TURBO /* Release one reference on the turbo parse snapshot and clear this message's * slot. refs == NULL means sole ownership (the message was never duplicated): * free directly, no atomics. Otherwise the counter is shared across MsgDup() * copies and the last owner out frees both the snapshot and the counter. */ void MsgReleaseTurboResult(smsg_t *const pMsg) { if (pMsg->turbo_result != NULL && pMsg->turbo_result_free != NULL) { if (pMsg->turbo_result_refs == NULL) { pMsg->turbo_result_free(pMsg->turbo_result); } else if (__atomic_sub_fetch(pMsg->turbo_result_refs, 1, __ATOMIC_ACQ_REL) == 0) { pMsg->turbo_result_free(pMsg->turbo_result); free(pMsg->turbo_result_refs); } } pMsg->turbo_result = NULL; pMsg->turbo_result_free = NULL; pMsg->turbo_result_to_json = NULL; pMsg->turbo_result_get_str = NULL; pMsg->turbo_result_refs = NULL; } #endif rsRetVal msgDestruct(smsg_t **ppThis) { DEFiRet; smsg_t *pThis; int currRefCount; #ifdef HAVE_MALLOC_TRIM int currCnt; #endif CODESTARTobjDestruct(msg); #if DEV_DEBUG == 1 dbgprintf( "msgDestruct\t0x%lx, " "Ref now: %d\n", (unsigned long)pThis, pThis->iRefCount - 1); #endif #ifdef HAVE_ATOMIC_BUILTINS currRefCount = ATOMIC_DEC_AND_FETCH(&pThis->iRefCount, NULL); #else MsgLock(pThis); currRefCount = --pThis->iRefCount; #endif if (currRefCount == 0) { #if DEV_DEBUG == 1 dbgprintf("msgDestruct\t0x%lx, RefCount now 0, doing DESTROY\n", (unsigned long)pThis); #endif if (pThis->pszRawMsg != pThis->szRawMsg) free(pThis->pszRawMsg); freeTAG(pThis); freeHOSTNAME(pThis); if (pThis->pInputName != NULL) prop.Destruct(&pThis->pInputName); if ((pThis->msgFlags & NEEDS_DNSRESOL) == 0) { if (pThis->rcvFrom.pRcvFrom != NULL) prop.Destruct(&pThis->rcvFrom.pRcvFrom); } else { free(pThis->rcvFrom.pfrominet); } if (pThis->pRcvFromIP != NULL) prop.Destruct(&pThis->pRcvFromIP); if (pThis->pRcvFromPort != NULL) prop.Destruct(&pThis->pRcvFromPort); free(pThis->pszRcvdAt3164); free(pThis->pszRcvdAt3339); free(pThis->pszRcvdAt_MySQL); free(pThis->pszRcvdAt_PgSQL); free(pThis->pszTIMESTAMP_MySQL); free(pThis->pszTIMESTAMP_PgSQL); free(pThis->pszStrucData); if (pThis->iLenPROGNAME >= CONF_PROGNAME_BUFSIZE) free(pThis->PROGNAME.ptr); if (pThis->pCSAPPNAME != NULL) rsCStrDestruct(&pThis->pCSAPPNAME); if (pThis->pCSPROCID != NULL) rsCStrDestruct(&pThis->pCSPROCID); if (pThis->pCSMSGID != NULL) rsCStrDestruct(&pThis->pCSMSGID); if (pThis->json != NULL) json_object_put(pThis->json); if (pThis->localvars != NULL) json_object_put(pThis->localvars); #ifdef HAVE_LOGNORM_TURBO MsgReleaseTurboResult(pThis); #endif if (pThis->pszUUID != NULL) free(pThis->pszUUID); #ifndef HAVE_ATOMIC_BUILTINS MsgUnlock(pThis); #endif pthread_mutex_destroy(&pThis->mut); /* now we need to do our own optimization. Testing has shown that at least the glibc * malloc() subsystem returns memory to the OS far too late in our case. So we need * to help it a bit, by calling malloc_trim(), which will tell the alloc subsystem * to consolidate and return to the OS. We keep 128K for our use, as a safeguard * to too-frequent reallocs. But more importantly, we call this hook only every * 100,000 messages (which is an approximation, as we do not work with atomic * operations on the counter. --- rgerhards, 2009-06-22. */ #ifdef HAVE_MALLOC_TRIM { /* standard C requires a new block for a new variable definition! * To simplify matters, we use modulo arithmetic and live with the fact * that we trim too often when the counter wraps. */ static unsigned iTrimCtr = 1; currCnt = ATOMIC_INC_AND_FETCH_unsigned(&iTrimCtr, &mutTrimCtr); if (currCnt % 100000 == 0) { malloc_trim(128 * 1024); } } #endif } else { #ifndef HAVE_ATOMIC_BUILTINS MsgUnlock(pThis); #endif pThis = NULL; /* tell framework not to destructing the object! */ } ENDobjDestruct (msg) /* The macros below are used in MsgDup(). I use macros * to keep the fuction code somewhat more readyble. It is my * replacement for inline functions in CPP */ #define tmpCOPYSZ(name) \ if (pOld->psz##name != NULL) { \ if ((pNew->psz##name = srUtilStrDup(pOld->psz##name, pOld->iLen##name)) == NULL) { \ msgDestruct(&pNew); \ return NULL; \ } \ pNew->iLen##name = pOld->iLen##name; \ } /* copy the CStr objects. * if the old value is NULL, we do not need to do anything because we * initialized the new value to NULL via calloc(). */ #define tmpCOPYCSTR(name) \ if (pOld->pCS##name != NULL) { \ if (rsCStrConstructFromCStr(&(pNew->pCS##name), pOld->pCS##name) != RS_RET_OK) { \ msgDestruct(&pNew); \ return NULL; \ } \ cstrFinalize(pNew->pCS##name); \ } /* Constructs a message object by duplicating another one. * Returns NULL if duplication failed. Most message fields are immutable * after construction. The JSON and turbo snapshot fields are mutable, so * they are copied coherently under the source message lock below. */ smsg_t *MsgDup(smsg_t *pOld) { smsg_t *pNew; rsRetVal localRet; assert(pOld != NULL); if (msgConstructWithTime(&pNew, &pOld->tTIMESTAMP, pOld->ttGenTime) != RS_RET_OK) { return NULL; } /* now copy the message properties */ pNew->iRefCount = 1; pNew->iSeverity = pOld->iSeverity; pNew->iFacility = pOld->iFacility; pNew->msgFlags = pOld->msgFlags; pNew->iProtocolVersion = pOld->iProtocolVersion; pNew->tRcvdAt = pOld->tRcvdAt; pNew->offMSG = pOld->offMSG; pNew->iLenRawMsg = pOld->iLenRawMsg; pNew->iLenMSG = pOld->iLenMSG; pNew->iLenTAG = pOld->iLenTAG; pNew->iLenHOSTNAME = pOld->iLenHOSTNAME; if ((pOld->msgFlags & NEEDS_DNSRESOL)) { localRet = msgSetFromSockinfo(pNew, pOld->rcvFrom.pfrominet); if (localRet != RS_RET_OK) { /* if something fails, we accept loss of this property, it is * better than losing the whole message. */ pNew->msgFlags &= ~NEEDS_DNSRESOL; pNew->rcvFrom.pRcvFrom = NULL; /* make sure no dangling values */ } } else { if (pOld->rcvFrom.pRcvFrom != NULL) { pNew->rcvFrom.pRcvFrom = pOld->rcvFrom.pRcvFrom; prop.AddRef(pNew->rcvFrom.pRcvFrom); } } if (pOld->pRcvFromIP != NULL) { pNew->pRcvFromIP = pOld->pRcvFromIP; prop.AddRef(pNew->pRcvFromIP); } if (pOld->pRcvFromPort != NULL) { pNew->pRcvFromPort = pOld->pRcvFromPort; prop.AddRef(pNew->pRcvFromPort); } if (pOld->pInputName != NULL) { pNew->pInputName = pOld->pInputName; prop.AddRef(pNew->pInputName); } if (pOld->iLenTAG > 0) { if (pOld->iLenTAG < CONF_TAG_BUFSIZE) { memcpy(pNew->TAG.szBuf, pOld->TAG.szBuf, pOld->iLenTAG + 1); } else { if ((pNew->TAG.pszTAG = srUtilStrDup(pOld->TAG.pszTAG, pOld->iLenTAG)) == NULL) { msgDestruct(&pNew); return NULL; } pNew->iLenTAG = pOld->iLenTAG; } } if (pOld->pszRawMsg == pOld->szRawMsg) { memcpy(pNew->szRawMsg, pOld->szRawMsg, pOld->iLenRawMsg + 1); pNew->pszRawMsg = pNew->szRawMsg; } else { tmpCOPYSZ(RawMsg); } if (pOld->pszHOSTNAME == NULL) { pNew->pszHOSTNAME = NULL; } else { if (pOld->iLenHOSTNAME < CONF_HOSTNAME_BUFSIZE) { memcpy(pNew->szHOSTNAME, pOld->szHOSTNAME, pOld->iLenHOSTNAME + 1); pNew->pszHOSTNAME = pNew->szHOSTNAME; } else { tmpCOPYSZ(HOSTNAME); } } if (pOld->pszStrucData == NULL) { pNew->pszStrucData = NULL; } else { pNew->pszStrucData = (uchar *)strdup((char *)pOld->pszStrucData); pNew->lenStrucData = pOld->lenStrucData; } tmpCOPYCSTR(APPNAME); tmpCOPYCSTR(PROCID); tmpCOPYCSTR(MSGID); MsgLock(pOld); #ifdef HAVE_LOGNORM_TURBO /* Share the turbo parse snapshot with the duplicate. The snapshot is * immutable after parsing, so copies may read it concurrently; ownership * is tracked by a lazily-allocated shared counter (see msg.h). The source * message lock serializes first-counter publication and makes the JSON and * lazy-callback snapshot coherent. On counter allocation failure, * materialize the source while locked so the duplicate still receives the * normalized fields through its deep-copied $! tree. */ if (pOld->turbo_result != NULL) { if (pOld->turbo_result_refs == NULL) { unsigned *refs = malloc(sizeof(*refs)); if (refs != NULL) { *refs = 2; /* pOld + pNew */ pOld->turbo_result_refs = refs; } else if (!msgMaterializeTurboJSON(pOld)) { /* A second allocation failure means neither shared snapshot * ownership nor a complete JSON copy can be established. */ MsgUnlock(pOld); msgDestruct(&pNew); return NULL; } } else { __atomic_add_fetch(pOld->turbo_result_refs, 1, __ATOMIC_RELAXED); } if (pOld->turbo_result_refs != NULL) { pNew->turbo_result = pOld->turbo_result; pNew->turbo_result_free = pOld->turbo_result_free; pNew->turbo_result_to_json = pOld->turbo_result_to_json; pNew->turbo_result_get_str = pOld->turbo_result_get_str; pNew->turbo_result_refs = pOld->turbo_result_refs; } } #endif if (pOld->json != NULL) pNew->json = jsonDeepCopy(pOld->json); if (pOld->localvars != NULL) pNew->localvars = jsonDeepCopy(pOld->localvars); MsgUnlock(pOld); /* we do not copy all other cache properties, as we do not even know * if they are needed once again. So we let them re-create if needed. */ return pNew; } #undef tmpCOPYSZ #undef tmpCOPYCSTR /* Return a textual representation of @json. * * The pointer is owned by @json; do NOT free it. * To keep the string beyond the next mutation, serialization call, * or destruction of @json, make a copy (e.g., strdup()). */ static const char *jsonToString(struct json_object *const json) { if (!json) { return NULL; } if (json_object_get_type(json) == json_type_string) { /* Direct pointer to internal string storage. * - Stable across repeated json_object_get_string() calls. * - Invalidated once the object is modified or fjson_object_put(). */ return json_object_get_string(json); } /* Non-string types serialize into json->_pb. * - json->_pb is reset/overwritten on every serialization or mutation. * - The returned pointer becomes invalid immediately after that. */ return json_object_to_json_string_ext(json, glblJsonFormatOpt); } /* This method serializes a message object. That means the whole * object is modified into text form. That text form is suitable for * later reconstruction of the object by calling MsgDeSerialize(). * The most common use case for this method is the creation of an * on-disk representation of the message object. * We do not serialize the cache properties. We re-create them when needed. * This saves us a lot of memory. Performance is no concern, as serializing * is a so slow operation that recration of the caches does not count. Also, * we do not serialize --currently none--, as this is only a helper variable * during msg construction - and never again used later. * rgerhards, 2008-01-03 */ static rsRetVal MsgSerialize(smsg_t *pThis, strm_t *pStrm) { uchar *psz; int len; DEFiRet; assert(pThis != NULL); assert(pStrm != NULL); #ifdef HAVE_LOGNORM_TURBO /* Disk queues persist JSON, not the opaque module-owned snapshot. */ MsgLock(pThis); const int materialized = msgMaterializeTurboJSON(pThis); MsgUnlock(pThis); if (!materialized) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); #endif /* then serialize elements */ CHKiRet(obj.BeginSerialize(pStrm, (obj_t *)pThis)); objSerializeSCALAR(pStrm, iProtocolVersion, SHORT); objSerializeSCALAR(pStrm, iSeverity, SHORT); objSerializeSCALAR(pStrm, iFacility, SHORT); objSerializeSCALAR(pStrm, msgFlags, INT); objSerializeSCALAR(pStrm, ttGenTime, INT); objSerializeSCALAR(pStrm, tRcvdAt, SYSLOGTIME); objSerializeSCALAR(pStrm, tTIMESTAMP, SYSLOGTIME); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszTAG"), PROPTYPE_PSZ, (void *)((pThis->iLenTAG < CONF_TAG_BUFSIZE) ? pThis->TAG.szBuf : pThis->TAG.pszTAG))); objSerializePTR(pStrm, pszRawMsg, PSZ); objSerializePTR(pStrm, pszHOSTNAME, PSZ); getInputName(pThis, &psz, &len); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszInputName"), PROPTYPE_PSZ, (void *)psz)); psz = getRcvFrom(pThis); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFrom"), PROPTYPE_PSZ, (void *)psz)); psz = getRcvFromIP(pThis); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRcvFromIP"), PROPTYPE_PSZ, (void *)psz)); psz = pThis->pszStrucData; CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszStrucData"), PROPTYPE_PSZ, (void *)psz)); if (pThis->json != NULL) { MsgLock(pThis); psz = (uchar *)jsonToString(pThis->json); MsgUnlock(pThis); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("json"), PROPTYPE_PSZ, (void *)psz)); } if (pThis->localvars != NULL) { MsgLock(pThis); psz = (uchar *)jsonToString(pThis->localvars); MsgUnlock(pThis); CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("localvars"), PROPTYPE_PSZ, (void *)psz)); } objSerializePTR(pStrm, pCSAPPNAME, CSTR); objSerializePTR(pStrm, pCSPROCID, CSTR); objSerializePTR(pStrm, pCSMSGID, CSTR); objSerializePTR(pStrm, pszUUID, PSZ); if (pThis->pRuleset != NULL) { CHKiRet(obj.SerializeProp(pStrm, UCHAR_CONSTANT("pszRuleset"), PROPTYPE_PSZ, rulesetGetName(pThis->pRuleset))); } /* offset must be serialized after pszRawMsg, because we need that to obtain the correct * MSG size. */ objSerializeSCALAR(pStrm, offMSG, INT); CHKiRet(obj.EndSerialize(pStrm)); finalize_it: RETiRet; } /* This is a helper for MsgDeserialize that re-inits the var object. This * whole construct should be replaced, var is really ready to be retired. * But as an interim help during refactoring let's introduce this function * here (and thus NOT as method of var object!). -- rgerhads, 2012-11-06 */ static void reinitVar(var_t *pVar) { rsCStrDestruct(&pVar->pcsName); /* no longer needed */ if (pVar->varType == VARTYPE_STR) { rsCStrDestruct(&pVar->val.pStr); } memset(&pVar->val, 0, sizeof(pVar->val)); pVar->varType = VARTYPE_NONE; } /* deserialize the message again * we deserialize the properties in the same order that we serialized them. Except * for some checks to cover downlevel version, we do not need to do all these * CPU intense name checkings. */ #define isProp(name) !rsCStrSzStrCmp(pVar->pcsName, (uchar *)name, sizeof(name) - 1) rsRetVal MsgDeserialize(smsg_t *const pMsg, strm_t *pStrm) { prop_t *myProp; prop_t *propRcvFrom = NULL; prop_t *propRcvFromIP = NULL; struct json_tokener *tokener; var_t *pVar = NULL; DEFiRet; ISOBJ_TYPE_assert(pStrm, strm); CHKiRet(var.Construct(&pVar)); CHKiRet(var.ConstructFinalize(pVar)); CHKiRet(objDeserializeProperty(pVar, pStrm)); if (isProp("iProtocolVersion")) { setProtocolVersion(pMsg, pVar->val.num); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("iSeverity")) { pMsg->iSeverity = pVar->val.num; reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("iFacility")) { pMsg->iFacility = pVar->val.num; reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("msgFlags")) { pMsg->msgFlags = pVar->val.num; reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("ttGenTime")) { pMsg->ttGenTime = pVar->val.num; reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("tRcvdAt")) { memcpy(&pMsg->tRcvdAt, &pVar->val.vSyslogTime, sizeof(struct syslogTime)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("tTIMESTAMP")) { memcpy(&pMsg->tTIMESTAMP, &pVar->val.vSyslogTime, sizeof(struct syslogTime)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszTAG")) { MsgSetTAG(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszRawMsg")) { MsgSetRawMsg(pMsg, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszHOSTNAME")) { MsgSetHOSTNAME(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszInputName")) { /* we need to create a property */ CHKiRet(prop.Construct(&myProp)); CHKiRet(prop.SetString(myProp, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr))); CHKiRet(prop.ConstructFinalize(myProp)); MsgSetInputName(pMsg, myProp); prop.Destruct(&myProp); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszRcvFrom")) { MsgSetRcvFromStr(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr), &propRcvFrom); prop.Destruct(&propRcvFrom); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszRcvFromIP")) { MsgSetRcvFromIPStr(pMsg, rsCStrGetSzStrNoNULL(pVar->val.pStr), rsCStrLen(pVar->val.pStr), &propRcvFromIP); prop.Destruct(&propRcvFromIP); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszStrucData")) { MsgSetStructuredData(pMsg, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("json")) { tokener = json_tokener_new(); pMsg->json = json_tokener_parse_ex(tokener, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr)); json_tokener_free(tokener); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("localvars")) { tokener = json_tokener_new(); pMsg->localvars = json_tokener_parse_ex(tokener, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr), cstrLen(pVar->val.pStr)); json_tokener_free(tokener); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pCSAPPNAME")) { MsgSetAPPNAME(pMsg, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pCSPROCID")) { MsgSetPROCID(pMsg, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pCSMSGID")) { MsgSetMSGID(pMsg, (char *)rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszUUID")) { pMsg->pszUUID = ustrdup(rsCStrGetSzStrNoNULL(pVar->val.pStr)); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } if (isProp("pszRuleset")) { MsgSetRulesetByName(pMsg, pVar->val.pStr); reinitVar(pVar); CHKiRet(objDeserializeProperty(pVar, pStrm)); } /* "offMSG" must always be our last field, so we use this as an * indicator if the sequence is correct. This is a bit questionable, * but on the other hand it works decently AND we will probably replace * the whole persisted format soon in any case. -- rgerhards, 2012-11-06 */ if (!isProp("offMSG")) { DBGPRINTF("error property: %s\n", rsCStrGetSzStrNoNULL(pVar->pcsName)); ABORT_FINALIZE(RS_RET_DS_PROP_SEQ_ERR); } MsgSetMSGoffs(pMsg, pVar->val.num); finalize_it: if (pVar != NULL) var.Destruct(&pVar); if (Debug && iRet != RS_RET_OK) { dbgprintf("MsgDeserialize error %d\n", iRet); } RETiRet; } #undef isProp /* Increment reference count - see description of the "msg" * structure for details. As a convenience to developers, * this method returns the msg pointer that is passed to it. * It is recommended that it is called as follows: * * pSecondMsgPointer = MsgAddRef(pOrgMsgPointer); */ smsg_t *MsgAddRef(smsg_t *const pM) { assert(pM != NULL); #ifdef HAVE_ATOMIC_BUILTINS ATOMIC_INC(&pM->iRefCount, NULL); #else MsgLock(pM); pM->iRefCount++; MsgUnlock(pM); #endif #if DEV_DEBUG == 1 dbgprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount); #endif return (pM); } /* This functions tries to acquire the PROCID from TAG. Its primary use is * when a legacy syslog message has been received and should be forwarded as * syslog-protocol (or the PROCID is requested for any other reason). * In legacy syslog, the PROCID is considered to be the character sequence * between the first [ and the first ]. This usually are digits only, but we * do not check that. However, if there is no closing ], we do not assume we * can obtain a PROCID. Take in mind that not every legacy syslog message * actually has a PROCID. * rgerhards, 2005-11-24 * THIS MUST be called with the message lock locked. */ static rsRetVal acquirePROCIDFromTAG(smsg_t *const pM) { register int i; uchar *pszTag; DEFiRet; assert(pM != NULL); if (pM->pCSPROCID != NULL) return RS_RET_OK; /* we are already done ;) */ if (msgGetProtocolVersion(pM) != 0) return RS_RET_OK; /* we can only emulate if we have legacy format */ pszTag = (uchar *)((pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG); /* find first '['... */ i = 0; while ((i < pM->iLenTAG) && (pszTag[i] != '[')) ++i; if (!(i < pM->iLenTAG)) return RS_RET_OK; /* no [, so can not emulate... */ ++i; /* skip '[' */ /* now obtain the PROCID string... */ CHKiRet(cstrConstruct(&pM->pCSPROCID)); while ((i < pM->iLenTAG) && (pszTag[i] != ']')) { CHKiRet(cstrAppendChar(pM->pCSPROCID, pszTag[i])); ++i; } if (!(i < pM->iLenTAG)) { /* oops... it looked like we had a PROCID, but now it has * turned out this is not true. In this case, we need to free * the buffer and simply return. Note that this is NOT an error * case! */ cstrDestruct(&pM->pCSPROCID); FINALIZE; } /* OK, finally we could obtain a PROCID. So let's use it ;) */ cstrFinalize(pM->pCSPROCID); finalize_it: RETiRet; } /* Parse and set the "programname" for a given MSG object. Programname * is a BSD concept, it is the tag without any instance-specific information. * Precisely, the programname is terminated by either (whichever occurs first): * - end of tag * - nonprintable character * - ':' * - '[' * - '/' * The above definition has been taken from the FreeBSD syslogd sources. * * The program name is not parsed by default, because it is infrequently-used. * IMPORTANT: A locked message object must be provided, else a crash will occur. * rgerhards, 2005-10-19 */ static rsRetVal acquireProgramName(smsg_t *const pM) { int i; uchar *pszTag, *pszProgName; DEFiRet; assert(pM != NULL); pszTag = (uchar *)((pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG); for (i = 0; (i < pM->iLenTAG) && isprint((int)pszTag[i]) && (pszTag[i] != '\0') && (pszTag[i] != ':') && (pszTag[i] != '[') && (runConf->globals.parser.bPermitSlashInProgramname || (pszTag[i] != '/')); ++i); /* just search end of PROGNAME */ if (i < CONF_PROGNAME_BUFSIZE) { pszProgName = pM->PROGNAME.szBuf; } else { CHKmalloc(pM->PROGNAME.ptr = malloc(i + 1)); pszProgName = pM->PROGNAME.ptr; } memcpy((char *)pszProgName, (char *)pszTag, i); pszProgName[i] = '\0'; pM->iLenPROGNAME = i; finalize_it: RETiRet; } /* Access methods - dumb & easy, not a comment for each ;) */ void setProtocolVersion(smsg_t *const pM, int iNewVersion) { assert(pM != NULL); if (iNewVersion != 0 && iNewVersion != 1) { dbgprintf("Tried to set unsupported protocol version %d - changed to 0.\n", iNewVersion); iNewVersion = 0; } pM->iProtocolVersion = iNewVersion; } /* note: string is taken from constant pool, do NOT free */ static const char *getProtocolVersionString(smsg_t *const pM) { assert(pM != NULL); return (pM->iProtocolVersion ? "1" : "0"); } void msgSetPRI(smsg_t *const __restrict__ pMsg, syslog_pri_t pri) { if (pri > LOG_MAXPRI) pri = LOG_PRI_INVLD; pMsg->iFacility = pri2fac(pri), pMsg->iSeverity = pri2sev(pri); } #ifdef USE_LIBUUID /* note: libuuid seems not to be thread-safe, so we need * to get some safeguards in place. */ static pthread_mutex_t mutUUID = PTHREAD_MUTEX_INITIALIZER; static void call_uuid_generate(uuid_t uuid) { pthread_mutex_lock(&mutUUID); pthread_cleanup_push(mutexCancelCleanup, &mutUUID); uuid_generate(uuid); pthread_cleanup_pop(1); } static void msgSetUUID(smsg_t *const pM) { size_t lenRes = sizeof(uuid_t) * 2 + 1; char hex_char[] = "0123456789ABCDEF"; unsigned int byte_nbr; uuid_t uuid; dbgprintf("[MsgSetUUID] START, lenRes %llu\n", (long long unsigned)lenRes); assert(pM != NULL); if ((pM->pszUUID = (uchar *)malloc(lenRes)) == NULL) { pM->pszUUID = (uchar *)""; } else { call_uuid_generate(uuid); for (byte_nbr = 0; byte_nbr < sizeof(uuid_t); byte_nbr++) { pM->pszUUID[byte_nbr * 2 + 0] = hex_char[uuid[byte_nbr] >> 4]; pM->pszUUID[byte_nbr * 2 + 1] = hex_char[uuid[byte_nbr] & 15]; } pM->pszUUID[lenRes - 1] = '\0'; dbgprintf("[MsgSetUUID] UUID : %s LEN: %d \n", pM->pszUUID, (int)lenRes); } dbgprintf("[MsgSetUUID] END\n"); } static void getUUID(smsg_t *const pM, uchar **pBuf, int *piLen) { dbgprintf("[getUUID] START\n"); if (pM == NULL) { dbgprintf("[getUUID] pM is NULL\n"); *pBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { if (pM->pszUUID == NULL) { dbgprintf("[getUUID] pM->pszUUID is NULL\n"); MsgLock(pM); /* re-query, things may have changed in the mean time... */ if (pM->pszUUID == NULL) msgSetUUID(pM); MsgUnlock(pM); } else { /* UUID already there we reuse it */ dbgprintf("[getUUID] pM->pszUUID already exists\n"); } *pBuf = pM->pszUUID; *piLen = sizeof(uuid_t) * 2; } dbgprintf("[getUUID] END\n"); } #endif int ATTR_NONNULL() getRawMsgLen(const smsg_t *const pMsg) { return (pMsg->pszRawMsg == NULL) ? 0 : pMsg->iLenRawMsg; } void getRawMsg(const smsg_t *const pM, uchar **pBuf, int *piLen) { if (pM == NULL) { *pBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { if (pM->pszRawMsg == NULL) { *pBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { *pBuf = pM->pszRawMsg; *piLen = pM->iLenRawMsg; } } } void getRawMsgAfterPRI(smsg_t *const pM, uchar **pBuf, int *piLen) { if (pM == NULL) { *pBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { if (pM->pszRawMsg == NULL) { *pBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { /* unfortunately, pM->offAfterPRI seems NOT to be * correct/consistent in all cases. imuxsock and imudp * seem to have other values than imptcp. Testbench * covers some of that. As a work-around, we caluculate * the value ourselfes here. -- rgerhards, 2015-10-09 */ size_t offAfterPRI = 0; if (pM->pszRawMsg[0] == '<') { /* do we have a PRI? */ if (pM->pszRawMsg[2] == '>') offAfterPRI = 3; else if (pM->pszRawMsg[3] == '>') offAfterPRI = 4; else if (pM->pszRawMsg[4] == '>') offAfterPRI = 5; } *pBuf = pM->pszRawMsg + offAfterPRI; *piLen = pM->iLenRawMsg - offAfterPRI; } } } /* note: setMSGLen() is only for friends who really know what they * do. Setting an invalid length can be desasterous! */ void setMSGLen(smsg_t *const pM, int lenMsg) { pM->iLenMSG = lenMsg; } int getMSGLen(smsg_t *const pM) { return ((pM == NULL) ? 0 : pM->iLenMSG); } uchar *getMSG(smsg_t *const pM) { uchar *ret; if (pM == NULL) ret = UCHAR_CONSTANT(""); else { if (pM->iLenMSG == 0) ret = UCHAR_CONSTANT(""); else ret = pM->pszRawMsg + pM->offMSG; } return ret; } /* Get PRI value as integer */ int getPRIi(const smsg_t *const pM) { syslog_pri_t pri = (pM->iFacility << 3) + (pM->iSeverity); if (pri > 191) pri = LOG_PRI_INVLD; return pri; } /* Get PRI value in text form */ const char *getPRI(smsg_t *const pM) { /* PRI is a number in the range 0..191. Thus, we use a simple lookup table to obtain the * string value. It looks a bit clumpsy here in code ;) */ int iPRI; if (pM == NULL) return ""; iPRI = getPRIi(pM); return (iPRI > 191) ? "invld" : (char *)syslog_pri_names[iPRI].pszName; } static const char *formatISOWeekOrYear(enum tplFormatTypes eFmt, struct syslogTime *pTm) { if (pTm->year >= 1970 && pTm->year <= 2099) { int isoWeekYear; int isoWeek; isoWeek = getISOWeek(pTm, &isoWeekYear); if (eFmt == tplFmtISOWeek) { return two_digits[isoWeek]; } else { return years[isoWeekYear - 1967]; } } else { return "YEAR OUT OF RANGE(1970-2099)"; } } const char *getTimeReported(smsg_t *const pM, enum tplFormatTypes eFmt) { if (pM == NULL) return ""; switch (eFmt) { case tplFmtDefault: case tplFmtRFC3164Date: case tplFmtRFC3164BuggyDate: MsgLock(pM); if (pM->pszTIMESTAMP3164 == NULL) { pM->pszTIMESTAMP3164 = pM->pszTimestamp3164; datetime.formatTimestamp3164(&pM->tTIMESTAMP, pM->pszTIMESTAMP3164, (eFmt == tplFmtRFC3164BuggyDate)); } MsgUnlock(pM); return (pM->pszTIMESTAMP3164); case tplFmtMySQLDate: MsgLock(pM); if (pM->pszTIMESTAMP_MySQL == NULL) { if ((pM->pszTIMESTAMP_MySQL = malloc(15)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestampToMySQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_MySQL); } MsgUnlock(pM); return (pM->pszTIMESTAMP_MySQL); case tplFmtPgSQLDate: MsgLock(pM); if (pM->pszTIMESTAMP_PgSQL == NULL) { if ((pM->pszTIMESTAMP_PgSQL = malloc(21)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestampToPgSQL(&pM->tTIMESTAMP, pM->pszTIMESTAMP_PgSQL); } MsgUnlock(pM); return (pM->pszTIMESTAMP_PgSQL); case tplFmtRFC3339Date: MsgLock(pM); if (pM->pszTIMESTAMP3339 == NULL) { pM->pszTIMESTAMP3339 = pM->pszTimestamp3339; datetime.formatTimestamp3339(&pM->tTIMESTAMP, pM->pszTIMESTAMP3339); } MsgUnlock(pM); return (pM->pszTIMESTAMP3339); case tplFmtUnixDate: MsgLock(pM); if (pM->pszTIMESTAMP_Unix[0] == '\0') { datetime.formatTimestampUnix(&pM->tTIMESTAMP, pM->pszTIMESTAMP_Unix); } MsgUnlock(pM); return (pM->pszTIMESTAMP_Unix); case tplFmtSecFrac: if (pM->pszTIMESTAMP_SecFrac[0] == '\0') { MsgLock(pM); /* re-check, may have changed while we did not hold lock */ if (pM->pszTIMESTAMP_SecFrac[0] == '\0') { datetime.formatTimestampSecFrac(&pM->tTIMESTAMP, pM->pszTIMESTAMP_SecFrac); } MsgUnlock(pM); } return (pM->pszTIMESTAMP_SecFrac); case tplFmtWDayName: return wdayNames[getWeekdayNbr(&pM->tTIMESTAMP)]; case tplFmtWDay: return one_digit[getWeekdayNbr(&pM->tTIMESTAMP)]; case tplFmtMonth: return two_digits[(int)pM->tTIMESTAMP.month]; case tplFmtYear: if (pM->tTIMESTAMP.year >= 1967 && pM->tTIMESTAMP.year <= 2099) return years[pM->tTIMESTAMP.year - 1967]; else return "YEAR OUT OF RANGE(1967-2099)"; case tplFmtDay: return two_digits[(int)pM->tTIMESTAMP.day]; case tplFmtHour: return two_digits[(int)pM->tTIMESTAMP.hour]; case tplFmtMinute: return two_digits[(int)pM->tTIMESTAMP.minute]; case tplFmtSecond: return two_digits[(int)pM->tTIMESTAMP.second]; case tplFmtTZOffsHour: return two_digits[(int)pM->tTIMESTAMP.OffsetHour]; case tplFmtTZOffsMin: return two_digits[(int)pM->tTIMESTAMP.OffsetMinute]; case tplFmtTZOffsDirection: return (pM->tTIMESTAMP.OffsetMode == '+') ? "+" : "-"; case tplFmtOrdinal: return daysInYear[getOrdinal(&pM->tTIMESTAMP)]; case tplFmtWeek: return two_digits[getWeek(&pM->tTIMESTAMP)]; case tplFmtISOWeek: case tplFmtISOWeekYear: return formatISOWeekOrYear(eFmt, &pM->tTIMESTAMP); default: return "INVALID eFmt OPTION!"; } } static const char *getTimeUTC(struct syslogTime *const __restrict__ pTmIn, const enum tplFormatTypes eFmt, unsigned short *const __restrict__ pbMustBeFreed) { struct syslogTime tUTC; char *retbuf = NULL; timeConvertToUTC(pTmIn, &tUTC); struct syslogTime *const pTm = &tUTC; switch (eFmt) { case tplFmtDefault: if ((retbuf = malloc(16)) != NULL) { datetime.formatTimestamp3164(pTm, retbuf, 0); } break; case tplFmtMySQLDate: if ((retbuf = malloc(15)) != NULL) { datetime.formatTimestampToMySQL(pTm, retbuf); } break; case tplFmtPgSQLDate: if ((retbuf = malloc(21)) != NULL) { datetime.formatTimestampToPgSQL(pTm, retbuf); } break; case tplFmtRFC3164Date: case tplFmtRFC3164BuggyDate: if ((retbuf = malloc(16)) != NULL) { datetime.formatTimestamp3164(pTm, retbuf, (eFmt == tplFmtRFC3164BuggyDate)); } break; case tplFmtRFC3339Date: if ((retbuf = malloc(33)) != NULL) { datetime.formatTimestamp3339(pTm, retbuf); } break; case tplFmtUnixDate: if ((retbuf = malloc(12)) != NULL) { datetime.formatTimestampUnix(pTm, retbuf); } break; case tplFmtSecFrac: if ((retbuf = malloc(7)) != NULL) { datetime.formatTimestampSecFrac(pTm, retbuf); } break; case tplFmtWDayName: retbuf = strdup(wdayNames[getWeekdayNbr(pTm)]); break; case tplFmtWDay: retbuf = strdup(one_digit[getWeekdayNbr(pTm)]); break; case tplFmtMonth: retbuf = strdup(two_digits[(int)pTm->month]); break; case tplFmtYear: if (pTm->year >= 1967 && pTm->year <= 2099) retbuf = strdup(years[pTm->year - 1967]); else retbuf = strdup("YEAR OUT OF RANGE(1967-2099)"); break; case tplFmtDay: retbuf = strdup(two_digits[(int)pTm->day]); break; case tplFmtHour: retbuf = strdup(two_digits[(int)pTm->hour]); break; case tplFmtMinute: retbuf = strdup(two_digits[(int)pTm->minute]); break; case tplFmtSecond: retbuf = strdup(two_digits[(int)pTm->second]); break; case tplFmtTZOffsHour: retbuf = strdup(two_digits[(int)pTm->OffsetHour]); break; case tplFmtTZOffsMin: retbuf = strdup(two_digits[(int)pTm->OffsetMinute]); break; case tplFmtTZOffsDirection: retbuf = strdup((pTm->OffsetMode == '+') ? "+" : "-"); break; case tplFmtOrdinal: retbuf = strdup(daysInYear[getOrdinal(pTm)]); break; case tplFmtWeek: retbuf = strdup(two_digits[getWeek(pTm)]); break; case tplFmtISOWeek: case tplFmtISOWeekYear: retbuf = strdup(formatISOWeekOrYear(eFmt, pTm)); break; default: // Required to prevent compiler warning C4062 (unhandled enum value). // Unhandled eFmt values are correctly managed by the subsequent if(retbuf == NULL) check. break; } if (retbuf == NULL) { retbuf = (char *)"internal error: invalid eFmt option or malloc problem"; *pbMustBeFreed = 0; } else { *pbMustBeFreed = 1; } return retbuf; } static const char *getTimeGenerated(smsg_t *const __restrict__ pM, const enum tplFormatTypes eFmt) { struct syslogTime *const pTm = &pM->tRcvdAt; if (pM == NULL) return ""; switch (eFmt) { case tplFmtDefault: MsgLock(pM); if (pM->pszRcvdAt3164 == NULL) { if ((pM->pszRcvdAt3164 = malloc(16)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestamp3164(pTm, pM->pszRcvdAt3164, 0); } MsgUnlock(pM); return (pM->pszRcvdAt3164); case tplFmtMySQLDate: MsgLock(pM); if (pM->pszRcvdAt_MySQL == NULL) { if ((pM->pszRcvdAt_MySQL = malloc(15)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestampToMySQL(pTm, pM->pszRcvdAt_MySQL); } MsgUnlock(pM); return (pM->pszRcvdAt_MySQL); case tplFmtPgSQLDate: MsgLock(pM); if (pM->pszRcvdAt_PgSQL == NULL) { if ((pM->pszRcvdAt_PgSQL = malloc(21)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestampToPgSQL(pTm, pM->pszRcvdAt_PgSQL); } MsgUnlock(pM); return (pM->pszRcvdAt_PgSQL); case tplFmtRFC3164Date: case tplFmtRFC3164BuggyDate: MsgLock(pM); if (pM->pszRcvdAt3164 == NULL) { if ((pM->pszRcvdAt3164 = malloc(16)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestamp3164(pTm, pM->pszRcvdAt3164, (eFmt == tplFmtRFC3164BuggyDate)); } MsgUnlock(pM); return (pM->pszRcvdAt3164); case tplFmtRFC3339Date: MsgLock(pM); if (pM->pszRcvdAt3339 == NULL) { if ((pM->pszRcvdAt3339 = malloc(33)) == NULL) { MsgUnlock(pM); return ""; } datetime.formatTimestamp3339(pTm, pM->pszRcvdAt3339); } MsgUnlock(pM); return (pM->pszRcvdAt3339); case tplFmtUnixDate: MsgLock(pM); if (pM->pszRcvdAt_Unix[0] == '\0') { datetime.formatTimestampUnix(pTm, pM->pszRcvdAt_Unix); } MsgUnlock(pM); return (pM->pszRcvdAt_Unix); case tplFmtSecFrac: if (pM->pszRcvdAt_SecFrac[0] == '\0') { MsgLock(pM); /* re-check, may have changed while we did not hold lock */ if (pM->pszRcvdAt_SecFrac[0] == '\0') { datetime.formatTimestampSecFrac(pTm, pM->pszRcvdAt_SecFrac); } MsgUnlock(pM); } return (pM->pszRcvdAt_SecFrac); case tplFmtWDayName: return wdayNames[getWeekdayNbr(pTm)]; case tplFmtWDay: return one_digit[getWeekdayNbr(pTm)]; case tplFmtMonth: return two_digits[(int)pTm->month]; case tplFmtYear: if (pTm->year >= 1967 && pTm->year <= 2099) return years[pTm->year - 1967]; else return "YEAR OUT OF RANGE(1967-2099)"; case tplFmtDay: return two_digits[(int)pTm->day]; case tplFmtHour: return two_digits[(int)pTm->hour]; case tplFmtMinute: return two_digits[(int)pTm->minute]; case tplFmtSecond: return two_digits[(int)pTm->second]; case tplFmtTZOffsHour: return two_digits[(int)pTm->OffsetHour]; case tplFmtTZOffsMin: return two_digits[(int)pTm->OffsetMinute]; case tplFmtTZOffsDirection: return (pTm->OffsetMode == '+') ? "+" : "-"; case tplFmtOrdinal: return daysInYear[getOrdinal(pTm)]; case tplFmtWeek: return two_digits[getWeek(pTm)]; case tplFmtISOWeek: case tplFmtISOWeekYear: return formatISOWeekOrYear(eFmt, pTm); default: return "INVALID eFmt OPTION!"; } } static const char *getSeverity(smsg_t *const pM) { const char *name = NULL; if (pM == NULL) return ""; if (pM->iSeverity > 7) { name = "invld"; } else { name = syslog_number_names[pM->iSeverity]; } return name; } static const char *getSeverityStr(smsg_t *const pM) { const char *name = NULL; if (pM == NULL) return ""; if (pM->iSeverity > 7) { name = "invld"; } else { name = syslog_severity_names[pM->iSeverity]; } return name; } static const char *getFacility(smsg_t *const pM) { const char *name = NULL; if (pM == NULL) return ""; if (pM->iFacility > 23) { name = "invld"; } else { name = syslog_number_names[pM->iFacility]; } return name; } static const char *getFacilityStr(smsg_t *const pM) { const char *name = NULL; if (pM == NULL) return ""; if (pM->iFacility > 23) { name = "invld"; } else { name = syslog_fac_names[pM->iFacility]; } return name; } /* set flow control state (if not called, the default - NO_DELAY - is used) * This needs no locking because it is only done while the object is * not fully constructed (which also means you must not call this * method after the msg has been handed over to a queue). * rgerhards, 2008-03-14 */ rsRetVal MsgSetFlowControlType(smsg_t *const pMsg, flowControl_t eFlowCtl) { DEFiRet; assert(pMsg != NULL); assert(eFlowCtl == eFLOWCTL_NO_DELAY || eFlowCtl == eFLOWCTL_LIGHT_DELAY || eFlowCtl == eFLOWCTL_FULL_DELAY); pMsg->flowCtlType = eFlowCtl; RETiRet; } /* set offset after which PRI in raw msg starts * rgerhards, 2009-06-16 */ rsRetVal MsgSetAfterPRIOffs(smsg_t *const pMsg, int offs) { assert(pMsg != NULL); assert(offs >= 0 && offs <= pMsg->iLenRawMsg); if (offs < 0 || offs > pMsg->iLenRawMsg) { pMsg->offAfterPRI = 0; return RS_RET_ERR; } if (offs > 0) { assert(pMsg->pszRawMsg != NULL); assert(pMsg->pszRawMsg[0] == '<'); assert(pMsg->pszRawMsg[offs - 1] == '>'); } pMsg->offAfterPRI = offs; return RS_RET_OK; } /* rgerhards 2004-11-24: set APP-NAME in msg object * This is not locked, because it either is called during message * construction (where we need no locking) or later as part of a function * which already obtained the lock. So in general, this function here must * only be called when it it safe to do so without it aquiring a lock. */ rsRetVal ATTR_NONNULL(1, 2) MsgSetAPPNAME(smsg_t *__restrict__ const pMsg, const char *pszAPPNAME) { DEFiRet; assert(pMsg != NULL); if (pszAPPNAME[0] == '\0') { pszAPPNAME = "-"; /* RFC5424 NIL value */ } if (pMsg->pCSAPPNAME == NULL) { /* we need to obtain the object first */ CHKiRet(rsCStrConstruct(&pMsg->pCSAPPNAME)); } /* if we reach this point, we have the object */ CHKiRet(rsCStrSetSzStr(pMsg->pCSAPPNAME, (uchar *)pszAPPNAME)); cstrFinalize(pMsg->pCSAPPNAME); finalize_it: RETiRet; } /* rgerhards 2004-11-24: set PROCID in msg object */ rsRetVal MsgSetPROCID(smsg_t *__restrict__ const pMsg, const char *pszPROCID) { DEFiRet; ISOBJ_TYPE_assert(pMsg, msg); if (pMsg->pCSPROCID == NULL) { /* we need to obtain the object first */ CHKiRet(cstrConstruct(&pMsg->pCSPROCID)); } /* if we reach this point, we have the object */ CHKiRet(rsCStrSetSzStr(pMsg->pCSPROCID, (uchar *)pszPROCID)); cstrFinalize(pMsg->pCSPROCID); finalize_it: RETiRet; } /* check if we have a procid, and, if not, try to acquire/emulate it. * This must be called WITHOUT the message lock being held. * rgerhards, 2009-06-26 */ static void preparePROCID(smsg_t *const pM, sbool bLockMutex) { if (pM->pCSPROCID == NULL) { if (bLockMutex == LOCK_MUTEX) MsgLock(pM); /* re-query, things may have changed in the mean time... */ if (pM->pCSPROCID == NULL) acquirePROCIDFromTAG(pM); if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); } } #if 0 /* rgerhards, 2005-11-24 */ static int getPROCIDLen(smsg_t *pM, sbool bLockMutex) { assert(pM != NULL); preparePROCID(pM, bLockMutex); return (pM->pCSPROCID == NULL) ? 1 : rsCStrLen(pM->pCSPROCID); } #endif /* rgerhards, 2005-11-24 */ char *getPROCID(smsg_t *const pM, sbool bLockMutex) { uchar *pszRet; ISOBJ_TYPE_assert(pM, msg); if (bLockMutex == LOCK_MUTEX) MsgLock(pM); preparePROCID(pM, MUTEX_ALREADY_LOCKED); if (pM->pCSPROCID == NULL) pszRet = UCHAR_CONSTANT("-"); else pszRet = rsCStrGetSzStrNoNULL(pM->pCSPROCID); if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); return (char *)pszRet; } /* rgerhards 2004-11-24: set MSGID in msg object */ rsRetVal MsgSetMSGID(smsg_t *const pMsg, const char *pszMSGID) { DEFiRet; ISOBJ_TYPE_assert(pMsg, msg); if (pMsg->pCSMSGID == NULL) { /* we need to obtain the object first */ CHKiRet(rsCStrConstruct(&pMsg->pCSMSGID)); } /* if we reach this point, we have the object */ CHKiRet(rsCStrSetSzStr(pMsg->pCSMSGID, (uchar *)pszMSGID)); cstrFinalize(pMsg->pCSMSGID); finalize_it: RETiRet; } /* Return state of last parser. If it had success, "OK" is returned, else * "FAIL". All from the constant pool. */ static const char *getParseSuccess(smsg_t *const pM) { return (pM->bParseSuccess) ? "OK" : "FAIL"; } /* al, 2011-07-26: LockMsg to avoid race conditions */ static const char *getMSGID(smsg_t *const pM) { if (pM->pCSMSGID == NULL) { return "-"; } else { MsgLock(pM); char *pszreturn = (char *)rsCStrGetSzStrNoNULL(pM->pCSMSGID); MsgUnlock(pM); return pszreturn; } } /* rgerhards 2012-03-15: set parser success (an integer, acutally bool) */ void MsgSetParseSuccess(smsg_t *const pMsg, int bSuccess) { assert(pMsg != NULL); pMsg->bParseSuccess = bSuccess; } /* return full message as a json string */ const uchar *msgGetJSONMESG(smsg_t *__restrict__ const pMsg) { struct json_object *json; struct json_object *jval; uchar *pRes; /* result pointer */ rs_size_t bufLen = -1; /* length of string or -1, if not known */ json = json_object_new_object(); jval = json_object_new_string((char *)getMSG(pMsg)); json_object_object_add(json, "msg", jval); getRawMsg(pMsg, &pRes, &bufLen); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "rawmsg", jval); pRes = (uchar *)getTimeReported(pMsg, tplFmtRFC3339Date); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "timereported", jval); jval = json_object_new_string(getHOSTNAME(pMsg)); json_object_object_add(json, "hostname", jval); getTAG(pMsg, &pRes, &bufLen, LOCK_MUTEX); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "syslogtag", jval); getInputName(pMsg, &pRes, &bufLen); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "inputname", jval); jval = json_object_new_string((char *)getRcvFrom(pMsg)); json_object_object_add(json, "fromhost", jval); jval = json_object_new_string((char *)getRcvFromIP(pMsg)); json_object_object_add(json, "fromhost-ip", jval); jval = json_object_new_string((char *)getRcvFromPort(pMsg)); json_object_object_add(json, "fromhost-port", jval); jval = json_object_new_string(getPRI(pMsg)); json_object_object_add(json, "pri", jval); jval = json_object_new_string(getFacility(pMsg)); json_object_object_add(json, "syslogfacility", jval); jval = json_object_new_string(getSeverity(pMsg)); json_object_object_add(json, "syslogseverity", jval); pRes = (uchar *)getTimeGenerated(pMsg, tplFmtRFC3339Date); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "timegenerated", jval); jval = json_object_new_string((char *)getProgramName(pMsg, LOCK_MUTEX)); json_object_object_add(json, "programname", jval); jval = json_object_new_string(getProtocolVersionString(pMsg)); json_object_object_add(json, "protocol-version", jval); MsgGetStructuredData(pMsg, &pRes, &bufLen); jval = json_object_new_string((char *)pRes); json_object_object_add(json, "structured-data", jval); jval = json_object_new_string(getAPPNAME(pMsg, LOCK_MUTEX)); json_object_object_add(json, "app-name", jval); jval = json_object_new_string(getPROCID(pMsg, LOCK_MUTEX)); json_object_object_add(json, "procid", jval); jval = json_object_new_string(getMSGID(pMsg)); json_object_object_add(json, "msgid", jval); #ifdef USE_LIBUUID if (pMsg->pszUUID == NULL) { jval = NULL; } else { getUUID(pMsg, &pRes, &bufLen); jval = json_object_new_string((char *)pRes); } json_object_object_add(json, "uuid", jval); #endif json_object_object_add(json, "$!", json_object_get(pMsg->json)); pRes = (uchar *)strdup(jsonToString(json)); json_object_put(json); return pRes; } /* rgerhards 2009-06-12: set associated ruleset */ void MsgSetRuleset(smsg_t *const pMsg, ruleset_t *pRuleset) { assert(pMsg != NULL); pMsg->pRuleset = pRuleset; } /* set TAG in msg object * (rewritten 2009-06-18 rgerhards) */ void MsgSetTAG(smsg_t *__restrict__ const pMsg, const uchar *pszBuf, const size_t lenBuf) { uchar *pBuf; assert(pMsg != NULL); freeTAG(pMsg); if (pMsg->iLenPROGNAME >= CONF_PROGNAME_BUFSIZE) { free(pMsg->PROGNAME.ptr); pMsg->PROGNAME.ptr = NULL; } pMsg->iLenPROGNAME = -1; pMsg->iLenTAG = lenBuf; if (pMsg->iLenTAG < CONF_TAG_BUFSIZE) { /* small enough: use fixed buffer (faster!) */ pBuf = pMsg->TAG.szBuf; } else { if ((pBuf = (uchar *)malloc(pMsg->iLenTAG + 1)) == NULL) { /* truncate message, better than completely loosing it... */ pBuf = pMsg->TAG.szBuf; pMsg->iLenTAG = CONF_TAG_BUFSIZE - 1; } else { pMsg->TAG.pszTAG = pBuf; } } memcpy(pBuf, pszBuf, pMsg->iLenTAG); pBuf[pMsg->iLenTAG] = '\0'; /* this also works with truncation! */ } /* This function tries to emulate the TAG if none is * set. Its primary purpose is to provide an old-style TAG * when a syslog-protocol message has been received. Then, * the tag is APP-NAME "[" PROCID "]". The function first checks * if there is a TAG and, if not, if it can emulate it. * rgerhards, 2005-11-24 */ static void ATTR_NONNULL(1) tryEmulateTAG(smsg_t *const pM, const sbool bLockMutex) { size_t lenTAG; uchar bufTAG[CONF_TAG_MAXSIZE]; assert(pM != NULL); if (bLockMutex == LOCK_MUTEX) MsgLock(pM); if (pM->iLenTAG > 0) { if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); return; /* done, no need to emulate */ } if (msgGetProtocolVersion(pM) == 1) { if (!strcmp(getPROCID(pM, MUTEX_ALREADY_LOCKED), "-")) { /* no process ID, use APP-NAME only */ MsgSetTAG(pM, (uchar *)getAPPNAME(pM, MUTEX_ALREADY_LOCKED), getAPPNAMELen(pM, MUTEX_ALREADY_LOCKED)); } else { int snRet; /* now we can try to emulate */ snRet = snprintf((char *)bufTAG, CONF_TAG_MAXSIZE, "%s[%s]", getAPPNAME(pM, MUTEX_ALREADY_LOCKED), getPROCID(pM, MUTEX_ALREADY_LOCKED)); bufTAG[sizeof(bufTAG) - 1] = '\0'; /* just to make sure... */ if (snRet < 0) { lenTAG = 0; } else if ((size_t)snRet >= sizeof(bufTAG)) { lenTAG = sizeof(bufTAG) - 1; } else { lenTAG = snRet; } MsgSetTAG(pM, bufTAG, lenTAG); } /* Signal change in TAG for acquireProgramName */ pM->iLenPROGNAME = -1; } if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); } void ATTR_NONNULL(2, 3) getTAG(smsg_t *const pM, uchar **const ppBuf, int *const piLen, const sbool bLockMutex) { if (bLockMutex == LOCK_MUTEX) MsgLock(pM); if (pM == NULL) { *ppBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { if (pM->iLenTAG == 0) tryEmulateTAG(pM, MUTEX_ALREADY_LOCKED); if (pM->iLenTAG == 0) { *ppBuf = UCHAR_CONSTANT(""); *piLen = 0; } else { *ppBuf = (pM->iLenTAG < CONF_TAG_BUFSIZE) ? pM->TAG.szBuf : pM->TAG.pszTAG; *piLen = pM->iLenTAG; } } if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); } int getHOSTNAMELen(smsg_t *const pM) { if (pM == NULL) return 0; else if (pM->pszHOSTNAME == NULL) { resolveDNS(pM); if (pM->rcvFrom.pRcvFrom == NULL) return 0; else return prop.GetStringLen(pM->rcvFrom.pRcvFrom); } else return pM->iLenHOSTNAME; } const char *getHOSTNAME(smsg_t *const pM) { if (pM == NULL) return ""; else if (pM->pszHOSTNAME == NULL) { resolveDNS(pM); if (pM->rcvFrom.pRcvFrom == NULL) { return ""; } else { uchar *psz; int len; prop.GetString(pM->rcvFrom.pRcvFrom, &psz, &len); return (char *)psz; } } else { return (char *)pM->pszHOSTNAME; } } uchar *getRcvFrom(smsg_t *const pM) { uchar *psz; int len; if (pM == NULL) { psz = UCHAR_CONSTANT(""); } else { resolveDNS(pM); if (pM->rcvFrom.pRcvFrom == NULL) psz = UCHAR_CONSTANT(""); else prop.GetString(pM->rcvFrom.pRcvFrom, &psz, &len); } return psz; } void MsgGetRcvFromProp(smsg_t *const pM, const propid_t propid, uchar **const ppsz, int *const plen) { prop_t *pProp = NULL; assert(pM != NULL); assert(ppsz != NULL); assert(plen != NULL); if (pM->msgFlags & NEEDS_DNSRESOL) { (void)resolveDNS(pM); } switch (propid) { case PROP_FROMHOST: pProp = pM->rcvFrom.pRcvFrom; break; case PROP_FROMHOST_IP: pProp = pM->pRcvFromIP; break; case PROP_FROMHOST_PORT: pProp = pM->pRcvFromPort; break; default: assert(0); break; } if (pProp == NULL) { *ppsz = UCHAR_CONSTANT(""); *plen = 0; } else { prop.GetString(pProp, ppsz, plen); } } /* rgerhards 2004-11-24: set STRUCTURED DATA in msg object */ rsRetVal MsgSetStructuredData(smsg_t *const pMsg, const char *pszStrucData) { DEFiRet; ISOBJ_TYPE_assert(pMsg, msg); free(pMsg->pszStrucData); CHKmalloc(pMsg->pszStrucData = (uchar *)strdup(pszStrucData)); pMsg->lenStrucData = strlen(pszStrucData); finalize_it: RETiRet; } /* get the "STRUCTURED-DATA" as sz string, including length */ void MsgGetStructuredData(smsg_t *const pM, uchar **pBuf, rs_size_t *len) { MsgLock(pM); if (pM->pszStrucData == NULL) { *pBuf = UCHAR_CONSTANT("-"), *len = 1; } else { *pBuf = pM->pszStrucData, *len = pM->lenStrucData; } MsgUnlock(pM); } /* get the "programname" as sz string * rgerhards, 2005-10-19 */ uchar *ATTR_NONNULL(1) getProgramName(smsg_t *const pM, const sbool bLockMutex) { if (bLockMutex == LOCK_MUTEX) { MsgLock(pM); } if (pM->iLenPROGNAME == -1) { if (pM->iLenTAG == 0) { uchar *pRes; rs_size_t bufLen = -1; getTAG(pM, &pRes, &bufLen, MUTEX_ALREADY_LOCKED); } acquireProgramName(pM); } if (bLockMutex == LOCK_MUTEX) { MsgUnlock(pM); } return (pM->iLenPROGNAME < CONF_PROGNAME_BUFSIZE) ? pM->PROGNAME.szBuf : pM->PROGNAME.ptr; } /* check if we have a APPNAME, and, if not, try to acquire/emulate it. * rgerhards, 2009-06-26 */ static void ATTR_NONNULL(1) prepareAPPNAME(smsg_t *const pM, const sbool bLockMutex) { if (pM->pCSAPPNAME == NULL) { if (bLockMutex == LOCK_MUTEX) MsgLock(pM); /* re-query as things might have changed during locking */ if (pM->pCSAPPNAME == NULL) { if (msgGetProtocolVersion(pM) == 0) { /* only then it makes sense to emulate */ MsgSetAPPNAME(pM, (char *)getProgramName(pM, MUTEX_ALREADY_LOCKED)); } } if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); } } /* rgerhards, 2005-11-24 */ char *getAPPNAME(smsg_t *const pM, const sbool bLockMutex) { uchar *pszRet; assert(pM != NULL); if (bLockMutex == LOCK_MUTEX) MsgLock(pM); prepareAPPNAME(pM, MUTEX_ALREADY_LOCKED); if (pM->pCSAPPNAME == NULL) pszRet = UCHAR_CONSTANT(""); else pszRet = rsCStrGetSzStrNoNULL(pM->pCSAPPNAME); if (bLockMutex == LOCK_MUTEX) MsgUnlock(pM); return (char *)pszRet; } /* rgerhards, 2005-11-24 */ static int getAPPNAMELen(smsg_t *const pM, const sbool bLockMutex) { assert(pM != NULL); prepareAPPNAME(pM, bLockMutex); return (pM->pCSAPPNAME == NULL) ? 0 : rsCStrLen(pM->pCSAPPNAME); } /* rgerhards 2008-09-10: set pszInputName in msg object. This calls AddRef() * on the property, because this must be done in all current cases and there * is no case expected where this may not be necessary. * rgerhards, 2009-06-16 */ void MsgSetInputName(smsg_t *pThis, prop_t *inputName) { assert(pThis != NULL); prop.AddRef(inputName); if (pThis->pInputName != NULL) prop.Destruct(&pThis->pInputName); pThis->pInputName = inputName; } rsRetVal MsgSetInputNameStr(smsg_t *const pMsg, const uchar *const text, const int len) { prop_t *pProp = NULL; DEFiRet; CHKiRet(prop.Construct(&pProp)); CHKiRet(prop.SetString(pProp, text, len)); CHKiRet(prop.ConstructFinalize(pProp)); /* MsgSetInputName() retains an AddRef; release our constructor-owned * reference in finalize_it on both success and failure. */ MsgSetInputName(pMsg, pProp); finalize_it: if (pProp != NULL) prop.Destruct(&pProp); RETiRet; } rsRetVal MsgSetRcvFromText(smsg_t *const pMsg, const uchar *const text, const int len) { prop_t *pProp = NULL; DEFiRet; CHKiRet(prop.Construct(&pProp)); CHKiRet(prop.SetString(pProp, text, len)); CHKiRet(prop.ConstructFinalize(pProp)); /* MsgSetRcvFrom() retains an AddRef; release our constructor-owned * reference in finalize_it on both success and failure. */ MsgSetRcvFrom(pMsg, pProp); finalize_it: if (pProp != NULL) prop.Destruct(&pProp); RETiRet; } rsRetVal MsgSetRcvFromIPText(smsg_t *const pMsg, const uchar *const text, const int len) { prop_t *pProp = NULL; const rsRetVal r = MsgSetRcvFromIPStr(pMsg, text, len, &pProp); if (pProp != NULL) prop.Destruct(&pProp); return r; } rsRetVal MsgSetRcvFromPortText(smsg_t *const pMsg, const uchar *const text, const int len) { prop_t *pProp = NULL; const rsRetVal r = MsgSetRcvFromPortStr(pMsg, text, len, &pProp); if (pProp != NULL) prop.Destruct(&pProp); return r; } /* Set default TZ. Note that at most 7 chars are set, as we would * otherwise overrun our buffer! */ void MsgSetDfltTZ(smsg_t *pThis, char *tz) { rs_cstr_copy(pThis->dfltTZ, tz, sizeof(pThis->dfltTZ)); } /* Set the pfrominet socket store, so that we can obtain the peer at some * later time. Note that we do not check if pRcvFrom is already set, so this * function must only be called during message creation. * NOTE: msgFlags is NOT set. While this is somewhat a violation of layers, * it is done because it gains us some performance. So the caller must make * sure the message flags are properly maintained. For all current callers, * this is always the case and without extra effort required. * rgerhards, 2009-11-17 */ rsRetVal msgSetFromSockinfoLen(smsg_t *pThis, const struct sockaddr_storage *sa, const size_t salen) { DEFiRet; const size_t copyLen = (sa == NULL) ? 0 : ((salen < sizeof(struct sockaddr_storage)) ? salen : sizeof(struct sockaddr_storage)); assert(pThis->rcvFrom.pRcvFrom == NULL); CHKmalloc(pThis->rcvFrom.pfrominet = malloc(sizeof(struct sockaddr_storage))); memset(pThis->rcvFrom.pfrominet, 0, sizeof(struct sockaddr_storage)); if (copyLen > 0) { memcpy(pThis->rcvFrom.pfrominet, sa, copyLen); } finalize_it: RETiRet; } rsRetVal msgSetFromSockinfo(smsg_t *pThis, struct sockaddr_storage *sa) { return msgSetFromSockinfoLen(pThis, sa, sizeof(struct sockaddr_storage)); } /* rgerhards 2008-09-10: set RcvFrom name in msg object. This calls AddRef() * on the property, because this must be done in all current cases and there * is no case expected where this may not be necessary. * rgerhards, 2009-06-30 */ void MsgSetRcvFrom(smsg_t *pThis, prop_t *new) { prop.AddRef(new); MsgSetRcvFromWithoutAddRef(pThis, new); } /* This is used to set the property via a string. This function should not be * called if there is a reliable way for a caller to make sure that the * same name can be used across multiple messages. However, if it can not * ensure that, calling this function is the second best thing, because it * will re-use the previously created property if it contained the same * name (but it works only for the immediate previous). * rgerhards, 2009-06-31 */ void MsgSetRcvFromStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp) { assert(pThis != NULL); assert(ppProp != NULL); prop.CreateOrReuseStringProp(ppProp, psz, len); MsgSetRcvFrom(pThis, *ppProp); } /* set RcvFromIP name in msg object. This calls AddRef() * on the property, because this must be done in all current cases and there * is no case expected where this may not be necessary. * rgerhards, 2009-06-30 */ rsRetVal MsgSetRcvFromIP(smsg_t *pThis, prop_t *new) { assert(pThis != NULL); prop.AddRef(new); MsgSetRcvFromIPWithoutAddRef(pThis, new); return RS_RET_OK; } /* This is used to set the property via a string. This function should not be * called if there is a reliable way for a caller to make sure that the * same name can be used across multiple messages. However, if it can not * ensure that, calling this function is the second best thing, because it * will re-use the previously created property if it contained the same * name (but it works only for the immediate previous). * rgerhards, 2009-06-31 */ rsRetVal MsgSetRcvFromIPStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp) { DEFiRet; assert(pThis != NULL); CHKiRet(prop.CreateOrReuseStringProp(ppProp, psz, len)); MsgSetRcvFromIP(pThis, *ppProp); finalize_it: RETiRet; } rsRetVal MsgSetRcvFromPort(smsg_t *pThis, prop_t *new) { assert(pThis != NULL); prop.AddRef(new); MsgSetRcvFromPortWithoutAddRef(pThis, new); return RS_RET_OK; } rsRetVal MsgSetRcvFromPortStr(smsg_t *const pThis, const uchar *psz, const int len, prop_t **ppProp) { DEFiRet; assert(pThis != NULL); CHKiRet(prop.CreateOrReuseStringProp(ppProp, psz, len)); MsgSetRcvFromPort(pThis, *ppProp); finalize_it: RETiRet; } /* rgerhards 2004-11-09: set HOSTNAME in msg object * rgerhards, 2007-06-21: * Does not return anything. If an error occurs, the hostname is * simply not set. I have changed this behaviour. The only problem * we can run into is memory shortage. If we have such, it is better * to loose the hostname than the full message. So we silently ignore * that problem and hope that memory will be available the next time * we need it. The rest of the code already knows how to handle an * unset HOSTNAME. */ void MsgSetHOSTNAME(smsg_t *pThis, const uchar *pszHOSTNAME, const int lenHOSTNAME) { assert(pThis != NULL); freeHOSTNAME(pThis); pThis->iLenHOSTNAME = lenHOSTNAME; if (pThis->iLenHOSTNAME < CONF_HOSTNAME_BUFSIZE) { /* small enough: use fixed buffer (faster!) */ pThis->pszHOSTNAME = pThis->szHOSTNAME; } else if ((pThis->pszHOSTNAME = (uchar *)malloc(pThis->iLenHOSTNAME + 1)) == NULL) { /* truncate message, better than completely loosing it... */ pThis->pszHOSTNAME = pThis->szHOSTNAME; pThis->iLenHOSTNAME = CONF_HOSTNAME_BUFSIZE - 1; } memcpy(pThis->pszHOSTNAME, pszHOSTNAME, pThis->iLenHOSTNAME); pThis->pszHOSTNAME[pThis->iLenHOSTNAME] = '\0'; /* this also works with truncation! */ } /* set the offset of the MSG part into the raw msg buffer * Note that the offset may be higher than the length of the raw message * (exactly by one). This can happen if we have a message that does not * contain any MSG part. */ void MsgSetMSGoffs(smsg_t *const pMsg, int offs) { ISOBJ_TYPE_assert(pMsg, msg); pMsg->offMSG = offs; if (offs > pMsg->iLenRawMsg) { assert((int)offs - 1 == pMsg->iLenRawMsg); pMsg->iLenMSG = 0; } else { pMsg->iLenMSG = pMsg->iLenRawMsg - offs; } } /* replace the MSG part of a message. The update actually takes place inside * rawmsg. * There are two cases: either the new message will be larger than the new msg * or it will be less than or equal. If it is less than or equal, we can utilize * the previous message buffer. If it is larger, we can utilize the smsg_t-included * message buffer if it fits in there. If this is not the case, we need to alloc * a new, larger, chunk and copy over the data to it. Note that this function is * (hopefully) relatively seldom being called, so some performance impact is * uncritical. In any case, pszMSG is copied, so if it was dynamically allocated, * the caller is responsible for freeing it. * rgerhards, 2009-06-23 */ rsRetVal MsgReplaceMSG(smsg_t *pThis, const uchar *pszMSG, int lenMSG) { DEFiRet; ISOBJ_TYPE_assert(pThis, msg); assert(pszMSG != NULL); if (pThis->pszRawMsg == NULL) { pThis->pszRawMsg = pThis->szRawMsg; pThis->szRawMsg[0] = '\0'; } if (pThis->offMSG < 0 || pThis->offMSG > pThis->iLenRawMsg) { pThis->offMSG = pThis->iLenRawMsg; pThis->iLenMSG = 0; } else if (pThis->iLenMSG < 0 || pThis->iLenMSG > pThis->iLenRawMsg - pThis->offMSG) { pThis->iLenMSG = pThis->iLenRawMsg - pThis->offMSG; } CHKiRet(msgReplaceRawMsgSegment(&pThis->pszRawMsg, pThis->szRawMsg, CONF_RAWMSG_BUFSIZE, pThis->offMSG, pThis->iLenMSG, &pThis->iLenRawMsg, pszMSG, lenMSG)); pThis->iLenMSG = lenMSG; finalize_it: RETiRet; } /* truncate the (raw) message to configured max size. * The function makes sure that the stored rawmsg remains * properly terminated by '\0'. */ void ATTR_NONNULL() MsgTruncateToMaxSize(smsg_t *const pThis) { ISOBJ_TYPE_assert(pThis, msg); const int maxMsgSize = glblGetMaxLine(runConf); assert(pThis->iLenRawMsg > maxMsgSize); const int deltaSize = pThis->iLenRawMsg - maxMsgSize; pThis->pszRawMsg[maxMsgSize] = '\0'; pThis->iLenRawMsg = maxMsgSize; if (pThis->iLenMSG < deltaSize) { pThis->iLenMSG = 0; } else { pThis->iLenMSG -= deltaSize; } } /* set raw message in message object. Size of message is provided. * The function makes sure that the stored rawmsg is properly * terminated by '\0'. When a message is replaced, we try to keep * the existing MSG offset valid so that modules modifying only the * raw text do not need to recompute it. * rgerhards, 2009-06-16 */ void ATTR_NONNULL() MsgSetRawMsg(smsg_t *const pThis, const char *const pszRawMsg, const size_t lenMsg) { ISOBJ_TYPE_assert(pThis, msg); int deltaSize; if (pThis->pszRawMsg != pThis->szRawMsg) free(pThis->pszRawMsg); deltaSize = (int)lenMsg - pThis->iLenRawMsg; /* value < 0 in truncation case! */ pThis->iLenRawMsg = lenMsg; if (pThis->iLenRawMsg < CONF_RAWMSG_BUFSIZE) { /* small enough: use fixed buffer (faster!) */ pThis->pszRawMsg = pThis->szRawMsg; } else if ((pThis->pszRawMsg = (uchar *)malloc(pThis->iLenRawMsg + 1)) == NULL) { /* truncate message, better than completely loosing it... */ pThis->pszRawMsg = pThis->szRawMsg; pThis->iLenRawMsg = CONF_RAWMSG_BUFSIZE - 1; } memcpy(pThis->pszRawMsg, pszRawMsg, pThis->iLenRawMsg); pThis->pszRawMsg[pThis->iLenRawMsg] = '\0'; /* this also works with truncation! */ /* * Update cached MSG length. When offMSG already points into the * message (e.g. after initial parsing) adjusting iLenMSG avoids the * need for a costly re-parse in modules like mmexternal which may * replace the raw message text. */ if (pThis->iLenRawMsg > pThis->offMSG) pThis->iLenMSG += deltaSize; else pThis->iLenMSG = 0; } /* set raw message in message object. Size of message is not provided. This * function should only be used when it is unavoidable (and over time we should * try to remove it altogether). * rgerhards, 2009-06-16 */ void MsgSetRawMsgWOSize(smsg_t *const pMsg, char *pszRawMsg) { MsgSetRawMsg(pMsg, pszRawMsg, strlen(pszRawMsg)); } /* create textual representation of facility and severity. * The variable pRes must point to a user-supplied buffer of * at least 20 characters. */ static uchar *textpri(const smsg_t *const __restrict__ pMsg) { int lenfac = len_syslog_fac_names[pMsg->iFacility]; int lensev = len_syslog_severity_names[pMsg->iSeverity]; int totlen = lenfac + 1 + lensev + 1; char *pRes = malloc(totlen); if (pRes != NULL) { memcpy(pRes, syslog_fac_names[pMsg->iFacility], lenfac); pRes[lenfac] = '.'; memcpy(pRes + lenfac + 1, syslog_severity_names[pMsg->iSeverity], lensev + 1 /* for \0! */); } return (uchar *)pRes; } /* This function returns the current date in different * variants. It is used to construct the $NOW series of * system properties. The returned buffer must be freed * by the caller when no longer needed. If the function * can not allocate memory, it returns a NULL pointer. * Added 2007-07-10 rgerhards */ typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_HHOUR, NOW_QHOUR, NOW_MINUTE, NOW_WDAY } eNOWType; #define tmpBUFSIZE 16 /* size of formatting buffer */ static uchar *getNOW(eNOWType eNow, struct syslogTime *t, const int inUTC) { uchar *pBuf; struct syslogTime tt; if ((pBuf = (uchar *)malloc(tmpBUFSIZE)) == NULL) { return NULL; } if (t == NULL) { /* can happen if called via script engine */ datetime.getCurrTime(&tt, NULL, inUTC); t = &tt; } if (t->year == 0 || t->inUTC != inUTC) { /* not yet set! */ datetime.getCurrTime(t, NULL, inUTC); } switch (eNow) { case NOW_NOW: memcpy(pBuf, two_digits[t->year / 100], 2); memcpy(pBuf + 2, two_digits[t->year % 100], 2); pBuf[4] = '-'; memcpy(pBuf + 5, two_digits[(int)t->month], 2); pBuf[7] = '-'; memcpy(pBuf + 8, two_digits[(int)t->day], 3); break; case NOW_YEAR: memcpy(pBuf, two_digits[t->year / 100], 2); memcpy(pBuf + 2, two_digits[t->year % 100], 3); break; case NOW_MONTH: memcpy(pBuf, two_digits[(int)t->month], 3); break; case NOW_DAY: memcpy(pBuf, two_digits[(int)t->day], 3); break; case NOW_HOUR: memcpy(pBuf, two_digits[(int)t->hour], 3); break; case NOW_HHOUR: memcpy(pBuf, two_digits[t->minute / 30], 3); break; case NOW_QHOUR: memcpy(pBuf, two_digits[t->minute / 15], 3); break; case NOW_MINUTE: memcpy(pBuf, two_digits[(int)t->minute], 3); break; case NOW_WDAY: memcpy(pBuf, one_digit[(int)t->wday], 2); break; default: // We need to satisfy compiler which does not properly handle enum break; } return (pBuf); } #undef tmpBUFSIZE /* clean up */ #ifdef HAVE_LOGNORM_TURBO /* Lazy materialization of turbo result into json_object* tree. * Called when template/property access needs pMsg->json but mmnormalize * stored a turbo snapshot instead. One-shot: turbo_result_to_json is * NULLed after successful materialization so we never double-materialize, * while turbo_result stays valid for the get_str fast-path. * When pMsg->json is already non-NULL (imfile metadata, enrichment, ...), * snapshot fields are merged in using msgAddJSON() semantics: later * normalization fields replace colliding top-level keys. * Must be called with pMsg->mut held. */ static int msgMaterializeTurboJSON(smsg_t *pMsg) { struct json_object *snap_json = NULL; if (pMsg->turbo_result == NULL || pMsg->turbo_result_to_json == NULL) return 1; pMsg->turbo_result_to_json(pMsg->turbo_result, &snap_json); /* Keep the callback live after allocation failure so a later access may * retry instead of permanently losing the normalized fields. */ if (snap_json == NULL) return 0; pMsg->turbo_result_to_json = NULL; /* materialized successfully */ if (pMsg->json == NULL) { pMsg->json = snap_json; } else { /* Keep msgAddJSON() full-tree merge semantics: the normalization * result is the later write and therefore replaces matching keys. */ struct json_object_iterator it = json_object_iter_begin(snap_json); struct json_object_iterator itEnd = json_object_iter_end(snap_json); while (!json_object_iter_equal(&it, &itEnd)) { const char *key = json_object_iter_peek_name(&it); json_object_object_add(pMsg->json, key, json_object_get(json_object_iter_peek_value(&it))); json_object_iter_next(&it); } json_object_put(snap_json); } return 1; } #endif /* helper function to obtain correct JSON root and mutex depending on * property type (essentially based on the property id. If a non-json * property id is given the function errors out. * Note well: jroot points to a pointer to a (ptr to a) json object. * This is necessary because the caller needs a pointer to where the * json object pointer is stored, that in turn is necessary because * while the address of the actual pointer stays stable, the actual * content is volatile until the caller has locked the variable tree, * which we DO NOT do to keep calling semantics simple. */ static rsRetVal ATTR_NONNULL() getJSONRootAndMutex(smsg_t *const pMsg, const propid_t id, struct json_object ***const jroot, pthread_mutex_t **const mut) { DEFiRet; assert(jroot != NULL); /* asserts also help static analyzer! */ assert(mut != NULL); assert(*mut == NULL); /* caller shall have initialized this one! */ assert(id == PROP_CEE || id == PROP_LOCAL_VAR || id == PROP_GLOBAL_VAR); if (id == PROP_CEE) { *mut = &pMsg->mut; *jroot = &pMsg->json; } else if (id == PROP_LOCAL_VAR) { *mut = &pMsg->mut; *jroot = &pMsg->localvars; } else if (id == PROP_GLOBAL_VAR) { *mut = &glblVars_lock; *jroot = &global_var_root; } else { LogError(0, RS_RET_NON_JSON_PROP, "internal error: " "getJSONRootAndMutex; invalid property id %d", id); iRet = RS_RET_NON_JSON_PROP; } RETiRet; } /* basically same function, but does not use property id, but the the * variable name type indicator (char after starting $, e.g. $!myvar --> CEE) */ static rsRetVal ATTR_NONNULL() getJSONRootAndMutexByVarChar(smsg_t *const pMsg, const char c, struct json_object ***const jroot, pthread_mutex_t **const mut) { DEFiRet; propid_t id; assert(c == '!' || c == '.' || c == '/'); switch (c) { case '!': id = PROP_CEE; break; case '.': id = PROP_LOCAL_VAR; break; case '/': id = PROP_GLOBAL_VAR; break; default: LogError(0, RS_RET_NON_JSON_PROP, "internal error: " "getJSONRootAndMutex; invalid indicator char %c(%2.2x)", c, c); ABORT_FINALIZE(RS_RET_NON_JSON_PROP); break; } iRet = getJSONRootAndMutex(pMsg, id, jroot, mut); finalize_it: RETiRet; } /* Get a JSON-Property as string value (used for various types of JSON-based vars) */ rsRetVal getJSONPropVal( smsg_t *const pMsg, msgPropDescr_t *pProp, uchar **pRes, rs_size_t *buflen, unsigned short *pbMustBeFreed) { uchar *leaf; struct json_object **jroot; struct json_object *parent; struct json_object *field; pthread_mutex_t *mut = NULL; DEFiRet; *pRes = NULL; #ifdef HAVE_LOGNORM_TURBO /* Turbo fast-path: serve parse-origin fields directly from snapshot. * Avoids json-c tree materialization + navigation + strdup entirely. * * Guarded on pMsg->json == NULL: once anything has written to the * json-c tree (imfile metadata, msgMaterializeTurboJSON, `set` * statements, downstream enrichment), the turbo snapshot is no * longer authoritative — the slow path below honours the * later-writer-wins merge semantics of msgMaterializeTurboJSON. * Returning snapshot values in that state would bypass a more * recent write. The fast path is therefore only valid while the * message has no json tree yet, which is the common case for * pure-normalize pipelines with no post-parse mutation. * * Lock-free by design: pMsg->json, turbo_result and * turbo_result_get_str are all pointer-sized atomic reads. * Parser writes happen-before queue enqueue (full barrier); later * mutations to pMsg->json go through pMsg->mut. A reader racing * a concurrent json creation can observe the pre-write NULL * exactly once — an existing minor exposure, dramatically * narrower than the always-fires-even-after-mutation bug this * guard closes. Taking pMsg->mut here would defeat the very * reason this fast-path exists (scaling property access without * lock contention). */ if (pProp->id == PROP_CEE && pMsg->json == NULL && pMsg->turbo_result != NULL && pMsg->turbo_result_get_str != NULL) { const uchar *val; rs_size_t vlen; if (pMsg->turbo_result_get_str(pMsg->turbo_result, pProp->name, pProp->nameLen, &val, &vlen) == 0) { *pRes = (uchar *)malloc(vlen + 1); if (*pRes != NULL) { memcpy(*pRes, val, vlen); (*pRes)[vlen] = '\0'; *buflen = vlen; *pbMustBeFreed = 1; return RS_RET_OK; } } } #endif CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); #ifdef HAVE_LOGNORM_TURBO msgMaterializeTurboJSON(pMsg); #endif if (*jroot == NULL) FINALIZE; if (!strcmp((char *)pProp->name, "!")) { field = *jroot; } else { leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen); CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0)); if (jsonVarExtract(parent, (char *)leaf, &field) == FALSE) field = NULL; } if (field != NULL) { *pRes = (uchar *)strdup(jsonToString(field)); *buflen = (int)ustrlen(*pRes); *pbMustBeFreed = 1; } finalize_it: if (mut != NULL) pthread_mutex_unlock(mut); if (*pRes == NULL) { /* could not find any value, so set it to empty */ *pRes = (unsigned char *)""; *pbMustBeFreed = 0; } RETiRet; } /* Get a JSON-based-variable as native json object, except * when it is string type, in which case a string is returned. * This is an optimization to not use JSON when not strictly * necessary. This in turn is helpful, as calling json-c is * *very* expensive due to our need for locking and deep * copies. * The caller needs to check pjson and pcstr: one of them * is non-NULL and contains the return value. Note that * the caller is responsible for freeing the string pointer * it if is being returned. */ rsRetVal msgGetJSONPropJSONorString(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **pjson, uchar **pcstr) { struct json_object **jroot; uchar *leaf; struct json_object *parent; pthread_mutex_t *mut = NULL; DEFiRet; *pjson = NULL, *pcstr = NULL; #ifdef HAVE_LOGNORM_TURBO /* Turbo fast-path: serve parse-origin strings directly from snapshot. * See getJSONPropVal() above for the full rationale — guarded on * pMsg->json == NULL so post-parse mutations (set, enrichment, * materialize) fall through to the merge-aware slow path. */ if (pProp->id == PROP_CEE && pMsg->json == NULL && pMsg->turbo_result != NULL && pMsg->turbo_result_get_str != NULL) { const uchar *val; rs_size_t vlen; if (pMsg->turbo_result_get_str(pMsg->turbo_result, pProp->name, pProp->nameLen, &val, &vlen) == 0) { *pcstr = (uchar *)malloc(vlen + 1); if (*pcstr != NULL) { memcpy(*pcstr, val, vlen); (*pcstr)[vlen] = '\0'; *pjson = NULL; return RS_RET_OK; } } } #endif CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); #ifdef HAVE_LOGNORM_TURBO msgMaterializeTurboJSON(pMsg); #endif if (!strcmp((char *)pProp->name, "!")) { *pjson = *jroot; FINALIZE; } if (*jroot == NULL) { ABORT_FINALIZE(RS_RET_NOT_FOUND); } leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen); CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0)); if (jsonVarExtract(parent, (char *)leaf, pjson) == FALSE) { ABORT_FINALIZE(RS_RET_NOT_FOUND); } if (*pjson == NULL) { /* we had a NULL json object and represent this as empty string */ *pcstr = (uchar *)strdup(""); } else { if (json_object_get_type(*pjson) == json_type_string) { *pcstr = (uchar *)strdup(jsonToString(*pjson)); *pjson = NULL; } } finalize_it: /* we need a deep copy, as another thread may modify the object */ if (*pjson != NULL) *pjson = jsonDeepCopy(*pjson); if (mut != NULL) pthread_mutex_unlock(mut); RETiRet; } /* Get a JSON-based-variable as native json object */ rsRetVal msgGetJSONPropJSON(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **pjson) { struct json_object **jroot; uchar *leaf; struct json_object *parent; pthread_mutex_t *mut = NULL; DEFiRet; *pjson = NULL; CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); #ifdef HAVE_LOGNORM_TURBO msgMaterializeTurboJSON(pMsg); #endif if (!strcmp((char *)pProp->name, "!")) { *pjson = *jroot; FINALIZE; } leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen); CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0)); if (jsonVarExtract(parent, (char *)leaf, pjson) == FALSE) { ABORT_FINALIZE(RS_RET_NOT_FOUND); } finalize_it: /* we need a deep copy, as another thread may modify the object */ if (*pjson != NULL) *pjson = jsonDeepCopy(*pjson); if (mut != NULL) pthread_mutex_unlock(mut); RETiRet; } /* Helper for jsonAddVal(), to be called onces we know there are actually * json escapes inside the string. If so, this function takes over. * Splitting the functions permits us to make some performance optimizations. * For further details, see jsonAddVal(). */ static rsRetVal ATTR_NONNULL(1, 4) jsonAddVal_escaped(uchar *const pSrc, const unsigned buflen, const unsigned len_none_escaped_head, es_str_t **dst, const int escapeAll) { unsigned char c; es_size_t i; char numbuf[4]; unsigned ni; unsigned char nc; int j; uchar wrkbuf[100000]; size_t dst_realloc_size; size_t dst_size; uchar *dst_base = NULL; uchar *dst_w; uchar *newbuf; DEFiRet; assert(len_none_escaped_head <= buflen); /* first copy over unescaped head string */ if ((size_t)len_none_escaped_head > sizeof(wrkbuf) - 10) { /* The following condition is not expected to occur in normal operation. */ #if UINT_MAX > SIZE_MAX / 2 if ((size_t)len_none_escaped_head > SIZE_MAX / 2) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } #endif dst_size = (size_t)len_none_escaped_head * 2; CHKmalloc(dst_base = malloc(dst_size)); } else { dst_size = sizeof(wrkbuf); dst_base = wrkbuf; } dst_realloc_size = dst_size - 10; /* some buffer for escaping */ dst_w = dst_base; memcpy(dst_w, pSrc, len_none_escaped_head); dst_w += len_none_escaped_head; /* now do the escaping */ for (i = len_none_escaped_head; i < buflen; ++i) { const size_t dst_offset = dst_w - dst_base; if (dst_offset >= dst_realloc_size) { if (dst_size > SIZE_MAX / 2) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } const size_t new_size = 2 * dst_size; if (dst_base == wrkbuf) { CHKmalloc(newbuf = malloc(new_size)); memcpy(newbuf, dst_base, dst_offset); } else { CHKmalloc(newbuf = realloc(dst_base, new_size)); } dst_size = new_size; dst_realloc_size = new_size - 10; /* some buffer for escaping */ dst_base = newbuf; dst_w = dst_base + dst_offset; } c = pSrc[i]; if ((c >= 0x30 && c <= 0x5b) || (c >= 0x23 && c <= 0x2e) || (c >= 0x5d /* && c <= 0x10FFFF*/) || c == 0x20 || c == 0x21) { /* no need to escape */ *dst_w++ = c; } else { /* we must escape, try RFC4627-defined special sequences first */ switch (c) { case '\0': *dst_w++ = '\\'; *dst_w++ = 'u'; *dst_w++ = '0'; *dst_w++ = '0'; *dst_w++ = '0'; *dst_w++ = '0'; break; case '\"': *dst_w++ = '\\'; *dst_w++ = '"'; break; case '/': *dst_w++ = '\\'; *dst_w++ = '/'; break; case '\\': if (escapeAll == RSFALSE) { ni = i + 1; if (ni < buflen) { nc = pSrc[ni]; /* Attempt to not double encode */ if (nc == '"' || nc == '/' || nc == '\\' || nc == 'b' || nc == 'f' || nc == 'n' || nc == 'r' || nc == 't' || nc == 'u') { *dst_w++ = c; *dst_w++ = nc; i = ni; break; } } } *dst_w++ = '\\'; *dst_w++ = '\\'; break; case '\010': *dst_w++ = '\\'; *dst_w++ = 'b'; break; case '\014': *dst_w++ = '\\'; *dst_w++ = 'f'; break; case '\n': *dst_w++ = '\\'; *dst_w++ = 'n'; break; case '\r': *dst_w++ = '\\'; *dst_w++ = 'r'; break; case '\t': *dst_w++ = '\\'; *dst_w++ = 't'; break; default: /* TODO : proper Unicode encoding (see header comment) */ for (j = 0; j < 4; ++j) { numbuf[3 - j] = hexdigit[c % 16]; c = c / 16; } *dst_w++ = '\\'; *dst_w++ = 'u'; *dst_w++ = numbuf[0]; *dst_w++ = numbuf[1]; *dst_w++ = numbuf[2]; *dst_w++ = numbuf[3]; break; } } } if (*dst == NULL) { *dst = es_newStrFromBuf((char *)dst_base, dst_w - dst_base); } else { es_addBuf(dst, (const char *)dst_base, dst_w - dst_base); } finalize_it: if (dst_base != NULL && dst_base != wrkbuf) { free(dst_base); } RETiRet; } /* Encode a JSON value and add it to provided string. Note that * the string object may be NULL. In this case, it is created * if and only if escaping is needed. if escapeAll is false, previously * escaped strings are left as is */ static rsRetVal ATTR_NONNULL(1, 3) jsonAddVal(uchar *const pSrc, const unsigned buflen, es_str_t **dst, const int escapeAll) { es_size_t i; DEFiRet; for (i = 0; i < buflen; ++i) { const uchar c = pSrc[i]; if (!((c >= 0x30 && c <= 0x5b) || (c >= 0x23 && c <= 0x2e) || (c >= 0x5d /* && c <= 0x10FFFF*/) || c == 0x20 || c == 0x21)) { iRet = jsonAddVal_escaped(pSrc, buflen, i, dst, escapeAll); FINALIZE; } } if (*dst != NULL) { es_addBuf(dst, (const char *)pSrc, buflen); } finalize_it: RETiRet; } /* encode a property in JSON escaped format. This is a helper * to MsgGetProp. It needs to update all provided parameters. * For performance reasons, we begin to copy the string only * when we recognice that we actually need to do some escaping. * rgerhards, 2012-03-16 */ static rsRetVal jsonEncode(uchar **ppRes, unsigned short *pbMustBeFreed, int *pBufLen, int escapeAll) { unsigned buflen; uchar *pSrc; es_str_t *dst = NULL; DEFiRet; pSrc = *ppRes; buflen = (*pBufLen == -1) ? (int)ustrlen(pSrc) : *pBufLen; CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll)); if (dst != NULL) { /* we updated the string and need to replace the * previous data. */ if (*pbMustBeFreed) free(*ppRes); CHKmalloc(*ppRes = (uchar *)es_str2cstr(dst, NULL)); *pbMustBeFreed = 1; *pBufLen = -1; es_deleteStr(dst); } finalize_it: RETiRet; } /* Format a property as JSON field, that means * "name"="value" * where value is JSON-escaped (here we assume that the name * only contains characters from the valid character set). * Note: this function duplicates code from jsonEncode(). * TODO: these two functions should be combined, at least if * that makes any sense from a performance PoV - definitely * something to consider at a later stage. rgerhards, 2012-04-19 */ static rsRetVal ATTR_NONNULL() jsonField(const struct templateEntry *const pTpe, uchar **const ppRes, unsigned short *const pbMustBeFreed, int *const pBufLen, int escapeAll) { unsigned buflen; uchar *pSrc; es_str_t *dst = NULL; int is_numeric = 1; DEFiRet; pSrc = *ppRes; buflen = (*pBufLen == -1) ? (int)ustrlen(pSrc) : *pBufLen; dbgprintf("jsonEncode: datatype: %u, onEmpty: %u val %*s\n", (unsigned)pTpe->data.field.options.dataType, (unsigned)pTpe->data.field.options.onEmpty, buflen, pSrc); if (buflen == 0) { if (pTpe->data.field.options.onEmpty == TPE_DATAEMPTY_SKIP) { FINALIZE; } is_numeric = 0; } else if (pTpe->data.field.options.dataType == TPE_DATATYPE_NUMBER) { /* trim whitespace for numeric checks */ while (buflen > 0 && isspace((int)*pSrc)) { ++pSrc; --buflen; } while (buflen > 0 && isspace((int)pSrc[buflen - 1])) --buflen; if (pTpe->data.field.options.bOmitIfZero && buflen == 1 && pSrc[0] == '0') { *pBufLen = 0; FINALIZE; } } /* we hope we have only few escapes... */ if (pTpe->lenFieldName < 0 || (size_t)pTpe->lenFieldName > (size_t)INT_MAX - 15 || buflen > (size_t)INT_MAX - (size_t)pTpe->lenFieldName - 15) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(dst = es_newStr(buflen + pTpe->lenFieldName + 15)); es_addChar(&dst, '"'); es_addBuf(&dst, (char *)pTpe->fieldName, pTpe->lenFieldName); es_addBufConstcstr(&dst, "\":"); if (buflen == 0 && pTpe->data.field.options.onEmpty == TPE_DATAEMPTY_NULL) { es_addBufConstcstr(&dst, "null"); } else { if (pTpe->data.field.options.dataType == TPE_DATATYPE_AUTO) { for (unsigned i = 0; i < buflen; ++i) { if (pSrc[i] < '0' || pSrc[i] > '9') { is_numeric = 0; break; } } if (!is_numeric) { es_addChar(&dst, '"'); } CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll)); if (!is_numeric) { es_addChar(&dst, '"'); } } else if (pTpe->data.field.options.dataType == TPE_DATATYPE_STRING) { es_addChar(&dst, '"'); CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll)); es_addChar(&dst, '"'); } else if (pTpe->data.field.options.dataType == TPE_DATATYPE_NUMBER) { if (buflen == 0) { es_addChar(&dst, '0'); } else { CHKiRet(jsonAddVal(pSrc, buflen, &dst, escapeAll)); } } else if (pTpe->data.field.options.dataType == TPE_DATATYPE_BOOL) { if (buflen == 1 && *pSrc == '0') { es_addBufConstcstr(&dst, "false"); } else { es_addBufConstcstr(&dst, "true"); } } } if (*pbMustBeFreed) free(*ppRes); /* we know we do not have \0 chars - so the size does not change */ *pBufLen = es_strlen(dst); CHKmalloc(*ppRes = (uchar *)es_str2cstr(dst, NULL)); *pbMustBeFreed = 1; es_deleteStr(dst); finalize_it: RETiRet; } /* This function returns a string-representation of the * requested message property. This is a generic function used * to abstract properties so that these can be easier * queried. Returns NULL if property could not be found. * Actually, this function is a big if..elseif. What it does * is simply to map property names (from MonitorWare) to the * message object data fields. * * In case we need string forms of propertis we do not * yet have in string form, we do a memory allocation that * is sufficiently large (in all cases). Once the string * form has been obtained, it is saved until the Msg object * is finally destroyed. This is so that we save the processing * time in the (likely) case that this property is requested * again. It also saves us a lot of dynamic memory management * issues in the upper layers, because we so can guarantee that * the buffer will remain static AND available during the lifetime * of the object. Please note that both the max size allocation as * well as keeping things in memory might like look like a * waste of memory (some might say it actually is...) - we * deliberately accept this because performance is more important * to us ;) * rgerhards 2004-11-18 * Parameter "bMustBeFreed" is set by this function. It tells the * caller whether or not the string returned must be freed by the * caller itself. It is is 0, the caller MUST NOT free it. If it is * 1, the caller MUST free it. Handling this wrongly leads to either * a memory leak of a program abort (do to double-frees or frees on * the constant memory pool). So be careful to do it right. * rgerhards 2004-11-23 * regular expression support contributed by Andres Riancho merged * on 2005-09-13 * changed so that it now an be called without a template entry (NULL). * In this case, only the (unmodified) property is returned. This will * be used in selector line processing. * rgerhards 2005-09-15 */ /* a quick helper to save some writing: */ #define RET_OUT_OF_MEMORY \ { \ *pbMustBeFreed = 0; \ *pPropLen = sizeof("**OUT OF MEMORY**") - 1; \ return (UCHAR_CONSTANT("**OUT OF MEMORY**")); \ } /** * \brief Helper function to generate a string property from a source buffer. * * This function allocates a new buffer, copies the content from the source, * null-terminates it, and manages the memory of the previous result string. * * \param[in,out] ppRes Pointer to the result string pointer. The old string is freed if *pbMustBeFreed is set. * The new string is assigned to *ppRes. * \param[in,out] pbMustBeFreed Pointer to the boolean flag indicating if *ppRes must be freed. * Updated to 1 (true) upon successful allocation. * \param[out] pBufLen Pointer to store the length of the new string. * \param[in] pSrc Pointer to the source buffer to copy from. * \param[in] len Length of the data to copy. * * \return rsRetVal RS_RET_OK on success, RS_RET_OUT_OF_MEMORY on allocation failure. */ static rsRetVal msgPropStrGen( uchar **ppRes, unsigned short *pbMustBeFreed, rs_size_t *pBufLen, const uchar *pSrc, size_t len) { uchar *pBuf = NULL; DEFiRet; if (len > (size_t)INT_MAX || len == SIZE_MAX) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKmalloc(pBuf = malloc(len + 1)); memcpy(pBuf, pSrc, len); pBuf[len] = '\0'; if (*pbMustBeFreed == 1) free(*ppRes); *ppRes = pBuf; *pbMustBeFreed = 1; *pBufLen = (rs_size_t)len; finalize_it: if (iRet != RS_RET_OK) { free(pBuf); } RETiRet; } uchar *MsgGetProp(smsg_t *__restrict__ const pMsg, struct templateEntry *__restrict__ const pTpe, msgPropDescr_t *pProp, rs_size_t *__restrict__ const pPropLen, unsigned short *__restrict__ const pbMustBeFreed, struct syslogTime *const ttNow) { uchar *pRes; /* result pointer */ rs_size_t bufLen = -1; /* length of string or -1, if not known */ uchar *pBufStart; uchar *pBuf; int iLen; short iOffs; enum tplFormatTypes datefmt; int bDateInUTC; assert(pMsg != NULL); assert(pbMustBeFreed != NULL); #ifdef FEATURE_REGEXP /* Variables necessary for regular expression matching */ size_t nmatch = TPL_REGEX_MAX_MATCHES; regmatch_t pmatch[TPL_REGEX_MAX_MATCHES]; #endif *pbMustBeFreed = 0; switch (pProp->id) { case PROP_MSG: pRes = getMSG(pMsg); bufLen = getMSGLen(pMsg); break; case PROP_TIMESTAMP: if (pTpe != NULL) { datefmt = pTpe->data.field.eDateFormat; bDateInUTC = pTpe->data.field.options.bDateInUTC; } else { datefmt = tplFmtDefault; bDateInUTC = 0; } if (bDateInUTC) { pRes = (uchar *)getTimeUTC(&pMsg->tTIMESTAMP, datefmt, pbMustBeFreed); } else { pRes = (uchar *)getTimeReported(pMsg, datefmt); } break; case PROP_HOSTNAME: pRes = (uchar *)getHOSTNAME(pMsg); bufLen = getHOSTNAMELen(pMsg); break; case PROP_SYSLOGTAG: getTAG(pMsg, &pRes, &bufLen, LOCK_MUTEX); break; case PROP_RAWMSG: getRawMsg(pMsg, &pRes, &bufLen); break; case PROP_RAWMSG_AFTER_PRI: getRawMsgAfterPRI(pMsg, &pRes, &bufLen); break; case PROP_INPUTNAME: getInputName(pMsg, &pRes, &bufLen); break; case PROP_FROMHOST: MsgGetRcvFromProp(pMsg, PROP_FROMHOST, &pRes, &bufLen); break; case PROP_FROMHOST_IP: MsgGetRcvFromProp(pMsg, PROP_FROMHOST_IP, &pRes, &bufLen); break; case PROP_FROMHOST_PORT: MsgGetRcvFromProp(pMsg, PROP_FROMHOST_PORT, &pRes, &bufLen); break; case PROP_PRI: pRes = (uchar *)getPRI(pMsg); break; case PROP_PRI_TEXT: pRes = textpri(pMsg); if (pRes == NULL) RET_OUT_OF_MEMORY; *pbMustBeFreed = 1; break; case PROP_IUT: pRes = UCHAR_CONSTANT("1"); /* always 1 for syslog messages (a MonitorWare thing;)) */ bufLen = 1; break; case PROP_SYSLOGFACILITY: pRes = (uchar *)getFacility(pMsg); break; case PROP_SYSLOGFACILITY_TEXT: pRes = (uchar *)getFacilityStr(pMsg); break; case PROP_SYSLOGSEVERITY: pRes = (uchar *)getSeverity(pMsg); break; case PROP_SYSLOGSEVERITY_TEXT: pRes = (uchar *)getSeverityStr(pMsg); break; case PROP_TIMEGENERATED: if (pTpe != NULL) { datefmt = pTpe->data.field.eDateFormat; bDateInUTC = pTpe->data.field.options.bDateInUTC; } else { datefmt = tplFmtDefault; bDateInUTC = 0; } if (bDateInUTC) { pRes = (uchar *)getTimeUTC(&pMsg->tRcvdAt, datefmt, pbMustBeFreed); } else { pRes = (uchar *)getTimeGenerated(pMsg, datefmt); } break; case PROP_PROGRAMNAME: pRes = getProgramName(pMsg, LOCK_MUTEX); break; case PROP_PROTOCOL_VERSION: pRes = (uchar *)getProtocolVersionString(pMsg); break; case PROP_STRUCTURED_DATA: MsgGetStructuredData(pMsg, &pRes, &bufLen); break; case PROP_APP_NAME: pRes = (uchar *)getAPPNAME(pMsg, LOCK_MUTEX); break; case PROP_PROCID: pRes = (uchar *)getPROCID(pMsg, LOCK_MUTEX); break; case PROP_MSGID: pRes = (uchar *)getMSGID(pMsg); break; case PROP_JSONMESG: pRes = (uchar *)msgGetJSONMESG(pMsg); *pbMustBeFreed = 1; break; #ifdef USE_LIBUUID case PROP_UUID: getUUID(pMsg, &pRes, &bufLen); break; #endif case PROP_PARSESUCCESS: pRes = (uchar *)getParseSuccess(pMsg); break; case PROP_SYS_NOW: if ((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 10; } break; case PROP_SYS_YEAR: if ((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 4; } break; case PROP_SYS_MONTH: if ((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_DAY: if ((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_HOUR: if ((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_HHOUR: if ((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_QHOUR: if ((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_MINUTE: if ((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_NOW_UTC: if ((pRes = getNOW(NOW_NOW, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 10; } break; case PROP_SYS_YEAR_UTC: if ((pRes = getNOW(NOW_YEAR, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 4; } break; case PROP_SYS_MONTH_UTC: if ((pRes = getNOW(NOW_MONTH, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_DAY_UTC: if ((pRes = getNOW(NOW_DAY, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_HOUR_UTC: if ((pRes = getNOW(NOW_HOUR, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_HHOUR_UTC: if ((pRes = getNOW(NOW_HHOUR, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_QHOUR_UTC: if ((pRes = getNOW(NOW_QHOUR, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_MINUTE_UTC: if ((pRes = getNOW(NOW_MINUTE, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 2; } break; case PROP_SYS_WDAY: if ((pRes = getNOW(NOW_WDAY, ttNow, TIME_IN_LOCALTIME)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 1; } break; case PROP_SYS_WDAY_UTC: if ((pRes = getNOW(NOW_WDAY, ttNow, TIME_IN_UTC)) == NULL) { RET_OUT_OF_MEMORY; } else { *pbMustBeFreed = 1; bufLen = 1; } break; case PROP_SYS_NOW_UXTIMESTAMP: if ((pRes = malloc(16)) == NULL) { RET_OUT_OF_MEMORY; } else { snprintf((char *)pRes, 16 - 1, "%lld", (long long)getTime(NULL)); pRes[16 - 1] = '\0'; *pbMustBeFreed = 1; bufLen = -1; } break; case PROP_SYS_MYHOSTNAME: pRes = glbl.GetLocalHostName(); break; case PROP_CEE_ALL_JSON: case PROP_CEE_ALL_JSON_PLAIN: MsgLock(pMsg); #ifdef HAVE_LOGNORM_TURBO msgMaterializeTurboJSON(pMsg); #endif if (pMsg->json == NULL) { MsgUnlock(pMsg); pRes = (uchar *)"{}"; bufLen = 2; *pbMustBeFreed = 0; } else { const char *jstr; int jflag = 0; if (pProp->id == PROP_CEE_ALL_JSON) { jflag = JSON_C_TO_STRING_SPACED; } else if (pProp->id == PROP_CEE_ALL_JSON_PLAIN) { jflag = JSON_C_TO_STRING_PLAIN; } jstr = json_object_to_json_string_ext(pMsg->json, jflag); if (jstr == NULL) { MsgUnlock(pMsg); RET_OUT_OF_MEMORY; } pRes = (uchar *)strdup(jstr); MsgUnlock(pMsg); if (pRes == NULL) { RET_OUT_OF_MEMORY; } *pbMustBeFreed = 1; } break; case PROP_CEE: case PROP_LOCAL_VAR: case PROP_GLOBAL_VAR: getJSONPropVal(pMsg, pProp, &pRes, &bufLen, pbMustBeFreed); break; case PROP_SYS_BOM: pRes = (uchar *)"\xEF\xBB\xBF"; *pbMustBeFreed = 0; break; case PROP_SYS_UPTIME: #ifndef HAVE_SYSINFO_UPTIME /* An alternative on some systems (eg Solaris) is to scan * /var/adm/utmpx for last boot time. */ pRes = (uchar *)"UPTIME NOT available on this system"; *pbMustBeFreed = 0; #elif defined(__FreeBSD__) { struct timespec tp; if ((pRes = (uchar *)malloc(32)) == NULL) { RET_OUT_OF_MEMORY; } if (clock_gettime(CLOCK_UPTIME, &tp) == -1) { free(pRes); *pPropLen = sizeof("**SYSCALL FAILED**") - 1; return (UCHAR_CONSTANT("**SYSCALL FAILED**")); } *pbMustBeFreed = 1; snprintf((char *)pRes, 32, "%ld", tp.tv_sec); } #else { struct sysinfo s_info; if ((pRes = (uchar *)malloc(32)) == NULL) { RET_OUT_OF_MEMORY; } if (sysinfo(&s_info) < 0) { free(pRes); *pPropLen = sizeof("**SYSCALL FAILED**") - 1; return (UCHAR_CONSTANT("**SYSCALL FAILED**")); } *pbMustBeFreed = 1; snprintf((char *)pRes, 32, "%ld", s_info.uptime); } #endif break; default: /* there is no point in continuing, we may even otherwise render the * error message unreadable. rgerhards, 2007-07-10 */ dbgprintf("invalid property id: '%d'\n", pProp->id); *pbMustBeFreed = 0; *pPropLen = sizeof("**INVALID PROPERTY NAME**") - 1; return UCHAR_CONSTANT("**INVALID PROPERTY NAME**"); } /* If we did not receive a template pointer, we are already done... */ if (pTpe == NULL || !pTpe->bComplexProcessing) { *pPropLen = (bufLen == -1) ? (int)ustrlen(pRes) : bufLen; return pRes; } /* Now check if we need to make "temporary" transformations (these * are transformations that do not go back into the message - * memory must be allocated for them!). */ /* substring extraction */ /* first we check if we need to extract by field number * rgerhards, 2005-12-22 */ if (pTpe->data.field.has_fields == 1) { size_t iCurrFld; uchar *pFld; uchar *pFldEnd; /* first, skip to the field in question. The field separator * is always one character and is stored in the template entry. */ iCurrFld = 1; pFld = pRes; while (*pFld && iCurrFld < pTpe->data.field.iFieldNr) { /* skip fields until the requested field or end of string is found */ while (*pFld && (uchar)*pFld != pTpe->data.field.field_delim) ++pFld; /* skip to field terminator */ if (*pFld == pTpe->data.field.field_delim) { ++pFld; /* eat it */ #ifdef STRICT_GPLV3 if (pTpe->data.field.field_expand != 0) { while (*pFld == pTpe->data.field.field_delim) { ++pFld; } } #endif ++iCurrFld; } } dbgprintf("field requested %d, field found %d\n", pTpe->data.field.iFieldNr, (int)iCurrFld); if (iCurrFld == pTpe->data.field.iFieldNr) { /* field found, now extract it */ /* first of all, we need to find the end */ pFldEnd = pFld; while (*pFldEnd && *pFldEnd != pTpe->data.field.field_delim) ++pFldEnd; --pFldEnd; /* we are already at the delimiter - so we need to * step back a little not to copy it as part of the field. */ /* we got our end pointer, now do the copy */ /* TODO: code copied from below, this is a candidate for a separate function */ iLen = pFldEnd - pFld + 1; /* the +1 is for an actual char, NOT \0! */ if (msgPropStrGen(&pRes, pbMustBeFreed, &bufLen, pFld, iLen) != RS_RET_OK) { if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } RET_OUT_OF_MEMORY; } } else { /* field not found, return error */ if (*pbMustBeFreed == 1) free(pRes); *pbMustBeFreed = 0; *pPropLen = sizeof("**FIELD NOT FOUND**") - 1; return UCHAR_CONSTANT("**FIELD NOT FOUND**"); } #ifdef FEATURE_REGEXP } else { /* Check for regular expressions */ if (pTpe->data.field.has_regex != 0) { if (pTpe->data.field.has_regex == 2) { /* Could not compile regex before! */ if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } *pPropLen = sizeof("**NO MATCH** **BAD REGULAR EXPRESSION**") - 1; return UCHAR_CONSTANT("**NO MATCH** **BAD REGULAR EXPRESSION**"); } dbgprintf("string to match for regex is: %s\n", pRes); if (objUse(regexp, LM_REGEXP_FILENAME) == RS_RET_OK) { short iTry = 0; uchar bFound = 0; iOffs = 0; /* first see if we find a match, iterating through the series of * potential matches over the string. */ while (!bFound) { int iREstat; iREstat = regexp.regexec(&pTpe->data.field.re, (char *)(pRes + iOffs), nmatch, pmatch, 0); dbgprintf("regexec return is %d\n", iREstat); if (iREstat == 0) { if (pmatch[0].rm_so == -1) { dbgprintf( "oops ... start offset of successful " "regexec is -1\n"); break; } if (iTry == pTpe->data.field.iMatchToUse) { bFound = 1; } else { dbgprintf( "regex found at offset %d, new offset %d, " "tries %d\n", iOffs, (int)(iOffs + pmatch[0].rm_eo), iTry); iOffs += pmatch[0].rm_eo; ++iTry; } } else { break; } } dbgprintf("regex: end search, found %d\n", bFound); if (!bFound) { /* we got no match! */ if (pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) { if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } if (pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR) { bufLen = sizeof("**NO MATCH**") - 1; pRes = UCHAR_CONSTANT("**NO MATCH**"); } else if (pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_ZERO) { bufLen = 1; pRes = UCHAR_CONSTANT("0"); } else { bufLen = 0; pRes = UCHAR_CONSTANT(""); } } } else { /* Match- but did it match the one we wanted? */ /* we got no match! */ if (pmatch[pTpe->data.field.iSubMatchToUse].rm_so == -1) { if (pTpe->data.field.nomatchAction != TPL_REGEX_NOMATCH_USE_WHOLE_FIELD) { if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } if (pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_DFLTSTR) { bufLen = sizeof("**NO MATCH**") - 1; pRes = UCHAR_CONSTANT("**NO MATCH**"); } else if (pTpe->data.field.nomatchAction == TPL_REGEX_NOMATCH_USE_ZERO) { bufLen = 1; pRes = UCHAR_CONSTANT("0"); } else { bufLen = 0; pRes = UCHAR_CONSTANT(""); } } } /* OK, we have a usable match - we now need to malloc pB */ int iLenBuf; iLenBuf = pmatch[pTpe->data.field.iSubMatchToUse].rm_eo - pmatch[pTpe->data.field.iSubMatchToUse].rm_so; if (msgPropStrGen(&pRes, pbMustBeFreed, &bufLen, pRes + iOffs + pmatch[pTpe->data.field.iSubMatchToUse].rm_so, iLenBuf) != RS_RET_OK) { if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } RET_OUT_OF_MEMORY; } } } else { /* we could not load regular expression support. This is quite unexpected at * this stage of processing (after all, the config parser found it), but so * it is. We return an error in that case. -- rgerhards, 2008-03-07 */ dbgprintf("could not get regexp object pointer, so regexp can not be evaluated\n"); if (*pbMustBeFreed == 1) { free(pRes); *pbMustBeFreed = 0; } *pPropLen = sizeof("***REGEXP NOT AVAILABLE***") - 1; return UCHAR_CONSTANT("***REGEXP NOT AVAILABLE***"); } } #endif /* #ifdef FEATURE_REGEXP */ } if (pTpe->data.field.iFromPos != 0 || pTpe->data.field.iToPos != 0) { /* we need to obtain a private copy */ int iFrom, iTo; uchar *pSb; iFrom = pTpe->data.field.iFromPos; iTo = pTpe->data.field.iToPos; if (bufLen == -1) bufLen = ustrlen(pRes); if (pTpe->data.field.options.bFromPosEndRelative) { iFrom = (bufLen < iFrom) ? 0 : bufLen - iFrom; iTo = (bufLen < iTo) ? 0 : bufLen - iTo; } else { /* need to zero-base to and from (they are 1-based!) */ if (iFrom > 0) --iFrom; if (iTo > 0) { --iTo; } else if (iTo < 0) { /* note: we ADD negative value, 0-based (-1)! */ iTo = bufLen - 1 + iTo; if (iTo < 0) { iTo = 0; } } } if (iFrom >= bufLen) { DBGPRINTF("msgGetProp: iFrom %d >= buflen %d, returning empty string\n", iFrom, bufLen); if (*pbMustBeFreed == 1) free(pRes); pRes = (uchar *)""; *pbMustBeFreed = 0; bufLen = 0; } else if (iFrom == 0 && iTo >= bufLen && pTpe->data.field.options.bFixedWidth == 0) { /* in this case, the requested string is a superset of what we already have, * so there is no need to do any processing. This is a frequent case for size-limited * fields like TAG in the default forwarding template (so it is a useful optimization * to check for this condition ;)). -- rgerhards, 2009-07-09 */ ; /*DO NOTHING*/ } else { if (iTo >= bufLen) /* iTo is very large, if no to-position is set in the template! */ if (pTpe->data.field.options.bFixedWidth == 0) iTo = bufLen - 1; iLen = iTo - iFrom + 1; /* the +1 is for an actual char, NOT \0! */ pBufStart = pBuf = malloc(iLen + 1); if (pBuf == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } pSb = pRes; if (iFrom) { /* skip to the start of the substring (can't do pointer arithmetic * because the whole string might be smaller!!) */ while (*pSb && iFrom) { --iFrom; ++pSb; } } /* OK, we are at the begin - now let's copy... */ bufLen = iLen; while (iLen) { if (*pSb) { *pBuf++ = *pSb; ++pSb; } else { *pBuf++ = ' '; } --iLen; } *pBuf = '\0'; bufLen -= iLen; /* subtract remaining length if the string was smaller! */ if (*pbMustBeFreed == 1) free(pRes); pRes = pBufStart; *pbMustBeFreed = 1; } } /* now check if we need to do our "SP if first char is non-space" hack logic */ if (*pRes && pTpe->data.field.options.bSPIffNo1stSP) { /* here, we always destruct the buffer and return a new one */ uchar cFirst = *pRes; /* save first char */ if (*pbMustBeFreed == 1) free(pRes); pRes = (cFirst == ' ') ? UCHAR_CONSTANT("") : UCHAR_CONSTANT(" "); bufLen = (cFirst == ' ') ? 0 : 1; *pbMustBeFreed = 0; } if (*pRes) { /* case conversations (should go after substring, because so we are able to * work on the smallest possible buffer). */ if (pTpe->data.field.eCaseConv != tplCaseConvNo) { /* we need to obtain a private copy */ if (bufLen == -1) bufLen = ustrlen(pRes); uchar *pBStart; uchar *pB; uchar *pSrc; pBStart = pB = malloc(bufLen + 1); if (pB == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } pSrc = pRes; while (*pSrc) { *pB++ = (pTpe->data.field.eCaseConv == tplCaseConvUpper) ? (uchar)toupper((int)*pSrc) : (uchar)tolower((int)*pSrc); /* currently only these two exist */ ++pSrc; } *pB = '\0'; if (*pbMustBeFreed == 1) free(pRes); pRes = pBStart; *pbMustBeFreed = 1; } /* now do control character dropping/escaping/replacement * Only one of these can be used. If multiple options are given, the * result is random (though currently there obviously is an order of * preferrence, see code below. But this is NOT guaranteed. * RGerhards, 2006-11-17 * We must copy the strings if we modify them, because they may either * point to static memory or may point into the message object, in which * case we would actually modify the original property (which of course * is wrong). * This was found and fixed by varmojefkoj on 2007-09-11 */ if (pTpe->data.field.options.bDropCC) { int iLenBuf = 0; uchar *pSrc = pRes; uchar *pDstStart; uchar *pDst; uchar bDropped = 0; while (*pSrc) { if (!iscntrl((int)*pSrc++)) iLenBuf++; else bDropped = 1; } if (bDropped) { pDst = pDstStart = malloc(iLenBuf + 1); if (pDst == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } for (pSrc = pRes; *pSrc; pSrc++) { if (!iscntrl((int)*pSrc)) *pDst++ = *pSrc; } *pDst = '\0'; if (*pbMustBeFreed == 1) free(pRes); pRes = pDstStart; bufLen = iLenBuf; *pbMustBeFreed = 1; } } else if (pTpe->data.field.options.bSpaceCC) { uchar *pSrc; uchar *pDstStart; uchar *pDst; if (*pbMustBeFreed == 1) { /* in this case, we already work on dynamic * memory, so there is no need to copy it - we can * modify it in-place without any harm. This is a * performance optiomization. */ for (pDst = pRes; *pDst; pDst++) { if (iscntrl((int)*pDst)) *pDst = ' '; } } else { if (bufLen == -1) bufLen = ustrlen(pRes); pDst = pDstStart = malloc(bufLen + 1); if (pDst == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } for (pSrc = pRes; *pSrc; pSrc++) { if (iscntrl((int)*pSrc)) *pDst++ = ' '; else *pDst++ = *pSrc; } *pDst = '\0'; pRes = pDstStart; *pbMustBeFreed = 1; } } else if (pTpe->data.field.options.bEscapeCC || pTpe->data.field.options.bEscapeCCOctal) { /* we must first count how many control charactes are * present, because we need this to compute the new string * buffer length. While doing so, we also compute the string * length. */ int iNumCC = 0; int iLenBuf = 0; uchar *pSrc; uchar *pB; for (pB = pRes; *pB; ++pB) { ++iLenBuf; if (iscntrl((int)*pB)) ++iNumCC; } if (iNumCC > 0) { /* if 0, there is nothing to escape, so we are done */ /* OK, let's do the escaping... */ uchar *pBStart; uchar szCCEsc[8]; /* buffer for escape sequence */ int i; iLenBuf += iNumCC * 4; pBStart = pB = malloc(iLenBuf + 1); if (pB == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } for (pSrc = pRes; *pSrc; pSrc++) { if (iscntrl((int)*pSrc)) { const unsigned cc = (unsigned char)*pSrc; szCCEsc[0] = '#'; if (pTpe->data.field.options.bEscapeCCOctal) { szCCEsc[1] = (uchar)('0' + ((cc >> 6) & 7)); szCCEsc[2] = (uchar)('0' + ((cc >> 3) & 7)); szCCEsc[3] = (uchar)('0' + (cc & 7)); } else { szCCEsc[1] = (uchar)('0' + (cc / 100)); szCCEsc[2] = (uchar)('0' + ((cc / 10) % 10)); szCCEsc[3] = (uchar)('0' + (cc % 10)); } for (i = 0; i < 4; ++i) *pB++ = szCCEsc[i]; } else { *pB++ = *pSrc; } } *pB = '\0'; if (*pbMustBeFreed == 1) free(pRes); pRes = pBStart; bufLen = -1; *pbMustBeFreed = 1; } } } /* Take care of spurious characters to make the property safe * for a path definition */ if (pTpe->data.field.options.bSecPathDrop || pTpe->data.field.options.bSecPathReplace) { if (pTpe->data.field.options.bSecPathDrop) { int iLenBuf = 0; uchar *pSrc = pRes; uchar *pDstStart; uchar *pDst; uchar bDropped = 0; while (*pSrc) { if (*pSrc++ != '/') iLenBuf++; else bDropped = 1; } if (bDropped) { pDst = pDstStart = malloc(iLenBuf + 1); if (pDst == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } for (pSrc = pRes; *pSrc; pSrc++) { if (*pSrc != '/') *pDst++ = *pSrc; } *pDst = '\0'; if (*pbMustBeFreed == 1) free(pRes); pRes = pDstStart; bufLen = -1; /* TODO: can we do better? */ *pbMustBeFreed = 1; } } else { uchar *pSrc; uchar *pDstStart; uchar *pDst; if (*pbMustBeFreed == 1) { /* here, again, we can modify the string as we already obtained * a private buffer. As we do not change the size of that buffer, * in-place modification is possible. This is a performance * enhancement. */ for (pDst = pRes; *pDst; pDst++) { if (*pDst == '/') *pDst = '_'; } } else { if (bufLen == -1) bufLen = ustrlen(pRes); pDst = pDstStart = malloc(bufLen + 1); if (pDst == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } for (pSrc = pRes; *pSrc; pSrc++) { if (*pSrc == '/') *pDst++ = '_'; else *pDst++ = *pSrc; } *pDst = '\0'; /* we must NOT check if it needs to be freed, because we have done * this in the if above. So if we come to hear, the pSrc string needs * not to be freed (and we do not need to care about it). */ pRes = pDstStart; *pbMustBeFreed = 1; } } /* check for "." and ".." (note the parenthesis in the if condition!) */ if (*pRes == '\0') { if (*pbMustBeFreed == 1) free(pRes); pRes = UCHAR_CONSTANT("_"); bufLen = 1; *pbMustBeFreed = 0; } else if ((*pRes == '.') && (*(pRes + 1) == '\0' || (*(pRes + 1) == '.' && *(pRes + 2) == '\0'))) { uchar *pTmp = pRes; if (*(pRes + 1) == '\0') pRes = UCHAR_CONSTANT("_"); else pRes = UCHAR_CONSTANT("_."); ; if (*pbMustBeFreed == 1) free(pTmp); *pbMustBeFreed = 0; } } /* Now drop last LF if present (pls note that this must not be done * if bEscapeCC was set)! */ if (pTpe->data.field.options.bDropLastLF && !pTpe->data.field.options.bEscapeCC) { int iLn; uchar *pB; if (bufLen == -1) bufLen = ustrlen(pRes); iLn = bufLen; if (iLn > 0 && *(pRes + iLn - 1) == '\n') { /* we have a LF! */ /* check if we need to obtain a private copy */ if (*pbMustBeFreed == 0) { /* ok, original copy, need a private one */ pB = malloc(iLn + 1); if (pB == NULL) { RET_OUT_OF_MEMORY; } memcpy(pB, pRes, iLn - 1); pRes = pB; *pbMustBeFreed = 1; } *(pRes + iLn - 1) = '\0'; /* drop LF ;) */ --bufLen; } } /* Now everything is squased as much as possible and more or less ready to * go. This is the perfect place to compress any remaining spaces, if so * instructed by the user/config. */ if (pTpe->data.field.options.bCompressSP) { int needCompress = 0; int hadSP = 0; uchar *pB; if (*pbMustBeFreed == 0) { for (pB = pRes; *pB && needCompress == 0; ++pB) { if (*pB == ' ') { if (hadSP) { uchar *const tmp = ustrdup(pRes); if (tmp == NULL) /* better not compress than * loose message. */ break; *pbMustBeFreed = 1; pRes = tmp; needCompress = 1; } else { hadSP = 1; } } } } else { /* If we can modify the buffer in any case, we * do NOT check if we actually need to compress, * but "just do it" - that's the quickest way * to get it done. */ needCompress = 1; } if (needCompress) { hadSP = 0; uchar *pDst = pRes; int needCopy = 0; for (pB = pRes; *pB; ++pB) { if (*pB == ' ') { if (hadSP) { needCopy = 1; } else { hadSP = 1; if (needCopy) *pDst = *pB; ++pDst; } } else { hadSP = 0; if (needCopy) *pDst = *pB; ++pDst; } } *pDst = '\0'; bufLen = pDst - pRes; } } /* finally, we need to check if the property should be formatted in CSV or JSON. * For CSV we use RFC 4180, and always use double quotes. As of this writing, * this should be the last action carried out on the property, but in the * future there may be reasons to change that. -- rgerhards, 2009-04-02 */ if (pTpe->data.field.options.bCSV) { /* we need to obtain a private copy, as we need to at least add the double quotes */ int iBufLen; uchar *pBStart; uchar *pDst; uchar *pSrc; if (bufLen == -1) bufLen = ustrlen(pRes); iBufLen = bufLen; /* the malloc may be optimized, we currently use the worst case... */ pBStart = pDst = malloc(2 * iBufLen + 3); if (pDst == NULL) { if (*pbMustBeFreed == 1) free(pRes); RET_OUT_OF_MEMORY; } pSrc = pRes; *pDst++ = '"'; /* starting quote */ while (*pSrc) { if (*pSrc == '"') *pDst++ = '"'; /* need to add double double quote (see RFC4180) */ *pDst++ = *pSrc++; } *pDst++ = '"'; /* ending quote */ *pDst = '\0'; if (*pbMustBeFreed == 1) free(pRes); pRes = pBStart; bufLen = -1; *pbMustBeFreed = 1; } else if (pTpe->data.field.options.bJSON) { jsonEncode(&pRes, pbMustBeFreed, &bufLen, RSTRUE); } else if (pTpe->data.field.options.bJSONf) { jsonField(pTpe, &pRes, pbMustBeFreed, &bufLen, RSTRUE); } else if (pTpe->data.field.options.bJSONr) { jsonEncode(&pRes, pbMustBeFreed, &bufLen, RSFALSE); } else if (pTpe->data.field.options.bJSONfr) { jsonField(pTpe, &pRes, pbMustBeFreed, &bufLen, RSFALSE); } *pPropLen = (bufLen == -1) ? (int)ustrlen(pRes) : bufLen; return (pRes); } /* Set a single property based on the JSON object provided. The * property name is extracted from the JSON object. */ static rsRetVal msgSetPropViaJSON(smsg_t *__restrict__ const pMsg, const char *name, struct json_object *json, int sharedReference) { const char *psz; int val; prop_t *propFromHost = NULL; prop_t *propRcvFromIP = NULL; int bNeedFree = 1; DEFiRet; /* note: jsonToString() manages the memory of the returned * string. So we MUST NOT free it! */ dbgprintf("DDDD: msgSetPropViaJSON key: '%s'\n", name); if (json == NULL) { /* Ignore a JSON null value: a core property can be neither null nor * unset, and the setters below would otherwise crash on * strlen(jsonToString(NULL)). */ DBGPRINTF("msgSetPropViaJSON: null value for property '%s' ignored\n", name); return RS_RET_OK; } if (!strcmp(name, "rawmsg")) { psz = jsonToString(json); MsgSetRawMsg(pMsg, psz, strlen(psz)); } else if (!strcmp(name, "msg")) { psz = jsonToString(json); MsgReplaceMSG(pMsg, (const uchar *)psz, strlen(psz)); } else if (!strcmp(name, "syslogtag")) { psz = jsonToString(json); MsgSetTAG(pMsg, (const uchar *)psz, strlen(psz)); } else if (!strcmp(name, "pri")) { val = json_object_get_int(json); msgSetPRI(pMsg, val); } else if (!strcmp(name, "syslogfacility")) { val = json_object_get_int(json); if (val >= 0 && val <= 24) pMsg->iFacility = val; else DBGPRINTF("mmexternal: invalid fac %d requested -- ignored\n", val); } else if (!strcmp(name, "syslogseverity")) { val = json_object_get_int(json); if (val >= 0 && val <= 7) pMsg->iSeverity = val; else DBGPRINTF("mmexternal: invalid fac %d requested -- ignored\n", val); } else if (!strcmp(name, "procid")) { psz = jsonToString(json); MsgSetPROCID(pMsg, psz); } else if (!strcmp(name, "msgid")) { psz = jsonToString(json); MsgSetMSGID(pMsg, psz); } else if (!strcmp(name, "structured-data")) { psz = jsonToString(json); MsgSetStructuredData(pMsg, psz); } else if (!strcmp(name, "hostname") || !strcmp(name, "source")) { psz = jsonToString(json); MsgSetHOSTNAME(pMsg, (const uchar *)psz, strlen(psz)); } else if (!strcmp(name, "fromhost")) { psz = jsonToString(json); MsgSetRcvFromStr(pMsg, (const uchar *)psz, strlen(psz), &propFromHost); prop.Destruct(&propFromHost); } else if (!strcmp(name, "fromhost-ip")) { psz = jsonToString(json); MsgSetRcvFromIPStr(pMsg, (const uchar *)psz, strlen(psz), &propRcvFromIP); prop.Destruct(&propRcvFromIP); } else if (!strcmp(name, "$!")) { /* msgAddJSON expects that it can keep the object without incremeting * the json reference count. So we MUST NOT free (_put) the object in * this case. -- rgerhards, 2018-09-14 */ bNeedFree = 0; msgAddJSON(pMsg, (uchar *)"!", json, 0, sharedReference); } else { /* we ignore unknown properties */ DBGPRINTF("msgSetPropViaJSON: unkonwn property ignored: %s\n", name); } if (bNeedFree) { json_object_put(json); } RETiRet; } /* set message properties based on JSON string. This function does it all, * including parsing the JSON string. If an error is detected, the operation * is aborted at the time of error. Any modifications made before the * error ocurs are still PERSISTED. * This function is meant to support the external message modifiction module * interface. As such, replacing properties is expressively permited. Note that * properties which were derived from the message during parsing are NOT * updated if the underlying (raw)msg property is changed. */ rsRetVal MsgSetPropsViaJSON(smsg_t *__restrict__ const pMsg, const uchar *__restrict__ const jsonstr) { struct json_tokener *tokener = NULL; struct json_object *json; const char *errMsg; DEFiRet; DBGPRINTF("DDDDDD: JSON string for message mod: '%s'\n", jsonstr); if (!strcmp((char *)jsonstr, "{}")) /* shortcut for a common case */ FINALIZE; tokener = json_tokener_new(); json = json_tokener_parse_ex(tokener, (char *)jsonstr, ustrlen(jsonstr)); if (Debug) { errMsg = NULL; if (json == NULL) { enum json_tokener_error err; err = tokener->err; if (err != json_tokener_continue) errMsg = json_tokener_error_desc(err); else errMsg = "Unterminated input"; } else if (!json_object_is_type(json, json_type_object)) errMsg = "JSON value is not an object"; if (errMsg != NULL) { DBGPRINTF("MsgSetPropsViaJSON: Error parsing JSON '%s': %s\n", jsonstr, errMsg); } } if (json == NULL || !json_object_is_type(json, json_type_object)) { ABORT_FINALIZE(RS_RET_JSON_UNUSABLE); } MsgSetPropsViaJSON_Object(pMsg, json); finalize_it: if (tokener != NULL) json_tokener_free(tokener); RETiRet; } /* Used by MsgSetPropsViaJSON to set properties. * The same as MsgSetPropsViaJSON only that a json object is given and not a string */ rsRetVal MsgSetPropsViaJSON_Object(smsg_t *__restrict__ const pMsg, struct json_object *json) { DEFiRet; if (json == NULL || !json_object_is_type(json, json_type_object)) { DBGPRINTF("MsgSetPropsViaJSON_Object: json NULL or not object type\n"); ABORT_FINALIZE(RS_RET_JSON_UNUSABLE); } struct json_object_iterator it = json_object_iter_begin(json); struct json_object_iterator itEnd = json_object_iter_end(json); while (!json_object_iter_equal(&it, &itEnd)) { struct json_object *child = json_object_iter_peek_value(&it); json_object_get(child); msgSetPropViaJSON(pMsg, json_object_iter_peek_name(&it), child, 0); json_object_iter_next(&it); } json_object_put(json); finalize_it: RETiRet; } /* get the severity - this is an entry point that * satisfies the base object class getSeverity semantics. * rgerhards, 2008-01-14 */ rsRetVal MsgGetSeverity(smsg_t *const pMsg, int *piSeverity) { *piSeverity = pMsg->iSeverity; return RS_RET_OK; } static uchar *jsonPathGetLeaf(uchar *name, int lenName) { int i; for (i = lenName; i >= 0; --i) if (i == 0) { if (name[0] == '!' || name[0] == '.' || name[0] == '/') break; } else { if (name[i] == '!') break; } if (name[i] == '!' || name[i] == '.' || name[i] == '/') ++i; return name + i; } static json_bool jsonVarExtract(struct json_object *root, const char *key, struct json_object **value) { char namebuf[MAX_VARIABLE_NAME_LEN]; const size_t key_len = strlen(key); const char *array_idx_start = strstr(key, "["); const char *array_idx_end = NULL; char *array_idx_num_end_discovered = NULL; struct json_object *arr = NULL; if (array_idx_start != NULL) { array_idx_end = strstr(array_idx_start, "]"); } if (array_idx_end != NULL && (size_t)(array_idx_end - key + 1) == key_len) { errno = 0; const long idx = strtol(array_idx_start + 1, &array_idx_num_end_discovered, 10); if (errno == 0 && idx >= 0 && array_idx_num_end_discovered == array_idx_end) { const size_t name_len = (size_t)(array_idx_start - key); if (name_len >= sizeof(namebuf)) { return json_object_object_get_ex(root, key, value); } memcpy(namebuf, key, name_len); namebuf[name_len] = '\0'; json_bool found_obj = json_object_object_get_ex(root, namebuf, &arr); if (found_obj && json_object_is_type(arr, json_type_array)) { const size_t len = json_object_array_length(arr); if (len > (size_t)idx) { *value = json_object_array_get_idx(arr, (size_t)idx); if (*value != NULL) return TRUE; } return FALSE; } } } return json_object_object_get_ex(root, key, value); } static rsRetVal jsonPathFindNext( struct json_object *root, uchar *namestart, uchar **name, uchar *leaf, struct json_object **found, int bCreate) { uchar namebuf[MAX_VARIABLE_NAME_LEN]; struct json_object *json; size_t i; uchar *p = *name; DEFiRet; if (*p == '!' || (*name == namestart && (*p == '.' || *p == '/'))) ++p; for (i = 0; *p && !(p == namestart && (*p == '.' || *p == '/')) && *p != '!' && p != leaf; ++i, ++p) { if (i >= sizeof(namebuf) - 1) { LogError(0, RS_RET_INVLD_SETOP, "json path component too long in '%s' - refusing truncated lookup", namestart); ABORT_FINALIZE(RS_RET_INVLD_SETOP); } namebuf[i] = *p; } if (i > 0) { namebuf[i] = '\0'; if (jsonVarExtract(root, (char *)namebuf, &json) == FALSE) { json = NULL; } } else json = root; if (json == NULL) { if (!bCreate) { ABORT_FINALIZE(RS_RET_JNAME_INVALID); } else { if (json_object_get_type(root) != json_type_object) { DBGPRINTF( "jsonPathFindNext with bCreate: not a container in json path, " "name is '%s'\n", namestart); ABORT_FINALIZE(RS_RET_INVLD_SETOP); } json = json_object_new_object(); json_object_object_add(root, (char *)namebuf, json); } } *name = p; *found = json; finalize_it: RETiRet; } static rsRetVal jsonPathFindParent( struct json_object *jroot, uchar *name, uchar *leaf, struct json_object **parent, const int bCreate) { uchar *namestart; DEFiRet; namestart = name; *parent = jroot; while (name < leaf - 1) { CHKiRet(jsonPathFindNext(*parent, namestart, &name, leaf, parent, bCreate)); } if (*parent == NULL) ABORT_FINALIZE(RS_RET_NOT_FOUND); finalize_it: RETiRet; } static rsRetVal jsonMerge(struct json_object *existing, struct json_object *json) { DEFiRet; struct json_object_iterator it = json_object_iter_begin(json); struct json_object_iterator itEnd = json_object_iter_end(json); while (!json_object_iter_equal(&it, &itEnd)) { json_object_object_add(existing, json_object_iter_peek_name(&it), json_object_get(json_object_iter_peek_value(&it))); json_object_iter_next(&it); } /* note: json-c does ref counting. We added all descandants refcounts * in the loop above. So when we now free(_put) the root object, only * root gets freed(). */ json_object_put(json); RETiRet; } /* find a JSON structure element (field or container doesn't matter). */ rsRetVal jsonFind(smsg_t *const pMsg, msgPropDescr_t *pProp, struct json_object **jsonres) { uchar *leaf; struct json_object *parent; struct json_object *field; struct json_object **jroot = NULL; pthread_mutex_t *mut = NULL; DEFiRet; CHKiRet(getJSONRootAndMutex(pMsg, pProp->id, &jroot, &mut)); pthread_mutex_lock(mut); if (*jroot == NULL) { field = NULL; FINALIZE; } if (!strcmp((char *)pProp->name, "!")) { field = *jroot; } else if (!strcmp((char *)pProp->name, ".")) { field = *jroot; } else { leaf = jsonPathGetLeaf(pProp->name, pProp->nameLen); CHKiRet(jsonPathFindParent(*jroot, pProp->name, leaf, &parent, 0)); if (jsonVarExtract(parent, (char *)leaf, &field) == FALSE) field = NULL; } *jsonres = field; finalize_it: if (mut != NULL) pthread_mutex_unlock(mut); RETiRet; } /* check if JSON variable exists (works on terminal var and container) */ rsRetVal ATTR_NONNULL() msgCheckVarExists(smsg_t *const pMsg, msgPropDescr_t *pProp) { struct json_object *jsonres = NULL; DEFiRet; CHKiRet(jsonFind(pMsg, pProp, &jsonres)); if (jsonres == NULL) { iRet = RS_RET_NOT_FOUND; } finalize_it: RETiRet; } rsRetVal msgAddJSON(smsg_t *const pM, uchar *name, struct json_object *json, int force_reset, int sharedReference) { /* TODO: error checks! This is a quick&dirty PoC! */ struct json_object **jroot; struct json_object *parent, *leafnode; struct json_object *given = NULL; uchar *leaf; pthread_mutex_t *mut = NULL; DEFiRet; CHKiRet(getJSONRootAndMutexByVarChar(pM, name[0], &jroot, &mut)); pthread_mutex_lock(mut); #ifdef HAVE_LOGNORM_TURBO msgMaterializeTurboJSON(pM); #endif if (name[0] == '/') { /* globl var special handling */ if (sharedReference) { given = json; json = jsonDeepCopy(json); json_object_put(given); } } if (name[1] == '\0') { /* full tree? */ if (*jroot == NULL) *jroot = json; else CHKiRet(jsonMerge(*jroot, json)); } else { if (*jroot == NULL) { /* now we need a root obj */ *jroot = json_object_new_object(); } leaf = jsonPathGetLeaf(name, ustrlen(name)); iRet = jsonPathFindParent(*jroot, name, leaf, &parent, 1); if (unlikely(iRet != RS_RET_OK)) { json_object_put(json); FINALIZE; } if (json_object_get_type(parent) != json_type_object) { DBGPRINTF( "msgAddJSON: not a container in json path," "name is '%s'\n", name); json_object_put(json); ABORT_FINALIZE(RS_RET_INVLD_SETOP); } if (jsonVarExtract(parent, (char *)leaf, &leafnode) == FALSE) leafnode = NULL; /* json-c code indicates we can simply replace a * json type. Unfortunaltely, this is not documented * as part of the interface spec. We still use it, * because it speeds up processing. If it does not work * at some point, use * json_object_object_del(parent, (char*)leaf); * before adding. rgerhards, 2012-09-17 */ if (force_reset || (leafnode == NULL)) { json_object_object_add(parent, (char *)leaf, json); } else { if (json_object_get_type(json) == json_type_object) { if (json_object_get_type(leafnode) == json_type_object) { CHKiRet(jsonMerge(leafnode, json)); } else { json_object_object_add(parent, (char *)leaf, json); } } else { /* TODO: improve the code below, however, the current * state is not really bad */ if (json_object_get_type(leafnode) == json_type_object) { DBGPRINTF( "msgAddJSON: trying to update a container " "node with a leaf, name is %s - " "forbidden", name); json_object_put(json); ABORT_FINALIZE(RS_RET_INVLD_SETOP); } json_object_object_add(parent, (char *)leaf, json); } } } finalize_it: if (mut != NULL) pthread_mutex_unlock(mut); RETiRet; } rsRetVal msgDelJSON(smsg_t *const pM, uchar *name) { struct json_object **jroot; struct json_object *parent, *leafnode; uchar *leaf; pthread_mutex_t *mut = NULL; DEFiRet; CHKiRet(getJSONRootAndMutexByVarChar(pM, name[0], &jroot, &mut)); pthread_mutex_lock(mut); if (*jroot == NULL) { DBGPRINTF("msgDelJSONVar; jroot empty in unset for property %s\n", name); FINALIZE; } if (name[1] == '\0') { /* full tree! Strange, but I think we should permit this. After all, * we trust rsyslog.conf to be written by the admin. */ DBGPRINTF("unsetting JSON root object\n"); json_object_put(*jroot); *jroot = NULL; } else { leaf = jsonPathGetLeaf(name, ustrlen(name)); CHKiRet(jsonPathFindParent(*jroot, name, leaf, &parent, 0)); if (jsonVarExtract(parent, (char *)leaf, &leafnode) == FALSE) leafnode = NULL; if (leafnode == NULL) { DBGPRINTF("unset JSON: could not find '%s'\n", name); ABORT_FINALIZE(RS_RET_JNAME_NOTFOUND); } else { DBGPRINTF( "deleting JSON value path '%s', " "leaf '%s', type %d\n", name, leaf, json_object_get_type(leafnode)); json_object_object_del(parent, (char *)leaf); } } finalize_it: if (mut != NULL) pthread_mutex_unlock(mut); RETiRet; } /* add Metadata to the message. This is stored in a special JSON * container. Note that only string types are currently supported, * what should pose absolutely no problem with the string-ish nature * of rsyslog metadata. * added 2015-01-09 rgerhards */ rsRetVal msgAddMetadata(smsg_t *const __restrict__ pMsg, uchar *const __restrict__ metaname, uchar *const __restrict__ metaval) { DEFiRet; struct json_object *const json = json_object_new_object(); CHKmalloc(json); struct json_object *const jval = json_object_new_string((char *)metaval); if (jval == NULL) { json_object_put(json); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } json_object_object_add(json, (const char *const)metaname, jval); iRet = msgAddJSON(pMsg, (uchar *)"!metadata", json, 0, 0); finalize_it: RETiRet; } rsRetVal msgAddMultiMetadata(smsg_t *const __restrict__ pMsg, const uchar **__restrict__ metaname, const uchar **__restrict__ metaval, const int count) { DEFiRet; int i = 0; struct json_object *const json = json_object_new_object(); CHKmalloc(json); for (i = 0; i < count; i++) { struct json_object *const jval = json_object_new_string((char *)metaval[i]); if (jval == NULL) { json_object_put(json); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } json_object_object_add(json, (const char *const)metaname[i], jval); } iRet = msgAddJSON(pMsg, (uchar *)"!metadata", json, 0, 0); finalize_it: RETiRet; } struct json_object *jsonDeepCopy(struct json_object *src) { struct json_object *dst = NULL, *json; int arrayLen, i; if (src == NULL) goto done; switch (json_object_get_type(src)) { case json_type_boolean: dst = json_object_new_boolean(json_object_get_boolean(src)); break; case json_type_double: dst = json_object_new_double(json_object_get_double(src)); break; case json_type_int: dst = json_object_new_int64(json_object_get_int64(src)); break; case json_type_string: dst = json_object_new_string(jsonToString(src)); break; case json_type_object: dst = json_object_new_object(); struct json_object_iterator it = json_object_iter_begin(src); struct json_object_iterator itEnd = json_object_iter_end(src); while (!json_object_iter_equal(&it, &itEnd)) { json = jsonDeepCopy(json_object_iter_peek_value(&it)); json_object_object_add(dst, json_object_iter_peek_name(&it), json); json_object_iter_next(&it); } break; case json_type_array: arrayLen = json_object_array_length(src); dst = json_object_new_array(); for (i = 0; i < arrayLen; ++i) { json = json_object_array_get_idx(src, i); json = jsonDeepCopy(json); json_object_array_add(dst, json); } break; case json_type_null: default: DBGPRINTF("jsonDeepCopy(): error unknown type %d\n", json_object_get_type(src)); dst = NULL; break; } done: return dst; } rsRetVal msgSetJSONFromVar(smsg_t *const pMsg, uchar *varname, struct svar *v, int force_reset) { struct json_object *json = NULL; char *cstr; DEFiRet; switch (v->datatype) { case 'S': /* string */ CHKmalloc(cstr = es_str2cstr(v->d.estr, NULL)); json = json_object_new_string(cstr); free(cstr); break; case 'N': /* number (integer) */ json = json_object_new_int64(v->d.n); break; case 'J': /* native JSON */ json = jsonDeepCopy(v->d.json); break; default: DBGPRINTF("msgSetJSONFromVar: unsupported datatype %c\n", v->datatype); ABORT_FINALIZE(RS_RET_ERR); } msgAddJSON(pMsg, varname, json, force_reset, 0); finalize_it: RETiRet; } rsRetVal MsgAddToStructuredData(smsg_t *const pMsg, uchar *toadd, rs_size_t len) { uchar *newptr; rs_size_t newlen; int empty; DEFiRet; empty = pMsg->pszStrucData == NULL || pMsg->pszStrucData[0] == '-'; newlen = (empty) ? len : pMsg->lenStrucData + len; CHKmalloc(newptr = (uchar *)realloc(pMsg->pszStrucData, newlen + 1)); if (empty) { memcpy(newptr, toadd, len); } else { memcpy(newptr + pMsg->lenStrucData, toadd, len); } pMsg->pszStrucData = newptr; pMsg->pszStrucData[newlen] = '\0'; pMsg->lenStrucData = newlen; finalize_it: RETiRet; } /* Fill a message propert description. Space must already be alloced * by the caller. This is for efficiency, as we expect this to happen * as part of a larger structure alloc. * Note that CEE/LOCAL_VAR properties can come in either as * "$!xx"/"$.xx" or "!xx"/".xx" - we will unify them here. */ rsRetVal msgPropDescrFill(msgPropDescr_t *pProp, uchar *name, int nameLen) { propid_t id; int offs; DEFiRet; if (propNameToID(name, &id) != RS_RET_OK) { parser_errmsg("invalid property '%s'", name); /* now try to find some common error causes */ if (!strcasecmp((char *)name, "myhostname")) parser_errmsg( "did you mean '$myhostname' instead of '%s'? " "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "bom")) parser_errmsg( "did you mean '$bom' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "now")) parser_errmsg( "did you mean '$now' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "year")) parser_errmsg( "did you mean '$year' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "month")) parser_errmsg( "did you mean '$month' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "day")) parser_errmsg( "did you mean '$day' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "hour")) parser_errmsg( "did you mean '$hour' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "hhour")) parser_errmsg( "did you mean '$hhour' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "qhour")) parser_errmsg( "did you mean '$qhour' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "minute")) parser_errmsg( "did you mean '$minute' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "now-utc")) parser_errmsg( "did you mean '$now-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "year-utc")) parser_errmsg( "did you mean '$year-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "month-utc")) parser_errmsg( "did you mean '$month-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "day-utc")) parser_errmsg( "did you mean '$day-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "hour-utc")) parser_errmsg( "did you mean '$hour-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "hhour-utc")) parser_errmsg( "did you mean '$hhour-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "qhour-utc")) parser_errmsg( "did you mean '$qhour-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); else if (!strcasecmp((char *)name, "minute-utc")) parser_errmsg( "did you mean '$minute-utc' instead of '%s'?" "See also: https://www.rsyslog.com/rsyslog-info-1/", name); ABORT_FINALIZE(RS_RET_INVLD_PROP); } if (id == PROP_CEE || id == PROP_LOCAL_VAR || id == PROP_GLOBAL_VAR) { /* in these cases, we need the field name for later processing */ /* normalize name: remove $ if present */ offs = (name[0] == '$') ? 1 : 0; pProp->name = ustrdup(name + offs); pProp->nameLen = nameLen - offs; /* we patch the root name, so that support functions do not need to * check for different root chars. */ pProp->name[0] = '!'; } pProp->id = id; finalize_it: RETiRet; } void msgPropDescrDestruct(msgPropDescr_t *pProp) { if (pProp != NULL) { if (pProp->id == PROP_CEE || pProp->id == PROP_LOCAL_VAR || pProp->id == PROP_GLOBAL_VAR) free(pProp->name); } } /* dummy */ static rsRetVal msgQueryInterface(interface_t __attribute__((unused)) * i) { return RS_RET_NOT_IMPLEMENTED; } /* Initialize the message class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-01-04 */ BEGINObjClassInit(msg, 1, OBJ_IS_CORE_MODULE) pthread_mutex_init(&glblVars_lock, NULL); /* request objects we use */ CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(var, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize); /* some more inits */ #ifdef HAVE_MALLOC_TRIM INIT_ATOMIC_HELPER_MUT(mutTrimCtr); #endif ENDObjClassInit(msg) rsyslog-8.2608.0/runtime/PaxHeaders/errmsg.c0000644000000000000000000000013215241075234015670 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.334723937 rsyslog-8.2608.0/runtime/errmsg.c0000664000175000017500000003323015241075234015335 0ustar00rgerrger/* The errmsg object. * * Module begun 2008-03-05 by Rainer Gerhards, based on some code * from syslogd.c. I converted this module to lgpl and have checked that * all contributors agreed to that step. * Now moving to ASL 2.0, and contributor checks tell that there is no need * to take further case, as the code now boils to be either my own or, a few lines, * of the original BSD-licenses sysklogd code. rgerhards, 2012-01-16 * * Copyright 2008-2018 Adiscon GmbH. * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "obj.h" #include "msg.h" #include "errmsg.h" #include "operatingstate.h" #include "atomic.h" #include "srUtils.h" #include "stringbuf.h" #include "rsconf.h" /* static data */ #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif static int bHadErrMsgs; /* indicates if we had error messages since reset of this flag * This is used to abort a run if the config is unclean. */ #ifndef HAVE_ATOMIC_BUILTINS static DEF_ATOMIC_HELPER_MUT(mutHadErrMsgs) = PTHREAD_MUTEX_INITIALIZER; #define MUT_HAD_ERR_MSGS &mutHadErrMsgs #else #define MUT_HAD_ERR_MSGS NULL #endif static int fdOversizeMsgLog = -1; static pthread_mutex_t oversizeMsgLogMut = PTHREAD_MUTEX_INITIALIZER; /* ------------------------------ methods ------------------------------ */ static rsRetVal oversizeJsonAddStringLen(struct json_object *const json, const char *const name, const uchar *const value, const rs_size_t valueLen) { struct json_object *jval = NULL; const uchar *const safeValue = (value == NULL) ? (const uchar *)"" : value; const size_t safeLen = (valueLen == (rs_size_t)-1) ? strlen((const char *)safeValue) : (size_t)valueLen; const int jsonLen = (safeLen > INT_MAX) ? INT_MAX : (int)safeLen; DEFiRet; CHKmalloc(jval = json_object_new_string_len((const char *)safeValue, jsonLen)); json_object_object_add(json, name, jval); finalize_it: RETiRet; } static rsRetVal oversizeJsonAddProp(struct json_object *const json, smsg_t *const pMsg, const char *const name, const propid_t propId, struct templateEntry *const pTpe) { msgPropDescr_t propDescr = {.id = propId, .name = NULL, .nameLen = 0}; struct syslogTime ttNow; uchar *value = NULL; rs_size_t valueLen = -1; unsigned short mustBeFreed = 0; DEFiRet; memset(&ttNow, 0, sizeof(ttNow)); value = MsgGetProp(pMsg, pTpe, &propDescr, &valueLen, &mustBeFreed, &ttNow); CHKiRet(oversizeJsonAddStringLen(json, name, value, valueLen)); finalize_it: if (mustBeFreed) { free(value); } RETiRet; } static rsRetVal oversizeJsonAddMsg(struct json_object *const json, const smsg_t *const pMsg) { uchar *msg = (uchar *)""; rs_size_t msgLen = 0; if (pMsg->pszRawMsg != NULL && pMsg->offMSG >= 0 && pMsg->offMSG <= pMsg->iLenRawMsg && pMsg->iLenMSG > 0 && pMsg->iLenMSG <= pMsg->iLenRawMsg - pMsg->offMSG) { msg = pMsg->pszRawMsg + pMsg->offMSG; msgLen = pMsg->iLenMSG; } return oversizeJsonAddStringLen(json, "msg", msg, msgLen); } static rsRetVal oversizeJsonFromMsg(struct json_object **const json, const smsg_t *const pMsg) { struct templateEntry dateTpe; uchar *value = NULL; int valueLen = 0; DEFiRet; memset(&dateTpe, 0, sizeof(dateTpe)); dateTpe.data.field.eDateFormat = tplFmtRFC3339Date; CHKmalloc(*json = json_object_new_object()); CHKiRet(oversizeJsonAddMsg(*json, pMsg)); getRawMsg(pMsg, &value, &valueLen); CHKiRet(oversizeJsonAddStringLen(*json, "rawmsg", value, valueLen)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "timereported", PROP_TIMESTAMP, &dateTpe)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "hostname", PROP_HOSTNAME, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "syslogtag", PROP_SYSLOGTAG, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "inputname", PROP_INPUTNAME, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "fromhost", PROP_FROMHOST, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "fromhost-ip", PROP_FROMHOST_IP, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "fromhost-port", PROP_FROMHOST_PORT, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "pri", PROP_PRI, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "syslogfacility", PROP_SYSLOGFACILITY, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "syslogseverity", PROP_SYSLOGSEVERITY, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "timegenerated", PROP_TIMEGENERATED, &dateTpe)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "programname", PROP_PROGRAMNAME, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "protocol-version", PROP_PROTOCOL_VERSION, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "structured-data", PROP_STRUCTURED_DATA, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "app-name", PROP_APP_NAME, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "procid", PROP_PROCID, NULL)); CHKiRet(oversizeJsonAddProp(*json, (smsg_t *)pMsg, "msgid", PROP_MSGID, NULL)); #ifdef USE_LIBUUID if (pMsg->pszUUID == NULL) { json_object_object_add(*json, "uuid", NULL); } else { CHKiRet(oversizeJsonAddStringLen(*json, "uuid", pMsg->pszUUID, (rs_size_t)-1)); } #endif if (pMsg->json != NULL) { json_object_object_add(*json, "$!", json_object_get(pMsg->json)); } finalize_it: RETiRet; } /* Resets the error message flag. Must be done before processing config * files. */ void resetErrMsgsFlag(void) { ATOMIC_STORE_32BIT(&bHadErrMsgs, MUT_HAD_ERR_MSGS, 0); } int hadErrMsgs(void) { return ATOMIC_LOAD_32BIT(&bHadErrMsgs, MUT_HAD_ERR_MSGS); } /** @internal * Build and emit a single diagnostic line. * * - If iErrno != 0, append strerror(iErrno). * - If iErrCode is neither NO_ERRCODE nor RS_RET_ERR, append a help URL. * - Truncate to the configured max line length. * - Set the "had error" flag for LOG_ERR. */ static void doLogMsg(const int iErrno, const int iErrCode, const int severity, const char *msg) { char buf[2048]; char errStr[1024]; dbgprintf("Called LogMsg, msg: %s\n", msg); osf_write(OSF_TAG_MSG, msg); if (iErrno != 0) { rs_strerror_r(iErrno, errStr, sizeof(errStr)); if (iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) { snprintf(buf, sizeof(buf), "%s: %s [v%s]", msg, errStr, VERSION); } else { snprintf(buf, sizeof(buf), "%s: %s [v%s try https://www.rsyslog.com/e/%d ]", msg, errStr, VERSION, iErrCode * -1); } } else { if (iErrCode == NO_ERRCODE || iErrCode == RS_RET_ERR) { snprintf(buf, sizeof(buf), "%s [v%s]", msg, VERSION); } else { snprintf(buf, sizeof(buf), "%s [v%s try https://www.rsyslog.com/e/%d ]", msg, VERSION, iErrCode * -1); } } buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */ errno = 0; const int msglen = (int)strlen(buf); if (msglen > glblGetMaxLine(ourConf)) { /* in extreme cases, our error messages may be longer than the configured * max message size. If so, we just truncate without further indication, as * anything else would probably lead to a death loop on error messages. * Note that we do not split, as we really do not anticipate there is * much value in supporting extremely short max message sizes - we assume * it's just a testbench thing. -- rgerhards, 2018-05-11 */ buf[glblGetMaxLine(ourConf)] = '\0'; /* space must be available! */ } glblErrLogger(severity, iErrCode, (uchar *)buf); if (severity == LOG_ERR) ATOMIC_STORE_32BIT(&bHadErrMsgs, MUT_HAD_ERR_MSGS, 1); } /* We now receive three parameters: one is the internal error code * which will also become the error message number, the second is * errno - if it is non-zero, the corresponding error message is included * in the text and finally the message text itself. Note that it is not * 100% clean to use the internal errcode, as it may be reached from * multiple actual error causes. However, it is much better than having * no error code at all (and in most cases, a single internal error code * maps to a specific error event). * rgerhards, 2008-06-27 */ void __attribute__((format(printf, 3, 4))) LogError(const int iErrno, const int iErrCode, const char *fmt, ...) { va_list ap; char buf[2048]; int lenBuf; va_start(ap, fmt); lenBuf = vsnprintf(buf, sizeof(buf), fmt, ap); if (lenBuf < 0) { memcpy(buf, "error message lost due to problem with vsnprintf", sizeof("error message lost due to problem with vsnprintf")); } va_end(ap); buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */ doLogMsg(iErrno, iErrCode, LOG_ERR, buf); } /* We now receive three parameters: one is the internal error code * which will also become the error message number, the second is * errno - if it is non-zero, the corresponding error message is included * in the text and finally the message text itself. Note that it is not * 100% clean to use the internal errcode, as it may be reached from * multiple actual error causes. However, it is much better than having * no error code at all (and in most cases, a single internal error code * maps to a specific error event). * rgerhards, 2008-06-27 */ void __attribute__((format(printf, 4, 5))) LogMsg( const int iErrno, const int iErrCode, const int severity, const char *fmt, ...) { va_list ap; char buf[2048]; int lenBuf; va_start(ap, fmt); lenBuf = vsnprintf(buf, sizeof(buf), fmt, ap); if (lenBuf < 0) { memcpy(buf, "error message lost due to problem with vsnprintf", sizeof("error message lost due to problem with vsnprintf")); } va_end(ap); buf[sizeof(buf) - 1] = '\0'; /* just to be on the safe side... */ doLogMsg(iErrno, iErrCode, severity, buf); } /* Write an oversize message to the oversize message error log. * We do NOT handle errors during writing that log other than emitting * yet another error message. The reason is that there really is nothing * else that we could do in that case. * rgerhards, 2018-05-03 */ rsRetVal ATTR_NONNULL() writeOversizeMessageLog(const smsg_t *const pMsg) { struct json_object *json = NULL; char *rendered = NULL; struct json_object *jval; uchar *buf; size_t toWrite; ssize_t wrRet; int dummy; int mutexLocked = 0; DEFiRet; ISOBJ_TYPE_assert(pMsg, msg); if (glblGetOversizeMsgErrorFile(runConf) == NULL) { FINALIZE; } pthread_mutex_lock(&oversizeMsgLogMut); mutexLocked = 1; if (fdOversizeMsgLog == -1) { fdOversizeMsgLog = open((char *)glblGetOversizeMsgErrorFile(runConf), O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (fdOversizeMsgLog == -1) { LogError(errno, RS_RET_ERR, "error opening oversize message log file %s", glblGetOversizeMsgErrorFile(runConf)); FINALIZE; } } assert(fdOversizeMsgLog != -1); CHKiRet(oversizeJsonFromMsg(&json, pMsg)); /* Preserve the historical oversize errorfile field name while also * emitting the regular full-message JSON field "inputname". */ getInputName(pMsg, &buf, &dummy); CHKmalloc(jval = json_object_new_string((char *)buf)); json_object_object_add(json, "input", jval); CHKmalloc(rendered = strdup((char *)fjson_object_to_json_string(json))); toWrite = strlen(rendered) + 1; /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid * calling malloc() -- write() does NOT need '\0'! */ rendered[toWrite - 1] = '\n'; /* NO LONGER A STRING! */ wrRet = write(fdOversizeMsgLog, rendered, toWrite); if (wrRet != (ssize_t)toWrite) { LogError(errno, RS_RET_IO_ERROR, "error writing oversize message log file %s, write returned %lld", glblGetOversizeMsgErrorFile(runConf), (long long)wrRet); } finalize_it: free(rendered); if (mutexLocked) { pthread_mutex_unlock(&oversizeMsgLogMut); } if (json != NULL) { fjson_object_put(json); } RETiRet; } void errmsgDoHUP(void) { pthread_mutex_lock(&oversizeMsgLogMut); if (fdOversizeMsgLog != -1) { close(fdOversizeMsgLog); fdOversizeMsgLog = -1; } pthread_mutex_unlock(&oversizeMsgLogMut); } void errmsgExit(void) { if (fdOversizeMsgLog != -1) { close(fdOversizeMsgLog); } } rsyslog-8.2608.0/runtime/PaxHeaders/hashtable.c0000644000000000000000000000013215241075234016324 xustar0030 mtime=1787067036.600578201 30 atime=1787067036.746580934 30 ctime=1787067794.479726639 rsyslog-8.2608.0/runtime/hashtable.c0000664000175000017500000002721315241075234015775 0ustar00rgerrger/* Copyright (C) 2004 Christopher Clark */ /* taken from http://www.cl.cam.ac.uk/~cwc22/hashtable/ */ #include "hashtable_private.h" #include #include #include #include /* this code has several warnings, but we ignore them because * this seems to work and we do not want to engage in that code body. If * we really run into troubles, it is better to change to libfastjson, which * we should do in the medium to long term anyhow... */ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wredundant-decls" #endif /* Credit for primes table: Aaron Krowne http://br.endernet.org/~akrowne/ http://planetmath.org/encyclopedia/GoodHashTablePrimes.html */ static const unsigned int primes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; const unsigned int prime_table_length = sizeof(primes) / sizeof(primes[0]); #define MAX_LOAD_FACTOR 65 /* to get real factor, divide by 100! */ /* compute max load. We use a constant factor of 0.65, but do * everything times 100, so that we do not need floats. */ static inline unsigned getLoadLimit(unsigned size) { return (unsigned int)((unsigned long long)size * MAX_LOAD_FACTOR) / 100; } /*****************************************************************************/ struct hashtable *create_hashtable(unsigned int minsize, unsigned int (*hashf)(void *), int (*eqf)(void *, void *), void (*dest)(void *)) { struct hashtable *h; unsigned int pindex, size = primes[0]; /* Check requested hashtable isn't too large */ if (minsize > (1u << 30)) return NULL; /* Enforce size as prime */ for (pindex = 0; pindex < prime_table_length; pindex++) { if (primes[pindex] > minsize) { size = primes[pindex]; break; } } h = (struct hashtable *)malloc(sizeof(struct hashtable)); if (NULL == h) return NULL; /*oom*/ h->table = (struct entry **)malloc(sizeof(struct entry *) * size); if (NULL == h->table) { free(h); return NULL; } /*oom*/ memset(h->table, 0, size * sizeof(struct entry *)); h->tablelength = size; h->primeindex = pindex; h->entrycount = 0; h->hashfn = hashf; h->eqfn = eqf; h->dest = dest; h->loadlimit = getLoadLimit(size); return h; } /*****************************************************************************/ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif unsigned int #if defined(__clang__) __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif hash(struct hashtable *h, void *k) { /* Aim to protect against poor hash functions by adding logic here * - logic taken from java 1.4 hashtable source */ unsigned int i = h->hashfn(k); i += ~(i << 9); i ^= ((i >> 14) | (i << 18)); /* >>> */ i += (i << 4); i ^= ((i >> 10) | (i << 22)); /* >>> */ return i; } /*****************************************************************************/ static int hashtable_expand(struct hashtable *h) { /* Double the size of the table to accomodate more entries */ struct entry **newtable; struct entry *e; struct entry **pE; unsigned int newsize, i, idx; /* Check we're not hitting max capacity */ if (h->primeindex == (prime_table_length - 1)) return 0; newsize = primes[++(h->primeindex)]; newtable = (struct entry **)malloc(sizeof(struct entry *) * newsize); if (NULL != newtable) { memset(newtable, 0, newsize * sizeof(struct entry *)); /* This algorithm is not 'stable'. ie. it reverses the list * when it transfers entries between the tables */ for (i = 0; i < h->tablelength; i++) { while (NULL != (e = h->table[i])) { h->table[i] = e->next; idx = indexFor(newsize, e->h); e->next = newtable[idx]; newtable[idx] = e; } } free(h->table); h->table = newtable; } /* Plan B: realloc instead */ else { newtable = (struct entry **)realloc(h->table, newsize * sizeof(struct entry *)); if (NULL == newtable) { (h->primeindex)--; return 0; } h->table = newtable; memset(&newtable[h->tablelength], 0, (newsize - h->tablelength) * sizeof(struct entry *)); for (i = 0; i < h->tablelength; i++) { for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { idx = indexFor(newsize, e->h); if (idx == i) { pE = &(e->next); } else { *pE = e->next; e->next = newtable[idx]; newtable[idx] = e; } } } } h->tablelength = newsize; h->loadlimit = getLoadLimit(newsize); return -1; } /*****************************************************************************/ unsigned int hashtable_count(struct hashtable *h) { return h->entrycount; } /*****************************************************************************/ unsigned int hashtable_hash(struct hashtable *h, void *k) { return hash(h, k); } /*****************************************************************************/ int hashtable_insert_prehashed(struct hashtable *h, unsigned int hashvalue, void *k, void *v) { /* This method allows duplicate keys - but they shouldn't be used */ unsigned int idx; struct entry *e; if (++(h->entrycount) > h->loadlimit) { /* Ignore the return value. If expand fails, we should * still try cramming just this value into the existing table * -- we may not have memory for a larger table, but one more * element may be ok. Next time we insert, we'll try expanding again.*/ hashtable_expand(h); } e = (struct entry *)malloc(sizeof(struct entry)); if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ e->h = hashvalue; idx = indexFor(h->tablelength, e->h); e->k = k; e->v = v; e->next = h->table[idx]; h->table[idx] = e; return -1; } /*****************************************************************************/ int hashtable_insert(struct hashtable *h, void *k, void *v) { return hashtable_insert_prehashed(h, hashtable_hash(h, k), k, v); } /*****************************************************************************/ void * /* returns value associated with key */ hashtable_search_prehashed(struct hashtable *h, unsigned int hashvalue, void *k) { struct entry *e; unsigned int idx; idx = indexFor(h->tablelength, hashvalue); e = h->table[idx]; while (NULL != e) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; e = e->next; } return NULL; } /*****************************************************************************/ void * /* returns value associated with key */ hashtable_search(struct hashtable *h, void *k) { return hashtable_search_prehashed(h, hashtable_hash(h, k), k); } /*****************************************************************************/ void * /* returns value associated with key */ hashtable_remove_prehashed(struct hashtable *h, unsigned int hashvalue, void *k) { /* TODO: consider compacting the table when the load factor drops enough, * or provide a 'compact' method. */ struct entry *e; struct entry **pE; void *v; unsigned int idx; idx = indexFor(h->tablelength, hashvalue); pE = &(h->table[idx]); e = *pE; while (NULL != e) { /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { *pE = e->next; h->entrycount--; v = e->v; freekey(e->k); free(e); return v; } pE = &(e->next); e = e->next; } return NULL; } /*****************************************************************************/ void * /* returns value associated with key */ hashtable_remove(struct hashtable *h, void *k) { return hashtable_remove_prehashed(h, hashtable_hash(h, k), k); } /*****************************************************************************/ /* destroy */ void hashtable_destroy(struct hashtable *h, int free_values) { unsigned int i; struct entry *e, *f; struct entry **table = h->table; if (free_values) { for (i = 0; i < h->tablelength; i++) { e = table[i]; while (NULL != e) { f = e; e = e->next; freekey(f->k); if (h->dest == NULL) free(f->v); else h->dest(f->v); free(f); } } } else { for (i = 0; i < h->tablelength; i++) { e = table[i]; while (NULL != e) { f = e; e = e->next; freekey(f->k); free(f); } } } free(h->table); free(h); } /* some generic hash functions */ /* one provided by Aaaron Wiebe based on perl's hashing algorithm * (so probably pretty generic). Not for excessively large strings! */ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif unsigned __attribute__((nonnull(1))) int #if defined(__clang__) __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif hash_from_string(void *k) { char *rkey = (char *)k; unsigned hashval = 1; while (*rkey) hashval = hashval * 33 + *rkey++; return hashval; } int key_equals_string(void *key1, void *key2) { /* we must return true IF the keys are equal! */ return !strcmp(key1, key2); } /* * Copyright (c) 2002, Christopher Clark * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ rsyslog-8.2608.0/runtime/PaxHeaders/lmcry_ossl.h0000644000000000000000000000013115132411300016546 xustar0029 mtime=1768559296.26688564 30 atime=1782715518.782788738 30 ctime=1787067794.514727291 rsyslog-8.2608.0/runtime/lmcry_ossl.h0000666000175000017500000000242315132411300016216 0ustar00rgerrger/* An implementation of the cryprov interface for openssl. * * * This file is part of the rsyslog runtime library. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef INCLUDED_LMCRY_OSSL_H #define INCLUDED_LMCRY_OSSL_H #include "cryprov.h" /* interface is defined in cryprov.h, we just implement it! */ #define lmcry_gcryCURR_IF_VERSION cryprovCURR_IF_VERSION typedef cryprov_if_t lmcry_ossl_if_t; /* the lmcry_ossl object */ struct lmcry_ossl_s { BEGINobjInstance ; /* Data to implement generic object - MUST be the first data element! */ osslctx ctx; }; typedef struct lmcry_ossl_s lmcry_ossl_t; /* prototypes */ PROTOTYPEObj(lmcry_ossl); #endif /* #ifndef INCLUDED_LMCRY_GCRY_H */ rsyslog-8.2608.0/runtime/PaxHeaders/conf.c0000644000000000000000000000013215216464436015326 xustar0030 mtime=1782212894.020266087 30 atime=1787067618.044437901 30 ctime=1787067794.281722949 rsyslog-8.2608.0/runtime/conf.c0000664000175000017500000004723315216464436015003 0ustar00rgerrger/* The config file handler (not yet a real object) * * This file is based on an excerpt from syslogd.c, which dates back * much later. I began the file on 2008-02-19 as part of the modularization * effort. Over time, a clean abstraction will become even more important * because the config file handler will by dynamically be loaded and be * kept in memory only as long as the config file is actually being * processed. Thereafter, it shall be unloaded. -- rgerhards * Please note that the original syslogd.c source was under BSD license * at the time of the rsyslog fork from sysklogd. * * Copyright 2008-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define CFGLNSIZ 64 * 1024 /* the maximum size of a configuration file line, after re-combination */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBGEN_H #ifndef OS_SOLARIS #include #endif #endif #include "rsyslog.h" #include "dirty.h" #include "parse.h" #include "action.h" #include "template.h" #include "cfsysline.h" #include "modules.h" #include "outchannel.h" #include "stringbuf.h" #include "conf.h" #include "stringbuf.h" #include "srUtils.h" #include "errmsg.h" #include "net.h" #include "ruleset.h" #include "rsconf.h" #include "unicode-helper.h" #include "rainerscript.h" #ifdef OS_SOLARIS #define NAME_MAX MAXNAMELEN #endif /* forward definitions */ /* static data */ DEFobjStaticHelpers; DEFobjCurrIf(module) DEFobjCurrIf(net) DEFobjCurrIf(ruleset) int bConfStrictScoping = 0; /* force strict scoping during config processing? */ /* The following module-global variables are used for building * tag and host selector lines during startup and config reload. * This is stored as a global variable pool because of its ease. It is * also fairly compatible with multi-threading as the stratup code must * be run in a single thread anyways. So there can be no race conditions. * rgerhards 2005-10-18 */ EHostnameCmpMode eDfltHostnameCmpMode = HN_NO_COMP; cstr_t *pDfltHostnameCmp = NULL; cstr_t *pDfltProgNameCmp = NULL; /* process a $ModLoad config line. */ static rsRetVal doModLoad(uchar **pp, __attribute__((unused)) void *pVal) { DEFiRet; uchar szName[512]; uchar *pModName; assert(pp != NULL); assert(*pp != NULL); skipWhiteSpace(pp); /* skip over any whitespace */ if (getSubString(pp, (char *)szName, sizeof(szName), ' ') != 0) { LogError(0, RS_RET_NOT_FOUND, "could not extract module name"); ABORT_FINALIZE(RS_RET_NOT_FOUND); } skipWhiteSpace(pp); /* skip over any whitespace */ /* this below is a quick and dirty hack to provide compatibility with the * $ModLoad MySQL forward compatibility statement. This needs to be supported * for legacy format. */ if (!strcmp((char *)szName, "MySQL")) pModName = (uchar *)"ommysql.so"; else pModName = szName; CHKiRet(module.Load(pModName, 1, NULL)); finalize_it: RETiRet; } /* remove leading spaces from name; this "fixes" some anomalies in * getSubString(), but I was not brave enough to fix the former as * it has many other callers... -- rgerhards, 2013-05-27 */ static void ltrim(char *src) { char *dst = src; while (isspace(*src)) ++src; /*SKIP*/ ; if (dst != src) { while (*src != '\0') *dst++ = *src++; *dst = '\0'; } } /* parse and interpret a $-config line that starts with * a name (this is common code). It is parsed to the name * and then the proper sub-function is called to handle * the actual directive. * rgerhards 2004-11-17 * rgerhards 2005-06-21: previously only for templates, now * generalized. */ static rsRetVal doNameLine(uchar **pp, void *pVal) { DEFiRet; uchar *p; enum eDirective eDir; char szName[128]; assert(pp != NULL); p = *pp; assert(p != NULL); PRAGMA_DIAGNOSTIC_PUSH PRAGMA_IGNORE_Wvoid_pointer_to_enum_cast; /* this time, pVal actually is NOT a pointer! It is save to case, as * the enum was written to it, so there can be no loss of bits (ptr is larger). */ eDir = (enum eDirective)pVal; PRAGMA_DIAGNOSTIC_POP if (getSubString(&p, szName, sizeof(szName), ',') != 0) { LogError(0, RS_RET_NOT_FOUND, "Invalid config line: could not extract name - line ignored"); ABORT_FINALIZE(RS_RET_NOT_FOUND); } ltrim(szName); if (*p == ',') ++p; /* comma was eaten */ /* we got the name - now we pass name & the rest of the string * to the subfunction. It makes no sense to do further * parsing here, as this is in close interaction with the * respective subsystem. rgerhards 2004-11-17 */ switch (eDir) { case DIR_TEMPLATE: tplAddLine(loadConf, szName, &p); break; case DIR_OUTCHANNEL: ochAddLine(szName, &p); break; case DIR_ALLOWEDSENDER: net.addAllowedSenderLine(szName, &p); break; default: /* we do this to avoid compiler warning - not all * enum values call this function, so an incomplete list * is quite ok (but then we should not run into this code, * so at least we log a debug warning). */ dbgprintf("INTERNAL ERROR: doNameLine() called with invalid eDir %d.\n", eDir); break; } *pp = p; finalize_it: RETiRet; } /* Parse and interpret a system-directive in the config line * A system directive is one that starts with a "$" sign. It offers * extended configuration parameters. * 2004-11-17 rgerhards */ static rsRetVal cfsysline(uchar *p) { DEFiRet; uchar szCmd[64]; assert(p != NULL); errno = 0; if (getSubString(&p, (char *)szCmd, sizeof(szCmd), ' ') != 0) { LogError(0, RS_RET_NOT_FOUND, "Invalid $-configline " "- could not extract command - line ignored\n"); ABORT_FINALIZE(RS_RET_NOT_FOUND); } /* we now try and see if we can find the command in the registered * list of cfsysline handlers. -- rgerhards, 2007-07-31 */ CHKiRet(processCfSysLineCommand(szCmd, &p)); /* now check if we have some extra characters left on the line - that * should not be the case. Whitespace is OK, but everything else should * trigger a warning (that may be an indication of undesired behaviour). * An exception, of course, are comments (starting with '#'). * rgerhards, 2007-07-04 */ skipWhiteSpace(&p); if (*p && *p != '#') { /* we have a non-whitespace, so let's complain */ LogError(0, NO_ERRCODE, "error: extra characters in config line ignored: '%s'", p); } finalize_it: RETiRet; } /* Helper to cfline() and its helpers. Parses a template name * from an "action" line. Must be called with the Line pointer * pointing to the first character after the semicolon. * rgerhards 2004-11-19 * changed function to work with OMSR. -- rgerhards, 2007-07-27 * the default template is to be used when no template is specified. */ rsRetVal cflineParseTemplateName(uchar **pp, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *dfltTplName) { uchar *p; uchar *tplName = NULL; cstr_t *pStrB = NULL; DEFiRet; assert(pp != NULL); assert(*pp != NULL); assert(pOMSR != NULL); p = *pp; /* a template must follow - search it and complain, if not found */ skipWhiteSpace(&p); if (*p == ';') ++p; /* eat it */ else if (*p != '\0' && *p != '#') { LogError(0, RS_RET_ERR, "invalid character in selector line - ';template' expected"); ABORT_FINALIZE(RS_RET_ERR); } skipWhiteSpace(&p); /* go to begin of template name */ if (*p == '\0' || *p == '#') { /* no template specified, use the default */ CHKmalloc(tplName = (uchar *)strdup((char *)dfltTplName)); } else { /* template specified, pick it up */ CHKiRet(cstrConstruct(&pStrB)); /* now copy the string */ while (*p && *p != '#' && !isspace((int)*p)) { CHKiRet(cstrAppendChar(pStrB, *p)); ++p; } cstrFinalize(pStrB); CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &tplName, 0)); } CHKiRet(OMSRsetEntry(pOMSR, iEntry, tplName, iTplOpts)); finalize_it: if (iRet != RS_RET_OK) { free(tplName); if (pStrB != NULL) cstrDestruct(&pStrB); } *pp = p; RETiRet; } /* Helper to cfline(). Parses a file name up until the first * comma and then looks for the template specifier. Tries * to find that template. * rgerhards 2004-11-18 * parameter pFileName must point to a buffer large enough * to hold the largest possible filename. * rgerhards, 2007-07-25 * updated to include OMSR pointer -- rgerhards, 2007-07-27 * updated to include template name -- rgerhards, 2008-03-28 * rgerhards, 2010-01-19: file names end at the first space */ rsRetVal cflineParseFileName( uchar *p, uchar *pFileName, omodStringRequest_t *pOMSR, int iEntry, int iTplOpts, uchar *pszTpl) { register uchar *pName; int i; DEFiRet; assert(pOMSR != NULL); pName = pFileName; i = 1; /* we start at 1 so that we reseve space for the '\0'! */ while (*p && *p != ';' && *p != ' ' && i < MAXFNAME) { *pName++ = *p++; ++i; } *pName = '\0'; iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, pszTpl); RETiRet; } /* Decode a traditional PRI filter */ /* GPLv3 - stems back to sysklogd */ rsRetVal DecodePRIFilter(uchar *pline, uchar pmask[]) { uchar *p; register uchar *q; register int i, i2; uchar *bp; int pri; /* this MUST be int, as -1 is used to convey an error state */ int singlpri = 0; int ignorepri = 0; uchar buf[2048]; /* buffer for facility and priority names */ uchar xbuf[200]; DEFiRet; assert(pline != NULL); dbgprintf("Decoding traditional PRI filter '%s'\n", pline); for (i = 0; i <= LOG_NFACILITIES; i++) { pmask[i] = TABLE_NOPRI; } /* scan through the list of selectors */ for (p = pline; *p && *p != '\t' && *p != ' ';) { /* find the end of this facility name list */ for (q = p; *q && *q != '\t' && *q++ != '.';) continue; /* collect priority name */ for (bp = buf; *q && !strchr("\t ,;", *q) && bp < buf + sizeof(buf) - 1;) *bp++ = *q++; *bp = '\0'; /* skip cruft */ if (*q) { while (strchr(",;", *q)) q++; } /* decode priority name */ if (*buf == '!') { ignorepri = 1; /* copy below is ok, we can NOT go off the allocated area */ for (bp = buf; *(bp + 1); bp++) *bp = *(bp + 1); *bp = '\0'; } else { ignorepri = 0; } if (*buf == '=') { singlpri = 1; pri = decodeSyslogName(&buf[1], syslogPriNames); } else { singlpri = 0; pri = decodeSyslogName(buf, syslogPriNames); } if (pri < 0) { snprintf((char *)xbuf, sizeof(xbuf), "unknown priority name \"%s\"", buf); LogError(0, RS_RET_ERR, "%s", xbuf); return RS_RET_ERR; } /* scan facilities */ while (*p && !strchr("\t .;", *p)) { for (bp = buf; *p && !strchr("\t ,;.", *p) && bp < buf + sizeof(buf) - 1;) *bp++ = *p++; *bp = '\0'; if (*buf == '*') { for (i = 0; i <= LOG_NFACILITIES; i++) { if (pri == INTERNAL_NOPRI) { if (ignorepri) pmask[i] = TABLE_ALLPRI; else pmask[i] = TABLE_NOPRI; } else if (singlpri) { if (ignorepri) { if (pmask[i] == TABLE_NOPRI) pmask[i] = TABLE_ALLPRI; pmask[i] &= ~(1 << pri); } else { pmask[i] |= (1 << pri); } } else { if (pri == TABLE_ALLPRI) { if (ignorepri) pmask[i] = TABLE_NOPRI; else pmask[i] = TABLE_ALLPRI; } else { if (ignorepri) { if (pmask[i] == TABLE_NOPRI) pmask[i] = TABLE_ALLPRI; for (i2 = 0; i2 <= pri; ++i2) pmask[i] &= ~(1 << i2); } else { for (i2 = 0; i2 <= pri; ++i2) pmask[i] |= (1 << i2); } } } } } else { i = decodeSyslogName(buf, syslogFacNames); if (i < 0) { snprintf((char *)xbuf, sizeof(xbuf), "unknown facility name \"%s\"", buf); LogError(0, RS_RET_ERR, "%s", xbuf); return RS_RET_ERR; } if (pri == INTERNAL_NOPRI) { if (ignorepri) pmask[i >> 3] = TABLE_ALLPRI; else pmask[i >> 3] = TABLE_NOPRI; } else if (singlpri) { if (ignorepri) { if (pmask[i >> 3] == TABLE_NOPRI) pmask[i >> 3] = TABLE_ALLPRI; pmask[i >> 3] &= ~(1 << pri); } else { pmask[i >> 3] |= (1 << pri); } } else { if (pri == TABLE_ALLPRI) { if (ignorepri) pmask[i >> 3] = TABLE_NOPRI; else pmask[i >> 3] = TABLE_ALLPRI; } else { if (ignorepri) { if (pmask[i >> 3] == TABLE_NOPRI) pmask[i >> 3] = TABLE_ALLPRI; for (i2 = 0; i2 <= pri; ++i2) pmask[i >> 3] &= ~(1 << i2); } else { for (i2 = 0; i2 <= pri; ++i2) pmask[i >> 3] |= (1 << i2); } } } } while (*p == ',' || *p == ' ') p++; } p = q; } RETiRet; } /* process the action part of a selector line * rgerhards, 2007-08-01 */ rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction) { modInfo_t *pMod; cfgmodules_etry_t *node; omodStringRequest_t *pOMSR; int bHadWarning = 0; action_t *pAction = NULL; void *pModData; DEFiRet; assert(p != NULL); assert(ppAction != NULL); /* loop through all modules and see if one picks up the line */ node = module.GetNxtCnfType(conf, NULL, eMOD_OUT); /* Note: clang static analyzer reports that node maybe == NULL. However, this is * not possible, because we have the built-in output modules which are always * present. Anyhow, we guard this by an assert. -- rgerhards, 2010-12-16 */ assert(node != NULL); while (node != NULL) { pOMSR = NULL; pMod = node->pMod; iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR); dbgprintf("tried selector action for %s: %d\n", module.GetName(pMod), iRet); if (iRet == RS_RET_OK_WARN) { bHadWarning = 1; iRet = RS_RET_OK; } if (iRet == RS_RET_OK) { if ((iRet = addAction(&pAction, pMod, pModData, pOMSR, NULL, NULL)) == RS_RET_OK) { /* here check if the module is compatible with select features * (currently, we have no such features!) */ conf->actions.nbrActions++; /* one more active action! */ } break; } else if (iRet != RS_RET_CONFLINE_UNPROCESSED) { /* In this case, the module would have handled the config * line, but some error occurred while doing so. This error should * already by reported by the module. We do not try any other * modules on this line, because we found the right one. * rgerhards, 2007-07-24 */ dbgprintf("error %d parsing config line\n", (int)iRet); break; } node = module.GetNxtCnfType(conf, node, eMOD_OUT); } *ppAction = pAction; if (iRet == RS_RET_OK && bHadWarning) iRet = RS_RET_OK_WARN; RETiRet; } /* return the current number of active actions * rgerhards, 2008-07-28 */ static rsRetVal GetNbrActActions(rsconf_t *conf, int *piNbrActions) { DEFiRet; assert(piNbrActions != NULL); *piNbrActions = conf->actions.nbrActions; RETiRet; } /* queryInterface function * rgerhards, 2008-02-29 */ BEGINobjQueryInterface(conf) CODESTARTobjQueryInterface(conf); if (pIf->ifVersion != confCURR_IF_VERSION) { /* check for current version, increment on each change */ ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); } /* ok, we have the right interface, so let's fill it * Please note that we may also do some backwards-compatibility * work here (if we can support an older interface version - that, * of course, also affects the "if" above). */ pIf->doNameLine = doNameLine; pIf->cfsysline = cfsysline; pIf->doModLoad = doModLoad; pIf->GetNbrActActions = GetNbrActActions; finalize_it: ENDobjQueryInterface(conf) /* Reset config variables to default values. * rgerhards, 2010-07-23 */ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { bConfStrictScoping = 0; return RS_RET_OK; } /* exit our class * rgerhards, 2008-03-11 */ BEGINObjClassExit(conf, OBJ_IS_CORE_MODULE) /* CHANGE class also in END MACRO! */ CODESTARTObjClassExit(conf); /* free no-longer needed module-global variables */ if (pDfltHostnameCmp != NULL) { rsCStrDestruct(&pDfltHostnameCmp); } if (pDfltProgNameCmp != NULL) { rsCStrDestruct(&pDfltProgNameCmp); } /* release objects we no longer need */ objRelease(module, CORE_COMPONENT); objRelease(net, LM_NET_FILENAME); objRelease(ruleset, CORE_COMPONENT); ENDObjClassExit(conf) /* Initialize our class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-29 */ BEGINAbstractObjClassInit(conf, 1, OBJ_IS_CORE_MODULE) /* class, version - CHANGE class also in END MACRO! */ /* request objects we use */ CHKiRet(objUse(module, CORE_COMPONENT)); CHKiRet(objUse(net, LM_NET_FILENAME)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); /* These commands will NOT be supported -- the new v6.3 config system provides * far better methods. We will remove the related code soon. -- rgerhards, 2012-01-09 */ CHKiRet( regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); ENDObjClassInit(conf) rsyslog-8.2608.0/runtime/PaxHeaders/segdisk_crc.h0000644000000000000000000000013215241075234016656 xustar0030 mtime=1787067036.609578369 30 atime=1787067036.681579717 30 ctime=1787067794.411725372 rsyslog-8.2608.0/runtime/segdisk_crc.h0000664000175000017500000000024515241075234016323 0ustar00rgerrger#ifndef INCLUDED_SEGDISK_CRC_H #define INCLUDED_SEGDISK_CRC_H #include #include uint32_t segdiskCrc32c(const void *buf, size_t len); #endif rsyslog-8.2608.0/PaxHeaders/install-sh0000644000000000000000000000013215241076160014542 xustar0030 mtime=1787067504.274316096 30 atime=1787067507.961384877 30 ctime=1787067790.730656775 rsyslog-8.2608.0/install-sh0000755000175000017500000003577615241076160014231 0ustar00rgerrger#!/bin/sh # install - install a program, script, or datafile scriptversion=2020-11-14.01; # 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. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # 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_mkdir= # Desired mode of installed file. mode=0755 # Create dirs (including intermediate dirs) using mode 755. # This is like GNU 'install' as of coreutils 8.32 (2020). mkdir_umask=22 backupsuffix= chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly 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 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. -p pass -p to $cpprog. -s $stripprog installed files. -S SUFFIX attempt to back up existing files, with suffix SUFFIX. -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 By default, rm is invoked with -f; when overridden with RMPROG, it's up to you to specify -f if you want it. If -S is not specified, no backups are attempted. Email bug reports to bug-automake@gnu.org. Automake home page: https://www.gnu.org/software/automake/ " 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 *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -p) cpprog="$cpprog -p";; -s) stripcmd=$stripprog;; -S) backupsuffix="$2" shift;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi 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 if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi 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=$? # Don't chown directories that already exist. if test $dstdir_status = 0; then chowncmd="" fi 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. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dstbase=`basename "$src"` case $dst in */) dst=$dst$dstbase;; *) dst=$dst/$dstbase;; esac dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi case $dstdir in */) dstdirslash=$dstdir;; *) dstdirslash=$dstdir/;; esac obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # 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 # The $RANDOM variable is not portable (e.g., dash). Use it # here however when possible just to lower collision chance. tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap ' ret=$? rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null exit $ret ' 0 # Because "mkdir -p" follows existing symlinks and we likely work # directly in world-writeable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/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. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # 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 oIFS=$IFS IFS=/ set -f set fnord $dstdir shift 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=${dstdirslash}_inst.$$_ rmtmp=${dstdirslash}_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 && { test -z "$stripcmd" || { # Create $dsttmp read-write so that cp doesn't create it read-only, # which would cause strip to fail. if test -z "$doit"; then : >"$dsttmp" # No need to fork-exec 'touch'. else $doit touch "$dsttmp" fi } } && $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` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # If $backupsuffix is set, and the file being installed # already exists, attempt a backup. Don't worry if it fails, # e.g., if mv doesn't support -f. if test -n "$backupsuffix" && test -f "$dst"; then $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null fi # 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 "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd "$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 'before-save-hook 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: rsyslog-8.2608.0/PaxHeaders/NEWS0000644000000000000000000000013215035412264013240 xustar0030 mtime=1752569012.325278836 30 atime=1782715518.795788959 30 ctime=1787067790.717656533 rsyslog-8.2608.0/NEWS0000666000175000017500000000007615035412264012711 0ustar00rgerrgerThis file has been superseded by ChangeLog. Please see there. rsyslog-8.2608.0/PaxHeaders/COPYING0000644000000000000000000000013115035412264013573 xustar0029 mtime=1752569012.32130663 30 atime=1782715518.795788959 30 ctime=1787067790.707656347 rsyslog-8.2608.0/COPYING0000666000175000017500000010451215035412264013245 0ustar00rgerrger GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . rsyslog-8.2608.0/PaxHeaders/contrib0000644000000000000000000000013015241076633014127 xustar0030 mtime=1787067803.301891028 28 atime=1787067808.7849932 30 ctime=1787067803.301891028 rsyslog-8.2608.0/contrib/0000775000175000017500000000000015241076633013652 5ustar00rgerrgerrsyslog-8.2608.0/contrib/PaxHeaders/imhttp0000644000000000000000000000013015241076633015434 xustar0030 mtime=1787067803.120887655 28 atime=1787067808.7849932 30 ctime=1787067803.120887655 rsyslog-8.2608.0/contrib/imhttp/0000775000175000017500000000000015241076633015157 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imhttp/PaxHeaders/Makefile.am0000644000000000000000000000013215131231047017535 xustar0030 mtime=1768239655.583210602 30 atime=1787067434.018005259 30 ctime=1787067803.115887562 rsyslog-8.2608.0/contrib/imhttp/Makefile.am0000666000175000017500000000033215131231047017201 0ustar00rgerrgerpkglib_LTLIBRARIES = imhttp.la imhttp_la_SOURCES = imhttp.c imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS) imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS) rsyslog-8.2608.0/contrib/imhttp/PaxHeaders/imhttp.c0000644000000000000000000000013215241075234017160 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.714580335 30 ctime=1787067803.120887655 rsyslog-8.2608.0/contrib/imhttp/imhttp.c0000664000175000017500000022474215241075234016637 0ustar00rgerrger/* imhttp.c * This is an input module for receiving http input. * * This file is originally contribution to rsyslog. * * Copyright 2025 Adiscon GmbH and Others * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "cfsysline.h" /* access to config file objects */ #include "module-template.h" #include "ruleset.h" #include "unicode-helper.h" #include "rsyslog.h" #include "errmsg.h" #include "statsobj.h" #include "ratelimit.h" #include "dirty.h" #include "civetweb.h" #include #include MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imhttp") /* static data */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) DEFobjCurrIf(statsobj) #define CIVETWEB_OPTION_NAME_PORTS "listening_ports" #define CIVETWEB_OPTION_NAME_DOCUMENT_ROOT "document_root" #define MAX_READ_BUFFER_SIZE 16384 #define MAX_REQUEST_BODY_SIZE (16 * 1024 * 1024) #define INIT_SCRATCH_BUF_SIZE 4096 /* General purpose buffer size. */ /** * Basic-auth credentials are capped at 2 KiB of Base64 text. That is well * above practical user-id/password sizes, yet still small enough to keep the * parser on a fixed stack buffer and to reject oversized headers as hostile. */ #define IMHTTP_MAX_BUF_LEN (8192) #define BASIC_AUTH_MAX_ENCODED 2048 #define BASIC_AUTH_MAX_DECODED ((BASIC_AUTH_MAX_ENCODED / 4) * 3) #define DEFAULT_HEALTH_CHECK_PATH "/healthz" #define DEFAULT_PROM_METRICS_PATH "/metrics" #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif struct option { const char *name; const char *val; }; struct auth_s { char workbuf[BASIC_AUTH_MAX_DECODED + 1]; char *pszUser; char *pszPasswd; const char *pszApiKey; }; /** * Route auth settings are borrowed from the finalized module config. * * CivetWeb handlers only keep references because the config lifetime covers * the full server lifetime. */ struct route_auth_ctx_s { const char *pszBasicAuthFile; const char *pszApiKeyFile; }; struct data_parse_s { sbool content_compressed; sbool compressedDataComplete; sbool bzInitDone; /* did we do an init of zstrm already? */ z_stream zstrm; /* zip stream to use for tcp compression */ uint64_t requestBodyBytes; uint64_t decompressedBodyBytes; // Currently only used for octet specific parsing enum { eAtStrtFram, eInOctetCnt, eInMsg, } inputState; size_t iOctetsRemain; /* Number of Octets remaining in message */ enum { TCP_FRAMING_OCTET_STUFFING, TCP_FRAMING_OCTET_COUNTING } framingMode; }; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ instanceConf_t *root, *tail; struct option ports; struct option docroot; struct option *options; int nOptions; char *pszLstnPortFileName; char *pszHealthCheckPath; char *pszMetricsPath; char *pszHealthCheckAuthFile; char *pszMetricsAuthFile; char *pszHealthCheckApiKeyFile; char *pszMetricsApiKeyFile; struct route_auth_ctx_s healthCheckAuthCtx; struct route_auth_ctx_s metricsAuthCtx; }; struct instanceConf_s { struct instanceConf_s *next; uchar *pszBindRuleset; /* name of ruleset to bind to */ uchar *pszEndpoint; /* endpoint to configure */ uchar *pszBasicAuthFile; /* file containing basic auth users/pass */ uchar *pszApiKeyFile; /* file containing accepted API keys */ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ ratelimit_t *ratelimiter; int ratelimitInterval; int ratelimitBurst; uchar *pszRatelimitName; uchar *pszInputName; /* value for inputname property, NULL is OK and handled by core engine */ prop_t *pInputName; sbool flowControl; sbool bDisableLFDelim; sbool bSuppOctetFram; sbool bAddMetadata; struct route_auth_ctx_s authCtx; }; struct conn_wrkr_s { struct data_parse_s parseState; uchar *pMsg; /* msg scratch buffer */ size_t iMsg; /* index of next char to store in msg */ uchar zipBuf[64 * 1024]; uchar *pDecompressedReqBuf; size_t decompressedReqBufSize; size_t decompressedReqBufLen; multi_submit_t multiSub; smsg_t *pMsgs[CONF_NUM_MULTISUB]; char *pReadBuf; size_t readBufSize; prop_t *propRemoteAddr; const struct mg_request_info *pri; /* do not free me - used to hold a reference only */ char *pScratchBuf; size_t scratchBufSize; }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current load process */ static prop_t *pInputName = NULL; // static size_t s_iMaxLine = 16; /* get maximum size we currently support */ static size_t s_iMaxLine = 16384; /* get maximum size we currently support */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = {{"ports", eCmdHdlrString, 0}, {"listenportfilename", eCmdHdlrString, 0}, {"documentroot", eCmdHdlrString, 0}, {"liboptions", eCmdHdlrArray, 0}, {"healthcheckpath", eCmdHdlrString, 0}, {"metricspath", eCmdHdlrString, 0}, {"healthcheckbasicauthfile", eCmdHdlrString, 0}, {"metricsbasicauthfile", eCmdHdlrString, 0}, {"healthcheckapikeyfile", eCmdHdlrString, 0}, {"metricsapikeyfile", eCmdHdlrString, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static struct cnfparamdescr inppdescr[] = {{"endpoint", eCmdHdlrString, 0}, {"basicauthfile", eCmdHdlrString, 0}, {"apikeyfile", eCmdHdlrString, 0}, {"ruleset", eCmdHdlrString, 0}, {"flowcontrol", eCmdHdlrBinary, 0}, {"disablelfdelimiter", eCmdHdlrBinary, 0}, {"supportoctetcountedframing", eCmdHdlrBinary, 0}, {"name", eCmdHdlrString, 0}, {"ratelimit.interval", eCmdHdlrInt, 0}, {"ratelimit.burst", eCmdHdlrInt, 0}, {"ratelimit.name", eCmdHdlrString, 0}, {"addmetadata", eCmdHdlrBinary, 0}}; #include "im-helper.h" /* must be included AFTER the type definitions! */ static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; static struct { statsobj_t *stats; STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted) STATSCOUNTER_DEF(ctrFailed, mutCtrFailed); STATSCOUNTER_DEF(ctrDiscarded, mutCtrDiscarded); } statsCounter; #include "im-helper.h" /* must be included AFTER the type definitions! */ #define min(a, b) \ ({ \ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ _a < _b ? _a : _b; \ }) #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 #define EXIT_URI "/exit" volatile int exitNow = 0; struct mg_callbacks callbacks; typedef struct httpserv_s { struct mg_context *ctx; struct mg_callbacks callbacks; const char **civetweb_options; size_t civetweb_options_count; } httpserv_t; static httpserv_t *s_httpserv; static sbool s_civetweb_initialized = 0; /* FORWARD DECLARATIONS */ static rsRetVal processData(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len); /** * Install borrowed auth sources for a route. * * @param authCtx route-local auth state to populate * @param basicAuthFile borrowed htpasswd path, or NULL * @param apiKeyFile borrowed API-key file path, or NULL * * @note The pointers are borrowed from the module config and must outlive the * request handler registration. */ static void routeAuthCtxSet(struct route_auth_ctx_s *const authCtx, const char *const basicAuthFile, const char *const apiKeyFile) { if (authCtx == NULL) { return; } authCtx->pszBasicAuthFile = basicAuthFile; authCtx->pszApiKeyFile = apiKeyFile; } /** * Check whether a route needs auth handling. * * @param authCtx route-local auth state * @return non-zero if Basic auth or API-key auth is configured * * @note Public routes skip auth handler registration entirely so the request * path stays on the fast path. */ static sbool routeAuthConfigured(const struct route_auth_ctx_s *const authCtx) { return authCtx != NULL && (authCtx->pszBasicAuthFile != NULL || authCtx->pszApiKeyFile != NULL); } static rsRetVal createInstance(instanceConf_t **pinst) { instanceConf_t *inst; DEFiRet; CHKmalloc(inst = calloc(1, sizeof(instanceConf_t))); inst->next = NULL; inst->pszBindRuleset = NULL; inst->pBindRuleset = NULL; inst->pszEndpoint = NULL; inst->pszBasicAuthFile = NULL; inst->pszApiKeyFile = NULL; inst->ratelimiter = NULL; inst->pszInputName = NULL; inst->pInputName = NULL; inst->ratelimitBurst = -1; inst->ratelimitInterval = -1; inst->pszRatelimitName = NULL; inst->flowControl = 1; inst->bDisableLFDelim = 0; inst->bSuppOctetFram = 0; inst->bAddMetadata = 0; // construct statsobj /* node created, let's add to config */ if (loadModConf->tail == NULL) { loadModConf->tail = loadModConf->root = inst; } else { loadModConf->tail->next = inst; loadModConf->tail = inst; } *pinst = inst; finalize_it: RETiRet; } static rsRetVal processCivetwebOptions(char *const param, const char **const name, const char **const paramval) { DEFiRet; char *parsedName = NULL; char *parsedVal = NULL; *name = NULL; *paramval = NULL; char *val = strstr(param, "="); if (val == NULL) { LogError(0, RS_RET_PARAM_ERROR, "missing equal sign in " "parameter '%s'", param); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } *val = '\0'; /* terminates name */ ++val; /* now points to begin of value */ CHKmalloc(parsedName = strdup(param)); CHKmalloc(parsedVal = strdup(val)); *name = parsedName; parsedName = NULL; *paramval = parsedVal; parsedVal = NULL; finalize_it: free(parsedName); free(parsedVal); RETiRet; } static sbool valid_civetweb_option(const struct mg_option *valid_opts, const char *option) { const struct mg_option *pvalid_opts = valid_opts; for (; pvalid_opts != NULL && pvalid_opts->name != NULL; pvalid_opts++) { if (strcmp(pvalid_opts->name, option) == 0) { return TRUE; } } return FALSE; } /* * thread_type: * 0 indicates the master thread * 1 indicates a worker thread handling client connections * 2 indicates an internal helper thread (timer thread) */ static void *init_thread(ATTR_UNUSED const struct mg_context *ctx, int thread_type) { DEFiRet; struct conn_wrkr_s *data = NULL; if (thread_type == 1) { CHKmalloc(data = calloc(1, sizeof(struct conn_wrkr_s))); data->pMsg = NULL; data->iMsg = 0; data->parseState.bzInitDone = 0; data->parseState.content_compressed = 0; data->parseState.inputState = eAtStrtFram; data->parseState.iOctetsRemain = 0; data->multiSub.maxElem = CONF_NUM_MULTISUB; data->multiSub.ppMsgs = data->pMsgs; data->multiSub.nElem = 0; CHKmalloc(data->pReadBuf = malloc(MAX_READ_BUFFER_SIZE)); data->readBufSize = MAX_READ_BUFFER_SIZE; data->parseState.bzInitDone = 0; data->parseState.content_compressed = 0; data->parseState.inputState = eAtStrtFram; data->parseState.iOctetsRemain = 0; CHKmalloc(data->pMsg = calloc(1, 1 + s_iMaxLine)); data->iMsg = 0; data->propRemoteAddr = NULL; data->pScratchBuf = NULL; data->scratchBufSize = 0; } finalize_it: if (iRet != RS_RET_OK) { free(data != NULL ? data->pReadBuf : NULL); free(data != NULL ? data->pMsg : NULL); free(data); return NULL; } return data; } static void exit_thread(ATTR_UNUSED const struct mg_context *ctx, ATTR_UNUSED int thread_type, void *thread_pointer) { if (thread_type == 1) { struct conn_wrkr_s *data = (struct conn_wrkr_s *)thread_pointer; if (data == NULL) { return; } if (data->propRemoteAddr) { prop.Destruct(&data->propRemoteAddr); } if (data->scratchBufSize) { free(data->pScratchBuf); } free(data->pReadBuf); free(data->pDecompressedReqBuf); free(data->pMsg); free(data); } } static void cleanupHttpServer(void) { if (s_httpserv != NULL) { if (s_httpserv->ctx != NULL) { mg_stop(s_httpserv->ctx); s_httpserv->ctx = NULL; } free(s_httpserv->civetweb_options); s_httpserv->civetweb_options = NULL; s_httpserv->civetweb_options_count = 0; free(s_httpserv); s_httpserv = NULL; } if (s_civetweb_initialized) { mg_exit_library(); s_civetweb_initialized = 0; } } static rsRetVal msgAddMetadataFromHttpHeader(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr) { struct json_object *json = NULL; DEFiRet; const struct mg_request_info *ri = connWrkr->pri; #define MAX_HTTP_HEADERS 64 /* hard limit */ int count = min(ri->num_headers, MAX_HTTP_HEADERS); if (connWrkr->pScratchBuf == NULL) { return RS_RET_OK; } CHKmalloc(json = json_object_new_object()); for (int i = 0; i < count; i++) { if (ri->http_headers[i].name == NULL || ri->http_headers[i].value == NULL) { continue; } struct json_object *const jval = json_object_new_string(ri->http_headers[i].value); CHKmalloc(jval); /* truncate header names bigger than INIT_SCRATCH_BUF_SIZE */ if (connWrkr->scratchBufSize > 0) { const size_t header_name_len = strlen(ri->http_headers[i].name); const size_t copy_len = header_name_len < connWrkr->scratchBufSize - 1 ? header_name_len : connWrkr->scratchBufSize - 1; memcpy(connWrkr->pScratchBuf, ri->http_headers[i].name, copy_len); connWrkr->pScratchBuf[copy_len] = '\0'; } /* make header lowercase */ char *pname = connWrkr->pScratchBuf; while (pname && *pname != '\0') { *pname = tolower((unsigned char)*pname); pname++; } json_object_object_add(json, (const char *const)connWrkr->pScratchBuf, jval); } struct json_object *const toAdd = json; json = NULL; CHKiRet(msgAddJSON(pMsg, (uchar *)"!metadata!httpheaders", toAdd, 0, 0)); finalize_it: if (iRet != RS_RET_OK && json) { json_object_put(json); } RETiRet; } static rsRetVal msgAddMetadataFromHttpQueryParams(smsg_t *const __restrict__ pMsg, struct conn_wrkr_s *connWrkr) { struct json_object *json = NULL; DEFiRet; const struct mg_request_info *ri = connWrkr->pri; if (ri && ri->query_string && connWrkr->pScratchBuf != NULL) { if (connWrkr->scratchBufSize > 0) { const size_t query_len = strlen(ri->query_string); const size_t copy_len = query_len < connWrkr->scratchBufSize - 1 ? query_len : connWrkr->scratchBufSize - 1; memcpy(connWrkr->pScratchBuf, ri->query_string, copy_len); connWrkr->pScratchBuf[copy_len] = '\0'; } char *pquery_str = connWrkr->pScratchBuf; if (pquery_str) { CHKmalloc(json = json_object_new_object()); char *saveptr = NULL; char *kv_pair = strtok_r(pquery_str, "&;", &saveptr); for (; kv_pair != NULL; kv_pair = strtok_r(NULL, "&;", &saveptr)) { char *saveptr2 = NULL; char *key = strtok_r(kv_pair, "=", &saveptr2); if (key) { char *value = strtok_r(NULL, "=", &saveptr2); struct json_object *const jval = json_object_new_string(value != NULL ? value : ""); CHKmalloc(jval); json_object_object_add(json, (const char *)key, jval); } } struct json_object *const toAdd = json; json = NULL; CHKiRet(msgAddJSON(pMsg, (uchar *)"!metadata!queryparams", toAdd, 0, 0)); } } finalize_it: if (iRet != RS_RET_OK && json) { json_object_put(json); } RETiRet; } static rsRetVal doSubmitMsg(const instanceConf_t *const __restrict__ inst, struct conn_wrkr_s *connWrkr, const uchar *msg, size_t len) { smsg_t *pMsg = NULL; DEFiRet; assert(len <= s_iMaxLine); if (len == 0) { DBGPRINTF("discarding zero-sized message\n"); FINALIZE; } CHKiRet(msgConstruct(&pMsg)); MsgSetFlowControlType(pMsg, inst->flowControl ? eFLOWCTL_LIGHT_DELAY : eFLOWCTL_NO_DELAY); if (inst->pInputName) { MsgSetInputName(pMsg, inst->pInputName); } else { MsgSetInputName(pMsg, pInputName); } MsgSetRawMsg(pMsg, (const char *)msg, len); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ if (connWrkr->propRemoteAddr) { MsgSetRcvFromIP(pMsg, connWrkr->propRemoteAddr); } if (inst) { MsgSetRuleset(pMsg, inst->pBindRuleset); } // TODO: make these flags configurable. pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; if (inst->bAddMetadata) { CHKiRet(msgAddMetadataFromHttpHeader(pMsg, connWrkr)); CHKiRet(msgAddMetadataFromHttpQueryParams(pMsg, connWrkr)); } CHKiRet(ratelimitAddMsg(inst->ratelimiter, &connWrkr->multiSub, pMsg)); STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted); finalize_it: connWrkr->iMsg = 0; if (iRet != RS_RET_OK) { if (pMsg != NULL && iRet != RS_RET_DISCARDMSG) { msgDestruct(&pMsg); } STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded); } RETiRet; } static rsRetVal processOctetMsgLen(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, char ch) { DEFiRet; if (connWrkr->parseState.inputState == eAtStrtFram) { if (inst->bSuppOctetFram && isdigit(ch)) { connWrkr->parseState.inputState = eInOctetCnt; connWrkr->parseState.iOctetsRemain = 0; connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_COUNTING; } else { connWrkr->parseState.inputState = eInMsg; connWrkr->parseState.framingMode = TCP_FRAMING_OCTET_STUFFING; } } // parsing character. if (connWrkr->parseState.inputState == eInOctetCnt) { if (isdigit(ch)) { if (connWrkr->parseState.iOctetsRemain <= 200000000) { connWrkr->parseState.iOctetsRemain = connWrkr->parseState.iOctetsRemain * 10 + ch - '0'; } // temporarily save this character into the message buffer if (connWrkr->iMsg + 1 < s_iMaxLine) { connWrkr->pMsg[connWrkr->iMsg++] = ch; } } else { const char *remoteAddr = ""; if (connWrkr->propRemoteAddr) { remoteAddr = (const char *)propGetSzStr(connWrkr->propRemoteAddr); } /* handle space delimeter */ if (ch != ' ') { LogError(0, NO_ERRCODE, "Framing Error in received TCP message " "from peer: (ip) %s: to input: %s, delimiter is not " "SP but has ASCII value %d.", remoteAddr, inst->pszInputName, ch); } if (connWrkr->parseState.iOctetsRemain < 1) { LogError(0, NO_ERRCODE, "Framing Error in received TCP message" " from peer: (ip) %s: delimiter is not " "SP but has ASCII value %d.", remoteAddr, ch); } else if (connWrkr->parseState.iOctetsRemain > s_iMaxLine) { DBGPRINTF("truncating message with %zu octets - max msg size is %zu\n", connWrkr->parseState.iOctetsRemain, s_iMaxLine); LogError(0, NO_ERRCODE, "received oversize message from peer: " "(hostname) (ip) %s: size is %zu bytes, max msg " "size is %zu, truncating...", remoteAddr, connWrkr->parseState.iOctetsRemain, s_iMaxLine); } connWrkr->parseState.inputState = eInMsg; } /* reset msg len for actual message processing */ connWrkr->iMsg = 0; /* retrieve next character */ } RETiRet; } static rsRetVal processOctetCounting(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len) { DEFiRet; const uchar *pbuf = (const uchar *)buf; const uchar *pbufLast = pbuf + len; while (pbuf < pbufLast) { char ch = *pbuf; if (connWrkr->parseState.inputState == eAtStrtFram || connWrkr->parseState.inputState == eInOctetCnt) { CHKiRet(processOctetMsgLen(inst, connWrkr, ch)); if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING) { pbuf++; } } else if (connWrkr->parseState.inputState == eInMsg) { if (connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_STUFFING) { if (connWrkr->iMsg >= s_iMaxLine) { CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); connWrkr->parseState.inputState = eAtStrtFram; } else { if (ch == '\n') { CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); connWrkr->parseState.inputState = eAtStrtFram; } else { connWrkr->pMsg[connWrkr->iMsg++] = ch; } pbuf++; } } else { assert(connWrkr->parseState.framingMode == TCP_FRAMING_OCTET_COUNTING); const size_t remainingBytes = pbufLast - pbuf; const size_t frameBytes = min(connWrkr->parseState.iOctetsRemain, remainingBytes); size_t copyBytes = 0; if (connWrkr->iMsg < s_iMaxLine) { copyBytes = min(frameBytes, s_iMaxLine - connWrkr->iMsg); if (copyBytes != 0) { memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, copyBytes); connWrkr->iMsg += copyBytes; } } pbuf += frameBytes; connWrkr->parseState.iOctetsRemain -= frameBytes; if (connWrkr->parseState.iOctetsRemain == 0) { CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); connWrkr->parseState.inputState = eAtStrtFram; } } } else { // unexpected assert(0); break; } } finalize_it: RETiRet; } static rsRetVal processDisableLF(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len) { DEFiRet; const uchar *pbuf = (const uchar *)buf; size_t remainingBytes = len; const uchar *pbufLast = pbuf + len; while (pbuf < pbufLast) { size_t count = 0; if (connWrkr->iMsg + remainingBytes >= s_iMaxLine) { count = s_iMaxLine - connWrkr->iMsg; } else { count = remainingBytes; } if (count) { memcpy(connWrkr->pMsg + connWrkr->iMsg, pbuf, count); pbuf += count; connWrkr->iMsg += count; remainingBytes -= count; } CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); } finalize_it: RETiRet; } static rsRetVal processDataUncompressed(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len) { const uchar *pbuf = (const uchar *)buf; DEFiRet; if (inst->bDisableLFDelim) { /* do block processing */ iRet = processDisableLF(inst, connWrkr, buf, len); } else if (inst->bSuppOctetFram) { iRet = processOctetCounting(inst, connWrkr, buf, len); } else { const uchar *pbufLast = pbuf + len; while (pbuf < pbufLast) { char ch = *pbuf; if (connWrkr->iMsg >= s_iMaxLine) { CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); } if (ch == '\n') { CHKiRet(doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg)); } else { connWrkr->pMsg[connWrkr->iMsg++] = ch; } pbuf++; } } finalize_it: RETiRet; } /** * Apply the imhttp request body limit to streaming byte counters. * * @note Content-Length only covers compressed wire bytes when gzip is used. * Keep both the wire stream and the inflated stream bounded, and parse a * gzip request only after its full inflated body stayed within the limit. */ static rsRetVal trackRequestBodyBytes(uint64_t *const counter, const size_t len, const char *const label) { DEFiRet; if (*counter > MAX_REQUEST_BODY_SIZE || (uint64_t)len > (uint64_t)MAX_REQUEST_BODY_SIZE - *counter) { LogError(0, RS_RET_OVERSIZE_MSG, "imhttp: rejecting request body after %s size exceeded maximum %d bytes", label, MAX_REQUEST_BODY_SIZE); ABORT_FINALIZE(RS_RET_OVERSIZE_MSG); } *counter += len; finalize_it: RETiRet; } static rsRetVal appendDecompressedRequestBody(struct conn_wrkr_s *const connWrkr, const uchar *const buf, const size_t len) { DEFiRet; uchar *newBuf = NULL; CHKiRet(trackRequestBodyBytes(&connWrkr->parseState.decompressedBodyBytes, len, "decompressed")); if (len == 0) { FINALIZE; } if (connWrkr->decompressedReqBufLen > MAX_REQUEST_BODY_SIZE || len > (size_t)MAX_REQUEST_BODY_SIZE - connWrkr->decompressedReqBufLen) { ABORT_FINALIZE(RS_RET_OVERSIZE_MSG); } const size_t required = connWrkr->decompressedReqBufLen + len; if (required > connWrkr->decompressedReqBufSize) { size_t newSize = connWrkr->decompressedReqBufSize == 0 ? INIT_SCRATCH_BUF_SIZE : connWrkr->decompressedReqBufSize; while (newSize < required) { if (newSize > (size_t)MAX_REQUEST_BODY_SIZE / 2) { newSize = MAX_REQUEST_BODY_SIZE; } else { newSize *= 2; } } CHKmalloc(newBuf = realloc(connWrkr->pDecompressedReqBuf, newSize)); connWrkr->pDecompressedReqBuf = newBuf; connWrkr->decompressedReqBufSize = newSize; } memcpy(connWrkr->pDecompressedReqBuf + connWrkr->decompressedReqBufLen, buf, len); connWrkr->decompressedReqBufLen += len; finalize_it: RETiRet; } static rsRetVal processDataCompressed(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len) { DEFiRet; if (!connWrkr->parseState.bzInitDone) { /* allocate deflate state */ connWrkr->parseState.zstrm.zalloc = Z_NULL; connWrkr->parseState.zstrm.zfree = Z_NULL; connWrkr->parseState.zstrm.opaque = Z_NULL; int rc = inflateInit2(&connWrkr->parseState.zstrm, (MAX_WBITS | 16)); if (rc != Z_OK) { dbgprintf("imhttp: error %d returned from zlib/inflateInit()\n", rc); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } connWrkr->parseState.bzInitDone = 1; } connWrkr->parseState.zstrm.next_in = (Bytef *)buf; connWrkr->parseState.zstrm.avail_in = (uInt)len; /* run inflate() on buffer until everything has been uncompressed */ size_t outtotal = 0; do { int zRet = 0; size_t outavail = 0; dbgprintf("imhttp: in inflate() loop, avail_in %d, total_in %ld\n", connWrkr->parseState.zstrm.avail_in, connWrkr->parseState.zstrm.total_in); connWrkr->parseState.zstrm.avail_out = sizeof(connWrkr->zipBuf); connWrkr->parseState.zstrm.next_out = connWrkr->zipBuf; zRet = inflate(&connWrkr->parseState.zstrm, Z_SYNC_FLUSH); dbgprintf("imhttp: inflate(), ret: %d, avail_out: %d\n", zRet, connWrkr->parseState.zstrm.avail_out); outavail = sizeof(connWrkr->zipBuf) - connWrkr->parseState.zstrm.avail_out; if (outavail != 0) { outtotal += outavail; CHKiRet(appendDecompressedRequestBody(connWrkr, connWrkr->zipBuf, outavail)); } if (zRet == Z_STREAM_END) { if (connWrkr->decompressedReqBufLen != 0) { CHKiRet(processDataUncompressed(inst, connWrkr, (const char *)connWrkr->pDecompressedReqBuf, connWrkr->decompressedReqBufLen)); } connWrkr->decompressedReqBufLen = 0; connWrkr->parseState.compressedDataComplete = 1; break; } if (zRet == Z_BUF_ERROR) { if (outavail == 0 && connWrkr->parseState.zstrm.avail_in != 0) { LogError(0, RS_RET_ZLIB_ERR, "imhttp: zlib inflate made no progress while input remained"); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } break; } if (zRet != Z_OK) { LogError(0, RS_RET_ZLIB_ERR, "imhttp: zlib inflate failed with status %d", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } } while (connWrkr->parseState.zstrm.avail_out == 0); dbgprintf("imhttp: processDataCompressed complete, sizes: in %lld, out %llu\n", (long long)len, (long long unsigned)outtotal); finalize_it: RETiRet; } static rsRetVal processData(const instanceConf_t *const inst, struct conn_wrkr_s *connWrkr, const char *buf, size_t len) { DEFiRet; // inst->bDisableLFDelim = 0; if (connWrkr->parseState.content_compressed) { iRet = processDataCompressed(inst, connWrkr, buf, len); } else { iRet = processDataUncompressed(inst, connWrkr, buf, len); } RETiRet; } static const char *skipWhitespace(const char *str) { while (str != NULL && isspace((unsigned char)*str)) { ++str; } return str; } /** * Parse a Basic-auth header into the reusable auth scratch state. * * @param conn CivetWeb request connection * @param auth caller-owned auth scratch state * @return non-zero when the header was present and decodes to user:password * * @note The decoded buffer is reused across calls so the parser can avoid * extra allocations for the common in-buffer case. */ static sbool parse_basic_auth_header(struct mg_connection *conn, struct auth_s *auth) { if (!auth || !conn) { return 0; } const char *auth_header = NULL; if (((auth_header = mg_get_header(conn, "Authorization")) == NULL) || strncasecmp(auth_header, "Basic ", 6) != 0) { return 0; } const char *src = auth_header + 6; size_t encoded_len = strlen(src); if (encoded_len > BASIC_AUTH_MAX_ENCODED) { LogError(0, NO_ERRCODE, "imhttp: rejecting oversized Basic-auth header (%zu bytes, max %d bytes)", encoded_len, BASIC_AUTH_MAX_ENCODED); return 0; } size_t len = apr_base64_decode(auth->workbuf, src); if (len == 0 || len > BASIC_AUTH_MAX_DECODED) { return 0; } if (memchr(auth->workbuf, '\0', len) != NULL) { return 0; } auth->workbuf[len] = '\0'; char *passwd = NULL, *saveptr = NULL; char *user = strtok_r(auth->workbuf, ":", &saveptr); if (user) { passwd = strtok_r(NULL, ":", &saveptr); } auth->pszUser = user; auth->pszPasswd = passwd; return (auth->pszUser != NULL && auth->pszPasswd != NULL); } /** * Parse an Elastic-style API-key header from the request. * * @param conn CivetWeb request connection * @param auth parsed auth output * @return non-zero when a usable API key token was found * * @note Accept both Authorization: ApiKey and X-API-Key because Elastic * agents and intermediaries do not always use the same header form. * Leading whitespace after the scheme is ignored for robustness. */ static sbool parse_api_key_header(struct mg_connection *conn, struct auth_s *auth) { if (!auth || !conn) { return 0; } const char *auth_header = mg_get_header(conn, "Authorization"); if (auth_header != NULL && strncasecmp(auth_header, "ApiKey ", 7) == 0) { auth->pszApiKey = skipWhitespace(auth_header + 7); if (auth->pszApiKey != NULL) { size_t key_len = strlen(auth->pszApiKey); if (key_len > BASIC_AUTH_MAX_ENCODED) { return 0; } } return (auth->pszApiKey != NULL && auth->pszApiKey[0] != '\0'); } auth->pszApiKey = skipWhitespace(mg_get_header(conn, "X-API-Key")); if (auth->pszApiKey != NULL) { size_t key_len = strlen(auth->pszApiKey); if (key_len > BASIC_AUTH_MAX_ENCODED) { auth->pszApiKey = NULL; return 0; } } return (auth->pszApiKey != NULL && auth->pszApiKey[0] != '\0'); } /** * Validate a Basic-auth credential pair against an htpasswd file. * * @param filep open htpasswd file * @param auth parsed Basic-auth credentials * @return non-zero if the first matching user/password pair validates * * @note Comments and blank lines are ignored so the file can stay human * maintainable without affecting auth behavior. */ static sbool read_auth_file(FILE *filep, struct auth_s *auth) { if (filep == NULL || auth == NULL || auth->pszUser == NULL || auth->pszPasswd == NULL) { return 0; } char workbuf[IMHTTP_MAX_BUF_LEN]; size_t l = 0; char *user; char *passwd; while (fgets(workbuf, sizeof(workbuf), filep)) { l = strnlen(workbuf, sizeof(workbuf)); while (l > 0) { if (isspace((unsigned char)workbuf[l - 1]) || iscntrl((unsigned char)workbuf[l - 1])) { workbuf[--l] = '\0'; } else { break; } } if (l < 1 || workbuf[0] == '#') { continue; } user = workbuf; passwd = strchr(workbuf, ':'); if (!passwd) { continue; } *passwd++ = '\0'; if (!strcasecmp(auth->pszUser, user)) { return (apr_password_validate(auth->pszPasswd, passwd) == APR_SUCCESS); } } return 0; } /** * Validate an API key against a token file. * * @param filep open token file * @param presentedApiKey key extracted from the request * @return non-zero if the first matching token validates * * @note The file format is deliberately one token per line so the auth path * stays a simple string compare instead of a parser. */ static sbool read_api_key_file(FILE *filep, const char *presentedApiKey) { char workbuf[IMHTTP_MAX_BUF_LEN]; size_t l = 0; if (filep == NULL || presentedApiKey == NULL || presentedApiKey[0] == '\0') { return 0; } while (fgets(workbuf, sizeof(workbuf), filep)) { l = strnlen(workbuf, sizeof(workbuf)); while (l > 0) { if (isspace((unsigned char)workbuf[l - 1]) || iscntrl((unsigned char)workbuf[l - 1])) { workbuf[--l] = '\0'; } else { break; } } if (l < 1 || workbuf[0] == '#') { continue; } if (strcmp(presentedApiKey, workbuf) == 0) { return 1; } } return 0; } /** * Open an auth file and report failures through the rsyslog error path. * * @param conn CivetWeb request connection used for request-scoped logging * @param authFile path to the auth file * @return open FILE handle, or NULL on error * * @note LogError() is used so errno expansion flows through rsyslog's normal * message formatting instead of hand-formatting strerror strings here. */ static FILE *openAuthFile(struct mg_connection *conn, const char *authFile) { FILE *fp = NULL; int fd = -1; if (authFile == NULL) { mg_cry(conn, "warning: auth file not configured for this endpoint.\n"); return NULL; } fd = open(authFile, O_RDONLY | O_NOFOLLOW); if (fd == -1) { LogError(errno, RS_RET_NO_FILE_ACCESS, "imhttp: auth file '%s' could not be accessed", authFile); return NULL; } fp = fdopen(fd, "r"); if (fp == NULL) { close(fd); LogError(errno, RS_RET_NO_FILE_ACCESS, "imhttp: fdopen failed for '%s'", authFile); } return fp; } /** * Validate a Basic-auth request against an htpasswd file. * * @param conn CivetWeb request connection * @param authFile htpasswd file path * @return non-zero on successful authorization * * @note This preserves the pre-existing Basic-auth contract while sharing the * file-open path with API-key auth. */ static sbool authorize_basic(struct mg_connection *conn, const char *authFile) { sbool ret = 0; FILE *fp = NULL; struct auth_s auth = {.pszUser = NULL, .pszPasswd = NULL, .pszApiKey = NULL}; fp = openAuthFile(conn, authFile); if (fp == NULL) { goto finalize; } if (!parse_basic_auth_header(conn, &auth)) { goto finalize; } ret = read_auth_file(fp, &auth); finalize: if (fp != NULL) { fclose(fp); } return ret; } /** * Validate an API-key request against a token file. * * @param conn CivetWeb request connection * @param authFile API-key file path * @return non-zero on successful authorization * * @note One token per line keeps matching deterministic and avoids parser * ambiguity in the auth path. */ static sbool authorize_api_key(struct mg_connection *conn, const char *authFile) { sbool ret = 0; FILE *fp = NULL; struct auth_s auth = {.pszUser = NULL, .pszPasswd = NULL, .pszApiKey = NULL}; fp = openAuthFile(conn, authFile); if (fp == NULL) { goto finalize; } if (!parse_api_key_header(conn, &auth)) { goto finalize; } ret = read_api_key_file(fp, auth.pszApiKey); finalize: if (fp != NULL) { fclose(fp); } return ret; } /** * Send the 401 response matching the route's configured auth scheme. * * @param conn CivetWeb request connection * @param authCtx route-local auth state * * @note Basic auth advertises a challenge header so standard clients can retry. * API-key-only routes intentionally avoid a browser-oriented challenge. */ static void sendUnauthorized(struct mg_connection *conn, const struct route_auth_ctx_s *authCtx) { if (authCtx != NULL && authCtx->pszBasicAuthFile != NULL) { mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n" "WWW-Authenticate: Basic realm=\"User Visible Realm\"\r\n" "Connection: close\r\n" "Content-Length: 0\r\n" "\r\n"); } else { mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); } } /** * CivetWeb auth callback for imhttp routes. * * @param conn CivetWeb request connection * @param cbdata route-local auth context * @return non-zero when the request is authorized * * @note When both schemes are configured, explicit Basic auth wins first so we * preserve the existing htpasswd behavior; API key auth is the fallback. */ static int routeAuthHandler(struct mg_connection *conn, void *cbdata) { const struct route_auth_ctx_s *authCtx = (const struct route_auth_ctx_s *)cbdata; const char *authHeader = mg_get_header(conn, "Authorization"); int ret = 0; if (!routeAuthConfigured(authCtx)) { return 1; } if (authCtx->pszBasicAuthFile != NULL && authHeader != NULL && strncasecmp(authHeader, "Basic ", 6) == 0) { ret = authorize_basic(conn, authCtx->pszBasicAuthFile); } if (!ret && authCtx->pszApiKeyFile != NULL) { ret = authorize_api_key(conn, authCtx->pszApiKeyFile); } if (!ret) { sendUnauthorized(conn, authCtx); } return ret; } /** * Register a request handler and attach auth handling when needed. * * @param ctx CivetWeb context * @param path request path * @param handler request handler * @param handlerCbdata handler-specific callback data * @param authCtx optional route-local auth context * * @note Keeping handler and auth registration together makes it easier to add * more mock endpoints later without duplicating the wiring rules. */ static void registerRoute(struct mg_context *ctx, const char *path, int (*handler)(struct mg_connection *, void *), void *handlerCbdata, struct route_auth_ctx_s *authCtx) { if (ctx == NULL || path == NULL || path[0] == '\0') { return; } mg_set_request_handler(ctx, path, handler, handlerCbdata); if (routeAuthConfigured(authCtx)) { mg_set_auth_handler(ctx, path, routeAuthHandler, authCtx); } } /* cbdata should actually contain instance data and we can actually use this instance data * to hold reusable scratch buffer. */ static int postHandler(struct mg_connection *conn, void *cbdata) { int rc = 1; rsRetVal localRet = RS_RET_OK; instanceConf_t *inst = (instanceConf_t *)cbdata; const struct mg_request_info *ri = mg_get_request_info(conn); struct conn_wrkr_s *connWrkr = mg_get_thread_pointer(conn); if (connWrkr == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "imhttp: thread pointer (connWrkr) is NULL"); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); return 500; } connWrkr->multiSub.nElem = 0; memset(&connWrkr->parseState, 0, sizeof(connWrkr->parseState)); connWrkr->decompressedReqBufLen = 0; connWrkr->pri = ri; if (inst->bAddMetadata && connWrkr->scratchBufSize == 0) { connWrkr->pScratchBuf = calloc(1, INIT_SCRATCH_BUF_SIZE); if (!connWrkr->pScratchBuf) { mg_cry(conn, "%s() - could not alloc scratch buffer!\n", __FUNCTION__); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } connWrkr->scratchBufSize = INIT_SCRATCH_BUF_SIZE; } if (0 != strcmp(ri->request_method, "POST")) { /* Not a POST request */ int ret = mg_get_request_link(conn, connWrkr->pReadBuf, connWrkr->readBufSize); mg_printf(conn, "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); mg_printf(conn, "%s method not allowed in the POST handler\n", ri->request_method); if (ret >= 0) { mg_printf(conn, "use a web tool to send a POST request to %s\n", connWrkr->pReadBuf); } STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); rc = 405; FINALIZE; } if (ri->remote_addr[0] != '\0') { size_t len = strnlen(ri->remote_addr, sizeof(ri->remote_addr)); prop.CreateOrReuseStringProp(&connWrkr->propRemoteAddr, (const uchar *)ri->remote_addr, len); } if (ri->num_headers > 0) { int i; for (i = 0; i < ri->num_headers; i++) { if (!strcasecmp(ri->http_headers[i].name, "content-encoding") && !strcasecmp(ri->http_headers[i].value, "gzip")) { connWrkr->parseState.content_compressed = 1; } } } if (ri->content_length >= 0) { /* We know the content length in advance */ if ((uint64_t)ri->content_length > MAX_REQUEST_BODY_SIZE) { LogError(0, RS_RET_PARAM_ERROR, "imhttp: rejecting request body with Content-Length %lld exceeding maximum %d", (long long)ri->content_length, MAX_REQUEST_BODY_SIZE); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded); mg_printf(conn, "HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 413; FINALIZE; } if (!connWrkr->parseState.content_compressed && (uint64_t)ri->content_length + 1 > connWrkr->readBufSize) { char *newReadBuf = realloc(connWrkr->pReadBuf, (size_t)ri->content_length + 1); if (newReadBuf == NULL) { mg_cry(conn, "%s() - realloc failed!\n", __FUNCTION__); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } connWrkr->pReadBuf = newReadBuf; connWrkr->readBufSize = ri->content_length + 1; } } else { /* We must read until we find the end (chunked encoding * or connection close), indicated my mg_read returning 0 */ } while (1) { int count = mg_read(conn, connWrkr->pReadBuf, connWrkr->readBufSize); if (count > 0) { localRet = trackRequestBodyBytes(&connWrkr->parseState.requestBodyBytes, (size_t)count, "wire"); if (localRet == RS_RET_OVERSIZE_MSG) { STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded); mg_printf(conn, "HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 413; FINALIZE; } if (localRet != RS_RET_OK) { LogError(0, localRet, "imhttp: failed tracking request payload size"); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } localRet = processData(inst, connWrkr, (const char *)connWrkr->pReadBuf, count); if (localRet != RS_RET_OK) { if (localRet == RS_RET_OVERSIZE_MSG) { STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded); mg_printf(conn, "HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 413; FINALIZE; } LogError(0, localRet, "imhttp: failed processing request payload"); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } } else { break; } } if (connWrkr->parseState.content_compressed && !connWrkr->parseState.compressedDataComplete) { LogError(0, RS_RET_ZLIB_ERR, "imhttp: compressed request body ended before gzip stream completed"); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } /* submit remainder */ localRet = doSubmitMsg(inst, connWrkr, connWrkr->pMsg, connWrkr->iMsg); if (localRet != RS_RET_OK) { LogError(0, localRet, "imhttp: failed submitting final request message"); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } localRet = multiSubmitFlush(&connWrkr->multiSub); if (localRet != RS_RET_OK) { LogError(0, localRet, "imhttp: failed flushing submitted messages"); STATSCOUNTER_INC(statsCounter.ctrFailed, statsCounter.mutCtrFailed); mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"); rc = 500; FINALIZE; } mg_send_http_ok(conn, "text/plain", 0); rc = 200; finalize_it: if (connWrkr->parseState.bzInitDone) { inflateEnd(&connWrkr->parseState.zstrm); } /* reset */ connWrkr->iMsg = 0; return rc; } /* Health Check Handler */ static int health_check_handler(struct mg_connection *conn, ATTR_UNUSED void *cbdata) { const char *body = "OK\n"; mg_send_http_ok(conn, "text/plain; charset=utf-8", strlen(body)); mg_write(conn, body, strlen(body)); return 200; // CivetWeb expects handler to return HTTP status or specific flags } /* * prometheus_metrics_handler * Export rsyslog statistics in Prometheus text format. */ struct stats_buf { char *buf; size_t len; size_t cap; }; static rsRetVal prom_stats_collect(void *usrptr, const char *line) { struct stats_buf *sb = (struct stats_buf *)usrptr; const size_t line_len = strlen(line); if (line_len > ((size_t)-1) - sb->len - 1) { return RS_RET_OUT_OF_MEMORY; } const size_t needed = sb->len + line_len + 1; if (needed > sb->cap) { size_t newcap = sb->cap ? sb->cap * 2 : 1024; while (newcap < needed) { if (newcap > ((size_t)-1) / 2) { return RS_RET_OUT_OF_MEMORY; } newcap *= 2; } char *tmp = realloc(sb->buf, newcap); if (tmp == NULL) { return RS_RET_OUT_OF_MEMORY; } sb->buf = tmp; sb->cap = newcap; } memcpy(sb->buf + sb->len, line, line_len); sb->len += line_len; sb->buf[sb->len] = '\0'; return RS_RET_OK; } static int prometheus_metrics_handler(struct mg_connection *conn, ATTR_UNUSED void *cbdata) { struct stats_buf sb = {.buf = NULL, .len = 0, .cap = 0}; rsRetVal ret = RS_RET_OK; int http_status = 200; const char *imhttp_up_metric = "# HELP imhttp_up Indicates if the imhttp module is operational (1 for up, 0 for down).\n" "# TYPE imhttp_up gauge\n" "imhttp_up 1\n"; ret = prom_stats_collect(&sb, imhttp_up_metric); if (ret != RS_RET_OK) { LogError(0, RS_RET_OUT_OF_MEMORY, "imhttp: failed to allocate initial buffer for statistics"); http_status = 500; goto finalize; } ret = statsobj.GetAllStatsLines(prom_stats_collect, &sb, statsFmt_Prometheus, 0); if (ret != RS_RET_OK) { LogError(0, ret, "imhttp: failed to retrieve statistics"); http_status = 500; goto finalize; } mg_printf(conn, "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain; version=0.0.4; charset=utf-8\r\n" "Content-Length: %zu\r\n" "Connection: close\r\n" "\r\n", sb.len); mg_write(conn, sb.buf, sb.len); finalize: if (http_status != 200) { mg_printf(conn, "HTTP/1.1 500 Internal Server Error\r\nConnection: close\r\n\r\n"); } free(sb.buf); return http_status; } static int runloop(void) { dbgprintf("imhttp started.\n"); /* Register handlers under context lock to avoid civetweb races */ mg_lock_context(s_httpserv->ctx); for (instanceConf_t *inst = runModConf->root; inst != NULL; inst = inst->next) { assert(inst->pszEndpoint); if (inst->pszEndpoint) { dbgprintf("setting request handler: '%s'\n", inst->pszEndpoint); routeAuthCtxSet(&inst->authCtx, (const char *)inst->pszBasicAuthFile, (const char *)inst->pszApiKeyFile); registerRoute(s_httpserv->ctx, (const char *)inst->pszEndpoint, postHandler, inst, &inst->authCtx); } } if (runModConf->pszHealthCheckPath && runModConf->pszHealthCheckPath[0] != '\0') { dbgprintf("imhttp: setting request handler for global health check: '%s'\n", runModConf->pszHealthCheckPath); routeAuthCtxSet(&runModConf->healthCheckAuthCtx, runModConf->pszHealthCheckAuthFile, runModConf->pszHealthCheckApiKeyFile); registerRoute(s_httpserv->ctx, runModConf->pszHealthCheckPath, health_check_handler, NULL, &runModConf->healthCheckAuthCtx); } if (runModConf->pszMetricsPath && runModConf->pszMetricsPath[0] != '\0') { dbgprintf("imhttp: setting request handler for Prometheus metrics: '%s'\n", runModConf->pszMetricsPath); routeAuthCtxSet(&runModConf->metricsAuthCtx, runModConf->pszMetricsAuthFile, runModConf->pszMetricsApiKeyFile); registerRoute(s_httpserv->ctx, runModConf->pszMetricsPath, prometheus_metrics_handler, NULL /* cbdata, not used */, &runModConf->metricsAuthCtx); } mg_unlock_context(s_httpserv->ctx); /* Wait until the server should be closed */ while (glbl.GetGlobalInputTermState() == 0) { sleep(1); } return EXIT_SUCCESS; } BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst; int i; CODESTARTnewInpInst; DBGPRINTF("newInpInst (imhttp)\n"); pvals = nvlstGetParams(lst, &inppblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imhttp: required parameter are missing\n"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("input param blk in imtcp:\n"); cnfparamsPrint(&inppblk, pvals); } CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "endpoint")) { CHKmalloc(inst->pszEndpoint = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "basicauthfile")) { CHKmalloc(inst->pszBasicAuthFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "apikeyfile")) { CHKmalloc(inst->pszApiKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "name")) { CHKmalloc(inst->pszInputName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "ratelimit.burst")) { inst->ratelimitBurst = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "ratelimit.interval")) { inst->ratelimitInterval = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "ratelimit.name")) { CHKmalloc(inst->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "flowcontrol")) { inst->flowControl = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "disablelfdelimiter")) { inst->bDisableLFDelim = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "supportoctetcountedframing")) { inst->bSuppOctetFram = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "addmetadata")) { inst->bAddMetadata = (int)pvals[i].val.d.n; } else { dbgprintf( "imhttp: program error, non-handled " "param '%s'\n", inppblk.descr[i].name); } } if (inst->pszRatelimitName != NULL) { if (inst->ratelimitInterval != -1 || inst->ratelimitBurst != -1) { LogError(0, RS_RET_INVALID_PARAMS, "imhttp: ratelimit.name is mutually exclusive with " "ratelimit.interval and ratelimit.burst - using ratelimit.name"); } inst->ratelimitInterval = 0; inst->ratelimitBurst = 0; } else { if (inst->ratelimitInterval == -1) inst->ratelimitInterval = 0; if (inst->ratelimitBurst == -1) inst->ratelimitBurst = 10000; } if (inst->pszInputName) { CHKiRet(prop.Construct(&inst->pInputName)); CHKiRet(prop.SetString(inst->pInputName, inst->pszInputName, ustrlen(inst->pszInputName))); CHKiRet(prop.ConstructFinalize(inst->pInputName)); } if (inst->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfig(&inst->ratelimiter, loadModConf->pConf, (char *)inst->pszRatelimitName, "imhttp", NULL)); } else { CHKiRet(ratelimitNew(&inst->ratelimiter, "imhttp", NULL)); ratelimitSetLinuxLike(inst->ratelimiter, (unsigned)inst->ratelimitInterval, (unsigned)inst->ratelimitBurst); } finalize_it: CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; loadModConf->ports.name = NULL; loadModConf->docroot.name = NULL; loadModConf->nOptions = 0; loadModConf->options = NULL; loadModConf->pszLstnPortFileName = NULL; loadModConf->pszHealthCheckAuthFile = NULL; loadModConf->pszMetricsAuthFile = NULL; loadModConf->pszHealthCheckApiKeyFile = NULL; loadModConf->pszMetricsApiKeyFile = NULL; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; char *cstr = NULL; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imhttp: error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for imhttp:\n"); cnfparamsPrint(&modpblk, pvals); } for (int i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "ports")) { assert(loadModConf->ports.name == NULL); assert(loadModConf->ports.val == NULL); CHKmalloc(loadModConf->ports.name = strdup(CIVETWEB_OPTION_NAME_PORTS)); CHKmalloc(loadModConf->ports.val = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "listenportfilename")) { free(loadModConf->pszLstnPortFileName); CHKmalloc(loadModConf->pszLstnPortFileName = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "documentroot")) { assert(loadModConf->docroot.name == NULL); assert(loadModConf->docroot.val == NULL); CHKmalloc(loadModConf->docroot.name = strdup(CIVETWEB_OPTION_NAME_DOCUMENT_ROOT)); CHKmalloc(loadModConf->docroot.val = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "liboptions")) { if (pvals[i].val.d.ar->nmemb == 0) { continue; } const int nmemb = pvals[i].val.d.ar->nmemb; if (nmemb < 0 || (size_t)nmemb > ((size_t)-1) / sizeof(struct option)) { LogError(0, RS_RET_PARAM_ERROR, "imhttp: too many liboptions configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKmalloc(loadModConf->options = calloc((size_t)nmemb, sizeof(struct option))); for (int j = 0; j < nmemb; ++j) { CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL)); CHKiRet(processCivetwebOptions(cstr, &loadModConf->options[j].name, &loadModConf->options[j].val)); ++loadModConf->nOptions; free(cstr); cstr = NULL; } } else if (!strcmp(modpblk.descr[i].name, "healthcheckpath")) { free(loadModConf->pszHealthCheckPath); CHKmalloc(loadModConf->pszHealthCheckPath = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "metricspath")) { free(loadModConf->pszMetricsPath); CHKmalloc(loadModConf->pszMetricsPath = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "healthcheckbasicauthfile")) { free(loadModConf->pszHealthCheckAuthFile); CHKmalloc(loadModConf->pszHealthCheckAuthFile = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "metricsbasicauthfile")) { free(loadModConf->pszMetricsAuthFile); CHKmalloc(loadModConf->pszMetricsAuthFile = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "healthcheckapikeyfile")) { free(loadModConf->pszHealthCheckApiKeyFile); CHKmalloc(loadModConf->pszHealthCheckApiKeyFile = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "metricsapikeyfile")) { free(loadModConf->pszMetricsApiKeyFile); CHKmalloc(loadModConf->pszMetricsApiKeyFile = es_str2cstr(pvals[i].val.d.estr, NULL)); } else { dbgprintf( "imhttp: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } /* Set defaults if not configured but enabled */ // TODO: add ability to disable functionality, especially important if we // use this solely for health checking etc if (loadModConf->pszHealthCheckPath == NULL) { CHKmalloc(loadModConf->pszHealthCheckPath = strdup(DEFAULT_HEALTH_CHECK_PATH)); } if (loadModConf->pszMetricsPath == NULL) { CHKmalloc(loadModConf->pszMetricsPath = strdup(DEFAULT_PROM_METRICS_PATH)); } finalize_it: free(cstr); if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; /* done loading */ ENDendCnfLoad /* function to generate error message if framework does not find requested ruleset */ static inline void std_checkRuleset_genErrMsg(ATTR_UNUSED modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "imhttp: ruleset '%s' for %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->pszEndpoint); } static rsRetVal writeListenPortFile(const modConfData_t *const conf) { struct mg_server_port ports[2]; char portBuf[32]; int nPorts; int fd = -1; int len; ssize_t wr; DEFiRet; if (conf->pszLstnPortFileName == NULL) FINALIZE; nPorts = mg_get_server_ports(s_httpserv->ctx, sizeof(ports) / sizeof(ports[0]), ports); if (nPorts != 1) { LogError(0, RS_RET_ERR, "imhttp: listenPortFileName requires exactly one bound listener, got %d", nPorts); ABORT_FINALIZE(RS_RET_ERR); } len = snprintf(portBuf, sizeof(portBuf), "%u", (unsigned)ports[0].port); if (len < 0 || (size_t)len >= sizeof(portBuf)) { LogError(0, RS_RET_ERR, "imhttp: listenPortFileName: internal port formatting error"); ABORT_FINALIZE(RS_RET_ERR); } fd = open(conf->pszLstnPortFileName, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0600); if (fd == -1) { LogError(errno, RS_RET_IO_ERROR, "imhttp: listenPortFileName: error while trying to open file"); ABORT_FINALIZE(RS_RET_IO_ERROR); } for (int off = 0; off < len;) { wr = write(fd, portBuf + off, (size_t)(len - off)); if (wr < 0) { if (errno == EINTR) continue; LogError(errno, RS_RET_IO_ERROR, "imhttp: listenPortFileName: error while trying to write file"); ABORT_FINALIZE(RS_RET_IO_ERROR); } off += (int)wr; } if (close(fd) != 0) { fd = -1; LogError(errno, RS_RET_IO_ERROR, "imhttp: listenPortFileName: error while trying to close file"); ABORT_FINALIZE(RS_RET_IO_ERROR); } fd = -1; finalize_it: if (fd != -1) close(fd); RETiRet; } BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = pModConf->root; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); if (inst->pszEndpoint == NULL || inst->pszEndpoint[0] != '/') { LogError(0, RS_RET_CONFIG_ERROR, "imhttp: endpoint '%s' is invalid, must start with '/'", inst->pszEndpoint ? (const char *)inst->pszEndpoint : "(null)"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } /* verify civetweb options are valid */ const struct mg_option *valid_opts = mg_get_valid_options(); for (int i = 0; i < pModConf->nOptions; ++i) { if (!valid_civetweb_option(valid_opts, pModConf->options[i].name)) { LogError(0, RS_RET_CONF_PARSE_WARNING, "imhttp: module loaded, but " "invalid civetweb option found - imhttp may not receive connections."); iRet = RS_RET_CONF_PARSE_WARNING; } } if (pModConf->pszHealthCheckPath == NULL || pModConf->pszHealthCheckPath[0] != '/') { LogError(0, RS_RET_CONF_PARSE_WARNING, "imhttp: healthCheckPath '%s' is invalid, must start with '/'. Using default '%s'.", pModConf->pszHealthCheckPath ? pModConf->pszHealthCheckPath : "(null)", DEFAULT_HEALTH_CHECK_PATH); free(pModConf->pszHealthCheckPath); CHKmalloc(pModConf->pszHealthCheckPath = strdup(DEFAULT_HEALTH_CHECK_PATH)); } if (pModConf->pszMetricsPath == NULL || pModConf->pszMetricsPath[0] != '/') { LogError(0, RS_RET_CONF_PARSE_WARNING, "imhttp: metricsPath '%s' is invalid, must start with '/'. Using default '%s'.", pModConf->pszMetricsPath ? pModConf->pszMetricsPath : "(null)", DEFAULT_PROM_METRICS_PATH); free(pModConf->pszMetricsPath); CHKmalloc(pModConf->pszMetricsPath = strdup(DEFAULT_PROM_METRICS_PATH)); } finalize_it: ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; if (!s_httpserv) { CHKmalloc(s_httpserv = calloc(1, sizeof(httpserv_t))); } /* options represents (key, value) so allocate 2x, and null terminated */ size_t count = 1; if (runModConf->ports.val) { count += 2; } if (runModConf->docroot.val) { count += 2; } if (runModConf->nOptions < 0 || (size_t)runModConf->nOptions > ((size_t)-1 - count) / 2 || (size_t)runModConf->nOptions > ((size_t)-1) / sizeof(*s_httpserv->civetweb_options)) { LogError(0, RS_RET_PARAM_ERROR, "imhttp: too many civetweb options configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } count += (2 * runModConf->nOptions); if (count > ((size_t)-1) / sizeof(*s_httpserv->civetweb_options)) { LogError(0, RS_RET_PARAM_ERROR, "imhttp: too many civetweb options configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKmalloc(s_httpserv->civetweb_options = calloc(count, sizeof(*s_httpserv->civetweb_options))); const char **pcivetweb_options = s_httpserv->civetweb_options; if (runModConf->nOptions) { s_httpserv->civetweb_options_count = count; for (int i = 0; i < runModConf->nOptions; ++i) { *pcivetweb_options = runModConf->options[i].name; pcivetweb_options++; *pcivetweb_options = runModConf->options[i].val; pcivetweb_options++; } } /* append port, docroot */ if (runModConf->ports.val) { *pcivetweb_options = runModConf->ports.name; pcivetweb_options++; *pcivetweb_options = runModConf->ports.val; pcivetweb_options++; } if (runModConf->docroot.val) { *pcivetweb_options = runModConf->docroot.name; pcivetweb_options++; *pcivetweb_options = runModConf->docroot.val; pcivetweb_options++; } const char **option = s_httpserv->civetweb_options; for (; option && *option != NULL; option++) { dbgprintf("imhttp: civetweb option: %s\n", *option); } CHKiRet(statsobj.Construct(&statsCounter.stats)); CHKiRet(statsobj.SetName(statsCounter.stats, UCHAR_CONSTANT("imhttp"))); CHKiRet(statsobj.SetOrigin(statsCounter.stats, UCHAR_CONSTANT("imhttp"))); STATSCOUNTER_INIT(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted); CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrSubmitted))); STATSCOUNTER_INIT(statsCounter.ctrFailed, statsCounter.mutCtrFailed); CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("failed"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrFailed))); STATSCOUNTER_INIT(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded); CHKiRet(statsobj.AddCounter(statsCounter.stats, UCHAR_CONSTANT("discarded"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(statsCounter.ctrDiscarded))); CHKiRet(statsobj.ConstructFinalize(statsCounter.stats)); /* init civetweb libs and start server w/no input */ mg_init_library(MG_FEATURES_TLS); s_civetweb_initialized = 1; memset(&callbacks, 0, sizeof(callbacks)); // callbacks.log_message = log_message; // callbacks.init_ssl = init_ssl; callbacks.init_thread = init_thread; callbacks.exit_thread = exit_thread; s_httpserv->ctx = mg_start(&callbacks, NULL, s_httpserv->civetweb_options); /* Check return value: */ if (s_httpserv->ctx == NULL) { LogError(0, RS_RET_INTERNAL_ERROR, "Cannot start CivetWeb - mg_start failed.\n"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } CHKiRet(writeListenPortFile(runModConf)); finalize_it: if (iRet != RS_RET_OK) { cleanupHttpServer(); if (statsCounter.stats != NULL) { statsobj.Destruct(&statsCounter.stats); } LogError(0, NO_ERRCODE, "imhttp: error %d trying to activate configuration", iRet); } RETiRet; ENDactivateCnf BEGINfreeCnf instanceConf_t *inst, *del; CODESTARTfreeCnf; for (inst = pModConf->root; inst != NULL;) { if (inst->ratelimiter) { ratelimitDestruct(inst->ratelimiter); } if (inst->pInputName) { prop.Destruct(&inst->pInputName); } free(inst->pszEndpoint); free(inst->pszBasicAuthFile); free(inst->pszApiKeyFile); free(inst->pszBindRuleset); free(inst->pszInputName); free(inst->pszRatelimitName); del = inst; inst = inst->next; free(del); } for (int i = 0; i < pModConf->nOptions; ++i) { free((void *)pModConf->options[i].name); free((void *)pModConf->options[i].val); } free(pModConf->options); free((void *)pModConf->ports.name); free((void *)pModConf->ports.val); free((void *)pModConf->docroot.name); free((void *)pModConf->docroot.val); free((void *)pModConf->pszLstnPortFileName); free((void *)pModConf->pszHealthCheckPath); free((void *)pModConf->pszMetricsPath); free((void *)pModConf->pszHealthCheckAuthFile); free((void *)pModConf->pszMetricsAuthFile); free((void *)pModConf->pszHealthCheckApiKeyFile); free((void *)pModConf->pszMetricsApiKeyFile); if (statsCounter.stats) { statsobj.Destruct(&statsCounter.stats); } ENDfreeCnf /* This function is called to gather input. */ BEGINrunInput CODESTARTrunInput; runloop(); ENDrunInput /* initialize and return if will run or not */ BEGINwillRun CODESTARTwillRun; ENDwillRun BEGINafterRun CODESTARTafterRun; cleanupHttpServer(); ENDafterRun BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; // if(eFeat == sFEATURENonCancelInputTermination) // iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINmodExit CODESTARTmodExit; if (pInputName != NULL) { prop.Destruct(&pInputName); } /* release objects we used */ objRelease(statsobj, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imhttp"), sizeof("imhttp") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); ENDmodInit rsyslog-8.2608.0/contrib/imhttp/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160017553 xustar0030 mtime=1787067504.609322346 30 atime=1787067579.771724234 30 ctime=1787067803.118887618 rsyslog-8.2608.0/contrib/imhttp/Makefile.in0000664000175000017500000006557315241076160017237 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imhttp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) imhttp_la_LIBADD = am_imhttp_la_OBJECTS = imhttp_la-imhttp.lo imhttp_la_OBJECTS = $(am_imhttp_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 = imhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imhttp_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imhttp_la-imhttp.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imhttp_la_SOURCES) DIST_SOURCES = $(imhttp_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imhttp.la imhttp_la_SOURCES = imhttp.c imhttp_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(APU_CFLAGS) imhttp_la_LDFLAGS = -module -avoid-version $(CIVETWEB_LIBS) $(APU_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imhttp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imhttp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imhttp.la: $(imhttp_la_OBJECTS) $(imhttp_la_DEPENDENCIES) $(EXTRA_imhttp_la_DEPENDENCIES) $(AM_V_CCLD)$(imhttp_la_LINK) -rpath $(pkglibdir) $(imhttp_la_OBJECTS) $(imhttp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imhttp_la-imhttp.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imhttp_la-imhttp.lo: imhttp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imhttp_la-imhttp.lo -MD -MP -MF $(DEPDIR)/imhttp_la-imhttp.Tpo -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imhttp_la-imhttp.Tpo $(DEPDIR)/imhttp_la-imhttp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imhttp.c' object='imhttp_la-imhttp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imhttp_la-imhttp.lo `test -f 'imhttp.c' || echo '$(srcdir)/'`imhttp.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imhttp_la-imhttp.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/README0000644000000000000000000000013215035412264015061 xustar0030 mtime=1752569012.326271887 30 atime=1782715518.789788857 30 ctime=1787067790.754657223 rsyslog-8.2608.0/contrib/README0000666000175000017500000000110315035412264014522 0ustar00rgerrgerThis directory contains a number of possibly useful things that do not directly relate to rsyslog. They are not actively supported, but as I said often helpful. Use them with some care, as they may be outdated in respect to the current release of rsyslog. At least some of this stuff has been found by our users and been included after a brief check and possibly an adaptation. If you have something useful you would like to see in contrib, just drop us a note (see https://www.rsyslog.com for how to do that at the time your are reading this document). rgerhards, 2007-08-08 rsyslog-8.2608.0/contrib/PaxHeaders/ffaup0000644000000000000000000000013015241076627015233 xustar0030 mtime=1787067799.859826893 28 atime=1787067808.7849932 30 ctime=1787067799.859826893 rsyslog-8.2608.0/contrib/ffaup/0000775000175000017500000000000015241076627014756 5ustar00rgerrgerrsyslog-8.2608.0/contrib/ffaup/PaxHeaders/Makefile.am0000644000000000000000000000012615131231047017334 xustar0029 mtime=1768239655.58121057 29 atime=1787067433.89800302 28 ctime=1787067799.8548268 rsyslog-8.2608.0/contrib/ffaup/Makefile.am0000666000175000017500000000031415131231047016775 0ustar00rgerrger# # ffaup support # pkglib_LTLIBRARIES = ffaup.la ffaup_la_SOURCES = ffaup.c ffaup_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) ffaup_la_LDFLAGS = -module -avoid-version ffaup_la_LIBADD = $(FAUP_LIBS) rsyslog-8.2608.0/contrib/ffaup/PaxHeaders/ffaup.c0000644000000000000000000000013115132411300016532 xustar0030 mtime=1768559296.135883568 29 atime=1782715518.78878884 30 ctime=1787067799.860826912 rsyslog-8.2608.0/contrib/ffaup/ffaup.c0000666000175000017500000003565115132411300016213 0ustar00rgerrger/* ffaup.c * This is a function module for URL parsing. * * File begun on 2021/10/23 by TBertin * * Copyright 2007-2021 Theo Bertin for Advens * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #ifndef _AIX #include #endif #include #include #include #include #include #include #include "config.h" #include "rsyslog.h" #include "parserif.h" #include "module-template.h" #include "rainerscript.h" MODULE_TYPE_FUNCTION MODULE_TYPE_NOKEEP; DEF_FMOD_STATIC_DATA; faup_options_t *glbOptions = NULL; enum _faup_parse_type_t { FAUP_PARSE_ALL, FAUP_PARSE_SCHEME, FAUP_PARSE_CREDENTIAL, FAUP_PARSE_SUBDOMAIN, FAUP_PARSE_DOMAIN, FAUP_PARSE_DOMAIN_WITHOUT_TLD, FAUP_PARSE_HOST, FAUP_PARSE_TLD, FAUP_PARSE_PORT, FAUP_PARSE_RESOURCE_PATH, FAUP_PARSE_QUERY_STRING, FAUP_PARSE_FRAGMENT }; typedef enum _faup_parse_type_t faup_parse_type_t; static inline sbool check_param_count_faup(unsigned short nParams) { return nParams != 1; } static void ATTR_NONNULL() do_faup_parse(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti, const faup_parse_type_t parse_type) { struct svar srcVal; int bMustFree; cnfexprEval(func->expr[0], &srcVal, usrptr, pWti); char *url = (char *)var2CString(&srcVal, &bMustFree); /* We use the faup_handler_t struct directly instead of calling faup_init to avoid overhead and useless allocations. Using one handler is not possible as the lib is not thread-safe and thread-locale solutions still cause some issues. If the faup_init function changes significantly in the future, it may cause issue. (Validated with faup v1.5 and faup-master fecf768603e713bc903c56c8df0870fae14e3f93) */ faup_handler_t fh = {0}; fh.options = glbOptions; // default, return 0 ret->datatype = 'N'; ret->d.n = 0; if (!faup_decode(&fh, url, strlen(url))) { parser_errmsg("faup: could not parse the value\n"); // No returned error code, so the reason doesn't matter FINALIZE; } switch (parse_type) { case FAUP_PARSE_ALL: ret->datatype = 'J'; ret->d.json = json_object_new_object(); json_object_object_add( ret->d.json, "scheme", json_object_new_string_len(url + faup_get_scheme_pos(&fh), faup_get_scheme_size(&fh))); json_object_object_add( ret->d.json, "credential", json_object_new_string_len(url + faup_get_credential_pos(&fh), faup_get_credential_size(&fh))); json_object_object_add( ret->d.json, "subdomain", json_object_new_string_len(url + faup_get_subdomain_pos(&fh), faup_get_subdomain_size(&fh))); json_object_object_add( ret->d.json, "domain", json_object_new_string_len(url + faup_get_domain_pos(&fh), faup_get_domain_size(&fh))); json_object_object_add(ret->d.json, "domain_without_tld", json_object_new_string_len(url + faup_get_domain_without_tld_pos(&fh), faup_get_domain_without_tld_size(&fh))); json_object_object_add(ret->d.json, "host", json_object_new_string_len(url + faup_get_host_pos(&fh), faup_get_host_size(&fh))); json_object_object_add(ret->d.json, "tld", json_object_new_string_len(url + faup_get_tld_pos(&fh), faup_get_tld_size(&fh))); json_object_object_add(ret->d.json, "port", json_object_new_string_len(url + faup_get_port_pos(&fh), faup_get_port_size(&fh))); json_object_object_add( ret->d.json, "resource_path", json_object_new_string_len(url + faup_get_resource_path_pos(&fh), faup_get_resource_path_size(&fh))); json_object_object_add( ret->d.json, "query_string", json_object_new_string_len(url + faup_get_query_string_pos(&fh), faup_get_query_string_size(&fh))); json_object_object_add( ret->d.json, "fragment", json_object_new_string_len(url + faup_get_fragment_pos(&fh), faup_get_fragment_size(&fh))); break; case FAUP_PARSE_SCHEME: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_scheme_pos(&fh), faup_get_scheme_size(&fh)); break; case FAUP_PARSE_CREDENTIAL: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_credential_pos(&fh), faup_get_credential_size(&fh)); break; case FAUP_PARSE_SUBDOMAIN: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_subdomain_pos(&fh), faup_get_subdomain_size(&fh)); break; case FAUP_PARSE_DOMAIN: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_domain_pos(&fh), faup_get_domain_size(&fh)); break; case FAUP_PARSE_DOMAIN_WITHOUT_TLD: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_domain_without_tld_pos(&fh), faup_get_domain_without_tld_size(&fh)); break; case FAUP_PARSE_HOST: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_host_pos(&fh), faup_get_host_size(&fh)); break; case FAUP_PARSE_TLD: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_tld_pos(&fh), faup_get_tld_size(&fh)); break; case FAUP_PARSE_PORT: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_port_pos(&fh), faup_get_port_size(&fh)); break; case FAUP_PARSE_RESOURCE_PATH: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_resource_path_pos(&fh), faup_get_resource_path_size(&fh)); break; case FAUP_PARSE_QUERY_STRING: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_query_string_pos(&fh), faup_get_query_string_size(&fh)); break; case FAUP_PARSE_FRAGMENT: ret->datatype = 'S'; ret->d.estr = es_newStrFromCStr(url + faup_get_fragment_pos(&fh), faup_get_fragment_size(&fh)); break; default: break; } finalize_it: if (bMustFree) { free(url); } varFreeMembers(&srcVal); } static void ATTR_NONNULL() do_faup_parse_full(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_ALL); } static void ATTR_NONNULL() do_faup_parse_scheme(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SCHEME); } static void ATTR_NONNULL() do_faup_parse_credential(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_CREDENTIAL); } static void ATTR_NONNULL() do_faup_parse_subdomain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SUBDOMAIN); } static void ATTR_NONNULL() do_faup_parse_domain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN); } static void ATTR_NONNULL() do_faup_parse_domain_without_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN_WITHOUT_TLD); } static void ATTR_NONNULL() do_faup_parse_host(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_HOST); } static void ATTR_NONNULL() do_faup_parse_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_TLD); } static void ATTR_NONNULL() do_faup_parse_port(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_PORT); } static void ATTR_NONNULL() do_faup_parse_resource_path(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_RESOURCE_PATH); } static void ATTR_NONNULL() do_faup_parse_query_string(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_QUERY_STRING); } static void ATTR_NONNULL() do_faup_parse_fragment(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_FRAGMENT); } static rsRetVal ATTR_NONNULL(1) initFunc_faup_parse(struct cnffunc *const func) { DEFiRet; // Rsyslog cannot free the funcdata object, // a library-specific freeing function will be used during destruction func->destructable_funcdata = 0; if (check_param_count_faup(func->nParams)) { parser_errmsg("ffaup: ffaup(key) insufficient params.\n"); ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); } finalize_it: RETiRet; } static struct scriptFunct functions[] = { {"faup", 1, 1, do_faup_parse_full, initFunc_faup_parse, NULL}, {"faup_scheme", 1, 1, do_faup_parse_scheme, initFunc_faup_parse, NULL}, {"faup_credential", 1, 1, do_faup_parse_credential, initFunc_faup_parse, NULL}, {"faup_subdomain", 1, 1, do_faup_parse_subdomain, initFunc_faup_parse, NULL}, {"faup_domain", 1, 1, do_faup_parse_domain, initFunc_faup_parse, NULL}, {"faup_domain_without_tld", 1, 1, do_faup_parse_domain_without_tld, initFunc_faup_parse, NULL}, {"faup_host", 1, 1, do_faup_parse_host, initFunc_faup_parse, NULL}, {"faup_tld", 1, 1, do_faup_parse_tld, initFunc_faup_parse, NULL}, {"faup_port", 1, 1, do_faup_parse_port, initFunc_faup_parse, NULL}, {"faup_resource_path", 1, 1, do_faup_parse_resource_path, initFunc_faup_parse, NULL}, {"faup_query_string", 1, 1, do_faup_parse_query_string, initFunc_faup_parse, NULL}, {"faup_fragment", 1, 1, do_faup_parse_fragment, initFunc_faup_parse, NULL}, {NULL, 0, 0, NULL, NULL, NULL} // last element to check end of array }; BEGINgetFunctArray CODESTARTgetFunctArray; dbgprintf("Faup: ffaup\n"); *version = 1; *functArray = functions; ENDgetFunctArray BEGINmodExit CODESTARTmodExit; dbgprintf("ffaup: freeing options\n"); if (glbOptions) { faup_options_free(glbOptions); glbOptions = NULL; } ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_FMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ dbgprintf("ffaup: initializing options\n"); glbOptions = faup_options_new(); if (!glbOptions) { parser_errmsg("ffaup: could not initialize options\n"); ABORT_FINALIZE(RS_RET_FAUP_INIT_OPTIONS_FAILED); } // Don't generate a string output, and don't load LUA modules // This is useful only for the faup executable glbOptions->output = FAUP_OUTPUT_NONE; glbOptions->exec_modules = FAUP_MODULES_NOEXEC; CODEmodInit_QueryRegCFSLineHdlr dbgprintf("rsyslog ffaup init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/ffaup/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160017347 xustar0030 mtime=1787067504.399318428 30 atime=1787067579.013710099 30 ctime=1787067799.856826837 rsyslog-8.2608.0/contrib/ffaup/Makefile.in0000664000175000017500000006555415241076160017032 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/ffaup ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = ffaup_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_ffaup_la_OBJECTS = ffaup_la-ffaup.lo ffaup_la_OBJECTS = $(am_ffaup_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 = ffaup_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(ffaup_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/ffaup_la-ffaup.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(ffaup_la_SOURCES) DIST_SOURCES = $(ffaup_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # ffaup support # pkglib_LTLIBRARIES = ffaup.la ffaup_la_SOURCES = ffaup.c ffaup_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) ffaup_la_LDFLAGS = -module -avoid-version ffaup_la_LIBADD = $(FAUP_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/ffaup/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/ffaup/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } ffaup.la: $(ffaup_la_OBJECTS) $(ffaup_la_DEPENDENCIES) $(EXTRA_ffaup_la_DEPENDENCIES) $(AM_V_CCLD)$(ffaup_la_LINK) -rpath $(pkglibdir) $(ffaup_la_OBJECTS) $(ffaup_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ffaup_la-ffaup.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< ffaup_la-ffaup.lo: ffaup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ffaup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ffaup_la-ffaup.lo -MD -MP -MF $(DEPDIR)/ffaup_la-ffaup.Tpo -c -o ffaup_la-ffaup.lo `test -f 'ffaup.c' || echo '$(srcdir)/'`ffaup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ffaup_la-ffaup.Tpo $(DEPDIR)/ffaup_la-ffaup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ffaup.c' object='ffaup_la-ffaup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ffaup_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ffaup_la-ffaup.lo `test -f 'ffaup.c' || echo '$(srcdir)/'`ffaup.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/ffaup_la-ffaup.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/ffaup_la-ffaup.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmcount0000644000000000000000000000013215241076631015611 xustar0030 mtime=1787067801.499857448 30 atime=1787067808.785993219 30 ctime=1787067801.499857448 rsyslog-8.2608.0/contrib/mmcount/0000775000175000017500000000000015241076631015332 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmcount/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017716 xustar0029 mtime=1752569012.32825799 30 atime=1787067434.125007256 30 ctime=1787067801.494857354 rsyslog-8.2608.0/contrib/mmcount/Makefile.am0000666000175000017500000000031115035412264017360 0ustar00rgerrgerpkglib_LTLIBRARIES = mmcount.la mmcount_la_SOURCES = mmcount.c mmcount_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmcount_la_LDFLAGS = -module -avoid-version mmcount_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/mmcount/PaxHeaders/mmcount.c0000644000000000000000000000013115216464435017520 xustar0030 mtime=1782212893.960265117 29 atime=1782715518.78878884 30 ctime=1787067801.500857466 rsyslog-8.2608.0/contrib/mmcount/mmcount.c0000664000175000017500000002164415216464435017174 0ustar00rgerrger/* mmcount.c * count messages by priority or json property of given app-name. * * Copyright 2013 Red Hat Inc. * Copyright 2014 Rainer Gerhards * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "hashtable.h" #define JSON_COUNT_NAME "!mmcount" #define SEVERITY_COUNT 8 MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmcount") DEF_OMOD_STATIC_DATA; /* config variables */ typedef struct _instanceData { char *pszAppName; int severity[SEVERITY_COUNT]; char *pszKey; char *pszValue; int valueCounter; struct hashtable *ht; pthread_mutex_t mut; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"appname", eCmdHdlrGetWord, 0}, {"key", eCmdHdlrGetWord, 0}, {"value", eCmdHdlrGetWord, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; pthread_mutex_init(&pData->mut, NULL); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance static inline void setInstParamDefaults(instanceData *pData) { int i; pData->pszAppName = NULL; for (i = 0; i < SEVERITY_COUNT; i++) pData->severity[i] = 0; pData->pszKey = NULL; pData->pszValue = NULL; pData->valueCounter = 0; pData->ht = NULL; } static unsigned int hash_from_key_fn(void *k) { return *(unsigned int *)k; } static int key_equals_fn(void *k1, void *k2) { return (*(unsigned int *)k1 == *(unsigned int *)k2); } BEGINnewActInst struct cnfparamvals *pvals; int i; CODESTARTnewActInst; DBGPRINTF("newActInst (mmcount)\n"); if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "appname")) { CHKmalloc(pData->pszAppName = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } if (!strcmp(actpblk.descr[i].name, "key")) { CHKmalloc(pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } if (!strcmp(actpblk.descr[i].name, "value")) { CHKmalloc(pData->pszValue = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } dbgprintf( "mmcount: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } if (pData->pszAppName == NULL) { dbgprintf("mmcount: action requires a appname"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (pData->pszKey != NULL && pData->pszValue == NULL) { if (NULL == (pData->ht = create_hashtable(100, hash_from_key_fn, key_equals_fn, NULL))) { DBGPRINTF("mmcount: error creating hash table!\n"); ABORT_FINALIZE(RS_RET_ERR); } } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume static int *getCounter(struct hashtable *ht, const char *str) { unsigned int key; int *pCounter; unsigned int *pKey; /* we dont store str as key, instead we store hash of the str as key to reduce memory usage */ key = hash_from_string((char *)str); pCounter = hashtable_search(ht, &key); if (pCounter) { return pCounter; } /* counter is not found for the str, so add new entry and return the counter */ if (NULL == (pKey = (unsigned int *)malloc(sizeof(unsigned int)))) { DBGPRINTF("mmcount: memory allocation for key failed\n"); return NULL; } *pKey = key; if (NULL == (pCounter = (int *)malloc(sizeof(int)))) { DBGPRINTF("mmcount: memory allocation for value failed\n"); free(pKey); return NULL; } *pCounter = 0; if (!hashtable_insert(ht, pKey, pCounter)) { DBGPRINTF("mmcount: inserting element into hashtable failed\n"); free(pKey); free(pCounter); return NULL; } return pCounter; } BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; smsg_t *pMsg = ppMsg[0]; char *appname; struct json_object *json = NULL; struct json_object *keyjson = NULL; const char *pszValue; int *pCounter; instanceData *const pData = pWrkrData->pData; CODESTARTdoAction; appname = getAPPNAME(pMsg, LOCK_MUTEX); pthread_mutex_lock(&pData->mut); if (0 != strcmp(appname, pData->pszAppName)) { /* we are not working for this appname. nothing to do */ ABORT_FINALIZE(RS_RET_OK); } if (!pData->pszKey) { /* no key given for count, so we count severity */ if (pMsg->iSeverity < SEVERITY_COUNT) { pData->severity[pMsg->iSeverity]++; json = json_object_new_int(pData->severity[pMsg->iSeverity]); } ABORT_FINALIZE(RS_RET_OK); } /* key is given, so get the property json */ msgPropDescr_t pProp; msgPropDescrFill(&pProp, (uchar *)pData->pszKey, strlen(pData->pszKey)); rsRetVal localRet = msgGetJSONPropJSON(pMsg, &pProp, &keyjson); msgPropDescrDestruct(&pProp); if (localRet != RS_RET_OK) { /* key not found in the message. nothing to do */ ABORT_FINALIZE(RS_RET_OK); } /* key found, so get the value */ pszValue = (char *)json_object_get_string(keyjson); if (pszValue == NULL) { /* json null object returns NULL! */ pszValue = ""; } if (pData->pszValue) { /* value also given for count */ if (!strcmp(pszValue, pData->pszValue)) { /* count for (value and key and appname) matched */ pData->valueCounter++; json = json_object_new_int(pData->valueCounter); } ABORT_FINALIZE(RS_RET_OK); } /* value is not given, so we count for each value of given key */ pCounter = getCounter(pData->ht, pszValue); if (pCounter) { (*pCounter)++; json = json_object_new_int(*pCounter); } finalize_it: pthread_mutex_unlock(&pData->mut); if (json) { msgAddJSON(pMsg, (uchar *)JSON_COUNT_NAME, json, 0, 0); } ENDdoAction NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmcount: module compiled with rsyslog version %s.\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/mmcount/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160017727 xustar0030 mtime=1787067504.802325946 29 atime=1787067579.27171491 30 ctime=1787067801.496857392 rsyslog-8.2608.0/contrib/mmcount/Makefile.in0000664000175000017500000006564215241076160017411 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmcount ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) mmcount_la_DEPENDENCIES = am_mmcount_la_OBJECTS = mmcount_la-mmcount.lo mmcount_la_OBJECTS = $(am_mmcount_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 = mmcount_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(mmcount_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmcount_la-mmcount.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmcount_la_SOURCES) DIST_SOURCES = $(mmcount_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmcount.la mmcount_la_SOURCES = mmcount.c mmcount_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmcount_la_LDFLAGS = -module -avoid-version mmcount_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmcount/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmcount/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmcount.la: $(mmcount_la_OBJECTS) $(mmcount_la_DEPENDENCIES) $(EXTRA_mmcount_la_DEPENDENCIES) $(AM_V_CCLD)$(mmcount_la_LINK) -rpath $(pkglibdir) $(mmcount_la_OBJECTS) $(mmcount_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmcount_la-mmcount.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmcount_la-mmcount.lo: mmcount.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmcount_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmcount_la-mmcount.lo -MD -MP -MF $(DEPDIR)/mmcount_la-mmcount.Tpo -c -o mmcount_la-mmcount.lo `test -f 'mmcount.c' || echo '$(srcdir)/'`mmcount.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmcount_la-mmcount.Tpo $(DEPDIR)/mmcount_la-mmcount.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmcount.c' object='mmcount_la-mmcount.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmcount_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmcount_la-mmcount.lo `test -f 'mmcount.c' || echo '$(srcdir)/'`mmcount.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmcount_la-mmcount.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmcount_la-mmcount.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmsequence0000644000000000000000000000013215241076631016271 xustar0030 mtime=1787067801.585859051 30 atime=1787067808.785993219 30 ctime=1787067801.585859051 rsyslog-8.2608.0/contrib/mmsequence/0000775000175000017500000000000015241076631016012 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmsequence/PaxHeaders/mmsequence.c0000644000000000000000000000013215216464435020661 xustar0030 mtime=1782212893.962265149 30 atime=1787067641.391873202 30 ctime=1787067801.586859069 rsyslog-8.2608.0/contrib/mmsequence/mmsequence.c0000664000175000017500000002656515216464435020343 0ustar00rgerrger/* mmsequence.c * Generate a number based on some sequence. * * Copyright 2013 pavel@levshin.spb.ru. * * Based on: mmcount.c * Copyright 2013 Red Hat Inc. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "hashtable.h" #define JSON_VAR_NAME "$!mmsequence" enum mmSequenceModes { mmSequenceRandom, mmSequencePerInstance, mmSequencePerKey }; MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmsequence") DEF_OMOD_STATIC_DATA; /* config variables */ typedef struct _instanceData { enum mmSequenceModes mode; int valueFrom; int valueTo; int step; unsigned int seed; int value; char *pszKey; char *pszVar; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"mode", eCmdHdlrGetWord, 0}, {"from", eCmdHdlrNonNegInt, 0}, {"to", eCmdHdlrPositiveInt, 0}, {"step", eCmdHdlrNonNegInt, 0}, {"key", eCmdHdlrGetWord, 0}, {"var", eCmdHdlrGetWord, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; /* table for key-counter pairs */ static struct hashtable *ght; static pthread_mutex_t ght_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t inst_mutex = PTHREAD_MUTEX_INITIALIZER; BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance static inline void setInstParamDefaults(instanceData *pData) { pData->mode = mmSequencePerInstance; pData->valueFrom = 0; pData->valueTo = INT_MAX; pData->step = 1; pData->pszKey = (char *)""; pData->pszVar = (char *)JSON_VAR_NAME; } BEGINnewActInst struct cnfparamvals *pvals; int i; char *cstr; CODESTARTnewActInst; DBGPRINTF("newActInst (mmsequence)\n"); if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "mode")) { if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"random", sizeof("random") - 1)) { pData->mode = mmSequenceRandom; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"instance", sizeof("instance") - 1)) { pData->mode = mmSequencePerInstance; } else if (!es_strbufcmp(pvals[i].val.d.estr, (uchar *)"key", sizeof("key") - 1)) { pData->mode = mmSequencePerKey; } else { CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_INVLD_MODE, "mmsequence: invalid mode '%s' - ignored", cstr); free(cstr); } continue; } if (!strcmp(actpblk.descr[i].name, "from")) { pData->valueFrom = pvals[i].val.d.n; continue; } if (!strcmp(actpblk.descr[i].name, "to")) { pData->valueTo = pvals[i].val.d.n; continue; } if (!strcmp(actpblk.descr[i].name, "step")) { pData->step = pvals[i].val.d.n; continue; } if (!strcmp(actpblk.descr[i].name, "key")) { CHKmalloc(pData->pszKey = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } if (!strcmp(actpblk.descr[i].name, "var")) { CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); if (strlen(cstr) < 3) { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "mmsequence: valid variable name should be at least " "3 symbols long, got %s", cstr); free(cstr); } else if (cstr[0] != '$') { LogError(0, RS_RET_VALUE_NOT_SUPPORTED, "mmsequence: valid variable name should start with $," "got %s", cstr); free(cstr); } else { pData->pszVar = cstr; } continue; } dbgprintf( "mmsequence: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } switch (pData->mode) { case mmSequenceRandom: pData->seed = (unsigned int)(intptr_t)pData ^ (unsigned int)time(NULL); break; case mmSequencePerInstance: pData->value = pData->valueTo; break; case mmSequencePerKey: if (pthread_mutex_lock(&ght_mutex)) { DBGPRINTF("mmsequence: mutex lock has failed!\n"); ABORT_FINALIZE(RS_RET_ERR); } if (ght == NULL) { if (NULL == (ght = create_hashtable(100, hash_from_string, key_equals_string, NULL))) { pthread_mutex_unlock(&ght_mutex); DBGPRINTF("mmsequence: error creating hash table!\n"); ABORT_FINALIZE(RS_RET_ERR); } } pthread_mutex_unlock(&ght_mutex); break; default: LogError(0, RS_RET_INVLD_MODE, "mmsequence: this mode is not currently implemented"); } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume static int *getCounter(struct hashtable *ht, char *str, int initial) { int *pCounter; char *pStr; pCounter = hashtable_search(ht, str); if (pCounter) { return pCounter; } /* counter is not found for the str, so add new entry and return the counter */ if (NULL == (pStr = strdup(str))) { DBGPRINTF("mmsequence: memory allocation for key failed\n"); return NULL; } if (NULL == (pCounter = (int *)malloc(sizeof(*pCounter)))) { DBGPRINTF("mmsequence: memory allocation for value failed\n"); free(pStr); return NULL; } *pCounter = initial; if (!hashtable_insert(ht, pStr, pCounter)) { DBGPRINTF("mmsequence: inserting element into hashtable failed\n"); free(pStr); free(pCounter); return NULL; } return pCounter; } BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; smsg_t *pMsg = ppMsg[0]; struct json_object *json; int val = 0; int *pCounter; instanceData *pData; CODESTARTdoAction; pData = pWrkrData->pData; switch (pData->mode) { case mmSequenceRandom: val = pData->valueFrom + (rand_r(&pData->seed) % (pData->valueTo - pData->valueFrom)); break; case mmSequencePerInstance: if (!pthread_mutex_lock(&inst_mutex)) { if (pData->value >= pData->valueTo - pData->step) { pData->value = pData->valueFrom; } else { pData->value += pData->step; } val = pData->value; pthread_mutex_unlock(&inst_mutex); } else { LogError(0, RS_RET_ERR, "mmsequence: mutex lock has failed!"); } break; case mmSequencePerKey: if (!pthread_mutex_lock(&ght_mutex)) { pCounter = getCounter(ght, pData->pszKey, pData->valueTo); if (pCounter) { if (*pCounter >= pData->valueTo - pData->step || *pCounter < pData->valueFrom) { *pCounter = pData->valueFrom; } else { *pCounter += pData->step; } val = *pCounter; } else { LogError(0, RS_RET_NOT_FOUND, "mmsequence: unable to fetch the counter from hash"); } pthread_mutex_unlock(&ght_mutex); } else { LogError(0, RS_RET_ERR, "mmsequence: mutex lock has failed!"); } break; default: LogError(0, RS_RET_NOT_IMPLEMENTED, "mmsequence: this mode is not currently implemented"); } /* finalize_it: */ json = json_object_new_int(val); if (json == NULL) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "mmsequence: unable to create JSON"); } else { struct json_object *const toAdd = json; json = NULL; rsRetVal local_ret = msgAddJSON(pMsg, (uchar *)pData->pszVar + 1, toAdd, 0, 0); if (RS_RET_OK != local_ret) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "mmsequence: unable to pass out the value"); if (local_ret == RS_RET_NON_JSON_PROP) { json_object_put(toAdd); } } } ENDdoAction NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmsequence: module compiled with rsyslog version %s.\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/mmsequence/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020377 xustar0030 mtime=1752569012.329251042 30 atime=1787067434.211008861 30 ctime=1787067801.581858976 rsyslog-8.2608.0/contrib/mmsequence/Makefile.am0000666000175000017500000000033315035412264020044 0ustar00rgerrgerpkglib_LTLIBRARIES = mmsequence.la mmsequence_la_SOURCES = mmsequence.c mmsequence_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmsequence_la_LDFLAGS = -module -avoid-version mmsequence_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/mmsequence/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020410 xustar0030 mtime=1787067504.956328819 30 atime=1787067579.366716682 30 ctime=1787067801.583859013 rsyslog-8.2608.0/contrib/mmsequence/Makefile.in0000664000175000017500000006612015241076160020061 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmsequence ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) mmsequence_la_DEPENDENCIES = am_mmsequence_la_OBJECTS = mmsequence_la-mmsequence.lo mmsequence_la_OBJECTS = $(am_mmsequence_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 = mmsequence_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(mmsequence_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmsequence_la-mmsequence.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmsequence_la_SOURCES) DIST_SOURCES = $(mmsequence_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmsequence.la mmsequence_la_SOURCES = mmsequence.c mmsequence_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmsequence_la_LDFLAGS = -module -avoid-version mmsequence_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmsequence/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmsequence/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmsequence.la: $(mmsequence_la_OBJECTS) $(mmsequence_la_DEPENDENCIES) $(EXTRA_mmsequence_la_DEPENDENCIES) $(AM_V_CCLD)$(mmsequence_la_LINK) -rpath $(pkglibdir) $(mmsequence_la_OBJECTS) $(mmsequence_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmsequence_la-mmsequence.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmsequence_la-mmsequence.lo: mmsequence.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmsequence_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmsequence_la-mmsequence.lo -MD -MP -MF $(DEPDIR)/mmsequence_la-mmsequence.Tpo -c -o mmsequence_la-mmsequence.lo `test -f 'mmsequence.c' || echo '$(srcdir)/'`mmsequence.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmsequence_la-mmsequence.Tpo $(DEPDIR)/mmsequence_la-mmsequence.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmsequence.c' object='mmsequence_la-mmsequence.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmsequence_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmsequence_la-mmsequence.lo `test -f 'mmsequence.c' || echo '$(srcdir)/'`mmsequence.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmsequence_la-mmsequence.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmsequence_la-mmsequence.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imtuxedoulog0000644000000000000000000000013215241076632016655 xustar0030 mtime=1787067802.939884282 30 atime=1787067808.785993219 30 ctime=1787067802.939884282 rsyslog-8.2608.0/contrib/imtuxedoulog/0000775000175000017500000000000015241076632016376 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imtuxedoulog/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264020761 xustar0029 mtime=1752569012.32825799 30 atime=1787067434.108006939 30 ctime=1787067802.931884133 rsyslog-8.2608.0/contrib/imtuxedoulog/Makefile.am0000666000175000017500000000043315035412264020430 0ustar00rgerrgerpkglib_LTLIBRARIES = imtuxedoulog.la imtuxedoulog_la_SOURCES = imtuxedoulog.c imtuxedoulog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imtuxedoulog_la_LDFLAGS = -module -avoid-version imtuxedoulog_la_LIBADD = if OS_AIX imtuxedoulog_la_CPPFLAGS += -ma endif rsyslog-8.2608.0/contrib/imtuxedoulog/PaxHeaders/imtuxedoulog.c0000644000000000000000000000013215220503174021614 xustar0030 mtime=1782744700.130046227 30 atime=1782744704.702125399 30 ctime=1787067802.941884319 rsyslog-8.2608.0/contrib/imtuxedoulog/imtuxedoulog.c0000664000175000017500000007030215220503174021262 0ustar00rgerrger/* imtuxedoulog.c * * This is the input module for reading Tuxedo ULOG files. The particularity of this file * is that the timestamp is split between the filename (date) and the log line (time). * So this module switches on the date base betwwen files to open only the current file. * The log line is parsed according to the Tuxedo format. The ECID is extracted as a * structured data attribute. * * Work originally begun on 2019-01-11 by Philippe Duveau * * This file is contribution of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include /* do NOT remove: will soon be done by the module generation macros */ #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #ifdef _AIX #include #endif #include "rsyslog.h" /* error codes etc... */ #include "dirty.h" #include "cfsysline.h" /* access to config file objects */ #include "module-template.h" /* generic module interface code - very important, read it! */ #include "srUtils.h" /* some utility functions */ #include "msg.h" #include "stream.h" #include "errmsg.h" #include "glbl.h" #include "unicode-helper.h" #include "prop.h" #include "stringbuf.h" #include "ruleset.h" #include "ratelimit.h" struct instanceConf_s { uchar *pszUlogBaseName; uchar *pszCurrFName; struct tm currTm; uchar *pszTag; size_t lenTag; uchar *pszStateFile; uchar *pszBindRuleset; int nMultiSub; int iPersistStateInterval; int iFacility; int iSeverity; strm_t *pStrm; /* its stream (NULL if not assigned) */ int maxLinesAtOnce; ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ ratelimit_t *ratelimiter; multi_submit_t multiSub; int nRecords; struct instanceConf_s *next; struct instanceConf_s *prev; }; /* config variables */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static instanceConf_t *confRoot = NULL; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for run process */ MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imtuxedoulog") /* defines */ /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ DEFobjCurrIf(glbl) DEFobjCurrIf(strm) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) #define NUM_MULTISUB 1024 /* default max number of submits */ #define DFLT_PollInterval 10 int iPollInterval = DFLT_PollInterval; int iPersistStateInterval = 0; /* how often if state file to be persisted? (default 0->never) */ struct syslogTime syslogTz; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* module-global parameters */ /* input instance parameters */ static struct cnfparamdescr inppdescr[] = {{"ulogbase", eCmdHdlrString, CNFPARAM_REQUIRED}, {"tag", eCmdHdlrString, CNFPARAM_REQUIRED}, {"severity", eCmdHdlrSeverity, 0}, {"facility", eCmdHdlrFacility, 0}, {"ruleset", eCmdHdlrString, 0}, {"maxlinesatonce", eCmdHdlrInt, 0}, {"persiststateinterval", eCmdHdlrInt, 0}, {"maxsubmitatonce", eCmdHdlrInt, 0}}; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; #include "im-helper.h" /* must be included AFTER the type definitions! */ static uchar *mkFileNameWithTime(instanceConf_t *in) { uchar out[MAXFNAME]; struct timeval tp; #if defined(__hpux) struct timezone tz; gettimeofday(&tp, &tz); #else gettimeofday(&tp, NULL); #endif localtime_r(&tp.tv_sec, &(in->currTm)); snprintf((char *)out, MAXFNAME, "%s.%02d%02d%02d", (char *)in->pszUlogBaseName, in->currTm.tm_mon + 1, in->currTm.tm_mday, in->currTm.tm_year % 100); return ustrdup(out); } /* * Helper function to combine statefile and workdir */ static int getFullStateFileName(uchar *pszstatefile, uchar *pszout, int ilenout) { int lenout; const uchar *pszworkdir; /* Get Raw Workdir, if it is NULL we need to propper handle it */ pszworkdir = glblGetWorkDirRaw(runModConf->pConf); /* Construct file name */ lenout = snprintf((char *)pszout, ilenout, "%s/%s", (char *)(pszworkdir == NULL ? "." : (char *)pszworkdir), (char *)pszstatefile); /* return out length */ return lenout; } /* this generates a state file name suitable for the current file. To avoid * malloc calls, it must be passed a buffer which should be MAXFNAME large. * Note: the buffer is not necessarily populated ... always ONLY use the * RETURN VALUE! */ static uchar *ATTR_NONNULL(2) getStateFileName(instanceConf_t *const __restrict__ pInst, uchar *const __restrict__ buf, size_t lenbuf, const uchar *pszFileName) { uchar *ret; /* Use pszFileName parameter if set */ pszFileName = pszFileName == NULL ? pInst->pszUlogBaseName : pszFileName; DBGPRINTF("getStateFileName for '%s'\n", pszFileName); if (pInst == NULL || pInst->pszStateFile == NULL) { lenbuf = snprintf((char *)buf, lenbuf - 1, "imtuxedoulog-state:%s", pszFileName); buf[lenbuf] = '\0'; /* be on the safe side... */ uchar *p = buf; for (; *p; ++p) { if (*p == '/') *p = '-'; } ret = buf; } else { ret = pInst->pszStateFile; } return ret; } /* this func parses the line according to samples described in README.md */ static rsRetVal parseMsg(smsg_t *pMsg, char *rawMsg, size_t msgLen, instanceConf_t *const __restrict__ pInst) { char *prog, *host, *text = NULL, *strtData = NULL, *tmp; int hour, min, sec; rsRetVal ret; if (msgLen < 11) return RS_RET_COULD_NOT_PARSE; hour = (rawMsg[0] ^ 0x30) * 10 + (rawMsg[1] ^ 0x30); min = (rawMsg[2] ^ 0x30) * 10 + (rawMsg[3] ^ 0x30); sec = (rawMsg[4] ^ 0x30) * 10 + (rawMsg[5] ^ 0x30); if (hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59) return RS_RET_COULD_NOT_PARSE; host = rawMsg + ((rawMsg[10] == '.') ? 11 : 10); prog = memchr(host, '!', msgLen - (host - rawMsg)); if (prog == NULL) return RS_RET_COULD_NOT_PARSE; prog++; strtData = memchr(prog, ':', msgLen - (prog - rawMsg)); if (strtData == NULL) return RS_RET_COULD_NOT_PARSE; pMsg->tTIMESTAMP.year = pInst->currTm.tm_year + 1900; pMsg->tTIMESTAMP.month = pInst->currTm.tm_mon + 1; pMsg->tTIMESTAMP.day = pInst->currTm.tm_mday; pMsg->tTIMESTAMP.hour = hour; pMsg->tTIMESTAMP.minute = min; pMsg->tTIMESTAMP.second = sec; pMsg->tTIMESTAMP.OffsetMode = syslogTz.OffsetMode; pMsg->tTIMESTAMP.OffsetHour = syslogTz.OffsetHour; pMsg->tTIMESTAMP.OffsetMinute = syslogTz.OffsetMinute; pMsg->tTIMESTAMP.secfrac = 0; for (size_t i = 7; i < msgLen && i < 10 && rawMsg[i] >= '0' && rawMsg[i] <= '9'; ++i) { pMsg->tTIMESTAMP.secfrac = (pMsg->tTIMESTAMP.secfrac * 10) + (rawMsg[i] - '0'); } /* secfracprecision depends on the char on position 9 (case 1 or case 2) */ pMsg->tTIMESTAMP.secfracPrecision = (rawMsg[9] == '.') ? 2 : 3; for (tmp = strtData; prog < tmp && *tmp != '.'; tmp--); if (tmp > prog) *tmp = '\0'; else *strtData = '\0'; if ((size_t)(strtData - rawMsg) > msgLen - 2) return RS_RET_COULD_NOT_PARSE; strtData = strtData + 2; /* Case 4 */ if ((size_t)(strtData - rawMsg) <= msgLen - 5 && memcmp(strtData, "gtrid", 5) == 0) { strtData = memchr(strtData, ':', msgLen - (strtData - rawMsg)); if (strtData == NULL || (size_t)(strtData - rawMsg) > msgLen - 2) return RS_RET_COULD_NOT_PARSE; strtData += 2; } text = strtData; /* ecid point to message text or the word ECID */ if ((size_t)(strtData - rawMsg) <= msgLen - 4 && memcmp(strtData, "ECID", 4) == 0) { char *const ecidEnd = ((size_t)(strtData - rawMsg) <= msgLen - 7) ? memchr(strtData + 6, '>', msgLen - (strtData - rawMsg) - 6) : NULL; /* case 3 : we have the word ECID */ if (ecidEnd != NULL && (size_t)(ecidEnd - rawMsg) <= msgLen - 3) { text = ecidEnd; *(--strtData) = '['; strtData[5] = '='; strtData[6] = '\"'; *text++ = '\"'; *text++ = ']'; text++; ret = MsgAddToStructuredData(pMsg, (uchar *)strtData, text - strtData); if (ret != RS_RET_OK) LogMsg(0, ret, LOG_WARNING, "Add StructuredData to message failed."); } } /* now compute the new length */ msgLen -= text - rawMsg; if (text != NULL) MsgSetRawMsg(pMsg, text, msgLen); MsgSetMSGoffs(pMsg, 0); /* set hostname */ MsgSetHOSTNAME(pMsg, (const uchar *)host, prog - host - 1); if (*prog == '\0') return 0; /* set procid */ ret = MsgSetPROCID(pMsg, prog); if (ret != RS_RET_OK) LogMsg(0, ret, LOG_WARNING, "Set PROCID to message failed."); return RS_RET_OK; } /* enqueue the read file line as a message. The provided string is * not freed - this must be done by the caller. */ #define MAX_OFFSET_REPRESENTATION_NUM_BYTES 20 static rsRetVal enqLine(instanceConf_t *const __restrict__ pInst, cstr_t *const __restrict__ cstrLine) { DEFiRet; smsg_t *pMsg; const size_t msgLen = cstrLen(cstrLine); rsRetVal ret; if (msgLen == 0) { /* we do not process empty lines */ FINALIZE; } CHKiRet(msgConstruct(&pMsg)); if (parseMsg(pMsg, (char *)rsCStrGetSzStrNoNULL(cstrLine), msgLen, pInst) != RS_RET_OK) { if ((ret = msgDestruct(&pMsg)) != RS_RET_OK) LogMsg(0, ret, LOG_ERR, "msgDestruct failed."); FINALIZE; } MsgSetInputName(pMsg, pInputName); MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag); msgSetPRI(pMsg, pInst->iFacility | pInst->iSeverity); MsgSetRuleset(pMsg, pInst->pBindRuleset); if ((ret = MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY)) != RS_RET_OK) LogMsg(0, ret, LOG_WARNING, "Set Flow Control to message failed."); if ((ret = MsgSetAPPNAME(pMsg, (const char *)pInst->pszTag)) != RS_RET_OK) LogMsg(0, ret, LOG_WARNING, "Set APPNAME to message failed."); if ((iRet = ratelimitAddMsg(pInst->ratelimiter, &pInst->multiSub, pMsg)) != RS_RET_OK) { if ((ret = msgDestruct(&pMsg)) != RS_RET_OK) LogMsg(0, ret, LOG_ERR, "msgDestruct failed."); } finalize_it: RETiRet; } /* try to open a file which has a state file. If the state file does not * exist or cannot be read, an error is returned. */ static rsRetVal ATTR_NONNULL(1) openFileWithStateFile(instanceConf_t *const __restrict__ pInst) { DEFiRet; strm_t *psSF = NULL; uchar pszSFNam[MAXFNAME]; size_t lenSFNam; struct stat stat_buf; uchar statefile[MAXFNAME]; uchar *const statefn = getStateFileName(pInst, statefile, sizeof(statefile), NULL); DBGPRINTF("trying to open state for '%s', state file '%s'\n", pInst->pszUlogBaseName, statefn); /* Get full path and file name */ lenSFNam = getFullStateFileName(statefn, pszSFNam, sizeof(pszSFNam)); /* check if the file exists */ if (stat((char *)pszSFNam, &stat_buf) == -1) { if (errno == ENOENT) { DBGPRINTF("NO state file (%s) exists for '%s'\n", pszSFNam, pInst->pszUlogBaseName); ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); } else { char errStr[1024]; rs_strerror_r(errno, errStr, sizeof(errStr)); DBGPRINTF("error trying to access state file for '%s':%s\n", pInst->pszUlogBaseName, errStr); ABORT_FINALIZE(RS_RET_IO_ERROR); } } /* If we reach this point, we have a state file */ CHKiRet(strm.Construct(&psSF)); CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_READ)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetFName(psSF, pszSFNam, lenSFNam)); CHKiRet(strm.SetFileNotFoundError(psSF, 1)); CHKiRet(strm.ConstructFinalize(psSF)); /* read back in the object */ CHKiRet(obj.Deserialize(&pInst->pStrm, (uchar *)"strm", psSF, NULL, pInst)); DBGPRINTF( "deserialized state file, state file base name '%s', " "configured base name '%s'\n", pInst->pStrm->pszFName, pInst->pszUlogBaseName); if (ustrcmp(pInst->pStrm->pszFName, pInst->pszCurrFName)) { LogError(0, RS_RET_STATEFILE_WRONG_FNAME, "imtuxedoulog: state file '%s' " "contains file name '%s', but is used for file '%s'. State " "file deleted, starting from begin of file.", pszSFNam, pInst->pStrm->pszFName, pInst->pszCurrFName); unlink((char *)pszSFNam); ABORT_FINALIZE(RS_RET_STATEFILE_WRONG_FNAME); } strm.CheckFileChange(pInst->pStrm); CHKiRet(strm.SeekCurrOffs(pInst->pStrm)); /* note: we do not delete the state file, so that the last position remains * known even in the case that rsyslogd aborts for some reason (like powerfail) */ finalize_it: if (psSF != NULL) strm.Destruct(&psSF); RETiRet; } /* try to open a file for which no state file exists. This function does NOT * check if a state file actually exists or not -- this must have been * checked before calling it. */ static rsRetVal openFileWithoutStateFile(instanceConf_t *const __restrict__ pInst) { DEFiRet; DBGPRINTF("clean startup withOUT state file for '%s'\n", pInst->pszUlogBaseName); if (pInst->pStrm != NULL) strm.Destruct(&pInst->pStrm); CHKiRet(strm.Construct(&pInst->pStrm)); CHKiRet(strm.SettOperationsMode(pInst->pStrm, STREAMMODE_READ)); CHKiRet(strm.SetsType(pInst->pStrm, STREAMTYPE_FILE_MONITOR)); CHKiRet(strm.SetFName(pInst->pStrm, pInst->pszCurrFName, strlen((char *)pInst->pszCurrFName))); CHKiRet(strm.SetFileNotFoundError(pInst->pStrm, 1)); CHKiRet(strm.ConstructFinalize(pInst->pStrm)); finalize_it: RETiRet; } /* try to open a file. This involves checking if there is a status file and, * if so, reading it in. Processing continues from the last known location. */ static rsRetVal openFile(instanceConf_t *const __restrict__ pInst) { DEFiRet; CHKiRet_Hdlr(openFileWithStateFile(pInst)) { CHKiRet(openFileWithoutStateFile(pInst)); } CHKiRet(strm.SetbReopenOnTruncate(pInst->pStrm, 1)); finalize_it: RETiRet; } /* This function persists information for a specific file being monitored. * To do so, it simply persists the stream object. We do NOT abort on error * iRet as that makes matters worse (at least we can try persisting the others...). * rgerhards, 2008-02-13 */ static void persistStrmState(instanceConf_t *pInst) { DEFiRet; strm_t *psSF = NULL; /* state file (stream) */ size_t lenDir; uchar statefile[MAXFNAME]; uchar *const statefn = getStateFileName(pInst, statefile, sizeof(statefile), NULL); DBGPRINTF("persisting state for '%s' to file '%s'\n", pInst->pszUlogBaseName, statefn); CHKiRet(strm.Construct(&psSF)); lenDir = ustrlen(glbl.GetWorkDir(runModConf->pConf)); if (lenDir > 0) CHKiRet(strm.SetDir(psSF, glbl.GetWorkDir(runModConf->pConf), lenDir)); CHKiRet(strm.SettOperationsMode(psSF, STREAMMODE_WRITE_TRUNC)); CHKiRet(strm.SetsType(psSF, STREAMTYPE_FILE_SINGLE)); CHKiRet(strm.SetFName(psSF, statefn, strlen((char *)statefn))); CHKiRet(strm.SetFileNotFoundError(psSF, 1)); CHKiRet(strm.ConstructFinalize(psSF)); CHKiRet(strm.Serialize(pInst->pStrm, psSF)); CHKiRet(strm.Flush(psSF)); CHKiRet(strm.Destruct(&psSF)); finalize_it: if (psSF != NULL) strm.Destruct(&psSF); if (iRet != RS_RET_OK) { LogError(0, iRet, "imtuxedoulog: could not persist state " "file %s - data may be repeated on next " "startup. Is WorkDirectory set?", statefn); } } /* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27 */ static void pollFileCancelCleanup(void *pArg) { cstr_t **ppCStr = (cstr_t **)pArg; if (*ppCStr != NULL) { rsCStrDestruct(ppCStr); } } static void pollFileReal(instanceConf_t *pInst, int *pbHadFileData, cstr_t **ppCStr) { DEFiRet; int nProcessed = 0; if (pInst->pStrm == NULL) { CHKiRet(openFile(pInst)); /* open file */ } /* loop below will be exited when strmReadLine() returns EOF */ while (glbl.GetGlobalInputTermState() == 0) { if (pInst->maxLinesAtOnce != 0 && nProcessed >= pInst->maxLinesAtOnce) break; CHKiRet(strm.ReadLine(pInst->pStrm, ppCStr, 0, 0, NULL, -1, NULL)); ++nProcessed; if (pbHadFileData != NULL) *pbHadFileData = 1; /* this is just a flag, so set it and forget it */ CHKiRet(enqLine(pInst, *ppCStr)); /* process line */ rsCStrDestruct(ppCStr); /* discard string (must be done by us!) */ if (pInst->iPersistStateInterval > 0 && ++pInst->nRecords >= pInst->iPersistStateInterval) { persistStrmState(pInst); pInst->nRecords = 0; } } finalize_it: multiSubmitFlush(&pInst->multiSub); if (*ppCStr != NULL) { rsCStrDestruct(ppCStr); } } /* poll a file, need to check file rollover etc. open file if not open */ static void pollFile(instanceConf_t *pInst, int *pbHadFileData) { cstr_t *pCStr = NULL; /* Note: we must do pthread_cleanup_push() immediately, because the POSIX macros * otherwise do not work if I include the _cleanup_pop() inside an if... -- rgerhards, 2008-08-14 */ pthread_cleanup_push(pollFileCancelCleanup, &pCStr); pollFileReal(pInst, pbHadFileData, &pCStr); pthread_cleanup_pop(0); } /* create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal ATTR_NONNULL(1) createInstance(instanceConf_t **const pinst) { instanceConf_t *inst; DEFiRet; CHKmalloc(inst = malloc(sizeof(instanceConf_t))); inst->next = NULL; inst->pBindRuleset = NULL; inst->ratelimiter = NULL; inst->pStrm = NULL; inst->multiSub.ppMsgs = NULL; inst->pszBindRuleset = NULL; inst->pszUlogBaseName = NULL; inst->pszCurrFName = NULL; inst->pszTag = NULL; inst->pszStateFile = NULL; inst->nMultiSub = NUM_MULTISUB; inst->iSeverity = 5; inst->iFacility = 128; inst->maxLinesAtOnce = 0; inst->iPersistStateInterval = 0; inst->nRecords = 0; *pinst = inst; finalize_it: RETiRet; } /* This adds a new listener object to the bottom of the list, but * it does NOT initialize any data members except for the list * pointers themselves. */ static rsRetVal ATTR_NONNULL() lstnAdd(instanceConf_t *pInst) { DEFiRet; CHKiRet(ratelimitNew(&pInst->ratelimiter, "imtuxedoulog", (char *)pInst->pszUlogBaseName)); CHKmalloc(pInst->multiSub.ppMsgs = malloc(pInst->nMultiSub * sizeof(smsg_t *))); pInst->multiSub.maxElem = pInst->nMultiSub; pInst->multiSub.nElem = 0; /* insert it at the begin of the list */ pInst->prev = NULL; pInst->next = confRoot; if (confRoot != NULL) confRoot->prev = pInst; confRoot = pInst; finalize_it: RETiRet; } /* delete a listener object */ static void ATTR_NONNULL(1) lstnDel(instanceConf_t *pInst) { DBGPRINTF("lstnDel called for %s\n", pInst->pszUlogBaseName); if (pInst->pStrm != NULL) { /* stream open? */ persistStrmState(pInst); strm.Destruct(&(pInst->pStrm)); } if (pInst->ratelimiter != NULL) ratelimitDestruct(pInst->ratelimiter); if (pInst->multiSub.ppMsgs != NULL) free(pInst->multiSub.ppMsgs); free(pInst->pszUlogBaseName); if (pInst->pszCurrFName != NULL) free(pInst->pszCurrFName); if (pInst->pszTag) free(pInst->pszTag); if (pInst->pszStateFile) free(pInst->pszStateFile); if (pInst->pszBindRuleset != NULL) free(pInst->pszBindRuleset); free(pInst); } /* Monitor files in traditional polling mode. */ static void do_polling(void) { int bHadFileData; /* were there at least one file with data during this run? */ struct stat sb; while (glbl.GetGlobalInputTermState() == 0) { do { instanceConf_t *pInst; bHadFileData = 0; for (pInst = confRoot; pInst != NULL; pInst = pInst->next) { uchar *temp = mkFileNameWithTime(pInst); DBGPRINTF("imtuxedoulog: do_polling start '%s' / '%s'\n", pInst->pszUlogBaseName, temp); /* * Is the file name is different : a rotation time is reached * If so, then it the new file exists ? and is a file ? */ if (temp && stat((const char *)temp, &sb) == 0 && S_ISREG(sb.st_mode) && (pInst->pszCurrFName == NULL || strcmp((char *)temp, (char *)pInst->pszCurrFName) != 0)) { DBGPRINTF( "imtuxedoulog: timed file : rotation reach " "switching form '%s' to '%s' !", (char *)pInst->pszUlogBaseName, temp); /* first of all change the listener datas */ if (pInst->pszCurrFName != NULL) { free(pInst->pszCurrFName); strm.Destruct(&pInst->pStrm); } pInst->pszCurrFName = temp; temp = NULL; /* And finish by destroy the stream object, so the next polling will recreate * it based on new data. */ if (glbl.GetGlobalInputTermState() == 1) break; /* terminate input! */ } if (temp) free(temp); /* let's poll the file */ if (pInst->pszCurrFName != NULL) pollFile(pInst, &bHadFileData); DBGPRINTF("imtuxedoulog: do_polling end for '%s'\n", pInst->pszUlogBaseName); if (pInst->iPersistStateInterval == -1) persistStrmState(pInst); } } while (bHadFileData == 1 && glbl.GetGlobalInputTermState() == 0); /* Note: the additional 10ns wait is vitally important. It guards rsyslog * against totally hogging the CPU if the users selects a polling interval * of 0 seconds. It doesn't hurt any other valid scenario. So do not remove. * rgerhards, 2008-02-14 */ if (glbl.GetGlobalInputTermState() == 0) srSleep(iPollInterval, 10); } } BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst; int i; CODESTARTnewInpInst; DBGPRINTF("newInpInst (imtuxedoulog)\n"); pvals = nvlstGetParams(lst, &inppblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { DBGPRINTF("input param blk in imtuxedoulog:\n"); cnfparamsPrint(&inppblk, pvals); } CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "ulogbase")) { CHKmalloc(inst->pszUlogBaseName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "tag")) { CHKmalloc(inst->pszTag = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); inst->lenTag = es_strlen(pvals[i].val.d.estr); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "severity")) { inst->iSeverity = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "facility")) { inst->iFacility = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "maxlinesatonce")) { inst->maxLinesAtOnce = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "persiststateinterval")) { inst->iPersistStateInterval = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "maxsubmitatonce")) { inst->nMultiSub = pvals[i].val.d.n; } else { DBGPRINTF( "program error, non-handled " "param '%s'\n", inppblk.descr[i].name); } } if (inst->pszUlogBaseName == NULL) { lstnDel(inst); LogError(0, RS_RET_FILE_NOT_SPECIFIED, "ulogbase is not configured - no input will be gathered"); ABORT_FINALIZE(RS_RET_FILE_NOT_SPECIFIED); } if ((iRet = lstnAdd(inst)) != RS_RET_OK) { LogError(0, iRet, "add input %s to list failed", inst->pszUlogBaseName); lstnDel(inst); ABORT_FINALIZE(iRet); } finalize_it: CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = confRoot; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); } ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINrunInput CODESTARTrunInput; do_polling(); DBGPRINTF("terminating upon request of rsyslog core\n"); ENDrunInput BEGINwillRun CODESTARTwillRun; /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imtuxedoulog"), sizeof("imtuxedoulog") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun; while (confRoot != NULL) { instanceConf_t *inst = confRoot; confRoot = confRoot->next; lstnDel(inst); } if (pInputName != NULL) prop.Destruct(&pInputName); ENDafterRun BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINmodExit CODESTARTmodExit; /* release objects we used */ objRelease(strm, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "imtuxedoulog: ruleset '%s' for ULOG base %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->pszUlogBaseName); } BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(strm, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/imtuxedoulog/PaxHeaders/README.md0000644000000000000000000000013115035412264020204 xustar0029 mtime=1752569012.32825799 30 atime=1782715518.787788823 30 ctime=1787067802.937884245 rsyslog-8.2608.0/contrib/imtuxedoulog/README.md0000666000175000017500000000410115035412264017647 0ustar00rgerrger# imtuxedoulog : Tuxedo ULOG input module ### Module summary This module is created to consume Tuxedo ULOG file. This file has the following characteristics : - the file name is compose of a prefix and the date of the file. - the lines of logs are produced by call to userlog() tuxedo method. - Tuxedo server based on JAVA writes java's exceptions as log lines in ULOG file. This version of the module ignores those lines. - The ECID (Execution Context ID) is extracted and placed as a structured data named ECID. ### Why this module instead of using imfile As the file name is a rotation base of the current date, imfile must use a glob to manage this rotation. Imfile must use fs notify implement of the OS. This interface is implemented in imfile for Linux and Solaris but not AIX. Like imfile does, this module is using the same rsyslog core stream and then gets advantages its evolves. Primary we tried to integrating in imfile a "glob like" in polling mode, it increased the module complexity and make it unmaintainable. So imfile could not be a valid candidate on none fs notification OS like AIX. ### Ulog log samples This are different case of logs in the ULOG file according to the usage. Case 1: second fraction precision = 2 ``` 105211.70.sic-in2-tmsl1!IMSproxiCSFI4EC.26607818.1.0: TSAM_CAT:305:4563628752 ; I ;TPSUCCESS service ^host ^prog lprog> ^text ``` Case 2: second fraction precision = 3 ``` 011458.705.sic-tst-tmsl1!LMS.5243392.772.3: TSAM_CAT:305: WARN: (23498) times logon TSAM Plus manager ^host ^prog lprog> ^text ``` Case 3: with ECID ``` 105211.704.sic-in2-tmsl1!IMSproxiCSFI4EC.26607818.1.0: ECID <000003GBORvD4iopwSXBiW01xG2M00001n>: 4563628752 ^host ^prog lprog> ^ecid ^text ``` Case 4: with gtrid & ECID ``` 164313.151.sic-tst-tmsm1!ARTIMPP_UDB.42722.1.0: gtrid x0 ... a0f: ECID <000001833^5pVl3iY00f003UF^>: TRACE:at ^host ^prog lprog> ^ecid ^text ``` rsyslog-8.2608.0/contrib/imtuxedoulog/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020773 xustar0030 mtime=1787067504.771325368 30 atime=1787067579.710723097 30 ctime=1787067802.934884188 rsyslog-8.2608.0/contrib/imtuxedoulog/Makefile.in0000664000175000017500000006641115241076160020447 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @OS_AIX_TRUE@am__append_1 = -ma subdir = contrib/imtuxedoulog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) imtuxedoulog_la_DEPENDENCIES = am_imtuxedoulog_la_OBJECTS = imtuxedoulog_la-imtuxedoulog.lo imtuxedoulog_la_OBJECTS = $(am_imtuxedoulog_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 = imtuxedoulog_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(imtuxedoulog_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imtuxedoulog_la_SOURCES) DIST_SOURCES = $(imtuxedoulog_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ README.md DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imtuxedoulog.la imtuxedoulog_la_SOURCES = imtuxedoulog.c imtuxedoulog_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) \ $(RSRT_CFLAGS) $(am__append_1) imtuxedoulog_la_LDFLAGS = -module -avoid-version imtuxedoulog_la_LIBADD = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imtuxedoulog/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imtuxedoulog/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imtuxedoulog.la: $(imtuxedoulog_la_OBJECTS) $(imtuxedoulog_la_DEPENDENCIES) $(EXTRA_imtuxedoulog_la_DEPENDENCIES) $(AM_V_CCLD)$(imtuxedoulog_la_LINK) -rpath $(pkglibdir) $(imtuxedoulog_la_OBJECTS) $(imtuxedoulog_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imtuxedoulog_la-imtuxedoulog.lo: imtuxedoulog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imtuxedoulog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imtuxedoulog_la-imtuxedoulog.lo -MD -MP -MF $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Tpo -c -o imtuxedoulog_la-imtuxedoulog.lo `test -f 'imtuxedoulog.c' || echo '$(srcdir)/'`imtuxedoulog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Tpo $(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imtuxedoulog.c' object='imtuxedoulog_la-imtuxedoulog.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imtuxedoulog_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imtuxedoulog_la-imtuxedoulog.lo `test -f 'imtuxedoulog.c' || echo '$(srcdir)/'`imtuxedoulog.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imtuxedoulog_la-imtuxedoulog.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omczmq0000644000000000000000000000013015241076625015436 xustar0029 mtime=1787067797.73778735 30 atime=1787067808.785993219 29 ctime=1787067797.73778735 rsyslog-8.2608.0/contrib/omczmq/0000775000175000017500000000000015241076625015161 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omczmq/PaxHeaders/README0000644000000000000000000000013215035412264016367 xustar0030 mtime=1752569012.329251042 30 atime=1782715518.793788925 30 ctime=1787067797.735787313 rsyslog-8.2608.0/contrib/omczmq/README0000666000175000017500000000557315035412264016047 0ustar00rgerrgerCZMQ Output Plugin REQUIREMENTS: * libsodium ( https://github.com/jedisct1/libsodium ) * zeromq built with libsodium support ( http://zeromq.org/ ) * czmq ( http://czmq.zeromq.org/ ) EXPLANATION OF OPTIONS Module ------ servercertpath: path to server cert if using CURVE clientcertpath: path to client cert(s) if using CURVE authtype: CURVESERVER, CURVECLIENT (omit for no auth) authenticator: whether to start an authenticator thread Action ------ type: type of action (omczmq for this plugin) endpoints: comma delimited list of zeromq endpoints (see zeromq documentation) socktype: zeromq socket type (currently supports PUSH, PUB, DEALER, RADIO, CLIENT, SCATTER) sendtimeout: timeout in ms before send errors sendhwm: number of messages to store in internal buffer before discarding (defaults to 1000) connecttimeout: connection timeout in ms(requires libzmq 4.2 or higher) heartbeativl: time in ms between sending heartbeat PING messages (requires libzmq 4.2 or higher) heartbeattimeout: time in milliseconds to wait for a PING response before disconnect(libzmq 4.2 or higher) heartbeatttl: time remote peer should wait between PINGs before disconnect (libzmq 4.2 or higher) topicframe: "on" to send topic as separate frame if PUB socket topics: comma delimited list of topics or templates to make topics from if PUB or RADIO socket dynatopic: if "on" topics list is treated as list of template names template: template to use for message (defaults to RSYSLOG_ForwardFormat) EXAMPLE CONFIGURATION This configuration sets up an omczmq endpoint as a ZMQ_PUB socket with CURVE authentication. Clients whose certificates are in the '/etc/curve.d/allowed_clients/' directory will be allowed to connect. Each message is published on two topics ( "hostname.programname" and "programname.hostname" ) which are constructed from properties of the log message. For instance, a log from sshd from host.example.com will be published on two topics: * host.example.com.sshd * sshd.host.example.com In this configuration, the output is configured to send each message as a two frame message, with the topic in the first flame and the rsyslog message in the second. ------------------------------------------------------------------------------- module( load="omczmq" servercertpath="/etc/curve.d/example_server" clientcertpath="/etc/curve.d/allowed_clients" authtype="CURVESERVER" authenticator="on" ) template(name="host_program_topic" type="list") { property(name="hostname") constant(value=".") property(name="programname") } template(name="program_host_topic" type="list") { property(name="programname") constant(value=".") property(name="hostname") } action( name="to_zeromq" type="omczmq" socktype="PUB" endpoints="@tcp://*:31338" topics="host_program_topic,program_host_topic" dynatopic="on" topicframe="on" ) ------------------------------------------------------------------------------- rsyslog-8.2608.0/contrib/omczmq/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017542 xustar0030 mtime=1752569012.329251042 29 atime=1787067434.26400985 30 ctime=1787067797.728787182 rsyslog-8.2608.0/contrib/omczmq/Makefile.am0000666000175000017500000000033715035412264017214 0ustar00rgerrgerpkglib_LTLIBRARIES = omczmq.la omczmq_la_SOURCES = omczmq.c omczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS) omczmq_la_LDFLAGS = -module -avoid-version omczmq_la_LIBADD = $(CZMQ_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/omczmq/PaxHeaders/omczmq.c0000644000000000000000000000013215216464435017171 xustar0030 mtime=1782212893.962265149 30 atime=1782715518.790788874 30 ctime=1787067797.738787369 rsyslog-8.2608.0/contrib/omczmq/omczmq.c0000664000175000017500000005670615216464435016653 0ustar00rgerrger/** * @file omczmq.c * @brief Output module for sending messages over ZeroMQ. * * This module uses the CZMQ high-level API to create and manage ZeroMQ * sockets. Messages are formatted using rsyslog templates and published * according to the configured socket type and topic list, which may be * static or generated dynamically from templates. CURVE * authentication and heartbeat settings are supported when available. * * Copyright (C) 2016 Brian Knox * Copyright (C) 2014 Rainer Gerhards * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omczmq") DEF_OMOD_STATIC_DATA; static pthread_mutex_t mutDoAct = PTHREAD_MUTEX_INITIALIZER; static struct cnfparamdescr modpdescr[] = {{"authenticator", eCmdHdlrBinary, 0}, {"authtype", eCmdHdlrGetWord, 0}, {"clientcertpath", eCmdHdlrGetWord, 0}, {"servercertpath", eCmdHdlrGetWord, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; struct modConfData_s { rsconf_t *pConf; uchar *tplName; int authenticator; char *authType; char *serverCertPath; char *clientCertPath; }; static modConfData_t *runModConf = NULL; static zactor_t *authActor; typedef struct _instanceData { zsock_t *sock; bool serverish; int sendTimeout; zlist_t *topics; bool sendError; char *sockEndpoints; int sockType; int sendHWM; #if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MINOR >= 2) int heartbeatIvl; int heartbeatTimeout; int heartbeatTTL; int connectTimeout; #endif uchar *tplName; sbool topicFrame; sbool dynaTopic; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; static struct cnfparamdescr actpdescr[] = { {"endpoints", eCmdHdlrGetWord, 1}, {"socktype", eCmdHdlrGetWord, 1}, {"sendhwm", eCmdHdlrGetWord, 0}, #if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MINOR >= 2) {"heartbeatttl", eCmdHdlrGetWord, 0}, {"heartbeativl", eCmdHdlrGetWord, 0}, {"heartbeattimeout", eCmdHdlrGetWord, 0}, {"connecttimeout", eCmdHdlrGetWord, 0}, #endif {"sendtimeout", eCmdHdlrGetWord, 0}, {"template", eCmdHdlrGetWord, 0}, {"topics", eCmdHdlrGetWord, 0}, {"topicframe", eCmdHdlrGetWord, 0}, {"dynatopic", eCmdHdlrBinary, 0}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; /** * @brief Initialize the CZMQ socket for an action instance. * * Creates the socket of the configured type, applies optional CURVE * authentication and heartbeat parameters and attaches it to the * configured endpoints. The @a serverish flag is set according to * the socket type to control how CZMQ connects or binds the socket. * * @param pData action instance configuration * @retval RS_RET_OK on success * @retval RS_RET_SUSPENDED on initialization failure */ static rsRetVal initCZMQ(instanceData *pData) { DEFiRet; int rc; putenv((char *)"ZSYS_SIGHANDLER=false"); pData->sock = zsock_new(pData->sockType); if (!pData->sock) { LogError(0, RS_RET_NO_ERRCODE, "omczmq: new socket failed for endpoints: %s", pData->sockEndpoints); ABORT_FINALIZE(RS_RET_SUSPENDED); } zsock_set_sndtimeo(pData->sock, pData->sendTimeout); #if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MINOR >= 2) if (pData->heartbeatIvl > 0 && pData->heartbeatTimeout > 0 && pData->heartbeatTTL > 0) { zsock_set_heartbeat_ivl(pData->sock, pData->heartbeatIvl); zsock_set_heartbeat_timeout(pData->sock, pData->heartbeatTimeout); zsock_set_heartbeat_ttl(pData->sock, pData->heartbeatTTL); } #endif if (runModConf->authType) { if (!strcmp(runModConf->authType, "CURVESERVER")) { zcert_t *serverCert = zcert_load(runModConf->serverCertPath); if (!serverCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->serverCertPath); ABORT_FINALIZE(RS_RET_ERR); } zsock_set_zap_domain(pData->sock, "global"); zsock_set_curve_server(pData->sock, 1); zcert_apply(serverCert, pData->sock); zcert_destroy(&serverCert); } else if (!strcmp(runModConf->authType, "CURVECLIENT")) { zcert_t *serverCert = zcert_load(runModConf->serverCertPath); if (!serverCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->serverCertPath); ABORT_FINALIZE(RS_RET_ERR); } const char *server_key = zcert_public_txt(serverCert); zcert_destroy(&serverCert); zsock_set_curve_serverkey(pData->sock, server_key); zcert_t *clientCert = zcert_load(runModConf->clientCertPath); if (!clientCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->clientCertPath); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(clientCert, pData->sock); zcert_destroy(&clientCert); } } switch (pData->sockType) { case ZMQ_PUB: /* ZMQ_RADIO socket type is available and stable in all czmq versions that * define it. The previous version restriction (< 4.2.0) was incorrect and * has been removed. */ #if defined(ZMQ_RADIO) case ZMQ_RADIO: #endif pData->serverish = true; break; case ZMQ_PUSH: #if defined(ZMQ_SCATTER) case ZMQ_SCATTER: #endif case ZMQ_DEALER: #if defined(ZMQ_CLIENT) case ZMQ_CLIENT: #endif pData->serverish = false; break; default: break; } rc = zsock_attach(pData->sock, pData->sockEndpoints, pData->serverish); if (rc == -1) { LogError(0, NO_ERRCODE, "zsock_attach to %s failed", pData->sockEndpoints); ABORT_FINALIZE(RS_RET_SUSPENDED); } finalize_it: RETiRet; } /** * @brief Send a formatted message through the configured CZMQ socket. * * For PUB or RADIO sockets a list of topics can be configured. Each * topic triggers a send operation. When @c topicFrame is true on PUB * sockets, the topic is transmitted in a separate frame, otherwise it * is prepended to the message. RADIO sockets instead set the frame's * group name to the topic. When @c dynaTopic is enabled, template * results beyond index @c 0 provide the topic strings. Other socket * types simply transmit the message stored in @c ppString[0]. * * @param ppString array of template results; message text is in * @c ppString[0] and additional elements may hold topics * @param pData action instance data * @retval RS_RET_OK on success * @retval RS_RET_SUSPENDED if transmission fails */ static rsRetVal outputCZMQ(uchar **ppString, instanceData *pData) { DEFiRet; if (NULL == pData->sock) { CHKiRet(initCZMQ(pData)); } /* if we are using a PUB (or RADIO) socket and we have a topic list then we * need some special care and attention */ /* ZMQ_RADIO socket type support - available in all czmq versions that define it */ #if defined(ZMQ_RADIO) DBGPRINTF("omczmq: ZMQ_RADIO is defined...\n"); if ((pData->sockType == ZMQ_PUB || pData->sockType == ZMQ_RADIO) && pData->topics) { #else DBGPRINTF("omczmq: ZMQ_RADIO is NOT defined...\n"); if (pData->sockType == ZMQ_PUB && pData->topics) { #endif int templateIndex = 1; const char *topic = (const char *)zlist_first(pData->topics); while (topic) { int rc; /* if dynaTopic is true, the topic is constructed by rsyslog * by applying the supplied template to the message properties */ if (pData->dynaTopic) topic = (const char *)ppString[templateIndex]; if (pData->sockType == ZMQ_PUB) { /* if topicFrame is true, send the topic as a separate zmq frame */ if (pData->topicFrame) { rc = zstr_sendx(pData->sock, topic, (char *)ppString[0], NULL); } /* if topicFrame is false, concatenate the topic with the * message in the same frame */ else { rc = zstr_sendf(pData->sock, "%s%s", topic, (char *)ppString[0]); } /* if we have a send error notify rsyslog */ if (rc != 0) { pData->sendError = true; ABORT_FINALIZE(RS_RET_SUSPENDED); } } /* ZMQ_RADIO socket type support - available in all czmq versions that define it */ #if defined(ZMQ_RADIO) else if (pData->sockType == ZMQ_RADIO) { DBGPRINTF("omczmq: sending on RADIO socket...\n"); zframe_t *frame = zframe_from((char *)ppString[0]); if (!frame) { DBGPRINTF("omczmq: failed to create frame...\n"); pData->sendError = true; ABORT_FINALIZE(RS_RET_SUSPENDED); } rc = zframe_set_group(frame, topic); if (rc != 0) { DBGPRINTF("omczmq: failed to set group '%d'...\n", rc); pData->sendError = true; ABORT_FINALIZE(RS_RET_SUSPENDED); } DBGPRINTF("omczmq: set RADIO group to '%s'\n", topic); rc = zframe_send(&frame, pData->sock, 0); if (rc != 0) { pData->sendError = true; ABORT_FINALIZE(RS_RET_SUSPENDED); } } #endif /* get the next topic from the list, and increment * our topic index */ topic = zlist_next(pData->topics); templateIndex++; } } /* we aren't a PUB socket and we don't have a topic list - this means * we can just send the message using the rsyslog template */ else { int rc = zstr_send(pData->sock, (char *)ppString[0]); if (rc != 0) { pData->sendError = true; DBGPRINTF("omczmq: send error: %d", rc); ABORT_FINALIZE(RS_RET_SUSPENDED); } } finalize_it: RETiRet; } static inline void setInstParamDefaults(instanceData *pData) { pData->sockEndpoints = NULL; pData->sock = NULL; pData->sendError = false; pData->serverish = false; pData->tplName = NULL; pData->sockType = -1; pData->sendTimeout = -1; pData->topics = NULL; pData->topicFrame = false; #if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MINOR >= 2) pData->heartbeatIvl = 0; pData->heartbeatTimeout = 0; pData->heartbeatTTL = 0; #endif } BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) { iRet = RS_RET_OK; } ENDisCompatibleWithFeature BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; ENDdbgPrintInstInfo BEGINfreeInstance CODESTARTfreeInstance; zlist_destroy(&pData->topics); zsock_destroy(&pData->sock); free(pData->sockEndpoints); free(pData->tplName); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINtryResume instanceData *pData; CODESTARTtryResume; pthread_mutex_lock(&mutDoAct); pData = pWrkrData->pData; DBGPRINTF("omczmq: trying to resume...\n"); zsock_destroy(&pData->sock); iRet = initCZMQ(pData); pthread_mutex_unlock(&mutDoAct); ENDtryResume BEGINbeginCnfLoad CODESTARTbeginCnfLoad; runModConf = pModConf; runModConf->pConf = pConf; runModConf->authenticator = 0; runModConf->authType = NULL; runModConf->serverCertPath = NULL; runModConf->clientCertPath = NULL; ENDbeginCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; if (runModConf->authenticator == 1) { if (!authActor) { DBGPRINTF("omczmq: starting authActor\n"); authActor = zactor_new(zauth, NULL); if (!strcmp(runModConf->clientCertPath, "*")) { zstr_sendx(authActor, "CURVE", CURVE_ALLOW_ANY, NULL); } else { zstr_sendx(authActor, "CURVE", runModConf->clientCertPath, NULL); } zsock_wait(authActor); } } ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(pModConf->tplName); free(pModConf->authType); free(pModConf->serverCertPath); free(pModConf->clientCertPath); DBGPRINTF("omczmq: stopping authActor\n"); zactor_destroy(&authActor); ENDfreeCnf BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) { DBGPRINTF("omczmq: pvals[i].bUSed continuing\n"); continue; } if (!strcmp(modpblk.descr[i].name, "authenticator")) { runModConf->authenticator = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "authtype")) { CHKmalloc(runModConf->authType = es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: authtype set to %s\n", runModConf->authType); } else if (!strcmp(modpblk.descr[i].name, "servercertpath")) { CHKmalloc(runModConf->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: serverCertPath set to %s\n", runModConf->serverCertPath); } else if (!strcmp(modpblk.descr[i].name, "clientcertpath")) { CHKmalloc(runModConf->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: clientCertPath set to %s\n", runModConf->clientCertPath); } else { LogError(0, RS_RET_INVALID_PARAMS, "omczmq: config error, unknown " "param %s in setModCnf\n", modpblk.descr[i].name); } } DBGPRINTF("omczmq: authenticator set to %d\n", runModConf->authenticator); DBGPRINTF("omczmq: authType set to %s\n", runModConf->authType); DBGPRINTF("omczmq: serverCertPath set to %s\n", runModConf->serverCertPath); DBGPRINTF("omczmq: clientCertPath set to %s\n", runModConf->clientCertPath); finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; runModConf = NULL; ENDendCnfLoad BEGINdoAction instanceData *pData; CODESTARTdoAction; pthread_mutex_lock(&mutDoAct); pData = pWrkrData->pData; iRet = outputCZMQ(ppString, pData); pthread_mutex_unlock(&mutDoAct); ENDdoAction BEGINnewActInst struct cnfparamvals *pvals; int i; int iNumTpls; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } if (!strcmp(actpblk.descr[i].name, "endpoints")) { CHKmalloc(pData->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: sockEndPoints set to '%s'\n", pData->sockEndpoints); } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: template set to '%s'\n", pData->tplName); } else if (!strcmp(actpblk.descr[i].name, "dynatopic")) { pData->dynaTopic = pvals[i].val.d.n; DBGPRINTF("omczmq: dynaTopic set to %s\n", pData->dynaTopic ? "true" : "false"); } else if (!strcmp(actpblk.descr[i].name, "sendtimeout")) { char *tmpSendTimeout; CHKmalloc(tmpSendTimeout = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->sendTimeout = atoi(tmpSendTimeout); free(tmpSendTimeout); DBGPRINTF("omczmq: sendTimeout set to %d\n", pData->sendTimeout); } else if (!strcmp(actpblk.descr[i].name, "sendhwm")) { char *tmpSendTimeout; CHKmalloc(tmpSendTimeout = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->sendHWM = atoi(tmpSendTimeout); free(tmpSendTimeout); DBGPRINTF("omczmq: sendHWM set to %d\n", pData->sendHWM); } #if (CZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MAJOR >= 4 && ZMQ_VERSION_MINOR >= 2) else if (!strcmp(actpblk.descr[i].name, "heartbeativl")) { char *tmpHeartbeatIvl; CHKmalloc(tmpHeartbeatIvl = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->heartbeatIvl = atoi(tmpHeartbeatIvl); free(tmpHeartbeatIvl); DBGPRINTF("omczmq: heartbeatbeatIvl set to %d\n", pData->heartbeatIvl); } else if (!strcmp(actpblk.descr[i].name, "heartbeattimeout")) { char *tmpHeartbeatTimeout; CHKmalloc(tmpHeartbeatTimeout = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->heartbeatTimeout = atoi(tmpHeartbeatTimeout); free(tmpHeartbeatTimeout); DBGPRINTF("omczmq: heartbeatTimeout set to %d\n", pData->heartbeatTimeout); } else if (!strcmp(actpblk.descr[i].name, "heartbeatttl")) { char *tmpHeartbeatTimeout; CHKmalloc(tmpHeartbeatTimeout = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->heartbeatTTL = atoi(tmpHeartbeatTimeout); free(tmpHeartbeatTimeout); DBGPRINTF("omczmq: heartbeatTTL set to %d\n", pData->heartbeatTTL); } #endif else if (!strcmp(actpblk.descr[i].name, "socktype")) { char *stringType; CHKmalloc(stringType = es_str2cstr(pvals[i].val.d.estr, NULL)); if (stringType != NULL) { if (!strcmp("PUB", stringType)) { pData->sockType = ZMQ_PUB; DBGPRINTF("omczmq: sockType set to ZMQ_PUB\n"); } /* ZMQ_RADIO socket type support - available in all czmq versions that define it */ #if defined(ZMQ_RADIO) else if (!strcmp("RADIO", stringType)) { pData->sockType = ZMQ_RADIO; DBGPRINTF("omczmq: sockType set to ZMQ_RADIO\n"); } #endif else if (!strcmp("PUSH", stringType)) { pData->sockType = ZMQ_PUSH; DBGPRINTF("omczmq: sockType set to ZMQ_PUSH\n"); } #if defined(ZMQ_SCATTER) else if (!strcmp("SCATTER", stringType)) { pData->sockType = ZMQ_SCATTER; DBGPRINTF("omczmq: sockType set to ZMQ_SCATTER\n"); } #endif else if (!strcmp("DEALER", stringType)) { pData->sockType = ZMQ_DEALER; DBGPRINTF("omczmq: sockType set to ZMQ_DEALER\n"); } #if defined(ZMQ_CLIENT) else if (!strcmp("CLIENT", stringType)) { pData->sockType = ZMQ_CLIENT; DBGPRINTF("omczmq: sockType set to ZMQ_CLIENT\n"); } #endif free(stringType); } else { LogError(0, RS_RET_OUT_OF_MEMORY, "omczmq: out of memory"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } else if (!strcmp(actpblk.descr[i].name, "topicframe")) { pData->topicFrame = pvals[i].val.d.n; DBGPRINTF("omczmq: topicFrame set to %s\n", pData->topicFrame ? "true" : "false"); } else if (!strcmp(actpblk.descr[i].name, "topics")) { pData->topics = zlist_new(); char *topics; CHKmalloc(topics = es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("omczmq: topics set to %s\n", topics); char *topics_org = topics; char topic[256]; if (topics == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "out of memory"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } while (*topics) { char *delimiter = strchr(topics, ','); if (!delimiter) { delimiter = topics + strlen(topics); } memcpy(topic, topics, delimiter - topics); topic[delimiter - topics] = 0; char *current_topic = strdup(topic); zlist_append(pData->topics, current_topic); if (*delimiter == 0) { break; } topics = delimiter + 1; } free(topics_org); } else { LogError(0, NO_ERRCODE, "omczmq: config error - '%s' is not a valid option", actpblk.descr[i].name); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } iNumTpls = 1; if (pData->dynaTopic) { iNumTpls = zlist_size(pData->topics) + iNumTpls; } CODE_STD_STRING_REQUESTnewActInst(iNumTpls); if (pData->tplName == NULL) { CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)strdup("RSYSLOG_ForwardFormat"), OMSR_NO_RQD_TPL_OPTS)); } else { CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)pData->tplName, OMSR_NO_RQD_TPL_OPTS)); } i = 1; if (pData->dynaTopic) { char *topic = zlist_first(pData->topics); while (topic) { CHKiRet(OMSRsetEntry(*ppOMSR, i, (uchar *)strdup(topic), OMSR_NO_RQD_TPL_OPTS)); i++; topic = zlist_next(pData->topics); } } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINinitConfVars CODESTARTinitConfVars; ENDinitConfVars NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING); DBGPRINTF("omczmq: module compiled with rsyslog version %s.\n", VERSION); INITLegCnfVars; ENDmodInit rsyslog-8.2608.0/contrib/omczmq/PaxHeaders/Makefile.in0000644000000000000000000000013215241076161017555 xustar0030 mtime=1787067505.056330685 30 atime=1787067579.304715525 30 ctime=1787067797.732787257 rsyslog-8.2608.0/contrib/omczmq/Makefile.in0000664000175000017500000006566515241076161017243 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omczmq ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omczmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_omczmq_la_OBJECTS = omczmq_la-omczmq.lo omczmq_la_OBJECTS = $(am_omczmq_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 = omczmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omczmq_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omczmq_la-omczmq.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omczmq_la_SOURCES) DIST_SOURCES = $(omczmq_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omczmq.la omczmq_la_SOURCES = omczmq.c omczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS) omczmq_la_LDFLAGS = -module -avoid-version omczmq_la_LIBADD = $(CZMQ_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omczmq/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omczmq/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omczmq.la: $(omczmq_la_OBJECTS) $(omczmq_la_DEPENDENCIES) $(EXTRA_omczmq_la_DEPENDENCIES) $(AM_V_CCLD)$(omczmq_la_LINK) -rpath $(pkglibdir) $(omczmq_la_OBJECTS) $(omczmq_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omczmq_la-omczmq.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omczmq_la-omczmq.lo: omczmq.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omczmq_la-omczmq.lo -MD -MP -MF $(DEPDIR)/omczmq_la-omczmq.Tpo -c -o omczmq_la-omczmq.lo `test -f 'omczmq.c' || echo '$(srcdir)/'`omczmq.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omczmq_la-omczmq.Tpo $(DEPDIR)/omczmq_la-omczmq.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omczmq.c' object='omczmq_la-omczmq.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omczmq_la-omczmq.lo `test -f 'omczmq.c' || echo '$(srcdir)/'`omczmq.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omczmq_la-omczmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omczmq_la-omczmq.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omrabbitmq0000644000000000000000000000013215241076625016267 xustar0030 mtime=1787067797.823788952 30 atime=1787067808.785993219 30 ctime=1787067797.823788952 rsyslog-8.2608.0/contrib/omrabbitmq/0000775000175000017500000000000015241076625016010 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omrabbitmq/PaxHeaders/omrabbitmq.c0000644000000000000000000000013215216464435020647 xustar0030 mtime=1782212893.964265181 30 atime=1787067630.769675164 30 ctime=1787067797.823788952 rsyslog-8.2608.0/contrib/omrabbitmq/omrabbitmq.c0000664000175000017500000014740015216464435020321 0ustar00rgerrger/* omrabbitmq.c * * This output plugin enables rsyslog to send messages to the RabbitMQ. * * Copyright 2012-2013 Vaclav Tomec * Copyright 2014 Rainer Gerhards * Copyright 2022 Hamid Maadani * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * . * * Author: Vaclav Tomec * * * TLS & AMQP heartbeat support added by: * Hamid Maadani * * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "debug.h" #include "datetime.h" #include "rsconf.h" #include /* rabbitmq-c 0.8.0+ uses rabbitmq-c/ prefix for headers */ #ifdef HAVE_RABBITMQ_C_AMQP_H /* rabbitmq-c 0.8.0+ header path */ #include #include #include #include #else /* Fallback for older rabbitmq-c versions (< 0.8.0) */ #include "amqp.h" #include "amqp_framing.h" #include "amqp_tcp_socket.h" #include "amqp_ssl_socket.h" #endif #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 4) #error "rabbitmq-c version must be >= 0.4.0" #endif #define RABBITMQ_CHANNEL 1 MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omrabbitmq") /* * internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) static int instance_counter = 0; static int mode_test = 0; typedef struct { char *host; /* rabbitmq server fqdn or IP */ int port; /* rabbitmq server port */ } server_t; typedef struct { server_t s; /* rabbitmq server */ int failures; /* rabbitmq server failures */ } server_wrk_t; typedef struct { time_t return_check_interval; /* time interval between usual server health checks */ time_t half_return_check_interval; /* for computing */ time_t quick_oscillation_interval; /* time interval below which the service is not stable */ int quick_oscillation_max; /* number of quick oscillation after which the connection is kept on backup */ time_t graceful_interval; /* time interval the connection is kept on backup after which the usual server * check restarts */ int quick_oscillation_count; /* current number of simultaneous quick oscillation detected */ } recover_t; typedef struct _instanceData { /* here you need to define all action-specific data. A record of type * instanceData will be handed over to each instance of the action. Keep * in mind that there may be several invocations of the same type of action * inside rsyslog.conf, and this is what keeps them apart. Do NOT use * static data for this! */ amqp_bytes_t exchange; /* exchange to send message to */ amqp_bytes_t routing_key; /* fixed routing_key to use */ uchar *routing_key_template; /* routing_key template */ int idx_routing_key_template; /* routing_key template index in doAction tab */ sbool populate_properties; /* populates message properties */ int delivery_mode; /* delivery mode transient or persistent message */ amqp_bytes_t expiration; /* message expiration */ uchar *body_template; /* body template */ int idx_body_template; /* body template index in doAction tab */ amqp_basic_properties_t amqp_props_tpl_type; /* */ char *content_type; /* */ amqp_basic_properties_t amqp_props_plaintext; /* */ char *exchange_type; /* */ int durable; /* */ int auto_delete; /* */ int iidx; int nbWrkr; server_t server1; /* first rabbitmq server */ server_t server2; /* second rabbitmq server */ char *vhost; /* rabbitmq server vhost */ char *user; /* rabbitmq username */ char *password; /* rabbitmq username's password */ int ssl; /* should amqp connection be made over TLS? */ int initOpenSSL; /* should rabbitmq-c initialize OpenSSL? */ int verifyPeer; /* should peer be verified for TLS? */ int verifyHostname; /* should hostname be verified for TLS? */ int heartbeat; /* AMQP heartbeat interval in seconds (0 means disabled, which is default) */ char *caCert; /* CA certificate to be used for TLS connection */ recover_t recover_policy; } instanceData; typedef struct wrkrInstanceData { amqp_connection_state_t a_conn; /* amqp connection */ int connected; int channel_opened; pthread_t thread; /* */ short thread_running; /* */ pthread_mutex_t send_mutex; /* */ pthread_cond_t cond; /* */ rsRetVal state; /* state of the connection */ server_wrk_t serverPrefered; /* usual rabbitmq server */ server_wrk_t serverBackup; /* backup rabbitmq server */ server_wrk_t *serverActive; /* active rabbitmq server */ instanceData *pData; recover_t recover_policy; time_t last_failback; int iidx; int widx; int go_on; } wrkrInstanceData_t; typedef struct _msg2amqp_props_ { propid_t id; const char *name; amqp_bytes_t *standardprop; int flag; } msg2amqp_props_t; /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"host", eCmdHdlrString, 0}, {"port", eCmdHdlrInt, 0}, {"virtual_host", eCmdHdlrGetWord, 0}, {"heartbeat_interval", eCmdHdlrNonNegInt, 0}, {"user", eCmdHdlrGetWord, 0}, {"password", eCmdHdlrGetWord, 0}, {"ssl", eCmdHdlrBinary, 0}, {"init_openssl", eCmdHdlrBinary, 0}, {"verify_peer", eCmdHdlrBinary, 0}, {"verify_hostname", eCmdHdlrBinary, 0}, {"ca_cert", eCmdHdlrGetWord, 0}, {"exchange", eCmdHdlrGetWord, 0}, {"routing_key", eCmdHdlrGetWord, 0}, {"routing_key_template", eCmdHdlrGetWord, 0}, {"delivery_mode", eCmdHdlrGetWord, 0}, {"expiration", eCmdHdlrNonNegInt, 0}, {"populate_properties", eCmdHdlrBinary, 0}, {"body_template", eCmdHdlrGetWord, 0}, {"content_type", eCmdHdlrGetWord, 0}, {"recover_policy", eCmdHdlrString, 0}, {"exchange_type", eCmdHdlrGetWord, 0}, {"durable", eCmdHdlrBinary, 0}, {"auto_delete", eCmdHdlrBinary, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; static amqp_bytes_t cstring_bytes(const char *str) { return str ? amqp_cstring_bytes(str) : amqp_empty_bytes; } /* Initialize recover structure from the configuration string */ static void init_recover(recover_t *fb, char *str) { time_t value[4] = {0, 0, 0, 0}; if (str && *str) { int i = -1; do { value[++i] = strtoul(str, &str, 10); if (*str) str++; } while (i < 3 && value[i] && *str); } fb->return_check_interval = (value[0]) ? value[0] : 60; fb->half_return_check_interval = fb->return_check_interval / 2; fb->quick_oscillation_interval = (value[1]) ? value[1] : (fb->return_check_interval / 10); fb->quick_oscillation_max = (value[2]) ? (int)(value[2]) : 3; fb->graceful_interval = (value[3]) ? value[3] : (fb->return_check_interval * 10) - fb->half_return_check_interval; fb->quick_oscillation_count = 0; } /* this method compute the delay before next reconnection attempt according */ static unsigned long next_check(recover_t *fb, time_t last_failback) { time_t now = time(NULL); srandom(now); if (now - last_failback < fb->quick_oscillation_interval) { /* quick oscillation detected */ fb->quick_oscillation_count++; if (fb->quick_oscillation_count > fb->quick_oscillation_max) { /* too much oscillation inserting a graceful sleep */ fb->quick_oscillation_count = 0; return fb->graceful_interval + fb->return_check_interval * random() / RAND_MAX; } } else fb->quick_oscillation_count = 0; /* returning a standard delay between 0,5 and 1,5 * return_check_interval */ return fb->half_return_check_interval + fb->return_check_interval * random() / RAND_MAX; } /* authenticate to rabbitmq server and set connection parameter according to rsyslog configuration */ static int amqp_authenticate(wrkrInstanceData_t *self, amqp_connection_state_t a_conn) { amqp_rpc_reply_t ret; /* define the frame size */ int frame_size = (glbl.GetMaxLine(runConf) < 130000) ? 131072 : (glbl.GetMaxLine(runConf) + 1072); /* authenticate */ ret = amqp_login(a_conn, (char const *)self->pData->vhost, 1, frame_size, self->pData->heartbeat, AMQP_SASL_METHOD_PLAIN, self->pData->user, self->pData->password); if (ret.reply_type != AMQP_RESPONSE_NORMAL) { LogError(0, RS_RET_RABBITMQ_LOGIN_ERR, "omrabbitmq module %d/%d: login to AMQP " "server %s failed. (%d / %s)", self->iidx, self->widx, self->serverActive->s.host, ret.reply_type, amqp_error_string2(ret.library_error)); return 0; } /* open the communication channel */ amqp_channel_open(a_conn, 1); if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL) { LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: open channel failed.", self->iidx, self->widx); return 0; } if (self->pData->exchange_type) { /* we declare the exchange according to specifications */ amqp_table_t props = {0, NULL}; #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 6) amqp_exchange_declare(a_conn, 1, self->pData->exchange, cstring_bytes(self->pData->exchange_type), 0, self->pData->durable, props); #else amqp_exchange_declare(a_conn, 1, self->pData->exchange, cstring_bytes(self->pData->exchange_type), 0, self->pData->durable, self->pData->auto_delete, 0, props); #endif if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL) { /* if a problem occurs on declaring the exchange we receive a channel_close with the * error then we can log the error, respond a channel_close_ok and reopen it * so we can work with the existing exchange. */ amqp_channel_close_ok_t chan_cls_ok; amqp_channel_close_t *chan_cls = (amqp_channel_close_t *)amqp_get_rpc_reply(a_conn).reply.decoded; if (amqp_get_rpc_reply(a_conn).reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION) { LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: disconnected while exchange declare (%d)", self->iidx, self->widx, amqp_get_rpc_reply(a_conn).library_error); return 0; } LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: exchange declare failed %.*s.", self->iidx, self->widx, (int)chan_cls->reply_text.len, (char *)chan_cls->reply_text.bytes); chan_cls_ok.dummy = '\0'; amqp_send_method(a_conn, 1, AMQP_CHANNEL_CLOSE_OK_METHOD, &chan_cls_ok); /* reopen the communication channel in case of error it should be close by server*/ amqp_channel_open(a_conn, 1); if (amqp_get_rpc_reply(a_conn).reply_type != AMQP_RESPONSE_NORMAL) { LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: " "open channel failed.", self->iidx, self->widx); return 0; } } } /* release the buffers if possible */ amqp_maybe_release_buffers(a_conn); return 1; } /* This method establish a new connection * @self pointer on the worker datas * @server pointer on the server datas (preferred or backup) * @return the connection state or NULL on error */ static amqp_connection_state_t tryConnection(wrkrInstanceData_t *self, server_t *server) { int retconn = 0; struct timeval delay; delay.tv_sec = 1; delay.tv_usec = 0; amqp_socket_t *sockfd = NULL; amqp_connection_state_t a_conn = amqp_new_connection(); if (a_conn) { if (self->pData->ssl) { /* amqp_set_initialize_ssl_library() deprecated in 0.8.0+ */ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) if (!self->pData->initOpenSSL) { // prevent OpenSSL double initialization amqp_set_initialize_ssl_library(0); } #endif sockfd = amqp_ssl_socket_new(a_conn); } else { sockfd = amqp_tcp_socket_new(a_conn); } } if (sockfd) { if (self->pData->ssl) { #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) amqp_ssl_socket_set_verify(sockfd, self->pData->verifyPeer); #else amqp_ssl_socket_set_verify_peer(sockfd, self->pData->verifyPeer); amqp_ssl_socket_set_verify_hostname(sockfd, self->pData->verifyHostname); #endif if (self->pData->caCert) { amqp_ssl_socket_set_cacert(sockfd, self->pData->caCert); } } LogError(0, RS_RET_RABBITMQ_CHANNEL_ERR, "omrabbitmq module %d/%d: server %s port %d.", self->iidx, self->widx, server->host, server->port); #if defined(_AIX) retconn = amqp_socket_open(sockfd, server->host, server->port); #else retconn = amqp_socket_open_noblock(sockfd, (const char *)server->host, server->port, &delay); #endif } if (retconn == AMQP_STATUS_OK && amqp_authenticate(self, a_conn)) return a_conn; /* the connection failed so free it and return NULL */ amqp_connection_close(a_conn, 200); amqp_destroy_connection(a_conn); /* amqp_uninitialize_ssl_library() deprecated in 0.8.0+ */ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) if (self->pData->ssl && self->pData->initOpenSSL) { amqp_uninitialize_ssl_library(); } #endif return NULL; } static int manage_connection(wrkrInstanceData_t *self, amqp_frame_t *pFrame) { int result; pthread_mutex_unlock(&self->send_mutex); do { if (self->serverActive == &self->serverBackup) { amqp_connection_state_t new_conn; struct timeval delay; /* The worker is connected to the backup server. * next_check function compute the delay before trying to recover * the connection to the preferred server according to recover_policy */ delay.tv_sec = next_check(&self->recover_policy, self->last_failback); delay.tv_usec = 0; result = amqp_simple_wait_frame_noblock(self->a_conn, pFrame, &delay); /* if connected to backup server then check if usual server is alive. * if so then disconnect from backup */ if (result == AMQP_STATUS_TIMEOUT && (new_conn = tryConnection(self, &(self->serverPrefered.s))) != NULL) { /* connection is re-established to preferred server so * swap connections */ amqp_connection_state_t old_conn = self->a_conn; /* now lock to avoid message publishing. */ pthread_mutex_lock(&self->send_mutex); self->a_conn = new_conn; self->serverActive = &self->serverPrefered; self->serverActive->failures = 0; pthread_mutex_unlock(&self->send_mutex); /* back to unlock mode */ DBGPRINTF("omrabbitmq module %d: reconnects to usual server.\n", self->iidx); amqp_connection_close(old_conn, 200); amqp_destroy_connection(old_conn); /* amqp_uninitialize_ssl_library() deprecated in 0.8.0+ */ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) if (self->pData->ssl && self->pData->initOpenSSL) { amqp_uninitialize_ssl_library(); } #endif } } else { result = amqp_simple_wait_frame(self->a_conn, pFrame); } } while (result == AMQP_STATUS_TIMEOUT); /* now lock the mutex to avoid message publishing. */ pthread_mutex_lock(&self->send_mutex); return result; } static void send_connection_close(amqp_connection_state_t state) { amqp_connection_close_t *req = malloc(sizeof(amqp_connection_close_t)); memset(req, 0, sizeof(amqp_connection_close_t)); req->reply_code = 200; req->reply_text.bytes = (void *)"200"; req->reply_text.len = 3; req->class_id = (uint16_t)(AMQP_CONNECTION_CLOSE_METHOD >> 16); req->method_id = (uint16_t)(AMQP_CONNECTION_CLOSE_METHOD & 0xFFFF); amqp_send_method(state, 0, AMQP_CONNECTION_CLOSE_METHOD, req); free(req); } static void send_channel_close(amqp_connection_state_t state, amqp_channel_t ch) { amqp_channel_close_t *req = malloc(sizeof(amqp_channel_close_t)); memset(req, 0, sizeof(amqp_channel_close_t)); req->reply_code = 200; req->reply_text.bytes = (void *)"200"; req->reply_text.len = 3; req->class_id = (uint16_t)(AMQP_CHANNEL_CLOSE_METHOD >> 16); req->method_id = (uint16_t)(AMQP_CHANNEL_CLOSE_METHOD & 0xFFFF); amqp_send_method(state, ch, AMQP_CHANNEL_CLOSE_METHOD, req); free(req); } static void send_connection_close_ok(amqp_connection_state_t state) { amqp_connection_close_ok_t *req = malloc(sizeof(amqp_connection_close_ok_t)); memset(req, 0, sizeof(amqp_connection_close_ok_t)); req->dummy = '\0'; amqp_send_method(state, 0, AMQP_CONNECTION_CLOSE_OK_METHOD, req); free(req); } static void send_channel_close_ok(amqp_connection_state_t state, amqp_channel_t ch) { amqp_channel_close_ok_t *req = malloc(sizeof(amqp_channel_close_ok_t)); memset(req, 0, sizeof(amqp_channel_close_ok_t)); req->dummy = '\0'; amqp_send_method(state, ch, AMQP_CHANNEL_CLOSE_OK_METHOD, req); free(req); } /* run_connection_routine is the thread monitoring of the rabbitmq connection. * This method manage reconnection to preferred and backup servers apply the recover_policy */ static void *run_connection_routine(void *arg) { wrkrInstanceData_t *self = (wrkrInstanceData_t *)arg; amqp_frame_t frm; int result; self->connected = 0; self->channel_opened = 0; rsRetVal state_out = RS_RET_SUSPENDED; dbgSetThrdName((uchar *)"amqp connection"); /* now lock to avoid message publishing during part of the thread loop */ pthread_mutex_lock(&self->send_mutex); self->thread_running = 1; self->state = RS_RET_OK; srSleep(0, 100); DBGPRINTF("omrabbitmq module %d/%d: connection thread started\n", self->iidx, self->widx); int go_on = self->go_on; while (go_on) // this loop is used to reconnect on connection failure { if (self->a_conn != NULL) { amqp_connection_close(self->a_conn, 200); amqp_destroy_connection(self->a_conn); /* amqp_uninitialize_ssl_library() deprecated in 0.8.0+ */ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) if (self->pData->ssl && self->pData->initOpenSSL) { amqp_uninitialize_ssl_library(); } #endif } self->a_conn = NULL; if (!self->go_on) { go_on = 0; state_out = RS_RET_DISABLE_ACTION; continue; /* lets go back to wile (go_on) and leave cleanly */ } if (self->serverActive == &self->serverBackup) { self->serverBackup.failures = 0; self->serverPrefered.failures = 0; self->serverActive = &self->serverPrefered; } do { /* this loop tries 3 times per server before switching servers */ if ((self->a_conn = tryConnection(self, &(self->serverActive->s))) != NULL) { self->serverActive->failures = 0; } else { /* set 1 second before retry */ struct timeval delay; delay.tv_sec = 1; delay.tv_usec = 0; self->serverActive->failures++; /* if 3 tries */ if (self->serverActive->failures == 3) { if (!self->serverBackup.s.host || self->serverBackup.failures == 3) { LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module connection " "failed 3 times on each server."); } if (self->serverActive == &self->serverBackup) { self->serverBackup.failures = 0; self->serverPrefered.failures = 0; self->serverActive = &self->serverPrefered; } else { /* on usual server switch to backup server */ if (self->serverBackup.s.host) self->serverActive = &self->serverBackup; else self->serverPrefered.failures = 0; } /* set 5 second before new round trip */ delay.tv_sec = 5; } select(0, NULL, NULL, NULL, &delay); } } while (self->a_conn == NULL && self->go_on); if (!self->go_on) { go_on = 0; state_out = RS_RET_DISABLE_ACTION; continue; /* lets go back to wile (go_on) and leave cleanly */ } /* signal that the thread is started */ pthread_cond_signal(&self->cond); self->connected = 1; self->channel_opened = 1; DBGPRINTF("omrabbitmq module %d: connected.\n", self->iidx); self->state = RS_RET_OK; if (self->serverActive == &self->serverBackup) self->last_failback = time(NULL); while (self->connected) // this loop is used to manage an established connection { result = manage_connection(self, &frm); switch (result) { case AMQP_STATUS_NO_MEMORY: LogError(0, RS_RET_OUT_OF_MEMORY, "omrabbitmq module %d/%d: no memory " ": aborting module.", self->iidx, self->widx); go_on = 0; /* non recoverable error let's go out */ self->connected = 0; state_out = RS_RET_DISABLE_ACTION; break; case AMQP_STATUS_BAD_AMQP_DATA: LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module %d/%d: bad " "data received : reconnect.", self->iidx, self->widx); self->connected = 0; break; case AMQP_STATUS_SOCKET_ERROR: LogError(0, RS_RET_RABBITMQ_CONN_ERR, "omrabbitmq module %d/%d: Socket" " error : reconnect.", self->iidx, self->widx); self->connected = 0; break; case AMQP_STATUS_CONNECTION_CLOSED: LogError(0, RS_RET_OUT_OF_MEMORY, "omrabbitmq module %d/%d: Connection" " closed : reconnect.", self->iidx, self->widx); self->connected = 0; break; case AMQP_STATUS_OK: /* perhaps not a frame type so ignore it */ if (frm.frame_type == AMQP_FRAME_METHOD) { amqp_method_number_t id = frm.payload.method.id; /* now handle frames from the server */ switch (id) { case AMQP_CONNECTION_CLOSE_OK_METHOD: /* We asked to close the connection and server has responded to us */ self->connected = 0; go_on = 0; break; case AMQP_CHANNEL_CLOSE_OK_METHOD: /* We asked to close the channel and server has responded to us */ send_connection_close(self->a_conn); self->channel_opened = 0; break; case AMQP_CHANNEL_CLOSE_METHOD: /* the server wants to close the channel then the connection */ LogMsg(0, RS_RET_OK, LOG_WARNING, "omrabbitmq module %d/%d: " "Close Channel Received (%X).", self->iidx, self->widx, id); /* answer the server request & send the method */ send_channel_close_ok(self->a_conn, frm.channel); self->channel_opened = 0; break; case AMQP_CONNECTION_CLOSE_METHOD: /* the server want to close the connection */ LogMsg(0, RS_RET_OK, LOG_WARNING, "omrabbitmq module %d/%d: " "Close Connection Received (%X).", self->iidx, self->widx, id); /* answer the server request */ send_connection_close_ok(self->a_conn); self->connected = 0; break; default: LogMsg(0, RS_RET_OK, LOG_WARNING, "omrabbitmq module %d/%d: " "Unmanaged amqp method received (%X) : ignored.", self->iidx, self->widx, id); } /* switch (frm.payload.method.id) */ } /* if (frm.frame_type == AMQP_FRAME_METHOD) */ break; default: // No action needed for other cases break; } /* switch (result) */ } } self->state = state_out; /* The core ask to die so let's disconnect */ if (self->a_conn != NULL) { if (self->channel_opened) amqp_channel_close(self->a_conn, 1, 200); if (self->connected) amqp_connection_close(self->a_conn, 200); amqp_destroy_connection(self->a_conn); self->a_conn = NULL; /* amqp_uninitialize_ssl_library() deprecated in 0.8.0+ */ #if (AMQP_VERSION_MAJOR == 0) && (AMQP_VERSION_MINOR < 8) if (self->pData->ssl && self->pData->initOpenSSL) { amqp_uninitialize_ssl_library(); } #endif } self->thread_running = 0; /* Finishing by unlocking before the end of the thread */ pthread_mutex_unlock(&self->send_mutex); /* Now notify the worker that this thread is stopping */ pthread_cond_signal(&self->cond); return NULL; } /* ============================================================================================ * Main thread * ============================================================================================ */ static rsRetVal startAMQPConnection(wrkrInstanceData_t *self) { DEFiRet; pthread_mutex_lock(&self->send_mutex); self->go_on = 1; if (self->thread_running == 0) { if (!pthread_create(&self->thread, NULL, run_connection_routine, self)) { pthread_cond_wait(&self->cond, &self->send_mutex); iRet = self->state; } else { iRet = RS_RET_DISABLE_ACTION; } } pthread_mutex_unlock(&self->send_mutex); RETiRet; } static void closeAMQPConnection(wrkrInstanceData_t *self) { if (!self || !self->a_conn) return; void *ret; /* Now locks to allow exclusive access to sock */ pthread_mutex_lock(&self->send_mutex); self->go_on = 0; /* send the method */ if (self->a_conn) { if (self->channel_opened) { send_channel_close(self->a_conn, 0); } else { send_connection_close(self->a_conn); } } /* Release the lock */ pthread_mutex_unlock(&self->send_mutex); /* Now wvait for the thread to stop */ pthread_join(self->thread, &ret); } /* * Report general error */ static int manage_error(int x, char const *context) { int retVal = 0; // false if (x < 0) { #if (AMQP_VERSION_MINOR >= 4) const char *errstr = amqp_error_string2(-x); LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, errstr); #else char *errstr = amqp_error_string(-x); LogError(0, RS_RET_ERR, "omrabbitmq: %s: %s", context, errstr); free(errstr); #endif retVal = 1; // true } return retVal; } static rsRetVal publishRabbitMQ(wrkrInstanceData_t *self, amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_basic_properties_t *p_amqp_props, amqp_bytes_t body_bytes) { DEFiRet; /* locks to allow exclusive access to connection */ if (mode_test > 0) { struct timeval tv; tv.tv_sec = mode_test / 1000; tv.tv_usec = mode_test % 1000 * 1000; select(0, NULL, NULL, NULL, &tv); } pthread_mutex_lock(&self->send_mutex); if (self->state != RS_RET_OK) ABORT_FINALIZE(self->state); if (!self->a_conn) { ABORT_FINALIZE(RS_RET_RABBITMQ_CONN_ERR); } if (manage_error(amqp_basic_publish(self->a_conn, 1, exchange, routing_key, 0, 0, p_amqp_props, body_bytes), "amqp_basic_publish")) { /* error already notified */ FINALIZE; } finalize_it: /* release exclusive access to connection */ pthread_mutex_unlock(&self->send_mutex); RETiRet; } BEGINdoAction int iLen; CODESTARTdoAction; /* The first element is a smsg_t pointer */ smsg_t **pMsg = (smsg_t **)pMsgData; smsg_t *msg = pMsg[0]; amqp_bytes_t body_bytes; amqp_basic_properties_t *amqp_props_msg; if (!pWrkrData->pData->idx_body_template) { /* No body template so send it as rawmsg */ getRawMsg(msg, (uchar **)(&body_bytes.bytes), &iLen); body_bytes.len = (size_t)iLen; amqp_props_msg = &pWrkrData->pData->amqp_props_plaintext; } else { /* we have a body template */ body_bytes = cstring_bytes((char *)ppString[pWrkrData->pData->idx_body_template]); amqp_props_msg = &pWrkrData->pData->amqp_props_tpl_type; } if (pWrkrData->pData->populate_properties) { /* populate amqp message properties */ msgPropDescr_t pProp; int i, custom = 0; amqp_basic_properties_t amqp_props; memcpy(&amqp_props, amqp_props_msg, sizeof(amqp_basic_properties_t)); /* list and mapping of smsg to amqp properties */ msg2amqp_props_t prop_list[] = {{PROP_SYSLOGFACILITY_TEXT, "facility", NULL, 0}, {PROP_SYSLOGSEVERITY_TEXT, "severity", NULL, 0}, {PROP_HOSTNAME, "hostname", NULL, 0}, {PROP_FROMHOST, "fromhost", NULL, 0}, {PROP_SYSLOGTAG, NULL, &(amqp_props.app_id), AMQP_BASIC_APP_ID_FLAG}}; int len = sizeof(prop_list) / sizeof(msg2amqp_props_t); uchar *val[sizeof(prop_list) / sizeof(msg2amqp_props_t)]; rs_size_t valLen[sizeof(prop_list) / sizeof(msg2amqp_props_t)]; unsigned short mustBeFreed[sizeof(prop_list) / sizeof(msg2amqp_props_t)]; struct amqp_table_entry_t_ tab_entries[sizeof(prop_list) / sizeof(msg2amqp_props_t)]; amqp_props.headers.entries = tab_entries; amqp_props.timestamp = (uint64_t)datetime.syslogTime2time_t(&msg->tTIMESTAMP); amqp_props._flags |= AMQP_BASIC_TIMESTAMP_FLAG; for (i = 0; i < len; i++) { /* for each msg property in list get the value and initialize flags */ pProp.id = prop_list[i].id; valLen[i] = 0; mustBeFreed[i] = 0; val[i] = (uchar *)MsgGetProp(msg, NULL, &pProp, &(valLen[i]), &(mustBeFreed[i]), NULL); if (val[i] && *val[i]) { if (prop_list[i].name) { /* custom amqp properties */ tab_entries[custom].key = amqp_cstring_bytes(prop_list[i].name); tab_entries[custom].value.kind = AMQP_FIELD_KIND_UTF8; tab_entries[custom].value.value.bytes = amqp_cstring_bytes((char *)val[i]); amqp_props._flags |= AMQP_BASIC_HEADERS_FLAG; custom++; } else { /* standard amqp properties*/ prop_list[i].standardprop->bytes = val[i]; prop_list[i].standardprop->len = (size_t)valLen[i]; amqp_props._flags |= prop_list[i].flag; } } } amqp_props.headers.num_entries = custom; /* CHKiRet could not be used because we need to release allocations */ iRet = publishRabbitMQ(pWrkrData, pWrkrData->pData->exchange, (pWrkrData->pData->routing_key_template) ? cstring_bytes((char *)ppString[pWrkrData->pData->idx_routing_key_template]) : pWrkrData->pData->routing_key, &amqp_props, body_bytes); for (i = 0; i < len; i++) if (mustBeFreed[i]) free(val[i]); } else { /* As CHKiRet could not be used earlier, iRet is directly used again */ iRet = publishRabbitMQ(pWrkrData, pWrkrData->pData->exchange, (pWrkrData->pData->routing_key_template) ? cstring_bytes((char *)ppString[pWrkrData->pData->idx_routing_key_template]) : pWrkrData->pData->routing_key, amqp_props_msg, body_bytes); } ENDdoAction BEGINtryResume CODESTARTtryResume; iRet = startAMQPConnection(pWrkrData); ENDtryResume BEGINcreateInstance void *env_var; CODESTARTcreateInstance; if ((env_var = getenv("OMRABBITMQ_TEST")) != NULL) mode_test = atoi(env_var); memset(pData, 0, sizeof(instanceData)); pData->iidx = ++instance_counter; pData->delivery_mode = 2; pData->exchange_type = NULL; pData->durable = 0; pData->auto_delete = 1; pData->ssl = 0; pData->initOpenSSL = 0; pData->verifyPeer = 0; pData->verifyHostname = 0; pData->caCert = NULL; pData->heartbeat = 0; ENDcreateInstance BEGINfreeInstance CODESTARTfreeInstance; /* this is a cleanup callback. All dynamically-allocated resources * in instance data must be cleaned up here. Prime examples are * malloc()ed memory, file & database handles and the like. */ if (pData->exchange.bytes) free(pData->exchange.bytes); if (pData->routing_key.bytes) free(pData->routing_key.bytes); if (pData->routing_key_template) free(pData->routing_key_template); if (pData->body_template) free(pData->body_template); if (pData->expiration.bytes) free(pData->expiration.bytes); if (pData->content_type) free(pData->content_type); if (pData->vhost) free(pData->vhost); if (pData->user) free(pData->user); if (pData->password) free(pData->password); if (pData->exchange_type) free(pData->exchange_type); if (pData->server1.host) free(pData->server1.host); if (pData->caCert) free(pData->caCert); ENDfreeInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; /* use this to specify if select features are supported by this * plugin. If not, the framework will handle that. Currently, only * RepeatedMsgReduction ("last message repeated n times") is optional. */ if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; /* permits to spit out some debug info */ dbgprintf("omrabbitmq instance : %d\n", pData->iidx); if (pData->server2.host) { dbgprintf("\thost1='%s' \n", pData->server1.host); dbgprintf("\tport1=%d\n", pData->server1.port); dbgprintf("\thost2='%s' \n", pData->server2.host); dbgprintf("\tport2=%d\n", pData->server2.port); dbgprintf("\tfailback policy :"); dbgprintf("\t\tusual server check interval=%" PRIdMAX " s", (intmax_t)pData->recover_policy.return_check_interval); dbgprintf("\t\tquick oscillation limit=%" PRIdMAX " s", (intmax_t)pData->recover_policy.quick_oscillation_interval); dbgprintf("\t\tmax number of oscillation=%d s", pData->recover_policy.quick_oscillation_max); dbgprintf("\t\tgraceful interval after quick oscillation detection=%" PRIdMAX " s", (intmax_t)pData->recover_policy.graceful_interval); } else { dbgprintf("\thost='%s' \n", pData->server1.host); dbgprintf("\tport=%d\n", pData->server1.port); } dbgprintf("\tvirtual_host='%s'\n", pData->vhost); dbgprintf("\tuser='%s'\n", pData->user == NULL ? "(not configured)" : pData->user); dbgprintf("\tpassword=(%sconfigured)\n", pData->password == NULL ? "not " : ""); dbgprintf("\tssl=%d\n", pData->ssl); dbgprintf("\tinit_openssl=%d\n", pData->initOpenSSL); dbgprintf("\tverify_peer=%d\n", pData->verifyPeer); dbgprintf("\tverify_hostname=%d\n", pData->verifyHostname); dbgprintf("\tca_cert='%s'\n", pData->caCert); dbgprintf("\theartbeat_interval=%d\n", pData->heartbeat); dbgprintf("\texchange='%*s'\n", (int)pData->exchange.len, (char *)pData->exchange.bytes); dbgprintf("\trouting_key='%*s'\n", (int)pData->routing_key.len, (char *)pData->routing_key.bytes); dbgprintf("\trouting_key_template='%s'\n", pData->routing_key_template); dbgprintf("\tbody_template='%s'\n", pData->body_template); dbgprintf("\texchange_type='%s'\n", pData->exchange_type); dbgprintf("\tauto_delete=%d\n", pData->auto_delete); dbgprintf("\tdurable=%d\n", pData->durable); dbgprintf("\tpopulate_properties=%s\n", (pData->populate_properties) ? "ON" : "OFF"); dbgprintf((pData->delivery_mode == 1) ? "\tdelivery_mode=TRANSIENT\n" : "\tdelivery_mode=PERSISTENT\n"); if (pData->expiration.len == 0) { dbgprintf("\texpiration=UNLIMITED\n"); } else { dbgprintf("\texpiration=%*s\n", (int)pData->expiration.len, (char *)pData->expiration.bytes); } ENDdbgPrintInstInfo BEGINnewActInst struct cnfparamvals *pvals; int i; char *host = NULL, *vhost = NULL, *user = NULL, *password = NULL, *recover = NULL; int port = 0; long long expiration = 0; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); /* let read parameters */ for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "host")) { CHKmalloc(host = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "recover_policy")) { CHKmalloc(recover = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "port")) { port = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "virtual_host")) { CHKmalloc(vhost = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "user")) { CHKmalloc(user = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "password")) { CHKmalloc(password = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "ssl")) { pData->ssl = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ca_cert")) { CHKmalloc(pData->caCert = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "heartbeat_interval")) { pData->heartbeat = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "init_openssl")) { pData->initOpenSSL = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "verify_peer")) { pData->verifyPeer = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "verify_hostname")) { pData->verifyHostname = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "exchange")) { char *tmp; CHKmalloc(tmp = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->exchange = cstring_bytes(tmp); } else if (!strcmp(actpblk.descr[i].name, "routing_key")) { char *tmp; CHKmalloc(tmp = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->routing_key = cstring_bytes(tmp); } else if (!strcmp(actpblk.descr[i].name, "routing_key_template")) { CHKmalloc(pData->routing_key_template = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "populate_properties")) { pData->populate_properties = (sbool)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "delivery_mode")) { char *temp; CHKmalloc(temp = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (temp) { if (!strcasecmp(temp, "TRANSIENT") || !strcmp(temp, "1")) { pData->delivery_mode = 1; } else { if (!strcasecmp(temp, "PERSISTENT") || !strcmp(temp, "2")) { pData->delivery_mode = 2; } else { pData->delivery_mode = 0; } } free(temp); } } else if (!strcmp(actpblk.descr[i].name, "expiration")) { expiration = pvals[i].val.d.n; if (expiration > 0) { char buf[40]; snprintf(buf, 40, "%lld", expiration); #ifndef __clang_analyzer__ pData->expiration = cstring_bytes(strdup(buf)); #endif } } else if (!strcmp(actpblk.descr[i].name, "body_template")) { CHKmalloc(pData->body_template = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "content_type")) { CHKmalloc(pData->content_type = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "exchange_type")) { CHKmalloc(pData->exchange_type = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "auto_delete")) { pData->auto_delete = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "durable")) { pData->durable = (int)pvals[i].val.d.n; } else { LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d: program error, non-handled param '%s'\n", pData->iidx, actpblk.descr[i].name); } } /* let's check config validity */ if (host == NULL) { LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: parameter " "host must be specified", pData->iidx); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* first if a template for routing_key is set let verify its existence */ if (pData->routing_key_template && tplFind(ourConf, (char *)pData->routing_key_template, strlen((char *)pData->routing_key_template)) == NULL) { LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d : template '%s'" " used for routing key does not exist !", pData->iidx, pData->routing_key_template); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* an exchange must be defined */ if (pData->exchange.bytes == NULL) { LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: parameter " "exchange must be specified", pData->iidx); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* a static or a template's routing_key must be defined */ if (pData->routing_key.bytes == NULL && pData->routing_key_template == NULL) { LogError(0, RS_RET_INVALID_PARAMS, "omrabbitmq module %d disabled: " "one of parameters routing_key or " "routing_key_template must be specified", pData->iidx); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* a valid delivery mode must be defined : a 0 means that an invalid value * has been done */ if (!pData->delivery_mode) { LogError(0, RS_RET_CONF_PARAM_INVLD, "omrabbitmq module %d disabled: " "parameter delivery_mode must be " "TRANSIENT or PERSISTENT (default)", pData->iidx); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* first if a template for message body is set let verify its existence */ if (pData->body_template && *pData->body_template && tplFind(ourConf, (char *)pData->body_template, strlen((char *)pData->body_template)) == NULL) { LogError(0, RS_RET_CONF_PARAM_INVLD, "omrabbitmq module %d : template '%s'" " used for body does not exist !", pData->iidx, pData->body_template); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* Let's define the size of the doAction tab */ CODE_STD_STRING_REQUESTnewActInst(1 + ((pData->routing_key_template) ? 1 : 0) + ((pData->body_template && *pData->body_template == '\0') ? 0 : 1)); /* Set the plain text message props */ memset(&pData->amqp_props_plaintext, 0, sizeof(amqp_basic_properties_t)); pData->amqp_props_plaintext._flags = AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_CONTENT_TYPE_FLAG; pData->amqp_props_plaintext.delivery_mode = pData->delivery_mode; /* persistent delivery mode */ pData->amqp_props_plaintext.content_type = amqp_cstring_bytes("plain/text"); if (pData->expiration.len) { pData->amqp_props_plaintext._flags |= AMQP_BASIC_EXPIRATION_FLAG; pData->amqp_props_plaintext.expiration = pData->expiration; } memcpy(&pData->amqp_props_tpl_type, &pData->amqp_props_plaintext, sizeof(amqp_basic_properties_t)); /* The first position of doAction tab will contain the internal message */ CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); // RabbitMQ properties initialization if (pData->routing_key_template) { pData->idx_routing_key_template = 1; CHKiRet( OMSRsetEntry(*ppOMSR, 1, (uchar *)strdup((const char *)pData->routing_key_template), OMSR_NO_RQD_TPL_OPTS)); } /* if pData->body_template is NULL (not defined) then let's use former * json format if pData->body_template is not an empty string then let's * use it. In this case the content type is defined either * by the template name or the user defined content_type if set * otherwise raw data (unformatted) are sent this is done setting * pData->idx_body_template to 0 */ if (pData->body_template == NULL) { /* no template */ DBGPRINTF("Body_template is using default StdJSONFmt definition.\n"); pData->idx_body_template = pData->idx_routing_key_template + 1; CHKiRet(OMSRsetEntry(*ppOMSR, pData->idx_body_template, (uchar *)strdup(" StdJSONFmt"), OMSR_NO_RQD_TPL_OPTS)); pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes("application/json"); } else if (*pData->body_template) { pData->idx_body_template = pData->idx_routing_key_template + 1; CHKiRet(OMSRsetEntry(*ppOMSR, pData->idx_body_template, (uchar *)strdup((const char *)pData->body_template), OMSR_NO_RQD_TPL_OPTS)); pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes((pData->content_type) ? pData->content_type : (char *)pData->body_template); } else { pData->idx_body_template = 0; pData->amqp_props_tpl_type.content_type = amqp_cstring_bytes((pData->content_type) ? pData->content_type : "raw"); } /* treatment of the server parameter * first the default port */ pData->server2.port = pData->server1.port = port ? port : 5672; char *temp; int p; pData->server1.host = host; /* Is there more than one server in parameter */ if ((pData->server2.host = strchr(pData->server1.host, ' ')) != NULL) { *pData->server2.host++ = '\0'; /* is there a port with the second server */ if ((temp = strchr(pData->server2.host, ':')) != NULL) { *temp++ = '\0'; p = atoi(temp); if (p) pData->server2.port = p; } } /* is there a port with the first/unique server */ if ((temp = strchr(pData->server1.host, ':')) != NULL) { *temp++ = '\0'; p = atoi(temp); if (p) pData->server1.port = p; } pData->vhost = vhost ? vhost : strdup("/"); pData->user = user ? user : strdup(""); pData->password = password ? password : strdup(""); init_recover(&pData->recover_policy, recover); if (recover) free(recover); dbgPrintInstInfo(pData); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; memset(pWrkrData, 0, sizeof(wrkrInstanceData_t)); pWrkrData->pData = pData; pthread_mutex_init(&pWrkrData->send_mutex, NULL); pthread_cond_init(&pWrkrData->cond, NULL); pWrkrData->state = RS_RET_SUSPENDED; pWrkrData->iidx = pData->iidx; pWrkrData->widx = ++pData->nbWrkr; memcpy(&(pWrkrData->recover_policy), &(pData->recover_policy), sizeof(recover_t)); if (pData->server2.host && *pData->server2.host) { time_t odd = time(NULL) % 2; memcpy(&(pWrkrData->serverPrefered.s), (odd) ? &pData->server1 : &pData->server2, sizeof(server_t)); memcpy(&(pWrkrData->serverBackup.s), (odd) ? &pData->server2 : &pData->server1, sizeof(server_t)); } else { memcpy(&(pWrkrData->serverPrefered.s), &pData->server1, sizeof(server_t)); } pWrkrData->serverActive = &pWrkrData->serverPrefered; startAMQPConnection(pWrkrData); ENDcreateWrkrInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; if (pWrkrData != NULL) { closeAMQPConnection(pWrkrData); pthread_mutex_destroy(&(pWrkrData->send_mutex)); pthread_cond_destroy(&(pWrkrData->cond)); } ENDfreeWrkrInstance BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/omrabbitmq/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020372 xustar0030 mtime=1752569012.330244093 30 atime=1787067434.332011119 30 ctime=1787067797.819788878 rsyslog-8.2608.0/contrib/omrabbitmq/Makefile.am0000666000175000017500000000037415035412264020044 0ustar00rgerrgerpkglib_LTLIBRARIES = omrabbitmq.la omrabbitmq_la_SOURCES = omrabbitmq.c omrabbitmq_la_CPPFLAGS = $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) omrabbitmq_la_LDFLAGS = -module -avoid-version omrabbitmq_la_LIBADD = $(RABBITMQ_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/omrabbitmq/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161020403 xustar0030 mtime=1787067505.188333147 29 atime=1787067579.17571312 30 ctime=1787067797.821788915 rsyslog-8.2608.0/contrib/omrabbitmq/Makefile.in0000664000175000017500000006623615241076161020065 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omrabbitmq ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omrabbitmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_omrabbitmq_la_OBJECTS = omrabbitmq_la-omrabbitmq.lo omrabbitmq_la_OBJECTS = $(am_omrabbitmq_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 = omrabbitmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omrabbitmq_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omrabbitmq_la_SOURCES) DIST_SOURCES = $(omrabbitmq_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omrabbitmq.la omrabbitmq_la_SOURCES = omrabbitmq.c omrabbitmq_la_CPPFLAGS = $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) omrabbitmq_la_LDFLAGS = -module -avoid-version omrabbitmq_la_LIBADD = $(RABBITMQ_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omrabbitmq/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omrabbitmq/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omrabbitmq.la: $(omrabbitmq_la_OBJECTS) $(omrabbitmq_la_DEPENDENCIES) $(EXTRA_omrabbitmq_la_DEPENDENCIES) $(AM_V_CCLD)$(omrabbitmq_la_LINK) -rpath $(pkglibdir) $(omrabbitmq_la_OBJECTS) $(omrabbitmq_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omrabbitmq_la-omrabbitmq.lo: omrabbitmq.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omrabbitmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omrabbitmq_la-omrabbitmq.lo -MD -MP -MF $(DEPDIR)/omrabbitmq_la-omrabbitmq.Tpo -c -o omrabbitmq_la-omrabbitmq.lo `test -f 'omrabbitmq.c' || echo '$(srcdir)/'`omrabbitmq.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omrabbitmq_la-omrabbitmq.Tpo $(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omrabbitmq.c' object='omrabbitmq_la-omrabbitmq.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omrabbitmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omrabbitmq_la-omrabbitmq.lo `test -f 'omrabbitmq.c' || echo '$(srcdir)/'`omrabbitmq.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omrabbitmq_la-omrabbitmq.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/improg0000644000000000000000000000013215241076633015426 xustar0030 mtime=1787067803.031885996 30 atime=1787067808.785993219 30 ctime=1787067803.031885996 rsyslog-8.2608.0/contrib/improg/0000775000175000017500000000000015241076633015147 5ustar00rgerrgerrsyslog-8.2608.0/contrib/improg/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017531 xustar0029 mtime=1752569012.32825799 30 atime=1787067434.091006621 30 ctime=1787067803.026885903 rsyslog-8.2608.0/contrib/improg/Makefile.am0000666000175000017500000000050715035412264017202 0ustar00rgerrgerpkglib_LTLIBRARIES = improg.la improg_la_SOURCES = improg.c improg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) improg_la_LDFLAGS = -module -avoid-version improg_la_LIBADD = if ENABLE_LIBLOGGING_STDLOG improg_la_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) improg_la_LDFLAGS += $(LIBLOGGING_STDLOG_LIBS) endif rsyslog-8.2608.0/contrib/improg/PaxHeaders/improg.c0000644000000000000000000000013215220503174017134 xustar0030 mtime=1782744700.130046227 30 atime=1787067646.196962786 30 ctime=1787067803.031885996 rsyslog-8.2608.0/contrib/improg/improg.c0000664000175000017500000005422315220503174016606 0ustar00rgerrger/* improg.c * This input plugin enables rsyslog to execute a program and * receive from it the message stream as standard input. * One message per line with a maximum size * * NOTE: read comments in module-template.h for more specifics! * * File begun on 2009-04-01 by RGerhards * File copied and adjust from improg.c on 2019-02-07 by Ph. Duveau * * Copyright 2009-2018 Adiscon GmbH. * * This file is contribution of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Very strange error on solaris 11 LOG_CRON already defined here. * It is redefined in rsyslog.h * The error also appeared with module omprog but the warning is * accepted without generated an error */ #ifdef LOG_CRON #undef LOG_CRON #endif #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "unicode-helper.h" #include "errmsg.h" #include "cfsysline.h" #include "glbl.h" #include "prop.h" #include "ruleset.h" #include "ratelimit.h" #include "stringbuf.h" MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("improg") #if defined(__sun) extern char **environ; #endif struct instanceConf_s { uchar *pszBinary; /* name of external program to call */ char **aParams; /* optional parameters to pass to external program */ int iParams; /* holds the count of parameters if set */ uchar *pszTag; size_t lenTag; int iFacility; int iSeverity; int bConfirmMessages; /* does the program provide feedback via stdout? */ int bSignalOnClose; /* should send SIGTERM to program before closing pipe? */ long lCloseTimeout; /* how long to wait for program to terminate after closing pipe (ms) */ int bKillUnresponsive; /* should send SIGKILL if closeTimeout is reached? */ cstr_t *ppCStr; int bIsRunning; /* is program currently running? 0-no, 1-yes */ pid_t pid; /* pid of currently running child process */ int fdPipeToChild; /* fd for sending data to the program */ int fdPipeFromChild; /* fd for receiving messages from the program, or -1 */ uchar *pszBindRuleset; ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ ratelimit_t *ratelimiter; struct instanceConf_s *next; struct instanceConf_s *prev; }; /* config variables */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) static prop_t *pInputName = NULL; #define NO_HUP_FORWARD -1 /* indicates that HUP should NOT be forwarded */ #define DEFAULT_CONFIRM_TIMEOUT_MS 10000 #define DEFAULT_CLOSE_TIMEOUT_MS 5000 #define RESPONSE_LINE_BUFFER_SIZE 4096 #define OUTPUT_CAPTURE_BUFFER_SIZE 4096 #define MAX_FD_TO_CLOSE 65535 static instanceConf_t *confRoot = NULL; static fd_set rfds; static int nfds = 0; #include "im-helper.h" /* must be included AFTER the type definitions! */ static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *pInst) { LogError(0, NO_ERRCODE, "improg: ruleset '%s' for binary %s not found - " "using default ruleset instead", pInst->pszBindRuleset, pInst->pszBinary); } /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr inppdescr[] = {{"binary", eCmdHdlrString, CNFPARAM_REQUIRED}, {"tag", eCmdHdlrString, CNFPARAM_REQUIRED}, {"severity", eCmdHdlrSeverity, 0}, {"facility", eCmdHdlrFacility, 0}, {"ruleset", eCmdHdlrString, 0}, {"confirmmessages", eCmdHdlrBinary, 0}, {"signalonclose", eCmdHdlrBinary, 0}, {"closetimeout", eCmdHdlrInt, 0}, {"killunresponsive", eCmdHdlrBinary, 0}}; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; /* execute the external program (must be called in child context after fork). */ static __attribute__((noreturn)) void execBinary(const instanceConf_t *pInst, int pipeToParent, int pipeFromParent) { int maxFd, fd, sigNum; struct sigaction sigAct; sigset_t sigSet; char errStr[1024]; if (dup2(pipeToParent, STDOUT_FILENO) == -1) { goto failed; } if (pipeFromParent != -1) { if (dup2(pipeFromParent, STDIN_FILENO) == -1) { goto failed; } } /* close the file handles the child process doesn't need (all above STDERR). * The following way is simple and portable, though not perfect. * See https://stackoverflow.com/a/918469 for alternatives. */ maxFd = sysconf(_SC_OPEN_MAX); if (maxFd < 0 || maxFd > MAX_FD_TO_CLOSE) { maxFd = MAX_FD_TO_CLOSE; } #ifdef VALGRIND else { maxFd -= 10; } #endif for (fd = STDERR_FILENO + 1; fd <= maxFd; ++fd) { close(fd); } /* reset signal handlers to default */ memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = SIG_DFL; for (sigNum = 1; sigNum < NSIG; ++sigNum) { sigaction(sigNum, &sigAct, NULL); } /* we need to block SIGINT, otherwise our program is cancelled when we are * stopped in debug mode. */ sigAct.sa_handler = SIG_IGN; sigaction(SIGINT, &sigAct, NULL); sigemptyset(&sigSet); sigprocmask(SIG_SETMASK, &sigSet, NULL); alarm(0); /* finally exec program */ execve((char *)pInst->pszBinary, pInst->aParams, environ); failed: /* an error occurred: log it and exit the child process. We use the * 'syslog' system call to log the error (we cannot use LogMsg/LogError, * since these functions add directly to the rsyslog input queue). */ rs_strerror_r(errno, errStr, sizeof(errStr)); DBGPRINTF("improg: failed to execute program '%s': %s\n", pInst->pszBinary, errStr); openlog("rsyslogd", 0, LOG_SYSLOG); syslog(LOG_ERR, "improg: failed to execute program '%s': %s\n", pInst->pszBinary, errStr); /* let's print the error to stderr for test bench purposes */ fprintf(stderr, "improg: failed to execute program '%s': %s\n", pInst->pszBinary, errStr); exit(1); } /* creates a pipe and starts program, uses pipe as stdin for program. * rgerhards, 2009-04-01 */ static rsRetVal openPipe(instanceConf_t *pInst) { int pipeFromChild[2] = {-1, -1}; int pipeToChild[2] = {-1, -1}; pid_t cpid; DEFiRet; /* if the 'confirmMessages' setting is enabled, open a pipe to send message confirmations to the program */ if (pInst->bConfirmMessages && pipe(pipeToChild) == -1) { ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE); } /* open a pipe to receive messages to the program */ if (pipe(pipeFromChild) == -1) { ABORT_FINALIZE(RS_RET_ERR_CREAT_PIPE); } DBGPRINTF("improg: executing program '%s' with '%d' parameters\n", pInst->pszBinary, pInst->iParams); cpid = fork(); if (cpid == -1) { ABORT_FINALIZE(RS_RET_ERR_FORK); } if (cpid == 0) { /* we are now the child process: execute the program */ /* close the pipe ends that the child doesn't need */ close(pipeFromChild[0]); if (pipeToChild[1] != -1) { close(pipeToChild[1]); } execBinary(pInst, pipeFromChild[1], pipeToChild[0]); /* NO CODE HERE - WILL NEVER BE REACHED! */ } DBGPRINTF("improg: child has pid %ld\n", (long int)cpid); /* close the pipe ends that the parent doesn't need */ close(pipeFromChild[1]); if (pipeToChild[0] != -1) { close(pipeToChild[0]); } pInst->fdPipeToChild = pipeToChild[1]; /* we'll send messages confirmations to the program via this fd */ pInst->fdPipeFromChild = pipeFromChild[0]; /* we'll receive message via this fd */ FD_SET(pInst->fdPipeFromChild, &rfds); /* manage select read fd set */ nfds = (nfds > pInst->fdPipeFromChild) ? nfds : pInst->fdPipeFromChild + 1; pInst->pid = cpid; pInst->bIsRunning = 1; finalize_it: if (iRet != RS_RET_OK) { if (pipeFromChild[0] != -1) { close(pipeFromChild[0]); close(pipeFromChild[1]); } if (pipeToChild[0] != -1) { close(pipeToChild[0]); close(pipeToChild[1]); } } RETiRet; } static void waitForChild(instanceConf_t *pInst) { int status; int ret; long counter; counter = pInst->lCloseTimeout / 10; while ((ret = waitpid(pInst->pid, &status, WNOHANG)) == 0 && counter > 0) { srSleep(0, 10000); /* 0 seconds, 10 milliseconds */ --counter; } if (ret == 0) { /* timeout reached */ if (!pInst->bKillUnresponsive) { LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: program '%s' (pid %ld) did not terminate " "within timeout (%ld ms); ignoring it", pInst->pszBinary, (long int)pInst->pid, pInst->lCloseTimeout); return; } LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: program '%s' (pid %ld) did not terminate " "within timeout (%ld ms); killing it", pInst->pszBinary, (long int)pInst->pid, pInst->lCloseTimeout); if (kill(pInst->pid, SIGKILL) == -1) { LogError(errno, RS_RET_SYS_ERR, "improg: could not send SIGKILL to child process"); return; } ret = waitpid(pInst->pid, &status, 0); } /* waitpid will fail with errno == ECHILD if the child process has already been reaped by the rsyslogd main loop (see rsyslogd.c) */ if (ret == pInst->pid) { glblReportChildProcessExit(runConf, pInst->pszBinary, pInst->pid, status); } } /* Send SIGTERM to child process if configured to do so, close pipe * and wait for child to terminate. */ static void terminateChild(instanceConf_t *pInst) { if (pInst->bIsRunning) { if (pInst->fdPipeFromChild != -1) { close(pInst->fdPipeFromChild); FD_CLR(pInst->fdPipeFromChild, &rfds); pInst->fdPipeFromChild = -1; } if (pInst->fdPipeToChild != -1) { close(pInst->fdPipeToChild); pInst->fdPipeToChild = -1; } /* wait for the child AFTER closing the pipe, so it receives EOF */ waitForChild(pInst); pInst->bIsRunning = 0; } } static rsRetVal startChild(instanceConf_t *pInst) { DEFiRet; if (!pInst->bIsRunning) CHKiRet(openPipe(pInst)); finalize_it: if (iRet != RS_RET_OK && pInst->bIsRunning) { /* if initialization has failed, terminate program */ terminateChild(pInst); } RETiRet; } static rsRetVal enqLine(instanceConf_t *const __restrict__ pInst) { DEFiRet; smsg_t *pMsg; if (cstrLen(pInst->ppCStr) == 0) { /* we do not process empty lines */ FINALIZE; } CHKiRet(msgConstruct(&pMsg)); MsgSetMSGoffs(pMsg, 0); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetInputName(pMsg, pInputName); MsgSetAPPNAME(pMsg, (const char *)pInst->pszTag); MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag); msgSetPRI(pMsg, pInst->iFacility | pInst->iSeverity); MsgSetRawMsg(pMsg, (const char *)rsCStrGetBufBeg(pInst->ppCStr), cstrLen(pInst->ppCStr)); MsgSetRuleset(pMsg, pInst->pBindRuleset); ratelimitAddMsg(pInst->ratelimiter, NULL, pMsg); finalize_it: RETiRet; } /* read line(s) from the external program and sent them when they are complete */ static rsRetVal readChild(instanceConf_t *const pInst) { char c; int retval; while ((retval = read(pInst->fdPipeFromChild, &c, 1)) == 1) { if (c == '\n') { enqLine(pInst); /* if confirm required then send an ACK to the program */ if (pInst->bConfirmMessages) { if (write(pInst->fdPipeToChild, "ACK\n", sizeof("ACK\n") - 1) <= 0) LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: pipe to child seems to be closed."); } rsCStrTruncate(pInst->ppCStr, rsCStrLen(pInst->ppCStr)); } else { cstrAppendChar(pInst->ppCStr, c); } } return (retval == 0) ? RS_RET_EOF : RS_RET_IO_ERROR; } /* create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal ATTR_NONNULL(1) createInstance(instanceConf_t **const ppInst) { instanceConf_t *pInst; DEFiRet; CHKmalloc(pInst = malloc(sizeof(instanceConf_t))); pInst->next = NULL; pInst->pszBindRuleset = NULL; pInst->pBindRuleset = NULL; pInst->ratelimiter = NULL; pInst->iSeverity = 5; pInst->iFacility = 128; pInst->pszTag = NULL; pInst->lenTag = 0; pInst->bIsRunning = 0; pInst->pid = -1; pInst->fdPipeToChild = -1; pInst->fdPipeFromChild = -1; pInst->pszBinary = NULL; pInst->aParams = NULL; pInst->iParams = 0; pInst->bConfirmMessages = 1; pInst->bSignalOnClose = 0; pInst->lCloseTimeout = 200; pInst->bKillUnresponsive = 1; *ppInst = pInst; finalize_it: RETiRet; } /* This adds a new listener object to the bottom of the list, but * it does NOT initialize any data members except for the list * pointers themselves. */ static rsRetVal ATTR_NONNULL() lstnAdd(instanceConf_t *pInst) { DEFiRet; CHKiRet(ratelimitNew(&pInst->ratelimiter, "improg", (char *)pInst->pszBinary)); /* insert it at the begin of the list */ pInst->prev = NULL; pInst->next = confRoot; if (confRoot != NULL) confRoot->prev = pInst; confRoot = pInst; finalize_it: RETiRet; } /* delete a listener object */ static void ATTR_NONNULL(1) lstnFree(instanceConf_t *pInst) { DBGPRINTF("lstnFree called for %s\n", pInst->pszBinary); if (pInst->ratelimiter != NULL) ratelimitDestruct(pInst->ratelimiter); if (pInst->pszBinary != NULL) free(pInst->pszBinary); if (pInst->pszTag) free(pInst->pszTag); if (pInst->pszBindRuleset != NULL) free(pInst->pszBindRuleset); if (pInst->aParams) { int i; for (i = 0; pInst->aParams[i]; i++) free(pInst->aParams[i]); free(pInst->aParams); } if (pInst->ppCStr) rsCStrDestruct(&pInst->ppCStr); free(pInst); } /* read */ BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *pInst = NULL; int i; CODESTARTnewInpInst; DBGPRINTF("newInpInst (improg)\n"); pvals = nvlstGetParams(lst, &inppblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { DBGPRINTF("input param blk in improg:\n"); cnfparamsPrint(&inppblk, pvals); } CHKiRet(createInstance(&pInst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "binary")) { CHKiRet(split_binary_parameters(&pInst->pszBinary, &pInst->aParams, &pInst->iParams, pvals[i].val.d.estr)); } else if (!strcmp(inppblk.descr[i].name, "tag")) { CHKmalloc(pInst->pszTag = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); pInst->lenTag = es_strlen(pvals[i].val.d.estr); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(pInst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "severity")) { pInst->iSeverity = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "facility")) { pInst->iFacility = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "confirmmessages")) { pInst->bConfirmMessages = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "signalonclose")) { pInst->bSignalOnClose = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "closetimeout")) { pInst->lCloseTimeout = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "killunresponsive")) { pInst->bKillUnresponsive = pvals[i].val.d.n; } else { DBGPRINTF( "program error, non-handled " "param '%s'\n", inppblk.descr[i].name); } } if (pInst->pszBinary == NULL) { LogError(0, RS_RET_FILE_NOT_SPECIFIED, "ulogbase is not configured - no input will be gathered"); ABORT_FINALIZE(RS_RET_FILE_NOT_SPECIFIED); } CHKiRet(cstrConstruct(&pInst->ppCStr)); if ((iRet = lstnAdd(pInst)) != RS_RET_OK) { ABORT_FINALIZE(iRet); } finalize_it: CODE_STD_FINALIZERnewInpInst if (pInst && iRet != RS_RET_OK) lstnFree(pInst); cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINwillRun CODESTARTwillRun; /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("improg"), sizeof("improg") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); finalize_it: ENDwillRun BEGINrunInput struct timeval tv; int retval; instanceConf_t *pInst; rsRetVal readRet; CODESTARTrunInput; FD_ZERO(&rfds); for (pInst = confRoot; pInst != NULL; pInst = pInst->next) { startChild(pInst); } for (pInst = confRoot; pInst != NULL; pInst = pInst->next) { if (pInst->bIsRunning && pInst->fdPipeToChild > 0) { if (write(pInst->fdPipeToChild, "START\n", sizeof("START\n") - 1) <= 0) LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: pipe to child seems to be closed."); DBGPRINTF("Sending START to %s\n", pInst->pszBinary); } } /* main module loop */ tv.tv_usec = 1000; while (glbl.GetGlobalInputTermState() == 0) { fd_set temp; memcpy(&temp, &rfds, sizeof(fd_set)); tv.tv_sec = 0; /* wait for external data or 0.1 second */ retval = select(nfds, &temp, NULL, NULL, &tv); /* retval is the number of fd with data to read */ while (retval > 0) { for (pInst = confRoot; pInst != NULL; pInst = pInst->next) { if (pInst->fdPipeFromChild != -1 && FD_ISSET(pInst->fdPipeFromChild, &temp)) { DBGPRINTF("read child %s\n", pInst->pszBinary); readRet = readChild(pInst); if (readRet == RS_RET_EOF) { DBGPRINTF("improg: program '%s' closed stdout pipe\n", pInst->pszBinary); terminateChild(pInst); } else if (readRet != RS_RET_OK) { LogError(errno, readRet, "improg: error reading from child process"); terminateChild(pInst); } retval--; } } } tv.tv_usec = 100000; } DBGPRINTF("terminating upon request of rsyslog core\n"); ENDrunInput /* This function is called by the framework after runInput() has been terminated. It * shall free any resources and prepare the module for unload. * CODEqueryEtryPt_STD_IMOD_QUERIES */ BEGINafterRun CODESTARTafterRun; instanceConf_t *pInst = confRoot, *nextInst; confRoot = NULL; DBGPRINTF("afterRun\n"); while (pInst != NULL) { nextInst = pInst->next; if (pInst->bIsRunning) { if (pInst->bSignalOnClose) { kill(pInst->pid, SIGTERM); LogMsg(0, NO_ERRCODE, LOG_INFO, "%s SIGTERM signaled.", pInst->aParams[0]); } if (pInst->fdPipeToChild > 0) { if (write(pInst->fdPipeToChild, "STOP\n", strlen("STOP\n")) <= 0 && !pInst->bSignalOnClose) LogMsg(0, NO_ERRCODE, LOG_WARNING, "improg: pipe to child seems to be closed."); } terminateChild(pInst); } lstnFree(pInst); pInst = nextInst; } if (pInputName != NULL) prop.Destruct(&pInputName); ENDafterRun BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) { iRet = RS_RET_OK; } ENDisCompatibleWithFeature BEGINbeginCnfLoad CODESTARTbeginCnfLoad; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf instanceConf_t *pInst; CODESTARTcheckCnf; for (pInst = confRoot; pInst != NULL; pInst = pInst->next) { std_checkRuleset(pModConf, pInst); } ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINmodExit CODESTARTmodExit; objRelease(ruleset, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/improg/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160017542 xustar0030 mtime=1787067504.738324752 30 atime=1787067579.740723656 29 ctime=1787067803.02888594 rsyslog-8.2608.0/contrib/improg/Makefile.in0000664000175000017500000006603715241076160017223 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_1 = $(LIBLOGGING_STDLOG_CFLAGS) @ENABLE_LIBLOGGING_STDLOG_TRUE@am__append_2 = $(LIBLOGGING_STDLOG_LIBS) subdir = contrib/improg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) improg_la_DEPENDENCIES = am_improg_la_OBJECTS = improg_la-improg.lo improg_la_OBJECTS = $(am_improg_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 = improg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(improg_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/improg_la-improg.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(improg_la_SOURCES) DIST_SOURCES = $(improg_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = improg.la improg_la_SOURCES = improg.c improg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) \ $(am__append_1) improg_la_LDFLAGS = -module -avoid-version $(am__append_2) improg_la_LIBADD = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/improg/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/improg/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } improg.la: $(improg_la_OBJECTS) $(improg_la_DEPENDENCIES) $(EXTRA_improg_la_DEPENDENCIES) $(AM_V_CCLD)$(improg_la_LINK) -rpath $(pkglibdir) $(improg_la_OBJECTS) $(improg_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/improg_la-improg.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< improg_la-improg.lo: improg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(improg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT improg_la-improg.lo -MD -MP -MF $(DEPDIR)/improg_la-improg.Tpo -c -o improg_la-improg.lo `test -f 'improg.c' || echo '$(srcdir)/'`improg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/improg_la-improg.Tpo $(DEPDIR)/improg_la-improg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='improg.c' object='improg_la-improg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(improg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o improg_la-improg.lo `test -f 'improg.c' || echo '$(srcdir)/'`improg.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/improg_la-improg.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/improg_la-improg.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/pmaixforwardedfrom0000644000000000000000000000013215241076625020032 xustar0030 mtime=1787067797.025774083 30 atime=1787067808.785993219 30 ctime=1787067797.025774083 rsyslog-8.2608.0/contrib/pmaixforwardedfrom/0000775000175000017500000000000015241076625017553 5ustar00rgerrgerrsyslog-8.2608.0/contrib/pmaixforwardedfrom/PaxHeaders/pmaixforwardedfrom.c0000644000000000000000000000013215132411300024131 xustar0030 mtime=1768559296.141883663 30 atime=1787067628.590634536 30 ctime=1787067797.025774083 rsyslog-8.2608.0/contrib/pmaixforwardedfrom/pmaixforwardedfrom.c0000666000175000017500000001373415132411300023607 0ustar00rgerrger/* pmaixforwardedfrom.c * * this cleans up messages forwarded from AIX * * instead of actually parsing the message, this modifies the message and then falls through to allow a * later parser to handle the now modified message * * created 2010-12-13 by David Lang based on pmlastmsg * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" #include "rsconf.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.aixforwardedfrom") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* static data */ static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINparse uchar *p2parse; int lenMsg; int skipLen = 0; #define OpeningText "Message forwarded from " #define OpeningText2 "From " CODESTARTparse; dbgprintf("Message will now be parsed by fix AIX Forwarded From parser.\n"); assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ /* check if this message is of the type we handle in this (very limited) parser */ /* first, we permit SP */ while (lenMsg && *p2parse == ' ') { --lenMsg; ++p2parse; } if ((unsigned)lenMsg < 24) { /* too short, can not be "our" message */ /* minimum message, 16 character timestamp, 'From ", 1 character name, ': '*/ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* skip over timestamp */ lenMsg -= 16; p2parse += 16; /* if there is the string "Message forwarded from " were the hostname should be */ if (!strncasecmp((char *)p2parse, OpeningText, sizeof(OpeningText) - 1)) skipLen = 23; /* or "From " */ if (!strncasecmp((char *)p2parse, OpeningText2, sizeof(OpeningText2) - 1)) skipLen = 5; DBGPRINTF("pmaixforwardedfrom: skipLen %d\n", skipLen); if (!skipLen) { /* wrong opening text */ DBGPRINTF("not a AIX message forwarded from mangled log!\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* bump the message portion up by skipLen(23 or 5) characters to overwrite the "Message forwarded from " or "From " with the hostname */ lenMsg -= skipLen; if (lenMsg < 2) { dbgprintf("not a AIX message forwarded from message has nothing after header\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } memmove(p2parse, p2parse + skipLen, lenMsg); *(p2parse + lenMsg) = '\n'; *(p2parse + lenMsg + 1) = '\0'; pMsg->iLenRawMsg -= skipLen; pMsg->iLenMSG -= skipLen; /* now look for the : after the hostname to walk past the hostname, also watch for a space in case this isn't really an AIX log, but has a similar preamble */ while (lenMsg && *p2parse != ' ' && *p2parse != ':') { --lenMsg; ++p2parse; } if (lenMsg < 1) { dbgprintf( "not a AIX message forwarded from message has nothing after colon " "or no colon at all\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } if (lenMsg && *p2parse != ':') { DBGPRINTF( "not a AIX message forwarded from mangled log but similar enough that the preamble has " "been removed\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* bump the message portion up by one character to overwrite the extra : */ lenMsg -= 1; memmove(p2parse, p2parse + 1, lenMsg); *(p2parse + lenMsg) = '\n'; *(p2parse + lenMsg + 1) = '\0'; pMsg->iLenRawMsg -= 1; pMsg->iLenMSG -= 1; /* now, claim to abort so that something else can parse the now modified message */ DBGPRINTF("pmaixforwardedfrom: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); finalize_it: ENDparse BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); DBGPRINTF("aixforwardedfrom parser init called, compiled with version %s\n", VERSION); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); /* cache value, is set only during rsyslogd option processing */ ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/contrib/pmaixforwardedfrom/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264022134 xustar0030 mtime=1752569012.331237145 30 atime=1787067434.366011753 29 ctime=1787067797.02077399 rsyslog-8.2608.0/contrib/pmaixforwardedfrom/Makefile.am0000666000175000017500000000044215035412264021603 0ustar00rgerrgerpkglib_LTLIBRARIES = pmaixforwardedfrom.la pmaixforwardedfrom_la_SOURCES = pmaixforwardedfrom.c pmaixforwardedfrom_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmaixforwardedfrom_la_LDFLAGS = -module -avoid-version pmaixforwardedfrom_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/pmaixforwardedfrom/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161022146 xustar0029 mtime=1787067505.25333436 30 atime=1787067579.112711945 30 ctime=1787067797.022774027 rsyslog-8.2608.0/contrib/pmaixforwardedfrom/Makefile.in0000664000175000017500000006707215241076161021627 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/pmaixforwardedfrom ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) pmaixforwardedfrom_la_DEPENDENCIES = am_pmaixforwardedfrom_la_OBJECTS = \ pmaixforwardedfrom_la-pmaixforwardedfrom.lo pmaixforwardedfrom_la_OBJECTS = $(am_pmaixforwardedfrom_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 = pmaixforwardedfrom_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(pmaixforwardedfrom_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__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmaixforwardedfrom_la_SOURCES) DIST_SOURCES = $(pmaixforwardedfrom_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = pmaixforwardedfrom.la pmaixforwardedfrom_la_SOURCES = pmaixforwardedfrom.c pmaixforwardedfrom_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmaixforwardedfrom_la_LDFLAGS = -module -avoid-version pmaixforwardedfrom_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/pmaixforwardedfrom/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/pmaixforwardedfrom/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } pmaixforwardedfrom.la: $(pmaixforwardedfrom_la_OBJECTS) $(pmaixforwardedfrom_la_DEPENDENCIES) $(EXTRA_pmaixforwardedfrom_la_DEPENDENCIES) $(AM_V_CCLD)$(pmaixforwardedfrom_la_LINK) -rpath $(pkglibdir) $(pmaixforwardedfrom_la_OBJECTS) $(pmaixforwardedfrom_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmaixforwardedfrom_la-pmaixforwardedfrom.lo: pmaixforwardedfrom.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmaixforwardedfrom_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmaixforwardedfrom_la-pmaixforwardedfrom.lo -MD -MP -MF $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Tpo -c -o pmaixforwardedfrom_la-pmaixforwardedfrom.lo `test -f 'pmaixforwardedfrom.c' || echo '$(srcdir)/'`pmaixforwardedfrom.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Tpo $(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmaixforwardedfrom.c' object='pmaixforwardedfrom_la-pmaixforwardedfrom.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmaixforwardedfrom_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmaixforwardedfrom_la-pmaixforwardedfrom.lo `test -f 'pmaixforwardedfrom.c' || echo '$(srcdir)/'`pmaixforwardedfrom.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmaixforwardedfrom_la-pmaixforwardedfrom.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmrfc5424addhmac0000644000000000000000000000013215241076632017055 xustar0030 mtime=1787067802.185870231 30 atime=1787067808.785993219 30 ctime=1787067802.185870231 rsyslog-8.2608.0/contrib/mmrfc5424addhmac/0000775000175000017500000000000015241076632016576 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmrfc5424addhmac/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264021162 xustar0030 mtime=1752569012.329251042 30 atime=1787067434.194008543 30 ctime=1787067802.181870156 rsyslog-8.2608.0/contrib/mmrfc5424addhmac/Makefile.am0000666000175000017500000000044115035412264020627 0ustar00rgerrgerpkglib_LTLIBRARIES = mmrfc5424addhmac.la mmrfc5424addhmac_la_SOURCES = mmrfc5424addhmac.c mmrfc5424addhmac_la_CPPFLAGS = $(OPENSSL_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmrfc5424addhmac_la_LDFLAGS = -module -avoid-version mmrfc5424addhmac_la_LIBADD = $(OPENSSL_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/mmrfc5424addhmac/PaxHeaders/mmrfc5424addhmac.c0000644000000000000000000000013215216464435022227 xustar0030 mtime=1782212893.962265149 30 atime=1782715518.787788823 30 ctime=1787067802.187870268 rsyslog-8.2608.0/contrib/mmrfc5424addhmac/mmrfc5424addhmac.c0000664000175000017500000002417015216464435021677 0ustar00rgerrger/* mmrfc5424addhmac.c * custom module: add hmac to RFC5424 messages * * Note on important design decision: This module is fully self-contained. * Most importantly, it does not rely on mmpstrucdata to populate the * structured data portion of the messages JSON. There are two reasons * for this: * 1. robustness * - this guard against misconfiguration * - it permits us to be more liberal in regard to malformed * structured data * - it permits us to handle border-cases (like duplicate * SD-IDs) with much less complexity * 2. performance * With being "on the spot" of what we need we can reduce memory * reads and writes. This is a considerable save if the JSON representation * is not otherwise needed. * * Note that the recommended calling sequence if both of these modules * are used is * * 1. mmrfc5424addhmac * 2. mmpstrucdata * * This sequence permits mmpstrucdata to pick up the modifications we * made in this module here. * * Copyright 2013 Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmrfc5424addhmac") DEF_OMOD_STATIC_DATA; /* config variables */ typedef struct _instanceData { uchar *key; int16_t keylen; /* cached length of key, to avoid recomputation */ uchar *sdid; /* SD-ID to be used to persist the hmac */ int16_t sdidLen; const EVP_MD *algo; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"key", eCmdHdlrString, 1}, {"hashfunction", eCmdHdlrString, 1}, {"sd_id", eCmdHdlrGetWord, 1}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance static inline void setInstParamDefaults(instanceData *pData) { pData->key = NULL; } BEGINnewActInst struct cnfparamvals *pvals; char *ciphername; int i; CODESTARTnewActInst; DBGPRINTF("newActInst (mmrfc5424addhmac)\n"); if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "key")) { CHKmalloc(pData->key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); pData->keylen = es_strlen(pvals[i].val.d.estr); } else if (!strcmp(actpblk.descr[i].name, "hashfunction")) { CHKmalloc(ciphername = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->algo = EVP_get_digestbyname(ciphername); if (pData->algo == NULL) { LogError(0, RS_RET_CRY_INVLD_ALGO, "hashFunction '%s' unknown to openssl - " "cannot continue", ciphername); free(ciphername); ABORT_FINALIZE(RS_RET_CRY_INVLD_ALGO); } free(ciphername); } else if (!strcmp(actpblk.descr[i].name, "sd_id")) { CHKmalloc(pData->sdid = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); pData->sdidLen = es_strlen(pvals[i].val.d.estr); } else { dbgprintf( "mmrfc5424addhmac: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume /* turn the binary data in bin of length len into a * printable hex string. "print" must be 2*len+1 (for \0) */ static void hexify(uchar *bin, int len, uchar *print) { static const char hexchars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; int iSrc, iDst; for (iSrc = iDst = 0; iSrc < len; ++iSrc) { print[iDst++] = hexchars[bin[iSrc] >> 4]; print[iDst++] = hexchars[bin[iSrc] & 0x0f]; } print[iDst] = '\0'; } /* skip to end of current SD-ID. This function can be improved * in regard to fully parsing based on RFC5424, HOWEVER, this would * also reduce performance. So we consider the current implementation * to be superior. */ static void skipSDID(uchar *sdbuf, int sdlen, int *rootIdx) { int i; i = *rootIdx; while (i < sdlen) { if (sdbuf[i] == ']') { if (i > *rootIdx && sdbuf[i - 1] == '\\') { ; /* escaped, nothing to do! */ } else { ++i; /* eat ']' */ break; } } ++i; } *rootIdx = i; } static void getSDID(uchar *sdbuf, int sdlen, int *rootIdx, uchar *sdid, size_t sdidSize) { int i; size_t j; i = *rootIdx; j = 0; if (sdbuf[i] != '[') { ++i; goto done; } ++i; while (i < sdlen && sdbuf[i] != '=' && sdbuf[i] != ' ' && sdbuf[i] != ']' && sdbuf[i] != '"') { if (j + 1 < sdidSize) { sdid[j++] = sdbuf[i]; } ++i; } done: if (sdidSize > 0) { sdid[j] = '\0'; } *rootIdx = i; } /* check if "our" hmac is already present */ static sbool isHmacPresent(instanceData *pData, smsg_t *pMsg) { uchar *sdbuf; rs_size_t sdlen; sbool found; int i; uchar sdid[33]; /* RFC-based size limit */ MsgGetStructuredData(pMsg, &sdbuf, &sdlen); found = 0; if (sdbuf[0] == '-') /* RFC: struc data is empty! */ goto done; i = 0; while (i < sdlen && !found) { getSDID(sdbuf, sdlen, &i, sdid, sizeof(sdid)); if (!strcmp((char *)pData->sdid, (char *)sdid)) { found = 1; break; } skipSDID(sdbuf, sdlen, &i); } done: return found; } static rsRetVal hashMsg(instanceData *pData, smsg_t *pMsg) { uchar *pRawMsg; int lenRawMsg; uchar *sdbuf; rs_size_t sdlen; unsigned int hashlen; uchar hash[EVP_MAX_MD_SIZE]; uchar hashPrintable[2 * EVP_MAX_MD_SIZE + 1]; uchar newsd[64 * 1024]; /* we assume this is sufficient... */ int lenNewsd; DEFiRet; MsgGetStructuredData(pMsg, &sdbuf, &sdlen); getRawMsg(pMsg, &pRawMsg, &lenRawMsg); HMAC(pData->algo, pData->key, pData->keylen, pRawMsg, lenRawMsg, hash, &hashlen); hexify(hash, hashlen, hashPrintable); lenNewsd = snprintf((char *)newsd, sizeof(newsd), "[%s hash=\"%s\"]", (char *)pData->sdid, (char *)hashPrintable); if (lenNewsd < 0 || (size_t)lenNewsd >= sizeof(newsd)) { LogError(0, RS_RET_INVALID_VALUE, "mmrfc5424addhmac: sdId '%s' too long to build HMAC structured data", pData->sdid); ABORT_FINALIZE(RS_RET_INVALID_VALUE); } MsgAddToStructuredData(pMsg, newsd, lenNewsd); finalize_it: RETiRet; } BEGINdoAction instanceData *pData = pWrkrData->pData; smsg_t *pMsg; void *pMsgVoid; CODESTARTdoAction; pMsgVoid = ppString[0]; pMsg = pMsgVoid; if (msgGetProtocolVersion(pMsg) == MSG_RFC5424_PROTOCOL && !isHmacPresent(pData, pMsg)) { hashMsg(pData, pMsg); } else { if (Debug) { uchar *pRawMsg; int lenRawMsg; getRawMsg(pMsg, &pRawMsg, &lenRawMsg); dbgprintf( "mmrfc5424addhmac: non-rfc5424 or HMAC already " "present: %.256s\n", pRawMsg); } } ENDdoAction NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; EVP_cleanup(); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmrfc5424addhmac: module compiled with rsyslog version %s.\n", VERSION); OpenSSL_add_all_digests(); ENDmodInit rsyslog-8.2608.0/contrib/mmrfc5424addhmac/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160021172 xustar0030 mtime=1787067504.927328278 29 atime=1787067579.39771726 30 ctime=1787067802.183870193 rsyslog-8.2608.0/contrib/mmrfc5424addhmac/Makefile.in0000664000175000017500000006700415241076160020646 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmrfc5424addhmac ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = mmrfc5424addhmac_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_mmrfc5424addhmac_la_OBJECTS = \ mmrfc5424addhmac_la-mmrfc5424addhmac.lo mmrfc5424addhmac_la_OBJECTS = $(am_mmrfc5424addhmac_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 = mmrfc5424addhmac_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(mmrfc5424addhmac_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__maybe_remake_depfiles = depfiles am__depfiles_remade = \ ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmrfc5424addhmac_la_SOURCES) DIST_SOURCES = $(mmrfc5424addhmac_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmrfc5424addhmac.la mmrfc5424addhmac_la_SOURCES = mmrfc5424addhmac.c mmrfc5424addhmac_la_CPPFLAGS = $(OPENSSL_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmrfc5424addhmac_la_LDFLAGS = -module -avoid-version mmrfc5424addhmac_la_LIBADD = $(OPENSSL_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmrfc5424addhmac/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmrfc5424addhmac/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmrfc5424addhmac.la: $(mmrfc5424addhmac_la_OBJECTS) $(mmrfc5424addhmac_la_DEPENDENCIES) $(EXTRA_mmrfc5424addhmac_la_DEPENDENCIES) $(AM_V_CCLD)$(mmrfc5424addhmac_la_LINK) -rpath $(pkglibdir) $(mmrfc5424addhmac_la_OBJECTS) $(mmrfc5424addhmac_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmrfc5424addhmac_la-mmrfc5424addhmac.lo: mmrfc5424addhmac.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmrfc5424addhmac_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmrfc5424addhmac_la-mmrfc5424addhmac.lo -MD -MP -MF $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Tpo -c -o mmrfc5424addhmac_la-mmrfc5424addhmac.lo `test -f 'mmrfc5424addhmac.c' || echo '$(srcdir)/'`mmrfc5424addhmac.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Tpo $(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmrfc5424addhmac.c' object='mmrfc5424addhmac_la-mmrfc5424addhmac.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmrfc5424addhmac_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmrfc5424addhmac_la-mmrfc5424addhmac.lo `test -f 'mmrfc5424addhmac.c' || echo '$(srcdir)/'`mmrfc5424addhmac.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmrfc5424addhmac_la-mmrfc5424addhmac.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmdarwin0000644000000000000000000000013215241076631015745 xustar0030 mtime=1787067801.762862348 30 atime=1787067808.785993219 30 ctime=1787067801.762862348 rsyslog-8.2608.0/contrib/mmdarwin/0000775000175000017500000000000015241076631015466 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmdarwin/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264020052 xustar0029 mtime=1752569012.32825799 30 atime=1787067434.142007573 30 ctime=1787067801.754862199 rsyslog-8.2608.0/contrib/mmdarwin/Makefile.am0000666000175000017500000000033015035412264017515 0ustar00rgerrgerpkglib_LTLIBRARIES = mmdarwin.la mmdarwin_la_SOURCES = mmdarwin.c protocol.h mmdarwin_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmdarwin_la_LDFLAGS = -module -avoid-version mmdarwin_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/mmdarwin/PaxHeaders/mmdarwin.c0000644000000000000000000000013215216464435020011 xustar0030 mtime=1782212893.960265117 30 atime=1787067642.101886439 30 ctime=1787067801.759862292 rsyslog-8.2608.0/contrib/mmdarwin/mmdarwin.c0000664000175000017500000007235415216464435017470 0ustar00rgerrger/* Copyright 2019 Advens * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "parserif.h" #include "unicode-helper.h" #include #include #include #include #include #include #include #include "protocol.h" /* custom file written for Darwin */ #define JSON_DEFAULT_CONTAINER "!mmdarwin" #define JSON_DARWIN_ID "darwin_id" #define INVLD_SOCK -1 #define INITIAL_BUFFER_SIZE 32 #define BUFFER_DEFAULT_MAX_SIZE 65536 MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmdarwin") DEFobjCurrIf(glbl) DEF_OMOD_STATIC_DATA; typedef struct dyn_buffer_t { char *buffer; size_t bufferAllocSize; size_t bufferMsgSize; size_t bufferMaxSize; } dyn_buffer; /* config variables */ typedef struct _instanceData { char *pUUIDKey; /* the key to the UUID generated by an mmdarwin instance */ char *pCertitudeKey; /* the key name to save in the enriched log line the certitude obtained from Darwin */ uchar *pSockName; /* the socket path of the filter which will be used by Darwin */ unsigned long long int filterCode; /* the filter code associated to the filter which will be used by Darwin */ enum darwin_filter_response_type response; /* the type of response for Darwin: no / back / darwin / both */ struct { int nmemb; char **name; char **varname; } fieldList; /* our keys (fields) to be extracted from the JSON-parsed log line */ unsigned int socketMaxUse; sbool sendPartial; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; int sock; /* the socket of the filter which will be used by Darwin */ struct sockaddr_un addr; /* the sockaddr_un used to connect to the Darwin filter */ uint8_t pktSentSocket; dyn_buffer darwinBody; /* the body object used (and reused) to hold data to send to Darwin */ dyn_buffer fieldBuffer; } wrkrInstanceData_t; struct modConfData_s { /* our overall config object */ rsconf_t *pConf; const char *container; }; /* modConf ptr to use for the current load process */ static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current exec process */ static modConfData_t *runModConf = NULL; /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"container", eCmdHdlrGetWord, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* tables for interfacing with the v6 config system * action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"key", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"socketpath", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"fields", eCmdHdlrArray, CNFPARAM_REQUIRED}, {"filtercode", eCmdHdlrGetWord, 0}, /* optional parameter */ {"response", eCmdHdlrGetWord, 0}, /* optional parameter */ {"send_partial", eCmdHdlrBinary, 0}, /* optional parameter */ {"socket_max_use", eCmdHdlrNonNegInt, 0}, /* optional parameter - will disappear in future updates */ }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; /* custom functions */ #define min(a, b) \ ({ \ __typeof__(a) _a = (a); \ __typeof__(b) _b = (b); \ _a < _b ? _a : _b; \ }) static rsRetVal openSocket(wrkrInstanceData_t *pWrkrData); static rsRetVal closeSocket(wrkrInstanceData_t *pWrkrData); static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData); static rsRetVal sendMsg(wrkrInstanceData_t *pWrkrData, void *msg, size_t len); static rsRetVal receiveMsg(wrkrInstanceData_t *pWrkrData, void *response, size_t len); const char *get_uuid_object(smsg_t *const pMsg); int get_field(smsg_t *const pMsg, const char *pFieldName, char **ppRetString); int expand_buffer(dyn_buffer *pBody, size_t new_size); int add_field_to_body(dyn_buffer *pBody, const char *field, size_t size); int start_new_line(dyn_buffer *pBody); int end_body(dyn_buffer *pBody); /* open socket to remote system */ static rsRetVal openSocket(wrkrInstanceData_t *pWrkrData) { DEFiRet; assert(pWrkrData->sock == INVLD_SOCK); if ((pWrkrData->sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { char errStr[1024]; int eno = errno; DBGPRINTF("mmdarwin::openSocket:: error %d creating AF_UNIX/SOCK_STREAM: %s.\n", eno, rs_strerror_r(eno, errStr, sizeof(errStr))); pWrkrData->sock = INVLD_SOCK; ABORT_FINALIZE(RS_RET_NO_SOCKET); } memset(&pWrkrData->addr, 0, sizeof(struct sockaddr_un)); pWrkrData->addr.sun_family = AF_UNIX; rs_cstr_copy(pWrkrData->addr.sun_path, (const char *)pWrkrData->pData->pSockName, sizeof(pWrkrData->addr.sun_path)); DBGPRINTF("mmdarwin::openSocket:: connecting to Darwin...\n"); if (connect(pWrkrData->sock, (struct sockaddr *)&pWrkrData->addr, sizeof(struct sockaddr_un)) == -1) { LogError(errno, RS_RET_NO_SOCKET, "mmdarwin::openSocket:: error connecting to Darwin " "via socket '%s'", pWrkrData->pData->pSockName); pWrkrData->sock = INVLD_SOCK; ABORT_FINALIZE(RS_RET_NO_SOCKET); } DBGPRINTF("mmdarwin::openSocket:: connected !\n"); finalize_it: if (iRet != RS_RET_OK) { closeSocket(pWrkrData); } RETiRet; } /* close socket to remote system */ static rsRetVal closeSocket(wrkrInstanceData_t *pWrkrData) { DEFiRet; if (pWrkrData->sock != INVLD_SOCK) { if (close(pWrkrData->sock) != 0) { char errStr[1024]; int eno = errno; DBGPRINTF("mmdarwin::closeSocket:: error %d closing the socket: %s.\n", eno, rs_strerror_r(eno, errStr, sizeof(errStr))); } pWrkrData->sock = INVLD_SOCK; } RETiRet; } /* try to resume connection if it is not ready */ static rsRetVal doTryResume(wrkrInstanceData_t *pWrkrData) { DEFiRet; DBGPRINTF("mmdarwin::doTryResume:: trying to resume\n"); closeSocket(pWrkrData); iRet = openSocket(pWrkrData); if (iRet != RS_RET_OK) { iRet = RS_RET_SUSPENDED; } RETiRet; } /* send a message via TCP * inspired by rgehards, 2007-12-20 */ static rsRetVal sendMsg(wrkrInstanceData_t *pWrkrData, void *msg, size_t len) { DEFiRet; DBGPRINTF("mmdarwin::sendMsg:: sending message to Darwin...\n"); if (pWrkrData->sock == INVLD_SOCK) { CHKiRet(doTryResume(pWrkrData)); } if (pWrkrData->sock != INVLD_SOCK) { if (send(pWrkrData->sock, msg, len, 0) == -1) { char errStr[1024]; DBGPRINTF("mmdarwin::sendData:: error while sending data: error[%d] -> %s\n", errno, rs_strerror_r(errno, errStr, sizeof(errStr))); iRet = RS_RET_SUSPENDED; } } finalize_it: RETiRet; } /* receive a message via TCP * inspired by rgehards, 2007-12-20 */ static rsRetVal receiveMsg(wrkrInstanceData_t *pWrkrData, void *response, size_t len) { DEFiRet; DBGPRINTF("mmdarwin::receiveMsg:: receiving message from Darwin...\n"); if (pWrkrData->sock == INVLD_SOCK) { CHKiRet(doTryResume(pWrkrData)); } if (pWrkrData->sock != INVLD_SOCK) { if (recv(pWrkrData->sock, response, len, MSG_WAITALL) <= 0) { char errStr[1024]; DBGPRINTF("mmdarwin::receiveMsg:: error while receiving data: error[%d] -> %s\n", errno, rs_strerror_r(errno, errStr, sizeof(errStr))); iRet = RS_RET_NONE; } } finalize_it: RETiRet; } /** * Get the string corresponding to a field supposedly present in the provided message * * params: * - pMsg: a pointer to the rsyslog message where the field should be * - pFieldName: a nul-terminated pointer to string representing the name of the field to search for * - ppRetString: the pointer to contain the potential return string * * return: 1 if a string was put in ppRetString, 0 otherwise * * note: the string placed in ppRetString should be freed by the caller */ int get_field(smsg_t *const pMsg, const char *pFieldName, char **ppRetString) { DBGPRINTF("mmdarwin::get_field:: getting key '%s' in msg\n", pFieldName); struct json_object *pJson = NULL; char *pFieldString = NULL; int retVal = 0; msgPropDescr_t propDesc; msgPropDescrFill(&propDesc, (uchar *)pFieldName, strlen(pFieldName)); msgGetJSONPropJSONorString(pMsg, &propDesc, &pJson, (uchar **)&pFieldString); if (pFieldString) { *ppRetString = pFieldString; DBGPRINTF("mmdarwin::get_field:: got string\n"); retVal = 1; } else if (pJson) { pFieldString = (char *)json_object_get_string(pJson); if (pFieldString) { *ppRetString = strdup(pFieldString); retVal = 1; DBGPRINTF("mmdarwin::get_field:: got string from json\n"); json_object_put(pJson); } } msgPropDescrDestruct(&propDesc); return retVal; } /** * expands the buffer object in the dyn_buffer object * * params: * - pBody: a pointer to the concerned structure to expand * - new_size: the new size to give to the underlying buffer * * return: 0 if the expansion was successful, -1 otherwise */ int expand_buffer(dyn_buffer *pBody, size_t new_size) { /* return error if new_size tries to exceed max defined size */ if (new_size > pBody->bufferMaxSize) return -1; while (pBody->bufferAllocSize < new_size) pBody->bufferAllocSize += INITIAL_BUFFER_SIZE; DBGPRINTF("mmdarwin::expand_buffer:: expanding buffer to %zu\n", pBody->bufferAllocSize); char *tmp = realloc(pBody->buffer, pBody->bufferAllocSize * sizeof(char)); if (!tmp) { DBGPRINTF("mmdarwin::expand_buffer:: could not resize buffer\n"); return -1; } pBody->buffer = tmp; return 0; } /** * adds a field to the dyn_buffer buffer * * params: * - pBody: the pointer on the dyn_buffer structure * - field: the potentially not null-terminated string to add as a field to the dyn_buffer * - size: the size of the string (without the '\0' character) * * return: 0 if the field was indeed added to the dyn_buffer, -1 otherwise */ int add_field_to_body(dyn_buffer *pBody, const char *field, size_t size) { /* get required additional size for field, quotes, colon, and \0 and potentially also for the beginning of the message structure */ int beginning = (pBody->bufferMsgSize == 0) ? 2 : 0; size_t requiredBodySize = pBody->bufferMsgSize + size + 4 + beginning; /* resize body buffer if necessary */ if (requiredBodySize > pBody->bufferAllocSize) { if (expand_buffer(pBody, requiredBodySize) != 0) { return -1; } } /* add message structure beginning if current message is empty */ if (!pBody->bufferMsgSize) { pBody->buffer[0] = '['; pBody->buffer[1] = '['; pBody->bufferMsgSize += 2; } /* add field with quotes and colon */ pBody->buffer[pBody->bufferMsgSize++] = '\"'; memcpy((void *)&pBody->buffer[pBody->bufferMsgSize], (const void *)field, size); pBody->bufferMsgSize += size; pBody->buffer[pBody->bufferMsgSize++] = '\"'; pBody->buffer[pBody->bufferMsgSize++] = ','; return 0; } /** * small helper function to start a new input line (used for bulk-calls) in the dyn_buffer. * will close current line with a ']' and start the next with a '['. * will also remove leading ',' in fields list. * * params: * - pBody: the pointer on the dyn_buffer on which to start a new input line * * return: 0 if successful, -1 otherwise */ int start_new_line(dyn_buffer *pBody) { /* don't if the message is empty */ if (!pBody->bufferMsgSize) { return -1; } DBGPRINTF("mmdarwin::start_new_line:: starting new line entry in body\n"); if (pBody->bufferAllocSize < pBody->bufferMsgSize + 2) { if (expand_buffer(pBody, pBody->bufferAllocSize + 2) != 0) { return -1; } } pBody->buffer[pBody->bufferMsgSize - 1] = ']'; pBody->buffer[pBody->bufferMsgSize++] = ','; pBody->buffer[pBody->bufferMsgSize++] = '['; return 0; } /** * small helper function to close the dyn_buffer structure. * will close the line list with two ']' and will remove the leading ',' in the fields list * * params: * - pBody: the pointer on the dyn_buffer on which to start a new input line * * return: 0 if successful, -1 otherwise */ int end_body(dyn_buffer *pBody) { /* don't if the message is empty */ if (!pBody->bufferMsgSize) { return -1; } DBGPRINTF("mmdarwin::end_body:: finishing body structure\n"); if (pBody->bufferAllocSize < pBody->bufferMsgSize + 2) { if (expand_buffer(pBody, pBody->bufferAllocSize + 2) != 0) { return -1; } } pBody->buffer[pBody->bufferMsgSize - 1] = ']'; pBody->buffer[pBody->bufferMsgSize++] = ']'; pBody->buffer[pBody->bufferMsgSize++] = '\0'; return 0; } /** * Get the potential existing uuid put by previous mmdarwin call in a json * * params: * - pJson: the pointer on the json * * return: a valid json_object pointer if found, NULL otherwise */ const char *get_uuid_object(smsg_t *const pMsg) { struct json_object *mmdarwin_object = NULL; const char *result = NULL, *key = NULL; msgPropDescr_t propDesc; msgPropDescrFill(&propDesc, (uchar *)runModConf->container, strlen(runModConf->container)); msgGetJSONPropJSON(pMsg, &propDesc, &mmdarwin_object); if (mmdarwin_object) { struct json_object_iterator it = json_object_iter_begin(mmdarwin_object); struct json_object_iterator itEnd = json_object_iter_end(mmdarwin_object); while (!json_object_iter_equal(&it, &itEnd)) { key = json_object_iter_peek_name(&it); if (!strcmp(key, JSON_DARWIN_ID)) { // should always be a (non-empty) null-terminated string, safe to use with strdup() result = strdup(json_object_get_string(json_object_iter_peek_value(&it))); break; } json_object_iter_next(&it); } json_object_put(mmdarwin_object); } msgPropDescrDestruct(&propDesc); return result; } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free((void *)pModConf->container); ENDfreeCnf BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; DBGPRINTF("%s\n", pData->pSockName); ENDdbgPrintInstInfo BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; pWrkrData->pktSentSocket = 0; pWrkrData->darwinBody.bufferAllocSize = 0; pWrkrData->darwinBody.bufferMaxSize = BUFFER_DEFAULT_MAX_SIZE; pWrkrData->darwinBody.bufferMsgSize = 0; pWrkrData->sock = INVLD_SOCK; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; if (pData->fieldList.name != NULL) { for (int i = 0; i < pData->fieldList.nmemb; ++i) { free(pData->fieldList.name[i]); free(pData->fieldList.varname[i]); } free(pData->fieldList.name); free(pData->fieldList.varname); } free(pData->pUUIDKey); free(pData->pCertitudeKey); free(pData->pSockName); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; closeSocket(pWrkrData); free(pWrkrData->darwinBody.buffer); ENDfreeWrkrInstance BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; loadModConf->container = NULL; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "mmdarwin: error processing module config parameters missing [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { DBGPRINTF("mmdarwin::setModCnf:: module (global) param blk for mmdarwin:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "container")) { CHKmalloc(loadModConf->container = es_str2cstr(pvals[i].val.d.estr, NULL)); if (loadModConf->container[0] != '!' && loadModConf->container[0] != '.') { LogError(0, RS_RET_INVALID_PARAMS, "mmdarwin: container should either" " begin with '!' or '.'\n"); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } } else { DBGPRINTF( "mmdarwin::setModCnf:: program error, non-handled " "param '%s'\n", modpblk.descr[i].name); } } if (loadModConf->container == NULL) { CHKmalloc(loadModConf->container = strdup(JSON_DEFAULT_CONTAINER)); } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf static inline void setInstParamDefaults(instanceData *pData) { DBGPRINTF("mmdarwin::setInstParamDefaults::\n"); pData->pUUIDKey = NULL; pData->pCertitudeKey = NULL; pData->pSockName = NULL; pData->fieldList.nmemb = 0; pData->filterCode = DARWIN_FILTER_CODE_NO; pData->response = DARWIN_RESPONSE_SEND_NO; pData->socketMaxUse = 0; pData->sendPartial = 0; } BEGINnewActInst struct cnfparamvals *pvals; int i; CODESTARTnewActInst; DBGPRINTF("mmdarwin::newActInst::\n"); if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "key")) { char *key = es_str2cstr(pvals[i].val.d.estr, NULL); char vnamebuf[1024]; snprintf(vnamebuf, sizeof(vnamebuf), "%s!%s", loadModConf->container, key); CHKmalloc(pData->pCertitudeKey = strdup(vnamebuf)); free(key); DBGPRINTF("mmdarwin::newActInst:: certitudeKey is %s\n", pData->pCertitudeKey); } else if (!strcmp(actpblk.descr[i].name, "socketpath")) { CHKmalloc(pData->pSockName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); DBGPRINTF("mmdarwin::newActInst:: sockName is %s\n", pData->pSockName); } else if (!strcmp(actpblk.descr[i].name, "socket_max_use")) { pData->socketMaxUse = (uint32_t)pvals[i].val.d.n; DBGPRINTF("mmdarwin::newActInst:: socketMaxUse is %d\n", pData->socketMaxUse); } else if (!strcmp(actpblk.descr[i].name, "send_partial")) { pData->sendPartial = (sbool)pvals[i].val.d.n; if (pData->sendPartial) { DBGPRINTF("mmdarwin::newActInst:: sending bodies even if fields are missing\n"); } else { DBGPRINTF("mmdarwin::newActInst:: only sending complete bodies\n"); } } else if (!strcmp(actpblk.descr[i].name, "response")) { char *response; CHKmalloc(response = es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcmp(response, "no")) { pData->response = DARWIN_RESPONSE_SEND_NO; DBGPRINTF("mmdarwin::newActInst:: response type is 'no'\n"); } else if (!strcmp(response, "back")) { pData->response = DARWIN_RESPONSE_SEND_BACK; DBGPRINTF("mmdarwin::newActInst:: response type is 'back'\n"); } else if (!strcmp(response, "darwin")) { pData->response = DARWIN_RESPONSE_SEND_DARWIN; DBGPRINTF("mmdarwin::newActInst:: response type is 'darwin'\n"); } else if (!strcmp(response, "both")) { pData->response = DARWIN_RESPONSE_SEND_BOTH; DBGPRINTF("mmdarwin::newActInst:: response type is 'both'\n"); } else { DBGPRINTF("mmdarwin::newActInst:: invalid 'response' value: %s. 'No response' set.\n", response); pData->response = DARWIN_RESPONSE_SEND_NO; DBGPRINTF("mmdarwin::newActInst:: response type is 'no'\n"); } free(response); } else if (!strcmp(actpblk.descr[i].name, "filtercode")) { char *filterCode; CHKmalloc(filterCode = es_str2cstr(pvals[i].val.d.estr, NULL)); pData->filterCode = strtoull(filterCode, NULL, 16); free(filterCode); } else if (!strcmp(actpblk.descr[i].name, "fields")) { pData->fieldList.nmemb = pvals[i].val.d.ar->nmemb; CHKmalloc(pData->fieldList.name = calloc(pData->fieldList.nmemb, sizeof(char *))); CHKmalloc(pData->fieldList.varname = calloc(pData->fieldList.nmemb, sizeof(char *))); for (int j = 0; j < pData->fieldList.nmemb; ++j) { char *param; CHKmalloc(param = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL)); char *varname = NULL; char *name; if (*param == ':') { char *b = strchr(param + 1, ':'); if (b == NULL) { parser_errmsg("mmdarwin::newActInst:: missing closing colon: '%s'", param); ABORT_FINALIZE(RS_RET_ERR); } *b = '\0'; /* split name & varname */ varname = param + 1; name = b + 1; } else { name = param; } CHKmalloc(pData->fieldList.name[j] = strdup(name)); char vnamebuf[1024]; snprintf(vnamebuf, sizeof(vnamebuf), "%s!%s", loadModConf->container, (varname == NULL) ? name : varname); CHKmalloc(pData->fieldList.varname[j] = strdup(vnamebuf)); free(param); DBGPRINTF("mmdarwin::newActInst:: will look for field %s\n", pData->fieldList.name[j]); } } else { DBGPRINTF("mmdarwin::newActInst:: program error, non-handled param '%s'\n", actpblk.descr[i].name); } } // reserve space for 'container!key\0' size_t sizeKey = strlen(loadModConf->container) + strlen(JSON_DARWIN_ID) + 2; pData->pUUIDKey = malloc(sizeKey); snprintf(pData->pUUIDKey, sizeKey, "%s!%s", loadModConf->container, JSON_DARWIN_ID); DBGPRINTF("mmdarwin:: uuid key is %s\n", pData->pUUIDKey); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINtryResume CODESTARTtryResume; iRet = doTryResume(pWrkrData); ENDtryResume BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; /* the raw data */ smsg_t *pMsg = ppMsg[0]; /* the raw log line */ instanceData *pData = pWrkrData->pData; /* the parameters given for the plugin */ char *pFieldValue = NULL; /* ponter to the found field value */ int fieldsNum = 0; /* number of fields retrieved */ CODESTARTdoAction; DBGPRINTF("mmdarwin::doAction:: beggining action\n"); pWrkrData->darwinBody.bufferMsgSize = 0; fieldsNum = 0; for (int i = 0; i < pData->fieldList.nmemb; i++) { DBGPRINTF("mmdarwin::doAction:: processing field '%s'\n", pData->fieldList.name[i]); pFieldValue = NULL; /* case 1: static field. We simply forward it to Darwin */ if (pData->fieldList.name[i][0] != '!' && pData->fieldList.name[i][0] != '.') { pFieldValue = strdup(pData->fieldList.name[i]); } /* case 2: dynamic field. We retrieve its value from the JSON logline and forward it to * Darwin */ else { if (!get_field(pMsg, pData->fieldList.name[i], &pFieldValue)) { DBGPRINTF( "mmdarwin::doAction:: \ could not extract field '%s' from message\n", pData->fieldList.name[i]); continue; } } DBGPRINTF("mmdarwin::doAction:: got value of field '%s': '%s'\n", pData->fieldList.name[i], pFieldValue); if (add_field_to_body(&(pWrkrData->darwinBody), pFieldValue, strlen(pFieldValue)) != 0) { DBGPRINTF("mmdarwin::doAction:: could not add field to body, aborting\n"); free(pFieldValue); ABORT_FINALIZE(RS_RET_ERR); } fieldsNum++; free(pFieldValue); } if (fieldsNum) { if (!pData->sendPartial && fieldsNum != pData->fieldList.nmemb) { DBGPRINTF( "mmdarwin::doAction:: not all fields could be retrieved, not sending partial message." " (if you wish to send partial messages anyway, set 'send_partial' to 'on' in instance parameters)\n"); FINALIZE; } if (end_body(&(pWrkrData->darwinBody)) != 0) ABORT_FINALIZE(RS_RET_ERR); } else { DBGPRINTF("mmdarwin::doAction:: no fields retrieved, finalizing\n"); FINALIZE; } DBGPRINTF("mmdarwin::doAction:: body to send: '%s'\n", pWrkrData->darwinBody.buffer); if (pData->socketMaxUse) { /* need to rotate socket connections */ if (!pWrkrData->pktSentSocket) { DBGPRINTF("mmdarwin::doAction:: opening a new connection\n"); CHKiRet(doTryResume(pWrkrData)); } pWrkrData->pktSentSocket = (pWrkrData->pktSentSocket + 1) % pData->socketMaxUse; } /* the Darwin header to be sent to the filter */ darwin_filter_packet_t header = {.type = DARWIN_PACKET_OTHER, .response = pData->response, .filter_code = pData->filterCode, .body_size = pWrkrData->darwinBody.bufferMsgSize}; const char *uuid = get_uuid_object(pMsg); if (uuid) { DBGPRINTF("mmdarwin: using existing UUID = %s\n", uuid); if (uuid_parse(uuid, header.evt_id)) LogError(0, RS_RET_ERR, "mmdarwin:: failed to parse existing UUID: %s\n", uuid); free((void *)uuid); } else { uuid_generate(header.evt_id); char uuidStr[40]; uuid_unparse(header.evt_id, uuidStr); DBGPRINTF("mmdarwin: generated new UUID = %s\n", uuidStr); msgAddJSON(pMsg, (uchar *)pData->pUUIDKey, json_object_new_string(uuidStr), 0, 0); } DBGPRINTF("mmdarwin::doAction:: sending header to Darwin\n"); CHKiRet(sendMsg(pWrkrData, &header, sizeof(darwin_filter_packet_t))); DBGPRINTF("mmdarwin::doAction:: sending body to Darwin\n"); CHKiRet(sendMsg(pWrkrData, (void *)(pWrkrData->darwinBody.buffer), pWrkrData->darwinBody.bufferMsgSize)); /* there is no need to wait for a response that will never come */ if (pData->response == DARWIN_RESPONSE_SEND_NO || pData->response == DARWIN_RESPONSE_SEND_DARWIN) { DBGPRINTF( "mmdarwin::doAction:: no response will be sent back " "(darwin response type is set to 'no' or 'darwin')\n"); goto finalize_it; } darwin_filter_packet_t response; memset(&response, 0, sizeof(response)); DBGPRINTF("mmdarwin::doAction:: receiving from Darwin\n"); CHKiRet(receiveMsg(pWrkrData, &response, sizeof(response))); unsigned int certitude = response.certitude_list[0]; DBGPRINTF("mmdarwin::doAction:: end of the transaction, certitude is %d\n", certitude); msgAddJSON(pMsg, (uchar *)pData->pCertitudeKey, json_object_new_int(certitude), 0, 0); finalize_it: DBGPRINTF("mmdarwin::doAction:: finished processing log line\n"); ENDdoAction NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; objRelease(glbl, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; /* we only support the current interface specification */ *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmdarwin::modInit:: module compiled with rsyslog version %s.\n", VERSION); CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/mmdarwin/PaxHeaders/protocol.h0000644000000000000000000000013215132411300020015 xustar0030 mtime=1768559296.138883615 30 atime=1787067642.141887185 30 ctime=1787067801.762862348 rsyslog-8.2608.0/contrib/mmdarwin/protocol.h0000666000175000017500000000452515132411300017471 0ustar00rgerrger/* Copyright 2019 Advens * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DARWIN_PROTOCOL_H #define DARWIN_PROTOCOL_H #ifdef __cplusplus extern "C" { #endif #include #include #define DARWIN_FILTER_CODE_NO 0x00000000 // the default certitude list size, which is 1, to allow FMAs (see flexible array members on C99) for both C and C++ // code #define DEFAULT_CERTITUDE_LIST_SIZE 1 /// Represent the receiver of the results. /// /// \enum darwin_response_type enum darwin_filter_response_type { DARWIN_RESPONSE_SEND_NO = 0, //!< Don't send results to anybody. DARWIN_RESPONSE_SEND_BACK, //!< Send results back to caller. DARWIN_RESPONSE_SEND_DARWIN, //!< Send results to the next filter. DARWIN_RESPONSE_SEND_BOTH, //!< Send results to both caller and the next filter. }; /// Represent the type of information sent. /// /// \enum darwin_packet_type enum darwin_packet_type { DARWIN_PACKET_OTHER = 0, //!< Information sent by something else. DARWIN_PACKET_FILTER, //!< Information sent by another filter. }; /// First packet to be sent to a filter. /// /// \struct darwin_filter_packet_t typedef struct { enum darwin_packet_type type; //!< The type of information sent. enum darwin_filter_response_type response; //!< Whom the response will be sent to. long filter_code; //!< The unique identifier code of a filter. size_t body_size; //!< The complete size of the the parameters to be sent unsigned char evt_id[16]; //!< An array containing the event ID size_t certitude_size; //!< The size of the list containing the certitudes. unsigned int certitude_list[DEFAULT_CERTITUDE_LIST_SIZE]; //!< The scores or the certitudes of the module. May be used to pass other info in specific cases. } darwin_filter_packet_t; #ifdef __cplusplus }; #endif #endif /* !DARWIN_PROTOCOL_H */ rsyslog-8.2608.0/contrib/mmdarwin/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020064 xustar0030 mtime=1787067504.833326524 30 atime=1787067578.855707152 30 ctime=1787067801.757862255 rsyslog-8.2608.0/contrib/mmdarwin/Makefile.in0000664000175000017500000006574715241076160017553 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmdarwin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) mmdarwin_la_DEPENDENCIES = am_mmdarwin_la_OBJECTS = mmdarwin_la-mmdarwin.lo mmdarwin_la_OBJECTS = $(am_mmdarwin_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 = mmdarwin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(mmdarwin_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmdarwin_la_SOURCES) DIST_SOURCES = $(mmdarwin_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmdarwin.la mmdarwin_la_SOURCES = mmdarwin.c protocol.h mmdarwin_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmdarwin_la_LDFLAGS = -module -avoid-version mmdarwin_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmdarwin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmdarwin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmdarwin.la: $(mmdarwin_la_OBJECTS) $(mmdarwin_la_DEPENDENCIES) $(EXTRA_mmdarwin_la_DEPENDENCIES) $(AM_V_CCLD)$(mmdarwin_la_LINK) -rpath $(pkglibdir) $(mmdarwin_la_OBJECTS) $(mmdarwin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmdarwin_la-mmdarwin.lo: mmdarwin.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmdarwin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmdarwin_la-mmdarwin.lo -MD -MP -MF $(DEPDIR)/mmdarwin_la-mmdarwin.Tpo -c -o mmdarwin_la-mmdarwin.lo `test -f 'mmdarwin.c' || echo '$(srcdir)/'`mmdarwin.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmdarwin_la-mmdarwin.Tpo $(DEPDIR)/mmdarwin_la-mmdarwin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmdarwin.c' object='mmdarwin_la-mmdarwin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmdarwin_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmdarwin_la-mmdarwin.lo `test -f 'mmdarwin.c' || echo '$(srcdir)/'`mmdarwin.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmdarwin_la-mmdarwin.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imbatchreport0000644000000000000000000000013215241076632016773 xustar0030 mtime=1787067802.546876958 30 atime=1787067808.785993219 30 ctime=1787067802.546876958 rsyslog-8.2608.0/contrib/imbatchreport/0000775000175000017500000000000015241076632016514 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imbatchreport/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264021100 xustar0030 mtime=1752569012.326271887 30 atime=1787067433.951004009 30 ctime=1787067802.542876883 rsyslog-8.2608.0/contrib/imbatchreport/Makefile.am0000666000175000017500000000035515035412264020551 0ustar00rgerrgerpkglib_LTLIBRARIES = imbatchreport.la imbatchreport_la_SOURCES = imbatchreport.c imbatchreport_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imbatchreport_la_LDFLAGS = -module -avoid-version imbatchreport_la_LIBADD = rsyslog-8.2608.0/contrib/imbatchreport/PaxHeaders/imbatchreport.c0000644000000000000000000000013115220503174022047 xustar0030 mtime=1782744700.129046209 29 atime=1787067644.37292878 30 ctime=1787067802.546876958 rsyslog-8.2608.0/contrib/imbatchreport/imbatchreport.c0000664000175000017500000010176715220503174021530 0ustar00rgerrger/* imbatchreport.c * * This is the input module for reading full text file data. A text file is a * non-binary file who's lines are delimited by the \n character. The file is * treated as a single message. An optional structured data can be written at * the end of the file. * * No state file are used as it should only grow with time. Instead the state * is managed using the name of the file. A "glob" allows the module to identify * "to be treated" files. The module can be configured either to deleted the * the file on success either to rename the file on success. The size limit is * fixed by rsyslog max message size global parameter. All files larger than this * limit produce a message which references it as "too large" and its new location * The "too large" files are also renamed to keep them available. * * This modules allows one to centralize batch reports with other standard logs and * performance monitoring in a single repository (ElasticSearch, HDFS, ...). This * centralization helps to identify cause of global performance issues. * * Work originally begun on 2014-07-01 by Philippe Duveau @ Pari Mutuel Urbain * * This file is contribution of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include /* do NOT remove: will soon be done by the module generation macros */ #include #include #include #include #ifdef HAVE_SYS_STAT_H #include #endif #include "rsyslog.h" /* error codes etc... */ #include "dirty.h" #include "cfsysline.h" /* access to config file objects */ #include "module-template.h" #include "srUtils.h" /* some utility functions */ #include "msg.h" #include "errmsg.h" #include "glbl.h" #include "datetime.h" #include "unicode-helper.h" #include "prop.h" #include "stringbuf.h" #include "ruleset.h" #include "ratelimit.h" #include MODULE_TYPE_INPUT /* must be present for input modules, do not remove */ MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imbatchreport") /* defines for freebsd */ #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif /* Module static data */ DEF_IMOD_STATIC_DATA /* must be present, starts static data */ DEFobjCurrIf(glbl) DEFobjCurrIf(ruleset) DEFobjCurrIf(datetime) DEFobjCurrIf(prop) #define SRUCTDATA_BUFFER_LEN 150 #define READ_BUFFER_LEN 512 #define FILE_TOO_LARGE "File too large : " #define FILE_TOO_LARGE_LEN sizeof(FILE_TOO_LARGE) - 1 #define DFLT_PollInterval 10 #define ADD_METADATA_UNSPECIFIED -1 typedef enum action_batchreport_t { action_nothing, action_rename, action_delete } action_batchreport_t; struct instanceConf_s { uchar *pszFollow_glob; uchar *pszDirName; uchar *pszFileBaseName; uchar *pszTag; int lenTag; uchar *pszTSk; int lenTSk; uchar *pszProgk; int lenProgk; int must_stop; uchar *pszBindRuleset; int bDedupSpace; int iFacility; int iSeverity; char *ff_regex; /* Full treatment : this should contain a regex applied on filename. The matching part is then replaced with ff_replace to put the file out of scan criteria */ regex_t ff_preg; char *ff_rename; int len_rename; char *ff_reject; int len_reject; int filename_oversize; ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ ratelimit_t *ratelimiter; struct instanceConf_s *next; action_batchreport_t action; char *pszNewFName; int fd; sbool goon; }; /* global configuration variables */ static struct { uchar *hostname; size_t lhostname; char *msg_buffer; size_t max_msg_size; instanceConf_t *root; /* number of seconds to sleep when there was no file activity */ int iPollInterval; } fixedModConf; /* config variables */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"pollinginterval", eCmdHdlrPositiveInt, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* input instance parameters */ static struct cnfparamdescr inppdescr[] = { {"reports", eCmdHdlrString, CNFPARAM_REQUIRED}, {"tag", eCmdHdlrString, CNFPARAM_REQUIRED}, {"programkey", eCmdHdlrString, 0}, {"timestampkey", eCmdHdlrString, 0}, {"deduplicatespace", eCmdHdlrBinary, 0}, {"rename", eCmdHdlrString, 0}, {"delete", eCmdHdlrString, 0}, {"severity", eCmdHdlrSeverity, 0}, {"facility", eCmdHdlrFacility, 0}, {"ruleset", eCmdHdlrString, 0}, }; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; #include "im-helper.h" /* must be included AFTER the type definitions! */ /* enqueue the read file line as a message. The provided string is * not freed - thuis must be done by the caller. */ static rsRetVal enqMsg(instanceConf_t *pInst, smsg_t *pMsg) { DEFiRet; MsgSetFlowControlType(pMsg, eFLOWCTL_FULL_DELAY); MsgSetInputName(pMsg, pInputName); MsgSetHOSTNAME(pMsg, fixedModConf.hostname, (const int)fixedModConf.lhostname); MsgSetTAG(pMsg, pInst->pszTag, pInst->lenTag); MsgSetPROCID(pMsg, "-"); MsgSetMSGID(pMsg, "-"); pMsg->iFacility = pInst->iFacility >> 3; pMsg->iSeverity = pInst->iSeverity; MsgSetRuleset(pMsg, pInst->pBindRuleset); CHKiRet(ratelimitAddMsg(pInst->ratelimiter, NULL, pMsg)); finalize_it: RETiRet; } /* The following is a cancel cleanup handler for strmReadLine(). It is necessary in case * strmReadLine() is cancelled while processing the stream. -- rgerhards, 2008-03-27 */ static void pollFileCancelCleanup(void *pArg) { instanceConf_t *ppInst = (instanceConf_t *)pArg; if (ppInst->fd > 0) close(ppInst->fd); if (ppInst->pszNewFName) free(ppInst->pszNewFName); } /* readAndSendFile try to read the file and send the message. * @param pInst point to instance * @param filename the file name * @param fstate the file stat */ static rsRetVal readAndSendFile(instanceConf_t *pInst, char *filename, char *fpath, struct stat *fstat) { smsg_t *pMsg = NULL; size_t file_len, read_len = 0, sd_buf_l, msg_len = 0, idx = 0; int last_is_space = 0; struct timeval tvm; uchar sd_buffer[SRUCTDATA_BUFFER_LEN]; uchar read_buffer[READ_BUFFER_LEN]; DEFiRet; CHKiRet(msgConstruct(&pMsg)); msgAddMetadata(pMsg, (uchar *)"filename", (uchar *)filename); /* get the file modification time : end of the batch*/ tvm.tv_sec = fstat->st_mtime; tvm.tv_usec = 0; file_len = lseek(pInst->fd, 0, SEEK_END); MsgSetStructuredData(pMsg, "-"); /* Let's read the end of the file first and put it in the buffer for structuredData * This will help to find the real end of the message */ sd_buf_l = (file_len < SRUCTDATA_BUFFER_LEN) ? file_len : SRUCTDATA_BUFFER_LEN; if (lseek(pInst->fd, file_len - sd_buf_l, SEEK_SET) >= 0) { uchar *sdp = sd_buffer + sd_buf_l - 1; int nb_rm = 0; /* number of space chars removed */ size_t stdata_len = 0, t; char *tmp; if ((t = read(pInst->fd, sd_buffer, sd_buf_l)) != sd_buf_l) { LogError(0, RS_RET_READ_ERR, "read end of file for structured data failed (%zu / %zu)", t, sd_buf_l); return RS_RET_READ_ERR; } /* let's trim the end */ for (; sdp > sd_buffer && (*sdp == '\n' || *sdp == '\t' || *sdp == ' '); sdp--, sd_buf_l--) file_len--; if (sd_buf_l > 1 && *sdp == ']') { stdata_len = 1; /* it seems that we have structured data let find the begin */ for (; sdp > sd_buffer && *sdp != '['; sdp--, stdata_len++) { if (*sdp == '\n') { /* line feed not supported in structured data */ stdata_len--; memmove(sdp, sdp + 1, stdata_len); nb_rm++; } } if (*sdp == '[') { /* we got a structured data */ DBGPRINTF("structured data : %.*s\n", (int)stdata_len, sdp); MsgAddToStructuredData(pMsg, sdp, stdata_len); /* extracting timestamp from structured data overwrite the file creation time */ if (pInst->pszTSk) { uchar *field = (uchar *)strstr((char *)sdp, (char *)pInst->pszTSk), v; if (field != NULL) { tvm.tv_sec = 0; tvm.tv_usec = 0; for (field += pInst->lenTSk; (v = *field ^ 0x30) <= 9; field++) tvm.tv_sec = tvm.tv_sec * 10 + v; } } /* extracting program from structured data */ if (pInst->pszProgk) { char *field = strstr((char *)sdp, (char *)pInst->pszProgk); if (field != NULL) { tmp = field + pInst->lenProgk; if ((field = strchr(tmp, '\"')) != NULL) { *field = '\0'; MsgSetAPPNAME(pMsg, tmp); } } } /* let's trim until useful message end */ for (sdp--; sdp > sd_buffer && (*sdp == '\n' || *sdp == '\t' || *sdp == ' '); sdp--) nb_rm++; } } /* computing the new file_len */ file_len -= nb_rm + stdata_len; } datetime.timeval2syslogTime(&tvm, &pMsg->tTIMESTAMP, TIME_IN_UTC); pMsg->ttGenTime = tvm.tv_sec; /* go back to beginning */ if (lseek(pInst->fd, 0, SEEK_SET) < 0) { LogError(0, RS_RET_READ_ERR, "readAndSendFile : error while seeking to beginning."); return RS_RET_READ_ERR; } /* Now read the file */ msg_len = 0; while (msg_len < fixedModConf.max_msg_size && (read_len = read(pInst->fd, read_buffer, (file_len > READ_BUFFER_LEN) ? READ_BUFFER_LEN : file_len)) > 0) { file_len -= read_len; idx = 0; while (read_len > 0 && msg_len < fixedModConf.max_msg_size) { switch (read_buffer[idx]) { case '\t': case ' ': /* this is to reduce consecutive spaces to only one */ if (!last_is_space) fixedModConf.msg_buffer[msg_len++] = ' '; /* if pInst->bDedupSpace is off last_is_space will never be true */ last_is_space = pInst->bDedupSpace; break; case '\n': /* this is for trailing spaces */ if (last_is_space) msg_len--; fixedModConf.msg_buffer[msg_len++] = '\\'; /* risk of overflow is managed by making buffer one char longer * than fixedModConf.max_msg_size */ fixedModConf.msg_buffer[msg_len++] = 'n'; break; default: fixedModConf.msg_buffer[msg_len++] = read_buffer[idx]; last_is_space = 0; } idx++; read_len--; } } close(pInst->fd); pInst->fd = 0; if (file_len > 0 || read_len > 0) { /* file is too large to be stored in one message */ memcpy(fixedModConf.msg_buffer, FILE_TOO_LARGE, FILE_TOO_LARGE_LEN); msg_len = strlen(fpath); memcpy(fixedModConf.msg_buffer + FILE_TOO_LARGE_LEN, fpath, msg_len); msg_len += FILE_TOO_LARGE_LEN; } /* file is stored in the message */ MsgSetRawMsg(pMsg, fixedModConf.msg_buffer, msg_len); MsgSetMSGoffs(pMsg, 0); if ((iRet = enqMsg(pInst, pMsg)) == RS_RET_OK && (file_len > 0 || read_len > 0)) iRet = RS_RET_FILE_TOO_LARGE; finalize_it: RETiRet; } /* poll a glob */ static void pollFile(instanceConf_t *pInst) { pInst->fd = 0; glob_t glob_res; pthread_cleanup_push(pollFileCancelCleanup, pInst); DBGPRINTF("polling files : %s\n", pInst->pszFollow_glob); /* We "glob" to find candidate regular file (or other) */ if (glob((char *)pInst->pszFollow_glob, GLOB_NOSORT, 0, &glob_res) != 0) FINALIZE; for (size_t i = 0; i < glob_res.gl_pathc && glbl.GetGlobalInputTermState() == 0; i++) { struct stat fstat; rsRetVal ret; char *filename = strrchr(glob_res.gl_pathv[i], '/'); if (filename) filename++; else filename = glob_res.gl_pathv[i]; char *fpath = glob_res.gl_pathv[i]; /* let's verify that the file is a regular one */ if (!stat(fpath, &fstat) && S_ISREG(fstat.st_mode)) { regmatch_t matches[1]; int toolargeOrFailure = 0; DBGPRINTF("Regular file found '%s')\n", fpath); /* With this test we verify that we have conditions to remove the * file from glob scope. If the regular expression not apply we * can not rename it */ if (regexec(&pInst->ff_preg, fpath, 1, matches, 0)) { pInst->must_stop = 1; FINALIZE; } pInst->fd = open(fpath, O_NOCTTY | O_RDONLY | O_NONBLOCK | O_LARGEFILE, 0); if (pInst->fd <= 0) { /* file could be open unfortunately we will try each polling */ char errStr[512]; int eno = errno; rs_strerror_r(eno, errStr, sizeof(errStr)); LogError(0, RS_RET_READ_ERR, "open the file %s failed with error %s", fpath, errStr); continue; } /* let's read the file and send it to output */ ret = readAndSendFile(pInst, filename, fpath, &fstat); /* is the file to large to be sent */ toolargeOrFailure = ret == RS_RET_FILE_TOO_LARGE; if (ret != RS_RET_OK && ret != RS_RET_FILE_TOO_LARGE) { LogError(0, ret, "The module could not manage the file %s", fpath); toolargeOrFailure = 1; } if (pInst->action == action_rename || toolargeOrFailure) { pInst->pszNewFName = (char *)malloc(strlen(fpath) + pInst->filename_oversize); memcpy(pInst->pszNewFName, fpath, matches[0].rm_so); memcpy((char *)pInst->pszNewFName + matches[0].rm_so, (toolargeOrFailure) ? pInst->ff_reject : pInst->ff_rename, strlen((toolargeOrFailure) ? pInst->ff_reject : pInst->ff_rename) + 1); if (rename(fpath, pInst->pszNewFName)) { /* if the module can not rename the file, it must stop to avoid flooding * but it keep chance to manage max files as possible */ LogError(0, RS_RET_STREAM_DISABLED, "module stopped : was unable" " to rename form %s to %s.", fpath, pInst->pszNewFName); pInst->must_stop = 1; } else DBGPRINTF("file %s sent and renamed to %s.\n", fpath, pInst->pszNewFName); free(pInst->pszNewFName); pInst->pszNewFName = NULL; } else { if (unlink(fpath)) { /* if the module can not remove the file, it must stop to avoid flooding * but it keep chance to manage max files as possible */ LogError(0, RS_RET_STREAM_DISABLED, "module stopped : unable to delete %s.", fpath); pInst->must_stop = 1; } else DBGPRINTF("file %s sent and deleted\n", fpath); } } /* if stat */ } /* for */ finalize_it: globfree(&glob_res); pthread_cleanup_pop(0); } static void addInstance(instanceConf_t *inst) { if (fixedModConf.root == NULL) { fixedModConf.root = inst; } else { fixedModConf.root->next = inst; fixedModConf.root = inst; } } /* create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal createInstance(instanceConf_t **pinst) { instanceConf_t *inst; DEFiRet; *pinst = NULL; CHKmalloc(inst = (instanceConf_t *)malloc(sizeof(instanceConf_t))); inst->next = NULL; inst->pBindRuleset = NULL; inst->pszBindRuleset = NULL; inst->pszFollow_glob = NULL; inst->pszDirName = NULL; inst->pszFileBaseName = NULL; inst->pszTag = NULL; inst->pszTSk = NULL; inst->pszProgk = NULL; inst->ff_regex = NULL; inst->ff_rename = NULL; inst->ff_reject = NULL; inst->iSeverity = LOG_NOTICE; inst->iFacility = LOG_LOCAL0; inst->len_rename = 0; inst->len_reject = 0; inst->bDedupSpace = 1; inst->goon = 0; inst->ratelimiter = NULL; inst->action = action_nothing; inst->must_stop = 0; *pinst = inst; finalize_it: RETiRet; } /* the basen(ame) buffer must be of size MAXFNAME * returns the index of the slash in front of basename */ static int getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path) { int i; const int lenName = ustrlen(path); for (i = lenName; i >= 0; --i) { if (path[i] == '/') { if (i == lenName) basen[0] = '\0'; else { memcpy(basen, path + i + 1, lenName - i); } break; } } if (i == -1) { memcpy(basen, path, lenName); i = 0; } return i; } /* this function checks instance parameters and does some required pre-processing * (e.g. split filename in path and actual name) * Note: we do NOT use dirname()/basename() as they have portability problems. */ static rsRetVal checkInstance(instanceConf_t *inst) { char dirn[MAXFNAME]; uchar basen[MAXFNAME]; int i; struct stat sb; int r; int eno; char errStr[512], *s, *d; regmatch_t matches[1]; DEFiRet; i = getBasename(basen, inst->pszFollow_glob); memcpy(dirn, inst->pszFollow_glob, i); dirn[i] = '\0'; CHKmalloc(inst->pszFileBaseName = (uchar *)strdup((char *)basen)); CHKmalloc(inst->pszDirName = (uchar *)strdup(dirn)); if (dirn[0] == '\0') { dirn[0] = '.'; dirn[1] = '\0'; } r = stat(dirn, &sb); if (r != 0) { eno = errno; rs_strerror_r(eno, errStr, sizeof(errStr)); LogError(0, RS_RET_CONFIG_ERROR, "Configured directory can not be stated '%s': %s", dirn, errStr); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (!S_ISDIR(sb.st_mode)) { LogError(0, RS_RET_CONFIG_ERROR, "Configured directory is NOT a directory : '%s'", dirn); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (stat((char *)inst->pszFollow_glob, &sb) == 0 && !S_ISREG(sb.st_mode)) { LogError(0, RS_RET_CONFIG_ERROR, "Configured report is not a glob or a regular file."); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } for (s = (char *)inst->pszFollow_glob, d = dirn; *s; s++, d++) *d = (*s != '*' && *s != '?') ? *s : '~'; *d = '\0'; if (regexec(&inst->ff_preg, dirn, 1, matches, 0)) { LogError(0, RS_RET_CONFIG_ERROR, "Regex does not match globed filenames: Instance ignored to avoid loops."); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (inst->action == action_rename) { memcpy(dirn + matches[0].rm_so, inst->ff_rename, strlen(inst->ff_rename) + 1); if (fnmatch((char *)inst->pszFollow_glob, dirn, FNM_PATHNAME) == 0) { LogError(0, RS_RET_INVALID_PARAMS, "Normal renaming leaves files in glob scope: Instance ignored to avoid loops."); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } memcpy(dirn + matches[0].rm_so, inst->ff_reject, strlen(inst->ff_reject) + 1); if (fnmatch((char *)inst->pszFollow_glob, dirn, FNM_PATHNAME) == 0) { LogError(0, RS_RET_INVALID_PARAMS, "Reject renaming leaves files in glob scope: Instance ignored to avoid loops."); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } dbgprintf("instance checked"); finalize_it: RETiRet; } static void freeInstance(instanceConf_t *inst) { if (inst == NULL) return; if (inst->pszBindRuleset) free(inst->pszBindRuleset); if (inst->pszFollow_glob) free(inst->pszFollow_glob); if (inst->pszDirName) free(inst->pszDirName); if (inst->pszFileBaseName) free(inst->pszFileBaseName); if (inst->pszTag) free(inst->pszTag); if (inst->pszTSk) free(inst->pszTSk); if (inst->pszProgk) free(inst->pszProgk); if (inst->len_reject) regfree(&inst->ff_preg); if (inst->ff_regex) free(inst->ff_regex); if (inst->ff_rename) free(inst->ff_rename); if (inst->ff_reject) free(inst->ff_reject); if (inst->ratelimiter) ratelimitDestruct(inst->ratelimiter); free(inst); } BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst = NULL; int i; char *temp; CODESTARTnewInpInst; DBGPRINTF("newInpInst (imbatchreport)\n"); pvals = nvlstGetParams(lst, &inppblk, NULL); if (pvals == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } DBGPRINTF("input param blk in imbatchreport:\n"); if (Debug) cnfparamsPrint(&inppblk, pvals); CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "reports")) { CHKmalloc(inst->pszFollow_glob = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "tag")) { CHKmalloc(inst->pszTag = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); inst->lenTag = ustrlen(inst->pszTag); } else if (!strcmp(inppblk.descr[i].name, "programkey")) { CHKmalloc(inst->pszProgk = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); inst->lenProgk = ustrlen(inst->pszProgk) + 2; } else if (!strcmp(inppblk.descr[i].name, "timestampkey")) { CHKmalloc(inst->pszTSk = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); inst->lenTSk = ustrlen(inst->pszTSk) + 1; } else if (!strcmp(inppblk.descr[i].name, "deduplicatespace")) { inst->bDedupSpace = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "severity")) { inst->iSeverity = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "facility")) { inst->iFacility = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "rename")) { if (inst->action == action_delete) { LogError(0, RS_RET_PARAM_ERROR, "'rename' and 'delete' are exclusive !"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKmalloc(inst->ff_regex = es_str2cstr(pvals[i].val.d.estr, NULL)); while ((temp = strchr(inst->ff_regex, '\t')) != NULL) *temp = ' '; inst->len_reject = 0; if ((inst->ff_rename = strchr(inst->ff_regex, ' ')) != NULL) { *inst->ff_rename++ = '\0'; while (*inst->ff_rename == ' ') inst->ff_rename++; if ((inst->ff_reject = strchr(inst->ff_rename, ' ')) != NULL) { *inst->ff_reject++ = '\0'; while (*inst->ff_reject == ' ') inst->ff_reject++; temp = strchr(inst->ff_reject, ' '); if (temp) *temp = '\0'; if (strcmp(inst->ff_rename, "-")) { inst->ff_rename = strdup(inst->ff_rename); inst->len_rename = strlen(inst->ff_rename); } else { inst->ff_rename = strdup(""); inst->len_rename = 0; } inst->ff_reject = strdup(inst->ff_reject); inst->len_reject = strlen(inst->ff_reject); if (inst->len_reject && regcomp(&inst->ff_preg, (char *)inst->ff_regex, REG_EXTENDED)) { inst->len_reject = 0; LogError(0, RS_RET_SYNTAX_ERROR, "The first part of 'rename' " "parameter does not contain a valid regex"); ABORT_FINALIZE(RS_RET_SYNTAX_ERROR); } } } if (inst->len_reject == 0) { LogError(0, RS_RET_PARAM_ERROR, "'rename' must specify THREE " "parameters separated by spaces or tabs ! The second " "parameter can be a null string to get this use a '-'."); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } inst->action = action_rename; } else if (!strcmp(inppblk.descr[i].name, "delete")) { if (inst->action == action_rename) { LogError(0, RS_RET_PARAM_ERROR, "'rename' and 'delete' are exclusive !"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKmalloc(inst->ff_regex = es_str2cstr(pvals[i].val.d.estr, NULL)); while ((temp = strchr(inst->ff_regex, '\t')) != NULL) *temp = ' '; inst->len_reject = 0; if ((inst->ff_reject = strchr(inst->ff_regex, ' ')) != NULL) { *inst->ff_reject++ = '\0'; while (*inst->ff_reject == ' ') inst->ff_reject++; temp = strchr(inst->ff_reject, ' '); if (temp) *temp = '\0'; inst->ff_reject = strdup(inst->ff_reject); inst->len_reject = strlen(inst->ff_reject); if (regcomp(&inst->ff_preg, (char *)inst->ff_regex, REG_EXTENDED)) { inst->len_reject = 0; LogError(0, RS_RET_SYNTAX_ERROR, "The first part of 'delete' parameter does not contain a valid regex"); ABORT_FINALIZE(RS_RET_SYNTAX_ERROR); } } if (inst->len_reject == 0) { LogError(0, RS_RET_PARAM_ERROR, "'delete' must specify TWO parameters separated by spaces or tabs !"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } inst->action = action_delete; } else { dbgprintf("Configuration param '%s' non-handled\n", inppblk.descr[i].name); } } if (inst->action == action_nothing) { LogError(0, RS_RET_PARAM_NOT_PERMITTED, "either 'rename' or 'delete' must be set"); ABORT_FINALIZE(RS_RET_PARAM_NOT_PERMITTED); } inst->filename_oversize = (inst->len_rename > inst->len_reject) ? inst->len_rename : inst->len_reject; CHKiRet(ratelimitNew(&inst->ratelimiter, "imbatchreport", (char *)inst->pszFollow_glob)); inst->goon = 1; CHKiRet(checkInstance(inst)); finalize_it: CODE_STD_FINALIZERnewInpInst if (iRet == RS_RET_OK) addInstance(inst); else freeInstance(inst); cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINbeginCnfLoad CODESTARTbeginCnfLoad; pModConf->pConf = pConf; fixedModConf.iPollInterval = DFLT_PollInterval; fixedModConf.msg_buffer = NULL; fixedModConf.root = NULL; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for imbatchreport:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "pollinginterval")) { fixedModConf.iPollInterval = (int)pvals[i].val.d.n; } else { dbgprintf( "program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; dbgprintf("polling interval is %d\n", fixedModConf.iPollInterval); ENDendCnfLoad BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = fixedModConf.root; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); } if (fixedModConf.root == NULL) { LogError(0, RS_RET_NO_LISTNERS, "no files configured to be monitored - no input will be gathered"); iRet = RS_RET_NO_LISTNERS; } ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf instanceConf_t *inst, *del; CODESTARTfreeCnf; for (inst = fixedModConf.root; inst != NULL;) { del = inst; inst = inst->next; freeInstance(del); } ENDfreeCnf BEGINwillRun CODESTARTwillRun; CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imbatchreport"), sizeof("imbatchreport") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); fixedModConf.max_msg_size = glbl.GetMaxLine(runConf); DBGPRINTF("Max message len %zu\n", fixedModConf.max_msg_size); CHKmalloc(fixedModConf.msg_buffer = (char *)malloc(fixedModConf.max_msg_size + 1)); finalize_it: ENDwillRun BEGINrunInput CODESTARTrunInput; fixedModConf.hostname = glbl.GetLocalHostName(); fixedModConf.lhostname = ustrlen(fixedModConf.hostname); while (glbl.GetGlobalInputTermState() == 0) { instanceConf_t *pInst; for (pInst = fixedModConf.root; pInst != NULL; pInst = pInst->next) { if (pInst->goon) { if (glbl.GetGlobalInputTermState() == 1) break; pollFile(pInst); /* We got a major problem so */ pInst->goon = !pInst->must_stop; } } if (glbl.GetGlobalInputTermState() == 0) srSleep(fixedModConf.iPollInterval, 10); } DBGPRINTF("terminating upon request of rsyslog core\n"); RETiRet; ENDrunInput /* This function is called by the framework after runInput() has been terminated. It * shall free any resources and prepare the module for unload. */ BEGINafterRun CODESTARTafterRun; if (fixedModConf.msg_buffer) free(fixedModConf.msg_buffer); if (pInputName != NULL) prop.Destruct(&pInputName); ENDafterRun BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK; ENDisCompatibleWithFeature /* The following entry points are defined in module-template.h. * In general, they need to be present, but you do NOT need to provide * any code here. */ BEGINmodExit CODESTARTmodExit; objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt /* modInit() is called once the module is loaded. It must perform all module-wide * initialization tasks. There are also a number of housekeeping tasks that the * framework requires. These are handled by the macros. Please note that the * complexity of processing is depending on the actual module. However, only * thing absolutely necessary should be done here. Actual app-level processing * is to be performed in runInput(). A good sample of what to do here may be to * set some variable defaults. */ BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); ENDmodInit static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "ruleset '%s' for %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->pszFollow_glob); } rsyslog-8.2608.0/contrib/imbatchreport/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160021110 xustar0030 mtime=1787067504.485320033 30 atime=1787067579.585720766 29 ctime=1787067802.54487692 rsyslog-8.2608.0/contrib/imbatchreport/Makefile.in0000664000175000017500000006640315241076160020566 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imbatchreport ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) imbatchreport_la_DEPENDENCIES = am_imbatchreport_la_OBJECTS = imbatchreport_la-imbatchreport.lo imbatchreport_la_OBJECTS = $(am_imbatchreport_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 = imbatchreport_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(imbatchreport_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imbatchreport_la_SOURCES) DIST_SOURCES = $(imbatchreport_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imbatchreport.la imbatchreport_la_SOURCES = imbatchreport.c imbatchreport_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imbatchreport_la_LDFLAGS = -module -avoid-version imbatchreport_la_LIBADD = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imbatchreport/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imbatchreport/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imbatchreport.la: $(imbatchreport_la_OBJECTS) $(imbatchreport_la_DEPENDENCIES) $(EXTRA_imbatchreport_la_DEPENDENCIES) $(AM_V_CCLD)$(imbatchreport_la_LINK) -rpath $(pkglibdir) $(imbatchreport_la_OBJECTS) $(imbatchreport_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imbatchreport_la-imbatchreport.lo: imbatchreport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imbatchreport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imbatchreport_la-imbatchreport.lo -MD -MP -MF $(DEPDIR)/imbatchreport_la-imbatchreport.Tpo -c -o imbatchreport_la-imbatchreport.lo `test -f 'imbatchreport.c' || echo '$(srcdir)/'`imbatchreport.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imbatchreport_la-imbatchreport.Tpo $(DEPDIR)/imbatchreport_la-imbatchreport.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imbatchreport.c' object='imbatchreport_la-imbatchreport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imbatchreport_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imbatchreport_la-imbatchreport.lo `test -f 'imbatchreport.c' || echo '$(srcdir)/'`imbatchreport.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imbatchreport_la-imbatchreport.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imkubernetes0000644000000000000000000000013215241076627016631 xustar0030 mtime=1787067799.081812396 30 atime=1787067808.785993219 30 ctime=1787067799.081812396 rsyslog-8.2608.0/contrib/imkubernetes/0000775000175000017500000000000015241076627016352 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imkubernetes/PaxHeaders/Makefile.am0000644000000000000000000000013215241075234020733 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.675579605 30 ctime=1787067799.075812285 rsyslog-8.2608.0/contrib/imkubernetes/Makefile.am0000664000175000017500000000036215241075234020400 0ustar00rgerrgerpkglib_LTLIBRARIES = imkubernetes.la imkubernetes_la_SOURCES = imkubernetes.c imkubernetes_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) imkubernetes_la_LDFLAGS = -module -avoid-version imkubernetes_la_LIBADD = $(CURL_LIBS) rsyslog-8.2608.0/contrib/imkubernetes/PaxHeaders/imkubernetes.c0000644000000000000000000000013215241075234021540 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.715580354 30 ctime=1787067799.081812396 rsyslog-8.2608.0/contrib/imkubernetes/imkubernetes.c0000664000175000017500000014441215241075234021212 0ustar00rgerrger/* imkubernetes.c * Kubernetes-native container log input module. * * This module tails Kubernetes pod/container log files from the host * filesystem, parses CRI or Docker json-file records, and optionally enriches * them with pod metadata from the Kubernetes API. * * Copyright (C) 2026 the rsyslog project. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cfsysline.h" #include "datetime.h" #include "debug.h" #include "errmsg.h" #include "glbl.h" #include "module-template.h" #include "msg.h" #include "parser.h" #include "prop.h" #include "ratelimit.h" #include "ruleset.h" #include "srUtils.h" #include "statsobj.h" #include "unicode-helper.h" MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imkubernetes") #define DFLT_LOG_FILE_GLOB "/var/log/pods/*/*/*.log" #define DFLT_KUBERNETES_URL "https://kubernetes.default.svc.cluster.local:443" #define DFLT_TOKEN_FILE "/var/run/secrets/kubernetes.io/serviceaccount/token" #define DFLT_CA_CERT_FILE "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" #define DFLT_pollingInterval 1 #define DFLT_cacheEntryTtl 300 #define DFLT_freshStartTail 0 #define DFLT_bEscapeLF 1 #define DFLT_enrichKubernetes 1 #define DFLT_SEVERITY pri2sev(LOG_INFO) #define DFLT_FACILITY pri2fac(LOG_USER) #define CRI_PARTIAL_HARD_LIMIT_FACTOR 10 enum { dst_invalid = -1, dst_stdout, dst_stderr }; typedef struct partial_msg_s { uchar *data; size_t len; size_t cap; int stream_type; struct syslogTime st; time_t ttGenTime; sbool hasTime; sbool truncated; } partial_msg_t; typedef struct path_meta_s { char *namespace_name; char *pod_name; char *pod_uid; char *container_name; char *container_id; int restart_count; } path_meta_t; typedef struct file_state_s { char *path; ino_t inode; off_t offset; sbool seen; path_meta_t meta; partial_msg_t partial; struct file_state_s *next; } file_state_t; typedef struct pod_cache_entry_s { char *key; time_t expires_at; struct json_object *json; struct pod_cache_entry_s *next; } pod_cache_entry_t; typedef struct curl_buf_s { char *data; size_t len; size_t cap; } curl_buf_t; typedef struct parsed_record_s { const uchar *msg; uchar *owned_msg; size_t len; int stream_type; struct syslogTime st; time_t ttGenTime; sbool hasTime; sbool is_partial; const char *format_name; sbool parse_error; } parsed_record_t; struct modConfData_s { rsconf_t *pConf; uchar *logFileGlob; int iPollInterval; int cacheEntryTtl; int iDfltSeverity; int iDfltFacility; sbool bEscapeLf; sbool freshStartTail; sbool enrichKubernetes; uchar *kubernetesUrl; uchar *token; uchar *tokenFile; uchar *caCertFile; sbool allowUnsignedCerts; sbool skipVerifyHost; uchar *pszBindRuleset; ruleset_t *pBindRuleset; }; static modConfData_t *loadModConf = NULL; static modConfData_t *runModConf = NULL; static int bLegacyCnfModGlobalsPermitted; DEF_IMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(parser) DEFobjCurrIf(ruleset) DEFobjCurrIf(statsobj) DEFobjCurrIf(datetime) static prop_t *pInputName = NULL; static ratelimit_t *ratelimiter = NULL; static statsobj_t *modStats = NULL; static file_state_t *g_fileStates = NULL; static pod_cache_entry_t *g_podCache = NULL; static CURL *g_apiCurl = NULL; static struct curl_slist *g_apiHdr = NULL; static char *gLineBuf = NULL; static size_t gLineBufCap = 0; STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted) STATSCOUNTER_DEF(ctrParseErrors, mutCtrParseErrors) STATSCOUNTER_DEF(ctrFilesDiscovered, mutCtrFilesDiscovered) STATSCOUNTER_DEF(ctrCriRecords, mutCtrCriRecords) STATSCOUNTER_DEF(ctrDockerJsonRecords, mutCtrDockerJsonRecords) STATSCOUNTER_DEF(ctrCacheHits, mutCtrCacheHits) STATSCOUNTER_DEF(ctrCacheMisses, mutCtrCacheMisses) STATSCOUNTER_DEF(ctrApiErrors, mutCtrApiErrors) STATSCOUNTER_DEF(ctrLostRatelimit, mutCtrLostRatelimit) static struct cnfparamdescr modpdescr[] = { {"logfileglob", eCmdHdlrString, 0}, {"pollinginterval", eCmdHdlrPositiveInt, 0}, {"cacheentryttl", eCmdHdlrPositiveInt, 0}, {"freshstarttail", eCmdHdlrBinary, 0}, {"defaultseverity", eCmdHdlrSeverity, 0}, {"defaultfacility", eCmdHdlrFacility, 0}, {"escapelf", eCmdHdlrBinary, 0}, {"enrichkubernetes", eCmdHdlrBinary, 0}, {"kubernetesurl", eCmdHdlrString, 0}, {"token", eCmdHdlrString, 0}, {"tokenfile", eCmdHdlrString, 0}, {"tls.cacert", eCmdHdlrString, 0}, {"allowunsignedcerts", eCmdHdlrBinary, 0}, {"skipverifyhost", eCmdHdlrBinary, 0}, {"ruleset", eCmdHdlrString, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static void freePathMeta(path_meta_t *meta) { if (meta == NULL) { return; } free(meta->namespace_name); free(meta->pod_name); free(meta->pod_uid); free(meta->container_name); free(meta->container_id); memset(meta, 0, sizeof(*meta)); meta->restart_count = -1; } static void freePartialMsg(partial_msg_t *partial) { if (partial == NULL) { return; } free(partial->data); memset(partial, 0, sizeof(*partial)); partial->stream_type = dst_invalid; } static void freeFileStates(void) { file_state_t *curr = g_fileStates; while (curr != NULL) { file_state_t *next = curr->next; free(curr->path); freePathMeta(&curr->meta); freePartialMsg(&curr->partial); free(curr); curr = next; } g_fileStates = NULL; } static void freePodCache(void) { pod_cache_entry_t *curr = g_podCache; while (curr != NULL) { pod_cache_entry_t *next = curr->next; free(curr->key); if (curr->json != NULL) { json_object_put(curr->json); } free(curr); curr = next; } g_podCache = NULL; } static char *dupRange(const char *start, size_t len) { char *out = NULL; if (start == NULL) { return NULL; } out = malloc(len + 1); if (out == NULL) { return NULL; } memcpy(out, start, len); out[len] = '\0'; return out; } static rsRetVal partialAppend(partial_msg_t *partial, const uchar *msg, size_t len) { DEFiRet; size_t needed; uchar *newbuf = NULL; assert(partial != NULL); if (msg == NULL || len == 0) { FINALIZE; } needed = partial->len + len + 1; if (needed > partial->cap) { size_t newcap = partial->cap == 0 ? 256 : partial->cap; while (newcap < needed) { newcap *= 2; } CHKmalloc(newbuf = realloc(partial->data, newcap)); partial->data = newbuf; partial->cap = newcap; } memcpy(partial->data + partial->len, msg, len); partial->len += len; partial->data[partial->len] = '\0'; finalize_it: RETiRet; } static sbool partialIsActive(const partial_msg_t *partial) { assert(partial != NULL); return partial->len > 0 || partial->truncated; } static void partialInitFromRecord(partial_msg_t *partial, const parsed_record_t *record) { assert(partial != NULL); assert(record != NULL); partial->stream_type = record->stream_type; partial->hasTime = record->hasTime; partial->ttGenTime = record->ttGenTime; if (record->hasTime) { memcpy(&partial->st, &record->st, sizeof(record->st)); } } static rsconf_t *getActiveConf(void) { return runModConf != NULL ? runModConf->pConf : NULL; } static size_t multiplyPartialLimit(size_t limit, size_t factor) { if (factor != 0 && limit > (size_t)-1 / factor) { return (size_t)-1; } return limit * factor; } static size_t getPartialMessageLimit(sbool *hardLimit) { rsconf_t *const cnf = getActiveConf(); const int maxLine = glbl.GetMaxLine(cnf); const int oversizeMode = cnf != NULL ? glblGetOversizeMsgInputMode(cnf) : glblOversizeMsgInputMode_Truncate; if (hardLimit != NULL) { *hardLimit = 0; } if (maxLine <= 0) { return 0; } if (oversizeMode == glblOversizeMsgInputMode_Truncate) { return (size_t)maxLine; } if (hardLimit != NULL) { *hardLimit = 1; } return multiplyPartialLimit((size_t)maxLine, CRI_PARTIAL_HARD_LIMIT_FACTOR); } static void markPartialTruncated(partial_msg_t *partial, size_t limit, sbool hardLimit) { assert(partial != NULL); if (!partial->truncated) { partial->truncated = 1; LogError(0, NO_ERRCODE, "imkubernetes: CRI partial message exceeded %s (%zu), truncating logical record", hardLimit ? "partial hard limit" : "maxMessageSize", limit); } } static rsRetVal partialAppendBounded(partial_msg_t *partial, const uchar *msg, size_t len) { sbool hardLimit = 0; const size_t limit = getPartialMessageLimit(&hardLimit); size_t appendLen = len; DEFiRet; assert(partial != NULL); if (limit > 0) { if (partial->len >= limit) { appendLen = 0; } else if (appendLen > limit - partial->len) { appendLen = limit - partial->len; } if (appendLen < len) { markPartialTruncated(partial, limit, hardLimit); } } if (appendLen > 0) { CHKiRet(partialAppend(partial, msg, appendLen)); } finalize_it: RETiRet; } static void trimTrailingNewline(const char *line, size_t *len) { while (*len > 0 && (line[*len - 1] == '\n' || line[*len - 1] == '\r')) { --(*len); } } static rsRetVal parseTimestamp3339(const char *ts, size_t len, struct syslogTime *st, time_t *ttGenTime, sbool *ok) { DEFiRet; uchar *mutableTs = NULL; uchar *parsePtr = NULL; int parseLen; assert(st != NULL); assert(ttGenTime != NULL); assert(ok != NULL); *ok = 0; *ttGenTime = 0; CHKmalloc(mutableTs = (uchar *)dupRange(ts, len)); parsePtr = mutableTs; parseLen = (int)len; if (datetime.ParseTIMESTAMP3339(st, &parsePtr, &parseLen) == RS_RET_OK) { *ttGenTime = datetime.syslogTime2time_t(st); *ok = 1; } finalize_it: free(mutableTs); RETiRet; } static sbool parsePodsPath(const char *path, path_meta_t *meta) { const char *filePart; const char *containerStart; const char *containerEnd; const char *podStart; const char *podEnd; const char *podsDirStart; const char *podsDirEnd; const char *u1; const char *u2; char *restartStr = NULL; char *restartEnd = NULL; filePart = strrchr(path, '/'); if (filePart == NULL || filePart == path) { return 0; } containerEnd = filePart; containerStart = containerEnd; while (containerStart > path && containerStart[-1] != '/') { --containerStart; } if (containerStart == path) { return 0; } podEnd = containerStart - 1; podStart = podEnd; while (podStart > path && podStart[-1] != '/') { --podStart; } if (podStart == path) { return 0; } podsDirEnd = podStart - 1; podsDirStart = podsDirEnd; while (podsDirStart > path && podsDirStart[-1] != '/') { --podsDirStart; } if ((size_t)(podsDirEnd - podsDirStart) != sizeof("pods") - 1 || strncmp(podsDirStart, "pods", sizeof("pods") - 1)) { return 0; } u1 = memchr(podStart, '_', (size_t)(podEnd - podStart)); if (u1 == NULL) { return 0; } u2 = memchr(u1 + 1, '_', (size_t)(podEnd - (u1 + 1))); if (u2 == NULL) { return 0; } meta->namespace_name = dupRange(podStart, (size_t)(u1 - podStart)); meta->pod_name = dupRange(u1 + 1, (size_t)(u2 - (u1 + 1))); meta->pod_uid = dupRange(u2 + 1, (size_t)(podEnd - (u2 + 1))); meta->container_name = dupRange(containerStart, (size_t)(containerEnd - containerStart)); if (meta->namespace_name == NULL || meta->pod_name == NULL || meta->pod_uid == NULL || meta->container_name == NULL) { freePathMeta(meta); return 0; } restartStr = dupRange(filePart + 1, strlen(filePart + 1)); if (restartStr != NULL) { char *dot = strrchr(restartStr, '.'); if (dot != NULL) { *dot = '\0'; } errno = 0; meta->restart_count = (int)strtol(restartStr, &restartEnd, 10); if (errno != 0 || restartEnd == restartStr || *restartEnd != '\0') { free(restartStr); freePathMeta(meta); return 0; } } free(restartStr); return 1; } static sbool parseContainersPath(const char *path, path_meta_t *meta) { const char *filePart = strrchr(path, '/'); char *base = NULL; char *dot = NULL; char *dash = NULL; char *u1 = NULL; char *u2 = NULL; if (filePart == NULL) { filePart = path; } else { ++filePart; } base = strdup(filePart); if (base == NULL) { return 0; } dot = strrchr(base, '.'); if (dot != NULL) { *dot = '\0'; } dash = strrchr(base, '-'); if (dash == NULL || dash == base || dash[1] == '\0') { free(base); return 0; } *dash = '\0'; u1 = strchr(base, '_'); if (u1 == NULL) { free(base); return 0; } u2 = strchr(u1 + 1, '_'); if (u2 == NULL) { free(base); return 0; } meta->pod_name = dupRange(base, (size_t)(u1 - base)); meta->namespace_name = dupRange(u1 + 1, (size_t)(u2 - (u1 + 1))); meta->container_name = strdup(u2 + 1); meta->container_id = strdup(dash + 1); meta->restart_count = -1; free(base); if (meta->pod_name == NULL || meta->namespace_name == NULL || meta->container_name == NULL || meta->container_id == NULL) { freePathMeta(meta); return 0; } return 1; } static sbool populatePathMeta(const char *path, path_meta_t *meta) { const char *containersSeg = strstr(path, "/containers/"); const char *podsSeg = strstr(path, "/pods/"); memset(meta, 0, sizeof(*meta)); meta->restart_count = -1; if (containersSeg != NULL) { if (parseContainersPath(path, meta)) { return 1; } freePathMeta(meta); } if (podsSeg != NULL) { if (parsePodsPath(path, meta)) { return 1; } freePathMeta(meta); } if (parsePodsPath(path, meta)) { return 1; } freePathMeta(meta); if (parseContainersPath(path, meta)) { return 1; } freePathMeta(meta); return 0; } static file_state_t *findFileState(const char *path) { file_state_t *curr; for (curr = g_fileStates; curr != NULL; curr = curr->next) { if (!strcmp(curr->path, path)) { return curr; } } return NULL; } static file_state_t *createFileState(const char *path) { file_state_t *state = NULL; state = calloc(1, sizeof(*state)); if (state == NULL) { return NULL; } state->path = strdup(path); if (state->path == NULL) { free(state); return NULL; } state->offset = 0; state->inode = 0; state->seen = 1; state->partial.stream_type = dst_invalid; if (!populatePathMeta(path, &state->meta)) { LogError(0, RS_RET_ERR, "imkubernetes: could not parse kubernetes metadata from path '%s'", path); STATSCOUNTER_INC(ctrParseErrors, mutCtrParseErrors); } state->next = g_fileStates; g_fileStates = state; STATSCOUNTER_INC(ctrFilesDiscovered, mutCtrFilesDiscovered); return state; } static void markAllFileStatesUnseen(void) { file_state_t *curr; for (curr = g_fileStates; curr != NULL; curr = curr->next) { curr->seen = 0; } } static void sweepFileStates(void) { file_state_t **cursor = &g_fileStates; while (*cursor != NULL) { file_state_t *curr = *cursor; if (curr->seen) { cursor = &curr->next; continue; } *cursor = curr->next; free(curr->path); freePathMeta(&curr->meta); freePartialMsg(&curr->partial); free(curr); } } static pod_cache_entry_t *findPodCacheEntry(const char *key, time_t now) { pod_cache_entry_t **cursor = &g_podCache; while (*cursor != NULL) { pod_cache_entry_t *curr = *cursor; if (curr->expires_at <= now) { *cursor = curr->next; free(curr->key); if (curr->json != NULL) { json_object_put(curr->json); } free(curr); continue; } if (!strcmp(curr->key, key)) { return curr; } cursor = &curr->next; } return NULL; } static rsRetVal setPodCacheEntry(const char *key, struct json_object *json, time_t now) { DEFiRet; pod_cache_entry_t *entry = NULL; assert(key != NULL); assert(json != NULL); if ((entry = findPodCacheEntry(key, now)) != NULL) { if (entry->json != NULL) { json_object_put(entry->json); } entry->json = json; entry->expires_at = now + runModConf->cacheEntryTtl; entry = NULL; FINALIZE; } CHKmalloc(entry = calloc(1, sizeof(*entry))); CHKmalloc(entry->key = strdup(key)); entry->json = json; entry->expires_at = now + runModConf->cacheEntryTtl; entry->next = g_podCache; g_podCache = entry; entry = NULL; finalize_it: if (entry != NULL) { free(entry->key); free(entry); } RETiRet; } static size_t apiCurlCB(void *data, size_t size, size_t nmemb, void *buffer) { curl_buf_t *buf = (curl_buf_t *)buffer; size_t realsize = size * nmemb; size_t needed = buf->len + realsize + 1; char *newbuf; if (needed > buf->cap) { size_t newcap = buf->cap == 0 ? 1024 : buf->cap; while (newcap < needed) { newcap *= 2; } newbuf = realloc(buf->data, newcap); if (newbuf == NULL) { return 0; } buf->data = newbuf; buf->cap = newcap; } memcpy(buf->data + buf->len, data, realsize); buf->len += realsize; buf->data[buf->len] = '\0'; return realsize; } static char *readFileTrimmed(const char *path) { FILE *fp = NULL; char *line = NULL; size_t cap = 0; ssize_t len; fp = fopen(path, "r"); if (fp == NULL) { return NULL; } len = getline(&line, &cap, fp); fclose(fp); if (len < 0) { free(line); return NULL; } while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r')) { line[--len] = '\0'; } return line; } static void copyJsonField(struct json_object *dst, struct json_object *src, const char *field) { struct json_object *value = NULL; if (dst == NULL || src == NULL || !json_object_is_type(src, json_type_object)) { return; } if (json_object_object_get_ex(src, field, &value)) { json_object_object_add(dst, (char *)field, json_object_get(value)); } } static rsRetVal initApiClient(void) { DEFiRet; CURLcode ccode; char *token = NULL; char authHeader[4096]; int authLen; if (!runModConf->enrichKubernetes) { FINALIZE; } if ((ccode = curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) { LogError(0, RS_RET_ERR, "imkubernetes: curl_global_init failed: %s", curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } if (runModConf->token != NULL) { token = strdup((char *)runModConf->token); } else if (runModConf->tokenFile != NULL) { token = readFileTrimmed((char *)runModConf->tokenFile); } g_apiCurl = curl_easy_init(); if (g_apiCurl == NULL) { LogError(0, RS_RET_ERR, "imkubernetes: curl_easy_init failed"); ABORT_FINALIZE(RS_RET_ERR); } if (token != NULL && token[0] != '\0') { authLen = snprintf(authHeader, sizeof(authHeader), "Authorization: Bearer %s", token); if (authLen < 0 || (size_t)authLen >= sizeof(authHeader)) { LogError(0, RS_RET_ERR, "imkubernetes: bearer token is too long for Authorization header"); ABORT_FINALIZE(RS_RET_ERR); } authHeader[sizeof(authHeader) - 1] = '\0'; g_apiHdr = curl_slist_append(g_apiHdr, authHeader); } curl_easy_setopt(g_apiCurl, CURLOPT_HTTPHEADER, g_apiHdr); curl_easy_setopt(g_apiCurl, CURLOPT_WRITEFUNCTION, apiCurlCB); curl_easy_setopt(g_apiCurl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(g_apiCurl, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(g_apiCurl, CURLOPT_USERAGENT, "rsyslog/imkubernetes"); if (runModConf->caCertFile != NULL) { curl_easy_setopt(g_apiCurl, CURLOPT_CAINFO, runModConf->caCertFile); } if (runModConf->allowUnsignedCerts) { curl_easy_setopt(g_apiCurl, CURLOPT_SSL_VERIFYPEER, 0L); } if (runModConf->skipVerifyHost) { curl_easy_setopt(g_apiCurl, CURLOPT_SSL_VERIFYHOST, 0L); } finalize_it: free(token); RETiRet; } static void freeApiClient(void) { if (g_apiCurl != NULL) { curl_easy_cleanup(g_apiCurl); g_apiCurl = NULL; } if (g_apiHdr != NULL) { curl_slist_free_all(g_apiHdr); g_apiHdr = NULL; } if (runModConf != NULL && runModConf->enrichKubernetes) { curl_global_cleanup(); } } static rsRetVal queryPodMetadata(const path_meta_t *meta, struct json_object **result) { DEFiRet; char *url = NULL; curl_buf_t buf = {0}; CURLcode ccode; long respCode = 0; struct json_object *reply = NULL; struct json_object *metadata = NULL; struct json_object *status = NULL; struct json_object *ownerRefs = NULL; struct json_object *ownerRef = NULL; struct json_object *out = NULL; struct json_object *value = NULL; assert(result != NULL); *result = NULL; if (g_apiCurl == NULL || meta == NULL || meta->namespace_name == NULL || meta->pod_name == NULL) { FINALIZE; } if (asprintf(&url, "%s/api/v1/namespaces/%s/pods/%s", (char *)runModConf->kubernetesUrl, meta->namespace_name, meta->pod_name) == -1) { url = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } curl_easy_setopt(g_apiCurl, CURLOPT_URL, url); curl_easy_setopt(g_apiCurl, CURLOPT_WRITEDATA, &buf); ccode = curl_easy_perform(g_apiCurl); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imkubernetes: kubernetes API request failed for '%s': %s", url, curl_easy_strerror(ccode)); STATSCOUNTER_INC(ctrApiErrors, mutCtrApiErrors); ABORT_FINALIZE(RS_RET_ERR); } ccode = curl_easy_getinfo(g_apiCurl, CURLINFO_RESPONSE_CODE, &respCode); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imkubernetes: curl_easy_getinfo failed for '%s': %s", url, curl_easy_strerror(ccode)); STATSCOUNTER_INC(ctrApiErrors, mutCtrApiErrors); ABORT_FINALIZE(RS_RET_ERR); } if (respCode == 404) { ABORT_FINALIZE(RS_RET_NOT_FOUND); } if (respCode != 200) { LogError(0, RS_RET_ERR, "imkubernetes: kubernetes API returned %ld for '%s'", respCode, url); STATSCOUNTER_INC(ctrApiErrors, mutCtrApiErrors); ABORT_FINALIZE(RS_RET_ERR); } reply = json_tokener_parse(buf.data != NULL ? buf.data : "{}"); if (reply == NULL) { STATSCOUNTER_INC(ctrApiErrors, mutCtrApiErrors); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } if (!json_object_is_type(reply, json_type_object)) { STATSCOUNTER_INC(ctrApiErrors, mutCtrApiErrors); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } CHKmalloc(out = json_object_new_object()); if (json_object_object_get_ex(reply, "metadata", &metadata)) { copyJsonField(out, metadata, "uid"); if (json_object_object_get_ex(metadata, "uid", &value)) { json_object_object_del(out, "uid"); json_object_object_add(out, "pod_id", json_object_get(value)); } copyJsonField(out, metadata, "creationTimestamp"); if (json_object_object_get_ex(metadata, "creationTimestamp", &value)) { json_object_object_del(out, "creationTimestamp"); json_object_object_add(out, "creation_timestamp", json_object_get(value)); } copyJsonField(out, metadata, "labels"); copyJsonField(out, metadata, "annotations"); if (json_object_object_get_ex(metadata, "ownerReferences", &ownerRefs) && json_object_is_type(ownerRefs, json_type_array) && json_object_array_length(ownerRefs) > 0) { ownerRef = json_object_array_get_idx(ownerRefs, 0); copyJsonField(out, ownerRef, "kind"); if (json_object_object_get_ex(ownerRef, "kind", &value)) { json_object_object_del(out, "kind"); json_object_object_add(out, "owner_kind", json_object_get(value)); } copyJsonField(out, ownerRef, "name"); if (json_object_object_get_ex(ownerRef, "name", &value)) { json_object_object_del(out, "name"); json_object_object_add(out, "owner_name", json_object_get(value)); } } } if (json_object_object_get_ex(reply, "status", &status)) { copyJsonField(out, status, "podIP"); if (json_object_object_get_ex(status, "podIP", &value)) { json_object_object_del(out, "podIP"); json_object_object_add(out, "pod_ip", json_object_get(value)); } copyJsonField(out, status, "hostIP"); if (json_object_object_get_ex(status, "hostIP", &value)) { json_object_object_del(out, "hostIP"); json_object_object_add(out, "host_ip", json_object_get(value)); } } if (json_object_object_get_ex(reply, "spec", &status)) { if (json_object_object_get_ex(status, "nodeName", &value)) { json_object_object_add(out, "host", json_object_get(value)); } } json_object_object_add(out, "master_url", json_object_new_string((char *)runModConf->kubernetesUrl)); *result = out; out = NULL; finalize_it: free(url); free(buf.data); if (reply != NULL) { json_object_put(reply); } if (out != NULL) { json_object_put(out); } RETiRet; } static struct json_object *getPodMetadataForState(const path_meta_t *meta) { char *key = NULL; time_t now; struct json_object *cached = NULL; struct json_object *fresh = NULL; pod_cache_entry_t *entry = NULL; rsRetVal iRet; if (!runModConf->enrichKubernetes || meta == NULL || meta->namespace_name == NULL || meta->pod_name == NULL) { return NULL; } datetime.GetTime(&now); if (asprintf(&key, "%s/%s", meta->namespace_name, meta->pod_name) == -1) { key = NULL; return NULL; } entry = findPodCacheEntry(key, now); if (entry != NULL) { cached = entry->json; STATSCOUNTER_INC(ctrCacheHits, mutCtrCacheHits); free(key); return cached; } STATSCOUNTER_INC(ctrCacheMisses, mutCtrCacheMisses); iRet = queryPodMetadata(meta, &fresh); if (iRet == RS_RET_OK && fresh != NULL) { if (setPodCacheEntry(key, fresh, now) == RS_RET_OK) { free(key); return fresh; } json_object_put(fresh); } free(key); return NULL; } static rsRetVal addRuntimeMetadata(smsg_t *pMsg, const file_state_t *state, const parsed_record_t *record) { struct json_object *k8s = NULL; struct json_object *docker = NULL; struct json_object *podMd = NULL; struct json_object *value = NULL; DEFiRet; assert(pMsg != NULL); assert(state != NULL); assert(record != NULL); CHKmalloc(k8s = json_object_new_object()); if (state->meta.namespace_name != NULL) { json_object_object_add(k8s, "namespace_name", json_object_new_string(state->meta.namespace_name)); } if (state->meta.pod_name != NULL) { json_object_object_add(k8s, "pod_name", json_object_new_string(state->meta.pod_name)); } if (state->meta.pod_uid != NULL) { json_object_object_add(k8s, "pod_uid", json_object_new_string(state->meta.pod_uid)); } if (state->meta.container_name != NULL) { json_object_object_add(k8s, "container_name", json_object_new_string(state->meta.container_name)); } if (state->meta.restart_count >= 0) { json_object_object_add(k8s, "restart_count", json_object_new_int(state->meta.restart_count)); } json_object_object_add(k8s, "log_file", json_object_new_string(state->path)); json_object_object_add(k8s, "stream", json_object_new_string(record->stream_type == dst_stderr ? "stderr" : "stdout")); json_object_object_add(k8s, "log_format", json_object_new_string(record->format_name)); if (record->parse_error) { json_object_object_add(k8s, "parse_error", json_object_new_boolean(1)); } podMd = getPodMetadataForState(&state->meta); if (podMd != NULL) { copyJsonField(k8s, podMd, "pod_id"); copyJsonField(k8s, podMd, "creation_timestamp"); copyJsonField(k8s, podMd, "labels"); copyJsonField(k8s, podMd, "annotations"); copyJsonField(k8s, podMd, "owner_kind"); copyJsonField(k8s, podMd, "owner_name"); copyJsonField(k8s, podMd, "pod_ip"); copyJsonField(k8s, podMd, "host_ip"); copyJsonField(k8s, podMd, "master_url"); if (json_object_object_get_ex(podMd, "host", &value)) { json_object_object_add(k8s, "host", json_object_get(value)); } } CHKmalloc(docker = json_object_new_object()); if (state->meta.container_id != NULL) { json_object_object_add(docker, "container_id", json_object_new_string(state->meta.container_id)); } iRet = msgAddJSON(pMsg, (uchar *)"!kubernetes", k8s, 0, 0); k8s = NULL; CHKiRet(iRet); iRet = msgAddJSON(pMsg, (uchar *)"!docker", docker, 0, 0); docker = NULL; CHKiRet(iRet); finalize_it: if (k8s != NULL) { json_object_put(k8s); } if (docker != NULL) { json_object_put(docker); } RETiRet; } static rsRetVal enqMsg(const file_state_t *state, const parsed_record_t *record) { smsg_t *pMsg = NULL; DEFiRet; if (record == NULL || record->msg == NULL) { FINALIZE; } if (record->hasTime) { CHKiRet(msgConstructWithTime(&pMsg, &record->st, record->ttGenTime)); } else { CHKiRet(msgConstruct(&pMsg)); } MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (const char *)record->msg, record->len); if (runModConf->bEscapeLf) { parser.SanitizeMsg(pMsg); } else { if (pMsg->iLenRawMsg > 0 && pMsg->pszRawMsg[pMsg->iLenRawMsg - 1] == '\0') { pMsg->iLenRawMsg--; } } MsgSetMSGoffs(pMsg, 0); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP()); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, UCHAR_CONSTANT("kubernetes:"), sizeof("kubernetes:") - 1); MsgSetRuleset(pMsg, runModConf->pBindRuleset); pMsg->iFacility = runModConf->iDfltFacility; pMsg->iSeverity = (record->stream_type == dst_stderr) ? LOG_ERR : runModConf->iDfltSeverity; CHKiRet(addRuntimeMetadata(pMsg, state, record)); CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg)); STATSCOUNTER_INC(ctrSubmitted, mutCtrSubmitted); finalize_it: if (iRet == RS_RET_DISCARDMSG) { STATSCOUNTER_INC(ctrLostRatelimit, mutCtrLostRatelimit); } RETiRet; } /* * CRI P fragments are accumulated until their closing F record, so they need * their own memory guard. In truncate mode the guard is maxMessageSize. Other * oversize input modes are honored by letting the completed logical record * reach the core submit path, but still capping the accumulator at a * maxMessageSize-derived hard limit so an unfinished run cannot grow forever. * Once capped, consume later fragments until the closing F flushes state; the * closing fragment must never be emitted as a standalone record. */ static rsRetVal emitPartialIfComplete(file_state_t *state, const parsed_record_t *record) { parsed_record_t finalRecord = {0}; DEFiRet; if (!record->is_partial && !partialIsActive(&state->partial)) { CHKiRet(enqMsg(state, record)); FINALIZE; } if (record->is_partial && !partialIsActive(&state->partial)) { partialInitFromRecord(&state->partial, record); } if (partialIsActive(&state->partial) && state->partial.stream_type != record->stream_type) { freePartialMsg(&state->partial); if (record->is_partial) { partialInitFromRecord(&state->partial, record); } } if (record->is_partial) { CHKiRet(partialAppendBounded(&state->partial, record->msg, record->len)); FINALIZE; } if (partialIsActive(&state->partial)) { CHKiRet(partialAppendBounded(&state->partial, record->msg, record->len)); finalRecord.msg = state->partial.data; finalRecord.len = state->partial.len; finalRecord.stream_type = state->partial.stream_type; finalRecord.hasTime = state->partial.hasTime; finalRecord.ttGenTime = state->partial.ttGenTime; finalRecord.format_name = record->format_name; finalRecord.parse_error = record->parse_error; if (finalRecord.hasTime) { memcpy(&finalRecord.st, &state->partial.st, sizeof(finalRecord.st)); } CHKiRet(enqMsg(state, &finalRecord)); freePartialMsg(&state->partial); FINALIZE; } CHKiRet(enqMsg(state, record)); finalize_it: RETiRet; } static sbool parseCriLine(const char *line, size_t len, parsed_record_t *record) { const char *sp1; const char *sp2; const char *sp3; sp1 = memchr(line, ' ', len); if (sp1 == NULL) { return 0; } sp2 = memchr(sp1 + 1, ' ', len - (size_t)(sp1 + 1 - line)); if (sp2 == NULL) { return 0; } sp3 = memchr(sp2 + 1, ' ', len - (size_t)(sp2 + 1 - line)); if (sp3 == NULL || sp3 <= sp2 + 1) { return 0; } if ((size_t)(sp2 - (sp1 + 1)) != 6) { return 0; } if (memcmp(sp1 + 1, "stdout", 6) && memcmp(sp1 + 1, "stderr", 6)) { return 0; } record->stream_type = !memcmp(sp1 + 1, "stderr", 6) ? dst_stderr : dst_stdout; record->is_partial = (*(sp2 + 1) == 'P'); record->msg = (const uchar *)(sp3 + 1); record->len = len - (size_t)(sp3 + 1 - line); record->format_name = "cri"; parseTimestamp3339(line, (size_t)(sp1 - line), &record->st, &record->ttGenTime, &record->hasTime); return 1; } static sbool parseDockerJsonLine(const char *line, size_t len, parsed_record_t *record) { struct json_object *json = NULL; struct json_object *logObj = NULL; struct json_object *streamObj = NULL; struct json_object *timeObj = NULL; const char *msg = NULL; size_t msgLen = 0; (void)len; json = json_tokener_parse(line); if (json == NULL) { return 0; } if (!json_object_is_type(json, json_type_object)) { json_object_put(json); return 0; } if (!json_object_object_get_ex(json, "log", &logObj) || !json_object_is_type(logObj, json_type_string)) { json_object_put(json); return 0; } msg = json_object_get_string(logObj); msgLen = strlen(msg); if (msgLen > 0 && msg[msgLen - 1] == '\n') { --msgLen; } record->owned_msg = (uchar *)dupRange(msg, msgLen); if (record->owned_msg == NULL) { json_object_put(json); return 0; } record->msg = record->owned_msg; record->len = msgLen; record->stream_type = dst_stdout; record->hasTime = 0; record->is_partial = 0; record->format_name = "docker_json"; if (json_object_object_get_ex(json, "stream", &streamObj) && json_object_is_type(streamObj, json_type_string)) { const char *stream = json_object_get_string(streamObj); if (stream != NULL && !strcmp(stream, "stderr")) { record->stream_type = dst_stderr; } } if (json_object_object_get_ex(json, "time", &timeObj) && json_object_is_type(timeObj, json_type_string)) { const char *timeStr = json_object_get_string(timeObj); if (timeStr != NULL) { parseTimestamp3339(timeStr, strlen(timeStr), &record->st, &record->ttGenTime, &record->hasTime); } } json_object_put(json); return 1; } static rsRetVal processLine(file_state_t *state, const char *line, size_t len) { parsed_record_t record = {0}; DEFiRet; trimTrailingNewline(line, &len); if (len == 0) { FINALIZE; } if (parseCriLine(line, len, &record)) { STATSCOUNTER_INC(ctrCriRecords, mutCtrCriRecords); CHKiRet(emitPartialIfComplete(state, &record)); FINALIZE; } if (parseDockerJsonLine(line, len, &record)) { STATSCOUNTER_INC(ctrDockerJsonRecords, mutCtrDockerJsonRecords); CHKiRet(emitPartialIfComplete(state, &record)); FINALIZE; } record.msg = (const uchar *)line; record.len = len; record.stream_type = dst_stdout; record.hasTime = 0; record.is_partial = 0; record.format_name = "raw"; record.parse_error = 1; STATSCOUNTER_INC(ctrParseErrors, mutCtrParseErrors); CHKiRet(emitPartialIfComplete(state, &record)); finalize_it: free(record.owned_msg); RETiRet; } static rsRetVal processFileState(file_state_t *state) { DEFiRet; FILE *fp = NULL; ssize_t readLen; struct stat st; off_t pos; assert(state != NULL); if (stat(state->path, &st) != 0) { FINALIZE; } if (state->inode != 0 && (state->inode != st.st_ino || st.st_size < state->offset)) { state->offset = 0; freePartialMsg(&state->partial); } state->inode = st.st_ino; if (state->offset == 0 && runModConf->freshStartTail && st.st_size > 0) { state->offset = st.st_size; FINALIZE; } if (st.st_size <= state->offset) { FINALIZE; } fp = fopen(state->path, "r"); if (fp == NULL) { ABORT_FINALIZE(RS_RET_NO_FILE_ACCESS); } if (fseeko(fp, state->offset, SEEK_SET) != 0) { ABORT_FINALIZE(RS_RET_ERR); } while ((readLen = getline(&gLineBuf, &gLineBufCap, fp)) >= 0) { CHKiRet(processLine(state, gLineBuf, (size_t)readLen)); } if (ferror(fp)) { ABORT_FINALIZE(RS_RET_ERR); } pos = ftello(fp); if (pos == (off_t)-1) { ABORT_FINALIZE(RS_RET_ERR); } state->offset = pos; finalize_it: if (fp != NULL) { fclose(fp); } RETiRet; } static rsRetVal scanAndProcessFiles(void) { DEFiRet; glob_t matches; int gret; size_t i; memset(&matches, 0, sizeof(matches)); markAllFileStatesUnseen(); gret = glob((char *)runModConf->logFileGlob, 0, NULL, &matches); if (gret != 0 && gret != GLOB_NOMATCH) { ABORT_FINALIZE(RS_RET_ERR); } for (i = 0; i < matches.gl_pathc; ++i) { file_state_t *state = findFileState(matches.gl_pathv[i]); if (state == NULL) { state = createFileState(matches.gl_pathv[i]); if (state == NULL) { continue; } } state->seen = 1; processFileState(state); } sweepFileStates(); finalize_it: globfree(&matches); RETiRet; } static rsRetVal applyConfigParams(struct nvlst *lst, struct cnfparamblk *paramblk, const char *context) { struct cnfparamvals *pvals = NULL; int i; DEFiRet; pvals = nvlstGetParams(lst, paramblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imkubernetes: error processing %s config parameters", context); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("%s param blk for imkubernetes:\n", context); cnfparamsPrint(paramblk, pvals); } for (i = 0; i < paramblk->nParams; ++i) { if (!pvals[i].bUsed) { continue; } else if (!strcmp(paramblk->descr[i].name, "logfileglob")) { free(loadModConf->logFileGlob); CHKmalloc(loadModConf->logFileGlob = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(paramblk->descr[i].name, "pollinginterval")) { loadModConf->iPollInterval = (int)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "cacheentryttl")) { loadModConf->cacheEntryTtl = (int)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "freshstarttail")) { loadModConf->freshStartTail = (sbool)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "defaultseverity")) { loadModConf->iDfltSeverity = (int)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "defaultfacility")) { loadModConf->iDfltFacility = (int)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "escapelf")) { loadModConf->bEscapeLf = (sbool)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "enrichkubernetes")) { loadModConf->enrichKubernetes = (sbool)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "kubernetesurl")) { free(loadModConf->kubernetesUrl); CHKmalloc(loadModConf->kubernetesUrl = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(paramblk->descr[i].name, "token")) { free(loadModConf->token); CHKmalloc(loadModConf->token = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(paramblk->descr[i].name, "tokenfile")) { free(loadModConf->tokenFile); CHKmalloc(loadModConf->tokenFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(paramblk->descr[i].name, "tls.cacert")) { free(loadModConf->caCertFile); CHKmalloc(loadModConf->caCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(paramblk->descr[i].name, "allowunsignedcerts")) { loadModConf->allowUnsignedCerts = (sbool)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "skipverifyhost")) { loadModConf->skipVerifyHost = (sbool)pvals[i].val.d.n; } else if (!strcmp(paramblk->descr[i].name, "ruleset")) { free(loadModConf->pszBindRuleset); CHKmalloc(loadModConf->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } } finalize_it: if (pvals != NULL) { cnfparamvalsDestruct(pvals, paramblk); } RETiRet; } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; pModConf->logFileGlob = NULL; pModConf->iPollInterval = DFLT_pollingInterval; pModConf->cacheEntryTtl = DFLT_cacheEntryTtl; pModConf->iDfltSeverity = DFLT_SEVERITY; pModConf->iDfltFacility = DFLT_FACILITY; pModConf->bEscapeLf = DFLT_bEscapeLF; pModConf->freshStartTail = DFLT_freshStartTail; pModConf->enrichKubernetes = DFLT_enrichKubernetes; pModConf->kubernetesUrl = NULL; pModConf->token = NULL; pModConf->tokenFile = NULL; pModConf->caCertFile = NULL; pModConf->allowUnsignedCerts = 0; pModConf->skipVerifyHost = 0; pModConf->pszBindRuleset = NULL; pModConf->pBindRuleset = NULL; bLegacyCnfModGlobalsPermitted = 1; ENDbeginCnfLoad BEGINsetModCnf CODESTARTsetModCnf; CHKiRet(applyConfigParams(lst, &modpblk, "module")); bLegacyCnfModGlobalsPermitted = 0; finalize_it: ENDsetModCnf BEGINnewInpInst CODESTARTnewInpInst; CHKiRet(applyConfigParams(lst, &inppblk, "input")); finalize_it: CODE_STD_FINALIZERnewInpInst ENDnewInpInst BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf ruleset_t *pRuleset = NULL; rsRetVal localRet; CODESTARTcheckCnf; if (loadModConf->iPollInterval <= 0) { LogError(0, RS_RET_CONFIG_ERROR, "imkubernetes: PollingInterval must be greater than zero"); iRet = RS_RET_CONFIG_ERROR; } loadModConf->pBindRuleset = NULL; if (loadModConf->pszBindRuleset != NULL) { localRet = ruleset.GetRuleset(loadModConf->pConf, &pRuleset, loadModConf->pszBindRuleset); if (localRet == RS_RET_NOT_FOUND) { LogError(0, NO_ERRCODE, "imkubernetes: ruleset '%s' not found - using default ruleset instead", loadModConf->pszBindRuleset); FINALIZE; } CHKiRet(localRet); loadModConf->pBindRuleset = pRuleset; } finalize_it: ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; if (loadModConf->logFileGlob == NULL) { CHKmalloc(loadModConf->logFileGlob = (uchar *)strdup(DFLT_LOG_FILE_GLOB)); } if (loadModConf->kubernetesUrl == NULL) { CHKmalloc(loadModConf->kubernetesUrl = (uchar *)strdup(DFLT_KUBERNETES_URL)); } if (loadModConf->tokenFile == NULL) { CHKmalloc(loadModConf->tokenFile = (uchar *)strdup(DFLT_TOKEN_FILE)); } if (loadModConf->caCertFile == NULL) { CHKmalloc(loadModConf->caCertFile = (uchar *)strdup(DFLT_CA_CERT_FILE)); } runModConf = loadModConf; CHKiRet(statsobj.Construct(&modStats)); CHKiRet(statsobj.SetName(modStats, UCHAR_CONSTANT("imkubernetes"))); CHKiRet(statsobj.SetOrigin(modStats, UCHAR_CONSTANT("imkubernetes"))); STATSCOUNTER_INIT(ctrSubmitted, mutCtrSubmitted); STATSCOUNTER_INIT(ctrParseErrors, mutCtrParseErrors); STATSCOUNTER_INIT(ctrFilesDiscovered, mutCtrFilesDiscovered); STATSCOUNTER_INIT(ctrCriRecords, mutCtrCriRecords); STATSCOUNTER_INIT(ctrDockerJsonRecords, mutCtrDockerJsonRecords); STATSCOUNTER_INIT(ctrCacheHits, mutCtrCacheHits); STATSCOUNTER_INIT(ctrCacheMisses, mutCtrCacheMisses); STATSCOUNTER_INIT(ctrApiErrors, mutCtrApiErrors); STATSCOUNTER_INIT(ctrLostRatelimit, mutCtrLostRatelimit); CHKiRet( statsobj.AddCounter(modStats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrSubmitted)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("parse.errors"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrParseErrors)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("files.discovered"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrFilesDiscovered)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("records.cri"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCriRecords)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("records.dockerjson"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrDockerJsonRecords)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("kube.cache_hits"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCacheHits)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("kube.cache_misses"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCacheMisses)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("kube.api_errors"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrApiErrors)); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("ratelimit.discarded"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrLostRatelimit)); CHKiRet(statsobj.ConstructFinalize(modStats)); finalize_it: ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(loadModConf->logFileGlob); free(loadModConf->kubernetesUrl); free(loadModConf->token); free(loadModConf->tokenFile); free(loadModConf->caCertFile); free(loadModConf->pszBindRuleset); if (modStats != NULL) { statsobj.Destruct(&modStats); modStats = NULL; } ENDfreeCnf BEGINrunInput CODESTARTrunInput; CHKiRet(ratelimitNew(&ratelimiter, "imkubernetes", NULL)); CHKiRet(initApiClient()); while (glbl.GetGlobalInputTermState() == 0) { scanAndProcessFiles(); srSleep(runModConf->iPollInterval, 0); } finalize_it: freeApiClient(); freePodCache(); freeFileStates(); free(gLineBuf); gLineBuf = NULL; gLineBufCap = 0; if (ratelimiter != NULL) { ratelimitDestruct(ratelimiter); ratelimiter = NULL; } ENDrunInput BEGINwillRun CODESTARTwillRun; ENDwillRun BEGINafterRun CODESTARTafterRun; ENDafterRun BEGINmodExit CODESTARTmodExit; if (pInputName != NULL) { prop.Destruct(&pInputName); } objRelease(parser, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) { iRet = RS_RET_OK; } ENDisCompatibleWithFeature BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imkubernetes"), sizeof("imkubernetes") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); ENDmodInit rsyslog-8.2608.0/contrib/imkubernetes/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020743 xustar0030 mtime=1787067504.672323521 30 atime=1787067579.647721922 30 ctime=1787067799.078812341 rsyslog-8.2608.0/contrib/imkubernetes/Makefile.in0000664000175000017500000006637715241076160020432 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imkubernetes ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = imkubernetes_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_imkubernetes_la_OBJECTS = imkubernetes_la-imkubernetes.lo imkubernetes_la_OBJECTS = $(am_imkubernetes_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 = imkubernetes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(imkubernetes_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imkubernetes_la-imkubernetes.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imkubernetes_la_SOURCES) DIST_SOURCES = $(imkubernetes_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imkubernetes.la imkubernetes_la_SOURCES = imkubernetes.c imkubernetes_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) imkubernetes_la_LDFLAGS = -module -avoid-version imkubernetes_la_LIBADD = $(CURL_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imkubernetes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imkubernetes/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imkubernetes.la: $(imkubernetes_la_OBJECTS) $(imkubernetes_la_DEPENDENCIES) $(EXTRA_imkubernetes_la_DEPENDENCIES) $(AM_V_CCLD)$(imkubernetes_la_LINK) -rpath $(pkglibdir) $(imkubernetes_la_OBJECTS) $(imkubernetes_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkubernetes_la-imkubernetes.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imkubernetes_la-imkubernetes.lo: imkubernetes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkubernetes_la-imkubernetes.lo -MD -MP -MF $(DEPDIR)/imkubernetes_la-imkubernetes.Tpo -c -o imkubernetes_la-imkubernetes.lo `test -f 'imkubernetes.c' || echo '$(srcdir)/'`imkubernetes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkubernetes_la-imkubernetes.Tpo $(DEPDIR)/imkubernetes_la-imkubernetes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imkubernetes.c' object='imkubernetes_la-imkubernetes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkubernetes_la-imkubernetes.lo `test -f 'imkubernetes.c' || echo '$(srcdir)/'`imkubernetes.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imkubernetes_la-imkubernetes.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imkubernetes_la-imkubernetes.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omamqp10000644000000000000000000000013215241076632015503 xustar0030 mtime=1787067802.462875392 30 atime=1787067808.785993219 30 ctime=1787067802.462875392 rsyslog-8.2608.0/contrib/omamqp1/0000775000175000017500000000000015241076632015224 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omamqp1/PaxHeaders/Makefile.am0000644000000000000000000000013215132411300017574 xustar0030 mtime=1768559296.139883631 30 atime=1787067434.246009514 30 ctime=1787067802.453875225 rsyslog-8.2608.0/contrib/omamqp1/Makefile.am0000666000175000017500000000110715132411300017241 0ustar00rgerrgerpkglib_LTLIBRARIES = omamqp1.la omamqp1_la_SOURCES = omamqp1.c if ENABLE_QPIDPROTON_STATIC omamqp1_la_LDFLAGS = -module -avoid-version -Wl,-whole-archive -l:libqpid-proton-proactor-static.a -l:libqpid-proton-core-static.a -Wl,--no-whole-archive $(PTHREADS_LIBS) $(OPENSSL_LIBS) ${RT_LIBS} -lsasl2 omamqp1_la_LIBADD = else omamqp1_la_LDFLAGS = -module -avoid-version $(PROTON_PROACTOR_LIBS) $(PTHREADS_LIBS) $(OPENSSL_LIBS) -lm omamqp1_la_LIBADD = endif omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(PROTON_PROACTOR_CFLAGS) -Wno-error=switch EXTRA_DIST = rsyslog-8.2608.0/contrib/omamqp1/PaxHeaders/README.md0000644000000000000000000000013215035412264017033 xustar0030 mtime=1752569012.329251042 30 atime=1782715518.795788959 30 ctime=1787067802.459875337 rsyslog-8.2608.0/contrib/omamqp1/README.md0000666000175000017500000002552215035412264016507 0ustar00rgerrger# AMQP 1.0 Output Module # The omamqp1 output module can be used to send log messages via an AMQP 1.0-compatible messaging bus. This module requires the Apache QPID Proton python library, version 0.10+. This should be installed on the system that is running rsyslogd. ## Message Format ## Messages sent from this module to the message bus contain a list of strings. Each string is a separate log message. The list is ordered such that the oldest log appears at the front of the list, whilst the most recent log is at the end of the list. ## Configuration ## This module is configured via the rsyslog.conf configuration file. To use this module it must first be imported. Example: module(load="omamqp1") Actions can then be created using this module. Example: action(type="omamqp1" host="localhost:5672" target="amq.topic") The following parameters are recognized by the module: * host - The address of the message bus. Optionally a port can be included, separated by a ':'. Example: "localhost:5672" * target - The destination for the generated messages. This can be the name of a queue or topic. On some messages buses it may be necessary to create this target manually. Example: "amq.topic" * username - Optional. Used by SASL to authenticate with the message bus. * password - Optional. Used by SASL to authenticate with the message bus. * template - Template to use to format the record. Defaults to `RSYSLOG_FileFormat` * idleTimeout - The idle timeout in seconds. This enables connection heartbeats and is used to detect a failed connection to the message bus. Set to zero to disable. * maxResend - number of times an undeliverable message is re-sent to the message bus before it is dropped. This is unrelated to rsyslog's action.resumeRetryCount. Once the connection to the message bus is active this module is ready to receive log messages from rsyslog (i.e. the module has 'resumed'). Even though the connection is active, any particular message may be rejected by the message bus (e.g. 'unrouteable'). The module will retry (e.g. 'suspend') for up to maxResend attempts before discarding the message as undeliverable. Setting this to zero disables the limit and unrouteable messages will be retried as long as the connection stays up. You probably do not want that to happen. The default is 10. * reconnectDelay - The time in seconds this module will delay before attempting to re-established a failed connection (default 5 seconds). * disableSASL - Setting this to a non-zero value will disable SASL negotiation. Only necessary if the message bus does not offer SASL. ## Dependencies ## The package is dependent on the QPID Proton AMQP 1.0 library. To build this package you must also have the QPID Proton C headers installed. Pre-built packages are available for Fedora 22+ via the base Fedora repos. Packages for RHEL/Centos based systems can be obtained via [EPEL](https://fedoraproject.org/wiki/EPEL). In order to build the module, install the _qpid-proton-c-devel_ package. Pre-built packages from most Ubuntu/Debian systems are available via the [QPID project's PPA on Launchpad](https://launchpad.net/~qpid). For example, to install the latest version of the Proton packages (as of this writing): $ sudo add-apt-repository ppa:qpid/released $ sudo apt-get update $ sudo apt-get install libqpid-proton3 libqpid-proton3-dev Check your distribution for the availability of Proton packages. Alternatively, you can pull down the Proton code from the [project website](http://qpid.apache.org/) and build it yourself. ## Debugging ## Debug logging can be enabled using the environment variables `RSYSLOG_DEBUG` and `RSYSLOG_DEBUGLOG`, export RSYSLOG_DEBUG=debug export RSYSLOG_DEBUGLOG=/tmp/rsyslog.debug.log or with the old-style rsyslog debug configuration settings. For example: $DebugFile /tmp/omamqp1-debug.txt $DebugLevel 2 There are a number of tracepoints within the omamqp1.c code. ---- ## Notes on use with the QPID C++ broker (qpidd) ## _Note well: These notes assume use of version 0.34 of the QPID C++ broker. Previous versions may not be fully compatible_ To use the Apache QPID C++ broker _qpidd_ as the message bus, a version of qpidd that supports the AMQP 1.0 protocol must be used. Since qpidd can be packaged without AMQP 1.0 support you should verify AMQP 1.0 has been enabled by checking for AMQP 1.0 related options in the qpidd help text. For example: qpidd --help ... AMQP 1.0 Options: --domain DOMAIN Domain of this broker --queue-patterns PATTERN Pattern for on-demand queues --topic-patterns PATTERN Pattern for on-demand topics If no AMQP 1.0 related options appear in the help output, then AMQP 1.0 has not been included with your qpidd. The destination for message (target) must be created before log messages arrive. This can be done using the qpid-config tool. Example: qpid-config add queue rsyslogd Alternatively, the target can be created on demand by configuring a queue-pattern (or topic-pattern) that matches the target. To do this, add a _queue-patterns_ (or _topic_patterns_) directive to the qpidd configuration file /etc/qpid/qpidd.conf. For example, to have qpidd automatically create a queue named _rsyslogd_, add the following to the qpidd configuration file: queue-patterns=rsyslogd or, if a topic is desired instead of a queue: topic-patterns=rsyslogd These dynamic targets are auto-delete and will be destroyed once there are no longer any subscribers or queue-bound messages. Versions of qpidd <= 0.34 also need to have the SASL service name set to 'amqp'. Add this to the qpidd.conf file: sasl-service-name=amqp ---- ## Notes on use with the QPID Dispatch Router (qdrouterd) ## _Note well: These notes assume use of version 0.5 of the QPID Dispatch Router Previous versions may not be fully compatible_ The default qdrouterd configuration does not have SASL authentication turned on. You must set up SASL in the qdrouter configuration file /etc/qpid-dispatch/qdrouterd.conf First create a SASL configuration file for qdrouterd. This configuration file is usually /etc/sasl2/qdrouterd.conf, but its default location may vary depending on your platform's configuration. This document assumes you understand how to properly configure SASL. Here is an example qdrouterd SASL configuration file that allows the client to use the DIGEST-MD5 or PLAIN authentication mechanisms, plus a SASL user database: pwcheck_method: auxprop auxprop_plugin: sasldb sasldb_path: /var/lib/qdrouterd/qdrouterd.sasldb mech_list: DIGEST-MD5 PLAIN Once a SASL configuration file has been set up for qdrouterd the path to the directory holding the configuration file and the basename of the configuration file (sas '.conf') must be added to the /etc/qpid-dispatch/qdrouterd.conf configuration file. This is done by adding _saslConfigPath_ and _saslConfigName_ to the _container_ section of the configuration file. For example, assuming the file /etc/sasl2/qdrouter.conf holds the qdrouterd SASL configuration: container { workerThreads: 4 containerName: Qpid.Dispatch.Router.A saslConfigPath: /etc/sasl2 saslConfigName: qdrouterd } In addition, the address used by the omamqp1 module to connect to qdrouterd must have SASL authentication turned on. This is done by adding the _authenticatePeer_ attribute set to 'yes' to the corresponding _listener_ entry: listener { addr: 0.0.0.0 port: amqp authenticatePeer: yes } This should complete the SASL setup needed by qdrouterd. The target address used as the destination for the log messages must be picked with care. qdrouterd uses the prefix of the target address to determine the forwarding pattern used for messages sent using that target address. Addresses starting with the prefix _queue_ are distributed to only one message receiver. If there are multiple message consumers listening to that target address, only one listener will receive the message. In this case, qdrouterd will load balance messages across the multiple consumers - much like a queue with competing subscribers. For example: "queue/rsyslogd" If a multicast pattern is desired - where all active listeners receive their own copy of the message - the target address prefix _multicast_ may be used. For example: "multicast/rsyslogd" Note well: if there are _no_ active receivers for the log messages, messages will be rejected the qdrouterd. In this case the omamqp1 module will return a _SUSPENDED_ result to the rsyslogd main task. rsyslogd may then re-submit the rejected log messages to the module, which will attempt to send them again. This retry option is configured via rsyslogd - it is not part of this module. Refer to the rsyslogd actions documentation. ---- ### Using qdrouterd in combination with qpidd ### A qdrouterd-based message bus can use a broker as a message storage mechanism for those that require broker-based message services (such as a message store). This section explains how to configure qdrouterd and qpidd for this type of deployment. Please read the notes for deploying qpidd and qdrouterd first. Each qdrouterd instance that is to connect the broker to the message bus must define a _connector_ section in the qdrouterd.conf file. This connector contains the addressing information necessary to have the message bus set up a connection to the broker. For example, if a broker is available on host broker.host.com at port 5672: connector { name: mybroker role: on-demand addr: broker.host.com port: 5672 } In order to route messages to and from the broker, a static _link route_ must be configured on qdrouterd. This link route contains a target address prefix and the name of the connector to use for forwarding matching messages. For example, to have qdrouterd forward messages that have a target address prefixed by 'Broker' to the connector defined above, the following link pattern must be added to the qdrouterd.conf configuration: linkRoutePattern { prefix: /Broker/ connector: mybroker } A queue must then be created on the broker. The name of the queue must be prefixed by the same prefix specified in the linkRoutePattern entry. For example: $ qpid-config add queue Broker/rsyslogd Lastly, use the name of the queue for the target address used by the omamqp module. For example, assuming qdrouterd is listening on local port 5672: action(type="omamqp1" host="localhost:5672" target="Broker/rsyslogd") # Tests ## Valgrind For investigating leaks, valgrind will not give you the full symbols in the stack because rsyslog unloads the module before the leak checker finishes. The test adds the following using `add_conf` add_conf ' global(debug.unloadModules="off") ' Then you should get a full stacktrace with full symbols. rsyslog-8.2608.0/contrib/omamqp1/PaxHeaders/omamqp1.c0000644000000000000000000000013215216464435017303 xustar0030 mtime=1782212893.962265149 30 atime=1787067643.935920632 30 ctime=1787067802.462875392 rsyslog-8.2608.0/contrib/omamqp1/omamqp1.c0000664000175000017500000007631015216464435016756 0ustar00rgerrger/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * * omamqp1.c * * This output plugin enables rsyslog to send messages to an AMQP 1.0 protocol * compliant message bus. * * AMQP glue code Copyright (C) 2015-2016 Kenneth A. Giusti * */ /** * @file omamqp1.c * @brief rsyslog output plugin for AMQP 1.0 via Qpid Proton. * * Each action instance spawns a dedicated protocol thread that manages the * AMQP connection. Worker threads batch log messages and send them to this * thread through a small command queue for asynchronous transmission. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* work-around issues in this contributed module */ #pragma GCC diagnostic ignored "-Wswitch-enum" #pragma GCC diagnostic ignored "-Wdeprecated-declarations" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omamqp1") /* internal structures */ DEF_OMOD_STATIC_DATA; /* Settings for the action */ typedef struct _configSettings { pn_url_t *url; /* address of message bus */ uchar *username; /* authentication credentials */ uchar *password; uchar *target; /* endpoint for sent log messages */ uchar *templateName; int bDisableSASL; /* do not enable SASL? 0-enable 1-disable */ int idleTimeout; /* disconnect idle connection (seconds) */ int reconnectDelay; /* pause before re-connecting (seconds) */ int maxRetries; /* drop unrouteable messages after maxRetries attempts */ } configSettings_t; /* Control for communicating with the protocol engine thread */ typedef enum { // commands sent to protocol thread COMMAND_DONE, // marks command complete COMMAND_SEND, // send a message to the message bus COMMAND_IS_READY, // is the connection to the message bus active? COMMAND_SHUTDOWN // cleanup and terminate protocol thread. } commands_t; typedef struct _threadIPC { pthread_mutex_t lock; pthread_cond_t condition; commands_t command; rsRetVal result; // of command pn_message_t *message; uint64_t tag; // per message id } threadIPC_t; /* per-instance data */ typedef struct _instanceData { configSettings_t config; threadIPC_t ipc; int bThreadRunning; pthread_t thread_id; pn_reactor_t *reactor; pn_handler_t *handler; pn_message_t *message; int log_count; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; /* glue code */ typedef void dispatch_t(pn_handler_t *, pn_event_t *, pn_event_type_t); static void _init_thread_ipc(threadIPC_t *pIPC); static void _clean_thread_ipc(threadIPC_t *ipc); static void _init_config_settings(configSettings_t *pConfig); static void _clean_config_settings(configSettings_t *pConfig); static rsRetVal _shutdown_thread(instanceData *pData); static rsRetVal _new_handler( pn_handler_t **handler, pn_reactor_t *reactor, dispatch_t *dispatcher, configSettings_t *config, threadIPC_t *ipc); static void _del_handler(pn_handler_t *handler); static rsRetVal _launch_protocol_thread(instanceData *pData); static rsRetVal _issue_command(threadIPC_t *ipc, pn_reactor_t *reactor, commands_t command, pn_message_t *message); static void dispatcher(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type); /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = {{"host", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"target", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"username", eCmdHdlrGetWord, 0}, {"password", eCmdHdlrGetWord, 0}, {"template", eCmdHdlrGetWord, 0}, {"idleTimeout", eCmdHdlrNonNegInt, 0}, {"reconnectDelay", eCmdHdlrPositiveInt, 0}, {"maxRetries", eCmdHdlrNonNegInt, 0}, {"disableSASL", eCmdHdlrInt, 0}}; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; { if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; } ENDisCompatibleWithFeature BEGINcreateInstance CODESTARTcreateInstance; { memset(pData, 0, sizeof(instanceData)); _init_config_settings(&pData->config); _init_thread_ipc(&pData->ipc); } ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINfreeInstance CODESTARTfreeInstance; { _shutdown_thread(pData); _clean_config_settings(&pData->config); _clean_thread_ipc(&pData->ipc); if (pData->reactor) pn_reactor_free(pData->reactor); if (pData->handler) pn_handler_free(pData->handler); if (pData->message) pn_message_free(pData->message); } ENDfreeInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; { configSettings_t *cfg = &pData->config; dbgprintf("omamqp1:\n"); dbgprintf(" host=%s\n", pn_url_str(cfg->url)); dbgprintf(" username=%s\n", cfg->username); // dbgprintf(" password=%s\n", pData->password); dbgprintf(" target=%s\n", cfg->target); dbgprintf(" template=%s\n", cfg->templateName); dbgprintf(" disableSASL=%d\n", cfg->bDisableSASL); dbgprintf(" idleTimeout=%d\n", cfg->idleTimeout); dbgprintf(" reconnectDelay=%d\n", cfg->reconnectDelay); dbgprintf(" maxRetries=%d\n", cfg->maxRetries); dbgprintf(" running=%d\n", pData->bThreadRunning); } ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; { // is the link active? instanceData *pData = pWrkrData->pData; iRet = _issue_command(&pData->ipc, pData->reactor, COMMAND_IS_READY, NULL); } ENDtryResume /** * @brief Initialize a new batch of log records. * * beginTransaction() prepares a Proton message and opens a list container * that will hold each formatted log message added by doAction(). */ BEGINbeginTransaction CODESTARTbeginTransaction; { DBGPRINTF("omamqp1: beginTransaction\n"); instanceData *pData = pWrkrData->pData; pData->log_count = 0; if (pData->message) pn_message_free(pData->message); pData->message = pn_message(); CHKmalloc(pData->message); pn_data_t *body = pn_message_body(pData->message); pn_data_put_list(body); pn_data_enter(body); } finalize_it: ENDbeginTransaction /** * @brief Append a formatted message to the current batch. * * This function is invoked for each log record emitted by rsyslog. The * formatted string provided by the template is stored in the Proton * message created in beginTransaction(). * * The actual transmission is deferred until endTransaction() issues a * COMMAND_SEND to the protocol thread. */ BEGINdoAction CODESTARTdoAction; { DBGPRINTF("omamqp1: doAction\n"); instanceData *pData = pWrkrData->pData; if (!pData->message) ABORT_FINALIZE(RS_RET_OK); pn_bytes_t msg = pn_bytes(strlen((const char *)ppString[0]), (const char *)ppString[0]); pn_data_t *body = pn_message_body(pData->message); pn_data_put_string(body, msg); pData->log_count++; iRet = RS_RET_DEFER_COMMIT; } finalize_it: ENDdoAction /** * @brief Finalize the batch and forward it to the protocol thread. * * Closes the list started in beginTransaction() and hands the assembled * message to amqp1_thread via COMMAND_SEND. If no messages were queued the * Proton message is discarded. */ BEGINendTransaction CODESTARTendTransaction; { DBGPRINTF("omamqp1: endTransaction\n"); instanceData *pData = pWrkrData->pData; if (!pData->message) ABORT_FINALIZE(RS_RET_OK); pn_data_t *body = pn_message_body(pData->message); pn_data_exit(body); pn_message_t *message = pData->message; pData->message = NULL; if (pData->log_count > 0) { DBGPRINTF("omamqp1: sending [%d] records\n", pData->log_count); CHKiRet(_issue_command(&pData->ipc, pData->reactor, COMMAND_SEND, message)); } else { DBGPRINTF("omamqp1: no log messages to send\n"); pn_message_free(message); } } finalize_it: ENDendTransaction BEGINnewActInst struct cnfparamvals *pvals; int i; configSettings_t *cs; CODESTARTnewActInst; { if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); cs = &pData->config; CODE_STD_STRING_REQUESTnewActInst(1); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "host")) { char *u; CHKmalloc(u = es_str2cstr(pvals[i].val.d.estr, NULL)); cs->url = pn_url_parse(u); if (!cs->url) { LogError(0, RS_RET_CONF_PARSE_ERROR, "omamqp1: Invalid host URL configured: '%s'", u); free(u); ABORT_FINALIZE(RS_RET_CONF_PARSE_ERROR); } free(u); } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(cs->templateName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "target")) { CHKmalloc(cs->target = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "username")) { CHKmalloc(cs->username = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "password")) { CHKmalloc(cs->password = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "reconnectDelay")) { cs->reconnectDelay = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "idleTimeout")) { cs->idleTimeout = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "maxRetries")) { cs->maxRetries = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "disableSASL")) { cs->bDisableSASL = (int)pvals[i].val.d.n; } else { dbgprintf("omamqp1: program error, unrecognized param '%s', ignored.\n", actpblk.descr[i].name); } } CHKiRet(OMSRsetEntry( *ppOMSR, 0, (uchar *)strdup((cs->templateName == NULL) ? "RSYSLOG_FileFormat" : (char *)cs->templateName), OMSR_NO_RQD_TPL_OPTS)); // once configuration is known, start the protocol engine thread pData->reactor = pn_reactor(); CHKmalloc(pData->reactor); CHKiRet(_new_handler(&pData->handler, pData->reactor, dispatcher, &pData->config, &pData->ipc)); CHKiRet(_launch_protocol_thread(pData)); } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_TXIF_OMOD_QUERIES /* use transaction interface */ CODEqueryEtryPt_STD_OMOD8_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; { *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING); DBGPRINTF("omamqp1: module compiled with rsyslog version %s.\n", VERSION); DBGPRINTF("omamqp1: %susing transactional output interface.\n", bCoreSupportsBatching ? "" : "not "); } ENDmodInit /////////////////////////////////////// // All the Proton-specific glue code // /////////////////////////////////////// /* state maintained by the protocol thread */ typedef struct { const configSettings_t *config; threadIPC_t *ipc; pn_reactor_t *reactor; // AMQP 1.0 protocol engine pn_connection_t *conn; pn_link_t *sender; pn_delivery_t *delivery; char *encode_buffer; size_t buffer_size; uint64_t tag; int msgs_sent; int msgs_settled; int retries; sbool stopped; } protocolState_t; // protocolState_t is embedded in the engine handler #define PROTOCOL_STATE(eh) ((protocolState_t *)pn_handler_mem(eh)) static void _init_config_settings(configSettings_t *pConfig) { memset(pConfig, 0, sizeof(configSettings_t)); pConfig->reconnectDelay = 5; pConfig->maxRetries = 10; } static void _clean_config_settings(configSettings_t *pConfig) { if (pConfig->url) pn_url_free(pConfig->url); if (pConfig->username) free(pConfig->username); if (pConfig->password) free(pConfig->password); if (pConfig->target) free(pConfig->target); if (pConfig->templateName) free(pConfig->templateName); memset(pConfig, 0, sizeof(configSettings_t)); } static void _init_thread_ipc(threadIPC_t *pIPC) { memset(pIPC, 0, sizeof(threadIPC_t)); pthread_mutex_init(&pIPC->lock, NULL); pthread_cond_init(&pIPC->condition, NULL); pIPC->command = COMMAND_DONE; pIPC->result = RS_RET_OK; } static void _clean_thread_ipc(threadIPC_t *ipc) { pthread_cond_destroy(&ipc->condition); pthread_mutex_destroy(&ipc->lock); } // create a new handler for the engine and set up the protocolState static rsRetVal _new_handler( pn_handler_t **handler, pn_reactor_t *reactor, dispatch_t *dispatch, configSettings_t *config, threadIPC_t *ipc) { DEFiRet; *handler = pn_handler_new(dispatch, sizeof(protocolState_t), _del_handler); CHKmalloc(*handler); pn_handler_add(*handler, pn_handshaker()); protocolState_t *pState = PROTOCOL_STATE(*handler); memset(pState, 0, sizeof(protocolState_t)); pState->buffer_size = 64; // will grow if not enough pState->encode_buffer = (char *)malloc(pState->buffer_size); CHKmalloc(pState->encode_buffer); pState->reactor = reactor; pState->stopped = false; // these are _references_, don't free them: pState->config = config; pState->ipc = ipc; finalize_it: RETiRet; } // in case existing buffer too small static rsRetVal _grow_buffer(protocolState_t *pState) { DEFiRet; if (pState->buffer_size > ((size_t)-1) / 2) { LogError(0, RS_RET_OUT_OF_MEMORY, "omamqp1: encode buffer size overflow"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } size_t new_size = pState->buffer_size * 2; char *new_buf = realloc(pState->encode_buffer, new_size); CHKmalloc(new_buf); pState->encode_buffer = new_buf; pState->buffer_size = new_size; finalize_it: RETiRet; } /* release the pn_handler_t instance. Do not call this directly, * it will be called by the reactor when all references to the * handler have been released. */ static void _del_handler(pn_handler_t *handler) { protocolState_t *pState = PROTOCOL_STATE(handler); if (pState->encode_buffer) free(pState->encode_buffer); } // Close the sender and its parent session and connection static void _close_connection(protocolState_t *ps) { if (ps->sender) { pn_link_close(ps->sender); pn_session_close(pn_link_session(ps->sender)); } if (ps->conn) pn_connection_close(ps->conn); } static void _abort_command(protocolState_t *ps) { threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); switch (ipc->command) { case COMMAND_SEND: dbgprintf("omamqp1: aborted the message send in progress\n"); CASE_FALLTHROUGH case COMMAND_IS_READY: ipc->result = RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; case COMMAND_SHUTDOWN: // cannot be aborted case COMMAND_DONE: break; default: // No action needed for other cases break; } pthread_mutex_unlock(&ipc->lock); } // log a protocol error received from the message bus static void _log_error(const char *message, pn_condition_t *cond) { const char *name = pn_condition_get_name(cond); const char *desc = pn_condition_get_description(cond); dbgprintf("omamqp1: %s %s:%s\n", message, (name) ? name : "", (desc) ? desc : ""); } /* is the link ready to send messages? */ static sbool _is_ready(pn_link_t *link) { return (link && pn_link_state(link) == (PN_LOCAL_ACTIVE | PN_REMOTE_ACTIVE) && pn_link_credit(link) > 0); } /* Process each event emitted by the protocol engine */ static void dispatcher(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type) { protocolState_t *ps = PROTOCOL_STATE(handler); const configSettings_t *cfg = ps->config; // DBGPRINTF("omamqp1: Event received: %s\n", pn_event_type_name(type)); switch (type) { case PN_LINK_REMOTE_OPEN: DBGPRINTF("omamqp1: Message bus opened link.\n"); break; case PN_DELIVERY: // has the message been delivered to the message bus? if (ps->delivery) { assert(ps->delivery == pn_event_delivery(event)); if (pn_delivery_updated(ps->delivery)) { rsRetVal result = RS_RET_IDLE; uint64_t rs = pn_delivery_remote_state(ps->delivery); switch (rs) { case PN_ACCEPTED: DBGPRINTF("omamqp1: Message ACCEPTED by message bus\n"); result = RS_RET_OK; break; case PN_REJECTED: dbgprintf("omamqp1: message bus rejected log message: invalid message - dropping\n"); // message bus considers this a 'bad message'. Cannot be redelivered. // Likely a configuration error. Drop the message by returning OK result = RS_RET_OK; break; case PN_RELEASED: case PN_MODIFIED: // the message bus cannot accept the message. This may be temporary - retry // up to maxRetries before dropping if (++ps->retries >= cfg->maxRetries) { dbgprintf("omamqp1: message bus failed to accept message - dropping\n"); result = RS_RET_OK; } else { dbgprintf("omamqp1: message bus cannot accept message, retrying\n"); result = RS_RET_SUSPENDED; } break; case PN_RECEIVED: // not finished yet, wait for next delivery update break; default: // no other terminal states defined, so ignore anything else dbgprintf("omamqp1: unknown delivery state=0x%lX, assuming message accepted\n", (unsigned long)pn_delivery_remote_state(ps->delivery)); result = RS_RET_OK; break; } if (result != RS_RET_IDLE) { // the command is complete threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); assert(ipc->command == COMMAND_SEND); ipc->result = result; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); pthread_mutex_unlock(&ipc->lock); pn_delivery_settle(ps->delivery); ps->delivery = NULL; if (result == RS_RET_OK) { ps->retries = 0; } } } } break; case PN_CONNECTION_BOUND: if (!cfg->bDisableSASL) { // force use of SASL, even allowing PLAIN authentication pn_sasl_t *sasl = pn_sasl(pn_event_transport(event)); #if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10 pn_sasl_set_allow_insecure_mechs(sasl, true); #else // proton version <= 0.9 only supports PLAIN authentication const char *user = cfg->username ? (char *)cfg->username : pn_url_get_username(cfg->url); if (user) { pn_sasl_plain(sasl, user, (cfg->password ? (char *)cfg->password : pn_url_get_password(cfg->url))); } #endif } if (cfg->idleTimeout) { // configured as seconds, set as milliseconds pn_transport_set_idle_timeout(pn_event_transport(event), cfg->idleTimeout * 1000); } break; case PN_CONNECTION_UNBOUND: DBGPRINTF("omamqp1: cleaning up connection resources\n"); pn_connection_release(pn_event_connection(event)); ps->conn = NULL; ps->sender = NULL; ps->delivery = NULL; break; case PN_TRANSPORT_ERROR: { // TODO: if auth failure, does it make sense to retry??? pn_transport_t *tport = pn_event_transport(event); pn_condition_t *cond = pn_transport_condition(tport); if (pn_condition_is_set(cond)) { _log_error("transport failure", cond); } dbgprintf("omamqp1: network transport failed, reconnecting...\n"); // the protocol thread will attempt to reconnect if it is not // being shut down } break; default: break; } } /** * @brief Send a control command to the protocol thread. * * The calling worker thread populates the shared IPC structure with the * command and optional message payload, wakes the Proton reactor and waits * on the condition variable until amqp1_thread processes the request. */ static rsRetVal _issue_command(threadIPC_t *ipc, pn_reactor_t *reactor, commands_t command, pn_message_t *message) { DEFiRet; DBGPRINTF("omamqp1: Sending command %d to protocol thread\n", command); pthread_mutex_lock(&ipc->lock); if (message) { assert(ipc->message == NULL); ipc->message = message; } assert(ipc->command == COMMAND_DONE); ipc->command = command; pn_reactor_wakeup(reactor); while (ipc->command != COMMAND_DONE) { pthread_cond_wait(&ipc->condition, &ipc->lock); } iRet = ipc->result; if (ipc->message) { pn_message_free(ipc->message); ipc->message = NULL; } pthread_mutex_unlock(&ipc->lock); DBGPRINTF("omamqp1: Command %d completed, status=%d\n", command, iRet); RETiRet; } /** * @brief Check for and execute pending commands from the main thread. * * Invoked by the protocol thread between reactor events to handle requests * like message send, readiness queries or shutdown. */ static void _poll_command(protocolState_t *ps) { if (ps->stopped) return; threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); switch (ipc->command) { case COMMAND_SHUTDOWN: DBGPRINTF("omamqp1: Protocol thread processing shutdown command\n"); ps->stopped = true; _close_connection(ps); // wait for the shutdown to complete before ack'ing this command break; case COMMAND_IS_READY: DBGPRINTF("omamqp1: Protocol thread processing ready query command\n"); ipc->result = _is_ready(ps->sender) ? RS_RET_OK : RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; case COMMAND_SEND: if (ps->delivery) break; // currently processing this command DBGPRINTF("omamqp1: Protocol thread processing send message command\n"); if (!_is_ready(ps->sender)) { ipc->result = RS_RET_SUSPENDED; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); break; } // send the message ++ps->tag; ps->delivery = pn_delivery(ps->sender, pn_dtag((const char *)&ps->tag, sizeof(ps->tag))); pn_message_t *message = ipc->message; assert(message); int rc = 0; size_t len = ps->buffer_size; do { rc = pn_message_encode(message, ps->encode_buffer, &len); if (rc == PN_OVERFLOW) { _grow_buffer(ps); len = ps->buffer_size; } } while (rc == PN_OVERFLOW); pn_link_send(ps->sender, ps->encode_buffer, len); pn_link_advance(ps->sender); ++ps->msgs_sent; // command completes when remote updates the delivery (see PN_DELIVERY) break; case COMMAND_DONE: break; default: // No action needed for other cases break; } pthread_mutex_unlock(&ipc->lock); } /** * @brief Worker thread driving the Proton reactor. * * This thread owns the AMQP connection and processes commands issued via * _issue_command(). It reconnects on failure and periodically polls for * shutdown requests. */ static void *amqp1_thread(void *arg) { pn_handler_t *handler = (pn_handler_t *)arg; protocolState_t *ps = PROTOCOL_STATE(handler); const configSettings_t *cfg = ps->config; // have pn_reactor_process() exit after 5 sec to poll for commands pn_reactor_set_timeout(ps->reactor, 5000); pn_reactor_start(ps->reactor); while (!ps->stopped) { // setup a connection: const char *host = pn_url_get_host(cfg->url); const char *port = pn_url_get_port(cfg->url); if (!port) port = "5672"; #if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 13 ps->conn = pn_reactor_connection_to_host(ps->reactor, host, port, handler); pn_connection_set_hostname(ps->conn, host); #else { char host_addr[300]; ps->conn = pn_reactor_connection(ps->reactor, handler); snprintf(host_addr, sizeof(host_addr), "%s:%s", host, port); pn_connection_set_hostname(ps->conn, host_addr); } #endif pn_connection_set_container(ps->conn, "rsyslogd-omamqp1"); #if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10 // proton version <= 0.9 did not support Cyrus SASL const char *user = cfg->username ? (char *)cfg->username : pn_url_get_username(cfg->url); if (user) pn_connection_set_user(ps->conn, user); const char *pword = cfg->password ? (char *)cfg->password : pn_url_get_password(cfg->url); if (pword) pn_connection_set_password(ps->conn, pword); #endif pn_connection_open(ps->conn); pn_session_t *ssn = pn_session(ps->conn); pn_session_open(ssn); ps->sender = pn_sender(ssn, (char *)cfg->target); pn_link_set_snd_settle_mode(ps->sender, PN_SND_UNSETTLED); char *addr = (char *)ps->config->target; pn_terminus_set_address(pn_link_target(ps->sender), addr); pn_terminus_set_address(pn_link_source(ps->sender), addr); pn_link_open(ps->sender); // run the protocol engine until the connection closes or thread is shut down sbool engine_running = true; while (engine_running) { engine_running = pn_reactor_process(ps->reactor); _poll_command(ps); } _abort_command(ps); // unblock main thread if necessary // delay reconnectDelay seconds before re-connecting: int delay = ps->config->reconnectDelay; while (delay-- > 0 && !ps->stopped) { /* Sleep in one-second increments to pace reconnect attempts and * still allow _poll_command() to observe shutdown requests. */ srSleep(1, 0); _poll_command(ps); } } pn_reactor_stop(ps->reactor); // stop command is now done: threadIPC_t *ipc = ps->ipc; pthread_mutex_lock(&ipc->lock); ipc->result = RS_RET_OK; ipc->command = COMMAND_DONE; pthread_cond_signal(&ipc->condition); pthread_mutex_unlock(&ipc->lock); DBGPRINTF("omamqp1: Protocol thread stopped\n"); return 0; } /** * @brief Spawn the protocol thread that manages the AMQP connection. * * The thread executes amqp1_thread() using the instance's handler and * sets the bThreadRunning flag on success. */ static rsRetVal _launch_protocol_thread(instanceData *pData) { int rc; DBGPRINTF("omamqp1: Starting protocol thread\n"); do { rc = pthread_create(&pData->thread_id, NULL, amqp1_thread, pData->handler); if (!rc) { pData->bThreadRunning = true; return RS_RET_OK; } } while (rc == EAGAIN); LogError(0, RS_RET_SYS_ERR, "omamqp1: thread create failed: %d", rc); return RS_RET_SYS_ERR; } /** * @brief Request protocol thread termination and wait for completion. */ static rsRetVal _shutdown_thread(instanceData *pData) { DEFiRet; if (pData->bThreadRunning) { DBGPRINTF("omamqp1: shutting down thread...\n"); CHKiRet(_issue_command(&pData->ipc, pData->reactor, COMMAND_SHUTDOWN, NULL)); pthread_join(pData->thread_id, NULL); pData->bThreadRunning = false; DBGPRINTF("omamqp1: thread shutdown complete\n"); } finalize_it: RETiRet; } /* vi:set ai: */ rsyslog-8.2608.0/contrib/omamqp1/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161017621 xustar0029 mtime=1787067505.02233005 30 atime=1787067579.522719591 30 ctime=1787067802.456875281 rsyslog-8.2608.0/contrib/omamqp1/Makefile.in0000664000175000017500000006661015241076161017277 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omamqp1 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) omamqp1_la_DEPENDENCIES = am_omamqp1_la_OBJECTS = omamqp1_la-omamqp1.lo omamqp1_la_OBJECTS = $(am_omamqp1_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 = omamqp1_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omamqp1_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omamqp1_la-omamqp1.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omamqp1_la_SOURCES) DIST_SOURCES = $(omamqp1_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ README.md DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omamqp1.la omamqp1_la_SOURCES = omamqp1.c @ENABLE_QPIDPROTON_STATIC_FALSE@omamqp1_la_LDFLAGS = -module -avoid-version $(PROTON_PROACTOR_LIBS) $(PTHREADS_LIBS) $(OPENSSL_LIBS) -lm @ENABLE_QPIDPROTON_STATIC_TRUE@omamqp1_la_LDFLAGS = -module -avoid-version -Wl,-whole-archive -l:libqpid-proton-proactor-static.a -l:libqpid-proton-core-static.a -Wl,--no-whole-archive $(PTHREADS_LIBS) $(OPENSSL_LIBS) ${RT_LIBS} -lsasl2 @ENABLE_QPIDPROTON_STATIC_FALSE@omamqp1_la_LIBADD = @ENABLE_QPIDPROTON_STATIC_TRUE@omamqp1_la_LIBADD = omamqp1_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(PROTON_PROACTOR_CFLAGS) -Wno-error=switch EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omamqp1/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omamqp1/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omamqp1.la: $(omamqp1_la_OBJECTS) $(omamqp1_la_DEPENDENCIES) $(EXTRA_omamqp1_la_DEPENDENCIES) $(AM_V_CCLD)$(omamqp1_la_LINK) -rpath $(pkglibdir) $(omamqp1_la_OBJECTS) $(omamqp1_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omamqp1_la-omamqp1.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omamqp1_la-omamqp1.lo: omamqp1.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omamqp1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omamqp1_la-omamqp1.lo -MD -MP -MF $(DEPDIR)/omamqp1_la-omamqp1.Tpo -c -o omamqp1_la-omamqp1.lo `test -f 'omamqp1.c' || echo '$(srcdir)/'`omamqp1.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omamqp1_la-omamqp1.Tpo $(DEPDIR)/omamqp1_la-omamqp1.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omamqp1.c' object='omamqp1_la-omamqp1.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omamqp1_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omamqp1_la-omamqp1.lo `test -f 'omamqp1.c' || echo '$(srcdir)/'`omamqp1.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omamqp1_la-omamqp1.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omamqp1_la-omamqp1.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmkubernetes0000644000000000000000000000013215241076632016631 xustar0030 mtime=1787067802.723880256 30 atime=1787067808.786993238 30 ctime=1787067802.723880256 rsyslog-8.2608.0/contrib/mmkubernetes/0000775000175000017500000000000015241076632016352 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmkubernetes/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020736 xustar0030 mtime=1752569012.329251042 30 atime=1787067434.178008245 30 ctime=1787067802.712880051 rsyslog-8.2608.0/contrib/mmkubernetes/Makefile.am0000666000175000017500000000053215035412264020404 0ustar00rgerrgerpkglib_LTLIBRARIES = mmkubernetes.la mmkubernetes_la_SOURCES = mmkubernetes.c mmkubernetes_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBLOGNORM_CFLAGS) mmkubernetes_la_LDFLAGS = -module -avoid-version mmkubernetes_la_LIBADD = $(CURL_LIBS) $(LIBLOGNORM_LIBS) EXTRA_DIST = k8s_filename.rulebase k8s_container_name.rulebase rsyslog-8.2608.0/contrib/mmkubernetes/PaxHeaders/mmkubernetes.c0000644000000000000000000000013215241075234021550 xustar0030 mtime=1787067036.572577677 30 atime=1787067036.715580354 30 ctime=1787067802.717880145 rsyslog-8.2608.0/contrib/mmkubernetes/mmkubernetes.c0000664000175000017500000031317015241075234021221 0ustar00rgerrger/* mmkubernetes.c * This is a message modification module. It uses metadata obtained * from the message to query Kubernetes and obtain additional metadata * relating to the container instance. * * Inspired by: * https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter * * NOTE: read comments in module-template.h for details on the calling interface! * * Copyright 2016 Red Hat Inc. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* needed for asprintf */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "module-template.h" #include "errmsg.h" #include "statsobj.h" #include "regexp.h" #include "hashtable.h" #include "hashtable_itr.h" #include "srUtils.h" #include "unicode-helper.h" #include "datetime.h" /* static data */ MODULE_TYPE_OUTPUT /* this is technically an output plugin */ MODULE_TYPE_KEEP /* releasing the module would cause a leak through libcurl */ MODULE_CNFNAME("mmkubernetes") DEF_OMOD_STATIC_DATA; DEFobjCurrIf(regexp) DEFobjCurrIf(statsobj) DEFobjCurrIf(datetime) #define HAVE_LOADSAMPLESFROMSTRING 1 #if defined(NO_LOADSAMPLESFROMSTRING) #undef HAVE_LOADSAMPLESFROMSTRING #endif /* original from fluentd plugin: * 'var\.log\.containers\.(?[a-z0-9]([-a-z0-9]*[a-z0-9])?\ * (\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?[^_]+)_\ * (?.+)-(?[a-z0-9]{64})\.log$' * this is for _tag_ match, not actual filename match - in_tail turns filename * into a fluentd tag */ #define DFLT_FILENAME_LNRULES \ "rule=:/var/log/containers/%pod_name:char-to:_%_" \ "%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log" #define DFLT_FILENAME_RULEBASE "/etc/rsyslog.d/k8s_filename.rulebase" /* original from fluentd plugin: * '^(?[^_]+)_(?[^\._]+)\ * (\.(?[^_]+))?_(?[^_]+)_\ * (?[^_]+)_[^_]+_[^_]+$' */ #define DFLT_CONTAINER_LNRULES \ "rule=:%k8s_prefix:char-to:_%_%container_name:char-to:.%." \ "%container_hash:char-to:_%_" \ "%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%\n" \ "rule=:%k8s_prefix:char-to:_%_%container_name:char-to:_%_" \ "%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest%" #define DFLT_CONTAINER_RULEBASE "/etc/rsyslog.d/k8s_container_name.rulebase" #define DFLT_SRCMD_PATH "$!metadata!filename" #define DFLT_DSTMD_PATH "$!" #define DFLT_DE_DOT 1 /* true */ #define DFLT_DE_DOT_SEPARATOR "_" #define DFLT_CONTAINER_NAME "$!CONTAINER_NAME" /* name of variable holding CONTAINER_NAME value */ #define DFLT_CONTAINER_ID_FULL "$!CONTAINER_ID_FULL" /* name of variable holding CONTAINER_ID_FULL value */ #define DFLT_KUBERNETES_URL "https://kubernetes.default.svc.cluster.local:443" #define DFLT_BUSY_RETRY_INTERVAL 5 /* retry every 5 seconds */ #define DFLT_SSL_PARTIAL_CHAIN 0 /* disallow X509_V_FLAG_PARTIAL_CHAIN by default */ #define DFLT_CACHE_ENTRY_TTL 3600 /* delete entries from the cache older than 3600 seconds */ #define DFLT_INCLUDE_NAMESPACE_METADATA 1 #define DFLT_CACHE_EXPIRE_INTERVAL \ -1 /* delete all expired entries from the cache every N seconds \ -1 disables cache expiration/ttl checking \ 0 means - run cache expiration for every record */ #define DFLT_TOKEN_RELOAD_INTERVAL \ 3600 /* proactively re-read the bearer token from tokenfile every N \ seconds so a rotated projected ServiceAccount token is picked up without a \ restart; 0 disables the proactive reload */ /* only support setting the partial chain flag on openssl platforms that have the define */ #if defined(ENABLE_OPENSSL) && defined(X509_V_FLAG_PARTIAL_CHAIN) #define SUPPORT_SSL_PARTIAL_CHAIN 1 #endif struct cache_entry_s { time_t ttl; /* when this entry should expire */ void *data; /* the user data */ }; static struct cache_s { const uchar *kbUrl; sbool includeNamespaceMetadata; struct hashtable *mdHt; struct hashtable *nsHt; pthread_mutex_t *cacheMtx; time_t lastBusyTime; /* when we got the last busy response from kubernetes */ time_t expirationTime; /* if cache expiration checking is enable, time to check for expiration */ } **caches; typedef struct { int nmemb; uchar **patterns; regex_t *regexps; } annotation_match_t; /* module configuration data */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ uchar *kubernetesUrl; /* scheme, host, port, and optional path prefix for Kubernetes API lookups */ uchar **kubernetesUrls; /* ordered failover list; kubernetesUrl is the primary */ int nKubernetesUrls; uchar *srcMetadataPath; /* where to get data for kubernetes queries */ uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */ uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */ sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */ sbool skipVerifyHost; /* For testing/debugging - skip cert hostname verify (CURLOPT_SSL_VERIFYHOST FALSE) */ uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */ uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */ sbool de_dot; /* If true (default), convert '.' characters in labels & annotations to de_dot_separator */ uchar *de_dot_separator; /* separator character (default '_') to use for de_dotting */ size_t de_dot_separator_len; /* length of separator character */ annotation_match_t annotation_match; /* annotation keys must match these to be included in record */ char *fnRules; /* lognorm rules for container log filename match */ uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */ char *contRules; /* lognorm rules for CONTAINER_NAME value match */ uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */ int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */ sbool sslPartialChain; /* if true, allow using intermediate certs without root certs */ int cacheEntryTTL; /* delete entries from the cache if they are older than this many seconds */ int cacheExpireInterval; /* delete all expired entries from the cache every this many seconds */ sbool includeNamespaceMetadata; /* query and attach namespace metadata */ int tokenReloadInterval; /* proactively re-read the token from tokenFile every this many seconds (0 disables); guards against short-lived rotated SA tokens going stale */ }; /* action (instance) configuration data */ typedef struct _instanceData { uchar *kubernetesUrl; /* scheme, host, port, and optional path prefix for Kubernetes API lookups */ uchar **kubernetesUrls; /* ordered failover list; kubernetesUrl is the primary */ int nKubernetesUrls; msgPropDescr_t *srcMetadataDescr; /* where to get data for kubernetes queries */ uchar *dstMetadataPath; /* where to put metadata obtained from kubernetes */ uchar *caCertFile; /* File holding the CA cert (+optional chain) of CA that issued the Kubernetes server cert */ uchar *myCertFile; /* File holding cert corresponding to private key used for client cert auth */ uchar *myPrivKeyFile; /* File holding private key corresponding to cert used for client cert auth */ sbool allowUnsignedCerts; /* For testing/debugging - do not check for CA certs (CURLOPT_SSL_VERIFYPEER FALSE) */ sbool skipVerifyHost; /* For testing/debugging - skip cert hostname verify (CURLOPT_SSL_VERIFYHOST FALSE) */ uchar *token; /* The token value to use to authenticate to Kubernetes - takes precedence over tokenFile */ uchar *tokenFile; /* The file whose contents is the token value to use to authenticate to Kubernetes */ sbool de_dot; /* If true (default), convert '.' characters in labels & annotations to de_dot_separator */ uchar *de_dot_separator; /* separator character (default '_') to use for de_dotting */ size_t de_dot_separator_len; /* length of separator character */ annotation_match_t annotation_match; /* annotation keys must match these to be included in record */ char *fnRules; /* lognorm rules for container log filename match */ uchar *fnRulebase; /* lognorm rulebase filename for container log filename match */ ln_ctx fnCtxln; /**< context to be used for liblognorm */ char *contRules; /* lognorm rules for CONTAINER_NAME value match */ uchar *contRulebase; /* lognorm rulebase filename for CONTAINER_NAME value match */ ln_ctx contCtxln; /**< context to be used for liblognorm */ msgPropDescr_t *contNameDescr; /* CONTAINER_NAME field */ msgPropDescr_t *contIdFullDescr; /* CONTAINER_ID_FULL field */ struct cache_s *cache; int busyRetryInterval; /* how to handle 429 response - 0 means error, non-zero means retry every N seconds */ sbool sslPartialChain; /* if true, allow using intermediate certs without root certs */ int cacheEntryTTL; /* delete entries from the cache if they are older than this many seconds */ int cacheExpireInterval; /* delete all expired entries from the cache every this many seconds */ sbool includeNamespaceMetadata; /* query and attach namespace metadata */ int tokenReloadInterval; /* proactively re-read the token from tokenFile every this many seconds (0 disables); guards against short-lived rotated SA tokens going stale */ } instanceData; typedef struct wrkrInstanceData { instanceData *pData; CURL *curlCtx; struct curl_slist *curlHdr; time_t lastTokenReload; /* when curlHdr's bearer token was last (re)read from disk */ char *curlRply; size_t curlRplyLen; statsobj_t *stats; /* stats for this instance */ STATSCOUNTER_DEF(k8sRecordSeen, mutK8sRecordSeen); STATSCOUNTER_DEF(namespaceMetadataSuccess, mutNamespaceMetadataSuccess); STATSCOUNTER_DEF(namespaceMetadataNotFound, mutNamespaceMetadataNotFound); STATSCOUNTER_DEF(namespaceMetadataBusy, mutNamespaceMetadataBusy); STATSCOUNTER_DEF(namespaceMetadataError, mutNamespaceMetadataError); STATSCOUNTER_DEF(podMetadataSuccess, mutPodMetadataSuccess); STATSCOUNTER_DEF(podMetadataNotFound, mutPodMetadataNotFound); STATSCOUNTER_DEF(podMetadataBusy, mutPodMetadataBusy); STATSCOUNTER_DEF(podMetadataError, mutPodMetadataError); STATSCOUNTER_DEF(podCacheNumEntries, mutPodCacheNumEntries); STATSCOUNTER_DEF(namespaceCacheNumEntries, mutNamespaceCacheNumEntries); STATSCOUNTER_DEF(podCacheHits, mutPodCacheHits); STATSCOUNTER_DEF(namespaceCacheHits, mutNamespaceCacheHits); /* cache misses should correspond to metadata success, busy, etc. k8s api calls */ STATSCOUNTER_DEF(podCacheMisses, mutPodCacheMisses); STATSCOUNTER_DEF(namespaceCacheMisses, mutNamespaceCacheMisses); } wrkrInstanceData_t; /* module parameters (v6 config format) */ static struct cnfparamdescr modpdescr[] = {{"kubernetesurl", eCmdHdlrArray, 0}, {"srcmetadatapath", eCmdHdlrString, 0}, {"dstmetadatapath", eCmdHdlrString, 0}, {"tls.cacert", eCmdHdlrString, 0}, {"tls.mycert", eCmdHdlrString, 0}, {"tls.myprivkey", eCmdHdlrString, 0}, {"allowunsignedcerts", eCmdHdlrBinary, 0}, {"skipverifyhost", eCmdHdlrBinary, 0}, {"token", eCmdHdlrString, 0}, {"tokenfile", eCmdHdlrString, 0}, {"annotation_match", eCmdHdlrArray, 0}, {"de_dot", eCmdHdlrBinary, 0}, {"de_dot_separator", eCmdHdlrString, 0}, {"filenamerulebase", eCmdHdlrString, 0}, {"containerrulebase", eCmdHdlrString, 0}, {"busyretryinterval", eCmdHdlrInt, 0}, {"sslpartialchain", eCmdHdlrBinary, 0}, {"cacheentryttl", eCmdHdlrInt, 0}, {"cacheexpireinterval", eCmdHdlrInt, 0}, {"includenamespacemetadata", eCmdHdlrBinary, 0}, {"tokenreloadinterval", eCmdHdlrInt, 0} #if HAVE_LOADSAMPLESFROMSTRING == 1 , {"filenamerules", eCmdHdlrArray, 0}, {"containerrules", eCmdHdlrArray, 0} #endif }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* action (instance) parameters (v6 config format) */ static struct cnfparamdescr actpdescr[] = {{"kubernetesurl", eCmdHdlrArray, 0}, {"srcmetadatapath", eCmdHdlrString, 0}, {"dstmetadatapath", eCmdHdlrString, 0}, {"tls.cacert", eCmdHdlrString, 0}, {"tls.mycert", eCmdHdlrString, 0}, {"tls.myprivkey", eCmdHdlrString, 0}, {"allowunsignedcerts", eCmdHdlrBinary, 0}, {"skipverifyhost", eCmdHdlrBinary, 0}, {"token", eCmdHdlrString, 0}, {"tokenfile", eCmdHdlrString, 0}, {"annotation_match", eCmdHdlrArray, 0}, {"de_dot", eCmdHdlrBinary, 0}, {"de_dot_separator", eCmdHdlrString, 0}, {"filenamerulebase", eCmdHdlrString, 0}, {"containerrulebase", eCmdHdlrString, 0}, {"busyretryinterval", eCmdHdlrInt, 0}, {"sslpartialchain", eCmdHdlrBinary, 0}, {"cacheentryttl", eCmdHdlrInt, 0}, {"cacheexpireinterval", eCmdHdlrInt, 0}, {"includenamespacemetadata", eCmdHdlrBinary, 0}, {"tokenreloadinterval", eCmdHdlrInt, 0} #if HAVE_LOADSAMPLESFROMSTRING == 1 , {"filenamerules", eCmdHdlrArray, 0}, {"containerrules", eCmdHdlrArray, 0} #endif }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ static void free_annotationmatch(annotation_match_t *match) { if (match) { for (int ii = 0; ii < match->nmemb; ++ii) { if (match->patterns) free(match->patterns[ii]); if (match->regexps) regexp.regfree(&match->regexps[ii]); } free(match->patterns); match->patterns = NULL; free(match->regexps); match->regexps = NULL; match->nmemb = 0; } } static void freeKubernetesUrlList(uchar ***urls, int *const nUrls, uchar **const primaryUrl) { int i; if (urls == NULL || nUrls == NULL || primaryUrl == NULL) return; free(*primaryUrl); *primaryUrl = NULL; if (*urls != NULL) { for (i = 0; i < *nUrls; ++i) free((*urls)[i]); free(*urls); *urls = NULL; } *nUrls = 0; } static void freeInstanceKubernetesUrls(instanceData *pData) { if (pData == NULL) return; freeKubernetesUrlList(&pData->kubernetesUrls, &pData->nKubernetesUrls, &pData->kubernetesUrl); } static rsRetVal setKubernetesUrls(uchar ***dstUrls, int *const dstNUrls, uchar **const dstPrimaryUrl, uchar *const *const srcUrls, const int srcNUrls) { DEFiRet; uchar **newUrls = NULL; uchar *newPrimary = NULL; int i; if (dstUrls == NULL || dstNUrls == NULL || dstPrimaryUrl == NULL || srcUrls == NULL || srcNUrls <= 0) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: kubernetesurl must not be empty"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKmalloc(newUrls = calloc((size_t)srcNUrls, sizeof(uchar *))); for (i = 0; i < srcNUrls; ++i) { if (srcUrls[i] == NULL || srcUrls[i][0] == '\0') { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: empty kubernetesurl entry"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKmalloc(newUrls[i] = (uchar *)strdup((const char *)srcUrls[i])); } CHKmalloc(newPrimary = (uchar *)strdup((const char *)newUrls[0])); freeKubernetesUrlList(dstUrls, dstNUrls, dstPrimaryUrl); *dstPrimaryUrl = newPrimary; *dstUrls = newUrls; *dstNUrls = srcNUrls; newPrimary = NULL; newUrls = NULL; finalize_it: free(newPrimary); if (newUrls != NULL) { for (i = 0; i < srcNUrls; ++i) free(newUrls[i]); free(newUrls); } RETiRet; } static rsRetVal setKubernetesUrlsFromArray(uchar ***dstUrls, int *const dstNUrls, uchar **const dstPrimaryUrl, struct cnfarray *const ar) { DEFiRet; uchar **urls = NULL; int i; if (ar == NULL || ar->nmemb <= 0) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: kubernetesurl must not be empty"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CHKmalloc(urls = calloc((size_t)ar->nmemb, sizeof(uchar *))); for (i = 0; i < ar->nmemb; ++i) CHKmalloc(urls[i] = (uchar *)es_str2cstr(ar->arr[i], NULL)); CHKiRet(setKubernetesUrls(dstUrls, dstNUrls, dstPrimaryUrl, urls, ar->nmemb)); finalize_it: if (urls != NULL) { for (i = 0; i < (ar == NULL ? 0 : ar->nmemb); ++i) free(urls[i]); free(urls); } RETiRet; } static int init_annotationmatch(annotation_match_t *match, struct cnfarray *ar) { DEFiRet; match->nmemb = ar->nmemb; CHKmalloc(match->patterns = calloc(match->nmemb, sizeof(uchar *))); CHKmalloc(match->regexps = calloc(match->nmemb, sizeof(regex_t))); for (int jj = 0; jj < ar->nmemb; ++jj) { int rexret = 0; match->patterns[jj] = (uchar *)es_str2cstr(ar->arr[jj], NULL); rexret = regexp.regcomp(&match->regexps[jj], (char *)match->patterns[jj], REG_EXTENDED | REG_NOSUB); if (0 != rexret) { char errMsg[512]; regexp.regerror(rexret, &match->regexps[jj], errMsg, sizeof(errMsg)); iRet = RS_RET_CONFIG_ERROR; LogError(0, iRet, "error: could not compile annotation_match string [%s]" " into an extended regexp - %d: %s\n", match->patterns[jj], rexret, errMsg); break; } } finalize_it: if (iRet) free_annotationmatch(match); RETiRet; } static int copy_annotationmatch(annotation_match_t *src, annotation_match_t *dest) { DEFiRet; dest->nmemb = src->nmemb; CHKmalloc(dest->patterns = malloc(sizeof(uchar *) * dest->nmemb)); CHKmalloc(dest->regexps = calloc(dest->nmemb, sizeof(regex_t))); for (int jj = 0; jj < src->nmemb; ++jj) { CHKmalloc(dest->patterns[jj] = (uchar *)strdup((char *)src->patterns[jj])); /* assumes was already successfully compiled */ regexp.regcomp(&dest->regexps[jj], (char *)dest->patterns[jj], REG_EXTENDED | REG_NOSUB); } finalize_it: if (iRet) free_annotationmatch(dest); RETiRet; } /* takes a hash of annotations and returns another json object hash containing only the * keys that match - this logic is taken directly from fluent-plugin-kubernetes_metadata_filter * except that we do not add the key multiple times to the object to be returned */ static struct json_object *match_annotations(annotation_match_t *match, struct json_object *annotations) { struct json_object *ret = NULL; for (int jj = 0; jj < match->nmemb; ++jj) { struct json_object_iterator it = json_object_iter_begin(annotations); struct json_object_iterator itEnd = json_object_iter_end(annotations); for (; !json_object_iter_equal(&it, &itEnd); json_object_iter_next(&it)) { const char *const key = json_object_iter_peek_name(&it); if (!ret || !fjson_object_object_get_ex(ret, key, NULL)) { if (!regexp.regexec(&match->regexps[jj], key, 0, NULL, 0)) { if (!ret) { ret = json_object_new_object(); } json_object_object_add(ret, key, json_object_get(json_object_iter_peek_value(&it))); } } } } return ret; } /* This will take a hash of labels or annotations and will de_dot the keys. * It will return a brand new hash. AFAICT, there is no safe way to * iterate over the hash while modifying it in place. */ static struct json_object *de_dot_json_object(struct json_object *jobj, const char *delim, size_t delim_len) { struct json_object *ret = NULL; struct json_object_iterator it = json_object_iter_begin(jobj); struct json_object_iterator itEnd = json_object_iter_end(jobj); es_str_t *new_es_key = NULL; DEFiRet; ret = json_object_new_object(); while (!json_object_iter_equal(&it, &itEnd)) { const char *const key = json_object_iter_peek_name(&it); const char *cc = strstr(key, "."); if (NULL == cc) { json_object_object_add(ret, key, json_object_get(json_object_iter_peek_value(&it))); } else { char *new_key = NULL; const char *prevcc = key; new_es_key = es_newStrFromCStr(key, (es_size_t)(cc - prevcc)); while (cc) { if (es_addBuf(&new_es_key, (char *)delim, (es_size_t)delim_len)) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); cc += 1; /* one past . */ prevcc = cc; /* beginning of next substring */ if ((cc = strstr(prevcc, ".")) || (cc = strchr(prevcc, '\0'))) { if (es_addBuf(&new_es_key, (char *)prevcc, (es_size_t)(cc - prevcc))) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (!*cc) cc = NULL; /* EOS - done */ } } new_key = es_str2cstr(new_es_key, NULL); es_deleteStr(new_es_key); new_es_key = NULL; json_object_object_add(ret, new_key, json_object_get(json_object_iter_peek_value(&it))); free(new_key); } json_object_iter_next(&it); } finalize_it: if (iRet != RS_RET_OK) { json_object_put(ret); ret = NULL; } if (new_es_key) es_deleteStr(new_es_key); return ret; } /* given a "metadata" object field, do * - make sure "annotations" field has only the matching keys * - de_dot the "labels" and "annotations" fields keys * This modifies the jMetadata object in place */ static void parse_labels_annotations( struct json_object *jMetadata, annotation_match_t *match, sbool de_dot, const char *delim, size_t delim_len) { struct json_object *jo = NULL; if (fjson_object_object_get_ex(jMetadata, "annotations", &jo)) { if ((jo = match_annotations(match, jo))) json_object_object_add(jMetadata, "annotations", jo); else json_object_object_del(jMetadata, "annotations"); } /* dedot labels and annotations */ if (de_dot) { struct json_object *jo2 = NULL; if (fjson_object_object_get_ex(jMetadata, "annotations", &jo)) { if ((jo2 = de_dot_json_object(jo, delim, delim_len))) { json_object_object_add(jMetadata, "annotations", jo2); } } if (fjson_object_object_get_ex(jMetadata, "labels", &jo)) { if ((jo2 = de_dot_json_object(jo, delim, delim_len))) { json_object_object_add(jMetadata, "labels", jo2); } } } } #if HAVE_LOADSAMPLESFROMSTRING == 1 static int array_to_rules(struct cnfarray *ar, char **rules) { DEFiRet; es_str_t *tmpstr = NULL; es_size_t size = 0; if (rules == NULL) FINALIZE; *rules = NULL; if (!ar->nmemb) FINALIZE; for (int jj = 0; jj < ar->nmemb; jj++) size += es_strlen(ar->arr[jj]); if (!size) FINALIZE; CHKmalloc(tmpstr = es_newStr(size)); CHKiRet((es_addStr(&tmpstr, ar->arr[0]))); CHKiRet((es_addBufConstcstr(&tmpstr, "\n"))); for (int jj = 1; jj < ar->nmemb; ++jj) { CHKiRet((es_addStr(&tmpstr, ar->arr[jj]))); CHKiRet((es_addBufConstcstr(&tmpstr, "\n"))); } CHKiRet((es_addBufConstcstr(&tmpstr, "\0"))); CHKmalloc(*rules = es_str2cstr(tmpstr, NULL)); finalize_it: if (tmpstr) { es_deleteStr(tmpstr); } if (iRet != RS_RET_OK) { free(*rules); *rules = NULL; } RETiRet; } #endif /* callback for liblognorm error messages */ static void errCallBack(void __attribute__((unused)) * cookie, const char *msg, size_t __attribute__((unused)) lenMsg) { LogError(0, RS_RET_ERR_LIBLOGNORM, "liblognorm error: %s", msg); } static rsRetVal set_lnctx(ln_ctx *ctxln, char *instRules, uchar *instRulebase, char *modRules, uchar *modRulebase) { DEFiRet; if (ctxln == NULL) FINALIZE; CHKmalloc(*ctxln = ln_initCtx()); ln_setErrMsgCB(*ctxln, errCallBack, NULL); if (instRules) { #if HAVE_LOADSAMPLESFROMSTRING == 1 if (ln_loadSamplesFromString(*ctxln, instRules) != 0) { LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' " "could not be loaded", instRules); ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); } #else (void)instRules; #endif } else if (instRulebase) { if (ln_loadSamples(*ctxln, (char *)instRulebase) != 0) { LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' " "could not be loaded", instRulebase); ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); } } else if (modRules) { #if HAVE_LOADSAMPLESFROMSTRING == 1 if (ln_loadSamplesFromString(*ctxln, modRules) != 0) { LogError(0, RS_RET_NO_RULEBASE, "error: normalization rules '%s' " "could not be loaded", modRules); ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); } #else (void)modRules; #endif } else if (modRulebase) { if (ln_loadSamples(*ctxln, (char *)modRulebase) != 0) { LogError(0, RS_RET_NO_RULEBASE, "error: normalization rulebase '%s' " "could not be loaded", modRulebase); ABORT_FINALIZE(RS_RET_ERR_LIBLOGNORM_SAMPDB_LOAD); } } finalize_it: if (iRet != RS_RET_OK) { ln_exitCtx(*ctxln); *ctxln = NULL; } RETiRet; } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; FILE *fp = NULL; int ret; char errStr[1024]; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "mmkubernetes: " "error processing module config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for mmkubernetes:\n"); cnfparamsPrint(&modpblk, pvals); } loadModConf->de_dot = DFLT_DE_DOT; loadModConf->busyRetryInterval = DFLT_BUSY_RETRY_INTERVAL; loadModConf->sslPartialChain = DFLT_SSL_PARTIAL_CHAIN; loadModConf->cacheEntryTTL = DFLT_CACHE_ENTRY_TTL; loadModConf->cacheExpireInterval = DFLT_CACHE_EXPIRE_INTERVAL; loadModConf->includeNamespaceMetadata = DFLT_INCLUDE_NAMESPACE_METADATA; loadModConf->tokenReloadInterval = DFLT_TOKEN_RELOAD_INTERVAL; for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } else if (!strcmp(modpblk.descr[i].name, "kubernetesurl")) { CHKiRet(setKubernetesUrlsFromArray(&loadModConf->kubernetesUrls, &loadModConf->nKubernetesUrls, &loadModConf->kubernetesUrl, pvals[i].val.d.ar)); } else if (!strcmp(modpblk.descr[i].name, "srcmetadatapath")) { free(loadModConf->srcMetadataPath); CHKmalloc(loadModConf->srcMetadataPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); /* todo: sanitize the path */ } else if (!strcmp(modpblk.descr[i].name, "dstmetadatapath")) { free(loadModConf->dstMetadataPath); CHKmalloc(loadModConf->dstMetadataPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); /* todo: sanitize the path */ } else if (!strcmp(modpblk.descr[i].name, "tls.cacert")) { free(loadModConf->caCertFile); CHKmalloc(loadModConf->caCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->caCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: 'tls.cacert' file %s couldn't be accessed: %s\n", loadModConf->caCertFile, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(modpblk.descr[i].name, "tls.mycert")) { free(loadModConf->myCertFile); CHKmalloc(loadModConf->myCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->myCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: 'tls.mycert' file %s couldn't be accessed: %s\n", loadModConf->myCertFile, errStr); } else { fclose(fp); fp = NULL; } } else if (!strcmp(modpblk.descr[i].name, "tls.myprivkey")) { CHKmalloc(loadModConf->myPrivKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->myPrivKeyFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n", loadModConf->myPrivKeyFile, errStr); } else { fclose(fp); fp = NULL; } } else if (!strcmp(modpblk.descr[i].name, "allowunsignedcerts")) { loadModConf->allowUnsignedCerts = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "skipverifyhost")) { loadModConf->skipVerifyHost = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "token")) { free(loadModConf->token); CHKmalloc(loadModConf->token = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "tokenfile")) { free(loadModConf->tokenFile); CHKmalloc(loadModConf->tokenFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->tokenFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: token file %s couldn't be accessed: %s\n", loadModConf->tokenFile, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(modpblk.descr[i].name, "annotation_match")) { free_annotationmatch(&loadModConf->annotation_match); if ((ret = init_annotationmatch(&loadModConf->annotation_match, pvals[i].val.d.ar))) ABORT_FINALIZE(ret); } else if (!strcmp(modpblk.descr[i].name, "de_dot")) { loadModConf->de_dot = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "de_dot_separator")) { free(loadModConf->de_dot_separator); CHKmalloc(loadModConf->de_dot_separator = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); #if HAVE_LOADSAMPLESFROMSTRING == 1 } else if (!strcmp(modpblk.descr[i].name, "filenamerules")) { free(loadModConf->fnRules); CHKiRet((array_to_rules(pvals[i].val.d.ar, &loadModConf->fnRules))); #endif } else if (!strcmp(modpblk.descr[i].name, "filenamerulebase")) { free(loadModConf->fnRulebase); CHKmalloc(loadModConf->fnRulebase = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->fnRulebase, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: filenamerulebase file %s couldn't be accessed: %s\n", loadModConf->fnRulebase, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } #if HAVE_LOADSAMPLESFROMSTRING == 1 } else if (!strcmp(modpblk.descr[i].name, "containerrules")) { free(loadModConf->contRules); CHKiRet((array_to_rules(pvals[i].val.d.ar, &loadModConf->contRules))); #endif } else if (!strcmp(modpblk.descr[i].name, "containerrulebase")) { free(loadModConf->contRulebase); CHKmalloc(loadModConf->contRulebase = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)loadModConf->contRulebase, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: containerrulebase file %s couldn't be accessed: %s\n", loadModConf->contRulebase, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(modpblk.descr[i].name, "busyretryinterval")) { loadModConf->busyRetryInterval = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "sslpartialchain")) { #if defined(SUPPORT_SSL_PARTIAL_CHAIN) loadModConf->sslPartialChain = pvals[i].val.d.n; #else LogMsg(0, RS_RET_VALUE_NOT_IN_THIS_MODE, LOG_INFO, "sslpartialchain is only supported for OpenSSL\n"); #endif } else if (!strcmp(modpblk.descr[i].name, "cacheentryttl")) { loadModConf->cacheEntryTTL = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "cacheexpireinterval")) { loadModConf->cacheExpireInterval = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "includenamespacemetadata")) { loadModConf->includeNamespaceMetadata = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "tokenreloadinterval")) { loadModConf->tokenReloadInterval = pvals[i].val.d.n; } else { dbgprintf( "mmkubernetes: program error, non-handled " "param '%s' in module() block\n", modpblk.descr[i].name); /* todo: error message? */ } } #if HAVE_LOADSAMPLESFROMSTRING == 1 if (loadModConf->fnRules && loadModConf->fnRulebase) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: only 1 of filenamerules or filenamerulebase may be used"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (loadModConf->contRules && loadModConf->contRulebase) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: only 1 of containerrules or containerrulebase may be used"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } #endif if ((loadModConf->cacheExpireInterval > -1)) { if ((loadModConf->cacheEntryTTL < 0)) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: cacheentryttl value [%d] is invalid - " "value must be 0 or greater", loadModConf->cacheEntryTTL); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } if (loadModConf->tokenReloadInterval < 0) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: tokenreloadinterval value [%d] is invalid - " "value must be 0 (disabled) or greater", loadModConf->tokenReloadInterval); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* set defaults */ if (loadModConf->srcMetadataPath == NULL) loadModConf->srcMetadataPath = (uchar *)strdup(DFLT_SRCMD_PATH); if (loadModConf->dstMetadataPath == NULL) loadModConf->dstMetadataPath = (uchar *)strdup(DFLT_DSTMD_PATH); if (loadModConf->de_dot_separator == NULL) loadModConf->de_dot_separator = (uchar *)strdup(DFLT_DE_DOT_SEPARATOR); if (loadModConf->de_dot_separator) loadModConf->de_dot_separator_len = strlen((const char *)loadModConf->de_dot_separator); #if HAVE_LOADSAMPLESFROMSTRING == 1 if (loadModConf->fnRules == NULL && loadModConf->fnRulebase == NULL) loadModConf->fnRules = strdup(DFLT_FILENAME_LNRULES); if (loadModConf->contRules == NULL && loadModConf->contRulebase == NULL) loadModConf->contRules = strdup(DFLT_CONTAINER_LNRULES); #else if (loadModConf->fnRulebase == NULL) loadModConf->fnRulebase = (uchar *)strdup(DFLT_FILENAME_RULEBASE); if (loadModConf->contRulebase == NULL) loadModConf->contRulebase = (uchar *)strdup(DFLT_CONTAINER_RULEBASE); #endif caches = calloc(1, sizeof(struct cache_s *)); finalize_it: if (fp) fclose(fp); if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINfreeInstance CODESTARTfreeInstance; freeInstanceKubernetesUrls(pData); msgPropDescrDestruct(pData->srcMetadataDescr); free(pData->srcMetadataDescr); free(pData->dstMetadataPath); free(pData->caCertFile); free(pData->myCertFile); free(pData->myPrivKeyFile); free(pData->token); free(pData->tokenFile); free(pData->fnRules); free(pData->fnRulebase); ln_exitCtx(pData->fnCtxln); free(pData->contRules); free(pData->contRulebase); ln_exitCtx(pData->contCtxln); free_annotationmatch(&pData->annotation_match); free(pData->de_dot_separator); msgPropDescrDestruct(pData->contNameDescr); free(pData->contNameDescr); msgPropDescrDestruct(pData->contIdFullDescr); free(pData->contIdFullDescr); ENDfreeInstance static size_t curlCB(char *data, size_t size, size_t nmemb, void *usrptr) { DEFiRet; wrkrInstanceData_t *pWrkrData = (wrkrInstanceData_t *)usrptr; char *buf; size_t newlen; newlen = pWrkrData->curlRplyLen + size * nmemb; CHKmalloc(buf = realloc(pWrkrData->curlRply, newlen)); memcpy(buf + pWrkrData->curlRplyLen, data, size * nmemb); pWrkrData->curlRply = buf; pWrkrData->curlRplyLen = newlen; finalize_it: if (iRet != RS_RET_OK) { return 0; } return size * nmemb; } #if defined(SUPPORT_SSL_PARTIAL_CHAIN) static CURLcode set_ssl_partial_chain(CURL *curl, void *ssl_ctx, void *userptr) { (void)userptr; /* currently unused */ CURLcode rv = CURLE_ABORTED_BY_CALLBACK; X509_STORE *store = NULL; store = SSL_CTX_get_cert_store((SSL_CTX *)ssl_ctx); if (!store) goto finalize_it; if (!X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN)) goto finalize_it; rv = CURLE_OK; finalize_it: return rv; } #endif /** * (Re)build the curl Authorization header for a worker from the current bearer * token and bind it to the worker's curl handle. * * The token is read fresh on every call: @c pData->token (inline, takes * precedence) or the contents of @c pData->tokenFile. This lets a rotated or * late-authorized projected ServiceAccount token be picked up without * recreating the worker. Any header list previously installed on the handle is * released. @c lastTokenReload is stamped so the proactive reload in queryKB() * can schedule the next refresh. * * Shared by createWrkrInstance() (initial build) and the reload paths in * queryKB() (proactive interval + reactive on 401), so the token is read * through a single code path. * * @param[in] pWrkrData worker instance whose curlHdr is (re)built and bound to * its already-initialized curlCtx * @returns RS_RET_OK on success, or an error code (the previously installed * header is left in place on failure) */ static rsRetVal mmk_build_token_header(wrkrInstanceData_t *pWrkrData) { DEFiRet; struct curl_slist *hdr = NULL; char *tokenHdr = NULL; char *token = NULL; FILE *fp = NULL; hdr = curl_slist_append(hdr, "Content-Type: text/json; charset=utf-8"); if (hdr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); if (pWrkrData->pData->token) { /* asprintf leaves the pointer undefined on failure, so NULL it before * aborting - finalize_it frees tokenHdr unconditionally */ if (asprintf(&tokenHdr, "Authorization: Bearer %s", pWrkrData->pData->token) == -1) { tokenHdr = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } else if (pWrkrData->pData->tokenFile) { struct stat statbuf; fp = fopen((const char *)pWrkrData->pData->tokenFile, "r"); if (fp && !fstat(fileno(fp), &statbuf)) { size_t bytesread; CHKmalloc(token = malloc((statbuf.st_size + 1) * sizeof(char))); /* require a complete read: a partial read during a rotation race * would yield a truncated (invalid) token, so leave tokenHdr NULL * and let the caller keep the existing header */ if ((bytesread = fread(token, sizeof(char), statbuf.st_size, fp)) == (size_t)statbuf.st_size && bytesread > 0) { token[bytesread] = '\0'; if (asprintf(&tokenHdr, "Authorization: Bearer %s", token) == -1) { tokenHdr = NULL; ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } } } /* If a token source is configured but we could not read a token (e.g. the * projected token volume is transiently unavailable during rotation), do not * tear down a header that is already installed: keep the existing, * still-likely-valid Authorization header and leave lastTokenReload * unchanged so the caller retries the reload on the next lookup. On the * initial build (curlHdr == NULL) there is nothing to preserve, so we fall * through and install the token-less header, matching the original startup * behavior. */ if (tokenHdr == NULL && (pWrkrData->pData->token || pWrkrData->pData->tokenFile) && pWrkrData->curlHdr != NULL) { ABORT_FINALIZE(RS_RET_ERR); } if (tokenHdr) { struct curl_slist *new_hdr = curl_slist_append(hdr, tokenHdr); if (new_hdr == NULL) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); hdr = new_hdr; } /* swap in the fresh header, releasing any previously installed one */ if (pWrkrData->curlHdr != NULL) { curl_slist_free_all(pWrkrData->curlHdr); } pWrkrData->curlHdr = hdr; curl_easy_setopt(pWrkrData->curlCtx, CURLOPT_HTTPHEADER, hdr); hdr = NULL; pWrkrData->lastTokenReload = time(NULL); finalize_it: free(token); free(tokenHdr); if (fp != NULL) { fclose(fp); } if (hdr != NULL) { curl_slist_free_all(hdr); } RETiRet; } BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; CURL *ctx; char *statsName = NULL; CHKiRet(statsobj.Construct(&(pWrkrData->stats))); if ((-1 == asprintf(&statsName, "mmkubernetes(%s)", pWrkrData->pData->kubernetesUrl)) || (!statsName)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } CHKiRet(statsobj.SetName(pWrkrData->stats, (uchar *)statsName)); free(statsName); statsName = NULL; CHKiRet(statsobj.SetOrigin(pWrkrData->stats, UCHAR_CONSTANT("mmkubernetes"))); STATSCOUNTER_INIT(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("recordseen"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->k8sRecordSeen))); STATSCOUNTER_INIT(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatasuccess"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataSuccess))); STATSCOUNTER_INIT(pWrkrData->namespaceMetadataNotFound, pWrkrData->mutNamespaceMetadataNotFound); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatanotfound"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataNotFound))); STATSCOUNTER_INIT(pWrkrData->namespaceMetadataBusy, pWrkrData->mutNamespaceMetadataBusy); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadatabusy"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataBusy))); STATSCOUNTER_INIT(pWrkrData->namespaceMetadataError, pWrkrData->mutNamespaceMetadataError); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacemetadataerror"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceMetadataError))); STATSCOUNTER_INIT(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatasuccess"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataSuccess))); STATSCOUNTER_INIT(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatanotfound"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataNotFound))); STATSCOUNTER_INIT(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadatabusy"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataBusy))); STATSCOUNTER_INIT(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podmetadataerror"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podMetadataError))); STATSCOUNTER_INIT(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachenumentries"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheNumEntries))); STATSCOUNTER_INIT(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachenumentries"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheNumEntries))); STATSCOUNTER_INIT(pWrkrData->namespaceCacheHits, pWrkrData->mutNamespaceCacheHits); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachehits"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheHits))); STATSCOUNTER_INIT(pWrkrData->podCacheHits, pWrkrData->mutPodCacheHits); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachehits"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheHits))); STATSCOUNTER_INIT(pWrkrData->namespaceCacheMisses, pWrkrData->mutNamespaceCacheMisses); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("namespacecachemisses"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->namespaceCacheMisses))); STATSCOUNTER_INIT(pWrkrData->podCacheMisses, pWrkrData->mutPodCacheMisses); CHKiRet(statsobj.AddCounter(pWrkrData->stats, UCHAR_CONSTANT("podcachemisses"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pWrkrData->podCacheMisses))); CHKiRet(statsobj.ConstructFinalize(pWrkrData->stats)); ctx = curl_easy_init(); pWrkrData->curlCtx = ctx; curl_easy_setopt(ctx, CURLOPT_WRITEFUNCTION, curlCB); curl_easy_setopt(ctx, CURLOPT_WRITEDATA, pWrkrData); if (pWrkrData->pData->caCertFile) curl_easy_setopt(ctx, CURLOPT_CAINFO, pWrkrData->pData->caCertFile); if (pWrkrData->pData->myCertFile) curl_easy_setopt(ctx, CURLOPT_SSLCERT, pWrkrData->pData->myCertFile); if (pWrkrData->pData->myPrivKeyFile) curl_easy_setopt(ctx, CURLOPT_SSLKEY, pWrkrData->pData->myPrivKeyFile); if (pWrkrData->pData->allowUnsignedCerts) curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYPEER, 0L); if (pWrkrData->pData->skipVerifyHost) curl_easy_setopt(ctx, CURLOPT_SSL_VERIFYHOST, 0L); #if defined(SUPPORT_SSL_PARTIAL_CHAIN) if (pWrkrData->pData->sslPartialChain) { curl_easy_setopt(ctx, CURLOPT_SSL_CTX_FUNCTION, set_ssl_partial_chain); curl_easy_setopt(ctx, CURLOPT_SSL_CTX_DATA, NULL); } #endif /* build the Authorization header from the current token on disk and bind it * to the handle just initialized; shared with the reload paths in queryKB() * so the token is read through one code path. */ CHKiRet(mmk_build_token_header(pWrkrData)); finalize_it: free(statsName); if (iRet != RS_RET_OK) { /* rsyslog does not call freeWrkrInstance when createWrkrInstance fails, * so release the curl handle here to avoid leaking it (e.g. if the * initial token-header build fails). */ if (pWrkrData->curlCtx != NULL) { curl_easy_cleanup(pWrkrData->curlCtx); pWrkrData->curlCtx = NULL; } if (pWrkrData->curlHdr != NULL) { curl_slist_free_all(pWrkrData->curlHdr); pWrkrData->curlHdr = NULL; } if (pWrkrData->stats) { statsobj.Destruct(&(pWrkrData->stats)); } } ENDcreateWrkrInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; curl_easy_cleanup(pWrkrData->curlCtx); curl_slist_free_all(pWrkrData->curlHdr); statsobj.Destruct(&(pWrkrData->stats)); ENDfreeWrkrInstance /* next function is work-around to avoid type-unsafe casts. It looks * like not really needed in practice, but gcc 8 complains and doing * it 100% correct for sure does not hurt ;-) -- rgerhards, 2018-07-19 */ static void hashtable_json_object_put(void *jso) { json_object_put((struct fjson_object *)jso); } static void cache_entry_free(struct cache_entry_s *cache_entry) { if (NULL != cache_entry) { if (cache_entry->data) { hashtable_json_object_put(cache_entry->data); cache_entry->data = NULL; } free(cache_entry); } } static void cache_entry_free_raw(void *cache_entry_void) { cache_entry_free((struct cache_entry_s *)cache_entry_void); } static struct cache_s *cacheNew(instanceData *pData) { DEFiRet; struct cache_s *cache = NULL; time_t now; int need_mutex_destroy = 0; CHKmalloc(cache = (struct cache_s *)calloc(1, sizeof(struct cache_s))); CHKmalloc(cache->cacheMtx = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t))); CHKmalloc(cache->mdHt = create_hashtable(100, hash_from_string, key_equals_string, cache_entry_free_raw)); CHKmalloc(cache->nsHt = create_hashtable(100, hash_from_string, key_equals_string, cache_entry_free_raw)); CHKiConcCtrl(pthread_mutex_init(cache->cacheMtx, NULL)); need_mutex_destroy = 1; datetime.GetTime(&now); cache->kbUrl = pData->kubernetesUrl; cache->includeNamespaceMetadata = pData->includeNamespaceMetadata; cache->expirationTime = 0; if (pData->cacheExpireInterval > -1) cache->expirationTime = pData->cacheExpireInterval + pData->cacheEntryTTL + now; cache->lastBusyTime = 0; dbgprintf("mmkubernetes: created cache mdht [%p] nsht [%p]\n", cache->mdHt, cache->nsHt); finalize_it: if (iRet != RS_RET_OK) { LogError(errno, iRet, "mmkubernetes: cacheNew: unable to create metadata cache for %s", pData->kubernetesUrl); if (cache) { if (cache->mdHt) hashtable_destroy(cache->mdHt, 1); if (cache->nsHt) hashtable_destroy(cache->nsHt, 1); if (cache->cacheMtx) { if (need_mutex_destroy) pthread_mutex_destroy(cache->cacheMtx); free(cache->cacheMtx); } free(cache); cache = NULL; } } return cache; } static void cacheFree(struct cache_s *cache) { hashtable_destroy(cache->mdHt, 1); hashtable_destroy(cache->nsHt, 1); pthread_mutex_destroy(cache->cacheMtx); free(cache->cacheMtx); free(cache); } /* must be called with cache->cacheMtx held */ /* assumes caller has reference to jso (json_object_get or is a new object) */ static struct cache_entry_s *cache_entry_new(time_t ttl, struct fjson_object *jso) { DEFiRet; struct cache_entry_s *cache_entry = NULL; CHKmalloc(cache_entry = malloc(sizeof(struct cache_entry_s))); cache_entry->ttl = ttl; cache_entry->data = (void *)jso; finalize_it: if (iRet) { free(cache_entry); cache_entry = NULL; } return cache_entry; } static int cache_delete_expired_entries(wrkrInstanceData_t *pWrkrData, int isnsmd, time_t now) { struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt; struct hashtable_itr *itr = NULL; int more; if ((pWrkrData->pData->cacheExpireInterval < 0) || (now < pWrkrData->pData->cache->expirationTime)) { return 0; /* not enabled or not time yet */ } /* set next expiration time */ pWrkrData->pData->cache->expirationTime = now + pWrkrData->pData->cacheExpireInterval; if (hashtable_count(ht) < 1) return 1; /* expire interval hit but nothing to do */ itr = hashtable_iterator(ht); if (NULL == itr) return 1; /* expire interval hit but nothing to do - err? */ do { struct cache_entry_s *cache_entry = (struct cache_entry_s *)hashtable_iterator_value(itr); if (now >= cache_entry->ttl) { cache_entry_free(cache_entry); if (isnsmd) { STATSCOUNTER_DEC(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries); } else { STATSCOUNTER_DEC(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries); } more = hashtable_iterator_remove(itr); } else { more = hashtable_iterator_advance(itr); } } while (more); free(itr); dbgprintf("mmkubernetes: cache_delete_expired_entries: cleaned [%s] cache - size is now [%llu]\n", isnsmd ? "namespace" : "pod", isnsmd ? pWrkrData->namespaceCacheNumEntries : pWrkrData->podCacheNumEntries); return 1; } /* must be called with cache->cacheMtx held */ static struct fjson_object *cache_entry_get(wrkrInstanceData_t *pWrkrData, int isnsmd, const char *key, time_t now) { struct fjson_object *jso = NULL; struct cache_entry_s *cache_entry = NULL; int checkttl = 1; struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt; /* see if it is time for a general cache expiration */ if (cache_delete_expired_entries(pWrkrData, isnsmd, now)) checkttl = 0; /* no need to check ttl now */ cache_entry = (struct cache_entry_s *)hashtable_search(ht, (void *)key); if (cache_entry && checkttl && (now >= cache_entry->ttl)) { cache_entry = (struct cache_entry_s *)hashtable_remove(ht, (void *)key); if (isnsmd) { STATSCOUNTER_DEC(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries); } else { STATSCOUNTER_DEC(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries); } cache_entry_free(cache_entry); cache_entry = NULL; } if (cache_entry) { jso = (struct fjson_object *)cache_entry->data; if (isnsmd) { STATSCOUNTER_INC(pWrkrData->namespaceCacheHits, pWrkrData->mutNamespaceCacheHits); } else { STATSCOUNTER_INC(pWrkrData->podCacheHits, pWrkrData->mutPodCacheHits); } dbgprintf("mmkubernetes: cache_entry_get: cache hit for [%s] cache key [%s] - hits is now [%llu]\n", isnsmd ? "namespace" : "pod", key, isnsmd ? pWrkrData->namespaceCacheHits : pWrkrData->podCacheHits); } else { if (isnsmd) { STATSCOUNTER_INC(pWrkrData->namespaceCacheMisses, pWrkrData->mutNamespaceCacheMisses); } else { STATSCOUNTER_INC(pWrkrData->podCacheMisses, pWrkrData->mutPodCacheMisses); } dbgprintf("mmkubernetes: cache_entry_get: cache miss for [%s] cache key [%s] - misses is now [%llu]\n", isnsmd ? "namespace" : "pod", key, isnsmd ? pWrkrData->namespaceCacheMisses : pWrkrData->podCacheMisses); } return jso; } /* must be called with cache->cacheMtx held */ /* key is passed in - caller must copy or otherwise ensure it is ok to pass off * ownership */ static rsRetVal cache_entry_add(wrkrInstanceData_t *pWrkrData, int isnsmd, const char *key, struct fjson_object *jso, time_t now, const int bDupKey) { DEFiRet; struct cache_entry_s *cache_entry = NULL; struct hashtable *ht = isnsmd ? pWrkrData->pData->cache->nsHt : pWrkrData->pData->cache->mdHt; char *dup_key = NULL; if (key == NULL) ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); /* see if it is time for a general cache expiration */ (void)cache_delete_expired_entries(pWrkrData, isnsmd, now); CHKmalloc(cache_entry = cache_entry_new(now + pWrkrData->pData->cacheEntryTTL, jso)); if (cache_entry) { if (bDupKey) CHKmalloc(dup_key = strdup(key)); if (!hashtable_insert(ht, (void *)(bDupKey ? dup_key : key), cache_entry)) ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); dup_key = NULL; if (isnsmd) { STATSCOUNTER_INC(pWrkrData->namespaceCacheNumEntries, pWrkrData->mutNamespaceCacheNumEntries); } else { STATSCOUNTER_INC(pWrkrData->podCacheNumEntries, pWrkrData->mutPodCacheNumEntries); } cache_entry = NULL; } finalize_it: free(dup_key); if (cache_entry) cache_entry_free(cache_entry); return iRet; } /* must be called with cache->cacheMtx held */ static struct fjson_object *cache_entry_get_md(wrkrInstanceData_t *pWrkrData, const char *key, time_t now) { return cache_entry_get(pWrkrData, 0, key, now); } /* must be called with cache->cacheMtx held */ static struct fjson_object *cache_entry_get_nsmd(wrkrInstanceData_t *pWrkrData, const char *key, time_t now) { return cache_entry_get(pWrkrData, 1, key, now); } /* must be called with cache->cacheMtx held */ static rsRetVal cache_entry_add_md(wrkrInstanceData_t *pWrkrData, const char *key, struct fjson_object *jso, time_t now) { return cache_entry_add(pWrkrData, 0, key, jso, now, 0); } /* must be called with cache->cacheMtx held */ static rsRetVal cache_entry_add_nsmd(wrkrInstanceData_t *pWrkrData, const char *key, struct fjson_object *jso, time_t now) { return cache_entry_add(pWrkrData, 1, key, jso, now, 1); } BEGINnewActInst struct cnfparamvals *pvals = NULL; int i; FILE *fp = NULL; char *rxstr = NULL; char *srcMetadataPath = NULL; char errStr[1024]; CODESTARTnewActInst; DBGPRINTF("newActInst (mmkubernetes)\n"); pvals = nvlstGetParams(lst, &actpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "mmkubernetes: " "error processing config parameters [action(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("action param blk in mmkubernetes:\n"); cnfparamsPrint(&actpblk, pvals); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); pData->de_dot = loadModConf->de_dot; pData->allowUnsignedCerts = loadModConf->allowUnsignedCerts; pData->skipVerifyHost = loadModConf->skipVerifyHost; pData->busyRetryInterval = loadModConf->busyRetryInterval; pData->sslPartialChain = loadModConf->sslPartialChain; pData->cacheEntryTTL = loadModConf->cacheEntryTTL; pData->cacheExpireInterval = loadModConf->cacheExpireInterval; pData->includeNamespaceMetadata = loadModConf->includeNamespaceMetadata; pData->tokenReloadInterval = loadModConf->tokenReloadInterval; for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } else if (!strcmp(actpblk.descr[i].name, "kubernetesurl")) { CHKiRet(setKubernetesUrlsFromArray(&pData->kubernetesUrls, &pData->nKubernetesUrls, &pData->kubernetesUrl, pvals[i].val.d.ar)); } else if (!strcmp(actpblk.descr[i].name, "srcmetadatapath")) { msgPropDescrDestruct(pData->srcMetadataDescr); free(pData->srcMetadataDescr); CHKmalloc(pData->srcMetadataDescr = malloc(sizeof(msgPropDescr_t))); CHKmalloc(srcMetadataPath = es_str2cstr(pvals[i].val.d.estr, NULL)); CHKiRet(msgPropDescrFill(pData->srcMetadataDescr, (uchar *)srcMetadataPath, strlen(srcMetadataPath))); /* todo: sanitize the path */ } else if (!strcmp(actpblk.descr[i].name, "dstmetadatapath")) { free(pData->dstMetadataPath); CHKmalloc(pData->dstMetadataPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); /* todo: sanitize the path */ } else if (!strcmp(actpblk.descr[i].name, "tls.cacert")) { free(pData->caCertFile); CHKmalloc(pData->caCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->caCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: certificate file %s couldn't be accessed: %s\n", pData->caCertFile, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(actpblk.descr[i].name, "tls.mycert")) { CHKmalloc(pData->myCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->myCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: 'tls.mycert' file %s couldn't be accessed: %s\n", pData->myCertFile, errStr); } else { fclose(fp); fp = NULL; } } else if (!strcmp(actpblk.descr[i].name, "tls.myprivkey")) { CHKmalloc(pData->myPrivKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->myPrivKeyFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n", pData->myPrivKeyFile, errStr); } else { fclose(fp); fp = NULL; } } else if (!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) { pData->allowUnsignedCerts = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "skipverifyhost")) { pData->skipVerifyHost = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "token")) { free(pData->token); CHKmalloc(pData->token = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "tokenfile")) { free(pData->tokenFile); CHKmalloc(pData->tokenFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->tokenFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: token file %s couldn't be accessed: %s\n", pData->tokenFile, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(actpblk.descr[i].name, "annotation_match")) { free_annotationmatch(&pData->annotation_match); if (RS_RET_OK != (iRet = init_annotationmatch(&pData->annotation_match, pvals[i].val.d.ar))) ABORT_FINALIZE(iRet); } else if (!strcmp(actpblk.descr[i].name, "de_dot")) { pData->de_dot = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "de_dot_separator")) { free(pData->de_dot_separator); CHKmalloc(pData->de_dot_separator = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); #if HAVE_LOADSAMPLESFROMSTRING == 1 } else if (!strcmp(modpblk.descr[i].name, "filenamerules")) { free(pData->fnRules); CHKiRet((array_to_rules(pvals[i].val.d.ar, &pData->fnRules))); #endif } else if (!strcmp(modpblk.descr[i].name, "filenamerulebase")) { free(pData->fnRulebase); CHKmalloc(pData->fnRulebase = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->fnRulebase, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: filenamerulebase file %s couldn't be accessed: %s\n", pData->fnRulebase, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } #if HAVE_LOADSAMPLESFROMSTRING == 1 } else if (!strcmp(modpblk.descr[i].name, "containerrules")) { free(pData->contRules); CHKiRet((array_to_rules(pvals[i].val.d.ar, &pData->contRules))); #endif } else if (!strcmp(modpblk.descr[i].name, "containerrulebase")) { free(pData->contRulebase); CHKmalloc(pData->contRulebase = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->contRulebase, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); iRet = RS_RET_NO_FILE_ACCESS; LogError(0, iRet, "error: containerrulebase file %s couldn't be accessed: %s\n", pData->contRulebase, errStr); ABORT_FINALIZE(iRet); } else { fclose(fp); fp = NULL; } } else if (!strcmp(actpblk.descr[i].name, "busyretryinterval")) { pData->busyRetryInterval = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "sslpartialchain")) { #if defined(SUPPORT_SSL_PARTIAL_CHAIN) pData->sslPartialChain = pvals[i].val.d.n; #else LogMsg(0, RS_RET_VALUE_NOT_IN_THIS_MODE, LOG_INFO, "sslpartialchain is only supported for OpenSSL\n"); #endif } else if (!strcmp(actpblk.descr[i].name, "cacheentryttl")) { pData->cacheEntryTTL = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "cacheexpireinterval")) { pData->cacheExpireInterval = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "includenamespacemetadata")) { pData->includeNamespaceMetadata = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "tokenreloadinterval")) { pData->tokenReloadInterval = pvals[i].val.d.n; } else { dbgprintf( "mmkubernetes: program error, non-handled " "param '%s' in action() block\n", actpblk.descr[i].name); /* todo: error message? */ } } #if HAVE_LOADSAMPLESFROMSTRING == 1 if (pData->fnRules && pData->fnRulebase) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: only 1 of filenamerules or filenamerulebase may be used"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (pData->contRules && pData->contRulebase) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: only 1 of containerrules or containerrulebase may be used"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } #endif CHKiRet( set_lnctx(&pData->fnCtxln, pData->fnRules, pData->fnRulebase, loadModConf->fnRules, loadModConf->fnRulebase)); CHKiRet(set_lnctx(&pData->contCtxln, pData->contRules, pData->contRulebase, loadModConf->contRules, loadModConf->contRulebase)); if ((pData->cacheExpireInterval > -1)) { if ((pData->cacheEntryTTL < 0)) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: cacheentryttl value [%d] is invalid - " "value must be 0 or greater", pData->cacheEntryTTL); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } if (pData->tokenReloadInterval < 0) { LogError(0, RS_RET_CONFIG_ERROR, "mmkubernetes: tokenreloadinterval value [%d] is invalid - " "value must be 0 (disabled) or greater", pData->tokenReloadInterval); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (pData->nKubernetesUrls == 0) { if (loadModConf->nKubernetesUrls == 0) { uchar *const defaultUrl = UCHAR_CONSTANT(DFLT_KUBERNETES_URL); CHKiRet(setKubernetesUrls(&pData->kubernetesUrls, &pData->nKubernetesUrls, &pData->kubernetesUrl, &defaultUrl, 1)); } else { CHKiRet(setKubernetesUrls(&pData->kubernetesUrls, &pData->nKubernetesUrls, &pData->kubernetesUrl, loadModConf->kubernetesUrls, loadModConf->nKubernetesUrls)); } } if (pData->srcMetadataDescr == NULL) { CHKmalloc(pData->srcMetadataDescr = malloc(sizeof(msgPropDescr_t))); CHKiRet(msgPropDescrFill(pData->srcMetadataDescr, loadModConf->srcMetadataPath, strlen((char *)loadModConf->srcMetadataPath))); } if (pData->dstMetadataPath == NULL) pData->dstMetadataPath = (uchar *)strdup((char *)loadModConf->dstMetadataPath); if (pData->caCertFile == NULL && loadModConf->caCertFile) pData->caCertFile = (uchar *)strdup((char *)loadModConf->caCertFile); if (pData->myCertFile == NULL && loadModConf->myCertFile) pData->myCertFile = (uchar *)strdup((char *)loadModConf->myCertFile); if (pData->myPrivKeyFile == NULL && loadModConf->myPrivKeyFile) pData->myPrivKeyFile = (uchar *)strdup((char *)loadModConf->myPrivKeyFile); if (pData->token == NULL && loadModConf->token) pData->token = (uchar *)strdup((char *)loadModConf->token); if (pData->tokenFile == NULL && loadModConf->tokenFile) pData->tokenFile = (uchar *)strdup((char *)loadModConf->tokenFile); if (pData->de_dot_separator == NULL && loadModConf->de_dot_separator) pData->de_dot_separator = (uchar *)strdup((char *)loadModConf->de_dot_separator); if ((pData->annotation_match.nmemb == 0) && (loadModConf->annotation_match.nmemb > 0)) copy_annotationmatch(&loadModConf->annotation_match, &pData->annotation_match); if (pData->de_dot_separator) pData->de_dot_separator_len = strlen((const char *)pData->de_dot_separator); CHKmalloc(pData->contNameDescr = malloc(sizeof(msgPropDescr_t))); CHKiRet(msgPropDescrFill(pData->contNameDescr, (uchar *)DFLT_CONTAINER_NAME, strlen(DFLT_CONTAINER_NAME))); CHKmalloc(pData->contIdFullDescr = malloc(sizeof(msgPropDescr_t))); CHKiRet(msgPropDescrFill(pData->contIdFullDescr, (uchar *)DFLT_CONTAINER_ID_FULL, strlen(DFLT_CONTAINER_NAME))); /* get the cache for this url */ for (i = 0; caches[i] != NULL; i++) { if (!strcmp((char *)pData->kubernetesUrl, (char *)caches[i]->kbUrl) && pData->includeNamespaceMetadata == caches[i]->includeNamespaceMetadata) break; } if (caches[i] != NULL) { pData->cache = caches[i]; } else { CHKmalloc(pData->cache = cacheNew(pData)); struct cache_s **new_caches = realloc(caches, (i + 2) * sizeof(struct cache_s *)); CHKmalloc(new_caches); caches = new_caches; caches[i] = pData->cache; caches[i + 1] = NULL; } CODE_STD_FINALIZERnewActInst; if (pvals != NULL) cnfparamvalsDestruct(pvals, &actpblk); if (fp) fclose(fp); free(rxstr); free(srcMetadataPath); ENDnewActInst /* legacy config format is not supported */ BEGINparseSelectorAct CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) if (strncmp((char *)p, ":mmkubernetes:", sizeof(":mmkubernetes:") - 1)) { LogError(0, RS_RET_LEGA_ACT_NOT_SUPPORTED, "mmkubernetes supports only v6+ config format, use: " "action(type=\"mmkubernetes\" ...)"); } ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; int i; freeKubernetesUrlList(&pModConf->kubernetesUrls, &pModConf->nKubernetesUrls, &pModConf->kubernetesUrl); free(pModConf->srcMetadataPath); free(pModConf->dstMetadataPath); free(pModConf->caCertFile); free(pModConf->myCertFile); free(pModConf->myPrivKeyFile); free(pModConf->token); free(pModConf->tokenFile); free(pModConf->de_dot_separator); free(pModConf->fnRules); free(pModConf->fnRulebase); free(pModConf->contRules); free(pModConf->contRulebase); free_annotationmatch(&pModConf->annotation_match); for (i = 0; caches[i] != NULL; i++) { dbgprintf("mmkubernetes: freeing cache [%d] mdht [%p] nsht [%p]\n", i, caches[i]->mdHt, caches[i]->nsHt); cacheFree(caches[i]); } free(caches); ENDfreeCnf BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; dbgprintf("mmkubernetes\n"); dbgprintf("\tkubernetesUrl='%s'\n", pData->kubernetesUrl); dbgprintf("\tsrcMetadataPath='%s'\n", pData->srcMetadataDescr->name); dbgprintf("\tdstMetadataPath='%s'\n", pData->dstMetadataPath); dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile); dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile); dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile); dbgprintf("\tallowUnsignedCerts='%d'\n", pData->allowUnsignedCerts); dbgprintf("\tskipVerifyHost='%d'\n", pData->skipVerifyHost); dbgprintf("\ttoken='%s'\n", pData->token); dbgprintf("\ttokenFile='%s'\n", pData->tokenFile); dbgprintf("\tde_dot='%d'\n", pData->de_dot); dbgprintf("\tde_dot_separator='%s'\n", pData->de_dot_separator); dbgprintf("\tfilenamerulebase='%s'\n", pData->fnRulebase); dbgprintf("\tcontainerrulebase='%s'\n", pData->contRulebase); #if HAVE_LOADSAMPLESFROMSTRING == 1 dbgprintf("\tfilenamerules='%s'\n", pData->fnRules); dbgprintf("\tcontainerrules='%s'\n", pData->contRules); #endif dbgprintf("\tbusyretryinterval='%d'\n", pData->busyRetryInterval); dbgprintf("\tcacheentryttl='%d'\n", pData->cacheEntryTTL); dbgprintf("\tcacheexpireinterval='%d'\n", pData->cacheExpireInterval); dbgprintf("\tincludenamespacemetadata='%d'\n", pData->includeNamespaceMetadata); dbgprintf("\ttokenreloadinterval='%d'\n", pData->tokenReloadInterval); ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume static rsRetVal extractMsgMetadata(smsg_t *pMsg, instanceData *pData, struct json_object **json) { DEFiRet; uchar *filename = NULL, *container_name = NULL, *container_id_full = NULL; rs_size_t fnLen, container_name_len, container_id_full_len; unsigned short freeFn = 0, free_container_name = 0, free_container_id_full = 0; int lnret; struct json_object *cnid = NULL; if (!json) FINALIZE; *json = NULL; /* extract metadata from the CONTAINER_NAME field and see if CONTAINER_ID_FULL is present */ container_name = MsgGetProp(pMsg, NULL, pData->contNameDescr, &container_name_len, &free_container_name, NULL); container_id_full = MsgGetProp(pMsg, NULL, pData->contIdFullDescr, &container_id_full_len, &free_container_id_full, NULL); if (container_name && container_id_full && container_name_len && container_id_full_len) { dbgprintf("mmkubernetes: CONTAINER_NAME: '%s' CONTAINER_ID_FULL: '%s'.\n", container_name, container_id_full); if ((lnret = ln_normalize(pData->contCtxln, (char *)container_name, container_name_len, json))) { if (LN_WRONGPARSER != lnret) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: error parsing container_name [%s]: [%d]", container_name, lnret); ABORT_FINALIZE(RS_RET_ERR); } /* else assume parser didn't find a match and fall through */ } else if (fjson_object_object_get_ex(*json, "pod_name", NULL) && fjson_object_object_get_ex(*json, "namespace_name", NULL) && fjson_object_object_get_ex(*json, "container_name", NULL)) { /* if we have fields for pod name, namespace name, container name, * and container id, we are good to go */ /* add field for container id */ json_object_object_add(*json, "container_id", json_object_new_string_len((const char *)container_id_full, container_id_full_len)); ABORT_FINALIZE(RS_RET_OK); } } /* extract metadata from the file name */ filename = MsgGetProp(pMsg, NULL, pData->srcMetadataDescr, &fnLen, &freeFn, NULL); if ((filename == NULL) || (fnLen == 0)) ABORT_FINALIZE(RS_RET_NOT_FOUND); dbgprintf("mmkubernetes: filename: '%s' len %d.\n", filename, fnLen); if ((lnret = ln_normalize(pData->fnCtxln, (char *)filename, fnLen, json))) { if (LN_WRONGPARSER != lnret) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: error parsing container_name [%s]: [%d]", filename, lnret); ABORT_FINALIZE(RS_RET_ERR); } else { /* no match */ ABORT_FINALIZE(RS_RET_NOT_FOUND); } } /* if we have fields for pod name, namespace name, container name, * and container id, we are good to go */ if (fjson_object_object_get_ex(*json, "pod_name", NULL) && fjson_object_object_get_ex(*json, "namespace_name", NULL) && fjson_object_object_get_ex(*json, "container_name_and_id", &cnid)) { /* parse container_name_and_id into container_name and container_id */ const char *container_name_and_id = json_object_get_string(cnid); const char *last_dash = NULL; if (container_name_and_id && (last_dash = strrchr(container_name_and_id, '-')) && *(last_dash + 1) && (last_dash != container_name_and_id)) { json_object_object_add( *json, "container_name", json_object_new_string_len(container_name_and_id, (int)(last_dash - container_name_and_id))); json_object_object_add(*json, "container_id", json_object_new_string(last_dash + 1)); ABORT_FINALIZE(RS_RET_OK); } } ABORT_FINALIZE(RS_RET_NOT_FOUND); finalize_it: if (freeFn) free(filename); if (free_container_name) free(container_name); if (free_container_id_full) free(container_id_full); if (iRet != RS_RET_OK) { json_object_put(*json); *json = NULL; } RETiRet; } static rsRetVal queryKB(wrkrInstanceData_t *pWrkrData, char *url, time_t now, struct json_object **rply) { DEFiRet; CURLcode ccode; struct json_tokener *jt = NULL; struct json_object *jo; long resp_code = 400; int reloaded_token = 0; /* Proactive token refresh: the bearer token is cached in the curl header at * worker start and otherwise never re-read. A projected ServiceAccount token * may be short-lived (kubelet rotates the on-disk file well before expiry), * so re-read it every tokenReloadInterval seconds to stay inside the validity * window and avoid the 401 entirely. A single missed reload is harmless * because validity greatly exceeds the interval. The reactive reload-on-401 * below remains as a backstop for the startup / identity-warm-up window this * cannot cover. Done before the busy-time adjustment below, which mutates * `now`. tokenReloadInterval == 0 disables the proactive reload. Only * meaningful when reading from tokenFile: an inline token cannot change, so * skip the reload entirely in that case. */ if (pWrkrData->pData->tokenFile != NULL && pWrkrData->pData->token == NULL && pWrkrData->pData->tokenReloadInterval > 0 && now - pWrkrData->lastTokenReload >= pWrkrData->pData->tokenReloadInterval) { if (mmk_build_token_header(pWrkrData) != RS_RET_OK) { /* keep the existing (still likely-valid) header; retry next call */ LogMsg(0, RS_RET_OK, LOG_INFO, "mmkubernetes: proactive token reload failed; keeping cached " "token and will retry on the next lookup\n"); } } if (pWrkrData->pData->cache->lastBusyTime) { now -= pWrkrData->pData->cache->lastBusyTime; if (now < pWrkrData->pData->busyRetryInterval) { LogMsg(0, RS_RET_RETRY, LOG_DEBUG, "mmkubernetes: Waited [%" PRId64 "] of [%d] seconds for " "the requested url [%s]\n", (int64_t)now, pWrkrData->pData->busyRetryInterval, url); ABORT_FINALIZE(RS_RET_RETRY); } else { LogMsg(0, RS_RET_OK, LOG_DEBUG, "mmkubernetes: Cleared busy status after [%d] seconds - " "will retry the requested url [%s]\n", pWrkrData->pData->busyRetryInterval, url); pWrkrData->pData->cache->lastBusyTime = 0; } } /* query kubernetes for pod info */ ccode = curl_easy_setopt(pWrkrData->curlCtx, CURLOPT_URL, url); if (ccode != CURLE_OK) ABORT_FINALIZE(RS_RET_ERR); retry_query: if (CURLE_OK != (ccode = curl_easy_perform(pWrkrData->curlCtx))) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: failed to connect to [%s] - %d:%s\n", url, ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_SUSPENDED); } if (CURLE_OK != (ccode = curl_easy_getinfo(pWrkrData->curlCtx, CURLINFO_RESPONSE_CODE, &resp_code))) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: could not get response code from query to [%s] - %d:%s\n", url, ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } /* On a 401 the most likely cause is a stale bearer token: the projected SA * token rotated on disk, or this worker came up before its node identity was * authorized. The header is built once at worker construction and otherwise * only refreshed by the proactive interval above. Re-read the token from * disk, rebuild the header, and retry the request exactly once before * surfacing the error. The response body buffered from the failed attempt is * drained first so the retry parses cleanly. A 403 (Forbidden) is not * retried: it means the request authenticated but this identity lacks access, * so re-reading the same token cannot help. Only attempted when reading from * tokenFile: an inline token cannot change, so a reload+retry cannot help. */ if (resp_code == 401 && !reloaded_token && pWrkrData->pData->tokenFile != NULL && pWrkrData->pData->token == NULL) { reloaded_token = 1; if (pWrkrData->curlRply != NULL) { free(pWrkrData->curlRply); pWrkrData->curlRply = NULL; pWrkrData->curlRplyLen = 0; } if (mmk_build_token_header(pWrkrData) == RS_RET_OK) { LogMsg(0, RS_RET_OK, LOG_INFO, "mmkubernetes: got [%ld] for url [%s] - reloaded SA token " "and retrying once\n", resp_code, url); goto retry_query; } } if (resp_code == 401) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: Unauthorized: not allowed to view url - " "check token/auth credentials [%s]\n", url); ABORT_FINALIZE(RS_RET_ERR); } if (resp_code == 403) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: Forbidden: no access - " "check permissions to view url [%s]\n", url); ABORT_FINALIZE(RS_RET_ERR); } if (resp_code == 404) { LogMsg(0, RS_RET_NOT_FOUND, LOG_INFO, "mmkubernetes: Not Found: the resource does not exist at url [%s]\n", url); ABORT_FINALIZE(RS_RET_NOT_FOUND); } if (resp_code == 429) { if (pWrkrData->pData->busyRetryInterval) { pWrkrData->pData->cache->lastBusyTime = now; } LogMsg(0, RS_RET_RETRY, LOG_INFO, "mmkubernetes: Too Many Requests: the server is too heavily loaded " "to provide the data for the requested url [%s]\n", url); ABORT_FINALIZE(RS_RET_RETRY); } if (resp_code != 200) { LogMsg(0, RS_RET_ERR, LOG_ERR, "mmkubernetes: server returned unexpected code [%ld] for url [%s]\n", resp_code, url); ABORT_FINALIZE(RS_RET_ERR); } /* parse retrieved data */ jt = json_tokener_new(); json_tokener_reset(jt); jo = json_tokener_parse_ex(jt, pWrkrData->curlRply, pWrkrData->curlRplyLen); json_tokener_free(jt); if (!json_object_is_type(jo, json_type_object)) { json_object_put(jo); jo = NULL; LogMsg(0, RS_RET_JSON_PARSE_ERR, LOG_INFO, "mmkubernetes: unable to parse string as JSON:[%.*s]\n", (int)pWrkrData->curlRplyLen, pWrkrData->curlRply); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } dbgprintf("mmkubernetes: queryKB reply:\n%s\n", json_object_to_json_string_ext(jo, JSON_C_TO_STRING_PRETTY)); *rply = jo; finalize_it: if (pWrkrData->curlRply != NULL) { free(pWrkrData->curlRply); pWrkrData->curlRply = NULL; pWrkrData->curlRplyLen = 0; } RETiRet; } static rsRetVal queryKBWithFailover(wrkrInstanceData_t *pWrkrData, const char *apiPath, time_t now, struct json_object **rply) { DEFiRet; char *url = NULL; int i; for (i = 0; i < pWrkrData->pData->nKubernetesUrls; ++i) { if ((-1 == asprintf(&url, "%s%s", (char *)pWrkrData->pData->kubernetesUrls[i], apiPath)) || (!url)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iRet = queryKB(pWrkrData, url, now, rply); if (iRet != RS_RET_SUSPENDED || i == pWrkrData->pData->nKubernetesUrls - 1) { FINALIZE; } LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "mmkubernetes: failed to connect to [%s], trying next configured kubernetesurl", url); free(url); url = NULL; } finalize_it: free(url); RETiRet; } /* versions < 8.16.0 don't support BEGINdoAction_NoStrings */ #if defined(BEGINdoAction_NoStrings) BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; smsg_t *pMsg = ppMsg[0]; #else BEGINdoAction smsg_t *pMsg = (smsg_t *)ppString[0]; #endif const char *podName = NULL, *ns = NULL, *containerName = NULL, *containerID = NULL; char *mdKey = NULL; char *apiPath = NULL; struct json_object *jMetadata = NULL, *jMetadataCopy = NULL, *jMsgMeta = NULL, *jo = NULL; int add_pod_metadata = 1; time_t now; CODESTARTdoAction; CHKiRet_Hdlr(extractMsgMetadata(pMsg, pWrkrData->pData, &jMsgMeta)) { ABORT_FINALIZE((iRet == RS_RET_NOT_FOUND) ? RS_RET_OK : iRet); } datetime.GetTime(&now); STATSCOUNTER_INC(pWrkrData->k8sRecordSeen, pWrkrData->mutK8sRecordSeen); if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo)) podName = json_object_get_string(jo); if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo)) ns = json_object_get_string(jo); if (fjson_object_object_get_ex(jMsgMeta, "container_name", &jo)) containerName = json_object_get_string(jo); if (fjson_object_object_get_ex(jMsgMeta, "container_id", &jo)) containerID = json_object_get_string(jo); assert(podName != NULL); assert(ns != NULL); assert(containerName != NULL); assert(containerID != NULL); dbgprintf( "mmkubernetes:\n podName: '%s'\n namespace: '%s'\n containerName: '%s'\n" " containerID: '%s'\n", podName, ns, containerName, containerID); /* check cache for metadata */ if ((-1 == asprintf(&mdKey, "%s_%s_%s", ns, podName, containerName)) || (!mdKey)) { ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pthread_mutex_lock(pWrkrData->pData->cache->cacheMtx); jMetadata = cache_entry_get_md(pWrkrData, mdKey, now); if (jMetadata == NULL) { struct json_object *jReply = NULL, *jo2 = NULL, *jNsMeta = NULL, *jPodData = NULL; /* Namespace metadata is optional. The namespace name parsed from the * input path remains part of the basic pod identity either way. */ if (pWrkrData->pData->includeNamespaceMetadata) jNsMeta = cache_entry_get_nsmd(pWrkrData, (const char *)ns, now); if (pWrkrData->pData->includeNamespaceMetadata && jNsMeta == NULL) { /* query kubernetes for namespace info */ if ((-1 == asprintf(&apiPath, "/api/v1/namespaces/%s", ns)) || (!apiPath)) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iRet = queryKBWithFailover(pWrkrData, apiPath, now, &jReply); free(apiPath); apiPath = NULL; if (iRet == RS_RET_NOT_FOUND) { /* negative cache namespace - make a dummy empty namespace metadata object */ jNsMeta = json_object_new_object(); STATSCOUNTER_INC(pWrkrData->namespaceMetadataNotFound, pWrkrData->mutNamespaceMetadataNotFound); } else if (iRet == RS_RET_RETRY) { /* server is busy - retry or error */ STATSCOUNTER_INC(pWrkrData->namespaceMetadataBusy, pWrkrData->mutNamespaceMetadataBusy); if (0 == pWrkrData->pData->busyRetryInterval) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_ERR); } add_pod_metadata = 0; /* don't cache pod metadata either - retry both */ } else if (iRet != RS_RET_OK) { /* one of many possible transient errors: apiserver error, network, config, auth. * Instead of causing hard error and disabling this module, we can return * basic namespace metadata that is extracted from container log file path. * When transient error resolves, other metadata will become * available. For a new a new pod whose metadata is not yet cached, this * will allow 401, 403, 500, etc. return status from apiserver treated * similar to 404 returns. * */ jNsMeta = json_object_new_object(); STATSCOUNTER_INC(pWrkrData->namespaceMetadataError, pWrkrData->mutNamespaceMetadataError); } else if (fjson_object_object_get_ex(jReply, "metadata", &jNsMeta)) { jNsMeta = json_object_get(jNsMeta); parse_labels_annotations(jNsMeta, &pWrkrData->pData->annotation_match, pWrkrData->pData->de_dot, (const char *)pWrkrData->pData->de_dot_separator, pWrkrData->pData->de_dot_separator_len); STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess); } else { /* namespace with no metadata??? */ LogMsg(0, RS_RET_ERR, LOG_INFO, "mmkubernetes: namespace [%s] has no metadata!\n", ns); /* negative cache namespace - make a dummy empty namespace metadata object */ jNsMeta = json_object_new_object(); STATSCOUNTER_INC(pWrkrData->namespaceMetadataSuccess, pWrkrData->mutNamespaceMetadataSuccess); } if (jNsMeta) { if ((iRet = cache_entry_add_nsmd(pWrkrData, ns, jNsMeta, now))) { ABORT_FINALIZE(iRet); } } json_object_put(jReply); jReply = NULL; } if ((-1 == asprintf(&apiPath, "/api/v1/namespaces/%s/pods/%s", ns, podName)) || (!apiPath)) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } iRet = queryKBWithFailover(pWrkrData, apiPath, now, &jReply); free(apiPath); apiPath = NULL; if (iRet == RS_RET_NOT_FOUND) { /* negative cache pod - make a dummy empty pod metadata object */ iRet = RS_RET_OK; STATSCOUNTER_INC(pWrkrData->podMetadataNotFound, pWrkrData->mutPodMetadataNotFound); } else if (iRet == RS_RET_RETRY) { /* server is busy - retry or error */ STATSCOUNTER_INC(pWrkrData->podMetadataBusy, pWrkrData->mutPodMetadataBusy); if (0 == pWrkrData->pData->busyRetryInterval) { pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); ABORT_FINALIZE(RS_RET_ERR); } add_pod_metadata = 0; /* do not cache so that we can retry */ iRet = RS_RET_OK; } else if (iRet != RS_RET_OK) { /* This is likely caused by transient apiserver errors: 401, 403, 500, etc. * Treat it similar to 404 while returning file path based pod metadata. * When transient error condition resolves, additional metadata will be * available for events originating from a new pod whose metatadata is not * yet cached. * */ iRet = RS_RET_OK; STATSCOUNTER_INC(pWrkrData->podMetadataError, pWrkrData->mutPodMetadataError); } else { STATSCOUNTER_INC(pWrkrData->podMetadataSuccess, pWrkrData->mutPodMetadataSuccess); } jo = json_object_new_object(); if (jNsMeta && fjson_object_object_get_ex(jNsMeta, "uid", &jo2)) json_object_object_add(jo, "namespace_id", json_object_get(jo2)); if (jNsMeta && fjson_object_object_get_ex(jNsMeta, "labels", &jo2)) json_object_object_add(jo, "namespace_labels", json_object_get(jo2)); if (jNsMeta && fjson_object_object_get_ex(jNsMeta, "annotations", &jo2)) json_object_object_add(jo, "namespace_annotations", json_object_get(jo2)); if (jNsMeta && fjson_object_object_get_ex(jNsMeta, "creationTimestamp", &jo2)) json_object_object_add(jo, "creation_timestamp", json_object_get(jo2)); if (fjson_object_object_get_ex(jReply, "metadata", &jPodData)) { if (fjson_object_object_get_ex(jPodData, "uid", &jo2)) json_object_object_add(jo, "pod_id", json_object_get(jo2)); parse_labels_annotations(jPodData, &pWrkrData->pData->annotation_match, pWrkrData->pData->de_dot, (const char *)pWrkrData->pData->de_dot_separator, pWrkrData->pData->de_dot_separator_len); if (fjson_object_object_get_ex(jPodData, "annotations", &jo2)) json_object_object_add(jo, "annotations", json_object_get(jo2)); if (fjson_object_object_get_ex(jPodData, "labels", &jo2)) json_object_object_add(jo, "labels", json_object_get(jo2)); } if (fjson_object_object_get_ex(jReply, "spec", &jPodData)) { if (fjson_object_object_get_ex(jPodData, "nodeName", &jo2)) { json_object_object_add(jo, "host", json_object_get(jo2)); } } json_object_put(jReply); jReply = NULL; if (fjson_object_object_get_ex(jMsgMeta, "pod_name", &jo2)) json_object_object_add(jo, "pod_name", json_object_get(jo2)); if (fjson_object_object_get_ex(jMsgMeta, "namespace_name", &jo2)) json_object_object_add(jo, "namespace_name", json_object_get(jo2)); if (fjson_object_object_get_ex(jMsgMeta, "container_name", &jo2)) json_object_object_add(jo, "container_name", json_object_get(jo2)); json_object_object_add(jo, "master_url", json_object_new_string((const char *)pWrkrData->pData->kubernetesUrl)); jMetadata = json_object_new_object(); json_object_object_add(jMetadata, "kubernetes", jo); jo = json_object_new_object(); if (fjson_object_object_get_ex(jMsgMeta, "container_id", &jo2)) json_object_object_add(jo, "container_id", json_object_get(jo2)); json_object_object_add(jMetadata, "docker", jo); if (add_pod_metadata) { if ((iRet = cache_entry_add_md(pWrkrData, mdKey, jMetadata, now))) ABORT_FINALIZE(iRet); mdKey = NULL; } } /* make a copy of the metadata for the msg to own */ /* todo: use json_object_deep_copy when implementation available in libfastjson */ /* yes, this is expensive - but there is no other way to make this thread safe - we * can't allow the msg to have a shared pointer to an element inside the cache, * outside of the cache lock */ jMetadataCopy = json_tokener_parse(json_object_get_string(jMetadata)); if (!add_pod_metadata) { /* jMetadata object was created from scratch and not cached */ json_object_put(jMetadata); jMetadata = NULL; } pthread_mutex_unlock(pWrkrData->pData->cache->cacheMtx); /* the +1 is there to skip the leading '$' */ msgAddJSON(pMsg, (uchar *)pWrkrData->pData->dstMetadataPath + 1, jMetadataCopy, 0, 0); finalize_it: json_object_put(jMsgMeta); free(mdKey); free(apiPath); ENDdoAction BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature /* all the macros bellow have to be in a specific order */ BEGINmodExit CODESTARTmodExit; curl_global_cleanup(); objRelease(datetime, CORE_COMPONENT); objRelease(regexp, LM_REGEXP_FILENAME); objRelease(statsobj, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmkubernetes: module compiled with rsyslog version %s.\n", VERSION); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(regexp, LM_REGEXP_FILENAME)); CHKiRet(objUse(datetime, CORE_COMPONENT)); /* CURL_GLOBAL_ALL initializes more than is needed but the * libcurl documentation discourages use of other values */ curl_global_init(CURL_GLOBAL_ALL); ENDmodInit rsyslog-8.2608.0/contrib/mmkubernetes/PaxHeaders/k8s_container_name.rulebase0000644000000000000000000000013215035412264024175 xustar0030 mtime=1752569012.329251042 30 atime=1782715518.794788942 30 ctime=1787067802.723880256 rsyslog-8.2608.0/contrib/mmkubernetes/k8s_container_name.rulebase0000666000175000017500000000050715035412264023645 0ustar00rgerrgerversion=2 rule=:%k8s_prefix:char-to:_%_%container_name:char-to:.%.%container_hash:char-to:_%_%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest% rule=:%k8s_prefix:char-to:_%_%container_name:char-to:_%_%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest% rsyslog-8.2608.0/contrib/mmkubernetes/PaxHeaders/k8s_filename.rulebase0000644000000000000000000000013215035412264022773 xustar0030 mtime=1752569012.329251042 30 atime=1782715518.794788942 30 ctime=1787067802.721880219 rsyslog-8.2608.0/contrib/mmkubernetes/k8s_filename.rulebase0000666000175000017500000000017215035412264022441 0ustar00rgerrgerversion=2 rule=:/var/log/containers/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log rsyslog-8.2608.0/contrib/mmkubernetes/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020747 xustar0030 mtime=1787067504.895327681 30 atime=1787067579.616721344 30 ctime=1787067802.715880107 rsyslog-8.2608.0/contrib/mmkubernetes/Makefile.in0000664000175000017500000006657715241076160020440 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmkubernetes ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = mmkubernetes_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_mmkubernetes_la_OBJECTS = mmkubernetes_la-mmkubernetes.lo mmkubernetes_la_OBJECTS = $(am_mmkubernetes_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 = mmkubernetes_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(mmkubernetes_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmkubernetes_la_SOURCES) DIST_SOURCES = $(mmkubernetes_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmkubernetes.la mmkubernetes_la_SOURCES = mmkubernetes.c mmkubernetes_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBLOGNORM_CFLAGS) mmkubernetes_la_LDFLAGS = -module -avoid-version mmkubernetes_la_LIBADD = $(CURL_LIBS) $(LIBLOGNORM_LIBS) EXTRA_DIST = k8s_filename.rulebase k8s_container_name.rulebase all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmkubernetes/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmkubernetes/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmkubernetes.la: $(mmkubernetes_la_OBJECTS) $(mmkubernetes_la_DEPENDENCIES) $(EXTRA_mmkubernetes_la_DEPENDENCIES) $(AM_V_CCLD)$(mmkubernetes_la_LINK) -rpath $(pkglibdir) $(mmkubernetes_la_OBJECTS) $(mmkubernetes_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmkubernetes_la-mmkubernetes.lo: mmkubernetes.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmkubernetes_la-mmkubernetes.lo -MD -MP -MF $(DEPDIR)/mmkubernetes_la-mmkubernetes.Tpo -c -o mmkubernetes_la-mmkubernetes.lo `test -f 'mmkubernetes.c' || echo '$(srcdir)/'`mmkubernetes.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmkubernetes_la-mmkubernetes.Tpo $(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmkubernetes.c' object='mmkubernetes_la-mmkubernetes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmkubernetes_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmkubernetes_la-mmkubernetes.lo `test -f 'mmkubernetes.c' || echo '$(srcdir)/'`mmkubernetes.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmkubernetes_la-mmkubernetes.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/gnutls0000644000000000000000000000013215241076616015446 xustar0030 mtime=1787067790.767657465 30 atime=1787067808.786993238 30 ctime=1787067790.767657465 rsyslog-8.2608.0/contrib/gnutls/0000775000175000017500000000000015241076616015167 5ustar00rgerrgerrsyslog-8.2608.0/contrib/gnutls/PaxHeaders/cert.pem0000644000000000000000000000013215035412264017155 xustar0030 mtime=1752569012.326271887 30 atime=1782715518.796788976 30 ctime=1787067790.765657428 rsyslog-8.2608.0/contrib/gnutls/cert.pem0000666000175000017500000000165015035412264016625 0ustar00rgerrger-----BEGIN CERTIFICATE----- MIIChjCCAfGgAwIBAgIBADALBgkqhkiG9w0BAQUwWDELMAkGA1UEBhMCREUxHTAb BgNVBAoTFHJzeXNsb2cgdGVzdCByb290IENBMQswCQYDVQQLEwJDQTEdMBsGA1UE AxMUcnN5c2xvZy10ZXN0LXJvb3QtY2EwHhcNMDgwNTIwMTMwNDE5WhcNMTgwNTE4 MTMwNDI2WjA6MQswCQYDVQQGEwJERTEQMA4GA1UEChMHcnN5c2xvZzEZMBcGA1UE CxMQdGVzdCBjZXJ0aWZpY2F0ZTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGAxmHe fztJgaGxFYEceiUg0hdMlRVWBqoZelJ8BeXTDnXcu/5F2HtM+l+QDyDaGjKlx+NI K4rkj7d6Wd3AKPgOYS0VSDZe3a1xf9rRYzOthWTv7tYi4/LTqPXqN5lKE71dgrB/ /gOmvV/1YD776FIxVGCSAT0hHwkFC3slmpJSwD8CAwEAAaOBhDCBgTAMBgNVHRMB Af8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHREECzAJ ggdyc3lzbG9nMB0GA1UdDgQWBBQYu6eC9UALvC+5K5VOnFRi5OC98TAfBgNVHSME GDAWgBQzYQQgUm0YLNdarJnc2c1LxYVClDALBgkqhkiG9w0BAQUDgYEAXaymqsG9 PNBhhWIRFvXCDMaDM71vUtgSFoNUbxIV607ua2HQosPPM4EHIda6N6hdBK1bMQoG yqBwhvw0JVaVaO70Kbs2m2Ypk3YcpJtRqyp8q8+2y/w1Mk1QazFZC29aYgX2iNVf X4/x38YEL7Gu5vqPrTn++agnV4ZXECKuvLQ= -----END CERTIFICATE----- rsyslog-8.2608.0/contrib/gnutls/PaxHeaders/ca.pem0000644000000000000000000000013215035412264016603 xustar0030 mtime=1752569012.326271887 30 atime=1782715518.796788976 30 ctime=1787067790.762657372 rsyslog-8.2608.0/contrib/gnutls/ca.pem0000666000175000017500000000156715035412264016262 0ustar00rgerrger-----BEGIN CERTIFICATE----- MIICYjCCAc2gAwIBAgIBATALBgkqhkiG9w0BAQUwWDELMAkGA1UEBhMCREUxHTAb BgNVBAoTFHJzeXNsb2cgdGVzdCByb290IENBMQswCQYDVQQLEwJDQTEdMBsGA1UE AxMUcnN5c2xvZy10ZXN0LXJvb3QtY2EwHhcNMDgwNTIwMTI1ODEyWhcNMTgwNTE4 MTI1ODI0WjBYMQswCQYDVQQGEwJERTEdMBsGA1UEChMUcnN5c2xvZyB0ZXN0IHJv b3QgQ0ExCzAJBgNVBAsTAkNBMR0wGwYDVQQDExRyc3lzbG9nLXRlc3Qtcm9vdC1j YTCBnDALBgkqhkiG9w0BAQEDgYwAMIGIAoGAw2s+V+WCK7jx9MLpDD4pO8SCqq6Q nK/BptvKM+YeBrV9ud3lq6YgbpNmv3/wig43rqpolqk7PdDxTW/mdXPmM72oKr/N Fc2cAyOEXK8JTWiqwc//V4qMAnKFfLOxr1dr7WRD0k4Tc8+BWJMQjL2zmGXiSGEF YWYIFHLmnX4ZgyMCAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8E BQMDBwYAMB0GA1UdDgQWBBQzYQQgUm0YLNdarJnc2c1LxYVClDALBgkqhkiG9w0B AQUDgYEAuGWtH7Jkpa0n/izqQ5ddDQP/LT6taivCwlpEYEU9aumpQPWWxtYywKaP RfM1JTMLAiYd8MS7TJ8TYRvvR32Y02Y+OhXn11xERkWvBT2M9yzqX6hDfRueN7RT fPWsfm/NBTVojzjaECcTFenZid7PC5JiFbcU6PSUMZ49/JPhxAo= -----END CERTIFICATE----- rsyslog-8.2608.0/contrib/gnutls/PaxHeaders/key.pem0000644000000000000000000000013215035412264017010 xustar0030 mtime=1752569012.326271887 30 atime=1782715518.795788959 30 ctime=1787067790.767657465 rsyslog-8.2608.0/contrib/gnutls/key.pem0000666000175000017500000000156715035412264016467 0ustar00rgerrger-----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgQDGYd5/O0mBobEVgRx6JSDSF0yVFVYGqhl6UnwF5dMOddy7/kXY e0z6X5APINoaMqXH40griuSPt3pZ3cAo+A5hLRVINl7drXF/2tFjM62FZO/u1iLj 8tOo9eo3mUoTvV2CsH/+A6a9X/VgPvvoUjFUYJIBPSEfCQULeyWaklLAPwIDAQAB AoGARIwKqmHc+0rYenq7UUVE+vMMBjNyHyllVkvsCMmpzMRS+i5ZCf1I0vZ0O5X5 ZrX7bH8PL+R1J2eZgjXKMR3NMZBuyKHewItD9t2rIC0eD/ITlwq3VybbaMsw666e INxSmax+dS5CEcLevHHP3c+Q7S7QAFiWV43TdFUGXWJktIkCQQDPQ5WAZ+/Tvv0Q vtRjXMeTVaw/bSuKNUeDzFkmGyePnFeCReNFtJLE9PFSQWcPuYcbZgU59JTfA5ac Un+cHm31AkEA9Qek+q7PcJ+kON9E6SNodCZn6gLyHjnWrq4tf8pZO3NvoX2QiuD4 rwF7KWjr6q1JzADpLtwXnuYEhyiLFjJA4wJAcElMCEnG2y+ASH8p7z7HfKGQdLg/ O1wMB3JA5e0WLK5lllUogI4IaZ3N02NNY25+rLBDqpc/w+ZcxQnIypqNtQJATs9p ofON5wSB1oUBbhckZo9fxuWxqEUkJsUA/2Q+9R843XE8h166vdc1HOmRT8bywHne hmLl+gazmCFTMw1wzwJAHng+3zGUl4D8Ov3MPFD6hwYYK6/pEdtz/NUsCSazF7eK XuuP+DXPHNhXOuF1A3tP74pfc/fC1uCUH2G5z3Fy0Q== -----END RSA PRIVATE KEY----- rsyslog-8.2608.0/contrib/PaxHeaders/imdocker0000644000000000000000000000013215241076626015730 xustar0030 mtime=1787067798.995810794 30 atime=1787067808.786993238 30 ctime=1787067798.995810794 rsyslog-8.2608.0/contrib/imdocker/0000775000175000017500000000000015241076626015451 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imdocker/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020032 xustar0030 mtime=1752569012.327264939 30 atime=1787067433.985004643 30 ctime=1787067798.990810701 rsyslog-8.2608.0/contrib/imdocker/Makefile.am0000666000175000017500000000036615035412264017505 0ustar00rgerrgerpkglib_LTLIBRARIES = imdocker.la imdocker_la_SOURCES = imdocker.c imdocker_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS) imdocker_la_LDFLAGS = -module -avoid-version imdocker_la_LIBADD = $(CURL_LIBS) rsyslog-8.2608.0/contrib/imdocker/PaxHeaders/imdocker.c0000644000000000000000000000013215241075234017740 xustar0030 mtime=1787067036.570577639 30 atime=1787067036.714580335 30 ctime=1787067798.995810794 rsyslog-8.2608.0/contrib/imdocker/imdocker.c0000664000175000017500000021470115241075234017411 0ustar00rgerrger/* imdocker.c * This is an implementation of the docker container log input module. It uses the * Docker API in order to stream all container logs available on a host. Will also * update relevant container metadata. * * Copyright (C) 2018, 2025 the rsyslog project. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef __sun #define _XPG4_2 #endif #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include "cfsysline.h" /* access to config file objects */ #include "unicode-helper.h" #include "module-template.h" #include "srUtils.h" /* some utility functions */ #include "errmsg.h" #include "net.h" #include "glbl.h" #include "msg.h" #include "parser.h" #include "prop.h" #include "debug.h" #include "statsobj.h" #include "datetime.h" #include "ratelimit.h" #include "stringbuf.h" #include "hashtable.h" #include "hashtable_itr.h" #if !defined(_AIX) #pragma GCC diagnostic ignored "-Wswitch-enum" #endif MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imdocker") #define USE_MULTI_LINE #undef ENABLE_DEBUG_BYTE_BUFFER /* defines */ #define DOCKER_TAG_NAME "docker:" #define DOCKER_CONTAINER_ID_PARSE_NAME "Id" #define DOCKER_CONTAINER_NAMES_PARSE_NAME "Names" #define DOCKER_CONTAINER_IMAGE_PARSE_NAME "Image" #define DOCKER_CONTAINER_IMAGEID_PARSE_NAME "ImageID" #define DOCKER_CONTAINER_CREATED_PARSE_NAME "Created" #define DOCKER_CONTAINER_LABELS_PARSE_NAME "Labels" /* label defines */ #define DOCKER_CONTAINER_LABEL_KEY_STARTREGEX "imdocker.startregex" /* DEFAULT VALUES */ #define DFLT_pollingInterval 60 /* polling interval in seconds */ #define DFLT_retrieveNewLogsFromStart 1 /* Process newly found containers logs from start */ #define DFLT_containersLimit 25 /* maximum number of containers */ #define DFLT_trimLineOverBytes 4194304 /* limit log lines to the value - 4MB default */ #define DFLT_bEscapeLF 1 /* whether line feeds should be escaped */ #define DFLT_SEVERITY pri2sev(LOG_INFO) #define DFLT_FACILITY pri2fac(LOG_USER) enum { dst_invalid = -1, dst_stdin, dst_stdout, dst_stderr, dst_stream_type_count } docker_stream_type_t; /* imdocker specific structs */ typedef struct imdocker_buf_s { uchar *data; size_t len; size_t data_size; } imdocker_buf_t; typedef struct docker_cont_logs_buf_s { imdocker_buf_t *buf; int8_t stream_type; size_t bytes_remaining; } docker_cont_logs_buf_t; struct docker_cont_logs_inst_s; typedef rsRetVal (*submitmsg_funcptr)(struct docker_cont_logs_inst_s *pInst, docker_cont_logs_buf_t *pBufdata, const uchar *pszTag); typedef submitmsg_funcptr SubmitMsgFuncPtr; /* curl request instance */ typedef struct docker_cont_logs_req_s { CURL *curl; docker_cont_logs_buf_t *data_bufs[dst_stream_type_count]; SubmitMsgFuncPtr submitMsg; } docker_cont_logs_req_t; typedef struct imdocker_req_s { CURL *curl; imdocker_buf_t *buf; } imdocker_req_t; typedef struct docker_container_info_s { uchar *name; uchar *image; uchar *image_id; uint64_t created; /* json string container labels */ uchar *json_str_labels; } docker_container_info_t; typedef struct docker_cont_logs_inst_s { char *id; char short_id[12]; docker_container_info_t *container_info; docker_cont_logs_req_t *logsReq; uchar *start_regex; regex_t start_preg; /* compiled version of start_regex */ uint32_t prevSegEnd; } docker_cont_logs_inst_t; typedef struct docker_cont_log_instances_s { struct hashtable *ht_container_log_insts; struct hashtable *ht_seen_container_ids; pthread_mutex_t mut; CURLM *curlm; /* track the latest created container */ uint64_t last_container_created; uchar *last_container_id; time_t time_started; } docker_cont_log_instances_t; /* FORWARD DEFINITIONS */ /* imdocker_buf_t */ static rsRetVal imdockerBufNew(imdocker_buf_t **ppThis); static void imdockerBufDestruct(imdocker_buf_t *pThis); /* docker_cont_logs_buf_t */ static rsRetVal dockerContLogsBufNew(docker_cont_logs_buf_t **ppThis); static void dockerContLogsBufDestruct(docker_cont_logs_buf_t *pThis); static rsRetVal dockerContLogsBufWrite(docker_cont_logs_buf_t *pThis, const uchar *pdata, size_t write_size); /* imdocker_req_t */ static rsRetVal imdockerReqNew(imdocker_req_t **ppThis); static void imdockerReqDestruct(imdocker_req_t *pThis); /* docker_cont_logs_req_t */ static rsRetVal dockerContLogsReqNew(docker_cont_logs_req_t **ppThis, SubmitMsgFuncPtr submitMsg); static void dockerContLogsReqDestruct(docker_cont_logs_req_t *pThis); /* docker_cont_logs_inst_t */ static rsRetVal dockerContLogsInstNew(docker_cont_logs_inst_t **ppThis, const char *id, docker_container_info_t *container_info, SubmitMsgFuncPtr submitMsg); static void dockerContLogsInstDestruct(docker_cont_logs_inst_t *pThis); static rsRetVal dockerContLogsInstSetUrlById(sbool isInit, docker_cont_logs_inst_t *pThis, CURLM *curlm, const char *containerId); /* docker_cont_log_instances_t */ static rsRetVal dockerContLogReqsNew(docker_cont_log_instances_t **ppThis); static rsRetVal dockerContLogReqsDestruct(docker_cont_log_instances_t *pThis); static rsRetVal dockerContLogReqsGet(docker_cont_log_instances_t *pThis, docker_cont_logs_inst_t **ppContLogsInst, const char *id); static rsRetVal dockerContLogReqsPrint(docker_cont_log_instances_t *pThis); static rsRetVal dockerContLogReqsAdd(docker_cont_log_instances_t *pThis, docker_cont_logs_inst_t *pContLogsReqInst); static rsRetVal dockerContLogReqsRemove(docker_cont_log_instances_t *pThis, const char *id); static rsRetVal dockerContLogReqsRememberSeen(docker_cont_log_instances_t *pThis, const char *id); static rsRetVal dockerContLogReqsClearLastContainer(docker_cont_log_instances_t *pThis); /* docker_container_info_t */ static rsRetVal dockerContainerInfoNew(docker_container_info_t **pThis); static void dockerContainerInfoDestruct(docker_container_info_t *pThis); /* utility functions */ static CURLcode docker_get(imdocker_req_t *req, const char *url); static char *dupDockerContainerName(const char *pname); static rsRetVal allocContainerLogsUrl( char **out, const uchar *apiAddr, const uchar *apiVersion, const char *containerId, const uchar *options); static rsRetVal allocContainersListUrl( char **out, const uchar *apiAddr, const uchar *apiVersion, const uchar *options, const uchar *sinceId); static rsRetVal SubmitMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag); /* support multi-line */ static rsRetVal SubmitMsg2(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag); static size_t imdocker_container_list_curlCB(void *data, size_t size, size_t nmemb, void *buffer); static size_t imdocker_container_logs_curlCB(void *data, size_t size, size_t nmemb, void *buffer); static sbool get_stream_info(const uchar *data, size_t size, int8_t *stream_type, size_t *payload_size); static int8_t is_valid_stream_type(int8_t stream_type); /* Module static data */ DEF_IMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) DEFobjCurrIf(statsobj) statsobj_t *modStats; STATSCOUNTER_DEF(ctrSubmit, mutCtrSubmit) STATSCOUNTER_DEF(ctrLostRatelimit, mutCtrLostRatelimit) STATSCOUNTER_DEF(ctrCurlError, mutCtrCurlError) const char *DFLT_dockerAPIUnixSockAddr = "/var/run/docker.sock"; const char *DFLT_dockerAPIAdd = "http://localhost:2375"; const char *DFLT_apiVersionStr = "v1.27"; const char *DFLT_listContainersOptions = ""; const char *DFLT_getContainerLogOptions = "timestamps=0&follow=1&stdout=1&stderr=1&tail=1"; const char *DFLT_getContainerLogOptionsWithoutTail = "timestamps=0&follow=1&stdout=1&stderr=1"; /* Overall module configuration structure here. */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ uchar *apiVersionStr; uchar *listContainersOptions; uchar *getContainerLogOptions; uchar *getContainerLogOptionsWithoutTail; int iPollInterval; /* in seconds */ uchar *dockerApiUnixSockAddr; uchar *dockerApiAddr; sbool retrieveNewLogsFromStart; int containersLimit; int trimLineOverBytes; int iDfltSeverity; int iDfltFacility; sbool bEscapeLf; }; static modConfData_t *loadModConf = NULL; static modConfData_t *runModConf = NULL; static prop_t *pInputName = NULL; /* our inputName currently is always "imdocker", and this will hold it */ static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */ static ratelimit_t *ratelimiter = NULL; /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { {"apiversionstr", eCmdHdlrString, 0}, {"dockerapiunixsockaddr", eCmdHdlrString, 0}, {"dockerapiaddr", eCmdHdlrString, 0}, {"listcontainersoptions", eCmdHdlrString, 0}, {"getcontainerlogoptions", eCmdHdlrString, 0}, {"pollinginterval", eCmdHdlrPositiveInt, 0}, {"retrievenewlogsfromstart", eCmdHdlrBinary, 0}, {"trimlineoverbytes", eCmdHdlrPositiveInt, 0}, {"defaultseverity", eCmdHdlrSeverity, 0}, {"defaultfacility", eCmdHdlrFacility, 0}, {"escapelf", eCmdHdlrBinary, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static int bLegacyCnfModGlobalsPermitted; /* are legacy module-global config parameters permitted? */ /* imdocker specific functions */ static rsRetVal imdockerBufNew(imdocker_buf_t **ppThis) { DEFiRet; imdocker_buf_t *pThis = (imdocker_buf_t *)calloc(1, sizeof(imdocker_buf_t)); if (!pThis) { return RS_RET_OUT_OF_MEMORY; } *ppThis = pThis; RETiRet; } static void imdockerBufDestruct(imdocker_buf_t *pThis) { if (pThis) { if (pThis->data) { free(pThis->data); pThis->data = NULL; } free(pThis); } } static rsRetVal dockerContLogsBufNew(docker_cont_logs_buf_t **ppThis) { DEFiRet; docker_cont_logs_buf_t *pThis = (docker_cont_logs_buf_t *)calloc(1, sizeof(docker_cont_logs_buf_t)); if (pThis && (iRet = imdockerBufNew(&pThis->buf)) == RS_RET_OK) { pThis->stream_type = dst_invalid; pThis->bytes_remaining = 0; *ppThis = pThis; } else { dockerContLogsBufDestruct(pThis); } RETiRet; } static void dockerContLogsBufDestruct(docker_cont_logs_buf_t *pThis) { if (pThis) { if (pThis->buf) { imdockerBufDestruct(pThis->buf); } free(pThis); } } static rsRetVal dockerContLogsBufWrite(docker_cont_logs_buf_t *const pThis, const uchar *const pdata, const size_t write_size) { DEFiRet; imdocker_buf_t *const mem = pThis->buf; if (mem->len == SIZE_MAX || write_size > SIZE_MAX - mem->len - 1) { LogError(0, RS_RET_ERR, "%s() - buffer size overflow\n", __FUNCTION__); ABORT_FINALIZE(RS_RET_ERR); } if (mem->len + write_size + 1 > mem->data_size) { uchar *const pbuf = realloc(mem->data, mem->len + write_size + 1); if (pbuf == NULL) { LogError(errno, RS_RET_ERR, "%s() - realloc failed!\n", __FUNCTION__); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } mem->data = pbuf; mem->data_size = mem->len + write_size + 1; } /* copy the bytes, and advance pdata */ memcpy(&(mem->data[mem->len]), pdata, write_size); mem->len += write_size; mem->data[mem->len] = '\0'; if (write_size > pThis->bytes_remaining) { pThis->bytes_remaining = 0; } else { pThis->bytes_remaining -= write_size; } finalize_it: RETiRet; } static rsRetVal allocContainerLogsUrl( char **out, const uchar *apiAddr, const uchar *apiVersion, const char *containerId, const uchar *options) { DEFiRet; int needed; assert(out != NULL); assert(apiAddr != NULL); assert(apiVersion != NULL); assert(containerId != NULL); assert(options != NULL); *out = NULL; needed = snprintf(NULL, 0, "%s/%s/containers/%s/logs?%s", apiAddr, apiVersion, containerId, options); if (needed < 0) { ABORT_FINALIZE(RS_RET_ERR); } CHKmalloc(*out = malloc((size_t)needed + 1)); if (snprintf(*out, (size_t)needed + 1, "%s/%s/containers/%s/logs?%s", apiAddr, apiVersion, containerId, options) != needed) { ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (iRet != RS_RET_OK) { free(*out); *out = NULL; } RETiRet; } static rsRetVal allocContainersListUrl( char **out, const uchar *apiAddr, const uchar *apiVersion, const uchar *options, const uchar *sinceId) { DEFiRet; int needed; assert(out != NULL); assert(apiAddr != NULL); assert(apiVersion != NULL); assert(options != NULL); *out = NULL; if (sinceId != NULL) { needed = snprintf(NULL, 0, "%s/%s/containers/json?%s&filters={\"since\":[\"%s\"]}", apiAddr, apiVersion, options, sinceId); if (needed < 0) { ABORT_FINALIZE(RS_RET_ERR); } CHKmalloc(*out = malloc((size_t)needed + 1)); if (snprintf(*out, (size_t)needed + 1, "%s/%s/containers/json?%s&filters={\"since\":[\"%s\"]}", apiAddr, apiVersion, options, sinceId) != needed) { ABORT_FINALIZE(RS_RET_ERR); } } else { needed = snprintf(NULL, 0, "%s/%s/containers/json?%s", apiAddr, apiVersion, options); if (needed < 0) { ABORT_FINALIZE(RS_RET_ERR); } CHKmalloc(*out = malloc((size_t)needed + 1)); if (snprintf(*out, (size_t)needed + 1, "%s/%s/containers/json?%s", apiAddr, apiVersion, options) != needed) { ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (iRet != RS_RET_OK) { free(*out); *out = NULL; } RETiRet; } rsRetVal imdockerReqNew(imdocker_req_t **ppThis) { DEFiRet; imdocker_req_t *pThis = (imdocker_req_t *)calloc(1, sizeof(imdocker_req_t)); CHKmalloc(pThis); pThis->curl = curl_easy_init(); if (!pThis->curl) { ABORT_FINALIZE(RS_RET_ERR); } CHKiRet(imdockerBufNew(&(pThis->buf))); *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK && pThis) { imdockerReqDestruct(pThis); } RETiRet; } void imdockerReqDestruct(imdocker_req_t *pThis) { if (pThis) { if (pThis->buf) { imdockerBufDestruct(pThis->buf); } if (pThis->curl) { curl_easy_cleanup(pThis->curl); pThis->curl = NULL; } free(pThis); } } static rsRetVal dockerContLogsReqNew(docker_cont_logs_req_t **ppThis, SubmitMsgFuncPtr submitMsg) { DEFiRet; docker_cont_logs_req_t *pThis = (docker_cont_logs_req_t *)calloc(1, sizeof(docker_cont_logs_req_t)); CHKmalloc(pThis); pThis->submitMsg = submitMsg; pThis->curl = curl_easy_init(); if (!pThis->curl) { ABORT_FINALIZE(RS_RET_ERR); } for (int i = 0; i < dst_stream_type_count; i++) { CHKiRet(dockerContLogsBufNew(&pThis->data_bufs[i])); } *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { if (pThis) { dockerContLogsReqDestruct(pThis); } } RETiRet; } static void dockerContLogsReqDestruct(docker_cont_logs_req_t *pThis) { if (pThis) { for (int i = 0; i < dst_stream_type_count; i++) { dockerContLogsBufDestruct(pThis->data_bufs[i]); } if (pThis->curl) { curl_easy_cleanup(pThis->curl); pThis->curl = NULL; } free(pThis); } } /** * debugging aide */ static rsRetVal dockerContLogsInstPrint(docker_cont_logs_inst_t *pThis) { DEFiRet; DBGPRINTF("\t container id: %s\n", pThis->id); char *pUrl = NULL; curl_easy_getinfo(pThis->logsReq->curl, CURLINFO_EFFECTIVE_URL, &pUrl); DBGPRINTF("\t container url: %s\n", pUrl); RETiRet; } static void dockerContLogsInstDestruct(docker_cont_logs_inst_t *pThis) { if (pThis) { if (pThis->id) { free((void *)pThis->id); } if (pThis->container_info) { dockerContainerInfoDestruct(pThis->container_info); } if (pThis->logsReq) { dockerContLogsReqDestruct(pThis->logsReq); } if (pThis->start_regex) { free(pThis->start_regex); regfree(&pThis->start_preg); } free(pThis); } } static rsRetVal parseLabels(docker_cont_logs_inst_t *inst, const uchar *json) { DEFiRet; /* parse out if we need to do special handling for mult-line */ DBGPRINTF("%s() - parsing json=%s\n", __FUNCTION__, json); struct fjson_object *json_obj = fjson_tokener_parse((const char *)json); if (json_obj == NULL || !fjson_object_is_type(json_obj, fjson_type_object)) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imdocker: ignoring malformed container labels payload"); FINALIZE; } struct fjson_object_iterator it = fjson_object_iter_begin(json_obj); struct fjson_object_iterator itEnd = fjson_object_iter_end(json_obj); while (!fjson_object_iter_equal(&it, &itEnd)) { if (Debug) { DBGPRINTF("%s - \t%s: '%s'\n", __FUNCTION__, fjson_object_iter_peek_name(&it), fjson_object_get_string(fjson_object_iter_peek_value(&it))); } if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_LABEL_KEY_STARTREGEX) == 0) { CHKmalloc(inst->start_regex = (uchar *)strdup(fjson_object_get_string(fjson_object_iter_peek_value(&it)))); // compile the regex for future use. int err = regcomp(&inst->start_preg, fjson_object_get_string(fjson_object_iter_peek_value(&it)), REG_EXTENDED); if (err != 0) { char errbuf[512]; regerror(err, &inst->start_preg, errbuf, sizeof(errbuf)); LogError(0, err, "%s() - error in startregex compile: %s", __FUNCTION__, errbuf); ABORT_FINALIZE(RS_RET_ERR); } } fjson_object_iter_next(&it); } finalize_it: if (json_obj) { json_object_put(json_obj); } RETiRet; } static rsRetVal dockerContLogsInstNew(docker_cont_logs_inst_t **ppThis, const char *id, docker_container_info_t *container_info, SubmitMsgFuncPtr submitMsg) { DEFiRet; docker_cont_logs_inst_t *pThis = NULL; CHKmalloc(pThis = calloc(1, sizeof(docker_cont_logs_inst_t))); CHKmalloc(pThis->id = strdup((char *)id)); rs_cstr_copy(pThis->short_id, (const char *)id, sizeof(pThis->short_id)); CHKiRet(dockerContLogsReqNew(&pThis->logsReq, submitMsg)); /* make a copy */ if (container_info) { CHKiRet(dockerContainerInfoNew(&pThis->container_info)); if (container_info->image) { CHKmalloc(pThis->container_info->image = (uchar *)strdup((char *)container_info->image)); } if (container_info->image_id) { CHKmalloc(pThis->container_info->image_id = (uchar *)strdup((char *)container_info->image_id)); } if (container_info->name) { const char *pname = (const char *)container_info->name; /* removes un-needed characters */ CHKmalloc(pThis->container_info->name = (uchar *)dupDockerContainerName(pname)); } if (container_info->json_str_labels) { CHKmalloc(pThis->container_info->json_str_labels = (uchar *)strdup((char *)container_info->json_str_labels)); } pThis->container_info->created = container_info->created; } pThis->start_regex = NULL; pThis->prevSegEnd = 0; /* initialize based on labels found */ if (pThis->container_info && pThis->container_info->json_str_labels) { CHKiRet(parseLabels(pThis, pThis->container_info->json_str_labels)); } *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { if (pThis) { dockerContLogsInstDestruct(pThis); } } RETiRet; } static rsRetVal dockerContLogsInstSetUrl(docker_cont_logs_inst_t *pThis, CURLM *curlm, const char *pUrl) { DEFiRet; CURLcode ccode = CURLE_OK; CURLMcode mcode = CURLM_OK; if (curlm) { docker_cont_logs_req_t *req = pThis->logsReq; if (!runModConf->dockerApiAddr) { ccode = curl_easy_setopt(req->curl, CURLOPT_UNIX_SOCKET_PATH, runModConf->dockerApiUnixSockAddr); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_UNIX_SOCKET_PATH) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } } ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEFUNCTION, imdocker_container_logs_curlCB); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEFUNCTION) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEDATA, pThis); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEDATA) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } ccode = curl_easy_setopt(pThis->logsReq->curl, CURLOPT_URL, pUrl); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imdocker: could not set url - %d:%s\n", ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } ccode = curl_easy_setopt(pThis->logsReq->curl, CURLOPT_PRIVATE, pThis->id); if (ccode != CURLE_OK) { LogError(0, RS_RET_ERR, "imdocker: could not set private data - %d:%s\n", ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } mcode = curl_multi_add_handle(curlm, pThis->logsReq->curl); if (mcode != CURLM_OK) { LogError(0, RS_RET_ERR, "imdocker: error curl_multi_add_handle ret- %d:%s\n", mcode, curl_multi_strerror(mcode)); ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (ccode != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); } RETiRet; } static rsRetVal dockerContLogsInstSetUrlById(sbool isInit, docker_cont_logs_inst_t *pThis, CURLM *curlm, const char *containerId) { DEFiRet; char *url = NULL; const uchar *container_log_options = runModConf->getContainerLogOptionsWithoutTail; if (isInit || !runModConf->retrieveNewLogsFromStart) { container_log_options = runModConf->getContainerLogOptions; } const uchar *pApiAddr = (uchar *)"http:"; if (runModConf->dockerApiAddr) { pApiAddr = runModConf->dockerApiAddr; } CHKiRet(allocContainerLogsUrl(&url, pApiAddr, runModConf->apiVersionStr, containerId, container_log_options)); DBGPRINTF("%s() - url: %s\n", __FUNCTION__, url); CHKiRet(dockerContLogsInstSetUrl(pThis, curlm, url)); finalize_it: free(url); RETiRet; } /* special destructor for hashtable object. */ static void dockerContLogReqsDestructForHashtable(void *pData) { docker_cont_logs_inst_t *pThis = (docker_cont_logs_inst_t *)pData; dockerContLogsInstDestruct(pThis); } static rsRetVal dockerContLogReqsNew(docker_cont_log_instances_t **ppThis) { DEFiRet; docker_cont_log_instances_t *pThis = calloc(1, sizeof(docker_cont_log_instances_t)); CHKmalloc(pThis); CHKmalloc(pThis->ht_container_log_insts = create_hashtable(7, hash_from_string, key_equals_string, dockerContLogReqsDestructForHashtable)); CHKmalloc(pThis->ht_seen_container_ids = create_hashtable(7, hash_from_string, key_equals_string, NULL)); CHKiConcCtrl(pthread_mutex_init(&pThis->mut, NULL)); pThis->curlm = curl_multi_init(); if (!pThis->curlm) { ABORT_FINALIZE(RS_RET_ERR); } *ppThis = pThis; finalize_it: if (iRet != RS_RET_OK) { if (pThis) { dockerContLogReqsDestruct(pThis); } } RETiRet; } static rsRetVal dockerContLogReqsDestruct(docker_cont_log_instances_t *pThis) { DEFiRet; if (pThis) { if (pThis->ht_container_log_insts) { pthread_mutex_lock(&pThis->mut); hashtable_destroy(pThis->ht_container_log_insts, 1); pthread_mutex_unlock(&pThis->mut); } if (pThis->ht_seen_container_ids) { pthread_mutex_lock(&pThis->mut); hashtable_destroy(pThis->ht_seen_container_ids, 0); pthread_mutex_unlock(&pThis->mut); } if (pThis->last_container_id) { free(pThis->last_container_id); } curl_multi_cleanup(pThis->curlm); pthread_mutex_destroy(&pThis->mut); free(pThis); } RETiRet; } /* NOTE: not thread safe - used internally to update container log requests */ static rsRetVal dockerContLogReqsGet(docker_cont_log_instances_t *pThis, docker_cont_logs_inst_t **ppContLogsInst, const char *id) { DEFiRet; if (ppContLogsInst && id) { docker_cont_logs_inst_t *pSearchObj = hashtable_search(pThis->ht_container_log_insts, (void *)id); if (!pSearchObj) { return RS_RET_NOT_FOUND; } *ppContLogsInst = pSearchObj; } RETiRet; } /* debug print * * NOTE: not thread safe * */ static rsRetVal dockerContLogReqsPrint(docker_cont_log_instances_t *pThis) { DEFiRet; int count = 0; count = hashtable_count(pThis->ht_container_log_insts); if (count) { int ret = 0; struct hashtable_itr *itr = hashtable_iterator(pThis->ht_container_log_insts); DBGPRINTF("%s() - All container instances, count=%d...\n", __FUNCTION__, count); do { docker_cont_logs_inst_t *pObj = hashtable_iterator_value(itr); dockerContLogsInstPrint(pObj); ret = hashtable_iterator_advance(itr); } while (ret); free(itr); DBGPRINTF("End of container instances.\n"); } RETiRet; } /* NOTE: not thread safe */ static rsRetVal dockerContLogReqsAdd(docker_cont_log_instances_t *pThis, docker_cont_logs_inst_t *pContLogsReqInst) { DEFiRet; uchar *keyName = NULL; if (!pContLogsReqInst) { return RS_RET_ERR; } CHKmalloc(keyName = (uchar *)strdup((char *)pContLogsReqInst->id)); docker_cont_logs_inst_t *pFind; if (RS_RET_NOT_FOUND == dockerContLogReqsGet(pThis, &pFind, (void *)keyName)) { if (!hashtable_insert(pThis->ht_container_log_insts, keyName, pContLogsReqInst)) { ABORT_FINALIZE(RS_RET_ERR); } keyName = NULL; } finalize_it: free(keyName); RETiRet; } static rsRetVal dockerContLogReqsRemove(docker_cont_log_instances_t *pThis, const char *id) { DEFiRet; if (pThis && id) { CHKiConcCtrl(pthread_mutex_lock(&pThis->mut)); docker_cont_logs_inst_t *pRemoved = hashtable_remove(pThis->ht_container_log_insts, (void *)id); pthread_mutex_unlock(&pThis->mut); if (pRemoved) { dockerContLogsInstDestruct(pRemoved); } else { iRet = RS_RET_NOT_FOUND; } } finalize_it: RETiRet; } static rsRetVal dockerContLogReqsRememberId(struct hashtable *table, const char *id) { DEFiRet; uchar *keyName = NULL; if (table && id && hashtable_search(table, (void *)id) == NULL) { CHKmalloc(keyName = (uchar *)strdup(id)); if (!hashtable_insert(table, keyName, keyName)) { ABORT_FINALIZE(RS_RET_ERR); } keyName = NULL; } finalize_it: free(keyName); RETiRet; } static rsRetVal dockerContLogReqsRememberSeen(docker_cont_log_instances_t *pThis, const char *id) { return dockerContLogReqsRememberId(pThis ? pThis->ht_seen_container_ids : NULL, id); } static rsRetVal dockerContLogReqsPruneSeen(docker_cont_log_instances_t *pThis, struct hashtable *ht_current_ids) { DEFiRet; int ret = 0; struct hashtable_itr *itr = NULL; if (!pThis || !pThis->ht_seen_container_ids || !ht_current_ids || hashtable_count(pThis->ht_seen_container_ids) == 0) { FINALIZE; } CHKmalloc(itr = hashtable_iterator(pThis->ht_seen_container_ids)); do { char *id = hashtable_iterator_key(itr); if (hashtable_search(ht_current_ids, id) == NULL) { DBGPRINTF("prune stale seen container %s\n", id); ret = hashtable_iterator_remove(itr); } else { ret = hashtable_iterator_advance(itr); } } while (ret); finalize_it: free(itr); RETiRet; } static rsRetVal dockerContLogReqsUpdateLastContainer(docker_cont_log_instances_t *pThis, const char *containerId, uint64_t created) { DEFiRet; uchar *new_last_container_id = NULL; if (pThis && containerId && pThis->last_container_created < created) { CHKmalloc(new_last_container_id = (uchar *)strdup(containerId)); pThis->last_container_created = created; free(pThis->last_container_id); pThis->last_container_id = new_last_container_id; new_last_container_id = NULL; DBGPRINTF("last_container_id updated: ('%s', %u)\n", pThis->last_container_id, (unsigned)pThis->last_container_created); } finalize_it: free(new_last_container_id); RETiRet; } static rsRetVal dockerContLogReqsClearLastContainer(docker_cont_log_instances_t *pThis) { DEFiRet; if (pThis) { CHKiConcCtrl(pthread_mutex_lock(&pThis->mut)); free(pThis->last_container_id); pThis->last_container_id = NULL; pThis->last_container_created = 0; pthread_mutex_unlock(&pThis->mut); } finalize_it: RETiRet; } static rsRetVal dockerContainerInfoNew(docker_container_info_t **ppThis) { DEFiRet; docker_container_info_t *pThis = calloc(1, sizeof(docker_container_info_t)); CHKmalloc(pThis); *ppThis = pThis; finalize_it: RETiRet; } static void dockerContainerInfoDestruct(docker_container_info_t *pThis) { if (pThis) { if (pThis->image_id) { free(pThis->image_id); } if (pThis->image) { free(pThis->image); } if (pThis->name) { free(pThis->name); } if (pThis->json_str_labels) { free(pThis->json_str_labels); } free(pThis); } } BEGINbeginCnfLoad CODESTARTbeginCnfLoad; dbgprintf("imdocker: beginCnfLoad\n"); loadModConf = pModConf; pModConf->pConf = pConf; /* init our settings */ loadModConf->iPollInterval = DFLT_pollingInterval; /* in seconds */ loadModConf->retrieveNewLogsFromStart = DFLT_retrieveNewLogsFromStart; loadModConf->containersLimit = DFLT_containersLimit; loadModConf->trimLineOverBytes = DFLT_trimLineOverBytes; loadModConf->bEscapeLf = DFLT_bEscapeLF; /* Use the default url */ loadModConf->apiVersionStr = NULL; loadModConf->dockerApiUnixSockAddr = NULL; loadModConf->dockerApiAddr = NULL; loadModConf->listContainersOptions = NULL; loadModConf->getContainerLogOptions = NULL; loadModConf->getContainerLogOptionsWithoutTail = NULL; loadModConf->iDfltFacility = DFLT_FACILITY; loadModConf->iDfltSeverity = DFLT_SEVERITY; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; char *buf = NULL; cstr_t *option_cstr = NULL; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for imdocker:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { dbgprintf("%s() - iteration %d\n", __FUNCTION__, i); dbgprintf("%s() - modpblk descr: %s\n", __FUNCTION__, modpblk.descr[i].name); if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "pollinginterval")) { loadModConf->iPollInterval = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "containterlimit")) { loadModConf->containersLimit = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "trimlineoverbytes")) { loadModConf->trimLineOverBytes = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "listcontainersoptions")) { CHKmalloc(loadModConf->listContainersOptions = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "getcontainerlogoptions")) { CHKmalloc(loadModConf->getContainerLogOptions = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); /* also initialize the non-tail version */ CHKmalloc(buf = strdup((char *)loadModConf->getContainerLogOptions)); CHKiRet(rsCStrConstruct(&option_cstr)); const char *search_str = "tail="; size_t search_str_len = strlen(search_str); char *token = strtok(buf, "&"); while (token != NULL) { if (strncmp(token, search_str, search_str_len) == 0) { token = strtok(NULL, "&"); continue; } const rs_cstr_part_t parts[] = {{(const uchar *)token, strlen(token)}, {UCHAR_CONSTANT("&"), 1}}; CHKiRet(rsCStrAppendParts(option_cstr, parts, sizeof(parts) / sizeof(parts[0]))); token = strtok(NULL, "&"); } cstrFinalize(option_cstr); CHKiRet(cstrConvSzStrAndDestruct(&option_cstr, &loadModConf->getContainerLogOptionsWithoutTail, 0)); free(buf); buf = NULL; } else if (!strcmp(modpblk.descr[i].name, "dockerapiunixsockaddr")) { CHKmalloc(loadModConf->dockerApiUnixSockAddr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "dockerapiaddr")) { CHKmalloc(loadModConf->dockerApiAddr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "apiversionstr")) { CHKmalloc(loadModConf->apiVersionStr = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "retrievenewlogsfromstart")) { loadModConf->retrieveNewLogsFromStart = (sbool)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "defaultseverity")) { loadModConf->iDfltSeverity = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "defaultfacility")) { loadModConf->iDfltFacility = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "escapelf")) { loadModConf->bEscapeLf = (sbool)pvals[i].val.d.n; } else { LogError(0, RS_RET_INVALID_PARAMS, "imdocker: program error, non-handled " "param '%s' in setModCnf\n", modpblk.descr[i].name); } } /* disable legacy module-global config directives */ bLegacyCnfModGlobalsPermitted = 0; finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); if (option_cstr != NULL) rsCStrDestruct(&option_cstr); free(buf); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; if (!loadModConf->dockerApiUnixSockAddr) { CHKmalloc(loadModConf->dockerApiUnixSockAddr = (uchar *)strdup(DFLT_dockerAPIUnixSockAddr)); } if (!loadModConf->apiVersionStr) { CHKmalloc(loadModConf->apiVersionStr = (uchar *)strdup(DFLT_apiVersionStr)); } if (!loadModConf->listContainersOptions) { CHKmalloc(loadModConf->listContainersOptions = (uchar *)strdup(DFLT_listContainersOptions)); } if (!loadModConf->getContainerLogOptions) { CHKmalloc(loadModConf->getContainerLogOptions = (uchar *)strdup(DFLT_getContainerLogOptions)); } if (!loadModConf->getContainerLogOptionsWithoutTail) { CHKmalloc(loadModConf->getContainerLogOptionsWithoutTail = (uchar *)strdup(DFLT_getContainerLogOptionsWithoutTail)); } runModConf = loadModConf; /* support statistics gathering */ CHKiRet(statsobj.Construct(&modStats)); CHKiRet(statsobj.SetName(modStats, UCHAR_CONSTANT("imdocker"))); CHKiRet(statsobj.SetOrigin(modStats, UCHAR_CONSTANT("imdocker"))); STATSCOUNTER_INIT(ctrSubmit, mutCtrSubmit); CHKiRet( statsobj.AddCounter(modStats, UCHAR_CONSTANT("submitted"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrSubmit)); STATSCOUNTER_INIT(ctrLostRatelimit, mutCtrLostRatelimit); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("ratelimit.discarded"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrLostRatelimit)); STATSCOUNTER_INIT(ctrCurlError, mutCtrCurlError); CHKiRet(statsobj.AddCounter(modStats, UCHAR_CONSTANT("curl.errors"), ctrType_IntCtr, CTR_FLAG_RESETTABLE, &ctrCurlError)); CHKiRet(statsobj.ConstructFinalize(modStats)); /* end stats */ finalize_it: ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; if (loadModConf->dockerApiUnixSockAddr) { free(loadModConf->dockerApiUnixSockAddr); } if (loadModConf->dockerApiAddr) { free(loadModConf->dockerApiAddr); } if (loadModConf->apiVersionStr) { free(loadModConf->apiVersionStr); } if (loadModConf->getContainerLogOptions) { free(loadModConf->getContainerLogOptions); } if (loadModConf->getContainerLogOptionsWithoutTail) { free(loadModConf->getContainerLogOptionsWithoutTail); } if (loadModConf->listContainersOptions) { free(loadModConf->listContainersOptions); } statsobj.Destruct(&modStats); ENDfreeCnf static rsRetVal addDockerMetaData(const uchar *container_id, docker_container_info_t *pinfo, smsg_t *pMsg) { const uchar *names[5] = { (const uchar *)DOCKER_CONTAINER_ID_PARSE_NAME, (const uchar *)DOCKER_CONTAINER_NAMES_PARSE_NAME, (const uchar *)DOCKER_CONTAINER_IMAGE_PARSE_NAME, (const uchar *)DOCKER_CONTAINER_IMAGEID_PARSE_NAME, (const uchar *)DOCKER_CONTAINER_LABELS_PARSE_NAME}; const uchar *empty_str = (const uchar *)""; const uchar *id = container_id ? container_id : empty_str; const uchar *name = pinfo->name ? pinfo->name : empty_str; const uchar *image = pinfo->image ? pinfo->image : empty_str; const uchar *image_id = pinfo->image_id ? pinfo->image_id : empty_str; const uchar *json_str_labels = pinfo->json_str_labels ? pinfo->json_str_labels : empty_str; const uchar *values[5] = {id, name, image, image_id, json_str_labels}; return msgAddMultiMetadata(pMsg, names, values, 5); } static rsRetVal enqMsg(docker_cont_logs_inst_t *pInst, uchar *msg, size_t len, const uchar *pszTag, int facility, int severity, struct timeval *tp) { struct syslogTime st; smsg_t *pMsg; DEFiRet; if (!msg) { return RS_RET_ERR; } if (tp == NULL) { CHKiRet(msgConstruct(&pMsg)); } else { datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME); CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec)); } MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (char *)msg, len); if (loadModConf->bEscapeLf) { parser.SanitizeMsg(pMsg); } else { /* Perform some of the SanitizeMsg operations here - specifically: * - remove NULL character at end of message. * - drop trailing LFs. * See SanitizeMsg() for more info. */ size_t lenMsg = pMsg->iLenRawMsg; uchar *pszMsg = pMsg->pszRawMsg; if (lenMsg > 0 && pszMsg[lenMsg - 1] == '\0') { DBGPRINTF("dropped NULL at very end of message\n"); lenMsg--; } if (glbl.GetParserDropTrailingLFOnReception(loadModConf->pConf) && lenMsg > 0 && pszMsg[lenMsg - 1] == '\n') { DBGPRINTF("dropped LF at very end of message (DropTrailingLF is set)\n"); lenMsg--; pszMsg[lenMsg] = '\0'; } pMsg->iLenRawMsg = lenMsg; } MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); if (pLocalHostIP) { MsgSetRcvFromIP(pMsg, pLocalHostIP); } MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pszTag, ustrlen(pszTag)); pMsg->iFacility = facility; pMsg->iSeverity = severity; /* docker container metadata */ addDockerMetaData((const uchar *)pInst->short_id, pInst->container_info, pMsg); const char *name = (const char *)pInst->container_info->name; DBGPRINTF("imdocker: %s - %s:%s\n", __FUNCTION__, name, msg); CHKiRet(ratelimitAddMsg(ratelimiter, NULL, pMsg)); STATSCOUNTER_INC(ctrSubmit, mutCtrSubmit); finalize_it: if (iRet == RS_RET_DISCARDMSG) { STATSCOUNTER_INC(ctrLostRatelimit, mutCtrLostRatelimit); iRet = RS_RET_OK; } RETiRet; } static int8_t is_valid_stream_type(int8_t stream_type) { return (dst_invalid < stream_type && stream_type < dst_stream_type_count); } /* For use to get docker specific stream information */ static sbool get_stream_info(const uchar *data, size_t size, int8_t *stream_type, size_t *payload_size) { if (size < 8 || !data || !stream_type || !payload_size) { return 0; } const uchar *pdata = data; *stream_type = pdata[0]; pdata += 4; uint32_t len = 0; memcpy(&len, pdata, sizeof(len)); *payload_size = ntohl(len); return 1; } #ifdef ENABLE_DEBUG_BYTE_BUFFER static void debug_byte_buffer(const uchar *data, size_t size) { if (Debug) { DBGPRINTF("%s() - ENTER, size=%lu\n", __FUNCTION__, size); for (size_t i = 0; i < size; i++) { DBGPRINTF("0x%02x,", data[i]); } DBGPRINTF("\n"); } } #endif /** * imdocker_container_list_curlCB * * Callback function for CURLOPT_WRITEFUNCTION to get * the results of a docker api call to list all containers. * */ static size_t imdocker_container_list_curlCB(void *data, size_t size, size_t nmemb, void *buffer) { DEFiRet; size_t realsize; uchar *pbuf = NULL; imdocker_buf_t *mem = (imdocker_buf_t *)buffer; if (nmemb != 0 && size > SIZE_MAX / nmemb) ABORT_FINALIZE(RS_RET_ERR); realsize = size * nmemb; if (mem->len == SIZE_MAX || realsize > SIZE_MAX - mem->len - 1) ABORT_FINALIZE(RS_RET_ERR); if ((pbuf = realloc(mem->data, mem->len + realsize + 1)) == NULL) { LogError(errno, RS_RET_ERR, "%s() - realloc failed!\n", __FUNCTION__); ABORT_FINALIZE(RS_RET_ERR); } mem->data = pbuf; mem->data_size = mem->len + realsize + 1; memcpy(&(mem->data[mem->len]), data, realsize); mem->len += realsize; mem->data[mem->len] = 0; #ifdef ENABLE_DEBUG_BYTE_BUFFER debug_byte_buffer((const uchar *)data, realsize); #endif finalize_it: if (iRet != RS_RET_OK) { return 0; } return realsize; } static rsRetVal SubmitMultiLineMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag, size_t len) { DEFiRet; imdocker_buf_t *mem = (imdocker_buf_t *)pBufData->buf; DBGPRINTF("%s() {type=%d, len=%u} %s\n", __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data); uchar *message = (uchar *)mem->data; int facility = loadModConf->iDfltFacility; int severity = pBufData->stream_type == dst_stderr ? LOG_ERR : loadModConf->iDfltSeverity; if (len > mem->len) { LogError(0, RS_RET_ERR, "imdocker: multiline segment length %zu exceeds buffer length %zu", len, mem->len); ABORT_FINALIZE(RS_RET_ERR); } uchar savedChar = mem->data[len]; mem->data[len] = '\0'; const rsRetVal localRet = enqMsg(pInst, message, len, (const uchar *)pszTag, facility, severity, NULL); mem->data[len] = savedChar; CHKiRet(localRet); size_t size = mem->len - len; memmove(mem->data, mem->data + len, size); mem->data[size] = '\0'; mem->len = size; pBufData->bytes_remaining = 0; finalize_it: RETiRet; } static rsRetVal SubmitMsgWithStartRegex(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag) { DEFiRet; imdocker_buf_t *mem = (imdocker_buf_t *)pBufData->buf; /* must be null terminated string */ assert(mem->data[mem->len] == 0 || mem->data[mem->len] == '\0'); const char *thisLine = (const char *)mem->data; if (pInst->prevSegEnd) { thisLine = (const char *)mem->data + pInst->prevSegEnd; } DBGPRINTF("prevSeg: %d, thisLine: '%s'\n", pInst->prevSegEnd, thisLine); DBGPRINTF("line(s) so far: '%s'\n", mem->data); /* check if this line is a start of multi-line message */ regex_t *start_preg = (pInst->start_regex == NULL) ? NULL : &pInst->start_preg; const int isStartMatch = start_preg ? !regexec(start_preg, (char *)thisLine, 0, NULL, 0) : 0; if (isStartMatch && pInst->prevSegEnd != 0) { CHKiRet(SubmitMultiLineMsg(pInst, pBufData, pszTag, pInst->prevSegEnd)); pInst->prevSegEnd = 0; FINALIZE; } else { /* just continue parsing using same buffer */ pInst->prevSegEnd = mem->len; } finalize_it: RETiRet; } static rsRetVal SubmitMsg2(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag) { DEFiRet; imdocker_buf_t *mem = (imdocker_buf_t *)pBufData->buf; DBGPRINTF("%s() - {type=%d, len=%u} %s\n", __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data); if (pInst->start_regex) { CHKiRet(SubmitMsgWithStartRegex(pInst, pBufData, pszTag)); } else { CHKiRet(SubmitMsg(pInst, pBufData, pszTag)); } finalize_it: RETiRet; } static rsRetVal SubmitMsg(docker_cont_logs_inst_t *pInst, docker_cont_logs_buf_t *pBufData, const uchar *pszTag) { DEFiRet; imdocker_buf_t *mem = (imdocker_buf_t *)pBufData->buf; DBGPRINTF("%s() - {type=%d, len=%u} %s\n", __FUNCTION__, pBufData->stream_type, (unsigned int)mem->len, mem->data); uchar *message = mem->data; int facility = loadModConf->iDfltFacility; int severity = pBufData->stream_type == dst_stderr ? LOG_ERR : loadModConf->iDfltSeverity; CHKiRet(enqMsg(pInst, message, mem->len, (const uchar *)pszTag, facility, severity, NULL)); /* clear existing buffer. */ mem->len = 0; memset(mem->data, 0, mem->data_size); pBufData->bytes_remaining = 0; finalize_it: RETiRet; } /** imdocker_container_logs_curlCB * * Callback function for CURLOPT_WRITEFUNCTION, gets container logs * * The main container log stream handler. This function is registerred with curl to * as callback to handle container log streaming. It follows the docker stream protocol * as described in the docker container logs api. As per docker's api documentation, * Docker Stream format: * When the TTY setting is disabled in POST /containers/create, the stream over the * hijacked connected is multiplexed to separate out stdout and stderr. The stream * consists of a series of frames, each containing a header and a payload. * * The header contains the information which the stream writes (stdout or stderr). It also * contains the size of the associated frame encoded in the last four bytes (uint32). * * It is encoded on the first eight bytes like this: * * header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4} * STREAM_TYPE can be: * 0: stdin (is written on stdout) * 1: stdout * 2: stderr * * Docker sends out data in 16KB sized frames, however with the addition of a header * of 8 bytes, a frame may be split into 2 chunks by curl. The 2nd chunk will only * contain enough data to complete the frame (8 leftever bytes). Including the header, * this amounts to 16 bytes; 8 bytes for the header, and 8 bytes for the remaining frame * data. * */ static size_t imdocker_container_logs_curlCB(void *data, size_t size, size_t nmemb, void *buffer) { DEFiRet; const uint8_t frame_size = 8; const char imdocker_eol_char = '\n'; int8_t stream_type = dst_invalid; docker_cont_logs_inst_t *pInst = (docker_cont_logs_inst_t *)buffer; docker_cont_logs_req_t *req = pInst->logsReq; size_t realsize; const uchar *pdata = data; size_t write_size = 0; if (nmemb != 0 && size > SIZE_MAX / nmemb) ABORT_FINALIZE(RS_RET_ERR); realsize = size * nmemb; #ifdef ENABLE_DEBUG_BYTE_BUFFER debug_byte_buffer((const uchar *)data, realsize); #endif if (req->data_bufs[dst_stdout]->bytes_remaining || req->data_bufs[dst_stderr]->bytes_remaining) { /* on continuation, stream types should matches with previous */ if (req->data_bufs[dst_stdout]->bytes_remaining) { if (req->data_bufs[dst_stderr]->bytes_remaining != 0) { ABORT_FINALIZE(RS_RET_ERR); } } else if (req->data_bufs[dst_stderr]->bytes_remaining) { if (req->data_bufs[dst_stdout]->bytes_remaining != 0) { ABORT_FINALIZE(RS_RET_ERR); } } stream_type = req->data_bufs[dst_stdout]->bytes_remaining ? dst_stdout : dst_stderr; docker_cont_logs_buf_t *pDataBuf = req->data_bufs[stream_type]; /* read off the remaining bytes */ DBGPRINTF( "Chunk continuation, remaining bytes: type: %d, " "bytes remaining: %u, realsize: %u, data pos: %u\n", stream_type, (unsigned int)pDataBuf->bytes_remaining, (unsigned int)realsize, (unsigned int)pDataBuf->buf->len); write_size = MIN(pDataBuf->bytes_remaining, realsize); CHKiRet(dockerContLogsBufWrite(pDataBuf, pdata, write_size)); /* submit it */ if (pDataBuf->bytes_remaining == 0) { imdocker_buf_t *mem = pDataBuf->buf; if (mem->data[mem->len - 1] == imdocker_eol_char) { const char *szContainerId = NULL; CURLcode ccode; if (CURLE_OK != (ccode = curl_easy_getinfo(req->curl, CURLINFO_PRIVATE, &szContainerId))) { LogError(0, RS_RET_ERR, "imdocker: could not get private data req[%p] - %d:%s\n", req->curl, ccode, curl_easy_strerror(ccode)); ABORT_FINALIZE(RS_RET_ERR); } CHKiRet(req->submitMsg(pInst, pDataBuf, (const uchar *)DOCKER_TAG_NAME)); } } pdata += write_size; } /* not enough room left */ if ((size_t)(pdata - (const uchar *)data) >= realsize) { return (pdata - (const uchar *)data); } size_t payload_size = 0; const uchar *pread = pdata + frame_size; docker_cont_logs_buf_t *pDataBuf = NULL; if (get_stream_info(pdata, realsize, &stream_type, &payload_size) && is_valid_stream_type(stream_type)) { pDataBuf = req->data_bufs[stream_type]; pDataBuf->stream_type = stream_type; pDataBuf->bytes_remaining = payload_size; write_size = MIN(payload_size, realsize - frame_size); } else { /* copy all the data and submit to prevent data loss */ stream_type = req->data_bufs[dst_stderr]->bytes_remaining ? dst_stderr : dst_stdout; pDataBuf = req->data_bufs[stream_type]; pDataBuf->stream_type = stream_type; /* just write everything out */ pDataBuf->bytes_remaining = 0; write_size = realsize; pread = pdata; } /* allocate the expected payload size */ CHKiRet(dockerContLogsBufWrite(pDataBuf, pread, write_size)); if (pDataBuf->bytes_remaining == 0) { DBGPRINTF("%s() - write size is same as payload_size\n", __FUNCTION__); CHKiRet(req->submitMsg(pInst, pDataBuf, (const uchar *)DOCKER_TAG_NAME)); } finalize_it: if (iRet != RS_RET_OK) { return 0; } return realsize; } CURLcode docker_get(imdocker_req_t *req, const char *url) { CURLcode ccode; if (!runModConf->dockerApiAddr) { if ((ccode = curl_easy_setopt(req->curl, CURLOPT_UNIX_SOCKET_PATH, runModConf->dockerApiUnixSockAddr)) != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_UNIX_SOCKET_PATH) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); return ccode; } } if ((ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEFUNCTION, imdocker_container_list_curlCB)) != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEFUNCTION) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); return ccode; } if ((ccode = curl_easy_setopt(req->curl, CURLOPT_WRITEDATA, req->buf)) != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_WRITEDATA) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); return ccode; } if ((ccode = curl_easy_setopt(req->curl, CURLOPT_URL, url)) != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); LogError(0, RS_RET_ERR, "imdocker: curl_easy_setopt(CURLOPT_URL) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); return ccode; } CURLcode response = curl_easy_perform(req->curl); return response; } static char *dupDockerContainerName(const char *pname) { int len = strlen(pname); if (len >= 2 && *pname == '/') { /* skip '/' character */ return strdup(pname + 1); } else { return strdup(pname); } } static rsRetVal process_json(sbool isInit, const char *json, docker_cont_log_instances_t *pInstances) { DEFiRet; struct fjson_object *json_obj = NULL; struct hashtable *ht_current_container_ids = NULL; int mut_locked = 0; DBGPRINTF("%s() - parsing json=%s\n", __FUNCTION__, json); if (!pInstances) { ABORT_FINALIZE(RS_RET_OK); } json_obj = fjson_tokener_parse(json); if (!json_obj || !fjson_object_is_type(json_obj, fjson_type_array)) { ABORT_FINALIZE(RS_RET_OK); } int length = fjson_object_array_length(json_obj); CHKmalloc(ht_current_container_ids = create_hashtable(7, hash_from_string, key_equals_string, NULL)); /* LOCK the update process. */ CHKiConcCtrl(pthread_mutex_lock(&pInstances->mut)); mut_locked = 1; for (int i = 0; i < length; i++) { fjson_object *p_json_elm = json_object_array_get_idx(json_obj, i); DBGPRINTF("element: %d...\n", i); if (p_json_elm) { const char *containerId = NULL; docker_container_info_t containerInfo = { .name = NULL, .image = NULL, .image_id = NULL, .created = 0, .json_str_labels = NULL}; struct fjson_object_iterator it = fjson_object_iter_begin(p_json_elm); struct fjson_object_iterator itEnd = fjson_object_iter_end(p_json_elm); while (!fjson_object_iter_equal(&it, &itEnd)) { if (Debug) { DBGPRINTF("\t%s: '%s'\n", fjson_object_iter_peek_name(&it), fjson_object_get_string(fjson_object_iter_peek_value(&it))); } if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_ID_PARSE_NAME) == 0) { containerId = fjson_object_get_string(fjson_object_iter_peek_value(&it)); } else if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_NAMES_PARSE_NAME) == 0) { int names_array_length = fjson_object_array_length(fjson_object_iter_peek_value(&it)); if (names_array_length) { fjson_object *names_elm = json_object_array_get_idx(fjson_object_iter_peek_value(&it), 0); containerInfo.name = (uchar *)fjson_object_get_string(names_elm); } } else if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_IMAGE_PARSE_NAME) == 0) { containerInfo.image = (uchar *)fjson_object_get_string(fjson_object_iter_peek_value(&it)); } else if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_IMAGEID_PARSE_NAME) == 0) { containerInfo.image_id = (uchar *)fjson_object_get_string(fjson_object_iter_peek_value(&it)); } else if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_CREATED_PARSE_NAME) == 0) { containerInfo.created = fjson_object_get_int64(fjson_object_iter_peek_value(&it)); } else if (strcmp(fjson_object_iter_peek_name(&it), DOCKER_CONTAINER_LABELS_PARSE_NAME) == 0) { containerInfo.json_str_labels = (uchar *)fjson_object_get_string(fjson_object_iter_peek_value(&it)); DBGPRINTF("labels: %s\n", containerInfo.json_str_labels); } fjson_object_iter_next(&it); } if (containerId) { CHKiRet(dockerContLogReqsRememberId(ht_current_container_ids, containerId)); CHKiRet(dockerContLogReqsUpdateLastContainer(pInstances, containerId, containerInfo.created)); if (hashtable_search(pInstances->ht_seen_container_ids, (void *)containerId) != NULL) { DBGPRINTF("skip already seen container %s\n", containerId); continue; } docker_cont_logs_inst_t *pInst = NULL; iRet = dockerContLogReqsGet(pInstances, &pInst, containerId); if (iRet == RS_RET_NOT_FOUND) { #ifdef USE_MULTI_LINE if (dockerContLogsInstNew(&pInst, containerId, &containerInfo, SubmitMsg2) #else if (dockerContLogsInstNew(&pInst, containerId, &containerInfo, SubmitMsg) #endif == RS_RET_OK) { iRet = dockerContLogsInstSetUrlById(isInit, pInst, pInstances->curlm, containerId); if (iRet != RS_RET_OK) { dockerContLogsInstDestruct(pInst); pInst = NULL; ABORT_FINALIZE(iRet); } iRet = dockerContLogReqsAdd(pInstances, pInst); if (iRet != RS_RET_OK) { dockerContLogsInstDestruct(pInst); pInst = NULL; ABORT_FINALIZE(iRet); } CHKiRet(dockerContLogReqsRememberSeen(pInstances, containerId)); pInst = NULL; } } } } } CHKiRet(dockerContLogReqsPruneSeen(pInstances, ht_current_container_ids)); finalize_it: if (mut_locked) { pthread_mutex_unlock(&pInstances->mut); } if (ht_current_container_ids) { hashtable_destroy(ht_current_container_ids, 0); } if (json_obj) { json_object_put(json_obj); } RETiRet; } static sbool containerListErrorReferencesId(const char *json, const char *id) { sbool referencesId = 0; struct fjson_object *json_obj = NULL; struct fjson_object *message_obj = NULL; if (json == NULL || id == NULL) { goto done; } json_obj = fjson_tokener_parse(json); if (!json_obj || !fjson_object_is_type(json_obj, fjson_type_object)) { goto done; } if (!fjson_object_object_get_ex(json_obj, "message", &message_obj)) { goto done; } const char *const message = fjson_object_get_string(message_obj); referencesId = message != NULL && strstr(message, id) != NULL; done: if (json_obj) { json_object_put(json_obj); } return referencesId; } static rsRetVal getContainerIds(sbool isInit, docker_cont_log_instances_t *pInstances, const char *url, const char *sinceId, sbool *const pSinceRejected) { DEFiRet; imdocker_req_t *req = NULL; if (pSinceRejected != NULL) { *pSinceRejected = 0; } CHKiRet(imdockerReqNew(&req)); CURLcode response = docker_get(req, url); if (response != CURLE_OK) { DBGPRINTF("%s() - curl response: %d\n", __FUNCTION__, response); ABORT_FINALIZE(RS_RET_ERR); } if (pSinceRejected != NULL) { long http_status = 0; curl_easy_getinfo(req->curl, CURLINFO_RESPONSE_CODE, &http_status); if (http_status == 404 && containerListErrorReferencesId((const char *)req->buf->data, sinceId)) { *pSinceRejected = 1; ABORT_FINALIZE(RS_RET_OK); } } CHKiRet(process_json(isInit, (const char *)req->buf->data, pInstances)); finalize_it: if (req) { imdockerReqDestruct(req); } RETiRet; } static rsRetVal getContainerIdsAndAppend(sbool isInit, docker_cont_log_instances_t *pInstances) { DEFiRet; char *url = NULL; const uchar *pApiAddr = (uchar *)"http:"; if (runModConf->dockerApiAddr) { pApiAddr = runModConf->dockerApiAddr; } if (pInstances->last_container_id) { sbool sinceRejected = 0; CHKiRet(allocContainersListUrl(&url, pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions, pInstances->last_container_id)); DBGPRINTF("listcontainers url: %s\n", url); CHKiRet(getContainerIds(isInit, pInstances, (const char *)url, (const char *)pInstances->last_container_id, &sinceRejected)); if (sinceRejected) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imdocker: Docker rejected the last-seen container id; retrying container discovery without the " "since filter and ignoring containers already seen"); CHKiRet(dockerContLogReqsClearLastContainer(pInstances)); free(url); url = NULL; CHKiRet(allocContainersListUrl(&url, pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions, NULL)); } else { goto after_get_container_ids; } } else { CHKiRet( allocContainersListUrl(&url, pApiAddr, runModConf->apiVersionStr, runModConf->listContainersOptions, NULL)); } DBGPRINTF("listcontainers url: %s\n", url); CHKiRet(getContainerIds(isInit, pInstances, (const char *)url, NULL, NULL)); after_get_container_ids: if (Debug) { dockerContLogReqsPrint(pInstances); } finalize_it: free(url); RETiRet; } static void cleanupCompletedContainerRequests(docker_cont_log_instances_t *pInstances) { // clean up int rc = 0, msgs_left = 0; CURLMsg *msg = NULL; CURL *pCurl; while ((msg = curl_multi_info_read(pInstances->curlm, &msgs_left))) { if (msg->msg == CURLMSG_DONE) { pCurl = msg->easy_handle; rc = msg->data.result; if (rc != CURLE_OK) { STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); LogError(0, RS_RET_ERR, "imdocker: %s() - curl error code: %d:%s\n", __FUNCTION__, rc, curl_multi_strerror(rc)); continue; } CURLcode ccode; if (Debug) { long http_status = 0; curl_easy_getinfo(pCurl, CURLINFO_RESPONSE_CODE, &http_status); DBGPRINTF("http status: %lu\n", http_status); } curl_multi_remove_handle(pInstances->curlm, pCurl); const char *szContainerId = NULL; if ((ccode = curl_easy_getinfo(pCurl, CURLINFO_PRIVATE, &szContainerId)) == CURLE_OK) { DBGPRINTF("container disconnected: %s\n", szContainerId); dockerContLogReqsRemove(pInstances, szContainerId); DBGPRINTF("container removed...\n"); } else { LogError(0, RS_RET_ERR, "imdocker: private data not found " "curl_easy_setopt(CURLINFO_PRIVATE) error - %d:%s\n", ccode, curl_easy_strerror(ccode)); STATSCOUNTER_INC(ctrCurlError, mutCtrCurlError); } } } } static rsRetVal processAndPollContainerLogs(docker_cont_log_instances_t *pInstances) { DEFiRet; int count = 0; count = hashtable_count(pInstances->ht_container_log_insts); DBGPRINTF("%s() - container instances: %d\n", __FUNCTION__, count); int still_running = 0; curl_multi_perform(pInstances->curlm, &still_running); do { int numfds = 0; int res = curl_multi_wait(pInstances->curlm, NULL, 0, 1000, &numfds); if (res != CURLM_OK) { LogError(0, RS_RET_ERR, "error: curl_multi_wait() numfds=%d, res=%d:%s\n", numfds, res, curl_multi_strerror(res)); return res; } int prev_still_running = still_running; curl_multi_perform(pInstances->curlm, &still_running); if (prev_still_running > still_running) { cleanupCompletedContainerRequests(pInstances); } } while (still_running && glbl.GetGlobalInputTermState() == 0); cleanupCompletedContainerRequests(pInstances); RETiRet; } static void *getContainersTask(void *pdata) { docker_cont_log_instances_t *pInstances = (docker_cont_log_instances_t *)pdata; while (glbl.GetGlobalInputTermState() == 0) { for (int i = 0; i < runModConf->iPollInterval * 10 && glbl.GetGlobalInputTermState() == 0; ++i) { srSleep(0, 100000); } if (glbl.GetGlobalInputTermState() != 0) { break; } getContainerIdsAndAppend(false, pInstances); } return pdata; } /* This function is called to gather input. */ BEGINrunInput rsRetVal localRet = RS_RET_OK; docker_cont_log_instances_t *pInstances = NULL; pthread_t thrd_id; /* the worker's thread ID */ pthread_attr_t thrd_attr; CURLcode curlRet; int curl_initialized = 0; int get_containers_thread_initialized = 0; time_t now; CODESTARTrunInput; datetime.GetTime(&now); CHKiRet(ratelimitNew(&ratelimiter, "imdocker", NULL)); curlRet = curl_global_init(CURL_GLOBAL_ALL); if (curlRet != CURLE_OK) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "imdocker: curl_global_init failed: %s", curl_easy_strerror(curlRet)); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } curl_initialized = 1; localRet = dockerContLogReqsNew(&pInstances); if (localRet != RS_RET_OK) { return localRet; } pInstances->time_started = now; /* get all current containers now */ CHKiRet(getContainerIdsAndAppend(true, pInstances)); /* using default stacksize */ CHKiConcCtrl(pthread_attr_init(&thrd_attr)); CHKiConcCtrl(pthread_create(&thrd_id, &thrd_attr, getContainersTask, pInstances)); get_containers_thread_initialized = 1; while (glbl.GetGlobalInputTermState() == 0) { CHKiRet(processAndPollContainerLogs(pInstances)); if (glbl.GetGlobalInputTermState() == 0) { /* exited from processAndPollContainerLogs, sleep before retrying */ srSleep(1, 10); } } finalize_it: if (get_containers_thread_initialized) { pthread_join(thrd_id, NULL); pthread_attr_destroy(&thrd_attr); } if (pInstances) { dockerContLogReqsDestruct(pInstances); } if (curl_initialized) { curl_global_cleanup(); } if (ratelimiter) { ratelimitDestruct(ratelimiter); ratelimiter = NULL; } ENDrunInput BEGINwillRun CODESTARTwillRun; ENDwillRun BEGINafterRun CODESTARTafterRun; ENDafterRun BEGINmodExit CODESTARTmodExit; if (pInputName != NULL) prop.Destruct(&pInputName); if (pLocalHostIP != NULL) prop.Destruct(&pLocalHostIP); objRelease(parser, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); DBGPRINTF("imdocker version %s initializing\n", VERSION); /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imdocker"), sizeof("imdocker") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); ENDmodInit rsyslog-8.2608.0/contrib/imdocker/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020043 xustar0030 mtime=1787067504.546321171 30 atime=1787067579.833725391 30 ctime=1787067798.992810739 rsyslog-8.2608.0/contrib/imdocker/Makefile.in0000664000175000017500000006606015241076160017517 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imdocker ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = imdocker_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_imdocker_la_OBJECTS = imdocker_la-imdocker.lo imdocker_la_OBJECTS = $(am_imdocker_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 = imdocker_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imdocker_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imdocker_la-imdocker.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imdocker_la_SOURCES) DIST_SOURCES = $(imdocker_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imdocker.la imdocker_la_SOURCES = imdocker.c imdocker_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(CURL_CFLAGS) $(LIBLOGGING_STDLOG_CFLAGS) imdocker_la_LDFLAGS = -module -avoid-version imdocker_la_LIBADD = $(CURL_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imdocker/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imdocker/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imdocker.la: $(imdocker_la_OBJECTS) $(imdocker_la_DEPENDENCIES) $(EXTRA_imdocker_la_DEPENDENCIES) $(AM_V_CCLD)$(imdocker_la_LINK) -rpath $(pkglibdir) $(imdocker_la_OBJECTS) $(imdocker_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imdocker_la-imdocker.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imdocker_la-imdocker.lo: imdocker.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imdocker_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imdocker_la-imdocker.lo -MD -MP -MF $(DEPDIR)/imdocker_la-imdocker.Tpo -c -o imdocker_la-imdocker.lo `test -f 'imdocker.c' || echo '$(srcdir)/'`imdocker.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imdocker_la-imdocker.Tpo $(DEPDIR)/imdocker_la-imdocker.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imdocker.c' object='imdocker_la-imdocker.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imdocker_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imdocker_la-imdocker.lo `test -f 'imdocker.c' || echo '$(srcdir)/'`imdocker.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imdocker_la-imdocker.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imdocker_la-imdocker.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imkmsg0000644000000000000000000000013215241076623015417 xustar0030 mtime=1787067795.505745758 30 atime=1787067808.786993238 30 ctime=1787067795.505745758 rsyslog-8.2608.0/contrib/imkmsg/0000775000175000017500000000000015241076623015140 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imkmsg/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264017524 xustar0030 mtime=1752569012.327264939 30 atime=1787067434.034005558 30 ctime=1787067795.495745572 rsyslog-8.2608.0/contrib/imkmsg/Makefile.am0000666000175000017500000000035115035412264017171 0ustar00rgerrgerpkglib_LTLIBRARIES = imkmsg.la imkmsg_la_SOURCES = imkmsg.c imkmsg.h imkmsg_la_SOURCES += kmsg.c imkmsg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imkmsg_la_LDFLAGS = -module -avoid-version imkmsg_la_LIBADD = rsyslog-8.2608.0/contrib/imkmsg/PaxHeaders/kmsg.c0000644000000000000000000000013215216464435016605 xustar0030 mtime=1782212893.959265101 30 atime=1787067623.640542242 30 ctime=1787067795.505745758 rsyslog-8.2608.0/contrib/imkmsg/kmsg.c0000664000175000017500000002402115216464435016250 0ustar00rgerrger/* imkmsg driver for Linux /dev/kmsg structured logging * * This contains Linux-specific functionality to read /dev/kmsg * For a general overview, see head comment in imkmsg.c. * This is heavily based on imklog bsd.c file. * * Copyright 2008-2025 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "srUtils.h" #include "debug.h" #include "imkmsg.h" /* globals */ static int fklog = -1; /* kernel log fd */ static int bInInitialReading = 1; /* are we in the initial kmsg reading phase? */ /* Note: There is a problem with kernel log time. * See https://github.com/troglobit/sysklogd/commit/9f6fbb3301e571d8af95f8d771469291384e9e95 * We use the same work-around if bFixKernelStamp is on, and use the kernel log time * only for past records, which we assume to be from recent boot. Later on, we do not * use them but system time. * UNFORTUNATELY, with /dev/kmsg, we always get old messages on startup. That means we * may also pull old messages. We do not address this right now, as for 10 years "old * messages" was pretty acceptable. So we wait until someone complains. Hint: we could * do a seek to the end of kmsg if desired to not pull old messages. * 2023-10-31 rgerhards */ #ifndef _PATH_KLOG #define _PATH_KLOG "/dev/kmsg" #endif /* submit a message to imkmsg Syslog() API. In this function, we parse * necessary information from kernel log line, and make json string * from the rest. */ static void submitSyslog(modConfData_t *const pModConf, const uchar *buf) { size_t offs = 0; struct timeval tv; struct timeval *tp = NULL; struct sysinfo info; unsigned long int timestamp = 0; char name[1024]; char value[1024]; char msg[1024]; syslog_pri_t priority = 0; long int sequnum = 0; struct json_object *json = NULL, *jval; /* create new json object */ json = json_object_new_object(); /* get priority */ for (; isdigit(*buf); buf++) { priority = (priority * 10) + (*buf - '0'); } if (*buf != ',') { json_object_put(json); return; } buf++; /* get messages sequence number and add it to json */ for (; isdigit(*buf); buf++) { sequnum = (sequnum * 10) + (*buf - '0'); } if (*buf != ',') { json_object_put(json); return; } buf++; /* skip , */ jval = json_object_new_int(sequnum); json_object_object_add(json, "sequnum", jval); /* get timestamp */ for (; isdigit(*buf); buf++) { timestamp = (timestamp * 10) + (*buf - '0'); } while (*buf != ';' && *buf != '\0') { buf++; /* skip everything till the first ; */ } if (*buf == '\0') { json_object_put(json); return; } buf++; /* skip ; */ /* get message */ offs = 0; for (; *buf != '\n' && *buf != '\0'; buf++) { if (offs < sizeof(msg) - 1) { msg[offs++] = *buf; } } msg[offs] = '\0'; jval = json_object_new_string((char *)msg); json_object_object_add(json, "msg", jval); if (*buf != '\0') /* message has appended properties, skip \n */ buf++; while (*buf) { /* get name of the property */ buf++; /* skip ' ' */ offs = 0; for (; *buf != '=' && *buf != ' ' && *buf != '\n' && *buf != '\0'; buf++) { if (offs < sizeof(name) - 1) { name[offs++] = *buf; } } name[offs] = '\0'; if (*buf == '\n' || *buf == '\0') break; buf++; /* skip = or ' ' */ ; offs = 0; for (; *buf != '\n' && *buf != '\0'; buf++) { if (offs < sizeof(value) - 1) { value[offs++] = *buf; } } value[offs] = '\0'; if (*buf != '\0') { buf++; /* another property, skip \n */ } jval = json_object_new_string((char *)value); json_object_object_add(json, name, jval); } if ((pModConf->parseKernelStamp == KMSG_PARSE_TS_ALWAYS) || ((pModConf->parseKernelStamp == KMSG_PARSE_TS_STARTUP_ONLY) && bInInitialReading)) { /* calculate timestamp */ sysinfo(&info); gettimeofday(&tv, NULL); /* get boot time */ tv.tv_sec -= info.uptime; tv.tv_sec += timestamp / 1000000; tv.tv_usec += timestamp % 1000000; while (tv.tv_usec < 0) { tv.tv_sec--; tv.tv_usec += 1000000; } while (tv.tv_usec >= 1000000) { tv.tv_sec++; tv.tv_usec -= 1000000; } tp = &tv; } Syslog(priority, (uchar *)msg, tp, json); } /* open the kernel log - will be called inside the willRun() imkmsg entry point */ rsRetVal klogWillRunPrePrivDrop(modConfData_t __attribute__((unused)) * pModConf) { char errmsg[2048]; DEFiRet; fklog = open(_PATH_KLOG, O_RDONLY | O_NONBLOCK, 0); if (fklog < 0) { imkmsgLogIntMsg(LOG_ERR, "imkmsg: cannot open kernel log (%s): %s.", _PATH_KLOG, rs_strerror_r(errno, errmsg, sizeof(errmsg))); ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG); } finalize_it: RETiRet; } /* make sure the kernel log is readable after dropping privileges */ rsRetVal klogWillRunPostPrivDrop(modConfData_t __attribute__((unused)) * pModConf) { char errmsg[2048]; int r; DEFiRet; /* this normally returns EINVAL */ /* on an OpenVZ VM, we get EPERM */ r = read(fklog, NULL, 0); if (r < 0 && errno != EINVAL && errno != EAGAIN && errno != EWOULDBLOCK) { imkmsgLogIntMsg(LOG_ERR, "imkmsg: cannot open kernel log (%s): %s.", _PATH_KLOG, rs_strerror_r(errno, errmsg, sizeof(errmsg))); fklog = -1; ABORT_FINALIZE(RS_RET_ERR_OPEN_KLOG); } finalize_it: RETiRet; } static void change_reads_to_blocking(const int fd) { const int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); } /* Read kernel log while data are available, each read() reads one * record of printk buffer. */ static void readkmsg(modConfData_t *const pModConf) { int i; uchar pRcv[16 * 1024 + 1]; char errmsg[2048]; off_t seek_result = 0; if (pModConf->readMode == KMSG_READMODE_FULL_BOOT) { struct sysinfo info; sysinfo(&info); DBGPRINTF("imkmsg: system uptime is %lld, expected %d\n", (long long)info.uptime, pModConf->expected_boot_complete_secs); if (info.uptime > pModConf->expected_boot_complete_secs) { seek_result = lseek(fklog, 0, SEEK_END); } } else if (pModConf->readMode == KMSG_READMODE_NEW_ONLY) { seek_result = lseek(fklog, 0, SEEK_END); } else if (pModConf->readMode != KMSG_READMODE_FULL_ALWAYS) { imkmsgLogIntMsg(LOG_ERR, "imkmsg: internal program error, " "unknown read mode %d, assuming 'full-always'", pModConf->readMode); } if (seek_result == (off_t)-1) { imkmsgLogIntMsg(LOG_WARNING, "imkmsg: could not seek to requested klog entries - will" "now potentially output all messages"); } for (;;) { dbgprintf("imkmsg waiting for kernel log line\n"); /* every read() from the opened device node receives one record of the printk buffer */ i = read(fklog, pRcv, 8192); if (i > 0) { /* successful read of message of nonzero length */ pRcv[i] = '\0'; } else if (i < 0 && errno == EPIPE) { imkmsgLogIntMsg(LOG_WARNING, "imkmsg: some messages in circular buffer got overwritten"); continue; } else { /* something went wrong - error or zero length message */ if (i < 0) { #if EAGAIN != EWOULDBLOCK if (errno == EAGAIN || errno == EWOULDBLOCK) { #else if (errno == EAGAIN) { #endif DBGPRINTF("imkmsg: initial read done, changing to blocking mode\n"); change_reads_to_blocking(fklog); bInInitialReading = 0; continue; } } if (i < 0 && errno != EINTR && errno != EAGAIN) { /* error occurred */ imkmsgLogIntMsg(LOG_ERR, "imkmsg: error reading kernel log - shutting down: %s", rs_strerror_r(errno, errmsg, sizeof(errmsg))); fklog = -1; } break; } submitSyslog(pModConf, pRcv); } } /* to be called in the module's AfterRun entry point * rgerhards, 2008-04-09 */ rsRetVal klogAfterRun(modConfData_t *pModConf) { DEFiRet; if (fklog != -1) close(fklog); /* Turn on logging of messages to console, but only if a log level was speficied */ if (pModConf->console_log_level != -1) klogctl(7, NULL, 0); RETiRet; } /* to be called in the module's WillRun entry point, this is the main * "message pull" mechanism. * rgerhards, 2008-04-09 */ rsRetVal klogLogKMsg(modConfData_t *const pModConf) { DEFiRet; readkmsg(pModConf); RETiRet; } /* provide the (system-specific) default facility for internal messages * rgerhards, 2008-04-14 */ int klogFacilIntMsg(void) { return LOG_SYSLOG; } rsyslog-8.2608.0/contrib/imkmsg/PaxHeaders/imkmsg.h0000644000000000000000000000013215132733117017131 xustar0030 mtime=1768666703.860619527 30 atime=1787067623.670542801 30 ctime=1787067795.503745721 rsyslog-8.2608.0/contrib/imkmsg/imkmsg.h0000666000175000017500000000512715132733117016604 0ustar00rgerrger/* imkmsg.h * These are the definitions for the kmsg message generation module. * * Copyright 2007-2023 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef IMKLOG_H_INCLUDED #define IMKLOG_H_INCLUDED 1 #include "rsyslog.h" #include "dirty.h" typedef enum _kernel_ts_parse_mods { KMSG_PARSE_TS_OFF = 0, KMSG_PARSE_TS_ALWAYS = 1, KMSG_PARSE_TS_STARTUP_ONLY = 2 } t_kernel_ts_parse_mode; typedef enum _kernel_readmode { KMSG_READMODE_FULL_BOOT = 0, KMSG_READMODE_FULL_ALWAYS = 1, KMSG_READMODE_NEW_ONLY = 2 } t_kernel_readmode; /* we need to have the modConf type present in all submodules */ struct modConfData_s { rsconf_t *pConf; int iFacilIntMsg; uchar *pszPath; int console_log_level; int expected_boot_complete_secs; t_kernel_ts_parse_mode parseKernelStamp; t_kernel_readmode readMode; sbool configSetViaV2Method; }; /* interface to "drivers" * the platform specific drivers must implement these entry points. Only one * driver may be active at any given time, thus we simply rely on the linker * to resolve the addresses. * rgerhards, 2008-04-09 */ rsRetVal klogLogKMsg(modConfData_t *pModConf); rsRetVal klogWillRunPrePrivDrop(modConfData_t *pModConf); rsRetVal klogWillRunPostPrivDrop(modConfData_t *pModConf); rsRetVal klogAfterRun(modConfData_t *pModConf); /* the functions below may be called by the drivers */ rsRetVal imkmsgLogIntMsg(syslog_pri_t priority, const char *fmt, ...) __attribute__((format(printf, 2, 3))); rsRetVal Syslog(syslog_pri_t priority, uchar *msg, struct timeval *tp, struct json_object *json); int klogFacilIntMsg(void); /* prototypes */ extern int klog_getMaxLine(void); /* work-around for klog drivers to get configured max line size */ extern int InitKsyms(modConfData_t *); extern void DeinitKsyms(void); extern int InitMsyms(void); extern void DeinitMsyms(void); extern char *ExpandKadds(char *, char *); extern void SetParanoiaLevel(int); #endif /* #ifndef IMKLOG_H_INCLUDED */ rsyslog-8.2608.0/contrib/imkmsg/PaxHeaders/imkmsg.c0000644000000000000000000000013215241075234017124 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.715580354 30 ctime=1787067795.500745665 rsyslog-8.2608.0/contrib/imkmsg/imkmsg.c0000664000175000017500000002733715241075234016604 0ustar00rgerrger/* The kernel log module. * * This is rsyslog Linux only module for reading structured kernel logs. * Module is based on imklog module so it retains its structure * and other part is currently in kmsg.c file instead of this (imkmsg.c) * For more information see that file. * * To test under Linux: * echo test1 > /dev/kmsg * * Copyright (C) 2008-2023 Adiscon GmbH * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include "dirty.h" #include "cfsysline.h" #include "obj.h" #include "msg.h" #include "module-template.h" #include "datetime.h" #include "imkmsg.h" #include "net.h" #include "glbl.h" #include "prop.h" #include "errmsg.h" #include "unicode-helper.h" MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imkmsg") /* Module static data */ DEF_IMOD_STATIC_DATA; DEFobjCurrIf(datetime) DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(net) /* config settings */ typedef struct configSettings_s { int iFacilIntMsg; /* the facility to use for internal messages (set by driver) */ } configSettings_t; static configSettings_t cs; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current load process */ static int bLegacyCnfModGlobalsPermitted; /* are legacy module-global config parameters permitted? */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = {{"parsekerneltimestamp", eCmdHdlrGetWord, 0}, {"readmode", eCmdHdlrGetWord, 0}, {"expectedbootcompleteseconds", eCmdHdlrPositiveInt, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this module */ static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1 */ static inline void initConfigSettings(void) { cs.iFacilIntMsg = klogFacilIntMsg(); } /* enqueue the the kernel message into the message queue. * The provided msg string is not freed - thus must be done * by the caller. * rgerhards, 2008-04-12 */ static rsRetVal enqMsg(uchar *msg, uchar *pszTag, syslog_pri_t pri, struct timeval *tp, struct json_object *json) { struct syslogTime st; smsg_t *pMsg; DEFiRet; assert(msg != NULL); assert(pszTag != NULL); if (tp == NULL) { CHKiRet(msgConstruct(&pMsg)); } else { datetime.timeval2syslogTime(tp, &st, TIME_IN_LOCALTIME); CHKiRet(msgConstructWithTime(&pMsg, &st, tp->tv_sec)); } MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); MsgSetInputName(pMsg, pInputName); MsgSetRawMsgWOSize(pMsg, (char *)msg); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, pLocalHostIP); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetTAG(pMsg, pszTag, ustrlen(pszTag)); msgSetPRI(pMsg, pri); pMsg->json = json; CHKiRet(submitMsg2(pMsg)); finalize_it: RETiRet; } /* log an imkmsg-internal message * rgerhards, 2008-04-14 */ rsRetVal imkmsgLogIntMsg(syslog_pri_t priority, const char *fmt, ...) { DEFiRet; va_list ap; uchar msgBuf[2048]; /* we use the same size as sysklogd to remain compatible */ va_start(ap, fmt); vsnprintf((char *)msgBuf, sizeof(msgBuf), fmt, ap); va_end(ap); logmsgInternal(NO_ERRCODE, priority, msgBuf, 0); RETiRet; } /* log a message from /dev/kmsg */ rsRetVal Syslog(syslog_pri_t priority, uchar *pMsg, struct timeval *tp, struct json_object *json) { DEFiRet; iRet = enqMsg((uchar *)pMsg, (uchar *)"kernel:", priority, tp, json); RETiRet; } /* helper for some klog drivers which need to know the MaxLine global setting. They can * not obtain it themselfs, because they are no modules and can not query the object hander. * It would probably be a good idea to extend the interface to support it, but so far * we create a (sufficiently valid) work-around. -- rgerhards, 2008-11-24 */ int klog_getMaxLine(void) { return glbl.GetMaxLine(runModConf->pConf); } BEGINrunInput CODESTARTrunInput; /* this is an endless loop - it is terminated when the thread is * signalled to do so. This, however, is handled by the framework, * right into the sleep below. */ while (!thrdGetShallStop(pThrd)) { /* klogLogKMsg() waits for the next kernel message, obtains it * and then submits it to the rsyslog main queue. * rgerhards, 2008-04-09 */ CHKiRet(klogLogKMsg(runModConf)); } finalize_it: ENDrunInput BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; /* init our settings */ pModConf->iFacilIntMsg = klogFacilIntMsg(); pModConf->parseKernelStamp = KMSG_PARSE_TS_STARTUP_ONLY; pModConf->readMode = KMSG_READMODE_FULL_BOOT; pModConf->expected_boot_complete_secs = 90; loadModConf->configSetViaV2Method = 0; bLegacyCnfModGlobalsPermitted = 1; /* init legacy config vars */ initConfigSettings(); ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for imkmsg:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "parsekerneltimestamp")) { if (!es_strconstcmp(pvals[i].val.d.estr, "on") || !es_strconstcmp(pvals[i].val.d.estr, "always")) { loadModConf->parseKernelStamp = KMSG_PARSE_TS_ALWAYS; } else if (!es_strconstcmp(pvals[i].val.d.estr, "startup")) { loadModConf->parseKernelStamp = KMSG_PARSE_TS_STARTUP_ONLY; } else if (!es_strconstcmp(pvals[i].val.d.estr, "off")) { loadModConf->parseKernelStamp = KMSG_PARSE_TS_OFF; } else { char *cstr; CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_PARAM_ERROR, "imkmsg: unknown " "parse mode '%s'", cstr); free(cstr); } } else if (!strcmp(modpblk.descr[i].name, "expectedbootcompleteseconds")) { loadModConf->expected_boot_complete_secs = pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "readmode")) { if (!es_strconstcmp(pvals[i].val.d.estr, "full-boot")) { loadModConf->readMode = KMSG_READMODE_FULL_BOOT; } else if (!es_strconstcmp(pvals[i].val.d.estr, "full-always")) { loadModConf->readMode = KMSG_READMODE_FULL_ALWAYS; } else if (!es_strconstcmp(pvals[i].val.d.estr, "new-only")) { loadModConf->readMode = KMSG_READMODE_NEW_ONLY; } else { char *cstr; CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); LogError(0, RS_RET_PARAM_ERROR, "imkmsg: unknown " "read mode '%s', keeping default setting", cstr); free(cstr); } } else { LogMsg(0, RS_RET_INTERNAL_ERROR, LOG_WARNING, "imkmsg: RSYSLOG BUG, non-handled param '%s' in " "beginCnfLoad\n", modpblk.descr[i].name); } } /* disable legacy module-global config directives */ bLegacyCnfModGlobalsPermitted = 0; loadModConf->configSetViaV2Method = 1; finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; if (!loadModConf->configSetViaV2Method) { /* persist module-specific settings from legacy config system */ loadModConf->iFacilIntMsg = cs.iFacilIntMsg; } loadModConf = NULL; /* done loading */ ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnfPrePrivDrop CODESTARTactivateCnfPrePrivDrop; runModConf = pModConf; iRet = klogWillRunPrePrivDrop(runModConf); ENDactivateCnfPrePrivDrop BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINwillRun CODESTARTwillRun; iRet = klogWillRunPostPrivDrop(runModConf); ENDwillRun BEGINafterRun CODESTARTafterRun; iRet = klogAfterRun(runModConf); ENDafterRun BEGINmodExit CODESTARTmodExit; if (pInputName != NULL) prop.Destruct(&pInputName); if (pLocalHostIP != NULL) prop.Destruct(&pLocalHostIP); /* release objects we used */ objRelease(glbl, CORE_COMPONENT); objRelease(net, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; ENDqueryEtryPt static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { cs.iFacilIntMsg = klogFacilIntMsg(); return RS_RET_OK; } BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(datetime, CORE_COMPONENT)); CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(net, CORE_COMPONENT)); /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.CreateStringProp(&pInputName, UCHAR_CONSTANT("imkmsg"), sizeof("imkmsg") - 1)); CHKiRet(prop.CreateStringProp(&pLocalHostIP, UCHAR_CONSTANT("127.0.0.1"), sizeof("127.0.0.1") - 1)); /* init legacy config settings */ initConfigSettings(); CHKiRet(omsdRegCFSLineHdlr((uchar *)"debugprintkernelsymbols", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbollookup", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogsymbolstwice", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"klogusesyscallinterface", 0, eCmdHdlrGoneAway, NULL, NULL, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit rsyslog-8.2608.0/contrib/imkmsg/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160017535 xustar0030 mtime=1787067504.640322924 30 atime=1787067579.207713717 30 ctime=1787067795.498745628 rsyslog-8.2608.0/contrib/imkmsg/Makefile.in0000664000175000017500000007006315241076160017207 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imkmsg ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) imkmsg_la_DEPENDENCIES = am_imkmsg_la_OBJECTS = imkmsg_la-imkmsg.lo imkmsg_la-kmsg.lo imkmsg_la_OBJECTS = $(am_imkmsg_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 = imkmsg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imkmsg_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imkmsg_la-imkmsg.Plo \ ./$(DEPDIR)/imkmsg_la-kmsg.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imkmsg_la_SOURCES) DIST_SOURCES = $(imkmsg_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imkmsg.la imkmsg_la_SOURCES = imkmsg.c imkmsg.h kmsg.c imkmsg_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) imkmsg_la_LDFLAGS = -module -avoid-version imkmsg_la_LIBADD = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imkmsg/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imkmsg/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imkmsg.la: $(imkmsg_la_OBJECTS) $(imkmsg_la_DEPENDENCIES) $(EXTRA_imkmsg_la_DEPENDENCIES) $(AM_V_CCLD)$(imkmsg_la_LINK) -rpath $(pkglibdir) $(imkmsg_la_OBJECTS) $(imkmsg_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkmsg_la-imkmsg.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imkmsg_la-kmsg.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imkmsg_la-imkmsg.lo: imkmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkmsg_la-imkmsg.lo -MD -MP -MF $(DEPDIR)/imkmsg_la-imkmsg.Tpo -c -o imkmsg_la-imkmsg.lo `test -f 'imkmsg.c' || echo '$(srcdir)/'`imkmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkmsg_la-imkmsg.Tpo $(DEPDIR)/imkmsg_la-imkmsg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imkmsg.c' object='imkmsg_la-imkmsg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkmsg_la-imkmsg.lo `test -f 'imkmsg.c' || echo '$(srcdir)/'`imkmsg.c imkmsg_la-kmsg.lo: kmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imkmsg_la-kmsg.lo -MD -MP -MF $(DEPDIR)/imkmsg_la-kmsg.Tpo -c -o imkmsg_la-kmsg.lo `test -f 'kmsg.c' || echo '$(srcdir)/'`kmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imkmsg_la-kmsg.Tpo $(DEPDIR)/imkmsg_la-kmsg.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='kmsg.c' object='imkmsg_la-kmsg.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imkmsg_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imkmsg_la-kmsg.lo `test -f 'kmsg.c' || echo '$(srcdir)/'`kmsg.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imkmsg_la-imkmsg.Plo -rm -f ./$(DEPDIR)/imkmsg_la-kmsg.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imkmsg_la-imkmsg.Plo -rm -f ./$(DEPDIR)/imkmsg_la-kmsg.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omtcl0000644000000000000000000000013015241076632015244 xustar0029 mtime=1787067802.63287856 30 atime=1787067808.786993238 29 ctime=1787067802.63287856 rsyslog-8.2608.0/contrib/omtcl/0000775000175000017500000000000015241076632014767 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omtcl/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264017353 xustar0030 mtime=1752569012.331237145 30 atime=1787067434.349011436 30 ctime=1787067802.627878467 rsyslog-8.2608.0/contrib/omtcl/Makefile.am0000666000175000017500000000027415035412264017024 0ustar00rgerrgerpkglib_LTLIBRARIES = omtcl.la omtcl_la_SOURCES = omtcl.c omtcl_la_CPPFLAGS = $(RSRT_CFLAGS) $(TCL_INCLUDE_SPEC) omtcl_la_LDFLAGS = -module omtcl_la_LIBADD = $(TCL_LIB_SPEC) EXTRA_DIST = rsyslog-8.2608.0/contrib/omtcl/PaxHeaders/omtcl.c0000644000000000000000000000013115132411300016564 xustar0030 mtime=1768559296.141883663 30 atime=1787067644.778936349 29 ctime=1787067802.63287856 rsyslog-8.2608.0/contrib/omtcl/omtcl.c0000666000175000017500000001036015132411300016233 0ustar00rgerrger/* omtcl.c * invoke a tcl procedure for every message * * NOTE: read comments in module-template.h for more specifics! * * File begun on 2016-05-16 by fcr * * Copyright 2016 Francisco Castro * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" /* work around gcc-7 build problems - acceptable for contributed module */ #pragma GCC diagnostic ignored "-Wundef" #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "tcl.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; DEF_OMOD_STATIC_DATA; typedef struct _instanceData { Tcl_Interp* interp; Tcl_Obj* cmdName; } instanceData; typedef struct wrkrInstanceData { instanceData* pData; } wrkrInstanceData_t; BEGINinitConfVars CODESTARTinitConfVars; ENDinitConfVars BEGINcreateInstance CODESTARTcreateInstance; pData->interp = Tcl_CreateInterp(); pData->cmdName = NULL; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; /* not compatible with message reduction */ ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; if (pData->cmdName != NULL) Tcl_DecrRefCount(pData->cmdName); Tcl_DeleteInterp(pData->interp); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINdoAction Tcl_Obj* objv[2]; CODESTARTdoAction; objv[0] = pWrkrData->pData->cmdName; objv[1] = Tcl_NewStringObj((char*)ppString[0], -1); if (Tcl_EvalObjv(pWrkrData->pData->interp, 2, objv, 0) != TCL_OK) { iRet = RS_RET_ERR; DBGPRINTF("omtcl: %s", Tcl_GetStringResult(pWrkrData->pData->interp)); } ENDdoAction BEGINparseSelectorAct char fileName[PATH_MAX + 1]; char buffer[4096]; CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) if (strncmp((char*)p, ":omtcl:", sizeof(":omtcl:") - 1)) { ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); } p += sizeof(":omtcl:") - 1; if (getSubString(&p, fileName, PATH_MAX + 1, ',') || getSubString(&p, buffer, 4096, ';') || !strlen(buffer)) { LogError(0, RS_RET_INVALID_PARAMS, "Invalid OmTcl parameters"); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } if (*(p - 1) == ';') --p; CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*)"RSYSLOG_FileFormat")); CHKiRet(createInstance(&pData)); pData->cmdName = Tcl_NewStringObj(buffer, -1); Tcl_IncrRefCount(pData->cmdName); // TODO parse arguments: file,procname if (Tcl_EvalFile(pData->interp, fileName) == TCL_ERROR) { LogError(0, RS_RET_CONFIG_ERROR, "Loading Tcl script: %s", Tcl_GetStringResult(pData->interp)); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; INITLegCnfVars; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("omtcl: module compiled with rsyslog version %s.\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/omtcl/PaxHeaders/Makefile.in0000644000000000000000000000013215241076161017365 xustar0030 mtime=1787067505.220333744 30 atime=1787067579.554720188 30 ctime=1787067802.629878505 rsyslog-8.2608.0/contrib/omtcl/Makefile.in0000664000175000017500000006553215241076161017044 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omtcl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omtcl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_omtcl_la_OBJECTS = omtcl_la-omtcl.lo omtcl_la_OBJECTS = $(am_omtcl_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 = omtcl_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omtcl_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omtcl_la-omtcl.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omtcl_la_SOURCES) DIST_SOURCES = $(omtcl_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omtcl.la omtcl_la_SOURCES = omtcl.c omtcl_la_CPPFLAGS = $(RSRT_CFLAGS) $(TCL_INCLUDE_SPEC) omtcl_la_LDFLAGS = -module omtcl_la_LIBADD = $(TCL_LIB_SPEC) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omtcl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omtcl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omtcl.la: $(omtcl_la_OBJECTS) $(omtcl_la_DEPENDENCIES) $(EXTRA_omtcl_la_DEPENDENCIES) $(AM_V_CCLD)$(omtcl_la_LINK) -rpath $(pkglibdir) $(omtcl_la_OBJECTS) $(omtcl_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omtcl_la-omtcl.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omtcl_la-omtcl.lo: omtcl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omtcl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omtcl_la-omtcl.lo -MD -MP -MF $(DEPDIR)/omtcl_la-omtcl.Tpo -c -o omtcl_la-omtcl.lo `test -f 'omtcl.c' || echo '$(srcdir)/'`omtcl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omtcl_la-omtcl.Tpo $(DEPDIR)/omtcl_la-omtcl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omtcl.c' object='omtcl_la-omtcl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omtcl_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omtcl_la-omtcl.lo `test -f 'omtcl.c' || echo '$(srcdir)/'`omtcl.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omtcl_la-omtcl.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omtcl_la-omtcl.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imhiredis0000644000000000000000000000013015241076633016104 xustar0029 mtime=1787067803.38789263 30 atime=1787067808.786993238 29 ctime=1787067803.38789263 rsyslog-8.2608.0/contrib/imhiredis/0000775000175000017500000000000015241076633015627 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imhiredis/PaxHeaders/README0000644000000000000000000000013215131231047017031 xustar0030 mtime=1768239655.582210586 30 atime=1782715518.796788976 30 ctime=1787067803.385892593 rsyslog-8.2608.0/contrib/imhiredis/README0000666000175000017500000000423515131231047016503 0ustar00rgerrgerRedis Input Plugin using hiredis library REQUIREMENTS: * hiredis ( https://github.com/redis/hiredis.git ) USAGE: This plugin has two current "modes" that it supports: 1. "queue" The queue mode will LPOP or RPOP your message from a redis list. Following parameters are required: - mode: Set mode to "queue" to enable the queue mode - key: The key to xPOP on - server: The name or IP address of the redis server - port: The redis listening port Following parameters are optional: - password: If set, the plugin will issue an "AUTH" command before calling xPOP - uselpop: If set to "1", LPOP will be used instead of default RPOP Redis pipelining is used inside the worker thread. The dequeue batch size is configured with the "batchsize" parameter (default is 10). Imhiredis will query Redis every second to see if entries are in the list, if that's the case they will be dequeued continuously by batches of "batchsize elements" until none remains. Due to its balance between polling interval and pipelining and its use of lists, this mode is quite performant and reliable. However, due to the 1 second polling frequency, one may consider using the `subscribe` mode instead if very low latency is required. ``` module(load="imhiredis") input( type="imhiredis" mode="queue" key="vulture" server="127.0.0.1" port="6379" uselpop="1" password="foobar" batchsize="10" ) ``` 2. "subscribe" The subscribe mode will SUBSCRIBE to a redis channel. The "key" parameter is required and will be used for the subscribe channel. Following parameters are required: - mode: Set mode to "subscribe" to enable the subscribe mode - key: The key to subscribe to (aka the "channel") - server: The name or IP address of the redis server - port: The redis listening port Following parameters are optional: - password: If set, the plugin will issue an "AUTH" command before listening to a channel - uselpop: If set to "1", LPOP will be used instead of default RPOP ``` module(load="imhiredis") input( type="imhiredis" mode="subscribe" key="vulture" server="127.0.0.1" port="6379" password="foobar" batchsize="10" ) ``` TODO * TLS support rsyslog-8.2608.0/contrib/imhiredis/PaxHeaders/Makefile.am0000644000000000000000000000013215145046112020207 xustar0030 mtime=1771326538.884011758 30 atime=1787067434.001004942 30 ctime=1787067803.376892425 rsyslog-8.2608.0/contrib/imhiredis/Makefile.am0000664000175000017500000000043615145046112017656 0ustar00rgerrgerpkglib_LTLIBRARIES = imhiredis.la imhiredis_la_SOURCES = imhiredis.c imhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) $(HIREDIS_SSL_CFLAGS) imhiredis_la_LDFLAGS = -module -avoid-version imhiredis_la_LIBADD = $(HIREDIS_LIBS) $(HIREDIS_SSL_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/imhiredis/PaxHeaders/COPYING0000644000000000000000000000013215131231047017204 xustar0030 mtime=1768239655.582210586 30 atime=1782715518.795788959 30 ctime=1787067803.382892537 rsyslog-8.2608.0/contrib/imhiredis/COPYING0000666000175000017500000010437015131231047016657 0ustar00rgerrger GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . rsyslog-8.2608.0/contrib/imhiredis/PaxHeaders/imhiredis.c0000644000000000000000000000013215216464435020307 xustar0030 mtime=1782212893.959265101 30 atime=1782715518.791788891 30 ctime=1787067803.388892648 rsyslog-8.2608.0/contrib/imhiredis/imhiredis.c0000664000175000017500000025436415216464435017771 0ustar00rgerrger/* imhiredis.c * Copyright 2021 aDvens * * This file is contrib for rsyslog. * This input plugin is a log consumer from REDIS * See README for doc * * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * . * * Author: Jérémie Jourdin * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef HIREDIS_SSL #include #endif #include #include #include #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "atomic.h" #include "statsobj.h" #include "unicode-helper.h" #include "prop.h" #include "ruleset.h" #include "glbl.h" #include "cfsysline.h" #include "msg.h" #include "dirty.h" MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imhiredis") /* static data */ DEF_IMOD_STATIC_DATA; #define BATCH_SIZE 10 #define WAIT_TIME_MS 500 #define STREAM_INDEX_STR_BUFSZ 44 /* max stream index text plus NUL */ #define IMHIREDIS_MODE_QUEUE 1 #define IMHIREDIS_MODE_SUBSCRIBE 2 #define IMHIREDIS_MODE_STREAM 3 DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) DEFobjCurrIf(glbl) DEFobjCurrIf(statsobj) typedef struct redisNode_s { sbool isMaster; sbool usesSocket; uchar *socketPath; uchar *server; int port; struct redisNode_s *next; } redisNode; struct instanceConf_s { uchar *password; uchar *key; uchar *modeDescription; uchar *streamConsumerGroup; uchar *streamConsumerName; uchar *streamReadFrom; int streamAutoclaimIdleTime; sbool streamConsumerACK; int mode; uint batchsize; sbool useLPop; #ifdef HIREDIS_SSL sbool use_tls; /* Should we use TLS to connect to redis ? */ char *ca_cert_bundle; /* CA bundle file */ char *ca_cert_dir; /* Path of trusted certificates */ char *client_cert; /* Client certificate */ char *client_key; /* Client private key */ char *sni; /* TLS Server Name Indication */ #endif struct { int nmemb; char **name; char **varname; } fieldList; ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ uchar *pszBindRuleset; /* default name of Ruleset to bind to */ redisContext *conn; redisAsyncContext *aconn; #ifdef HIREDIS_SSL redisSSLContext *ssl_conn; /* redis ssl connection */ #endif struct event_base *evtBase; redisNode *currentNode; /* currently used redis node, can be any of the nodes in the redisNodesList list */ /* the list of seen nodes * the preferred node (the one from configuration) will always be the first element * second one is a master (if preferred one is unavailable/replica) or a replica, others are replicas * the preferred node may appear twice, but it is accepted */ redisNode *redisNodesList; struct instanceConf_s *next; }; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ instanceConf_t *root, *tail; }; /* The following structure controls the worker threads. Global data is * needed for their access. */ static struct imhiredisWrkrInfo_s { pthread_t tid; /* the worker's thread ID */ instanceConf_t *inst; /* Pointer to imhiredis instance */ rsRetVal (*fnConnectMaster)(instanceConf_t *inst); sbool (*fnIsConnected)(instanceConf_t *inst); rsRetVal (*fnRun)(instanceConf_t *inst); } *imhiredisWrkrInfo; /* GLOBAL DATA */ pthread_attr_t wrkrThrdAttr; /* Attribute for worker threads ; read only after startup */ static int activeHiredisworkers = 0; static const char *REDIS_REPLIES[] = { "unknown", // 0 "string", // 1 "array", // 2 "integer", // 3 "nil", // 4 "status", // 5 "error", // 6 "double", // 7 "bool", // 8 "map", // 9 "set", // 10 "attr", // 11 "push", // 12 "bignum", // 13 "verb", // 14 }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current load process */ static prop_t *pInputName = NULL; /* there is only one global inputName for all messages generated by this input */ /* module-global parameters */ static struct cnfparamdescr modpdescr[] = {}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; /* input instance parameters */ static struct cnfparamdescr inppdescr[] = { {"socketPath", eCmdHdlrGetWord, 0}, {"server", eCmdHdlrGetWord, 0}, {"port", eCmdHdlrInt, 0}, {"password", eCmdHdlrGetWord, 0}, {"mode", eCmdHdlrGetWord, 0}, {"batchsize", eCmdHdlrInt, 0}, {"key", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"uselpop", eCmdHdlrBinary, 0}, {"ruleset", eCmdHdlrString, 0}, {"stream.consumerGroup", eCmdHdlrGetWord, 0}, {"stream.consumerName", eCmdHdlrGetWord, 0}, {"stream.readFrom", eCmdHdlrGetWord, 0}, {"stream.consumerACK", eCmdHdlrBinary, 0}, {"stream.autoclaimIdleTime", eCmdHdlrNonNegInt, 0}, {"fields", eCmdHdlrArray, 0}, #ifdef HIREDIS_SSL {"use_tls", eCmdHdlrBinary, 0}, {"ca_cert_bundle", eCmdHdlrGetWord, 0}, {"ca_cert_dir", eCmdHdlrGetWord, 0}, {"client_cert", eCmdHdlrGetWord, 0}, {"client_key", eCmdHdlrGetWord, 0}, {"sni", eCmdHdlrGetWord, 0}, #endif }; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; struct timeval glblRedisConnectTimeout = {3, 0}; /* 3 seconds */ struct timeval glblRedisCommandTimeout = {5, 0}; /* 5 seconds */ #include "im-helper.h" /* must be included AFTER the type definitions! */ /* forward references */ static void redisAsyncRecvCallback(redisAsyncContext __attribute__((unused)) * c, void *reply, void *inst_obj); static void redisAsyncConnectCallback(const redisAsyncContext *c, int status); static void redisAsyncDisconnectCallback(const redisAsyncContext *c, int status); redisReply *getRole(redisContext *c); static struct json_object *_redisParseIntegerReply(const redisReply *reply); static struct json_object *_redisParseStringReply(const redisReply *reply); static struct json_object *_redisParseArrayReply(const redisReply *reply); #ifdef REDIS_REPLY_DOUBLE static struct json_object *_redisParseDoubleReply(const redisReply *reply); #endif static rsRetVal enqMsg(instanceConf_t *const inst, const char *message, size_t msgLen); static rsRetVal enqMsgJson(instanceConf_t *const inst, struct json_object **json, struct json_object **metadata); rsRetVal redisAuthentSynchronous(redisContext *conn, uchar *password); rsRetVal redisAuthentAsynchronous(redisAsyncContext *aconn, uchar *password); rsRetVal redisActualizeCurrentNode(instanceConf_t *inst); rsRetVal redisGetServersList(redisNode *node, instanceConf_t *const inst, redisNode **result); rsRetVal redisAuthenticate(instanceConf_t *inst); #ifdef HIREDIS_SSL rsRetVal redisInitSSLContext(redisContext *conn, redisSSLContext *ssl_context); #endif rsRetVal redisConnectSync(redisContext **conn, redisNode *node); rsRetVal connectMasterSync(instanceConf_t *inst); static sbool isConnectedSync(instanceConf_t *inst); rsRetVal redisConnectAsync(redisAsyncContext **aconn, redisNode *node); rsRetVal connectMasterAsync(instanceConf_t *inst); static sbool isConnectedAsync(instanceConf_t *inst); rsRetVal redisDequeue(instanceConf_t *inst); rsRetVal ensureConsumerGroupCreated(instanceConf_t *inst); rsRetVal ackStreamIndex(instanceConf_t *inst, uchar *stream, uchar *group, uchar *index); static rsRetVal enqueueRedisStreamReply(instanceConf_t *const inst, redisReply *reply); static rsRetVal handleRedisXREADReply(instanceConf_t *const inst, const redisReply *reply); static rsRetVal handleRedisXAUTOCLAIMReply(instanceConf_t *const inst, const redisReply *reply, char **autoclaimIndex); rsRetVal redisStreamRead(instanceConf_t *inst); rsRetVal redisSubscribe(instanceConf_t *inst); void workerLoop(struct imhiredisWrkrInfo_s *me); static void *imhirediswrkr(void *myself); static rsRetVal createRedisNode(redisNode **root); rsRetVal copyNode(redisNode *src, redisNode **dst); redisNode *freeNode(redisNode *node); void insertNodeAfter(redisNode *root, redisNode *elem); void dbgPrintNode(redisNode *node); static rsRetVal copyStreamIndexText( char *dst, size_t dstSize, const char *src, size_t srcLen, rsRetVal err, const char *context) { DEFiRet; assert(dst != NULL); assert(src != NULL); assert(context != NULL); if (srcLen >= dstSize) { LogError(0, err, "imhiredis: %s exceeds maximum supported stream index length of %zu bytes", context, dstSize - 1); ABORT_FINALIZE(err); } memcpy(dst, src, srcLen); dst[srcLen] = '\0'; finalize_it: RETiRet; } /* create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal createInstance(instanceConf_t **pinst) { DEFiRet; instanceConf_t *inst; CHKmalloc(inst = calloc(1, sizeof(instanceConf_t))); inst->next = NULL; inst->password = NULL; inst->key = NULL; inst->mode = 0; inst->batchsize = 0; inst->useLPop = 0; inst->streamConsumerGroup = NULL; inst->streamConsumerName = NULL; CHKmalloc(inst->streamReadFrom = calloc(1, STREAM_INDEX_STR_BUFSZ)); inst->streamAutoclaimIdleTime = 0; inst->streamConsumerACK = 1; inst->pszBindRuleset = NULL; inst->pBindRuleset = NULL; inst->fieldList.nmemb = 0; #ifdef HIREDIS_SSL inst->use_tls = 0; inst->ca_cert_bundle = NULL; inst->ca_cert_dir = NULL; inst->client_cert = NULL; inst->client_key = NULL; inst->sni = NULL; #endif /* Redis objects */ inst->conn = NULL; inst->aconn = NULL; #ifdef HIREDIS_SSL inst->ssl_conn = NULL; /* Connect later */ #endif /* redis nodes list */ CHKiRet(createRedisNode(&(inst->redisNodesList))); inst->currentNode = inst->redisNodesList; /* libevent base for async connection */ inst->evtBase = NULL; /* node created, let's add to config */ if (loadModConf->tail == NULL) { loadModConf->tail = loadModConf->root = inst; } else { loadModConf->tail->next = inst; loadModConf->tail = inst; } *pinst = inst; finalize_it: RETiRet; } /* this function checks instance parameters and does some required pre-processing */ static rsRetVal ATTR_NONNULL() checkInstance(instanceConf_t *const inst) { DEFiRet; /* first node should be created from configuration */ assert(inst->redisNodesList != NULL); /* check and print redis connection settings */ if (inst->redisNodesList->server != NULL && inst->redisNodesList->socketPath != NULL) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: both 'server' and 'socketPath' are given, " "ignoring 'socketPath'."); free(inst->redisNodesList->socketPath); inst->redisNodesList->socketPath = NULL; } if (inst->redisNodesList->server != NULL && inst->redisNodesList->server[0] != '\0') { if (inst->redisNodesList->port == 0) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: port not set, setting default 6379"); inst->redisNodesList->port = 6379; } DBGPRINTF("imhiredis: preferred server is %s (%d)\n", inst->redisNodesList->server, inst->redisNodesList->port); inst->redisNodesList->usesSocket = 0; } else if (inst->redisNodesList->socketPath != NULL && inst->redisNodesList->socketPath[0] != '\0') { DBGPRINTF("imhiredis: preferred server is %s\n", inst->redisNodesList->socketPath); inst->redisNodesList->usesSocket = 1; } else { LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: neither 'server' nor 'socketPath' are defined!"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } #ifdef HIREDIS_SSL redisSSLContextError ssl_error = REDIS_SSL_CTX_NONE; // Check and initialize SSL context if (inst->use_tls) { const char *tls_peer_name = inst->sni; if ((inst->client_cert == NULL) ^ (inst->client_key == NULL)) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_ERR, "imhiredis: \"client_cert\" and \"client_key\" must be specified together!"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (tls_peer_name == NULL && inst->redisNodesList->usesSocket == 0) { tls_peer_name = (const char *)inst->redisNodesList->server; } inst->ssl_conn = redisCreateSSLContext(inst->ca_cert_bundle, inst->ca_cert_dir, inst->client_cert, inst->client_key, tls_peer_name, &ssl_error); if (!inst->ssl_conn || ssl_error != REDIS_SSL_CTX_NONE) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: TLS configuration Error: %s", redisSSLContextGetError(ssl_error)); if (inst->ssl_conn != NULL) { redisFreeSSLContext(inst->ssl_conn); inst->ssl_conn = NULL; } ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } } #endif if (inst->mode < IMHIREDIS_MODE_QUEUE || inst->mode > IMHIREDIS_MODE_STREAM) { LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: invalid mode, please choose 'subscribe', " "'queue' or 'stream' mode."); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (inst->mode != IMHIREDIS_MODE_QUEUE && inst->useLPop) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'uselpop' set with mode != queue : ignored."); } if (inst->mode == IMHIREDIS_MODE_STREAM) { if (inst->streamConsumerGroup != NULL && inst->streamConsumerName == NULL) { LogError(0, RS_RET_CONFIG_ERROR, "imhiredis: invalid configuration, " "please set a consumer name when mode is 'stream' and a consumer group is set"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } if (inst->streamAutoclaimIdleTime != 0 && inst->streamConsumerGroup == NULL) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'stream.autoclaimIdleTime' " "set with no consumer group set : ignored."); } if (inst->streamReadFrom[0] == '\0') { inst->streamReadFrom[0] = '$'; } } else { if (inst->streamConsumerGroup != NULL) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'stream.consumerGroup' " "set with mode != stream : ignored."); } if (inst->streamConsumerName != NULL) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'stream.consumerName' " "set with mode != stream : ignored."); } if (inst->streamAutoclaimIdleTime != 0) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'stream.autoclaimIdleTime' " "set with mode != stream : ignored."); } if (inst->streamConsumerACK == 0) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'stream.consumerACK' " "disabled with mode != stream : ignored."); } if (inst->fieldList.nmemb > 0) { LogMsg(0, RS_RET_CONFIG_ERROR, LOG_WARNING, "imhiredis: 'fields' " "unused for mode != stream : ignored."); } } if (inst->batchsize != 0) { DBGPRINTF("imhiredis: batchsize is '%d'\n", inst->batchsize); } else { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: batchsize not set, setting to default (%d)", BATCH_SIZE); inst->batchsize = BATCH_SIZE; } if (inst->password != NULL) { DBGPRINTF("imhiredis: password is '%s'\n", inst->password); } // set default current node as first node in list (preferred node) inst->currentNode = inst->redisNodesList; // search master node (should be either preferred node or its master) if (RS_RET_OK != redisActualizeCurrentNode(inst) || inst->currentNode == NULL) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: could not connect to a valid master!"); } finalize_it: RETiRet; } /* function to generate an error message if the ruleset cannot be found */ static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "imhiredis: ruleset '%s' not found - " "using default ruleset instead", inst->pszBindRuleset); } BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst; int i; CODESTARTnewInpInst; DBGPRINTF("newInpInst (imhiredis)\n"); if ((pvals = nvlstGetParams(lst, &inppblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("input param blk in imhiredis:\n"); cnfparamsPrint(&inppblk, pvals); } CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "server")) { CHKmalloc(inst->redisNodesList->server = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "socketPath")) { CHKmalloc(inst->redisNodesList->socketPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "port")) { inst->redisNodesList->port = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "password")) { CHKmalloc(inst->password = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "stream.consumerGroup")) { CHKmalloc(inst->streamConsumerGroup = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "stream.consumerName")) { CHKmalloc(inst->streamConsumerName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "stream.consumerACK")) { inst->streamConsumerACK = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "stream.readFrom")) { CHKiRet(copyStreamIndexText( (char *)inst->streamReadFrom, STREAM_INDEX_STR_BUFSZ, (const char *)es_getBufAddr(pvals[i].val.d.estr), es_strlen(pvals[i].val.d.estr), RS_RET_PARAM_ERROR, "configured stream.readFrom value")); } else if (!strcmp(inppblk.descr[i].name, "stream.autoclaimIdleTime")) { inst->streamAutoclaimIdleTime = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "uselpop")) { inst->useLPop = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "mode")) { CHKmalloc(inst->modeDescription = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcmp((const char *)inst->modeDescription, "queue")) { inst->mode = IMHIREDIS_MODE_QUEUE; } else if (!strcmp((const char *)inst->modeDescription, "subscribe")) { inst->mode = IMHIREDIS_MODE_SUBSCRIBE; } else if (!strcmp((const char *)inst->modeDescription, "stream")) { inst->mode = IMHIREDIS_MODE_STREAM; } else { LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR, "imhiredis: unsupported mode " "'%s'", inst->modeDescription); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } } else if (!strcmp(inppblk.descr[i].name, "fields")) { inst->fieldList.nmemb = pvals[i].val.d.ar->nmemb; CHKmalloc(inst->fieldList.name = calloc(inst->fieldList.nmemb, sizeof(char *))); CHKmalloc(inst->fieldList.varname = calloc(inst->fieldList.nmemb, sizeof(char *))); for (int j = 0; j < pvals[i].val.d.ar->nmemb; ++j) { char *const param = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); char *varname = NULL; char *name; if (*param == ':') { char *b = strchr(param + 1, ':'); if (b == NULL) { LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR, "imhiredis: missing closing colon: '%s'", param); ABORT_FINALIZE(RS_RET_ERR); } *b = '\0'; /* split name & varname */ varname = param + 1; name = b + 1; } else { name = param; } CHKmalloc(inst->fieldList.name[j] = strdup(name)); char vnamebuf[1024]; snprintf(vnamebuf, sizeof(vnamebuf), "!%s", (varname == NULL) ? name : varname); CHKmalloc(inst->fieldList.varname[j] = strdup(vnamebuf)); DBGPRINTF("will map '%s' to '%s'\n", inst->fieldList.name[j], inst->fieldList.varname[j]); free(param); } } else if (!strcmp(inppblk.descr[i].name, "batchsize")) { inst->batchsize = (int)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "key")) { CHKmalloc(inst->key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); #ifdef HIREDIS_SSL } else if (!strcmp(inppblk.descr[i].name, "use_tls")) { inst->use_tls = pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "ca_cert_bundle")) { CHKmalloc(inst->ca_cert_bundle = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "ca_cert_dir")) { CHKmalloc(inst->ca_cert_dir = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "client_cert")) { CHKmalloc(inst->client_cert = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "client_key")) { CHKmalloc(inst->client_key = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "sni")) { CHKmalloc(inst->sni = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); #endif } else { dbgprintf( "imhiredis: program error, non-handled " "param '%s'\n", inppblk.descr[i].name); } } DBGPRINTF("imhiredis: checking config sanity\n"); if (inst->modeDescription == NULL) { CHKmalloc(inst->modeDescription = (uchar *)strdup("subscribe")); inst->mode = IMHIREDIS_MODE_SUBSCRIBE; LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: \"mode\" parameter not specified " "using default redis 'subscribe' mode -- this may not be what you want!"); } if (inst->key == NULL) { LogMsg(0, RS_RET_PARAM_ERROR, LOG_ERR, "imhiredis: \"key\" required parameter not specified!"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (inst->redisNodesList->server == NULL && inst->redisNodesList->socketPath == NULL) { CHKmalloc(inst->redisNodesList->server = (uchar *)strdup("127.0.0.1")); inst->redisNodesList->port = 6379; LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imhiredis: no server parameter specified " "using default 127.0.0.1:6379 -- this may not be what you want!"); } if (inst->password == NULL) { LogMsg(0, RS_RET_OK, LOG_INFO, "imhiredis: no password specified"); } DBGPRINTF("imhiredis: newInpInst key=%s, mode=%s, uselpop=%d\n", inst->key, inst->modeDescription, inst->useLPop); finalize_it: CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imhiredis: error processing module " "config parameters [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("module (global) param blk for imhiredis:\n"); cnfparamsPrint(&modpblk, pvals); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } else { dbgprintf( "imhiredis: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); } } finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = pModConf->root; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); } ENDcheckCnf BEGINactivateCnfPrePrivDrop CODESTARTactivateCnfPrePrivDrop; runModConf = pModConf; ENDactivateCnfPrePrivDrop BEGINactivateCnf CODESTARTactivateCnf; for (instanceConf_t *inst = pModConf->root; inst != NULL; inst = inst->next) { iRet = checkInstance(inst); if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE) { if ((inst->evtBase = event_base_new()) == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "imhiredis: could not create libevent base"); iRet = RS_RET_OUT_OF_MEMORY; break; } } } ENDactivateCnf BEGINfreeCnf instanceConf_t *inst, *del; redisNode *node; CODESTARTfreeCnf; for (inst = pModConf->root; inst != NULL;) { if (inst->evtBase) event_base_free(inst->evtBase); if (inst->password != NULL) free(inst->password); free(inst->modeDescription); free(inst->key); if (inst->streamConsumerGroup != NULL) free(inst->streamConsumerGroup); if (inst->streamConsumerName != NULL) free(inst->streamConsumerName); free(inst->streamReadFrom); free(inst->pszBindRuleset); if (inst->fieldList.name != NULL) { for (int i = 0; i < inst->fieldList.nmemb; ++i) { free(inst->fieldList.name[i]); free(inst->fieldList.varname[i]); } free(inst->fieldList.name); free(inst->fieldList.varname); } if (inst->conn != NULL) { redisFree(inst->conn); inst->conn = NULL; } if (inst->aconn != NULL) { redisAsyncFree(inst->aconn); inst->aconn = NULL; } #ifdef HIREDIS_SSL if (inst->ssl_conn != NULL) { redisFreeSSLContext(inst->ssl_conn); inst->ssl_conn = NULL; } if (inst->ca_cert_bundle != NULL) free(inst->ca_cert_bundle); if (inst->ca_cert_dir != NULL) free(inst->ca_cert_dir); if (inst->client_cert != NULL) free(inst->client_cert); if (inst->client_key != NULL) free(inst->client_key); if (inst->sni) free(inst->sni); #endif for (node = inst->redisNodesList; node != NULL; node = freeNode(node)) { ; } del = inst; inst = inst->next; free(del); } ENDfreeCnf /* Cleanup imhiredis worker threads */ static void shutdownImhiredisWorkers(void) { int i; instanceConf_t *inst; assert(imhiredisWrkrInfo != NULL); for (inst = runModConf->root; inst != NULL; inst = inst->next) { if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE && inst->aconn) { DBGPRINTF("imhiredis: disconnecting async worker\n"); redisAsyncDisconnect(inst->aconn); } } // event_base_loopbreak(runModConf->evtBase); DBGPRINTF("imhiredis: waiting on imhiredis workerthread termination\n"); for (i = 0; i < activeHiredisworkers; ++i) { pthread_join(imhiredisWrkrInfo[i].tid, NULL); DBGPRINTF("imhiredis: Stopped worker %d\n", i); } free(imhiredisWrkrInfo); imhiredisWrkrInfo = NULL; return; } /* This function is called to gather input. */ BEGINrunInput int i; instanceConf_t *inst; CODESTARTrunInput; DBGPRINTF("imhiredis: runInput loop started ...\n"); activeHiredisworkers = 0; for (inst = runModConf->root; inst != NULL; inst = inst->next) { ++activeHiredisworkers; } if (activeHiredisworkers == 0) { LogError(0, RS_RET_ERR, "imhiredis: no active inputs, input does " "not run - there should have been additional error " "messages given previously"); ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("imhiredis: Starting %d imhiredis workerthreads\n", activeHiredisworkers); imhiredisWrkrInfo = calloc(activeHiredisworkers, sizeof(struct imhiredisWrkrInfo_s)); if (imhiredisWrkrInfo == NULL) { LogError(errno, RS_RET_OUT_OF_MEMORY, "imhiredis: worker-info array allocation failed."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* Start worker threads for each imhiredis input source */ i = 0; for (inst = runModConf->root; inst != NULL; inst = inst->next) { /* init worker info structure! */ imhiredisWrkrInfo[i].inst = inst; /* Set reference pointer */ pthread_create(&imhiredisWrkrInfo[i].tid, &wrkrThrdAttr, imhirediswrkr, &(imhiredisWrkrInfo[i])); i++; } // This thread simply runs the various threads, then waits for Rsyslog to stop while (glbl.GetGlobalInputTermState() == 0) { if (glbl.GetGlobalInputTermState() == 0) /* Check termination state every 0.5s * should be sufficient to grant fast response to shutdown while not hogging CPU */ srSleep(0, 500000); } DBGPRINTF("imhiredis: terminating upon request of rsyslog core\n"); shutdownImhiredisWorkers(); finalize_it: ENDrunInput BEGINwillRun CODESTARTwillRun; /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("imhiredis"), sizeof("imhiredis") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun; if (pInputName != NULL) prop.Destruct(&pInputName); ENDafterRun BEGINmodExit CODESTARTmodExit; pthread_attr_destroy(&wrkrThrdAttr); /* force cleaning of all libevent-related structures * (clean shutdowns are not always guaranteed without it) */ libevent_global_shutdown(); /* release objects we used */ objRelease(statsobj, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); ENDmodExit BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr /* request objects we use */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); /* initialize "read-only" thread attributes */ pthread_attr_init(&wrkrThrdAttr); pthread_attr_setstacksize(&wrkrThrdAttr, 4096 * 1024); /* activate libevent for (p)threads support */ evthread_use_pthreads(); #ifdef HIREDIS_SSL // initialize OpenSSL redisInitOpenSSL(); #endif ENDmodInit /* ------------------------------ callbacks ------------------------------ */ /** * Asynchronous subscribe callback handler */ static void redisAsyncRecvCallback(redisAsyncContext *aconn, void *reply, void __attribute__((unused)) * unused) { /* redisReply is supposed to be an array of three elements: [''message', , ] JJO: For future reference (https://github.com/redis/hiredis/blob/master/README.md) Important: the current version of hiredis (1.0.0) frees replies when the asynchronous API is used. This means you should not call freeReplyObject when you use this API. The reply is cleaned up by hiredis after the callback returns. TODO We may have to change this function in the future to free replies. */ instanceConf_t *const inst = (instanceConf_t *)aconn->data; redisReply *r = (redisReply *)reply; if (r == NULL) return; if (r->elements < 3 || r->element[2]->str == NULL) { return; } enqMsg(inst, r->element[2]->str, r->element[2]->len); return; } /** * Asynchronous connection callback handler */ static void redisAsyncConnectCallback(const redisAsyncContext *c, int status) { if (status != REDIS_OK) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis (async): could not connect to redis: " "%s", c->errstr); // remove async context from instance config object, still contained in context's 'data' field instanceConf_t *inst = (instanceConf_t *)c->data; assert(inst != NULL); inst->aconn = NULL; return; } DBGPRINTF("imhiredis (async): successfully connected!\n"); return; } /** * Asynchronous disconnection callback handler */ static void redisAsyncDisconnectCallback(const redisAsyncContext *c, int status) { // remove context from instance config object (which is stored in the context 'data' field by us) // context will be freed by the library, so it's only set to NULL here instanceConf_t *inst = (instanceConf_t *)c->data; assert(inst != NULL); inst->aconn = NULL; inst->currentNode = NULL; if (status != REDIS_OK) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis (async): got disconnected from redis: " "%s", c->errstr); return; } DBGPRINTF("imhiredis (async): successfully disconnected!\n"); return; } /* ------------------------------ end callbacks ------------------------------ */ /* * sends a ROLE command to the redis pointed by context * context should be a valid redis context * returns a valid redisReply pointer if an array reply was received, NULL otherwise */ redisReply *getRole(redisContext *c) { redisReply *reply; assert(c != NULL); reply = redisCommand(c, "ROLE"); if (reply == NULL) { DBGPRINTF("imhiredis: could not get reply from ROLE command\n"); } else if (reply->type == REDIS_REPLY_ERROR) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis got an error while querying role -> " "%s\n", reply->str); freeReplyObject(reply); reply = NULL; } else if (reply->type != REDIS_REPLY_ARRAY) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "imhiredis: did not get an array from ROLE command"); freeReplyObject(reply); reply = NULL; } return reply; } static struct json_object *_redisParseIntegerReply(const redisReply *reply) { return json_object_new_int64(reply->integer); } #ifdef REDIS_REPLY_DOUBLE static struct json_object *_redisParseDoubleReply(const redisReply *reply) { return json_object_new_double_s(reply->dval, reply->str); } #endif static struct json_object *_redisParseStringReply(const redisReply *reply) { return json_object_new_string_len(reply->str, reply->len); } static struct json_object *_redisParseArrayReply(const redisReply *reply) { struct json_object *result = NULL; struct json_object *res = NULL; char *key = NULL; result = json_object_new_object(); // the redis type name is ARRAY, but represents a dict if (result != NULL) { for (size_t i = 0; i < reply->elements; i++) { if (reply->element[i]->type == REDIS_REPLY_STRING && i % 2 == 0) { key = reply->element[i]->str; } else { switch (reply->element[i]->type) { case REDIS_REPLY_INTEGER: res = _redisParseIntegerReply(reply->element[i]); json_object_object_add(result, key, res); break; #ifdef REDIS_REPLY_DOUBLE case REDIS_REPLY_DOUBLE: res = _redisParseDoubleReply(reply->element[i]); json_object_object_add(result, key, res); break; #endif case REDIS_REPLY_STRING: res = _redisParseStringReply(reply->element[i]); json_object_object_add(result, key, res); break; case REDIS_REPLY_ARRAY: res = _redisParseArrayReply(reply->element[i]); json_object_object_add(result, key, res); break; default: DBGPRINTF("Unhandled case!\n"); LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "Redis reply object contains an unhandled type!"); break; } } } } return result; } /* * enqueue the hiredis message. The provided string is * not freed - this must be done by the caller. */ static rsRetVal enqMsg(instanceConf_t *const inst, const char *message, size_t msgLen) { DEFiRet; smsg_t *pMsg; if (message == NULL || message[0] == '\0') { /* we do not process empty lines */ FINALIZE; } DBGPRINTF("imhiredis: enqMsg: Msg -> '%s'\n", message); CHKiRet(msgConstruct(&pMsg)); MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, message, msgLen); MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY); MsgSetRuleset(pMsg, inst->pBindRuleset); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ CHKiRet(submitMsg2(pMsg)); finalize_it: RETiRet; } static rsRetVal enqMsgJson(instanceConf_t *const inst, struct json_object **json, struct json_object **metadata) { DEFiRet; smsg_t *pMsg; struct json_object *tempJson = NULL; assert(json != NULL && *json != NULL); CHKiRet(msgConstruct(&pMsg)); // In case of allocation error -> needs to break MsgSetInputName(pMsg, pInputName); MsgSetRuleset(pMsg, inst->pBindRuleset); MsgSetMSGoffs(pMsg, 0); /* we do not have a header... */ if (RS_RET_OK != MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY)) LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "Could not set Flow Control on message."); if (inst->fieldList.nmemb != 0) { for (int i = 0; i < inst->fieldList.nmemb; i++) { DBGPRINTF("processing field '%s'\n", inst->fieldList.name[i]); /* case 1: static field. We simply forward it */ if (inst->fieldList.name[i][0] != '!' && inst->fieldList.name[i][0] != '.') { DBGPRINTF("field is static, taking it as it is...\n"); tempJson = json_object_new_string(inst->fieldList.name[i]); } /* case 2: dynamic field. We retrieve its value from the JSON logline and add it */ else { DBGPRINTF("field is dynamic, searching in root object...\n"); if (!json_object_object_get_ex(*json, inst->fieldList.name[i] + 1, &tempJson)) { DBGPRINTF("Did not find value %s in message\n", inst->fieldList.name[i]); continue; } // Getting object as it will not keep the same lifetime as its origin object tempJson = json_object_get(tempJson); } DBGPRINTF("got value of field '%s'\n", inst->fieldList.name[i]); DBGPRINTF("will insert to '%s'\n", inst->fieldList.varname[i]); if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)inst->fieldList.varname[i], tempJson, 0, 0)) { LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR, "Failed to add value to '%s'", inst->fieldList.varname[i]); } tempJson = NULL; } json_object_put(*json); *json = NULL; } else { struct json_object *const toAdd = *json; *json = NULL; if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)"!", toAdd, 0, 0)) { LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR, "Failed to add json info to message!"); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } } if (metadata != NULL && *metadata != NULL) { struct json_object *const toAddMeta = *metadata; *metadata = NULL; if (RS_RET_OK != msgAddJSON(pMsg, (uchar *)".", toAddMeta, 0, 0)) { LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR, "Failed to add metadata to message!"); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } } if (RS_RET_OK != submitMsg2(pMsg)) { LogMsg(0, RS_RET_OBJ_CREATION_FAILED, LOG_ERR, "Failed to submit message to main queue!"); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } DBGPRINTF("enqMsgJson: message enqueued!\n"); finalize_it: RETiRet; } /* * execute a synchronous authentication using the context conn * conn and password should be non-NULL * conn should be a valid context */ rsRetVal redisAuthentSynchronous(redisContext *conn, uchar *password) { DEFiRet; redisReply *reply = NULL; assert(conn != NULL); assert(password != NULL); assert(password[0] != '\0'); reply = (redisReply *)redisCommand(conn, "AUTH %s", password); if (reply == NULL) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: Could not authenticate!\n"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } else if (strncmp(reply->str, "OK", 2)) { LogError(0, RS_RET_REDIS_AUTH_FAILED, "imhiredis: Authentication failure -> %s\n", reply->str); ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED); } finalize_it: if (reply) freeReplyObject(reply); RETiRet; } /* * execute an asynchronous authentication using the context aconn * aconn and password should be non-NULL * aconn should be a valid (async) context */ rsRetVal redisAuthentAsynchronous(redisAsyncContext *aconn, uchar *password) { DEFiRet; assert(aconn != NULL); assert(password != NULL); assert(password[0] != '\0'); if (REDIS_OK != redisAsyncCommand(aconn, NULL, NULL, "AUTH %s", password)) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: error while authenticating asynchronously -> %s\n", aconn->errstr); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: RETiRet; } /* * connect to node, authenticate (if necessary), get role, then get all node information provided by ROLE * node should be a non-NULL valid redisNode pointer * inst is the instance configuration object (used for SSL/password settings) * result will hold the result of the ROLE command executed on the node: * - NULL if the node was a single master instance * - a single (master) node if the provided node was a replica * - a list of (replica) nodes if the provided node was a master */ rsRetVal redisGetServersList(redisNode *node, instanceConf_t *inst, redisNode **result) { DEFiRet; redisContext *context; redisReply *reply = NULL, *replica; unsigned int i; assert(node != NULL); CHKiRet(redisConnectSync(&context, node)); #ifdef HIREDIS_SSL if (inst->use_tls && inst->ssl_conn) { CHKiRet(redisInitSSLContext(context, inst->ssl_conn)); } #endif if (inst->password != NULL && inst->password[0] != '\0') { CHKiRet(redisAuthentSynchronous(context, inst->password)); } reply = getRole(context); if (reply == NULL) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: did not get the role of the server"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } /* * string comparisons for ROLE could be skipped * as each role returns a different number of elements, * but lets keep it as a security... */ if (reply->elements == 5 && strncmp(reply->element[0]->str, "slave", 5) == 0) { CHKiRet(createRedisNode(result)); (*result)->server = (uchar *)strdup((const char *)reply->element[1]->str); (*result)->port = reply->element[2]->integer; (*result)->isMaster = 1; } else if (reply->elements == 3 && reply->element[2]->type == REDIS_REPLY_ARRAY && strncmp(reply->element[0]->str, "master", 6) == 0) { // iterate on all replicas given in the reply (if any) for (i = 0; i < reply->element[2]->elements; i++) { replica = reply->element[2]->element[i]; if (replica->type == REDIS_REPLY_ARRAY && replica->elements == 3) { /* node will be a new node every time * with old ones shifted in the list */ CHKiRet(createRedisNode(result)); (*result)->server = (uchar *)strdup((const char *)replica->element[0]->str); // yes, the value in that case is a string and NOT an integer! (*result)->port = atoi(replica->element[1]->str); } } } else { // we have a sentinel, or a problem ABORT_FINALIZE(RS_RET_NOT_FOUND); } finalize_it: if (reply != NULL) freeReplyObject(reply); if (context != NULL) redisFree(context); RETiRet; } /* * actualize the current master node to use during connection for instance inst * inst should be a valid, non-NULL instanceConf object * inst should also possess at least a single node in inst->redisNodeList * if the function returns RS_RET_OK, inst->currentNode and inst->redisNodeList have been both updated * to reflect new master and potential replicas * the first configured node (called preferred node) is always kept as the first entry in redisNodeList */ rsRetVal redisActualizeCurrentNode(instanceConf_t *inst) { DEFiRet; redisReply *reply = NULL; redisNode *node, *tmp, *newList = NULL; assert(inst != NULL); assert(inst->redisNodesList != NULL); inst->currentNode = NULL; // keep first node in list = preferred node (comes from configuration) copyNode(inst->redisNodesList, &newList); newList->next = NULL; for (node = inst->redisNodesList; node != NULL; node = node->next) { tmp = NULL; DBGPRINTF("imhiredis: trying to connect to node to get info...\n"); dbgPrintNode(node); if (RS_RET_OK == redisGetServersList(node, inst, &tmp)) { // server replied if (tmp && tmp->isMaster) { DBGPRINTF("imhiredis: node replied with a master node, is a replica\n"); // master node, keep it as potential new active node inst->currentNode = tmp; tmp = NULL; // try to connect to the master and get replicas if (RS_RET_OK != redisGetServersList(inst->currentNode, inst, &tmp)) { /* had a master, but cannot connect * save suspected master in new list but keep searching with other nodes */ DBGPRINTF("imhiredis: had a master but cannot connect, keeping in list\n"); dbgPrintNode(inst->currentNode); insertNodeAfter(newList, inst->currentNode); inst->currentNode = NULL; continue; } } else { DBGPRINTF("imhiredis: node replied with a list of replicas, is a master\n"); // copy the node to the new currentNode, list owning node will be freed node->isMaster = 1; copyNode(node, &(inst->currentNode)); inst->currentNode->next = NULL; } /* * here, tmp is a list of replicas or NULL (single node) * inst->currentNode is the new active master */ // add the replicas to the list if (tmp) { insertNodeAfter(newList, tmp); DBGPRINTF("imhiredis: inserting replicas to list\n"); for (tmp = newList->next; tmp != NULL; tmp = tmp->next) { dbgPrintNode(tmp); } } // insert the master after the preferred node (configuration) DBGPRINTF("imhiredis: inserting new master node in list\n"); dbgPrintNode(inst->currentNode); insertNodeAfter(newList, inst->currentNode); // swap newList and redisNodesList to free old list at the end of the function tmp = newList; newList = inst->redisNodesList; inst->redisNodesList = tmp; FINALIZE; } } DBGPRINTF("imhiredis: did not find a valid master"); iRet = RS_RET_NOT_FOUND; inst->currentNode = NULL; finalize_it: if (reply != NULL) freeReplyObject(reply); // newList is always completely freed for (node = newList; node != NULL;) { node = freeNode(node); } RETiRet; } /* * authentication function, for both synchronous and asynchronous modes (queue or subscribe) * inst, inst->curentMode and inst->password should not be NULL */ rsRetVal redisAuthenticate(instanceConf_t *inst) { DEFiRet; redisContext *usedContext = NULL; redisReply *reply = NULL; assert(inst != NULL); assert(inst->currentNode != NULL); assert(inst->password != NULL); assert(inst->password[0] != '\0'); DBGPRINTF("imhiredis: authenticating...\n"); // Create a temporary context for synchronous connection, used to validate AUTH command in asynchronous contexts if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE) { if (RS_RET_OK != redisConnectSync(&usedContext, inst->currentNode)) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "imhiredis: could not connect to current " "active node synchronously to validate authentication"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } #ifdef HIREDIS_SSL if (inst->use_tls && inst->ssl_conn) { CHKiRet(redisInitSSLContext(usedContext, inst->ssl_conn)); } #endif } else { usedContext = inst->conn; } /* * Try synchronous connection, whatever the method for the instance * This is also done for the asynchronous mode, to validate the successful authentication */ CHKiRet(redisAuthentSynchronous(usedContext, inst->password)); if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE) { CHKiRet(redisAuthentAsynchronous(inst->aconn, inst->password)); } DBGPRINTF("imhiredis: authentication successful\n"); finalize_it: if (inst->mode == IMHIREDIS_MODE_SUBSCRIBE && usedContext) redisFree(usedContext); if (reply) freeReplyObject(reply); RETiRet; } #ifdef HIREDIS_SSL rsRetVal redisInitSSLContext(redisContext *conn, redisSSLContext *ssl_context) { DEFiRet; assert(conn != NULL); assert(ssl_context != NULL); if (redisInitiateSSLWithContext(conn, ssl_context) != REDIS_OK) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis error while initializing TLS context: %s", conn->errstr); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: RETiRet; } #endif /* * connection function for synchronous (queue) mode * node should not be NULL */ rsRetVal redisConnectSync(redisContext **conn, redisNode *node) { DEFiRet; redisOptions options = {0}; options.connect_timeout = &glblRedisConnectTimeout; options.command_timeout = &glblRedisCommandTimeout; assert(node != NULL); if (node->usesSocket) REDIS_OPTIONS_SET_UNIX(&options, (const char *)node->socketPath); else REDIS_OPTIONS_SET_TCP(&options, (const char *)node->server, node->port); *conn = redisConnectWithOptions(&options); if (*conn == NULL) { if (node->usesSocket) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s' " "-> could not allocate context!\n", node->socketPath); } else { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s', " "port %d -> could not allocate context!\n", node->server, node->port); } ABORT_FINALIZE(RS_RET_REDIS_ERROR); } else if ((*conn)->err) { if (node->usesSocket) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s' " "-> %s\n", node->socketPath, (*conn)->errstr); } else { LogError(0, RS_RET_REDIS_ERROR, "imhiredis: can not connect to redis server '%s', " "port %d -> %s\n", node->server, node->port, (*conn)->errstr); } ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: if (iRet != RS_RET_OK) { if (*conn) redisFree(*conn); *conn = NULL; } RETiRet; } /* * connection function for asynchronous (subscribe) mode * node should not be NULL */ rsRetVal redisConnectAsync(redisAsyncContext **aconn, redisNode *node) { DEFiRet; redisOptions options = {0}; options.connect_timeout = &glblRedisConnectTimeout; options.command_timeout = &glblRedisCommandTimeout; assert(node != NULL); if (node->usesSocket) REDIS_OPTIONS_SET_UNIX(&options, (const char *)node->socketPath); else REDIS_OPTIONS_SET_TCP(&options, (const char *)node->server, node->port); *aconn = redisAsyncConnectWithOptions(&options); if (*aconn == NULL) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): could not allocate context!\n"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } else if ((*aconn)->err) { if (node->usesSocket) { LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): cannot connect to server '%s' " "-> %s\n", node->socketPath, (*aconn)->errstr); } else { LogError(0, RS_RET_REDIS_ERROR, "imhiredis (async): cannot connect to server '%s', port '%d' " "-> %s\n", node->server, node->port, (*aconn)->errstr); } ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: if (iRet != RS_RET_OK) { if (*aconn) redisAsyncFree(*aconn); *aconn = NULL; } RETiRet; } /* * Helper method to connect to the current master asynchronously * 'inst' parameter should be non-NULL and have a valid currentNode object */ rsRetVal connectMasterAsync(instanceConf_t *inst) { DEFiRet; if (RS_RET_OK != redisConnectAsync(&(inst->aconn), inst->currentNode)) { inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_ERROR); } #ifdef HIREDIS_SSL if (inst->use_tls && inst->ssl_conn && redisInitSSLContext(&(inst->aconn->c), inst->ssl_conn) != RS_RET_OK) { redisAsyncFree(inst->aconn); inst->aconn = NULL; inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_ERROR); } #endif if (inst->password != NULL && inst->password[0] != '\0' && RS_RET_OK != redisAuthenticate(inst)) { redisAsyncFree(inst->aconn); inst->aconn = NULL; inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED); } // finalize context creation inst->aconn->data = (void *)inst; redisAsyncSetConnectCallback(inst->aconn, redisAsyncConnectCallback); redisAsyncSetDisconnectCallback(inst->aconn, redisAsyncDisconnectCallback); redisLibeventAttach(inst->aconn, inst->evtBase); finalize_it: RETiRet; } /* * Helper method to check if (async) instance is connected */ static sbool isConnectedAsync(instanceConf_t *inst) { return inst->aconn != NULL; } /* * Helper method to connect to the current master synchronously * 'inst' parameter should be non-NULL and have a valid currentNode object */ rsRetVal connectMasterSync(instanceConf_t *inst) { DEFiRet; if (RS_RET_OK != redisConnectSync(&(inst->conn), inst->currentNode)) { inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_ERROR); } #ifdef HIREDIS_SSL if (inst->use_tls && inst->ssl_conn) { if (redisInitSSLContext(inst->conn, inst->ssl_conn) != RS_RET_OK) { redisFree(inst->conn); inst->conn = NULL; inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_ERROR); } } #endif if (inst->password != NULL && inst->password[0] != '\0' && RS_RET_OK != redisAuthenticate(inst)) { redisFree(inst->conn); inst->conn = NULL; inst->currentNode = NULL; ABORT_FINALIZE(RS_RET_REDIS_AUTH_FAILED); } finalize_it: RETiRet; } /* * Helper method to check if instance is connected */ static sbool isConnectedSync(instanceConf_t *inst) { return inst->conn != NULL; } /* * dequeue all entries in the redis list, using batches of 10 commands */ rsRetVal redisDequeue(instanceConf_t *inst) { DEFiRet; redisReply *reply = NULL; uint replyType = 0, i; assert(inst != NULL); DBGPRINTF("redisDequeue: beginning to dequeue key '%s'\n", inst->key); do { // append a batch of inst->batchsize POP commands (either LPOP or RPOP depending on conf) if (inst->useLPop == 1) { DBGPRINTF("redisDequeue: Queuing #%d LPOP commands on key '%s' \n", inst->batchsize, inst->key); for (i = 0; i < inst->batchsize; ++i) { if (REDIS_OK != redisAppendCommand(inst->conn, "LPOP %s", inst->key)) break; } } else { DBGPRINTF("redisDequeue: Queuing #%d RPOP commands on key '%s' \n", inst->batchsize, inst->key); for (i = 0; i < inst->batchsize; i++) { if (REDIS_OK != redisAppendCommand(inst->conn, "RPOP %s", inst->key)) break; } } DBGPRINTF("redisDequeue: Dequeuing...\n") // parse responses from appended commands do { if (REDIS_OK != redisGetReply(inst->conn, (void **)&reply)) { // error getting reply, must stop LogError(0, RS_RET_REDIS_ERROR, "redisDequeue: Error reading reply after POP #%d " "on key '%s'", (inst->batchsize - i), inst->key); // close connection redisFree(inst->conn); inst->currentNode = NULL; inst->conn = NULL; ABORT_FINALIZE(RS_RET_REDIS_ERROR); } else { if (reply != NULL) { replyType = reply->type; switch (replyType) { case REDIS_REPLY_STRING: enqMsg(inst, reply->str, reply->len); break; case REDIS_REPLY_NIL: // replies are dequeued but are empty = end of list break; case REDIS_REPLY_ERROR: // There is a problem with the key or the Redis instance LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisDequeue: error " "while POP'ing key '%s' -> %s", inst->key, reply->str); ABORT_FINALIZE(RS_RET_REDIS_ERROR); default: LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "redisDequeue: " "unexpected reply type: %s", REDIS_REPLIES[replyType % 15]); } freeReplyObject(reply); reply = NULL; } else { /* reply == NULL */ LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisDequeue: unexpected empty reply " "for successful return"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } } // while there are replies to unpack, continue } while (--i > 0); if (replyType == REDIS_REPLY_NIL) { /* sleep 1s between 2 POP tries, when no new entries are available (list is empty) * this does NOT limit dequeing rate, but prevents the input from polling Redis too often */ for (i = 0; i < 10; i++) { // Time to stop the thread if (glbl.GetGlobalInputTermState() != 0) FINALIZE; // 100ms sleeps srSleep(0, 100000); } } // while input can run, continue with a new batch } while (glbl.GetGlobalInputTermState() == 0); DBGPRINTF("redisDequeue: finished to dequeue key '%s'\n", inst->key); finalize_it: if (reply) freeReplyObject(reply); RETiRet; } rsRetVal ensureConsumerGroupCreated(instanceConf_t *inst) { DEFiRet; redisReply *reply = NULL; DBGPRINTF("ensureConsumerGroupCreated: Creating group %s on stream %s\n", inst->streamConsumerGroup, inst->key); reply = (redisReply *)redisCommand(inst->conn, "XGROUP CREATE %s %s %s MKSTREAM", inst->key, inst->streamConsumerGroup, inst->streamReadFrom); if (reply != NULL) { switch (reply->type) { case REDIS_REPLY_STATUS: case REDIS_REPLY_STRING: if (0 == strncmp("OK", reply->str, reply->len)) DBGPRINTF( "ensureConsumerGroupCreated: Consumer group %s created successfully " "for stream %s\n", inst->streamConsumerGroup, inst->key); break; case REDIS_REPLY_ERROR: if (strcasestr(reply->str, "BUSYGROUP") != NULL) { DBGPRINTF( "ensureConsumerGroupCreated: Consumer group %s already exists for " "stream %s, ignoring\n", inst->streamConsumerGroup, inst->key); } else { LogError(0, RS_RET_ERR, "ensureConsumerGroupCreated: An unknown error " "occurred while creating a Consumer group %s on stream %s -> %s", inst->streamConsumerGroup, inst->key, reply->str); ABORT_FINALIZE(RS_RET_ERR); } break; default: LogError(0, RS_RET_ERR, "ensureConsumerGroupCreated: An unknown reply was received " "-> %s", REDIS_REPLIES[(reply->type) % 15]); ABORT_FINALIZE(RS_RET_ERR); } } else { LogError(0, RS_RET_REDIS_ERROR, "ensureConsumerGroupCreated: Could not create group %s on stream %s!", inst->streamConsumerGroup, inst->key); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: if (reply != NULL) freeReplyObject(reply); RETiRet; } rsRetVal ackStreamIndex(instanceConf_t *inst, uchar *stream, uchar *group, uchar *index) { DEFiRet; redisReply *reply = NULL; DBGPRINTF("ackStream: Acknowledging index '%s' in stream %s\n", index, stream); reply = (redisReply *)redisCommand(inst->conn, "XACK %s %s %s", stream, group, index); if (reply != NULL) { switch (reply->type) { case REDIS_REPLY_INTEGER: if (reply->integer == 1) { DBGPRINTF( "ackStreamIndex: index successfully acknowledged " "for stream %s\n", inst->key); } else { DBGPRINTF( "ackStreamIndex: message was not acknowledged " "-> already done?"); } break; case REDIS_REPLY_ERROR: LogError(0, RS_RET_ERR, "ackStreamIndex: An error occurred " "while trying to ACK message %s on %s[%s] -> %s", index, stream, group, reply->str); ABORT_FINALIZE(RS_RET_ERR); default: LogError(0, RS_RET_ERR, "ackStreamIndex: unexpected reply type: %s", REDIS_REPLIES[(reply->type) % 15]); ABORT_FINALIZE(RS_RET_ERR); } } else { LogError(0, RS_RET_REDIS_ERROR, "ackStreamIndex: Could not ACK message with index %s for %s[%s]!", index, stream, group); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } finalize_it: if (reply != NULL) { freeReplyObject(reply); } RETiRet; } static rsRetVal enqueueRedisStreamReply(instanceConf_t *const inst, redisReply *reply) { DEFiRet; struct json_object *json = NULL, *metadata = NULL, *redis = NULL; json = _redisParseArrayReply(reply->element[1]); CHKmalloc(metadata = json_object_new_object()); CHKmalloc(redis = json_object_new_object()); json_object_object_add(redis, "stream", json_object_new_string((char *)inst->key)); json_object_object_add(redis, "index", _redisParseStringReply(reply->element[0])); if (inst->streamConsumerGroup != NULL) { json_object_object_add(redis, "group", json_object_new_string((char *)inst->streamConsumerGroup)); } if (inst->streamConsumerName != NULL) { json_object_object_add(redis, "consumer", json_object_new_string((char *)inst->streamConsumerName)); } // ownership of redis object allocated by json_object_new_object() is taken by json // no need to free/destroy/put redis object json_object_object_add(metadata, "redis", redis); CHKiRet(enqMsgJson(inst, &json, &metadata)); // enqueued message successfully, json and metadata objects are now owned by enqueued message // no need to free/destroy/put json objects json = NULL; metadata = NULL; if (inst->streamConsumerGroup != NULL && inst->streamConsumerACK) { CHKiRet(ackStreamIndex(inst, (uchar *)inst->key, inst->streamConsumerGroup, (uchar *)reply->element[0]->str)); } finalize_it: // If that happens, there was an error during one of the steps and the json object is not enqueued if (json != NULL) json_object_put(json); if (metadata != NULL) json_object_put(metadata); RETiRet; } /* * handle the hiredis Stream XREAD/XREADGROUP return objects. The provided reply is * not freed - this must be done by the caller. * example of stream to parse: * 1) 1) "mystream" <- name of the stream indexes are from (list of streams requested) * 2) 1) 1) "1681749395006-0" <- list of indexes returned for stream * 2) 1) "key1" * 2) "value1" * 2) 1) "1681749409349-0" * 2) 1) "key2" * 2) "value2" * 3) "key2.2" * 4) "value2.2" * json equivalent: * [ * "mystream": [ * { * "1681749395006-0": { * "key1": "value1" * } * }, * { * "1681749409349-0": { * "key2": "value2", * "key2.2": "value2.2" * } * } * ] * ] */ static rsRetVal handleRedisXREADReply(instanceConf_t *const inst, const redisReply *reply) { DEFiRet; redisReply *streamObj = NULL, *msgList = NULL, *msgObj = NULL; if (reply == NULL || reply->type != REDIS_REPLY_ARRAY) { /* we do not process empty or non-ARRAY lines */ DBGPRINTF("handleRedisXREADReply: object is not an array, ignoring\n"); LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: object is not an array, ignoring"); ABORT_FINALIZE(RS_RET_OK_WARN); } else { // iterating on streams for (size_t i = 0; i < reply->elements; i++) { streamObj = reply->element[i]; // object should contain the name of the stream, and an array containing the messages if (streamObj->type != REDIS_REPLY_ARRAY || streamObj->elements != 2) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong object format, " "object should contain the name of the stream and an array of messages"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (streamObj->element[0]->type != REDIS_REPLY_STRING) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field format, " "first entry is not a string (supposed to be stream name)"); ABORT_FINALIZE(RS_RET_OK_WARN); } msgList = streamObj->element[1]; if (msgList->type != REDIS_REPLY_ARRAY) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field format, " "second entry is not an array (supposed to be list of messages for stream)"); ABORT_FINALIZE(RS_RET_OK_WARN); } DBGPRINTF("handleRedisXREADReply: enqueuing messages for stream '%s'\n", streamObj->element[0]->str); for (size_t j = 0; j < msgList->elements; j++) { msgObj = msgList->element[j]; // Object should contain the name of the index, and its content(s) if (msgObj->type != REDIS_REPLY_ARRAY || msgObj->elements != 2) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong object " "format, object should contain the index and its content(s)"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (msgObj->element[0]->type != REDIS_REPLY_STRING) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field " "format, first entry should be a string (index name)"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (msgObj->type != REDIS_REPLY_ARRAY) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXREADReply: wrong field " "format, second entry should be an array (index content(s))"); ABORT_FINALIZE(RS_RET_OK_WARN); } CHKiRet(enqueueRedisStreamReply(inst, msgObj)); // Update current stream index CHKiRet(copyStreamIndexText((char *)inst->streamReadFrom, STREAM_INDEX_STR_BUFSZ, msgObj->element[0]->str, msgObj->element[0]->len, RS_RET_REDIS_ERROR, "Redis XREAD stream index")); DBGPRINTF("handleRedisXREADReply: current stream index is %s\n", inst->streamReadFrom); } } } DBGPRINTF("handleRedisXREADReply: finished enqueuing!\n"); finalize_it: RETiRet; } /* * handle the hiredis Stream XAUTOCLAIM return object. The provided reply is * not freed - this must be done by the caller. * example of stream to parse: * 1) "1681904437564-0" <- next index to use for XAUTOCLAIM * 2) 1) 1) "1681904437525-0" <- list of indexes reclaimed * 2) 1) "toto" * 2) "tata" * 2) 1) "1681904437532-0" * 2) 1) "titi" * 2) "tutu" * 3) (empty) <- indexes that no longer exist, were deleted from the PEL * json equivalent: * "1681904437564-0": [ * { * "1681904437525-0": { * "toto": "tata" * } * }, * { * "1681904437532-0": { * "titi": "tutu" * } * } * ] */ static rsRetVal handleRedisXAUTOCLAIMReply(instanceConf_t *const inst, const redisReply *reply, char **autoclaimIndex) { DEFiRet; redisReply *msgList = NULL, *msgObj = NULL; if (reply == NULL || reply->type != REDIS_REPLY_ARRAY) { /* we do not process empty or non-ARRAY lines */ DBGPRINTF("handleRedisXAUTOCLAIMReply: object is not an array, ignoring\n"); FINALIZE; } else { // Object should contain between 2 and 3 elements (depends on Redis server version) if (reply->elements < 2 || reply->elements > 3) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: wrong number of fields, " "cannot process entry"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (reply->element[0]->type != REDIS_REPLY_STRING) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: the first element " "is not a string, cannot process entry"); ABORT_FINALIZE(RS_RET_OK_WARN); } msgList = reply->element[1]; if (msgList->type != REDIS_REPLY_ARRAY) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: the second element " "is not an array, cannot process entry"); ABORT_FINALIZE(RS_RET_OK_WARN); } DBGPRINTF("handleRedisXAUTOCLAIMReply: re-claiming messages for stream '%s'\n", inst->key); for (size_t j = 0; j < msgList->elements; j++) { msgObj = msgList->element[j]; // Object should contain the name of the index, and its content(s) if (msgObj->type != REDIS_REPLY_ARRAY || msgObj->elements != 2) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: wrong message " "format, cannot process"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (msgObj->element[0]->type != REDIS_REPLY_STRING) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: first message " "element not a string, cannot process"); ABORT_FINALIZE(RS_RET_OK_WARN); } if (msgObj->type != REDIS_REPLY_ARRAY) { LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "handleRedisXAUTOCLAIMReply: second message " "element not an array, cannot process"); ABORT_FINALIZE(RS_RET_OK_WARN); } CHKiRet(enqueueRedisStreamReply(inst, msgObj)); } // Update current stream index with next index from XAUTOCLAIM // No message has to be claimed after that if value is "0-0" CHKiRet(copyStreamIndexText(*autoclaimIndex, STREAM_INDEX_STR_BUFSZ, reply->element[0]->str, reply->element[0]->len, RS_RET_REDIS_ERROR, "Redis XAUTOCLAIM stream index")); DBGPRINTF("handleRedisXAUTOCLAIMReply: next stream index is %s\n", (*autoclaimIndex)); } DBGPRINTF("handleRedisXAUTOCLAIMReply: finished re-claiming!\n"); finalize_it: RETiRet; } /* * Read Redis stream */ rsRetVal redisStreamRead(instanceConf_t *inst) { DEFiRet; redisReply *reply = NULL; uint replyType = 0; sbool mustClaimIdle = 0; char *autoclaimIndex = NULL; assert(inst != NULL); // Ensure stream group is created before reading from it if (inst->streamConsumerGroup != NULL) { CHKiRet(ensureConsumerGroupCreated(inst)); } if (inst->streamAutoclaimIdleTime != 0) { DBGPRINTF("redisStreamRead: getting pending entries for stream '%s' from '%s', with idle time %d\n", inst->key, inst->streamReadFrom, inst->streamAutoclaimIdleTime); CHKmalloc(autoclaimIndex = calloc(1, STREAM_INDEX_STR_BUFSZ)); // Cannot claim from '$', will have to claim from the beginning of the stream if (inst->streamReadFrom[0] == '$') { LogMsg(0, RS_RET_OK, LOG_WARNING, "Cannot claim pending entries from '$', " "will have to claim from the beginning of the stream"); CHKiRet(copyStreamIndexText(autoclaimIndex, STREAM_INDEX_STR_BUFSZ, "0-0", strlen("0-0"), RS_RET_REDIS_ERROR, "default XAUTOCLAIM stream index")); } else { CHKiRet(copyStreamIndexText(autoclaimIndex, STREAM_INDEX_STR_BUFSZ, (const char *)inst->streamReadFrom, strlen((const char *)inst->streamReadFrom), RS_RET_REDIS_ERROR, "stored stream.readFrom value")); } mustClaimIdle = 1; } else { DBGPRINTF("redisStreamRead: beginning to read stream '%s' from '%s'\n", inst->key, inst->streamReadFrom); } do { if (inst->streamConsumerGroup == NULL) { reply = (redisReply *)redisCommand(inst->conn, "XREAD COUNT %d BLOCK %d STREAMS %s %s", BATCH_SIZE, WAIT_TIME_MS, inst->key, inst->streamReadFrom); } else { if (mustClaimIdle) { reply = (redisReply *)redisCommand(inst->conn, "XAUTOCLAIM %s %s %s %d %s COUNT %d", inst->key, inst->streamConsumerGroup, inst->streamConsumerName, inst->streamAutoclaimIdleTime, autoclaimIndex, BATCH_SIZE); } else { reply = (redisReply *)redisCommand(inst->conn, "XREADGROUP GROUP %s %s COUNT %d BLOCK %d STREAMS %s >", inst->streamConsumerGroup, inst->streamConsumerName, BATCH_SIZE, WAIT_TIME_MS, inst->key); } } if (reply == NULL) { LogError(0, RS_RET_REDIS_ERROR, "redisStreamRead: Error while trying to read stream '%s'", inst->key); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } replyType = reply->type; switch (replyType) { case REDIS_REPLY_ARRAY: DBGPRINTF("reply is an array, proceeding...\n"); if (mustClaimIdle) { CHKiRet(handleRedisXAUTOCLAIMReply(inst, reply, &autoclaimIndex)); if (!strncmp(autoclaimIndex, "0-0", 4)) { DBGPRINTF( "redisStreamRead: Caught up with pending messages, " "getting back to regular reads\n"); mustClaimIdle = 0; } } else { CHKiRet(handleRedisXREADReply(inst, reply)); } break; case REDIS_REPLY_NIL: // replies are dequeued but are empty = end of list if (mustClaimIdle) mustClaimIdle = 0; break; case REDIS_REPLY_ERROR: // There is a problem with the key or the Redis instance LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisStreamRead: error " "while reading stream(s) -> %s", reply->str); srSleep(1, 0); ABORT_FINALIZE(RS_RET_REDIS_ERROR); default: LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "redisStreamRead: unexpected " "reply type: %s", REDIS_REPLIES[replyType % 15]); } freeReplyObject(reply); reply = NULL; // while input can run, continue with a new batch } while (glbl.GetGlobalInputTermState() == 0); DBGPRINTF("redisStreamRead: finished to dequeue key '%s'\n", inst->key); finalize_it: if (reply != NULL) freeReplyObject(reply); if (inst->conn != NULL) { redisFree(inst->conn); inst->conn = NULL; inst->currentNode = NULL; } if (autoclaimIndex != NULL) free(autoclaimIndex); RETiRet; } /* * Subscribe to Redis channel */ rsRetVal redisSubscribe(instanceConf_t *inst) { DEFiRet; DBGPRINTF("redisSubscribe: subscribing to channel '%s'\n", inst->key); int ret = redisAsyncCommand(inst->aconn, redisAsyncRecvCallback, NULL, "SUBSCRIBE %s", inst->key); if (ret != REDIS_OK) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "redisSubscribe: Could not subscribe"); ABORT_FINALIZE(RS_RET_REDIS_ERROR); } // Will block on this function as long as connection is open and event loop is not stopped event_base_dispatch(inst->evtBase); DBGPRINTF("redisSubscribe: finished.\n"); finalize_it: RETiRet; } /* * generic worker function */ void workerLoop(struct imhiredisWrkrInfo_s *me) { uint i; DBGPRINTF("workerLoop: beginning of worker loop...\n"); // Connect first time without delay if (me->inst->currentNode != NULL) { rsRetVal ret = me->fnConnectMaster(me->inst); if (ret != RS_RET_OK) { LogMsg(0, ret, LOG_WARNING, "workerLoop: Could not connect successfully to master"); } } while (glbl.GetGlobalInputTermState() == 0) { if (!me->fnIsConnected(me->inst)) { /* * Sleep 10 seconds before attempting to resume a broken connexion * (sleep small amounts to avoid missing termination status) */ LogMsg(0, RS_RET_OK, LOG_INFO, "workerLoop: " "no valid connection, sleeping 10 seconds before retrying..."); for (i = 0; i < 100; i++) { // Rsyslog asked for shutdown, thread should be stopped if (glbl.GetGlobalInputTermState() != 0) goto end_loop; // 100ms sleeps srSleep(0, 100000); } // search the current master node if (me->inst->currentNode == NULL) { if (RS_RET_OK != redisActualizeCurrentNode(me->inst)) continue; } // connect to current master if (me->inst->currentNode != NULL) { rsRetVal ret = me->fnConnectMaster(me->inst); if (ret != RS_RET_OK) { LogMsg(0, ret, LOG_WARNING, "workerLoop: " "Could not connect successfully to master"); } } } if (me->fnIsConnected(me->inst)) { me->fnRun(me->inst); } } end_loop: return; } /* * Workerthread function for a single hiredis consumer */ static void *imhirediswrkr(void *myself) { struct imhiredisWrkrInfo_s *me = (struct imhiredisWrkrInfo_s *)myself; DBGPRINTF("imhiredis: started hiredis consumer workerthread\n"); dbgPrintNode(me->inst->currentNode); if (me->inst->mode == IMHIREDIS_MODE_QUEUE) { me->fnConnectMaster = connectMasterSync; me->fnIsConnected = isConnectedSync; me->fnRun = redisDequeue; } else if (me->inst->mode == IMHIREDIS_MODE_STREAM) { me->fnConnectMaster = connectMasterSync; me->fnIsConnected = isConnectedSync; me->fnRun = redisStreamRead; } else if (me->inst->mode == IMHIREDIS_MODE_SUBSCRIBE) { me->fnConnectMaster = connectMasterAsync; me->fnIsConnected = isConnectedAsync; me->fnRun = redisSubscribe; } workerLoop(me); DBGPRINTF("imhiredis: stopped hiredis consumer workerthread\n"); return NULL; } // -------------------------- redisNode functions ----------------------------------- /* * create a redisNode and set default values * if a valid node is given as parameter, the new node is inserted as the new head of the linked list */ static rsRetVal createRedisNode(redisNode **root) { redisNode *node; DEFiRet; CHKmalloc(node = malloc(sizeof(redisNode))); node->port = 0; node->server = NULL; node->socketPath = NULL; node->usesSocket = 0; node->isMaster = 0; node->next = NULL; if ((*root) == NULL) { *root = node; } else { node->next = (*root); *root = node; } finalize_it: RETiRet; } /* * make a complete copy of the src node into the newly-created node in dst * if dst already contains a node, the new node will be added as the new head of the provided list * src should not be NULL */ rsRetVal copyNode(redisNode *src, redisNode **dst) { DEFiRet; assert(src != NULL); CHKiRet(createRedisNode(dst)); (*dst)->isMaster = src->isMaster; (*dst)->next = src->next; (*dst)->port = src->port; (*dst)->usesSocket = src->usesSocket; if (src->server) (*dst)->server = (uchar *)strdup((const char *)src->server); if (src->socketPath) (*dst)->socketPath = (uchar *)strdup((const char *)src->socketPath); finalize_it: RETiRet; } /* * free all ressources of the node * will return next node if one is present, NULL otherwise */ redisNode *freeNode(redisNode *node) { redisNode *ret = NULL; if (node != NULL) { if (node->next != NULL) ret = node->next; if (node->server != NULL) free(node->server); if (node->socketPath != NULL) free(node->socketPath); free(node); } return ret; } /* * insert node 'elem' after node 'root' in the linked list * both root and elem should not be NULL */ void insertNodeAfter(redisNode *root, redisNode *elem) { assert(root != NULL); assert(elem != NULL); if (root->next != NULL) { elem->next = root->next; } root->next = elem; return; } void dbgPrintNode(redisNode *node) { if (node != NULL) { if (node->usesSocket) { if (node->isMaster) { DBGPRINTF("imhiredis: node is %s (master)\n", node->socketPath); } else { DBGPRINTF("imhiredis: node is %s (replica)\n", node->socketPath); } } else { if (node->isMaster) { DBGPRINTF("imhiredis: node is %s:%d (master)\n", node->server, node->port); } else { DBGPRINTF("imhiredis: node is %s:%d (replica)\n", node->server, node->port); } } } return; } rsyslog-8.2608.0/contrib/imhiredis/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020223 xustar0030 mtime=1787067504.579321786 30 atime=1787067579.894726528 30 ctime=1787067803.379892481 rsyslog-8.2608.0/contrib/imhiredis/Makefile.in0000664000175000017500000006626715241076160017710 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imhiredis ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = imhiredis_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_imhiredis_la_OBJECTS = imhiredis_la-imhiredis.lo imhiredis_la_OBJECTS = $(am_imhiredis_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 = imhiredis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imhiredis_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imhiredis_la-imhiredis.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imhiredis_la_SOURCES) DIST_SOURCES = $(imhiredis_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING \ README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imhiredis.la imhiredis_la_SOURCES = imhiredis.c imhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) $(HIREDIS_SSL_CFLAGS) imhiredis_la_LDFLAGS = -module -avoid-version imhiredis_la_LIBADD = $(HIREDIS_LIBS) $(HIREDIS_SSL_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imhiredis/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imhiredis/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imhiredis.la: $(imhiredis_la_OBJECTS) $(imhiredis_la_DEPENDENCIES) $(EXTRA_imhiredis_la_DEPENDENCIES) $(AM_V_CCLD)$(imhiredis_la_LINK) -rpath $(pkglibdir) $(imhiredis_la_OBJECTS) $(imhiredis_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imhiredis_la-imhiredis.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imhiredis_la-imhiredis.lo: imhiredis.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imhiredis_la-imhiredis.lo -MD -MP -MF $(DEPDIR)/imhiredis_la-imhiredis.Tpo -c -o imhiredis_la-imhiredis.lo `test -f 'imhiredis.c' || echo '$(srcdir)/'`imhiredis.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imhiredis_la-imhiredis.Tpo $(DEPDIR)/imhiredis_la-imhiredis.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imhiredis.c' object='imhiredis_la-imhiredis.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imhiredis_la-imhiredis.lo `test -f 'imhiredis.c' || echo '$(srcdir)/'`imhiredis.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imhiredis_la-imhiredis.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imhiredis_la-imhiredis.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omhttp0000644000000000000000000000013215241076626015446 xustar0030 mtime=1787067798.651804383 30 atime=1787067808.786993238 30 ctime=1787067798.651804383 rsyslog-8.2608.0/contrib/omhttp/0000775000175000017500000000000015241076626015167 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omhttp/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017547 xustar0030 mtime=1752569012.330244093 30 atime=1787067434.299010503 29 ctime=1787067798.64680429 rsyslog-8.2608.0/contrib/omhttp/Makefile.am0000666000175000017500000000034615035412264017221 0ustar00rgerrgerpkglib_LTLIBRARIES = omhttp.la omhttp_la_SOURCES = omhttp.c omhttp_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) omhttp_la_LDFLAGS = -module -avoid-version omhttp_la_LIBADD = $(CURL_LIBS) $(LIBM) EXTRA_DIST = rsyslog-8.2608.0/contrib/omhttp/PaxHeaders/omhttp.c0000644000000000000000000000013215241075234017174 xustar0030 mtime=1787067036.573577695 30 atime=1787067036.716580373 30 ctime=1787067798.651804383 rsyslog-8.2608.0/contrib/omhttp/omhttp.c0000664000175000017500000037326715241075234016662 0ustar00rgerrger/* omhttp.c * This is an http output module based on omelasticsearch * * NOTE: read comments in module-template.h for more specifics! * * Supports profile-based configuration for common HTTP endpoints: * - profile="loki" for Grafana Loki * - profile="hec:splunk:event" for Splunk HTTP Event Collector (Endpoint EVENT) * - profile="hec:splunk:raw" for Splunk HTTP Event Collector (Endpoint RAW) * (proof-of-concept only, see * https://github.com/rsyslog/rsyslog/issues/5756 for feedback) * The profile configuration is based on this method : * profile="techno:vendor:endpoint" * * Copyright 2011 Nathan Scott. * Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH. * Copyright 2018 Christian Tramnitz * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #endif #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "unicode-helper.h" #include "obj-types.h" #include "ratelimit.h" #include "ruleset.h" #include "statsobj.h" #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omhttp") /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) DEFobjCurrIf(statsobj) typedef struct _targetStats { statsobj_t *defaultstats; STATSCOUNTER_DEF(ctrMessagesSubmitted, mutCtrMessagesSubmitted); // Number of message submitted to module STATSCOUNTER_DEF(ctrMessagesSuccess, mutCtrMessagesSuccess); // Number of messages successfully sent STATSCOUNTER_DEF(ctrMessagesFail, mutCtrMessagesFail); // Number of messages that failed to send STATSCOUNTER_DEF(ctrMessagesRetry, mutCtrMessagesRetry); // Number of messages requeued for retry STATSCOUNTER_DEF(ctrHttpRequestSuccess, mutCtrHttpRequestSuccess); // Number of successful HTTP requests STATSCOUNTER_DEF(ctrHttpRequestFail, mutCtrHttpRequestFail); // Number of failed HTTP req, 4XX+ are NOT failures STATSCOUNTER_DEF(ctrHttpStatusSuccess, mutCtrHttpStatusSuccess); // Number of requests returning 1XX/2XX status STATSCOUNTER_DEF(ctrHttpStatusFail, mutCtrHttpStatusFail); // Number of requests returning 300+ status STATSCOUNTER_DEF(ctrHttpRequestsCount, mutCtrHttpRequestsCount); // Number of attempted HTTP requests STATSCOUNTER_DEF(httpRequestsBytes, mutHttpRequestsBytes); // Number of bytes in HTTP requests STATSCOUNTER_DEF(httpRequestsTimeMs, mutHttpRequestsTimeMs); // Number of Times(ms) in HTTP requests STATSCOUNTER_DEF(ctrHttpRequestsStatus0xx, mutCtrHttpRequestsStatus0xx); // HTTP requests returning 0xx STATSCOUNTER_DEF(ctrHttpRequestsStatus1xx, mutCtrHttpRequestsStatus1xx); // HTTP requests returning 1xx STATSCOUNTER_DEF(ctrHttpRequestsStatus2xx, mutCtrHttpRequestsStatus2xx); // HTTP requests returning 2xx STATSCOUNTER_DEF(ctrHttpRequestsStatus3xx, mutCtrHttpRequestsStatus3xx); // HTTP requests returning 3xx STATSCOUNTER_DEF(ctrHttpRequestsStatus4xx, mutCtrHttpRequestsStatus4xx); // HTTP requests returning 4xx STATSCOUNTER_DEF(ctrHttpRequestsStatus5xx, mutCtrHttpRequestsStatus5xx); // HTTP requests returning 5xx } targetStats_t; static prop_t *pInputName = NULL; static int omhttpInstancesCnt = 0; #define NAME_TPL_SPLK_EVENT " StdSplkEvent" #define NAME_TPL_SPLK_RAW " StdSplkRAW" static uchar template_StdSplkEvent[] = "\"{\\\"event\\\":\\\"%rawmsg:::json%\\\"}\""; static uchar template_StdSplkRaw[] = "\"%rawmsg:::drop-last-lf%\n\""; #define WRKR_DATA_TYPE_ES 0xBADF0001 #define HTTP_HEADER_CONTENT_JSON "Content-Type: application/json; charset=utf-8" #define HTTP_HEADER_CONTENT_TEXT "Content-Type: text/plain" #define HTTP_HEADER_CONTENT_KAFKA "Content-Type: application/vnd.kafka.v1+json" #define HTTP_HEADER_ENCODING_GZIP "Content-Encoding: gzip" #define HTTP_HEADER_EXPECT_EMPTY "Expect:" #define HTTP_DEFAULT_HEALTHCHECKTIMEDELAY 30 #define HTTP_DEFAULT_FAILURE_RETRY_DELAY 1 #define VALID_BATCH_FORMATS "newline jsonarray kafkarest lokirest" /* Splunk define value */ #define SPLUNK_HEC_RESTPATH_ENDPOINT_EVENT "services/collector/event" #define SPLUNK_HEC_RESTPATH_ENDPOINT_RAW "services/collector/raw" #define SPLUNK_HEC_RESTPATH_ENDPOINT_HEALTH "services/collector/health" #define SPLUNK_HEC_HEADER_AUTH "Splunk " #define SPLUNK_HEC_USER_AGENT "Rsyslog-omhttp" /* Default batch size constants */ #define DEFAULT_MAX_BATCH_BYTES (10 * 1024 * 1024) /* 10 MB - default max message size for AWS API Gateway */ #define DEFAULT_REPLY_MAX_BYTES (1024 * 1024) /* 1 MB - default max response size */ #define SPLUNK_HEC_MAX_BATCH_BYTES (1024 * 1024) /* 1 MB - Splunk HEC recommended limit */ typedef enum batchFormat_e { FMT_NEWLINE, FMT_JSONARRAY, FMT_KAFKAREST, FMT_LOKIREST } batchFormat_t; typedef enum vendor_e { LOKI, SPLUNK } vendor_t; /* REST API uses this URL: * https://:/restPath */ typedef struct curl_slist HEADER; typedef struct instanceConf_s { int defaultPort; int fdErrFile; /* error file fd or -1 if not open */ pthread_mutex_t mutErrFile; uchar **serverBaseUrls; int numServers; long healthCheckTimeout; long restPathTimeout; uchar *token; uchar *uid; uchar *pwd; uchar *authBuf; uchar *httpcontenttype; uchar *headerContentTypeBuf; uchar *httpheaderkey; uchar *httpheadervalue; uchar *headerBuf; uchar **httpHeaders; int nHttpHeaders; uchar *restPath; uchar *checkPath; uchar *proxyHost; int proxyPort; uchar *tplName; uchar *errorFile; sbool batchMode; uchar *batchFormatName; batchFormat_t batchFormat; vendor_t vendor; sbool bFreeBatchFormatName; sbool dynRestPath; size_t maxBatchBytes; size_t maxBatchSize; size_t replyMaxBytes; sbool compress; int compressionLevel; /* Compression level for zlib, default=-1, fastest=1, best=9, none=0*/ sbool useHttps; sbool allowUnsignedCerts; sbool skipVerifyHost; uchar *caCertFile; uchar *myCertFile; uchar *myPrivKeyFile; sbool reloadOnHup; sbool retryFailures; sbool retryAddMetadata; int nhttpRetryCodes; unsigned int *httpRetryCodes; int nIgnorableCodes; unsigned int *ignorableCodes; int ratelimitInterval; int ratelimitBurst; uchar *pszRatelimitName; /* for retries */ ratelimit_t *ratelimiter; uchar *retryRulesetName; ruleset_t *retryRuleset; struct instanceConf_s *next; uchar *statsName; /* Stats Counter */ targetStats_t *listObjStats; sbool statsBySenders; long healthCheckTimeDelay; // Delay between two Health Check (in seconds) sbool *serverSuspended; /* Array: Is server N globally suspended? */ time_t *serverNextRetry; /* Array: When can we try server N again? */ time_t *serverLastCheck; /* Array: Last successful shared health state update */ sbool *serverCheckInProgress; /* Array: Is a worker already probing server N? */ pthread_mutex_t mutGlobalState; /* Protects these arrays */ } instanceData; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ instanceConf_t *root, *tail; }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ /* * Struct used to describe a server * Now each destination server have is own Curl Handle to improve TLS Handshake and HTTP Keep-Alive */ typedef struct serverData_s { CURL *curlCheckConnHandle; /* libcurl session handle for checking the server connection */ CURL *curlPostHandle; /* libcurl session handle for posting data to the server */ HEADER *curlHeader; /* json POST request info */ HEADER *curlCheckHeader; /* health-check request headers */ uchar *fullUrlPost; /* Keep the full url in cache if dynRestPath is off else last URL used */ uchar *fullUrlHealth; /* Keep the full url healthCheck in cache */ uchar *restPATH; /* Keep restPath last used */ sbool gzipHeaderEnabled; /* Track whether the cached header includes gzip encoding */ } serverData_t; typedef struct wrkrInstanceData { PTR_ASSERT_DEF instanceData *pData; int numServers; int serverIndex; size_t replyLen; size_t replyBufLen; char *reply; long httpStatusCode; /* http status code of response */ sbool bzInitDone; z_stream zstrm; /* zip stream to use for gzip http compression */ struct { uchar **data; /* array of strings, this will be batched up lazily */ size_t sizeBytes; /* total length of this batch in bytes */ size_t nmemb; /* number of messages in batch (for statistics counting) */ } batch; struct { uchar *buf; size_t curLen; size_t len; } compressCtx; serverData_t **listServerDataWkr; } wrkrInstanceData_t; /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"server", eCmdHdlrArray, 0}, {"serverport", eCmdHdlrInt, 0}, {"healthchecktimeout", eCmdHdlrInt, 0}, {"restpathtimeout", eCmdHdlrInt, 0}, {"httpcontenttype", eCmdHdlrGetWord, 0}, {"httpheaderkey", eCmdHdlrGetWord, 0}, {"httpheadervalue", eCmdHdlrString, 0}, {"httpheaders", eCmdHdlrArray, 0}, {"token", eCmdHdlrGetWord, 0}, {"uid", eCmdHdlrGetWord, 0}, {"pwd", eCmdHdlrGetWord, 0}, {"restpath", eCmdHdlrGetWord, 0}, {"checkpath", eCmdHdlrGetWord, 0}, {"dynrestpath", eCmdHdlrBinary, 0}, {"proxyhost", eCmdHdlrString, 0}, {"proxyport", eCmdHdlrInt, 0}, {"batch", eCmdHdlrBinary, 0}, {"batch.format", eCmdHdlrGetWord, 0}, {"batch.maxbytes", eCmdHdlrSize, 0}, {"batch.maxsize", eCmdHdlrSize, 0}, {"replymaxbytes", eCmdHdlrSize, 0}, {"compress", eCmdHdlrBinary, 0}, {"compress.level", eCmdHdlrInt, 0}, {"usehttps", eCmdHdlrBinary, 0}, {"errorfile", eCmdHdlrGetWord, 0}, {"template", eCmdHdlrGetWord, 0}, {"allowunsignedcerts", eCmdHdlrBinary, 0}, {"skipverifyhost", eCmdHdlrBinary, 0}, {"tls.cacert", eCmdHdlrString, 0}, {"tls.mycert", eCmdHdlrString, 0}, {"tls.myprivkey", eCmdHdlrString, 0}, {"reloadonhup", eCmdHdlrBinary, 0}, {"httpretrycodes", eCmdHdlrArray, 0}, {"retry", eCmdHdlrBinary, 0}, {"retry.addmetadata", eCmdHdlrBinary, 0}, {"retry.ruleset", eCmdHdlrString, 0}, {"ratelimit.interval", eCmdHdlrInt, 0}, {"ratelimit.burst", eCmdHdlrInt, 0}, {"ratelimit.name", eCmdHdlrString, 0}, {"name", eCmdHdlrGetWord, 0}, {"httpignorablecodes", eCmdHdlrArray, 0}, {"profile", eCmdHdlrGetWord, 0}, {"statsbysenders", eCmdHdlrBinary, 0}, {"healthchecktimedelay", eCmdHdlrInt, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; static rsRetVal curlSetup(wrkrInstanceData_t *pWrkrData); static void curlCleanup(wrkrInstanceData_t *pWrkrData); static void freeWorkerServerData(wrkrInstanceData_t *pWrkrData); static void ATTR_NONNULL() curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData, serverData_t *serverData); static void cleanupServerData(serverData_t *serverData); static void freeServerData(serverData_t *serverData); static void ATTR_NONNULL(1) markServerSuspended(instanceData *pData, int serverIdx, time_t now); static void ATTR_NONNULL(1) markServerFailed(instanceData *pData, int serverIdx, time_t now); static void ATTR_NONNULL(1) markServerRateLimited(instanceData *pData, int serverIdx, time_t now); static void ATTR_NONNULL(1) markServerAvailable(instanceData *pData, int serverIdx, time_t now); /* compressCtx functions */ static void ATTR_NONNULL() initCompressCtx(wrkrInstanceData_t *pWrkrData); static void ATTR_NONNULL() freeCompressCtx(wrkrInstanceData_t *pWrkrData); static rsRetVal ATTR_NONNULL() resetCompressCtx(wrkrInstanceData_t *pWrkrData, size_t len); static rsRetVal ATTR_NONNULL() growCompressCtx(wrkrInstanceData_t *pWrkrData, size_t newLen); static rsRetVal ATTR_NONNULL() appendCompressCtx(wrkrInstanceData_t *pWrkrData, uchar *srcBuf, size_t srcLen); BEGINcreateInstance CODESTARTcreateInstance; pData->fdErrFile = -1; pthread_mutex_init(&pData->mutErrFile, NULL); // Mutex file pthread_mutex_init(&pData->mutGlobalState, NULL); // Mutex for checkConn pData->caCertFile = NULL; pData->myCertFile = NULL; pData->myPrivKeyFile = NULL; pData->ratelimiter = NULL; pData->retryRulesetName = NULL; pData->retryRuleset = NULL; pData->serverSuspended = NULL; pData->serverNextRetry = NULL; pData->serverLastCheck = NULL; pData->serverCheckInProgress = NULL; ENDcreateInstance BEGINcreateWrkrInstance uchar **batchData; int i = 0; CODESTARTcreateWrkrInstance; PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); pWrkrData->numServers = pData->numServers; pWrkrData->serverIndex = 0; pWrkrData->httpStatusCode = 0; pWrkrData->reply = NULL; pWrkrData->replyLen = 0; pWrkrData->replyBufLen = 0; pWrkrData->bzInitDone = 0; if (pData->batchMode) { pWrkrData->batch.nmemb = 0; pWrkrData->batch.sizeBytes = 0; batchData = (uchar **)malloc(pData->maxBatchSize * sizeof(uchar *)); if (batchData == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: cannot allocate memory for batch queue turning off batch mode\n"); pData->batchMode = 0; /* at least it works */ } else { pWrkrData->batch.data = batchData; } } pWrkrData->listServerDataWkr = calloc((size_t)pWrkrData->numServers, sizeof(serverData_t *)); if (pWrkrData->listServerDataWkr == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: cannot allocate memory for listServer\n"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } for (i = 0; i < pWrkrData->numServers; i++) { pWrkrData->listServerDataWkr[i] = (serverData_t *)calloc(1, sizeof(serverData_t)); if (pWrkrData->listServerDataWkr[i] == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: cannot allocate memory for listServer : %d\n", i); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pWrkrData->listServerDataWkr[i]->curlCheckConnHandle = NULL; pWrkrData->listServerDataWkr[i]->curlPostHandle = NULL; pWrkrData->listServerDataWkr[i]->curlHeader = NULL; pWrkrData->listServerDataWkr[i]->curlCheckHeader = NULL; pWrkrData->listServerDataWkr[i]->fullUrlPost = NULL; pWrkrData->listServerDataWkr[i]->fullUrlHealth = NULL; pWrkrData->listServerDataWkr[i]->restPATH = NULL; pWrkrData->listServerDataWkr[i]->gzipHeaderEnabled = 0; } initCompressCtx(pWrkrData); iRet = curlSetup(pWrkrData); finalize_it: if (iRet != RS_RET_OK) { freeWorkerServerData(pWrkrData); free(pWrkrData->listServerDataWkr); pWrkrData->listServerDataWkr = NULL; } ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINfreeInstance int i; CODESTARTfreeInstance; if (pData->fdErrFile != -1) close(pData->fdErrFile); pthread_mutex_destroy(&pData->mutErrFile); for (i = 0; i < pData->numServers; ++i) free(pData->serverBaseUrls[i]); free(pData->serverBaseUrls); free(pData->token); free(pData->uid); free(pData->httpcontenttype); free(pData->headerContentTypeBuf); free(pData->httpheaderkey); free(pData->httpheadervalue); for (i = 0; i < pData->nHttpHeaders; ++i) { free((void *)pData->httpHeaders[i]); } free(pData->httpHeaders); pData->nHttpHeaders = 0; free(pData->pwd); free(pData->authBuf); free(pData->headerBuf); free(pData->restPath); free(pData->checkPath); free(pData->proxyHost); free(pData->tplName); free(pData->errorFile); free(pData->caCertFile); free(pData->myCertFile); free(pData->myPrivKeyFile); free(pData->httpRetryCodes); free(pData->retryRulesetName); free(pData->ignorableCodes); if (pData->ratelimiter != NULL) ratelimitDestruct(pData->ratelimiter); free(pData->pszRatelimitName); if (pData->bFreeBatchFormatName) free(pData->batchFormatName); if (pData->listObjStats != NULL) { const int numStats = pData->statsBySenders ? pData->numServers : 1; for (int j = 0; j < numStats; ++j) { if (pData->listObjStats[j].defaultstats != NULL) statsobj.Destruct(&(pData->listObjStats[j].defaultstats)); } free(pData->listObjStats); } free(pData->statsName); free(pData->serverSuspended); free(pData->serverNextRetry); free(pData->serverLastCheck); free(pData->serverCheckInProgress); pthread_mutex_destroy(&pData->mutGlobalState); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; freeWorkerServerData(pWrkrData); free(pWrkrData->listServerDataWkr); pWrkrData->listServerDataWkr = NULL; free(pWrkrData->batch.data); pWrkrData->batch.data = NULL; if (pWrkrData->bzInitDone) deflateEnd(&pWrkrData->zstrm); freeCompressCtx(pWrkrData); free(pWrkrData->reply); pWrkrData->reply = NULL; pWrkrData->replyBufLen = 0; pWrkrData->replyLen = 0; ENDfreeWrkrInstance BEGINdbgPrintInstInfo int i; CODESTARTdbgPrintInstInfo; dbgprintf("omhttp\n"); dbgprintf("\ttemplate='%s'\n", pData->tplName); dbgprintf("\tnumServers=%d\n", pData->numServers); dbgprintf("\thealthCheckTimeout=%lu\n", pData->healthCheckTimeout); dbgprintf("\thealthchecktimedelay=%ld\n", pData->healthCheckTimeDelay); dbgprintf("\trestPathTimeout=%lu\n", pData->restPathTimeout); dbgprintf("\tserverBaseUrls="); for (i = 0; i < pData->numServers; ++i) dbgprintf("%c'%s'", i == 0 ? '[' : ' ', pData->serverBaseUrls[i]); dbgprintf("]\n"); dbgprintf("\tdefaultPort=%d\n", pData->defaultPort); dbgprintf("\ttoken='%s'\n", pData->token == NULL ? (uchar *)"(not configured)" : pData->token); dbgprintf("\tuid='%s'\n", pData->uid == NULL ? (uchar *)"(not configured)" : pData->uid); dbgprintf("\thttpcontenttype='%s'\n", pData->httpcontenttype == NULL ? (uchar *)"(not configured)" : pData->httpcontenttype); dbgprintf("\thttpheaderkey='%s'\n", pData->httpheaderkey == NULL ? (uchar *)"(not configured)" : pData->httpheaderkey); dbgprintf("\thttpheadervalue='%s'\n", pData->httpheadervalue == NULL ? (uchar *)"(not configured)" : pData->httpheadervalue); dbgprintf("\thttpHeaders=["); for (i = 0; i < pData->nHttpHeaders; ++i) dbgprintf("\t%s\n", pData->httpHeaders[i]); dbgprintf("\t]\n"); dbgprintf("\tpwd=(%sconfigured)\n", pData->pwd == NULL ? "not " : ""); dbgprintf("\trest path='%s'\n", pData->restPath); dbgprintf("\tcheck path='%s'\n", pData->checkPath); dbgprintf("\tdynamic rest path=%d\n", pData->dynRestPath); dbgprintf("\tproxy host='%s'\n", (pData->proxyHost == NULL) ? "unset" : (char *)pData->proxyHost); dbgprintf("\tproxy port='%d'\n", pData->proxyPort); dbgprintf("\tuse https=%d\n", pData->useHttps); dbgprintf("\tbatch=%d\n", pData->batchMode); dbgprintf("\tbatch.format='%s'\n", pData->batchFormatName); dbgprintf("\tbatch.maxbytes=%zu\n", pData->maxBatchBytes); dbgprintf("\tbatch.maxsize=%zu\n", pData->maxBatchSize); dbgprintf("\treplymaxbytes=%zu\n", pData->replyMaxBytes); dbgprintf("\tcompress=%d\n", pData->compress); dbgprintf("\tcompress.level=%d\n", pData->compressionLevel); dbgprintf("\tallowUnsignedCerts=%d\n", pData->allowUnsignedCerts); dbgprintf("\tskipVerifyHost=%d\n", pData->skipVerifyHost); dbgprintf("\terrorfile='%s'\n", pData->errorFile == NULL ? (uchar *)"(not configured)" : pData->errorFile); dbgprintf("\ttls.cacert='%s'\n", pData->caCertFile); dbgprintf("\ttls.mycert='%s'\n", pData->myCertFile); dbgprintf("\ttls.myprivkey='%s'\n", pData->myPrivKeyFile); dbgprintf("\treloadonhup='%d'\n", pData->reloadOnHup); for (i = 0; i < pData->nhttpRetryCodes; ++i) dbgprintf("%c'%d'", i == 0 ? '[' : ' ', pData->httpRetryCodes[i]); dbgprintf("]\n"); dbgprintf("\tretry='%d'\n", pData->retryFailures); dbgprintf("\tretry.addmetadata='%d'\n", pData->retryAddMetadata); dbgprintf("\tretry.ruleset='%s'\n", pData->retryRulesetName); dbgprintf("\tratelimit.interval='%d'\n", pData->ratelimitInterval); dbgprintf("\tratelimit.burst='%d'\n", pData->ratelimitBurst); for (i = 0; i < pData->nIgnorableCodes; ++i) dbgprintf("%c'%d'", i == 0 ? '[' : ' ', pData->ignorableCodes[i]); dbgprintf("]\n"); dbgprintf("\tratelimit.interval='%d'\n", pData->ratelimitInterval); dbgprintf("\tratelimit.burst='%d'\n", pData->ratelimitBurst); dbgprintf("\tstatsname='%s'\n", pData->statsName); dbgprintf("\tstatsbysenders='%d'\n", pData->statsBySenders); ENDdbgPrintInstInfo /* http POST result string ... useful for debugging */ static size_t curlResult(void *ptr, size_t size, size_t nmemb, void *userdata) { const char *const p = (const char *)ptr; wrkrInstanceData_t *const pWrkrData = (wrkrInstanceData_t *)userdata; char *buf; size_t size_add; size_t newlen; PTR_ASSERT_CHK(pWrkrData, WRKR_DATA_TYPE_ES); if (nmemb != 0 && size > SIZE_MAX / nmemb) { LogError(0, RS_RET_ERR, "omhttp: reply buffer size overflow in curlResult"); pWrkrData->replyLen = 0; if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[0] = '\0'; } return 0; } size_add = size * nmemb; if (size_add > SIZE_MAX - pWrkrData->replyLen) { LogError(0, RS_RET_ERR, "omhttp: reply buffer size overflow in curlResult"); pWrkrData->replyLen = 0; if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[0] = '\0'; } return 0; } newlen = pWrkrData->replyLen + size_add; if (newlen == SIZE_MAX) { LogError(0, RS_RET_ERR, "omhttp: reply buffer size overflow in curlResult"); pWrkrData->replyLen = 0; if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[0] = '\0'; } return 0; } if (pWrkrData->pData->replyMaxBytes > 0 && newlen > pWrkrData->pData->replyMaxBytes) { LogError(0, RS_RET_ERR, "omhttp: reply buffer exceeds replymaxbytes limit (%zu)", pWrkrData->pData->replyMaxBytes); if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[pWrkrData->replyLen] = '\0'; } return 0; } if (newlen + 1 > pWrkrData->replyBufLen) { if ((buf = realloc(pWrkrData->reply, newlen + 1)) == NULL) { LogError(errno, RS_RET_ERR, "omhttp: realloc failed in curlResult"); if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[pWrkrData->replyLen] = '\0'; } return 0; /* abort due to failure */ } pWrkrData->replyBufLen = newlen + 1; pWrkrData->reply = buf; } memcpy(pWrkrData->reply + pWrkrData->replyLen, p, size_add); pWrkrData->replyLen = newlen; if (pWrkrData->replyBufLen > 0) { pWrkrData->reply[pWrkrData->replyLen] = '\0'; } return size_add; } /* Build basic URL part, which includes hostname and port as follows: * http://hostname:port/ based on a server param * Newly creates a cstr for this purpose. * Note: serverParam MUST NOT end in '/' (caller must strip if it exists) */ static rsRetVal computeBaseUrl(const char *const serverParam, const int defaultPort, const sbool useHttps, uchar **baseUrl) { #define SCHEME_HTTPS "https://" #define SCHEME_HTTP "http://" char portBuf[64]; int r = 0; const char *host = serverParam; DEFiRet; assert(serverParam[strlen(serverParam) - 1] != '/'); es_str_t *urlBuf = es_newStr(256); if (urlBuf == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: failed to allocate es_str urlBuf in computeBaseUrl"); ABORT_FINALIZE(RS_RET_ERR); } /* Find where the hostname/ip of the server starts. If the scheme is not specified * in the uri, start the buffer with a scheme corresponding to the useHttps parameter. */ if (strcasestr(serverParam, SCHEME_HTTP)) host = serverParam + strlen(SCHEME_HTTP); else if (strcasestr(serverParam, SCHEME_HTTPS)) host = serverParam + strlen(SCHEME_HTTPS); else r = useHttps ? es_addBuf(&urlBuf, SCHEME_HTTPS, sizeof(SCHEME_HTTPS) - 1) : es_addBuf(&urlBuf, SCHEME_HTTP, sizeof(SCHEME_HTTP) - 1); if (r == 0) r = es_addBuf(&urlBuf, (char *)serverParam, strlen(serverParam)); if (r == 0 && !strchr(host, ':')) { snprintf(portBuf, sizeof(portBuf), ":%d", defaultPort); r = es_addBuf(&urlBuf, portBuf, strlen(portBuf)); } if (r == 0) r = es_addChar(&urlBuf, '/'); if (r == 0) *baseUrl = (uchar *)es_str2cstr(urlBuf, NULL); if (r != 0 || *baseUrl == NULL) { LogError(0, RS_RET_ERR, "omhttp: error occurred computing baseUrl from server %s", serverParam); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (urlBuf) { es_deleteStr(urlBuf); } RETiRet; } static inline void incrementServerIndex(wrkrInstanceData_t *pWrkrData) { pWrkrData->serverIndex = (pWrkrData->serverIndex + 1) % pWrkrData->pData->numServers; } static inline time_t getFailureRetryTime(const instanceData *const pData, const time_t now) { const long delay = (pData->healthCheckTimeDelay > 0) ? pData->healthCheckTimeDelay : HTTP_DEFAULT_HEALTHCHECKTIMEDELAY; return now + (time_t)delay; } static inline time_t getSendFailureRetryTime(const instanceData *const pData, const time_t now) { const long delay = (pData->healthCheckTimeDelay > 0) ? pData->healthCheckTimeDelay : HTTP_DEFAULT_FAILURE_RETRY_DELAY; return now + (time_t)delay; } static void ATTR_NONNULL(1) markServerSuspended(instanceData *const pData, const int serverIdx, const time_t now) { pthread_mutex_lock(&pData->mutGlobalState); pData->serverSuspended[serverIdx] = 1; pData->serverNextRetry[serverIdx] = getFailureRetryTime(pData, now); pData->serverCheckInProgress[serverIdx] = 0; pthread_mutex_unlock(&pData->mutGlobalState); } static void ATTR_NONNULL(1) markServerFailed(instanceData *const pData, const int serverIdx, const time_t now) { pthread_mutex_lock(&pData->mutGlobalState); pData->serverSuspended[serverIdx] = 1; pData->serverNextRetry[serverIdx] = getSendFailureRetryTime(pData, now); pData->serverCheckInProgress[serverIdx] = 0; pthread_mutex_unlock(&pData->mutGlobalState); } static void ATTR_NONNULL(1) markServerRateLimited(instanceData *const pData, const int serverIdx, const time_t now) { pthread_mutex_lock(&pData->mutGlobalState); pData->serverSuspended[serverIdx] = 1; pData->serverNextRetry[serverIdx] = getFailureRetryTime(pData, now); pthread_mutex_unlock(&pData->mutGlobalState); } static void ATTR_NONNULL(1) markServerAvailable(instanceData *const pData, const int serverIdx, const time_t now) { pthread_mutex_lock(&pData->mutGlobalState); pData->serverSuspended[serverIdx] = 0; pData->serverNextRetry[serverIdx] = 0; pData->serverLastCheck[serverIdx] = now; pData->serverCheckInProgress[serverIdx] = 0; pthread_mutex_unlock(&pData->mutGlobalState); } /* checks if connection to ES can be established; also iterates over * potential servers to support high availability (HA) feature. If it * needs to switch server, will record new one in curl handle. */ static rsRetVal ATTR_NONNULL() checkConn(wrkrInstanceData_t *const pWrkrData) { instanceData *pData = pWrkrData->pData; CURLcode res; es_str_t *urlBuf = NULL; time_t now = time(NULL); int i, serverIdx, r; int delayedServerIdx = -1; int reservedServerIdx = -1; DEFiRet; if (pData->checkPath == NULL) { DBGPRINTF("omhttp: checkConn no health check uri configured skipping it\n"); FINALIZE; } pWrkrData->replyLen = 0; for (i = 0; i < pData->numServers; ++i) { /* Round-robin */ serverIdx = (pWrkrData->serverIndex + i) % pData->numServers; serverData_t *server = pWrkrData->listServerDataWkr[serverIdx]; pthread_mutex_lock(&pData->mutGlobalState); if (pData->serverSuspended[serverIdx]) { if (now < pData->serverNextRetry[serverIdx]) { pthread_mutex_unlock(&pData->mutGlobalState); continue; /* Skip this server globally */ } DBGPRINTF("omhttp: Global suspend expired for server %d, retrying...\n", serverIdx); } else if (pData->healthCheckTimeDelay != -1 && pData->serverLastCheck[serverIdx] != 0 && now < (pData->serverLastCheck[serverIdx] + pData->healthCheckTimeDelay)) { pthread_mutex_unlock(&pData->mutGlobalState); if (delayedServerIdx == -1) { delayedServerIdx = serverIdx; } continue; } else if (pData->serverCheckInProgress[serverIdx]) { pthread_mutex_unlock(&pData->mutGlobalState); continue; } pData->serverCheckInProgress[serverIdx] = 1; reservedServerIdx = serverIdx; pthread_mutex_unlock(&pData->mutGlobalState); /* Setup URL and Handle if needed */ if (server->fullUrlHealth == NULL) { pWrkrData->replyLen = 0; if (urlBuf != NULL) { es_deleteStr(urlBuf); urlBuf = NULL; } urlBuf = es_newStr(256); if (urlBuf == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: unable to allocate urlBuf buffer."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } char *serverBase = (char *)pData->serverBaseUrls[serverIdx]; char *checkPath = (char *)pData->checkPath; /* Construct: http://host:port/ + checkPath */ r = es_addBuf(&urlBuf, serverBase, strlen(serverBase)); if (r == 0 && checkPath != NULL) { /* Ensure we don't double-slash if serverBase ends in / */ if (strlen(serverBase) > 0 && serverBase[strlen(serverBase) - 1] == '/' && checkPath[0] == '/') { r = es_addBuf(&urlBuf, checkPath + 1, strlen(checkPath) - 1); } else { r = es_addBuf(&urlBuf, checkPath, strlen(checkPath)); } } if (r == 0) server->fullUrlHealth = (uchar *)es_str2cstr(urlBuf, NULL); if (server->fullUrlHealth == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: unable to generate healthUrl buffer."); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } curl_easy_setopt(server->curlCheckConnHandle, CURLOPT_URL, (char *)server->fullUrlHealth); pWrkrData->replyLen = 0; res = curl_easy_perform(server->curlCheckConnHandle); if (res == CURLE_OK) { markServerAvailable(pData, serverIdx, now); reservedServerIdx = -1; pWrkrData->serverIndex = serverIdx; ABORT_FINALIZE(RS_RET_OK); } else { markServerSuspended(pData, serverIdx, now); reservedServerIdx = -1; DBGPRINTF("omhttp: server %d health check FAILED: %s\n", serverIdx, curl_easy_strerror(res)); } } if (delayedServerIdx != -1) { pWrkrData->serverIndex = delayedServerIdx; ABORT_FINALIZE(RS_RET_OK); } LogMsg(0, RS_RET_SUSPENDED, LOG_WARNING, "omhttp: All servers are globally suspended or unreachable."); ABORT_FINALIZE(RS_RET_SUSPENDED); finalize_it: if (reservedServerIdx != -1) { pthread_mutex_lock(&pData->mutGlobalState); pData->serverCheckInProgress[reservedServerIdx] = 0; pthread_mutex_unlock(&pData->mutGlobalState); } if (urlBuf != NULL) es_deleteStr(urlBuf); pWrkrData->replyLen = 0; if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[0] = '\0'; } RETiRet; } BEGINtryResume CODESTARTtryResume; DBGPRINTF("omhttp: tryResume called\n"); iRet = checkConn(pWrkrData); ENDtryResume /* get the current rest path for this message */ static void ATTR_NONNULL(1) getRestPath(const instanceData *const pData, uchar **const tpls, uchar **const restPath) { if (pData->dynRestPath && tpls != NULL) { *restPath = tpls[1]; } assert(restPath != NULL); return; } static rsRetVal ATTR_NONNULL(1) setPostURL(wrkrInstanceData_t *const pWrkrData, uchar **const tpls) { DEFiRet; instanceData *const pData = pWrkrData->pData; serverData_t *serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; uchar *restPath = NULL; es_str_t *url = NULL; /* Determine if we actually need to rebuild the URL. * We rebuild if: * - dynRestPath is ON (it changes per message) * - The cached fullUrlPost is NULL (first time for this server) */ if (pData->dynRestPath || serverData->fullUrlPost == NULL) { char *baseUrl = (char *)pData->serverBaseUrls[pWrkrData->serverIndex]; url = es_newStrFromCStr(baseUrl, strlen(baseUrl)); if (url == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: error allocating estr for POST url."); ABORT_FINALIZE(RS_RET_ERR); } /* Logic: Batch-specific path > Template-generated path > Default config path */ if (serverData->restPATH != NULL) { restPath = serverData->restPATH; } else if (pData->dynRestPath) { getRestPath(pData, tpls, &restPath); } else { restPath = pData->restPath; } if (restPath != NULL) { if (es_addBuf(&url, (char *)restPath, ustrlen(restPath)) != 0) { LogError(0, RS_RET_ERR, "omhttp: failure appending restPath to URL"); ABORT_FINALIZE(RS_RET_ERR); } } /* Clean up old cached URL before replacing */ if (serverData->fullUrlPost != NULL) { free(serverData->fullUrlPost); } serverData->fullUrlPost = (uchar *)es_str2cstr(url, NULL); if (serverData->fullUrlPost == NULL) { LogError(0, RS_RET_ERR, "omhttp: failure caching URL into serverData"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } } /* 2. Apply the URL to the Curl handle */ curl_easy_setopt(serverData->curlPostHandle, CURLOPT_URL, (char *)serverData->fullUrlPost); DBGPRINTF("omhttp: using REST URL: '%s' (server index %d)\n", serverData->fullUrlPost, pWrkrData->serverIndex); finalize_it: if (url != NULL) { es_deleteStr(url); } RETiRet; } /* * Dumps entire bulk request and response in error log * { * "request": { * "url": "https://url.com:443/path", * "postdata": "mypayload" } * "response" : { * "status": 400, * "response": "error string" } * } */ static rsRetVal renderJsonErrorMessage(wrkrInstanceData_t *pWrkrData, uchar *reqmsg, char **rendered) { DEFiRet; fjson_object *req = NULL; fjson_object *res = NULL; fjson_object *errRoot = NULL; uchar *url = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]->fullUrlPost; if (url == NULL) { url = pWrkrData->pData->serverBaseUrls[pWrkrData->serverIndex]; } if (url == NULL) { url = (uchar *)""; } if ((req = fjson_object_new_object()) == NULL) ABORT_FINALIZE(RS_RET_ERR); fjson_object_object_add(req, "url", fjson_object_new_string((char *)url)); fjson_object_object_add(req, "postdata", fjson_object_new_string((char *)reqmsg)); if ((res = fjson_object_new_object()) == NULL) { fjson_object_put(req); // cleanup request object ABORT_FINALIZE(RS_RET_ERR); } #define ERR_MSG_NULL "NULL: curl request failed or no response" fjson_object_object_add(res, "status", fjson_object_new_int(pWrkrData->httpStatusCode)); if (pWrkrData->reply == NULL) { fjson_object_object_add(res, "message", fjson_object_new_string_len(ERR_MSG_NULL, strlen(ERR_MSG_NULL))); } else { const size_t cappedLen = pWrkrData->replyLen > INT_MAX ? INT_MAX : pWrkrData->replyLen; fjson_object_object_add(res, "message", fjson_object_new_string_len(pWrkrData->reply, (int)cappedLen)); } if ((errRoot = fjson_object_new_object()) == NULL) { fjson_object_put(req); // cleanup request object fjson_object_put(res); // cleanup response object ABORT_FINALIZE(RS_RET_ERR); } fjson_object_object_add(errRoot, "request", req); fjson_object_object_add(errRoot, "response", res); CHKmalloc(*rendered = strdup((char *)fjson_object_to_json_string(errRoot))); finalize_it: if (errRoot != NULL) fjson_object_put(errRoot); RETiRet; } /* write data error request/replies to separate error file * Note: we open the file but never close it before exit. If it * needs to be closed, HUP must be sent. */ static rsRetVal ATTR_NONNULL() writeDataError(wrkrInstanceData_t *const pWrkrData, instanceData *const pData, uchar *const reqmsg) { char *rendered = NULL; size_t toWrite; ssize_t wrRet; sbool bMutLocked = 0; DEFiRet; if (pData->errorFile == NULL) { DBGPRINTF( "omhttp: no local error logger defined - " "ignoring REST error information\n"); FINALIZE; } pthread_mutex_lock(&pData->mutErrFile); bMutLocked = 1; CHKiRet(renderJsonErrorMessage(pWrkrData, reqmsg, &rendered)); if (pData->fdErrFile == -1) { pData->fdErrFile = open((char *)pData->errorFile, O_WRONLY | O_CREAT | O_APPEND | O_LARGEFILE | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (pData->fdErrFile == -1) { LogError(errno, RS_RET_ERR, "omhttp: error opening error file %s", pData->errorFile); ABORT_FINALIZE(RS_RET_ERR); } } /* we do not do real error-handling on the err file, as this finally complicates * things way to much. */ DBGPRINTF("omhttp: error record: '%s'\n", rendered); toWrite = strlen(rendered) + 1; /* Note: we overwrite the '\0' terminator with '\n' -- so we avoid * caling malloc() -- write() does NOT need '\0'! */ rendered[toWrite - 1] = '\n'; /* NO LONGER A STRING! */ wrRet = write(pData->fdErrFile, rendered, toWrite); if (wrRet != (ssize_t)toWrite) { LogError(errno, RS_RET_IO_ERROR, "omhttp: error writing error file %s, write returned %lld", pData->errorFile, (long long)wrRet); } finalize_it: if (bMutLocked) pthread_mutex_unlock(&pData->mutErrFile); free(rendered); RETiRet; } static rsRetVal msgAddResponseMetadata(smsg_t *const __restrict__ pMsg, wrkrInstanceData_t *const pWrkrData, size_t batch_index) { struct json_object *json = NULL; DEFiRet; CHKmalloc(json = json_object_new_object()); /* Following metadata is exposed: $!omhttp!response!code $!omhttp!response!body $!omhttp!response!batch_index */ json_object_object_add(json, "code", json_object_new_int(pWrkrData->httpStatusCode)); if (pWrkrData->reply) { const size_t cappedLen = pWrkrData->replyLen > INT_MAX ? INT_MAX : pWrkrData->replyLen; json_object_object_add(json, "body", json_object_new_string_len(pWrkrData->reply, (int)cappedLen)); } json_object_object_add(json, "batch_index", json_object_new_int(batch_index)); struct json_object *const toAdd = json; json = NULL; CHKiRet(msgAddJSON(pMsg, (uchar *)"!omhttp!response", toAdd, 0, 0)); /* TODO: possible future, an option to automatically parse to json? would be under: $!omhttp!response!parsed */ finalize_it: if (iRet != RS_RET_OK && json) { json_object_put(json); } RETiRet; } static rsRetVal queueBatchOnRetryRuleset(wrkrInstanceData_t *const pWrkrData, instanceData *const pData) { uchar *msgData; smsg_t *pMsg; DEFiRet; int indexStats = pData->statsBySenders ? pWrkrData->serverIndex : 0; if (pData->retryRuleset == NULL) { LogError(0, RS_RET_ERR, "omhttp: queueBatchOnRetryRuleset invalid call with a NULL retryRuleset"); ABORT_FINALIZE(RS_RET_ERR); } for (size_t i = 0; i < pWrkrData->batch.nmemb; i++) { msgData = pWrkrData->batch.data[i]; DBGPRINTF("omhttp: queueBatchOnRetryRuleset putting message '%s' into retry ruleset '%s'\n", msgData, pData->retryRulesetName); // Construct the message object CHKiRet(msgConstruct(&pMsg)); /* These messages are generated by an action worker. In recursive * retry-ruleset setups, FULL_DELAY can make that worker block on the * same queue it must drain. LIGHT_DELAY still applies short * backpressure without waiting indefinitely at the full-delay mark. */ CHKiRet(MsgSetFlowControlType(pMsg, eFLOWCTL_LIGHT_DELAY)); MsgSetInputName(pMsg, pInputName); MsgSetRawMsg(pMsg, (const char *)msgData, ustrlen(msgData)); MsgSetMSGoffs(pMsg, 0); // No header MsgSetTAG(pMsg, (const uchar *)"omhttp-retry", 12); // And place it on the retry ruleset MsgSetRuleset(pMsg, pData->retryRuleset); // Add response specific metadata if (pData->retryAddMetadata) { CHKiRet(msgAddResponseMetadata(pMsg, pWrkrData, i)); } ratelimitAddMsg(pData->ratelimiter, NULL, pMsg); // Count here in case not entire batch succeeds STATSCOUNTER_INC(pWrkrData->pData->listObjStats[indexStats].ctrMessagesRetry, pWrkrData->pData->listObjStats[indexStats].mutCtrMessagesRetry); } finalize_it: RETiRet; } static rsRetVal checkResult(wrkrInstanceData_t *pWrkrData, uchar *reqmsg) { instanceData *pData; long statusCode; size_t numMessages; sbool rateLimited = 0; DEFiRet; CURLcode resCurl = 0; int indexStats = 0; serverData_t *serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; pData = pWrkrData->pData; statusCode = pWrkrData->httpStatusCode; indexStats = pData->statsBySenders ? pWrkrData->serverIndex : 0; targetStats_t *const serverStats = &pData->listObjStats[indexStats]; if (pData->batchMode) { numMessages = pWrkrData->batch.nmemb; } else { numMessages = 1; } /* HTTP status code handling according to new semantics: * - 0xx: Transport/connection errors -> retriable * - 1xx/2xx: Success * - 3xx: Redirection -> non-retriable (for now, redirect support can be added later) * - 4xx: Client errors -> permanent failure (non-retriable) * - 5xx: Server errors -> retriable */ if (statusCode == 0) { // Transport/connection failure - retriable STATSCOUNTER_ADD(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail, numMessages); STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus0xx, serverStats->mutCtrHttpRequestsStatus0xx); iRet = RS_RET_SUSPENDED; } else if (statusCode >= 100 && statusCode < 300) { // 1xx (informational) and 2xx (success) - treat as success STATSCOUNTER_INC(serverStats->ctrHttpStatusSuccess, serverStats->mutCtrHttpStatusSuccess); STATSCOUNTER_ADD(serverStats->ctrMessagesSuccess, serverStats->mutCtrMessagesSuccess, numMessages); if (statusCode >= 100 && statusCode < 200) { STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus1xx, serverStats->mutCtrHttpRequestsStatus1xx); } else if (statusCode >= 200 && statusCode < 300) { STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus2xx, serverStats->mutCtrHttpRequestsStatus2xx); } iRet = RS_RET_OK; } else if (statusCode >= 300 && statusCode < 400) { // 3xx - redirection, treat as permanent failure (non-retriable) STATSCOUNTER_INC(serverStats->ctrHttpStatusFail, serverStats->mutCtrHttpStatusFail); STATSCOUNTER_ADD(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail, numMessages); STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus3xx, serverStats->mutCtrHttpRequestsStatus3xx); iRet = RS_RET_DATAFAIL; // permanent failure } else if (statusCode >= 400 && statusCode < 500) { STATSCOUNTER_INC(serverStats->ctrHttpStatusFail, serverStats->mutCtrHttpStatusFail); STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus4xx, serverStats->mutCtrHttpRequestsStatus4xx); if (statusCode == 429) { /* Return SUSPENDED to trigger rsyslog's retry logic */ STATSCOUNTER_ADD(serverStats->ctrMessagesRetry, serverStats->mutCtrMessagesRetry, numMessages); rateLimited = 1; iRet = RS_RET_SUSPENDED; } else { STATSCOUNTER_ADD(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail, numMessages); iRet = RS_RET_DATAFAIL; // permanent failure } } else if (statusCode >= 500) { // 5xx - server error, retriable STATSCOUNTER_INC(serverStats->ctrHttpStatusFail, serverStats->mutCtrHttpStatusFail); STATSCOUNTER_ADD(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail, numMessages); STATSCOUNTER_INC(serverStats->ctrHttpRequestsStatus5xx, serverStats->mutCtrHttpRequestsStatus5xx); iRet = RS_RET_SUSPENDED; } else { // Unexpected status code STATSCOUNTER_INC(serverStats->ctrHttpStatusFail, serverStats->mutCtrHttpStatusFail); STATSCOUNTER_ADD(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail, numMessages); iRet = RS_RET_DATAFAIL; } // get curl stats for instance { long req = 0; double total = 0; /* record total bytes */ resCurl = curl_easy_getinfo(serverData->curlPostHandle, CURLINFO_REQUEST_SIZE, &req); if (!resCurl) { STATSCOUNTER_ADD(serverStats->httpRequestsBytes, serverStats->mutHttpRequestsBytes, (uint64_t)req); } resCurl = curl_easy_getinfo(serverData->curlPostHandle, CURLINFO_TOTAL_TIME, &total); if (CURLE_OK == resCurl) { /* this needs to be converted to milliseconds */ long total_time_ms = (long)(total * 1000); STATSCOUNTER_ADD(serverStats->httpRequestsTimeMs, serverStats->mutHttpRequestsTimeMs, (uint64_t)total_time_ms); } } /* Check custom retry codes if configured, overriding default behavior */ if (pData->nhttpRetryCodes > 0) { sbool bMatch = 0; for (int i = 0; i < pData->nhttpRetryCodes && pData->httpRetryCodes[i] != 0; ++i) { if (statusCode == (long)pData->httpRetryCodes[i]) { bMatch = 1; break; } } if (bMatch) { /* Force retry for explicitly configured codes */ iRet = RS_RET_SUSPENDED; if (statusCode == 429) { rateLimited = 1; } } } // also check if we can mark this as processed if (iRet != RS_RET_OK && pData->ignorableCodes) { for (int i = 0; i < pData->nIgnorableCodes && pData->ignorableCodes[i] != 0; ++i) { if (statusCode == (long)pData->ignorableCodes[i]) { iRet = RS_RET_OK; rateLimited = 0; break; } } } if (statusCode == 429 && iRet != RS_RET_OK) { iRet = RS_RET_SUSPENDED; rateLimited = 1; } if (iRet != RS_RET_OK) { char *serverName = (char *)pData->serverBaseUrls[pWrkrData->serverIndex]; LogMsg(0, iRet, LOG_ERR, "omhttp: checkResult error http status server: %s code: %ld reply: %s", serverName, statusCode, pWrkrData->reply != NULL ? pWrkrData->reply : "NULL"); writeDataError(pWrkrData, pWrkrData->pData, reqmsg); if (iRet == RS_RET_DATAFAIL) { /* Permanent failure - don't retry */ ABORT_FINALIZE(iRet); } /* Handle retries */ if (pData->batchMode && pData->maxBatchSize > 1) { /* Batch mode: check if retry ruleset is configured */ if (pData->retryFailures && pData->retryRuleset != NULL) { /* Use retry ruleset for batch retry (legacy/advanced mode) */ rsRetVal retryRet = queueBatchOnRetryRuleset(pWrkrData, pData); if (retryRet != RS_RET_OK) { LogMsg(0, retryRet, LOG_ERR, "omhttp: checkResult error while queueing to retry ruleset - " "some messages may be lost"); } /* Don't suspend entire action - we handled individual messages */ iRet = RS_RET_OK; } else { /* No retry ruleset - use core retry by returning RS_RET_SUSPENDED */ /* This is the new default behavior */ DBGPRINTF("omhttp: batch failed, using core retry mechanism\n"); /* iRet already set to RS_RET_SUSPENDED */ } } else { /* Non-batch mode: use core retry (RS_RET_SUSPENDED already set) */ DBGPRINTF("omhttp: single message failed, using core retry mechanism\n"); } } if (rateLimited) { markServerRateLimited(pData, pWrkrData->serverIndex, time(NULL)); } else if (iRet == RS_RET_SUSPENDED) { markServerFailed(pData, pWrkrData->serverIndex, time(NULL)); } else if (iRet == RS_RET_OK && statusCode >= 100 && statusCode < 300) { markServerAvailable(pData, pWrkrData->serverIndex, time(NULL)); } finalize_it: RETiRet; } /* Compress a buffer before sending using zlib. Based on code from tools/omfwd.c * Initialize the zstrm object for gzip compression, using this init function. * deflateInit2(z_stream strm, int level, int method, * int windowBits, int memLevel, int strategy); * strm: the zlib stream held in pWrkrData * level: the compression level held in pData * method: the operation constant Z_DEFLATED * windowBits: the size of the compression window 15 = log_2(32768) * to configure as gzip add 16 to windowBits (w | 16) for final value 31 * memLevel: the memory optimization level 8 is default) * strategy: using Z_DEFAULT_STRATEGY is default */ static rsRetVal compressHttpPayload(wrkrInstanceData_t *pWrkrData, uchar *message, size_t len) { int zRet; unsigned outavail; uchar zipBuf[32 * 1024]; DEFiRet; if (len > UINT_MAX) { LogError(0, RS_RET_ERR, "omhttp: payload too large for gzip compression (%zu bytes)", len); ABORT_FINALIZE(RS_RET_ERR); } if (!pWrkrData->bzInitDone) { pWrkrData->zstrm.zalloc = Z_NULL; pWrkrData->zstrm.zfree = Z_NULL; pWrkrData->zstrm.opaque = Z_NULL; zRet = deflateInit2(&pWrkrData->zstrm, pWrkrData->pData->compressionLevel, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); if (zRet != Z_OK) { DBGPRINTF("omhttp: compressHttpPayload error %d returned from zlib/deflateInit2()\n", zRet); ABORT_FINALIZE(RS_RET_ZLIB_ERR); } pWrkrData->bzInitDone = 1; } else { deflateReset(&pWrkrData->zstrm); } CHKiRet(resetCompressCtx(pWrkrData, len)); /* now doing the compression */ pWrkrData->zstrm.next_in = (Bytef *)message; pWrkrData->zstrm.avail_in = (uInt)len; /* run deflate() on buffer until everything has been compressed */ do { DBGPRINTF("omhttp: compressHttpPayload in deflate() loop, avail_in %d, total_in %ld\n", pWrkrData->zstrm.avail_in, pWrkrData->zstrm.total_in); pWrkrData->zstrm.avail_out = sizeof(zipBuf); pWrkrData->zstrm.next_out = zipBuf; zRet = deflate(&pWrkrData->zstrm, Z_NO_FLUSH); DBGPRINTF("omhttp: compressHttpPayload after deflate, ret %d, avail_out %d\n", zRet, pWrkrData->zstrm.avail_out); if (zRet != Z_OK) ABORT_FINALIZE(RS_RET_ZLIB_ERR); outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out; if (outavail != 0) CHKiRet(appendCompressCtx(pWrkrData, zipBuf, outavail)); } while (pWrkrData->zstrm.avail_out == 0); /* run deflate again with Z_FINISH with no new input */ pWrkrData->zstrm.avail_in = 0; do { pWrkrData->zstrm.avail_out = sizeof(zipBuf); pWrkrData->zstrm.next_out = zipBuf; deflate(&pWrkrData->zstrm, Z_FINISH); /* returns Z_STREAM_END == 1 */ outavail = sizeof(zipBuf) - pWrkrData->zstrm.avail_out; if (outavail != 0) CHKiRet(appendCompressCtx(pWrkrData, zipBuf, outavail)); } while (pWrkrData->zstrm.avail_out == 0); finalize_it: if (pWrkrData->bzInitDone) deflateEnd(&pWrkrData->zstrm); pWrkrData->bzInitDone = 0; RETiRet; } static void ATTR_NONNULL() initCompressCtx(wrkrInstanceData_t *pWrkrData) { pWrkrData->compressCtx.buf = NULL; pWrkrData->compressCtx.curLen = 0; pWrkrData->compressCtx.len = 0; } static void ATTR_NONNULL() freeCompressCtx(wrkrInstanceData_t *pWrkrData) { if (pWrkrData->compressCtx.buf != NULL) { free(pWrkrData->compressCtx.buf); pWrkrData->compressCtx.buf = NULL; } } static rsRetVal ATTR_NONNULL() resetCompressCtx(wrkrInstanceData_t *pWrkrData, size_t len) { DEFiRet; pWrkrData->compressCtx.curLen = 0; pWrkrData->compressCtx.len = len; CHKiRet(growCompressCtx(pWrkrData, len)); finalize_it: if (iRet != RS_RET_OK) freeCompressCtx(pWrkrData); RETiRet; } static rsRetVal ATTR_NONNULL() growCompressCtx(wrkrInstanceData_t *pWrkrData, size_t newLen) { DEFiRet; if (pWrkrData->compressCtx.buf == NULL) { CHKmalloc(pWrkrData->compressCtx.buf = (uchar *)malloc(sizeof(uchar) * newLen)); } else { uchar *const newbuf = (uchar *)realloc(pWrkrData->compressCtx.buf, sizeof(uchar) * newLen); CHKmalloc(newbuf); pWrkrData->compressCtx.buf = newbuf; } pWrkrData->compressCtx.len = newLen; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL() appendCompressCtx(wrkrInstanceData_t *pWrkrData, uchar *srcBuf, size_t srcLen) { size_t newLen; DEFiRet; newLen = pWrkrData->compressCtx.curLen + srcLen; if (newLen > pWrkrData->compressCtx.len) CHKiRet(growCompressCtx(pWrkrData, newLen)); memcpy(pWrkrData->compressCtx.buf + pWrkrData->compressCtx.curLen, srcBuf, srcLen); pWrkrData->compressCtx.curLen = newLen; finalize_it: if (iRet != RS_RET_OK) freeCompressCtx(pWrkrData); RETiRet; } /* Some duplicate code to curlSetup, but we need to add the gzip content-encoding * header at runtime, and if the compression fails, we do not want to send it. * Additionally, the curlCheckConnHandle should not be configured with a gzip header. */ /* Local macro to safely append headers and handle OOM without * losing the already-built list. */ #define SAFE_APPEND(header_str) \ do { \ temp = curl_slist_append(slist, header_str); \ if (temp == NULL) { \ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); \ } \ slist = temp; \ } while (0); static rsRetVal ATTR_NONNULL() buildCurlHeaders(wrkrInstanceData_t *pWrkrData, serverData_t *serverData, HEADER **targetHeader, sbool contentEncodeGzip) { struct curl_slist *slist = NULL; /* Optimization: Temp pointer to capture return without losing list on error */ struct curl_slist *temp = NULL; DEFiRet; /* 1. Set Content-Type Header */ if (pWrkrData->pData->httpcontenttype != NULL) { // If content type specified use it, otherwise use a sane default SAFE_APPEND((char *)pWrkrData->pData->headerContentTypeBuf); } else { if (pWrkrData->pData->batchMode) { // If in batch mode, use the appropriate content type header for the format switch (pWrkrData->pData->batchFormat) { case FMT_JSONARRAY: SAFE_APPEND(HTTP_HEADER_CONTENT_JSON); break; case FMT_KAFKAREST: SAFE_APPEND(HTTP_HEADER_CONTENT_KAFKA); break; case FMT_NEWLINE: SAFE_APPEND(HTTP_HEADER_CONTENT_TEXT); break; case FMT_LOKIREST: SAFE_APPEND(HTTP_HEADER_CONTENT_JSON); break; default: SAFE_APPEND(HTTP_HEADER_CONTENT_TEXT); } } else { // Otherwise non batch, presume most users are sending JSON SAFE_APPEND(HTTP_HEADER_CONTENT_JSON); } } /* 2. Add Configured Header (Single Key-Value) */ if (pWrkrData->pData->headerBuf != NULL) { SAFE_APPEND((char *)pWrkrData->pData->headerBuf); } /* 3. Add Configured Headers (Array) */ for (int k = 0; k < pWrkrData->pData->nHttpHeaders; k++) { SAFE_APPEND((char *)pWrkrData->pData->httpHeaders[k]); } /* 4. Add Expect Header */ // When sending more than 1Kb, libcurl automatically sends an Except: 100-Continue header // and will wait 1s for a response. We disable this behavior. SAFE_APPEND(HTTP_HEADER_EXPECT_EMPTY); /* 5. Add Compression Header */ if (contentEncodeGzip) { SAFE_APPEND(HTTP_HEADER_ENCODING_GZIP); } curl_slist_free_all(*targetHeader); *targetHeader = slist; slist = NULL; serverData->gzipHeaderEnabled = contentEncodeGzip; finalize_it: if (iRet != RS_RET_OK) { /* If we failed halfway, free the list we were building. */ if (slist != NULL) curl_slist_free_all(slist); LogError(0, iRet, "omhttp: error allocating curl header slist"); } RETiRet; } #undef SAFE_APPEND static rsRetVal ATTR_NONNULL(1, 2) curlPost(wrkrInstanceData_t *pWrkrData, uchar *message, size_t msglen, uchar **tpls, const int nmsgs __attribute__((unused))) { CURLcode curlCode; CURL *curl = NULL; char errbuf[CURL_ERROR_SIZE] = ""; int indexStats; serverData_t *serverData; char *postData; size_t postLen; curl_off_t postLenCurl; sbool compressed; DEFiRet; PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); if (pWrkrData->pData->numServers > 1) { DBGPRINTF("omhttp: checkConn has to be done\n"); /* needs to be called to support ES HA feature */ CHKiRet(checkConn(pWrkrData)); } indexStats = pWrkrData->pData->statsBySenders ? pWrkrData->serverIndex : 0; serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; pWrkrData->replyLen = 0; pWrkrData->httpStatusCode = 0; if (pWrkrData->reply != NULL && pWrkrData->replyBufLen > 0) { pWrkrData->reply[0] = '\0'; } postData = (char *)message; postLen = msglen; compressed = 0; if (pWrkrData->pData->compress) { iRet = compressHttpPayload(pWrkrData, message, msglen); if (iRet != RS_RET_OK) { LogError(0, iRet, "omhttp: curlPost error while compressing, will default to uncompressed"); } else { postData = (char *)pWrkrData->compressCtx.buf; postLen = pWrkrData->compressCtx.curLen; compressed = 1; DBGPRINTF("omhttp: curlPost compressed %zu to %zu bytes\n", msglen, postLen); } } /* * Set URL into the Curl Handle if : * - Dynrestpath is set (need to be set each time) * - If first request and fullUrlPost not created */ if (pWrkrData->pData->dynRestPath || serverData->fullUrlPost == NULL) { CHKiRet(setPostURL(pWrkrData, tpls)); /* * Set Header if first request to the destination server */ if (serverData->curlHeader == NULL) { CHKiRet(buildCurlHeaders(pWrkrData, serverData, &serverData->curlHeader, compressed)); curl_easy_setopt(serverData->curlPostHandle, CURLOPT_HTTPHEADER, serverData->curlHeader); } } if (serverData->curlHeader == NULL || serverData->gzipHeaderEnabled != compressed) { CHKiRet(buildCurlHeaders(pWrkrData, serverData, &serverData->curlHeader, compressed)); curl_easy_setopt(serverData->curlPostHandle, CURLOPT_HTTPHEADER, serverData->curlHeader); } /* Set Curl object here */ curl = serverData->curlPostHandle; curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData); if (postLen > (size_t)LLONG_MAX) { LogError(0, RS_RET_ERR, "omhttp: POST payload too large for libcurl (%zu bytes)", postLen); ABORT_FINALIZE(RS_RET_ERR); } postLenCurl = (curl_off_t)postLen; curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE_LARGE, postLenCurl); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf); curlCode = curl_easy_perform(curl); DBGPRINTF("omhttp: curlPost curl returned %lld\n", (long long)curlCode); STATSCOUNTER_INC(pWrkrData->pData->listObjStats[indexStats].ctrHttpRequestsCount, pWrkrData->pData->listObjStats[indexStats].mutCtrHttpRequestsCount); if (curlCode != CURLE_OK) { STATSCOUNTER_INC(pWrkrData->pData->listObjStats[indexStats].ctrHttpRequestFail, pWrkrData->pData->listObjStats[indexStats].mutCtrHttpRequestFail); LogError(0, RS_RET_SUSPENDED, "omhttp: suspending ourselves due to server failure %lld: %s", (long long)curlCode, errbuf); markServerFailed(pWrkrData->pData, pWrkrData->serverIndex, time(NULL)); // Check the result here too and retry if needed, then we should suspend // Usually in batch mode we clobber any iRet values, but probably not a great // idea to keep hitting a dead server. The http status code will be 0 at this point. checkResult(pWrkrData, message); ABORT_FINALIZE(RS_RET_SUSPENDED); } else { STATSCOUNTER_INC(pWrkrData->pData->listObjStats[indexStats].ctrHttpRequestSuccess, pWrkrData->pData->listObjStats[indexStats].mutCtrHttpRequestSuccess); } // Grab the HTTP Response code curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &pWrkrData->httpStatusCode); if (pWrkrData->reply == NULL) { DBGPRINTF("omhttp: curlPost pWrkrData reply==NULL, replyLen = '%llu'\n", (unsigned long long)pWrkrData->replyLen); } else { DBGPRINTF("omhttp: curlPost pWrkrData replyLen = '%llu'\n", (unsigned long long)pWrkrData->replyLen); if (pWrkrData->replyBufLen > 0) { pWrkrData->reply[pWrkrData->replyLen] = '\0'; /* Append 0 byte when buffer is allocated to keep reply safely NUL-terminated */ } DBGPRINTF("omhttp: curlPost pWrkrData reply: '%s'\n", pWrkrData->reply); } CHKiRet(checkResult(pWrkrData, message)); finalize_it: incrementServerIndex(pWrkrData); pWrkrData->replyLen = 0; RETiRet; } /* Build a JSON batch that conforms to the Kafka Rest Proxy format. * See https://docs.confluent.io/current/kafka-rest/docs/quickstart.html for more info. * Want {"records": [{"value": "message1"}, {"value": "message2"}]} */ static rsRetVal serializeBatchKafkaRest(wrkrInstanceData_t *pWrkrData, char **batchBuf) { fjson_object *batchArray = NULL; fjson_object *recordObj = NULL; fjson_object *valueObj = NULL; fjson_object *msgObj = NULL; size_t numMessages = pWrkrData->batch.nmemb; size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas DBGPRINTF("omhttp: serializeBatchKafkaRest numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal); DEFiRet; batchArray = fjson_object_new_array(); if (batchArray == NULL) { LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create array"); ABORT_FINALIZE(RS_RET_ERR); } for (size_t i = 0; i < numMessages; i++) { valueObj = fjson_object_new_object(); if (valueObj == NULL) { fjson_object_put(batchArray); // cleanup LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create value object"); ABORT_FINALIZE(RS_RET_ERR); } msgObj = fjson_tokener_parse((char *)pWrkrData->batch.data[i]); if (msgObj == NULL) { LogError(0, NO_ERRCODE, "omhttp: serializeBatchKafkaRest failed to parse %s as json ignoring it", pWrkrData->batch.data[i]); continue; } fjson_object_object_add(valueObj, "value", msgObj); fjson_object_array_add(batchArray, valueObj); } recordObj = fjson_object_new_object(); if (recordObj == NULL) { fjson_object_put(batchArray); // cleanup LogError(0, RS_RET_ERR, "omhttp: serializeBatchKafkaRest failed to create record object"); ABORT_FINALIZE(RS_RET_ERR); } fjson_object_object_add(recordObj, "records", batchArray); const char *batchString = fjson_object_to_json_string_ext(recordObj, FJSON_TO_STRING_PLAIN); *batchBuf = strndup(batchString, strlen(batchString)); finalize_it: if (recordObj != NULL) { fjson_object_put(recordObj); recordObj = NULL; } RETiRet; } static rsRetVal serializeBatchLokiRest(wrkrInstanceData_t *pWrkrData, char **batchBuf) { fjson_object *batchArray = NULL; fjson_object *recordObj = NULL; fjson_object *msgObj = NULL; size_t numMessages = pWrkrData->batch.nmemb; size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas DBGPRINTF("omhttp: serializeBatchLokiRest numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal); DEFiRet; batchArray = fjson_object_new_array(); if (batchArray == NULL) { LogError(0, RS_RET_ERR, "omhttp: serializeBatchLokiRest failed to create array"); ABORT_FINALIZE(RS_RET_ERR); } for (size_t i = 0; i < numMessages; i++) { DBGPRINTF("omhttp: serializeBatchLokiRest parsing message [%s]\n", (char *)pWrkrData->batch.data[i]); msgObj = fjson_tokener_parse((char *)pWrkrData->batch.data[i]); if (msgObj == NULL) { LogError(0, NO_ERRCODE, "omhttp: serializeBatchLokiRest failed to parse %s as json ignoring it", pWrkrData->batch.data[i]); continue; } fjson_object_array_add(batchArray, msgObj); } recordObj = fjson_object_new_object(); if (recordObj == NULL) { fjson_object_put(batchArray); // cleanup LogError(0, RS_RET_ERR, "omhttp: serializeBatchLokiRest failed to create record object"); ABORT_FINALIZE(RS_RET_ERR); } fjson_object_object_add(recordObj, "streams", batchArray); const char *batchString = fjson_object_to_json_string_ext(recordObj, FJSON_TO_STRING_PLAIN); *batchBuf = strndup(batchString, strlen(batchString)); finalize_it: if (recordObj != NULL) { fjson_object_put(recordObj); recordObj = NULL; } RETiRet; } /* Build a JSON batch by placing each element in an array. */ static rsRetVal serializeBatchJsonArray(wrkrInstanceData_t *pWrkrData, char **batchBuf) { fjson_object *batchArray = NULL; fjson_object *msgObj = NULL; size_t numMessages = pWrkrData->batch.nmemb; size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages + 1; // messages + brackets + commas DBGPRINTF("omhttp: serializeBatchJsonArray numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal); DEFiRet; batchArray = fjson_object_new_array(); if (batchArray == NULL) { LogError(0, RS_RET_ERR, "omhttp: serializeBatchJsonArray failed to create array"); ABORT_FINALIZE(RS_RET_ERR); } for (size_t i = 0; i < numMessages; i++) { msgObj = fjson_tokener_parse((char *)pWrkrData->batch.data[i]); if (msgObj == NULL) { LogError(0, NO_ERRCODE, "omhttp: serializeBatchJsonArray failed to parse %s as json, ignoring it", pWrkrData->batch.data[i]); continue; } fjson_object_array_add(batchArray, msgObj); } const char *batchString = fjson_object_to_json_string_ext(batchArray, FJSON_TO_STRING_PLAIN); *batchBuf = strndup(batchString, strlen(batchString)); finalize_it: if (batchArray != NULL) { fjson_object_put(batchArray); batchArray = NULL; } RETiRet; } /* Build a batch by joining each element with a newline character. */ static rsRetVal serializeBatchNewline(wrkrInstanceData_t *pWrkrData, char **batchBuf) { DEFiRet; size_t numMessages = pWrkrData->batch.nmemb; size_t sizeTotal = pWrkrData->batch.sizeBytes + numMessages; // message + newline + null term int r = 0; DBGPRINTF("omhttp: serializeBatchNewline numMessages=%zd sizeTotal=%zd\n", numMessages, sizeTotal); es_str_t *batchString = es_newStr(1024); if (batchString == NULL) ABORT_FINALIZE(RS_RET_ERR); for (size_t i = 0; i < numMessages; i++) { size_t nToCopy = ustrlen(pWrkrData->batch.data[i]); if (r == 0) r = es_addBuf(&batchString, (char *)pWrkrData->batch.data[i], nToCopy); if (i == numMessages - 1) break; if (r == 0) r = es_addChar(&batchString, '\n'); } if (r == 0) *batchBuf = (char *)es_str2cstr(batchString, NULL); if (r != 0 || *batchBuf == NULL) { LogError(0, RS_RET_ERR, "omhttp: serializeBatchNewline failed to build batch string"); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (batchString != NULL) es_deleteStr(batchString); RETiRet; } /* Return the final batch size in bytes for each serialization method. * Used to decide if a batch should be flushed early. */ static size_t computeBatchSize(wrkrInstanceData_t *pWrkrData) { size_t extraBytes = 0; size_t sizeBytes = pWrkrData->batch.sizeBytes; size_t numMessages = pWrkrData->batch.nmemb; switch (pWrkrData->pData->batchFormat) { case FMT_JSONARRAY: // square brackets, commas between each message // 2 + numMessages - 1 = numMessages + 1 extraBytes = numMessages > 0 ? numMessages + 1 : 2; break; case FMT_KAFKAREST: // '{}', '[]', '"records":'= 2 + 2 + 10 = 14 // '{"value":}' for each message = n * 10 // plus commas between array elements (n > 0 ? n - 1 : 0) extraBytes = (numMessages * 10) + 14 + (numMessages > 0 ? numMessages - 1 : 0); break; case FMT_NEWLINE: // newlines between each message extraBytes = numMessages > 0 ? numMessages - 1 : 0; break; case FMT_LOKIREST: // {"streams":[ '{}', '[]', '"streams":' = 14 // {"stream": {key:value}..., "values":[[timestamp: msg1]]}, // {"stream": {key:value}..., "values":[[timestamp: msg2]]} // ]} // Approximate per-message wrapper overhead (2) plus commas between elements extraBytes = (numMessages * 2) + 14 + (numMessages > 0 ? numMessages - 1 : 0); break; default: // newlines between each message extraBytes = numMessages > 0 ? numMessages - 1 : 0; } return sizeBytes + extraBytes + 1; // plus a null } /* Return the delta of extra bytes added by appending one more message to * the current batch, based on the configured serialization format. */ static inline size_t computeDeltaExtraOnAppend(const wrkrInstanceData_t *pWrkrData) { const size_t numMessages = pWrkrData->batch.nmemb; switch (pWrkrData->pData->batchFormat) { case FMT_JSONARRAY: /* add a comma if there is already at least one element */ return (numMessages > 0) ? 1 : 0; case FMT_KAFKAREST: /* per-message wrapper overhead (e.g. {"value":}) + comma if needed */ return 10 + ((numMessages > 0) ? 1 : 0); case FMT_NEWLINE: /* add a newline if there is already at least one element */ return (numMessages > 0) ? 1 : 0; case FMT_LOKIREST: /* approximate per-message overhead in wrapper + comma if needed */ return 2 + ((numMessages > 0) ? 1 : 0); default: return (numMessages > 0) ? 1 : 0; } } static void ATTR_NONNULL() initializeBatch(wrkrInstanceData_t *pWrkrData) { pWrkrData->batch.sizeBytes = 0; pWrkrData->batch.nmemb = 0; } /* Adds a message to this worker's batch */ static rsRetVal buildBatch(wrkrInstanceData_t *pWrkrData, uchar *message) { DEFiRet; if (pWrkrData->batch.nmemb >= pWrkrData->pData->maxBatchSize) { LogError(0, RS_RET_ERR, "omhttp: buildBatch something has gone wrong," "number of messages in batch is bigger than the max batch size, bailing"); ABORT_FINALIZE(RS_RET_ERR); } pWrkrData->batch.data[pWrkrData->batch.nmemb] = message; pWrkrData->batch.sizeBytes += strlen((char *)message); pWrkrData->batch.nmemb++; finalize_it: RETiRet; } static rsRetVal submitBatch(wrkrInstanceData_t *pWrkrData, uchar **tpls) { DEFiRet; char *batchBuf = NULL; switch (pWrkrData->pData->batchFormat) { case FMT_JSONARRAY: iRet = serializeBatchJsonArray(pWrkrData, &batchBuf); break; case FMT_KAFKAREST: iRet = serializeBatchKafkaRest(pWrkrData, &batchBuf); break; case FMT_LOKIREST: iRet = serializeBatchLokiRest(pWrkrData, &batchBuf); break; case FMT_NEWLINE: iRet = serializeBatchNewline(pWrkrData, &batchBuf); break; default: iRet = serializeBatchNewline(pWrkrData, &batchBuf); } if (iRet != RS_RET_OK || batchBuf == NULL) ABORT_FINALIZE(iRet); DBGPRINTF("omhttp: submitBatch, batch: '%s' tpls: '%p'\n", batchBuf, tpls); CHKiRet(curlPost(pWrkrData, (uchar *)batchBuf, strlen(batchBuf), tpls, pWrkrData->batch.nmemb)); finalize_it: if (batchBuf != NULL) free(batchBuf); RETiRet; } static rsRetVal submitBatchDatafailOk(wrkrInstanceData_t *pWrkrData, uchar **tpls) { DEFiRet; const size_t nmemb = pWrkrData->batch.nmemb; const rsRetVal submitRet = submitBatch(pWrkrData, tpls); if (submitRet == RS_RET_DATAFAIL) { DBGPRINTF("omhttp: permanent data failure for batch of %zu message(s), continuing transaction\n", nmemb); FINALIZE; } CHKiRet(submitRet); finalize_it: RETiRet; } BEGINbeginTransaction CODESTARTbeginTransaction; if (!pWrkrData->pData->batchMode) { FINALIZE; } initializeBatch(pWrkrData); finalize_it: ENDbeginTransaction BEGINcommitTransaction unsigned i; size_t nBytes; sbool submit; CODESTARTcommitTransaction; instanceData *const pData = pWrkrData->pData; const int iNumTpls = pData->dynRestPath ? 2 : 1; int indexStats = pWrkrData->pData->statsBySenders ? pWrkrData->serverIndex : 0; for (i = 0; i < nParams; ++i) { uchar *payload = actParam(pParams, iNumTpls, i, 0).param; uchar *tpls[2] = {payload, NULL}; serverData_t *serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; if (iNumTpls == 2) tpls[1] = actParam(pParams, iNumTpls, i, 1).param; STATSCOUNTER_INC(pWrkrData->pData->listObjStats[indexStats].ctrMessagesSubmitted, pWrkrData->pData->listObjStats[indexStats].mutCtrMessagesSubmitted); if (pData->batchMode) { if (pData->dynRestPath) { uchar *restPath = actParam(pParams, iNumTpls, i, 1).param; if (serverData->restPATH == NULL) { CHKmalloc(serverData->restPATH = (uchar *)strdup((char *)restPath)); } else if (strcmp((char *)serverData->restPATH, (char *)restPath) != 0) { /* restPath changed -> flush current batch if it contains data */ if (pWrkrData->batch.nmemb > 0) { CHKiRet(submitBatchDatafailOk(pWrkrData, NULL)); serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; } initializeBatch(pWrkrData); free(serverData->restPATH); CHKmalloc(serverData->restPATH = (uchar *)strdup((char *)restPath)); } } /* If maxBatchSize is 1, immediately build and post a single-element batch */ if (pData->maxBatchSize == 1) { initializeBatch(pWrkrData); CHKiRet(buildBatch(pWrkrData, payload)); CHKiRet(submitBatchDatafailOk(pWrkrData, tpls)); initializeBatch(pWrkrData); continue; } /* Determine if we should submit due to size/bytes thresholds */ nBytes = ustrlen((char *)payload); submit = 0; if (pWrkrData->batch.nmemb >= pData->maxBatchSize) { submit = 1; DBGPRINTF("omhttp: maxbatchsize limit reached submitting batch of %zd elements.\n", pWrkrData->batch.nmemb); } else { const size_t predicted = computeBatchSize(pWrkrData) + nBytes + computeDeltaExtraOnAppend(pWrkrData); if (predicted > pData->maxBatchBytes) { submit = 1; DBGPRINTF("omhttp: maxbytes limit reached submitting partial batch of %zd elements.\n", pWrkrData->batch.nmemb); } } if (submit) { /* flush current batch, then start a new one. keep dyn restPath consistent */ CHKiRet(submitBatchDatafailOk(pWrkrData, NULL)); initializeBatch(pWrkrData); if (pData->dynRestPath) { uchar *restPath = actParam(pParams, iNumTpls, i, 1).param; serverData = pWrkrData->listServerDataWkr[pWrkrData->serverIndex]; if (serverData->restPATH == NULL || strcmp((char *)serverData->restPATH, (char *)restPath) != 0) { free(serverData->restPATH); CHKmalloc(serverData->restPATH = (uchar *)strdup((char *)restPath)); } } } CHKiRet(buildBatch(pWrkrData, payload)); } else { /* non-batch mode: send immediately */ const rsRetVal postRet = curlPost(pWrkrData, payload, strlen((char *)payload), tpls, 1); if (postRet == RS_RET_DATAFAIL) { DBGPRINTF("omhttp: permanent data failure for single message, continuing transaction\n"); continue; } CHKiRet(postRet); } } /* finalize any remaining batch data */ if (pData->batchMode) { if (pWrkrData->batch.nmemb > 0) { CHKiRet(submitBatchDatafailOk(pWrkrData, NULL)); } else { dbgprintf("omhttp: commitTransaction, pWrkrData->batch.nmemb = 0, nothing to send. \n"); } } finalize_it: ENDcommitTransaction /* Creates authentication header uid:pwd */ static rsRetVal computeAuthHeader(char *uid, char *pwd, uchar **authBuf) { int r; DEFiRet; es_str_t *auth = es_newStr(1024); if (auth == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: failed to allocate es_str auth for auth header construction"); ABORT_FINALIZE(RS_RET_ERR); } r = es_addBuf(&auth, uid, strlen(uid)); if (r == 0) r = es_addChar(&auth, ':'); if (r == 0 && pwd != NULL) r = es_addBuf(&auth, pwd, strlen(pwd)); if (r == 0) *authBuf = (uchar *)es_str2cstr(auth, NULL); if (r != 0 || *authBuf == NULL) { LogError(0, RS_RET_ERR, "omhttp: failed to build auth header\n"); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (auth != NULL) es_deleteStr(auth); RETiRet; } static rsRetVal computeApiHeader(char *key, char *value, uchar **headerBuf) { int r; DEFiRet; es_str_t *header = es_newStr(10240); if (header == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: failed to allocate es_str auth for api header construction"); ABORT_FINALIZE(RS_RET_ERR); } r = es_addBuf(&header, key, strlen(key)); if (r == 0) r = es_addChar(&header, ':'); if (r == 0) r = es_addChar(&header, ' '); if (r == 0 && value != NULL) r = es_addBuf(&header, value, strlen(value)); if (r == 0) *headerBuf = (uchar *)es_str2cstr(header, NULL); if (r != 0 || *headerBuf == NULL) { LogError(0, RS_RET_ERR, "omhttp: failed to build http header\n"); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (header != NULL) es_deleteStr(header); RETiRet; } static void ATTR_NONNULL() curlSetupCommon(wrkrInstanceData_t *const pWrkrData, serverData_t *const serverData, CURL *const handle) { instanceData *const pData = pWrkrData->pData; CURLcode cRet; PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, serverData->curlHeader); curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); curl_easy_setopt(handle, CURLOPT_WRITEDATA, pWrkrData); if (pData->proxyHost != NULL) { curl_easy_setopt(handle, CURLOPT_PROXY, pData->proxyHost); } if (pData->proxyPort != 0) { curl_easy_setopt(handle, CURLOPT_PROXYPORT, (long)pData->proxyPort); } if (pData->restPathTimeout) { curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, pData->restPathTimeout); } if (pData->allowUnsignedCerts) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L); if (pData->skipVerifyHost) curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L); if (pData->authBuf != NULL) { curl_easy_setopt(handle, CURLOPT_USERPWD, pData->authBuf); curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); } if (pData->caCertFile) curl_easy_setopt(handle, CURLOPT_CAINFO, pData->caCertFile); if (pData->myCertFile) curl_easy_setopt(handle, CURLOPT_SSLCERT, pData->myCertFile); if (pData->myPrivKeyFile) curl_easy_setopt(handle, CURLOPT_SSLKEY, pData->myPrivKeyFile); /* Set up a user-agent for HTTP keep alive working with Splunk HEC */ if (pData->vendor == SPLUNK) { cRet = curl_easy_setopt(handle, CURLOPT_USERAGENT, SPLUNK_HEC_USER_AGENT); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlSetupCommon unknown option CURLOPT_USERAGENT\n"); } /* Force Cache session for SSL */ if (pData->useHttps) { cRet = curl_easy_setopt(handle, CURLOPT_SSL_SESSIONID_CACHE, 1L); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlSetupCommon unknown option CURLOPT_SSL_SESSIONID_CACHE\n"); } /* uncomment for in-dept debuggung: curl_easy_setopt(handle, CURLOPT_VERBOSE, TRUE); */ } static void ATTR_NONNULL() curlCheckConnSetup(wrkrInstanceData_t *const pWrkrData, serverData_t *serverData) { PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curlSetupCommon(pWrkrData, serverData, serverData->curlCheckConnHandle); curl_easy_setopt(serverData->curlCheckConnHandle, CURLOPT_HTTPHEADER, serverData->curlCheckHeader); curl_easy_setopt(serverData->curlCheckConnHandle, CURLOPT_TIMEOUT_MS, pWrkrData->pData->healthCheckTimeout); } static void ATTR_NONNULL(1) curlPostSetup(wrkrInstanceData_t *const pWrkrData, serverData_t *serverData) { PTR_ASSERT_SET_TYPE(pWrkrData, WRKR_DATA_TYPE_ES); curlSetupCommon(pWrkrData, serverData, serverData->curlPostHandle); curl_easy_setopt(serverData->curlPostHandle, CURLOPT_POST, 1L); CURLcode cRet; /* Enable TCP keep-alive for this transfer */ cRet = curl_easy_setopt(serverData->curlPostHandle, CURLOPT_TCP_KEEPALIVE, 1L); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPALIVE\n"); /* keep-alive idle time to 120 seconds */ cRet = curl_easy_setopt(serverData->curlPostHandle, CURLOPT_TCP_KEEPIDLE, 120L); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPIDLE\n"); /* interval time between keep-alive probes: 60 seconds */ cRet = curl_easy_setopt(serverData->curlPostHandle, CURLOPT_TCP_KEEPINTVL, 60L); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_TCP_KEEPINTVL\n"); cRet = curl_easy_setopt(serverData->curlPostHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); if (cRet != CURLE_OK) DBGPRINTF("omhttp: curlPostSetup unknown option CURLOPT_HTTP_VERSION\n"); } static rsRetVal ATTR_NONNULL() curlSetup(wrkrInstanceData_t *const pWrkrData) { serverData_t *serverData = NULL; int i = 0; DEFiRet; for (i = 0; i < pWrkrData->pData->numServers; i++) { serverData = pWrkrData->listServerDataWkr[i]; assert(serverData != NULL); CHKiRet(buildCurlHeaders(pWrkrData, serverData, &serverData->curlHeader, 0)); CHKiRet(buildCurlHeaders(pWrkrData, serverData, &serverData->curlCheckHeader, 0)); CHKmalloc(serverData->curlCheckConnHandle = curl_easy_init()); CHKmalloc(serverData->curlPostHandle = curl_easy_init()); curlPostSetup(pWrkrData, serverData); curlCheckConnSetup(pWrkrData, serverData); } finalize_it: if (iRet != RS_RET_OK) { for (int j = 0; j < i; j++) { cleanupServerData(pWrkrData->listServerDataWkr[j]); } cleanupServerData(serverData); } RETiRet; } static void cleanupServerData(serverData_t *serverData) { if (serverData == NULL) { return; } curl_easy_cleanup(serverData->curlCheckConnHandle); serverData->curlCheckConnHandle = NULL; curl_easy_cleanup(serverData->curlPostHandle); serverData->curlPostHandle = NULL; free(serverData->fullUrlPost); serverData->fullUrlPost = NULL; free(serverData->fullUrlHealth); serverData->fullUrlHealth = NULL; free(serverData->restPATH); serverData->restPATH = NULL; curl_slist_free_all(serverData->curlHeader); serverData->curlHeader = NULL; curl_slist_free_all(serverData->curlCheckHeader); serverData->curlCheckHeader = NULL; serverData->gzipHeaderEnabled = 0; } static void freeServerData(serverData_t *serverData) { cleanupServerData(serverData); free(serverData); } static void freeWorkerServerData(wrkrInstanceData_t *pWrkrData) { if (pWrkrData->listServerDataWkr == NULL) { return; } for (int i = 0; i < pWrkrData->numServers; ++i) { freeServerData(pWrkrData->listServerDataWkr[i]); pWrkrData->listServerDataWkr[i] = NULL; } } static void ATTR_NONNULL() curlCleanup(wrkrInstanceData_t *const pWrkrData) { int size = pWrkrData->numServers; if (pWrkrData->listServerDataWkr != NULL) { for (int i = 0; i < size; i++) { cleanupServerData(pWrkrData->listServerDataWkr[i]); } } } static void ATTR_NONNULL() setInstParamDefaults(instanceData *const pData) { pData->serverBaseUrls = NULL; pData->defaultPort = 443; pData->healthCheckTimeout = 3500; pData->healthCheckTimeDelay = -1; // in seconds | -1 is disable | HTTP_DEFAULT_HEALTHCHECKTIMEDELAY pData->token = NULL; pData->uid = NULL; pData->restPathTimeout = 30000; // Set 30000ms (30s) timeout like health check pData->httpcontenttype = NULL; pData->headerContentTypeBuf = NULL; pData->httpheaderkey = NULL; pData->httpheadervalue = NULL; pData->httpHeaders = NULL; pData->nHttpHeaders = 0; pData->pwd = NULL; pData->authBuf = NULL; pData->headerBuf = NULL; pData->restPath = NULL; pData->checkPath = NULL; pData->dynRestPath = 0; pData->proxyHost = NULL; pData->proxyPort = 0; pData->batchMode = 0; pData->batchFormatName = (uchar *)"newline"; pData->batchFormat = FMT_NEWLINE; pData->bFreeBatchFormatName = 0; pData->useHttps = 1; pData->maxBatchBytes = DEFAULT_MAX_BATCH_BYTES; // 10 MB - default max message size for AWS API Gateway pData->maxBatchSize = 100; // 100 messages pData->replyMaxBytes = DEFAULT_REPLY_MAX_BYTES; // 1 MB default max response size (0 disables limit) pData->compress = 0; // off pData->compressionLevel = -1; // default compression pData->allowUnsignedCerts = 0; pData->skipVerifyHost = 0; pData->tplName = NULL; pData->errorFile = NULL; pData->caCertFile = NULL; pData->myCertFile = NULL; pData->myPrivKeyFile = NULL; pData->reloadOnHup = 0; pData->retryFailures = 0; pData->retryAddMetadata = 0; pData->nhttpRetryCodes = 0; pData->httpRetryCodes = NULL; pData->ratelimitBurst = -1; pData->ratelimitInterval = -1; pData->ratelimiter = NULL; pData->pszRatelimitName = NULL; pData->retryRulesetName = NULL; pData->retryRuleset = NULL; pData->nIgnorableCodes = 0; pData->ignorableCodes = NULL; pData->statsBySenders = 0; // Disable by default // increment number of instances ++omhttpInstancesCnt; } static rsRetVal checkHeaderParam(char *const param) { DEFiRet; char *val = strstr(param, ":"); if (val == NULL) { LogError(0, RS_RET_PARAM_ERROR, "missing ':' delimiter in " "parameter '%s'", param); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } finalize_it: RETiRet; } /* Apply profile settings to instance configuration * Profiles are meta-configurations that set multiple parameters at once * for common use cases like Loki or Splunk HEC */ static rsRetVal applyProfileSettings(instanceData *const pData, const char *const profile) { DEFiRet; if (strcasecmp(profile, "loki") == 0) { /* Loki profile settings */ LogMsg(0, RS_RET_OK, LOG_INFO, "omhttp: applying 'loki' profile"); pData->vendor = LOKI; /* Set batch format to lokirest if not already set */ if (!pData->bFreeBatchFormatName) { pData->batchFormatName = (uchar *)"lokirest"; pData->batchFormat = FMT_LOKIREST; } /* Set default rest path for Loki if not set */ if (pData->restPath == NULL) { CHKmalloc(pData->restPath = (uchar *)strdup("loki/api/v1/push")); } /* Enable batch mode by default for Loki */ if (!pData->batchMode) { pData->batchMode = 1; } /* Enable compression for Loki (typically beneficial) */ if (!pData->compress) { pData->compress = 1; pData->compressionLevel = -1; /* default compression */ } /* Set default retry codes to 5xx if not configured */ if (pData->nhttpRetryCodes == 0) { static const unsigned int loki_retry_codes[] = {500, 502, 503, 504}; const size_t num_codes = sizeof(loki_retry_codes) / sizeof(loki_retry_codes[0]); pData->nhttpRetryCodes = num_codes; CHKmalloc(pData->httpRetryCodes = malloc(sizeof(loki_retry_codes))); memcpy(pData->httpRetryCodes, loki_retry_codes, sizeof(loki_retry_codes)); } } else if (strncasecmp(profile, "hec:", 4) == 0) { /* HEC (HTTP Event Collector) profile */ const char *vendor = profile + 4; if (strncasecmp(vendor, "splunk:", 7) == 0) { /* Check endpoint */ const char *endpoint = vendor + 7; pData->vendor = SPLUNK; if (strcasecmp(endpoint, "raw") == 0) { LogMsg(0, RS_RET_OK, LOG_INFO, "omhttp: applying 'hec:splunk:raw' profile"); /* Set default rest path for Splunk HEC */ if (pData->restPath == NULL && !pData->dynRestPath) { CHKmalloc(pData->restPath = (uchar *)strdup(SPLUNK_HEC_RESTPATH_ENDPOINT_RAW)); } /* Set batch format to newline (Splunk HEC uses newline-delimited format) */ if (!pData->bFreeBatchFormatName) { pData->batchFormatName = (uchar *)"newline"; pData->batchFormat = FMT_NEWLINE; } /* Set a custom template */ if (pData->tplName == NULL) { CHKmalloc(pData->tplName = ustrdup((uchar *)NAME_TPL_SPLK_RAW)); } } else if (strcasecmp(endpoint, "event") == 0) { LogMsg(0, RS_RET_OK, LOG_INFO, "omhttp: applying 'hec:splunk:event' profile"); /* Set default rest path for Splunk HEC */ if (pData->restPath == NULL && !pData->dynRestPath) { CHKmalloc(pData->restPath = (uchar *)strdup(SPLUNK_HEC_RESTPATH_ENDPOINT_EVENT)); } /* Set batch format to newline (Splunk HEC uses newline-delimited format) */ if (!pData->bFreeBatchFormatName) { pData->batchFormatName = (uchar *)"newline"; pData->batchFormat = FMT_NEWLINE; } /* Enable batch mode for HEC */ if (!pData->batchMode) { pData->batchMode = 1; } /* Set a custom template */ if (pData->tplName == NULL) { CHKmalloc(pData->tplName = ustrdup((uchar *)NAME_TPL_SPLK_EVENT)); } } else { LogError(0, RS_RET_PARAM_ERROR, "omhttp: unknown Splunk HEC endpoint '%s' in profile", endpoint); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } /* Header */ if (pData->token != NULL) { /* Create authorization header */ es_str_t *tmpHeader = es_newStr(10240); int r = es_addBuf(&tmpHeader, "Authorization", strlen("Authorization")); if (r == 0) r = es_addChar(&tmpHeader, ':'); if (r == 0) r = es_addChar(&tmpHeader, ' '); if (r == 0) r = es_addBuf(&tmpHeader, SPLUNK_HEC_HEADER_AUTH, strlen(SPLUNK_HEC_HEADER_AUTH)); if (r == 0) r = es_addBuf(&tmpHeader, (char *)pData->token, ustrlen(pData->token)); if (r != 0 || tmpHeader == NULL) { LogError(0, RS_RET_ERR, "omhttp: error occurred computing token"); ABORT_FINALIZE(RS_RET_ERR); } // Correction of code if (pData->nHttpHeaders == 0) { CHKmalloc(pData->httpHeaders = malloc(sizeof(uchar *) * 1)); // Only one HEADER pData->nHttpHeaders = 1; pData->httpHeaders[0] = (uchar *)es_str2cstr(tmpHeader, NULL); } else { uchar **new_headers = realloc(pData->httpHeaders, sizeof(uchar *) * (pData->nHttpHeaders + 1)); if (new_headers == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: error reallocating httpHeaders for auth token"); es_deleteStr(tmpHeader); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } pData->httpHeaders = new_headers; pData->httpHeaders[pData->nHttpHeaders] = (uchar *)es_str2cstr(tmpHeader, NULL); pData->nHttpHeaders += 1; } if (tmpHeader != NULL) es_deleteStr(tmpHeader); } else { LogError(0, RS_RET_PARAM_ERROR, "omhttp: Splunk HEC endpoint : a token is need it"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } /* Set default max batch bytes (Splunk recommends < 1MB) */ if (pData->maxBatchBytes == DEFAULT_MAX_BATCH_BYTES) { /* still default */ pData->maxBatchBytes = SPLUNK_HEC_MAX_BATCH_BYTES; /* 1MB */ } /* Set default retry codes to 5xx * https://docs.splunk.com/Documentation/Splunk/9.4.2/Data/TroubleshootHTTPEventCollector#Possible_error_codes */ if (pData->nhttpRetryCodes == 0) { static const unsigned int splk_retry_codes[] = {500, 503}; const size_t num_codes = sizeof(splk_retry_codes) / sizeof(splk_retry_codes[0]); pData->nhttpRetryCodes = num_codes; CHKmalloc(pData->httpRetryCodes = malloc(sizeof(splk_retry_codes))); memcpy(pData->httpRetryCodes, splk_retry_codes, sizeof(splk_retry_codes)); } /* Define health Check URL */ if (pData->checkPath == NULL) { CHKmalloc(pData->checkPath = (uchar *)strdup(SPLUNK_HEC_RESTPATH_ENDPOINT_HEALTH)); } } else { LogError(0, RS_RET_PARAM_ERROR, "omhttp: unknown HEC vendor '%s' in profile", vendor); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } } else { LogError(0, RS_RET_PARAM_ERROR, "omhttp: unknown profile '%s'", profile); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } finalize_it: RETiRet; } static rsRetVal setStatsObject(instanceData *const pData, const char *const serverParam, size_t index) { uchar ctrName[256]; DEFiRet; targetStats_t *const serverStats = &pData->listObjStats[index]; if (serverParam == NULL) { snprintf((char *)ctrName, sizeof(ctrName), "%s(ALL)", pData->statsName); ctrName[sizeof(ctrName) - 1] = '\0'; } else { snprintf((char *)ctrName, sizeof(ctrName), "%s(%s)", pData->statsName, serverParam); ctrName[sizeof(ctrName) - 1] = '\0'; } // instantiate the stats object and add the counters CHKiRet(statsobj.Construct(&(serverStats->defaultstats))); CHKiRet(statsobj.SetName(serverStats->defaultstats, ctrName)); CHKiRet(statsobj.SetOrigin(serverStats->defaultstats, (uchar *)"omhttp")); STATSCOUNTER_INIT(serverStats->ctrMessagesSubmitted, serverStats->mutCtrMessagesSubmitted); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"messages.submitted", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrMessagesSubmitted))); STATSCOUNTER_INIT(serverStats->ctrMessagesSuccess, serverStats->mutCtrMessagesSuccess); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"messages.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrMessagesSuccess))); STATSCOUNTER_INIT(serverStats->ctrMessagesFail, serverStats->mutCtrMessagesFail); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"messages.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrMessagesFail))); STATSCOUNTER_INIT(serverStats->ctrMessagesRetry, serverStats->mutCtrMessagesRetry); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"messages.retry", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrMessagesRetry))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestSuccess, serverStats->mutCtrHttpRequestSuccess); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"request.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestSuccess))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestFail, serverStats->mutCtrHttpRequestFail); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"request.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestFail))); STATSCOUNTER_INIT(serverStats->ctrHttpStatusSuccess, serverStats->mutCtrHttpStatusSuccess); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"request.status.success", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpStatusSuccess))); STATSCOUNTER_INIT(serverStats->ctrHttpStatusFail, serverStats->mutCtrHttpStatusFail); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"request.status.fail", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpStatusFail))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsCount, serverStats->mutCtrHttpRequestsCount); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.count", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsCount))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus0xx, serverStats->mutCtrHttpRequestsStatus0xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.0xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus0xx))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus1xx, serverStats->mutCtrHttpRequestsStatus1xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.1xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus1xx))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus2xx, serverStats->mutCtrHttpRequestsStatus2xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.2xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus2xx))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus3xx, serverStats->mutCtrHttpRequestsStatus3xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.3xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus3xx))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus4xx, serverStats->mutCtrHttpRequestsStatus4xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.4xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus4xx))); STATSCOUNTER_INIT(serverStats->ctrHttpRequestsStatus5xx, serverStats->mutCtrHttpRequestsStatus5xx); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.status.5xx", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->ctrHttpRequestsStatus5xx))); STATSCOUNTER_INIT(serverStats->httpRequestsBytes, serverStats->mutHttpRequestsBytes); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.bytes", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->httpRequestsBytes))); STATSCOUNTER_INIT(serverStats->httpRequestsTimeMs, serverStats->mutHttpRequestsTimeMs); CHKiRet(statsobj.AddCounter(serverStats->defaultstats, (uchar *)"requests.time_ms", ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(serverStats->httpRequestsTimeMs))); CHKiRet(statsobj.ConstructFinalize(serverStats->defaultstats)); finalize_it: RETiRet; } BEGINnewActInst struct cnfparamvals *pvals; char *serverParam = NULL; struct cnfarray *servers = NULL; char *profileName = NULL; int i; int iNumTpls; FILE *fp; char errStr[1024]; char *batchFormatName; int compressionLevel = -1; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "server")) { servers = pvals[i].val.d.ar; } else if (!strcmp(actpblk.descr[i].name, "errorfile")) { CHKmalloc(pData->errorFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "serverport")) { pData->defaultPort = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "healthchecktimeout")) { pData->healthCheckTimeout = (long)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "healthchecktimedelay")) { pData->healthCheckTimeDelay = (long)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "restpathtimeout")) { pData->restPathTimeout = (long)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "token")) { CHKmalloc(pData->token = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "uid")) { CHKmalloc(pData->uid = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "httpcontenttype")) { CHKmalloc(pData->httpcontenttype = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "httpheaderkey")) { CHKmalloc(pData->httpheaderkey = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "httpheadervalue")) { CHKmalloc(pData->httpheadervalue = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "httpheaders")) { const int nmemb = pvals[i].val.d.ar->nmemb; if (nmemb < 0 || (size_t)nmemb > SIZE_MAX / sizeof(uchar *)) { LogError(0, RS_RET_PARAM_ERROR, "omhttp: too many httpheaders configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->nHttpHeaders = nmemb; CHKmalloc(pData->httpHeaders = malloc(sizeof(uchar *) * (size_t)nmemb)); for (int j = 0; j < nmemb; ++j) { char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); CHKiRet(checkHeaderParam(cstr)); pData->httpHeaders[j] = (uchar *)cstr; } } else if (!strcmp(actpblk.descr[i].name, "pwd")) { CHKmalloc(pData->pwd = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "restpath")) { CHKmalloc(pData->restPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "checkpath")) { CHKmalloc(pData->checkPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "dynrestpath")) { pData->dynRestPath = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "proxyhost")) { CHKmalloc(pData->proxyHost = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "proxyport")) { pData->proxyPort = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "batch")) { pData->batchMode = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "batch.format")) { CHKmalloc(batchFormatName = es_str2cstr(pvals[i].val.d.estr, NULL)); if (strstr(VALID_BATCH_FORMATS, batchFormatName) != NULL) { pData->batchFormatName = (uchar *)batchFormatName; pData->bFreeBatchFormatName = 1; if (!strcmp(batchFormatName, "newline")) { pData->batchFormat = FMT_NEWLINE; } else if (!strcmp(batchFormatName, "jsonarray")) { pData->batchFormat = FMT_JSONARRAY; } else if (!strcmp(batchFormatName, "kafkarest")) { pData->batchFormat = FMT_KAFKAREST; } else if (!strcmp(batchFormatName, "lokirest")) { pData->batchFormat = FMT_LOKIREST; } } else { LogError(0, NO_ERRCODE, "error: 'batch.format' %s unknown defaulting to 'newline'", batchFormatName); } } else if (!strcmp(actpblk.descr[i].name, "batch.maxbytes")) { pData->maxBatchBytes = (size_t)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "batch.maxsize")) { pData->maxBatchSize = (size_t)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "replymaxbytes")) { pData->replyMaxBytes = (size_t)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "compress")) { pData->compress = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "compress.level")) { compressionLevel = pvals[i].val.d.n; if (compressionLevel == -1 || (compressionLevel >= 0 && compressionLevel < 10)) { pData->compressionLevel = compressionLevel; } else { LogError(0, NO_ERRCODE, "omhttp: invalid compress.level %d using default instead," "valid levels are -1 and 0-9", compressionLevel); } } else if (!strcmp(actpblk.descr[i].name, "allowunsignedcerts")) { pData->allowUnsignedCerts = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "skipverifyhost")) { pData->skipVerifyHost = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "usehttps")) { pData->useHttps = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "tls.cacert")) { CHKmalloc(pData->caCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->caCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); LogError(0, RS_RET_NO_FILE_ACCESS, "error: 'tls.cacert' file %s couldn't be accessed: %s\n", pData->caCertFile, errStr); } else { fclose(fp); } } else if (!strcmp(actpblk.descr[i].name, "tls.mycert")) { CHKmalloc(pData->myCertFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->myCertFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); LogError(0, RS_RET_NO_FILE_ACCESS, "error: 'tls.mycert' file %s couldn't be accessed: %s\n", pData->myCertFile, errStr); } else { fclose(fp); } } else if (!strcmp(actpblk.descr[i].name, "tls.myprivkey")) { CHKmalloc(pData->myPrivKeyFile = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); fp = fopen((const char *)pData->myPrivKeyFile, "r"); if (fp == NULL) { rs_strerror_r(errno, errStr, sizeof(errStr)); LogError(0, RS_RET_NO_FILE_ACCESS, "error: 'tls.myprivkey' file %s couldn't be accessed: %s\n", pData->myPrivKeyFile, errStr); } else { fclose(fp); } } else if (!strcmp(actpblk.descr[i].name, "reloadonhup")) { pData->reloadOnHup = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "httpretrycodes")) { const int nmemb = pvals[i].val.d.ar->nmemb; if (nmemb < 0 || (size_t)nmemb > SIZE_MAX / sizeof(unsigned int)) { LogError(0, RS_RET_PARAM_ERROR, "omhttp: too many httpretrycodes configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->nhttpRetryCodes = nmemb; // note: use zero as sentinel value CHKmalloc(pData->httpRetryCodes = calloc((size_t)nmemb, sizeof(unsigned int))); int count = 0; for (int j = 0; j < nmemb; ++j) { int bSuccess = 0; long long n = es_str2num(pvals[i].val.d.ar->arr[j], &bSuccess); if (!bSuccess) { char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); LogError(0, RS_RET_NO_FILE_ACCESS, "error: 'httpRetryCode' '%s' is not a number - ignored\n", cstr); free(cstr); } else { pData->httpRetryCodes[count++] = n; } } } else if (!strcmp(actpblk.descr[i].name, "retry")) { pData->retryFailures = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "retry.ruleset")) { CHKmalloc(pData->retryRulesetName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "retry.addmetadata")) { pData->retryAddMetadata = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.burst")) { pData->ratelimitBurst = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.interval")) { pData->ratelimitInterval = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ratelimit.name")) { CHKmalloc(pData->pszRatelimitName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "name")) { CHKmalloc(pData->statsName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "httpignorablecodes")) { const int nmemb = pvals[i].val.d.ar->nmemb; if (nmemb < 0 || (size_t)nmemb > SIZE_MAX / sizeof(unsigned int)) { LogError(0, RS_RET_PARAM_ERROR, "omhttp: too many httpignorablecodes configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->nIgnorableCodes = nmemb; // note: use zero as sentinel value CHKmalloc(pData->ignorableCodes = calloc((size_t)nmemb, sizeof(unsigned int))); int count = 0; for (int j = 0; j < nmemb; ++j) { int bSuccess = 0; long long n = es_str2num(pvals[i].val.d.ar->arr[j], &bSuccess); if (!bSuccess) { char *cstr = es_str2cstr(pvals[i].val.d.ar->arr[j], NULL); LogError(0, RS_RET_NO_FILE_ACCESS, "error: 'httpIgnorableCodes' '%s' is not a number - ignored\n", cstr); free(cstr); } else { pData->ignorableCodes[count++] = n; } } } else if (!strcmp(actpblk.descr[i].name, "profile")) { CHKmalloc(profileName = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "statsbysenders")) { pData->statsBySenders = pvals[i].val.d.n; } else { LogError(0, RS_RET_INTERNAL_ERROR, "omhttp: program error, " "non-handled param '%s'", actpblk.descr[i].name); } } if (pData->pszRatelimitName != NULL) { if (pData->ratelimitInterval != -1 || pData->ratelimitBurst != -1) { LogError(0, RS_RET_INVALID_PARAMS, "omhttp: ratelimit.name is mutually exclusive with " "ratelimit.interval and ratelimit.burst - using ratelimit.name"); } pData->ratelimitInterval = 0; pData->ratelimitBurst = 0; } else { if (pData->ratelimitInterval == -1) pData->ratelimitInterval = 600; if (pData->ratelimitBurst == -1) pData->ratelimitBurst = 20000; } if (pData->pwd != NULL && pData->uid == NULL) { LogError(0, RS_RET_UID_MISSING, "omhttp: password is provided, but no uid " "- action definition invalid"); ABORT_FINALIZE(RS_RET_UID_MISSING); } if (pData->httpheaderkey != NULL && pData->httpheadervalue == NULL) { LogError(0, RS_RET_UID_MISSING, "omhttp: http header key is provided, but no http header value " "- action definition invalid"); ABORT_FINALIZE(RS_RET_UID_MISSING); } if (pData->dynRestPath && pData->restPath == NULL) { LogError(0, RS_RET_CONFIG_ERROR, "omhttp: requested dynamic rest path, but no name for rest " "path template given - action definition invalid"); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } /* Apply header before profile */ if (pData->httpcontenttype != NULL) CHKiRet(computeApiHeader((char *)"Content-Type", (char *)pData->httpcontenttype, &pData->headerContentTypeBuf)); if (pData->httpheaderkey != NULL) CHKiRet(computeApiHeader((char *)pData->httpheaderkey, (char *)pData->httpheadervalue, &pData->headerBuf)); /* Apply profile settings if specified */ if (profileName != NULL) { CHKiRet(applyProfileSettings(pData, profileName)); free(profileName); profileName = NULL; } if (pData->proxyHost == NULL) { const char *http_proxy; if ((http_proxy = getenv("http_proxy")) == NULL) { http_proxy = getenv("HTTP_PROXY"); } if (http_proxy != NULL) { pData->proxyHost = ustrdup(http_proxy); } } if (pData->uid != NULL) CHKiRet(computeAuthHeader((char *)pData->uid, (char *)pData->pwd, &pData->authBuf)); iNumTpls = 1; if (pData->dynRestPath) ++iNumTpls; DBGPRINTF("omhttp: requesting %d templates\n", iNumTpls); CODE_STD_STRING_REQUESTnewActInst(iNumTpls); CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar *)strdup((pData->tplName == NULL) ? " StdJSONFmt" : (char *)pData->tplName), OMSR_NO_RQD_TPL_OPTS)); /* we need to request additional templates. If we have a dynamic search index, * it will always be string 1. Type may be 1 or 2, depending on whether search * index is dynamic as well. Rule needs to be followed throughout the module. */ iNumTpls = 1; if (pData->dynRestPath) { CHKiRet(OMSRsetEntry(*ppOMSR, iNumTpls, ustrdup(pData->restPath), OMSR_NO_RQD_TPL_OPTS)); ++iNumTpls; } if (!pData->statsName) { uchar pszAName[64]; snprintf((char *)pszAName, sizeof(pszAName), "omhttp-%d", omhttpInstancesCnt); pData->statsName = ustrdup(pszAName); } if (servers != NULL) { const int nmemb = servers->nmemb; if (nmemb <= 0 || (size_t)nmemb > SIZE_MAX / sizeof(uchar *) || (pData->statsBySenders && (size_t)nmemb > SIZE_MAX / sizeof(targetStats_t)) || (size_t)nmemb > SIZE_MAX / sizeof(sbool) || (size_t)nmemb > SIZE_MAX / sizeof(time_t)) { LogError(0, RS_RET_PARAM_ERROR, "omhttp: too many servers configured"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } pData->numServers = nmemb; pData->serverBaseUrls = malloc((size_t)nmemb * sizeof(uchar *)); if (pData->serverBaseUrls == NULL) { LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer " "for http server configuration."); ABORT_FINALIZE(RS_RET_ERR); } /* Set up the stats object array */ const int numStats = pData->statsBySenders ? nmemb : 1; pData->listObjStats = malloc((size_t)numStats * sizeof(targetStats_t)); if (pData->listObjStats == NULL) { LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer " "for http server stats object."); ABORT_FINALIZE(RS_RET_ERR); } if (!pData->statsBySenders) { CHKiRet(setStatsObject(pData, NULL, 0)); } for (i = 0; i < servers->nmemb; ++i) { serverParam = es_str2cstr(servers->arr[i], NULL); if (serverParam == NULL) { LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer " "for http server configuration."); ABORT_FINALIZE(RS_RET_ERR); } /* Remove a trailing slash if it exists */ const size_t serverParamLastChar = strlen(serverParam) - 1; if (serverParam[serverParamLastChar] == '/') { serverParam[serverParamLastChar] = '\0'; } if (pData->statsBySenders) { CHKiRet(setStatsObject(pData, serverParam, i)); } CHKiRet(computeBaseUrl(serverParam, pData->defaultPort, pData->useHttps, pData->serverBaseUrls + i)); free(serverParam); serverParam = NULL; } } else { LogMsg(0, RS_RET_OK, LOG_WARNING, "omhttp: No servers specified, using localhost"); pData->numServers = 1; pData->serverBaseUrls = malloc(sizeof(uchar *)); if (pData->serverBaseUrls == NULL) { LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer " "for http server configuration."); ABORT_FINALIZE(RS_RET_ERR); } /* Set up the stats object array (force global stats) */ pData->listObjStats = malloc(sizeof(targetStats_t)); if (pData->listObjStats == NULL) { LogError(0, RS_RET_ERR, "omhttp: unable to allocate buffer " "for http server stats object."); ABORT_FINALIZE(RS_RET_ERR); } CHKiRet(setStatsObject(pData, NULL, 0)); CHKiRet(computeBaseUrl("localhost", pData->defaultPort, pData->useHttps, pData->serverBaseUrls)); } /* Alloc for checkConn */ pData->serverSuspended = calloc(pData->numServers, sizeof(sbool)); pData->serverNextRetry = calloc(pData->numServers, sizeof(time_t)); pData->serverLastCheck = calloc(pData->numServers, sizeof(time_t)); pData->serverCheckInProgress = calloc(pData->numServers, sizeof(sbool)); if (pData->serverSuspended == NULL || pData->serverNextRetry == NULL || pData->serverLastCheck == NULL || pData->serverCheckInProgress == NULL) { LogError(0, RS_RET_OUT_OF_MEMORY, "omhttp: failed to allocate global state arrays"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (pData->retryFailures) { if (pData->pszRatelimitName != NULL) { CHKiRet(ratelimitNewFromConfig(&pData->ratelimiter, loadModConf->pConf, (char *)pData->pszRatelimitName, "omhttp", NULL)); } else { CHKiRet(ratelimitNew(&pData->ratelimiter, "omhttp", NULL)); ratelimitSetLinuxLike(pData->ratelimiter, (unsigned)pData->ratelimitInterval, (unsigned)pData->ratelimitBurst); } ratelimitSetNoTimeCache(pData->ratelimiter); } /* node created, let's add to list of instance configs for the module */ if (loadModConf->tail == NULL) { loadModConf->tail = loadModConf->root = pData; } else { loadModConf->tail->next = pData; loadModConf->tail = pData; } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); if (serverParam) free(serverParam); if (profileName) free(profileName); ENDnewActInst BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; pModConf->root = pModConf->tail = NULL; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; loadModConf = NULL; /* done loading */ ENDendCnfLoad BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = pModConf->root; inst != NULL; inst = inst->next) { ruleset_t *pRuleset; rsRetVal localRet; if (inst->retryRulesetName) { localRet = ruleset.GetRuleset(pModConf->pConf, &pRuleset, inst->retryRulesetName); if (localRet == RS_RET_NOT_FOUND) { LogError(0, localRet, "omhttp: retry.ruleset '%s' not found - " "no retry ruleset will be used", inst->retryRulesetName); } else { inst->retryRuleset = pRuleset; } } } ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf // HUP handling for the instance... BEGINdoHUP CODESTARTdoHUP; pthread_mutex_lock(&pData->mutErrFile); if (pData->fdErrFile != -1) { close(pData->fdErrFile); pData->fdErrFile = -1; } pthread_mutex_unlock(&pData->mutErrFile); ENDdoHUP // HUP handling for the worker... BEGINdoHUPWrkr CODESTARTdoHUPWrkr; if (pWrkrData->pData->reloadOnHup) { LogMsg(0, NO_ERRCODE, LOG_INFO, "omhttp: received HUP reloading curl handles"); curlCleanup(pWrkrData); CHKiRet(curlSetup(pWrkrData)); } finalize_it: ENDdoHUPWrkr BEGINmodExit CODESTARTmodExit; if (pInputName != NULL) prop.Destruct(&pInputName); curl_global_cleanup(); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(statsobj, CORE_COMPONENT); ENDmodExit NO_LEGACY_CONF_parseSelectorAct BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMODTX_QUERIES CODEqueryEtryPt_STD_OMOD8_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES CODEqueryEtryPt_doHUP CODEqueryEtryPt_doHUPWrkr /* Load the worker HUP handling code */ CODEqueryEtryPt_STD_CONF2_QUERIES ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; uchar *pTmp; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(statsobj, CORE_COMPONENT)); if (curl_global_init(CURL_GLOBAL_ALL) != 0) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -http disabled"); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } /* Add custom template for Splunk endpoit RAW */ pTmp = template_StdSplkRaw; tplAddLine(ourConf, (char *)NAME_TPL_SPLK_RAW, &pTmp); /* Add custom template for Splunk endpoit EVENT */ pTmp = template_StdSplkEvent; tplAddLine(ourConf, (char *)NAME_TPL_SPLK_EVENT, &pTmp); CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("omhttp"), sizeof("omhttp") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); ENDmodInit /* vi:set ai: */ rsyslog-8.2608.0/contrib/omhttp/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161017561 xustar0030 mtime=1787067505.125331972 29 atime=1787067578.88670773 30 ctime=1787067798.649804346 rsyslog-8.2608.0/contrib/omhttp/Makefile.in0000664000175000017500000006571415241076161017243 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omhttp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omhttp_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_omhttp_la_OBJECTS = omhttp_la-omhttp.lo omhttp_la_OBJECTS = $(am_omhttp_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 = omhttp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omhttp_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omhttp_la-omhttp.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omhttp_la_SOURCES) DIST_SOURCES = $(omhttp_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omhttp.la omhttp_la_SOURCES = omhttp.c omhttp_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) omhttp_la_LDFLAGS = -module -avoid-version omhttp_la_LIBADD = $(CURL_LIBS) $(LIBM) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omhttp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omhttp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omhttp.la: $(omhttp_la_OBJECTS) $(omhttp_la_DEPENDENCIES) $(EXTRA_omhttp_la_DEPENDENCIES) $(AM_V_CCLD)$(omhttp_la_LINK) -rpath $(pkglibdir) $(omhttp_la_OBJECTS) $(omhttp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhttp_la-omhttp.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omhttp_la-omhttp.lo: omhttp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhttp_la-omhttp.lo -MD -MP -MF $(DEPDIR)/omhttp_la-omhttp.Tpo -c -o omhttp_la-omhttp.lo `test -f 'omhttp.c' || echo '$(srcdir)/'`omhttp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhttp_la-omhttp.Tpo $(DEPDIR)/omhttp_la-omhttp.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhttp.c' object='omhttp_la-omhttp.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttp_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhttp_la-omhttp.lo `test -f 'omhttp.c' || echo '$(srcdir)/'`omhttp.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omhttp_la-omhttp.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omhttp_la-omhttp.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/pmcisconames0000644000000000000000000000013215241076624016612 xustar0030 mtime=1787067796.675767561 30 atime=1787067808.786993238 30 ctime=1787067796.675767561 rsyslog-8.2608.0/contrib/pmcisconames/0000775000175000017500000000000015241076624016333 5ustar00rgerrgerrsyslog-8.2608.0/contrib/pmcisconames/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020716 xustar0030 mtime=1752569012.331237145 30 atime=1787067434.383012071 30 ctime=1787067796.670767468 rsyslog-8.2608.0/contrib/pmcisconames/Makefile.am0000666000175000017500000000036615035412264020371 0ustar00rgerrgerpkglib_LTLIBRARIES = pmcisconames.la pmcisconames_la_SOURCES = pmcisconames.c pmcisconames_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmcisconames_la_LDFLAGS = -module -avoid-version pmcisconames_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/pmcisconames/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161020727 xustar0029 mtime=1787067505.29033505 30 atime=1787067579.461718453 30 ctime=1787067796.672767505 rsyslog-8.2608.0/contrib/pmcisconames/Makefile.in0000664000175000017500000006632615241076161020411 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/pmcisconames ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) pmcisconames_la_DEPENDENCIES = am_pmcisconames_la_OBJECTS = pmcisconames_la-pmcisconames.lo pmcisconames_la_OBJECTS = $(am_pmcisconames_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 = pmcisconames_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(pmcisconames_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmcisconames_la_SOURCES) DIST_SOURCES = $(pmcisconames_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = pmcisconames.la pmcisconames_la_SOURCES = pmcisconames.c pmcisconames_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmcisconames_la_LDFLAGS = -module -avoid-version pmcisconames_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/pmcisconames/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/pmcisconames/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } pmcisconames.la: $(pmcisconames_la_OBJECTS) $(pmcisconames_la_DEPENDENCIES) $(EXTRA_pmcisconames_la_DEPENDENCIES) $(AM_V_CCLD)$(pmcisconames_la_LINK) -rpath $(pkglibdir) $(pmcisconames_la_OBJECTS) $(pmcisconames_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmcisconames_la-pmcisconames.lo: pmcisconames.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmcisconames_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmcisconames_la-pmcisconames.lo -MD -MP -MF $(DEPDIR)/pmcisconames_la-pmcisconames.Tpo -c -o pmcisconames_la-pmcisconames.lo `test -f 'pmcisconames.c' || echo '$(srcdir)/'`pmcisconames.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmcisconames_la-pmcisconames.Tpo $(DEPDIR)/pmcisconames_la-pmcisconames.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmcisconames.c' object='pmcisconames_la-pmcisconames.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmcisconames_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmcisconames_la-pmcisconames.lo `test -f 'pmcisconames.c' || echo '$(srcdir)/'`pmcisconames.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmcisconames_la-pmcisconames.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/pmcisconames/PaxHeaders/pmcisconames.c0000644000000000000000000000013115132411300021472 xustar0030 mtime=1768559296.141883663 30 atime=1787067627.500614213 29 ctime=1787067796.67676758 rsyslog-8.2608.0/contrib/pmcisconames/pmcisconames.c0000666000175000017500000001425415132411300021147 0ustar00rgerrger/* pmcisconames.c * * this detects logs sent by Cisco devices that mangle their syslog output when you tell them to log by name * by adding ' :' between the name and the %XXX-X-XXXXXXX: tag * * instead of actually parsing the message, this modifies the message and then falls through to allow a later * parser to handle the now modified message * * created 2010-12-13 by David Lang based on pmlastmsg * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" #include "rsconf.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.cisconames") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* static data */ static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINparse uchar *p2parse; int lenMsg; #define OpeningText ": %" CODESTARTparse; dbgprintf("Message will now be parsed by fix Cisco Names parser.\n"); assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ /* check if this message is of the type we handle in this (very limited) parser */ /* first, we permit SP */ while (lenMsg && *p2parse == ' ') { --lenMsg; ++p2parse; } if ((unsigned)lenMsg < 34) { /* too short, can not be "our" message */ /* minimum message, 16 character timestamp, 1 character name, ' : %ASA-1-000000: '*/ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* check if the timestamp is a 16 character or 21 character timestamp 'Mmm DD HH:MM:SS ' spaces at 3,6,15 : at 9,12 'Mmm DD YYYY HH:MM:SS ' spaces at 3,6,11,20 : at 14,17 check for the : first as that will differentiate the two conditions the fastest this allows the compiler to short circuit the rst of the tests if it is the wrong timestamp but still check the rest to see if it looks correct */ if (*(p2parse + 9) == ':' && *(p2parse + 12) == ':' && *(p2parse + 3) == ' ' && *(p2parse + 6) == ' ' && *(p2parse + 15) == ' ') { /* skip over timestamp */ dbgprintf("short timestamp found\n"); lenMsg -= 16; p2parse += 16; } else { if (*(p2parse + 14) == ':' && *(p2parse + 17) == ':' && *(p2parse + 3) == ' ' && *(p2parse + 6) == ' ' && *(p2parse + 11) == ' ' && *(p2parse + 20) == ' ') { /* skip over timestamp */ dbgprintf("long timestamp found\n"); lenMsg -= 21; p2parse += 21; } else { dbgprintf("timestamp is not one of the valid formats\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } } /* now look for the next space to walk past the hostname */ while (lenMsg && *p2parse != ' ') { --lenMsg; ++p2parse; } /* Note: we deliberately count the 0-byte below because we need to go chars+1! */ if (lenMsg < (int)sizeof(OpeningText)) { dbgprintf("pmcisconames: too short for being cisco messages\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* skip the space after the hostname */ lenMsg -= 1; p2parse += 1; /* if the syslog tag is : and the next thing starts with a % assume that this is a mangled cisco log and fix it */ if (strncasecmp((char *)p2parse, OpeningText, sizeof(OpeningText) - 1) != 0) { /* wrong opening text */ DBGPRINTF("not a cisco name mangled log!\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* bump the message portion up by two characters to overwrite the extra : */ lenMsg -= 2; memmove(p2parse, p2parse + 2, lenMsg); *(p2parse + lenMsg) = '\n'; *(p2parse + lenMsg + 1) = '\0'; pMsg->iLenRawMsg -= 2; pMsg->iLenMSG -= 2; /* now, claim to abort so that something else can parse the now modified message */ DBGPRINTF("pmcisconames: new message: [%d]'%s'\n", lenMsg, p2parse); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); finalize_it: ENDparse BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); DBGPRINTF("cisconames parser init called, compiled with version %s\n", VERSION); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); /* cache value, is set only during rsyslogd option processing */ ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/contrib/PaxHeaders/impcap0000644000000000000000000000013215241076632015401 xustar0030 mtime=1787067802.850882623 30 atime=1787067808.786993238 30 ctime=1787067802.850882623 rsyslog-8.2608.0/contrib/impcap/0000775000175000017500000000000015241076632015122 5ustar00rgerrgerrsyslog-8.2608.0/contrib/impcap/PaxHeaders/tcp_parser.c0000644000000000000000000000013215216464435017770 xustar0030 mtime=1782212893.960265117 30 atime=1787067645.708953688 30 ctime=1787067802.841882455 rsyslog-8.2608.0/contrib/impcap/tcp_parser.c0000664000175000017500000001025515216464435017437 0ustar00rgerrger/* tcp_parser.c * * This file contains functions to parse TCP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" #define SMB_PORT 445 #define HTTP_PORT 80 #define HTTP_PORT_ALT 8080 #define FTP_PORT 21 #define FTP_PORT_DATA 20 struct tcp_header_s { uint16_t srcPort; uint16_t dstPort; uint32_t seq; uint32_t ack; uint8_t dor; uint8_t flags; uint16_t windowSize; uint16_t checksum; uint16_t urgPointer; uint8_t options[]; }; typedef struct tcp_header_s tcp_header_t; static char flagCodes[10] = "FSRPAUECN"; /* * This function parses the bytes in the received packet to extract TCP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the TCP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where TCP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *tcp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("tcp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 20) { DBGPRINTF("TCP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } /* Union to prevent cast from uchar to tcp_header_t */ union { const uchar *pck; tcp_header_t *hdr; } tcp_header_to_char; tcp_header_to_char.pck = packet; tcp_header_t *tcp_header = tcp_header_to_char.hdr; uint8_t i, pos = 0; char flags[10] = {0}; for (i = 0; i < 8; ++i) { if (tcp_header->flags & (0x01 << i)) flags[pos++] = flagCodes[i]; } if (tcp_header->dor & 0x01) flags[pos++] = flagCodes[9]; uint16_t srcPort = ntohs(tcp_header->srcPort); uint16_t dstPort = ntohs(tcp_header->dstPort); uint8_t headerLength = (tcp_header->dor & 0xF0) >> 2; //>>4 to offset but <<2 to get offset as bytes if (headerLength < 20 || headerLength > pktSize) { DBGPRINTF("TCP invalid header length : %u packet size %d\n", headerLength, pktSize); RETURN_DATA_AFTER(0) } json_object_object_add(jparent, "net_src_port", json_object_new_int(srcPort)); json_object_object_add(jparent, "net_dst_port", json_object_new_int(dstPort)); json_object_object_add(jparent, "TCP_seq_number", json_object_new_int64(ntohl(tcp_header->seq))); json_object_object_add(jparent, "TCP_ack_number", json_object_new_int64(ntohl(tcp_header->ack))); json_object_object_add(jparent, "net_flags", json_object_new_string(flags)); if (srcPort == SMB_PORT || dstPort == SMB_PORT) { return smb_parse(packet + headerLength, pktSize - headerLength, jparent); } if (srcPort == FTP_PORT || dstPort == FTP_PORT || srcPort == FTP_PORT_DATA || dstPort == FTP_PORT_DATA) { return ftp_parse(packet + headerLength, pktSize - headerLength, jparent); } if (srcPort == HTTP_PORT || dstPort == HTTP_PORT || srcPort == HTTP_PORT_ALT || dstPort == HTTP_PORT_ALT) { return http_parse(packet + headerLength, pktSize - headerLength, jparent); } DBGPRINTF("tcp return after header length (%u)\n", headerLength); RETURN_DATA_AFTER(headerLength) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/ipv6_parser.c0000644000000000000000000000013215216464435020066 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.723953968 30 ctime=1787067802.829882232 rsyslog-8.2608.0/contrib/impcap/ipv6_parser.c0000664000175000017500000002572315216464435017543 0ustar00rgerrger/* ipv6_parser.c * * This file contains functions to parse IPv6 headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" typedef struct __attribute__((__packed__)) ipv6_header_s { #ifndef IPV6_VERSION_MASK #define IPV6_VERSION_MASK 0xF0000000 #endif #ifndef IPV6_TC_MASK #define IPV6_TC_MASK 0x0FF00000 #endif #ifndef IPV6_FLOW_MASK #define IPV6_FLOW_MASK 0x000FFFFF #endif uint32_t vtf; uint16_t dataLength; uint8_t nextHeader; #define IPV6_NHDR_HBH 0 #define IPV6_NHDR_TCP 6 #define IPV6_NHDR_UDP 17 #define IPV6_NHDR_ENCIP6 41 #define IPV6_NHDR_ROUT 43 #define IPV6_NHDR_FRAG 44 #define IPV6_NHDR_RRSV 46 #define IPV6_NHDR_SEC 50 #define IPV6_NHDR_AUTH 51 #define IPV6_NHDR_ICMP6 58 #define IPV6_NHDR_NONHDR 59 #define IPV6_NHDR_DOPTS 60 #define IPV6_NHDR_INVALID 255 uint8_t hopLimit; uint8_t addrSrc[16]; uint8_t addrDst[16]; } ipv6_header_t; #pragma GCC diagnostic pop #ifndef IPV6_VERSION #define IPV6_VERSION(h) (ntohl(h->vtf) & IPV6_VERSION_MASK) >> 28 #endif #ifndef IPV6_TC #define IPV6_TC(h) (ntohl(h->vtf) & IPV6_TC_MASK) >> 20 #endif #ifndef IPV6_FLOW #define IPV6_FLOW(h) (ntohl(h->vtf) & IPV6_FLOW_MASK) #endif /* extension headers */ typedef struct hbh_header_s { uint8_t nextHeader; uint8_t hLength; uint8_t *pOptions; } hbh_header_t; typedef struct dest_header_s { uint8_t nextHeader; uint8_t hLength; uint8_t *pOptions; } dest_header_t; typedef struct route_header_s { uint8_t nextHeader; uint8_t hLength; uint8_t rType; uint8_t segsLeft; uint32_t reserved; uint8_t addrs[16]; } route_header_t; typedef struct frag_header_s { uint8_t nextHeader; uint8_t reserved; uint16_t offsetFlags; uint32_t id; } frag_header_t; static inline uint8_t hbh_header_parse(const uchar **packet, int *pktSize) { DBGPRINTF("hbh_header_parse\n"); if (*pktSize < 2) { DBGPRINTF("IPv6 HBH header too small : %d\n", *pktSize); *pktSize = 0; return IPV6_NHDR_INVALID; } /* Union to prevent cast from uchar to hbh_header_t */ union { const uchar *pck; hbh_header_t *hdr; } hbh_header_to_char; hbh_header_to_char.pck = *packet; hbh_header_t *hbh_header = hbh_header_to_char.hdr; /* hbh_header->hLength is the number of octets of header in 8-octet units minus 1 * the header length SHOULD be a multiple of 8 */ int hByteLength = hbh_header->hLength * 8 + 8; DBGPRINTF("hByteLength: %d\n", hByteLength); if (*pktSize < hByteLength) { DBGPRINTF("IPv6 HBH header truncated : %d needed %d\n", *pktSize, hByteLength); *pktSize = 0; return IPV6_NHDR_INVALID; } *pktSize -= hByteLength; *packet += hByteLength; return hbh_header->nextHeader; } static inline uint8_t dest_header_parse(const uchar **packet, int *pktSize) { DBGPRINTF("dest_header_parse\n"); if (*pktSize < 2) { DBGPRINTF("IPv6 destination header too small : %d\n", *pktSize); *pktSize = 0; return IPV6_NHDR_INVALID; } /* Union to prevent cast from uchar to dest_header_t */ union { const uchar *pck; dest_header_t *hdr; } dest_header_to_char; dest_header_to_char.pck = *packet; dest_header_t *dest_header = dest_header_to_char.hdr; /* dest_header->hLength is the number of octets of header in 8-octet units minus 1 * the header length SHOULD be a multiple of 8 */ int hByteLength = dest_header->hLength * 8 + 8; DBGPRINTF("hByteLength: %d\n", hByteLength); if (*pktSize < hByteLength) { DBGPRINTF("IPv6 destination header truncated : %d needed %d\n", *pktSize, hByteLength); *pktSize = 0; return IPV6_NHDR_INVALID; } *pktSize -= hByteLength; *packet += hByteLength; return dest_header->nextHeader; } static inline uint8_t route_header_parse(const uchar **packet, int *pktSize, struct json_object *jparent) { DBGPRINTF("route_header_parse\n"); if (*pktSize < 2) { DBGPRINTF("IPv6 route header too small : %d\n", *pktSize); *pktSize = 0; return IPV6_NHDR_INVALID; } /* Union to prevent cast from uchar to route_header_t */ union { const uchar *pck; route_header_t *hdr; } route_header_to_char; route_header_to_char.pck = *packet; route_header_t *route_header = route_header_to_char.hdr; /* route_header->hLength is the number of octets of header in 8-octet units minus 1 * the header length (in bytes) SHOULD be a multiple of 8 */ int hByteLength = route_header->hLength * 8 + 8; if (*pktSize < hByteLength) { DBGPRINTF("IPv6 route header truncated : %d needed %d\n", *pktSize, hByteLength); *pktSize = 0; return IPV6_NHDR_INVALID; } *pktSize -= hByteLength; *packet += hByteLength; if (route_header->rType == 0) { json_object_object_add(jparent, "IP6_route_seg_left", json_object_new_int(route_header->segsLeft)); hByteLength -= 8; // leave only length of routing addresses char addrStr[40], routeFieldName[20]; int addrNum = 1; uint8_t *addr = &(route_header->addrs[0]); // while there is enough space for an IPv6 address while (hByteLength >= 16) { inet_ntop(AF_INET6, (void *)addr, addrStr, 40); snprintf(routeFieldName, 20, "IP6_route_%d", addrNum++); json_object_object_add(jparent, routeFieldName, json_object_new_string((char *)addrStr)); addr += 16; hByteLength -= 16; } } return route_header->nextHeader; } #define FRAG_OFFSET_MASK 0xFFF8 #define MFLAG_MASK 0x0001 static inline uint8_t frag_header_parse(const uchar **packet, int *pktSize, struct json_object *jparent) { DBGPRINTF("frag_header_parse\n"); if (*pktSize < 8) { DBGPRINTF("IPv6 fragment header too small : %d\n", *pktSize); *pktSize = 0; return IPV6_NHDR_INVALID; } /* Union to prevent cast from uchar to frag_header_t */ union { const uchar *pck; frag_header_t *hdr; } frag_header_to_char; frag_header_to_char.pck = *packet; frag_header_t *frag_header = frag_header_to_char.hdr; uint16_t flags = ntohs(frag_header->offsetFlags); json_object_object_add(jparent, "IP6_frag_offset", json_object_new_int((flags & FRAG_OFFSET_MASK) >> 3)); json_object_object_add(jparent, "IP6_frag_more", json_object_new_boolean(flags & MFLAG_MASK)); json_object_object_add(jparent, "IP6_frag_id", json_object_new_int64(frag_header->id)); *pktSize -= 8; *packet += 8; return frag_header->nextHeader; } /* * This function parses the bytes in the received packet to extract IPv6 metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the IPv6 header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where IPv6 metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *ipv6_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("ipv6_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 40) { /* too small for IPv6 header + data (header might be longer)*/ DBGPRINTF("IPv6 packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } ipv6_header_t *ipv6_header = (ipv6_header_t *)packet; char addrSrc[40], addrDst[40]; inet_ntop(AF_INET6, (void *)&ipv6_header->addrSrc, addrSrc, 40); inet_ntop(AF_INET6, (void *)&ipv6_header->addrDst, addrDst, 40); json_object_object_add(jparent, "net_dst_ip", json_object_new_string((char *)addrDst)); json_object_object_add(jparent, "net_src_ip", json_object_new_string((char *)addrSrc)); json_object_object_add(jparent, "net_ttl", json_object_new_int(ipv6_header->hopLimit)); uint8_t nextHeader = ipv6_header->nextHeader; packet += sizeof(ipv6_header_t); pktSize -= sizeof(ipv6_header_t); DBGPRINTF("beginning ext headers scan\n"); uint8_t hasNext = 1; do { switch (nextHeader) { case IPV6_NHDR_HBH: nextHeader = hbh_header_parse(&packet, &pktSize); break; case IPV6_NHDR_TCP: json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader)); return tcp_parse(packet, pktSize, jparent); case IPV6_NHDR_UDP: json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader)); return udp_parse(packet, pktSize, jparent); case IPV6_NHDR_ENCIP6: hasNext = 0; break; case IPV6_NHDR_ROUT: nextHeader = route_header_parse(&packet, &pktSize, jparent); break; case IPV6_NHDR_FRAG: nextHeader = frag_header_parse(&packet, &pktSize, jparent); break; case IPV6_NHDR_RRSV: hasNext = 0; break; case IPV6_NHDR_SEC: hasNext = 0; break; case IPV6_NHDR_AUTH: hasNext = 0; break; case IPV6_NHDR_ICMP6: json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader)); return icmp_parse(packet, pktSize, jparent); case IPV6_NHDR_NONHDR: hasNext = 0; break; case IPV6_NHDR_INVALID: hasNext = 0; break; case IPV6_NHDR_DOPTS: nextHeader = dest_header_parse(&packet, &pktSize); break; default: hasNext = 0; break; } } while (hasNext); if (nextHeader != IPV6_NHDR_INVALID) { json_object_object_add(jparent, "IP_proto", json_object_new_int(nextHeader)); } RETURN_DATA_AFTER(0) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/smb_parser.c0000644000000000000000000000013215216464435017763 xustar0030 mtime=1782212893.960265117 30 atime=1787067645.703953595 30 ctime=1787067802.844882511 rsyslog-8.2608.0/contrib/impcap/smb_parser.c0000664000175000017500000001105115216464435017425 0ustar00rgerrger/* smb_parser.c * * This file contains functions to parse SMB (version 2 and 3) headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" /* SMB2 opCodes */ #define SMB2_NEGOTIATE 0x00 #define SMB2_SESSIONSET 0x01 #define SMB2_SESSIONLOGOFF 0x02 #define SMB2_TREECONNECT 0x03 #define SMB2_TREEDISCONNECT 0x04 #define SMB2_CREATE 0x05 #define SMB2_CLOSE 0x06 #define SMB2_FLUSH 0x07 #define SMB2_READ 0x08 #define SMB2_WRITE 0x09 #define SMB2_LOCK 0x0a #define SMB2_IOCTL 0x0b #define SMB2_CANCEL 0x0c #define SMB2_KEEPALIVE 0x0d #define SMB2_FIND 0x0e #define SMB2_NOTIFY 0x0f #define SMB2_GETINFO 0x10 #define SMB2_SETINFO 0x11 #define SMB2_BREAK 0x12 struct smb_header_s { uint32_t version; uint16_t headerLength; uint16_t padding1; uint32_t ntStatus; uint16_t opCode; uint16_t padding2; uint32_t flags; uint32_t chainOffset; uint32_t comSeqNumber[2]; uint32_t processID; uint32_t treeID; uint32_t userID[2]; uint32_t signature[4]; }; typedef struct smb_header_s smb_header_t; static char flagCodes[5] = "RPCS"; /* * This function parses the bytes in the received packet to extract SMB2 metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the beginning of the header will be checked by the function * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where SMB2 metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("smb_parse\n"); DBGPRINTF("packet size %d\n", pktSize); int pktSizeCpy = pktSize; const uchar *packetCpy = packet; while (pktSizeCpy >= 4) { /* don't check packetCpy[0] to include SMB version byte at the beginning */ if (packetCpy[1] == 'S') { if (packetCpy[2] == 'M') { if (packetCpy[3] == 'B') { break; } } } packetCpy++, pktSizeCpy--; } if ((int)pktSizeCpy < 64) { DBGPRINTF("SMB packet too small : %d\n", pktSizeCpy); RETURN_DATA_AFTER(0) } /* Union to prevent cast from uchar to smb_header_t */ union { const uchar *pck; smb_header_t *hdr; } smb_header_to_char; smb_header_to_char.pck = packetCpy; smb_header_t *smb_header = smb_header_to_char.hdr; char flags[5] = {0}; uint64_t seqNum, userID; uint8_t version; version = (smb_header->version == 0xFF) ? 1 : 2; seqNum = smb_header->comSeqNumber[0] | smb_header->comSeqNumber[1] << 16; userID = smb_header->userID[0] | smb_header->userID[1] << 16; uint8_t i, pos = 0; for (i = 0; i < 4; ++i) { if (smb_header->flags & (0x01 << i)) flags[pos++] = flagCodes[i]; } json_object_object_add(jparent, "SMB_version", json_object_new_int(version)); json_object_object_add(jparent, "SMB_NTstatus", json_object_new_int64(smb_header->ntStatus)); json_object_object_add(jparent, "SMB_operation", json_object_new_int(smb_header->opCode)); json_object_object_add(jparent, "SMB_flags", json_object_new_string(flags)); json_object_object_add(jparent, "SMB_seqNumber", json_object_new_int64(seqNum)); json_object_object_add(jparent, "SMB_processID", json_object_new_int64(smb_header->processID)); json_object_object_add(jparent, "SMB_treeID", json_object_new_int64(smb_header->treeID)); json_object_object_add(jparent, "SMB_userID", json_object_new_int64(userID)); RETURN_DATA_AFTER(0) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/ftp_parser.c0000644000000000000000000000013215216464435017773 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.709953706 30 ctime=1787067802.846882549 rsyslog-8.2608.0/contrib/impcap/ftp_parser.c0000664000175000017500000001105515216464435017441 0ustar00rgerrger/* ftp_parser.c * * This file contains functions to parse FTP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" static const int ftp_cds[] = {100, 110, 120, 125, 150, 200, 202, 211, 212, 213, 214, 215, 220, 221, 225, 226, 227, 228, 229, 230, 231, 232, 250, 257, 300, 331, 332, 350, 400, 421, 425, 426, 430, 434, 450, 451, 452, 500, 501, 502, 503, 504, 530, 532, 550, 551, 552, 553, 600, 631, 632, 633, 10000, 100054, 10060, 10061, 10066, 10068, 0}; static const char *ftp_cmds[] = {"STOR", "TYPE", "ABOR", "ACCT", "ALLO", "APPE", "CDUP", "CWD", "DELE", "HELP", "LIST", "MKD", "MODE", "NLST", "NOOP", "PASS", "PASV", "PORT", "PWD", "QUIT", "REIN", "REST", "RETR", "RMD", "RNFR", "RNTO", "SITE", "SMNT", "STAT", "STOU", "STRU", "SYST", "USER", NULL}; /* * This function searches for a valid command in the header (from the list defined in ftp_cmds[]) * and returns either the command or a NULL pointer */ static const char *check_Command_ftp(uchar *first_part_packet) { DBGPRINTF("in check_Command_ftp\n"); DBGPRINTF("first_part_packet : '%s' \n", first_part_packet); int i = 0; for (i = 0; ftp_cmds[i] != NULL; i++) { if (strncmp((const char *)first_part_packet, ftp_cmds[i], strlen((const char *)ftp_cmds[i]) + 1) == 0) { return ftp_cmds[i]; } } return "UNKNOWN"; } /* * This function searches for a valid code in the header (from the list defined in ftp_cds[]) * and returns either the command or a NULL pointer */ static int check_Code_ftp(uchar *first_part_packet) { DBGPRINTF("in check_Code_ftp\n"); DBGPRINTF("first_part_packet : %s \n", first_part_packet); int i = 0; for (i = 0; ftp_cds[i] != 0; i++) { if (strtol((const char *)first_part_packet, NULL, 10) == ftp_cds[i]) { return ftp_cds[i]; } } return 0; } /* * This function parses the bytes in the received packet to extract FTP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the FTP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where FTP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *ftp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("ftp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 5) { /* too short for ftp packet*/ RETURN_DATA_AFTER(0) } uchar *packet2 = (uchar *)malloc((size_t)pktSize + 1); if (packet2 == NULL) { RETURN_DATA_AFTER(0) } memcpy(packet2, packet, pktSize); // strtok changes original packet packet2[pktSize] = '\0'; char *saveptr = NULL; uchar *frst_part_ftp; frst_part_ftp = (uchar *)strtok_r((char *)packet2, " ", &saveptr); // Get first part of packet ftp strtok_r(NULL, "\r\n", &saveptr); if (frst_part_ftp) { int code = check_Code_ftp(frst_part_ftp); const char *command = check_Command_ftp(frst_part_ftp); if (code != 0) { json_object_object_add(jparent, "FTP_response", json_object_new_int(code)); } else if (command != NULL) { json_object_object_add(jparent, "FTP_request", json_object_new_string(command)); } } free(packet2); RETURN_DATA_AFTER(0) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/http_parser.c0000644000000000000000000000013215216464435020161 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.739954266 30 ctime=1787067802.848882586 rsyslog-8.2608.0/contrib/impcap/http_parser.c0000664000175000017500000001142515216464435017630 0ustar00rgerrger/* http_parser.c * * This file contains functions to parse HTTP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" static const char *keywords[] = {"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT", "HTTP", NULL}; static inline char *string_split(char **initString, const char *delimiterString) { char *ret = *initString; if (*initString) { char *pos = strstr(*initString, delimiterString); if (pos) { *initString = pos; **initString = '\0'; *initString += strlen(delimiterString); } else { *initString = NULL; } } return ret; } static inline int has_status_keyword(char *http) { const char *found; int i; for (i = 0; keywords[i] != NULL; i++) { found = strstr(http, keywords[i]); if (found && (found - http) < 20) { return 1; } } return 0; } /* * This function catches HTTP header fields and status line * and adds them to the provided json object */ static inline void catch_status_and_fields(char *header, struct json_object *jparent) { DBGPRINTF("catch_status_and_fields\n"); struct json_object *fields = json_object_new_object(); char *statusLine = string_split(&header, "\r\n"); char *firstPart, *secondPart, *thirdPart; firstPart = string_split(&statusLine, " "); secondPart = string_split(&statusLine, " "); thirdPart = statusLine; if (firstPart && secondPart && thirdPart) { if (strstr(firstPart, "HTTP")) { json_object_object_add(jparent, "HTTP_version", json_object_new_string(firstPart)); json_object_object_add(jparent, "HTTP_status_code", json_object_new_string(secondPart)); json_object_object_add(jparent, "HTTP_reason", json_object_new_string(thirdPart)); } else { json_object_object_add(jparent, "HTTP_method", json_object_new_string(firstPart)); json_object_object_add(jparent, "HTTP_request_URI", json_object_new_string(secondPart)); json_object_object_add(jparent, "HTTP_version", json_object_new_string(thirdPart)); } } char *fieldValue = string_split(&header, "\r\n"); char *field, *value; while (fieldValue) { field = string_split(&fieldValue, ":"); value = fieldValue; if (value) { while (*value == ' ') { value++; } DBGPRINTF("got header field -> '%s': '%s'\n", field, value); json_object_object_add(fields, field, json_object_new_string(value)); } fieldValue = string_split(&header, "\r\n"); } json_object_object_add(jparent, "HTTP_header_fields", fields); return; } /* * This function parses the bytes in the received packet to extract HTTP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the beginning of the header will be checked by the function * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where HTTP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *http_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("http_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 6) { RETURN_DATA_AFTER(0) } char *pHttp = malloc((size_t)pktSize + 1); if (pHttp == NULL) { RETURN_DATA_AFTER(0) } char *http = pHttp; memcpy(http, packet, pktSize); *(http + pktSize) = '\0'; if (!has_status_keyword(http)) { free(pHttp); RETURN_DATA_AFTER(0) } char *header = string_split(&http, "\r\n\r\n"); catch_status_and_fields(header, jparent); free(pHttp); RETURN_DATA_AFTER(0) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/Makefile.am0000644000000000000000000000013215131231047017501 xustar0030 mtime=1768239655.583210602 30 atime=1787067434.068006192 30 ctime=1787067802.813881933 rsyslog-8.2608.0/contrib/impcap/Makefile.am0000666000175000017500000000123615131231047017151 0ustar00rgerrgerpkglib_LTLIBRARIES = impcap.la impcap_la_SOURCES = impcap.c impcap_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) impcap_la_LDFLAGS = -module -avoid-version impcap_la_LIBADD = -lpcap impcap_la_SOURCES += arp_parser.c impcap_la_SOURCES += eth_parser.c impcap_la_SOURCES += icmp_parser.c impcap_la_SOURCES += ipv4_parser.c impcap_la_SOURCES += ipv6_parser.c impcap_la_SOURCES += ipx_parser.c impcap_la_SOURCES += llc_parser.c impcap_la_SOURCES += udp_parser.c impcap_la_SOURCES += dns_parser.c impcap_la_SOURCES += tcp_parser.c impcap_la_SOURCES += smb_parser.c impcap_la_SOURCES += ftp_parser.c impcap_la_SOURCES += http_parser.c EXTRA_DIST=parsers.h rsyslog-8.2608.0/contrib/impcap/PaxHeaders/ipx_parser.c0000644000000000000000000000013015132411300017754 xustar0028 mtime=1768559296.1378836 30 atime=1787067645.722953949 30 ctime=1787067802.832882287 rsyslog-8.2608.0/contrib/impcap/ipx_parser.c0000666000175000017500000000731015132411300017425 0ustar00rgerrger/* ipx_parser.c * * This file contains functions to parse IPX (Novell) headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" struct __attribute__((__packed__)) ipx_header_s { uint16_t chksum; uint16_t pktLen; uint8_t transCtrl; uint8_t type; uint32_t dstNet; uint8_t dstNode[6]; uint16_t dstSocket; uint32_t srcNet; uint8_t srcNode[6]; uint16_t srcSocket; }; #pragma GCC diagnostic pop typedef struct ipx_header_s ipx_header_t; /* * This function parses the bytes in the received packet to extract IPX metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the IPX header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where IPX metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *ipx_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("entered ipx_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 30) { /* too short for IPX header */ DBGPRINTF("IPX packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } char ipxSrcNode[20], ipxDstNode[20]; ipx_header_t *ipx_header = (ipx_header_t *)packet; snprintf(ipxDstNode, sizeof(ipxDstNode), "%02x:%02x:%02x:%02x:%02x:%02x", ipx_header->dstNode[0], ipx_header->dstNode[1], ipx_header->dstNode[2], ipx_header->dstNode[3], ipx_header->dstNode[4], ipx_header->dstNode[5]); snprintf(ipxSrcNode, sizeof(ipxSrcNode), "%02x:%02x:%02x:%02x:%02x:%02x", ipx_header->srcNode[0], ipx_header->srcNode[1], ipx_header->srcNode[2], ipx_header->srcNode[3], ipx_header->srcNode[4], ipx_header->srcNode[5]); json_object_object_add(jparent, "IPX_transCtrl", json_object_new_int(ipx_header->transCtrl)); json_object_object_add(jparent, "IPX_type", json_object_new_int(ipx_header->type)); json_object_object_add(jparent, "IPX_dest_net", json_object_new_int(ntohl(ipx_header->dstNet))); json_object_object_add(jparent, "IPX_src_net", json_object_new_int(ntohl(ipx_header->srcNet))); json_object_object_add(jparent, "IPX_dest_node", json_object_new_string(ipxDstNode)); json_object_object_add(jparent, "IPX_src_node", json_object_new_string(ipxSrcNode)); json_object_object_add(jparent, "IPX_dest_socket", json_object_new_int(ntohs(ipx_header->dstSocket))); json_object_object_add(jparent, "IPX_src_socket", json_object_new_int(ntohs(ipx_header->srcSocket))); RETURN_DATA_AFTER(30) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/dns_parser.c0000644000000000000000000000013215216464435017766 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.746954396 30 ctime=1787067802.839882418 rsyslog-8.2608.0/contrib/impcap/dns_parser.c0000664000175000017500000003502415216464435017436 0ustar00rgerrger/* dns_parser.c * * This file contains functions to parse DNS headers. * * File begun on 2018-11-13 * * Created by: * - Kevin Guillemot (kevin.guillemot@advens.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" /* List of RCodes defined in RFC6895 : https://tools.ietf.org/html/rfc6895 */ static const char *dns_rcodes[] = {"NoError", // 0 "FormErr", // 1 "ServFail", // 2 "NXDomain", // 3 "NotImp", // 4 "Refused", // 5 "YXDomain", // 6 "YXRRSet", // 7 "NXRRSet", // 8 "NotAuth", // 9 "NotZone", // 10 "", // 11 - Reserved "", // 12 - Reserved "", // 13 - Reserved "", // 14 - Reserved "", // 15 - Reserved "BADVERS|BADSIG", // 16 "BADKEY", // 17 "BADTIME", // 18 "BADMODE", // 19 "BADNAME", // 20 "BADALG", // 21 "BADTRUNC", // 22 /* Reserved for private use */ NULL}; /* List of record types (maybe not complete) */ static const char *dns_types[] = {0, "A", // 1 "NS", // 2 "MD", // 3 "MF", // 4 "CNAME", // 5 "SOA", // 6 "MB", // 7 "MG", // 8 "MR", // 9 "NULL", // 10 "WKS", // 11 "PTR", // 12 "HINFO", // 13 "MINFO", // 14 "MX", // 15 "TXT", // 16 "RP", // 17 "AFSDB", // 18 "X25", // 19 "ISDN", // 20 "RT", // 21 "NSAP", // 22 "NSAP-PTR", // 23 "SIG", // 24 "KEY", // 25 "PX", // 26 "GPOS", // 27 "AAAA", // 28 "LOC", // 29 "NXT", // 30 "EID", // 31 "NIMLOC", // 32 "SRV", // 33 "ATMA", // 34 "NAPTR", // 35 "KX", // 36 "CERT", // 37 "A6", // 38 "DNAME", // 39 "SINK", // 40 "OPT", // 41 "APL", // 42 "DS", // 43 "SSHFP", // 44 "IPSECKEY", // 45 "RRSIG", // 46 "NSEC", // 47 "DNSKEY", // 48 "DHCID", // 49 "NSEC3", // 50 "NSEC3PARAM", // 51 "TLSA", // 51 "SMIMEA", // 52 "Unassigned", // 53 "HIP", // 53 "NINFO", // 54 "RKEY", // 55 "TALINK", // 56 "CDS", // 57 "CDNSKEY", // 58 "OPENPGPKEY", // 59 "CSYNC", // 60 "ZONEMD", // 61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "SPF", // 99 "UINFO", // 100 "UID", // 101 "GID", // 102 "UNSPEC", // 103 "NID", // 104 "L32", // 105 "L64", // 106 "LP", // 107 "EUI48", // 108 "EUI64", // 109 /* Reserved for private use */ NULL}; /* Part 2, since 249. To prevent useless large buffer in memory */ static const char *dns_types2[] = {"TKEY", "TSIG", "IXFR", "AXFR", "MAILB", "MAILA", "*", "URI", "CAA", "AVC", "DOA", "AMTRELAY", NULL}; /* Part 3, since 32768. To prevent useless large buffer in memory */ static const char *dns_types3[] = {"TA", "DLV", NULL}; /* This function takes an integer as parameter * and returns the corresponding string type of DNS query */ static const char *get_type(uint16_t x) { const char **types = NULL; uint16_t len_types3 = (sizeof(dns_types3) / sizeof(char *)) - 1; uint16_t len_types2 = (sizeof(dns_types2) / sizeof(char *)) - 1; uint16_t len_types = (sizeof(dns_types) / sizeof(char *)) - 1; if (x >= 32768 && x < 32768 + len_types3) { types = dns_types3; x -= 32768; } else if (x >= 249 && x < 249 + len_types2) { types = dns_types2; x -= 249; } else if (x > 0 && x < len_types) types = dns_types; else return "UNKNOWN"; if (types[x] != NULL) return types[x]; return "UNKNOWN"; } /* This function takes an integer as parameter * and returns the corresponding string class of DNS query */ static const char *get_class(uint16_t x) { switch (x) { case 1: return "IN"; case 3: return "CH"; case 4: return "HS"; case 254: return "QCLASS NONE"; case 255: return "QCLASS *"; default: // No action needed for other cases break; } return "UNKNOWN"; } /* * This function parses the bytes in the received packet to extract DNS metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where DNS metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *dns_parse(const uchar *packet, int pktSize, struct json_object *jparent) { const uchar *packet_ptr = packet; DBGPRINTF("dns_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 12) { DBGPRINTF("DNS packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } const uchar *end_packet = packet + pktSize; /* Union to prevent cast from uchar to smb_header_t */ union { unsigned short int *two_bytes; const uchar *pckt; } union_short_int; /* Get transaction id */ union_short_int.pckt = packet_ptr; unsigned short int transaction_id = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("transaction_id = %02x \n", transaction_id); union_short_int.pckt += 2; /* Get flags */ unsigned short int flags = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("flags = %02x \n", flags); /* Get response flag */ unsigned short int response_flag = (flags >> 15) & 0b1; // Get the left bit // DBGPRINTF("response_flag = %02x \n", response_flag); /* Get Opcode */ unsigned short int opcode = (flags >> 11) & 0b1111; // DBGPRINTF("opcode = %02x \n", opcode); /* Verify Z: reserved bit */ unsigned short int reserved = (flags >> 6) & 0b1; // DBGPRINTF("reserved = %02x \n", reserved); /* Reserved bit MUST be 0 */ if (reserved != 0) { DBGPRINTF("DNS packet reserved bit (Z) is not 0, aborting message. \n"); RETURN_DATA_AFTER(0) } /* Get reply code : 4 last bits */ unsigned short int reply_code = flags & 0b1111; // DBGPRINTF("reply_code = %02x \n", reply_code); union_short_int.pckt += 2; /* Get QDCOUNT */ unsigned short int query_count = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("query_count = %02x \n", query_count); union_short_int.pckt += 2; /* Get ANCOUNT */ unsigned short int answer_count = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("answer_count = %02x \n", answer_count); union_short_int.pckt += 2; /* Get NSCOUNT */ unsigned short int authority_count = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("authority_count = %02x \n", authority_count); union_short_int.pckt += 2; /* Get ARCOUNT */ unsigned short int additionnal_count = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("additionnal_count = %02x \n", additionnal_count); union_short_int.pckt += 2; packet_ptr = union_short_int.pckt; fjson_object *queries = NULL; if ((queries = json_object_new_array()) == NULL) { DBGPRINTF("impcap::dns_parser: Cannot create new json array. Stopping.\n"); RETURN_DATA_AFTER(0) } // For each query of query_count int query_cpt = 0; while (query_cpt < query_count && packet_ptr < end_packet) { size_t query_size = strnlen((const char *)packet_ptr, (size_t)(end_packet - packet_ptr)); // Check if query is valid (max 255 bytes, plus a '\0') if (query_size >= 256) { DBGPRINTF("impcap::dns_parser: Length of domain queried is > 255. Stopping.\n"); break; } // Check if remaining data is enough to hold query + '\0' + 4 bytes (QTYPE and QCLASS fields) if (query_size + 5 > (size_t)(end_packet - packet_ptr)) { DBGPRINTF("impcap::dns_parser: packet size too small to parse query. Stopping.\n"); break; } fjson_object *query = NULL; if ((query = json_object_new_object()) == NULL) { DBGPRINTF("impcap::dns_parser: Cannot create new json object. Stopping.\n"); break; } char domain_query[256] = {0}; uchar nb_char = *packet_ptr; packet_ptr++; size_t cpt = 0; while (cpt + 1 < query_size) { if (nb_char == 0) { nb_char = *packet_ptr; domain_query[cpt] = '.'; } else { domain_query[cpt] = (char)*packet_ptr; nb_char--; } cpt++; packet_ptr++; } domain_query[cpt] = '\0'; if (cpt) packet_ptr++; // pass the last \0, only if query was not empty // DBGPRINTF("Requested domain : '%s' \n", domain_query); /* Register the name in dict */ json_object_object_add(query, "qname", json_object_new_string(domain_query)); /* Get QTYPE */ union_short_int.pckt = packet_ptr; unsigned short int qtype = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("qtype = %02x \n", qtype); json_object_object_add(query, "qtype", json_object_new_int((int)qtype)); json_object_object_add(query, "type", json_object_new_string(get_type(qtype))); union_short_int.pckt += 2; /* Retrieve QCLASS */ unsigned short int qclass = ntohs(*(union_short_int.two_bytes)); // DBGPRINTF("qclass = %02x \n", qclass); json_object_object_add(query, "qclass", json_object_new_int((int)qclass)); json_object_object_add(query, "class", json_object_new_string(get_class(qclass))); packet_ptr = union_short_int.pckt + 2; /* Register the query in json array */ json_object_array_add(queries, query); query_cpt++; } json_object_object_add(jparent, "DNS_transaction_id", json_object_new_int((int)transaction_id)); json_bool is_reponse = FALSE; if (response_flag) is_reponse = TRUE; json_object_object_add(jparent, "DNS_response_flag", json_object_new_boolean(is_reponse)); json_object_object_add(jparent, "DNS_opcode", json_object_new_int(opcode)); json_object_object_add(jparent, "DNS_rcode", json_object_new_int((int)reply_code)); json_object_object_add(jparent, "DNS_error", json_object_new_string(dns_rcodes[reply_code])); json_object_object_add(jparent, "DNS_QDCOUNT", json_object_new_int((int)query_count)); json_object_object_add(jparent, "DNS_ANCOUNT", json_object_new_int((int)answer_count)); json_object_object_add(jparent, "DNS_NSCOUNT", json_object_new_int((int)authority_count)); json_object_object_add(jparent, "DNS_ARCOUNT", json_object_new_int((int)additionnal_count)); json_object_object_add(jparent, "DNS_Names", queries); /* Packet has been successfully parsed, there still can be some responses left, but do not process them */ RETURN_DATA_AFTER(0); } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/arp_parser.c0000644000000000000000000000013215241075234017755 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.715580354 30 ctime=1787067802.820882063 rsyslog-8.2608.0/contrib/impcap/arp_parser.c0000664000175000017500000001661015241075234017425 0ustar00rgerrger/* arp_parser.c * * This file contains functions to parse ARP and RARP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" struct arp_header_s { uint16_t hwType; uint16_t pType; uint8_t hwAddrLen; uint8_t pAddrLen; uint16_t opCode; uint8_t pAddr[]; }; typedef struct arp_header_s arp_header_t; static int arp_addr_lengths_available(const arp_header_t *arp_header, int pktSize) { const size_t hdrLen = sizeof(*arp_header); const size_t hwAddrLen = arp_header->hwAddrLen; const size_t pAddrLen = arp_header->pAddrLen; const size_t addrLen = 2 * (hwAddrLen + pAddrLen); if (!(pktSize >= 0 && (size_t)pktSize >= hdrLen && addrLen <= (size_t)pktSize - hdrLen)) { return 0; } if (ntohs(arp_header->hwType) == 1 && hwAddrLen < 6) { return 0; } if (ntohs(arp_header->pType) == ETHERTYPE_IP && pAddrLen < 4) { return 0; } return 1; } /* * This function parses the bytes in the received packet to extract ARP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the ARP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where ARP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *arp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("arp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 28) { /* too small for ARP header*/ DBGPRINTF("ARP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0); } /* Union to prevent cast from uchar to arp_header_t */ union { const uchar *pck; arp_header_t *hdr; } arp_header_to_char; arp_header_to_char.pck = packet; arp_header_t *arp_header = arp_header_to_char.hdr; char pAddrSrc[20], pAddrDst[20]; json_object_object_add(jparent, "ARP_hwType", json_object_new_int(ntohs(arp_header->hwType))); json_object_object_add(jparent, "ARP_pType", json_object_new_int(ntohs(arp_header->pType))); json_object_object_add(jparent, "ARP_op", json_object_new_int(ntohs(arp_header->opCode))); if (!arp_addr_lengths_available(arp_header, pktSize)) { DBGPRINTF("ARP packet address lengths exceed captured packet size: hwAddrLen=%u pAddrLen=%u pktSize=%d\n", arp_header->hwAddrLen, arp_header->pAddrLen, pktSize); RETURN_DATA_AFTER(28); } if (ntohs(arp_header->hwType) == 1) { /* ethernet addresses */ char hwAddrSrc[20], hwAddrDst[20]; ether_ntoa_r((struct ether_addr *)arp_header->pAddr, hwAddrSrc); ether_ntoa_r((struct ether_addr *)(arp_header->pAddr + arp_header->hwAddrLen + arp_header->pAddrLen), hwAddrDst); json_object_object_add(jparent, "ARP_hwSrc", json_object_new_string((char *)hwAddrSrc)); json_object_object_add(jparent, "ARP_hwDst", json_object_new_string((char *)hwAddrDst)); } if (ntohs(arp_header->pType) == ETHERTYPE_IP) { inet_ntop(AF_INET, (void *)(arp_header->pAddr + arp_header->hwAddrLen), pAddrSrc, 20); inet_ntop(AF_INET, (void *)(arp_header->pAddr + 2 * arp_header->hwAddrLen + arp_header->pAddrLen), pAddrDst, 20); json_object_object_add(jparent, "ARP_pSrc", json_object_new_string((char *)pAddrSrc)); json_object_object_add(jparent, "ARP_pDst", json_object_new_string((char *)pAddrDst)); } RETURN_DATA_AFTER(28); } /* * This function parses the bytes in the received packet to extract RARP metadata. * This is a copy of ARP handler, as structure is the same but protocol code and name are different * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the RARP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where RARP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *rarp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("rarp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 28) { /* too small for RARP header*/ DBGPRINTF("RARP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0); } /* Union to prevent cast from uchar to arp_header_t */ union { const uchar *pck; arp_header_t *hdr; } arp_header_to_char; arp_header_to_char.pck = packet; arp_header_t *rarp_header = arp_header_to_char.hdr; char pAddrSrc[20], pAddrDst[20]; json_object_object_add(jparent, "RARP_hwType", json_object_new_int(ntohs(rarp_header->hwType))); json_object_object_add(jparent, "RARP_pType", json_object_new_int(ntohs(rarp_header->pType))); json_object_object_add(jparent, "RARP_op", json_object_new_int(ntohs(rarp_header->opCode))); if (!arp_addr_lengths_available(rarp_header, pktSize)) { DBGPRINTF("RARP packet address lengths exceed captured packet size: hwAddrLen=%u pAddrLen=%u pktSize=%d\n", rarp_header->hwAddrLen, rarp_header->pAddrLen, pktSize); RETURN_DATA_AFTER(28); } if (ntohs(rarp_header->hwType) == 1) { /* ethernet addresses */ char hwAddrSrc[20], hwAddrDst[20]; ether_ntoa_r((struct ether_addr *)rarp_header->pAddr, hwAddrSrc); ether_ntoa_r((struct ether_addr *)(rarp_header->pAddr + rarp_header->hwAddrLen + rarp_header->pAddrLen), hwAddrDst); json_object_object_add(jparent, "RARP_hwSrc", json_object_new_string((char *)hwAddrSrc)); json_object_object_add(jparent, "RARP_hwDst", json_object_new_string((char *)hwAddrDst)); } if (ntohs(rarp_header->pType) == ETHERTYPE_IP) { inet_ntop(AF_INET, (void *)(rarp_header->pAddr + rarp_header->hwAddrLen), pAddrSrc, 20); inet_ntop(AF_INET, (void *)(rarp_header->pAddr + 2 * rarp_header->hwAddrLen + rarp_header->pAddrLen), pAddrDst, 20); json_object_object_add(jparent, "RARP_pSrc", json_object_new_string((char *)pAddrSrc)); json_object_object_add(jparent, "RARP_pDst", json_object_new_string((char *)pAddrDst)); } RETURN_DATA_AFTER(28); } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/llc_parser.c0000644000000000000000000000013215216464435017754 xustar0030 mtime=1782212893.960265117 30 atime=1787067645.727954042 30 ctime=1787067802.834882325 rsyslog-8.2608.0/contrib/impcap/llc_parser.c0000664000175000017500000001007115216464435017417 0ustar00rgerrger/* llc_parser.c * * This file contains functions to parse llc headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" /* * This function parses the bytes in the received packet to extract LLC metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the LLC header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where LLC metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *llc_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("entered llc_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 3) { /* too short for llc header */ DBGPRINTF("LLC packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } uint8_t dsapField, dsap, ssapField, ssap; uint16_t ctrl; uint8_t headerLen; dsapField = (uint8_t)packet[0]; ssapField = (uint8_t)packet[1]; DBGPRINTF("dsapField : %02X\n", dsapField); DBGPRINTF("ssapField : %02X\n", ssapField); if (dsapField == 0xff && ssapField == 0xff) { /* this is an IPX packet, without LLC */ return ipx_parse(packet, pktSize, jparent); } if ((packet[2] & 0x03) == 3) { /* U frame: LLC control is 8 bits */ ctrl = (uint8_t)packet[2]; headerLen = 3; } else { /* I and S data frames: LLC control is 16 bits */ if (pktSize < 4) { DBGPRINTF("LLC packet too small for 16-bit control : %d\n", pktSize); RETURN_DATA_AFTER(0) } ctrl = ntohs((uint16_t)packet[2]); headerLen = 4; } /* don't take last bit into account */ dsap = dsapField & 0xfe; ssap = ssapField & 0xfe; json_object_object_add(jparent, "LLC_dsap", json_object_new_int(dsap)); json_object_object_add(jparent, "LLC_ssap", json_object_new_int(ssap)); json_object_object_add(jparent, "LLC_ctrl", json_object_new_int(ctrl)); if (dsap == 0xaa && ssap == 0xaa && ctrl == 0x03) { /* SNAP header */ if (pktSize < headerLen + 5) { DBGPRINTF("LLC SNAP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(headerLen) } uint32_t orgCode = packet[headerLen] << 16 | packet[headerLen + 1] << 8 | packet[headerLen + 2]; uint16_t ethType = packet[headerLen + 3] << 8 | packet[headerLen + 4]; json_object_object_add(jparent, "SNAP_oui", json_object_new_int(orgCode)); json_object_object_add(jparent, "SNAP_ethType", json_object_new_int(ethType)); return eth_proto_parse(ethType, packet + headerLen, pktSize - headerLen, jparent); } if (dsap == 0x06 && ssap == 0x06 && ctrl == 0x03) { /* IPv4 header */ return ipv4_parse(packet + headerLen, pktSize - headerLen, jparent); } if (dsap == 0xe0 && ssap == 0xe0 && ctrl == 0x03) { /* IPX packet with LLC */ return ipx_parse(packet + headerLen, pktSize - headerLen, jparent); } RETURN_DATA_AFTER(headerLen) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/udp_parser.c0000644000000000000000000000013015132411300017744 xustar0028 mtime=1768559296.1378836 30 atime=1787067645.709953706 30 ctime=1787067802.836882362 rsyslog-8.2608.0/contrib/impcap/udp_parser.c0000666000175000017500000000571115132411300017420 0ustar00rgerrger/* udp_parser.c * * This file contains functions to parse UDP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" #define DNS_PORT 53 struct udp_header_s { uint16_t srcPort; uint16_t dstPort; uint16_t totalLength; uint16_t checksum; }; typedef struct udp_header_s udp_header_t; /* * This function parses the bytes in the received packet to extract UDP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the UDP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where UDP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *udp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("udp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 8) { DBGPRINTF("UDP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } /* Union to prevent cast from uchar to udp_header_t */ union { const uchar *pck; udp_header_t *hdr; } udp_header_to_char; udp_header_to_char.pck = packet; udp_header_t *udp_header = udp_header_to_char.hdr; // Prevent endianness issue unsigned short int src_port = ntohs(udp_header->srcPort); unsigned short int dst_port = ntohs(udp_header->dstPort); json_object_object_add(jparent, "net_src_port", json_object_new_int(src_port)); json_object_object_add(jparent, "net_dst_port", json_object_new_int(dst_port)); json_object_object_add(jparent, "UDP_Length", json_object_new_int(ntohs(udp_header->totalLength))); json_object_object_add(jparent, "UDP_Checksum", json_object_new_int(ntohs(udp_header->checksum))); if (src_port == DNS_PORT || dst_port == DNS_PORT) { return dns_parse(packet + sizeof(udp_header_t), pktSize - sizeof(udp_header_t), jparent); } RETURN_DATA_AFTER(8) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/ipv4_parser.c0000644000000000000000000000013215216464435020064 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.700953539 30 ctime=1787067802.827882194 rsyslog-8.2608.0/contrib/impcap/ipv4_parser.c0000664000175000017500000000703615216464435017536 0ustar00rgerrger/* ipv4_parser.c * * This file contains functions to parse IP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" struct ipv4_header_s { /*#if __BYTE_ORDER == __BIG_ENDIAN unsigned char version:4; unsigned char ihl:4; #else*/ unsigned char ihl : 4; unsigned char version : 4; // #endif uint8_t service; uint16_t totLen; uint16_t id; uint16_t frag; uint8_t ttl; uint8_t proto; uint16_t hdrChksum; uint8_t addrSrc[4]; uint8_t addrDst[4]; uint8_t pOptions[]; }; typedef struct ipv4_header_s ipv4_header_t; /* * This function parses the bytes in the received packet to extract IP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the IP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where IP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *ipv4_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("ipv4_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 20) { /* too small for IPv4 header + data (header might be longer)*/ DBGPRINTF("IPv4 packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } /* Union to prevent cast from uchar to ipv4_header_t */ union { const uchar *pck; ipv4_header_t *hdr; } ipv4_header_to_char; ipv4_header_to_char.pck = packet; ipv4_header_t *ipv4_header = ipv4_header_to_char.hdr; char addrSrc[20], addrDst[20]; uint8_t hdrLen = 4 * ipv4_header->ihl; /* 4 x length in words */ if (ipv4_header->ihl < 5 || hdrLen > pktSize) { DBGPRINTF("IPv4 invalid header length : %u packet size %d\n", hdrLen, pktSize); RETURN_DATA_AFTER(0) } inet_ntop(AF_INET, (void *)&ipv4_header->addrSrc, addrSrc, 20); inet_ntop(AF_INET, (void *)&ipv4_header->addrDst, addrDst, 20); json_object_object_add(jparent, "net_dst_ip", json_object_new_string((char *)addrDst)); json_object_object_add(jparent, "net_src_ip", json_object_new_string((char *)addrSrc)); json_object_object_add(jparent, "IP_ihl", json_object_new_int(ipv4_header->ihl)); json_object_object_add(jparent, "net_ttl", json_object_new_int(ipv4_header->ttl)); json_object_object_add(jparent, "IP_proto", json_object_new_int(ipv4_header->proto)); return ip_proto_parse(ipv4_header->proto, (packet + hdrLen), (pktSize - hdrLen), jparent); } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/parsers.h0000644000000000000000000000013115216464435017311 xustar0030 mtime=1782212893.960265117 29 atime=1787067645.69995352 30 ctime=1787067802.850882623 rsyslog-8.2608.0/contrib/impcap/parsers.h0000664000175000017500000001427015216464435016762 0ustar00rgerrger/* parser.h * * This file contains the prototypes of all the parsers available within impcap. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include "rsyslog.h" #include "msg.h" #include "dirty.h" #ifdef __FreeBSD__ #include #else #include #endif #include #include #include #include #include #include #include #include #ifndef INCLUDED_PARSER_H #define INCLUDED_PARSER_H 1 /* data return structure */ struct data_ret_s { size_t size; char *pData; }; typedef struct data_ret_s data_ret_t; #define RETURN_DATA_AFTER(x) \ data_ret_t *retData = malloc(sizeof(data_ret_t)); \ if (retData == NULL) return NULL; \ if (pktSize > x) { \ retData->size = pktSize - x; \ retData->pData = (char *)packet + x; \ } else { \ retData->size = 0; \ retData->pData = NULL; \ } \ return retData; /* --- handlers prototypes --- */ void packet_parse(uchar *arg, const struct pcap_pkthdr *pkthdr, const uchar *packet); data_ret_t *eth_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *llc_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *ipx_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *ipv4_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *icmp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *tcp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *udp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *ipv6_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *arp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *rarp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *ah_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *esp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *smb_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *ftp_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *http_parse(const uchar *packet, int pktSize, struct json_object *jparent); data_ret_t *dns_parse(const uchar *packet, int pktSize, struct json_object *jparent); // inline function definitions static inline data_ret_t *dont_parse(const uchar *packet, int pktSize, __attribute__((unused)) struct json_object *jparent); static inline data_ret_t *eth_proto_parse(uint16_t ethProto, const uchar *packet, int pktSize, struct json_object *jparent); static inline data_ret_t *ip_proto_parse(uint16_t ipProto, const uchar *packet, int pktSize, struct json_object *jparent); /* * Mock function to do no parsing when protocol is not a valid number */ static inline data_ret_t *dont_parse(const uchar *packet, int pktSize, __attribute__((unused)) struct json_object *jparent) { DBGPRINTF("protocol not handled\n"); RETURN_DATA_AFTER(0) } // proto code handlers static inline data_ret_t *eth_proto_parse(uint16_t ethProto, const uchar *packet, int pktSize, struct json_object *jparent) { switch (ethProto) { case ETHERTYPE_IP: return ipv4_parse(packet, pktSize, jparent); case ETHERTYPE_IPV6: return ipv6_parse(packet, pktSize, jparent); case ETHERTYPE_ARP: return arp_parse(packet, pktSize, jparent); case ETHERTYPE_REVARP: return rarp_parse(packet, pktSize, jparent); case ETHERTYPE_IPX: return ipx_parse(packet, pktSize, jparent); default: return dont_parse(packet, pktSize, jparent); } } static inline data_ret_t *ip_proto_parse(uint16_t ipProto, const uchar *packet, int pktSize, struct json_object *jparent) { switch (ipProto) { case IPPROTO_TCP: return tcp_parse(packet, pktSize, jparent); case IPPROTO_UDP: return udp_parse(packet, pktSize, jparent); case IPPROTO_ICMP: return icmp_parse(packet, pktSize, jparent); default: return dont_parse(packet, pktSize, jparent); } } #endif /* INCLUDED_PARSER_H */ rsyslog-8.2608.0/contrib/impcap/PaxHeaders/icmp_parser.c0000644000000000000000000000013015132411300020104 xustar0028 mtime=1768559296.1378836 30 atime=1787067645.697953483 30 ctime=1787067802.824882138 rsyslog-8.2608.0/contrib/impcap/icmp_parser.c0000666000175000017500000000505115132411300017555 0ustar00rgerrger/* icmp_parser.c * * This file contains functions to parse ICMP headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" struct icmp_header_s { uint8_t type; uint8_t code; uint16_t checksum; uint8_t data[]; }; typedef struct icmp_header_s icmp_header_t; /* * This function parses the bytes in the received packet to extract ICMP metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the ICMP header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where ICMP metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *icmp_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("icmp_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 8) { DBGPRINTF("ICMP packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0); } /* Union to prevent cast from uchar to icmp_header_t */ union { const uchar *pck; icmp_header_t *hdr; } icmp_header_to_char; icmp_header_to_char.pck = packet; icmp_header_t *icmp_header = icmp_header_to_char.hdr; json_object_object_add(jparent, "net_icmp_type", json_object_new_int(icmp_header->type)); json_object_object_add(jparent, "net_icmp_code", json_object_new_int(icmp_header->code)); json_object_object_add(jparent, "icmp_checksum", json_object_new_int(ntohs(icmp_header->checksum))); RETURN_DATA_AFTER(8) } rsyslog-8.2608.0/contrib/impcap/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160017516 xustar0030 mtime=1787067504.708324193 30 atime=1787067579.680722538 29 ctime=1787067802.81588197 rsyslog-8.2608.0/contrib/impcap/Makefile.in0000664000175000017500000012771215241076160017175 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/impcap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) impcap_la_DEPENDENCIES = am_impcap_la_OBJECTS = impcap_la-impcap.lo impcap_la-arp_parser.lo \ impcap_la-eth_parser.lo impcap_la-icmp_parser.lo \ impcap_la-ipv4_parser.lo impcap_la-ipv6_parser.lo \ impcap_la-ipx_parser.lo impcap_la-llc_parser.lo \ impcap_la-udp_parser.lo impcap_la-dns_parser.lo \ impcap_la-tcp_parser.lo impcap_la-smb_parser.lo \ impcap_la-ftp_parser.lo impcap_la-http_parser.lo impcap_la_OBJECTS = $(am_impcap_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 = impcap_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(impcap_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/impcap_la-arp_parser.Plo \ ./$(DEPDIR)/impcap_la-dns_parser.Plo \ ./$(DEPDIR)/impcap_la-eth_parser.Plo \ ./$(DEPDIR)/impcap_la-ftp_parser.Plo \ ./$(DEPDIR)/impcap_la-http_parser.Plo \ ./$(DEPDIR)/impcap_la-icmp_parser.Plo \ ./$(DEPDIR)/impcap_la-impcap.Plo \ ./$(DEPDIR)/impcap_la-ipv4_parser.Plo \ ./$(DEPDIR)/impcap_la-ipv6_parser.Plo \ ./$(DEPDIR)/impcap_la-ipx_parser.Plo \ ./$(DEPDIR)/impcap_la-llc_parser.Plo \ ./$(DEPDIR)/impcap_la-smb_parser.Plo \ ./$(DEPDIR)/impcap_la-tcp_parser.Plo \ ./$(DEPDIR)/impcap_la-udp_parser.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(impcap_la_SOURCES) DIST_SOURCES = $(impcap_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = impcap.la impcap_la_SOURCES = impcap.c arp_parser.c eth_parser.c icmp_parser.c \ ipv4_parser.c ipv6_parser.c ipx_parser.c llc_parser.c \ udp_parser.c dns_parser.c tcp_parser.c smb_parser.c \ ftp_parser.c http_parser.c impcap_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) impcap_la_LDFLAGS = -module -avoid-version impcap_la_LIBADD = -lpcap EXTRA_DIST = parsers.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/impcap/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/impcap/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } impcap.la: $(impcap_la_OBJECTS) $(impcap_la_DEPENDENCIES) $(EXTRA_impcap_la_DEPENDENCIES) $(AM_V_CCLD)$(impcap_la_LINK) -rpath $(pkglibdir) $(impcap_la_OBJECTS) $(impcap_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-arp_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-dns_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-eth_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ftp_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-http_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-icmp_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-impcap.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipv4_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipv6_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-ipx_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-llc_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-smb_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-tcp_parser.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/impcap_la-udp_parser.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< impcap_la-impcap.lo: impcap.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-impcap.lo -MD -MP -MF $(DEPDIR)/impcap_la-impcap.Tpo -c -o impcap_la-impcap.lo `test -f 'impcap.c' || echo '$(srcdir)/'`impcap.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-impcap.Tpo $(DEPDIR)/impcap_la-impcap.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='impcap.c' object='impcap_la-impcap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-impcap.lo `test -f 'impcap.c' || echo '$(srcdir)/'`impcap.c impcap_la-arp_parser.lo: arp_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-arp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-arp_parser.Tpo -c -o impcap_la-arp_parser.lo `test -f 'arp_parser.c' || echo '$(srcdir)/'`arp_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-arp_parser.Tpo $(DEPDIR)/impcap_la-arp_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='arp_parser.c' object='impcap_la-arp_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-arp_parser.lo `test -f 'arp_parser.c' || echo '$(srcdir)/'`arp_parser.c impcap_la-eth_parser.lo: eth_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-eth_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-eth_parser.Tpo -c -o impcap_la-eth_parser.lo `test -f 'eth_parser.c' || echo '$(srcdir)/'`eth_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-eth_parser.Tpo $(DEPDIR)/impcap_la-eth_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='eth_parser.c' object='impcap_la-eth_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-eth_parser.lo `test -f 'eth_parser.c' || echo '$(srcdir)/'`eth_parser.c impcap_la-icmp_parser.lo: icmp_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-icmp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-icmp_parser.Tpo -c -o impcap_la-icmp_parser.lo `test -f 'icmp_parser.c' || echo '$(srcdir)/'`icmp_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-icmp_parser.Tpo $(DEPDIR)/impcap_la-icmp_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='icmp_parser.c' object='impcap_la-icmp_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-icmp_parser.lo `test -f 'icmp_parser.c' || echo '$(srcdir)/'`icmp_parser.c impcap_la-ipv4_parser.lo: ipv4_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipv4_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipv4_parser.Tpo -c -o impcap_la-ipv4_parser.lo `test -f 'ipv4_parser.c' || echo '$(srcdir)/'`ipv4_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipv4_parser.Tpo $(DEPDIR)/impcap_la-ipv4_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipv4_parser.c' object='impcap_la-ipv4_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipv4_parser.lo `test -f 'ipv4_parser.c' || echo '$(srcdir)/'`ipv4_parser.c impcap_la-ipv6_parser.lo: ipv6_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipv6_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipv6_parser.Tpo -c -o impcap_la-ipv6_parser.lo `test -f 'ipv6_parser.c' || echo '$(srcdir)/'`ipv6_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipv6_parser.Tpo $(DEPDIR)/impcap_la-ipv6_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipv6_parser.c' object='impcap_la-ipv6_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipv6_parser.lo `test -f 'ipv6_parser.c' || echo '$(srcdir)/'`ipv6_parser.c impcap_la-ipx_parser.lo: ipx_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ipx_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ipx_parser.Tpo -c -o impcap_la-ipx_parser.lo `test -f 'ipx_parser.c' || echo '$(srcdir)/'`ipx_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ipx_parser.Tpo $(DEPDIR)/impcap_la-ipx_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipx_parser.c' object='impcap_la-ipx_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ipx_parser.lo `test -f 'ipx_parser.c' || echo '$(srcdir)/'`ipx_parser.c impcap_la-llc_parser.lo: llc_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-llc_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-llc_parser.Tpo -c -o impcap_la-llc_parser.lo `test -f 'llc_parser.c' || echo '$(srcdir)/'`llc_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-llc_parser.Tpo $(DEPDIR)/impcap_la-llc_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='llc_parser.c' object='impcap_la-llc_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-llc_parser.lo `test -f 'llc_parser.c' || echo '$(srcdir)/'`llc_parser.c impcap_la-udp_parser.lo: udp_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-udp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-udp_parser.Tpo -c -o impcap_la-udp_parser.lo `test -f 'udp_parser.c' || echo '$(srcdir)/'`udp_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-udp_parser.Tpo $(DEPDIR)/impcap_la-udp_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='udp_parser.c' object='impcap_la-udp_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-udp_parser.lo `test -f 'udp_parser.c' || echo '$(srcdir)/'`udp_parser.c impcap_la-dns_parser.lo: dns_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-dns_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-dns_parser.Tpo -c -o impcap_la-dns_parser.lo `test -f 'dns_parser.c' || echo '$(srcdir)/'`dns_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-dns_parser.Tpo $(DEPDIR)/impcap_la-dns_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dns_parser.c' object='impcap_la-dns_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-dns_parser.lo `test -f 'dns_parser.c' || echo '$(srcdir)/'`dns_parser.c impcap_la-tcp_parser.lo: tcp_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-tcp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-tcp_parser.Tpo -c -o impcap_la-tcp_parser.lo `test -f 'tcp_parser.c' || echo '$(srcdir)/'`tcp_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-tcp_parser.Tpo $(DEPDIR)/impcap_la-tcp_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tcp_parser.c' object='impcap_la-tcp_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-tcp_parser.lo `test -f 'tcp_parser.c' || echo '$(srcdir)/'`tcp_parser.c impcap_la-smb_parser.lo: smb_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-smb_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-smb_parser.Tpo -c -o impcap_la-smb_parser.lo `test -f 'smb_parser.c' || echo '$(srcdir)/'`smb_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-smb_parser.Tpo $(DEPDIR)/impcap_la-smb_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='smb_parser.c' object='impcap_la-smb_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-smb_parser.lo `test -f 'smb_parser.c' || echo '$(srcdir)/'`smb_parser.c impcap_la-ftp_parser.lo: ftp_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-ftp_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-ftp_parser.Tpo -c -o impcap_la-ftp_parser.lo `test -f 'ftp_parser.c' || echo '$(srcdir)/'`ftp_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-ftp_parser.Tpo $(DEPDIR)/impcap_la-ftp_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ftp_parser.c' object='impcap_la-ftp_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-ftp_parser.lo `test -f 'ftp_parser.c' || echo '$(srcdir)/'`ftp_parser.c impcap_la-http_parser.lo: http_parser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT impcap_la-http_parser.lo -MD -MP -MF $(DEPDIR)/impcap_la-http_parser.Tpo -c -o impcap_la-http_parser.lo `test -f 'http_parser.c' || echo '$(srcdir)/'`http_parser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/impcap_la-http_parser.Tpo $(DEPDIR)/impcap_la-http_parser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http_parser.c' object='impcap_la-http_parser.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(impcap_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o impcap_la-http_parser.lo `test -f 'http_parser.c' || echo '$(srcdir)/'`http_parser.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/impcap_la-arp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-dns_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-eth_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ftp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-http_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-icmp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-impcap.Plo -rm -f ./$(DEPDIR)/impcap_la-ipv4_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ipv6_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ipx_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-llc_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-smb_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-tcp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-udp_parser.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/impcap_la-arp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-dns_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-eth_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ftp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-http_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-icmp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-impcap.Plo -rm -f ./$(DEPDIR)/impcap_la-ipv4_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ipv6_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-ipx_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-llc_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-smb_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-tcp_parser.Plo -rm -f ./$(DEPDIR)/impcap_la-udp_parser.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/impcap/PaxHeaders/impcap.c0000644000000000000000000000013215241075234017070 xustar0030 mtime=1787067036.571577658 30 atime=1787067036.715580354 30 ctime=1787067802.818882026 rsyslog-8.2608.0/contrib/impcap/impcap.c0000664000175000017500000006407115241075234016544 0ustar00rgerrger/* impcap.c * * This is an input module using libpcap, a * portable C/C++ library for network traffic capture. * This module reads packets received from a network interface * using libpcap, to extract information such as IP addresses, ports, * protocols, etc... and make it available to rsyslog and other modules. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "rsyslog.h" #include "prop.h" #include "ruleset.h" #include "datetime.h" #include "errmsg.h" #include "unicode-helper.h" #include "module-template.h" #include "rainerscript.h" #include "rsconf.h" #include "glbl.h" #include "srUtils.h" #include "parsers.h" MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("impcap") #define DEFAULT_META_CONTAINER "!impcap" #define DEFAULT_DATA_CONTAINER "!data" /* static data */ DEF_IMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) DEFobjCurrIf(datetime) static prop_t *pInputName = NULL; char *stringToHex(char *string, size_t length); static ATTR_NORETURN void *startCaptureThread(void *instanceConf); /* conf structures */ struct instanceConf_s { char *interface; uchar *filePath; pcap_t *device; uchar *filter; uchar *tag; uint8_t promiscuous; uint8_t immediateMode; uint32_t bufSize; uint8_t bufTimeout; uint8_t pktBatchCnt; pthread_t tid; uchar *pszBindRuleset; /* name of ruleset to bind to */ ruleset_t *pBindRuleset; /* ruleset to bind listener to (use system default if unspecified) */ struct instanceConf_s *next; }; struct modConfData_s { rsconf_t *pConf; instanceConf_t *root, *tail; uint16_t snap_length; uint8_t metadataOnly; char *metadataContainer; char *dataContainer; }; static modConfData_t *loadModConf = NULL; /* modConf ptr to use for the current load process */ static modConfData_t *runModConf = NULL; /* modConf ptr to use for the current exec process */ /* input instance parameters */ static struct cnfparamdescr inppdescr[] = {{"interface", eCmdHdlrGetWord, 0}, {"file", eCmdHdlrString, 0}, {"promiscuous", eCmdHdlrBinary, 0}, {"filter", eCmdHdlrString, 0}, {"tag", eCmdHdlrString, 0}, {"ruleset", eCmdHdlrString, 0}, {"no_buffer", eCmdHdlrBinary, 0}, {"buffer_size", eCmdHdlrPositiveInt, 0}, {"buffer_timeout", eCmdHdlrPositiveInt, 0}, {"packet_count", eCmdHdlrPositiveInt, 0}}; static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; /* module-global parameters */ static struct cnfparamdescr modpdescr[] = {{"snap_length", eCmdHdlrPositiveInt, 0}, {"metadata_only", eCmdHdlrBinary, 0}, {"metadata_container", eCmdHdlrGetWord, 0}, {"data_container", eCmdHdlrGetWord, 0}}; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; #include "im-helper.h" /* * create input instance, set default parameters, and * add it to the list of instances. */ static rsRetVal createInstance(instanceConf_t **pinst) { instanceConf_t *inst; DEFiRet; CHKmalloc(inst = malloc(sizeof(instanceConf_t))); inst->next = NULL; inst->interface = NULL; inst->filePath = NULL; inst->device = NULL; inst->promiscuous = 0; inst->filter = NULL; inst->tag = NULL; inst->pszBindRuleset = NULL; inst->immediateMode = 0; inst->bufTimeout = 10; inst->bufSize = 1024 * 1024 * 15; /* should be enough for up to 10Gb interface*/ inst->pktBatchCnt = 5; /* node created, let's add to global config */ if (loadModConf->tail == NULL) { loadModConf->tail = loadModConf->root = inst; } else { loadModConf->tail->next = inst; loadModConf->tail = inst; } *pinst = inst; finalize_it: RETiRet; } /* input instances */ BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst; int i; CODESTARTnewInpInst; pvals = nvlstGetParams(lst, &inppblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "impcap: required parameters are missing\n"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(inppblk.descr[i].name, "interface")) { CHKmalloc(inst->interface = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "file")) { CHKmalloc(inst->filePath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "promiscuous")) { inst->promiscuous = (uint8_t)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "filter")) { CHKmalloc(inst->filter = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "tag")) { CHKmalloc(inst->tag = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "no_buffer")) { inst->immediateMode = (uint8_t)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "buffer_size")) { inst->bufSize = (uint32_t)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "buffer_timeout")) { inst->bufTimeout = (uint8_t)pvals[i].val.d.n; } else if (!strcmp(inppblk.descr[i].name, "packet_count")) { inst->pktBatchCnt = (uint8_t)pvals[i].val.d.n; } else { dbgprintf("impcap: non-handled param %s in beginCnfLoad\n", inppblk.descr[i].name); } } finalize_it: CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst /* global mod conf (v2 system) */ BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (pvals == NULL) { LogError(0, RS_RET_MISSING_CNFPARAMS, "impcap: error processing module " "config parameters missing [module(...)]"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(modpblk.descr[i].name, "snap_length")) { loadModConf->snap_length = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "metadata_only")) { loadModConf->metadataOnly = (uint8_t)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "metadata_container")) { CHKmalloc(loadModConf->metadataContainer = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "data_container")) { CHKmalloc(loadModConf->dataContainer = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { dbgprintf("impcap: non-handled param %s in beginSetModCnf\n", modpblk.descr[i].name); } } if (!loadModConf->metadataContainer) CHKmalloc(loadModConf->metadataContainer = strdup(DEFAULT_META_CONTAINER)); if (!loadModConf->dataContainer) CHKmalloc(loadModConf->dataContainer = strdup(DEFAULT_DATA_CONTAINER)); finalize_it: if (pvals != NULL) cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf /* config v2 system */ BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; loadModConf->pConf = pConf; loadModConf->metadataOnly = 0; loadModConf->snap_length = 65535; loadModConf->metadataContainer = NULL; loadModConf->dataContainer = NULL; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad /* function to generate error message if framework does not find requested ruleset */ static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "impcap: ruleset '%s' for interface %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->interface); } BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; if (pModConf->root == NULL) { LogError(0, RS_RET_NO_LISTNERS, "impcap: module loaded, but " "no interface defined - no input will be gathered"); iRet = RS_RET_NO_LISTNERS; } if (pModConf->metadataOnly) { /* if metadata_only is "on", snap_length is overwritten */ pModConf->snap_length = 100; /* arbitrary value, but should be enough for most protocols */ } if (!pModConf->metadataContainer || !pModConf->dataContainer) { LogError(0, RS_RET_LOAD_ERROR, "impcap: no name defined for metadata_container and " "data_container, this shouldn't happen"); } else { DBGPRINTF("impcap: metadata will be stored in '%s', and data in '%s'\n", pModConf->metadataContainer, pModConf->dataContainer); } for (inst = pModConf->root; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); if (inst->interface == NULL && inst->filePath == NULL) { iRet = RS_RET_INVALID_PARAMS; LogError(0, RS_RET_LOAD_ERROR, "impcap: 'interface' or 'file' must be specified"); break; } if (inst->interface != NULL && inst->filePath != NULL) { iRet = RS_RET_INVALID_PARAMS; LogError(0, RS_RET_LOAD_ERROR, "impcap: either 'interface' or 'file' must be specified"); break; } } ENDcheckCnf BEGINactivateCnfPrePrivDrop CODESTARTactivateCnfPrePrivDrop; runModConf = pModConf; ENDactivateCnfPrePrivDrop BEGINactivateCnf instanceConf_t *inst; pcap_t *dev = NULL; struct bpf_program filter_program; bpf_u_int32 SubNet, NetMask; char errBuf[PCAP_ERRBUF_SIZE]; uint8_t retCode = 0; CODESTARTactivateCnf; for (inst = pModConf->root; inst != NULL; inst = inst->next) { if (inst->filePath != NULL) { dev = pcap_open_offline((const char *)inst->filePath, errBuf); if (dev == NULL) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while opening capture file: '%s'", errBuf); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } } else if (inst->interface != NULL) { dev = pcap_create((const char *)inst->interface, errBuf); if (dev == NULL) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while creating packet capture: '%s'", errBuf); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } DBGPRINTF("setting snap_length %d\n", pModConf->snap_length); if (pcap_set_snaplen(dev, pModConf->snap_length)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting snap length: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } DBGPRINTF("setting promiscuous %d\n", inst->promiscuous); if (pcap_set_promisc(dev, inst->promiscuous)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting promiscuous mode: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } if (inst->immediateMode) { DBGPRINTF("setting immediate mode %d\n", inst->immediateMode); retCode = pcap_set_immediate_mode(dev, inst->immediateMode); if (retCode) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting immediate mode: '%s'," " using buffer instead\n", pcap_geterr(dev)); } } if (!inst->immediateMode || retCode) { DBGPRINTF("setting buffer size %u \n", inst->bufSize); if (pcap_set_buffer_size(dev, inst->bufSize)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting buffer size: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } DBGPRINTF("setting buffer timeout %dms\n", inst->bufTimeout); if (pcap_set_timeout(dev, inst->bufTimeout)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting buffer timeout: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } } switch (pcap_activate(dev)) { case PCAP_WARNING_PROMISC_NOTSUP: LogError(0, NO_ERRCODE, "interface doesn't support promiscuous mode"); break; case PCAP_WARNING_TSTAMP_TYPE_NOTSUP: LogError(0, NO_ERRCODE, "timestamp type is not supported"); break; case PCAP_WARNING: LogError(0, NO_ERRCODE, "pcap: %s", pcap_geterr(dev)); break; case PCAP_ERROR_ACTIVATED: LogError(0, RS_RET_LOAD_ERROR, "already activated, shouldn't happen"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR_NO_SUCH_DEVICE: LogError(0, RS_RET_LOAD_ERROR, "device doesn't exist"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR_PERM_DENIED: LogError(0, RS_RET_LOAD_ERROR, "elevated privilege needed to open capture " "interface"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR_PROMISC_PERM_DENIED: LogError(0, RS_RET_LOAD_ERROR, "elevated privilege needed to put interface " "in promiscuous mode"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR_RFMON_NOTSUP: LogError(0, RS_RET_LOAD_ERROR, "interface doesn't support monitor mode"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR_IFACE_NOT_UP: LogError(0, RS_RET_LOAD_ERROR, "interface is not up"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); case PCAP_ERROR: LogError(0, RS_RET_LOAD_ERROR, "pcap: %s", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); default: // No action needed for other cases break; } if (inst->filter != NULL) { DBGPRINTF("getting netmask on %s\n", inst->interface); // obtain the subnet if (pcap_lookupnet(inst->interface, &SubNet, &NetMask, errBuf)) { DBGPRINTF("could not get netmask\n"); NetMask = PCAP_NETMASK_UNKNOWN; } DBGPRINTF("setting filter to '%s'\n", inst->filter); /* Compile the filter */ if (pcap_compile(dev, &filter_program, (const char *)inst->filter, 1, NetMask)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while compiling filter: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } else if (pcap_setfilter(dev, &filter_program)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting filter: '%s'", pcap_geterr(dev)); pcap_freecode(&filter_program); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } pcap_freecode(&filter_program); } if (pcap_set_datalink(dev, DLT_EN10MB)) { LogError(0, RS_RET_LOAD_ERROR, "pcap: error while setting datalink type: '%s'", pcap_geterr(dev)); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } } /* inst->interface != NULL */ else { LogError(0, RS_RET_LOAD_ERROR, "impcap: no capture method specified, " "please specify either 'interface' or 'file' in config"); ABORT_FINALIZE(RS_RET_LOAD_ERROR); } inst->device = dev; } finalize_it: if (iRet != 0) { if (dev) pcap_close(dev); } ENDactivateCnf BEGINfreeCnf instanceConf_t *inst, *del; CODESTARTfreeCnf; DBGPRINTF("impcap: freeing confs...\n"); for (inst = pModConf->root; inst != NULL;) { del = inst; inst = inst->next; free(del->filePath); free(del->filter); free(del->pszBindRuleset); free(del->interface); free(del->tag); free(del); } free(pModConf->metadataContainer); free(pModConf->dataContainer); DBGPRINTF("impcap: finished freeing confs\n"); ENDfreeCnf /* runtime functions */ /* * Converts a list of bytes to their hexadecimal representation in ASCII * * Gets the list of bytes and the length as parameters * * Returns a pointer on the new list, being a string of ASCII characters * representing hexadecimal values, in the form "A5B34C65..." * its size is twice length parameter + 1 */ char *stringToHex(char *string, size_t length) { const char *hexChar = "0123456789ABCDEF"; char *retBuf; size_t i; if (length > (((size_t)-1) - 1) / 2) return NULL; retBuf = malloc((2 * length + 1) * sizeof(char)); if (retBuf == NULL) return NULL; for (i = 0; i < length; ++i) { retBuf[2 * i] = hexChar[(string[i] & 0xF0) >> 4]; retBuf[2 * i + 1] = hexChar[string[i] & 0x0F]; } retBuf[2 * length] = '\0'; return retBuf; } /* * This method parses every packet received by libpcap, and is called by it * It creates the message for Rsyslog, calls the parsers and add all necessary information * in the message */ void packet_parse(uchar *arg, const struct pcap_pkthdr *pkthdr, const uchar *packet) { DBGPRINTF("impcap : entered packet_parse\n"); smsg_t *pMsg; /* Prevent cast error from char to int with arg */ union { uchar *buf; int *id; } aux; aux.buf = arg; int *id = aux.id; msgConstruct(&pMsg); MsgSetInputName(pMsg, pInputName); // search inst in loadmodconf,and check if there is tag. if so set tag in msg. pthread_t ctid = pthread_self(); instanceConf_t *inst; for (inst = runModConf->root; inst != NULL; inst = inst->next) { if (pthread_equal(ctid, inst->tid)) { if (inst->pBindRuleset != NULL) { MsgSetRuleset(pMsg, inst->pBindRuleset); } if (inst->tag != NULL) { MsgSetTAG(pMsg, inst->tag, strlen((const char *)inst->tag)); } } } struct json_object *jown = json_object_new_object(); json_object_object_add(jown, "ID", json_object_new_int(++(*id))); struct syslogTime sysTimePkt; char timeStr[30]; struct timeval tv = pkthdr->ts; datetime.timeval2syslogTime(&tv, &sysTimePkt, 1 /*inUTC*/); if (datetime.formatTimestamp3339(&sysTimePkt, timeStr)) { json_object_object_add(jown, "timestamp", json_object_new_string(timeStr)); } json_object_object_add(jown, "net_bytes_total", json_object_new_int(pkthdr->len)); if (pkthdr->caplen > INT_MAX) { DBGPRINTF("impcap : captured packet too large to parse: %u\n", pkthdr->caplen); msgDestruct(&pMsg); json_object_put(jown); return; } data_ret_t *dataLeft = eth_parse(packet, (int)pkthdr->caplen, jown); if (dataLeft == NULL) { msgDestruct(&pMsg); json_object_put(jown); return; } json_object_object_add(jown, "net_bytes_data", json_object_new_int(dataLeft->size)); char *dataHex = stringToHex(dataLeft->pData, dataLeft->size); if (dataHex != NULL) { struct json_object *jadd = json_object_new_object(); json_object_object_add(jadd, "length", json_object_new_int(strlen(dataHex))); json_object_object_add(jadd, "content", json_object_new_string(dataHex)); msgAddJSON(pMsg, (uchar *)runModConf->dataContainer, jadd, 0, 0); free(dataHex); } free(dataLeft); msgAddJSON(pMsg, (uchar *)runModConf->metadataContainer, jown, 0, 0); submitMsg2(pMsg); } /* This is used to terminate the plugin. */ static void doSIGTTIN(int __attribute__((unused)) sig) { pthread_t tid = pthread_self(); const int bTerminate = PREFER_LOAD_INT(&bTerminateInputsSigSafe); DBGPRINTF("impcap: awoken via SIGTTIN; bTerminateInputsSigSafe: %d\n", bTerminate); if (bTerminate) { for (instanceConf_t *inst = runModConf->root; inst != NULL; inst = inst->next) { if (pthread_equal(tid, inst->tid)) { pcap_breakloop(inst->device); DBGPRINTF("impcap: thread %lx, termination requested via SIGTTIN - telling libpcap\n", (long unsigned int)tid); } } } } /* * This is the main function for each thread * taking care of a specified network interface */ static ATTR_NORETURN void *startCaptureThread(void *instanceConf) { int id = 0; pthread_t tid = pthread_self(); /* we want to support non-cancel input termination. To do so, we must signal libpcap * when to stop. As we run on the same thread, we need to register as SIGTTIN handler, * which will be used to put the terminating condition into libpcap. */ DBGPRINTF("impcap: setting catch for SIGTTIN, thread %lx\n", (long unsigned int)tid); sigset_t sigSet; struct sigaction sigAct; sigfillset(&sigSet); pthread_sigmask(SIG_BLOCK, &sigSet, NULL); sigemptyset(&sigSet); sigaddset(&sigSet, SIGTTIN); pthread_sigmask(SIG_UNBLOCK, &sigSet, NULL); memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = doSIGTTIN; sigaction(SIGTTIN, &sigAct, NULL); instanceConf_t *inst = (instanceConf_t *)instanceConf; DBGPRINTF("impcap: thread %lx, begin capture!\n", (long unsigned int)tid); while (glbl.GetGlobalInputTermState() == 0) { pcap_dispatch(inst->device, inst->pktBatchCnt, packet_parse, (uchar *)&id); } DBGPRINTF("impcap: thread %lx, capture finished\n", (long unsigned int)tid); pthread_exit(0); } BEGINrunInput instanceConf_t *inst; int ret = 0; CODESTARTrunInput; for (inst = runModConf->root; inst != NULL; inst = inst->next) { /* creates a thread and starts capturing on the interface */ ret = pthread_create(&inst->tid, NULL, startCaptureThread, inst); if (ret) { LogError(0, RS_RET_NO_RUN, "impcap: error while creating threads\n"); } } DBGPRINTF("impcap: starting to wait for close condition\n"); // TODO: Use thread for capture instead of just waiting while (glbl.GetGlobalInputTermState() == 0) { if (glbl.GetGlobalInputTermState() == 0) srSleep(0, 400000); } DBGPRINTF("impcap: received close signal, signaling instance threads...\n"); for (inst = runModConf->root; inst != NULL; inst = inst->next) { pthread_kill(inst->tid, SIGTTIN); } DBGPRINTF("impcap: threads signaled, waiting for join..."); for (inst = runModConf->root; inst != NULL; inst = inst->next) { pthread_join(inst->tid, NULL); pcap_close(inst->device); } DBGPRINTF("impcap: finished threads, stopping\n"); ENDrunInput BEGINwillRun CODESTARTwillRun; /* we need to create the inputName property (only once during our lifetime) */ CHKiRet(prop.Construct(&pInputName)); CHKiRet(prop.SetString(pInputName, UCHAR_CONSTANT("impcap"), sizeof("impcap") - 1)); CHKiRet(prop.ConstructFinalize(pInputName)); finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun; if (pInputName != NULL) { prop.Destruct(&pInputName); } ENDafterRun BEGINmodExit CODESTARTmodExit; DBGPRINTF("impcap:: modExit\n"); objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit /* declaration of functions */ BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES /* might need it */ CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/impcap/PaxHeaders/eth_parser.c0000644000000000000000000000013215216464435017762 xustar0030 mtime=1782212893.959265101 30 atime=1787067645.700953539 30 ctime=1787067802.822882101 rsyslog-8.2608.0/contrib/impcap/eth_parser.c0000664000175000017500000001462515216464435017436 0ustar00rgerrger/* eth_parser.c * * This file contains functions to parse Ethernet II headers. * * File begun on 2018-11-13 * * Created by: * - Théo Bertin (theo.bertin@advens.fr) * * With: * - François Bernard (francois.bernard@isen.yncrea.fr) * - Tianyu Geng (tianyu.geng@isen.yncrea.fr) * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "parsers.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpacked" #pragma GCC diagnostic ignored "-Wattributes" struct __attribute__((__packed__)) eth_header_s { uint8_t addrDst[6]; uint8_t addrSrc[6]; uint16_t type; }; struct __attribute__((__packed__)) vlan_header_s { uint8_t addrDst[6]; uint8_t addrSrc[6]; uint16_t vlanCode; uint16_t vlanTag; uint16_t type; }; #pragma GCC diagnostic pop typedef struct eth_header_s eth_header_t; typedef struct vlan_header_s vlan_header_t; /* * Get an ethernet header type as uint16_t * and return the correspondence as string * NOTE : Only most common types are present, to complete if needed */ static const char *eth_type_to_string(uint16_t eth_type) { switch (eth_type) { case 0x00bb: // Extreme Networks Discovery Protocol return "EDP"; case 0x0200: // PUP protocol return "PUP"; case 0x0800: // IP protocol return "IP"; case 0x0806: // address resolution protocol return "ARP"; case 0x88a2: // AoE protocol return "AOE"; case 0x2000: // Cisco Discovery Protocol return "CDP"; case 0x2004: // Cisco Dynamic Trunking Protocol return "DTP"; case 0x8035: // reverse addr resolution protocol return "REVARP"; case 0x8100: // IEEE 802.1Q VLAN tagging return "802.1Q"; case 0x88a8: // IEEE 802.1ad return "802.1AD"; case 0x9100: // Legacy QinQ return "QINQ1"; case 0x9200: // Legacy QinQ return "QINQ2"; case 0x8137: // Internetwork Packet Exchange return "IPX"; case 0x86DD: // IPv6 protocol return "IPv6"; case 0x880B: // PPP return "PPP"; case 0x8847: // MPLS return "MPLS"; case 0x8848: // MPLS Multicast return "MPLS_MCAST"; case 0x8863: // PPP Over Ethernet Discovery Stage return "PPPoE_DISC"; case 0x8864: // PPP Over Ethernet Session Stage return "PPPoE"; case 0x88CC: // Link Layer Discovery Protocol return "LLDP"; case 0x6558: // Transparent Ethernet Bridging return "TEB"; default: return "UNKNOWN"; } } /* * This function parses the bytes in the received packet to extract Ethernet II metadata. * * its parameters are: * - a pointer on the list of bytes representing the packet * the first byte must be the beginning of the ETH header * - the size of the list passed as first parameter * - a pointer on a json_object, containing all the metadata recovered so far * this is also where ETH metadata will be added * * This function returns a structure containing the data unprocessed by this parser * or the ones after (as a list of bytes), and the length of this data. */ data_ret_t *eth_parse(const uchar *packet, int pktSize, struct json_object *jparent) { DBGPRINTF("entered eth_parse\n"); DBGPRINTF("packet size %d\n", pktSize); if (pktSize < 14) { /* too short for eth header */ DBGPRINTF("ETH packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } eth_header_t *eth_header = (eth_header_t *)packet; char ethMacSrc[20], ethMacDst[20]; uint8_t hdrLen = 14; ether_ntoa_r((struct ether_addr *)eth_header->addrSrc, ethMacSrc); ether_ntoa_r((struct ether_addr *)eth_header->addrDst, ethMacDst); json_object_object_add(jparent, "ETH_src", json_object_new_string((char *)ethMacSrc)); json_object_object_add(jparent, "ETH_dst", json_object_new_string((char *)ethMacDst)); uint16_t ethType = (uint16_t)ntohs(eth_header->type); if (ethType == ETHERTYPE_VLAN) { if (pktSize < (int)sizeof(vlan_header_t)) { DBGPRINTF("VLAN packet too small : %d\n", pktSize); RETURN_DATA_AFTER(0) } vlan_header_t *vlan_header = (vlan_header_t *)packet; json_object_object_add(jparent, "ETH_tag", json_object_new_int(ntohs(vlan_header->vlanTag))); ethType = (uint16_t)ntohs(vlan_header->type); hdrLen += 4; } data_ret_t *ret; if (ethType < 1500) { /* this is a LLC header */ json_object_object_add(jparent, "ETH_len", json_object_new_int(ethType)); ret = llc_parse(packet + hdrLen, pktSize - hdrLen, jparent); if (ret == NULL) return NULL; /* packet has the minimum allowed size, so the remaining data is * most likely padding, this should not appear as data, so remove it * */ // TODO this is a quick win, a more elaborate solution would be to check if all data // is indeed zero, but that would take more processing time if (pktSize <= 60 && ret->pData != NULL) { if (!ret->pData[0]) ret->size = 0; } return ret; } json_object_object_add(jparent, "ETH_type", json_object_new_int(ethType)); json_object_object_add(jparent, "ETH_typestr", json_object_new_string((char *)eth_type_to_string(ethType))); ret = eth_proto_parse(ethType, (packet + hdrLen), (pktSize - hdrLen), jparent); if (ret == NULL) return NULL; /* packet has the minimum allowed size, so the remaining data is * most likely padding, this should not appear as data, so remove it */ if (pktSize <= 60 && ret->pData != NULL) { if (!ret->pData[0]) ret->size = 0; } return ret; } rsyslog-8.2608.0/contrib/PaxHeaders/pmpanngfw0000644000000000000000000000013215241076625016127 xustar0030 mtime=1787067797.201777363 30 atime=1787067808.786993238 30 ctime=1787067797.201777363 rsyslog-8.2608.0/contrib/pmpanngfw/0000775000175000017500000000000015241076625015650 5ustar00rgerrgerrsyslog-8.2608.0/contrib/pmpanngfw/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020232 xustar0030 mtime=1752569012.331237145 30 atime=1787067434.418012724 30 ctime=1787067797.192777195 rsyslog-8.2608.0/contrib/pmpanngfw/Makefile.am0000666000175000017500000000034415035412264017701 0ustar00rgerrgerpkglib_LTLIBRARIES = pmpanngfw.la pmpanngfw_la_SOURCES = pmpanngfw.c pmpanngfw_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmpanngfw_la_LDFLAGS = -module -avoid-version pmpanngfw_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/pmpanngfw/PaxHeaders/pmpanngfw.c0000644000000000000000000000013215216464435020347 xustar0030 mtime=1782212893.964265181 30 atime=1782715518.794788942 30 ctime=1787067797.201777363 rsyslog-8.2608.0/contrib/pmpanngfw/pmpanngfw.c0000664000175000017500000002054515216464435020021 0ustar00rgerrger/* pmpanngfw.c * * this detects logs sent by Palo Alto Networks NGFW and transforms CSV into tab-separated fields * for handling inside the mmnormalize * * Example: foo,"bar,""baz""",qux becomes foobar,"baz"qux * * created 2010-12-13 by Luigi Mori (lmori@paloaltonetworks.com) based on pmsnare * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" #include "typedefs.h" #include "rsconf.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.panngfw") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* static data */ static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ typedef struct { uint64 value; uint64 mask; } log_type_t; const log_type_t log_types[] = { {0x002c544145524854ULL, 0x00FFFFFFFFFFFFFFULL}, /* THREAT, */ {0x2c43494646415254ULL, 0xFFFFFFFFFFFFFFFFULL}, /* TRAFFIC, */ {0x002c4d4554535953ULL, 0x00FFFFFFFFFFFFFFULL}, /* CONFIG */ {0x002c4749464e4f43ULL, 0x00FFFFFFFFFFFFFFULL} /* SYSTEM */ }; #define NUM_LOG_TYPES (sizeof(log_types) / sizeof(log_type_t)) BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINparse uchar *p2parse; uchar *p2target; uchar *msgend; int lenMsg, lenDelta; int state; int num_fields = 4; uchar *f3_commas[3]; int cur_comma = 0; uint64 log_type; unsigned int j; CODESTARTparse; #define CSV_DELIMITER '\t' #define STATE_FIELD_START 0 #define STATE_IN_FIELD 1 #define STATE_IN_QUOTE 2 #define STATE_IN_QUOTE_QUOTE 3 state = STATE_FIELD_START; dbgprintf("Message will now be parsed by fix Palo Alto Networks NGFW parser.\n"); assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* point to start of text, after PRI */ msgend = p2parse + lenMsg; dbgprintf("pmpanngfw: msg to look at: [%d]'%s'\n", lenMsg, p2parse); /* pass the first 3 fields */ while (p2parse < msgend) { if (*p2parse == ',') { f3_commas[cur_comma] = p2parse; if (cur_comma == 2) { break; } cur_comma++; } p2parse++; } /* check number of fields detected so far */ if (cur_comma != 2) { dbgprintf("not a PAN-OS syslog message: first 3 fields not found\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* check msg length */ p2parse++; if ((p2parse > msgend) || ((msgend - p2parse) < (int)sizeof(uint64))) { dbgprintf("not a PAN-OS syslog message: too short\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* check log type */ memcpy(&log_type, p2parse, sizeof(log_type)); for (j = 0; j < (int)NUM_LOG_TYPES; j++) { if ((log_type & log_types[j].mask) == log_types[j].value) break; } if (j == NUM_LOG_TYPES) { dbgprintf("not a PAN-OS syslog message, log type: %llx\n", log_type); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* set the delimiter */ *f3_commas[0] = CSV_DELIMITER; *f3_commas[1] = CSV_DELIMITER; *f3_commas[2] = CSV_DELIMITER; p2target = p2parse; while (p2parse < msgend) { switch (state) { case STATE_FIELD_START: switch (*p2parse) { case '"': state = STATE_IN_QUOTE; p2parse++; break; case ',': state = STATE_FIELD_START; *p2target = CSV_DELIMITER; num_fields++; p2parse++; p2target++; break; default: state = STATE_IN_FIELD; *p2target = *p2parse; p2parse++; p2target++; } break; case STATE_IN_FIELD: switch (*p2parse) { case ',': state = STATE_FIELD_START; *p2target = CSV_DELIMITER; num_fields++; p2parse++; p2target++; break; default: *p2target = *p2parse; p2parse++; p2target++; } break; case STATE_IN_QUOTE: switch (*p2parse) { case '"': state = STATE_IN_QUOTE_QUOTE; p2parse++; break; default: *p2target = *p2parse; p2parse++; p2target++; } break; case STATE_IN_QUOTE_QUOTE: switch (*p2parse) { case '"': state = STATE_IN_QUOTE; *p2target = *p2parse; p2parse++; p2target++; break; case ',': state = STATE_FIELD_START; *p2target = CSV_DELIMITER; num_fields++; p2parse++; p2target++; break; default: dbgprintf("pmpanngfw: martian char (%d) after quote in quote\n", *p2parse); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } break; default: dbgprintf("how could I have reached this state ?!?\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } } if (p2parse != p2target) { lenDelta = p2parse - p2target; assert(lenDelta >= 2); *p2target = 0; pMsg->iLenRawMsg -= lenDelta; pMsg->iLenMSG -= lenDelta; } lenMsg = p2target - (pMsg->pszRawMsg + pMsg->offAfterPRI); DBGPRINTF("pmpanngfw: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI); DBGPRINTF("pmpanngfw: # fields: %d\n", num_fields); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); finalize_it: ENDparse BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); DBGPRINTF("panngfw parser init called, compiled with version %s\n", VERSION); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); /* cache value, is set only during rsyslogd option processing */ ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/contrib/pmpanngfw/PaxHeaders/README.md0000644000000000000000000000013215035412264017455 xustar0030 mtime=1752569012.331237145 30 atime=1782715518.793788925 30 ctime=1787067797.199777326 rsyslog-8.2608.0/contrib/pmpanngfw/README.md0000666000175000017500000001072515035412264017130 0ustar00rgerrger# pmpanngfw Module to detect and transform PAN-OS NGFW logs into a format compatible with mmnormalize ## How it works Original log: Apr 10 02:48:29 1,2012/04/10 02:48:29,001606001116,THREAT,url,1,2012/04/10 02:48:28,##IP##,##IP##,##IP##,##IP##,rule1,counselor,,facebook- base,vsys1,trust,untrust,ethernet1/2,ethernet1/1,forwardAll,2012/04/10 02:48:28,27555,1,8450,80,0,0,0x208000,tcp,alert,"www.facebook. com/ajax/pagelet/generic.php/ProfileTimelineSectionPagelet?__a=1&ajaxpipe=1&ajaxpipe_token=AXgw4BUd5yCuD2rQ&data={""profile_id"":603261604,""start"":1333263600,""end"":1335855599,""query_type"":5,""page_index"":1,""section_container_id"":""ucp7d6_26"",""section_pagelet_id"":""pagelet_timeline_recent"",""unit_container_id"":""ucp7d6_25"",""current_scrubber_key"":""recent"",""time_cutoff"":null,""buffer"":1300,""require_click"":false,""num_visible_units"":5,""remove_dupes"":true}&__user=857280013&__adt=3&__att=iframe",(9999),social-networking,informational,client-to-server,0,0x0,192.168.0.0-192.168.255.255,United States,0,text/html Transformed: Apr 10 02:48:29 12012/04/10 02:48:29001606001116THREATurl12012/04/10 02:48:28##IP####IP####IP####IP##rule1counselorfacebook-basevsys1trustuntrustethernet1/2ethernet1/1forwardAll 2012/04/10 02:48:28 27555184508000x208000tcp alertwww.facebook.com/ajax/pagelet/generic.php/ProfileTimelineSectionPagelet?__a=1&ajaxpipe=1&ajaxpipe_token=AXgw4BUd5yCuD2rQ&data={"profile_id":603261604,"start":1333263600,"end":1335855599,"query_type":5,"page_index":1,"section_container_id":"ucp7d6_26","section_pagelet_id":"pagelet_timeline_recent","unit_container_id":"ucp7d6_25","current_scrubber_key":"recent","time_cutoff":null,"buffer":1300,"require_click":false,"num_visible_units":5,"remove_dupes":true}&__user=857280013&__adt=3&__att=iframe(9999)social-networkinginformationalclient-to-server00x0192.168.0.0-192.168.255.255United States0text/html ## How to compile $ autoreconf -fvi $ ./configure --enable-pmpanngfw $ cd contrib/pmpanngfw/ $ make The resulting plugin should be found in contrib/pmpanngfw/.libs/ ## Example config module(load="imtcp") module(load="pmpanngfw") module(load="mmnormalize") module(load="omrabbitmq") template(name="csv" type="list") { property(name="$!src_ip" format="csv") constant(value=",") property(name="$!dest_ip" format="csv") constant(value=",") property(name="$!url") constant(value="\n") } $template alljson,"%$!all-json%\n" template(name="mmeld_json" type="list") { constant(value="{") property(outname="@timestamp" name="timestamp" format="jsonf" dateFormat="rfc3339") constant(value=",") property(outname="@source_host" name="source" format="jsonf") constant(value=",") property(outname="@message" name="msg" format="jsonf") constant(value=",") property(outname="@timegenerated" name="timegenerated" format="jsonf" dateFormat="rfc3339") constant(value=",") property(outname="@timereported" name="timereported" format="jsonf" dateFormat="rfc3339") constant(value=",") property(outname="src_ip" name="$!src_ip" format="jsonf") constant(value=",") property(outname="dest_ip" name="$!dest_ip" format="jsonf") constant(value=",") property(outname="url" name="$!url" format="jsonf") constant(value=",") property(outname="tags" name="$!event.tags" format="jsonf") constant(value="}") constant(value="\n") } ruleset(name="pan-ngfw" parser=["rsyslog.panngfw", "rsyslog.rfc5424", "rsyslog.rfc3164"]) { action(type="mmnormalize" rulebase="palo_alto_networks.rb" userawmsg="on") if strlen($!unparsed-data) == 0 then { if $!log_subtype == "url" then set $!url = $!misc; *.* action(type="omrabbitmq" host="localhost" virtual_host="/" user="guest" password="guest" exchange="mmeld-syslog" routing_key="" exchange_type="fanout" template="alljson") } *.* stop } input(type="imtcp" port="13514" ruleset="pan-ngfw") ## mmnormalize rulebase See https://gist.github.com/jtschichold/87f59b99d98c8eac1da5 rsyslog-8.2608.0/contrib/pmpanngfw/PaxHeaders/Makefile.in0000644000000000000000000000013215241076161020244 xustar0030 mtime=1787067505.377336673 30 atime=1787067579.076711274 30 ctime=1787067797.195777251 rsyslog-8.2608.0/contrib/pmpanngfw/Makefile.in0000664000175000017500000006606215241076161017722 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/pmpanngfw ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) pmpanngfw_la_DEPENDENCIES = am_pmpanngfw_la_OBJECTS = pmpanngfw_la-pmpanngfw.lo pmpanngfw_la_OBJECTS = $(am_pmpanngfw_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 = pmpanngfw_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmpanngfw_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmpanngfw_la_SOURCES) DIST_SOURCES = $(pmpanngfw_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ README.md DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = pmpanngfw.la pmpanngfw_la_SOURCES = pmpanngfw.c pmpanngfw_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmpanngfw_la_LDFLAGS = -module -avoid-version pmpanngfw_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/pmpanngfw/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/pmpanngfw/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } pmpanngfw.la: $(pmpanngfw_la_OBJECTS) $(pmpanngfw_la_DEPENDENCIES) $(EXTRA_pmpanngfw_la_DEPENDENCIES) $(AM_V_CCLD)$(pmpanngfw_la_LINK) -rpath $(pkglibdir) $(pmpanngfw_la_OBJECTS) $(pmpanngfw_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmpanngfw_la-pmpanngfw.lo: pmpanngfw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmpanngfw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmpanngfw_la-pmpanngfw.lo -MD -MP -MF $(DEPDIR)/pmpanngfw_la-pmpanngfw.Tpo -c -o pmpanngfw_la-pmpanngfw.lo `test -f 'pmpanngfw.c' || echo '$(srcdir)/'`pmpanngfw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmpanngfw_la-pmpanngfw.Tpo $(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmpanngfw.c' object='pmpanngfw_la-pmpanngfw.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmpanngfw_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmpanngfw_la-pmpanngfw.lo `test -f 'pmpanngfw.c' || echo '$(srcdir)/'`pmpanngfw.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmpanngfw_la-pmpanngfw.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/imczmq0000644000000000000000000000013215241076625015432 xustar0030 mtime=1787067797.912790611 30 atime=1787067808.786993238 30 ctime=1787067797.912790611 rsyslog-8.2608.0/contrib/imczmq/0000775000175000017500000000000015241076625015153 5ustar00rgerrgerrsyslog-8.2608.0/contrib/imczmq/PaxHeaders/README0000644000000000000000000000013215035412264016361 xustar0030 mtime=1752569012.326271887 30 atime=1782715518.792788908 30 ctime=1787067797.909790556 rsyslog-8.2608.0/contrib/imczmq/README0000666000175000017500000000206515035412264016032 0ustar00rgerrgerCZMQ Input Plugin REQUIREMENTS: * libsodium ( https://github.com/jedisct1/libsodium ) * zeromq v4.x build with libsodium support ( http://zeromq.org/ ) * czmq 3.x ( http://czmq.zeromq.org/ ) ------------------------------------------------------------------------------- module( load="imczmq" servercertpath="/etc/curve.d/server" clientcertpath="/etc/curve.d/" authtype="CURVESERVER" authenticator="on" ) input( type="imczmq" endpoints="@tcp://*:24555" socktype="PULL" ) ------------------------------------------------------------------------------- Explanation of Options: Module ------ servercertpath: path to server cert if using CURVE clientcertpath: path to client cert(s) if using CURVE authtype: CURVESERVER, CURVECLIENT (omit for no auth) authenticator: whether to start an authenticator thread Action ------ type: type of action (imczmq for this plugin) endpoints: comma delimited list of zeromq endpoints (see zeromq documentation) socktype: zeromq socket type (currently supports PULL, SUB, ROUTER, DISH, SERVER) authtype: CURVECLIENT or CURVESERVER rsyslog-8.2608.0/contrib/imczmq/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264017535 xustar0030 mtime=1752569012.326271887 30 atime=1787067433.967004307 30 ctime=1787067797.903790443 rsyslog-8.2608.0/contrib/imczmq/Makefile.am0000666000175000017500000000033715035412264017206 0ustar00rgerrgerpkglib_LTLIBRARIES = imczmq.la imczmq_la_SOURCES = imczmq.c imczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS) imczmq_la_LDFLAGS = -module -avoid-version imczmq_la_LIBADD = $(CZMQ_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/imczmq/PaxHeaders/imczmq.c0000644000000000000000000000013115216464435017154 xustar0030 mtime=1782212893.957265068 30 atime=1782715518.792788908 29 ctime=1787067797.91379063 rsyslog-8.2608.0/contrib/imczmq/imczmq.c0000664000175000017500000005107215216464435016626 0ustar00rgerrger/** * @file imczmq.c * @brief Input module for receiving messages via ZeroMQ. * * The module creates one or more CZMQ sockets according to the * configuration and converts each incoming frame into an rsyslog * message processed by the specified ruleset. Socket type, topics and * CURVE authentication parameters are fully configurable. * * Copyright (C) 2016 Brian Knox * Copyright (C) 2014 Rainer Gerhards * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include "cfsysline.h" #include "dirty.h" #include "errmsg.h" #include "glbl.h" #include "module-template.h" #include "msg.h" #include "net.h" #include "parser.h" #include "prop.h" #include "ruleset.h" #include "srUtils.h" #include "unicode-helper.h" #include MODULE_TYPE_INPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("imczmq"); DEF_IMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(prop) DEFobjCurrIf(ruleset) static struct cnfparamdescr modpdescr[] = { {"authenticator", eCmdHdlrBinary, 0}, {"authtype", eCmdHdlrString, 0}, {"servercertpath", eCmdHdlrString, 0}, {"clientcertpath", eCmdHdlrString, 0}, }; static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr}; struct modConfData_s { rsconf_t *pConf; instanceConf_t *root; instanceConf_t *tail; int authenticator; char *authType; char *serverCertPath; char *clientCertPath; }; struct instanceConf_s { bool serverish; int sockType; char *sockEndpoints; char *topics; uchar *pszBindRuleset; ruleset_t *pBindRuleset; struct instanceConf_s *next; }; struct listener_t { zsock_t *sock; ruleset_t *ruleset; }; static zlist_t *listenerList; static modConfData_t *runModConf = NULL; static prop_t *s_namep = NULL; enum { IMCZMQ_MAX_TOPIC_LEN = 255 }; static struct cnfparamdescr inppdescr[] = { {"endpoints", eCmdHdlrGetWord, 1}, {"socktype", eCmdHdlrGetWord, 1}, {"ruleset", eCmdHdlrGetWord, 0}, {"topics", eCmdHdlrGetWord, 0}, }; #include "im-helper.h" static struct cnfparamblk inppblk = {CNFPARAMBLK_VERSION, sizeof(inppdescr) / sizeof(struct cnfparamdescr), inppdescr}; static void setDefaults(instanceConf_t *iconf) { iconf->serverish = true; iconf->sockType = -1; iconf->sockEndpoints = NULL; iconf->topics = NULL; iconf->pszBindRuleset = NULL; iconf->pBindRuleset = NULL; iconf->next = NULL; }; static rsRetVal validateTopics(const char *topics) { DEFiRet; const char *cursor; if (topics == NULL) { FINALIZE; } for (cursor = topics; *cursor != '\0';) { const char *delimiter = strchr(cursor, ','); const size_t topic_len = (delimiter == NULL) ? strlen(cursor) : (size_t)(delimiter - cursor); if (topic_len > IMCZMQ_MAX_TOPIC_LEN) { LogError(0, RS_RET_PARAM_ERROR, "imczmq: configured topic exceeds maximum supported length of %u bytes", (unsigned)IMCZMQ_MAX_TOPIC_LEN); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (delimiter == NULL) { break; } cursor = delimiter + 1; } finalize_it: RETiRet; } /** * @brief Allocate a new listener configuration block. * * The new instance is initialized with default values and appended to * the module's list of listeners which will be activated when the * input starts. * * @param[out] pinst pointer receiving the allocated instance * @retval RS_RET_OK on success * @retval RS_RET_OUT_OF_MEMORY if allocation fails */ static rsRetVal createInstance(instanceConf_t **pinst) { DEFiRet; instanceConf_t *inst; CHKmalloc(inst = malloc(sizeof(instanceConf_t))); setDefaults(inst); if (runModConf->root == NULL || runModConf->tail == NULL) { runModConf->tail = runModConf->root = inst; } else { runModConf->tail->next = inst; runModConf->tail = inst; } *pinst = inst; finalize_it: RETiRet; } /** * @brief Create a CZMQ listener socket from the given configuration. * * The function initializes the socket, applies optional CURVE * authentication, subscribes to topics and attaches the socket to the * configured endpoints. The resulting listener structure is stored in * the global list used by the receiver loop. * * @param iconf configuration describing one listener * @retval RS_RET_OK on success * @retval RS_RET_ERR if socket setup fails */ static rsRetVal addListener(instanceConf_t *iconf) { DEFiRet; DBGPRINTF("imczmq: addListener called..\n"); struct listener_t *pData = NULL; CHKmalloc(pData = (struct listener_t *)malloc(sizeof(struct listener_t))); pData->ruleset = iconf->pBindRuleset; pData->sock = zsock_new(iconf->sockType); if (!pData->sock) { LogError(0, RS_RET_NO_ERRCODE, "imczmq: new socket failed for endpoints: %s", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_NO_ERRCODE); } DBGPRINTF("imczmq: created socket of type %d..\n", iconf->sockType); if (runModConf->authType) { if (!strcmp(runModConf->authType, "CURVESERVER")) { DBGPRINTF("imczmq: we are a CURVESERVER\n"); zcert_t *serverCert = zcert_load(runModConf->serverCertPath); if (!serverCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->serverCertPath); ABORT_FINALIZE(RS_RET_ERR); } zsock_set_zap_domain(pData->sock, "global"); zsock_set_curve_server(pData->sock, 1); zcert_apply(serverCert, pData->sock); zcert_destroy(&serverCert); } else if (!strcmp(runModConf->authType, "CURVECLIENT")) { DBGPRINTF("imczmq: we are a CURVECLIENT\n"); zcert_t *serverCert = zcert_load(runModConf->serverCertPath); if (!serverCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->serverCertPath); ABORT_FINALIZE(RS_RET_ERR); } const char *server_key = zcert_public_txt(serverCert); zcert_destroy(&serverCert); zsock_set_curve_serverkey(pData->sock, server_key); zcert_t *clientCert = zcert_load(runModConf->clientCertPath); if (!clientCert) { LogError(0, NO_ERRCODE, "could not load cert %s", runModConf->clientCertPath); ABORT_FINALIZE(RS_RET_ERR); } zcert_apply(clientCert, pData->sock); zcert_destroy(&clientCert); } } switch (iconf->sockType) { case ZMQ_SUB: /* ZMQ_DISH socket type is available and stable in all czmq versions that * define it. The previous version restriction (< 4.2.0) was incorrect and * has been removed. */ #if defined(ZMQ_DISH) case ZMQ_DISH: #endif iconf->serverish = false; break; case ZMQ_PULL: #if defined(ZMQ_GATHER) case ZMQ_GATHER: #endif case ZMQ_ROUTER: #if defined(ZMQ_SERVER) case ZMQ_SERVER: #endif iconf->serverish = true; break; default: break; } if (iconf->topics) { const char *topic_cursor = iconf->topics; // A zero-length topic means subscribe to everything if (!*topic_cursor && iconf->sockType == ZMQ_SUB) { DBGPRINTF("imczmq: subscribing to all topics\n"); zsock_set_subscribe(pData->sock, ""); } char topic[IMCZMQ_MAX_TOPIC_LEN + 1]; while (*topic_cursor) { const char *delimiter = strchr(topic_cursor, ','); const size_t topic_len = (delimiter == NULL) ? strlen(topic_cursor) : (size_t)(delimiter - topic_cursor); if (!delimiter) { delimiter = topic_cursor + topic_len; } memcpy(topic, topic_cursor, topic_len); topic[topic_len] = 0; DBGPRINTF("imczmq: subscribing to %s\n", topic); if (iconf->sockType == ZMQ_SUB) { zsock_set_subscribe(pData->sock, topic); } /* ZMQ_DISH socket type support - available in all czmq versions that define it */ #if defined(ZMQ_DISH) else if (iconf->sockType == ZMQ_DISH) { int rc = zsock_join(pData->sock, topic); if (rc != 0) { LogError(0, NO_ERRCODE, "could not join group %s", topic); ABORT_FINALIZE(RS_RET_ERR); } } #endif if (*delimiter == 0) { break; } topic_cursor = delimiter + 1; } } int rc = zsock_attach(pData->sock, (const char *)iconf->sockEndpoints, iconf->serverish); if (rc == -1) { LogError(0, NO_ERRCODE, "zsock_attach to %s failed", iconf->sockEndpoints); ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("imczmq: attached socket to %s\n", iconf->sockEndpoints); rc = zlist_append(listenerList, (void *)pData); if (rc != 0) { LogError(0, NO_ERRCODE, "could not append listener"); ABORT_FINALIZE(RS_RET_ERR); } finalize_it: if (iRet != RS_RET_OK) { free(pData); } RETiRet; } /** * @brief Receive messages from all configured CZMQ listeners. * * Builds a poller for the active sockets, waits for incoming frames and * converts them into rsyslog messages which are then processed by the * listener's ruleset. Authentication actors are started when requested * and resources are cleaned up on termination. * * @retval RS_RET_OK on graceful shutdown * @retval RS_RET_ERR on initialization or runtime failure */ static rsRetVal rcvData(void) { DEFiRet; if (!listenerList) { listenerList = zlist_new(); if (!listenerList) { LogError(0, NO_ERRCODE, "could not allocate list"); ABORT_FINALIZE(RS_RET_ERR); } } zactor_t *authActor = NULL; if (runModConf->authenticator == 1) { authActor = zactor_new(zauth, NULL); zstr_sendx(authActor, "CURVE", runModConf->clientCertPath, NULL); zsock_wait(authActor); } instanceConf_t *inst; for (inst = runModConf->root; inst != NULL; inst = inst->next) { CHKiRet(addListener(inst)); } zpoller_t *poller = zpoller_new(NULL); if (!poller) { LogError(0, NO_ERRCODE, "could not create poller"); ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("imczmq: created poller\n"); struct listener_t *pData; pData = zlist_first(listenerList); if (!pData) { LogError(0, NO_ERRCODE, "imczmq: no listeners were " "started, input not activated.\n"); ABORT_FINALIZE(RS_RET_NO_RUN); } while (pData) { int rc = zpoller_add(poller, pData->sock); if (rc != 0) { LogError(0, NO_ERRCODE, "imczmq: could not add " "socket to poller, input not activated.\n"); ABORT_FINALIZE(RS_RET_NO_RUN); } pData = zlist_next(listenerList); } zsock_t *which = (zsock_t *)zpoller_wait(poller, -1); while (which) { if (zpoller_terminated(poller)) { break; } pData = zlist_first(listenerList); while (pData->sock != which) { pData = zlist_next(listenerList); } if (which == pData->sock) { DBGPRINTF("imczmq: found matching socket\n"); } zframe_t *frame = zframe_recv(which); char *buf = NULL; if (frame != NULL) buf = zframe_strdup(frame); zframe_destroy(&frame); if (buf == NULL) { DBGPRINTF("imczmq: null buffer\n"); continue; } smsg_t *pMsg; if (msgConstruct(&pMsg) == RS_RET_OK) { MsgSetRawMsg(pMsg, buf, strlen(buf)); MsgSetInputName(pMsg, s_namep); MsgSetHOSTNAME(pMsg, glbl.GetLocalHostName(), ustrlen(glbl.GetLocalHostName())); MsgSetRcvFrom(pMsg, glbl.GetLocalHostNameProp()); MsgSetRcvFromIP(pMsg, glbl.GetLocalHostIP()); MsgSetMSGoffs(pMsg, 0); MsgSetFlowControlType(pMsg, eFLOWCTL_NO_DELAY); MsgSetRuleset(pMsg, pData->ruleset); pMsg->msgFlags = NEEDS_PARSING | PARSE_HOSTNAME; submitMsg2(pMsg); } free(buf); which = (zsock_t *)zpoller_wait(poller, -1); } finalize_it: zpoller_destroy(&poller); pData = zlist_first(listenerList); while (pData) { zsock_destroy(&pData->sock); free(pData->ruleset); pData = zlist_next(listenerList); } zlist_destroy(&listenerList); zactor_destroy(&authActor); RETiRet; } BEGINrunInput CODESTARTrunInput; iRet = rcvData(); ENDrunInput BEGINwillRun CODESTARTwillRun; CHKiRet(prop.Construct(&s_namep)); CHKiRet(prop.SetString(s_namep, UCHAR_CONSTANT("imczmq"), sizeof("imczmq") - 1)); CHKiRet(prop.ConstructFinalize(s_namep)); finalize_it: ENDwillRun BEGINafterRun CODESTARTafterRun; if (s_namep != NULL) { prop.Destruct(&s_namep); } ENDafterRun BEGINmodExit CODESTARTmodExit; objRelease(glbl, CORE_COMPONENT); objRelease(prop, CORE_COMPONENT); objRelease(ruleset, CORE_COMPONENT); ENDmodExit BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURENonCancelInputTermination) { iRet = RS_RET_OK; } ENDisCompatibleWithFeature BEGINbeginCnfLoad CODESTARTbeginCnfLoad; runModConf = pModConf; runModConf->pConf = pConf; runModConf->authenticator = 0; runModConf->authType = NULL; runModConf->serverCertPath = NULL; runModConf->clientCertPath = NULL; ENDbeginCnfLoad BEGINsetModCnf struct cnfparamvals *pvals = NULL; int i; CODESTARTsetModCnf; pvals = nvlstGetParams(lst, &modpblk, NULL); if (NULL == pvals) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imczmq: error processing module " "config parameters ['module(...)']"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } for (i = 0; i < modpblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } if (!strcmp(modpblk.descr[i].name, "authenticator")) { runModConf->authenticator = (int)pvals[i].val.d.n; } else if (!strcmp(modpblk.descr[i].name, "authtype")) { CHKmalloc(runModConf->authType = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "servercertpath")) { CHKmalloc(runModConf->serverCertPath = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(modpblk.descr[i].name, "clientcertpath")) { CHKmalloc(runModConf->clientCertPath = es_str2cstr(pvals[i].val.d.estr, NULL)); } else { LogError(0, RS_RET_INVALID_PARAMS, "imczmq: config error, unknown " "param %s in setModCnf\n", modpblk.descr[i].name); } } DBGPRINTF("imczmq: authenticator set to %d\n", runModConf->authenticator); DBGPRINTF("imczmq: authType set to %s\n", runModConf->authType); DBGPRINTF("imczmq: serverCertPath set to %s\n", runModConf->serverCertPath); DBGPRINTF("imczmq: clientCertPath set to %s\n", runModConf->clientCertPath); finalize_it: if (pvals != NULL) { cnfparamvalsDestruct(pvals, &modpblk); } ENDsetModCnf BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad static inline void std_checkRuleset_genErrMsg(__attribute__((unused)) modConfData_t *modConf, instanceConf_t *inst) { LogError(0, NO_ERRCODE, "imczmq: ruleset '%s' for socket %s not found - " "using default ruleset instead", inst->pszBindRuleset, inst->sockEndpoints); } BEGINcheckCnf instanceConf_t *inst; CODESTARTcheckCnf; for (inst = pModConf->root; inst != NULL; inst = inst->next) { std_checkRuleset(pModConf, inst); } ENDcheckCnf BEGINactivateCnfPrePrivDrop CODESTARTactivateCnfPrePrivDrop; runModConf = pModConf; putenv((char *)"ZSYS_SIGHANDLER=false"); ENDactivateCnfPrePrivDrop BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf instanceConf_t *inst, *inst_r; CODESTARTfreeCnf; free(pModConf->authType); free(pModConf->serverCertPath); free(pModConf->clientCertPath); for (inst = pModConf->root; inst != NULL;) { free(inst->pszBindRuleset); free(inst->sockEndpoints); free(inst->topics); inst_r = inst; inst = inst->next; free(inst_r); } ENDfreeCnf BEGINnewInpInst struct cnfparamvals *pvals; instanceConf_t *inst; int i; CODESTARTnewInpInst; DBGPRINTF("newInpInst (imczmq)\n"); pvals = nvlstGetParams(lst, &inppblk, NULL); if (NULL == pvals) { LogError(0, RS_RET_MISSING_CNFPARAMS, "imczmq: required parameters are missing\n"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { DBGPRINTF("imczmq: input param blk:\n"); cnfparamsPrint(&inppblk, pvals); } CHKiRet(createInstance(&inst)); for (i = 0; i < inppblk.nParams; ++i) { if (!pvals[i].bUsed) { continue; } if (!strcmp(inppblk.descr[i].name, "ruleset")) { CHKmalloc(inst->pszBindRuleset = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "endpoints")) { CHKmalloc(inst->sockEndpoints = es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(inppblk.descr[i].name, "topics")) { CHKmalloc(inst->topics = es_str2cstr(pvals[i].val.d.estr, NULL)); CHKiRet(validateTopics(inst->topics)); } else if (!strcmp(inppblk.descr[i].name, "socktype")) { char *stringType; CHKmalloc(stringType = es_str2cstr(pvals[i].val.d.estr, NULL)); if (NULL == stringType) { LogError(0, RS_RET_CONFIG_ERROR, "imczmq: out of memory error copying sockType param"); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } if (!strcmp("PULL", stringType)) { inst->sockType = ZMQ_PULL; } #if defined(ZMQ_GATHER) else if (!strcmp("GATHER", stringType)) { inst->sockType = ZMQ_GATHER; } #endif else if (!strcmp("SUB", stringType)) { inst->sockType = ZMQ_SUB; } /* ZMQ_DISH socket type support - available in all czmq versions that define it */ #if defined(ZMQ_DISH) else if (!strcmp("DISH", stringType)) { inst->sockType = ZMQ_DISH; } #endif else if (!strcmp("ROUTER", stringType)) { inst->sockType = ZMQ_ROUTER; } #if defined(ZMQ_SERVER) else if (!strcmp("SERVER", stringType)) { inst->sockType = ZMQ_SERVER; } #endif else { /* Config parsing should never accept unknown socktypes; fail closed if it does. */ LogError(0, RS_RET_CONFIG_ERROR, "imczmq: invalid socktype '%s'", stringType); free(stringType); ABORT_FINALIZE(RS_RET_CONFIG_ERROR); } free(stringType); } else { LogError(0, NO_ERRCODE, "imczmq: program error, non-handled " "param '%s'\n", inppblk.descr[i].name); } } finalize_it: CODE_STD_FINALIZERnewInpInst cnfparamvalsDestruct(pvals, &inppblk); ENDnewInpInst BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_IMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_CONF2_PREPRIVDROP_QUERIES; CODEqueryEtryPt_STD_CONF2_IMOD_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(prop, CORE_COMPONENT)); CHKiRet(objUse(ruleset, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/imczmq/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160017546 xustar0030 mtime=1787067504.515320592 30 atime=1787067579.335716104 30 ctime=1787067797.906790499 rsyslog-8.2608.0/contrib/imczmq/Makefile.in0000664000175000017500000006566515241076160017234 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/imczmq ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = imczmq_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_imczmq_la_OBJECTS = imczmq_la-imczmq.lo imczmq_la_OBJECTS = $(am_imczmq_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 = imczmq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(imczmq_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/imczmq_la-imczmq.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(imczmq_la_SOURCES) DIST_SOURCES = $(imczmq_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = imczmq.la imczmq_la_SOURCES = imczmq.c imczmq_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CZMQ_CFLAGS) imczmq_la_LDFLAGS = -module -avoid-version imczmq_la_LIBADD = $(CZMQ_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/imczmq/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/imczmq/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } imczmq.la: $(imczmq_la_OBJECTS) $(imczmq_la_DEPENDENCIES) $(EXTRA_imczmq_la_DEPENDENCIES) $(AM_V_CCLD)$(imczmq_la_LINK) -rpath $(pkglibdir) $(imczmq_la_OBJECTS) $(imczmq_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imczmq_la-imczmq.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< imczmq_la-imczmq.lo: imczmq.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT imczmq_la-imczmq.lo -MD -MP -MF $(DEPDIR)/imczmq_la-imczmq.Tpo -c -o imczmq_la-imczmq.lo `test -f 'imczmq.c' || echo '$(srcdir)/'`imczmq.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/imczmq_la-imczmq.Tpo $(DEPDIR)/imczmq_la-imczmq.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='imczmq.c' object='imczmq_la-imczmq.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(imczmq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o imczmq_la-imczmq.lo `test -f 'imczmq.c' || echo '$(srcdir)/'`imczmq.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/imczmq_la-imczmq.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/imczmq_la-imczmq.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omhttpfs0000644000000000000000000000013215241076632015774 xustar0030 mtime=1787067802.373873734 30 atime=1787067808.786993238 30 ctime=1787067802.373873734 rsyslog-8.2608.0/contrib/omhttpfs/0000775000175000017500000000000015241076632015515 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omhttpfs/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020101 xustar0030 mtime=1752569012.330244093 30 atime=1787067434.315010802 30 ctime=1787067802.366873603 rsyslog-8.2608.0/contrib/omhttpfs/Makefile.am0000666000175000017500000000042515035412264017550 0ustar00rgerrgerpkglib_LTLIBRARIES = omhttpfs.la omhttpfs_la_SOURCES = omhttpfs.c omhttpfs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBFASTJSON_CFLAGS) omhttpfs_la_LDFLAGS = -module -avoid-version omhttpfs_la_LIBADD = $(CURL_LIBS) $(LIBFASTJSON_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/omhttpfs/PaxHeaders/README.md0000644000000000000000000000013215035412264017324 xustar0030 mtime=1752569012.330244093 30 atime=1782715518.792788908 30 ctime=1787067802.371873697 rsyslog-8.2608.0/contrib/omhttpfs/README.md0000666000175000017500000000302015035412264016765 0ustar00rgerrgerOmHTTPFS === Author: sskaje ([sskaje@gmail.com](mailto:sskaje@gmail.com), [http://sskaje.me/](http://sskaje.me/)) OmHTTPFS is an Rsyslog plugin writing data to HDS via *Hadoop HDFS over HTTP*. ## Hadoop HDFS over HTTP Official site: [Hadoop HDFS over HTTP](http://hadoop.apache.org/docs/current/hadoop-hdfs-httpfs/index.html) HTTPFS is not well documented. I tried to read its source and write an [intro with examples](http://sskaje.me/2014/08/doc-for-httpfs/), until I found [Administering the file system by using HttpFS REST APIs](http://www-01.ibm.com/support/knowledgecenter/SSPT3X_2.1.2/com.ibm.swg.im.infosphere.biginsights.admin.doc/doc/admin_fileupload_rest_apis.html) by IBM. ## OmHDFS for Rsyslog Rsyslog provides a plugin named omHDFS which requires lots of work compiling and configuring, and it's not that usable. Here is what I tried before writing this omhttpfs: [Build omhdfs for Rsyslog](http://sskaje.me/2014/08/build-omhdfs-rsyslog/). ## Rsyslog config Legacy config **NOT** supported. Example: ``` module(load="omhttpfs") template(name="hdfs_tmp_file" type="string" string="/tmp/%$YEAR%/test.log") template(name="hdfs_tmp_filecontent" type="string" string="%$YEAR%-%$MONTH%-%$DAY% %MSG% ==\n") local4.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on") local5.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on" template="hdfs_tmp_filecontent") ``` Tested with CDH 5.2.0 + Rsyslog 8.6.0 on CentOS 7 \# EOF rsyslog-8.2608.0/contrib/omhttpfs/PaxHeaders/omhttpfs.c0000644000000000000000000000013115216464435020064 xustar0030 mtime=1782212893.964265181 29 atime=1787067643.55391351 30 ctime=1787067802.374873753 rsyslog-8.2608.0/contrib/omhttpfs/omhttpfs.c0000664000175000017500000006005115216464435017533 0ustar00rgerrger/* omhttpfs.c * Send all output to HDFS via httpfs * * Author: sskaje (sskaje@gmail.com, http://sskaje.me/) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "datetime.h" #include "statsobj.h" #include "unicode-helper.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omhttpfs") /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) /* local definitions */ #define OMHTTPFS_VERSION "1.0" #define OMHTTPFS_DEFAULT_PORT 14000 #define OMHTTPFS_DEFAULT_USER "hdfs" #define OMHTTPFS_DEFAULT_HOST "127.0.0.1" #define HTTPFS_URL_PREFIX_V1 "/webhdfs/v1" #define HTTPFS_URL_PREFIX_V1_SSL "/swebhdfs/v1" #define HTTPFS_CONTENT_TYPE "Content-Type: application/octet-stream" #define HTTPFS_USER_AGENT "omhttpfs by sskaje/" OMHTTPFS_VERSION #define HTTPFS_CONTENT_TYPE_JSON "application/json" #define HTTPFS_JSON_BOOLEAN_TRUE "{\"boolean\":true}" #define HTTPFS_FILEALREADYEXISTSEXCEPTION "FileAlreadyExistsException" #define HTTPFS_URL_BUFFER_LENGTH 2048 /* Examples: module(load="omhttpfs") template(name="hdfs_tmp_file" type="string" string="/tmp/%$YEAR%/test.log") template(name="hdfs_tmp_filecontent" type="string" string="%$YEAR%-%$MONTH%-%$DAY% %MSG% ==\n") local4.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on") local5.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on" template="hdfs_tmp_filecontent") */ #define DPP(x) DBGPRINTF("OMHTTPFS: %s:%d %s(): %s\n", __FILE__, __LINE__, __FUNCTION__, x) /** * Exception object * */ typedef struct _HTTPFS_JSON_REMOTE_EXCEPTION { char message[1024]; char exception[256]; char class[256]; } httpfs_json_remote_exception; typedef struct _instanceData { sbool https; uchar* host; uchar* ip; int port; uchar* user; int timeout; uchar* file; sbool isDynFile; uchar* tplName; } instanceData; typedef struct wrkrInstanceData { instanceData* pData; CURL* curl; uchar* file; int replyLen; char* reply; } wrkrInstanceData_t; /* tables for interfacing with the v6 config system */ /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"host", eCmdHdlrGetWord, 0}, {"port", eCmdHdlrInt, 0}, {"user", eCmdHdlrGetWord, 0}, {"https", eCmdHdlrBinary, 0}, {"file", eCmdHdlrGetWord, CNFPARAM_REQUIRED}, {"isdynfile", eCmdHdlrBinary, 0}, {"template", eCmdHdlrGetWord, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; /** * curl init * * @param wrkrInstanceData_t *pWrkrData * @param instanceData *pData * @return rsRetVal */ static rsRetVal httpfs_init_curl(wrkrInstanceData_t* pWrkrData, instanceData* pData) { CURL* curl = NULL; curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); if (pData->https) { DBGPRINTF("%s(): Enable HTTPS\n", __FUNCTION__); /* for ssl */ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); } } else { /* LOG */ LogError(0, RS_RET_OBJ_CREATION_FAILED, "omhttpfs: failed to init cURL\n"); return RS_RET_OBJ_CREATION_FAILED; } curl_easy_setopt(curl, CURLOPT_USERAGENT, HTTPFS_USER_AGENT); pWrkrData->curl = curl; return RS_RET_OK; } /** * Build HTTPFS URL * * @param wrkrInstanceData_t *pWrkrData * @param char* op * @param es_str_t** url_buf * @return rsRetVal */ static rsRetVal httpfs_build_url(wrkrInstanceData_t* pWrkrData, const char* op, es_str_t** url_buf) { *url_buf = es_newStr(HTTPFS_URL_BUFFER_LENGTH); if (pWrkrData->pData->https) { es_addBuf(url_buf, "https://", sizeof("https://") - 1); } else { es_addBuf(url_buf, "http://", sizeof("http://") - 1); } /* host */ es_addBuf(url_buf, (char*)pWrkrData->pData->host, strlen((char*)pWrkrData->pData->host)); /* port */ es_addChar(url_buf, ':'); char portBuf[6]; snprintf(portBuf, sizeof(portBuf), "%d", pWrkrData->pData->port); es_addBuf(url_buf, portBuf, strlen(portBuf)); /* prefix */ es_addBuf(url_buf, HTTPFS_URL_PREFIX_V1, sizeof(HTTPFS_URL_PREFIX_V1) - 1); /* path */ if (pWrkrData->file[0] != '/') { es_addChar(url_buf, '/'); } es_addBuf(url_buf, (char*)pWrkrData->file, strlen((char*)pWrkrData->file)); /* queries */ /* user */ es_addBuf(url_buf, "?user.name=", sizeof("?user.name=") - 1); es_addBuf(url_buf, (char*)pWrkrData->pData->user, strlen((char*)pWrkrData->pData->user)); /* extra parameters */ es_addBuf(url_buf, op, strlen(op)); return RS_RET_OK; } /** * curl set URL * * @param wrkrInstanceData_t *pWrkrData * @param char* op * @return void */ static void httpfs_set_url(wrkrInstanceData_t* pWrkrData, const char* op) { es_str_t* url; char* url_cstr; httpfs_build_url(pWrkrData, op, &url); url_cstr = es_str2cstr(url, NULL); curl_easy_setopt(pWrkrData->curl, CURLOPT_URL, url_cstr); free(url_cstr); } /** * Set http method to PUT * * @param CURL* curl * @return void */ static void httpfs_curl_set_put(CURL* curl) { curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl, CURLOPT_POST, 0L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); } /** * Set http method to POST * * @param CURL* curl * @return void */ static void httpfs_curl_set_post(CURL* curl) { curl_easy_setopt(curl, CURLOPT_HTTPGET, 0L); curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L); curl_easy_setopt(curl, CURLOPT_UPLOAD, 0L); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); } /** * Build curl slist * * @param struct curl_slist* headers * @param int hdr_count * @param ... * @return struct curl_slist* */ static struct curl_slist* httpfs_curl_add_header(struct curl_slist* headers, int hdr_count, ...) { const char* hdr; va_list ar; va_start(ar, hdr_count); for (; hdr_count > 0; hdr_count--) { hdr = va_arg(ar, const char*); if (hdr != NULL && hdr[0] != 0) { /* non-empty string */ headers = curl_slist_append(headers, hdr); } else { break; } } va_end(ar); headers = curl_slist_append(headers, "Expect:"); headers = curl_slist_append(headers, "Transfer-Encoding:"); return headers; } /** * Callback function for CURLOPT_WRITEFUNCTION * * @param void* contents * @param size_t size * @param size_t nmemb * @param void *userp * @return size_t */ static size_t httpfs_curl_result_callback(void* contents, size_t size, size_t nmemb, void* userp) { size_t realsize; char* newreply = NULL; wrkrInstanceData_t* mem = (wrkrInstanceData_t*)userp; if (nmemb != 0 && size > SIZE_MAX / nmemb) { dbgprintf("response buffer size overflow\n"); return 0; } realsize = size * nmemb; if (mem->replyLen < 0) { dbgprintf("response buffer size overflow\n"); return 0; } const size_t replyLen = (size_t)mem->replyLen; if (replyLen == SIZE_MAX || realsize > SIZE_MAX - replyLen - 1 || realsize > (size_t)INT_MAX - replyLen) { dbgprintf("response buffer size overflow\n"); return 0; } newreply = realloc(mem->reply, replyLen + realsize + 1); if (newreply == NULL) { /* out of memory! */ dbgprintf("not enough memory (realloc returned NULL)\n"); if (mem->reply != NULL) free(mem->reply); mem->reply = NULL; mem->replyLen = 0; return 0; } mem->reply = newreply; memcpy(&(mem->reply[replyLen]), contents, realsize); mem->replyLen = (int)(replyLen + realsize); mem->reply[mem->replyLen] = 0; return realsize; } /** * Variables declaration * used in httpfs related operation */ #define HTTPFS_CURL_VARS_INIT \ struct curl_slist* headers = NULL; \ long response_code; \ CURLcode res; \ char* content_type; /** * Resource release * used in httpfs related operation */ #define HTTPFS_CURL_VARS_RELEASE curl_slist_free_all(headers); /** * Curl execution * used in httpfs related operation */ #define HTTPFS_CURL_EXEC \ pWrkrData->reply = NULL; \ pWrkrData->replyLen = 0; \ curl_easy_setopt(pWrkrData->curl, CURLOPT_WRITEDATA, pWrkrData); \ curl_easy_setopt(pWrkrData->curl, CURLOPT_WRITEFUNCTION, httpfs_curl_result_callback); \ res = curl_easy_perform(pWrkrData->curl); \ if (res == CURLE_OK) { \ curl_easy_getinfo(pWrkrData->curl, CURLINFO_CONTENT_TYPE, &content_type); \ if (strncmp(content_type, HTTPFS_CONTENT_TYPE_JSON, strlen(HTTPFS_CONTENT_TYPE_JSON))) { \ } \ curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code); \ if (pWrkrData->reply != NULL) { \ pWrkrData->reply[pWrkrData->replyLen] = '\0'; \ } \ } else { \ LogError(0, RS_RET_ERR, "CURL request fail, code=%d, error string=%s\n", res, curl_easy_strerror(res)); \ return -1; \ } /** * Parse remote exception json string * * @param char* buf * @param int length * @param httpfs_json_remote_exception* jre * @return rsRetVal */ static rsRetVal httpfs_parse_exception(char* buf, int length, httpfs_json_remote_exception* jre) { DEFiRet; if (!length) { return RS_RET_JSON_PARSE_ERR; } struct json_tokener* jt = json_tokener_new(); json_tokener_reset(jt); struct json_object* json; json = json_tokener_parse_ex(jt, buf, length); if (!json_object_is_type(json, json_type_object)) { ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } if (!json_object_object_get_ex(json, "RemoteException", &json)) { ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } struct json_object* jobj; memset(jre, 0, sizeof(*jre)); const char* str; json_object_object_get_ex(json, "javaClassName", &jobj); str = json_object_get_string(jobj); rs_cstr_copy(jre->class, str, sizeof(jre->class)); json_object_object_get_ex(json, "exception", &jobj); str = json_object_get_string(jobj); rs_cstr_copy(jre->exception, str, sizeof(jre->exception)); json_object_object_get_ex(json, "message", &jobj); str = json_object_get_string(jobj); rs_cstr_copy(jre->message, str, sizeof(jre->message)); finalize_it: if (jt != NULL) json_tokener_free(jt); if (json != NULL) json_object_put(json); RETiRet; } /** * Create a file * op=CREATE * overwrite is turned off * * @param wrkrInstanceData_t *pWrkrData * @param char* buf * @return rsRetVal */ static rsRetVal httpfs_create_file(wrkrInstanceData_t* pWrkrData, uchar* buf) { /* httpfs.create automatically create folders, no mkdirs needed. */ /* curl -b /tmp/c.tmp -c /tmp/c.tmp -d 'aaaaabbbbb' -i -H 'Content-Type: application/octet-stream' -X PUT \ 'http://172.16.3.20:14000/webhdfs/v1/tmp/a/b?user.name=hdfs&op=create&data=true' */ HTTPFS_CURL_VARS_INIT DBGPRINTF("%s(): file=%s\n", __FUNCTION__, pWrkrData->file); httpfs_curl_set_put(pWrkrData->curl); /* overwrite - if a file with this name already exists, then if true, the file will be overwritten, and if false an error will be thrown. bufferSize - the size of the buffer to be used. replication - required block replication for the file. */ httpfs_set_url(pWrkrData, "&op=create&overwrite=false&data=true"); curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDS, (char*)buf); curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDSIZE, (long)strlen((char*)buf)); DBGPRINTF("%s(): msg=%s\n", __FUNCTION__, buf); headers = httpfs_curl_add_header(headers, 1, HTTPFS_CONTENT_TYPE); curl_easy_setopt(pWrkrData->curl, CURLOPT_HTTPHEADER, headers); HTTPFS_CURL_EXEC int success = 0; if (response_code == 201) { success = 1; } HTTPFS_CURL_VARS_RELEASE if (success) { return RS_RET_OK; } else { return RS_RET_ERR_HDFS_OPEN; } } /** * Append to file * op=APPEND * * @param wrkrInstanceData_t *pWrkrData * @param char* buf * @return rsRetVal */ static rsRetVal httpfs_append_file(wrkrInstanceData_t* pWrkrData, uchar* buf) { /* curl -b /tmp/c.tmp -c /tmp/c.tmp -d 'aaaaabbbbb' -i -H 'Content-Type: application/octet-stream' \ 'http://172.16.3.20:14000/webhdfs/v1/tmp/a/b?user.name=hdfs&op=append&data=true' */ HTTPFS_CURL_VARS_INIT DBGPRINTF("%s(): file=%s\n", __FUNCTION__, pWrkrData->file); httpfs_curl_set_post(pWrkrData->curl); httpfs_set_url(pWrkrData, "&op=append&data=true"); curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDS, (char*)buf); curl_easy_setopt(pWrkrData->curl, CURLOPT_POSTFIELDSIZE, (long)strlen((char*)buf)); headers = httpfs_curl_add_header(headers, 1, HTTPFS_CONTENT_TYPE); curl_easy_setopt(pWrkrData->curl, CURLOPT_HTTPHEADER, headers); DBGPRINTF("%s(): msg=%s\n", __FUNCTION__, buf); HTTPFS_CURL_EXEC int success = 0; if (response_code == 200) { success = 1; } else if (response_code == 404) { /* TODO: 404 ? */ } HTTPFS_CURL_VARS_RELEASE if (success) { return RS_RET_OK; } else { return RS_RET_ERR_HDFS_WRITE; } } /** * httpfs log * * @param wrkrInstanceData_t *pWrkrData * @param uchar* buf * @return rsRetVal */ static rsRetVal httpfs_log(wrkrInstanceData_t* pWrkrData, uchar* buf) { /** append ? 200/end : (404 || ?) create & ~overwrite ? 201/200/end : append ? 200/end : error ? */ DEFiRet; long response_code; httpfs_json_remote_exception jre; iRet = httpfs_append_file(pWrkrData, buf); if (iRet == RS_RET_OK) { DBGPRINTF("omhttpfs: Append success: %s\n", pWrkrData->file); return RS_RET_OK; } curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code != 404) { LogError(0, RS_RET_ERR_HDFS_WRITE, "omhttpfs: Append fail HTTP %ld: %s, reply: %s", response_code, pWrkrData->file, pWrkrData->reply ? pWrkrData->reply : "NULL"); return RS_RET_ERR_HDFS_WRITE; } iRet = httpfs_create_file(pWrkrData, buf); if (iRet == RS_RET_OK) { DBGPRINTF("omhttpfs: Create file success: %s\n", pWrkrData->file); return RS_RET_OK; } curl_easy_getinfo(pWrkrData->curl, CURLINFO_RESPONSE_CODE, &response_code); if (response_code == 201) { DBGPRINTF("omhttpfs: Create file success HTTP 201: %s\n", pWrkrData->file); return RS_RET_OK; } if (response_code == 500) { DBGPRINTF("omhttpfs: Create file failed HTTP %ld: %s\n", response_code, pWrkrData->file); httpfs_parse_exception(pWrkrData->reply, pWrkrData->replyLen, &jre); if (!strncmp(jre.exception, HTTPFS_FILEALREADYEXISTSEXCEPTION, strlen(HTTPFS_FILEALREADYEXISTSEXCEPTION))) { /* file exists, go to append */ DBGPRINTF("omhttpfs: File already exists, append again: %s\n", pWrkrData->file); iRet = httpfs_append_file(pWrkrData, buf); if (iRet == RS_RET_OK) { DBGPRINTF("omhttpfs: Re-Append success: %s\n", pWrkrData->file); return RS_RET_OK; } else { DBGPRINTF("omhttpfs: Re-Append failed: %s\n", pWrkrData->file); /* error exit */ } } else { DBGPRINTF("omhttpfs: Create file failed: %s %s\n", pWrkrData->file, pWrkrData->reply); } } else { DBGPRINTF("omhttpfs: Create file failed: %s %s\n", pWrkrData->file, pWrkrData->reply); } return RS_RET_ERR; } BEGINinitConfVars CODESTARTinitConfVars; ENDinitConfVars BEGINcreateInstance CODESTARTcreateInstance; DBGPRINTF("omhttpfs: createInstance\n"); ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; DBGPRINTF("omhttpfs: createWrkrInstance\n"); pWrkrData->curl = NULL; iRet = httpfs_init_curl(pWrkrData, pWrkrData->pData); DBGPRINTF("omhttpfs: createWrkrInstance,pData %p/%p, pWrkrData %p\n", pData, pWrkrData->pData, pWrkrData); ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; free(pData->file); free(pData->tplName); free(pData->host); free(pData->user); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; free(pWrkrData->file); if (pWrkrData->curl) { curl_easy_cleanup(pWrkrData->curl); pWrkrData->curl = NULL; } ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; DBGPRINTF("OmHTTPFS\n"); DBGPRINTF("Version: %s\n", OMHTTPFS_VERSION); DBGPRINTF("\tHost: %s\n", pData->host); DBGPRINTF("\tPort: %d\n", pData->port); DBGPRINTF("\tUser: %s\n", pData->user); DBGPRINTF("\tFile: %s\n", pData->file); ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; DBGPRINTF("omhttpfs: tryResume called\n"); /* TODO: test networking */ iRet = RS_RET_OK; ENDtryResume /** * Do Action */ BEGINdoAction CODESTARTdoAction; DBGPRINTF("omhttpfs: doAction\n"); /* dynamic file name */ if (pWrkrData->pData->isDynFile) { pWrkrData->file = ustrdup(ppString[1]); } else { pWrkrData->file = ustrdup(pWrkrData->pData->file); } /* ppString[0] -> log content */ iRet = httpfs_log(pWrkrData, ppString[0]); if (iRet != RS_RET_OK) { DBGPRINTF("omhttpfs: error writing httpfs, suspending\n"); iRet = RS_RET_SUSPENDED; } ENDdoAction /** * Set default parameters * * @param instanceData *pData * @return void */ static void setInstParamDefaults(instanceData* pData) { pData->host = (uchar*)strdup(OMHTTPFS_DEFAULT_HOST); pData->port = OMHTTPFS_DEFAULT_PORT; pData->user = (uchar*)strdup(OMHTTPFS_DEFAULT_USER); pData->https = 0; pData->file = NULL; pData->isDynFile = 0; pData->tplName = NULL; } BEGINnewActInst struct cnfparamvals* pvals; int i; uchar* tplToUse; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "host")) { CHKmalloc(pData->host = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "port")) { pData->port = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "user")) { CHKmalloc(pData->user = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "https")) { pData->https = pvals[i].val.d.n ? 1 : 0; } else if (!strcmp(actpblk.descr[i].name, "file")) { CHKmalloc(pData->file = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "isdynfile")) { pData->isDynFile = pvals[i].val.d.n ? 1 : 0; } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL)); } else { DBGPRINTF("omhttpfs: program error, non-handled param '%s'\n", actpblk.descr[i].name); } } if (pData->file == NULL) { /* Note: this is primarily to make clang static analyzer happy, as we * request via pblk that file is a mandatory parameter. However, this is * also a guard against something going really wrong... */ LogError(0, RS_RET_INTERNAL_ERROR, "omhttpfs: file is not set " "[this should not be possible]\n"); ABORT_FINALIZE(RS_RET_INTERNAL_ERROR); } if (pData->user == NULL || pData->user[0] == '\0') { pData->user = ustrdup((uchar*)OMHTTPFS_DEFAULT_USER); } if (pData->host == NULL || pData->host[0] == '\0') { pData->host = ustrdup((uchar*)OMHTTPFS_DEFAULT_HOST); } if (pData->isDynFile) { CODE_STD_STRING_REQUESTparseSelectorAct(2) CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->file), OMSR_NO_RQD_TPL_OPTS)); } else { CODE_STD_STRING_REQUESTparseSelectorAct(1) } tplToUse = ustrdup((pData->tplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pData->tplName); iRet = OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst NO_LEGACY_CONF_parseSelectorAct /** * Module Exit */ BEGINmodExit CODESTARTmodExit; /* */ curl_global_cleanup(); /* release what we no longer need */ objRelease(datetime, CORE_COMPONENT); objRelease(glbl, CORE_COMPONENT); ENDmodExit /** * Query Entry Point */ BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_CNFNAME_QUERIES; ENDqueryEtryPt /** * Module Init */ BEGINmodInit() CODESTARTmodInit; INITLegCnfVars; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr /* tell which objects we need */ CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); if (curl_global_init(CURL_GLOBAL_ALL) != 0) { LogError(0, RS_RET_OBJ_CREATION_FAILED, "CURL fail. -httpfs module init failed"); ABORT_FINALIZE(RS_RET_OBJ_CREATION_FAILED); } DBGPRINTF("omhttpfs version %s is initializing\n", OMHTTPFS_VERSION); ENDmodInit rsyslog-8.2608.0/contrib/omhttpfs/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161020112 xustar0029 mtime=1787067505.15633255 30 atime=1787067579.492719031 30 ctime=1787067802.369873659 rsyslog-8.2608.0/contrib/omhttpfs/Makefile.in0000664000175000017500000006615715241076161017576 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omhttpfs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omhttpfs_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_omhttpfs_la_OBJECTS = omhttpfs_la-omhttpfs.lo omhttpfs_la_OBJECTS = $(am_omhttpfs_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 = omhttpfs_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omhttpfs_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omhttpfs_la_SOURCES) DIST_SOURCES = $(omhttpfs_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ README.md DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omhttpfs.la omhttpfs_la_SOURCES = omhttpfs.c omhttpfs_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(CURL_CFLAGS) $(LIBFASTJSON_CFLAGS) omhttpfs_la_LDFLAGS = -module -avoid-version omhttpfs_la_LIBADD = $(CURL_LIBS) $(LIBFASTJSON_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omhttpfs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omhttpfs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omhttpfs.la: $(omhttpfs_la_OBJECTS) $(omhttpfs_la_DEPENDENCIES) $(EXTRA_omhttpfs_la_DEPENDENCIES) $(AM_V_CCLD)$(omhttpfs_la_LINK) -rpath $(pkglibdir) $(omhttpfs_la_OBJECTS) $(omhttpfs_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omhttpfs_la-omhttpfs.lo: omhttpfs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttpfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhttpfs_la-omhttpfs.lo -MD -MP -MF $(DEPDIR)/omhttpfs_la-omhttpfs.Tpo -c -o omhttpfs_la-omhttpfs.lo `test -f 'omhttpfs.c' || echo '$(srcdir)/'`omhttpfs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhttpfs_la-omhttpfs.Tpo $(DEPDIR)/omhttpfs_la-omhttpfs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhttpfs.c' object='omhttpfs_la-omhttpfs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhttpfs_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhttpfs_la-omhttpfs.lo `test -f 'omhttpfs.c' || echo '$(srcdir)/'`omhttpfs.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omhttpfs_la-omhttpfs.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/fmhash0000644000000000000000000000013215241076627015402 xustar0030 mtime=1787067799.602822104 30 atime=1787067808.787993257 30 ctime=1787067799.602822104 rsyslog-8.2608.0/contrib/fmhash/0000775000175000017500000000000015241076627015123 5ustar00rgerrgerrsyslog-8.2608.0/contrib/fmhash/PaxHeaders/fmhash.c0000644000000000000000000000013115216464435017070 xustar0030 mtime=1782212893.957265068 29 atime=1787067636.19577633 30 ctime=1787067799.602822104 rsyslog-8.2608.0/contrib/fmhash/fmhash.c0000664000175000017500000003056515216464435016546 0ustar00rgerrger/* * Copyright (c) 2018, Harshvardhan Shrivastava * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of the original author; nor the names of any contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 "config.h" #include #include #ifndef _AIX #include #endif #include #include #ifdef USE_HASH_XXHASH #include #endif #include "rsyslog.h" #include "parserif.h" #include "module-template.h" #include "rainerscript.h" MODULE_TYPE_FUNCTION MODULE_TYPE_NOKEEP; DEF_FMOD_STATIC_DATA; typedef uint64_t hash_t; typedef uint32_t seed_t; typedef struct hash_context_s hash_context_t; typedef hash_t (*hash_impl)(const void *, size_t, seed_t); typedef rsRetVal (*hash_wrapper_2)(struct svar *__restrict__ const, struct svar *__restrict__ const, hash_context_t *, hash_t *); typedef rsRetVal (*hash_wrapper_3)(struct svar *__restrict__ const, struct svar *__restrict__ const, struct svar *__restrict__ const, hash_context_t *, hash_t *); struct hash_context_s { hash_impl hashXX; hash_wrapper_2 hash_wrapper_1_2; hash_wrapper_3 hash_wrapper_2_3; }; #ifndef USE_HASH_XXHASH /* * Fowler–Noll–Vo hash 32 bit * http://www.isthe.com/chongo/src/fnv/hash_32.c */ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif static hash_t #if defined(__clang__) __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif fnv_32(const void *input, size_t len, seed_t seed) { unsigned char *bp = (unsigned char *)input; /* start of buffer */ /* * FNV-1 hash each octet in the buffer */ size_t i; for (i = 0; i < len; i++) { /* multiply by the 32 bit FNV magic prime mod 2^32 */ seed += (seed << 1) + (seed << 4) + (seed << 7) + (seed << 8) + (seed << 24); /* xor the bottom with the current octet */ seed ^= (seed_t)*bp++; } /* return our new hash value */ return seed; } /* * Modified Bernstein * http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif static hash_t #if defined(__clang__) __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif djb_hash(const void *input, size_t len, seed_t seed) { const char *p = input; hash_t hash = 5381; size_t i; for (i = 0; i < len; i++) { hash = 33 * hash ^ p[i]; } return hash + seed; } #endif /* ifndef USE_HASH_XXHASH */ /*Get 32 bit hash for input*/ static hash_t hash32(const void *input, size_t len, seed_t seed) { hash_t xhash = 0; #ifdef USE_HASH_XXHASH xhash = XXH32(input, len, seed); #else xhash = fnv_32(input, len, seed); #endif return xhash; } /*Get 64 bit hash for input*/ static hash_t hash64(const void *input, size_t len, seed_t seed) { hash_t xhash = 0; #ifdef USE_HASH_XXHASH xhash = XXH64(input, len, seed); #else xhash = djb_hash(input, len, seed); #endif return xhash; } static rsRetVal hash_wrapper2(struct svar *__restrict__ const sourceVal, struct svar *__restrict__ const seedVal, hash_context_t *hcontext, hash_t *xhash) { DEFiRet; int freeHashStr = 0, success = 0; char *hashStr = NULL; seed_t seed = 0; if (seedVal) { seed = var2Number(seedVal, &success); if (!success) { parser_warnmsg( "fmhash: hashXX(string, seed) didn't get a valid 'seed' limit" ", defaulting hash value to 0"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } } hashStr = (char *)var2CString(sourceVal, &freeHashStr); size_t len = strlen(hashStr); (*xhash) = hcontext->hashXX(hashStr, len, seed); DBGPRINTF("fmhash: hashXX generated hash %" PRIu64 " for string(%.*s)", (*xhash), (int)len, hashStr); finalize_it: if (freeHashStr) { free(hashStr); } RETiRet; } static rsRetVal hash_wrapper3(struct svar *__restrict__ const sourceVal, struct svar *__restrict__ const modVal, struct svar *__restrict__ const seedVal, hash_context_t *hcontext, hash_t *xhash) { DEFiRet; int success = 0; hash_t mod = var2Number(modVal, &success); if (!success) { parser_warnmsg( "fmhash: hashXXmod(string, mod)/hash64mod(string, mod, seed) didn't" " get a valid 'mod' limit, defaulting hash value to 0"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (mod == 0) { parser_warnmsg( "fmhash: hashXXmod(string, mod)/hash64mod(string, mod, seed) invalid" ", 'mod' is zero, , defaulting hash value to 0"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } CHKiRet((hcontext->hash_wrapper_1_2(sourceVal, seedVal, hcontext, xhash))); if (mod != 0) { (*xhash) = (*xhash) % mod; } DBGPRINTF("fmhash: hashXXmod generated hash-mod %" PRIu64 ".", (*xhash)); finalize_it: RETiRet; } static void init_hash32_context(hash_context_t *hash32_context) { hash32_context->hashXX = hash32; hash32_context->hash_wrapper_1_2 = hash_wrapper2; hash32_context->hash_wrapper_2_3 = hash_wrapper3; }; static void init_hash64_context(hash_context_t *hash64_context) { hash64_context->hashXX = hash64; hash64_context->hash_wrapper_1_2 = hash_wrapper2; hash64_context->hash_wrapper_2_3 = hash_wrapper3; }; static void ATTR_NONNULL() fmHashXX(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { DEFiRet; struct svar hashStrVal; struct svar seedVal; hash_context_t *hcontext = NULL; hash_t xhash = 0; cnfexprEval(func->expr[0], &hashStrVal, usrptr, pWti); if (func->nParams == 2) cnfexprEval(func->expr[1], &seedVal, usrptr, pWti); ret->d.n = 0; ret->datatype = 'N'; hcontext = (hash_context_t *)func->funcdata; CHKiRet((hcontext->hash_wrapper_1_2(&hashStrVal, (func->nParams == 2 ? &seedVal : NULL), hcontext, &xhash))); ret->d.n = xhash; finalize_it: varFreeMembers(&hashStrVal); if (func->nParams == 2) varFreeMembers(&seedVal); } static void ATTR_NONNULL() fmHashXXmod(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { DEFiRet; struct svar hashStrVal; struct svar modVal; struct svar seedVal; hash_context_t *hcontext = NULL; hash_t xhash = 0; cnfexprEval(func->expr[0], &hashStrVal, usrptr, pWti); cnfexprEval(func->expr[1], &modVal, usrptr, pWti); if (func->nParams == 3) cnfexprEval(func->expr[2], &seedVal, usrptr, pWti); ret->d.n = 0; ret->datatype = 'N'; hcontext = (hash_context_t *)func->funcdata; CHKiRet((hcontext->hash_wrapper_2_3(&hashStrVal, &modVal, func->nParams > 2 ? &seedVal : NULL, hcontext, &xhash))); ret->d.n = xhash; finalize_it: varFreeMembers(&hashStrVal); varFreeMembers(&modVal); if (func->nParams == 3) varFreeMembers(&seedVal); } static inline sbool check_param_count_hash(unsigned short nParams) { return (nParams != 1 && nParams != 2); } static inline sbool check_param_count_hashmod(unsigned short nParams) { return (nParams != 2 && nParams != 3); } static rsRetVal ATTR_NONNULL(1) init_fmHash64(struct cnffunc *const func) { DEFiRet; hash_context_t *hash_context = NULL; if (check_param_count_hash(func->nParams)) { parser_errmsg( "fmhash: hash64(string) / hash64(string, seed)" " insufficient params.\n"); ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); } func->destructable_funcdata = 1; CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t))); init_hash64_context(hash_context); func->funcdata = (void *)hash_context; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) init_fmHash64mod(struct cnffunc *const func) { DEFiRet; hash_context_t *hash_context = NULL; if (check_param_count_hashmod(func->nParams)) { parser_errmsg( "fmhash: hash64mod(string, mod)/hash64mod(string, mod, seed)" " insufficient params.\n"); ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); } func->destructable_funcdata = 1; CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t))); init_hash64_context(hash_context); func->funcdata = (void *)hash_context; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) init_fmHash32(struct cnffunc *const func) { DEFiRet; hash_context_t *hash_context = NULL; if (check_param_count_hash(func->nParams)) { parser_errmsg( "fmhash: hash32(string) / hash32(string, seed)" " insufficient params.\n"); ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); } func->destructable_funcdata = 1; CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t))); init_hash32_context(hash_context); func->funcdata = (void *)hash_context; finalize_it: RETiRet; } static rsRetVal ATTR_NONNULL(1) init_fmHash32mod(struct cnffunc *const func) { DEFiRet; hash_context_t *hash_context = NULL; if (check_param_count_hashmod(func->nParams)) { parser_errmsg( "fmhash: hash32mod(string, mod)/hash32mod(string, mod, seed)" " insufficient params.\n"); ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); } func->destructable_funcdata = 1; CHKmalloc(hash_context = calloc(1, sizeof(hash_context_t))); init_hash32_context(hash_context); func->funcdata = (void *)hash_context; finalize_it: RETiRet; } static struct scriptFunct functions[] = { {"hash64", 1, 2, fmHashXX, init_fmHash64, NULL}, {"hash64mod", 2, 3, fmHashXXmod, init_fmHash64mod, NULL}, {"hash32", 1, 2, fmHashXX, init_fmHash32, NULL}, {"hash32mod", 2, 3, fmHashXXmod, init_fmHash32mod, NULL}, {NULL, 0, 0, NULL, NULL, NULL} // last element to check end of array }; BEGINgetFunctArray CODESTARTgetFunctArray; dbgprintf("Hash: fmhhash\n"); *version = 1; *functArray = functions; ENDgetFunctArray BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_FMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf("rsyslog fmhash init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/fmhash/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017502 xustar0030 mtime=1752569012.326271887 30 atime=1787067433.917003374 29 ctime=1787067799.59882203 rsyslog-8.2608.0/contrib/fmhash/Makefile.am0000666000175000017500000000033315035412264017150 0ustar00rgerrger# # fmhash support # pkglib_LTLIBRARIES = fmhash.la fmhash_la_SOURCES = fmhash.c fmhash_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) fmhash_la_LDFLAGS = -module -avoid-version fmhash_la_LIBADD = $(HASH_XXHASH_LIBS) rsyslog-8.2608.0/contrib/fmhash/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160017514 xustar0030 mtime=1787067504.427318951 30 atime=1787067578.919708346 30 ctime=1787067799.600822067 rsyslog-8.2608.0/contrib/fmhash/Makefile.in0000664000175000017500000006565715241076160017203 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/fmhash ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = fmhash_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_fmhash_la_OBJECTS = fmhash_la-fmhash.lo fmhash_la_OBJECTS = $(am_fmhash_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 = fmhash_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(fmhash_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/fmhash_la-fmhash.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(fmhash_la_SOURCES) DIST_SOURCES = $(fmhash_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # fmhash support # pkglib_LTLIBRARIES = fmhash.la fmhash_la_SOURCES = fmhash.c fmhash_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) fmhash_la_LDFLAGS = -module -avoid-version fmhash_la_LIBADD = $(HASH_XXHASH_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/fmhash/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/fmhash/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } fmhash.la: $(fmhash_la_OBJECTS) $(fmhash_la_DEPENDENCIES) $(EXTRA_fmhash_la_DEPENDENCIES) $(AM_V_CCLD)$(fmhash_la_LINK) -rpath $(pkglibdir) $(fmhash_la_OBJECTS) $(fmhash_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmhash_la-fmhash.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< fmhash_la-fmhash.lo: fmhash.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmhash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fmhash_la-fmhash.lo -MD -MP -MF $(DEPDIR)/fmhash_la-fmhash.Tpo -c -o fmhash_la-fmhash.lo `test -f 'fmhash.c' || echo '$(srcdir)/'`fmhash.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fmhash_la-fmhash.Tpo $(DEPDIR)/fmhash_la-fmhash.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fmhash.c' object='fmhash_la-fmhash.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmhash_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fmhash_la-fmhash.lo `test -f 'fmhash.c' || echo '$(srcdir)/'`fmhash.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/fmhash_la-fmhash.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/fmhash_la-fmhash.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/pmsnare0000644000000000000000000000013215241076625015577 xustar0030 mtime=1787067797.111775686 30 atime=1787067808.787993257 30 ctime=1787067797.111775686 rsyslog-8.2608.0/contrib/pmsnare/0000775000175000017500000000000015241076625015320 5ustar00rgerrgerrsyslog-8.2608.0/contrib/pmsnare/PaxHeaders/Makefile.am0000644000000000000000000000013115035412264017701 xustar0030 mtime=1752569012.331237145 29 atime=1787067434.43601306 30 ctime=1787067797.106775593 rsyslog-8.2608.0/contrib/pmsnare/Makefile.am0000666000175000017500000000033015035412264017344 0ustar00rgerrgerpkglib_LTLIBRARIES = pmsnare.la pmsnare_la_SOURCES = pmsnare.c pmsnare_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmsnare_la_LDFLAGS = -module -avoid-version pmsnare_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/pmsnare/PaxHeaders/pmsnare.c0000644000000000000000000000013215216464435017467 xustar0030 mtime=1782212893.964265181 30 atime=1787067628.932640913 30 ctime=1787067797.111775686 rsyslog-8.2608.0/contrib/pmsnare/pmsnare.c0000664000175000017500000004217315216464435017142 0ustar00rgerrger/* pmsnare.c * * this detects logs sent by Snare and cleans them up so that they can be processed by the normal parser * * there are two variations of this, if the client is set to 'syslog' mode it sends * * timestamphostnametagotherstuff * * if the client is not set to syslog it sends * * hostnametagotherstuff * * The tabs can be represented in different ways. This module will auto-detect the tab representation based on * the global config settings, but they can be overridden for each instance in the config file if needed. * * ToDo, take advantage of items in the message itself to set more friendly information * where the normal parser will find it by re-writing more of the message * * Interesting information includes: * * in the case of windows snare messages: * the system hostname is field 12 * the severity is field 3 (criticality ranging form 0 to 4) * the source of the log is field 4 and may be able to be mapped to facility * * * created 2010-12-13 by David Lang based on pmlastmsg * Modified 2017-05-29 by Shane Lawrence. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" #include "rsconf.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("rsyslog.snare") MODULE_CNFNAME("pmsnare") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(parser) DEFobjCurrIf(datetime) /* static data */ static int bParseHOSTNAMEandTAG; /* cache for the equally-named global param - performance enhancement */ /* Keep a list of parser instances so we can apply global settings after config is loaded. */ typedef struct modInstances_s { instanceConf_t *root; instanceConf_t *tail; } modInstances_t; static modInstances_t *modInstances = NULL; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static modConfData_t *modConf = NULL; /* Per-instance config settings. */ static struct cnfparamdescr parserpdescr[] = {{"parser.controlcharacterescapeprefix", eCmdHdlrGetChar, 0}, {"parser.escapecontrolcharactersonreceive", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharactertab", eCmdHdlrBinary, 0}, {"parser.escapecontrolcharacterscstyle", eCmdHdlrBinary, 0}}; static struct cnfparamblk parserpblk = {CNFPARAMBLK_VERSION, sizeof(parserpdescr) / sizeof(struct cnfparamdescr), parserpdescr}; enum { PMSNARE_TAB_REPR_SIZE = 5 }; #define PMSNARE_SET_TAB_REPR(dst, literal) \ do { \ RS_STATIC_ASSERT(sizeof(literal) <= PMSNARE_TAB_REPR_SIZE, "pmsnare tabRepresentation literal too large"); \ memset((dst), 0, PMSNARE_TAB_REPR_SIZE); \ memcpy((dst), (literal), sizeof(literal)); \ } while (0) struct instanceConf_s { int bEscapeCCOnRcv; int bEscapeTab; int bParserEscapeCCCStyle; uchar cCCEscapeChar; int tabLength; char tabRepresentation[PMSNARE_TAB_REPR_SIZE]; struct instanceConf_s *next; }; static int hasPrefixWithFollowingTab(const uchar *const p, const int len, const char *const prefix, const int prefixLen, const instanceConf_t *const pInst) { return len >= prefixLen + pInst->tabLength && strncasecmp((const char *)p, prefix, prefixLen) == 0 && strncasecmp((const char *)(p + prefixLen), pInst->tabRepresentation, pInst->tabLength) == 0; } /* Creates the instance and adds it to the list of instances. */ static rsRetVal createInstance(instanceConf_t **pinst) { instanceConf_t *inst; DEFiRet; CHKmalloc(inst = malloc(sizeof(instanceConf_t))); inst->next = NULL; *pinst = inst; /* Add to list of instances. */ if (modInstances == NULL) { CHKmalloc(modInstances = malloc(sizeof(modInstances_t))); modInstances->tail = modInstances->root = NULL; } if (modInstances->tail == NULL) { modInstances->tail = modInstances->root = inst; } else { modInstances->tail->next = inst; modInstances->tail = inst; } finalize_it: RETiRet; } BEGINnewParserInst struct cnfparamvals *pvals = NULL; int i; CODESTARTnewParserInst; DBGPRINTF("newParserInst (pmsnare)\n"); inst = NULL; CHKiRet(createInstance(&inst)); /* Mark these as unset so we know if they should be overridden later. */ inst->bEscapeCCOnRcv = -1; inst->bEscapeTab = -1; inst->bParserEscapeCCCStyle = -1; inst->cCCEscapeChar = '\0'; /* If using the old config, just use global settings for each instance. */ if (lst == NULL) FINALIZE; /* If using the new config, process module settings for this instance. */ if ((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("pmsnare: parser param blk:\n"); cnfparamsPrint(&parserpblk, pvals); } for (i = 0; i < parserpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharactersonreceive")) { inst->bEscapeCCOnRcv = pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharactertab")) { inst->bEscapeTab = pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "parser.escapecontrolcharacterscstyle")) { inst->bParserEscapeCCCStyle = pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "parser.controlcharacterescapeprefix")) { { char *cstr; CHKmalloc(cstr = es_str2cstr(pvals[i].val.d.estr, NULL)); inst->cCCEscapeChar = (uchar)*cstr; free(cstr); } } else { dbgprintf("pmsnare: program error, non-handled param '%s'\n", parserpblk.descr[i].name); } } finalize_it: CODE_STD_FINALIZERnewParserInst if (lst != NULL) cnfparamvalsDestruct(pvals, &parserpblk); if (iRet != RS_RET_OK) free(inst); ENDnewParserInst BEGINfreeParserInst CODESTARTfreeParserInst; dbgprintf("pmsnare: free parser instance %p\n", pInst); ENDfreeParserInst BEGINcheckParserInst CODESTARTcheckParserInst; ENDcheckParserInst BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticSanitazion) iRet = RS_RET_OK; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature /* Interface with the global config. */ BEGINbeginCnfLoad CODESTARTbeginCnfLoad; modConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINsetModCnf CODESTARTsetModCnf; /* Could use module-globals here, but not global globals. */ (void)lst; ENDsetModCnf BEGINendCnfLoad instanceConf_t *inst; CODESTARTendCnfLoad; dbgprintf("pmsnare: Begin endCnfLoad\n"); /* Loop through each parser instance and apply global settings to any option that hasn't been overridden. * This can't be done any earlier because the config wasn't fully loaded until now. */ for (inst = modInstances->root; inst != NULL; inst = inst->next) { if (inst->bEscapeCCOnRcv == -1) inst->bEscapeCCOnRcv = glbl.GetParserEscapeControlCharactersOnReceive(modConf->pConf); if (inst->bEscapeTab == -1) inst->bEscapeTab = glbl.GetParserEscapeControlCharacterTab(modConf->pConf); if (inst->bParserEscapeCCCStyle == -1) inst->bParserEscapeCCCStyle = glbl.GetParserEscapeControlCharactersCStyle(modConf->pConf); if (inst->cCCEscapeChar == '\0') inst->cCCEscapeChar = glbl.GetParserControlCharacterEscapePrefix(modConf->pConf); /* Determine tab representation. Possible options: * "#011" escape on, escapetabs on, no change to prefix (default) * "?011" prefix changed in config * "\\t" C style * '\t' escape turned off */ if (inst->bEscapeCCOnRcv && inst->bEscapeTab) { if (inst->bParserEscapeCCCStyle) { PMSNARE_SET_TAB_REPR(inst->tabRepresentation, "\\t"); } else { PMSNARE_SET_TAB_REPR(inst->tabRepresentation, "#011"); inst->tabRepresentation[0] = inst->cCCEscapeChar; } } else { PMSNARE_SET_TAB_REPR(inst->tabRepresentation, "\t"); } inst->tabLength = strlen(inst->tabRepresentation); /* TODO: This debug message would be more useful if it told which Snare instance! */ dbgprintf("pmsnare: Snare parser will treat '%s' as tab.\n", inst->tabRepresentation); } assert(pModConf == modConf); ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; free(modInstances); modInstances = NULL; ENDfreeCnf BEGINparse2 uchar *p2parse; const uchar *tagStart; int lenMsg; int tagLen; int snaremessage; /* 0 means not a snare message, otherwise it's the index of the tab after the tag */ CODESTARTparse2; dbgprintf("Message will now be parsed by fix Snare parser.\n"); assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); /* check if this message is of the type we handle in this (very limited) parser * * - Find out if the first separator is a tab. * - If it is, see if the second word is one of our expected tags. * - If so, flag as Snare and replace the first tab with space so that * hostname and syslog tag are going to be parsed properly * - Else not a snare message, abort. * - Else assume valid 3164 timestamp, move over to the syslog tag. * - See if syslog header is followed by tab and one of our expected tags. * - If so, flag as Snare. * - See if either type flagged as Snare. * - If so, replace the tab with a space so that it will be parsed properly. */ snaremessage = 0; /* note: offAfterPRI is already the number of PRI chars (do not add one!) */ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* point to start of text, after PRI */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; dbgprintf("pmsnare: msg to look at: [%d]'%s'\n", lenMsg, p2parse); if ((unsigned)lenMsg < 30) { /* too short, can not be "our" message */ dbgprintf("pmsnare: Message is too short to be Snare!\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* Find the first separator and check if it's a tab. */ while (lenMsg && *p2parse != ' ' && *p2parse != '\t' && *p2parse != pInst->tabRepresentation[0]) { --lenMsg; ++p2parse; } if ((lenMsg > pInst->tabLength) && (strncasecmp((char *)p2parse, pInst->tabRepresentation, pInst->tabLength) == 0)) { dbgprintf("pmsnare: tab separated message\n"); dbgprintf("pmsnare: tab [%d]'%s' msg at the first separator: [%d]'%s'\n", pInst->tabLength, pInst->tabRepresentation, lenMsg, p2parse); /* Look for the Snare tag plus the following separator we rewrite below. */ tagStart = p2parse + pInst->tabLength; tagLen = lenMsg - pInst->tabLength; if (hasPrefixWithFollowingTab(tagStart, tagLen, "MSWinEventLog", 13, pInst)) { dbgprintf("Found a non-syslog Windows Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + pInst->tabLength + 13; } else if (hasPrefixWithFollowingTab(tagStart, tagLen, "LinuxKAudit", 11, pInst)) { dbgprintf("Found a non-syslog Linux Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + pInst->tabLength + 11; } else { /* Tab-separated but no Snare tag-> can't be Snare! */ ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } /* This is a non-syslog Snare message. Example: * other.lab.home MSWinEventLog 1 Security 606129 Wed May 17 02:25:10 2017 */ /* Remove the tab between the hostname and Snare tag. */ *p2parse = ' '; p2parse++; lenMsg--; lenMsg -= (pInst->tabLength - 1); /* size of tab goes from tabLength to 1, so shorten the message by the difference */ memmove(p2parse, p2parse + (pInst->tabLength - 1), lenMsg); /* move the message portion up to overwrite the tab */ *(p2parse + lenMsg) = '\0'; pMsg->iLenRawMsg -= (pInst->tabLength - 1); pMsg->iLenMSG -= (pInst->tabLength - 1); snaremessage -= (pInst->tabLength - 1); } else { /* The first separator is not a tab. Look for a syslog Snare message. Example: * <14>May 17 02:25:10 syslog.lab.home MSWinEventLog 1 Security 606129 Wed May 17 02:25:10 2017 */ /* go back to the beginning of the message */ lenMsg = pMsg->iLenRawMsg - pMsg->offAfterPRI; /* offAfterPRI is already the number of PRI chars (do not add one!) */ p2parse = pMsg->pszRawMsg + pMsg->offAfterPRI; /* skip over timestamp and space (15 chars + space). */ lenMsg -= 16; p2parse += 16; /* skip over what should be the hostname and space */ while (lenMsg && *p2parse != ' ') { --lenMsg; ++p2parse; } if (lenMsg) { --lenMsg; ++p2parse; } dbgprintf("pmsnare: tab [%d]'%s' msg after the timestamp and hostname: [%d]'%s'\n", pInst->tabLength, pInst->tabRepresentation, lenMsg, p2parse); /* Look for the Snare tag. */ if (hasPrefixWithFollowingTab(p2parse, lenMsg, "MSWinEventLog", 13, pInst)) { dbgprintf("Found a syslog Windows Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + 13; } else if (hasPrefixWithFollowingTab(p2parse, lenMsg, "LinuxKAudit", 11, pInst)) { dbgprintf("pmsnare: Found a syslog Linux Snare message.\n"); snaremessage = p2parse - pMsg->pszRawMsg + 11; } } if (snaremessage) { /* Skip to the end of the tag. */ p2parse = pMsg->pszRawMsg + snaremessage; lenMsg = pMsg->iLenRawMsg - snaremessage; /* Remove the tab after the tag. */ if (lenMsg < pInst->tabLength) { ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } *p2parse = ' '; p2parse++; lenMsg--; lenMsg -= (pInst->tabLength - 1); /* size of tab goes from tabLength to 1, so shorten the message by the difference */ memmove(p2parse, p2parse + (pInst->tabLength - 1), lenMsg); /* move the message portion up to overwrite the tab */ *(p2parse + lenMsg) = '\0'; pMsg->iLenRawMsg -= (pInst->tabLength - 1); pMsg->iLenMSG -= (pInst->tabLength - 1); DBGPRINTF("pmsnare: new message: [%d]'%s'\n", lenMsg, pMsg->pszRawMsg + pMsg->offAfterPRI); } ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); finalize_it: ENDparse2 BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(parser, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_MOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES; CODEqueryEtryPt_STD_PMOD2_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(parser, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); DBGPRINTF("snare parser init called, compiled with version %s\n", VERSION); bParseHOSTNAMEandTAG = glbl.GetParseHOSTNAMEandTAG(loadConf); /* cache value, is set only during rsyslogd option processing */ ENDmodInit /* vim:set ai: */ rsyslog-8.2608.0/contrib/pmsnare/PaxHeaders/Makefile.in0000644000000000000000000000013115241076161017713 xustar0030 mtime=1787067505.412337326 30 atime=1787067579.044710677 29 ctime=1787067797.10877563 rsyslog-8.2608.0/contrib/pmsnare/Makefile.in0000664000175000017500000006566115241076161017376 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/pmsnare ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) pmsnare_la_DEPENDENCIES = am_pmsnare_la_OBJECTS = pmsnare_la-pmsnare.lo pmsnare_la_OBJECTS = $(am_pmsnare_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 = pmsnare_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmsnare_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/pmsnare_la-pmsnare.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmsnare_la_SOURCES) DIST_SOURCES = $(pmsnare_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = pmsnare.la pmsnare_la_SOURCES = pmsnare.c pmsnare_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmsnare_la_LDFLAGS = -module -avoid-version pmsnare_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/pmsnare/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/pmsnare/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } pmsnare.la: $(pmsnare_la_OBJECTS) $(pmsnare_la_DEPENDENCIES) $(EXTRA_pmsnare_la_DEPENDENCIES) $(AM_V_CCLD)$(pmsnare_la_LINK) -rpath $(pkglibdir) $(pmsnare_la_OBJECTS) $(pmsnare_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmsnare_la-pmsnare.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmsnare_la-pmsnare.lo: pmsnare.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmsnare_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmsnare_la-pmsnare.lo -MD -MP -MF $(DEPDIR)/pmsnare_la-pmsnare.Tpo -c -o pmsnare_la-pmsnare.lo `test -f 'pmsnare.c' || echo '$(srcdir)/'`pmsnare.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmsnare_la-pmsnare.Tpo $(DEPDIR)/pmsnare_la-pmsnare.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmsnare.c' object='pmsnare_la-pmsnare.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmsnare_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmsnare_la-pmsnare.lo `test -f 'pmsnare.c' || echo '$(srcdir)/'`pmsnare.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/pmsnare_la-pmsnare.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmsnare_la-pmsnare.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmgrok0000644000000000000000000000013215241076631015423 xustar0030 mtime=1787067801.065849362 30 atime=1787067808.787993257 30 ctime=1787067801.065849362 rsyslog-8.2608.0/contrib/mmgrok/0000775000175000017500000000000015241076631015144 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmgrok/PaxHeaders/README0000644000000000000000000000013215035412264016355 xustar0030 mtime=1752569012.329251042 30 atime=1782715518.789788857 30 ctime=1787067801.062849305 rsyslog-8.2608.0/contrib/mmgrok/README0000666000175000017500000000244215035412264016025 0ustar00rgerrgerGrok Message Modify Plugin Using hundreds of grok patterns from logstash-patterns-core. Build This plugin requires libfastjson (always present in rsyslog core), glib2, and grok packages. If you use RH/CentOS/Fedora, you'll have to build grok rpms by yourself as follow: sudo yum install -y yum-utils rpmdevtools git clone git@github.com:jordansissel/grok.git mkdir -p ~/rpmbuild/SPECS/; cp grok/grok.spec.template ~/rpmbuild/SPECS/grok.spec (mkdir -p ~/rpmbuild/SOURCES/; cd ~/rpmbuild/SOURCES/; spectool -g ../SPECS/grok.spec) sudo yum-builddep ~/rpmbuild/SPECS/grok.spec rpmbuild -bb ~/rpmbuild/SPECS/grok.spec # use yum command instead of rpm, because grok depends on libevent, pcre, tokyocabinet sudo yum install -y libjson-c-devel glib2-devel ~/rpmbuild/RPMS/x86_64/grok*.rpm Example module(load="mmgrok") template(name="tmlp" type="string" string="%$!msg!test%\n") action(type="mmgrok" patterndir="path/to/yourpatternsDir" match="%{WORD:test}" source="msg" target="!msg") action(type="omfile" file="path/to/file" template="tmlp") Description patterndir: path to grok patterns dir, default: /usr/share/grok/patterns/base match:the pattern used to match message source: the source message/variable to be matched target: the root path to write the captured json tree rsyslog-8.2608.0/contrib/mmgrok/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264017531 xustar0030 mtime=1752569012.329251042 30 atime=1787067434.161007928 30 ctime=1787067801.056849194 rsyslog-8.2608.0/contrib/mmgrok/Makefile.am0000666000175000017500000000037015035412264017177 0ustar00rgerrgerpkglib_LTLIBRARIES = mmgrok.la mmgrok_la_SOURCES = mmgrok.c mmgrok_la_CPPFLAGS = $(GLIB_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmgrok_la_LDFLAGS = -module -avoid-version mmgrok_la_LIBADD = $(GLIB_LIBS) -lgrok $(LIBFASTJSON_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/mmgrok/PaxHeaders/mmgrok.c0000644000000000000000000000013215216464435017145 xustar0030 mtime=1782212893.960265117 30 atime=1782715518.789788857 30 ctime=1787067801.065849362 rsyslog-8.2608.0/contrib/mmgrok/mmgrok.c0000664000175000017500000002614115216464435016615 0ustar00rgerrger/* mmgrok.c * Grok the message is parsed into a structured json data inside JSON. */ #include "config.h" #include "rsyslog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "dirty.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmgrok"); static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal); DEF_OMOD_STATIC_DATA; typedef struct result_s { char *key; int key_len; const char *value; int value_len; } result_t; /* config variables */ typedef struct _instanceData { char *pszPatternDir; char *pszMatch; char *pszSource; char *pszTarget; /* as a json root for store parse json data */ msgPropDescr_t *sourceDescr; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; struct modConfData_s { rsconf_t *pConf; /* our overall config object */ }; static modConfData_t *loadModConf = NULL; static modConfData_t *runModConf = NULL; /* action (instance) parameters */ static struct cnfparamdescr actpdescr[] = { {"patterndir", eCmdHdlrString, 0}, {"match", eCmdHdlrString, 0}, {"source", eCmdHdlrString, 0}, {"target", eCmdHdlrString, 0}, }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINbeginCnfLoad CODESTARTbeginCnfLoad; loadModConf = pModConf; pModConf->pConf = pConf; ENDbeginCnfLoad BEGINendCnfLoad CODESTARTendCnfLoad; ENDendCnfLoad BEGINcheckCnf CODESTARTcheckCnf; ENDcheckCnf BEGINactivateCnf CODESTARTactivateCnf; runModConf = pModConf; ENDactivateCnf BEGINfreeCnf CODESTARTfreeCnf; ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINfreeInstance CODESTARTfreeInstance; free(pData->pszPatternDir); free(pData->pszMatch); free(pData->pszSource); free(pData->pszTarget); msgPropDescrDestruct(pData->sourceDescr); free(pData->sourceDescr); ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance static inline void setInstParamDefaults(instanceData *pData) { pData->pszPatternDir = NULL; pData->pszMatch = NULL; pData->pszSource = NULL; pData->pszTarget = NULL; pData->sourceDescr = NULL; } BEGINnewActInst struct cnfparamvals *pvals; int i; CODESTARTnewActInst; DBGPRINTF("newActInst (mmgrok)\n"); if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "patterndir")) { CHKmalloc(pData->pszPatternDir = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } else if (!strcmp(actpblk.descr[i].name, "match")) { CHKmalloc(pData->pszMatch = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } else if (!strcmp(actpblk.descr[i].name, "source")) { CHKmalloc(pData->pszSource = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } else if (!strcmp(actpblk.descr[i].name, "target")) { CHKmalloc(pData->pszTarget = es_str2cstr(pvals[i].val.d.estr, NULL)); continue; } else { DBGPRINTF( "mmgrok: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } if (pData->pszTarget == NULL) { CHKmalloc(pData->pszTarget = strdup("!")); } if (pData->pszSource != NULL && strcmp(pData->pszSource, "msg")) { CHKmalloc(pData->sourceDescr = malloc(sizeof(msgPropDescr_t))); CHKiRet(msgPropDescrFill(pData->sourceDescr, (uchar *)pData->pszSource, strlen(pData->pszSource))); } CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; DBGPRINTF("mmgrok\n"); ENDdbgPrintInstInfo BEGINtryResume CODESTARTtryResume; ENDtryResume static inline grok_t *CreateGrok(void) { grok_t *grok = grok_new(); if (grok == NULL) { DBGPRINTF("mmgrok: create a grok faile!"); exit(1); } grok_init(grok); return grok; } /* the parseing is complate message into json */ static rsRetVal smsg_to_json(GList *list, instanceData *pData, smsg_t *pMsg) { GList *it = list; struct json_object *json; struct json_object *jval; DEFiRet; json = json_object_new_object(); if (json == NULL) { ABORT_FINALIZE(RS_RET_ERR); } for (; it; it = it->next) { int key_len = ((result_t *)it->data)->key_len; char *key = (char *)malloc(key_len + 1); snprintf(key, key_len + 1, "%.*s", key_len, ((result_t *)it->data)->key); int value_len = ((result_t *)it->data)->value_len; char *value = (char *)malloc(value_len + 1); snprintf(value, value_len + 1, "%.*s", value_len, ((result_t *)it->data)->value); jval = json_object_new_string(value); json_object_object_add(json, key, jval); free(key); free(value); } msgAddJSON(pMsg, (uchar *)pData->pszTarget, json, 0, 0); finalize_it: RETiRet; } /* store parse result ,use list in glib*/ static rsRetVal parse_result_store(const grok_match_t gm, instanceData *pData, smsg_t *pMsg) { GList *re_list = NULL; char *pname; const char *pdata; int pname_len, pdata_len; char *key; DEFiRet; grok_match_walk_init(&gm); // grok API while (grok_match_walk_next(&gm, &pname, &pname_len, &pdata, &pdata_len) == 0) { /* parse key and value type from patterns */ key = strchr(pname, ':'); if (key != NULL) { int key_len; result_t *result = g_new0(result_t, 1); key_len = pname_len - ((key + 1) - pname); key = key + 1; pname_len = key_len; char *type = memchr(key, ':', pname_len); if (type != NULL) key_len = (type - key); /* store parse result into list */ result->key = key; result->key_len = key_len; result->value = pdata; result->value_len = pdata_len; /* the value of merger the same key*/ re_list = g_list_append(re_list, result); } } CHKiRet(smsg_to_json(re_list, pData, pMsg)); finalize_it: g_list_free_full(re_list, g_free); grok_match_walk_end(&gm); RETiRet; } /* motify message for per line */ static rsRetVal MotifyLine(char *line, grok_t *grok, instanceData *pData, smsg_t *pMsg) { grok_match_t gm; DEFiRet; grok_patterns_import_from_file(grok, pData->pszPatternDir); int compile = grok_compile(grok, pData->pszMatch); if (compile != GROK_OK) { DBGPRINTF("mmgrok: grok_compile faile!exit code: %d\n", compile); ABORT_FINALIZE(RS_RET_ERR); } int exe = grok_exec(grok, line, &gm); if (exe != GROK_OK) { DBGPRINTF("mmgrok: grok_exec faile!exit code: %d\n", exe); ABORT_FINALIZE(RS_RET_ERR); } (void)parse_result_store(gm, pData, pMsg); finalize_it: RETiRet; } /* motify rsyslog messages */ static rsRetVal MotifyMessage(instanceData *pData, smsg_t *pMsg, const uchar *msgBuf, const rs_size_t msgLen) { char *saveptr = NULL; char *msg = NULL; char *line = NULL; DEFiRet; grok_t *grok = CreateGrok(); msg = strndup((const char *)msgBuf, msgLen); CHKmalloc(msg); line = strtok_r(msg, "\n", &saveptr); while (line != NULL) { (void)MotifyLine(line, grok, pData, pMsg); line = strtok_r(NULL, "\n", &saveptr); } finalize_it: free(msg); grok_free(grok); RETiRet; } BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; smsg_t *pMsg = ppMsg[0]; uchar *buf; uchar *bufToFree = NULL; rs_size_t len; unsigned short freeBuf = 0; instanceData *pData; CODESTARTdoAction; pData = pWrkrData->pData; if (pData->sourceDescr == NULL) { buf = getMSG(pMsg); len = getMSGLen(pMsg); } else { buf = MsgGetProp(pMsg, NULL, pData->sourceDescr, &len, &freeBuf, NULL); if (freeBuf) bufToFree = buf; } while (len > 0 && isspace(*buf)) { ++buf; --len; } if (len == 0) { DBGPRINTF("mmgrok: not msg for mmgrok!"); ABORT_FINALIZE(RS_RET_NO_CEE_MSG); } CHKiRet(MotifyMessage(pData, pMsg, buf, len)); finalize_it: free(bufToFree); ENDdoAction BEGINparseSelectorAct CODESTARTparseSelectorAct; CODE_STD_STRING_REQUESTparseSelectorAct(1) if (strncmp((char *)p, ":mmgrok:", sizeof(":mmgrok:") - 1)) { ABORT_FINALIZE(RS_RET_CONFLINE_UNPROCESSED); } p += sizeof(":mmgrok:") - 1; /* eat indicator sequence (-1 because of '\0'!) */ CHKiRet(createInstance(&pData)); if (*(p - 1) == ';') --p; CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, OMSR_TPL_AS_MSG, (uchar *)"RSYSLOG_FileFormat")); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_STD_CONF2_QUERIES; ENDqueryEtryPt static rsRetVal resetConfigVariables(uchar __attribute__((unused)) * pp, void __attribute__((unused)) * pVal) { DEFiRet; RETiRet; } BEGINmodInit() rsRetVal localRet; rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts); unsigned long opts; int bMsgPassingSupported; CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; CODEmodInit_QueryRegCFSLineHdlr DBGPRINTF("mmgrok: module compiled with rsyslog version %s.\n", VERSION); bMsgPassingSupported = 0; localRet = pHostQueryEtryPt((uchar *)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts); if (localRet == RS_RET_OK) { CHKiRet((*pomsrGetSupportedTplOpts)(&opts)); if (opts & OMSR_TPL_AS_MSG) bMsgPassingSupported = 1; } else if (localRet != RS_RET_ENTRY_POINT_NOT_FOUND) { ABORT_FINALIZE(localRet); /* Something else went wrong, not acceptable */ } if (!bMsgPassingSupported) { DBGPRINTF( "mmgrok: msg-passing is not supported by rsyslog core, " "can not continue.\n"); ABORT_FINALIZE(RS_RET_NO_MSG_PASSING); } CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID)); ENDmodInit rsyslog-8.2608.0/contrib/mmgrok/PaxHeaders/Makefile.in0000644000000000000000000000013115241076160017541 xustar0030 mtime=1787067504.864327103 30 atime=1787067579.239714313 29 ctime=1787067801.05984925 rsyslog-8.2608.0/contrib/mmgrok/Makefile.in0000664000175000017500000006574615241076160017230 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmgrok ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = mmgrok_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_mmgrok_la_OBJECTS = mmgrok_la-mmgrok.lo mmgrok_la_OBJECTS = $(am_mmgrok_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 = mmgrok_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(mmgrok_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmgrok_la-mmgrok.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmgrok_la_SOURCES) DIST_SOURCES = $(mmgrok_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmgrok.la mmgrok_la_SOURCES = mmgrok.c mmgrok_la_CPPFLAGS = $(GLIB_CFLAGS) $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmgrok_la_LDFLAGS = -module -avoid-version mmgrok_la_LIBADD = $(GLIB_LIBS) -lgrok $(LIBFASTJSON_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmgrok/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmgrok/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmgrok.la: $(mmgrok_la_OBJECTS) $(mmgrok_la_DEPENDENCIES) $(EXTRA_mmgrok_la_DEPENDENCIES) $(AM_V_CCLD)$(mmgrok_la_LINK) -rpath $(pkglibdir) $(mmgrok_la_OBJECTS) $(mmgrok_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmgrok_la-mmgrok.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmgrok_la-mmgrok.lo: mmgrok.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmgrok_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmgrok_la-mmgrok.lo -MD -MP -MF $(DEPDIR)/mmgrok_la-mmgrok.Tpo -c -o mmgrok_la-mmgrok.lo `test -f 'mmgrok.c' || echo '$(srcdir)/'`mmgrok.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmgrok_la-mmgrok.Tpo $(DEPDIR)/mmgrok_la-mmgrok.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmgrok.c' object='mmgrok_la-mmgrok.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmgrok_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmgrok_la-mmgrok.lo `test -f 'mmgrok.c' || echo '$(srcdir)/'`mmgrok.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmgrok_la-mmgrok.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmgrok_la-mmgrok.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/fmunflatten0000644000000000000000000000013215241076627016457 xustar0030 mtime=1787067799.686823669 30 atime=1787067808.787993257 30 ctime=1787067799.686823669 rsyslog-8.2608.0/contrib/fmunflatten/0000775000175000017500000000000015241076627016200 5ustar00rgerrgerrsyslog-8.2608.0/contrib/fmunflatten/PaxHeaders/Makefile.am0000644000000000000000000000013215131231047020553 xustar0030 mtime=1768239655.582210586 30 atime=1787067433.934003692 30 ctime=1787067799.681823576 rsyslog-8.2608.0/contrib/fmunflatten/Makefile.am0000666000175000017500000000035715131231047020226 0ustar00rgerrgerpkglib_LTLIBRARIES = fmunflatten.la fmunflatten_la_SOURCES = fmunflatten.c fmunflatten_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JSON_C_CFLAGS) fmunflatten_la_LDFLAGS = -module -avoid-version fmunflatten_la_LIBADD = $(JSON_C_LIBS) rsyslog-8.2608.0/contrib/fmunflatten/PaxHeaders/fmunflatten.c0000644000000000000000000000013115132411300021176 xustar0030 mtime=1768559296.135883568 29 atime=1782715518.78878884 30 ctime=1787067799.688823706 rsyslog-8.2608.0/contrib/fmunflatten/fmunflatten.c0000666000175000017500000001740315132411300020652 0ustar00rgerrger/* * This is a function module providing ability to unflatten a JSON tree. * * Copyright 2020 Julien Thomas < jthomas @ zenetys.com > * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #ifndef _AIX #include #endif #include #include #include "rsyslog.h" #include "errmsg.h" #include "msg.h" #include "parserif.h" #include "module-template.h" #include "rainerscript.h" #include "wti.h" #define FMUNFLATTEN_KBUFLEN 256 #define _jso_type(x) json_type_to_name(json_object_get_type(x)) MODULE_TYPE_FUNCTION MODULE_TYPE_NOKEEP; DEF_FMOD_STATIC_DATA; struct unflatten_ctx { char *kbuf; size_t kbuf_len; char delim; }; /* forward declarations */ void unflatten_add(struct unflatten_ctx *ctx, struct json_object *dst, const char *key, struct json_object *value); void unflatten(struct unflatten_ctx *ctx, struct json_object *src, struct json_object *dst); void unflatten_add(struct unflatten_ctx *ctx, struct json_object *dst, const char *key, struct json_object *value) { const char *p = key; const char *q = p; int depth = 0; size_t klen; struct json_object *o; json_bool exists_already; int create; while (1) { while (*q != ctx->delim && *q != '\0') q++; klen = q - p; if (klen + 1 > ctx->kbuf_len) { DBGPRINTF( "warning: flat key \"%.20s...\" truncated at depth #%d, buffer too " "small (max %zd)\n", key, depth, ctx->kbuf_len); klen = ctx->kbuf_len - 1; } memcpy(ctx->kbuf, p, klen); ctx->kbuf[klen] = '\0'; exists_already = json_object_object_get_ex(dst, ctx->kbuf, &o); if (*q == ctx->delim) { if (!exists_already) create = 1; else if (json_object_is_type(o, json_type_object)) create = 0; else { DBGPRINTF( "warning: while processing flat key \"%s\" at depth #%d (intermediate " "node), overriding existing value of type %s by an object\n", key, depth, _jso_type(o)); json_object_object_del(dst, ctx->kbuf); create = 1; } if (create) { o = json_object_new_object(); json_object_object_add(dst, ctx->kbuf, o); } dst = o; p = q + 1; q = p; depth++; } else if (*q == '\0') { if (json_object_is_type(value, json_type_object)) { if (exists_already) { if (!json_object_is_type(o, json_type_object)) { DBGPRINTF( "warning: while processing flat key \"%s\" at depth #%d " "(final node), overriding existing value of type %s by an " "object\n", key, depth, _jso_type(o)); json_object_object_del(dst, ctx->kbuf); o = json_object_new_object(); json_object_object_add(dst, ctx->kbuf, o); } } else { o = json_object_new_object(); json_object_object_add(dst, ctx->kbuf, o); } unflatten(ctx, value, o); } else { if (exists_already) { DBGPRINTF( "warning: while processing flat key \"%s\" at depth #%d " "(final node), overriding existing value\n", key, depth); json_object_object_del(dst, ctx->kbuf); } o = jsonDeepCopy(value); json_object_object_add(dst, ctx->kbuf, o); } break; } } } void unflatten(struct unflatten_ctx *ctx, struct json_object *src, struct json_object *dst) { struct json_object_iterator it = json_object_iter_begin(src); struct json_object_iterator itEnd = json_object_iter_end(src); const char *key; struct json_object *value; while (!json_object_iter_equal(&it, &itEnd)) { key = json_object_iter_peek_name(&it); value = json_object_iter_peek_value(&it); unflatten_add(ctx, dst, key, value); json_object_iter_next(&it); } } static void ATTR_NONNULL() doFunc_unflatten(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { struct svar src_var; struct svar delim_var; char kbuf[FMUNFLATTEN_KBUFLEN]; struct unflatten_ctx ctx = {.kbuf = kbuf, .kbuf_len = sizeof(kbuf), .delim = 0}; /* A dummy value of 0 (number) is returned by default. Callers should also * call script_error() to check if this script function succeeded before * using the value it returns. */ ret->datatype = 'N'; ret->d.n = 0; wtiSetScriptErrno(pWti, RS_SCRIPT_EINVAL); cnfexprEval(func->expr[0], &src_var, usrptr, pWti); cnfexprEval(func->expr[1], &delim_var, usrptr, pWti); /* Check argument 2 (delimiter character). */ if (delim_var.datatype == 'S' && es_strlen(delim_var.d.estr) == 1) ctx.delim = *es_getBufAddr(delim_var.d.estr); else if (delim_var.datatype == 'N') ctx.delim = delim_var.d.n; if (ctx.delim == 0) { LogError(0, RS_RET_INVALID_PARAMS, "unflatten: invalid argument 2 (delim), single character " "required (as string or decimal charcode)"); FINALIZE; } /* Check argument 1 (source). Not logging an error avoids emitting logs for * messages when $! was not touched. */ if (src_var.datatype != 'J') { DBGPRINTF("unsupported argument 1 (src) datatype %c\n", src_var.datatype); FINALIZE; } ret->datatype = 'J'; if (json_object_is_type(src_var.d.json, json_type_object)) { ret->d.json = json_object_new_object(); unflatten(&ctx, src_var.d.json, ret->d.json); } else ret->d.json = jsonDeepCopy(src_var.d.json); wtiSetScriptErrno(pWti, RS_SCRIPT_EOK); finalize_it: varFreeMembers(&src_var); varFreeMembers(&delim_var); } static rsRetVal ATTR_NONNULL(1) initFunc_unflatten(struct cnffunc *const func) { DEFiRet; func->destructable_funcdata = 0; RETiRet; } static struct scriptFunct functions[] = { {"unflatten", 2, 2, doFunc_unflatten, initFunc_unflatten, NULL}, {NULL, 0, 0, NULL, NULL, NULL} /* last element to check end of array */ }; BEGINgetFunctArray CODESTARTgetFunctArray; *version = 1; *functArray = functions; ENDgetFunctArray BEGINmodExit CODESTARTmodExit; ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_FMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr dbgprintf("rsyslog fmunflatten init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/fmunflatten/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160020571 xustar0030 mtime=1787067504.455319473 30 atime=1787067578.950708924 30 ctime=1787067799.684823632 rsyslog-8.2608.0/contrib/fmunflatten/Makefile.in0000664000175000017500000006623615241076160020252 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/fmunflatten ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) fmunflatten_la_DEPENDENCIES = am_fmunflatten_la_OBJECTS = fmunflatten_la-fmunflatten.lo fmunflatten_la_OBJECTS = $(am_fmunflatten_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 = fmunflatten_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(fmunflatten_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(fmunflatten_la_SOURCES) DIST_SOURCES = $(fmunflatten_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = fmunflatten.la fmunflatten_la_SOURCES = fmunflatten.c fmunflatten_la_CPPFLAGS = $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(JSON_C_CFLAGS) fmunflatten_la_LDFLAGS = -module -avoid-version fmunflatten_la_LIBADD = $(JSON_C_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/fmunflatten/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/fmunflatten/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } fmunflatten.la: $(fmunflatten_la_OBJECTS) $(fmunflatten_la_DEPENDENCIES) $(EXTRA_fmunflatten_la_DEPENDENCIES) $(AM_V_CCLD)$(fmunflatten_la_LINK) -rpath $(pkglibdir) $(fmunflatten_la_OBJECTS) $(fmunflatten_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< fmunflatten_la-fmunflatten.lo: fmunflatten.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmunflatten_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fmunflatten_la-fmunflatten.lo -MD -MP -MF $(DEPDIR)/fmunflatten_la-fmunflatten.Tpo -c -o fmunflatten_la-fmunflatten.lo `test -f 'fmunflatten.c' || echo '$(srcdir)/'`fmunflatten.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fmunflatten_la-fmunflatten.Tpo $(DEPDIR)/fmunflatten_la-fmunflatten.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fmunflatten.c' object='fmunflatten_la-fmunflatten.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(fmunflatten_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fmunflatten_la-fmunflatten.lo `test -f 'fmunflatten.c' || echo '$(srcdir)/'`fmunflatten.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/fmunflatten_la-fmunflatten.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/pmdb2diag0000644000000000000000000000013215241076633015762 xustar0030 mtime=1787067803.296890934 30 atime=1787067808.787993257 30 ctime=1787067803.296890934 rsyslog-8.2608.0/contrib/pmdb2diag/0000775000175000017500000000000015241076633015503 5ustar00rgerrgerrsyslog-8.2608.0/contrib/pmdb2diag/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264020066 xustar0030 mtime=1752569012.331237145 30 atime=1787067434.401012406 30 ctime=1787067803.291890841 rsyslog-8.2608.0/contrib/pmdb2diag/Makefile.am0000666000175000017500000000034415035412264017535 0ustar00rgerrgerpkglib_LTLIBRARIES = pmdb2diag.la pmdb2diag_la_SOURCES = pmdb2diag.c pmdb2diag_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmdb2diag_la_LDFLAGS = -module -avoid-version pmdb2diag_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/pmdb2diag/PaxHeaders/pmdb2diag.c0000644000000000000000000000013215216464435020037 xustar0030 mtime=1782212893.964265181 30 atime=1782715518.787788823 30 ctime=1787067803.297890953 rsyslog-8.2608.0/contrib/pmdb2diag/pmdb2diag.c0000664000175000017500000002447115216464435017513 0ustar00rgerrger/* pmdb2diag.c * * This is a parser module specifically for DB2diag log file. * It extracted program, pid and severity from the log. * * Copyright 2015 Philippe Duveau @ Pari Mutuel Urbain. * * This file is contribution of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H #include #endif #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "msg.h" #include "module-template.h" #include "glbl.h" #include "errmsg.h" #include "parser.h" #include "datetime.h" #include "unicode-helper.h" MODULE_TYPE_PARSER MODULE_TYPE_NOKEEP; PARSER_NAME("db2.diag") MODULE_CNFNAME("pmdb2diag") /* internal structures */ DEF_PMOD_STATIC_DATA; DEFobjCurrIf(glbl) DEFobjCurrIf(datetime) static char *bounded_memchr(char *const start, const int len, const int ch) { if (len <= 0) return NULL; return memchr(start, ch, len); } /* input instance parameters */ static struct cnfparamdescr parserpdescr[] = { {"levelpos", eCmdHdlrInt, 0}, {"timepos", eCmdHdlrInt, 0}, {"timeformat", eCmdHdlrString, 0}, {"pidstarttoprogstartshift", eCmdHdlrInt, 0}, }; static struct cnfparamblk parserpblk = {CNFPARAMBLK_VERSION, sizeof(parserpdescr) / sizeof(struct cnfparamdescr), parserpdescr}; struct instanceConf_s { int levelpos; /* expected severity position in read message */ int timepos; /* expected time position in read message */ int pidstarttoprogstartshift; /* position of prog related to pid */ char *timeformat; /* format of timestamp in read message */ char sepSec; /* decimal separator between second and milliseconds */ }; BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATUREAutomaticPRIParsing) iRet = RS_RET_OK; ENDisCompatibleWithFeature BEGINparse2 struct tm tm; char *ms, *timepos, *pid, *prog, *eprog, *backslash, *end, *lvl, *rawStart, *space; int lprog, lpid, lvl_len, rawLen; char buffer[128]; CODESTARTparse2; assert(pMsg != NULL); assert(pMsg->pszRawMsg != NULL); DBGPRINTF("Message will now be parsed by \"db2diag\" parser.\n"); rawStart = (char *)pMsg->pszRawMsg + pMsg->offAfterPRI; rawLen = pMsg->iLenRawMsg - (int)pMsg->offAfterPRI; if (rawLen <= 0 || pInst->levelpos < 0 || pInst->timepos < 0 || pInst->pidstarttoprogstartshift < 0) { ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); } if (pInst->levelpos > rawLen - 4 || pInst->timepos >= rawLen) ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); /* Instead of comparing strings which a waste of cpu cycles we take interpret the 4 first chars of * level read it as int32 and compare it to same interpretation of our constant "levels" * So this test is not sensitive to ENDIANESS. This is not a clean way but very efficient. */ lvl = rawStart + pInst->levelpos; switch (*lvl) { case 'C': /* Critical */ pMsg->iSeverity = LOG_EMERG; lvl_len = 8; break; case 'A': /* Alert */ pMsg->iSeverity = LOG_ALERT; lvl_len = 5; break; case 'S': /* Severe */ pMsg->iSeverity = LOG_CRIT; lvl_len = 6; break; case 'E': /* Error / Event */ pMsg->iSeverity = (lvl[1] == 'r') ? LOG_ERR : LOG_NOTICE; lvl_len = 5; break; case 'W': /* Warning */ pMsg->iSeverity = LOG_WARNING; lvl_len = 7; break; case 'I': /* Info */ pMsg->iSeverity = LOG_INFO; lvl_len = 4; break; case 'D': /* Debug */ pMsg->iSeverity = LOG_DEBUG; lvl_len = 5; break; default: /* perhaps the message does not contain a proper level if so don't parse the log */ ABORT_FINALIZE(0); } /* let recheck with the real level len */ if (pInst->levelpos > rawLen - lvl_len) ABORT_FINALIZE(RS_RET_COULD_NOT_PARSE); DBGPRINTF("db2parse Level %d\n", pMsg->iSeverity); end = (char *)pMsg->pszRawMsg + pMsg->iLenRawMsg; timepos = rawStart + pInst->timepos; DBGPRINTF("db2parse Time %.30s\n", timepos); ms = strptime(timepos, pInst->timeformat, &tm); if (ms > timepos && *(ms - 1) == pInst->sepSec) { /* the timestamp could be properly interpreted by strptime & our format then set proper timestamp */ int secfrac = 0, tzoff = 0; char *tzpos = strchr(ms, '+'); if (!tzpos) tzpos = strchr(ms, '-'); if (!tzpos) tzpos = (char *)"+"; sscanf(ms, (*tzpos == '+') ? "%d+%d " : "%d-%d ", &secfrac, &tzoff); pMsg->tTIMESTAMP.year = tm.tm_year + 1900; pMsg->tTIMESTAMP.month = tm.tm_mon + 1; pMsg->tTIMESTAMP.day = tm.tm_mday; pMsg->tTIMESTAMP.hour = tm.tm_hour; pMsg->tTIMESTAMP.minute = tm.tm_min; pMsg->tTIMESTAMP.second = tm.tm_sec; pMsg->tTIMESTAMP.secfrac = secfrac; pMsg->tTIMESTAMP.secfracPrecision = tzpos - ms; pMsg->tTIMESTAMP.OffsetMode = *tzpos; pMsg->tTIMESTAMP.OffsetHour = tzoff / 60; pMsg->tTIMESTAMP.OffsetMinute = tzoff % 60; } pid = bounded_memchr(rawStart + pInst->levelpos + lvl_len, rawLen - (pInst->levelpos + lvl_len), ':'); if (!pid || pid >= end) ABORT_FINALIZE(0); if (end - pid < 3) ABORT_FINALIZE(0); pid += 2; space = bounded_memchr(pid, end - pid, ' '); if (space == NULL) ABORT_FINALIZE(0); lpid = space - pid; DBGPRINTF("db2parse pid %.*s\n", lpid, pid); /* set the pid */ snprintf(buffer, 128, "%.*s", lpid, pid); MsgSetPROCID(pMsg, buffer); if (pInst->pidstarttoprogstartshift > end - pid) ABORT_FINALIZE(0); prog = pid + pInst->pidstarttoprogstartshift; /* this offset between start of pid to start of prog */ if (prog >= end) ABORT_FINALIZE(0); eprog = bounded_memchr(prog, end - prog, ' '); /* let find the end of the program */ backslash = bounded_memchr(prog, end - prog, '\\'); /* perhaps program contain an backslash */ if (!backslash) backslash = end; /* Determine the final length of prog */ lprog = (eprog && eprog < backslash) ? eprog - prog : backslash - prog; DBGPRINTF("db2parse prog %.*s lprog %d\n", lprog, prog, lprog); /* set the appname */ snprintf(buffer, 128, "%.*s", lprog, prog); MsgSetAPPNAME(pMsg, buffer); /* the original raw msg if not altered by the parser */ finalize_it: ENDparse2 BEGINfreeParserInst CODESTARTfreeParserInst; free(pInst->timeformat); ENDfreeParserInst BEGINcheckParserInst CODESTARTcheckParserInst; ENDcheckParserInst static rsRetVal createInstance(instanceConf_t **ppInst) { instanceConf_t *pInst; DEFiRet; CHKmalloc(pInst = (instanceConf_t *)malloc(sizeof(instanceConf_t))); pInst->timeformat = NULL; pInst->levelpos = 59; pInst->timepos = 0; pInst->pidstarttoprogstartshift = 49; *ppInst = pInst; finalize_it: RETiRet; } BEGINnewParserInst struct cnfparamvals *pvals = NULL; int i; CODESTARTnewParserInst; inst = NULL; DBGPRINTF("newParserInst (pmdb2diag)\n"); CHKiRet(createInstance(&inst)); if (lst) { if ((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { DBGPRINTF("parser param blk in pmdb2diag:\n"); cnfparamsPrint(&parserpblk, pvals); } for (i = 0; i < parserpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(parserpblk.descr[i].name, "timeformat")) { CHKmalloc(inst->timeformat = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(parserpblk.descr[i].name, "timepos")) { inst->timepos = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "levelpos")) { inst->levelpos = (int)pvals[i].val.d.n; } else if (!strcmp(parserpblk.descr[i].name, "pidstarttoprogstartshift")) { inst->pidstarttoprogstartshift = (int)pvals[i].val.d.n; } else { DBGPRINTF( "pmdb2diag: program error, non-handled " "param '%s'\n", parserpblk.descr[i].name); } } } if (inst->timeformat == NULL) { CHKmalloc(inst->timeformat = strdup("%Y-%m-%d-%H.%M.%S.")); inst->sepSec = '.'; } else if (strlen(inst->timeformat) == 0) { LogError(0, RS_RET_INVALID_PARAMS, "pmdb2diag: timeformat must not be empty"); ABORT_FINALIZE(RS_RET_INVALID_PARAMS); } else { inst->sepSec = inst->timeformat[strlen(inst->timeformat) - 1]; } DBGPRINTF("pmdb2diag: parsing date/time with '%s' at position %d and level at position %d.\n", inst->timeformat, inst->timepos, inst->levelpos); finalize_it: CODE_STD_FINALIZERnewParserInst if (lst != NULL) cnfparamvalsDestruct(pvals, &parserpblk); ENDnewParserInst BEGINmodExit CODESTARTmodExit; /* release what we no longer need */ objRelease(glbl, CORE_COMPONENT); objRelease(datetime, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_PMOD2_QUERIES; CODEqueryEtryPt_IsCompatibleWithFeature_IF_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); CHKiRet(objUse(datetime, CORE_COMPONENT)); DBGPRINTF("pmdb2diag parser init called, compiled with version %s\n", VERSION); ENDmodInit rsyslog-8.2608.0/contrib/pmdb2diag/PaxHeaders/Makefile.in0000644000000000000000000000013215241076161020100 xustar0030 mtime=1787067505.338335945 30 atime=1787067579.864725969 30 ctime=1787067803.293890879 rsyslog-8.2608.0/contrib/pmdb2diag/Makefile.in0000664000175000017500000006604515241076161017557 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/pmdb2diag ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) pmdb2diag_la_DEPENDENCIES = am_pmdb2diag_la_OBJECTS = pmdb2diag_la-pmdb2diag.lo pmdb2diag_la_OBJECTS = $(am_pmdb2diag_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 = pmdb2diag_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(pmdb2diag_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(pmdb2diag_la_SOURCES) DIST_SOURCES = $(pmdb2diag_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = pmdb2diag.la pmdb2diag_la_SOURCES = pmdb2diag.c pmdb2diag_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) -I ../../tools pmdb2diag_la_LDFLAGS = -module -avoid-version pmdb2diag_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/pmdb2diag/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/pmdb2diag/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } pmdb2diag.la: $(pmdb2diag_la_OBJECTS) $(pmdb2diag_la_DEPENDENCIES) $(EXTRA_pmdb2diag_la_DEPENDENCIES) $(AM_V_CCLD)$(pmdb2diag_la_LINK) -rpath $(pkglibdir) $(pmdb2diag_la_OBJECTS) $(pmdb2diag_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< pmdb2diag_la-pmdb2diag.lo: pmdb2diag.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmdb2diag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pmdb2diag_la-pmdb2diag.lo -MD -MP -MF $(DEPDIR)/pmdb2diag_la-pmdb2diag.Tpo -c -o pmdb2diag_la-pmdb2diag.lo `test -f 'pmdb2diag.c' || echo '$(srcdir)/'`pmdb2diag.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/pmdb2diag_la-pmdb2diag.Tpo $(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='pmdb2diag.c' object='pmdb2diag_la-pmdb2diag.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(pmdb2diag_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o pmdb2diag_la-pmdb2diag.lo `test -f 'pmdb2diag.c' || echo '$(srcdir)/'`pmdb2diag.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/pmdb2diag_la-pmdb2diag.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/omhiredis0000644000000000000000000000013215241076625016115 xustar0030 mtime=1787067797.647785675 30 atime=1787067808.787993257 30 ctime=1787067797.647785675 rsyslog-8.2608.0/contrib/omhiredis/0000775000175000017500000000000015241076625015636 5ustar00rgerrgerrsyslog-8.2608.0/contrib/omhiredis/PaxHeaders/README0000644000000000000000000000013215035412264017044 xustar0030 mtime=1752569012.330244093 30 atime=1782715518.786788806 30 ctime=1787067797.645785637 rsyslog-8.2608.0/contrib/omhiredis/README0000666000175000017500000000334315035412264016515 0ustar00rgerrgerRedis Outplug Plugin using hiredis library REQUIREMENTS: * hiredis ( https://github.com/redis/hiredis.git ) USAGE: This plugin has three current "modes" that it supports: 1. "template" This is the original mode that the plugin supported. You use an rsyslog template to construct a command that is sent directly to redis. This mode currently has an issue dealing with strings that contain spaces. It's useful for doing things like incrementing counters for statistics. ``` module(load="omhiredis") template( name="simple_count" type="string" string="HINCRBY testcount %programname% 1") *.* action( name="count_redis" type="omhiredis" mode="template" template="simple_count" ) ``` 2. "queue" The queue mode will LPUSH your message to a redis list. Unlike the template mode, it handles full rsyslog messages properly. If a template is not supplied, it will default to the RSYSLOG_ForwardFormat template. The "key" parameter is required. ``` module(load="omhiredis") *.* action( name="push_redis" type="omhiredis" mode="queue" key="testqueue" ) ``` 3. "publish" The publish mode will PUBLISH to a redis channel. Unlike the template mode, it handles full rsyslog messages properly. If a template is not supplied, it will default to the RSYSLOG_ForwardFormat template. The "key" parameter is required and will be used for the publish channel. ``` module(load="omhiredis") *.* action( name="publish_redis" type="omhiredis" mode="publish" key="testpublish" ) ``` NOTES * dequeuebatchsize now sets the pipeline size for hiredis, allowing pipelining commands. rsyslog-8.2608.0/contrib/omhiredis/PaxHeaders/omhiredis.c0000644000000000000000000000013215216464435020323 xustar0030 mtime=1782212893.963265166 30 atime=1787067630.377667855 30 ctime=1787067797.647785675 rsyslog-8.2608.0/contrib/omhiredis/omhiredis.c0000664000175000017500000010445015216464435017773 0ustar00rgerrger/* omhiredis.c * Copyright 2012 Talksum, Inc * Copyright 2015 DigitalOcean, Inc * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see * . * * Author: Brian Knox * * * Author: Jérémie Jourdin (TLS support) * */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef HIREDIS_SSL #include #endif #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "srUtils.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "unicode-helper.h" #include "parserif.h" #include "action.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("omhiredis") /* internal structures */ DEF_OMOD_STATIC_DATA; #define OMHIREDIS_MODE_TEMPLATE 0 #define OMHIREDIS_MODE_QUEUE 1 #define OMHIREDIS_MODE_PUBLISH 2 #define OMHIREDIS_MODE_SET 3 #define OMHIREDIS_MODE_STREAM 4 /* our instance data. * this will be accessable * via pData */ typedef struct _instanceData { uchar *server; /* redis server address */ uchar *socketPath; /* redis server UDS address (This option only takes effect if the server is not set) */ int port; /* redis port */ uchar *serverpassword; /* redis password */ uchar *tplName; /* template name */ char *modeDescription; /* mode description */ int mode; /* mode constant */ uchar *key; /* key for QUEUE, PUBLISH and STREAM modes */ uchar *streamKeyAck; /* key name for STREAM ACKs (when enabled) */ uchar *streamGroupAck; /* group name for STREAM ACKs (when enabled) */ uchar *streamIndexAck; /* index name for STREAM ACKs (when enabled) */ int expiration; /* expiration value for SET/SETEX mode */ sbool dynaKey; /* Should we treat the key as a template? */ sbool streamDynaKeyAck; /* Should we treat the groupAck as a template? */ sbool streamDynaGroupAck; /* Should we treat the groupAck as a template? */ sbool streamDynaIndexAck; /* Should we treat the IndexAck as a template? */ sbool useRPush; /* Should we use RPUSH instead of LPUSH? */ uchar *streamOutField; /* Field to place message into (for stream insertions only) */ uint streamCapacityLimit; /* zero means stream is not capped (default) setting a non-zero value ultimately activates the approximate MAXLEN option '~' (see Redis XADD docs)*/ sbool streamAck; /* Should the module send an XACK for each inserted message? This feature requires that 3 infos are present in the '$.' object of the log: - $.redis!stream - $.redis!group - $.redis!index Those 3 infos can either be provided through usage of imhiredis or set manually with Rainerscript */ sbool streamDel; /* Should the module send an XDEL for each inserted message? This feature requires that 2 infos are present in the '$.' object of the log: - $.redis!stream - $.redis!index Those 2 infos can either be provided through usage of imhiredis or set manually with Rainerscript */ #ifdef HIREDIS_SSL sbool use_tls; /* Should we use TLS to connect to redis ? */ char *ca_cert_bundle; /* CA bundle file */ char *ca_cert_dir; /* Path of trusted certificates */ char *client_cert; /* Client certificate */ char *client_key; /* Client private key */ char *sni; /* TLS Server Name Indication */ #endif action_t *pAction; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; /* instanc data */ redisContext *conn; /* redis connection */ int count; /* count of command sent for current batch */ #ifdef HIREDIS_SSL redisSSLContext *ssl_conn; /* redis ssl connection */ redisSSLContextError ssl_error; /* ssl error handler */ #endif } wrkrInstanceData_t; static struct cnfparamdescr actpdescr[] = { {"server", eCmdHdlrGetWord, 0}, {"serverport", eCmdHdlrInt, 0}, {"socketpath", eCmdHdlrGetWord, 0}, {"serverpassword", eCmdHdlrGetWord, 0}, {"template", eCmdHdlrGetWord, 0}, {"mode", eCmdHdlrGetWord, 0}, {"key", eCmdHdlrGetWord, 0}, {"expiration", eCmdHdlrInt, 0}, {"dynakey", eCmdHdlrBinary, 0}, {"userpush", eCmdHdlrBinary, 0}, {"stream.outField", eCmdHdlrGetWord, 0}, {"stream.capacityLimit", eCmdHdlrNonNegInt, 0}, {"stream.ack", eCmdHdlrBinary, 0}, {"stream.del", eCmdHdlrBinary, 0}, {"stream.keyAck", eCmdHdlrGetWord, 0}, {"stream.groupAck", eCmdHdlrGetWord, 0}, {"stream.indexAck", eCmdHdlrGetWord, 0}, {"stream.dynaKeyAck", eCmdHdlrBinary, 0}, {"stream.dynaGroupAck", eCmdHdlrBinary, 0}, {"stream.dynaIndexAck", eCmdHdlrBinary, 0}, #ifdef HIREDIS_SSL {"use_tls", eCmdHdlrBinary, 0}, {"ca_cert_bundle", eCmdHdlrGetWord, 0}, {"ca_cert_dir", eCmdHdlrGetWord, 0}, {"client_cert", eCmdHdlrGetWord, 0}, {"client_key", eCmdHdlrGetWord, 0}, {"sni", eCmdHdlrGetWord, 0}, #endif }; static struct cnfparamblk actpblk = {CNFPARAMBLK_VERSION, sizeof(actpdescr) / sizeof(struct cnfparamdescr), actpdescr}; BEGINcreateInstance CODESTARTcreateInstance; ENDcreateInstance BEGINsetActionInfo CODESTARTsetActionInfo; pData->pAction = pAction; ENDsetActionInfo BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; pWrkrData->conn = NULL; /* Connect later */ #ifdef HIREDIS_SSL pWrkrData->ssl_conn = NULL; /* Connect later */ pWrkrData->ssl_error = REDIS_SSL_CTX_NONE; #endif ENDcreateWrkrInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; if (eFeat == sFEATURERepeatedMsgReduction) iRet = RS_RET_OK; ENDisCompatibleWithFeature /* called when closing */ static void closeHiredis(wrkrInstanceData_t *pWrkrData) { if (pWrkrData->conn != NULL) { redisFree(pWrkrData->conn); pWrkrData->conn = NULL; } #ifdef HIREDIS_SSL if (pWrkrData->ssl_conn != NULL) { redisFreeSSLContext(pWrkrData->ssl_conn); pWrkrData->ssl_conn = NULL; } #endif } /* Free our instance data. */ BEGINfreeInstance CODESTARTfreeInstance; if (pData->server != NULL) { free(pData->server); } if (pData->socketPath != NULL) { free(pData->socketPath); } free(pData->key); free(pData->modeDescription); free(pData->serverpassword); free(pData->tplName); free(pData->streamKeyAck); free(pData->streamGroupAck); free(pData->streamIndexAck); free(pData->streamOutField); #ifdef HIREDIS_SSL free(pData->ca_cert_bundle); free(pData->ca_cert_dir); free(pData->client_cert); free(pData->client_key); free(pData->sni); #endif ENDfreeInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; closeHiredis(pWrkrData); ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; /* nothing special here */ ENDdbgPrintInstInfo /* establish our connection to redis */ static rsRetVal initHiredis(wrkrInstanceData_t *pWrkrData, int bSilent) { char *server; sbool udsAddr = 0; redisReply *reply = NULL; DEFiRet; if (pWrkrData->pData->server != NULL) { server = (char *)pWrkrData->pData->server; } else if (pWrkrData->pData->socketPath != NULL) { udsAddr = 1; server = (char *)pWrkrData->pData->socketPath; } else { server = (char *)"127.0.0.1"; } struct timeval timeout = {1, 500000}; /* 1.5 seconds */ if (udsAddr) { LogMsg(0, RS_RET_OK, LOG_INFO, "omhiredis[%s]: trying connect to UDS socket '%s'", actionGetName(pWrkrData->pData->pAction), server); pWrkrData->conn = redisConnectUnixWithTimeout(server, timeout); } else { LogMsg(0, RS_RET_OK, LOG_INFO, "omhiredis[%s]: trying connect to '%s' at port %d", actionGetName(pWrkrData->pData->pAction), server, pWrkrData->pData->port); pWrkrData->conn = redisConnectWithTimeout(server, pWrkrData->pData->port, timeout); } if (pWrkrData->conn == NULL || pWrkrData->conn->err) { if (!bSilent) { const char *err_str = pWrkrData->conn == NULL ? "could not allocate context!" : pWrkrData->conn->errstr; if (udsAddr) { LogError(0, RS_RET_REDIS_ERROR, "omhiredis[%s]: can not connect to redis UDS socket '%s' -> %s", actionGetName(pWrkrData->pData->pAction), server, err_str); } else { LogError(0, RS_RET_REDIS_ERROR, "omhiredis[%s]: can not connect to redis server '%s', " "port %d -> %s", actionGetName(pWrkrData->pData->pAction), server, pWrkrData->pData->port, err_str); } } ABORT_FINALIZE(RS_RET_SUSPENDED); } #ifdef HIREDIS_SSL if (pWrkrData->pData->use_tls) { const char *tls_server_name = pWrkrData->pData->sni; if (tls_server_name == NULL && pWrkrData->pData->server != NULL) { tls_server_name = (const char *)pWrkrData->pData->server; } pWrkrData->ssl_conn = redisCreateSSLContext(pWrkrData->pData->ca_cert_bundle, pWrkrData->pData->ca_cert_dir, pWrkrData->pData->client_cert, pWrkrData->pData->client_key, tls_server_name, &pWrkrData->ssl_error); if (!pWrkrData->ssl_conn || pWrkrData->ssl_error != REDIS_SSL_CTX_NONE) { LogError(0, NO_ERRCODE, "omhiredis[%s]: SSL Context error: %s", actionGetName(pWrkrData->pData->pAction), redisSSLContextGetError(pWrkrData->ssl_error)); if (!bSilent) LogError(0, RS_RET_SUSPENDED, "omhiredis[%s]: can not initialize TLS context", actionGetName(pWrkrData->pData->pAction)); ABORT_FINALIZE(RS_RET_SUSPENDED); } if (redisInitiateSSLWithContext(pWrkrData->conn, pWrkrData->ssl_conn) != REDIS_OK) { LogError(0, NO_ERRCODE, "omhiredis[%s]: %s", actionGetName(pWrkrData->pData->pAction), pWrkrData->conn->errstr); if (!bSilent) LogError(0, RS_RET_SUSPENDED, "omhiredis[%s]: [TLS] can not initialize redis handle", actionGetName(pWrkrData->pData->pAction)); ABORT_FINALIZE(RS_RET_SUSPENDED); } } #endif if (pWrkrData->pData->serverpassword != NULL) { reply = redisCommand(pWrkrData->conn, "AUTH %s", (char *)pWrkrData->pData->serverpassword); if (reply == NULL) { DBGPRINTF("omhiredis: could not get reply from AUTH command\n"); ABORT_FINALIZE(RS_RET_SUSPENDED); } else if (reply->type == REDIS_REPLY_ERROR) { LogError(0, NO_ERRCODE, "omhiredis[%s]: error while authenticating: %s", actionGetName(pWrkrData->pData->pAction), reply->str); ABORT_FINALIZE(RS_RET_ERR); } } finalize_it: if (iRet != RS_RET_OK && pWrkrData->conn != NULL) { redisFree(pWrkrData->conn); pWrkrData->conn = NULL; } #ifdef HIREDIS_SSL if (iRet != RS_RET_OK && pWrkrData->ssl_conn != NULL) { redisFreeSSLContext(pWrkrData->ssl_conn); pWrkrData->ssl_conn = NULL; } #endif if (reply != NULL) freeReplyObject(reply); RETiRet; } static rsRetVal isMaster(wrkrInstanceData_t *pWrkrData) { DEFiRet; redisReply *reply = NULL; assert(pWrkrData->conn != NULL); reply = redisCommand(pWrkrData->conn, "ROLE"); if (reply == NULL) { LogMsg(0, RS_RET_OK, LOG_WARNING, "omhiredis[%s]: could not get reply from ROLE command", actionGetName(pWrkrData->pData->pAction)); ABORT_FINALIZE(RS_RET_SUSPENDED); } else if (reply->type == REDIS_REPLY_ERROR) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_WARNING, "omhiredis[%s]: got an error while querying role -> %s", actionGetName(pWrkrData->pData->pAction), reply->str); ABORT_FINALIZE(RS_RET_SUSPENDED); } else if (reply->type != REDIS_REPLY_ARRAY || reply->element[0]->type != REDIS_REPLY_STRING) { LogMsg(0, RS_RET_REDIS_ERROR, LOG_ERR, "omhiredis[%s]: did not get a proper reply from ROLE command", actionGetName(pWrkrData->pData->pAction)); ABORT_FINALIZE(RS_RET_SUSPENDED); } else { if (strncmp(reply->element[0]->str, "master", 6)) { LogMsg(0, RS_RET_OK, LOG_WARNING, "omhiredis[%s]: current connected node is not a master", actionGetName(pWrkrData->pData->pAction)); ABORT_FINALIZE(RS_RET_SUSPENDED); } } finalize_it: free(reply); RETiRet; } static rsRetVal writeHiredis(uchar *key, uchar *message, wrkrInstanceData_t *pWrkrData) { DEFiRet; int rc, expire; size_t msgLen; char *formattedMsg = NULL; /* if we do not have a redis connection, call * initHiredis and try to establish one */ if (pWrkrData->conn == NULL) CHKiRet(initHiredis(pWrkrData, 0)); /* try to append the command to the pipeline. * REDIS_ERR reply indicates something bad * happened, in which case abort. otherwise * increase our current pipeline count * by 1 and continue. */ switch (pWrkrData->pData->mode) { case OMHIREDIS_MODE_TEMPLATE: rc = redisAppendCommand(pWrkrData->conn, (char *)message); break; case OMHIREDIS_MODE_QUEUE: rc = redisAppendCommand(pWrkrData->conn, pWrkrData->pData->useRPush ? "RPUSH %s %s" : "LPUSH %s %s", key, (char *)message); break; case OMHIREDIS_MODE_PUBLISH: rc = redisAppendCommand(pWrkrData->conn, "PUBLISH %s %s", key, (char *)message); break; case OMHIREDIS_MODE_SET: expire = pWrkrData->pData->expiration; if (expire > 0) msgLen = redisFormatCommand(&formattedMsg, "SETEX %s %d %s", key, expire, message); else msgLen = redisFormatCommand(&formattedMsg, "SET %s %s", key, message); if (msgLen) rc = redisAppendFormattedCommand(pWrkrData->conn, formattedMsg, msgLen); else { dbgprintf("omhiredis: could not append SET command\n"); rc = REDIS_ERR; } break; case OMHIREDIS_MODE_STREAM: if (pWrkrData->pData->streamCapacityLimit != 0) { rc = redisAppendCommand(pWrkrData->conn, "XADD %s MAXLEN ~ %d * %s %s", key, pWrkrData->pData->streamCapacityLimit, pWrkrData->pData->streamOutField, message); } else { rc = redisAppendCommand(pWrkrData->conn, "XADD %s * %s %s", key, pWrkrData->pData->streamOutField, message); } break; default: dbgprintf("omhiredis: mode %d is invalid something is really wrong\n", pWrkrData->pData->mode); ABORT_FINALIZE(RS_RET_ERR); } if (rc == REDIS_ERR) { LogError(0, NO_ERRCODE, "omhiredis[%s]: %s", actionGetName(pWrkrData->pData->pAction), pWrkrData->conn->errstr); dbgprintf("omhiredis: %s\n", pWrkrData->conn->errstr); ABORT_FINALIZE(RS_RET_ERR); } else { pWrkrData->count++; } finalize_it: free(formattedMsg); RETiRet; } static rsRetVal ackHiredisStreamIndex(wrkrInstanceData_t *pWrkrData, uchar *key, uchar *group, uchar *index) { DEFiRet; if (REDIS_ERR == redisAppendCommand(pWrkrData->conn, "XACK %s %s %s", key, group, index)) { LogError(0, NO_ERRCODE, "omhiredis[%s]: %s", actionGetName(pWrkrData->pData->pAction), pWrkrData->conn->errstr); DBGPRINTF("omhiredis: %s\n", pWrkrData->conn->errstr); ABORT_FINALIZE(RS_RET_ERR); } else { pWrkrData->count++; } finalize_it: RETiRet; } static rsRetVal delHiredisStreamIndex(wrkrInstanceData_t *pWrkrData, uchar *key, uchar *index) { DEFiRet; if (REDIS_ERR == redisAppendCommand(pWrkrData->conn, "XDEL %s %s", key, index)) { LogError(0, NO_ERRCODE, "omhiredis[%s]: %s", actionGetName(pWrkrData->pData->pAction), pWrkrData->conn->errstr); DBGPRINTF("omhiredis: %s\n", pWrkrData->conn->errstr); ABORT_FINALIZE(RS_RET_ERR); } else { pWrkrData->count++; } finalize_it: RETiRet; } /* called when resuming from suspended state. * try to restablish our connection to redis */ BEGINtryResume CODESTARTtryResume; closeHiredis(pWrkrData); CHKiRet(initHiredis(pWrkrData, 0)); // Must get a master node for all modes, except 'publish' if (pWrkrData->pData->mode != OMHIREDIS_MODE_PUBLISH) { CHKiRet(isMaster(pWrkrData)); } finalize_it: ENDtryResume /* begin a transaction. * if I decide to use MULTI ... EXEC in the * future, this block should send the * MULTI command to redis. */ BEGINbeginTransaction CODESTARTbeginTransaction; dbgprintf("omhiredis: beginTransaction called\n"); pWrkrData->count = 0; ENDbeginTransaction /* call writeHiredis for this log line, * which appends it as a command to the * current pipeline */ BEGINdoAction uchar *message, *key, *keyNameAck, *groupNameAck, *IndexNameAck; int inputIndex = 0; CODESTARTdoAction; // Don't change the order of conditions/assignations here without changing the end of the newActInst function! message = ppString[inputIndex++]; key = pWrkrData->pData->dynaKey ? ppString[inputIndex++] : pWrkrData->pData->key; keyNameAck = pWrkrData->pData->streamDynaKeyAck ? ppString[inputIndex++] : pWrkrData->pData->streamKeyAck; groupNameAck = pWrkrData->pData->streamDynaGroupAck ? ppString[inputIndex++] : pWrkrData->pData->streamGroupAck; IndexNameAck = pWrkrData->pData->streamDynaIndexAck ? ppString[inputIndex++] : pWrkrData->pData->streamIndexAck; CHKiRet(writeHiredis(key, message, pWrkrData)); if (pWrkrData->pData->streamAck) { CHKiRet(ackHiredisStreamIndex(pWrkrData, keyNameAck, groupNameAck, IndexNameAck)); } if (pWrkrData->pData->streamDel) { CHKiRet(delHiredisStreamIndex(pWrkrData, keyNameAck, IndexNameAck)); } iRet = RS_RET_DEFER_COMMIT; finalize_it: ENDdoAction /* called when we have reached the end of a * batch (queue.dequeuebatchsize). this * iterates over the replies, putting them * into the pData->replies buffer. we currently * don't really bother to check for errors * which should be fixed */ BEGINendTransaction CODESTARTendTransaction; dbgprintf("omhiredis: endTransaction called\n"); redisReply *reply; int i; for (i = 0; i < pWrkrData->count; i++) { if (REDIS_OK != redisGetReply(pWrkrData->conn, (void *)&reply) || pWrkrData->conn->err) { dbgprintf("omhiredis: %s\n", pWrkrData->conn->errstr); LogError(0, RS_RET_REDIS_ERROR, "omhiredis[%s]: Error while processing replies: %s", actionGetName(pWrkrData->pData->pAction), pWrkrData->conn->errstr); closeHiredis(pWrkrData); ABORT_FINALIZE(RS_RET_SUSPENDED); } else { if (reply->type == REDIS_REPLY_ERROR) { LogError(0, RS_RET_REDIS_ERROR, "omhiredis[%s]: Received error from redis -> %s", actionGetName(pWrkrData->pData->pAction), reply->str); closeHiredis(pWrkrData); freeReplyObject(reply); ABORT_FINALIZE(RS_RET_SUSPENDED); } freeReplyObject(reply); } } finalize_it: ENDendTransaction /* set defaults. note server is set to NULL * and is set to a default in initHiredis if * it is still null when it's called - I should * probable just set the default here instead */ static void setInstParamDefaults(instanceData *pData) { pData->server = NULL; pData->socketPath = NULL; pData->port = 6379; pData->serverpassword = NULL; pData->tplName = NULL; pData->mode = OMHIREDIS_MODE_TEMPLATE; pData->expiration = 0; pData->modeDescription = NULL; pData->key = NULL; pData->dynaKey = 0; pData->useRPush = 0; pData->streamOutField = NULL; pData->streamKeyAck = NULL; pData->streamDynaKeyAck = 0; pData->streamGroupAck = NULL; pData->streamDynaGroupAck = 0; pData->streamIndexAck = NULL; pData->streamDynaIndexAck = 0; pData->streamCapacityLimit = 0; pData->streamAck = 0; pData->streamDel = 0; #ifdef HIREDIS_SSL pData->use_tls = 0; pData->ca_cert_bundle = NULL; pData->ca_cert_dir = NULL; pData->client_cert = NULL; pData->client_key = NULL; pData->sni = NULL; #endif pData->pAction = NULL; } /* here is where the work to set up a new instance * is done. this reads the config options from * the rsyslog conf and takes appropriate setup * actions. */ BEGINnewActInst struct cnfparamvals *pvals; int i; int iNumTpls; uchar *strDup = NULL; CODESTARTnewActInst; if ((pvals = nvlstGetParams(lst, &actpblk, NULL)) == NULL) ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); CHKiRet(createInstance(&pData)); setInstParamDefaults(pData); for (i = 0; i < actpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(actpblk.descr[i].name, "server")) { CHKmalloc(pData->server = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "serverport")) { pData->port = (int)pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "socketpath")) { CHKmalloc(pData->socketPath = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "serverpassword")) { CHKmalloc(pData->serverpassword = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "template")) { CHKmalloc(pData->tplName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "dynakey")) { pData->dynaKey = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "userpush")) { pData->useRPush = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.outField")) { CHKmalloc(pData->streamOutField = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "stream.keyAck")) { CHKmalloc(pData->streamKeyAck = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "stream.dynaKeyAck")) { pData->streamDynaKeyAck = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.groupAck")) { CHKmalloc(pData->streamGroupAck = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "stream.dynaGroupAck")) { pData->streamDynaGroupAck = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.indexAck")) { CHKmalloc(pData->streamIndexAck = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "stream.dynaIndexAck")) { pData->streamDynaIndexAck = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.capacityLimit")) { pData->streamCapacityLimit = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.ack")) { pData->streamAck = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "stream.del")) { pData->streamDel = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "mode")) { CHKmalloc(pData->modeDescription = es_str2cstr(pvals[i].val.d.estr, NULL)); if (!strcmp(pData->modeDescription, "template")) { pData->mode = OMHIREDIS_MODE_TEMPLATE; } else if (!strcmp(pData->modeDescription, "queue")) { pData->mode = OMHIREDIS_MODE_QUEUE; } else if (!strcmp(pData->modeDescription, "publish")) { pData->mode = OMHIREDIS_MODE_PUBLISH; } else if (!strcmp(pData->modeDescription, "set")) { pData->mode = OMHIREDIS_MODE_SET; } else if (!strcmp(pData->modeDescription, "stream")) { pData->mode = OMHIREDIS_MODE_STREAM; } else { dbgprintf("omhiredis: unsupported mode %s\n", actpblk.descr[i].name); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } } else if (!strcmp(actpblk.descr[i].name, "key")) { CHKmalloc(pData->key = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "expiration")) { pData->expiration = pvals[i].val.d.n; dbgprintf("omhiredis: expiration set to %d\n", pData->expiration); #ifdef HIREDIS_SSL } else if (!strcmp(actpblk.descr[i].name, "use_tls")) { pData->use_tls = pvals[i].val.d.n; } else if (!strcmp(actpblk.descr[i].name, "ca_cert_bundle")) { CHKmalloc(pData->ca_cert_bundle = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "ca_cert_dir")) { CHKmalloc(pData->ca_cert_dir = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "client_cert")) { CHKmalloc(pData->client_cert = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "client_key")) { CHKmalloc(pData->client_key = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); } else if (!strcmp(actpblk.descr[i].name, "sni")) { CHKmalloc(pData->sni = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); #endif } else { dbgprintf( "omhiredis: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } dbgprintf("omhiredis: checking config sanity\n"); #ifdef HIREDIS_SSL if ((pData->client_cert == NULL) ^ (pData->client_key == NULL)) { parser_errmsg("omhiredis: \"client_cert\" and \"client_key\" must be specified together!"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } if (pData->use_tls && pData->sni == NULL && pData->server == NULL) { parser_errmsg("omhiredis: TLS requires either \"server\" or \"sni\" to validate server identity"); ABORT_FINALIZE(RS_RET_PARAM_ERROR); } #endif if (!pData->modeDescription) { parser_warnmsg("omhiredis: no mode specified, setting it to 'template'\n"); pData->mode = OMHIREDIS_MODE_TEMPLATE; } if (pData->mode == OMHIREDIS_MODE_STREAM && !pData->streamOutField) { parser_warnmsg("omhiredis: no stream.outField set, using 'msg' as default"); pData->streamOutField = ustrdup("msg"); } if (pData->server != NULL && pData->socketPath != NULL) { parser_warnmsg("omhiredis: both 'server' and 'socketpath' are set; 'socketpath' will be ignored"); free(pData->socketPath); pData->socketPath = NULL; } if (pData->tplName == NULL) { if (pData->mode == OMHIREDIS_MODE_TEMPLATE) { parser_errmsg("omhiredis: selected mode requires a template"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } else { CHKmalloc(pData->tplName = ustrdup("RSYSLOG_ForwardFormat")); parser_warnmsg("omhiredis: no template set, using RSYSLOG_ForwardFormat as default"); } } if (pData->mode != OMHIREDIS_MODE_TEMPLATE && pData->key == NULL) { parser_errmsg("omhiredis: mode %s requires a key", pData->modeDescription); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (pData->expiration && pData->mode != OMHIREDIS_MODE_SET) { parser_warnmsg("omhiredis: expiration set but mode is not 'set', expiration will be ignored"); } if (pData->mode != OMHIREDIS_MODE_STREAM) { if (pData->streamOutField) { parser_warnmsg("omhiredis: stream.outField set but mode is not 'stream', field will be ignored"); } if (pData->streamAck) { parser_warnmsg("omhiredis: stream.ack set but mode is not 'stream', XACK will be ignored"); } if (pData->streamDel) { parser_warnmsg("omhiredis: stream.del set but mode is not 'stream', XDEL will be ignored"); } if (pData->streamCapacityLimit) { parser_warnmsg( "omhiredis: stream.capacityLimit set " "but mode is not 'stream', stream trimming will be ignored"); } if (pData->streamKeyAck) { parser_warnmsg( "omhiredis: stream.keyAck set " "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaKeyAck) { parser_warnmsg( "omhiredis: stream.dynaKeyAck set " "but mode is not 'stream', parameter will be ignored"); } if (pData->streamGroupAck) { parser_warnmsg( "omhiredis: stream.groupAck set " "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaGroupAck) { parser_warnmsg( "omhiredis: stream.dynaGroupAck set " "but mode is not 'stream', parameter will be ignored"); } if (pData->streamIndexAck) { parser_warnmsg( "omhiredis: stream.indexAck set " "but mode is not 'stream', parameter will be ignored"); } if (pData->streamDynaIndexAck) { parser_warnmsg( "omhiredis: stream.dynaIndexAck set " "but mode is not 'stream', parameter will be ignored"); } } else { if (pData->streamAck) { if (!pData->streamKeyAck || !pData->streamGroupAck || !pData->streamIndexAck) { parser_errmsg( "omhiredis: 'stream.ack' is set but one of " "'stream.keyAck', 'stream.groupAck' or 'stream.indexAck' is missing"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } } if (pData->streamDel) { if (!pData->streamKeyAck || !pData->streamIndexAck) { parser_errmsg( "omhiredis: 'stream.del' is set but one of " "'stream.keyAck' or 'stream.indexAck' is missing"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } } } if (pData->streamDynaKeyAck && pData->streamKeyAck == NULL) { parser_warnmsg("omhiredis: 'stream.dynaKeyAck' set but 'stream.keyAck' is empty, disabling"); pData->streamDynaKeyAck = 0; } if (pData->streamDynaGroupAck && pData->streamGroupAck == NULL) { parser_warnmsg("omhiredis: 'stream.dynaGroupAck' set but 'stream.groupAck' is empty, disabling"); pData->streamDynaGroupAck = 0; } if (pData->streamDynaIndexAck && pData->streamIndexAck == NULL) { parser_warnmsg("omhiredis: 'stream.dynaIndexAck' set but 'stream.indexAck' is empty, disabling"); pData->streamDynaIndexAck = 0; } iNumTpls = 1; if (pData->dynaKey) { assert(pData->key != NULL); iNumTpls += 1; } if (pData->streamDynaKeyAck) { assert(pData->streamKeyAck != NULL); iNumTpls += 1; } if (pData->streamDynaGroupAck) { assert(pData->streamGroupAck != NULL); iNumTpls += 1; } if (pData->streamDynaIndexAck) { assert(pData->streamIndexAck != NULL); iNumTpls += 1; } CODE_STD_STRING_REQUESTnewActInst(iNumTpls); /* Insert templates in opposite order (keep in sync with doAction), order will be * - tplName * - key * - streamKeyAck * - streamGroupAck * - streamIndexAck */ if (pData->streamDynaIndexAck) { CHKmalloc(strDup = ustrdup(pData->streamIndexAck)); CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS)); strDup = NULL; /* handed over */ } if (pData->streamDynaGroupAck) { CHKmalloc(strDup = ustrdup(pData->streamGroupAck)); CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS)); strDup = NULL; /* handed over */ } if (pData->streamDynaKeyAck) { CHKmalloc(strDup = ustrdup(pData->streamKeyAck)); CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS)); strDup = NULL; /* handed over */ } if (pData->dynaKey) { CHKmalloc(strDup = ustrdup(pData->key)); CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, strDup, OMSR_NO_RQD_TPL_OPTS)); strDup = NULL; /* handed over */ } CHKiRet(OMSRsetEntry(*ppOMSR, --iNumTpls, ustrdup(pData->tplName), OMSR_NO_RQD_TPL_OPTS)); CODE_STD_FINALIZERnewActInst; cnfparamvalsDestruct(pvals, &actpblk); free(strDup); ENDnewActInst NO_LEGACY_CONF_parseSelectorAct BEGINmodExit CODESTARTmodExit; ENDmodExit /* register our plugin entry points * with the rsyslog core engine */ BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_SetActionInfo_IF_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; CODEqueryEtryPt_TXIF_OMOD_QUERIES /* supports transaction interface */ ENDqueryEtryPt /* note we do not support rsyslog v5 syntax */ BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* only supports rsyslog 6 configs */ CODEmodInit_QueryRegCFSLineHdlr INITChkCoreFeature(bCoreSupportsBatching, CORE_FEATURE_BATCHING); if (!bCoreSupportsBatching) { LogError(0, NO_ERRCODE, "omhiredis: rsyslog core does not support batching - abort"); ABORT_FINALIZE(RS_RET_ERR); } DBGPRINTF("omhiredis: module compiled with rsyslog version %s.\n", VERSION); #ifdef HIREDIS_SSL // initialize OpenSSL redisInitOpenSSL(); #endif ENDmodInit rsyslog-8.2608.0/contrib/omhiredis/PaxHeaders/Makefile.am0000644000000000000000000000013215132733117020221 xustar0030 mtime=1768666703.860619527 30 atime=1787067434.281010167 30 ctime=1787067797.637785488 rsyslog-8.2608.0/contrib/omhiredis/Makefile.am0000666000175000017500000000043715132733117017673 0ustar00rgerrgerpkglib_LTLIBRARIES = omhiredis.la omhiredis_la_SOURCES = omhiredis.c omhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) $(HIREDIS_SSL_CFLAGS) omhiredis_la_LDFLAGS = -module -avoid-version omhiredis_la_LIBADD = $(HIREDIS_LIBS) $(HIREDIS_SSL_LIBS) EXTRA_DIST = rsyslog-8.2608.0/contrib/omhiredis/PaxHeaders/COPYING0000644000000000000000000000013215035412264017217 xustar0030 mtime=1752569012.330244093 30 atime=1782715518.785788789 30 ctime=1787067797.642785581 rsyslog-8.2608.0/contrib/omhiredis/COPYING0000666000175000017500000010437015035412264016672 0ustar00rgerrger GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . rsyslog-8.2608.0/contrib/omhiredis/PaxHeaders/Makefile.in0000644000000000000000000000013215241076161020232 xustar0030 mtime=1787067505.088331282 30 atime=1787067579.144712542 30 ctime=1787067797.638785506 rsyslog-8.2608.0/contrib/omhiredis/Makefile.in0000664000175000017500000006626715241076161017717 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/omhiredis ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = omhiredis_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_omhiredis_la_OBJECTS = omhiredis_la-omhiredis.lo omhiredis_la_OBJECTS = $(am_omhiredis_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 = omhiredis_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(omhiredis_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/omhiredis_la-omhiredis.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(omhiredis_la_SOURCES) DIST_SOURCES = $(omhiredis_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp COPYING \ README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = omhiredis.la omhiredis_la_SOURCES = omhiredis.c omhiredis_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) $(HIREDIS_CFLAGS) $(HIREDIS_SSL_CFLAGS) omhiredis_la_LDFLAGS = -module -avoid-version omhiredis_la_LIBADD = $(HIREDIS_LIBS) $(HIREDIS_SSL_LIBS) EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/omhiredis/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/omhiredis/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } omhiredis.la: $(omhiredis_la_OBJECTS) $(omhiredis_la_DEPENDENCIES) $(EXTRA_omhiredis_la_DEPENDENCIES) $(AM_V_CCLD)$(omhiredis_la_LINK) -rpath $(pkglibdir) $(omhiredis_la_OBJECTS) $(omhiredis_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/omhiredis_la-omhiredis.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< omhiredis_la-omhiredis.lo: omhiredis.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT omhiredis_la-omhiredis.lo -MD -MP -MF $(DEPDIR)/omhiredis_la-omhiredis.Tpo -c -o omhiredis_la-omhiredis.lo `test -f 'omhiredis.c' || echo '$(srcdir)/'`omhiredis.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/omhiredis_la-omhiredis.Tpo $(DEPDIR)/omhiredis_la-omhiredis.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='omhiredis.c' object='omhiredis_la-omhiredis.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(omhiredis_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o omhiredis_la-omhiredis.lo `test -f 'omhiredis.c' || echo '$(srcdir)/'`omhiredis.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/omhiredis_la-omhiredis.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/omhiredis_la-omhiredis.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/contrib/PaxHeaders/mmtaghostname0000644000000000000000000000013215241076633016775 xustar0030 mtime=1787067803.208889295 30 atime=1787067808.787993257 30 ctime=1787067803.208889295 rsyslog-8.2608.0/contrib/mmtaghostname/0000775000175000017500000000000015241076633016516 5ustar00rgerrgerrsyslog-8.2608.0/contrib/mmtaghostname/PaxHeaders/mmtaghostname.c0000644000000000000000000000013215216464435022065 xustar0030 mtime=1782212893.962265149 30 atime=1782715518.784788772 30 ctime=1787067803.209889313 rsyslog-8.2608.0/contrib/mmtaghostname/mmtaghostname.c0000664000175000017500000001372715216464435021543 0ustar00rgerrger/* mmtaghostname.c * This is a message modification module. * * The name of the module is inspired by the parser module pmnull * Its objectives are closed to this parser but as a message modification * it can be used in a different step of the message processing without * interfering in the parser chain process and can be applied before or * after parsing process. * * Its purposes are : * - to add a tag on message produce by input module which does not provide * a tag like imudp or imtcp. Useful when the tag is used for routing the * message. * - to force message hostname to the rsyslog valeur. The use case is * application in auto-scaling systems (AWS) providing logs through udp/tcp * were the name of the host is based on an ephemeral IPs with a short term * meaning. In this situation rsyslog local host name is generally the * auto-scaling name then logs produced by the application is affected to * the application instead of the ephemeral VM. * * * This file is a contribution of rsyslog. * * Author : Ph. Duveau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include "rsyslog.h" #include "conf.h" #include "syslogd-types.h" #include "template.h" #include "module-template.h" #include "errmsg.h" #include "cfsysline.h" #include "dirty.h" #include "unicode-helper.h" MODULE_TYPE_OUTPUT; MODULE_TYPE_NOKEEP; MODULE_CNFNAME("mmtaghostname") /* internal structures */ DEF_OMOD_STATIC_DATA; DEFobjCurrIf(glbl) /* parser instance parameters */ static struct cnfparamdescr parserpdescr[] = { {"tag", eCmdHdlrString, 0}, {"forcelocalhostname", eCmdHdlrBinary, 0}, }; static struct cnfparamblk parserpblk = {CNFPARAMBLK_VERSION, sizeof(parserpdescr) / sizeof(struct cnfparamdescr), parserpdescr}; typedef struct _instanceData { char *pszTag; size_t lenTag; int bForceLocalHostname; } instanceData; typedef struct wrkrInstanceData { instanceData *pData; } wrkrInstanceData_t; static const uchar *pszHostname = NULL; static size_t lenHostname = 0; BEGINcreateWrkrInstance CODESTARTcreateWrkrInstance; ENDcreateWrkrInstance BEGINfreeWrkrInstance CODESTARTfreeWrkrInstance; ENDfreeWrkrInstance BEGINdbgPrintInstInfo CODESTARTdbgPrintInstInfo; dbgprintf("mmtaghostname:\n"); dbgprintf("\ttag='%s'\n", pData->pszTag); dbgprintf("\tforce local hostname='%d'\n", pData->bForceLocalHostname); ENDdbgPrintInstInfo BEGINcreateInstance CODESTARTcreateInstance; pData->pszTag = NULL; pData->lenTag = 0; pData->bForceLocalHostname = 0; ENDcreateInstance BEGINfreeInstance CODESTARTfreeInstance; free(pData->pszTag); ENDfreeInstance BEGINisCompatibleWithFeature CODESTARTisCompatibleWithFeature; ENDisCompatibleWithFeature BEGINnewActInst struct cnfparamvals *pvals = NULL; int i; CODESTARTnewActInst; DBGPRINTF("newParserInst (mmtaghostname)\n"); CHKiRet(createInstance(&pData)); if (lst == NULL) FINALIZE; /* just set defaults, no param block! */ if ((pvals = nvlstGetParams(lst, &parserpblk, NULL)) == NULL) { ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); } if (Debug) { dbgprintf("parser param blk in mmtaghostname:\n"); cnfparamsPrint(&parserpblk, pvals); } for (i = 0; i < parserpblk.nParams; ++i) { if (!pvals[i].bUsed) continue; if (!strcmp(parserpblk.descr[i].name, "tag")) { CHKmalloc(pData->pszTag = (char *)es_str2cstr(pvals[i].val.d.estr, NULL)); pData->lenTag = strlen(pData->pszTag); } else if (!strcmp(parserpblk.descr[i].name, "forcelocalhostname")) { pData->bForceLocalHostname = pvals[i].val.d.n; } else { dbgprintf("program error, non-handled param '%s'\n", parserpblk.descr[i].name); } } CODE_STD_STRING_REQUESTnewActInst(1); CHKiRet(OMSRsetEntry(*ppOMSR, 0, NULL, OMSR_TPL_AS_MSG)); CODE_STD_FINALIZERnewActInst; if (lst != NULL) cnfparamvalsDestruct(pvals, &parserpblk); ENDnewActInst BEGINdoAction_NoStrings smsg_t **ppMsg = (smsg_t **)pMsgData; smsg_t *pMsg = ppMsg[0]; instanceData *pData = pWrkrData->pData; CODESTARTdoAction; DBGPRINTF("Message will now be managed by mmtaghostname\n"); if (pData->pszTag != NULL) { MsgSetTAG(pMsg, (uchar *)pData->pszTag, pData->lenTag); } if (pData->bForceLocalHostname) { if (pszHostname == NULL) { pszHostname = glbl.GetLocalHostName(); lenHostname = ustrlen(glbl.GetLocalHostName()); } MsgSetHOSTNAME(pMsg, pszHostname, lenHostname); DBGPRINTF("Message hostname forced to local\n"); } ENDdoAction BEGINtryResume CODESTARTtryResume; ENDtryResume BEGINparseSelectorAct CODESTARTparseSelectorAct; CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct BEGINmodExit CODESTARTmodExit; objRelease(glbl, CORE_COMPONENT); ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt; CODEqueryEtryPt_STD_OMOD_QUERIES; CODEqueryEtryPt_STD_OMOD8_QUERIES; CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES; ENDqueryEtryPt BEGINmodInit() CODESTARTmodInit; *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ CODEmodInit_QueryRegCFSLineHdlr CHKiRet(objUse(glbl, CORE_COMPONENT)); ENDmodInit rsyslog-8.2608.0/contrib/mmtaghostname/PaxHeaders/Makefile.am0000644000000000000000000000013215035412264021101 xustar0030 mtime=1752569012.329251042 30 atime=1787067434.228009178 30 ctime=1787067803.203889202 rsyslog-8.2608.0/contrib/mmtaghostname/Makefile.am0000666000175000017500000000035515035412264020552 0ustar00rgerrgerpkglib_LTLIBRARIES = mmtaghostname.la mmtaghostname_la_SOURCES = mmtaghostname.c mmtaghostname_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmtaghostname_la_LDFLAGS = -module -avoid-version mmtaghostname_la_LIBADD = EXTRA_DIST = rsyslog-8.2608.0/contrib/mmtaghostname/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160021112 xustar0030 mtime=1787067504.988329416 30 atime=1787067579.802724813 30 ctime=1787067803.205889239 rsyslog-8.2608.0/contrib/mmtaghostname/Makefile.in0000664000175000017500000006640115241076160020565 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = contrib/mmtaghostname ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__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)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) mmtaghostname_la_DEPENDENCIES = am_mmtaghostname_la_OBJECTS = mmtaghostname_la-mmtaghostname.lo mmtaghostname_la_OBJECTS = $(am_mmtaghostname_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 = mmtaghostname_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(mmtaghostname_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mmtaghostname_la_SOURCES) DIST_SOURCES = $(mmtaghostname_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkglib_LTLIBRARIES = mmtaghostname.la mmtaghostname_la_SOURCES = mmtaghostname.c mmtaghostname_la_CPPFLAGS = $(RSRT_CFLAGS) $(PTHREADS_CFLAGS) mmtaghostname_la_LDFLAGS = -module -avoid-version mmtaghostname_la_LIBADD = EXTRA_DIST = all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 contrib/mmtaghostname/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu contrib/mmtaghostname/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || 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)$(pkglibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \ } uninstall-pkglibLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \ done clean-pkglibLTLIBRARIES: -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES) @list='$(pkglib_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}; \ } mmtaghostname.la: $(mmtaghostname_la_OBJECTS) $(mmtaghostname_la_DEPENDENCIES) $(EXTRA_mmtaghostname_la_DEPENDENCIES) $(AM_V_CCLD)$(mmtaghostname_la_LINK) -rpath $(pkglibdir) $(mmtaghostname_la_OBJECTS) $(mmtaghostname_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mmtaghostname_la-mmtaghostname.lo: mmtaghostname.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmtaghostname_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mmtaghostname_la-mmtaghostname.lo -MD -MP -MF $(DEPDIR)/mmtaghostname_la-mmtaghostname.Tpo -c -o mmtaghostname_la-mmtaghostname.lo `test -f 'mmtaghostname.c' || echo '$(srcdir)/'`mmtaghostname.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mmtaghostname_la-mmtaghostname.Tpo $(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mmtaghostname.c' object='mmtaghostname_la-mmtaghostname.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mmtaghostname_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mmtaghostname_la-mmtaghostname.lo `test -f 'mmtaghostname.c' || echo '$(srcdir)/'`mmtaghostname.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; 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-pkglibLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-pkglibLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mmtaghostname_la-mmtaghostname.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-pkglibLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-pkglibLTLIBRARIES \ 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-pkglibLTLIBRARIES .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/PaxHeaders/config.h.in0000644000000000000000000000013215241076157014572 xustar0030 mtime=1787067503.869308541 30 atime=1787067579.988728281 30 ctime=1787067790.702656254 rsyslog-8.2608.0/config.h.in0000664000175000017500000005342215241076157014244 0ustar00rgerrger/* config.h.in. Generated from configure.ac by autoheader. */ /* Defined if debug mode is enabled (its easier to check). */ #undef DEBUG /* Defined if debugless mode is enabled. */ #undef DEBUGLESS /* Define to 1 if code coverage is enabled. */ #undef ENABLE_COVERAGE /* Define to 1 when libFuzzer targets are enabled. */ #undef ENABLE_FUZZING /* Indicator that GnuTLS is present */ #undef ENABLE_GNUTLS /* Indicator that IMDIAG is present */ #undef ENABLE_IMDIAG /* Indicator that we need to build a dummy imkafka module */ #undef ENABLE_IMKAFKA_DUMMY /* Enable push support in impstats module */ #undef ENABLE_IMPSTATS_PUSH /* Enable epoll mode for the imtcp input module */ #undef ENABLE_IMTCP_EPOLL /* Indicator that libcap-ng is present */ #undef ENABLE_LIBCAPNG /* Indicator that libcap-ng is present */ #undef ENABLE_LIBCAPNG_PRESENT /* Indicator that LIBGCRYPT is present */ #undef ENABLE_LIBGCRYPT /* Indicator that LIBZSTD is present */ #undef ENABLE_LIBZSTD /* Indicator that mbedtls is present */ #undef ENABLE_MBEDTLS /* Indicator that we need to build a dummy module */ #undef ENABLE_MMBDLOOKUP_DUMMY /* Indicator that we need to build a dummy omkafka module */ #undef ENABLE_OMKAFKA_DUMMY /* Enable protobuf encoding in omotel module */ #undef ENABLE_OMOTEL_PROTOBUF /* Indicator that openssl is present */ #undef ENABLE_OPENSSL /* Indicator that openssl(EVP_CIPHER_get_block_size) is present */ #undef ENABLE_OPENSSL_CRYPTO_PROVIDER /* Indicator that ossl driver is present */ #undef ENABLE_OSSL /* Indicator that RELP is present */ #undef ENABLE_RELP /* Indicator that wolfssl is present */ #undef ENABLE_WOLFSSL /* Regular expressions support enabled. */ #undef FEATURE_REGEXP /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* Define to 1 if you have the header file. */ #undef HAVE_APR_BASE64_H /* Define to 1 if you have the header file. */ #undef HAVE_APR_MD5_H /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H /* Define to 1 if you have the `asprintf' function. */ #undef HAVE_ASPRINTF /* Define if compiler provides atomic builtins */ #undef HAVE_ATOMIC_BUILTINS /* Define if compiler provides 64 bit atomic builtins */ #undef HAVE_ATOMIC_BUILTINS64 /* Define to 1 if you have the `basename' function. */ #undef HAVE_BASENAME /* Define to 1 if compiler supports __builtin_expect */ #undef HAVE_BUILTIN_EXPECT /* Define to 1 if your system has a working `chown' function. */ #undef HAVE_CHOWN /* Define to 1 if you have the header file. */ #undef HAVE_CIVETWEB_H /* Define to 1 if you have the `clock_gettime' function. */ #undef HAVE_CLOCK_GETTIME /* Define to 1 if you have the `close_range' function. */ #undef HAVE_CLOSE_RANGE /* Define to 1 if you have the header file. */ #undef HAVE_CURL_CURL_H /* Define to 1 if you have the header file. */ #undef HAVE_DBI_DBI_H /* Define to 1 if libdbi supports the new plugin-safe interface */ #undef HAVE_DBI_R /* Define to 1 if libdbi supports transactions */ #undef HAVE_DBI_TXSUPP /* Define to 1 if you have the declaration of `asprintf', and to 0 if you don't. */ #undef HAVE_DECL_ASPRINTF /* Define to 1 if you have the declaration of `strerror_r', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR_R /* Define to 1 if you have the declaration of `vasprintf', and to 0 if you don't. */ #undef HAVE_DECL_VASPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the `epoll_create' function. */ #undef HAVE_EPOLL_CREATE /* Define to 1 if you have the `epoll_create1' function. */ #undef HAVE_EPOLL_CREATE1 /* 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 `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `gethostbyname' function. */ #undef HAVE_GETHOSTBYNAME /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* set define */ #undef HAVE_GETIFADDRS /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define to 1 if you have the header file. */ #undef HAVE_GLOB_H /* set define */ #undef HAVE_GLOB_NOMAGIC /* Define to 1 if you have the `gnutls_certificate_set_retrieve_function' function. */ #undef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION /* Define to 1 if you have the `gnutls_certificate_type_set_priority' function. */ #undef HAVE_GNUTLS_CERTIFICATE_TYPE_SET_PRIORITY /* Define to 1 if you have the header file. */ #undef HAVE_GROK_H /* Define to 1 if you have the header file. */ #undef HAVE_HADOOP_HDFS_H /* Define to 1 if you have the header file. */ #undef HAVE_HDFS_H /* Define to 1 if you have the `inotify_init' function. */ #undef HAVE_INOTIFY_INIT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* jemalloc support is integrated. */ #undef HAVE_JEMALLOC /* Define to 1 if you have the header file. */ #undef HAVE_LIBGEN_H /* Define to 1 if liblogging-stdlog is available. */ #undef HAVE_LIBLOGGING_STDLOG /* Use v1 of libmongoc */ #undef HAVE_LIBMONGOC1 /* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */ #undef HAVE_LIBMYSQLCLIENT /* Define to 1 if you have the header file. */ #undef HAVE_LIBNET_H /* Define to 1 if you have the header file. */ #undef HAVE_LIBRDKAFKA_RDKAFKA_H /* libsystemd present */ #undef HAVE_LIBSYSTEMD /* Define if libyaml is available */ #undef HAVE_LIBYAML /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_CLOSE_RANGE_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_FS_H /* Define if ln_loadSamplesFromString exists. */ #undef HAVE_LOADSAMPLESFROMSTRING /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R /* liblognorm has turbo VM support */ #undef HAVE_LOGNORM_TURBO /* Define to 1 if you have the `lseek64' function. */ #undef HAVE_LSEEK64 /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `malloc_trim' function. */ #undef HAVE_MALLOC_TRIM /* Define to 1 if you have the header file. */ #undef HAVE_MAXMINDDB_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the header file. */ #undef HAVE_MINIX_CONFIG_H /* Define to 1 if you have the `mkdir' function. */ #undef HAVE_MKDIR /* mysql_library_init available */ #undef HAVE_MYSQL_LIBRARY_INIT /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_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_NET_SNMP_NET_SNMP_CONFIG_H /* Define to 1 if the system has the type `off64_t'. */ #undef HAVE_OFF64_T /* Define to 1 if you have the header file. */ #undef HAVE_PATHS_H /* Define to 1 if you have the header file. */ #undef HAVE_PCAP_H /* PGsslInUse function available */ #undef HAVE_PGSSLINUSE /* Define to 1 if you have the `port_create' function. */ #undef HAVE_PORT_CREATE /* Enable FEN support for imfile */ #undef HAVE_PORT_SOURCE_FILE /* Define to 1 if you have the `prctl' function. */ #undef HAVE_PRCTL /* Define to 1 if you have the header file. */ #undef HAVE_PROTOCOL_H /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Set-kind available for rwlock attr. */ #undef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP /* Can set thread-name. */ #undef HAVE_PTHREAD_SETNAME_NP /* Can set thread scheduling parameters */ #undef HAVE_PTHREAD_SETSCHEDPARAM /* Define if rabbitmq-c/amqp.h exists (rabbitmq-c 0.8.0+) */ #undef HAVE_RABBITMQ_C_AMQP_H /* Define to 1 if you have the `recvmmsg' function. */ #undef HAVE_RECVMMSG /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define if relpCltSetKeepAlive exists. */ #undef HAVE_RELPCLTSETKEEPALIVE /* Define if relpSrvSetTlsConfigCmd exists. */ #undef HAVE_RELPENGINESETTLSCFGCMD /* Define if relpEngineSetTLSLibByName exists. */ #undef HAVE_RELPENGINESETTLSLIBBYNAME /* Define if relpSrvSetLstnAddr exists. */ #undef HAVE_RELPSRVSETLSTNADDR /* Define if relpSrvSetOversizeMode exists. */ #undef HAVE_RELPSRVSETOVERSIZEMODE /* Define to 1 if you have the header file. */ #undef HAVE_RESOLV_H /* Define if resolver provides ns_initparse */ #undef HAVE_RESOLV_NS_INITPARSE /* Define if resolver provides res_n* APIs */ #undef HAVE_RESOLV_RES_N_API /* Define to 1 if you have the `res_nclose' function. */ #undef HAVE_RES_NCLOSE /* Define to 1 if you have the `res_ninit' function. */ #undef HAVE_RES_NINIT /* Define to 1 if you have the `res_nquery' function. */ #undef HAVE_RES_NQUERY /* Define to 1 if you have the `sched_get_priority_max' function. */ #undef HAVE_SCHED_GET_PRIORITY_MAX /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* set define */ #undef HAVE_SCM_CREDENTIALS /* Define to 1 if you have the `sd_journal_open_namespace' function. */ #undef HAVE_SD_JOURNAL_OPEN_NAMESPACE /* Define to 1 if you have the `sd_journal_stream_fd_with_namespace' function. */ #undef HAVE_SD_JOURNAL_STREAM_FD_WITH_NAMESPACE /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the header file. */ #undef HAVE_SEMAPHORE_H /* Define if setns exists. */ #undef HAVE_SETNS /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* snappy has pkg-config */ #undef HAVE_SNAPPY_PKG_CONFIG /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* set define */ #undef HAVE_SO_TIMESTAMP /* 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_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 `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 if you have `strerror_r'. */ #undef HAVE_STRERROR_R /* 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 `strndup' function. */ #undef HAVE_STRNDUP /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ #undef HAVE_STRUCT_SOCKADDR_SA_LEN /* Define to 1 if you have the `syscall' function. */ #undef HAVE_SYSCALL /* set define */ #undef HAVE_SYSINFO_UPTIME /* Define to 1 if you have the header file. */ #undef HAVE_SYS_EPOLL_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_INOTIFY_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_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_QUEUE_H /* Define if sys/queue.h provides STAILQ macros */ #undef HAVE_SYS_QUEUE_STAILQ /* 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_SYSCALL_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 that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* set define */ #undef HAVE_SYS_gettid /* Define to 1 if you have the `ttyname_r' function. */ #undef HAVE_TTYNAME_R /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_UTMPX_H /* Define to 1 if you have the header file. */ #undef HAVE_UTMP_H /* Define to 1 if you have the `vasprintf' function. */ #undef HAVE_VASPRINTF /* 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 you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* TLS support enabled in hiredis */ #undef HIREDIS_SSL /* the host environment, can be queried via a system variable */ #undef HOSTENV /* Define to 1 if `lstat' dereferences a symlink specified with a trailing slash. */ #undef LSTAT_FOLLOWS_SLASHED_SYMLINK /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define with a value if your does not define MAXHOSTNAMELEN */ #undef MAXHOSTNAMELEN /* replacement for missing PATH_MAX */ #undef MAXPATHLEN /* Defined if debug mode is disabled. */ #undef NDEBUG /* new systemd present */ #undef NEW_JOURNAL /* Define if ln_loadSamplesFromString does not exist. */ #undef NO_LOADSAMPLESFROMSTRING /* Define if OpenSSL ENGINE support is missing */ #undef OPENSSL_NO_ENGINE /* Indicator for a AIX OS */ #undef OS_AIX /* Indicator for APPLE OS */ #undef OS_APPLE /* Indicator for a BSD OS */ #undef OS_BSD /* Indicator for a Linux OS */ #undef OS_LINUX /* Indicator for a Solaris OS */ #undef OS_SOLARIS /* 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 /* "Configuration file path (default : /etc/rsyslog.conf)" */ #undef PATH_CONFFILE /* replacement for missing PATH_MAX */ #undef PATH_MAX /* "Pid file path (default : /var/run/rsyslogd.pid)" */ #undef PATH_PIDFILE /* platform id for display purposes */ #undef PLATFORM_ID /* platform id for display purposes */ #undef PLATFORM_ID_LSB /* default port for omrelp */ #undef RELP_DFLT_PT /* Define version of librelp used. */ #undef RELP_VERSION /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* 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 all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Define to 1 if strerror_r returns char *. */ #undef STRERROR_R_CHAR_P /* network support is integrated. */ #undef SYSLOG_INET /* Define to 1 if you can safely include both and . This macro is obsolete. */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Define if you want to use GSSAPI */ #undef USE_GSSAPI /* Using XXHASH for hash64. */ #undef USE_HASH_XXHASH /* Define if you want to enable libuuid support */ #undef USE_LIBUUID /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable general extensions on macOS. */ #ifndef _DARWIN_C_SOURCE # undef _DARWIN_C_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable X/Open compliant socket functions that do not require linking with -lxnet on HP-UX 11.11. */ #ifndef _HPUX_ALT_XOPEN_SOCKET_API # undef _HPUX_ALT_XOPEN_SOCKET_API #endif /* Identify the host operating system as Minix. This macro does not affect the system headers' behavior. A future release of Autoconf may stop defining this macro. */ #ifndef _MINIX # undef _MINIX #endif /* Enable general extensions on NetBSD. Enable NetBSD compatibility extensions on Minix. */ #ifndef _NETBSD_SOURCE # undef _NETBSD_SOURCE #endif /* Enable OpenBSD compatibility extensions on NetBSD. Oddly enough, this does nothing on OpenBSD. */ #ifndef _OPENBSD_SOURCE # undef _OPENBSD_SOURCE #endif /* Define to 1 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_SOURCE # undef _POSIX_SOURCE #endif /* Define to 2 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_1_SOURCE # undef _POSIX_1_SOURCE #endif /* Enable POSIX-compatible threading on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ #ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ # undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ #ifndef __STDC_WANT_IEC_60559_BFP_EXT__ # undef __STDC_WANT_IEC_60559_BFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ # undef __STDC_WANT_IEC_60559_DFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ # undef __STDC_WANT_IEC_60559_FUNCS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # undef __STDC_WANT_IEC_60559_TYPES_EXT__ #endif /* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ #ifndef __STDC_WANT_LIB_EXT2__ # undef __STDC_WANT_LIB_EXT2__ #endif /* Enable extensions specified by ISO/IEC 24747:2009. */ #ifndef __STDC_WANT_MATH_SPEC_FUNCS__ # undef __STDC_WANT_MATH_SPEC_FUNCS__ #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable X/Open extensions. Define to 500 only if necessary to make mbstate_t available. */ #ifndef _XOPEN_SOURCE # undef _XOPEN_SOURCE #endif /* If defined, the select() syscall won't be limited to a particular number of file descriptors. */ #undef USE_UNLIMITED_SELECT /* Defined if valgrind support settings are to be enabled (e.g. prevents dlclose()). */ #undef VALGRIND /* Version number of package */ #undef VERSION /* month part of real rsyslog version */ #undef VERSION_MONTH /* year part of real rsyslog version */ #undef VERSION_YEAR /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* 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 /* Use POSIX pthread semantics */ #undef _POSIX_PTHREAD_SEMANTICS /* 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 /* Use X/Open CAE Specification */ #undef _XOPEN_SOURCE /* 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 `int' if does not define. */ #undef mode_t /* Define to `long int' if does not define. */ #undef off_t /* Define as a signed integer type capable of holding a process identifier. */ #undef pid_t /* 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 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 /* Define to empty if the keyword `volatile' does not work. Warning: valid code using `volatile' can become incorrect without. Disable with care. */ #undef volatile rsyslog-8.2608.0/PaxHeaders/README.md0000644000000000000000000000013115200346625014020 xustar0030 mtime=1778503061.534495863 30 atime=1782715518.799789027 29 ctime=1787067790.74165698 rsyslog-8.2608.0/README.md0000664000175000017500000002303315200346625013466 0ustar00rgerrger# Rsyslog – What Is It? **Rsyslog** is a **r**ocket-fast **sys**tem for **log** processing pipelines. It offers high performance, advanced security features, and a **modular microkernel-like architecture**. Originally a regular syslogd, rsyslog has evolved into a highly versatile logging solution capable of ingesting data from numerous sources, transforming it, and outputting it to a wide variety of destinations. Rsyslog can deliver over one million messages per second to local destinations under minimal processing (based on v7, Dec 2013). Even with complex routing and remote forwarding, performance remains excellent. --- ## Table of Contents - [Getting Rsyslog News](#getting-rsyslog-news) - [🤖 Rsyslog Assistant (Experimental AI Help)](#rsyslog-assistant-experimental-ai-help) - [Getting Help (Other Sources)](#getting-help-other-sources) - [Installation](#installation) - [Contributing](#contributing) - [AI-Based Code Review (Experimental)](#ai-based-code-review-experimental) - [Documentation](#documentation) - [Project Philosophy](#project-philosophy) - [Global Accessibility and Collaboration](#global-accessibility-and-collaboration) - [Sponsors](#sponsors) - [Legal Notice (GDPR)](#legal-notice-gdpr) --- ## Getting Rsyslog News Stay up to date with official rsyslog announcements and community insights: **Official Channels** * [Website](https://rsyslog.com/) – official news and documentation * [RSS Feed](https://rsyslog.com/feed/) * [Telegram](https://t.me/rsyslog_official) * [WhatsApp](https://whatsapp.com/channel/0029VbBJQLhCxoArVHjrL32E) **Maintainer Insights** Updates, technical commentary, and behind-the-scenes notes from [Rainer Gerhards](https://www.linkedin.com/in/rgerhards/), rsyslog founder and maintainer: * [LinkedIn](https://www.linkedin.com/in/rgerhards/) * [X (Twitter)](https://x.com/rgerhards) * [Blog – rainer-gerhards.net](https://rainer.gerhards.net/) --- ## 🤖 Rsyslog Assistant (Experimental AI Help) Need help with rsyslog configuration or troubleshooting? Try the **[rsyslog Assistant](https://rsyslog.ai)** — your AI-powered support tool built by the rsyslog team. > ⚠� *Experimental.* May occasionally generate incorrect config examples — always review before applying. ✅ Trained on official docs and changelogs ✅ Covers both Linux rsyslog and Windows Agent ✅ Version-aware and best-practice focused 👉 Try it now: [rsyslog.ai](https://rsyslog.ai) --- ## Getting Help (Other Sources) * **💬 GitHub Discussions:** [Ask questions or start a conversation](https://github.com/rsyslog/rsyslog/discussions) * **📧 Mailing List:** [rsyslog mailing list](https://lists.adiscon.net/mailman/listinfo/rsyslog) * **� GitHub Issues:** [Open an issue](https://github.com/rsyslog/rsyslog/issues) --- ## Installation ### Via Distribution Package Managers Rsyslog is available in most Linux distribution repositories and often is pre-installed. ### Project-Provided Packages (Latest Versions) Distributions may lag behind in packaging the latest rsyslog releases. Official builds for newer versions are available here: * [RPM-based systems](https://rsyslog.com/rhelcentos-rpms/) * [Ubuntu](https://rsyslog.com/ubuntu-repository/) * [Debian](https://rsyslog.com/debian-repository/) * [Official Containers](packaging/docker/README.md) For users in regions where GitHub access is limited, see the [Global Accessibility and Collaboration](#global-accessibility-and-collaboration) section for alternative mirrors.
Building from Source (click to expand) See: [Build Instructions](https://rsyslog.com/doc/v8-stable/installation/build_from_repo.html) #### Build Environment Requirements * `pkg-config` * `libestr` * `liblogging` (stdlog component, for testbench) Build support libraries from source if you're working with the latest git master. #### Branch Guidance The `master` branch tracks active development. For production use, prefer the latest tagged release. #### OS-Specific Build Instructions Refer to the respective section in the original README for required packages on CentOS, Ubuntu, Debian, SUSE, etc. #### Development Containers & Testing Ready-to-use build environments are provided in `packaging/docker/dev_env`. These images were previously built in the separate [rsyslog-docker](https://github.com/rsyslog/rsyslog-docker) repository and are now maintained here. See `packaging/docker/README.md` for details. Runtime container definitions are in `packaging/docker/rsyslog`. Run the test suite inside the container with: ```bash make check -j4 ```
--- ## Contributing Rsyslog is a community-driven open-source project. Contributions are welcome and encouraged! * See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines * Starter tasks: [Good First Issues](https://rsyslog.com/tool_good-first-issues) * To develop new output plugins in Python or Perl, see [plugins/external/README.md](plugins/external/README.md) * If you're working with AI coding agents (e.g. GitHub Copilot, OpenAI Codex), see [AGENTS.md](AGENTS.md) * Community: [Code of Conduct](CODE_OF_CONDUCT.md) If GitHub access is difficult in your region, please contact us or use one of the mirrors listed below; we will help route your patch for review. **Commit Assistant (recommended):** Draft compliant commit messages with [rsyslog Commit Assistant](https://rsyslog.com/tool_rsyslog-commit-assistant) and follow rules in [CONTRIBUTING.md](CONTRIBUTING.md). Put the substance into the **commit message** (amend before PR if needed). --- ### AI-Based Code Review (Experimental) We are currently testing AI-based code review for pull requests. At this time, we use **Google Gemini** to automatically analyze code and provide comments on new PRs. * Reviews are **informational only** * Every contribution is still **manually reviewed** by human experts * The goal is to evaluate how AI can support contributor feedback and code quality assurance Please report any issues, false positives, or suggestions about the AI review process. --- ## Documentation Documentation is located in the `doc/` directory of this repository. Contributions to the documentation should be made there. Visit the latest version online: * [docs.rsyslog.com/doc](https://docs.rsyslog.com/doc/) --- ## Project Philosophy Rsyslog development is driven by real-world use cases, open standards, and an active community. While sponsored primarily by Adiscon, technical decisions are made independently via consensus. All contributors are welcome — there is no formal membership beyond participation. --- ## Global Accessibility and Collaboration Rsyslog aims to remain accessible worldwide. Different regions sometimes face network or platform limits, so we provide mirrors to ensure that everyone can obtain the source code and contribute on equal terms. - **GitHub (canonical):** https://github.com/rsyslog/rsyslog - **European mirror (Germany, hosted on DigitalOcean):** https://github-mirror.rsyslog.com/rsyslog/rsyslog - **Community mirror (China, maintained by Gitee):** https://gitee.com/mirrors_rsyslog All pull requests ultimately flow through GitHub, where our CI and review infrastructure run. If you experience access issues but can provide a patch, the rsyslog team will gladly assist in forwarding it to GitHub. Our contribution workflow remains GitHub-based for now because CI and automated testing are tightly integrated there. Always verify releases and tags from the official GitHub repository before production use. > *Open source should have no borders.* > (FR) Le code ouvert ne devrait pas avoir de frontières > (ZH) 开�应该没有边界 > (JA) オープンソース�国境��� > (ES) El código abierto no debe tener fronteras > (HI) ओपन सोर�स की कोई सीमा�� नहीं होनी चाहि� > (AR) المصدر الم�توح يجب ألا يكون له حدود --- ## Sponsors The rsyslog project is proudly supported by organizations that help sustain its continuous development, infrastructure, and innovation. (See also [Project Philosophy](#project-philosophy).) ### Prime Sponsor **[Adiscon GmbH](https://www.adiscon.com/)** Adiscon employs core rsyslog developers including Rainer Gerhards and provides ongoing engineering, infrastructure, and CI resources. Through its commercial Windows log management products — such as [WinSyslog](https://www.winsyslog.com/) and [Rsyslog Windows Agent](https://www.winsyslog.com/rsyslog-windows-agent/) — Adiscon helps fund rsyslog’s continued open-source development and ecosystem growth. ### Major Sponsor

DigitalOcean Logo

**[DigitalOcean](https://www.digitalocean.com/)** powers key parts of rsyslog’s CI pipeline, package distribution network, and AI infrastructure as part of their [#DOforOpenSource](https://www.digitalocean.com/open-source) initiative. Their support enables fast, globally available builds and the next generation of AI-assisted rsyslog documentation and tooling. ### Additional Acknowledgments rsyslog also benefits from various open-source infrastructure providers and community initiatives that make modern CI, code hosting, and collaboration possible. --- _If your organization benefits from rsyslog and would like to contribute to its sustainability, please consider [sponsoring or contributing](https://github.com/sponsors/rsyslog)._ --- ## Legal Notice (GDPR) Contributions to rsyslog are stored in git history and publicly distributed. rsyslog-8.2608.0/PaxHeaders/compat0000644000000000000000000000013215241076622013752 xustar0030 mtime=1787067794.017718029 30 atime=1787067808.787993257 30 ctime=1787067794.017718029 rsyslog-8.2608.0/compat/0000775000175000017500000000000015241076622013473 5ustar00rgerrgerrsyslog-8.2608.0/compat/PaxHeaders/asprintf.c0000644000000000000000000000013215216464435016026 xustar0030 mtime=1782212893.956265052 30 atime=1787067616.138402361 30 ctime=1787067794.012717936 rsyslog-8.2608.0/compat/asprintf.c0000664000175000017500000000401215216464435015467 0ustar00rgerrger/* compatibility file for systems without asprintf. * * Copyright 2019 P Duveau * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #if !defined(HAVE_VASPRINTF) || !defined(HAVE_ASPRINTF) static int compat_vasprintf_impl(char **strp, const char *fmt, va_list ap) #if defined(__GNUC__) __attribute__((format(printf, 2, 0))) #endif ; static int compat_vasprintf_impl(char **strp, const char *fmt, va_list ap) { va_list ap_copy; int len; char *buf; if (strp == NULL || fmt == NULL) { return -1; } *strp = NULL; va_copy(ap_copy, ap); len = vsnprintf(NULL, 0, fmt, ap_copy); va_end(ap_copy); if (len < 0) { return -1; } buf = malloc((size_t)len + 1); if (buf == NULL) { return -1; } va_copy(ap_copy, ap); if (vsnprintf(buf, (size_t)len + 1, fmt, ap_copy) != len) { va_end(ap_copy); free(buf); return -1; } va_end(ap_copy); *strp = buf; return len; } #endif #ifndef HAVE_VASPRINTF int vasprintf(char **strp, const char *fmt, va_list ap) { return compat_vasprintf_impl(strp, fmt, ap); } #endif #ifndef HAVE_ASPRINTF int asprintf(char **strp, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = compat_vasprintf_impl(strp, fmt, ap); va_end(ap); return ret; } #endif rsyslog-8.2608.0/compat/PaxHeaders/getifaddrs.c0000644000000000000000000000013215216464435016314 xustar0030 mtime=1782212893.956265052 30 atime=1787067616.138402361 30 ctime=1787067794.004717787 rsyslog-8.2608.0/compat/getifaddrs.c0000664000175000017500000003565515216464435015776 0ustar00rgerrger#include "config.h" #ifndef HAVE_GETIFADDRS /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #if !defined(_AIX) #include #endif #include #include #if defined(_AIX) #include #include #endif #include #include #if defined(_AIX) #include #endif #if !defined(_AIX) #include #endif #include #include #include #include #if defined(_AIX) #include #endif /* Normally this is defined in but was new for Solaris 11 */ #ifndef LIFC_ENABLED #define LIFC_ENABLED 0x20 #endif #if defined(_AIX) /* Use ifaddrs_rsys instead of ifaddrs and ifreq instead of lifreq */ int getallifaddrs(sa_family_t af, struct ifaddrs_rsys **ifap, int64_t flags); int getallifs(int s, sa_family_t af, struct ifreq **ifr, int *numifs, int64_t ifc_flags); #else int getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags); int getallifs(int s, sa_family_t af, struct lifreq **lifr, int *numifs, int64_t lifc_flags); #endif /* * Create a linked list of `struct ifaddrs_rsys' structures, one for each * address that is UP. If successful, store the list in *ifap and * return 0. On errors, return -1 and set `errno'. * * The storage returned in *ifap is allocated dynamically and can * only be properly freed by passing it to `freeifaddrs'. */ int #if defined(_AIX) getifaddrs(struct ifaddrs_rsys **ifap) #else getifaddrs(struct ifaddrs **ifap) #endif { int err; char *cp; #if defined(_AIX) struct ifaddrs_rsys *curr; #else struct ifaddrs *curr; #endif if (ifap == NULL) { errno = EINVAL; return (-1); } *ifap = NULL; err = getallifaddrs(AF_UNSPEC, ifap, LIFC_ENABLED); if (err == 0) { for (curr = *ifap; curr != NULL; curr = curr->ifa_next) { if ((cp = strchr(curr->ifa_name, ':')) != NULL) *cp = '\0'; } } return (err); } void #if defined(_AIX) freeifaddrs(struct ifaddrs_rsys *ifa) #else freeifaddrs(struct ifaddrs *ifa) #endif { #if defined(_AIX) struct ifaddrs_rsys *curr; #else struct ifaddrs *curr; #endif while (ifa != NULL) { curr = ifa; ifa = ifa->ifa_next; free(curr->ifa_name); free(curr->ifa_addr); free(curr->ifa_netmask); free(curr->ifa_dstaddr); free(curr); } } /* * Returns all addresses configured on the system. If flags contain * LIFC_ENABLED, only the addresses that are UP are returned. * Address list that is returned by this function must be freed * using freeifaddrs(). */ #if defined(_AIX) int getallifaddrs(sa_family_t af, struct ifaddrs_rsys **ifap, int64_t flags) { struct ifreq *buf = NULL; struct ifreq *ifrp; struct ifreq ifrl; struct in6_ifreq ifrl6; int ret; int s, n, iflen; struct ifaddrs_rsys *curr, *prev; sa_family_t ifr_af; int sock4; int sock6; int err; int ifsize; char *s_ifrp, *e_ifrp; int flag; if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (-1); if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { err = errno; close(sock4); errno = err; return (-1); } retry: /* Get all interfaces from SIOCGIFCONF */ ret = getallifs(sock4, af, &buf, &iflen, (flags & ~LIFC_ENABLED)); if (ret != 0) goto fail; /* * Loop through the interfaces obtained from SIOCGIFCOMF * and retrieve the addresses, netmask and flags. */ prev = NULL; s_ifrp = (char *)buf; e_ifrp = (char *)buf + iflen; *ifap = NULL; while (s_ifrp < e_ifrp) { ifrp = (struct ifreq *)s_ifrp; ifsize = sizeof(struct ifreq); if (ifrp->ifr_addr.sa_len > sizeof(ifrp->ifr_ifru)) { ifsize += ifrp->ifr_addr.sa_len - sizeof(ifrp->ifr_ifru); } /* Prepare for the ioctl call */ const char *name_end = memchr(ifrp->ifr_name, '\0', sizeof(ifrl.ifr_name)); size_t name_len = name_end == NULL ? sizeof(ifrl.ifr_name) : (size_t)(name_end - ifrp->ifr_name); memset(ifrl.ifr_name, 0, sizeof(ifrl.ifr_name)); memset(ifrl6.ifr_name, 0, sizeof(ifrl6.ifr_name)); memcpy(ifrl.ifr_name, ifrp->ifr_name, name_len); memcpy(ifrl6.ifr_name, ifrp->ifr_name, name_len); ifr_af = ifrp->ifr_addr.sa_family; if (ifr_af != AF_INET && ifr_af != AF_INET6) goto next; s = (ifr_af == AF_INET ? sock4 : sock6); if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifrl) < 0) goto fail; if ((flags & LIFC_ENABLED) && !(ifrl.ifr_flags & IFF_UP)) { goto next; } /* * Allocate the current list node. Each node contains data * for one ifaddrs structure. */ curr = calloc(1, sizeof(struct ifaddrs_rsys)); if (curr == NULL) goto fail; if (prev != NULL) { prev->ifa_next = curr; } else { /* First node in the linked list */ *ifap = curr; } prev = curr; /* AIXPORT : ifreq field names used instead of linux lifreq field names */ curr->ifa_flags = ifrl.ifr_flags; if ((curr->ifa_name = strdup(ifrp->ifr_name)) == NULL) goto fail; curr->ifa_addr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_addr == NULL) goto fail; (void)memcpy(curr->ifa_addr, &ifrp->ifr_addr, sizeof(struct sockaddr_storage)); /* Get the netmask */ if (ifr_af == AF_INET) { if (ioctl(s, SIOCGIFNETMASK, (caddr_t)&ifrl) < 0) { goto fail; } curr->ifa_netmask = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_netmask == NULL) goto fail; (void)memcpy(curr->ifa_netmask, &ifrl.ifr_addr, sizeof(struct sockaddr_storage)); } else { if (ioctl(s, SIOCGIFNETMASK6, (caddr_t)&ifrl6) < 0) { goto fail; } curr->ifa_netmask = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_netmask == NULL) goto fail; (void)memcpy(curr->ifa_netmask, &ifrl6.ifr_Addr, sizeof(struct sockaddr_storage)); } /* Get the destination for a pt-pt interface */ if (curr->ifa_flags & IFF_POINTOPOINT) { if (ifr_af == AF_INET) { if (ioctl(s, SIOCGIFDSTADDR, (caddr_t)&ifrl) < 0) goto fail; curr->ifa_dstaddr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_dstaddr == NULL) goto fail; (void)memcpy(curr->ifa_dstaddr, &ifrl.ifr_addr, sizeof(struct sockaddr_storage)); } else { if (ioctl(s, SIOCGIFDSTADDR6, (caddr_t)&ifrl6) < 0) goto fail; curr->ifa_dstaddr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_dstaddr == NULL) goto fail; (void)memcpy(curr->ifa_dstaddr, &ifrl6.ifr_Addr, sizeof(struct sockaddr_storage)); } /* Do not get broadcast address for IPv6 */ } else if ((curr->ifa_flags & IFF_BROADCAST) && (ifr_af == AF_INET)) { if (ioctl(s, SIOCGIFBRDADDR, (caddr_t)&ifrl) < 0) goto fail; curr->ifa_broadaddr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_broadaddr == NULL) goto fail; (void)memcpy(curr->ifa_broadaddr, &ifrl.ifr_addr, sizeof(struct sockaddr_storage)); } next: s_ifrp += ifsize; } free(buf); close(sock4); close(sock6); return (0); fail: err = errno; free(buf); freeifaddrs(*ifap); *ifap = NULL; if (err == ENXIO) goto retry; close(sock4); close(sock6); errno = err; return (-1); } /* * Do a SIOCGIFCONF and store all the interfaces in `buf'. */ int getallifs(int s, sa_family_t af, struct ifreq **ifr, int *iflen, int64_t ifc_flags) { int ifsize; struct ifconf ifc; size_t bufsize; char *tmp; caddr_t *buf = (caddr_t *)ifr; *buf = NULL; retry: if (ioctl(s, SIOCGSIZIFCONF, &ifsize) < 0) goto fail; /* * When calculating the buffer size needed, add a small number * of interfaces to those we counted. We do this to capture * the interface status of potential interfaces which may have * been plumbed between the SIOCGSIZIFCONF and the SIOCGIFCONF. */ bufsize = ifsize + (4 * sizeof(struct in6_ifreq)); if ((tmp = realloc(*buf, bufsize)) == NULL) goto fail; *buf = tmp; ifc.ifc_buf = *buf; ifc.ifc_len = bufsize; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) goto fail; *iflen = ifc.ifc_len; if (*iflen >= bufsize) { /* * If every entry was filled, there are probably * more interfaces than (ifn + 4) * Redo the ioctls SIOCGSIZIFCONF and SIOCGIFCONF to * get all the interfaces. */ goto retry; } return (0); fail: free(*buf); *buf = NULL; return (-1); } #else /* _AIX */ int getallifaddrs(sa_family_t af, struct ifaddrs **ifap, int64_t flags) { struct lifreq *buf = NULL; struct lifreq *lifrp; struct lifreq lifrl; int ret; int s, n, numifs; struct ifaddrs *curr, *prev; sa_family_t lifr_af; int sock4; int sock6; int err; if ((sock4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return (-1); if ((sock6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { err = errno; close(sock4); errno = err; return (-1); } retry: /* Get all interfaces from SIOCGLIFCONF */ ret = getallifs(sock4, af, &buf, &numifs, (flags & ~LIFC_ENABLED)); if (ret != 0) goto fail; /* * Loop through the interfaces obtained from SIOCGLIFCOMF * and retrieve the addresses, netmask and flags. */ prev = NULL; lifrp = buf; *ifap = NULL; for (n = 0; n < numifs; n++, lifrp++) { /* Prepare for the ioctl call */ const char *name_end = memchr(lifrp->lifr_name, '\0', sizeof(lifrl.lifr_name)); size_t name_len = name_end == NULL ? sizeof(lifrl.lifr_name) : (size_t)(name_end - lifrp->lifr_name); memset(lifrl.lifr_name, 0, sizeof(lifrl.lifr_name)); memcpy(lifrl.lifr_name, lifrp->lifr_name, name_len); lifr_af = lifrp->lifr_addr.ss_family; if (af != AF_UNSPEC && lifr_af != af) continue; s = (lifr_af == AF_INET ? sock4 : sock6); if (ioctl(s, SIOCGLIFFLAGS, (caddr_t)&lifrl) < 0) goto fail; if ((flags & LIFC_ENABLED) && !(lifrl.lifr_flags & IFF_UP)) continue; /* * Allocate the current list node. Each node contains data * for one ifaddrs structure. */ curr = calloc(1, sizeof(struct ifaddrs)); if (curr == NULL) goto fail; if (prev != NULL) { prev->ifa_next = curr; } else { /* First node in the linked list */ *ifap = curr; } prev = curr; curr->ifa_flags = lifrl.lifr_flags; if ((curr->ifa_name = strdup(lifrp->lifr_name)) == NULL) goto fail; curr->ifa_addr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_addr == NULL) goto fail; (void)memcpy(curr->ifa_addr, &lifrp->lifr_addr, sizeof(struct sockaddr_storage)); /* Get the netmask */ if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_netmask = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_netmask == NULL) goto fail; (void)memcpy(curr->ifa_netmask, &lifrl.lifr_addr, sizeof(struct sockaddr_storage)); /* Get the destination for a pt-pt interface */ if (curr->ifa_flags & IFF_POINTOPOINT) { if (ioctl(s, SIOCGLIFDSTADDR, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_dstaddr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_dstaddr == NULL) goto fail; (void)memcpy(curr->ifa_dstaddr, &lifrl.lifr_addr, sizeof(struct sockaddr_storage)); } else if (curr->ifa_flags & IFF_BROADCAST) { if (ioctl(s, SIOCGLIFBRDADDR, (caddr_t)&lifrl) < 0) goto fail; curr->ifa_broadaddr = malloc(sizeof(struct sockaddr_storage)); if (curr->ifa_broadaddr == NULL) goto fail; (void)memcpy(curr->ifa_broadaddr, &lifrl.lifr_addr, sizeof(struct sockaddr_storage)); } } free(buf); close(sock4); close(sock6); return (0); fail: err = errno; free(buf); freeifaddrs(*ifap); *ifap = NULL; if (err == ENXIO) goto retry; close(sock4); close(sock6); errno = err; return (-1); } /* * Do a SIOCGLIFCONF and store all the interfaces in `buf'. */ int getallifs(int s, sa_family_t af, struct lifreq **lifr, int *numifs, int64_t lifc_flags) { struct lifnum lifn; struct lifconf lifc; size_t bufsize; char *tmp; caddr_t *buf = (caddr_t *)lifr; lifn.lifn_family = af; lifn.lifn_flags = lifc_flags; *buf = NULL; retry: if (ioctl(s, SIOCGLIFNUM, &lifn) < 0) goto fail; /* * When calculating the buffer size needed, add a small number * of interfaces to those we counted. We do this to capture * the interface status of potential interfaces which may have * been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF. */ bufsize = (lifn.lifn_count + 4) * sizeof(struct lifreq); if ((tmp = realloc(*buf, bufsize)) == NULL) goto fail; *buf = tmp; lifc.lifc_family = af; lifc.lifc_flags = lifc_flags; lifc.lifc_len = bufsize; lifc.lifc_buf = *buf; if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) goto fail; *numifs = lifc.lifc_len / sizeof(struct lifreq); if (*numifs >= (lifn.lifn_count + 4)) { /* * If every entry was filled, there are probably * more interfaces than (lifn.lifn_count + 4). * Redo the ioctls SIOCGLIFNUM and SIOCGLIFCONF to * get all the interfaces. */ goto retry; } return (0); fail: free(*buf); *buf = NULL; return (-1); } #endif /* _AIX */ #endif /* HAVE_GETIFADDRS */ rsyslog-8.2608.0/compat/PaxHeaders/Makefile.am0000644000000000000000000000013215216464435016070 xustar0030 mtime=1782212893.956265052 30 atime=1787067433.880002684 30 ctime=1787067793.997717657 rsyslog-8.2608.0/compat/Makefile.am0000664000175000017500000000042015216464435015530 0ustar00rgerrgernoinst_LTLIBRARIES = compat.la compat_la_SOURCES = getifaddrs.c ifaddrs.h strndup.c asprintf.c asprintf.h solaris_elf_fix.c compat_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) compat_la_LDFLAGS = -module -avoid-version compat_la_LIBADD = $(IMUDP_LIBS) rsyslog-8.2608.0/compat/PaxHeaders/asprintf.h0000644000000000000000000000013215216464435016033 xustar0030 mtime=1782212893.956265052 30 atime=1787067616.800414705 30 ctime=1787067794.014717973 rsyslog-8.2608.0/compat/asprintf.h0000664000175000017500000000136015216464435015477 0ustar00rgerrger#ifndef INCLUDED_COMPAT_ASPRINTF_H #define INCLUDED_COMPAT_ASPRINTF_H #include #include #include "config.h" #ifdef __cplusplus extern "C" { #endif #if !defined(HAVE_DECL_ASPRINTF) || !HAVE_DECL_ASPRINTF #if defined(__GNUC__) int asprintf(char **strp, const char *fmt, ...) __attribute__((format(printf, 2, 3))); #else int asprintf(char **strp, const char *fmt, ...); #endif #endif #if !defined(HAVE_DECL_VASPRINTF) || !HAVE_DECL_VASPRINTF #if defined(__GNUC__) int vasprintf(char **strp, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); #else int vasprintf(char **strp, const char *fmt, va_list ap); #endif #endif #ifdef __cplusplus } #endif #endif /* INCLUDED_COMPAT_ASPRINTF_H */ rsyslog-8.2608.0/compat/PaxHeaders/solaris_elf_fix.c0000644000000000000000000000013215035412264017340 xustar0030 mtime=1752569012.325278836 30 atime=1787067616.138402361 30 ctime=1787067794.017718029 rsyslog-8.2608.0/compat/solaris_elf_fix.c0000666000175000017500000000206315035412264017007 0ustar00rgerrger/* This file ensure that is at least one symbol in our compat * convenience library. Otherwise, at least the Solaris linker * bails out with an error message like this: * * ld: elf error: file ../compat/.libs/compat.a: elf_getarsym * * Copyright 2016 Rainer Gerhards and Adiscon * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #if defined(OS_SOLARIS) || defined(__xlc__) int SOLARIS_and_XLC_wants_a_symbol_inside_the_lib; #endif rsyslog-8.2608.0/compat/PaxHeaders/Makefile.in0000644000000000000000000000013215241076160016071 xustar0030 mtime=1787067504.369317868 30 atime=1787067576.784668531 30 ctime=1787067794.000717713 rsyslog-8.2608.0/compat/Makefile.in0000664000175000017500000007072215241076160015545 0ustar00rgerrger# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = compat ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ac_check_define.m4 \ $(top_srcdir)/m4/atomic_operations.m4 \ $(top_srcdir)/m4/atomic_operations_64bit.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = compat_la_DEPENDENCIES = $(am__DEPENDENCIES_1) am_compat_la_OBJECTS = compat_la-getifaddrs.lo compat_la-strndup.lo \ compat_la-asprintf.lo compat_la-solaris_elf_fix.lo compat_la_OBJECTS = $(am_compat_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 = compat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(compat_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__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/compat_la-asprintf.Plo \ ./$(DEPDIR)/compat_la-getifaddrs.Plo \ ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo \ ./$(DEPDIR)/compat_la-strndup.Plo am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(compat_la_SOURCES) DIST_SOURCES = $(compat_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = clean-coverage-recursive \ distclean-coverage-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ APU_CFLAGS = @APU_CFLAGS@ APU_LIBS = @APU_LIBS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CIVETWEB_LIBS = @CIVETWEB_LIBS@ CONF_FILE_PATH = @CONF_FILE_PATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CURL_CFLAGS = @CURL_CFLAGS@ CURL_LIBS = @CURL_LIBS@ CYGPATH_W = @CYGPATH_W@ CZMQ_CFLAGS = @CZMQ_CFLAGS@ CZMQ_LIBS = @CZMQ_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DL_LIBS = @DL_LIBS@ DOC_FILES = @DOC_FILES@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FAUP_LIBS = @FAUP_LIBS@ FGREP = @FGREP@ FILECMD = @FILECMD@ GAI_LIBS = @GAI_LIBS@ GCOV = @GCOV@ GENHTML = @GENHTML@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ GNUTLS_LIBS = @GNUTLS_LIBS@ GREP = @GREP@ GSS_CFLAGS = @GSS_CFLAGS@ GSS_LIBS = @GSS_LIBS@ GT_KSI_LS12_CFLAGS = @GT_KSI_LS12_CFLAGS@ GT_KSI_LS12_LIBS = @GT_KSI_LS12_LIBS@ HASH_XXHASH_LIBS = @HASH_XXHASH_LIBS@ HIREDIS_CFLAGS = @HIREDIS_CFLAGS@ HIREDIS_LIBS = @HIREDIS_LIBS@ HIREDIS_SSL_CFLAGS = @HIREDIS_SSL_CFLAGS@ HIREDIS_SSL_LIBS = @HIREDIS_SSL_LIBS@ IMPSTATS_PUSH_CFLAGS = @IMPSTATS_PUSH_CFLAGS@ IMPSTATS_PUSH_CURL_CFLAGS = @IMPSTATS_PUSH_CURL_CFLAGS@ IMPSTATS_PUSH_CURL_LIBS = @IMPSTATS_PUSH_CURL_LIBS@ IMPSTATS_PUSH_LIBS = @IMPSTATS_PUSH_LIBS@ IMPSTATS_PUSH_PROTOBUF_CFLAGS = @IMPSTATS_PUSH_PROTOBUF_CFLAGS@ IMPSTATS_PUSH_PROTOBUF_LIBS = @IMPSTATS_PUSH_PROTOBUF_LIBS@ IMPSTATS_PUSH_SNAPPY_CFLAGS = @IMPSTATS_PUSH_SNAPPY_CFLAGS@ IMPSTATS_PUSH_SNAPPY_LIBS = @IMPSTATS_PUSH_SNAPPY_LIBS@ IMUDP_LIBS = @IMUDP_LIBS@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ IP = @IP@ JAVA = @JAVA@ JAVAC = @JAVAC@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBCAPNG_CFLAGS = @LIBCAPNG_CFLAGS@ LIBCAPNG_LIBS = @LIBCAPNG_LIBS@ LIBCAPNG_PRESENT_CFLAGS = @LIBCAPNG_PRESENT_CFLAGS@ LIBCAPNG_PRESENT_LIBS = @LIBCAPNG_PRESENT_LIBS@ LIBDBI_CFLAGS = @LIBDBI_CFLAGS@ LIBDBI_LIBS = @LIBDBI_LIBS@ LIBESTR_CFLAGS = @LIBESTR_CFLAGS@ LIBESTR_LIBS = @LIBESTR_LIBS@ LIBEVENT_CFLAGS = @LIBEVENT_CFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBFASTJSON_CFLAGS = @LIBFASTJSON_CFLAGS@ LIBFASTJSON_LIBS = @LIBFASTJSON_LIBS@ LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBLOGGING_CFLAGS = @LIBLOGGING_CFLAGS@ LIBLOGGING_LIBS = @LIBLOGGING_LIBS@ LIBLOGGING_STDLOG_CFLAGS = @LIBLOGGING_STDLOG_CFLAGS@ LIBLOGGING_STDLOG_LIBS = @LIBLOGGING_STDLOG_LIBS@ LIBLOGNORM_CFLAGS = @LIBLOGNORM_CFLAGS@ LIBLOGNORM_LIBS = @LIBLOGNORM_LIBS@ LIBLZ4_CFLAGS = @LIBLZ4_CFLAGS@ LIBLZ4_LIBS = @LIBLZ4_LIBS@ LIBM = @LIBM@ LIBMONGOC_CFLAGS = @LIBMONGOC_CFLAGS@ LIBMONGOC_LIBS = @LIBMONGOC_LIBS@ LIBOBJS = @LIBOBJS@ LIBRDKAFKA_CFLAGS = @LIBRDKAFKA_CFLAGS@ LIBRDKAFKA_LIBS = @LIBRDKAFKA_LIBS@ LIBRESOLV_LIBS = @LIBRESOLV_LIBS@ LIBS = @LIBS@ LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ LIBSYSTEMD_JOURNAL_CFLAGS = @LIBSYSTEMD_JOURNAL_CFLAGS@ LIBSYSTEMD_JOURNAL_LIBS = @LIBSYSTEMD_JOURNAL_LIBS@ LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ LIBTOOL = @LIBTOOL@ LIBUUID_CFLAGS = @LIBUUID_CFLAGS@ LIBUUID_LIBS = @LIBUUID_LIBS@ LIBYAML_CFLAGS = @LIBYAML_CFLAGS@ LIBYAML_LIBS = @LIBYAML_LIBS@ LIB_FUZZING_ENGINE = @LIB_FUZZING_ENGINE@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MBEDTLS_CFLAGS = @MBEDTLS_CFLAGS@ MBEDTLS_LIBS = @MBEDTLS_LIBS@ MKDIR_P = @MKDIR_P@ MYSQL_CFLAGS = @MYSQL_CFLAGS@ MYSQL_CONFIG = @MYSQL_CONFIG@ MYSQL_LIBS = @MYSQL_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OMOTEL_HTTP_CFLAGS = @OMOTEL_HTTP_CFLAGS@ OMOTEL_HTTP_LIBS = @OMOTEL_HTTP_LIBS@ OMOTEL_PROTOBUF_CFLAGS = @OMOTEL_PROTOBUF_CFLAGS@ OMOTEL_PROTOBUF_LIBS = @OMOTEL_PROTOBUF_LIBS@ OPENSSL_CFLAGS = @OPENSSL_CFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PGSQL_CFLAGS = @PGSQL_CFLAGS@ PGSQL_LIBS = @PGSQL_LIBS@ PG_CONFIG = @PG_CONFIG@ PID_FILE_PATH = @PID_FILE_PATH@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PROTOC_C = @PROTOC_C@ PROTON_CFLAGS = @PROTON_CFLAGS@ PROTON_LIBS = @PROTON_LIBS@ PROTON_PROACTOR_CFLAGS = @PROTON_PROACTOR_CFLAGS@ PROTON_PROACTOR_LIBS = @PROTON_PROACTOR_LIBS@ PTHREADS_CFLAGS = @PTHREADS_CFLAGS@ PTHREADS_LIBS = @PTHREADS_LIBS@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RABBITMQ_CFLAGS = @RABBITMQ_CFLAGS@ RABBITMQ_LIBS = @RABBITMQ_LIBS@ RANLIB = @RANLIB@ READLINK = @READLINK@ REDIS = @REDIS@ RELP_CFLAGS = @RELP_CFLAGS@ RELP_LIBS = @RELP_LIBS@ RSRT_CFLAGS = @RSRT_CFLAGS@ RSRT_CFLAGS1 = @RSRT_CFLAGS1@ RSRT_LIBS = @RSRT_LIBS@ RSRT_LIBS1 = @RSRT_LIBS1@ RST2MAN = @RST2MAN@ RT_LIBS = @RT_LIBS@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SNMP_CFLAGS = @SNMP_CFLAGS@ SNMP_LIBS = @SNMP_LIBS@ SOL_LIBS = @SOL_LIBS@ STRIP = @STRIP@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_INCLUDE_SPEC = @TCL_INCLUDE_SPEC@ TCL_LIB_FILE = @TCL_LIB_FILE@ TCL_LIB_FLAG = @TCL_LIB_FLAG@ TCL_LIB_SPEC = @TCL_LIB_SPEC@ TCL_PATCH_LEVEL = @TCL_PATCH_LEVEL@ TCL_SRC_DIR = @TCL_SRC_DIR@ TCL_STUB_LIB_FILE = @TCL_STUB_LIB_FILE@ TCL_STUB_LIB_FLAG = @TCL_STUB_LIB_FLAG@ TCL_STUB_LIB_SPEC = @TCL_STUB_LIB_SPEC@ TCL_VERSION = @TCL_VERSION@ UDPSPOOF_CFLAGS = @UDPSPOOF_CFLAGS@ UDPSPOOF_LIBS = @UDPSPOOF_LIBS@ VALGRIND = @VALGRIND@ VERSION = @VERSION@ WARN_CFLAGS = @WARN_CFLAGS@ WARN_LDFLAGS = @WARN_LDFLAGS@ WARN_SCANNERFLAGS = @WARN_SCANNERFLAGS@ WGET = @WGET@ WOLFSSL_CFLAGS = @WOLFSSL_CFLAGS@ WOLFSSL_LIBS = @WOLFSSL_LIBS@ YACC = @YACC@ YACC_FOUND = @YACC_FOUND@ YFLAGS = @YFLAGS@ ZLIB_CFLAGS = @ZLIB_CFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ ZSTD_CFLAGS = @ZSTD_CFLAGS@ ZSTD_LIBS = @ZSTD_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_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@ mandir = @mandir@ mkdir_p = @mkdir_p@ moddirs = @moddirs@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = compat.la compat_la_SOURCES = getifaddrs.c ifaddrs.h strndup.c asprintf.c asprintf.h solaris_elf_fix.c compat_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) compat_la_LDFLAGS = -module -avoid-version compat_la_LIBADD = $(IMUDP_LIBS) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(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 compat/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu compat/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; $(top_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): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_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}; \ } compat.la: $(compat_la_OBJECTS) $(compat_la_DEPENDENCIES) $(EXTRA_compat_la_DEPENDENCIES) $(AM_V_CCLD)$(compat_la_LINK) $(compat_la_OBJECTS) $(compat_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-asprintf.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-getifaddrs.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-solaris_elf_fix.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/compat_la-strndup.Plo@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @echo '# dummy' >$@-t && $(am__mv) $@-t $@ am--depfiles: $(am__depfiles_remade) .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< compat_la-getifaddrs.lo: getifaddrs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-getifaddrs.lo -MD -MP -MF $(DEPDIR)/compat_la-getifaddrs.Tpo -c -o compat_la-getifaddrs.lo `test -f 'getifaddrs.c' || echo '$(srcdir)/'`getifaddrs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-getifaddrs.Tpo $(DEPDIR)/compat_la-getifaddrs.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='getifaddrs.c' object='compat_la-getifaddrs.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-getifaddrs.lo `test -f 'getifaddrs.c' || echo '$(srcdir)/'`getifaddrs.c compat_la-strndup.lo: strndup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-strndup.lo -MD -MP -MF $(DEPDIR)/compat_la-strndup.Tpo -c -o compat_la-strndup.lo `test -f 'strndup.c' || echo '$(srcdir)/'`strndup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-strndup.Tpo $(DEPDIR)/compat_la-strndup.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='strndup.c' object='compat_la-strndup.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-strndup.lo `test -f 'strndup.c' || echo '$(srcdir)/'`strndup.c compat_la-asprintf.lo: asprintf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-asprintf.lo -MD -MP -MF $(DEPDIR)/compat_la-asprintf.Tpo -c -o compat_la-asprintf.lo `test -f 'asprintf.c' || echo '$(srcdir)/'`asprintf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-asprintf.Tpo $(DEPDIR)/compat_la-asprintf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='asprintf.c' object='compat_la-asprintf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-asprintf.lo `test -f 'asprintf.c' || echo '$(srcdir)/'`asprintf.c compat_la-solaris_elf_fix.lo: solaris_elf_fix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT compat_la-solaris_elf_fix.lo -MD -MP -MF $(DEPDIR)/compat_la-solaris_elf_fix.Tpo -c -o compat_la-solaris_elf_fix.lo `test -f 'solaris_elf_fix.c' || echo '$(srcdir)/'`solaris_elf_fix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/compat_la-solaris_elf_fix.Tpo $(DEPDIR)/compat_la-solaris_elf_fix.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='solaris_elf_fix.c' object='compat_la-solaris_elf_fix.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(compat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o compat_la-solaris_elf_fix.lo `test -f 'solaris_elf_fix.c' || echo '$(srcdir)/'`solaris_elf_fix.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs clean-coverage-local: distclean-coverage-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: 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-noinstLTLIBRARIES \ mostlyclean-am clean-coverage: clean-coverage-am clean-coverage-am: clean-coverage-local distclean: distclean-am -rm -f ./$(DEPDIR)/compat_la-asprintf.Plo -rm -f ./$(DEPDIR)/compat_la-getifaddrs.Plo -rm -f ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo -rm -f ./$(DEPDIR)/compat_la-strndup.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags distclean-coverage: distclean-coverage-am distclean-coverage-am: distclean-coverage-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/compat_la-asprintf.Plo -rm -f ./$(DEPDIR)/compat_la-getifaddrs.Plo -rm -f ./$(DEPDIR)/compat_la-solaris_elf_fix.Plo -rm -f ./$(DEPDIR)/compat_la-strndup.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-coverage-am clean-coverage-local clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-coverage-am \ distclean-coverage-local 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-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 .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: rsyslog-8.2608.0/compat/PaxHeaders/ifaddrs.h0000644000000000000000000000013215132411300015575 xustar0030 mtime=1768559296.134883552 30 atime=1782715518.799789027 30 ctime=1787067794.007717843 rsyslog-8.2608.0/compat/ifaddrs.h0000666000175000017500000000673415132411300015255 0ustar00rgerrger#include "config.h" #ifndef HAVE_GETIFADDRS /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _IFADDRS_H #define _IFADDRS_H #ifdef __cplusplus extern "C" { #endif #include /* * The `getifaddrs' function generates a linked list of these structures. * Each element of the list describes one network interface. */ #if defined(_AIX) struct ifaddrs_rsys { struct ifaddrs_rsys *ifa_next; /* Pointer to the next structure. */ #else struct ifaddrs { struct ifaddrs *ifa_next; /* Pointer to the next structure. */ #endif char *ifa_name; /* Name of this network interface. */ uint64_t ifa_flags; /* Flags as from SIOCGLIFFLAGS ioctl. */ struct sockaddr *ifa_addr; /* Network address of this interface. */ struct sockaddr *ifa_netmask; /* Netmask of this interface. */ union { /* * At most one of the following two is valid. If the * IFF_BROADCAST bit is set in `ifa_flags', then * `ifa_broadaddr' is valid. If the IFF_POINTOPOINT bit is * set, then `ifa_dstaddr' is valid. It is never the case that * both these bits are set at once. */ struct sockaddr *ifu_broadaddr; struct sockaddr *ifu_dstaddr; } ifa_ifu; void *ifa_data; /* Address-specific data (may be unused). */ /* * This may have been defined in . */ #ifndef ifa_broadaddr #define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ #endif #ifndef ifa_dstaddr #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of p-to-p link */ #endif }; /* * Create a linked list of `struct ifaddrs' structures, one for each * network interface on the host machine. If successful, store the * list in *ifap and return 0. On errors, return -1 and set `errno'. * * The storage returned in *ifap is allocated dynamically and can * only be properly freed by passing it to `freeifaddrs'. */ #if defined(_AIX) extern int getifaddrs(struct ifaddrs_rsys **); #else extern int getifaddrs(struct ifaddrs **); #endif /* Reclaim the storage allocated by a previous `getifaddrs' call. */ #if defined(_AIX) extern void freeifaddrs(struct ifaddrs_rsys *); #else extern void freeifaddrs(struct ifaddrs *); #endif #ifdef __cplusplus } #endif #endif /* _IFADDRS_H */ #endif /* HAVE_GETIFADDRS */ rsyslog-8.2608.0/compat/PaxHeaders/strndup.c0000644000000000000000000000013215172337145015675 xustar0030 mtime=1776926309.338899846 30 atime=1787067616.138402361 30 ctime=1787067794.010717899 rsyslog-8.2608.0/compat/strndup.c0000664000175000017500000000247415172337145015350 0ustar00rgerrger/* compatibility file for systems without strndup. * * Copyright 2015 Rainer Gerhards and Adiscon * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #ifndef HAVE_STRNDUP #include #include extern char *strndup(const char *s, size_t n); char *strndup(const char *s, size_t n) { const size_t len = strlen(s); char *new_s; if (len <= n) return strdup(s); new_s = malloc(n + 1); if (new_s == NULL) return NULL; memcpy(new_s, s, n); new_s[n] = '\0'; return new_s; } #else /* XLC needs at least one method in source file even static to compile */ #ifdef __xlc__ static void dummy(void) {} #endif #endif /* #ifndef HAVE_STRNDUP */ rsyslog-8.2608.0/PaxHeaders/aclocal.m40000644000000000000000000000013015241076156014404 xustar0030 mtime=1787067502.852289569 29 atime=1787067502.95529149 29 ctime=1787067790.69765616 rsyslog-8.2608.0/aclocal.m40000664000175000017500000065014615241076156014066 0ustar00rgerrger# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 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.71],, [m4_warning([this file was generated for autoconf 2.71. 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'.])]) # ============================================================================ # https://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html # ============================================================================ # # SYNOPSIS # # AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # For every FLAG1, FLAG2 it is checked whether the compiler works with the # flag. If it does, the flag is added FLAGS-VARIABLE # # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. # CFLAGS) is used. During the check the flag is always added to the # current language's flags. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: This macro depends on the AX_APPEND_FLAG and # AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with # AX_APPEND_LINK_FLAGS. # # LICENSE # # Copyright (c) 2011 Maarten Bosmans # # 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 any # warranty. #serial 7 AC_DEFUN([AX_APPEND_COMPILE_FLAGS], [AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4]) done ])dnl AX_APPEND_COMPILE_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_append_flag.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE]) # # DESCRIPTION # # FLAG is appended to the FLAGS-VARIABLE shell variable, with a space # added in between. # # If FLAGS-VARIABLE is not specified, the current language's flags (e.g. # CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains # FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly # FLAG. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # 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 any # warranty. #serial 8 AC_DEFUN([AX_APPEND_FLAG], [dnl AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) AS_VAR_SET_IF(FLAGS,[ AS_CASE([" AS_VAR_GET(FLAGS) "], [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], [ AS_VAR_APPEND(FLAGS,[" $1"]) AC_RUN_LOG([: FLAGS="$FLAGS"]) ]) ], [ AS_VAR_SET(FLAGS,[$1]) AC_RUN_LOG([: FLAGS="$FLAGS"]) ]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html # =========================================================================== # # SYNOPSIS # # AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # For every FLAG1, FLAG2 it is checked whether the linker works with the # flag. If it does, the flag is added FLAGS-VARIABLE # # If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is # used. During the check the flag is always added to the linker's flags. # # If EXTRA-FLAGS is defined, it is added to the linker's default flags # when the check is done. The check is thus made with the flags: "LDFLAGS # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG. # Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS. # # LICENSE # # Copyright (c) 2011 Maarten Bosmans # # 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 any # warranty. #serial 7 AC_DEFUN([AX_APPEND_LINK_FLAGS], [AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) for flag in $1; do AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4]) done ])dnl AX_APPEND_LINK_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the current language's compiler # or gives an error. (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the current language's default # flags (e.g. CFLAGS) when the check is done. The check is thus made with # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_COMPILE_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # 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 any # warranty. #serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_COMPILE_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # # Check whether the given FLAG works with the linker or gives an error. # (Warnings, however, are ignored) # # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on # success/failure. # # If EXTRA-FLAGS is defined, it is added to the linker's default flags # when the check is done. The check is thus made with the flags: "LDFLAGS # EXTRA-FLAGS FLAG". This can for example be used to force the linker to # issue an error when a bad flag is given. # # INPUT gives an alternative input source to AC_LINK_IFELSE. # # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. # # LICENSE # # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # # 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 any # warranty. #serial 6 AC_DEFUN([AX_CHECK_LINK_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl ])dnl AX_CHECK_LINK_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_compiler_flags.html # =========================================================================== # # SYNOPSIS # # AX_COMPILER_FLAGS([CFLAGS-VARIABLE], [LDFLAGS-VARIABLE], [IS-RELEASE], [EXTRA-BASE-CFLAGS], [EXTRA-YES-CFLAGS], [UNUSED], [UNUSED], [UNUSED], [EXTRA-BASE-LDFLAGS], [EXTRA-YES-LDFLAGS], [UNUSED], [UNUSED], [UNUSED]) # # DESCRIPTION # # Check for the presence of an --enable-compile-warnings option to # configure, defaulting to "error" in normal operation, or "yes" if # IS-RELEASE is equal to "yes". Return the value in the variable # $ax_enable_compile_warnings. # # Depending on the value of --enable-compile-warnings, different compiler # warnings are checked to see if they work with the current compiler and, # if so, are appended to CFLAGS-VARIABLE and LDFLAGS-VARIABLE. This # allows a consistent set of baseline compiler warnings to be used across # a code base, irrespective of any warnings enabled locally by individual # developers. By standardising the warnings used by all developers of a # project, the project can commit to a zero-warnings policy, using -Werror # to prevent compilation if new warnings are introduced. This makes # catching bugs which are flagged by warnings a lot easier. # # By providing a consistent --enable-compile-warnings argument across all # projects using this macro, continuous integration systems can easily be # configured the same for all projects. Automated systems or build # systems aimed at beginners may want to pass the --disable-Werror # argument to unconditionally prevent warnings being fatal. # # --enable-compile-warnings can take the values: # # * no: Base compiler warnings only; not even -Wall. # * yes: The above, plus a broad range of useful warnings. # * error: The above, plus -Werror so that all warnings are fatal. # Use --disable-Werror to override this and disable fatal # warnings. # # The set of base and enabled flags can be augmented using the # EXTRA-*-CFLAGS and EXTRA-*-LDFLAGS variables, which are tested and # appended to the output variable if --enable-compile-warnings is not # "no". Flags should not be disabled using these arguments, as the entire # point of AX_COMPILER_FLAGS is to enforce a consistent set of useful # compiler warnings on code, using warnings which have been chosen for low # false positive rates. If a compiler emits false positives for a # warning, a #pragma should be used in the code to disable the warning # locally. See: # # https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas # # The EXTRA-* variables should only be used to supply extra warning flags, # and not general purpose compiler flags, as they are controlled by # configure options such as --disable-Werror. # # IS-RELEASE can be used to disable -Werror when making a release, which # is useful for those hairy moments when you just want to get the release # done as quickly as possible. Set it to "yes" to disable -Werror. By # default, it uses the value of $ax_is_release, so if you are using the # AX_IS_RELEASE macro, there is no need to pass this parameter. For # example: # # AX_IS_RELEASE([git-directory]) # AX_COMPILER_FLAGS() # # CFLAGS-VARIABLE defaults to WARN_CFLAGS, and LDFLAGS-VARIABLE defaults # to WARN_LDFLAGS. Both variables are AC_SUBST-ed by this macro, but must # be manually added to the CFLAGS and LDFLAGS variables for each target in # the code base. # # If C++ language support is enabled with AC_PROG_CXX, which must occur # before this macro in configure.ac, warning flags for the C++ compiler # are AC_SUBST-ed as WARN_CXXFLAGS, and must be manually added to the # CXXFLAGS variables for each target in the code base. EXTRA-*-CFLAGS can # be used to augment the base and enabled flags. # # Warning flags for g-ir-scanner (from GObject Introspection) are # AC_SUBST-ed as WARN_SCANNERFLAGS. This variable must be manually added # to the SCANNERFLAGS variable for each GIR target in the code base. If # extra g-ir-scanner flags need to be enabled, the AX_COMPILER_FLAGS_GIR # macro must be invoked manually. # # AX_COMPILER_FLAGS may add support for other tools in future, in addition # to the compiler and linker. No extra EXTRA-* variables will be added # for those tools, and all extra support will still use the single # --enable-compile-warnings configure option. For finer grained control # over the flags for individual tools, use AX_COMPILER_FLAGS_CFLAGS, # AX_COMPILER_FLAGS_LDFLAGS and AX_COMPILER_FLAGS_* for new tools. # # The UNUSED variables date from a previous version of this macro, and are # automatically appended to the preceding non-UNUSED variable. They should # be left empty in new uses of the macro. # # LICENSE # # Copyright (c) 2014, 2015 Philip Withnall # Copyright (c) 2015 David King # # 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 any # warranty. #serial 14 # _AX_COMPILER_FLAGS_LANG([LANGNAME]) m4_defun([_AX_COMPILER_FLAGS_LANG], [m4_ifdef([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [], [m4_define([_AX_COMPILER_FLAGS_LANG_]$1[_enabled], [])dnl AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_]$1[FLAGS])])dnl ]) AC_DEFUN([AX_COMPILER_FLAGS],[ # C support is enabled by default. _AX_COMPILER_FLAGS_LANG([C]) # Only enable C++ support if AC_PROG_CXX is called. The redefinition of # AC_PROG_CXX is so that a fatal error is emitted if this macro is called # before AC_PROG_CXX, which would otherwise cause no C++ warnings to be # checked. AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AX_COMPILER_FLAGS_LANG([CXX])], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AX_COMPILER_FLAGS_LANG([CXX])])]) AX_REQUIRE_DEFINED([AX_COMPILER_FLAGS_LDFLAGS]) # Default value for IS-RELEASE is $ax_is_release ax_compiler_flags_is_release=m4_tolower(m4_normalize(ifelse([$3],, [$ax_is_release], [$3]))) AC_ARG_ENABLE([compile-warnings], AS_HELP_STRING([--enable-compile-warnings=@<:@no/yes/error@:>@], [Enable compiler warnings and errors]),, [AS_IF([test "$ax_compiler_flags_is_release" = "yes"], [enable_compile_warnings="yes"], [enable_compile_warnings="error"])]) AC_ARG_ENABLE([Werror], AS_HELP_STRING([--disable-Werror], [Unconditionally make all compiler warnings non-fatal]),, [enable_Werror=maybe]) # Return the user's chosen warning level AS_IF([test "$enable_Werror" = "no" -a \ "$enable_compile_warnings" = "error"],[ enable_compile_warnings="yes" ]) ax_enable_compile_warnings=$enable_compile_warnings AX_COMPILER_FLAGS_CFLAGS([$1],[$ax_compiler_flags_is_release], [$4],[$5 $6 $7 $8]) m4_ifdef([_AX_COMPILER_FLAGS_LANG_CXX_enabled], [AX_COMPILER_FLAGS_CXXFLAGS([WARN_CXXFLAGS], [$ax_compiler_flags_is_release], [$4],[$5 $6 $7 $8])]) AX_COMPILER_FLAGS_LDFLAGS([$2],[$ax_compiler_flags_is_release], [$9],[$10 $11 $12 $13]) AX_COMPILER_FLAGS_GIR([WARN_SCANNERFLAGS],[$ax_compiler_flags_is_release]) ])dnl AX_COMPILER_FLAGS # ============================================================================= # https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_cflags.html # ============================================================================= # # SYNOPSIS # # AX_COMPILER_FLAGS_CFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) # # DESCRIPTION # # Add warning flags for the C compiler to VARIABLE, which defaults to # WARN_CFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be # manually added to the CFLAGS variable for each target in the code base. # # This macro depends on the environment set up by AX_COMPILER_FLAGS. # Specifically, it uses the value of $ax_enable_compile_warnings to decide # which flags to enable. # # LICENSE # # Copyright (c) 2014, 2015 Philip Withnall # Copyright (c) 2017, 2018 Reini Urban # # 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 any # warranty. #serial 17 AC_DEFUN([AX_COMPILER_FLAGS_CFLAGS],[ AC_REQUIRE([AC_PROG_SED]) AX_REQUIRE_DEFINED([AX_APPEND_COMPILE_FLAGS]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) # Variable names m4_define([ax_warn_cflags_variable], [m4_normalize(ifelse([$1],,[WARN_CFLAGS],[$1]))]) AC_LANG_PUSH([C]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ [#ifndef __cplusplus #error "no C++" #endif]])], [ax_compiler_cxx=yes;], [ax_compiler_cxx=no;]) # Always pass -Werror=unknown-warning-option to get Clang to fail on bad # flags, otherwise they are always appended to the warn_cflags variable, and # Clang warns on them for every compilation unit. # If this is passed to GCC, it will explode, so the flag must be enabled # conditionally. AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ ax_compiler_flags_test="-Werror=unknown-warning-option" ],[ ax_compiler_flags_test="" ]) # Check that -Wno-suggest-attribute=format is supported AX_CHECK_COMPILE_FLAG([-Wno-suggest-attribute=format],[ ax_compiler_no_suggest_attribute_flags="-Wno-suggest-attribute=format" ],[ ax_compiler_no_suggest_attribute_flags="" ]) # Base flags AX_APPEND_COMPILE_FLAGS([ dnl -fno-strict-aliasing dnl $3 dnl ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) AS_IF([test "$ax_enable_compile_warnings" != "no"],[ if test "$ax_compiler_cxx" = "no" ; then # C-only flags. Warn in C++ AX_APPEND_COMPILE_FLAGS([ dnl -Wnested-externs dnl -Wmissing-prototypes dnl -Wstrict-prototypes dnl -Wdeclaration-after-statement dnl -Wimplicit-function-declaration dnl -Wold-style-definition dnl -Wjump-misses-init dnl ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) fi # "yes" flags AX_APPEND_COMPILE_FLAGS([ dnl -Wall dnl -Wextra dnl -Wundef dnl -Wwrite-strings dnl -Wpointer-arith dnl -Wmissing-declarations dnl -Wredundant-decls dnl -Wno-unused-parameter dnl -Wno-missing-field-initializers dnl -Wformat=2 dnl -Wcast-align dnl -Wformat-nonliteral dnl -Wformat-security dnl -Wsign-compare dnl -Wstrict-aliasing dnl -Wshadow dnl -Winline dnl -Wpacked dnl -Wmissing-format-attribute dnl -Wmissing-noreturn dnl -Winit-self dnl -Wredundant-decls dnl -Wmissing-include-dirs dnl -Wunused-but-set-variable dnl -Warray-bounds dnl -Wreturn-type dnl -Wswitch-enum dnl -Wswitch-default dnl -Wduplicated-cond dnl -Wduplicated-branches dnl -Wlogical-op dnl -Wrestrict dnl -Wnull-dereference dnl -Wdouble-promotion dnl $4 dnl $5 dnl $6 dnl $7 dnl ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) ]) AS_IF([test "$ax_enable_compile_warnings" = "error"],[ # "error" flags; -Werror has to be appended unconditionally because # it's not possible to test for # # suggest-attribute=format is disabled because it gives too many false # positives AX_APPEND_FLAG([-Werror],ax_warn_cflags_variable) AX_APPEND_COMPILE_FLAGS([ dnl [$ax_compiler_no_suggest_attribute_flags] dnl ],ax_warn_cflags_variable,[$ax_compiler_flags_test]) ]) # In the flags below, when disabling specific flags, always add *both* # -Wno-foo and -Wno-error=foo. This fixes the situation where (for example) # we enable -Werror, disable a flag, and a build bot passes CFLAGS=-Wall, # which effectively turns that flag back on again as an error. for flag in $ax_warn_cflags_variable; do AS_CASE([$flag], [-Wno-*=*],[], [-Wno-*],[ AX_APPEND_COMPILE_FLAGS([-Wno-error=$(AS_ECHO([$flag]) | $SED 's/^-Wno-//')], ax_warn_cflags_variable, [$ax_compiler_flags_test]) ]) done AC_LANG_POP([C]) # Substitute the variables AC_SUBST(ax_warn_cflags_variable) ])dnl AX_COMPILER_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_gir.html # =========================================================================== # # SYNOPSIS # # AX_COMPILER_FLAGS_GIR([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) # # DESCRIPTION # # Add warning flags for the g-ir-scanner (from GObject Introspection) to # VARIABLE, which defaults to WARN_SCANNERFLAGS. VARIABLE is AC_SUBST-ed # by this macro, but must be manually added to the SCANNERFLAGS variable # for each GIR target in the code base. # # This macro depends on the environment set up by AX_COMPILER_FLAGS. # Specifically, it uses the value of $ax_enable_compile_warnings to decide # which flags to enable. # # LICENSE # # Copyright (c) 2015 Philip Withnall # # 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 any # warranty. #serial 6 AC_DEFUN([AX_COMPILER_FLAGS_GIR],[ AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) # Variable names m4_define([ax_warn_scannerflags_variable], [m4_normalize(ifelse([$1],,[WARN_SCANNERFLAGS],[$1]))]) # Base flags AX_APPEND_FLAG([$3],ax_warn_scannerflags_variable) AS_IF([test "$ax_enable_compile_warnings" != "no"],[ # "yes" flags AX_APPEND_FLAG([ dnl --warn-all dnl $4 dnl $5 dnl $6 dnl $7 dnl ],ax_warn_scannerflags_variable) ]) AS_IF([test "$ax_enable_compile_warnings" = "error"],[ # "error" flags AX_APPEND_FLAG([ dnl --warn-error dnl ],ax_warn_scannerflags_variable) ]) # Substitute the variables AC_SUBST(ax_warn_scannerflags_variable) ])dnl AX_COMPILER_FLAGS # ============================================================================== # https://www.gnu.org/software/autoconf-archive/ax_compiler_flags_ldflags.html # ============================================================================== # # SYNOPSIS # # AX_COMPILER_FLAGS_LDFLAGS([VARIABLE], [IS-RELEASE], [EXTRA-BASE-FLAGS], [EXTRA-YES-FLAGS]) # # DESCRIPTION # # Add warning flags for the linker to VARIABLE, which defaults to # WARN_LDFLAGS. VARIABLE is AC_SUBST-ed by this macro, but must be # manually added to the LDFLAGS variable for each target in the code base. # # This macro depends on the environment set up by AX_COMPILER_FLAGS. # Specifically, it uses the value of $ax_enable_compile_warnings to decide # which flags to enable. # # LICENSE # # Copyright (c) 2014, 2015 Philip Withnall # Copyright (c) 2017, 2018 Reini Urban # # 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 any # warranty. #serial 9 AC_DEFUN([AX_COMPILER_FLAGS_LDFLAGS],[ AX_REQUIRE_DEFINED([AX_APPEND_LINK_FLAGS]) AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG]) AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) # Variable names m4_define([ax_warn_ldflags_variable], [m4_normalize(ifelse([$1],,[WARN_LDFLAGS],[$1]))]) # Always pass -Werror=unknown-warning-option to get Clang to fail on bad # flags, otherwise they are always appended to the warn_ldflags variable, # and Clang warns on them for every compilation unit. # If this is passed to GCC, it will explode, so the flag must be enabled # conditionally. AX_CHECK_COMPILE_FLAG([-Werror=unknown-warning-option],[ ax_compiler_flags_test="-Werror=unknown-warning-option" ],[ ax_compiler_flags_test="" ]) AX_CHECK_LINK_FLAG([-Wl,--as-needed], [ AX_APPEND_LINK_FLAGS([-Wl,--as-needed], [AM_LDFLAGS],[$ax_compiler_flags_test]) ]) AX_CHECK_LINK_FLAG([-Wl,-z,relro], [ AX_APPEND_LINK_FLAGS([-Wl,-z,relro], [AM_LDFLAGS],[$ax_compiler_flags_test]) ]) AX_CHECK_LINK_FLAG([-Wl,-z,now], [ AX_APPEND_LINK_FLAGS([-Wl,-z,now], [AM_LDFLAGS],[$ax_compiler_flags_test]) ]) AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [ AX_APPEND_LINK_FLAGS([-Wl,-z,noexecstack], [AM_LDFLAGS],[$ax_compiler_flags_test]) ]) # textonly, retpolineplt not yet # macOS and cygwin linker do not have --as-needed AX_CHECK_LINK_FLAG([-Wl,--no-as-needed], [ ax_compiler_flags_as_needed_option="-Wl,--no-as-needed" ], [ ax_compiler_flags_as_needed_option="" ]) # macOS linker speaks with a different accent ax_compiler_flags_fatal_warnings_option="" AX_CHECK_LINK_FLAG([-Wl,--fatal-warnings], [ ax_compiler_flags_fatal_warnings_option="-Wl,--fatal-warnings" ]) AX_CHECK_LINK_FLAG([-Wl,-fatal_warnings], [ ax_compiler_flags_fatal_warnings_option="-Wl,-fatal_warnings" ]) # Base flags AX_APPEND_LINK_FLAGS([ dnl $ax_compiler_flags_as_needed_option dnl $3 dnl ],ax_warn_ldflags_variable,[$ax_compiler_flags_test]) AS_IF([test "$ax_enable_compile_warnings" != "no"],[ # "yes" flags AX_APPEND_LINK_FLAGS([$4 $5 $6 $7], ax_warn_ldflags_variable, [$ax_compiler_flags_test]) ]) AS_IF([test "$ax_enable_compile_warnings" = "error"],[ # "error" flags; -Werror has to be appended unconditionally because # it's not possible to test for # # suggest-attribute=format is disabled because it gives too many false # positives AX_APPEND_LINK_FLAGS([ dnl $ax_compiler_flags_fatal_warnings_option dnl ],ax_warn_ldflags_variable,[$ax_compiler_flags_test]) ]) # Substitute the variables AC_SUBST(ax_warn_ldflags_variable) ])dnl AX_COMPILER_FLAGS # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_is_release.html # =========================================================================== # # SYNOPSIS # # AX_IS_RELEASE(POLICY) # # DESCRIPTION # # Determine whether the code is being configured as a release, or from # git. Set the ax_is_release variable to 'yes' or 'no'. # # If building a release version, it is recommended that the configure # script disable compiler errors and debug features, by conditionalising # them on the ax_is_release variable. If building from git, these # features should be enabled. # # The POLICY parameter specifies how ax_is_release is determined. It can # take the following values: # # * git-directory: ax_is_release will be 'no' if a '.git' # directory or git worktree exists # * minor-version: ax_is_release will be 'no' if the minor version number # in $PACKAGE_VERSION is odd; this assumes # $PACKAGE_VERSION follows the 'major.minor.micro' scheme # * micro-version: ax_is_release will be 'no' if the micro version number # in $PACKAGE_VERSION is odd; this assumes # $PACKAGE_VERSION follows the 'major.minor.micro' scheme # * dash-version: ax_is_release will be 'no' if there is a dash '-' # in $PACKAGE_VERSION, for example 1.2-pre3, 1.2.42-a8b9 # or 2.0-dirty (in particular this is suitable for use # with git-version-gen) # * always: ax_is_release will always be 'yes' # * never: ax_is_release will always be 'no' # # Other policies may be added in future. # # LICENSE # # Copyright (c) 2015 Philip Withnall # Copyright (c) 2016 Collabora Ltd. # # 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. #serial 8 AC_DEFUN([AX_IS_RELEASE],[ AC_BEFORE([AC_INIT],[$0]) m4_case([$1], [git-directory],[ # $is_release = (.git directory does not exist) AS_IF([test -d ${srcdir}/.git || (test -f ${srcdir}/.git && grep \.git/worktrees ${srcdir}/.git)],[ax_is_release=no],[ax_is_release=yes]) ], [minor-version],[ # $is_release = ($minor_version is even) minor_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'` AS_IF([test "$(( $minor_version % 2 ))" -ne 0], [ax_is_release=no],[ax_is_release=yes]) ], [micro-version],[ # $is_release = ($micro_version is even) micro_version=`echo "$PACKAGE_VERSION" | sed 's/[[^.]]*\.[[^.]]*\.\([[^.]]*\).*/\1/'` AS_IF([test "$(( $micro_version % 2 ))" -ne 0], [ax_is_release=no],[ax_is_release=yes]) ], [dash-version],[ # $is_release = ($PACKAGE_VERSION has a dash) AS_CASE([$PACKAGE_VERSION], [*-*], [ax_is_release=no], [*], [ax_is_release=yes]) ], [always],[ax_is_release=yes], [never],[ax_is_release=no], [ AC_MSG_ERROR([Invalid policy. Valid policies: git-directory, minor-version, micro-version, dash-version, always, never.]) ]) ]) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_java.html # =========================================================================== # # SYNOPSIS # # AX_PROG_JAVA # # DESCRIPTION # # Here is a summary of the main macros: # # AX_PROG_JAVAC: finds a Java compiler. # # AX_PROG_JAVA: finds a Java virtual machine. # # AX_CHECK_CLASS: finds if we have the given class (beware of CLASSPATH!). # # AX_CHECK_RQRD_CLASS: finds if we have the given class and stops # otherwise. # # AX_TRY_COMPILE_JAVA: attempt to compile user given source. # # AX_TRY_RUN_JAVA: attempt to compile and run user given source. # # AX_JAVA_OPTIONS: adds Java configure options. # # AX_PROG_JAVA tests an existing Java virtual machine. It uses the # environment variable JAVA then tests in sequence various common Java # virtual machines. For political reasons, it starts with the free ones. # You *must* call [AX_PROG_JAVAC] before. # # If you want to force a specific VM: # # - at the configure.in level, set JAVA=yourvm before calling AX_PROG_JAVA # # (but after AC_INIT) # # - at the configure level, setenv JAVA # # You can use the JAVA variable in your Makefile.in, with @JAVA@. # # *Warning*: its success or failure can depend on a proper setting of the # CLASSPATH env. variable. # # TODO: allow to exclude virtual machines (rationale: most Java programs # cannot run with some VM like kaffe). # # Note: This is part of the set of autoconf M4 macros for Java programs. # It is VERY IMPORTANT that you download the whole set, some macros depend # on other. Unfortunately, the autoconf archive does not support the # concept of set of macros, so I had to break it for submission. # # A Web page, with a link to the latest CVS snapshot is at # . # # This is a sample configure.in Process this file with autoconf to produce # a configure script. # # AC_INIT(UnTag.java) # # dnl Checks for programs. # AC_CHECK_CLASSPATH # AX_PROG_JAVAC # AX_PROG_JAVA # # dnl Checks for classes # AX_CHECK_RQRD_CLASS(org.xml.sax.Parser) # AX_CHECK_RQRD_CLASS(com.jclark.xml.sax.Driver) # # AC_OUTPUT(Makefile) # # LICENSE # # Copyright (c) 2008 Stephane Bortzmeyer # # 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 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, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 10 AU_ALIAS([AC_PROG_JAVA], [AX_PROG_JAVA]) AC_DEFUN([AX_PROG_JAVA],[ m4_define([m4_ax_prog_java_list], [kaffe java])dnl AS_IF([test "x$JAVAPREFIX" = x], [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list])], [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list], [], [$JAVAPREFIX/bin])]) test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH]) m4_undefine([m4_ax_prog_java_list])dnl AX_PROG_JAVA_WORKS AC_PROVIDE([$0])dnl ]) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_java_works.html # =========================================================================== # # SYNOPSIS # # AX_PROG_JAVA_WORKS # # DESCRIPTION # # Internal use ONLY. # # Note: This is part of the set of autoconf M4 macros for Java programs. # It is VERY IMPORTANT that you download the whole set, some macros depend # on other. Unfortunately, the autoconf archive does not support the # concept of set of macros, so I had to break it for submission. The # general documentation, as well as the sample configure.in, is included # in the AX_PROG_JAVA macro. # # LICENSE # # Copyright (c) 2008 Stephane Bortzmeyer # # 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 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, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 11 AU_ALIAS([AC_PROG_JAVA_WORKS], [AX_PROG_JAVA_WORKS]) AC_DEFUN([AX_PROG_JAVA_WORKS], [ if test x$ac_cv_prog_javac_works = xno; then AC_MSG_ERROR([Cannot compile java source. $JAVAC does not work properly]) fi if test x$ac_cv_prog_javac_works = x; then AX_PROG_JAVAC fi AC_CACHE_CHECK(if $JAVA works, ac_cv_prog_java_works, [ JAVA_TEST=Test.java CLASS_TEST=Test.class TEST=Test changequote(, )dnl cat << \EOF > $JAVA_TEST /* [#]line __oline__ "configure" */ public class Test { public static void main (String args[]) { System.exit (0); } } EOF changequote([, ])dnl if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) && test -s $CLASS_TEST; then : else echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD cat $JAVA_TEST >&AS_MESSAGE_LOG_FD AC_MSG_ERROR(The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)) fi if AC_TRY_COMMAND($JAVA -classpath . $JAVAFLAGS $TEST) >/dev/null 2>&1; then ac_cv_prog_java_works=yes else echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD cat $JAVA_TEST >&AS_MESSAGE_LOG_FD AC_MSG_ERROR(The Java VM $JAVA failed (see config.log, check the CLASSPATH?)) fi rm -f $JAVA_TEST $CLASS_TEST ]) AC_PROVIDE([$0])dnl ] ) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_javac.html # =========================================================================== # # SYNOPSIS # # AX_PROG_JAVAC # # DESCRIPTION # # AX_PROG_JAVAC tests an existing Java compiler. It uses the environment # variable JAVAC then tests in sequence various common Java compilers. For # political reasons, it starts with the free ones. # # If you want to force a specific compiler: # # - at the configure.in level, set JAVAC=yourcompiler before calling # AX_PROG_JAVAC # # - at the configure level, setenv JAVAC # # You can use the JAVAC variable in your Makefile.in, with @JAVAC@. # # *Warning*: its success or failure can depend on a proper setting of the # CLASSPATH env. variable. # # TODO: allow to exclude compilers (rationale: most Java programs cannot # compile with some compilers like guavac). # # Note: This is part of the set of autoconf M4 macros for Java programs. # It is VERY IMPORTANT that you download the whole set, some macros depend # on other. Unfortunately, the autoconf archive does not support the # concept of set of macros, so I had to break it for submission. The # general documentation, as well as the sample configure.in, is included # in the AX_PROG_JAVA macro. # # LICENSE # # Copyright (c) 2008 Stephane Bortzmeyer # # 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 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, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 8 AU_ALIAS([AC_PROG_JAVAC], [AX_PROG_JAVAC]) AC_DEFUN([AX_PROG_JAVAC],[ m4_define([m4_ax_prog_javac_list],["gcj -C" guavac jikes javac])dnl AS_IF([test "x$JAVAPREFIX" = x], [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list])], [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list], [], [$JAVAPREFIX/bin])]) m4_undefine([m4_ax_prog_javac_list])dnl test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH]) AX_PROG_JAVAC_WORKS AC_PROVIDE([$0])dnl ]) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_javac_works.html # =========================================================================== # # SYNOPSIS # # AX_PROG_JAVAC_WORKS # # DESCRIPTION # # Internal use ONLY. # # Note: This is part of the set of autoconf M4 macros for Java programs. # It is VERY IMPORTANT that you download the whole set, some macros depend # on other. Unfortunately, the autoconf archive does not support the # concept of set of macros, so I had to break it for submission. The # general documentation, as well as the sample configure.in, is included # in the AX_PROG_JAVA macro. # # LICENSE # # Copyright (c) 2008 Stephane Bortzmeyer # # 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 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, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 7 AU_ALIAS([AC_PROG_JAVAC_WORKS], [AX_PROG_JAVAC_WORKS]) AC_DEFUN([AX_PROG_JAVAC_WORKS],[ AC_CACHE_CHECK([if $JAVAC works], ac_cv_prog_javac_works, [ JAVA_TEST=Test.java CLASS_TEST=Test.class cat << \EOF > $JAVA_TEST /* [#]line __oline__ "configure" */ public class Test { } EOF if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) >/dev/null 2>&1; then ac_cv_prog_javac_works=yes else AC_MSG_ERROR([The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)]) echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD cat $JAVA_TEST >&AS_MESSAGE_LOG_FD fi rm -f $JAVA_TEST $CLASS_TEST ]) AC_PROVIDE([$0])dnl ]) # =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_require_defined.html # =========================================================================== # # SYNOPSIS # # AX_REQUIRE_DEFINED(MACRO) # # DESCRIPTION # # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have # been defined and thus are available for use. This avoids random issues # where a macro isn't expanded. Instead the configure script emits a # non-fatal: # # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found # # It's like AC_REQUIRE except it doesn't expand the required macro. # # Here's an example: # # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) # # LICENSE # # Copyright (c) 2014 Mike Frysinger # # 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 any # warranty. #serial 2 AC_DEFUN([AX_REQUIRE_DEFINED], [dnl m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) ])dnl AX_REQUIRE_DEFINED # pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurrence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES #------------------------------------------------------------------------ # SC_PATH_TCLCONFIG -- # # Locate the tclConfig.sh file and perform a sanity check on # the Tcl compile flags # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tcl=... # # Defines the following vars: # TCL_BIN_DIR Full path to the directory containing # the tclConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TCLCONFIG], [ # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true AC_ARG_WITH(tcl, AS_HELP_STRING([--with-tcl], [directory containing tcl configuration (tclConfig.sh)]), [with_tclconfig="${withval}"]) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself]) with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh]) fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh]) else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_PATH_TKCONFIG -- # # Locate the tkConfig.sh file # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --with-tk=... # # Defines the following vars: # TK_BIN_DIR Full path to the directory containing # the tkConfig.sh file #------------------------------------------------------------------------ AC_DEFUN([SC_PATH_TKCONFIG], [ # # Ok, lets find the tk configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tk # if test x"${no_tk}" = x ; then # we reset no_tk in case something fails here no_tk=true AC_ARG_WITH(tk, AS_HELP_STRING([--with-tk], [directory containing tk configuration (tkConfig.sh)]), [with_tkconfig="${withval}"]) AC_MSG_CHECKING([for Tk configuration]) AC_CACHE_VAL(ac_cv_c_tkconfig,[ # First check to see if --with-tkconfig was specified. if test x"${with_tkconfig}" != x ; then case "${with_tkconfig}" in */tkConfig.sh ) if test -f "${with_tkconfig}"; then AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself]) with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`" fi ;; esac if test -f "${with_tkconfig}/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`" else AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh]) fi fi # then check for a private Tk library if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ../tk \ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../tk \ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \ ../../../tk \ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ ; do if test -f "$i/Tk.framework/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib/tk8.6 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/local/lib/tk8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tk8.6 2>/dev/null` \ ; do if test -f "$i/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tkconfig}" = x ; then for i in \ ${srcdir}/../tk \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do if test -f "$i/unix/tkConfig.sh" ; then ac_cv_c_tkconfig="`(cd $i/unix; pwd)`" break fi done fi ]) if test x"${ac_cv_c_tkconfig}" = x ; then TK_BIN_DIR="# no Tk configs found" AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh]) else no_tk= TK_BIN_DIR="${ac_cv_c_tkconfig}" AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh]) fi fi ]) #------------------------------------------------------------------------ # SC_LOAD_TCLCONFIG -- # # Load the tclConfig.sh file # # Arguments: # # Requires the following vars to be set: # TCL_BIN_DIR # # Results: # # Substitutes the following vars: # TCL_BIN_DIR # TCL_SRC_DIR # TCL_LIB_FILE #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TCLCONFIG], [ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh]) if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TCL_BIN_DIR}/tclConfig.sh" else AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh]) fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi AC_SUBST(TCL_VERSION) AC_SUBST(TCL_PATCH_LEVEL) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) AC_SUBST(TCL_STUB_LIB_FLAG) AC_SUBST(TCL_STUB_LIB_SPEC) ]) #------------------------------------------------------------------------ # SC_LOAD_TKCONFIG -- # # Load the tkConfig.sh file # # Arguments: # # Requires the following vars to be set: # TK_BIN_DIR # # Results: # # Sets the following vars that should be in tkConfig.sh: # TK_BIN_DIR #------------------------------------------------------------------------ AC_DEFUN([SC_LOAD_TKCONFIG], [ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh]) if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then AC_MSG_RESULT([loading]) . "${TK_BIN_DIR}/tkConfig.sh" else AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh]) fi # If the TK_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TK_LIB_SPEC will be set to the value # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC # instead of TK_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TK_BIN_DIR}/Makefile" ; then TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}" TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}" TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tk was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tk.framework installed in an arbitrary location. case ${TK_DEFS} in *TK_FRAMEWORK*) if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then for i in "`cd "${TK_BIN_DIR}"; pwd`" \ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}" break fi done fi if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}" TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}" fi ;; esac fi AC_SUBST(TK_VERSION) AC_SUBST(TK_BIN_DIR) AC_SUBST(TK_SRC_DIR) AC_SUBST(TK_LIB_FILE) AC_SUBST(TK_LIB_FLAG) AC_SUBST(TK_LIB_SPEC) AC_SUBST(TK_STUB_LIB_FILE) AC_SUBST(TK_STUB_LIB_FLAG) AC_SUBST(TK_STUB_LIB_SPEC) ]) #------------------------------------------------------------------------ # SC_PROG_TCLSH # Locate a tclsh shell installed on the system path. This macro # will only find a Tcl shell that already exists on the system. # It will not find a Tcl shell in the Tcl build directory or # a Tcl shell that has been installed from the Tcl build directory. # If a Tcl shell can't be located on the PATH, then TCLSH_PROG will # be set to "". Extensions should take care not to create Makefile # rules that are run by default and depend on TCLSH_PROG. An # extension can't assume that an executable Tcl shell exists at # build time. # # Arguments: # none # # Results: # Substitutes the following vars: # TCLSH_PROG #------------------------------------------------------------------------ AC_DEFUN([SC_PROG_TCLSH], [ AC_MSG_CHECKING([for tclsh]) AC_CACHE_VAL(ac_cv_path_tclsh, [ search_path=`echo ${PATH} | sed -e 's/:/ /g'` for dir in $search_path ; do for j in `ls -r $dir/tclsh[[8-9]]* 2> /dev/null` \ `ls -r $dir/tclsh* 2> /dev/null` ; do if test x"$ac_cv_path_tclsh" = x ; then if test -f "$j" ; then ac_cv_path_tclsh=$j break fi fi done done ]) if test -f "$ac_cv_path_tclsh" ; then TCLSH_PROG="$ac_cv_path_tclsh" AC_MSG_RESULT([$TCLSH_PROG]) else # It is not an error if an installed version of Tcl can't be located. TCLSH_PROG="" AC_MSG_RESULT([No tclsh found on PATH]) fi AC_SUBST(TCLSH_PROG) ]) #------------------------------------------------------------------------ # SC_BUILD_TCLSH # Determine the fully qualified path name of the tclsh executable # in the Tcl build directory. This macro will correctly determine # the name of the tclsh executable even if tclsh has not yet # been built in the build directory. The build tclsh must be used # when running tests from an extension build directory. It is not # correct to use the TCLSH_PROG in cases like this. # # Arguments: # none # # Results: # Substitutes the following values: # BUILD_TCLSH #------------------------------------------------------------------------ AC_DEFUN([SC_BUILD_TCLSH], [ AC_MSG_CHECKING([for tclsh in Tcl build directory]) BUILD_TCLSH="${TCL_BIN_DIR}"/tclsh AC_MSG_RESULT([$BUILD_TCLSH]) AC_SUBST(BUILD_TCLSH) ]) #------------------------------------------------------------------------ # SC_ENABLE_SHARED -- # # Allows the building of shared libraries # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-shared=yes|no # # Defines the following vars: # STATIC_BUILD Used for building import/export libraries # on Windows. # # Sets the following vars: # SHARED_BUILD Value of 1 or 0 #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_SHARED], [ AC_MSG_CHECKING([how to build libraries]) AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared], [build and link with shared libraries (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "$tcl_ok" = "yes" ; then AC_MSG_RESULT([shared]) SHARED_BUILD=1 else AC_MSG_RESULT([static]) SHARED_BUILD=0 AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?]) fi AC_SUBST(SHARED_BUILD) ]) #------------------------------------------------------------------------ # SC_ENABLE_FRAMEWORK -- # # Allows the building of shared libraries into frameworks # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-framework=yes|no # # Sets the following vars: # FRAMEWORK_BUILD Value of 1 or 0 #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_FRAMEWORK], [ if test "`uname -s`" = "Darwin" ; then AC_MSG_CHECKING([how to package libraries]) AC_ARG_ENABLE(framework, AS_HELP_STRING([--enable-framework], [package shared libraries in MacOSX frameworks (default: off)]), [enable_framework=$enableval], [enable_framework=no]) if test $enable_framework = yes; then if test $SHARED_BUILD = 0; then AC_MSG_WARN([Frameworks can only be built if --enable-shared is yes]) enable_framework=no fi if test $tcl_corefoundation = no; then AC_MSG_WARN([Frameworks can only be used when CoreFoundation is available]) enable_framework=no fi fi if test $enable_framework = yes; then AC_MSG_RESULT([framework]) FRAMEWORK_BUILD=1 else if test $SHARED_BUILD = 1; then AC_MSG_RESULT([shared library]) else AC_MSG_RESULT([static library]) fi FRAMEWORK_BUILD=0 fi fi ]) #------------------------------------------------------------------------ # SC_ENABLE_THREADS -- # # Specify if thread support should be enabled # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-threads # # Sets the following vars: # THREADS_LIBS Thread library(s) # # Defines the following vars: # TCL_THREADS # _REENTRANT # _THREAD_SAFE #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_THREADS], [ AC_ARG_ENABLE(threads, AS_HELP_STRING([--enable-threads], [build with threads (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) if test "${TCL_THREADS}" = 1; then tcl_threaded_core=1; fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention AC_DEFINE(USE_THREAD_ALLOC, 1, [Do we want to use the threaded memory allocator?]) AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) if test "`uname -s`" = "SunOS" ; then AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) fi AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?]) AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no) if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] AC_CHECK_LIB(pthread, __pthread_mutex_init, tcl_ok=yes, tcl_ok=no) fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else AC_CHECK_LIB(pthreads, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else AC_CHECK_LIB(c, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "no"; then AC_CHECK_LIB(c_r, pthread_mutex_init, tcl_ok=yes, tcl_ok=no) if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 AC_MSG_WARN([Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile...]) fi fi fi fi # Does the pthread-implementation provide # 'pthread_attr_setstacksize' ? ac_saved_libs=$LIBS LIBS="$LIBS $THREADS_LIBS" AC_CHECK_FUNCS(pthread_attr_setstacksize pthread_atfork) LIBS=$ac_saved_libs else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output AC_MSG_CHECKING([for building with threads]) if test "${TCL_THREADS}" = 1; then AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?]) if test "${tcl_threaded_core}" = 1; then AC_MSG_RESULT([yes (threaded core)]) else AC_MSG_RESULT([yes]) fi else AC_MSG_RESULT([no]) fi AC_SUBST(TCL_THREADS) ]) #------------------------------------------------------------------------ # SC_ENABLE_SYMBOLS -- # # Specify if debugging symbols should be used. # Memory (TCL_MEM_DEBUG) and compile (TCL_COMPILE_DEBUG) debugging # can also be enabled. # # Arguments: # none # # Requires the following vars to be set in the Makefile: # CFLAGS_DEBUG # CFLAGS_OPTIMIZE # LDFLAGS_DEBUG # LDFLAGS_OPTIMIZE # # Results: # # Adds the following arguments to configure: # --enable-symbols # # Defines the following vars: # CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true # Sets to $(CFLAGS_OPTIMIZE) if false # LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true # Sets to $(LDFLAGS_OPTIMIZE) if false #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_SYMBOLS], [ AC_MSG_CHECKING([for build with symbols]) AC_ARG_ENABLE(symbols, AS_HELP_STRING([--enable-symbols], [build with debugging symbols (default: off)]), [tcl_ok=$enableval], [tcl_ok=no]) # FIXME: Currently, LDFLAGS_DEFAULT is not used, it should work like CFLAGS_DEFAULT. if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT='$(CFLAGS_OPTIMIZE)' LDFLAGS_DEFAULT='$(LDFLAGS_OPTIMIZE)' AC_DEFINE(NDEBUG, 1, [Is no debugging enabled?]) AC_MSG_RESULT([no]) AC_DEFINE(TCL_CFG_OPTIMIZED, 1, [Is this an optimized build?]) else CFLAGS_DEFAULT='$(CFLAGS_DEBUG)' LDFLAGS_DEFAULT='$(LDFLAGS_DEBUG)' if test "$tcl_ok" = "yes"; then AC_MSG_RESULT([yes (standard debugging)]) fi fi AC_SUBST(CFLAGS_DEFAULT) AC_SUBST(LDFLAGS_DEFAULT) if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?]) fi ifelse($1,bccdebug,dnl Only enable 'compile' for the Tcl core itself if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then AC_DEFINE(TCL_COMPILE_DEBUG, 1, [Is bytecode debugging enabled?]) AC_DEFINE(TCL_COMPILE_STATS, 1, [Are bytecode statistics enabled?]) fi) if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then AC_MSG_RESULT([enabled symbols mem ]ifelse($1,bccdebug,[compile ])[debugging]) else AC_MSG_RESULT([enabled $tcl_ok debugging]) fi fi ]) #------------------------------------------------------------------------ # SC_ENABLE_LANGINFO -- # # Allows use of modern nl_langinfo check for better l10n. # This is only relevant for Unix. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-langinfo=yes|no (default is yes) # # Defines the following vars: # HAVE_LANGINFO Triggers use of nl_langinfo if defined. #------------------------------------------------------------------------ AC_DEFUN([SC_ENABLE_LANGINFO], [ AC_ARG_ENABLE(langinfo, AS_HELP_STRING([--enable-langinfo], [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]), [langinfo_ok=$enableval], [langinfo_ok=yes]) HAVE_LANGINFO=0 if test "$langinfo_ok" = "yes"; then AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no]) fi AC_MSG_CHECKING([whether to use nl_langinfo]) if test "$langinfo_ok" = "yes"; then AC_CACHE_VAL(tcl_cv_langinfo_h, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[nl_langinfo(CODESET);]])], [tcl_cv_langinfo_h=yes], [tcl_cv_langinfo_h=no])]) AC_MSG_RESULT([$tcl_cv_langinfo_h]) if test $tcl_cv_langinfo_h = yes; then AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?]) fi else AC_MSG_RESULT([$langinfo_ok]) fi ]) #-------------------------------------------------------------------- # SC_CONFIG_MANPAGES # # Decide whether to use symlinks for linking the manpages, # whether to compress the manpages after installation, and # whether to add a package name suffix to the installed # manpages to avoidfile name clashes. # If compression is enabled also find out what file name suffix # the given compression program is using. # # Arguments: # none # # Results: # # Adds the following arguments to configure: # --enable-man-symlinks # --enable-man-compression=PROG # --enable-man-suffix[=STRING] # # Defines the following variable: # # MAN_FLAGS - The apropriate flags for installManPage # according to the user's selection. # #-------------------------------------------------------------------- AC_DEFUN([SC_CONFIG_MANPAGES], [ AC_MSG_CHECKING([whether to use symlinks for manpages]) AC_ARG_ENABLE(man-symlinks, AS_HELP_STRING([--enable-man-symlinks], [use symlinks for the manpages (default: off)]), [test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"], [enableval="no"]) AC_MSG_RESULT([$enableval]) AC_MSG_CHECKING([whether to compress the manpages]) AC_ARG_ENABLE(man-compression, AS_HELP_STRING([--enable-man-compression=PROG], [compress the manpages with PROG (default: off)]), [case $enableval in yes) AC_MSG_ERROR([missing argument to --enable-man-compression]);; no) ;; *) MAN_FLAGS="$MAN_FLAGS --compress $enableval";; esac], [enableval="no"]) AC_MSG_RESULT([$enableval]) if test "$enableval" != "no"; then AC_MSG_CHECKING([for compressed file suffix]) touch TeST $enableval TeST Z=`ls TeST* | sed 's/^....//'` rm -f TeST* MAN_FLAGS="$MAN_FLAGS --extension $Z" AC_MSG_RESULT([$Z]) fi AC_MSG_CHECKING([whether to add a package name suffix for the manpages]) AC_ARG_ENABLE(man-suffix, AS_HELP_STRING([--enable-man-suffix=STRING], [use STRING as a suffix to manpage file names (default: no, AC_PACKAGE_NAME if enabled without specifying STRING)]), [case $enableval in yes) enableval="AC_PACKAGE_NAME" MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; no) ;; *) MAN_FLAGS="$MAN_FLAGS --suffix $enableval";; esac], [enableval="no"]) AC_MSG_RESULT([$enableval]) AC_SUBST(MAN_FLAGS) ]) #-------------------------------------------------------------------- # SC_CONFIG_SYSTEM # # Determine what the system is (some things cannot be easily checked # on a feature-driven basis, alas). This can usually be done via the # "uname" command, but there are a few systems, like Next, where # this doesn't work. # # Arguments: # none # # Results: # Defines the following var: # # system - System/platform/version identification code. # #-------------------------------------------------------------------- AC_DEFUN([SC_CONFIG_SYSTEM], [ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [ if test -f /usr/lib/NextStep/software_version; then tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then AC_MSG_WARN([can't find uname command]) tcl_cv_sys_version=unknown else # Special check for weird MP-RAS system (uname returns weird # results, and the version is kept in special file). if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then tcl_cv_sys_version=MP-RAS-`awk '{print $[3]}' /etc/.relid` fi if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi ]) system=$tcl_cv_sys_version ]) #-------------------------------------------------------------------- # SC_CONFIG_CFLAGS # # Try to determine the proper flags to pass to the compiler # for building shared libraries and other such nonsense. # # Arguments: # none # # Results: # # Defines and substitutes the following vars: # # DL_OBJS - Name of the object file that implements dynamic # loading for Tcl on this system. # DL_LIBS - Library file(s) to include in tclsh and other base # applications in order for the "load" command to work. # LDFLAGS - Flags to pass to the compiler when linking object # files into an executable application binary such # as tclsh. # LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. Could # be the same as CC_SEARCH_FLAGS if ${CC} is used to link. # CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib", # that tell the run-time dynamic linker where to look # for shared libraries such as libtcl.so. Depends on # the variable LIB_RUNTIME_DIR in the Makefile. # MAKE_LIB - Command to execute to build the a library; # differs when building shared or static. # MAKE_STUB_LIB - # Command to execute to build a stub library. # INSTALL_LIB - Command to execute to install a library; # differs when building shared or static. # INSTALL_STUB_LIB - # Command to execute to install a stub library. # STLIB_LD - Base command to use for combining object files # into a static library. # SHLIB_CFLAGS - Flags to pass to cc when compiling the components # of a shared library (may request position-independent # code, among other things). # SHLIB_LD - Base command to use for combining object files # into a shared library. # SHLIB_LD_LIBS - Dependent libraries for the linker to scan when # creating shared libraries. This symbol typically # goes at the end of the "ld" commands that build # shared libraries. The value of the symbol defaults to # "${LIBS}" if all of the dependent libraries should # be specified when creating a shared library. If # dependent libraries should not be specified (as on # SunOS 4.x, where they cause the link to fail, or in # general if Tcl and Tk aren't themselves shared # libraries), then this symbol has an empty string # as its value. # SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable # extensions. An empty string means we don't know how # to use shared libraries on this platform. # TCL_SHLIB_LD_EXTRAS - Additional element which are added to SHLIB_LD_LIBS # TK_SHLIB_LD_EXTRAS for the build of Tcl and Tk, but not recorded in the # tclConfig.sh, since they are only used for the build # of Tcl and Tk. # Examples: MacOS X records the library version and # compatibility version in the shared library. But # of course the Tcl version of this is only used for Tcl. # LIB_SUFFIX - Specifies everything that comes after the "libfoo" # in a static or shared library name, using the $VERSION variable # to put the version in the right place. This is used # by platforms that need non-standard library names. # Examples: ${VERSION}.so.1.1 on NetBSD, since it needs # to have a version after the .so, and ${VERSION}.a # on AIX, since a shared library needs to have # a .a extension whereas shared objects for loadable # extensions have a .so extension. Defaults to # ${VERSION}${SHLIB_SUFFIX}. # TCL_LIBS - # Libs to use when linking Tcl shell or some other # shell that includes Tcl libs. # CFLAGS_DEBUG - # Flags used when running the compiler in debug mode # CFLAGS_OPTIMIZE - # Flags used when running the compiler in optimize mode # CFLAGS - Additional CFLAGS added as necessary (usually 64-bit) # #-------------------------------------------------------------------- AC_DEFUN([SC_CONFIG_CFLAGS], [ # Step 0.a: Enable 64 bit support? AC_MSG_CHECKING([if 64bit support is requested]) AC_ARG_ENABLE(64bit, AS_HELP_STRING([--enable-64bit], [enable 64bit support (default: off)]), [do64bit=$enableval], [do64bit=no]) AC_MSG_RESULT([$do64bit]) # Step 0.b: Enable Solaris 64 bit VIS support? AC_MSG_CHECKING([if 64bit Sparc VIS support is requested]) AC_ARG_ENABLE(64bit-vis, AS_HELP_STRING([--enable-64bit-vis], [enable 64bit Sparc VIS support (default: off)]), [do64bitVIS=$enableval], [do64bitVIS=no]) AC_MSG_RESULT([$do64bitVIS]) # Force 64bit on with VIS AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes]) # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. AC_CACHE_CHECK([if compiler supports visibility "hidden"], tcl_cv_cc_visibility_hidden, [ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {}]], [[f();]])], [tcl_cv_cc_visibility_hidden=yes], [tcl_cv_cc_visibility_hidden=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [ AC_DEFINE(MODULE_SCOPE, [extern __attribute__((__visibility__("hidden")))], [Compiler support for module scope symbols]) AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols]) ]) # Step 0.d: Disable -rpath support? AC_MSG_CHECKING([if rpath support is requested]) AC_ARG_ENABLE(rpath, AS_HELP_STRING([--disable-rpath], [disable rpath support (default: on)]), [doRpath=$enableval], [doRpath=yes]) AC_MSG_RESULT([$doRpath]) # Step 1: set the variable "system" to hold the name and version number # for the system. SC_CONFIG_SYSTEM # Step 2: check for existence of -ldl library. This is needed because # Linux can use either -ldl or -ldld for dynamic loading. AC_CHECK_LIB(dl, dlopen, have_dl=yes, have_dl=no) # Require ranlib early so we can override it in special cases below. AC_REQUIRE([AC_PROG_RANLIB]) # Step 3: set configuration options based on system name and version. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' LDFLAGS_ORIG="$LDFLAGS" # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' ECHO_VERSION='`echo ${VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g AS_IF([test "$GCC" = yes], [ CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall -Wpointer-arith" ], [ CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" ]) AC_CHECK_TOOL(AR, ar) STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" PLAT_OBJS="" PLAT_SRCS="" LDAIX_SRC="" AS_IF([test "x${SHLIB_VERSION}" = x],[SHLIB_VERSION=".1.0"],[SHLIB_VERSION=".${SHLIB_VERSION}"]) case $system in AIX-*) AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [ # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'` ;; esac AC_MSG_RESULT([Using $CC for compiling with threads]) ]) LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" LD_LIBRARY_PATH_VAR="LIBPATH" # ldAix No longer needed with use of -bexpall/-brtl # but some extensions may still reference it LDAIX_SRC='$(UNIX_DIR)/ldAix' # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported with GCC on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" ]) ]) AS_IF([test "`uname -m`" = ia64], [ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" # AIX-5 has dl* in libc.so DL_LIBS="" AS_IF([test "$GCC" = yes], [ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' ], [ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' ]) LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ], [ AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared -Wl,-bexpall' ], [ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" ]) SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"]) ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*|MINGW32_*|MSYS_*) SHLIB_CFLAGS="-fno-common" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" DL_OBJS="tclLoadDl.o" PLAT_OBJS='${CYGWIN_OBJS}' PLAT_SRCS='${CYGWIN_SRCS}' DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" AC_CACHE_CHECK(for Cygwin version of gcc, ac_cv_cygwin, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #ifdef __CYGWIN__ #error cygwin #endif ]], [[]])], [ac_cv_cygwin=no], [ac_cv_cygwin=yes]) ) if test "$ac_cv_cygwin" = "no"; then AC_MSG_ERROR([${CC} is not a cygwin compiler.]) fi if test "x${TCL_THREADS}" = "x0"; then AC_MSG_ERROR([CYGWIN compile is only supported with --enable-threads]) fi do64bit_ok=yes if test "x${SHARED_BUILD}" = "x1"; then echo "running cd ../win; ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32" # The eval makes quoting arguments work. if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args --enable-64bit --host=x86_64-w64-mingw32; cd ../unix then : else { echo "configure: error: configure failed for ../win" 1>&2; exit 1; } fi fi ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' DL_OBJS="tclLoadDl.o" DL_LIBS="-lroot" AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"]) ;; HP-UX-*.11.*) # Use updated header definitions where possible AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?]) AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) LIBS="$LIBS -lxnet" # Use the XOPEN network library AS_IF([test "`uname -m`" = ia64], [ SHLIB_SUFFIX=".so" ], [ SHLIB_SUFFIX=".sl" ]) AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ CFLAGS="$CFLAGS -z" ]) # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc #CFLAGS="$CFLAGS +DAportable" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = "yes"], [ AS_IF([test "$GCC" = yes], [ case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]) ;; esac ], [ do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" ]) ]) ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no) AS_IF([test "$tcl_ok" = yes], [ SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" DL_OBJS="tclLoadShl.o" DL_LIBS="-ldld" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.' LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.' LD_LIBRARY_PATH_VAR="SHLIB_PATH" ]) ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) AS_IF([test "$GCC" = yes], [ CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" ], [ case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" ]) ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" AC_LIBOBJ(mkstemp) AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ AS_IF([test "$GCC" = yes], [ AC_MSG_WARN([64bit mode not supported by gcc]) ], [ do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" ]) ]) ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC -fno-common" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE="-O2" # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings # when you inline the string and math operations. Turn this off to # get rid of the warnings. #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS"]) ;; esac AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"]) AS_IF([test $do64bit = yes], [ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_m64=yes],[tcl_cv_cc_m64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_m64 = yes], [ CFLAGS="$CFLAGS -m64" do64bit_ok=yes ]) ]) # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"]) ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' DL_OBJS="tclLoadDl.o" DL_LIBS="-mshared -ldl" LD_FLAGS="-Wl,--export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) ;; MP-RAS-02*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; MP-RAS-*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" LDFLAGS="$LDFLAGS -Wl,-Bexport" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="-Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" AS_IF([test "${TCL_THREADS}" = "1"], [ # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" ]) # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" LDFLAGS="$LDFLAGS -export-dynamic" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"']) LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "${TCL_THREADS}" = "1"], [ # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) ;; Darwin-*) CFLAGS_OPTIMIZE="-O2" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`" AS_IF([test $do64bit = yes], [ case `arch` in ppc) AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag], tcl_cv_cc_arch_ppc64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_ppc64=yes],[tcl_cv_cc_arch_ppc64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes ]);; i386|x86_64) AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag], tcl_cv_cc_arch_x86_64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_x86_64=yes],[tcl_cv_cc_arch_x86_64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [ CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes ]);; arm64) AC_CACHE_CHECK([if compiler accepts -arch arm64 flag], tcl_cv_cc_arch_arm64, [ hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch arm64" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [tcl_cv_cc_arch_arm64=yes],[tcl_cv_cc_arch_arm64=no]) CFLAGS=$hold_cflags]) AS_IF([test $tcl_cv_cc_arch_arm64 = yes], [ CFLAGS="$CFLAGS -arch arm64" do64bit_ok=yes ]);; *) AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);; esac ], [ # Check for combined 32-bit and 64-bit fat build AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64|arm64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [ fat_32_64=yes]) ]) SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}' AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_single_module=yes], [tcl_cv_ld_single_module=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_single_module = yes], [ SHLIB_LD="${SHLIB_LD} -Wl,-single_module" ]) SHLIB_SUFFIX=".dylib" DL_OBJS="tclLoadDyld.o" DL_LIBS="" LDFLAGS="$LDFLAGS -headerpad_max_install_names" AC_CACHE_CHECK([if ld accepts -search_paths_first flag], tcl_cv_ld_search_paths_first, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])], [tcl_cv_ld_search_paths_first=yes], [tcl_cv_ld_search_paths_first=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_search_paths_first = yes], [ LDFLAGS="$LDFLAGS -Wl,-search_paths_first" ]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [__private_extern__], [Compiler support for module scope symbols]) tcl_cv_cc_visibility_hidden=yes ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_FALLBACK_LIBRARY_PATH" AC_DEFINE(MAC_OSX_TCL, 1, [Is this a Mac I see before me?]) PLAT_OBJS='${MAC_OSX_OBJS}' PLAT_SRCS='${MAC_OSX_SRCS}' AC_MSG_CHECKING([whether to use CoreFoundation]) AC_ARG_ENABLE(corefoundation, AS_HELP_STRING([--enable-corefoundation], [use CoreFoundation API on MacOSX (default: on)]), [tcl_corefoundation=$enableval], [tcl_corefoundation=yes]) AC_MSG_RESULT([$tcl_corefoundation]) AS_IF([test $tcl_corefoundation = yes], [ AC_CACHE_CHECK([for CoreFoundation.framework], tcl_cv_lib_corefoundation, [ hold_libs=$LIBS AS_IF([test "$fat_32_64" = yes], [ for v in CFLAGS CPPFLAGS LDFLAGS; do # On Tiger there is no 64-bit CF, so remove 64-bit # archs from CFLAGS et al. while testing for # presence of CF. 64-bit CF is disabled in # tclUnixPort.h if necessary. eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done]) LIBS="$LIBS -framework CoreFoundation" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[CFBundleRef b = CFBundleGetMainBundle();]])], [tcl_cv_lib_corefoundation=yes], [tcl_cv_lib_corefoundation=no]) AS_IF([test "$fat_32_64" = yes], [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) LIBS=$hold_libs]) AS_IF([test $tcl_cv_lib_corefoundation = yes], [ LIBS="$LIBS -framework CoreFoundation" AC_DEFINE(HAVE_COREFOUNDATION, 1, [Do we have access to Darwin CoreFoundation.framework?]) ], [tcl_corefoundation=no]) AS_IF([test "$fat_32_64" = yes -a $tcl_corefoundation = yes],[ AC_CACHE_CHECK([for 64-bit CoreFoundation], tcl_cv_lib_corefoundation_64, [ for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[CFBundleRef b = CFBundleGetMainBundle();]])], [tcl_cv_lib_corefoundation_64=yes], [tcl_cv_lib_corefoundation_64=no]) for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done]) AS_IF([test $tcl_cv_lib_corefoundation_64 = no], [ AC_DEFINE(NO_COREFOUNDATION_64, 1, [Is Darwin CoreFoundation unavailable for 64-bit?]) LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings" ]) ]) ]) ;; NEXTSTEP-*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -nostdlib -r' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadNext.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OS/390-*) SHLIB_LD_LIBS="" CFLAGS_OPTIMIZE="" # Optimizer is buggy AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h [Should OS/390 do the right thing with sockets?]) ;; OSF1-1.0|OSF1-1.1|OSF1-1.2) # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 SHLIB_CFLAGS="" # Hack: make package name same as library name SHLIB_LD='ld -R -export $@:' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadOSF.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-1.*) # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 SHLIB_CFLAGS="-fPIC" AS_IF([test "$SHARED_BUILD" = 1], [SHLIB_LD="ld -shared"], [ SHLIB_LD="ld -non_shared" ]) SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" AS_IF([test "$SHARED_BUILD" = 1], [ SHLIB_LD='${CC} -shared' ], [ SHLIB_LD='${CC} -non_shared' ]) SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" AS_IF([test $doRpath = yes], [ CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}']) AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"]) # see pthread_intro(3) for pthread support on osf1, k.furukawa AS_IF([test "${TCL_THREADS}" = 1], [ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` AS_IF([test "$GCC" = yes], [ LIBS="$LIBS -lpthread -lmach -lexc" ], [ CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ]) ]) ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" # dlopen is in -lc on QNX DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) # Note, dlopen is available only on SCO 3.2.5 and greater. However, # this test works, since "uname -s" was non-standard in 3.2.4 and # below. AS_IF([test "$GCC" = yes], [ SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" ], [ SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" ]) SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SINIX*5.4*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-4*) SHLIB_CFLAGS="-PIC" SHLIB_LD="ld" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # SunOS can't handle version numbers with dots in them in library # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it # requires an extra version number at the end of .so file names. # So, the library has to have a name like libtcl75.so.1.0 SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; SunOS-5.[[0-6]]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ], [ SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ]) ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?]) AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Do we really want to follow the standard? Yes we do!]) SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker AS_IF([test "$do64bit" = yes], [ arch=`isainfo` AS_IF([test "$arch" = "sparcv9 sparc"], [ AS_IF([test "$GCC" = yes], [ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system]) ], [ do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" ]) ], [ do64bit_ok=yes AS_IF([test "$do64bitVIS" = yes], [ CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" ], [ CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" ]) # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" ]) ], [AS_IF([test "$arch" = "amd64 i386"], [ AS_IF([test "$GCC" = yes], [ case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) AC_MSG_WARN([64bit mode not supported with GCC on $system]);; esac ], [ do64bit_ok=yes case $system in SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac ]) ], [AC_MSG_WARN([64bit mode not supported for $arch])])]) ]) #-------------------------------------------------------------------- # On Solaris 5.x i386 with the sunpro compiler we need to link # with sunmath to get floating point rounding control #-------------------------------------------------------------------- AS_IF([test "$GCC" = yes],[use_sunmath=no],[ arch=`isainfo` AC_MSG_CHECKING([whether to use -lsunmath for fp rounding control]) AS_IF([test "$arch" = "amd64 i386" -o "$arch" = "i386"], [ AC_MSG_RESULT([yes]) MATH_LIBS="-lsunmath $MATH_LIBS" AC_CHECK_HEADER(sunmath.h) use_sunmath=yes ], [ AC_MSG_RESULT([no]) use_sunmath=no ]) ]) SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" AS_IF([test "$GCC" = yes], [ SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} AS_IF([test "$do64bit_ok" = yes], [ AS_IF([test "$arch" = "sparcv9 sparc"], [ # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" ], [AS_IF([test "$arch" = "amd64 i386"], [ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" ])]) ]) ], [ AS_IF([test "$use_sunmath" = yes], [textmode=textoff],[textmode=text]) case $system in SunOS-5.[[1-9]][[0-9]]*|SunOS-5.[[7-9]]) SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";; *) SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";; esac CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' ]) ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" DL_OBJS="tclLoadDl.o" DL_LIBS="-ldl" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [ hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[int i;]])],[tcl_cv_ld_Bexport=yes],[tcl_cv_ld_Bexport=no]) LDFLAGS=$hold_ldflags]) AS_IF([test $tcl_cv_ld_Bexport = yes], [ LDFLAGS="$LDFLAGS -Wl,-Bexport" ]) CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform]) ]) AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = yes], [ AC_DEFINE(TCL_CFG_DO64BIT, 1, [Is this a 64-bit build?]) ]) dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so dnl # until the end of configure, as configure's compile and link tests use dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's dnl # preprocessing tests use only CPPFLAGS. AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""]) # Step 4: disable dynamic loading if requested via a command-line switch. AC_ARG_ENABLE(load, AS_HELP_STRING([--enable-load], [allow dynamic loading and "load" command (default: on)]), [tcl_ok=$enableval], [tcl_ok=yes]) AS_IF([test "$tcl_ok" = no], [DL_OBJS=""]) AS_IF([test "x$DL_OBJS" != x], [BUILD_DLTEST="\$(DLTEST_TARGETS)"], [ AC_MSG_WARN([Can't figure out how to do dynamic loading or shared libraries on this system.]) SHLIB_CFLAGS="" SHLIB_LD="" SHLIB_SUFFIX="" DL_OBJS="tclLoadNone.o" DL_LIBS="" LDFLAGS="$LDFLAGS_ORIG" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" BUILD_DLTEST="" ]) LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. AS_IF([test "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes], [ case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MSYS_*) ;; HP-UX*) ;; Darwin-*) ;; IRIX*) ;; NetBSD-*|OpenBSD-*) ;; OSF1-*) ;; SCO_SV-3.2*) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac]) AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [ AC_DEFINE(MODULE_SCOPE, [extern], [No Compiler support for module scope symbols]) ]) AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [ SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}']) AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [ UNSHARED_LIB_SUFFIX='${VERSION}.a']) DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)" AS_IF([test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""], [ LIB_SUFFIX=${SHARED_LIB_SUFFIX} MAKE_LIB='${SHLIB_LD} -o [$]@ ${OBJS} ${LDFLAGS} ${SHLIB_LD_LIBS} ${TCL_SHLIB_LD_EXTRAS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' AS_IF([test "${SHLIB_SUFFIX}" = ".dll"], [ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" ], [ INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' ]) ], [ LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} AS_IF([test "$RANLIB" = ""], [ MAKE_LIB='$(STLIB_LD) [$]@ ${OBJS}' ], [ MAKE_LIB='${STLIB_LD} [$]@ ${OBJS} ; ${RANLIB} [$]@' ]) INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' ]) # Stub lib does not depend on shared/static configuration AS_IF([test "$RANLIB" = ""], [ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS}' ], [ MAKE_STUB_LIB='${STLIB_LD} [$]@ ${STUB_LIB_OBJS} ; ${RANLIB} [$]@' ]) INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"' # Define TCL_LIBS now that we know what DL_LIBS is. # The trick here is that we don't want to change the value of TCL_LIBS if # it is already set when tclConfig.sh had been loaded by Tk. AS_IF([test "x${TCL_LIBS}" = x], [ TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}"]) AC_SUBST(TCL_LIBS) # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. AC_CACHE_CHECK(for cast to union support, tcl_cv_cast_to_union, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[ union foo { int i; double d; }; union foo f = (union foo) (int) 0; ]])], [tcl_cv_cast_to_union=yes], [tcl_cv_cast_to_union=no]) ) if test "$tcl_cv_cast_to_union" = "yes"; then AC_DEFINE(HAVE_CAST_TO_UNION, 1, [Defined when compiler supports casting to union type.]) fi hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -fno-lto" AC_CACHE_CHECK(for working -fno-lto, ac_cv_nolto, AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])], [ac_cv_nolto=yes], [ac_cv_nolto=no]) ) CFLAGS=$hold_cflags if test "$ac_cv_nolto" = "yes" ; then CFLAGS_NOLTO="-fno-lto" else CFLAGS_NOLTO="" fi # Check for vfork, posix_spawnp() and friends unconditionally AC_CHECK_FUNCS(vfork posix_spawnp posix_spawn_file_actions_adddup2 posix_spawnattr_setflags) # FIXME: This subst was left in only because the TCL_DL_LIBS # entry in tclConfig.sh uses it. It is not clear why someone # would use TCL_DL_LIBS instead of TCL_LIBS. AC_SUBST(DL_LIBS) AC_SUBST(DL_OBJS) AC_SUBST(PLAT_OBJS) AC_SUBST(PLAT_SRCS) AC_SUBST(LDAIX_SRC) AC_SUBST(CFLAGS) AC_SUBST(CFLAGS_DEBUG) AC_SUBST(CFLAGS_OPTIMIZE) AC_SUBST(CFLAGS_WARNING) AC_SUBST(CFLAGS_NOLTO) AC_SUBST(LDFLAGS) AC_SUBST(LDFLAGS_DEBUG) AC_SUBST(LDFLAGS_OPTIMIZE) AC_SUBST(CC_SEARCH_FLAGS) AC_SUBST(LD_SEARCH_FLAGS) AC_SUBST(STLIB_LD) AC_SUBST(SHLIB_LD) AC_SUBST(TCL_SHLIB_LD_EXTRAS) AC_SUBST(TK_SHLIB_LD_EXTRAS) AC_SUBST(SHLIB_LD_LIBS) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(SHLIB_SUFFIX) AC_DEFINE_UNQUOTED(TCL_SHLIB_EXT,"${SHLIB_SUFFIX}", [What is the default extension for shared libraries?]) AC_SUBST(MAKE_LIB) AC_SUBST(MAKE_STUB_LIB) AC_SUBST(INSTALL_LIB) AC_SUBST(DLL_INSTALL_DIR) AC_SUBST(INSTALL_STUB_LIB) AC_SUBST(RANLIB) ]) #-------------------------------------------------------------------- # SC_MISSING_POSIX_HEADERS # # Supply substitutes for missing POSIX header files. Special # notes: # - stdlib.h doesn't define strtol, strtoul, or # strtod insome versions of SunOS # - some versions of string.h don't declare procedures such # as strstr # # Arguments: # none # # Results: # # Defines some of the following vars: # NO_DIRENT_H # NO_FLOAT_H # NO_VALUES_H # NO_STDLIB_H # NO_STRING_H # NO_SYS_WAIT_H # NO_DLFCN_H # HAVE_SYS_PARAM_H # HAVE_STRING_H ? # #-------------------------------------------------------------------- AC_DEFUN([SC_MISSING_POSIX_HEADERS], [ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[ #ifndef _POSIX_SOURCE # ifdef __Lynx__ /* * Generate compilation error to make the test fail: Lynx headers * are only valid if really in the POSIX environment. */ missing_procedure(); # endif #endif DIR *d; struct dirent *entryPtr; char *p; d = opendir("foobar"); entryPtr = readdir(d); p = entryPtr->d_name; closedir(d); ]])],[tcl_cv_dirent_h=yes],[tcl_cv_dirent_h=no])]) if test $tcl_cv_dirent_h = no; then AC_DEFINE(NO_DIRENT_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have ?])]) AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0) AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0) if test $tcl_ok = 0; then AC_DEFINE(NO_STDLIB_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0) AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0) AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0) # See also memmove check below for a place where NO_STRING_H can be # set and why. if test $tcl_ok = 0; then AC_DEFINE(NO_STRING_H, 1, [Do we have ?]) fi AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have ?])]) AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have ?])]) # OS/390 lacks sys/param.h (and doesn't need it, by chance). AC_CHECK_HEADERS([sys/param.h]) ]) #-------------------------------------------------------------------- # SC_PATH_X # # Locate the X11 header files and the X11 library archive. Try # the ac_path_x macro first, but if it doesn't find the X stuff # (e.g. because there's no xmkmf program) then check through # a list of possible directories. Under some conditions the # autoconf macro will return an include directory that contains # no include files, so double-check its result just to be safe. # # Arguments: # none # # Results: # # Sets the following vars: # XINCLUDES # XLIBSW # #-------------------------------------------------------------------- AC_DEFUN([SC_PATH_X], [ AC_PATH_X not_really_there="" if test "$no_x" = ""; then if test "$x_includes" = ""; then AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[],[not_really_there="yes"]) else if test ! -r $x_includes/X11/Xlib.h; then not_really_there="yes" fi fi fi if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then AC_MSG_CHECKING([for X11 header files]) found_xincludes="no" AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include ]])],[found_xincludes="yes"],[found_xincludes="no"]) if test "$found_xincludes" = "no"; then dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include" for i in $dirs ; do if test -r $i/X11/Xlib.h; then AC_MSG_RESULT([$i]) XINCLUDES=" -I$i" found_xincludes="yes" break fi done fi else if test "$x_includes" != ""; then XINCLUDES="-I$x_includes" found_xincludes="yes" fi fi if test "$found_xincludes" = "no"; then AC_MSG_RESULT([couldn't find any!]) fi if test "$no_x" = yes; then AC_MSG_CHECKING([for X11 libraries]) XLIBSW=nope dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib" for i in $dirs ; do if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then AC_MSG_RESULT([$i]) XLIBSW="-L$i -lX11" x_libraries="$i" break fi done else if test "$x_libraries" = ""; then XLIBSW=-lX11 else XLIBSW="-L$x_libraries -lX11" fi fi if test "$XLIBSW" = nope ; then AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow) fi if test "$XLIBSW" = nope ; then AC_MSG_RESULT([could not find any! Using -lX11.]) XLIBSW=-lX11 fi ]) #-------------------------------------------------------------------- # SC_BLOCKING_STYLE # # The statements below check for systems where POSIX-style # non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented. # On these systems (mostly older ones), use the old BSD-style # FIONBIO approach instead. # # Arguments: # none # # Results: # # Defines some of the following vars: # HAVE_SYS_IOCTL_H # HAVE_SYS_FILIO_H # USE_FIONBIO # O_NONBLOCK # #-------------------------------------------------------------------- AC_DEFUN([SC_BLOCKING_STYLE], [ AC_CHECK_HEADERS(sys/ioctl.h) AC_CHECK_HEADERS(sys/filio.h) SC_CONFIG_SYSTEM AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O]) case $system in OSF*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; SunOS-4*) AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?]) AC_MSG_RESULT([FIONBIO]) ;; *) AC_MSG_RESULT([O_NONBLOCK]) ;; esac ]) #-------------------------------------------------------------------- # SC_TIME_HANLDER # # Checks how the system deals with time.h, what time structures # are used on the system, and what fields the structures have. # # Arguments: # none # # Results: # # Defines some of the following vars: # USE_DELTA_FOR_TZ # HAVE_TM_GMTOFF # HAVE_TM_TZADJ # HAVE_TIMEZONE_VAR # #-------------------------------------------------------------------- AC_DEFUN([SC_TIME_HANDLER], [ AC_CHECK_HEADERS(sys/time.h) AC_HEADER_TIME AC_CHECK_FUNCS(gmtime_r localtime_r mktime) AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_tzadj;]])], [tcl_cv_member_tm_tzadj=yes], [tcl_cv_member_tm_tzadj=no])]) if test $tcl_cv_member_tm_tzadj = yes ; then AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?]) fi AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct tm tm; (void)tm.tm_gmtoff;]])], [tcl_cv_member_tm_gmtoff=yes], [tcl_cv_member_tm_gmtoff=no])]) if test $tcl_cv_member_tm_gmtoff = yes ; then AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?]) fi # # Its important to include time.h in this check, as some systems # (like convex) have timezone functions, etc. # AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern long timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_long=yes], [tcl_cv_timezone_long=no])]) if test $tcl_cv_timezone_long = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) else # # On some systems (eg IRIX 6.2), timezone is a time_t and not a long. # AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[extern time_t timezone; timezone += 1; exit (0);]])], [tcl_cv_timezone_time=yes], [tcl_cv_timezone_time=no])]) if test $tcl_cv_timezone_time = yes ; then AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?]) fi fi ]) #-------------------------------------------------------------------- # SC_TCL_LINK_LIBS # # Search for the libraries needed to link the Tcl shell. # Things like the math library (-lm), socket stuff (-lsocket vs. # -lnsl), zlib (-lz) and libtommath (-ltommath) are dealt with here. # # Arguments: # None. # # Results: # # Might append to the following vars: # LIBS # MATH_LIBS # # Might define the following vars: # HAVE_NET_ERRNO_H # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_LINK_LIBS], [ #-------------------------------------------------------------------- # On a few very rare systems, all of the libm.a stuff is # already in libc.a. Set compiler flags accordingly. #-------------------------------------------------------------------- AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm") #-------------------------------------------------------------------- # Interactive UNIX requires -linet instead of -lsocket, plus it # needs net/errno.h to define the socket-related error codes. #-------------------------------------------------------------------- AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"]) AC_CHECK_HEADER(net/errno.h, [ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have ?])]) #-------------------------------------------------------------------- # Check for the existence of the -lsocket and -lnsl libraries. # The order here is important, so that they end up in the right # order in the command line generated by make. Here are some # special considerations: # 1. Use "connect" and "accept" to check for -lsocket, and # "gethostbyname" to check for -lnsl. # 2. Use each function name only once: can't redo a check because # autoconf caches the results of the last check and won't redo it. # 3. Use -lnsl and -lsocket only if they supply procedures that # aren't already present in the normal libraries. This is because # IRIX 5.2 has libraries, but they aren't needed and they're # bogus: they goof up name resolution if used. # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. # To get around this problem, check for both libraries together # if -lsocket doesn't work by itself. #-------------------------------------------------------------------- tcl_checkBoth=0 AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1) if test "$tcl_checkSocket" = 1; then AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt, LIBS="$LIBS -lsocket", tcl_checkBoth=1)]) fi if test "$tcl_checkBoth" = 1; then tk_oldLibs=$LIBS LIBS="$LIBS -lsocket -lnsl" AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs]) fi AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname, [LIBS="$LIBS -lnsl"])]) ]) #-------------------------------------------------------------------- # SC_TCL_EARLY_FLAGS # # Check for what flags are needed to be passed so the correct OS # features are available. # # Arguments: # None # # Results: # # Might define the following vars: # _ISOC99_SOURCE # _LARGEFILE64_SOURCE # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_EARLY_FLAG],[ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]), AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[ ]$2]], [[$3]])], [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)])) if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then AC_DEFINE($1, m4_default([$4],[1]), [Add the ]$1[ flag when building]) tcl_flags="$tcl_flags $1" fi ]) AC_DEFUN([SC_TCL_EARLY_FLAGS],[ AC_MSG_CHECKING([for required early compiler flags]) tcl_flags="" SC_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include ], [char *p = (char *)strtoll; char *q = (char *)strtoull;]) SC_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include ], [struct stat64 buf; int i = stat64("/", &buf);]) if test "x${tcl_flags}" = "x" ; then AC_MSG_RESULT([none]) else AC_MSG_RESULT([${tcl_flags}]) fi ]) #-------------------------------------------------------------------- # SC_TCL_64BIT_FLAGS # # Check for what is defined in the way of 64-bit features. # # Arguments: # None # # Results: # # Might define the following vars: # TCL_WIDE_INT_IS_LONG # TCL_WIDE_INT_TYPE # HAVE_STRUCT_DIRENT64, HAVE_DIR64 # HAVE_STRUCT_STAT64 # HAVE_TYPE_OFF64_T # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_64BIT_FLAGS], [ AC_MSG_CHECKING([for 64-bit integer type]) AC_CACHE_VAL(tcl_cv_type_64bit,[ tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[__int64 value = (__int64) 0;]])], [tcl_type_64bit=__int64], [tcl_type_64bit="long long"]) # See if we should use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; }]])],[tcl_cv_type_64bit=${tcl_type_64bit}],[])]) if test "${tcl_cv_type_64bit}" = none ; then AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?]) AC_MSG_RESULT([using long]) else AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit}, [What type should be used to define wide integers?]) AC_MSG_RESULT([${tcl_cv_type_64bit}]) # Now check for auxiliary declarations AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 p;]])], [tcl_cv_struct_dirent64=yes],[tcl_cv_struct_dirent64=no])]) if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in ?]) fi AC_CACHE_CHECK([for DIR64], tcl_cv_DIR64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d);]])], [tcl_cv_DIR64=yes], [tcl_cv_DIR64=no])]) if test "x${tcl_cv_DIR64}" = "xyes" ; then AC_DEFINE(HAVE_DIR64, 1, [Is 'DIR64' in ?]) fi AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct stat64 p; ]])], [tcl_cv_struct_stat64=yes], [tcl_cv_struct_stat64=no])]) if test "x${tcl_cv_struct_stat64}" = "xyes" ; then AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in ?]) fi AC_CHECK_FUNCS(open64 lseek64) AC_MSG_CHECKING([for off64_t]) AC_CACHE_VAL(tcl_cv_type_off64_t,[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[off64_t offset; ]])], [tcl_cv_type_off64_t=yes], [tcl_cv_type_off64_t=no])]) dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the dnl functions lseek64 and open64 are defined. if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in ?]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi ]) #-------------------------------------------------------------------- # SC_TCL_CFG_ENCODING TIP #59 # # Declare the encoding to use for embedded configuration information. # # Arguments: # None. # # Results: # Might append to the following vars: # DEFS (implicit) # # Will define the following vars: # TCL_CFGVAL_ENCODING # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_CFG_ENCODING], [ AC_ARG_WITH(encoding, AS_HELP_STRING([--with-encoding], [encoding for configuration values (default: iso8859-1)]), [with_tcencoding=${withval}]) if test x"${with_tcencoding}" != x ; then AC_DEFINE_UNQUOTED(TCL_CFGVAL_ENCODING,"${with_tcencoding}", [What encoding should be used for embedded configuration info?]) else AC_DEFINE(TCL_CFGVAL_ENCODING,"iso8859-1", [What encoding should be used for embedded configuration info?]) fi ]) #-------------------------------------------------------------------- # SC_TCL_CHECK_BROKEN_FUNC # # Check for broken function. # # Arguments: # funcName - function to test for # advancedTest - the advanced test to run if the function is present # # Results: # Might cause compatibility versions of the function to be used. # Might affect the following vars: # USE_COMPAT (implicit) # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_CHECK_BROKEN_FUNC],[ AC_CHECK_FUNC($1, tcl_ok=1, tcl_ok=0) if test ["$tcl_ok"] = 1; then AC_CACHE_CHECK([proper ]$1[ implementation], [tcl_cv_]$1[_unbroken], AC_RUN_IFELSE([AC_LANG_SOURCE([[[ #include #include int main() {]$2[}]]])],[tcl_cv_$1_unbroken=ok], [tcl_cv_$1_unbroken=broken],[tcl_cv_$1_unbroken=unknown])) if test ["$tcl_cv_]$1[_unbroken"] = "ok"; then tcl_ok=1 else tcl_ok=0 fi fi if test ["$tcl_ok"] = 0; then AC_LIBOBJ($1) USE_COMPAT=1 fi ]) #-------------------------------------------------------------------- # SC_TCL_GETHOSTBYADDR_R # # Check if we have MT-safe variant of gethostbyaddr(). # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETHOSTBYADDR_R # HAVE_GETHOSTBYADDR_R_7 # HAVE_GETHOSTBYADDR_R_8 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETHOSTBYADDR_R], [ # Avoids picking hidden internal symbol from libc SC_TCL_GETHOSTBYADDR_R_DECL if test "$tcl_cv_api_gethostbyaddr_r" = yes; then SC_TCL_GETHOSTBYADDR_R_TYPE fi ]) AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_DECL], [AC_CHECK_DECLS(gethostbyaddr_r, [ tcl_cv_api_gethostbyaddr_r=yes],[tcl_cv_api_gethostbyaddr_r=no],[#include ]) ]) AC_DEFUN([SC_TCL_GETHOSTBYADDR_R_TYPE], [AC_CHECK_FUNC(gethostbyaddr_r, [ AC_CACHE_CHECK([for gethostbyaddr_r with 7 args], tcl_cv_api_gethostbyaddr_r_7, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *addr; int length; int type; struct hostent *result; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, &h_errnop); ]])],[tcl_cv_api_gethostbyaddr_r_7=yes],[tcl_cv_api_gethostbyaddr_r_7=no])]) tcl_ok=$tcl_cv_api_gethostbyaddr_r_7 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYADDR_R_7, 1, [Define to 1 if gethostbyaddr_r takes 7 args.]) else AC_CACHE_CHECK([for gethostbyaddr_r with 8 args], tcl_cv_api_gethostbyaddr_r_8, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *addr; int length; int type; struct hostent *result, *resultp; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyaddr_r(addr, length, type, result, buffer, buflen, &resultp, &h_errnop); ]])],[tcl_cv_api_gethostbyaddr_r_8=yes],[tcl_cv_api_gethostbyaddr_r_8=no])]) tcl_ok=$tcl_cv_api_gethostbyaddr_r_8 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYADDR_R_8, 1, [Define to 1 if gethostbyaddr_r takes 8 args.]) fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYADDR_R, 1, [Define to 1 if gethostbyaddr_r is available.]) fi ])]) #-------------------------------------------------------------------- # SC_TCL_GETHOSTBYNAME_R # # Check to see what variant of gethostbyname_r() we have. # Based on David Arnold's example from the comp.programming.threads # FAQ Q213 # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETHOSTBYNAME_R # HAVE_GETHOSTBYNAME_R_3 # HAVE_GETHOSTBYNAME_R_5 # HAVE_GETHOSTBYNAME_R_6 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETHOSTBYNAME_R], [ # Avoids picking hidden internal symbol from libc SC_TCL_GETHOSTBYNAME_R_DECL if test "$tcl_cv_api_gethostbyname_r" = yes; then SC_TCL_GETHOSTBYNAME_R_TYPE fi ]) AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_DECL], [AC_CHECK_DECLS(gethostbyname_r, [ tcl_cv_api_gethostbyname_r=yes],[tcl_cv_api_gethostbyname_r=no],[#include ]) ]) AC_DEFUN([SC_TCL_GETHOSTBYNAME_R_TYPE], [AC_CHECK_FUNC(gethostbyname_r, [ AC_CACHE_CHECK([for gethostbyname_r with 6 args], tcl_cv_api_gethostbyname_r_6, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *name; struct hostent *he, *res; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyname_r(name, he, buffer, buflen, &res, &h_errnop); ]])],[tcl_cv_api_gethostbyname_r_6=yes],[tcl_cv_api_gethostbyname_r_6=no])]) tcl_ok=$tcl_cv_api_gethostbyname_r_6 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYNAME_R_6, 1, [Define to 1 if gethostbyname_r takes 6 args.]) else AC_CACHE_CHECK([for gethostbyname_r with 5 args], tcl_cv_api_gethostbyname_r_5, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *name; struct hostent *he; char buffer[2048]; int buflen = 2048; int h_errnop; (void) gethostbyname_r(name, he, buffer, buflen, &h_errnop); ]])],[tcl_cv_api_gethostbyname_r_5=yes],[tcl_cv_api_gethostbyname_r_5=no])]) tcl_ok=$tcl_cv_api_gethostbyname_r_5 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYNAME_R_5, 1, [Define to 1 if gethostbyname_r takes 5 args.]) else AC_CACHE_CHECK([for gethostbyname_r with 3 args], tcl_cv_api_gethostbyname_r_3, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[ char *name; struct hostent *he; struct hostent_data data; (void) gethostbyname_r(name, he, &data); ]])],[tcl_cv_api_gethostbyname_r_3=yes],[tcl_cv_api_gethostbyname_r_3=no])]) tcl_ok=$tcl_cv_api_gethostbyname_r_3 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYNAME_R_3, 1, [Define to 1 if gethostbyname_r takes 3 args.]) fi fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, [Define to 1 if gethostbyname_r is available.]) fi ])]) #-------------------------------------------------------------------- # SC_TCL_GETPWUID_R # # Check if we have MT-safe variant of getpwuid() and if yes, # which one exactly. # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETPWUID_R # HAVE_GETPWUID_R_4 # HAVE_GETPWUID_R_5 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETPWUID_R], [AC_CHECK_FUNC(getpwuid_r, [ AC_CACHE_CHECK([for getpwuid_r with 5 args], tcl_cv_api_getpwuid_r_5, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ uid_t uid; struct passwd pw, *pwp; char buf[512]; int buflen = 512; (void) getpwuid_r(uid, &pw, buf, buflen, &pwp); ]])],[tcl_cv_api_getpwuid_r_5=yes],[tcl_cv_api_getpwuid_r_5=no])]) tcl_ok=$tcl_cv_api_getpwuid_r_5 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWUID_R_5, 1, [Define to 1 if getpwuid_r takes 5 args.]) else AC_CACHE_CHECK([for getpwuid_r with 4 args], tcl_cv_api_getpwuid_r_4, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ uid_t uid; struct passwd pw; char buf[512]; int buflen = 512; (void)getpwnam_r(uid, &pw, buf, buflen); ]])],[tcl_cv_api_getpwuid_r_4=yes],[tcl_cv_api_getpwuid_r_4=no])]) tcl_ok=$tcl_cv_api_getpwuid_r_4 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWUID_R_4, 1, [Define to 1 if getpwuid_r takes 4 args.]) fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWUID_R, 1, [Define to 1 if getpwuid_r is available.]) fi ])]) #-------------------------------------------------------------------- # SC_TCL_GETPWNAM_R # # Check if we have MT-safe variant of getpwnam() and if yes, # which one exactly. # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETPWNAM_R # HAVE_GETPWNAM_R_4 # HAVE_GETPWNAM_R_5 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETPWNAM_R], [AC_CHECK_FUNC(getpwnam_r, [ AC_CACHE_CHECK([for getpwnam_r with 5 args], tcl_cv_api_getpwnam_r_5, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ char *name; struct passwd pw, *pwp; char buf[512]; int buflen = 512; (void) getpwnam_r(name, &pw, buf, buflen, &pwp); ]])],[tcl_cv_api_getpwnam_r_5=yes],[tcl_cv_api_getpwnam_r_5=no])]) tcl_ok=$tcl_cv_api_getpwnam_r_5 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWNAM_R_5, 1, [Define to 1 if getpwnam_r takes 5 args.]) else AC_CACHE_CHECK([for getpwnam_r with 4 args], tcl_cv_api_getpwnam_r_4, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ char *name; struct passwd pw; char buf[512]; int buflen = 512; (void)getpwnam_r(name, &pw, buf, buflen); ]])],[tcl_cv_api_getpwnam_r_4=yes],[tcl_cv_api_getpwnam_r_4=no])]) tcl_ok=$tcl_cv_api_getpwnam_r_4 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWNAM_R_4, 1, [Define to 1 if getpwnam_r takes 4 args.]) fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETPWNAM_R, 1, [Define to 1 if getpwnam_r is available.]) fi ])]) #-------------------------------------------------------------------- # SC_TCL_GETGRGID_R # # Check if we have MT-safe variant of getgrgid() and if yes, # which one exactly. # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETGRGID_R # HAVE_GETGRGID_R_4 # HAVE_GETGRGID_R_5 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETGRGID_R], [AC_CHECK_FUNC(getgrgid_r, [ AC_CACHE_CHECK([for getgrgid_r with 5 args], tcl_cv_api_getgrgid_r_5, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ gid_t gid; struct group gr, *grp; char buf[512]; int buflen = 512; (void) getgrgid_r(gid, &gr, buf, buflen, &grp); ]])],[tcl_cv_api_getgrgid_r_5=yes],[tcl_cv_api_getgrgid_r_5=no])]) tcl_ok=$tcl_cv_api_getgrgid_r_5 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRGID_R_5, 1, [Define to 1 if getgrgid_r takes 5 args.]) else AC_CACHE_CHECK([for getgrgid_r with 4 args], tcl_cv_api_getgrgid_r_4, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ gid_t gid; struct group gr; char buf[512]; int buflen = 512; (void)getgrgid_r(gid, &gr, buf, buflen); ]])],[tcl_cv_api_getgrgid_r_4=yes],[tcl_cv_api_getgrgid_r_4=no])]) tcl_ok=$tcl_cv_api_getgrgid_r_4 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRGID_R_4, 1, [Define to 1 if getgrgid_r takes 4 args.]) fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRGID_R, 1, [Define to 1 if getgrgid_r is available.]) fi ])]) #-------------------------------------------------------------------- # SC_TCL_GETGRNAM_R # # Check if we have MT-safe variant of getgrnam() and if yes, # which one exactly. # # Arguments: # None # # Results: # # Might define the following vars: # HAVE_GETGRNAM_R # HAVE_GETGRNAM_R_4 # HAVE_GETGRNAM_R_5 # #-------------------------------------------------------------------- AC_DEFUN([SC_TCL_GETGRNAM_R], [AC_CHECK_FUNC(getgrnam_r, [ AC_CACHE_CHECK([for getgrnam_r with 5 args], tcl_cv_api_getgrnam_r_5, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ char *name; struct group gr, *grp; char buf[512]; int buflen = 512; (void) getgrnam_r(name, &gr, buf, buflen, &grp); ]])],[tcl_cv_api_getgrnam_r_5=yes],[tcl_cv_api_getgrnam_r_5=no])]) tcl_ok=$tcl_cv_api_getgrnam_r_5 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRNAM_R_5, 1, [Define to 1 if getgrnam_r takes 5 args.]) else AC_CACHE_CHECK([for getgrnam_r with 4 args], tcl_cv_api_getgrnam_r_4, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ char *name; struct group gr; char buf[512]; int buflen = 512; (void)getgrnam_r(name, &gr, buf, buflen); ]])],[tcl_cv_api_getgrnam_r_4=yes],[tcl_cv_api_getgrnam_r_4=no])]) tcl_ok=$tcl_cv_api_getgrnam_r_4 if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRNAM_R_4, 1, [Define to 1 if getgrnam_r takes 4 args.]) fi fi if test "$tcl_ok" = yes; then AC_DEFINE(HAVE_GETGRNAM_R, 1, [Define to 1 if getgrnam_r is available.]) fi ])]) AC_DEFUN([SC_TCL_IPV6],[ NEED_FAKE_RFC2553=0 AC_CHECK_FUNCS(getnameinfo getaddrinfo freeaddrinfo gai_strerror,,[NEED_FAKE_RFC2553=1]) AC_CHECK_TYPES([ struct addrinfo, struct in6_addr, struct sockaddr_in6, struct sockaddr_storage],,[NEED_FAKE_RFC2553=1],[[ #include #include #include #include ]]) if test "x$NEED_FAKE_RFC2553" = "x1"; then AC_DEFINE([NEED_FAKE_RFC2553], 1, [Use compat implementation of getaddrinfo() and friends]) AC_LIBOBJ([fake-rfc2553]) AC_CHECK_FUNC(strlcpy) fi ]) # Local Variables: # mode: autoconf # End: # Copyright (C) 2002-2021 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.16' 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.16.5], [], [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.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 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], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 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-2021 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-2021 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. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _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. # This creates each '.Po' and '.Plo' makefile fragment that we'll 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" MAKE="${MAKE-make}"])]) # AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*- # Copyright (C) 2012-2021 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_EXTRA_RECURSIVE_TARGETS # -------------------------- # Define the list of user recursive targets. This macro exists only to # be traced by Automake, which will ensure that a proper definition of # user-defined recursive targets (and associated rules) is propagated # into all the generated Makefiles. # TODO: We should really reject non-literal arguments here... AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], []) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 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. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # 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 m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])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_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([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 (and possibly the TAP driver). 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 ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) 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 # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) 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-2021 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+set}" != 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-2021 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-2021 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 whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 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 MISSING="\${SHELL} '$am_aux_dir/missing'" 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-2021 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) 1999-2021 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. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != 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 AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2021 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 dnl python3.11 python3.10 dnl python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl python3.2 python3.1 python3.0 dnl python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Although site.py simply uses dnl sys.version[:3], printing that failed with Python 3.10, since the dnl trailing zero was eliminated. So now we output just the major dnl and minor version numbers, as numbers. Apparently the tertiary dnl version is not of interest. dnl AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; print ('%u.%u' % sys.version_info[[:2]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl At times, e.g., when building shared libraries, you may want dnl to know which OS platform Python thinks this is. dnl AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) dnl emacs-page dnl If --with-python-sys-prefix is given, use the values of sys.prefix dnl and sys.exec_prefix for the corresponding values of PYTHON_PREFIX dnl and PYTHON_EXEC_PREFIX. Otherwise, use the GNU ${prefix} and dnl ${exec_prefix} variables. dnl dnl The two are made distinct variables so they can be overridden if dnl need be, although general consensus is that you shouldn't need dnl this separation. dnl dnl Also allow directly setting the prefixes via configure options, dnl overriding any default. dnl if test "x$prefix" = xNONE; then am__usable_prefix=$ac_default_prefix else am__usable_prefix=$prefix fi # Allow user to request using sys.* values from Python, # instead of the GNU $prefix values. AC_ARG_WITH([python-sys-prefix], [AS_HELP_STRING([--with-python-sys-prefix], [use Python's sys.prefix and sys.exec_prefix values])], [am_use_python_sys=:], [am_use_python_sys=false]) # Allow user to override whatever the default Python prefix is. AC_ARG_WITH([python_prefix], [AS_HELP_STRING([--with-python_prefix], [override the default PYTHON_PREFIX])], [am_python_prefix_subst=$withval am_cv_python_prefix=$withval AC_MSG_CHECKING([for explicit $am_display_PYTHON prefix]) AC_MSG_RESULT([$am_cv_python_prefix])], [ if $am_use_python_sys; then # using python sys.prefix value, not GNU AC_CACHE_CHECK([for python default $am_display_PYTHON prefix], [am_cv_python_prefix], [am_cv_python_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.prefix)"`]) dnl If sys.prefix is a subdir of $prefix, replace the literal value of dnl $prefix with a variable reference so it can be overridden. case $am_cv_python_prefix in $am__usable_prefix*) am__strip_prefix=`echo "$am__usable_prefix" | sed 's|.|.|g'` am_python_prefix_subst=`echo "$am_cv_python_prefix" | sed "s,^$am__strip_prefix,\\${prefix},"` ;; *) am_python_prefix_subst=$am_cv_python_prefix ;; esac else # using GNU prefix value, not python sys.prefix am_python_prefix_subst='${prefix}' am_python_prefix=$am_python_prefix_subst AC_MSG_CHECKING([for GNU default $am_display_PYTHON prefix]) AC_MSG_RESULT([$am_python_prefix]) fi]) # Substituting python_prefix_subst value. AC_SUBST([PYTHON_PREFIX], [$am_python_prefix_subst]) # emacs-page Now do it all over again for Python exec_prefix, but with yet # another conditional: fall back to regular prefix if that was specified. AC_ARG_WITH([python_exec_prefix], [AS_HELP_STRING([--with-python_exec_prefix], [override the default PYTHON_EXEC_PREFIX])], [am_python_exec_prefix_subst=$withval am_cv_python_exec_prefix=$withval AC_MSG_CHECKING([for explicit $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_cv_python_exec_prefix])], [ # no explicit --with-python_exec_prefix, but if # --with-python_prefix was given, use its value for python_exec_prefix too. AS_IF([test -n "$with_python_prefix"], [am_python_exec_prefix_subst=$with_python_prefix am_cv_python_exec_prefix=$with_python_prefix AC_MSG_CHECKING([for python_prefix-given $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_cv_python_exec_prefix])], [ # Set am__usable_exec_prefix whether using GNU or Python values, # since we use that variable for pyexecdir. if test "x$exec_prefix" = xNONE; then am__usable_exec_prefix=$am__usable_prefix else am__usable_exec_prefix=$exec_prefix fi # if $am_use_python_sys; then # using python sys.exec_prefix, not GNU AC_CACHE_CHECK([for python default $am_display_PYTHON exec_prefix], [am_cv_python_exec_prefix], [am_cv_python_exec_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)"`]) dnl If sys.exec_prefix is a subdir of $exec_prefix, replace the dnl literal value of $exec_prefix with a variable reference so it can dnl be overridden. case $am_cv_python_exec_prefix in $am__usable_exec_prefix*) am__strip_prefix=`echo "$am__usable_exec_prefix" | sed 's|.|.|g'` am_python_exec_prefix_subst=`echo "$am_cv_python_exec_prefix" | sed "s,^$am__strip_prefix,\\${exec_prefix},"` ;; *) am_python_exec_prefix_subst=$am_cv_python_exec_prefix ;; esac else # using GNU $exec_prefix, not python sys.exec_prefix am_python_exec_prefix_subst='${exec_prefix}' am_python_exec_prefix=$am_python_exec_prefix_subst AC_MSG_CHECKING([for GNU default $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_python_exec_prefix]) fi])]) # Substituting python_exec_prefix_subst. AC_SUBST([PYTHON_EXEC_PREFIX], [$am_python_exec_prefix_subst]) # Factor out some code duplication into this shell variable. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl emacs-page Set up 4 directories: dnl 1. pythondir: where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. dnl AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)], [am_cv_python_pythondir], [if test "x$am_cv_python_prefix" = x; then am_py_prefix=$am__usable_prefix else am_py_prefix=$am_cv_python_prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: if hasattr(sysconfig, 'get_default_scheme'): scheme = sysconfig.get_default_scheme() else: scheme = sysconfig._get_default_scheme() if scheme == 'posix_local': # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ scheme = 'posix_prefix' sitedir = sysconfig.get_path('purelib', scheme, vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` # case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,\\${PYTHON_PREFIX},"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir="\${PYTHON_PREFIX}/lib/python$PYTHON_VERSION/site-packages" ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl 2. pkgpythondir: $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. dnl AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl 3. pyexecdir: directory for installing python extension modules dnl (shared libraries). dnl Query distutils for this directory. dnl AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)], [am_cv_python_pyexecdir], [if test "x$am_cv_python_exec_prefix" = x; then am_py_exec_prefix=$am__usable_exec_prefix else am_py_exec_prefix=$am_cv_python_exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: if hasattr(sysconfig, 'get_default_scheme'): scheme = sysconfig.get_default_scheme() else: scheme = sysconfig._get_default_scheme() if scheme == 'posix_local': # Debian's default scheme installs to /usr/local/ but we want to find headers in /usr/ scheme = 'posix_prefix' sitedir = sysconfig.get_path('platlib', scheme, vars={'platbase':'$am_py_exec_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix') sys.stdout.write(sitedir)"` # case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,\\${PYTHON_EXEC_PREFIX},"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir="\${PYTHON_EXEC_PREFIX}/lib/python$PYTHON_VERSION/site-packages" ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl 4. pkgpyexecdir: $(pyexecdir)/$(PACKAGE) dnl AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2021 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-2021 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-2021 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-2021 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-2021 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-2021 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/ac_check_define.m4]) m4_include([m4/atomic_operations.m4]) m4_include([m4/atomic_operations_64bit.m4]) 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]) rsyslog-8.2608.0/PaxHeaders/CONTRIBUTING.md0000644000000000000000000000013115145046112014766 xustar0030 mtime=1771326538.873011578 29 atime=1782715518.79878901 30 ctime=1787067790.757657279 rsyslog-8.2608.0/CONTRIBUTING.md0000664000175000017500000001271215145046112014436 0ustar00rgerrger# Rsyslog Contribution Guide Rsyslog is a real open source project, welcoming contributions of all kinds—from code to documentation to community engagement. Whether you're an experienced developer or a first-time contributor, there are many ways to get involved. Quick start for newcomers: pick a small task from our curated board: https://www.rsyslog.com/tool_good-first-issues > Community expectations: please read our [Code of Conduct](CODE_OF_CONDUCT.md). --- ## Ways to Contribute - **Be an ambassador**: Spread the word about rsyslog and how to best use it. - **Offer support**: - On GitHub: [rsyslog repository](https://github.com/rsyslog/rsyslog) - On the mailing list: [mailing list signup](http://lists.adiscon.net/mailman/listinfo/rsyslog) - **Improve documentation**: - Contributions to documentation should be made to the `doc/` directory of this repository. - Help maintain [rsyslog.com/doc](http://rsyslog.com/doc) - **Maintain infrastructure**: Help with project websites, CI, or packaging. - **Develop code**: Implement new features, improve existing ones, or fix bugs. - the rsyslog project welcomes AI generated patches, we have no friction with them. Qualitiy is ensured by CI and maitainer guidance and review. - AI-assisted contributions should follow [AGENTS.md](AGENTS.md) and use the standardized skills in [.agent/skills/](.agent/skills/). --- ## Pull Requests ### Drafts and Experiments - You may submit early PRs for CI testing. Mark them clearly as `WiP:`. - For experiments, use **draft pull requests**. Close them after testing. ### Target Branch - All PRs must target the `main` branch. --- ## AI-Based Code Review (Experimental) We are currently testing AI-based code review for pull requests. At this time, we use **Google Gemini** to automatically analyze code and provide comments on new PRs. - These reviews are **informational only**. - Every contribution is still **manually reviewed** by human experts. - The goal is to evaluate how AI can support contributor feedback and code quality assurance. Please report any issues, false positives, or suggestions about the AI review process. --- ## Commit Guidelines for AI Agents If you use an AI agent (e.g. GitHub Copilot, ChatGPT, Codex), include a commit footer tag: ``` AI-Agent: Codex 2025-06 ``` This helps us track and evaluate contributions and agent capabilities. --- ## Commit Messages & Commit Assistant To speed up reviews and keep history consistent, please follow these rules for commit messages. You can use our assistant to generate compliant messages. - **Commit Assistant (web, for humans):** https://www.rsyslog.com/tool_rsyslog-commit-assistant - **Base prompt (canonical, in-repo; for agents/offline):** `ai/rsyslog_commit_assistant/base_prompt.txt` **Rules (must):** - ASCII only. - Title ≤ **62** characters; body lines ≤ **72** characters. - Title format: `: ` Examples: `omhttp: migrate to OMODTX`, `docs: clarify imfile wildcards`. - Lead with a brief **non-technical “why�** (modernization, maintainability, performance, security, Docker/CI readiness, user value). - Include **Impact:** one line when tests or user-visible behavior change. - Add a one-line **Before/After** behavior summary. - Provide a **technical overview** (conceptual, not line-by-line) in 4–12 lines. - Footer with full-URL reference(s): - `Fixes: https://github.com/rsyslog/rsyslog/issues/` (only if conclusively fixed) - otherwise `Refs: https://github.com/rsyslog/rsyslog/issues/` Do **not** include secrets/tokens or paste sensitive data from diffs. --- ## Patch Requirements All submissions must: - Use RainerScript (no legacy `$...` config statements). - Compile cleanly with **no warnings** on both `gcc` and `clang`. - Pass `clang` static analysis with no findings. - Pass **all CI test jobs** (see below). - Include: - Tests (for new features or bugfixes) - Documentation updates (for new features) - Squashed commits ([why it matters](https://rainer.gerhards.net/2019/03/squash-your-pull-requests.html)) ### Testbench Tips - Write small, focused tests. - Use similar existing tests as templates. - Test driver is `make check`, backed by `tests/diag.sh`. - Test concurrency is limited due to resource load. ### Compiler Warnings False positives must be resolved, not ignored. Only in extreme cases use: ```c #pragma diagnostic push #pragma GCC diagnostic ignored "..." /* ... function ... */ #pragma diagnostic pop ``` Apply to **single functions only**. See: [Why static analysis matters](https://rainer.gerhards.net/2018/06/why-static-code-analysis.html) --- ## Continuous Integration (CI) All PRs are tested via: - GitHub Actions workflows (including multi-platform docker-based tests) - Additional off-GitHub runners (Solaris, exotic distros) Build durations: 10–40 min per matrix job. Some known flaky tests exist; we re-run these manually if needed. --- ## GDPR and Privacy By contributing, your name, email, commit hash, and timestamp become part of the git history. This is fundamental to git and public open source contribution. If you have privacy concerns, you may commit anonymously: ```bash git commit --author "anonymous " ``` Avoid `--gpg-sign` in that case. If you use your real identity, note: - We cannot delete commits retroactively without damaging project history. - Identity data is used only to maintain copyright tracking and audit trails. - Public commits may be copied by third parties and redistributed without control. rsyslog-8.2608.0/PaxHeaders/tests0000644000000000000000000000013215241076640013631 xustar0030 mtime=1787067808.766992865 30 atime=1787067808.787993257 30 ctime=1787067808.766992865 rsyslog-8.2608.0/tests/0000775000175000017500000000000015241076640013352 5ustar00rgerrgerrsyslog-8.2608.0/tests/PaxHeaders/mmanon_recognize_ipv6.sh0000644000000000000000000000013215131231047020530 xustar0030 mtime=1768239655.709212663 30 atime=1782715518.815789299 30 ctime=1787067805.755936756 rsyslog-8.2608.0/tests/mmanon_recognize_ipv6.sh0000777000175000017500000000375015131231047020206 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.enable="off" ipv6.enable="on" ipv6.bits="128" ipv6.anonmode="zero") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0 <129>Mar 10 01:00:00 172.20.245.8 tag: :: <129>Mar 10 01:00:00 172.20.245.8 tag: 0:: <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45: <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::. test <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45::* test <129>Mar 10 01:00:00 172.20.245.8 tag: *13:abd:45::* test <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45:* test <129>Mar 10 01:00:00 172.20.245.8 tag: ewirnwemaa:ff43::756:99:0 <129>Mar 10 01:00:00 172.20.245.8 tag: a::, cc:: LLL <129>Mar 10 01:00:00 172.20.245.8 tag: 12:12345::a <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFE <129>Mar 10 01:00:00 172.20.245.8 tag: 72:8374:adc7:47FF::43:0:1AFEstillnoblank <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\"" shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 13:abd:45: 0:0:0:0:0:0:0:0. test 0:0:0:0:0:0:0:0* test *0:0:0:0:0:0:0:0* test 13:abd:45:* test ewirnwem0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0, 0:0:0:0:0:0:0:0 LLL 12:10:0:0:0:0:0:0:0 textnoblank0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0stillnoblank textnoblank0:0:0:0:0:0:0:0stillnoblank' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_processing_test4.sh0000644000000000000000000000013215241075234022151 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067805.869938881 rsyslog-8.2608.0/tests/mmnormalize_processing_test4.sh0000775000175000017500000000327415241075234021626 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST-02:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n") template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n") ruleset(name="ruleset1") { action(type="mmnormalize" rulebase="'$srcdir/testsuites/mmnormalize_processing_tests.rulebase'" useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_record") action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_path") } ' FAKETIME='2017-03-08 14:56:37' startup tcpflood -m1 -M "\"<187>Mar 8 14:56:37 host4 Process2: {SER4.local7 Y01 LNX [SRCH ALRT DASH REPT ANOM]} (/sb/env/logs/dir1/dir2/log_20170308.log) in 1: X/c79RgpDtrva5we84XHTg== (String)\"" shutdown_when_empty wait_shutdown echo '2017-03-08T14:56:37+02:00 2017-03-08T14:56:37+02:00 host4 Process2 in 1: X/c79RgpDtrva5we84XHTg== (String) /sb/logs/incoming/2017/03/08/svc_SER4/ret_Y01/os_LNX/127.0.0.1/r_relay1/sb/env/logs/dir1/dir2/log_20170308.log.gz' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_query_string_vg.sh0000644000000000000000000000013215171370365022255 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.814789282 30 ctime=1787067807.003960012 rsyslog-8.2608.0/tests/rscript_faup_query_string_vg.sh0000775000175000017500000000021515171370365021722 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_query_string.sh rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_dtls_certvalid_missing.sh0000644000000000000000000000013115216464436022362 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.814789282 30 ctime=1787067807.798974827 rsyslog-8.2608.0/tests/sndrcv_dtls_certvalid_missing.sh0000775000175000017500000000427115216464436022036 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verify cert-valid DTLS behavior when the sender lacks a usable certificate. # The receiver output must stay empty after the rejected handshake. . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls} export NUMMESSAGES=1 # export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" add_conf ' global( # debug.whitelist="on" # debug.files=["imdtls.c", "modules.c", "errmsg.c", "action.c"] ) module( load="../plugins/imdtls/.libs/imdtls" ) input( type="imdtls" port="0" listenPortFileName="'$PORT_RCVR_FILE'" tls.cacert="'$srcdir'/tls-certs/ca.pem" tls.mycert="'$srcdir'/tls-certs/cert.pem" tls.myprivkey="'$srcdir'/tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( # debug.whitelist="on" # debug.files=["omdtls.c", "modules.c", "errmsg.c", "action.c"] ) # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") # Load modules module( load="../plugins/omdtls/.libs/omdtls" ) local4.* { action( name="omdtls" type="omdtls" target="127.0.0.1" port="'$PORT_RCVR'" action.resumeInterval="1" action.resumeRetryCount="2" ) stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # Kindly check for a failed session content_check "OpenSSL Error Stack" content_check "peer did not return a certificate" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-setex.sh0000644000000000000000000000013215145046113017346 xustar0030 mtime=1771326539.054014533 30 atime=1782715518.814789282 30 ctime=1787067806.605952596 rsyslog-8.2608.0/tests/omhiredis-setex.sh0000775000175000017500000000323315145046113017016 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging # export RS_REDIR=-d . ${srcdir:=.}/diag.sh init EXPIRATION="3" start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omhiredis/.libs/omhiredis") template(name="outfmt" type="string" string="%msg%") local4.* { action(type="omhiredis" name="omhiredis-setex" server="127.0.0.1" serverport="'$REDIS_RANDOM_PORT'" mode="set" key="outKey" expiration="'$EXPIRATION'" template="outfmt") stop } action(type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'" template="outfmt") ' # Should get 'none' redis_command "TYPE outKey" > $RSYSLOG_OUT_LOG startup # Inject 1 message injectmsg 1 1 shutdown_when_empty wait_shutdown # Should get the remaining expiration time (over -1, under 5) ttl=$(redis_command "TTL outKey" | sed '1d') # Should get ' msgnum:00000001:' redis_command "GET outKey" >> $RSYSLOG_OUT_LOG sleep $EXPIRATION # Should get 'none' redis_command "TYPE outKey" >> $RSYSLOG_OUT_LOG if [ $ttl -lt 0 ] || [ $ttl -gt $EXPIRATION ]; then echo "ERROR: expiration is not in [0:$EXPIRATION] -> $ttl" error_exit 1 fi # The first get is before inserting # The third is while the key is still valid # The fourth is after the key expired export EXPECTED="none msgnum:00000001: none" cmp_exact $RSYSLOG_OUT_LOG content_check "omhiredis[omhiredis-setex]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-str.sh0000644000000000000000000000013215171370365021657 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.814789282 30 ctime=1787067804.843919762 rsyslog-8.2608.0/tests/rscript_compare_numstr-str.sh0000775000175000017500000000014615171370365021327 0ustar00rgerrger#!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='"abc"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue.sh0000644000000000000000000000013215241075234020210 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.716898761 rsyslog-8.2608.0/tests/segmented-diskqueue.sh0000775000175000017500000000243415241075234017662 0ustar00rgerrger#!/bin/bash # Verify the experimental segmentedDisk pure-disk queue can write, drain, and # delete segmented queue files. The oracle is final sequence correctness; line # count is used only to synchronize shutdown once all messages reached omfile. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue( queue.type="segmentedDisk" queue.filename="mainq" queue.maxFileSize="8k" queue.dequeueBatchSize="64" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") else action(type="omfile" file="'$RSYSLOG_DYNNAME'.syslog.log") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check if find "${RSYSLOG_DYNNAME}.spool" -maxdepth 1 \( -name 'mainq.segq' -o -name 'mainq.*.seg' \) | grep -q .; then echo "FAIL: segmentedDisk left queue files behind after clean drain" find "${RSYSLOG_DYNNAME}.spool" -maxdepth 1 \( -name 'mainq.segq' -o -name 'mainq.*.seg' \) -print error_exit 1 fi check_not_present "open error" "$RSYSLOG_DYNNAME.syslog.log" rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_omsnmpv1_udp_invalidoid.sh0000644000000000000000000000013215216464436022461 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.813789265 30 ctime=1787067805.671935191 rsyslog-8.2608.0/tests/sndrcv_omsnmpv1_udp_invalidoid.sh0000775000175000017500000000240015216464436022124 0ustar00rgerrger#!/bin/bash # alorbach, 2019-11-27 # Required Packages # pip install pysnmp # # Ubuntu 18 Packages needed # apt install snmp libsnmp-dev # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export TESTMESSAGES=1 export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.omsnmp.debuglog" generate_conf PORT_SNMP="$(get_free_port)" export PORT_SNMP # Start SNMP Trap Receiver snmp_start_trapreceiver ${PORT_SNMP} ${RSYSLOG_OUT_LOG} add_conf ' module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) module( load="../plugins/omsnmp/.libs/omsnmp" ) # set up the action template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omsnmp" name="name" server="127.0.0.1" port="'${PORT_SNMP}'" version="0" community="public" enterpriseOID="1337.1.3.3.7.1.3.3.7" messageOID="invalidOIDstring" TrapType="5" specificType="0" ) ' startup tcpflood -p'$TCPFLOOD_PORT' -m${TESTMESSAGES} shutdown_when_empty wait_shutdown snmp_stop_trapreceiver content_check "Parsing SyslogMessageOID failed" ${RSYSLOG_DYNNAME}.started content_check "Unknown Object Identifier" ${RSYSLOG_DYNNAME}.started exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_root.sh0000644000000000000000000000013215145046113020501 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.812789248 30 ctime=1787067805.958940539 rsyslog-8.2608.0/tests/imuxsock_logger_root.sh0000775000175000017500000000163315145046113020153 0ustar00rgerrger#!/bin/bash # note: we must be root and no other syslogd running in order to # carry out this test. echo \[imuxsock_logger_root.sh\]: test trailing LF handling in imuxsock echo This test must be run as root with no other active syslogd if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imuxsock/.libs/imuxsock $template outfmt,"%msg:%\n" *.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # send a message with trailing LF logger test # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log if [ ! $? -eq 0 ]; then echo "imuxsock_logger.sh failed" exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-load.sh0000644000000000000000000000013115035412264017304 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.811789231 29 ctime=1787067805.78993739 rsyslog-8.2608.0/tests/clickhouse-load.sh0000777000175000017500000000172315035412264016761 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.load (id, ipaddress, message) VALUES (%msg:F,58:2%, ' add_conf "'%fromhost-ip%', '%msg:F,58:2%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" usehttps="off" user="default" pwd="" template="outfmt" bulkmode="off") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.load ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="SELECT message FROM rsyslog.load ORDER BY id" > $RSYSLOG_OUT_LOG clickhouse-client --query="DROP TABLE rsyslog.load" seq_check 0 $(( NUMMESSAGES - 1 )) exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-crash-checkpoint.sh0000644000000000000000000000013215241075234023433 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.796900251 rsyslog-8.2608.0/tests/segmented-diskqueue-crash-checkpoint.sh0000775000175000017500000000030515241075234023100 0ustar00rgerrger#!/bin/bash # Crash after an ordinary checkpoint publication and recover without loss. export SEGDISK_FAULT_POINT=checkpoint-published . ${srcdir:=.}/testsuites/segmented-diskqueue-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_num-str.sh0000644000000000000000000000013215171370365021126 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.810789214 30 ctime=1787067804.846919818 rsyslog-8.2608.0/tests/rscript_compare_num-str.sh0000775000175000017500000000014215171370365020572 0ustar00rgerrger#!/bin/bash export LOWER_VAL='1' export HIGHER_VAL='"b"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_split.sh0000644000000000000000000000013115241075234017140 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.793581814 30 ctime=1787067804.912921048 rsyslog-8.2608.0/tests/rscript_split.sh0000775000175000017500000000435315241075234016615 0ustar00rgerrger#!/bin/bash # Added 2025-12-19 by 20syldev, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!result%\n") if $msg contains "msgnum:00000000" then { # Basic case: normal split with multi-char separator set $!input = "abc@example.com, def@example.com, ghi@example.com"; set $!result = split($!input, ", "); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000001" then { # Edge case: empty input string set $!result = split("", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000002" then { # Edge case: trailing separator set $!result = split("a,b,", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000003" then { # Edge case: leading separator set $!result = split(",a,b", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000004" then { # Edge case: multiple separators together (empty field) set $!result = split("a,,b", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000005" then { # Edge case: input string is just the separator set $!result = split(",", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000006" then { # Edge case: input string with no separators set $!result = split("abc", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000007" then { # Edge case: empty separator string (returns empty array) set $!result = split("abc", ""); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m8 shutdown_when_empty wait_shutdown export EXPECTED='[ "abc@example.com", "def@example.com", "ghi@example.com" ] [ "" ] [ "a", "b", "" ] [ "", "a", "b" ] [ "a", "", "b" ] [ "", "" ] [ "abc" ] [ ]' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_mbedtls_certvalid_expired.sh0000644000000000000000000000013215241075234023710 xustar0030 mtime=1787067036.644579024 30 atime=1787067036.797581889 30 ctime=1787067807.417967727 rsyslog-8.2608.0/tests/sndrcv_tls_mbedtls_certvalid_expired.sh0000775000175000017500000000351415241075234023362 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="mbedtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.PermitExpiredCerts="off" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'" defaultNetstreamDriver="mbedtls" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown content_check "X509 - Certificate verification failed" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_toupper.sh0000644000000000000000000000013115241075234017503 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.793581814 30 ctime=1787067804.869920246 rsyslog-8.2608.0/tests/rscript_toupper.sh0000775000175000017500000000112015241075234017145 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!str!var1 = toupper("test"); set $!str!var2 = toupper("TeSt"); set $!str!var3 = toupper(""); template(name="outfmt" type="string" string="%!str%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown export EXPECTED='{ "var1": "TEST", "var2": "TEST", "var3": "" }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-bulk-errfile-popul-erronly-interleaved.sh0000644000000000000000000000013115216464436024364 xustar0030 mtime=1782212894.051266588 29 atime=1782715518.80878918 30 ctime=1787067803.954903196 rsyslog-8.2608.0/tests/es-bulk-errfile-popul-erronly-interleaved.sh0000775000175000017500000000263015216464436024035 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ensure_elasticsearch_ready init_elasticsearch echo '{ "name" : "foo" } {"name": bar"} {"name": "baz"} {"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") # Note: we must mess up with the template, because we can not # instruct ES to put further constraints on the data type and # values. So we require integer and make sure it is none. template(name="tpl" type="list") { constant(value="{\"") property(name="$!key") constant(value="\":") property(name="$!obj") constant(value="}") } module(load="../plugins/omelasticsearch/.libs/omelasticsearch") module(load="../plugins/imfile/.libs/imfile") ruleset(name="foo") { set $!key = "my_obj"; set $!obj = $msg; action(type="omelasticsearch" template="tpl" searchIndex="rsyslog_testbench" bulkmode="on" serverport="19200" errorFile="./'${RSYSLOG_DYNNAME}'.errorfile" erroronly="on" interleaved="on") } input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile" Tag="foo" Severity="info" ruleset="foo") ' startup shutdown_when_empty wait_shutdown $PYTHON $srcdir/elasticsearch-error-format-check.py errorinterleaved ret=$? if [ "$ret" -ne 0 ] then echo "error: Format for error file different! " "$ret" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/compresssp-stringtpl.sh0000644000000000000000000000013215241075234020462 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067804.322910053 rsyslog-8.2608.0/tests/compresssp-stringtpl.sh0000775000175000017500000000174715241075234020142 0ustar00rgerrger#!/bin/bash # addd 2016-03-22 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:::compressSPACE%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup # we need to generate a file, because otherwise our multiple spaces # do not survive the execution paths through the shell echo "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test" >$RSYSLOG_DYNNAME.tmp tcpflood -I $RSYSLOG_DYNNAME.tmp rm $RSYSLOG_DYNNAME.tmp #tcpflood -m1 -M"\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000 test test test\"" shutdown_when_empty wait_shutdown export EXPECTED="msgnum:0000000 test test test" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafilecachesize-invalid.sh0000644000000000000000000000013015241075234022605 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.783581627 30 ctime=1787067804.188907556 rsyslog-8.2608.0/tests/omfile-dynafilecachesize-invalid.sh0000775000175000017500000000234115241075234022256 0ustar00rgerrger#!/bin/bash # Ensure action-level dynaFileCacheSize values below 1 are normalized instead # of crashing startup or dynafile writes. . ${srcdir:=.}/diag.sh init require_plugin imtcp generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") template(name="dynfile" type="string" string="'$RSYSLOG_DYNNAME'.out.log") template(name="outfmt" type="string" string="%msg:F,58:2%\n") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") :msg, contains, "msg:" action(type="omfile" dynafile="dynfile" template="outfmt" dynaFileCacheSize="0") ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:normalized-cache-size\"" shutdown_when_empty wait_shutdown grep "DynaFileCacheSize must be greater 0 (0 given), changed to 1." "${RSYSLOG_DYNNAME}.started" > /dev/null || { echo "FAIL: expected normalization message not found in startup log" cat "${RSYSLOG_DYNNAME}.started" error_exit 1 } printf 'normalized-cache-size\n' > "${RSYSLOG_DYNNAME}.expected" cmp_exact_file "${RSYSLOG_DYNNAME}.expected" "${RSYSLOG_DYNNAME}.out.log" || { echo "FAIL: dynafile write did not succeed after normalization" cat "${RSYSLOG_DYNNAME}.out.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-feedback-mt.sh0000644000000000000000000000013215132733117017703 xustar0030 mtime=1768666703.965621117 30 atime=1782715518.807789163 30 ctime=1787067806.048942217 rsyslog-8.2608.0/tests/omprog-feedback-mt.sh0000777000175000017500000000350415132733117017356 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Similar to the 'omprog-feedback.sh' test, with multiple worker threads # on high load, and a given error rate (percentage of failed messages, i.e. # confirmed as failed by the program). Note: the action retry interval # (1 second) causes a very low throughput; we need to set a very low error # rate to avoid the test lasting too much. . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "On Solaris, this test causes rsyslog to hang for unknown reasons" if [ "$CC" == "gcc" ] && [[ "$CFLAGS" == *"-coverage"* ]]; then printf 'This test does not work with gcc coverage instrumentation\n' printf 'It will hang, but we do not know why. See\n' printf 'https://github.com/rsyslog/rsyslog/issues/3361\n' exit 77 fi export NUMMESSAGES=10000 # number of logs to send export ERROR_RATE_PERCENT=1 # percentage of logs to be retried export command_line="$srcdir/testsuites/omprog-feedback-mt-bin.sh $ERROR_RATE_PERCENT" generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") main_queue( queue.timeoutShutdown="30000" # long shutdown timeout for the main queue ) :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $command_line` template="outfmt" name="omprog_action" confirmMessages="on" queue.type="LinkedList" # use a dedicated queue queue.workerThreads="10" # ...with multiple workers queue.size="10000" # ...high capacity (default is 1000) queue.timeoutShutdown="60000" # ...and a long shutdown timeout action.resumeInterval="1" # retry interval: 1 second ) } ' startup injectmsg 0 $NUMMESSAGES wait_file_lines "$RSYSLOG_OUT_LOG" $NUMMESSAGES shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_num-num-vg.sh0000644000000000000000000000013215171370365021527 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.807789163 30 ctime=1787067805.257927477 rsyslog-8.2608.0/tests/rscript_compare_num-num-vg.sh0000775000175000017500000000017215171370365021176 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='1' export HIGHER_VAL='2' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/omelasticsearch-searchtype-deprecated.sh0000644000000000000000000000013215216464436023661 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.806789146 30 ctime=1787067804.505913463 rsyslog-8.2608.0/tests/omelasticsearch-searchtype-deprecated.sh0000775000175000017500000000326015216464436023331 0ustar00rgerrger#!/bin/bash # Verify that explicit omelasticsearch searchType use emits a deprecation warning. . ${srcdir:=.}/diag.sh init require_plugin omelasticsearch WARN="omelasticsearch: parameter 'searchType' is deprecated because Elasticsearch mapping types are obsolete; remove this parameter for Elasticsearch 8 and later" generate_conf add_conf ' module(load="../plugins/omelasticsearch/.libs/omelasticsearch") template(name="outfmt" type="string" string="%msg%\n") action(type="omelasticsearch" server="localhost" serverport="19200" searchIndex="rsyslog_testbench" searchType="_doc" template="outfmt") ' rsyslogd_config_check > "${RSYSLOG_DYNNAME}.with-searchtype.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: config with searchType did not validate" cat "${RSYSLOG_DYNNAME}.with-searchtype.log" error_exit 1 fi content_check "$WARN" "${RSYSLOG_DYNNAME}.with-searchtype.log" generate_conf add_conf ' module(load="../plugins/omelasticsearch/.libs/omelasticsearch") template(name="outfmt" type="string" string="%msg%\n") action(type="omelasticsearch" server="localhost" serverport="19200" searchIndex="rsyslog_testbench" template="outfmt") ' rsyslogd_config_check > "${RSYSLOG_DYNNAME}.without-searchtype.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: config without searchType did not validate" cat "${RSYSLOG_DYNNAME}.without-searchtype.log" error_exit 1 fi if grep -F "$WARN" "${RSYSLOG_DYNNAME}.without-searchtype.log" > /dev/null; then echo "FAIL: config without searchType emitted deprecation warning" cat "${RSYSLOG_DYNNAME}.without-searchtype.log" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_syssock.sh0000644000000000000000000000013215131231047021211 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.806789146 30 ctime=1787067804.684916799 rsyslog-8.2608.0/tests/imuxsock_logger_syssock.sh0000777000175000017500000000133715131231047020666 0ustar00rgerrger#!/bin/bash # test trailing LF handling in imuxsock # note: we use the system socket, but assign a different name to # it. This is not 100% the same thing as running as root, but it # is pretty close to it. -- rgerhards, 201602-19 . ${srcdir:=.}/diag.sh init check_logger_has_option_d export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket") $template outfmt,"%msg:%\n" *.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup logger -d -u $RSYSLOG_DYNNAME-testbench_socket test shutdown_when_empty wait_shutdown export EXPECTED=" test" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-cri-partial-split.sh0000644000000000000000000000013215241075234022273 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067808.171981778 rsyslog-8.2608.0/tests/imkubernetes-cri-partial-split.sh0000775000175000017500000000644415241075234021752 0ustar00rgerrger#!/bin/bash # Verify that CRI partial assembly honors oversizemsg.input.mode="split". # The partial accumulator must not truncate at maxMessageSize; instead the # completed logical record reaches the core submit path and is split there. # The API helper signals readiness after binding; its 2m timeout is hang # protection, while the explicit kill and wait below own normal cleanup. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes check_command_available timeout export NUMMESSAGES=3 pwd=$( pwd ) testsrv=imk8s-partial-split-server k8s_srv_port=0 k8s_srv_port_file=${RSYSLOG_DYNNAME}${testsrv}.port logdir="${RSYSLOG_DYNNAME}.spool/pods/namespace-name1_pod-name1_uid1/container-a" logfile="${logdir}/0.log" mkdir -p "$logdir" echo starting kubernetes test server MMK8S_INCLUDE_NODE_NAME=1 timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py \ 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ $k8s_srv_port_file \ > ${RSYSLOG_DYNNAME}.spool/imkubernetes_partial_split_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started assign_file_content k8s_srv_port "$k8s_srv_port_file" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'" maxMessageSize="128" oversizemsg.input.mode="split" oversizemsg.report="off") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" KubernetesUrl="http://localhost:'$k8s_srv_port'" Token="dummy" cacheEntryTtl="60") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="pod_id" name="$!kubernetes!pod_id" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup { for i in $(seq 1 8); do printf '2026-04-20T10:00:%02d.000000000Z stdout P %s\n' "$i" \ 'partial-fragment-0123456789' done printf '%s\n' '2026-04-20T10:00:30.000000000Z stdout F closing-tail-split' printf '%s\n' '2026-04-20T10:00:31.000000000Z stdout F after split partial' } > "$logfile" wait_file_lines "$RSYSLOG_OUT_LOG" 3 wait_queueempty shutdown_when_empty wait_shutdown kill $BGPROCESS wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid if ! $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "cri"] assert len(records) == 3, records expected = ("partial-fragment-0123456789" * 8) + "closing-tail-split" first = records[0] second = records[1] assert first["msg"] == expected[:128], first assert second["msg"] == expected[128:], second for item in (first, second): assert item["stream"] == "stdout", item assert item["pod_id"] == "pod-name1-id", item independent = records[2] assert independent["msg"] == "after split partial", independent assert independent["stream"] == "stdout", independent assert independent["pod_id"] == "pod-name1-id", independent PY then error_exit 1 "imkubernetes did not pass oversized CRI partials to core split handling" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rpm-baseline-patch-policy.sh0000644000000000000000000000013215241075234021210 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.691579904 30 ctime=1787067803.673897959 rsyslog-8.2608.0/tests/rpm-baseline-patch-policy.sh0000775000175000017500000001476015241075234020667 0ustar00rgerrger#!/bin/sh # SPDX-License-Identifier: Apache-2.0 # Copyright 2026 Rainer Gerhards and Others # # This file is part of the rsyslog project, released under ASL 2.0. # Verify RPM daily-stable patch policies are exact and content-pinned. A # reviewed patch must be removed from both its source and explicit %patch # application, while an unreviewed baseline patch must reject packaging before # a build can apply a stale downstream change to current upstream sources. set -eu test_dir=$(CDPATH='' cd -- "$(dirname "$0")" && pwd) helper="$test_dir/../devtools/release/validate-rpm-baseline-patches.py" work_dir="./rpm-baseline-patch-policy-work.$$" command -v python3 >/dev/null 2>&1 || exit 77 cleanup() { rm -rf -- "$work_dir" } trap cleanup EXIT HUP INT TERM digest() { python3 - "$1" <<'PY' import hashlib import pathlib import sys print(hashlib.sha256(pathlib.Path(sys.argv[1]).read_bytes()).hexdigest()) PY } mkdir -p "$work_dir/SPECS" "$work_dir/SOURCES" cat >"$work_dir/SPECS/rsyslog.spec" <<'EOF' Name: rsyslog Patch4: integrated.patch Patch5: legacy-integrated.patch %prep %patch -P4 -p1 %patch5 -p1 EOF printf '%s\n' 'reviewed patch content' >"$work_dir/SOURCES/integrated.patch" printf '%s\n' 'reviewed legacy patch content' >"$work_dir/SOURCES/legacy-integrated.patch" integrated_digest=$(digest "$work_dir/SOURCES/integrated.patch") legacy_digest=$(digest "$work_dir/SOURCES/legacy-integrated.patch") cat >"$work_dir/policy.json" <"$work_dir/reject/SPECS/rsyslog.spec" printf '%s\n' 'unreviewed patch content' >"$work_dir/reject/SOURCES/unreviewed.patch" printf '%s\n' '{"integrated_baseline_patches": []}' >"$work_dir/reject/policy.json" if result=$(python3 "$helper" "$work_dir/reject/SPECS/rsyslog.spec" "$work_dir/reject/policy.json" test 2>&1); then echo "unreviewed baseline patch was accepted" >&2 exit 1 fi printf '%s\n' "$result" | grep -F 'baseline gained unreviewed patches' >/dev/null mkdir -p "$work_dir/unnumbered/SPECS" "$work_dir/unnumbered/SOURCES" cat >"$work_dir/unnumbered/SPECS/rsyslog.spec" <<'EOF' Patch: unnumbered.patch Patch4: numbered.patch %prep %patch -p1 %patch -P4 -p1 EOF printf '%s\n' 'unnumbered content' >"$work_dir/unnumbered/SOURCES/unnumbered.patch" printf '%s\n' 'numbered content' >"$work_dir/unnumbered/SOURCES/numbered.patch" unnumbered_digest=$(digest "$work_dir/unnumbered/SOURCES/unnumbered.patch") numbered_digest=$(digest "$work_dir/unnumbered/SOURCES/numbered.patch") cat >"$work_dir/unnumbered/policy.json" <"$fixture/SPECS/rsyslog.spec" printf '%s\n' 'unnumbered zero-form content' >"$fixture/SOURCES/unnumbered.patch" zero_digest=$(digest "$fixture/SOURCES/unnumbered.patch") cat >"$fixture/policy.json" <"$work_dir/atomic/SPECS/rsyslog.spec" <<'EOF' Patch0: first.patch Patch1: changed.patch %prep %patch -P0 -p1 %patch -P1 -p1 EOF printf '%s\n' 'first content' >"$work_dir/atomic/SOURCES/first.patch" printf '%s\n' 'changed content' >"$work_dir/atomic/SOURCES/changed.patch" first_digest=$(digest "$work_dir/atomic/SOURCES/first.patch") cat >"$work_dir/atomic/policy.json" <&2 exit 1 fi cmp "$work_dir/atomic/original.spec" "$work_dir/atomic/SPECS/rsyslog.spec" test -f "$work_dir/atomic/SOURCES/first.patch" mkdir -p "$work_dir/duplicate/SPECS" "$work_dir/duplicate/SOURCES" cat >"$work_dir/duplicate/SPECS/rsyslog.spec" <<'EOF' Patch4: first.patch Patch04: duplicate.patch EOF printf '%s\n' 'first content' >"$work_dir/duplicate/SOURCES/first.patch" printf '%s\n' 'duplicate content' >"$work_dir/duplicate/SOURCES/duplicate.patch" first_digest=$(digest "$work_dir/duplicate/SOURCES/first.patch") duplicate_digest=$(digest "$work_dir/duplicate/SOURCES/duplicate.patch") cat >"$work_dir/duplicate/policy.json" <&1); then echo "equivalent patch numbers were accepted" >&2 exit 1 fi printf '%s\n' "$result" | grep -F 'duplicate test baseline patch declaration' >/dev/null rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse_qradar.sh0000644000000000000000000000013215145046113020125 xustar0030 mtime=1771326539.045014386 30 atime=1782715518.805789129 30 ctime=1787067807.134962454 rsyslog-8.2608.0/tests/mmjsonparse_qradar.sh0000775000175000017500000000344615145046113017603 0ustar00rgerrger#!/bin/bash # added 2025-10-01 by rgerhards # check mmjsonparse with qradar generated json # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="subtree" subtree="$!qradar") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") action(type="mmjsonparse" container="!qradar" cookie="<01> @cee:" useRawMsg="on" ) if $parsesuccess == "OK" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg_file $srcdir/testsuites/qradar_json shutdown_when_empty wait_shutdown # Validate semantic JSON equality between input and output echo "Performing JSON semantic validation..." # Try Python validation first if [ -n "$PYTHON" ] && command -v "$PYTHON" >/dev/null 2>&1; then echo "Using Python for JSON validation..." if $PYTHON "$srcdir/validate_json_equality.py" $srcdir/testsuites/qradar_json $RSYSLOG_OUT_LOG "<01> @cee:"; then echo "✓ Python JSON validation passed!" validation_passed=true else echo "✗ Python JSON validation failed!" validation_passed=false fi else echo "Python not available, trying shell validation..." if bash "$srcdir/validate_json_shell.sh" $srcdir/testsuites/qradar_json $RSYSLOG_OUT_LOG "<01> @cee:"; then echo "✓ Shell JSON validation passed!" validation_passed=true else echo "✗ Shell JSON validation failed!" validation_passed=false fi fi if [ "$validation_passed" != "true" ]; then echo "JSON validation failed! Showing actual output for manual review:" echo "============================================================" cat -n $RSYSLOG_OUT_LOG echo "============================================================" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmexternal-mmnormalize-json-tree.sh0000644000000000000000000000013115216464436022657 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.805789129 30 ctime=1787067807.090961634 rsyslog-8.2608.0/tests/mmexternal-mmnormalize-json-tree.sh0000775000175000017500000000204515216464436022330 0ustar00rgerrger#!/bin/bash # added 2026-05-22 by Codex, released under ASL 2.0 # Regression coverage for issue #689: mmexternal must be able to merge a # returned $! tree after mmnormalize has already populated message variables. # The oracle is the configured omfile output after synchronized shutdown, so # the test verifies the final rsyslog message state rather than plugin stderr. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/mmexternal/.libs/mmexternal") template(name="outfmt" type="string" string="%$!all-json%\n") action(type="mmnormalize" rule=["rule=:%text:rest%"] useRawMsg="off") action(type="mmexternal" interface.input="fulljson" binary="'$PYTHON' '${srcdir}'/testsuites/mmexternal-SegFault-mm-python.py") action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal "<13>Mar 10 01:00:00 host tag:test-message" shutdown_when_empty wait_shutdown content_check '"text": "test-message"' content_check '"sometag": "somevalue"' exit_test rsyslog-8.2608.0/tests/PaxHeaders/omotel-protobuf-basic.sh0000644000000000000000000000013115171370365020460 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.804789112 30 ctime=1787067806.211945254 rsyslog-8.2608.0/tests/omotel-protobuf-basic.sh0000775000175000017500000000631615171370365020136 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-protobuf-basic.sh -- basic functionality test for omotel protobuf encoding ## ## Starts OTEL Collector, sends messages via omotel with protocol "http/protobuf", ## and verifies messages are received and stored correctly. . ${srcdir:=.}/diag.sh init # Check if omotel module is available require_plugin omotel export NUMMESSAGES=1000 export EXTRA_EXIT=otel export SEQ_CHECK_OPTIONS=-d # Download and prepare OTEL Collector download_otel_collector prepare_otel_collector start_otel_collector # Read the port from the port file if [ ! -f ${RSYSLOG_DYNNAME}.otel_port.file ]; then echo "ERROR: OTEL Collector port file not found: ${RSYSLOG_DYNNAME}.otel_port.file" error_exit 1 fi otel_port=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) if [ -z "$otel_port" ]; then echo "ERROR: OTEL Collector port is empty" error_exit 1 fi echo "Using OTEL Collector port: $otel_port" generate_conf add_conf ' template(name="otlpBody" type="string" string="msgnum:%msg:F,58:2%") module(load="../plugins/omotel/.libs/omotel") if $msg contains "msgnum:" then action( name="omotel-protobuf" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port'" path="/v1/logs" protocol="http/protobuf" batch.max_items="100" batch.timeout.ms="1000" ) ' startup injectmsg shutdown_when_empty wait_shutdown # Stop OTEL Collector to ensure file exporter flushes data stop_otel_collector # Give OTEL Collector a moment to flush the output file after shutdown if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi # Extract data from OTEL Collector output otel_collector_get_data python3 - "$RSYSLOG_DYNNAME.otel-output.json" <<'PY' import json import sys path = sys.argv[1] try: records = [] with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue payload = json.loads(line) if "resourceLogs" in payload: for resource_log in payload["resourceLogs"]: if "scopeLogs" in resource_log: for scope_log in resource_log["scopeLogs"]: if "logRecords" in scope_log: records.extend(scope_log["logRecords"]) except Exception as exc: sys.stderr.write(f"omotel-protobuf-basic: failed to parse OTLP output: {exc}\n") sys.exit(1) if not records: sys.stderr.write("omotel-protobuf-basic: OTLP output did not contain any logRecords\n") sys.exit(1) def has_hostname(attrs): for entry in attrs: if entry.get("key") == "log.syslog.hostname": val = entry.get("value", {}).get("stringValue", "") if val: return True return False for idx, record in enumerate(records): if record.get("severityNumber", 0) == 0: sys.stderr.write(f"omotel-protobuf-basic: record {idx} missing severityNumber\n") sys.exit(1) if not has_hostname(record.get("attributes", [])): sys.stderr.write(f"omotel-protobuf-basic: record {idx} missing log.syslog.hostname attribute\n") sys.exit(1) PY seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_query_string.sh0000644000000000000000000000013215241075234021554 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.962959248 rsyslog-8.2608.0/tests/rscript_faup_query_string.sh0000775000175000017500000000204015241075234021217 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://user:pass@www.rsyslog.com:443/doc/v8-stable/rainerscript/functions/mo-faup.html?param=value#faup"; set $.faup = faup_query_string($!url); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 ?param=value' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-kafkarest-retry.sh0000644000000000000000000000013215131231047021740 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.803789095 30 ctime=1787067806.135943838 rsyslog-8.2608.0/tests/omhttp-batch-kafkarest-retry.sh0000777000175000017500000000320315131231047021407 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 omhttp_start_server 0 --fail-every 100 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="2048") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") # Echo message as-is for retry template(name="tpl_echo" type="string" string="%msg%") ruleset(name="ruleset_omhttp_retry") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl_echo" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="kafkarest" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } ruleset(name="ruleset_omhttp") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="kafkarest" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint kafkarest omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_err.sh0000644000000000000000000000013215145046113020306 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.802789078 30 ctime=1787067804.668916501 rsyslog-8.2608.0/tests/imuxsock_logger_err.sh0000775000175000017500000000213015145046113017751 0ustar00rgerrger#!/bin/bash # this is primarily a safeguard to ensure the imuxsock tests basically work # added 2014-12-04 by Rainer Gerhards, licensed under ASL 2.0 echo \[imuxsock_logger.sh\]: test imuxsock . ${srcdir:=.}/diag.sh init check_logger_has_option_d generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") *.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # send a message with trailing LF logger -d -u $RSYSLOG_DYNNAME-testbench_socket "wrong message" # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log if [ $? -eq 0 ]; then echo "imuxsock_logger_err.sh did not report an error where it should!" exit 1 else echo "all well, we saw the error that we wanted to have" fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omamqp1-basic-vg.sh0000644000000000000000000000013215171370365017311 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.802789078 30 ctime=1787067808.188982094 rsyslog-8.2608.0/tests/omamqp1-basic-vg.sh0000775000175000017500000000010615171370365016755 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omamqp1-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_kafka.sh0000644000000000000000000000013115216464436016703 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.802789078 30 ctime=1787067806.261946186 rsyslog-8.2608.0/tests/sndrcv_kafka.sh0000775000175000017500000000624615216464436016363 0ustar00rgerrger#!/bin/bash # added 2017-05-03 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export TESTMESSAGESFULL=100000 # Generate random topic name RANDTOPIC="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka download_kafka stop_zookeeper stop_kafka start_zookeeper start_kafka create_kafka_topic $RANDTOPIC '.dep_wrk' '22181' export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/omkafka/.libs/omkafka") template(name="outfmt" type="string" string="%msg%\n") local4.* { action( name="kafka-fwd" type="omkafka" topic="'$RANDTOPIC'" broker="localhost:29092" template="outfmt" confParam=[ "compression.codec=none", "socket.timeout.ms=10000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "queue.buffering.max.messages=10000", "enable.auto.commit=true", "message.send.max.retries=1"] topicConfParam=["message.timeout.ms=10000"] partitions.auto="on" closeTimeout="60000" resubmitOnFailure="on" keepFailedMessages="on" failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC'.data" action.resumeInterval="1" action.resumeRetryCount="10" queue.saveonshutdown="on" ) stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.snd.othermsg'") ' echo Starting sender instance [omkafka] startup # --- # Injection messages now before starting receiver, simply because omkafka will take some time and # there is no reason to wait for the receiver to startup first. echo Inject messages into rsyslog sender instance injectmsg 1 $TESTMESSAGES # --- Create/Start imkafka receiver config export RSYSLOG_DEBUGLOG="log2" generate_conf 2 add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") /* Polls messages from kafka server!*/ input( type="imkafka" topic="'$RANDTOPIC'" broker="localhost:29092" consumergroup="default" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=5000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "enable.partition.eof=false" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" ) } else { action( type="omfile" file="'$RSYSLOG_DYNNAME.rcv.othermsg'") } ' 2 echo Starting receiver instance [imkafka] startup 2 # --- echo Stopping sender instance [omkafka] shutdown_when_empty wait_shutdown echo Stopping receiver instance [imkafka] kafka_wait_group_coordinator shutdown_when_empty 2 wait_shutdown 2 delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181' # Dump Kafka log | uncomment if needed # dump_kafka_serverlog kafka_check_broken_broker $RSYSLOG_DYNNAME.snd.othermsg kafka_check_broken_broker $RSYSLOG_DYNNAME.rcv.othermsg seq_check 1 $TESTMESSAGESFULL -d echo success exit_test rsyslog-8.2608.0/tests/PaxHeaders/execonlywhenprevsuspended-queue.sh0000644000000000000000000000013115035412264022700 xustar0029 mtime=1752569012.38883413 30 atime=1782715518.802789078 30 ctime=1787067804.635915886 rsyslog-8.2608.0/tests/execonlywhenprevsuspended-queue.sh0000777000175000017500000000176515035412264022363 0ustar00rgerrger#!/bin/bash # rgerhards, 2015-05-27 echo ===================================================================================== echo \[execonlywhenprevsuspended-queue.sh\]: test execonly...suspended functionality with action on its own queue uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' main_queue(queue.workerthreads="1") # omtesting provides the ability to cause "SUSPENDED" action state module(load="../plugins/omtesting/.libs/omtesting") $MainMsgQueueTimeoutShutdown 100000 template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { :omtesting:fail 2 0 # omtesting has only legacy params! action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" queue.type="linkedList" action.ExecOnlyWhenPreviousIsSuspended="on" ) } ' startup injectmsg 0 1000 shutdown_when_empty wait_shutdown seq_check 1 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_previous_action_suspended.sh0000644000000000000000000000013115241075234023270 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067804.887920582 rsyslog-8.2608.0/tests/rscript_previous_action_suspended.sh0000775000175000017500000000125515241075234022743 0ustar00rgerrger#!/bin/bash # Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omtesting/.libs/omtesting") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="output_writer") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } :msg, contains, "msgnum:" { :omtesting:fail 2 0 if previous_action_suspended() then call output_writer } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown seq_check 1 9 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-feedback-timeout.sh0000644000000000000000000000013215216464436020761 xustar0030 mtime=1782212894.080267057 30 atime=1782715518.827789503 30 ctime=1787067806.051942273 rsyslog-8.2608.0/tests/omprog-feedback-timeout.sh0000775000175000017500000000261315216464436020432 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests the feedback feature of omprog (confirmMessages=on), # by checking that omprog restarts the program if it does not send the # feedback before the configured 'confirmTimeout'. Also tests the # keep-alive feature. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-feedback-timeout-bin.sh` template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process confirmMessages="on" confirmTimeout="2000" # 2 seconds action.resumeInterval="1" action.resumeRetryCount="10" reportFailures="on" ) } ' startup injectmsg 0 10 content_check_with_count "=> msgnum:00000004:" 2 90 shutdown_when_empty wait_shutdown export EXPECTED="Starting <= OK => msgnum:00000000: <= OK => msgnum:00000001: <= OK => msgnum:00000002: <= OK => msgnum:00000003: <= OK => msgnum:00000004: <= (timeout) Starting <= OK => msgnum:00000004: <= OK => msgnum:00000005: <= OK => msgnum:00000006: <= OK => msgnum:00000007: <= ........OK => msgnum:00000008: <= OK => msgnum:00000009: <= OK" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/fieldtest-udp.sh0000644000000000000000000000013215241075234017011 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067803.657897661 rsyslog-8.2608.0/tests/fieldtest-udp.sh0000775000175000017500000000236315241075234016464 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 # Verify UDP parser field extraction from a PIX-style message. The test uses # an imudp-assigned port file so parallel test runs cannot cross-feed messages; # the extracted field in RSYSLOG_OUT_LOG is the pass/fail oracle. . ${srcdir:=.}/diag.sh init generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imudp.port" add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_RCVR_FILE'" ruleset="ruleset1") template(name="outfmt" type="string" string="%msg:F,32:2%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_tcpflood_port "$PORT_RCVR_FILE" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: DROP_url_www.sina.com.cn:IN=eth1 OUT=eth0 SRC=192.168.10.78 DST=61.172.201.194 LEN=1182 TOS=0x00 PREC=0x00 TTL=63 ID=14368 DF PROTO=TCP SPT=33343 DPT=80 WINDOW=92 RES=0x00 ACK PSH URGP=0\"" shutdown_when_empty wait_shutdown echo 'DROP_url_www.sina.com.cn:IN=eth1' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/README0000644000000000000000000000013215241075234014564 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.761581215 30 ctime=1787067803.540895481 rsyslog-8.2608.0/tests/README0000664000175000017500000001135515241075234014235 0ustar00rgerrger# rsyslog testbench quick reference This directory houses the rsyslog Automake test suite. The [`tests/AGENTS.md`](./AGENTS.md) file gives AI agents authoring guidance and conventions; this README focuses on operators and contributors who need to run the suite. Most scripts validate a single module, but complex end-to-end scenarios are welcome. For a minimal example, examine `rtinit.c`, which performs a simple runtime init/deinit cycle. The `tests/` subtree is the single Automake-owned test area for rsyslog. The shell-driven testbench remains here, and fast C unit-test sources for isolated helpers are organized in [`tests/unit/`](./unit/README.md) but are built and run by [`tests/Makefile.am`](./Makefile.am). ## Quickstart Bootstrap the build tree before attempting to run tests: ```sh ./autogen.sh ./configure --enable-testbench make -j$(nproc) make check ``` `make check` compiles the helper binaries, prepares fixtures, and then executes the entire suite, including the unit tests sourced from `tests/unit/`. Use Ctrl+C to stop an ongoing run. ## Running individual scenarios ``` make .log ``` For example, `make imfile-basic.log` produces `imfile-basic.log` and `imfile-basic.trs`. Remove those files before re-running to clear cached results. When you need Automake’s logging but do not want to type the `.log` suffix, use: ``` make check TESTS='imfile-basic.sh' ``` You can also execute scripts directly (`./tests/imfile-basic.sh`) for quicker iteration, though Automake will not capture transcripts. To run the linkedlist unit test through the shared harness from the repository root: ``` make check TESTS='runtime_unit_linkedlist' ``` ## Harness conventions - Include `diag.sh` at the top of every shell test using the POSIX `.` command: `. "$srcdir/diag.sh"`. - Prefer helpers such as `cmp_exact` and `require_plugin` over ad-hoc shell so diagnostics stay consistent. See `tests/AGENTS.md` for a longer checklist. - Name Valgrind-enabled wrappers with the `-vg.sh` suffix and Helgrind-enabled scripts with `-vgthread.sh`. `tests/timereported-utc-vg.sh` illustrates how to include the base scenario using the `.` command rather than duplicating it and how to trim emitted messages when a slow test would otherwise become prohibitively long under Valgrind. Some legacy wrappers predate this pattern; follow the newer style when adding or refactoring coverage. ## Environment setup snippets ### MariaDB/MySQL ``` echo "create user 'rsyslog'@'localhost' identified by 'testbench';" | mysql -u root mysql -u root < ../plugins/ommysql/createDB.sql echo "grant all on Syslog.* to 'rsyslog'@'localhost';" | mysql -u root ``` ### openSUSE tips Use the graphical `yast2` tool to adjust hostname and firewall rules. SSH access is disabled in the firewall by default. ## Debugging aids To pause a test and attach a debugger, add the following guard: ```sh . "$srcdir/diag.sh" startup if [ -n "${USE_GDB:-}" ]; then echo "attach gdb here" sleep 54321 || : fi ``` Run the scenario in the background, wait for the prompt, and attach GDB: ``` USE_GDB=1 make mytest.sh.log & tail -f mytest.sh.log # wait for "attach gdb here" gdb ../tools/rsyslogd ``` After continuing in GDB, terminate the `sleep` with `pkill -f 54321` (or locate the PID via `ps -ef | grep 54321`). ## Core dump analysis Core files are best-effort diagnostics, not the test oracle. The harness tries to enable them with `ulimit -c unlimited`, but crash collectors such as `systemd-coredump`, `apport`, container policy, file permissions, or size limits may redirect or suppress local files. On failure, `diag.sh` prints the active core policy (`kernel.core_pattern`, `kernel.core_uses_pid`, and `fs.suid_dumpable` when available). The harness analyzes a core only when it can attribute the file to the expected process by pid/executable metadata, or when the filename is clearly test-specific via `RSYSLOG_DYNNAME`. Generic `core.*` files from parallel or stale tests are ignored unless ownership is proven. If `core_pattern` pipes crashes to an external collector, generic local core scanning is skipped. Valgrind `vgcore.*` files are handled separately because they belong to the supervised Valgrind run and remain a Valgrind failure signal. For local debugging you may still switch a disposable development host to a classic core pattern such as `core.%e.%p`, but avoid applying such changes on production hosts. The `tcpflood` shell helper configures and validates a per-invocation proper-termination marker. Direct `./tcpflood` invocations can use `-q ` for the same final-exit marker when the test needs tcpflood abort detection. Tests that intentionally trigger a tcpflood send failure should call `tcpflood --check-only` and assert the rsyslog-side result. rsyslog-8.2608.0/tests/PaxHeaders/override_gethostname_nonfqdn.c0000644000000000000000000000013215132411300021773 xustar0030 mtime=1768559296.295886099 30 atime=1782715518.827789503 30 ctime=1787067803.550895667 rsyslog-8.2608.0/tests/override_gethostname_nonfqdn.c0000666000175000017500000000037715132411300021450 0ustar00rgerrger#include int gethostname(char *name, size_t __attribute__((unused)) len) { *name++ = 'n'; *name++ = 'o'; *name++ = 'n'; *name++ = 'f'; *name++ = 'q'; *name++ = 'd'; *name++ = 'n'; *name++ = '\0'; return 0; } rsyslog-8.2608.0/tests/PaxHeaders/dns_srv_mock.py0000644000000000000000000000013115216464436016754 xustar0029 mtime=1782212894.04826654 30 atime=1782715518.827789503 30 ctime=1787067808.234982951 rsyslog-8.2608.0/tests/dns_srv_mock.py0000775000175000017500000001021415216464436016422 0ustar00rgerrger#!/usr/bin/env python3 import argparse import json import socket import struct import sys from typing import Dict, List, Optional, Tuple SRV_TYPE = 33 A_TYPE = 1 CLASS_IN = 1 def encode_name(name: str) -> bytes: name = name.rstrip('.') if not name: return b"\0" parts = name.split('.') encoded = bytearray() for part in parts: encoded.append(len(part)) encoded.extend(part.encode('utf-8')) encoded.append(0) return bytes(encoded) def parse_name(data: bytes, offset: int) -> Tuple[str, int]: labels = [] jumped = False start_offset = offset while True: if offset >= len(data): return ".", offset length = data[offset] if length == 0: offset += 1 break if length & 0xC0 == 0xC0: if offset + 1 >= len(data): return ".", offset + 1 pointer = ((length & 0x3F) << 8) | data[offset + 1] offset = pointer if not jumped: start_offset += 2 jumped = True continue offset += 1 labels.append(data[offset: offset + length].decode('utf-8')) offset += length return '.'.join(labels) + '.', (start_offset if jumped else offset) def build_response(data: bytes, records: Dict[str, Dict[str, List[Dict[str, str]]]]) -> bytes: if len(data) < 12: return data tid, flags, qdcount, _, _, _ = struct.unpack('!HHHHHH', data[:12]) offset = 12 qname, offset = parse_name(data, offset) qtype, qclass = struct.unpack('!HH', data[offset: offset + 4]) offset += 4 answers = [] if qtype == SRV_TYPE: for entry in records.get('SRV', {}).get(qname, []): priority = int(entry.get('priority', 0)) weight = int(entry.get('weight', 0)) port = int(entry.get('port', 0)) target = entry.get('target', '') rdata = struct.pack('!HHH', priority, weight, port) + encode_name(target) answers.append((qtype, qclass, 30, rdata, entry)) elif qtype == A_TYPE: addr = records.get('A', {}).get(qname) if addr: rdata = socket.inet_aton(addr) answers.append((qtype, qclass, 60, rdata, None)) has_answer = bool(answers) flags_out = 0x8180 if has_answer else 0x8183 response = struct.pack('!HHHHHH', tid, flags_out, 1, len(answers), 0, 0) response += data[12:offset] for ans in answers: response += encode_name(qname) response += struct.pack('!HHI', ans[0], ans[1], ans[2]) response += struct.pack('!H', len(ans[3])) response += ans[3] return response def write_port(port_file: str, port: int) -> None: with open(port_file, 'w', encoding='utf-8') as handle: handle.write("{}\n".format(port)) handle.flush() def serve(address: str, port: int, records: Dict[str, Dict[str, List[Dict[str, str]]]], port_file: Optional[str]) -> None: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((address, port)) if port_file: write_port(port_file, sock.getsockname()[1]) while True: data, client = sock.recvfrom(2048) if not data: continue resp = build_response(data, records) try: sock.sendto(resp, client) except socket.error: continue def main() -> int: parser = argparse.ArgumentParser(description='Minimal UDP DNS server for SRV testing') parser.add_argument('--port', type=int, required=True) parser.add_argument('--address', default='127.0.0.1') parser.add_argument('--records', required=True, help='Path to JSON records file') parser.add_argument('--port-file', help='Write the bound port to this file') args = parser.parse_args() try: with open(args.records, 'r', encoding='utf-8') as f: records = json.load(f) except Exception as exc: # pragma: no cover - test helper print('failed to load records: {}'.format(exc), file=sys.stderr) return 1 serve(args.address, args.port, records, args.port_file) return 0 if __name__ == '__main__': raise SystemExit(main()) rsyslog-8.2608.0/tests/PaxHeaders/imkafka_multi_topic.sh0000644000000000000000000000013115216464436020262 xustar0030 mtime=1782212894.058266701 30 atime=1782715518.827789503 29 ctime=1787067806.25894613 rsyslog-8.2608.0/tests/imkafka_multi_topic.sh0000775000175000017500000000404315216464436017733 0ustar00rgerrger#!/bin/bash # Test that a single imkafka input() can consume from multiple topics # specified as an array: topic=["topic1", "topic2"] # added 2026-05-29 by contributor # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init check_command_available kcat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=1000 export TESTMESSAGESFULL=$TESTMESSAGES export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka RANDTOPIC1="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" RANDTOPIC2="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC1 RANDTOPIC2 download_kafka stop_zookeeper stop_kafka start_zookeeper start_kafka wait_for_kafka_startup create_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181' create_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181' generate_conf add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") input( type="imkafka" topic=["'$RANDTOPIC1'", "'$RANDTOPIC2'"] broker="127.0.0.1:29092" consumergroup="default" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=5000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "enable.partition.eof=false" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) } ' startup HALF=$((TESTMESSAGES / 2)) # Inject first half of messages into topic 1 i=1 while (( i <= HALF )); do printf ' msgnum:%8.8d\n' $i i=$((i + 1)) done | kcat -P -b 127.0.0.1:29092 -t $RANDTOPIC1 # Inject second half of messages into topic 2 i=$((HALF + 1)) while (( i <= TESTMESSAGES )); do printf ' msgnum:%8.8d\n' $i i=$((i + 1)) done | kcat -P -b 127.0.0.1:29092 -t $RANDTOPIC2 wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES ${RETRIES:-200} shutdown_when_empty wait_shutdown delete_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181' delete_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181' seq_check 1 $TESTMESSAGESFULL -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/impstats-push-tls-missing-key.sh0000644000000000000000000000013215145046113022113 xustar0030 mtime=1771326539.040014305 30 atime=1782715518.827789503 30 ctime=1787067806.742955149 rsyslog-8.2608.0/tests/impstats-push-tls-missing-key.sh0000775000175000017500000000170515145046113021565 0ustar00rgerrger#!/bin/bash # Test for impstats push TLS validation - missing keyfile # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "Solaris has limitations" export RS_REDIR="2>$RSYSLOG_DYNNAME.err.log" generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" interval="1" format="prometheus" log.file="'"$RSYSLOG_OUT_LOG"'" resetCounters="off" # Push config (TLS validation) push.url="https://localhost:8428/api/v1/write" push.tls.certfile="/etc/ssl/certs/ca-certificates.crt" ) action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) ' startup sleep 1 shutdown_when_empty wait_shutdown if ! grep -q "push.tls.certfile is set but push.tls.keyfile is missing" "$RSYSLOG_DYNNAME.err.log"; then echo "FAIL: expected TLS missing keyfile error in $RSYSLOG_DYNNAME.err.log" cat -n "$RSYSLOG_DYNNAME.err.log" || true error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-mmkubernetes-namespace-metadata-off.sh0000644000000000000000000000013215241075234024161 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067808.149981368 rsyslog-8.2608.0/tests/yaml-mmkubernetes-namespace-metadata-off.sh0000775000175000017500000000621515241075234023634 0ustar00rgerrger#!/bin/bash # Verify includeNamespaceMetadata=off reaches mmkubernetes through the YAML # frontend. The retained pod metadata and absent namespace metadata are the # observable parity oracle. The two-minute server timeout is hang protection; # readiness and cleanup use PID/port files rather than timing assumptions. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init check_command_available timeout require_yaml_support require_plugin mmkubernetes ../contrib/mmkubernetes pwd=$(pwd) testsrv=mmk8s-test-server k8s_srv_port_file="${RSYSLOG_DYNNAME}${testsrv}.port" generate_conf --yaml-only timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ ${k8s_srv_port_file} > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_file_exists "$k8s_srv_port_file" k8s_srv_port="$(cat "$k8s_srv_port_file")" wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imfile/.libs/imfile"' add_yaml_conf ' - load: "../plugins/mmjsonparse/.libs/mmjsonparse"' add_yaml_conf ' - load: "../contrib/mmkubernetes/.libs/mmkubernetes"' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imfile' add_yaml_conf ' file: "'$RSYSLOG_DYNNAME.spool'/pod-*.log"' add_yaml_conf ' tag: kubernetes' add_yaml_conf ' addmetadata: on' add_yaml_conf ' ruleset: main' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf ' string: "%$!all-json-plain%\n"' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: main' add_yaml_conf ' statements:' add_yaml_conf ' - type: mmjsonparse' add_yaml_conf ' cookie: ""' add_yaml_conf ' - type: mmkubernetes' add_yaml_conf ' token: dummy' add_yaml_conf ' kubernetesurl: "http://localhost:'$k8s_srv_port'"' add_yaml_conf ' includenamespacemetadata: off' add_yaml_conf ' filenamerules:' add_yaml_conf ' - "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"' add_yaml_conf ' - type: omfile' add_yaml_conf ' file: "'$RSYSLOG_OUT_LOG'"' add_yaml_conf ' template: outfmt' cat > ${RSYSLOG_DYNNAME}.spool/pod-name2578_namespace-name2578_container-name2578-id2578.log < $RSYSLOG_DYNNAME.input ./msleep 2000 rm ./'$RSYSLOG_DYNNAME'.input ./msleep 3000 shutdown_when_empty wait_shutdown grep "file.*$RSYSLOG_DYNNAME.input.*No such file or directory" ${RSYSLOG2_OUT_LOG} > /dev/null if [ $? -ne 0 ]; then echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi if [ $(grep "No such file or directory" ${RSYSLOG2_OUT_LOG} | wc -l) -ne 1 ]; then echo "FAIL: expected error message is put out multiple times. ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi echo 'testmessage1 testmessage2 testmessage3' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_num2ipv4.sh0000644000000000000000000000013215241075234017472 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.792581796 30 ctime=1787067804.861920098 rsyslog-8.2608.0/tests/rscript_num2ipv4.sh0000775000175000017500000000272415241075234017146 0ustar00rgerrger#!/bin/bash # add 2017-02-09 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/fmhttp/.libs/fmhttp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!ip!v0 = num2ipv4(""); set $!ip!v1 = num2ipv4("0"); set $!ip!v2 = num2ipv4("1"); set $!ip!v3 = num2ipv4("256"); set $!ip!v4 = num2ipv4("65536"); set $!ip!v5 = num2ipv4("16777216"); set $!ip!v6 = num2ipv4("135"); set $!ip!v7 = num2ipv4("16843009"); set $!ip!v8 = num2ipv4("3777036554"); set $!ip!v9 = num2ipv4("2885681153"); set $!ip!v10 = num2ipv4("4294967295"); set $!ip!e1 = num2ipv4("a"); set $!ip!e2 = num2ipv4("-123"); set $!ip!e3 = num2ipv4("1725464567890"); set $!ip!e4 = num2ipv4("4294967296"); set $!ip!e5 = num2ipv4("2839."); template(name="outfmt" type="string" string="%!ip%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown echo '{ "v0": "0.0.0.0", "v1": "0.0.0.0", "v2": "0.0.0.1", "v3": "0.0.1.0", "v4": "0.1.0.0", "v5": "1.0.0.0", "v6": "0.0.0.135", "v7": "1.1.1.1", "v8": "225.33.1.10", "v9": "172.0.0.1", "v10": "255.255.255.255", "e1": "-1", "e2": "-1", "e3": "-1", "e4": "-1", "e5": "-1" }' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid function output detected, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-full.sh0000644000000000000000000000013215035412264017176 xustar0030 mtime=1752569012.386848027 30 atime=1782715518.825789469 30 ctime=1787067804.444912327 rsyslog-8.2608.0/tests/diskqueue-full.sh0000777000175000017500000000150115035412264016644 0ustar00rgerrger#!/bin/bash # checks that nothing bad happens if a DA (disk) queue runs out # of configured disk space # addd 2017-02-07 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.filename="mainq" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutenqueue="300000" queue.lowwatermark="5000" ) template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :omtesting:sleep 0 5000 :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 20000 ls -l ${RSYSLOG_DYNNAME}.spool shutdown_when_empty wait_shutdown ls -l ${RSYSLOG_DYNNAME}.spool seq_check 0 19999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmdb-open-missing-vg.sh0000644000000000000000000000013215216464436020207 xustar0030 mtime=1782212894.073266944 30 atime=1782715518.825789469 30 ctime=1787067807.264964876 rsyslog-8.2608.0/tests/mmdb-open-missing-vg.sh0000775000175000017500000000076315216464436017664 0ustar00rgerrger#!/usr/bin/env bash # Valgrind companion for GitHub issue #4024. The missing-database path used to # leave a partially-created worker instance behind, which could crash only after # shutdown cleanup. Running the same scenario under Valgrind makes that oracle # explicit for CI. script_dir=$(dirname "$0") : ${srcdir:=.} export USE_VALGRIND="YES" export RS_TESTBENCH_VALGRIND_EXTRA_OPTS="$RS_TESTBENCH_VALGRIND_EXTRA_OPTS --suppressions=$srcdir/libmaxmindb.supp" . "$script_dir/mmdb-open-missing.sh" rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-crash-commit.sh0000644000000000000000000000013215241075234022574 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.800900326 rsyslog-8.2608.0/tests/segmented-diskqueue-crash-commit.sh0000775000175000017500000000027215241075234022244 0ustar00rgerrger#!/bin/bash # Crash after commit-frontier publication and recover without loss. export SEGDISK_FAULT_POINT=commit-published . ${srcdir:=.}/testsuites/segmented-diskqueue-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/randomgen.c0000644000000000000000000000013215132733117016022 xustar0030 mtime=1768666703.965621117 30 atime=1782715518.825789469 30 ctime=1787067803.600896599 rsyslog-8.2608.0/tests/randomgen.c0000666000175000017500000000733115132733117015474 0ustar00rgerrger/* generates random data for later use in test cases. Of course, * we could generate random data during the testcase itself, but * the core idea is that we record the random data so that we have * a chance to reproduce a problem should it occur. IMHO this * provides the best compromise, by a) having randomness but * b) knowing what was used during the test. * * Params * -f output file name (stdout if not given) * -s size of test data, plain number is size in k, 1MB default * -u uses /dev/urandom instead of libc random number generator * (when available). Note that this is usually much slower. * * Part of the testbench for rsyslog. * * Copyright 2010-2016 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #define EXIT_FAILURE 1 static char *fileName = NULL; /* name of output file */ static int tryUseURandom = 0; /* try to use /dev/urandom? */ static long long fileSize = 1024 * 1024; /* file size in K, 1MB default */ /* generate the random file. This code really can be improved (e.g. read /dev/urandom * when available) */ static void genFile(void) { long i; FILE *fp; FILE *rfp = NULL; if (fileName == NULL) { fp = stdout; } else { if ((fp = fopen(fileName, "w")) == NULL) { perror(fileName); } } /* try to use /dev/urandom, if available */ if (tryUseURandom) rfp = fopen("/dev/urandom", "r"); if (rfp == NULL) { /* fallback, use libc random number generator */ for (i = 0; i < fileSize; ++i) { if (fputc((char)rand(), fp) == EOF) { perror(fileName); exit(1); } } } else { /* use /dev/urandom */ printf("using /dev/urandom"); for (i = 0; i < fileSize; ++i) { if (fputc(fgetc(rfp), fp) == EOF) { perror(fileName); exit(1); } } } if (fileName != NULL) fclose(fp); } /* Run the test. * rgerhards, 2009-04-03 */ int main(int argc, char *argv[]) { int ret = 0; int opt; srand(time(NULL)); /* seed is good enough for our needs */ while ((opt = getopt(argc, argv, "f:s:u")) != -1) { switch (opt) { case 'f': fileName = optarg; break; case 's': fileSize = atol(optarg) * 1024; break; case 'u': tryUseURandom = 1; break; default: printf("invalid option '%c' or value missing - terminating...\n", opt); exit(1); break; } } printf("generating random data file '%s' of %ldkb - may take a short while...\n", fileName, (long)(fileSize / 1024)); genFile(); exit(ret); } rsyslog-8.2608.0/tests/PaxHeaders/imptcp-persource-ratelimit-policy.sh0000644000000000000000000000013215241075234023026 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.770581384 30 ctime=1787067805.654934874 rsyslog-8.2608.0/tests/imptcp-persource-ratelimit-policy.sh0000775000175000017500000000705515241075234022504 0ustar00rgerrger#!/bin/bash ## Test that imptcp inherits per-source limiting through ratelimitAddMsg(). ## The policy key template is configured only in the ratelimit YAML file; the ## module should not compute or pass a per-source key itself. ## The impstats sleep gives the one-second stats interval time to publish the ## key-evaluation counters that prove tplToString and parser use for this ## custom hostname template. The submitted counter must match the delivered ## message count, proving per-source drops return the same discard status as the ## regular ratelimiter and are not counted as successfully submitted. . ${srcdir:=.}/diag.sh init require_plugin impstats skip_ARM "ratelimit timing flaky on ARM" export NUMMESSAGES=10 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export STATSFILE="$RSYSLOG_DYNNAME.stats" POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" INPUT_FILE="$(pwd)/${RSYSLOG_DYNNAME}.input" export POLICY_FILE INPUT_FILE cat > "$POLICY_FILE" < "$INPUT_FILE" for i in $(seq 1 20); do echo "<13>Jan 1 00:00:00 noisyhost app: msgnum:$i" >> "$INPUT_FILE" done for i in $(seq 1 5); do echo "<13>Jan 1 00:00:00 quiethost app: msgnum:$i" >> "$INPUT_FILE" done tcpflood -p"$ptcp_port" -I "$INPUT_FILE" sleep 2 shutdown_when_empty wait_shutdown noisy_count=$(grep -c "host=noisyhost" "$RSYSLOG_OUT_LOG") quiet_count=$(grep -c "host=quiethost" "$RSYSLOG_OUT_LOG") content_count=$((noisy_count + quiet_count)) submitted_count=$(grep "origin=imptcp" "$STATSFILE" | grep -o "submitted=[0-9]*" | sed 's/.*=//' | sort -n | tail -1) tpl_evals=$(grep "ratelimit.per_source.per_source" "$STATSFILE" | grep -o "per_source_key_tpl_evals=[0-9]*" | tail -1 | sed 's/.*=//') parse_evals=$(grep "ratelimit.per_source.per_source" "$STATSFILE" | grep -o "per_source_key_parse_evals=[0-9]*" | tail -1 | sed 's/.*=//') echo "noisy_count: $noisy_count" echo "quiet_count: $quiet_count" echo "submitted_count: $submitted_count" echo "tpl_evals: $tpl_evals" echo "parse_evals: $parse_evals" if [ "$quiet_count" -ne 5 ]; then echo "FAIL: expected 5 quiethost messages, got $quiet_count" error_exit 1 fi if [ "$noisy_count" -ge 20 ]; then echo "FAIL: per-source ratelimit did not drop noisyhost messages" error_exit 1 fi if [ "$noisy_count" -le 0 ]; then echo "FAIL: per-source ratelimit dropped all noisyhost messages" error_exit 1 fi if [ "${submitted_count:-0}" -ne "$content_count" ]; then echo "FAIL: imptcp submitted counter counted per-source-dropped messages" echo "stats content:" cat "$STATSFILE" error_exit 1 fi if [ "${tpl_evals:-0}" -le 0 ]; then echo "FAIL: expected custom per-source template to use tplToString" error_exit 1 fi if [ "${parse_evals:-0}" -le 0 ]; then echo "FAIL: expected custom hostname template to parse messages before evaluation" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/dynfile_invld_async.sh0000644000000000000000000000013115241075234020262 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.605915327 rsyslog-8.2608.0/tests/dynfile_invld_async.sh0000775000175000017500000000371715241075234017742 0ustar00rgerrger#!/bin/bash # This test checks if omfile segfaults when a file open() in dynacache mode fails. # The test is mimiced after a real-life scenario (which, of course, was much more # complex). # # added 2010-03-09 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:3%\n" $template dynfile,"%msg:F,58:2%.log" # complete name is in message $OMFileFlushOnTXEnd on $OMFileAsyncWriting on $DynaFileCacheSize 4 local0.* ?dynfile;outfmt ' startup # we send handcrafted message. We have a dynafile cache of 4, and now send one message # each to fill up the cache. tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3\"" # the next one has caused a segfault in practice # note that /proc/rsyslog.error.file must not be creatable tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom\"" # some more writes tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7\"" # done message generation shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG seq_check 0 7 exit_test rsyslog-8.2608.0/tests/PaxHeaders/operatingstate-empty.sh0000644000000000000000000000013115035412264020423 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.823789435 29 ctime=1787067803.98790381 rsyslog-8.2608.0/tests/operatingstate-empty.sh0000777000175000017500000000135715035412264020103 0ustar00rgerrger#!/bin/bash # added 2018-10-24 by Rainer Gerhards # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(operatingStateFile="'$RSYSLOG_DYNNAME.osf'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # create an unclean file err_osf_content="" printf '%s' "$err_osf_content" > $RSYSLOG_DYNNAME.osf startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! check_file_exists "$RSYSLOG_DYNNAME.osf.previous" check_file_exists "$RSYSLOG_DYNNAME.osf" content_check "this may be an indication of a problem, e.g. empty file" "$RSYSLOG_OUT_LOG" content_check "CLEAN CLOSE" "$RSYSLOG_DYNNAME.osf" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-freshStartTail1.sh0000644000000000000000000000013215035412264020522 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.823789435 30 ctime=1787067807.960977846 rsyslog-8.2608.0/tests/imfile-freshStartTail1.sh0000777000175000017500000000146015035412264020174 0ustar00rgerrger#!/bin/bash # add 2018-05-17 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" freshStartTail="on" Tag="pro" File="'$RSYSLOG_DYNNAME'.input") template(name="outfmt" type="string" string="%msg%\n") :syslogtag, contains, "pro" action(type="omfile" File=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup echo '{ "id": "jinqiao1"}' > $RSYSLOG_DYNNAME.input ./msleep 2000 echo '{ "id": "jinqiao2"}' >> $RSYSLOG_DYNNAME.input shutdown_when_empty wait_shutdown echo '{ "id": "jinqiao1"} { "id": "jinqiao2"}' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-basic-vg.sh0000644000000000000000000000013215216464436021305 xustar0030 mtime=1782212894.068266863 30 atime=1782715518.822789418 30 ctime=1787067807.445968249 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-basic-vg.sh0000775000175000017500000000062515216464436020757 0ustar00rgerrger#!/bin/bash if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi export USE_VALGRIND="YES" RSYSLOG_PRELOAD=$(find /usr -name libmbed\*.so | sed ':start;N;s/\n\//:\//;t start;P;D') export RSYSLOG_PRELOAD . ${srcdir:-.}/imtcp-tls-mbedtls-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_50_ipv6.sh0000644000000000000000000000013015131231047020024 xustar0030 mtime=1768239655.709212663 30 atime=1782715518.822789418 28 ctime=1787067805.7529367 rsyslog-8.2608.0/tests/mmanon_zero_50_ipv6.sh0000777000175000017500000000240715131231047017502 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv6.bits="50" ipv6.anonmode="zero") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0 <129>Mar 10 01:00:00 172.20.245.8 tag: :: <129>Mar 10 01:00:00 172.20.245.8 tag: 0:: <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45: <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\"" shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk ffff:ffff:ffff:ffff:fffc:0:0:0 61:34:ad:0:0:0:0:0 aa:ff43:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 13:abd:45: textnoblank72:8374:adc7:47ff:0:0:0:0stillnoblank' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-lb-2target-retry.sh0000644000000000000000000000013215216464436020470 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.822789418 30 ctime=1787067804.140906662 rsyslog-8.2608.0/tests/omfwd-lb-2target-retry.sh0000775000175000017500000000720215216464436020140 0ustar00rgerrger#!/bin/bash # Verifies that native omfwd load balancing can resume a target that was # unavailable during the first message batch. Phase 1 keeps target 2 bound but # not listening, so all initial messages must go to target 1. Phase 2 releases # target 2, waits until minitcpsrv has actually called listen(), then waits # until the one-second pool retry interval is certainly eligible in omfwd's # whole-second timer model before injecting another full batch. After injection # the test waits for minitcpsrv to accept the retry connection. Before shutdown, # the test waits until both receivers show the expected exact line counts; this # is the oracle that target 2 resumed and the second batch was split evenly # rather than still flowing only to target 1. # Added 2024-02-24 by rgerhards. Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf export NUMMESSAGES=10000 # MUST be an EVEN number! # starting minitcpsrvr receivers so that we can obtain their port # numbers TARGET2_LISTEN_RELEASE="$RSYSLOG_DYNNAME.minitcpsrvr2.listen" TARGET2_LISTEN_READY="$RSYSLOG_DYNNAME.minitcpsrvr2.ready" TARGET2_ACCEPT_READY="$RSYSLOG_DYNNAME.minitcpsrvr2.accepted" rm -f "$TARGET2_LISTEN_RELEASE" rm -f "$TARGET2_LISTEN_READY" rm -f "$TARGET2_ACCEPT_READY" start_minitcpsrvr $RSYSLOG_OUT_LOG 1 start_minitcpsrvr $RSYSLOG2_OUT_LOG 2 "$TARGET2_LISTEN_RELEASE" "$TARGET2_LISTEN_READY" "$TARGET2_ACCEPT_READY" # regular startup add_conf ' $MainMsgQueueTimeoutShutdown 10000 $MainMsgQueueWorkerThreads 2 template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="builtin:omfwd" template="outfmt") if $msg contains "msgnum:" then { action(type="omfwd" target=["127.0.0.1", "127.0.0.1"] port=["'$MINITCPSRVR_PORT1'", "'$MINITCPSRVR_PORT2'"] protocol="tcp" pool.resumeInterval="1" action.resumeRetryCount="-1" action.resumeInterval="5") } ' startup # we need special logic. In a first iteration, the second target is offline # so everything is expected to go the the first target, only. injectmsg # combine both files to check for correct message content #cat "$RSYSLOG_OUT_LOG" "$RSYSLOG2_OUT_LOG" > "$SEQ_CHECK_FILE" wait_queueempty wait_file_lines cp "$RSYSLOG_OUT_LOG" tmp.log seq_check printf "\nSUCCESS for part 1 of the test\n\n" # target2 has held its port bound but not listening since before rsyslog # startup. This keeps phase 1 offline without exposing a get_free_port race. touch "$TARGET2_LISTEN_RELEASE" echo "waiting until the previously suspended pool member is listening" wait_file_exists "$TARGET2_LISTEN_READY" retry_ready_after=$(( $(date +%s) + 2 )) echo "waiting until the target-pool retry interval is eligible" while [ "$(date +%s)" -lt "$retry_ready_after" ]; do $TESTTOOL_DIR/msleep 100 done injectmsg $NUMMESSAGES $NUMMESSAGES echo "waiting until omfwd retries and reconnects the previously suspended pool member" wait_file_exists "$TARGET2_ACCEPT_READY" target2_expected=$(( NUMMESSAGES / 2 )) target1_expected=$(( NUMMESSAGES + target2_expected )) wait_file_lines --abort-on-oversize "$RSYSLOG2_OUT_LOG" "$target2_expected" wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" "$target1_expected" shutdown_when_empty wait_shutdown target2_actual="$(wc -l < "$RSYSLOG2_OUT_LOG")" if [ "$target2_actual" != "$target2_expected" ]; then echo "ERROR: RSYSLOG2_OUT_LOG has invalid number of messages $target2_actual, expected $target2_expected" cat -n $RSYSLOG2_OUT_LOG | head -10 error_exit 100 fi # combine both files to check for correct message content export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.log-combined" export NUMMESSAGES=$((NUMMESSAGES*2)) cat "$RSYSLOG_OUT_LOG" "$RSYSLOG2_OUT_LOG" > "$SEQ_CHECK_FILE" seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/override_epoll_ctl.c0000644000000000000000000000013215216464436017734 xustar0030 mtime=1782212894.080267057 30 atime=1782715518.821789401 30 ctime=1787067803.543895537 rsyslog-8.2608.0/tests/override_epoll_ctl.c0000664000175000017500000000152215216464436017400 0ustar00rgerrger#define _GNU_SOURCE #include "config.h" #include #include #include #include #include typedef int (*epoll_ctl_func_t)(int epfd, int op, int fd, struct epoll_event *event); static epoll_ctl_func_t real_epoll_ctl = NULL; static void __attribute__((constructor)) init_real_epoll_ctl(void) { real_epoll_ctl = (epoll_ctl_func_t)dlsym(RTLD_NEXT, "epoll_ctl"); } int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { const char *const marker = getenv("RSYSLOG_TEST_EPOLL_CTL_FAIL_MARKER"); if (op == EPOLL_CTL_ADD && marker != NULL && marker[0] != '\0' && access(marker, F_OK) == 0) { errno = ENOMEM; return -1; } if (real_epoll_ctl == NULL) { errno = ENOSYS; return -1; } return real_epoll_ctl(epfd, op, fd, event); } rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_str-num-vg.sh0000644000000000000000000000013215171370365021540 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.820789384 30 ctime=1787067805.234927048 rsyslog-8.2608.0/tests/rscript_compare_str-num-vg.sh0000775000175000017500000000017415171370365021211 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"-"' export HIGHER_VAL='1' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-enhanced-validation.sh0000644000000000000000000000013215132733117022630 xustar0030 mtime=1768666703.959621026 30 atime=1782715518.819789367 30 ctime=1787067805.069923973 rsyslog-8.2608.0/tests/mmsnareparse-enhanced-validation.sh0000777000175000017500000001055015132733117022302 0ustar00rgerrger#!/bin/bash ## @file tests/mmsnareparse-enhanced-validation.sh ## @brief Validate enhanced parsing, validation, and stats for mmsnareparse. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmsnareparse/.libs/mmsnareparse") template(name="validation_test_json" type="list" option.jsonf="on") { property(outname="eventid" name="$!win!Event!EventID" format="jsonf") property(outname="validation_errors" name="$!win!Validation!Errors" format="jsonf") property(outname="parsing_stats" name="$!win!Stats!ParsingStats" format="jsonf") property(outname="event_json" name="$!win" format="jsonf") } input(type="imtcp" port="'$TCPFLOOD_PORT'") action(type="mmsnareparse" rootpath="!win" validation_mode="strict" debugjson="on" template="validation_test_json") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="validation_test_json") ' startup tcpflood -m1 -M "\"<14>Jun 10 11:30:45 LAB-LOGON105 MSWinEventLog\t1\tSecurity\t10105\tMon Jun 10 11:30:45 2024\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\tLAB-LOGON105\tLogon\t\tAn account was successfully logged on. Subject: Security ID: SYSTEM Account Name: HOST-007\\$ Account Domain: WORKGROUP Logon ID: 0x3E7 Logon Information: Logon Type: 7 Restricted Admin Mode: - Remote Credential Guard: - Virtual Account: No Elevated Token: No Impersonation Level: Impersonation New Logon: Security ID: CLOUDDOMAIN\\User009 Account Name: user010@example.com Account Domain: CLOUDDOMAIN Logon ID: 0xFD5113F Linked Logon ID: 0xFD5112A Network Account Name: - Network Account Domain: - Logon GUID: {00000000-0000-0000-0000-000000000000} Process Information: Process ID: 0x30c Process Name: C:\\Windows\\System32\\lsass.exe Network Information: Workstation Name: HOST-007 Source Network Address: - Source Port: - Detailed Authentication Information: Logon Process: Negotiat Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0\t1\"" shutdown_when_empty wait_shutdown python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys from pathlib import Path path = Path(sys.argv[1]) data = [] try: for line in path.read_text().splitlines(): line = line.strip() if not line: continue try: data.append(json.loads(line)) except json.JSONDecodeError as exc: raise SystemExit(f"failed to decode JSON line: {line}\n{exc}") except FileNotFoundError as exc: raise SystemExit(f"output log not found: {exc}") event = next((entry for entry in data if entry.get("eventid")), None) if event is None: raise SystemExit("no event record with an eventid was captured") try: stats = json.loads(event["parsing_stats"]) except (KeyError, json.JSONDecodeError) as exc: raise SystemExit(f"unable to parse parsing_stats payload: {exc}") try: errors = json.loads(event["validation_errors"]) except (KeyError, json.JSONDecodeError) as exc: raise SystemExit(f"unable to parse validation_errors payload: {exc}") if event["eventid"] != "4624": raise SystemExit(f"unexpected eventid: {event['eventid']}") if errors != []: raise SystemExit(f"expected no validation errors, got: {errors}") expected_stats = {"total_fields": 25, "successful_parses": 25, "failed_parses": 0} if stats != expected_stats: raise SystemExit(f"unexpected parsing stats: {stats}") try: event_root = json.loads(event["event_json"]) except (KeyError, json.JSONDecodeError) as exc: raise SystemExit(f"unable to parse event_json payload: {exc}") logon = event_root.get("Logon", {}) new_logon = event_root.get("NewLogon", {}) network = event_root.get("Network", {}) auth = event_root.get("Authentication", {}) placeholder_checks = [ (logon, "RemoteCredentialGuard", "Logon"), (new_logon, "NetworkAccountName", "NewLogon"), (new_logon, "NetworkAccountDomain", "NewLogon"), (network, "SourceNetworkAddress", "Network"), (network, "SourcePort", "Network"), (auth, "TransitedServices", "Authentication"), (auth, "PackageName", "Authentication"), ] for container_obj, field_name, container_name in placeholder_checks: if field_name in container_obj: raise SystemExit( f"placeholder field {container_name}.{field_name} should be absent but was present: {container_obj[field_name]}" ) PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/action-tx-errfile.sh0000644000000000000000000000013115216464436017603 xustar0030 mtime=1782212894.045266491 29 atime=1782715518.81878935 30 ctime=1787067805.929939999 rsyslog-8.2608.0/tests/action-tx-errfile.sh0000775000175000017500000000416015216464436017254 0ustar00rgerrger#!/bin/bash # added by Rainer Gerhards 2018-01-05 # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50 # sufficient for our needs! export SEQ_CHECK_OPTIONS=-i2 EXPECTED_ERRFILE="$(cat "${srcdir}/testsuites/action-tx-errfile.result")" || exit 1 export EXPECTED_ERRFILE EXPECTED_ERRFILE_LINES="$(printf '%s\n' "$EXPECTED_ERRFILE" | wc -l)" export EXPECTED_ERRFILE_LINES check_sql_and_errfile_data_ready() { mysql_get_data seq_check --check-only 0 $((NUMMESSAGES - 2)) || return 1 if [ ! -f "$RSYSLOG2_OUT_LOG" ]; then return 1 fi current_errfile_lines=$(wc -l < "$RSYSLOG2_OUT_LOG") if [ "$current_errfile_lines" -ne "$EXPECTED_ERRFILE_LINES" ]; then return 1 fi printf '%s\n' "$EXPECTED_ERRFILE" | cmp - "$RSYSLOG2_OUT_LOG" > /dev/null } export QUEUE_EMPTY_CHECK_FUNC=check_sql_and_errfile_data_ready generate_conf printf '%s\n' \ 'INFO: this test intentionally generates MySQL syntax errors for odd messages.' \ 'INFO: odd messages leave $!facility unset, causing ommysql RS_RET_DATAFAIL -2218.' \ 'INFO: the expected SQL errors must be recorded in action.errorfile.' add_conf ' $ModLoad ../plugins/ommysql/.libs/ommysql global(errormessagestostderr.maxnumber="5") template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on") if((not($msg contains "error")) and ($msg contains "msgnum:")) then { set $.num = field($msg, 58, 2); if $.num % 2 == 0 then { set $!facility = $syslogfacility; } else { # Intentionally leave $!facility unset so this odd message generates # a MySQL syntax error. The test verifies that the failed action is # written to action.errorfile, not that SQL insertion succeeds. set $/cntr = 0; } action(type="ommysql" name="mysql_action" server="127.0.0.1" template="tpl" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'") } ' mysql_prep_for_test startup injectmsg shutdown_when_empty wait_shutdown export EXPECTED="$EXPECTED_ERRFILE" cmp_exact ${RSYSLOG2_OUT_LOG} mysql_get_data seq_check 0 $((NUMMESSAGES - 2)) -i2 exit_test rsyslog-8.2608.0/tests/PaxHeaders/hostname-with-slash-pmrfc3164.sh0000644000000000000000000000013215241075234021562 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.768581346 30 ctime=1787067804.040904798 rsyslog-8.2608.0/tests/hostname-with-slash-pmrfc3164.sh0000775000175000017500000000161315241075234021232 0ustar00rgerrger#!/bin/bash # addd 2016-07-11 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%hostname%\n") parser(name="pmrfc3164.hostname_with_slashes" type="pmrfc3164" permit.slashesinhostname="on") $rulesetparser pmrfc3164.hostname_with_slashes local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup echo '<167>Mar 6 16:57:54 hostname1/hostname2 test: msgnum:0' > $RSYSLOG_DYNNAME.input tcpflood -B -I $RSYSLOG_DYNNAME.input shutdown_when_empty wait_shutdown echo "hostname1/hostname2" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zlib-expansion-guard.sh0000644000000000000000000000013215241075234024203 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067805.572933346 rsyslog-8.2608.0/tests/imtcp-stream-always-zlib-expansion-guard.sh0000775000175000017500000000320015241075234023645 0ustar00rgerrger#!/bin/bash # added 2026-05-19 by Codex, released under ASL 2.0 # Sends a valid but highly expanding zlib stream; the oracle is that imtcp logs # an invalid compressed stream before submitting decompressed messages. . ${srcdir:=.}/diag.sh init require_plugin imtcp check_command_available python3 wait_invalid_stream_log() { content_check --check-only "decompressed bytes exceeded configured expansion ratio" "$RSYSLOG_OUT_LOG" } export QUEUE_EMPTY_CHECK_FUNC=wait_invalid_stream_log generate_conf add_conf ' $MaxMessageSize 10k global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zlib" compression.maxExpansionRatio="2") if $syslogtag contains "rsyslogd" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action(type="omfile" file="'$RSYSLOG2_OUT_LOG'") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" python3 - "$TCPFLOOD_PORT" <<'PY' import socket import sys import zlib port = int(sys.argv[1]) line = b"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" payload = line * 3000 compressed = zlib.compress(payload, level=9) sock = socket.create_connection(("127.0.0.1", port)) sock.sendall(compressed) sock.close() PY shutdown_when_empty wait_shutdown content_check "decompressed bytes exceeded configured expansion ratio" if [ -s "$RSYSLOG2_OUT_LOG" ]; then echo "FAIL: expansion-guarded zlib stream unexpectedly produced messages" cat "$RSYSLOG2_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-wrong-template-option.sh0000644000000000000000000000013215035412264022641 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.817789333 30 ctime=1787067805.806937707 rsyslog-8.2608.0/tests/clickhouse-wrong-template-option.sh0000777000175000017500000000217415035412264022316 0ustar00rgerrger#!/bin/bash # add 2018-12-19 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" type="string" string="INSERT INTO rsyslog.template (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, ' add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" usehttps="off" bulkmode="off" user="default" pwd="" template="outfmt") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.template ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="DROP TABLE rsyslog.template" content_check "you have to specify the SQL or stdSQL option in your template!" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-ruleset-no-queue-warning.sh0000644000000000000000000000013215241075234022234 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.685579792 30 ctime=1787067805.473931501 rsyslog-8.2608.0/tests/imtcp-ruleset-no-queue-warning.sh0000775000175000017500000000330115241075234021700 0ustar00rgerrger#!/bin/bash # Verify issue #1324: an input bound to a ruleset without its own non-direct # queue emits a config warning, while a ruleset with queue.type="LinkedList" # stays warning-free. The oracle is rsyslogd -N1 output, so no listener is # started and no socket readiness timing is involved. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init require_plugin imtcp generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") ruleset(name="shared") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="shared") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.warn.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: expected config validation to continue after ruleset queue warning" cat "${RSYSLOG_DYNNAME}.warn.log" error_exit 1 fi content_check "input-bound ruleset 'shared' has no dedicated non-direct queue" \ "${RSYSLOG_DYNNAME}.warn.log" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") ruleset(name="queued" queue.type="LinkedList") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="queued") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.quiet.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: expected config validation to accept queued ruleset binding" cat "${RSYSLOG_DYNNAME}.quiet.log" error_exit 1 fi check_not_present "input-bound ruleset 'queued' has no dedicated non-direct queue" \ "${RSYSLOG_DYNNAME}.quiet.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omawslogshlc-env.sh0000644000000000000000000000013215241075234017530 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.686579811 30 ctime=1787067806.334947546 rsyslog-8.2608.0/tests/omawslogshlc-env.sh0000775000175000017500000000106215241075234017176 0ustar00rgerrger#!/bin/bash omawslogshlc_require_env() { if [[ -z "${AWS_CWL_BEARER_TOKEN}" ]]; then echo "SKIP: AWS_CWL_BEARER_TOKEN environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AWS_CWL_REGION}" ]]; then echo "SKIP: AWS_CWL_REGION environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AWS_CWL_LOG_GROUP}" ]]; then echo "SKIP: AWS_CWL_LOG_GROUP environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AWS_CWL_LOG_STREAM}" ]]; then echo "SKIP: AWS_CWL_LOG_STREAM environment variable not set - SKIPPING" exit 77 fi } rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-limited-batch.sh0000644000000000000000000000013215035412264021074 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.817789333 30 ctime=1787067805.797937539 rsyslog-8.2608.0/tests/clickhouse-limited-batch.sh0000777000175000017500000000173515035412264020553 0ustar00rgerrger#!/bin/bash # add 2018-12-20 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100000 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.limited (id, ipaddress, message) VALUES (%msg:F,58:2%, ' add_conf "'%fromhost-ip%', '%msg:F,58:2%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" user="default" pwd="" template="outfmt" maxbytes="1k") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.limited ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="SELECT message FROM rsyslog.limited ORDER BY id" > $RSYSLOG_OUT_LOG clickhouse-client --query="DROP TABLE rsyslog.limited" seq_check 0 $(( NUMMESSAGES - 1 )) exit_test rsyslog-8.2608.0/tests/PaxHeaders/discard-allmark.sh0000644000000000000000000000013115241075234017271 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.693916967 rsyslog-8.2608.0/tests/discard-allmark.sh0000775000175000017500000000151215241075234016740 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 echo =============================================================================== echo \[discard-allmark.sh\]: testing discard-allmark functionality . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $ActionWriteAllMarkMessages on :msg, contains, "00000001" ~ $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup tcpflood -m10 -i1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 2 10 exit_test rsyslog-8.2608.0/tests/PaxHeaders/cfg1.cfgtest0000644000000000000000000000013215131231047016077 xustar0030 mtime=1768239655.700212516 30 atime=1782715518.816789316 30 ctime=1787067808.391985877 rsyslog-8.2608.0/tests/cfg1.cfgtest0000666000175000017500000000035215131231047015545 0ustar00rgerrgerrsyslogd: invalid or yet-unknown config file command - have you forgotten to load a module? [try https://www.rsyslog.com/e/3003 ] rsyslogd: the last error occurred in ./cfg1.testin, line 2 rsyslogd: End of config validation run. Bye. rsyslog-8.2608.0/tests/PaxHeaders/killrsyslog.sh0000644000000000000000000000013215216464436016626 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.846789826 30 ctime=1787067808.417986362 rsyslog-8.2608.0/tests/killrsyslog.sh0000775000175000017500000000064715216464436016304 0ustar00rgerrger#!/bin/bash #check if rsyslog instance exists and, if so, kill it if [ -e "rsyslog.pid" ] then echo rsyslog.pid exists, trying to shut down rsyslogd process "$(cat rsyslog.pid)". kill -9 "$(cat rsyslog.pid)" sleep 1 rm rsyslog.pid fi if [ -e "rsyslog2.pid" ] then echo rsyslog2.pid exists, trying to shut down rsyslogd process "$(cat rsyslog2.pid)". kill -9 "$(cat rsyslog2.pid)" sleep 1 rm rsyslog2.pid fi rsyslog-8.2608.0/tests/PaxHeaders/manytcp.sh0000644000000000000000000000013215132733117015713 xustar0030 mtime=1768666703.958621011 30 atime=1782715518.846789826 30 ctime=1787067804.464912699 rsyslog-8.2608.0/tests/manytcp.sh0000777000175000017500000000216415132733117015367 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" skip_platform "SunOS" "timing on connection establishment is different on solaris and makes this test fail" skip_platform "Darwin" "Test fails on MacOS" export NUMMESSAGES=40000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' $MaxOpenFiles 2100 module(load="../plugins/imtcp/.libs/imtcp" maxSessions="2100") input(type="imtcp" name="test-input" socketBacklog="2000" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" workerthreads="8") $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup # we first send a single message so that the output file is opened. Otherwise, we may # use up all file handles for tcp connections and so the output file could eventually # not be opened. 2019-03-18 rgerhards tcpflood -m1 tcpflood -c-2000 -i1 -m $((NUMMESSAGES - 1 )) shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-dockerjson-basic.sh0000644000000000000000000000013215241075234022153 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067808.173981815 rsyslog-8.2608.0/tests/imkubernetes-dockerjson-basic.sh0000775000175000017500000000444115241075234021625 0ustar00rgerrger#!/bin/bash # Verify Docker json-file parsing from a Kubernetes /var/log/containers-style # path with API enrichment disabled. Parsed output metadata is the oracle. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes pwd=$( pwd ) logdir="${RSYSLOG_DYNNAME}.spool/containers" logfile="${logdir}/pod-name2_namespace-name2_container-b-deadbeef.log" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" EnrichKubernetes="off") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="namespace" name="$!kubernetes!namespace_name" format="jsonf") property(outname="pod" name="$!kubernetes!pod_name" format="jsonf") property(outname="container" name="$!kubernetes!container_name" format="jsonf") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="container_id" name="$!docker!container_id" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' mkdir -p "$logdir" startup cat > "$logfile" <<'EOF' {"log":"docker stdout line\n","stream":"stdout","time":"2026-04-20T10:01:00.123456789Z"} {"log":"docker stderr line\n","stream":"stderr","time":"2026-04-20T10:01:01.123456789Z"} EOF wait_file_lines "$RSYSLOG_OUT_LOG" 2 wait_queueempty shutdown_when_empty wait_shutdown $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "docker_json"] assert len(records) == 2, records by_msg = {item["msg"]: item for item in records} stdout = by_msg["docker stdout line"] assert stdout["namespace"] == "namespace-name2" assert stdout["pod"] == "pod-name2" assert stdout["container"] == "container-b" assert stdout["stream"] == "stdout" assert stdout["format"] == "docker_json" assert stdout["container_id"] == "deadbeef" stderr = by_msg["docker stderr line"] assert stderr["stream"] == "stderr" assert stderr["format"] == "docker_json" assert stderr["container_id"] == "deadbeef" PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-msg-truncation-on-number.sh0000644000000000000000000000013215132733117022404 xustar0030 mtime=1768666703.957620996 30 atime=1782715518.846789826 30 ctime=1787067807.175963218 rsyslog-8.2608.0/tests/imptcp-msg-truncation-on-number.sh0000777000175000017500000000276115132733117022063 0ustar00rgerrger#!/bin/bash # addd 2017-03-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "Darwin" "Test fails on MacOS 13, TCP chunking causes false octet-counting detection with sequence 9876543210" generate_conf add_conf ' $MaxMessageSize 128 global(processInternalMessages="on" oversizemsg.input.mode="accept") module(load="../plugins/imptcp/.libs/imptcp") input( type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" maxframesize="128") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncatedtest1 test2 test3 test4 test5 ab 9876543210 cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestetstetstetstetstetsstetstetsytetestetste\"" shutdown_when_empty wait_shutdown grep "Framing Error" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi grep " 9876543210cdefghijklmn test8 test9 test10 test11 test12 test13 test14 test15 kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk tag: testtestets" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message from imptcp truncation not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-cee.sh0000644000000000000000000000013215241075234020742 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.756899506 rsyslog-8.2608.0/tests/segmented-diskqueue-cee.sh0000775000175000017500000000026215241075234020411 0ustar00rgerrger#!/bin/bash # Run the CEE/message-variable action-queue persistence regression unchanged # against segmentedDisk. export QUEUE_TYPE=segmentedDisk . ${srcdir:=.}/cee_diskqueue.sh rsyslog-8.2608.0/tests/PaxHeaders/cfg4.cfgtest0000644000000000000000000000013215035412264016107 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.846789826 30 ctime=1787067808.407986176 rsyslog-8.2608.0/tests/cfg4.cfgtest0000666000175000017500000000005515035412264015555 0ustar00rgerrgerrsyslogd: End of config validation run. Bye. rsyslog-8.2608.0/tests/PaxHeaders/imfifo-vg.sh0000644000000000000000000000013215216464436016133 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.846789826 30 ctime=1787067803.889901984 rsyslog-8.2608.0/tests/imfifo-vg.sh0000775000175000017500000000007715216464436015606 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imfifo.sh rsyslog-8.2608.0/tests/PaxHeaders/imdtls-basic-timeout.sh0000644000000000000000000000013215241075234020277 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.769581365 30 ctime=1787067807.776974417 rsyslog-8.2608.0/tests/imdtls-basic-timeout.sh0000775000175000017500000000373415241075234017755 0ustar00rgerrger#!/bin/bash # added 2023-10-05 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 # Verify that imdtls keeps accepting DTLS traffic across spaced send bursts # within the configured session timeout. Success is the full message sequence. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2000 export SENDESSAGES=500 generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" export TIMEOUT="5" add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imdtls/.libs/imdtls" ) # tls.authmode="anon" ) input( type="imdtls" port="0" listenPortFileName="'$PORT_RCVR_FILE'" timeout="'$TIMEOUT'" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" # valgrind --tool=helgrind $RS_TEST_VALGRIND_EXTRA_OPTS $RS_TESTBENCH_VALGRIND_EXTRA_OPTS --log-fd=1 --error-exitcode=10 tcpflood -b1 -W1000 -p"$PORT_RCVR" -m"$SENDESSAGES" -Tdtls -x"$srcdir/tls-certs/ca.pem" -Z"$srcdir/tls-certs/cert.pem" -z"$srcdir/tls-certs/key.pem" -L0 # ./msleep 500 tcpflood -b1 -W1000 -i500 -p"$PORT_RCVR" -m"$SENDESSAGES" -Tdtls -x"$srcdir/tls-certs/ca.pem" -Z"$srcdir/tls-certs/cert.pem" -z"$srcdir/tls-certs/key.pem" -L0 tcpflood -b1 -W1000 -i1000 -p"$PORT_RCVR" -m"$SENDESSAGES" -Tdtls -x"$srcdir/tls-certs/ca.pem" -Z"$srcdir/tls-certs/cert.pem" -z"$srcdir/tls-certs/key.pem" -L0 tcpflood -b1 -W1000 -i1500 -p"$PORT_RCVR" -m"$SENDESSAGES" -Tdtls -x"$srcdir/tls-certs/ca.pem" -Z"$srcdir/tls-certs/cert.pem" -z"$srcdir/tls-certs/key.pem" -L0 wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl-internalmsg_severity-info-shown.sh0000644000000000000000000000013215035412264023517 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.845789809 30 ctime=1787067804.072905394 rsyslog-8.2608.0/tests/glbl-internalmsg_severity-info-shown.sh0000777000175000017500000000111415035412264023165 0ustar00rgerrger#!/bin/bash # check that info-severity messages are actually emitted; we use # lookup table as a simple sample to get such a message. # addd 2019-05-07 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(internalmsg.severity="info") lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup shutdown_when_empty wait_shutdown content_check "lookup table 'xlate' loaded from file" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zstd-expansion-guard.sh0000644000000000000000000000013115241075234024226 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.774581459 30 ctime=1787067805.596933793 rsyslog-8.2608.0/tests/imtcp-stream-always-zstd-expansion-guard.sh0000775000175000017500000000364315241075234023704 0ustar00rgerrger#!/bin/bash # added 2026-05-19 by Codex, released under ASL 2.0 # Sends a valid but highly expanding zstd stream; the oracle is that imtcp logs # an invalid compressed stream before submitting decompressed messages. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime check_command_available python3 check_command_available zstd wait_invalid_stream_log() { content_check --check-only "decompressed bytes exceeded configured expansion ratio" "$RSYSLOG_OUT_LOG" } export QUEUE_EMPTY_CHECK_FUNC=wait_invalid_stream_log generate_conf add_conf ' $MaxMessageSize 10k global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zstd" compression.maxExpansionRatio="2") if $syslogtag contains "rsyslogd" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action(type="omfile" file="'$RSYSLOG2_OUT_LOG'") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" python3 - "$RSYSLOG_DYNNAME.rawmsg" <<'PY' import sys path = sys.argv[1] line = b"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" with open(path, "wb") as stream: stream.write(line * 3000) PY zstd -q -19 -c "$RSYSLOG_DYNNAME.rawmsg" > "$RSYSLOG_DYNNAME.zst" python3 - "$TCPFLOOD_PORT" "$RSYSLOG_DYNNAME.zst" <<'PY' import socket import sys port = int(sys.argv[1]) path = sys.argv[2] with open(path, "rb") as stream: payload = stream.read() sock = socket.create_connection(("127.0.0.1", port)) sock.sendall(payload) sock.close() PY shutdown_when_empty wait_shutdown content_check "decompressed bytes exceeded configured expansion ratio" if [ -s "$RSYSLOG2_OUT_LOG" ]; then echo "FAIL: expansion-guarded zstd stream unexpectedly produced messages" cat "$RSYSLOG2_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-find-json-invalid.sh0000644000000000000000000000013115216464436022116 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.845789809 30 ctime=1787067807.149962733 rsyslog-8.2608.0/tests/mmjsonparse-find-json-invalid.sh0000775000175000017500000000225515216464436021572 0ustar00rgerrger#!/bin/bash # Test mmjsonparse find-json mode with invalid JSON # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmjsonparse/.libs/mmjsonparse") template(name="outfmt" type="string" string="%msg% parsesuccess=%parsesuccess% json=%$!%\n") # Test invalid JSON if $msg contains "INVALID" then { action(type="mmjsonparse" mode="find-json") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") stop } # Test no JSON present if $msg contains "NOJSON" then { action(type="mmjsonparse" mode="find-json") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") stop } ' startup injectmsg_literal '<167>Jan 16 16:57:54 host.example.net TAG: INVALID prefix {invalid json' injectmsg_literal '<167>Jan 16 16:57:54 host.example.net TAG: NOJSON just plain text without any json' shutdown_when_empty wait_shutdown export EXPECTED=' INVALID prefix {invalid json parsesuccess=FAIL json={ "msg": " INVALID prefix {invalid json" } NOJSON just plain text without any json parsesuccess=FAIL json={ "msg": " NOJSON just plain text without any json" }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_8_ipv4.sh0000644000000000000000000000013215241075234017755 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.730936291 rsyslog-8.2608.0/tests/mmanon_zero_8_ipv4.sh0000775000175000017500000000154715241075234017433 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.bits="8") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255 <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\"" shutdown_when_empty wait_shutdown export EXPECTED=' 1.1.1.0 0.0.0.0 172.0.234.0 111.1.1.0.' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/ratelimit-policy-persource-mixed-invalid.sh0000644000000000000000000000013215241075234024264 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.789581739 30 ctime=1787067805.636934539 rsyslog-8.2608.0/tests/ratelimit-policy-persource-mixed-invalid.sh0000775000175000017500000000250215241075234023732 0ustar00rgerrger#!/bin/bash ## Regression test for ambiguous per-source ratelimit configuration. ## A policy YAML file that contains a perSource section is the canonical ## source of per-source settings; mixing it with legacy perSourcePolicy or ## perSourceKeyTpl on the same ratelimit object must fail at config load. . ${srcdir:=.}/diag.sh init if [ -z "$RSYSLOGD" ]; then export RSYSLOGD=../tools/rsyslogd fi POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" STDERR_FILE="${RSYSLOG_DYNNAME}.stderr.log" export POLICY_FILE cat > "$POLICY_FILE" < /dev/null 2> "$STDERR_FILE" if grep -q "do not mix it with legacy perSource/perSourcePolicy/perSourceKeyTpl/maxStates/topN parameters" "$STDERR_FILE"; then exit_test fi echo "FAIL: mixed canonical and legacy per-source ratelimit config was not rejected as expected" cat "$STDERR_FILE" error_exit 1 rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-scope-main.sh0000644000000000000000000000013215241075234022241 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.767899711 rsyslog-8.2608.0/tests/segmented-diskqueue-scope-main.sh0000775000175000017500000000030015241075234021701 0ustar00rgerrger#!/bin/bash # segmentedDisk wrapper for the backend-neutral main-queue scope driver. export QUEUE_TYPE=segmentedDisk QUEUE_SCOPE=main . ${srcdir:=.}/testsuites/pure-disk-queue-scope-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-lokirest-retry-vg.sh0000644000000000000000000000013115171370365022245 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.844789792 30 ctime=1787067806.188944825 rsyslog-8.2608.0/tests/omhttp-batch-lokirest-retry-vg.sh0000775000175000017500000000012515171370365021713 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-redis-start-after.sh0000644000000000000000000000013215131231047021545 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.844789792 30 ctime=1787067806.546951496 rsyslog-8.2608.0/tests/imhiredis-redis-start-after.sh0000777000175000017500000000217715131231047021225 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init # Start redis once to be able to generate configuration start_redis stop_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mykey" mode="queue" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup start_redis redis_command "RPUSH mykey message1" redis_command "RPUSH mykey message2" redis_command "RPUSH mykey message3" wait_content '1 message3' shutdown_when_empty wait_shutdown stop_redis content_check '1 message3' content_check '2 message2' content_check '3 message1' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-basic-errfile-empty.sh0000644000000000000000000000013215132733117020510 xustar0030 mtime=1768666703.955620965 30 atime=1782715518.843789775 30 ctime=1787067803.928902711 rsyslog-8.2608.0/tests/es-basic-errfile-empty.sh0000777000175000017500000000171715132733117020167 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_PORT=19200 export NUMMESSAGES=1500 # slow test, thus low number - large number is NOT necessary export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check ensure_elasticsearch_ready init_elasticsearch generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") :msg, contains, "msgnum:" action(type="omelasticsearch" template="tpl" serverport=`echo $ES_PORT` searchIndex="rsyslog_testbench" errorFile="./'${RSYSLOG_DYNNAME}.errorfile'") ' startup injectmsg shutdown_when_empty wait_shutdown es_getdata if [ -f ${RSYSLOG_DYNNAME}.errorfile ] then echo "error: error file exists!" error_exit 1 fi seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/global-maxopenfiles-rainerscript.sh0000644000000000000000000000013215216464436022703 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.842789758 30 ctime=1787067804.563914544 rsyslog-8.2608.0/tests/global-maxopenfiles-rainerscript.sh0000775000175000017500000000121115216464436022345 0ustar00rgerrger#!/bin/bash # Validate the modern global(maxOpenFiles=...) setting. The test starts # rsyslogd so it exercises both the RainerScript global-parameter backend and # the activation-time setrlimit path. The oracle is a clean startup/shutdown # using the current shell soft limit, which should be accepted without needing # extra privileges. . ${srcdir:=.}/diag.sh init max_open_files="$(ulimit -n)" if [ "${max_open_files}" = "unlimited" ]; then max_open_files=4096 fi generate_conf add_conf ' global(maxOpenFiles="'${max_open_files}'") action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out") ' startup shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-mmnormalize-debug.sh0000644000000000000000000000013215241075234020616 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067807.104961894 rsyslog-8.2608.0/tests/yaml-mmnormalize-debug.sh0000775000175000017500000000251215241075234020265 0ustar00rgerrger#!/bin/bash # Verify that YAML passes mmnormalize's debug parameters and directs liblognorm # trace output to its configured file. A non-empty trace file is the oracle. . ${srcdir:=.}/diag.sh init require_plugin mmnormalize DEBUG_LOG="${RSYSLOG_DYNNAME}.yaml-mmnormalize-debug.log" generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"' add_yaml_conf ' - load: "../plugins/mmnormalize/.libs/mmnormalize"' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imtcp' add_yaml_conf ' port: "0"' add_yaml_conf ' listenPortFileName: "'$RSYSLOG_DYNNAME'.tcpflood_port"' add_yaml_conf ' ruleset: normalize' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: normalize' add_yaml_conf ' statements:' add_yaml_conf ' - type: mmnormalize' add_yaml_conf ' useRawMsg: on' add_yaml_conf ' debug: on' add_yaml_conf ' debugFile: "'$DEBUG_LOG'"' add_yaml_conf ' rule: "rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%"' add_yaml_conf ' - type: omfile' add_yaml_conf ' file: "'$RSYSLOG_OUT_LOG'"' startup tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\"" shutdown_when_empty wait_shutdown if [ ! -s "$DEBUG_LOG" ]; then echo "expected liblognorm trace output in $DEBUG_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-endmsg.regex-with-example.sh0000644000000000000000000000013215216464436022503 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.840789724 30 ctime=1787067808.060979709 rsyslog-8.2608.0/tests/imfile-endmsg.regex-with-example.sh0000775000175000017500000001227715216464436022163 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # This test verifies imfile endmsg.regex message assembly for CRI-O and JSON # container log fragments, including metadata and normalized multiline output. # The oracle is six completed output records: two completed records from each # input in the first batch, then one multiline record from each input after the # final terminator arrives. The trailing partial records must remain buffered. . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify # The final multiline record can be delayed heavily when the full test suite # runs at extreme concurrency. This timeout bounds that wait while preserving # the exact six-record oracle below. export IMFILECHECKTIMEOUT="180" export IMFILELASTINPUTLINES="6" mkdir $RSYSLOG_DYNNAME.statefiles generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile" statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.*.input" Tag="file:" addMetadata="on" escapelf="off" endmsg.regex="(^[^ ]+ (stdout|stderr) F )|(\\n\"}$)") if $msg startswith "{" then { action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.json.rulebase'") foreach ($.ii in $!multilinejson) do { if strlen($!@timestamp) == 0 then { set $!@timestamp = $.ii!time; } if strlen($!stream) == 0 then { set $!stream = $.ii!stream; } if strlen($!log) == 0 then { set $!log = $.ii!log; } else { reset $!log = $!log & $.ii!log; } } unset $!multilinejson; } else { action(type="mmnormalize" rulebase="'$srcdir/imfile-endmsg.regex.crio.rulebase'") foreach ($.ii in $!multilinecrio) do { if strlen($!@timestamp) == 0 then { set $!@timestamp = $.ii!time; } if strlen($!stream) == 0 then { set $!stream = $.ii!stream; } if strlen($!log) == 0 then { set $!log = $.ii!log; } else { reset $!log = $!log & $.ii!log; } } unset $!multilinecrio; } template(name="outfmt" type="list") { property(name="$!all-json-plain") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' if [ "${USE_VALGRIND:-false}" == "true" ] ; then startup_vg else startup fi if [ -n "${USE_GDB:-}" ] ; then echo attach gdb here sleep 54321 || : fi # write the beginning of the file echo 'date stdout P msgnum:0' > $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:0"}' > $RSYSLOG_DYNNAME.json.input echo 'date stdout F msgnum:1' >> $RSYSLOG_DYNNAME.crio.input printf '%s\n' '{"time":"date", "stream":"stdout", "log":"msgnum:1\n"}' >> $RSYSLOG_DYNNAME.json.input echo 'date stdout F msgnum:2' >> $RSYSLOG_DYNNAME.crio.input printf '%s\n' '{"time":"date", "stream":"stdout", "log":"msgnum:2\n"}' >> $RSYSLOG_DYNNAME.json.input if [ -n "${USE_GDB:-}" ] ; then sleep 54321 || : fi wait_file_lines $RSYSLOG_OUT_LOG 4 $IMFILECHECKTIMEOUT echo 'date stdout P msgnum:3' >> $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:3"}' >> $RSYSLOG_DYNNAME.json.input echo 'date stdout P msgnum:4' >> $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:4"}' >> $RSYSLOG_DYNNAME.json.input echo 'date stdout P msgnum:5' >> $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:5"}' >> $RSYSLOG_DYNNAME.json.input if [ -n "${USE_GDB:-}" ] ; then sleep 54321 || : fi # The second batch is intentionally incomplete. Drain the queue before appending # the terminators so the test checks imfile's cross-append multiline state # instead of depending on a fixed sleep under load. wait_queueempty echo 'date stdout F msgnum:6' >> $RSYSLOG_DYNNAME.crio.input printf '%s\n' '{"time":"date", "stream":"stdout", "log":"msgnum:6\n"}' >> $RSYSLOG_DYNNAME.json.input echo 'date stdout P msgnum:7' >> $RSYSLOG_DYNNAME.crio.input echo '{"time":"date", "stream":"stdout", "log":"msgnum:7"}' >> $RSYSLOG_DYNNAME.json.input wait_file_lines $RSYSLOG_OUT_LOG $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT shutdown_when_empty # shut down rsyslogd when done processing messages if [ "${USE_VALGRIND:-false}" == "true" ] ; then wait_shutdown_vg check_exit_vg else wait_shutdown # we need to wait until rsyslogd is finished! fi ## check if we have the correct number of messages NUMLINES=$(wc -l $RSYSLOG_OUT_LOG | awk '{print $1}' 2>/dev/null) rc=0 if [ ! $NUMLINES -eq $IMFILELASTINPUTLINES ]; then echo "ERROR: expecting $IMFILELASTINPUTLINES lines, got $NUMLINES" rc=1 fi ## check if all the data we expect to get in the file is there for string in "metadata.*filename.*json[.]input.*msgnum:0msgnum:1" \ "metadata.*filename.*crio[.]input.*msgnum:0msgnum:1" \ "metadata.*filename.*json[.]input.*msgnum:2" \ "metadata.*filename.*crio[.]input.*msgnum:2" \ "metadata.*filename.*json[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" \ "metadata.*filename.*crio[.]input.*msgnum:3msgnum:4msgnum:5msgnum:6" ; do if grep "$string" $RSYSLOG_OUT_LOG > /dev/null 2>&1 ; then : # ok else echo "Error: the expected string '$string' not found" rc=1 fi done if [ $rc -ne 0 ]; then cat $RSYSLOG_OUT_LOG exit 1 fi ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-endregex-timeout-polling.sh0000644000000000000000000000013215216464436022442 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.839789707 30 ctime=1787067807.916977026 rsyslog-8.2608.0/tests/imfile-endregex-timeout-polling.sh0000775000175000017500000000313115216464436022107 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init if [ $(uname) = "SunOS" ] ; then echo "Solaris: FIX ME" exit 77 fi mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile" mode="polling" pollingInterval="2" ) input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" PersistStateInterval="1" readTimeout="2" startmsg.regex="^[^ ]") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # we need to sleep a bit between writes to give imfile a chance # to pick up the data (IN MULTIPLE ITERATIONS!) echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input ./msleep 10000 echo ' msgnum:2 msgnum:3' >> $RSYSLOG_DYNNAME.input # the next line terminates our test. It is NOT written to the output file, # as imfile waits whether or not there is a follow-up line that it needs # to combine. echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input ./msleep 2000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! printf '%s\n' 'HEADER msgnum:0\\n msgnum:1 HEADER msgnum:2\\n msgnum:3' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-persist-state-1.sh0000644000000000000000000000013215035412264020447 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.837789673 30 ctime=1787067807.958977808 rsyslog-8.2608.0/tests/imfile-persist-state-1.sh0000777000175000017500000000147215035412264020124 0ustar00rgerrger#!/bin/bash # added 2016-11-02 by rgerhards # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input( type="imfile" file="./'$RSYSLOG_DYNNAME'.input" tag="file:" startmsg.regex="^msgnum" PersistStateInterval="1" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' # generate input file first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). ./inputfilegen -m5 -d4000 > $RSYSLOG_DYNNAME.input startup shutdown_when_empty wait_shutdown seq_check 0 3 exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_prog_confirm.sh0000644000000000000000000000013215216464436020311 xustar0030 mtime=1782212894.058266701 30 atime=1782715518.832789588 30 ctime=1787067806.013941564 rsyslog-8.2608.0/tests/improg_prog_confirm.sh0000775000175000017500000000140115216464436017754 0ustar00rgerrger#!/bin/bash # add 2019-04-04 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/improg/.libs/improg") input(type="improg" tag="tag" ruleset="ruleset" binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -c -n 1" confirmmessages="on" signalonclose="off" killunresponsive="on" ) ruleset(name="ruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup wait_content "program data" "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "program data" if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then echo $RSYSLOG_DYNNAME'.stderr missing' error_exit 1 fi export EXPECTED='START Received ACK Received STOP Received' cmp_exact $RSYSLOG_DYNNAME.stderr exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-errfile-maxsize-filled.sh0000644000000000000000000000013215131231047021707 xustar0030 mtime=1768239655.711212696 30 atime=1782715518.832789588 30 ctime=1787067804.166907146 rsyslog-8.2608.0/tests/omfwd-errfile-maxsize-filled.sh0000777000175000017500000000113115131231047021354 0ustar00rgerrger#!/bin/bash # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ERRFILE="$RSYSLOG_DYNNAME.err" export MAX_ERROR_SIZE=1999 export INITIAL_FILE_SIZE=$((MAX_ERROR_SIZE - 100)) dd if=/dev/urandom of=${ERRFILE} bs=1 count=${INITIAL_FILE_SIZE} generate_conf add_conf ' action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist" action.errorfile="'$ERRFILE'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'") ' startup shutdown_when_empty wait_shutdown check_file_exists ${ERRFILE} file_size_check ${ERRFILE} ${MAX_ERROR_SIZE} exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_gzip.sh0000644000000000000000000000013115241075234016567 xustar0030 mtime=1787067036.643579006 29 atime=1787067036.79658187 30 ctime=1787067804.475912904 rsyslog-8.2608.0/tests/sndrcv_gzip.sh0000775000175000017500000000242615241075234016243 0ustar00rgerrger#!/bin/bash # This test is similar to tcpsndrcv, but it forwards messages in # zlib-compressed format (our own syslog extension). # rgerhards, 2009-11-11 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' *.* @@(z5)127.0.0.1:'$RCVR_PORT' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize-debug.sh0000644000000000000000000000013215241075234017656 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.686579811 30 ctime=1787067807.102961857 rsyslog-8.2608.0/tests/mmnormalize-debug.sh0000775000175000017500000000177015241075234017332 0ustar00rgerrger#!/bin/bash # Verify that mmnormalize directs enabled liblognorm tracing to its configured # file. A non-empty trace file after a normalized message is the success oracle. . ${srcdir:=.}/diag.sh init require_plugin mmnormalize DEBUG_LOG="${RSYSLOG_DYNNAME}.mmnormalize-debug.log" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="normalize") ruleset(name="normalize") { action(type="mmnormalize" useRawMsg="on" debug="on" debugFile="'$DEBUG_LOG'" rule="rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\"" shutdown_when_empty wait_shutdown if [ ! -s "$DEBUG_LOG" ]; then echo "expected liblognorm trace output in $DEBUG_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-wildcards-dirs.sh0000644000000000000000000000013215216464436020426 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.831789571 30 ctime=1787067807.972978069 rsyslog-8.2608.0/tests/imfile-wildcards-dirs.sh0000775000175000017500000000342315216464436020077 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init export IMFILEINPUTFILES="10" export IMFILECHECKTIMEOUT="60" mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' /* Filter out busy debug output, comment out if needed */ global( debug.whitelist="off" debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"] ) global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module( load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*/*.logfile" Tag="file:" Severity="error" Facility="local7" addMetadata="on" ) template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value=", ") property(name="$!metadata!filename") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' # generate input files first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). # Start rsyslog now before adding more files startup for i in $(seq 1 $IMFILEINPUTFILES); do mkdir $RSYSLOG_DYNNAME.input.dir$i ./inputfilegen -m 1 -i $((i - 1)) > $RSYSLOG_DYNNAME.input.dir$i/file.tmp mv $RSYSLOG_DYNNAME.input.dir$i/file.tmp $RSYSLOG_DYNNAME.input.dir$i/file.logfile done ls -d $RSYSLOG_DYNNAME.input.* # Content check with timeout content_check_with_count "HEADER msgnum:" $IMFILEINPUTFILES $IMFILECHECKTIMEOUT for i in $(seq 1 $IMFILEINPUTFILES); do rm -rf $RSYSLOG_DYNNAME.input.dir$i/ done shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! exit_test rsyslog-8.2608.0/tests/PaxHeaders/now-utc-casecmp.sh0000644000000000000000000000013215241075234017245 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 30 ctime=1787067805.832938191 rsyslog-8.2608.0/tests/now-utc-casecmp.sh0000775000175000017500000000213415241075234016714 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # addd 2016-02-23 by RGerhards, released under ASL 2.0 # requires faketime echo \[now-utc-casecmp\]: test \$year-utc, \$month-utc, \$day-utc . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST-02:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$Now%:%$Year%-%$Month%-%$Day%,%$Now-utc%:%$Year-utc%-%$Month-utc%-%$Day-utc%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' FAKETIME='2016-01-01 01:00:00' startup # what we send actually is irrelevant, as we just use system properties. # but we need to send one message in order to gain output! tcpflood -m1 shutdown_when_empty wait_shutdown echo "2016-01-01:2016-01-01,2015-12-31:2015-12-31" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid timestamps generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error-exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omkafka-failedmsg-malformed.sh0000644000000000000000000000013215216464436021556 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.831789571 30 ctime=1787067806.225945515 rsyslog-8.2608.0/tests/omkafka-failedmsg-malformed.sh0000775000175000017500000000220415216464436021223 0ustar00rgerrger#!/usr/bin/env bash # Regression coverage for GitHub issue #4452's restart-crash class. omkafka # must ignore malformed persisted failed-message records instead of # dereferencing a missing tab separator while loading replay state. . ${srcdir:=.}/diag.sh init require_plugin omkafka failed_msg_file="${RSYSLOG_DYNNAME}.failedmsg" printf 'malformed persisted failed message without separators\n' > "$failed_msg_file" generate_conf add_conf ' module(load="../plugins/omkafka/.libs/omkafka") template(name="outfmt" type="string" string="%msg%\n") action(type="omkafka" topic="unreachable" broker="127.0.0.1:9" template="outfmt" resubmitOnFailure="on" keepFailedMessages="on" failedMsgFile="'$failed_msg_file'" action.resumeRetryCount="0") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 rc=$? if [ "$rc" -eq 139 ]; then echo "FAIL: omkafka crashed while loading malformed failed-message state" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi content_check "omkafka: loadFailedMsgs droping invalid msg found" "${RSYSLOG_DYNNAME}.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/complex1.sh0000644000000000000000000000013215216464436016000 xustar0030 mtime=1782212894.047266524 30 atime=1782715518.830789554 30 ctime=1787067804.613915476 rsyslog-8.2608.0/tests/complex1.sh0000775000175000017500000001027215216464436015451 0ustar00rgerrger#!/bin/bash # This is a rather complex test that runs a number of features together. # # added 2010-03-16 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on all flavors of Solaris." export NUMMESSAGES=40000 generate_conf add_conf ' $MaxMessageSize 10k $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 $template outfmt,"%msg:F,58:3%,%msg:F,58:4%,%msg:F,58:5%\n" $template dynfile,"'$RSYSLOG_DYNNAME'.out.%inputname%.%msg:F,58:2%.log.Z" ## RULESET with listener $Ruleset R13514 # queue params: $ActionQueueTimeoutShutdown 60000 $ActionQueueTimeoutEnqueue 20000 $ActionQueueSize 5000 $ActionQueueSaveOnShutdown on $ActionQueueHighWaterMark 4900 $ActionQueueLowWaterMark 3500 $ActionQueueType FixedArray $ActionQueueWorkerThreads 1 # action params: $OMFileFlushOnTXEnd off $OMFileZipLevel 6 $DynaFileCacheSize 4 $omfileFlushInterval 1 *.* ?dynfile;outfmt action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile") # listener $InputTCPServerInputName R13514 $InputTCPServerBindRuleset R13514 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port $InputTCPServerRun 0 ## RULESET with listener $Ruleset R_PORT2 # queue params: $ActionQueueTimeoutShutdown 60000 $ActionQueueTimeoutEnqueue 20000 $ActionQueueSize 5000 $ActionQueueSaveOnShutdown on $ActionQueueHighWaterMark 4900 $ActionQueueLowWaterMark 3500 $ActionQueueType FixedArray $ActionQueueWorkerThreads 1 # action params: $OMFileFlushOnTXEnd off $OMFileZipLevel 6 $OMFileIOBufferSize 256k $DynaFileCacheSize 4 $omfileFlushInterval 1 *.* ?dynfile;outfmt action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile") # listener $InputTCPServerInputName R_PORT2 $InputTCPServerBindRuleset R_PORT2 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port2 $InputTCPServerRun 0 ## RULESET with listener $Ruleset R_PORT3 # queue params: $ActionQueueTimeoutShutdown 60000 $ActionQueueTimeoutEnqueue 20000 $ActionQueueSize 5000 $ActionQueueSaveOnShutdown on $ActionQueueHighWaterMark 4900 $ActionQueueLowWaterMark 3500 $ActionQueueType FixedArray $ActionQueueWorkerThreads 1 # action params: $OMFileFlushOnTXEnd off $OMFileZipLevel 6 $OMFileIOBufferSize 256k $DynaFileCacheSize 4 $omfileFlushInterval 1 *.* ?dynfile;outfmt action(type="omfile" file ="'$RSYSLOG_DYNNAME'.countfile") # listener $InputTCPServerInputName R_PORT3 $InputTCPServerBindRuleset R_PORT3 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port3 $InputTCPServerRun 0 ' count_function() { # TODO: try to make this work on the compressed files, only # idea does not work as we miss end-of-zip record # leaving it commented out if we see we should really switch to that # method; if we do not need for an extended period of time, this shall # be removed -- rgerhards, 2018-12-19 #mkdir "$RSYSLOG_DYNNAME.countwrk" #cp $RSYSLOG_DYNNAME.out.*.log.Z "$RSYSLOG_DYNNAME.countwrk" #cd "$RSYSLOG_DYNNAME.countwrk" #gunzip $RSYSLOG_DYNNAME.out.*.log.Z #printf '%d' $(cat $RSYSLOG_DYNNAME.out.*.log | wc -l) #cd .. #rm -rf "$RSYSLOG_DYNNAME.countwrk" # now the real - simple - code: printf '%d' $(wc -l < $RSYSLOG_DYNNAME.countfile) } startup assign_file_content TCPFLOOD_PORT "$RSYSLOG_DYNNAME.tcpflood_port" assign_file_content RSYSLOG_PORT2 "$RSYSLOG_DYNNAME.tcpflood_port2" assign_file_content RSYSLOG_PORT3 "$RSYSLOG_DYNNAME.tcpflood_port3" echo ports: $TCPFLOOD_PORT $RSYSLOG_PORT2 $RSYSLOG_PORT3 # send 40,000 messages of 400 bytes plus header max, via three dest ports export TCPFLOOD_PORT="$TCPFLOOD_PORT:$RSYSLOG_PORT2:$RSYSLOG_PORT3" tcpflood -m$NUMMESSAGES -rd400 -P129 -f5 -n3 -c15 -i1 # note: we have FlushOnTX=off, so we will not see the last block inside the file; # as such we wait until a "sufficiently large" number of messages has arrived and # hope that shutdown_when_empty gets us toward the rest. It's still a bit racy, # but should be better than without the wait_file_lines. wait_file_lines --delay 1000 --count-function count_function DUMMY-filename $((NUMMESSAGES - 1500)) shutdown_when_empty wait_shutdown ls $RSYSLOG_DYNNAME.out.*.log.Z gunzip $RSYSLOG_DYNNAME.out.*.log.Z cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG seq_check 1 $NUMMESSAGES -E exit_test rsyslog-8.2608.0/tests/PaxHeaders/uxsockrcvr.c0000644000000000000000000000013215216464436016271 xustar0030 mtime=1782212894.092267251 30 atime=1782715518.829789537 30 ctime=1787067803.639897326 rsyslog-8.2608.0/tests/uxsockrcvr.c0000664000175000017500000002201515216464436015735 0ustar00rgerrger/* receives messages from a specified unix sockets and writes * output to specfied file. * * Command line options: * -s name of socket (required) * -o name of output file (stdout if not given) * -l add newline after each message received (default: do not add anything) * -r file to write the receiver ready generation after bind/listen * -t timeout in seconds (default 60) * * Part of the testbench for rsyslog. * * Copyright 2010 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include #include #include #include #include #include #if defined(_AIX) #include #include #include #include #else #include #endif #include #include #include #include #if defined(__FreeBSD__) #include #endif #define DFLT_TIMEOUT 60 char *sockName = NULL; int sockType = SOCK_DGRAM; int sockConnected = 0; int addNL = 0; int abstract; #define MAX_FDS 4 int sockBacklog = MAX_FDS - 1; struct pollfd fds[MAX_FDS]; int nfds; volatile int need_reset; static const char *readyFile; static unsigned int readyGeneration; /* called to clean up on exit */ void cleanup(void) { int index; /* * This function is called from a signal handler. Ensure any * called functions are async-signal-safe as per * signal-safety(7). close and unlink are safe. */ if (!abstract) unlink(sockName); for (index = 0; index < nfds; ++index) { close(fds[index].fd); fds[index].fd = -1; } nfds = 0; } void doTerm(int __attribute__((unused)) signum) { exit(1); } void doReset(int __attribute__((unused)) signum) { need_reset = 1; } void usage(void) { fprintf(stderr, "usage: uxsockrcvr -s /socket/name -o /output/file -l\n" "-l adds newline after each message received\n" "-s MUST be specified\n" "-a Use abstract socket name\n" "-r file to write receiver ready generation after bind/listen\n" "-T {DGRAM|STREAM" #ifdef SOCK_SEQPACKET "|SEQPACKET" #endif /* def SOCK_SEQPACKET */ "} Set socket type (default DGRAM)\n" "if -o ist not specified, stdout is used\n"); exit(1); } static void signal_ready(void) { FILE *fp; if (readyFile == NULL) return; if ((fp = fopen(readyFile, "w")) == NULL) { perror(readyFile); exit(1); } fprintf(fp, "%u\n", ++readyGeneration); fclose(fp); } static struct { const char *id; int val; int connected; } _sockType_map[] = { {"DGRAM", SOCK_DGRAM, 0}, {"STREAM", SOCK_STREAM, 1}, #ifdef SOCK_SEQPACKET {"SEQPACKET", SOCK_SEQPACKET, 1}, #endif /* def SOCK_SEQPACKET */ {NULL, 0, 0}, }; static void _decode_sockType(const char *s) { int index; for (index = 0; _sockType_map[index].id; ++index) { if (!strcasecmp(s, _sockType_map[index].id)) { sockType = _sockType_map[index].val; sockConnected = _sockType_map[index].connected; return; } } fprintf(stderr, "?Illegal socket type '%s'. Valid socket types:\n", s); for (index = 0; _sockType_map[index].id; ++index) { fprintf(stderr, " %s\n", _sockType_map[index].id); } exit(1); } void initialize_socket(void) { struct sockaddr_un addr; /* address of server */ /* Create a UNIX datagram socket for server */ if ((fds[0].fd = socket(AF_UNIX, sockType, 0)) < 0) { perror("server: socket"); exit(1); } /* Set up address structure for server socket */ memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; const size_t sockname_len = strlen(sockName); /* Require non-abstract addresses to be terminated. */ if (sockname_len >= (sizeof(addr.sun_path) - 1)) { fprintf(stderr, "error: socket path would be truncated\n"); exit(1); } memcpy(addr.sun_path + abstract, sockName, sockname_len); /* * Abstract socket addresses do not require termination. */ if (!abstract && addr.sun_path[sizeof(addr.sun_path) - 1]) { addr.sun_path[sizeof(addr.sun_path) - 1] = 0; } /* * For pathname addresses, the +1 is the terminating \0 character. * For abstract addresses, the +1 is the leading \0 character. * Technically, Linux doesn't care about that terminating \0 for * pathname addresses. */ if (bind(fds[0].fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + sockname_len + 1) < 0) { perror("server: bind"); close(fds[0].fd); exit(1); } if (sockConnected && listen(fds[0].fd, sockBacklog) == -1) { perror("server: listen"); close(fds[0].fd); exit(1); } fds[0].events = POLLIN; nfds = 1; signal_ready(); } int main(int argc, char *argv[]) { int opt; int rlen; int timeout = DFLT_TIMEOUT; FILE *fp = stdout; unsigned char data[128 * 1024]; struct sockaddr from; socklen_t fromlen; int index; if (argc < 2) { fprintf(stderr, "error: too few arguments!\n"); usage(); } while ((opt = getopt(argc, argv, "as:o:lr:t:T:")) != EOF) { switch ((char)opt) { case 'a': abstract = 1; break; case 'l': addNL = 1; break; case 's': sockName = optarg; break; case 'o': if ((fp = fopen(optarg, "w")) == NULL) { perror(optarg); exit(1); } break; case 'r': readyFile = optarg; break; case 't': timeout = atoi(optarg); break; case 'T': _decode_sockType(optarg); break; default: usage(); } } timeout = timeout * 1000; if (sockName == NULL) { fprintf(stderr, "error: -s /socket/name must be specified!\n"); exit(1); } if (signal(SIGTERM, doTerm) == SIG_ERR) { perror("signal(SIGTERM, ...)"); exit(1); } if (signal(SIGINT, doTerm) == SIG_ERR) { perror("signal(SIGINT, ...)"); exit(1); } if (signal(SIGHUP, doReset) == SIG_ERR) { perror("signal(SIGHUP, ...)"); exit(1); } for (index = 0; index < MAX_FDS; ++index) { fds[index].fd = -1; } atexit(cleanup); /* we now run in an endless loop. We do not check who sends us * data. This should be no problem for our testbench use. */ while (1) { if (need_reset) { need_reset = 0; cleanup(); } if (!nfds) { initialize_socket(); } rlen = poll(fds, nfds, timeout); if (rlen == -1) { if (errno == EINTR) { continue; } perror("uxsockrcvr : poll\n"); exit(1); } else if (rlen == 0) { fprintf(stderr, "Socket timed out - nothing to receive\n"); exit(1); } if (sockConnected && fds[0].revents & POLLIN) { fds[nfds].fd = accept(fds[0].fd, NULL, NULL); fds[nfds].events = POLLIN; fds[nfds].revents = 0; if (fds[nfds].fd < 0) { perror("accept"); } else if (++nfds == MAX_FDS) { fds[0].events = 0; } } for (index = sockConnected; index < nfds; ++index) { if (fds[index].revents & POLLIN) { fromlen = sizeof(from); rlen = recvfrom(fds[index].fd, data, 2000, 0, &from, &fromlen); if (rlen == -1) { perror("uxsockrcvr : recv\n"); exit(1); } else { fwrite(data, 1, rlen, fp); if (addNL) fputc('\n', fp); } } if (fds[index].revents & POLLHUP) { close(fds[index].fd); fds[index].fd = -1; fds[index].events = 0; } } while (nfds && fds[nfds - 1].fd < 0) { --nfds; } } return 0; } rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_str-num.sh0000644000000000000000000000013215171370365021126 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.829789537 30 ctime=1787067804.841919725 rsyslog-8.2608.0/tests/rscript_compare_str-num.sh0000775000175000017500000000014215171370365020572 0ustar00rgerrger#!/bin/bash export LOWER_VAL='"-"' export HIGHER_VAL='1' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_is_time.sh0000644000000000000000000000013215241075234017437 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067804.876920377 rsyslog-8.2608.0/tests/rscript_is_time.sh0000775000175000017500000000740015241075234017107 0ustar00rgerrger#!/bin/bash # Added 2017-12-16 by Stephen Workman, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omstdout/.libs/omstdout") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # $DebugLevel 2 set $!result!date_auto_1 = is_time("Oct 5 01:10:11"); set $!result!errno_date_auto_1 = script_error(); set $!result!date_auto_2 = is_time("2017-10-05T01:10:11Z"); set $!result!errno_date_auto_2 = script_error(); set $!result!date_auto_3 = is_time("2017-10-05T01:10:11-03:00"); set $!result!errno_date_auto_3 = script_error(); set $!result!date_auto_4 = is_time("90210"); set $!result!errno_date_auto_4 = script_error(); set $!result!date_explicit_1 = is_time("Oct 5 01:10:11", "date-rfc3164"); set $!result!errno_date_explicit_1 = script_error(); set $!result!date_explicit_2 = is_time("2017-10-05T01:10:11Z", "date-rfc3339"); set $!result!errno_date_explicit_2 = script_error(); set $!result!date_explicit_3 = is_time("2017-10-05T01:10:11+04:00", "date-rfc3339"); set $!result!errno_date_explicit_3 = script_error(); set $!result!date_explicit_4 = is_time(90210, "date-unix"); set $!result!errno_date_explicit_4 = script_error(); set $!result!date_explicit_5 = is_time(-88, "date-unix"); set $!result!errno_date_explicit_5 = script_error(); set $!result!date_explicit_6 = is_time(0, "date-unix"); set $!result!errno_date_explicit_6 = script_error(); set $!result!date_explicit_7 = is_time("90210", "date-unix"); set $!result!errno_date_explicit_7 = script_error(); set $!result!date_explicit_8 = is_time("-88", "date-unix"); set $!result!errno_date_explicit_8 = script_error(); # Bad dates set $!result!date_fail_1 = is_time("Oct 88 01:10:11"); set $!result!errno_date_fail_1 = script_error(); set $!result!date_fail_2 = is_time("not at all a date"); set $!result!errno_date_fail_2 = script_error(); # Wrong format set $!result!date_fail_3 = is_time("Oct 5 01:10:11", "date-rfc3339"); set $!result!errno_date_fail_3 = script_error(); set $!result!date_fail_4 = is_time("2017-10-05T01:10:11Z", "date-rfc3164"); set $!result!errno_date_fail_4 = script_error(); set $!result!date_fail_5 = is_time("Oct 5 01:10:11", "date-unix"); set $!result!errno_date_fail_5 = script_error(); # Invalid format set $!result!date_fail_6 = is_time("90210", "date-spoonix"); set $!result!errno_date_fail_6 = script_error(); template(name="outfmt" type="string" string="%!result%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") local4.* :omstdout:;outfmt ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown # Our fixed and calculated expected results export EXPECTED='{ "date_auto_1": 1, "errno_date_auto_1": 0, "date_auto_2": 1, "errno_date_auto_2": 0, "date_auto_3": 1, "errno_date_auto_3": 0, "date_auto_4": 1, "errno_date_auto_4": 0, "date_explicit_1": 1, "errno_date_explicit_1": 0, "date_explicit_2": 1, "errno_date_explicit_2": 0, "date_explicit_3": 1, "errno_date_explicit_3": 0, "date_explicit_4": 1, "errno_date_explicit_4": 0, "date_explicit_5": 1, "errno_date_explicit_5": 0, "date_explicit_6": 1, "errno_date_explicit_6": 0, "date_explicit_7": 1, "errno_date_explicit_7": 0, "date_explicit_8": 1, "errno_date_explicit_8": 0, "date_fail_1": 0, "errno_date_fail_1": 1, "date_fail_2": 0, "errno_date_fail_2": 1, "date_fail_3": 0, "errno_date_fail_3": 1, "date_fail_4": 0, "errno_date_fail_4": 1, "date_fail_5": 0, "errno_date_fail_5": 1, "date_fail_6": 0, "errno_date_fail_6": 1 }' # FreeBSD's cmp does not support reading from STDIN cmp <(echo "$EXPECTED") $RSYSLOG_OUT_LOG if [[ $? -ne 0 ]]; then printf "Invalid function output detected!\n" printf "Expected: $EXPECTED\n" printf "Got: " cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_non_object.sh0000644000000000000000000000012715241075234022212 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 27 ctime=1787067806.895958 rsyslog-8.2608.0/tests/rscript_unflatten_non_object.sh0000775000175000017500000000171315241075234021657 0ustar00rgerrger#!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $/cpt = $/cpt + 1; if ($/cpt == 1) then set $! = "string"; else set $! = 42; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m 2 wait_file_lines "$RSYSLOG_OUT_LOG" 2 60 shutdown_when_empty wait_shutdown EXPECTED=' msgnum:00000000: 0 string msgnum:00000001: 0 42' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-endregex-timeout-with-shutdown-polling.sh0000644000000000000000000000013215131231047025246 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.860790064 30 ctime=1787067807.926977212 rsyslog-8.2608.0/tests/imfile-endregex-timeout-with-shutdown-polling.sh0000777000175000017500000000324415131231047024722 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init export IMFILECHECKTIMEOUT="60" mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile" mode="polling" pollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" PersistStateInterval="1" readTimeout="3" startmsg.regex="^[^ ]") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # we need to sleep a bit between writes to give imfile a chance # to pick up the data (IN MULTIPLE ITERATIONS!) echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input content_check_with_count 'msgnum:0 msgnum:1' 1 $IMFILECHECKTIMEOUT echo ' msgnum:2 msgnum:3' >> $RSYSLOG_DYNNAME.input # we now do a stop and restart of rsyslog. This checks that everything # works across restarts. shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! #echo DROPPING YOU TO BASH! #bash startup # new data echo ' msgnum:4' >> $RSYSLOG_DYNNAME.input content_check_with_count 'msgnum:2 msgnum:3 msgnum:4' 1 $IMFILECHECKTIMEOUT echo ' msgnum:5 msgnum:6' >> $RSYSLOG_DYNNAME.input content_check_with_count 'msgnum:5 msgnum:6' 1 $IMFILECHECKTIMEOUT shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-pos-from-to-oversize.sh0000644000000000000000000000013215241075234022077 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.799581927 30 ctime=1787067804.274909159 rsyslog-8.2608.0/tests/template-pos-from-to-oversize.sh0000775000175000017500000000272115241075234021550 0ustar00rgerrger#!/bin/bash # addd 2016-03-28 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init echo "*** string template ****" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="-%msg:109:116:%-\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 shutdown_when_empty wait_shutdown echo "--" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid output generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG echo "expected was:" echo "--" exit 1 fi; echo "*** list template ****" rm $RSYSLOG_OUT_LOG # cleanup previous run generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="list") { constant(value="-") property(name="msg" position.from="109" position.to="116") constant(value="-") constant(value="\n") } :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 shutdown_when_empty wait_shutdown echo "--" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid output generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG echo "expected was:" echo "--" exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omelasticsearch-bulk-metadata-escape.sh0000644000000000000000000000013215241075234023355 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.686579811 30 ctime=1787067804.502913408 rsyslog-8.2608.0/tests/omelasticsearch-bulk-metadata-escape.sh0000775000175000017500000001054615241075234023032 0ustar00rgerrger#!/bin/bash # Regression test for omelasticsearch bulk metadata JSON escaping. Dynamic # metadata templates can be derived from remote message content; the oracle is # the captured _bulk request body from a local HTTP endpoint. The first bulk # metadata line must remain valid JSON and preserve attacker-shaped quotes as # data inside _index, _type, _parent, and _id values. The local capture # server writes its dynamic port before rsyslog starts and is killed by trap. . ${srcdir:=.}/diag.sh init require_plugin omelasticsearch if ! command -v python3 >/dev/null 2>&1; then printf 'SKIP: python3 is required for local omelasticsearch capture server\n' skip_test fi cat > "$RSYSLOG_DYNNAME.capture-es.py" <<'PY' import http.server import json import pathlib import socketserver import sys base = pathlib.Path(sys.argv[1]) class Handler(http.server.BaseHTTPRequestHandler): protocol_version = 'HTTP/1.1' def do_GET(self): data = json.dumps({ 'version': { 'number': '8.0.0', 'distribution': 'elasticsearch', 'build_flavor': 'default', }, 'tagline': 'You Know, for Search', }).encode() self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(data))) self.end_headers() self.wfile.write(data) def do_POST(self): length = int(self.headers.get('Content-Length', '0')) body = self.rfile.read(length) (base.with_suffix('.bulk.path')).write_text(self.path) (base.with_suffix('.bulk.body')).write_bytes(body) data = b'{"errors":false,"items":[{"index":{"status":201}}]}' self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(data))) self.end_headers() self.wfile.write(data) def log_message(self, fmt, *args): return with socketserver.TCPServer(('127.0.0.1', 0), Handler) as httpd: base.with_suffix('.capture.port').write_text(str(httpd.server_address[1])) httpd.serve_forever() PY python3 "$RSYSLOG_DYNNAME.capture-es.py" "$RSYSLOG_DYNNAME" & capture_pid=$! cleanup_capture() { kill "$capture_pid" 2>/dev/null || true wait "$capture_pid" 2>/dev/null || true } trap cleanup_capture EXIT wait_file_exists "$RSYSLOG_DYNNAME.capture.port" 10 capture_port=$(cat "$RSYSLOG_DYNNAME.capture.port") generate_conf add_conf ' module(load="../plugins/omelasticsearch/.libs/omelasticsearch") template(name="msgTpl" type="string" string="{\"msg\":\"%msg:::json%\"}") template(name="idxTpl" type="string" string="rsyslog-%msg%") template(name="typeTpl" type="string" string="type-%msg%") template(name="parentTpl" type="string" string="parent-%msg%") template(name="idTpl" type="string" string="id-%msg%") if $msg contains "bad" then { action(type="omelasticsearch" server="127.0.0.1" serverport="'$capture_port'" bulkmode="on" dynSearchIndex="on" searchIndex="idxTpl" dynSearchType="on" searchType="typeTpl" dynParent="on" parent="parentTpl" dynbulkid="on" bulkid="idTpl" template="msgTpl" esversion.major="7" action.resumeRetryCount="0" action.resumeInterval="1") } ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z host testprog - - - bad"quote\slash' shutdown_when_empty wait_shutdown wait_file_exists "$RSYSLOG_DYNNAME.bulk.body" 10 python3 - "$RSYSLOG_DYNNAME.bulk.path" "$RSYSLOG_DYNNAME.bulk.body" <<'PY' import json import sys from pathlib import Path path = Path(sys.argv[1]).read_text() body = Path(sys.argv[2]).read_text() lines = body.splitlines() if path != '/_bulk': raise SystemExit('unexpected bulk path: ' + path) if len(lines) != 2: raise SystemExit('unexpected bulk body line count: ' + repr(lines)) metadata = json.loads(lines[0]) document = json.loads(lines[1]) index = metadata['index'] expected = r'bad"quote\slash' expected_values = { '_index': 'rsyslog-' + expected, '_type': 'type-' + expected, '_parent': 'parent-' + expected, '_id': 'id-' + expected, } if index != expected_values: raise SystemExit('unexpected escaped metadata: ' + repr(index)) if document != {'msg': expected}: raise SystemExit('unexpected escaped document: ' + repr(document)) PY if [ $? -ne 0 ]; then error_exit 1 fi exit_testrsyslog-8.2608.0/tests/PaxHeaders/imfile-fileNotFoundError-parameter.sh0000644000000000000000000000013215035412264023066 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.859790047 30 ctime=1787067807.885976448 rsyslog-8.2608.0/tests/imfile-fileNotFoundError-parameter.sh0000777000175000017500000000131315035412264022535 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 echo [imfile-file-not-found-error.sh] . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="testsuites/NotExistingInputFile" Tag="tag1" fileNotFoundError="off") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup shutdown_when_empty wait_shutdown grep "error*file*NotExistingInputFile*No such file or directory" $RSYSLOG_OUT_LOG > /dev/null if [ $? -eq 0 ]; then echo echo "FAIL: error message from missing input file found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-prioritize-san-cn-fallback.sh0000644000000000000000000000013215241075234024242 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.685579792 30 ctime=1787067807.475968808 rsyslog-8.2608.0/tests/imtcp-tls-ossl-prioritize-san-cn-fallback.sh0000775000175000017500000000243015241075234023710 0ustar00rgerrger#!/bin/bash # Verify the legacy OpenSSL x509/name behavior for certificates that contain a # DNS SAN and a different CN. With PrioritizeSAN left at its default off value, # rsyslog may authorize the peer by the CN after the SAN does not match. The # oracle is exact receipt of the tcpflood sequence after the listener reports # its kernel-assigned port. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer="rsyslog-client" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh0000644000000000000000000000013215241075234023573 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067807.372966888 rsyslog-8.2608.0/tests/imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh0000775000175000017500000000360215241075234023243 0ustar00rgerrger#!/bin/bash # This test checks imtcp functionality with multiple drivers running together. It is # a minimal test. # added 2021-04-27 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=60000 # must be evenly dividable by 3 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" name="i1" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" name="i2" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2" assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3" tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 3)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3)) tcpflood -p$RS_PORT -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3 * 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-suspended-no-early-commit.sh0000644000000000000000000000013115216464436022365 xustar0030 mtime=1782212894.077267008 29 atime=1782715518.85879003 30 ctime=1787067804.148906811 rsyslog-8.2608.0/tests/omfwd-suspended-no-early-commit.sh0000775000175000017500000000272515216464436022043 0ustar00rgerrger#!/bin/bash # Regression coverage for GitHub issue #5132. A transactional action that has # exhausted its immediate resume attempts must not call the module commit hook # again while its next retry timestamp is still in the future. The oracle is # the action/omfwd debug log: we wait until actionTryCommit reports that it # skipped transaction processing for the suspended action, then assert that no # commitTransaction call entered while the action state was still "susp". # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' global( debug.whitelist="on" debug.files=["action.c", "../action.c", "../../runtime/action.c", "../../../runtime/action.c", "omfwd.c"] ) template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( name="forwarder" type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp" template="outfmt" queue.type="LinkedList" queue.dequeueBatchSize="1" action.resumeInterval="1" action.resumeIntervalMax="2" action.resumeRetryCount="0" ) } ' startup injectmsg 0 1 wait_content "actionTryCommit\\[forwarder\\]: skip transaction while state is susp" "$RSYSLOG_DEBUGLOG" shutdown_immediate wait_shutdown check_not_present "entering actionCallCommitTransaction[forwarder], state: susp" "$RSYSLOG_DEBUGLOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-checkpoint-0.sh0000644000000000000000000000013215241075234022472 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.778899916 rsyslog-8.2608.0/tests/segmented-diskqueue-checkpoint-0.sh0000775000175000017500000000033015241075234022135 0ustar00rgerrger#!/bin/bash # Verify checkpointInterval=0 performs no completion-driven state writes. export CHECKPOINT_INTERVAL=0 export EXPECTED_PERIODIC_WRITES=0 . ${srcdir:=.}/testsuites/segmented-diskqueue-checkpoint-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/yaml-filter-actions.sh0000644000000000000000000000013215241075234020123 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.801581964 30 ctime=1787067805.382929806 rsyslog-8.2608.0/tests/yaml-filter-actions.sh0000775000175000017500000000247415241075234017601 0ustar00rgerrger#!/bin/bash # Tests the YAML Phase 2 structured filter+actions shortcut: # - filter: "*.* " (PRI filter) with a single action # - filter: ":msg, contains, ..." (property filter) with multiple actions # - actions: without a filter (unconditional routing) # # The test sends 50 messages tagged with "msgnum:"; all 50 should appear in # the unconditional omfile output. Messages NOT containing "missing" should # still pass the property filter (negation is not tested here). # # Added 2025 by contributors, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=50 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << YAMLEOF modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" rulesets: - name: main filter: "*.*" actions: - type: omfile template: outfmt file: "${RSYSLOG_OUT_LOG}" YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-startup-bounded.sh0000644000000000000000000000013215241075234023326 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.852901295 rsyslog-8.2608.0/tests/segmented-diskqueue-startup-bounded.sh0000775000175000017500000000045315241075234022777 0ustar00rgerrger#!/bin/bash # Run restart recovery with impstats assertions proving startup reads no payload # and probes only the bounded current/reserved segment paths. # This file is part of the rsyslog project, released under ASL 2.0. export CHECK_STARTUP_STATS=on . ${srcdir:=.}/segmented-diskqueue-restart.sh rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_anon_rebind.sh0000644000000000000000000000013115241075234020756 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.292965398 rsyslog-8.2608.0/tests/sndrcv_tls_anon_rebind.sh0000775000175000017500000000417015241075234020430 0ustar00rgerrger#!/bin/bash # testing sending and receiving via TLS with anon auth and rebind # rgerhards, 2011-04-04 # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "Test fails with environment-induced errors, which we cannot solve" export NUMMESSAGES=25000 #25000 # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="gtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port") $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon $ActionSendTCPRebindInterval 50 *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 $NUMMESSAGES # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/omruleset-queue.sh0000644000000000000000000000013215131231047017373 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.856789996 30 ctime=1787067807.818975199 rsyslog-8.2608.0/tests/omruleset-queue.sh0000777000175000017500000000272615131231047017053 0ustar00rgerrger#!/bin/bash # test for omruleset. What we do is have the main queue forward # all messages to a secondary ruleset via omruleset, which then does # the actual file write. We check if all messages arrive at the file, # what implies that omruleset works. No filters or special queue modes # are used, but the ruleset uses its own queue. So we can also inject # more messages without running into troubles. # added 2009-11-02 by rgerhards # This file is part of the rsyslog project, released under GPLv3 echo =============================================================================== echo \[omruleset-queue.sh\]: test for omruleset functionality with a ruleset queue uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init export NUMMESSAGES=20000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' $ModLoad ../plugins/omruleset/.libs/omruleset $ruleset rsinclude # create ruleset main queue with default parameters $RulesetCreateMainQueue on # make sure we do not terminate too early! $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt $ruleset RSYSLOG_DefaultRuleset $ActionOmrulesetRulesetName rsinclude *.* :omruleset: ' startup injectmsg echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize-turbo-message-lifecycle.sh0000644000000000000000000000013115241075234023301 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.686579811 29 ctime=1787067807.10796195 rsyslog-8.2608.0/tests/mmnormalize-turbo-message-lifecycle.sh0000775000175000017500000000244515241075234022756 0ustar00rgerrger#!/bin/bash # Verify that turbo mmnormalize CEE fields survive both MsgDup() through a # queued ruleset and disk-queue serialization. The output files are the # oracle: each must contain the normalized field after synchronized shutdown. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin mmnormalize generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME'.spool") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="normalize") template(name="outfmt" type="string" string="%$!host% %$!tag%\n") ruleset(name="copy" queue.type="LinkedList") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ruleset(name="normalize") { action(type="mmnormalize" useRawMsg="on" turbo="on" rule="rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%") call copy action(type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="outfmt" queue.type="disk" queue.filename="turbo-lifecycle") } ' startup tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\"" shutdown_when_empty wait_shutdown export EXPECTED='ubuntu tag1' cmp_exact "$RSYSLOG_OUT_LOG" cmp_exact "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_privdropgroup.sh0000644000000000000000000000013215131231047020722 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.856789996 30 ctime=1787067804.224908227 rsyslog-8.2608.0/tests/rscript_privdropgroup.sh0000777000175000017500000000120015131231047020364 0ustar00rgerrger#!/bin/bash # added 2021-09-23 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.group.keepsupplemental="on" privdrop.group.name="'${TESTBENCH_TESTUSER[groupname]}'") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-template-subtree.sh0000644000000000000000000000013215241075234020462 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.803582002 30 ctime=1787067805.415930421 rsyslog-8.2608.0/tests/yaml-template-subtree.sh0000775000175000017500000000366415241075234020142 0ustar00rgerrger#!/bin/bash # Tests YAML subtree template: a template of type=subtree produces a JSON # rendering of the specified message-variable subtree. # # The config sets two fields on $!usr, then applies a subtree template # pointing at $!usr. The output is valid JSON containing both fields. # This verifies that the YAML "type: subtree" + "subtree:" parameters # are wired through to tplProcessCnf() correctly. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: # String template used only for seq_check - name: seqfmt type: string string: "%msg:F,58:2%\n" # Subtree template: renders $!usr as JSON - name: jsontree type: subtree subtree: "$!usr" rulesets: - name: main script: | if $msg contains "msgnum:" then { set $!usr!msgnum = field($msg, 58, 2); set $!usr!host = $hostname; action(type="omfile" template="seqfmt" file="${RSYSLOG_OUT_LOG}") action(type="omfile" template="jsontree" file="${RSYSLOG_DYNNAME}.json") } YAMLEOF sed -i \ -e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \ -e "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" \ "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check # Each JSON line must contain "msgnum" and "host" keys if ! grep -q '"msgnum"' "${RSYSLOG_DYNNAME}.json"; then echo "FAIL: expected 'msgnum' key in subtree JSON output" exit 1 fi if ! grep -q '"host"' "${RSYSLOG_DYNNAME}.json"; then echo "FAIL: expected 'host' key in subtree JSON output" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_exists-yes.sh0000644000000000000000000000013215131231047020115 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.854789962 30 ctime=1787067804.892920675 rsyslog-8.2608.0/tests/rscript_exists-yes.sh0000777000175000017500000000075415131231047017574 0ustar00rgerrger#!/bin/bash # add 2020-10-02 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%!result%\n") set $!p1!p2!val="yes!"; if $msg contains "msgnum" then { if exists($!p1!p2!val) then set $!result = "on"; else set $!result = "off"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='on' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript-config_enable-off-vg.sh0000644000000000000000000000013215035412264021660 xustar0030 mtime=1752569012.409688211 30 atime=1782715518.854789962 30 ctime=1787067805.173925911 rsyslog-8.2608.0/tests/rscript-config_enable-off-vg.sh0000777000175000017500000000100615035412264021326 0ustar00rgerrger#!/bin/bash # added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init export DO_STOP=off generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { if $msg contains "msgnum:00000000" then { include(text="stop" config.enabled=`echo $DO_STOP`) } action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg seq_check 0 9 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-persource-port-keys.sh0000644000000000000000000000013215241075234021314 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.685579792 30 ctime=1787067805.652934837 rsyslog-8.2608.0/tests/imtcp-persource-port-keys.sh0000775000175000017500000000023715241075234020765 0ustar00rgerrger#!/bin/bash ## Run the shared exact port-key ratelimit test through imtcp. export PORT_KEY_MODULE=imtcp . ${srcdir:=.}/ratelimit-persource-port-keys-common.sh rsyslog-8.2608.0/tests/PaxHeaders/yaml-statements-reload-lookup.sh0000644000000000000000000000013215171370365022147 xustar0030 mtime=1776677109.474913588 30 atime=1782715518.853789945 30 ctime=1787067805.420930514 rsyslog-8.2608.0/tests/yaml-statements-reload-lookup.sh0000775000175000017500000000363415171370365021624 0ustar00rgerrger#!/bin/bash # Tests reload_lookup_table: statement in a YAML statements: block. # # A lookup table is loaded via lookup_tables: and a statements: block # uses reload_lookup_table: conditional on a specific message. This # exercises the YAML → RainerScript code path for the statement, verifying # the positional arguments ("table"[, "stub_value"]) are emitted correctly. # # Messages are injected via imdiag (injectmsg) and routed to the YAML # "main" ruleset via a "call main" statement added to the default ruleset # in the .conf preamble. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") # Route imdiag-injected messages from DefaultRuleset into main call main ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' lookup_tables: - name: xlate file: "${RSYSLOG_DYNNAME}.xlate.lkp_tbl" templates: - name: outfmt type: string string: "- %msg% %$.lkp%\n" rulesets: - name: main statements: - set: var: "$.lkp" expr: 'lookup("xlate", $msg)' - if: '$msg contains "msgnum:00000002:"' then: - reload_lookup_table: table: xlate stub_value: reload_failed - type: omfile file: "${RSYSLOG_OUT_LOG}" template: outfmt YAMLEOF sed -i \ -e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \ -e "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" \ "${RSYSLOG_DYNNAME}.yaml" cp -f "$srcdir/testsuites/xlate.lkp_tbl" "${RSYSLOG_DYNNAME}.xlate.lkp_tbl" startup # Put updated table in place; message 2 will trigger reload cp -f "$srcdir/testsuites/xlate_more.lkp_tbl" "${RSYSLOG_DYNNAME}.xlate.lkp_tbl" injectmsg 0 3 await_lookup_table_reload wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmdb-container-empty.sh0000644000000000000000000000013215035412264020272 xustar0030 mtime=1752569012.400750748 30 atime=1782715518.850789894 30 ctime=1787067807.256964727 rsyslog-8.2608.0/tests/mmdb-container-empty.sh0000777000175000017500000000154215035412264017745 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$!src_geoip%\n") module(load="../plugins/mmdblookup/.libs/mmdblookup" container="!") module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmnormalize" rulebase=`echo $srcdir/mmdb.rb`) action(type="mmdblookup" mmdbfile=`echo $srcdir/test.mmdb` key="$!ip" fields=":src_geoip!city_name:city" ) action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m 1 -j "202.106.0.20\ " shutdown_when_empty wait_shutdown content_check '{ "city_name": "Beijing" }' exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_domain_without_tld_vg.sh0000644000000000000000000000013215171370365023417 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.850789894 30 ctime=1787067806.989959752 rsyslog-8.2608.0/tests/rscript_faup_domain_without_tld_vg.sh0000775000175000017500000000022315171370365023063 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_domain_without_tld.sh rsyslog-8.2608.0/tests/PaxHeaders/rs-cnum.sh0000644000000000000000000000013115241075234015623 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 29 ctime=1787067804.92592129 rsyslog-8.2608.0/tests/rs-cnum.sh0000775000175000017500000000136015241075234015273 0ustar00rgerrger#!/bin/bash # add 2018-04-04 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!var = cnum(15*3); template(name="outfmt" type="string" string="-%$!var%-\n") :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" shutdown_when_empty wait_shutdown echo '-45-' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/execonlywhenprevsuspended.sh0000644000000000000000000000013115035412264021556 xustar0029 mtime=1752569012.38883413 30 atime=1782715518.849789877 30 ctime=1787067804.622915644 rsyslog-8.2608.0/tests/execonlywhenprevsuspended.sh0000777000175000017500000000163315035412264021233 0ustar00rgerrger#!/bin/bash # we test the execonly if previous is suspended directive. This is the # most basic test which solely tests a single case but no dependencies within # the ruleset. # rgerhards, 2010-06-23 echo ===================================================================================== echo \[execonlywhenprevsuspended.sh\]: test execonly...suspended functionality simple case . ${srcdir:=.}/diag.sh init generate_conf add_conf ' main_queue(queue.workerthreads="1") # omtesting provides the ability to cause "SUSPENDED" action state $ModLoad ../plugins/omtesting/.libs/omtesting $MainMsgQueueTimeoutShutdown 100000 $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" :omtesting:fail 2 0 $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"';outfmt ' startup injectmsg 0 1000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 1 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/gzipwr_flushInterval.sh0000644000000000000000000000013215241075234020470 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.767581328 30 ctime=1787067804.595915141 rsyslog-8.2608.0/tests/gzipwr_flushInterval.sh0000775000175000017500000000170015241075234020135 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" export NUMMESSAGES=5000 #even number! export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.gz generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" zipLevel="6" ioBufferSize="256k" flushOnTXEnd="off" flushInterval="1" asyncWriting="on" file="'$RSYSLOG_OUT_LOG'.gz") ' startup tcpflood -m$((NUMMESSAGES / 2)) -P129 ./msleep 5000 #wait for flush seq_check 0 2499 tcpflood -i$((NUMMESSAGES / 2)) -m$((NUMMESSAGES / 2)) -P129 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-action-duplicate-name.sh0000644000000000000000000000013115216464436021352 xustar0030 mtime=1782212894.092267251 29 atime=1782715518.84878986 30 ctime=1787067805.425930607 rsyslog-8.2608.0/tests/yaml-action-duplicate-name.sh0000775000175000017500000000242715216464436021027 0ustar00rgerrger#!/bin/bash # Verify that duplicate YAML action names warn through the shared action # backend. The oracle is successful -N1 config validation plus duplicate-name # diagnostic; no runtime message-processing output is involved. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' templates: - name: outfmt type: string string: "%msg%\n" rulesets: - name: main filter: "*.*" actions: - name: dup_action type: omfile file: "${RSYSLOG_OUT_LOG}.1" template: outfmt - name: dup_action type: omfile file: "${RSYSLOG_OUT_LOG}.2" template: outfmt YAMLEOF sed -i \ -e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \ "${RSYSLOG_DYNNAME}.yaml" ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: expected YAML config validation to continue after duplicate action-name warning" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi content_check "action: duplicate name 'dup_action' in current config set; impstats counters may be ambiguous" \ "${RSYSLOG_DYNNAME}.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/ffmpcre-basic.sh0000644000000000000000000000013215241075234016741 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067807.011960162 rsyslog-8.2608.0/tests/ffmpcre-basic.sh0000775000175000017500000000144415241075234016413 0ustar00rgerrger#!/bin/bash # added 2025-06-07 by Codex, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/fmpcre/.libs/fmpcre") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$.hit%\n") set $.hit = pcre_match($msg, "h.llo"); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -M "\"<13>Jan 1 00:00:00 host tag: hello\"" tcpflood -m1 -M "\"<13>Jan 1 00:00:00 host tag: hallo\"" shutdown_when_empty wait_shutdown echo '1 1' | cmp - $RSYSLOG_OUT_LOG if [ $? -ne 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-stream-auto-legacy-single.sh0000644000000000000000000000013215241075234022514 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.684579773 30 ctime=1787067806.841956993 rsyslog-8.2608.0/tests/imptcp-stream-auto-legacy-single.sh0000775000175000017500000000226515241075234022170 0ustar00rgerrger#!/bin/bash # Backward compatibility test for imptcp compression.mode="stream:auto" when # the session is plain TCP carrying omfwd's legacy "@@(zN)" single-message # compression. AUTO must first check the zlib stream header; if the connection # is classified as plain, built-in legacy-z transport-frame decompression must # remain enabled. The oracle is complete, ordered delivery of legacy-compressed # messages. # # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:auto") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' *.* @@(z5)127.0.0.1:'$RCVR_PORT' ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/json_object_looping.sh0000644000000000000000000000013215216464436020276 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.847789843 30 ctime=1787067807.198963646 rsyslog-8.2608.0/tests/json_object_looping.sh0000775000175000017500000000630715216464436017753 0ustar00rgerrger#!/bin/bash # added 2016-03-31 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[json_object_looping.sh\]: basic test for looping over json object / associative-array . ${srcdir:=.}/diag.sh init # ARM ASan can abort inside libsanitizer quarantine during worker-thread startup # before rsyslog emits a useful ASan report. Keep this scoped to ARM+ASan so # x86 ASan and non-ASan ARM lanes continue to cover the foreach behavior. skip_ARM_ASAN "libsanitizer quarantine CHECK failure during threaded foreach startup" generate_conf add_conf ' template(name="garply" type="string" string="garply: %$.garply%\n") template(name="corge" type="string" string="corge: key: %$.corge!key% val: %$.corge!value%\n") template(name="prefixed_corge" type="string" string="prefixed_corge: %$.corge%\n") template(name="quux" type="string" string="quux: %$.quux%\n") template(name="modified" type="string" string="new: %$!foo!str4% deleted: %$!foo!str3%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse") set $.garply = ""; ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") { action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_corge" queue.type="linkedlist") } foreach ($.quux in $!foo) do { if ($.quux!key == "str2") then { set $.quux!random_key = $.quux!key; unset $!foo!str3; #because it is deep copied, the foreach loop will still see str3, but the "modified" action in the bottom will not set $!foo!str4 = "jkl3"; } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux") foreach ($.corge in $.quux!value) do { action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="corge" queue.type="linkedlist" action.copyMsg="on") call prefixed_writer foreach ($.grault in $.corge!value) do { if ($.garply != "") then set $.garply = $.garply & ", "; set $.garply = $.garply & $.grault!key & "=" & $.grault!value; } } } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="modified") ' startup tcpflood -m 1 -I $srcdir/testsuites/json_object_input echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check 'quux: { "key": "str1", "value": "abc0" }' content_check 'quux: { "key": "str2", "value": "def1", "random_key": "str2" }' content_check 'quux: { "key": "str3", "value": "ghi2" }' assert_content_missing 'quux: { "key": "str4", "value": "jkl3" }' content_check 'new: jkl3' assert_content_missing 'deleted: ghi2' content_check 'quux: { "key": "obj", "value": { "bar": { "k1": "important_msg", "k2": "other_msg" } } }' custom_content_check 'corge: key: bar val: { "k1": "important_msg", "k2": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log custom_content_check 'prefixed_corge: { "key": "bar", "value": { "k1": "important_msg", "k2": "other_msg" } }' $RSYSLOG_DYNNAME.out.prefixed.log content_check 'garply: k1=important_msg, k2=other_msg' exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-no-sni.sh0000644000000000000000000000013115216464436020342 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.847789843 29 ctime=1787067807.62797164 rsyslog-8.2608.0/tests/omfwd-tls-ossl-no-sni.sh0000775000175000017500000000127315216464436020015 0ustar00rgerrger#!/bin/bash # Author: John Cantu # Test that no TLS SNI is sent by omfwd when connecting to an IP address . ${srcdir:=.}/diag.sh init port_file="$RSYSLOG_DYNNAME.sni-server.port" omfwd_sni_server "openssl" "$port_file" port=$(cat "$port_file") generate_conf add_conf ' global(DefaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" \ net.ipprotocol="ipv4-only") action(type="omfwd" target="127.0.0.1" protocol="tcp" port="'$port'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="anon" ) ' startup omfwd_sni_check "(NULL)" shutdown_immediate wait_shutdown kill -9 $(cat "$RSYSLOG_DYNNAME.sni-server.pid") exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_http_request.sh0000644000000000000000000000013115241075234020534 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 29 ctime=1787067805.95094039 rsyslog-8.2608.0/tests/rscript_http_request.sh0000775000175000017500000000274415241075234020213 0ustar00rgerrger#!/bin/bash # add 2017-12-01 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init rsyslog_testbench_test_url_access http://testbench.rsyslog.com/testbench/echo-get.php generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/fmhttp/.libs/fmhttp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # for debugging the test itself: #template(name="outfmt" type="string" string="%$!%: :%$.%: %rawmsg%\n") template(name="outfmt" type="string" string="%$!%\n") if $msg contains "msgnum:" then { set $.url = "http://testbench.rsyslog.com/testbench/echo-get.php?content=" & ltrim($msg); set $!reply = http_request($.url); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m10 wait_file_lines $RSYSLOG_OUT_LOG 10 200 shutdown_when_empty wait_shutdown # check for things that look like http failures if grep -q "DOCTYPE" "$RSYSLOG_OUT_LOG" ; then printf 'SKIP: looks like we have problems with the upstream http server:\n' cat -n "$RSYSLOG_OUT_LOG" printf '\n' error_exit 177 fi export EXPECTED='{ "reply": "msgnum:00000000:" } { "reply": "msgnum:00000001:" } { "reply": "msgnum:00000002:" } { "reply": "msgnum:00000003:" } { "reply": "msgnum:00000004:" } { "reply": "msgnum:00000005:" } { "reply": "msgnum:00000006:" } { "reply": "msgnum:00000007:" } { "reply": "msgnum:00000008:" } { "reply": "msgnum:00000009:" }' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zstd-secure-defaults.sh0000644000000000000000000000013115241075234024215 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.685579792 30 ctime=1787067805.594933756 rsyslog-8.2608.0/tests/imtcp-stream-always-zstd-secure-defaults.sh0000775000175000017500000001053215241075234023666 0ustar00rgerrger#!/bin/bash # added 2026-07-20 by Codex, released under ASL 2.0 # Validates the RainerScript secure-default policy for the aggregate zstd # decoder-window limit. Configuration-validation exit status and startup # diagnostics are the oracle; no listener runtime timing is involved. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime modpath="${RSYSLOG_MODDIR}" run_expect_success() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -ne 0 ]; then echo "FAIL: expected ${cfg} to validate" cat "${log}" error_exit 1 fi } run_expect_failure() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -eq 0 ]; then echo "FAIL: expected ${cfg} to fail validation" cat "${log}" error_exit 1 fi } write_input_config() { local cfg="$1" local policy="$2" local mode="$3" local driver="$4" local limit="$5" cat >"${cfg}" <"${RSYSLOG_DYNNAME}.strict-module-inherit.conf" <<'CONF_EOF' global(compatibility.defaults.secure="strict") module(load="../plugins/imtcp/.libs/imtcp" compression.mode="stream:always" compression.driver="zstd" compression.maxTotalZstdWindowBytes="2097152") input(type="imtcp" port="0") action(type="omfile" file="/dev/null") CONF_EOF run_expect_success "${RSYSLOG_DYNNAME}.strict-module-inherit.conf" \ "${RSYSLOG_DYNNAME}.strict-module-inherit.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-module-params.sh0000644000000000000000000000013215035412264020256 xustar0030 mtime=1752569012.402736851 30 atime=1782715518.847789843 30 ctime=1787067804.179907388 rsyslog-8.2608.0/tests/omfile-module-params.sh0000777000175000017500000000101715035412264017726 0ustar00rgerrger#!/bin/bash # addd 2018-08-02 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 # we only check output fmt, so few messages are OK generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="../plugins/imtcp/.libs/imtcp") module(load="builtin:omfile" template="outfmt") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-fail-with-400.sh0000644000000000000000000000013215132733117021015 xustar0030 mtime=1768666703.963621086 30 atime=1782715518.847789843 30 ctime=1787067806.124943633 rsyslog-8.2608.0/tests/omhttp-batch-fail-with-400.sh0000777000175000017500000000272215132733117020471 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 omhttp_start_server 0 --fail-with-400-after 1000 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="500") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") # Wrap message as a single batch for retry template(name="tpl_retry" type="string" string="[%msg%]") ruleset(name="ruleset_omhttp") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="off" retry="on" # Configure retry codes - only retry 5xx server errors, not 4xx client errors # This fixes the bug where HTTP 400 errors were incorrectly retried httpretrycodes=["500", "502", "503", "504"] # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server # Test expects only the first 1000 messages to be processed successfully # Messages after 1000 get HTTP 400 errors and should NOT be retried seq_check $SEQ_CHECK_OPTIONS 0 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_rename_params.sh0000644000000000000000000000013215035412264023353 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.846789826 30 ctime=1787067808.113980697 rsyslog-8.2608.0/tests/imbatchreport_errmsg_rename_params.sh0000777000175000017500000000067415035412264023033 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" reports="*.done" rename=".done$ - ") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "'rename' must specify THREE parameters separated by spaces or tabs" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_conflict1-vg.sh0000644000000000000000000000013215171370365022367 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.873790285 30 ctime=1787067806.908958242 rsyslog-8.2608.0/tests/rscript_unflatten_conflict1-vg.sh0000775000175000017500000000012415171370365022033 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_conflict1.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_ruleset_call_indirect-invld.sh0000644000000000000000000000013115035412264023455 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.872790268 29 ctime=1787067804.77191842 rsyslog-8.2608.0/tests/rscript_ruleset_call_indirect-invld.sh0000777000175000017500000000140415035412264023126 0ustar00rgerrger#!/bin/bash # added 2016-12-11 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" field.delimiter="58" field.number="2") constant(value="\n") } ruleset(name="rs") { action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt") } if $msg contains "msgnum" then call_indirect "does-not-exist"; else action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 5 shutdown_when_empty wait_shutdown grep "error.*does-not-exist" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/stats-prometheus.sh0000644000000000000000000000013215241075234017567 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.797581889 30 ctime=1787067806.701954385 rsyslog-8.2608.0/tests/stats-prometheus.sh0000775000175000017500000000210015241075234017227 0ustar00rgerrger#!/bin/bash # added 2025-07-12 by Codex # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="prometheus") if ($msg == "this condition will never match") then { action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`) } ' startup injectmsg_file $srcdir/testsuites/dynstats_input_1 wait_queueempty wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown # The main queue's legacy name contains a space. Prometheus output must use # the reversible U__ form, including the doubled separator underscore. custom_content_check '# TYPE U__main_20_Q__enqueued__total counter' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log" exit_testrsyslog-8.2608.0/tests/PaxHeaders/cee_diskqueue.sh0000644000000000000000000000013215241075234017053 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.762581234 30 ctime=1787067804.939921551 rsyslog-8.2608.0/tests/cee_diskqueue.sh0000775000175000017500000000136415241075234016526 0ustar00rgerrger#!/bin/bash # check if CEE properties are properly saved & restored to/from disk queue # added 2012-09-19 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test probably does not work on all flavors of Solaris" export NUMMESSAGES=5000 QUEUE_TYPE=${QUEUE_TYPE:-disk} generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") template(name="outfmt" type="string" string="%$!usr!msg:F,58:2%\n") set $!usr!msg = $msg; if $msg contains "msgnum" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" queue.type="'$QUEUE_TYPE'" queue.filename="rsyslog-act1") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/uxsock_simple_abstract.sh0000644000000000000000000000013215216464436021020 xustar0030 mtime=1782212894.091267235 30 atime=1782715518.870790234 30 ctime=1787067807.650972069 rsyslog-8.2608.0/tests/uxsock_simple_abstract.sh0000775000175000017500000000501415216464436020467 0ustar00rgerrger#!/bin/bash # This tests basic omuxsock functionality. A socket receiver is started which sends # all data to an output file, then a rsyslog instance is started which generates # messages and sends them to the unix socket. Datagram sockets are being used. # added 2010-08-06 by Rgerhards # Updated 2025-04-16 for abstract sockets . ${srcdir:=.}/diag.sh init uname if [ $(uname) != "Linux" ] ; then echo "This test requires Linux (AF_UNIX abstract addresses)" exit 77 fi wait_receiver_ready() { expected_generation=$1 ready_file=$2 count=1 while [ "$count" -le "$TB_TIMEOUT_STARTSTOP" ]; do if [ -r "$ready_file" ] && [ "$(cat "$ready_file")" = "$expected_generation" ]; then return fi $TESTTOOL_DIR/msleep 100 count=$((count + 1)) done echo "uxsockrcvr did not report ready generation $expected_generation for $ready_file" error_exit 1 } SOCKET_NAME="$RSYSLOG_DYNNAME-testbench-dgram-uxsock-abstract" # create the pipe and start a background process that copies data from # it to the "regular" work file generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 $template outfmt,"%msg:F,58:2%\n" module( load = "../plugins/omuxsock/.libs/omuxsock" template = "outfmt" ) :msg, contains, "msgnum:" action( type = "omuxsock" SocketName = "'$SOCKET_NAME'" abstract = "1" ) ' RECEIVER_READY=$RSYSLOG_DYNNAME.uxsockrcvr.ready ./uxsockrcvr -a -s$SOCKET_NAME -o $RSYSLOG_OUT_LOG -r $RECEIVER_READY -t 60 & BGPROCESS=$! echo background uxsockrcvr process id is $BGPROCESS wait_receiver_ready 1 "$RECEIVER_READY" # now do the usual run RS_REDIR="> ${RSYSLOG_DYNNAME}.log 2>&1" startup # 10000 messages should be enough injectmsg 0 10000 wait_queueempty echo resetting uxsockrcvr... kill -HUP $BGPROCESS wait_receiver_ready 2 "$RECEIVER_READY" injectmsg 10000 10000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # wait for the cp process to finish, do pipe-specific cleanup echo shutting down uxsockrcvr... # TODO: we should do this more reliable in the long run! (message counter? timeout?) kill $BGPROCESS wait $BGPROCESS echo background process has terminated, continue test... # and continue the usual checks seq_check 0 19999 # Verify that we do NOT get messages for when our receiver reset. # We only expect these messages if we have a connected socket. # We don't redirect with valgrind if [ "${USE_VALGRIND}" != "YES" ]; then check_not_present "omuxsock suspending: send(), socket " ${RSYSLOG_DYNNAME}.log fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_all.sh0000644000000000000000000000013215241075234017571 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067806.926958578 rsyslog-8.2608.0/tests/rscript_faup_all.sh0000775000175000017500000000354015241075234017242 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://www.rsyslog.com/doc/v8-stable/rainerscript/functions/mo-faup.html"; set $.faup = faup($!url); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 3 wait_file_lines "$RSYSLOG_OUT_LOG" 3 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "", "fragment": "" } msgnum:00000001: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "", "fragment": "" } msgnum:00000002: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "", "fragment": "" }' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafile-template-type-invalid.sh0000644000000000000000000000013115241075234023517 xustar0030 mtime=1787067036.631578781 29 atime=1787067036.68757983 30 ctime=1787067804.181907426 rsyslog-8.2608.0/tests/omfile-dynafile-template-type-invalid.sh0000775000175000017500000000220015241075234023161 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Ensure strict dynafile template-type mode rejects uninspectable templates for # legacy selector actions as well as modern actions. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="builtin:omfile" dynafile.restrictTemplateType="on") template(name="dynfile" type="subtree" subtree="$!dynfile") template(name="outfmt" type="string" string="%msg:F,58:2%\n") *.* ?dynfile;outfmt ' if ../tools/rsyslogd -C -N1 -M"$RSYSLOG_MODDIR" -f"${TESTCONF_NM}.conf" \ >"${RSYSLOG_DYNNAME}.log" 2>&1; then echo "FAIL: expected config validation failure for subtree dynafile template" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 else exit_code=$? if [ "$exit_code" -ne 1 ]; then echo "FAIL: expected exit code 1, got $exit_code" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi fi grep -F "dynafile template 'dynfile' uses a template type that cannot be safely inspected" \ "${RSYSLOG_DYNNAME}.log" >/dev/null || { echo "FAIL: expected dynafile template type validation error" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-include.sh0000644000000000000000000000013215241075234016623 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.801581964 30 ctime=1787067805.374929657 rsyslog-8.2608.0/tests/yaml-include.sh0000775000175000017500000000436515241075234016302 0ustar00rgerrger#!/bin/bash # Tests that YAML config files can include both: # - another .yaml file (YAML-from-YAML include) # - a .conf (RainerScript) file (RainerScript-from-YAML include) # Verifies the extension-based router in cnfDoInclude() works correctly. # # Template "outfmt" is defined in the main YAML's templates: section so that # it is registered via cnfDoObj() before any flex buffers are consumed. # The included .conf file adds a second template ("confmt") to prove that # RainerScript includes from YAML are processed; that template is used by a # second action in the ruleset script so both outputs are checked. # # Added 2025 by contributors, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=50 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' # Testbench preamble in RainerScript; main config in YAML include(file="'${RSYSLOG_DYNNAME}'.yaml") ' # Sub-config included from YAML as a .conf (RainerScript) fragment. # Defines a second template so we can verify .conf includes are processed. cat > "${RSYSLOG_DYNNAME}_inc.conf" << CONFEOF template(name="confmt" type="string" string="%msg:F,58:2%\n") CONFEOF # Sub-config included from YAML as a nested .yaml file — loads imtcp. cat > "${RSYSLOG_DYNNAME}_sub.yaml" << 'SUBEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" SUBEOF # Main YAML config. # templates: is processed via cnfDoObj() during YAML loading (before any flex # buffers are consumed), so "outfmt" is always available to the ruleset script. cat > "${RSYSLOG_DYNNAME}.yaml" << YAMLEOF include: - path: "${RSYSLOG_DYNNAME}_sub.yaml" - path: "${RSYSLOG_DYNNAME}_inc.conf" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" rulesets: - name: main script: | :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}") YAMLEOF # Expand shell vars sed -i \ -e "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" \ -e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \ "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-sigalgs-common.sh0000644000000000000000000000013115241075234023146 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 29 ctime=1787067808.21398256 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-sigalgs-common.sh0000775000175000017500000002200615241075234022616 0ustar00rgerrger#!/bin/bash # Common matrix for PKCS#11-backed omfwd mTLS signing algorithm tests. . ${srcdir:=.}/diag.sh init case "$(basename "$0")" in omfwd-tls-ossl-pkcs11-sigalgs-common.sh) printf 'info: shared helper script; skipping direct execution\n' skip_test ;; esac check_command_available openssl check_command_available softhsm2-util check_command_available pkcs11-tool if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi find_first_existing() { for candidate in "$@"; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } setup_variant() { case "${PKCS11_SIGALG_VARIANT}" in key_only) TEST_SUFFIX="key-mtls-sigalgs" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-key-mtls-sigalgs" TEST_CA_REF="$workdir/ca.pem" TEST_CERT_REF="$workdir/client.pem" TEST_KEY_REF="$key_uri" ;; cert_key) TEST_SUFFIX="cert-mtls-sigalgs" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-cert-mtls-sigalgs" TEST_CA_REF="$workdir/ca.pem" TEST_CERT_REF="$cert_uri" TEST_KEY_REF="$key_uri" ;; ca_key) TEST_SUFFIX="ca-mtls-sigalgs" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-ca-mtls-sigalgs" TEST_CA_REF="$ca_uri" TEST_CERT_REF="$workdir/client.pem" TEST_KEY_REF="$key_uri" ;; full) TEST_SUFFIX="mtls-sigalgs" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-mtls-sigalgs" TEST_CA_REF="$ca_uri" TEST_CERT_REF="$cert_uri" TEST_KEY_REF="$key_uri" ;; *) printf 'unknown PKCS11_SIGALG_VARIANT=%s\n' "${PKCS11_SIGALG_VARIANT}" >&2 error_exit 1 ;; esac } provider_module=$(find_first_existing \ /usr/lib64/ossl-modules/pkcs11.so \ /usr/lib/ossl-modules/pkcs11.so \ /usr/lib/x86_64-linux-gnu/ossl-modules/pkcs11.so \ /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so \ /usr/local/lib64/ossl-modules/pkcs11.so \ /usr/local/lib/ossl-modules/pkcs11.so) || { printf 'info: skipping test - pkcs11 OpenSSL provider module not found\n' skip_test } softhsm_module=$(find_first_existing \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/pkcs11/libsofthsm2.so \ /usr/lib64/softhsm/libsofthsm2.so \ /usr/lib/softhsm/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib64/libsofthsm2.so \ /usr/lib/libsofthsm2.so) || { printf 'info: skipping test - SoftHSM PKCS#11 module not found\n' skip_test } token_label="rsyslog-test-token" token_pin="123456" token_so_pin="12345678" workdir="$RSYSLOG_DYNNAME.${PKCS11_SIGALG_VARIANT}" softhsm_conf="$workdir/softhsm2.conf" openssl_conf="$workdir/openssl-pkcs11.cnf" token_dir="$workdir/tokens" mkdir -p "$workdir" "$token_dir" cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 3072 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 3072 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 3072 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 openssl x509 -in "$workdir/ca.pem" -outform DER -out "$workdir/ca.der" || error_exit 1 openssl x509 -in "$workdir/client.pem" -outform DER -out "$workdir/client.der" || error_exit 1 openssl pkey -in "$workdir/client.key" -pubout -outform DER -out "$workdir/client.pub.der" || \ error_exit 1 cat >"$softhsm_conf" <"$openssl_conf" <"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf "$(cat <1 2003-03-01T01:00:00.000Z host app - - - ${msg}" wait_file_lines "$server_capture" 1 shutdown_when_empty wait_shutdown wait $server_pid || { cat "$server_stderr" error_exit 1 } content_count_check --regex "^${msg}\$" 1 "$server_capture" } run_case \ "tls12-rsa-sha256" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA256" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA256" run_case \ "tls12-rsa-sha384" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA384" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA384" run_case \ "tls12-rsa-sha512" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA512" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=RSA+SHA512" run_case \ "tls13-rsa-pss-sha256" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha256" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha256" run_case \ "tls13-rsa-pss-sha384" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha384" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha384" run_case \ "tls13-rsa-pss-sha512" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha512" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=rsa_pss_rsae_sha512" exit_test rsyslog-8.2608.0/tests/PaxHeaders/chkseq.c0000644000000000000000000000013015216464436015334 xustar0030 mtime=1782212894.046266507 28 atime=1782715518.8687902 30 ctime=1787067803.559895835 rsyslog-8.2608.0/tests/chkseq.c0000664000175000017500000002170315216464436015005 0ustar00rgerrger/* Checks if a file consists of line of strictly monotonically * increasing numbers. An expected start and end number may * be set. * * Params * -f file to process, if not given stdin is processed. * -s -e * default for s is 0. -e should be given (else it is also 0) * -d may be specified, in which case duplicate messages are permitted. * -m number of messages permitted to be missing without triggering a * failure. This is necessary for some failover tests, where it is * impossible to totally guard against message loss. By default, NO * message is permitted to be lost. * -T anticipate truncation (which means specified payload length may be * more than actual payload (which may have been truncated) * -i increment between messages (default: 1). Can be used for tests which * intentionally leave consistent gaps in the message numbering. * * Part of the testbench for rsyslog. * * Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include #include #include #if defined(_AIX) #include #else #include #endif #define EDBUF_SIZE (500 * 1024) int main(int argc, char *argv[]) { FILE *fp; int val = -1; int i; int ret = 0; int scanfOK; int verbose = 0; int bHaveExtraData = 0; int bAnticipateTruncation = 0; int dupsPermitted = 0; int start = 0, end = 0; int opt; int lostok = 0; /* how many messages are OK to be lost? */ int nDups = 0; int increment = 1; int reachedEOF = 0; int edLen; /* length of extra data */ static char edBuf[EDBUF_SIZE]; /* buffer for extra data (pretty large to be on the safe side...) */ static char ioBuf[sizeof(edBuf) + 1024]; char extraFmt[64]; char *file = NULL; snprintf(extraFmt, sizeof(extraFmt), "%%d,%%d,%%%zus\n", sizeof(edBuf) - 1); while ((opt = getopt(argc, argv, "i:e:f:ds:vm:ET")) != EOF) { switch ((char)opt) { case 'f': file = optarg; break; case 'd': dupsPermitted = 1; break; case 'i': increment = atoi(optarg); break; case 'e': end = atoi(optarg); break; case 's': start = atoi(optarg); break; case 'v': ++verbose; break; case 'm': lostok = atoi(optarg); break; case 'E': bHaveExtraData = 1; break; case 'T': bAnticipateTruncation = 1; break; default: printf("Invalid call of chkseq, optchar='%c'\n", opt); printf("Usage: chkseq -f -s -e [-d] [-E] [-T] [-v] [-m] [-i]\n"); exit(1); } } if (start > end) { printf("start must be less than or equal end!\n"); exit(1); } if (verbose) { printf("chkseq: start %d, end %d\n", start, end); } /* read file */ if (file == NULL) { fp = stdin; } else { fp = fopen(file, "r"); } if (fp == NULL) { printf("error opening file '%s'\n", file); perror(file); exit(1); } for (i = start; i <= end; i += increment) { if (bHaveExtraData) { edLen = 0; edBuf[0] = '\0'; if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, extraFmt, &val, &edLen, edBuf) == 3; } if (scanfOK && edLen != (int)strlen(edBuf)) { if (bAnticipateTruncation == 1) { if (edLen < (int)strlen(edBuf)) { printf( "extra data length specified %d, but actually is %ld in" " record %d (truncation was anticipated, but payload should" " have been smaller than data-length, not larger)\n", edLen, (long)strlen(edBuf), i); exit(1); } } else { printf("extra data length specified %d, but actually is %ld in record %d\n", edLen, (long)strlen(edBuf), i); exit(1); } } } else { if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0; } } if (!scanfOK) { if (feof(fp) && lostok > 0) { while (i <= end && lostok > 0) { --lostok; printf("message %d missing (ok due to -m [now %d])\n", i, lostok); i += increment; } if (i > end) break; } printf("scanf error in index i=%d\n", i); exit(1); } while (val > i && lostok > 0) { --lostok; printf("message %d missing (ok due to -m [now %d])\n", i, lostok); i += increment; } if (val != i) { if (val == i - increment && dupsPermitted) { --i; ++nDups; } else { printf("read value %d, but expected value %d\n", val, i); exit(1); } } } if (i - increment != end) { printf("lastrecord does not match. file: %d, expected %d\n", i - increment, end); exit(1); } int c = getc(fp); if (c == EOF) { reachedEOF = 1; } else { ungetc(c, fp); /* if duplicates are permitted, we need to do a final check if we have duplicates at the * end of file. */ if (dupsPermitted) { i = end; while (!feof(fp)) { if (bHaveExtraData) { edLen = 0; edBuf[0] = '\0'; if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, extraFmt, &val, &edLen, edBuf) == 3; } if (scanfOK && edLen != (int)strlen(edBuf)) { if (bAnticipateTruncation == 1) { if (edLen < (int)strlen(edBuf)) { printf( "extra data length specified %d, but " "actually is %ld in record %d (truncation was" " anticipated, but payload should have been " "smaller than data-length, not larger)\n", edLen, (long)strlen(edBuf), i); exit(1); } } else { printf( "extra data length specified %d, but actually " "is %ld in record %d\n", edLen, (long)strlen(edBuf), i); exit(1); } } } else { if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0; } } if (!scanfOK || val != i) { reachedEOF = !scanfOK && feof(fp); goto breakIF; } } reachedEOF = feof(fp) ? 1 : 0; } else { reachedEOF = 0; } } breakIF: if (nDups != 0) printf("info: had %d duplicates (this is no error)\n", nDups); if (!reachedEOF) { printf("end of processing, but NOT end of file! First line of extra data is:\n"); for (c = fgetc(fp); c != '\n' && c != EOF; c = fgetc(fp)) putchar(c); putchar('\n'); exit(1); } exit(ret); } rsyslog-8.2608.0/tests/PaxHeaders/imdocker-basic.sh0000644000000000000000000000013015216464436017122 xustar0030 mtime=1782212894.053266621 28 atime=1782715518.8687902 30 ctime=1787067806.337947602 rsyslog-8.2608.0/tests/imdocker-basic.sh0000775000175000017500000000203415216464436016572 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # imdocker unit tests are enabled with --enable-imdocker-tests . ${srcdir:=.}/diag.sh init NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1) export COOKIE generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imdocker/.libs/imdocker" ListContainersOptions="all=true" GetContainerLogOptions="timestamps=0&follow=1&stdout=1&stderr=0") if $!metadata!Names == "'$COOKIE'" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' # launch a docker runtime to generate some logs. docker run \ --name $COOKIE \ -e NUMMESSAGES=$NUMMESSAGES \ alpine \ /bin/sh -c 'for i in $(seq 0 $((NUMMESSAGES-1))); do echo "$i"; done' > /dev/null #export RS_REDIR=-d startup shutdown_when_empty wait_shutdown echo "cookie: $COOKIE, file name: $RSYSLOG_OUT_LOG" seq_check docker container rm $COOKIE exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse_simple.sh0000644000000000000000000000013115216464436020156 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.867790183 30 ctime=1787067807.170963125 rsyslog-8.2608.0/tests/mmjsonparse_simple.sh0000775000175000017500000000137215216464436017631 0ustar00rgerrger#!/bin/bash # added 2014-07-15 by rgerhards # basic test for mmjsonparse module with defaults # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' template(name="outfmt" type="string" string="%$!msgnum%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse") if $parsesuccess == "OK" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m $NUMMESSAGES -j "@cee: " shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-custom.sh0000644000000000000000000000013115241075234020244 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067805.076924104 rsyslog-8.2608.0/tests/mmsnareparse-custom.sh0000775000175000017500000000367115241075234017723 0ustar00rgerrger#!/bin/bash ## Validate custom pattern loading and section detection for mmsnareparse. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init DEF_FILE="${RSYSLOG_DYNNAME}.defs.json" cat >"$DEF_FILE" <<'JSON' { "sections": [ { "pattern": "Custom Block*", "canonical": "CustomBlock", "behavior": "standard", "priority": 250, "sensitivity": "case_insensitive" } ], "fields": [ { "pattern": "CustomEventTag", "canonical": "CustomEventTag", "section": "EventData", "priority": 80, "value_type": "string" } ], "eventFields": [ { "event_id": 4001, "patterns": [ { "pattern": "WidgetID", "canonical": "WidgetID", "section": "CustomBlock", "value_type": "string" } ] } ], "events": [ { "event_id": 4001, "category": "Custom", "subtype": "Injected", "outcome": "success" } ] } JSON generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmsnareparse/.libs/mmsnareparse" \ definition.file="'${PWD}/${DEF_FILE}'" \ validation.mode="strict") template(name="customfmt" type="list") { property(name="$!win!Event!Category") constant(value=",") property(name="$!win!CustomBlock!WidgetID") constant(value=",") property(name="$!win!EventData!CustomEventTag") constant(value=",") property(name="$!win!Event!Outcome") constant(value="\n") } action(type="mmsnareparse") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="customfmt") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" tcpflood -m 1 -I "${srcdir}/testsuites/mmsnareparse/sample-custom-pattern.data" shutdown_when_empty wait_shutdown content_check ',ZX-42,Demo,success' "$RSYSLOG_OUT_LOG" rm -f "$DEF_FILE" exit_test rsyslog-8.2608.0/tests/PaxHeaders/kafka-selftest.sh0000644000000000000000000000013215216464436017154 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.866790166 30 ctime=1787067806.223945477 rsyslog-8.2608.0/tests/kafka-selftest.sh0000775000175000017500000000271415216464436016627 0ustar00rgerrger#!/bin/bash # added 2018-10-26 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init check_command_available kcat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 RANDTOPIC="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. #export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka download_kafka stop_zookeeper stop_kafka start_zookeeper start_kafka create_kafka_topic $RANDTOPIC '.dep_wrk' '22181' printf 'injecting messages via kcat\n' injectmsg_kcat # experimental: wait until kcat receives everything timeoutend=10 timecounter=0 printf 'receiving messages via kcat\n' while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) kcat -b 127.0.0.1:29092 -e -C -o beginning -t $RANDTOPIC -f '%s\n' > $RSYSLOG_OUT_LOG count=$(wc -l < ${RSYSLOG_OUT_LOG}) if [ $count -eq $TESTMESSAGES ]; then printf '**** wait-kafka-lines success, have %d lines ****\n\n' "$TESTMESSAGES" break else if [ "$timecounter" == "$timeoutend" ]; then echo wait-kafka-lines failed, expected $TESTMESSAGES got $count error_exit 1 else echo wait-file-lines not yet there, currently $count lines printf '\n' $TESTTOOL_DIR/msleep 1000 fi fi done unset count #end experimental delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181' sed -i 's/ msgnum://' "$RSYSLOG_OUT_LOG" seq_check 1 $TESTMESSAGES -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-x509fingerprint.sh0000644000000000000000000000013215241075234022557 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.776581496 30 ctime=1787067807.403967466 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-x509fingerprint.sh0000775000175000017500000000234015241075234022225 0ustar00rgerrger#!/bin/bash # added 2018-12-22 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["nsd_mbedtls.c", "tcpsrv.c, "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/fingerprint" PermittedPeer=["SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-invld-rulebase-vg.sh0000644000000000000000000000013215171370365022126 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.866790166 30 ctime=1787067807.073961317 rsyslog-8.2608.0/tests/pmnormalize-invld-rulebase-vg.sh0000775000175000017500000000022115171370365021570 0ustar00rgerrger#!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/pmnormalize-invld-rulebase.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-errfile-maxsize.sh0000644000000000000000000000013215131231047020452 xustar0030 mtime=1768239655.711212696 30 atime=1782715518.866790166 30 ctime=1787067804.163907091 rsyslog-8.2608.0/tests/omfwd-errfile-maxsize.sh0000777000175000017500000000074215131231047020126 0ustar00rgerrger#!/bin/bash # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export MAX_ERROR_SIZE=1999 generate_conf add_conf ' action(type="omfwd" target="1.2.3.4" port="1234" Protocol="tcp" NetworkNamespace="doesNotExist" action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'") ' startup shutdown_when_empty wait_shutdown check_file_exists ${RSYSLOG2_OUT_LOG} file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE} exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_33_ipv4.sh0000644000000000000000000000013215241075234020033 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.728936253 rsyslog-8.2608.0/tests/mmanon_zero_33_ipv4.sh0000775000175000017500000000216415241075234017505 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.bits="33") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255 <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\"" shutdown_when_empty wait_shutdown export EXPECTED=' 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0.' cmp_exact grep 'invalid number of ipv4.bits (33), corrected to 32' ${RSYSLOG2_OUT_LOG} > /dev/null if [ $? -ne 0 ]; then echo "invalid response generated, ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-retry-restart.sh0000644000000000000000000000013115241075234021421 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 29 ctime=1787067803.82690081 rsyslog-8.2608.0/tests/segmented-da-retry-restart.sh0000775000175000017500000000062015241075234021067 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Exercise the shared suspended-action restart oracle for both DA memory queue # types with the automatic segmented engine selection. for DA_QUEUE_TYPE in LinkedList FixedArray; do export DA_QUEUE_TYPE DA_ENGINE=auto "${srcdir:=.}/testsuites/da-engine-retry-restart-driver.sh" || exit $? done rsyslog-8.2608.0/tests/PaxHeaders/lookup_table_duplicate.sh0000644000000000000000000000013215216464436020762 xustar0030 mtime=1782212894.073266944 30 atime=1782715518.865790149 30 ctime=1787067804.978922278 rsyslog-8.2608.0/tests/lookup_table_duplicate.sh0000775000175000017500000000235415216464436020435 0ustar00rgerrger#!/bin/bash # Verify that duplicate RainerScript lookup_table names are rejected during # config validation. This covers the issue #5316 regression path where repeated # generated definitions created unreachable lookup tables and one reloader # thread per duplicate before reporting the real config problem. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl") lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl") template(name="outfmt" type="string" string="%msg%\n") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' cp -f "$srcdir/testsuites/xlate.lkp_tbl" "$RSYSLOG_DYNNAME.xlate.lkp_tbl" ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -eq 0 ]; then echo "FAIL: expected config validation failure for duplicate lookup_table name" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi grep -F "lookup_table: duplicate name 'xlate' in current config set" "${RSYSLOG_DYNNAME}.log" >/dev/null || { echo "FAIL: expected duplicate lookup_table name error message" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/omotel-trace-correlation.sh0000644000000000000000000000013215145046113021147 xustar0030 mtime=1771326539.059014615 30 atime=1782715518.864790132 30 ctime=1787067806.220945422 rsyslog-8.2608.0/tests/omotel-trace-correlation.sh0000775000175000017500000001544215145046113020624 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-trace-correlation.sh -- test trace correlation support for omotel module ## ## Tests that trace_id, span_id, and trace_flags are extracted from message ## properties and included in the OTLP export. Uses mmjsonparse to extract ## trace properties from JSON messages. . ${srcdir:=.}/diag.sh init # Check if omotel module is available require_plugin omotel require_plugin mmjsonparse export NUMMESSAGES=10 export EXTRA_EXIT=otel export SEQ_CHECK_OPTIONS=-d # Download and prepare OTEL Collector download_otel_collector prepare_otel_collector start_otel_collector # Read the port from the port file if [ ! -f ${RSYSLOG_DYNNAME}.otel_port.file ]; then echo "ERROR: OTEL Collector port file not found: ${RSYSLOG_DYNNAME}.otel_port.file" error_exit 1 fi otel_port=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) if [ -z "$otel_port" ]; then echo "ERROR: OTEL Collector port is empty" error_exit 1 fi echo "Using OTEL Collector port: $otel_port" # Create input file with syslog messages containing JSON with trace context cat > ${RSYSLOG_DYNNAME}.input << 'INPUTFILE' <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000001"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000002"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000003"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000004"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000005"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000006"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000007"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000008"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000009"} <14>1 2024-01-01T12:00:00.000Z testhost testapp 12345 - [test@123] {"trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","trace_flags":"01","message":"test message 00000010"} INPUTFILE generate_conf add_conf ' template(name="otlpBody" type="string" string="%msg%") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/omotel/.libs/omotel") # Parse JSON to extract trace properties action(type="mmjsonparse" mode="find-json") # Export with trace correlation action( name="omotel-http" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port'" path="/v1/logs" trace_id.property="trace_id" span_id.property="span_id" trace_flags.property="trace_flags" batch.max_items="100" batch.timeout.ms="1000" ) ' startup injectmsg_file ${RSYSLOG_DYNNAME}.input shutdown_when_empty wait_shutdown # Stop OTEL Collector to ensure file exporter flushes data stop_otel_collector # Give OTEL Collector a moment to flush the output file after shutdown if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi # Extract data from OTEL Collector output otel_collector_get_data python3 - "$RSYSLOG_DYNNAME.otel-output.json" <<'PY' import json import sys path = sys.argv[1] try: # OTEL Collector file exporter writes newline-delimited JSON (one JSON object per line) records = [] with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue payload = json.loads(line) if "resourceLogs" in payload: for resource_log in payload["resourceLogs"]: if "scopeLogs" in resource_log: for scope_log in resource_log["scopeLogs"]: if "logRecords" in scope_log: records.extend(scope_log["logRecords"]) except Exception as exc: sys.stderr.write(f"omotel-trace-correlation: failed to parse OTLP output: {exc}\n") sys.exit(1) if not records: sys.stderr.write("omotel-trace-correlation: OTLP output did not contain any logRecords\n") sys.exit(1) sys.stdout.write(f"omotel-trace-correlation: found {len(records)} log records in OTLP output\n") # Expected trace values expected_trace_id = "4bf92f3577b34da6a3ce929d0e0e4736" expected_span_id = "00f067aa0ba902b7" expected_trace_flags = 1 sys.stdout.write(f"omotel-trace-correlation: expected traceId='{expected_trace_id}', spanId='{expected_span_id}', flags={expected_trace_flags}\n") # Verify trace correlation fields for idx, record in enumerate(records): trace_id = record.get("traceId") span_id = record.get("spanId") trace_flags = record.get("flags") sys.stdout.write(f"omotel-trace-correlation: record {idx}: traceId={trace_id}, spanId={span_id}, flags={trace_flags}\n") if trace_id is None: sys.stderr.write(f"omotel-trace-correlation: record {idx} missing traceId\n") sys.exit(1) if trace_id != expected_trace_id: sys.stderr.write(f"omotel-trace-correlation: record {idx} traceId mismatch: expected '{expected_trace_id}', got '{trace_id}'\n") sys.exit(1) if span_id is None: sys.stderr.write(f"omotel-trace-correlation: record {idx} missing spanId\n") sys.exit(1) if span_id != expected_span_id: sys.stderr.write(f"omotel-trace-correlation: record {idx} spanId mismatch: expected '{expected_span_id}', got '{span_id}'\n") sys.exit(1) if trace_flags is None: sys.stderr.write(f"omotel-trace-correlation: record {idx} missing flags\n") sys.exit(1) if trace_flags != expected_trace_flags: sys.stderr.write(f"omotel-trace-correlation: record {idx} flags mismatch: expected {expected_trace_flags}, got {trace_flags}\n") sys.exit(1) sys.stdout.write(f"omotel-trace-correlation: verified {len(records)} records with trace correlation\n") PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_gtls_servercert_mbedtls_clientanon.sh0000644000000000000000000000013215216464436025652 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.864790132 30 ctime=1787067807.413967652 rsyslog-8.2608.0/tests/sndrcv_tls_gtls_servercert_mbedtls_clientanon.sh0000775000175000017500000000356115216464436025326 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-find-json-basic.sh0000644000000000000000000000013115216464436021551 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.863790115 30 ctime=1787067807.141962584 rsyslog-8.2608.0/tests/mmjsonparse-find-json-basic.sh0000775000175000017500000000231215216464436021217 0ustar00rgerrger#!/bin/bash # Test mmjsonparse find-json mode basic functionality # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmjsonparse/.libs/mmjsonparse") template(name="outfmt" type="string" string="%msg% parsesuccess=%parsesuccess% json=%$!%\n") # Legacy cookie mode (default) - should NOT parse text with JSON if $msg contains "LEGACY" then { action(type="mmjsonparse") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") stop } # Find-JSON mode - should parse text with embedded JSON if $msg contains "FINDJSON" then { action(type="mmjsonparse" mode="find-json") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") stop } ' startup injectmsg_literal '<167>Jan 16 16:57:54 host.example.net TAG: LEGACY prefix {"field":"value"}' injectmsg_literal '<167>Jan 16 16:57:54 host.example.net TAG: FINDJSON prefix {"field":"value"}' shutdown_when_empty wait_shutdown export EXPECTED=' LEGACY prefix {"field":"value"} parsesuccess=FAIL json={ "msg": "LEGACY prefix {\"field\":\"value\"}" } FINDJSON prefix {"field":"value"} parsesuccess=OK json={ "field": "value" }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_conflict3.sh0000644000000000000000000000013215241075234021752 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 30 ctime=1787067806.891957925 rsyslog-8.2608.0/tests/rscript_unflatten_conflict3.sh0000775000175000017500000000241315241075234021421 0ustar00rgerrger#!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $!a!b = "foo"; set $!a.b = "bar"; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "a": { "b": "bar" } }' cmp_exact "$RSYSLOG_OUT_LOG" EXPECTED='fmunflatten.c: warning: while processing flat key "a.b" at depth #1 (final node), overriding existing value' if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then echo "GREP FAILED" echo " => FILE: $RSYSLOG_DEBUGLOG" echo " => EXPECTED: $EXPECTED" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-find-json-invalid-mode.sh0000644000000000000000000000013115216464436023040 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.863790115 30 ctime=1787067807.153962808 rsyslog-8.2608.0/tests/mmjsonparse-find-json-invalid-mode.sh0000775000175000017500000000101615216464436022506 0ustar00rgerrger#!/bin/bash # Test mmjsonparse invalid mode parameter error handling # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmjsonparse/.libs/mmjsonparse") template(name="outfmt" type="string" string="%msg%\n") action(type="mmjsonparse" mode="INVALID") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown content_check --regex "mmjsonparse: invalid mode 'INVALID'" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-getrequest-file.sh0000644000000000000000000000013215216464436020660 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.863790115 30 ctime=1787067806.407948906 rsyslog-8.2608.0/tests/imhttp-getrequest-file.sh0000775000175000017500000000136615216464436020335 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify imhttp static file serving while the HTTP listener uses an # OS-assigned port. The fetched file content is the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'" documentroot="'$srcdir'/testsuites/docroot") ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" curl -s http://localhost:$IMHTTP_PORT/file.txt > "$RSYSLOG_OUT_LOG" shutdown_when_empty echo "file name: $RSYSLOG_OUT_LOG" content_check "This is a test of get page" exit_test rsyslog-8.2608.0/tests/PaxHeaders/config-translate-rs-roundtrip.sh0000644000000000000000000000013215241075234022146 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067805.446930998 rsyslog-8.2608.0/tests/config-translate-rs-roundtrip.sh0000775000175000017500000000573215241075234021624 0ustar00rgerrger#!/bin/bash # check canonical RainerScript -> YAML -> RainerScript round-trip. # # Part of the testbench for rsyslog. # # This file is part of rsyslog. # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp modpath="../runtime/.libs:../plugins/imtcp/.libs:../.libs" outlog="/tmp/${RSYSLOG_DYNNAME}.roundtrip.log" portfile="${RSYSLOG_DYNNAME}.tcpflood_port" cat > "${RSYSLOG_DYNNAME}.conf" < "${RSYSLOG_DYNNAME}.expected.yaml" < "${RSYSLOG_DYNNAME}.expected.conf" </dev/null 2>&1 openssl req -new -key "$CERTDIR/client-key.pem" -out "$CERTDIR/client.csr" \ -subj "/C=US/ST=Test/O=rsyslog/CN=malicious-client" >/dev/null 2>&1 cat > "$CERTDIR/client-ext.cnf" <<'EOF' [usr_cert] basicConstraints=CA:FALSE # subjectAltName = SEQUENCE { dNSName "rsyslog-client\0.attacker" } subjectAltName=DER:30:1a:82:18:72:73:79:73:6c:6f:67:2d:63:6c:69:65:6e:74:00:2e:61:74:74:61:63:6b:65:72 EOF openssl x509 -req -in "$CERTDIR/client.csr" \ -CA "$srcdir/tls-certs/ca.pem" -CAkey "$srcdir/tls-certs/ca-key.pem" -set_serial 01 \ -out "$CERTDIR/client-cert.pem" -days 365 -sha256 \ -extfile "$CERTDIR/client-ext.cnf" -extensions usr_cert >/dev/null 2>&1 # Sanity-check that the fixture really contains the embedded-NUL SAN bytes. openssl x509 -in "$CERTDIR/client-cert.pem" -outform DER -out "$CERTDIR/client-cert.der" python3 - "$CERTDIR/client-cert.der" <<'PY' from pathlib import Path import sys cert = Path(sys.argv[1]).read_bytes() if b"rsyslog-client\x00.attacker" not in cert: raise SystemExit("embedded-NUL SAN fixture was not generated") PY generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer=["rsyslog-client"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -p"$TCPFLOOD_PORT" -m"$NUMMESSAGES" -Ttls \ -x"$srcdir/tls-certs/ca.pem" \ -Z"$CERTDIR/client-cert.pem" \ -z"$CERTDIR/client-key.pem" || true shutdown_when_empty wait_shutdown content_check --regex "peer name not authorized" check_not_present "msgnum:00000000" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_mbedtls_certvalid_revoked.sh0000644000000000000000000000013215171370365023714 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.861790081 30 ctime=1787067807.420967783 rsyslog-8.2608.0/tests/sndrcv_tls_mbedtls_certvalid_revoked.sh0000775000175000017500000000046515171370365023370 0ustar00rgerrger#!/bin/bash # added 2020-01-17 by RGerhards, released under ASL 2.0 export RS_TLS_DRIVER=mbedtls export TEXT_TO_CHECK="X509 - Certificate verification failed" #export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" #export RSYSLOG_DEBUGLOG="log" . ${srcdir:=.}/sndrcv_tls_certvalid_revoked.sh rsyslog-8.2608.0/tests/PaxHeaders/abort-uncleancfg-badcfg-check.sh0000644000000000000000000000013115035412264021727 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.861790081 29 ctime=1787067804.58191488 rsyslog-8.2608.0/tests/abort-uncleancfg-badcfg-check.sh0000777000175000017500000000073015035412264021401 0ustar00rgerrger#!/bin/bash # Copyright 2015-01-29 by Tim Eifler # This file is part of the rsyslog project, released under ASL 2.0 # The configuration test should fail because of the invalid config file. . ${srcdir:=.}/diag.sh init ../tools/rsyslogd -C -N1 -f$srcdir/testsuites/abort-uncleancfg-badcfg.conf -M../runtime/.libs:../.libs if [ $? == 0 ]; then echo "Error: config check should fail" error_exit 1 fi printf 'unclean config lead to exit, as expected - OK\n' exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-rule_invld-data.sh0000644000000000000000000000013115241075234021644 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.787581702 29 ctime=1787067807.06396113 rsyslog-8.2608.0/tests/pmnormalize-rule_invld-data.sh0000775000175000017500000000203515241075234021314 0ustar00rgerrger#!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/pmnormalize/.libs/pmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") parser(name="custom.pmnormalize" type="pmnormalize" undefinedPropertyError="on" rule="rule=:<%pri:number%> %fromhost-ip:ipv4% %hostname:word% %syslogtag:char-to:\\x3a%: %msg:rest%") template(name="test" type="string" string="%msg%\n") ruleset(name="ruleset" parser="custom.pmnormalize") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="test") } action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsg") ' startup tcpflood -m1 -M "\" 127.0.0.1 ubuntu tag1: this is a test message\"" shutdown_when_empty wait_shutdown export EXPECTED=' 127.0.0.1 ubuntu tag1: this is a test message' cmp_exact content_check --regex "error .* during ln_normalize" $RSYSLOG_DYNNAME.othermsg exit_test rsyslog-8.2608.0/tests/PaxHeaders/msg-deadlock-headerless-noappname.sh0000644000000000000000000000013215241075234022663 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.782581608 30 ctime=1787067804.469912793 rsyslog-8.2608.0/tests/msg-deadlock-headerless-noappname.sh0000775000175000017500000000117715241075234022340 0ustar00rgerrger#!/bin/bash # this checks against a situation where a deadlock was caused in # practice. # added 2018-10-17 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="input") ruleset(name="input") { set $!tag = $app-name; action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -p $TCPFLOOD_PORT -M "[2018-10-16 09:59:13] ping pong" shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropgroupid.sh0000644000000000000000000000013215131231047017471 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.885790489 30 ctime=1787067804.239908507 rsyslog-8.2608.0/tests/privdropgroupid.sh0000777000175000017500000000115515131231047017144 0ustar00rgerrger#!/bin/bash # addd 2016-03-24 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.group.keepsupplemental="on") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) $PrivDropToGroupID '${TESTBENCH_TESTUSER[gid]}' ' #add_conf "\$PrivDropToGroupID ${TESTBENCH_TESTUSER[gid]}" startup shutdown_when_empty wait_shutdown content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/empty-hostname.sh0000644000000000000000000000013215145046113017207 xustar0030 mtime=1771326539.036014239 30 atime=1782715518.885790489 30 ctime=1787067803.997903997 rsyslog-8.2608.0/tests/empty-hostname.sh0000775000175000017500000000237515145046113016665 0ustar00rgerrger#!/bin/bash # This tests checks for a anomaly we have seen in practice: # gethostname() may return an empty string as hostname (""). This broke # some versions of rsyslog, newer ones return "localhost" in that case. # The test is done with the help of a preload library specifically written # for this purpose (liboverride_gethostname.so). It will override # gethostname() and return an empty string. Then, the test checks if the # hardcoded default of "localhost-empty-hostname" is used. # Note that the test may fail if the library is not properly preloaded. # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "AIX" "we cannot preload required dummy lib" skip_ASAN "LD_PRELOAD conflicts with ASan runtime load order" generate_conf add_conf ' action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' export RSYSLOG_PRELOAD=.libs/liboverride_gethostname.so startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! grep " localhost-empty-hostname " < $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "expected hostname \"localhost-empty-hostname\" not found in logs, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-jsonf-nested-fallback-flat.sh0000644000000000000000000000013215216464436023141 xustar0030 mtime=1782212894.086267154 30 atime=1782715518.884790472 30 ctime=1787067804.262908935 rsyslog-8.2608.0/tests/template-jsonf-nested-fallback-flat.sh0000775000175000017500000000146115216464436022612 0ustar00rgerrger#!/bin/bash # Verify jsonftree conflict fallback still emits valid flat JSON (ASL 2.0). . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="nested_fallback" type="list" option.jsonftree="on") { constant(outname="a" value="A" format="jsonf") constant(outname="a.b" value="B" format="jsonf") } local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="nested_fallback") ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys with open(sys.argv[1], 'r', encoding='utf-8') as fh: actual = json.loads(fh.read()) expected = {"a": "A", "a.b": "B"} if actual != expected: print('invalid fallback JSON generated') print('actual:', actual) print('expected:', expected) sys.exit(1) PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/mysql-unavailable-transaction.sh0000644000000000000000000000013115216464436022220 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.884790472 29 ctime=1787067805.92193985 rsyslog-8.2608.0/tests/mysql-unavailable-transaction.sh0000775000175000017500000000203315216464436021666 0ustar00rgerrger#!/usr/bin/env bash # Regression coverage for GitHub issue #4199. ommysql must suspend cleanly when # the database connection is unavailable while transaction support is active. # The oracle is synchronized shutdown plus the normal ommysql diagnostic in # rsyslog's configured output path; the test must not crash or hang. . ${srcdir:=.}/diag.sh init require_plugin ommysql export NUMMESSAGES=1 mysql_port="$(get_free_port)" generate_conf add_conf ' module(load="../plugins/ommysql/.libs/ommysql") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action(type="ommysql" server="127.0.0.1" serverport="'$mysql_port'" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" queue.type="Direct" action.resumeRetryCount="0" action.resumeInterval="1") } syslog.* { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup injectmsg shutdown_when_empty wait_shutdown content_check "ommysql:" "$RSYSLOG_OUT_LOG" check_not_present "Segmentation fault" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp_spframingfix.sh0000644000000000000000000000013215241075234020131 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067805.542932787 rsyslog-8.2608.0/tests/imtcp_spframingfix.sh0000775000175000017500000000155215241075234017603 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 echo ==================================================================================== echo TEST: \[imptcp_spframingfix.sh\]: test imptcp in regard to Cisco ASA framing fix . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" framingfix.cisco.asa="on") template(name="outfmt" type="string" string="%rawmsg:6:7%\n") ruleset(name="remote") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -B -I ${srcdir}/testsuites/spframingfix.testdata shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate seq_check 0 19 exit_test rsyslog-8.2608.0/tests/PaxHeaders/fac_mail.sh0000644000000000000000000000013215241075234015773 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.292909494 rsyslog-8.2608.0/tests/fac_mail.sh0000775000175000017500000000117715241075234015450 0ustar00rgerrger#!/bin/bash # added 2014-09-17 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(type="string" name="outfmt" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") mail.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m$NUMMESSAGES -P 17 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_all_2.sh0000644000000000000000000000013215241075234020012 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067806.930958652 rsyslog-8.2608.0/tests/rscript_faup_all_2.sh0000775000175000017500000000372615241075234017471 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://user:pass@www.rsyslog.com:443/doc/v8-stable/rainerscript/functions/mo-faup.html?param=value#faup"; set $.faup = faup($!url); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 3 wait_file_lines "$RSYSLOG_OUT_LOG" 3 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "scheme": "https", "credential": "user:pass", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "443", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "?param=value", "fragment": "#faup" } msgnum:00000001: 0 { "scheme": "https", "credential": "user:pass", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "443", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "?param=value", "fragment": "#faup" } msgnum:00000002: 0 { "scheme": "https", "credential": "user:pass", "subdomain": "www", "domain": "rsyslog.com", "domain_without_tld": "rsyslog", "host": "www.rsyslog.com", "tld": "com", "port": "443", "resource_path": "\/doc\/v8-stable\/rainerscript\/functions\/mo-faup.html", "query_string": "?param=value", "fragment": "#faup" }' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-stop.sh0000644000000000000000000000013215035412264017353 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.885790489 30 ctime=1787067805.812937819 rsyslog-8.2608.0/tests/clickhouse-stop.sh0000777000175000017500000000132515035412264017025 0ustar00rgerrger#!/bin/bash # This is not a real test, but a script to stop clickhouse. It is # implemented as test so that we can stop clickhouse at the time we need # it (do so via Makefile.am). # Copyright (C) 2018 Pascal Withopf and Adiscon GmbH # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init if [ "$CLICKHOUSE_STOP_CMD" == "" ]; then exit_test fi clickhouse-client --query="DROP DATABASE rsyslog" sleep 1 printf 'stopping clickhouse...\n' #$SUDO sed -n -r 's/PID: ([0-9]+\.*)/\1/p' /var/lib/clickhouse/status > /tmp/clickhouse-server.pid #$SUDO kill $($SUDO sed -n -r 's/PID: ([0-9]+\.*)/\1/p' /var/lib/clickhouse/status) eval $CLICKHOUSE_STOP_CMD sleep 1 # cosmetic: give clickhouse a chance to emit shutdown message exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zstd-flushoff.sh0000644000000000000000000000013115241075234022736 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.774581459 30 ctime=1787067805.581933514 rsyslog-8.2608.0/tests/imtcp-stream-always-zstd-flushoff.sh0000775000175000017500000000244115241075234022407 0ustar00rgerrger#!/bin/bash # added 2026-05-17 by Codex, released under ASL 2.0 # Verifies that zstd stream:always data is held until the omfwd stream closes # when flushOnTXEnd is off; the receiver must emit no early partial message. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime export NUMMESSAGES=1 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zstd") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.driver="zstd" compression.stream.flushOnTXEnd="off") ' 2 startup 2 injectmsg2 sleep 1 if [ -s "$RSYSLOG_OUT_LOG" ]; then echo "FAIL: receiver emitted data before sender shutdown with compression.stream.flushOnTXEnd=off" cat "$RSYSLOG_OUT_LOG" error_exit 1 fi shutdown_when_empty 2 wait_shutdown 2 wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-api-key-auth.sh0000644000000000000000000000013215216464436022463 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.885790489 30 ctime=1787067806.374948291 rsyslog-8.2608.0/tests/imhttp-post-payload-api-key-auth.sh0000775000175000017500000000272115216464436022134 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify this imhttp POST-payload variant while the HTTP listener uses an # OS-assigned port. The HTTP status and configured output checks are the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" apiKeyFile="'$srcdir'/testsuites/imhttp-apikeys.txt") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" ret=$(curl -s -o /dev/null -w '%{http_code}' \ -H 'Authorization: ApiKey wrong-token' \ -H Content-Type:application/json \ http://localhost:$IMHTTP_PORT/postrequest \ -d '[{"foo":"bar"}]') if [ "$ret" != "401" ]; then echo "ERROR: expected 401 for invalid API key, got $ret" error_exit 1 fi ret=$(curl -s -o /dev/null -w '%{http_code}' \ -H 'Authorization: ApiKey secret-token-1' \ -H Content-Type:application/json \ http://localhost:$IMHTTP_PORT/postrequest \ -d '[{"foo":"bar"}]') if [ "$ret" != "200" ]; then echo "ERROR: expected 200 for valid API key, got $ret" error_exit 1 fi wait_queueempty shutdown_when_empty wait_shutdown content_check '[{"foo":"bar"}]' exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_object-vg.sh0000644000000000000000000000013215171370365021753 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.884790472 30 ctime=1787067806.921958484 rsyslog-8.2608.0/tests/rscript_unflatten_object-vg.sh0000775000175000017500000000012115171370365021414 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_object.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-lb-1target-retry-1_byte_buf.sh0000644000000000000000000000013215216464436022504 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.884790472 30 ctime=1787067804.130906475 rsyslog-8.2608.0/tests/omfwd-lb-1target-retry-1_byte_buf.sh0000775000175000017500000000215715216464436022160 0ustar00rgerrger#!/bin/bash # This wrapper retries the shared skeleton once more when TCP timing races # trigger the known omfwd load-balancer flake. The second attempt keeps the # same 1-byte-buffer scenario; it only avoids failing the suite on one unlucky # receiver-close/reconnect timing window. export srcdir="${srcdir:=.}" export OMFWD_IOBUF_SIZE=10 # triggers edge cases skeleton="$srcdir/omfwd-lb-1target-retry-test_skeleton.sh" max_attempts=2 attempt=1 result=1 while [ "$attempt" -le "$max_attempts" ]; do if [ "$attempt" -gt 1 ]; then echo "Retrying omfwd 1-byte load-balancer test (attempt $attempt of $max_attempts) to mitigate TCP buffer timing races." fi if [ "$attempt" -lt "$max_attempts" ]; then TESTBENCH_SUPPRESS_FAIL_MARKER=YES bash "$skeleton" else bash "$skeleton" fi result=$? if [ "$result" -eq 0 ]; then if [ "$attempt" -gt 1 ]; then echo "omfwd 1-byte load-balancer test passed on retry." fi exit 0 fi attempt=$((attempt + 1)) done echo "omfwd 1-byte load-balancer test failed after $max_attempts attempts." exit "$result" rsyslog-8.2608.0/tests/PaxHeaders/omazureeventhubs-interrupt.sh0000644000000000000000000000013215216464436021710 xustar0030 mtime=1782212894.076266993 30 atime=1782715518.883790455 30 ctime=1787067806.282946577 rsyslog-8.2608.0/tests/omazureeventhubs-interrupt.sh0000775000175000017500000001267215216464436021367 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 echo This test must be run as root [raw socket access required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full # --- If test is needed, create helper script to store environment variables for # �venthubs access: # export AZURE_HOST="" # export AZURE_PORT="" # export AZURE_KEY_NAME="" # export AZURE_KEY="" # export AZURE_CONTAINER="" # --- . omazureeventhubs-env.sh export NUMMESSAGES=10000 export NUMMESSAGESFULL=$NUMMESSAGES export WAITTIMEOUT=60 export QUEUESIZE=100000 export DEQUEUESIZE=64 export DEQUEUESIZEMIN=32 export TESTWORKERTHREADS=3 export interrupt_host="$AZURE_HOST" export interrupt_port="$AZURE_PORT" export interrupt_tick="10" TEST_TIMEOUT_WAIT=180 # REQUIRES EXTERNAL ENVIRONMENT VARIABLES if [[ -z "${AZURE_HOST}" ]]; then echo "SKIP: AZURE_HOST environment variable not SET! Example: .servicebus.windows.net - SKIPPING" exit 77 fi if [[ -z "${AZURE_PORT}" ]]; then echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY_NAME}" ]]; then echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY}" ]]; then echo "SKIP: AZURE_KEY environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_CONTAINER}" ]]; then echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: - SKIPPING" exit 77 fi export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME" export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME" # --- Create/Start omazureeventhubs sender config generate_conf add_conf ' global( # debug.whitelist="on" # debug.files=["omazureeventhubs.c", "modules.c", "errmsg.c", "action.c", "queue.c", "ruleset.c"] ) # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") # Load mods module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs") # templates template(name="outfmt" type="string" string="%msg:F,58:2%\n") local4.* { action( name="omazureeventhubs" type="omazureeventhubs" azurehost="'$AZURE_HOST'" azureport="'$AZURE_PORT'" azure_key_name="'$AZURE_KEY_NAME'" azure_key="'$AZURE_KEY'" container="'$AZURE_CONTAINER'" # amqp_address="amqps://'$AZURE_KEY_NAME':'$AZURE_KEY'@'$AZURE_HOST'/'$AZURE_NAME'" template="outfmt" queue.type="FixedArray" queue.size="'$QUEUESIZE'" queue.saveonshutdown="on" queue.dequeueBatchSize="'$DEQUEUESIZE'" queue.minDequeueBatchSize="'$DEQUEUESIZEMIN'" queue.minDequeueBatchSize.timeout="1000" # 1 sec queue.workerThreads="'$TESTWORKERTHREADS'" queue.workerThreadMinimumMessages="'$DEQUEUESIZEMIN'" queue.timeoutWorkerthreadShutdown="60000" queue.timeoutEnqueue="2000" queue.timeoutshutdown="1000" action.resumeInterval="1" action.resumeRetryCount="2" ) action( type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") ' echo Starting sender instance [omazureeventhubs] startup echo Inject messages into rsyslog sender instance injectmsg 1 $NUMMESSAGES wait_file_lines --interrupt-connection $interrupt_host $interrupt_port $interrupt_tick $RSYSLOG_OUT_LOG $NUMMESSAGESFULL $TEST_TIMEOUT_WAIT timeoutend=$WAITTIMEOUT timecounter=0 lastcurrent_time=0 echo "CHECK $RSYSLOG_DYNNAME.pstats" while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then # Read IMPSTATS for verification IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5) SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2) FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2) ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2) if ! [[ $SUBMITTED_MSG =~ $re ]] ; then echo "**** omazureeventhubs WAITING FOR IMPSTATS" else if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then if [ "$ACCEPTED_MSG" -ge "$NUMMESSAGESFULL" ]; then echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" shutdown_when_empty wait_shutdown #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log exit_test else echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" fi else echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" current_time=$(date +%s) if [ $interrupt_connection == "YES" ] && [ $current_time -gt $lastcurrent_time ] && [ $((current_time % $interrupt_tick)) -eq 0 ] && [ ${count} -gt 1 ]; then # Interrupt Connection - requires root and linux kernel >= 4.9 in order to work! echo "**** omazureeventhubs WAITING: Interrupt Connection on ${interrupt_host}:${interrupt_port}" sudo ss -K dst ${interrupt_host} dport = ${interrupt_port} fi lastcurrent_time=$current_time fi fi fi $TESTTOOL_DIR/msleep 1000 done unset count shutdown_when_empty wait_shutdown error_exit 1 rsyslog-8.2608.0/tests/PaxHeaders/timegenerated-dateordinal.sh0000644000000000000000000000013215241075234021341 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.799581927 30 ctime=1787067805.844938415 rsyslog-8.2608.0/tests/timegenerated-dateordinal.sh0000775000175000017500000000725315241075234021017 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # addd 2016-03-02 by RGerhards, released under ASL 2.0 # Note: we run several subtests here in order to save us # from creating additional tests # requires faketime echo \[timegenerated-dateordinal\]: check valid dates with ordinal format . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=UTC+00:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%timegenerated:::date-ordinal%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' echo "***SUBTEST: check 1970-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='1970-01-01 00:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact echo "***SUBTEST: check 2000-03-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2000-03-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="061" cmp_exact echo "***SUBTEST: check 2016-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2016-01-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact echo "***SUBTEST: check 2016-02-29" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2016-02-29 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="060" cmp_exact echo "***SUBTEST: check 2016-03-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2016-03-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="061" cmp_exact echo "***SUBTEST: check 2016-03-03" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2016-03-03 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="063" cmp_exact echo "***SUBTEST: check 2016-12-31" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2016-12-31 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="366" cmp_exact echo "***SUBTEST: check 2017-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2017-01-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact echo "***SUBTEST: check 2020-03-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2020-03-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="061" cmp_exact echo "***SUBTEST: check 2038-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2038-01-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact rsyslog_testbench_require_y2k38_support echo "***SUBTEST: check 2038-12-31" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2038-12-31 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="365" cmp_exact echo "***SUBTEST: check 2040-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2040-01-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact echo "***SUBTEST: check 2040-12-31" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2040-12-31 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="366" cmp_exact echo "***SUBTEST: check 2100-01-01" rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest FAKETIME='2100-01-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="001" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-basic-ignorecodes-vg.sh0000644000000000000000000000013215171370365021550 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.883790455 30 ctime=1787067806.176944602 rsyslog-8.2608.0/tests/omhttp-basic-ignorecodes-vg.sh0000775000175000017500000000012115171370365021211 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-basic-ignorecodes.sh rsyslog-8.2608.0/tests/PaxHeaders/imrelp-manyconn.sh0000644000000000000000000000013015035412264017345 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.883790455 29 ctime=1787067807.68697274 rsyslog-8.2608.0/tests/imrelp-manyconn.sh0000777000175000017500000000121115035412264017013 0ustar00rgerrger#!/bin/bash # adddd 2016-06-08 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" export NUMMESSAGES=100000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" port="'$TCPFLOOD_PORT'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -Trelp-plain -c-2000 -p$TCPFLOOD_PORT -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_table_no_hup_reload.sh0000644000000000000000000000013215035412264021615 xustar0030 mtime=1752569012.399757696 30 atime=1782715518.882790438 30 ctime=1787067804.963921998 rsyslog-8.2608.0/tests/lookup_table_no_hup_reload.sh0000777000175000017500000000176515035412264021277 0ustar00rgerrger#!/bin/bash # test for lookup-table with HUP based reloading disabled # added 2015-09-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="off") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown assert_content_missing "foo_new" assert_content_missing "bar_new" assert_content_missing "baz" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_all_empty_vg.sh0000644000000000000000000000013215171370365021510 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.882790438 30 ctime=1787067806.975959491 rsyslog-8.2608.0/tests/rscript_faup_all_empty_vg.sh0000775000175000017500000000021215171370365021152 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_all_empty.sh rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-good-template.sh0000644000000000000000000000013215171370365021142 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.881790421 30 ctime=1787067806.298946875 rsyslog-8.2608.0/tests/omazuredce-good-template.sh0000775000175000017500000000240215171370365020607 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . ${srcdir:=.}/omazuredce-env.sh require_plugin "omazuredce" omazuredce_require_env export NUMMESSAGES=1 generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omazuredce/.libs/omazuredce") template(name="tplAzureDceGood" type="string" string="{\"message\":\"%msg:::json%\"}") local4.* action( type="omazuredce" template="tplAzureDceGood" client_id="'$AZURE_DCE_CLIENT_ID'" client_secret=`echo $AZURE_DCE_CLIENT_SECRET` tenant_id="'$AZURE_DCE_TENANT_ID'" dce_url="'$AZURE_DCE_URL'" dcr_id="'$AZURE_DCE_DCR_ID'" table_name="'$AZURE_DCE_TABLE_NAME'" max_batch_bytes="1048576" flush_timeout_ms="0" action.resumeInterval="1" action.resumeRetryCount="1" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown content_check "omazuredce: posted batch records=" error_count=$(grep -c -F "omazuredce: message template must render a JSON object" < "$RSYSLOG_OUT_LOG") if [ "${error_count:=0}" -ne 0 ]; then echo "FAIL: valid template unexpectedly triggered template validation error" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_number_comparison_LE-vg.sh0000644000000000000000000000013215171370365022527 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.881790421 30 ctime=1787067805.228926936 rsyslog-8.2608.0/tests/rscript_number_comparison_LE-vg.sh0000775000175000017500000000012515171370365022174 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_number_comparison_LE.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-cleanup-failure.sh0000644000000000000000000000013215241075234022562 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 30 ctime=1787067803.859901425 rsyslog-8.2608.0/tests/segmented-da-idle-cleanup-failure.sh0000775000175000017500000000474515241075234022243 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Force idle cleanup to encounter an unexpected file in the private store # directory. The first cleanup must fail visibly while restoring a valid empty # materialized store and keeping its worker alive. The restored state must # reference one newly created active segment, proving partially removed old # topology cannot be stranded beside the replacement state. Removing the # blocker must allow the next complete idle interval to dematerialize normally. # The 30-second path waits are event-driven; the generous bound only prevents # a hung cleanup worker from stalling overloaded parallel CI indefinitely. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" SEG_DIR="$SPOOL_DIR/cleanup-failure.segq" STATS_FILE="${RSYSLOG_DYNNAME}.stats" wait_path() { local mode="$1" path="$2" timeoutend=$((SECONDS + 30)) while true; do [ "$mode" = present ] && [ -e "$path" ] && return [ "$mode" = absent ] && [ ! -e "$path" ] && return [ "$SECONDS" -ge "$timeoutend" ] && error_exit 1 "path did not become $mode: $path" ./msleep 50 done } generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") module(load="../plugins/impstats/.libs/impstats" interval="1" log.syslog="off" log.file="'"$STATS_FILE"'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" name="cleanup-failure" file="'"$RSYSLOG_OUT_LOG"'" template="outfmt" queue.type="LinkedList" queue.filename="cleanup-failure" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.dequeueSlowdown="5" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="200") ' startup injectmsg wait_path present "$SEG_DIR" touch "$SEG_DIR/blocker" wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" 300 wait_content 'store.idleCleanupFailures=1' "$STATS_FILE" wait_path present "$SEG_DIR/state" find "$SEG_DIR" -maxdepth 1 -name '*.open' -print -quit | grep -q . || error_exit 1 "cleanup failure did not restore an active segment" segment_count=$(find "$SEG_DIR" -maxdepth 1 -type f -name 'segment-*' -print | wc -l) [ "$segment_count" -eq 1 ] || error_exit 1 "cleanup failure retained $segment_count segments instead of one replacement active segment" rm -f "$SEG_DIR/blocker" wait_path absent "$SEG_DIR" wait_content 'store.idleDematerializations=1' "$STATS_FILE" shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_gtls_serveranon_mbedtls_clientanon.sh0000644000000000000000000000013215216464436025650 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.881790421 30 ctime=1787067807.410967597 rsyslog-8.2608.0/tests/sndrcv_tls_gtls_serveranon_mbedtls_clientanon.sh0000775000175000017500000000355015216464436025322 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="anon" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-missing-state.sh0000644000000000000000000000013215241075234022775 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.735899115 rsyslog-8.2608.0/tests/segmented-diskqueue-missing-state.sh0000775000175000017500000000026115241075234022443 0ustar00rgerrger#!/bin/bash # Missing-state wrapper for fail-fast offline-recovery coverage. export STATE_MUTATION=missing . ${srcdir:=.}/testsuites/segmented-diskqueue-invalid-state-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/json-onempty-at-end.sh0000644000000000000000000000013215131231047020042 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.880790404 30 ctime=1787067804.250908712 rsyslog-8.2608.0/tests/json-onempty-at-end.sh0000777000175000017500000000120515131231047017511 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # written 2019-05-10 by Rainer Gerhards . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="json" type="list" option.jsonf="on") { property(outname="empty_null" format="jsonf" name="$!empty" onEmpty="null") property(outname="empty_skip" format="jsonf" name="$!empty" onEmpty="skip") } set $!val0 = 0; set $!val = 42; set $!empty = ""; set $!string = "1.2.3.4"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="json") ' startup shutdown_when_empty wait_shutdown content_check '{"empty_null":null}' check_not_present 'empty_skip' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdocker-basic-vg.sh0000644000000000000000000000013215171370365017533 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.879790387 30 ctime=1787067806.354947918 rsyslog-8.2608.0/tests/imdocker-basic-vg.sh0000775000175000017500000000010715171370365017200 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imdocker-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_mozilla_tld_vg.sh0000644000000000000000000000013115171370365022033 xustar0030 mtime=1776677109.469913511 29 atime=1782715518.87879037 30 ctime=1787067807.008960105 rsyslog-8.2608.0/tests/rscript_faup_mozilla_tld_vg.sh0000775000175000017500000000021415171370365021500 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_mozilla_tld.sh rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_kafka_multi_topics.sh0000644000000000000000000000013015216464436021475 xustar0029 mtime=1782212894.08226709 29 atime=1782715518.87879037 30 ctime=1787067806.263946223 rsyslog-8.2608.0/tests/sndrcv_kafka_multi_topics.sh0000775000175000017500000001144015216464436021146 0ustar00rgerrger#!/bin/bash # added 2018-08-13 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 : "${STARTUP_MAX_RUNTIME:=300}" export STARTUP_MAX_RUNTIME . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full export TESTMESSAGES=50000 export TESTMESSAGESFULL=100000 # Generate random topic name RANDTOPIC1="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC1 RANDTOPIC2="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC2 # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka echo STEP: Check and Stop previous instances of kafka/zookeeper download_kafka stop_zookeeper stop_kafka echo STEP: Create kafka/zookeeper instance and topics start_zookeeper start_kafka create_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181' create_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181' # --- Create omkafka sender config export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/omkafka/.libs/omkafka") template(name="outfmt" type="string" string="%msg%\n") local4.* action( name="kafka-fwd" type="omkafka" topic="'$RANDTOPIC1'" broker="localhost:29092" template="outfmt" confParam=[ "compression.codec=none", "socket.timeout.ms=10000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "queue.buffering.max.messages=10000", "enable.auto.commit=true", "message.send.max.retries=1"] topicConfParam=["message.timeout.ms=10000"] partitions.auto="on" closeTimeout="60000" resubmitOnFailure="on" keepFailedMessages="on" failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC1'.data" action.resumeInterval="1" action.resumeRetryCount="10" queue.saveonshutdown="on" ) local4.* action( name="kafka-fwd-2" type="omkafka" topic="'$RANDTOPIC2'" broker="localhost:29092" template="outfmt" confParam=[ "compression.codec=none", "socket.timeout.ms=10000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "queue.buffering.max.messages=10000", "enable.auto.commit=true", "message.send.max.retries=1"] topicConfParam=["message.timeout.ms=10000"] partitions.auto="on" closeTimeout="60000" resubmitOnFailure="on" keepFailedMessages="on" failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC2'.data" action.resumeInterval="1" action.resumeRetryCount="10" queue.saveonshutdown="on" ) syslog.* action(type="omfile" file="'$RSYSLOG_DYNNAME.sender.syslog'") ' echo STEP: Starting sender instance [omkafka] startup # --- # Injection messages now before starting receiver, simply because omkafka will take some time and # there is no reason to wait for the receiver to startup first. echo STEP: Inject messages into rsyslog sender instance injectmsg 1 $TESTMESSAGES # --- Create omkafka receiver config export RSYSLOG_DEBUGLOG="log2" generate_conf 2 add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") /* Polls messages from kafka server!*/ input( type="imkafka" topic="'$RANDTOPIC1'" broker="localhost:29092" consumergroup="default1" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=10000", "enable.partition.eof=false", "reconnect.backoff.jitter.ms=1000", "socket.keepalive.enable=true"] ) input( type="imkafka" topic="'$RANDTOPIC2'" broker="localhost:29092" consumergroup="default2" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=10000", "enable.partition.eof=false", "reconnect.backoff.jitter.ms=1000", "socket.keepalive.enable=true"] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) } syslog.* action(type="omfile" file="'$RSYSLOG_DYNNAME.receiver.syslog'") ' 2 echo STEP: Starting receiver instance [imkafka] startup 2 # --- echo STEP: Stopping sender instance [omkafka] shutdown_when_empty wait_shutdown echo STEP: Stopping receiver instance [imkafka] kafka_wait_group_coordinator shutdown_when_empty 2 wait_shutdown 2 echo STEP: delete kafka topics delete_kafka_topic $RANDTOPIC1 '.dep_wrk' '22181' delete_kafka_topic $RANDTOPIC2 '.dep_wrk' '22181' kafka_check_broken_broker "$RSYSLOG_DYNNAME.sender.syslog" kafka_check_broken_broker "$RSYSLOG_DYNNAME.receiver.syslog" # Dump Kafka log | uncomment if needed # dump_kafka_serverlog # Do the final sequence check seq_check 1 $TESTMESSAGES -d linecount=$(wc -l < ${RSYSLOG_OUT_LOG}) if [ $linecount -ge $TESTMESSAGESFULL ]; then echo "Info: Count correct: $linecount" else echo "Count error detected in $RSYSLOG_OUT_LOG" echo "number of lines in file: $linecount" error_exit 1 fi echo success exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdocker-new-logs-from-start-vg.sh0000644000000000000000000000013115171370365022300 xustar0030 mtime=1776677109.460913372 29 atime=1782715518.87879037 30 ctime=1787067806.362948068 rsyslog-8.2608.0/tests/imdocker-new-logs-from-start-vg.sh0000775000175000017500000000012515171370365021746 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imdocker-new-logs-from-start.sh rsyslog-8.2608.0/tests/PaxHeaders/imtuxedoulog_errmsg_no_params.sh0000644000000000000000000000013215035412264022402 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.875790319 30 ctime=1787067808.178981908 rsyslog-8.2608.0/tests/imtuxedoulog_errmsg_no_params.sh0000777000175000017500000000057315035412264022060 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imtuxedoulog/.libs/imtuxedoulog") input(type="imtuxedoulog") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "parameter 'ulogbase' required but not specified" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-retry-timeout-vg.sh0000644000000000000000000000013115171370365021020 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.874790302 30 ctime=1787067806.193944919 rsyslog-8.2608.0/tests/omhttp-retry-timeout-vg.sh0000775000175000017500000000011515171370365020465 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-retry-timeout.sh rsyslog-8.2608.0/tests/PaxHeaders/msgdup.sh0000644000000000000000000000013115131231047015530 xustar0029 mtime=1768239655.71021268 30 atime=1782715518.874790302 30 ctime=1787067804.387911265 rsyslog-8.2608.0/tests/msgdup.sh0000777000175000017500000000240615131231047015204 0ustar00rgerrger#!/bin/bash # This tests the border case that a message is exactly as large as the default # buffer size (101 chars) and is reduced in size afterwards. This has been seen # in practice. # see also https://github.com/rsyslog/rsyslog/issues/1658 # Copyright (C) 2017 by Rainer Gerhards, released under ASL 2.0 (2017-07-11) . ${srcdir:=.}/diag.sh init check_logger_has_option_d generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="rs" queue.type="LinkedList") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") stop } *.=notice call rs ' startup logger -d -u $RSYSLOG_DYNNAME-testbench_socket -t RSYSLOG_TESTBENCH 'test 01234567890123456789012345678901234567890123456789012345 ' #Note: LF at end of message is IMPORTANT, it is bug triggering condition # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! export EXPECTED=" test 01234567890123456789012345678901234567890123456789012345" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/incltest_dir.sh0000644000000000000000000000013215035412264016722 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.889790557 30 ctime=1787067804.944921644 rsyslog-8.2608.0/tests/incltest_dir.sh0000777000175000017500000000103515035412264016372 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf env|grep src echo ac_top_srcdir: $ac_top_srcdir echo FULL ENV: env echo FS info: set -x pwd echo "srcdir: $srcdir" ls -l ${srcdir}/testsuites/incltest.d/ ls -l ${srcdir}/testsuites find ../../../.. -name incltest.d set +x add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/ " startup # 100 messages are enough - the question is if the include is read ;) injectmsg 0 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-corruption-codec.sh0000644000000000000000000000013215241075234023465 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.729899003 rsyslog-8.2608.0/tests/segmented-diskqueue-corruption-codec.sh0000775000175000017500000000025415241075234023135 0ustar00rgerrger#!/bin/bash # Run the segmentedDisk corruption driver with valid payload CRC but invalid TLV. export CORRUPTION_KIND=codec . ${srcdir:=.}/segmented-diskqueue-corruption.sh rsyslog-8.2608.0/tests/PaxHeaders/es-maxbytes-bulk.sh0000644000000000000000000000013015132733117017432 xustar0029 mtime=1768666703.95662098 29 atime=1782715518.88879054 30 ctime=1787067803.926902674 rsyslog-8.2608.0/tests/es-maxbytes-bulk.sh0000777000175000017500000000152215132733117017105 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_PORT=19200 export NUMMESSAGES=10000 export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check ensure_elasticsearch_ready init_elasticsearch generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") :msg, contains, "msgnum:" action(type="omelasticsearch" template="tpl" serverport="'$ES_PORT'" searchIndex="rsyslog_testbench" bulkmode="on" maxbytes="1k") ' startup injectmsg shutdown_when_empty wait_shutdown es_getdata $NUMMESSAGES $ES_PORT seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrabbitmq_data_1server-vg.sh0000644000000000000000000000013115171370365021453 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.889790557 30 ctime=1787067806.533951254 rsyslog-8.2608.0/tests/omrabbitmq_data_1server-vg.sh0000775000175000017500000000021415171370365021120 0ustar00rgerrger#!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/omrabbitmq_data_1server.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_b64_decode-vg.sh0000644000000000000000000000013115171370365020322 xustar0030 mtime=1776677109.468913495 29 atime=1782715518.88879054 30 ctime=1787067805.153925539 rsyslog-8.2608.0/tests/rscript_b64_decode-vg.sh0000775000175000017500000000033615171370365017774 0ustar00rgerrger#!/bin/bash # test for b64_decode function in rainerscript # added 2024-06-11 by KGuillemot # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_b64_decode.sh rsyslog-8.2608.0/tests/PaxHeaders/test_id_usage_output.sh0000644000000000000000000000013215035412264020476 xustar0030 mtime=1752569012.416639571 30 atime=1782715518.887790523 30 ctime=1787067804.028904575 rsyslog-8.2608.0/tests/test_id_usage_output.sh0000777000175000017500000000042315035412264020146 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./test_id &> $RSYSLOG_DYNNAME.output grep "usage: test_id" $RSYSLOG_DYNNAME.output if [ ! $? -eq 0 ]; then echo "invalid response generated" error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_ccmiddle_syssock.sh0000644000000000000000000000013215145046113021501 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.887790523 30 ctime=1787067804.689916892 rsyslog-8.2608.0/tests/imuxsock_ccmiddle_syssock.sh0000775000175000017500000000165415145046113021156 0ustar00rgerrger#!/bin/bash # test trailing LF handling in imuxsock # part of rsyslog, released under ASL 2.0 . ${srcdir:=.}/diag.sh init uname if [ $(uname) = "SunOS" ] ; then echo "Solaris: FIX ME" exit 77 fi ./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # send a message with trailing LF ./syslog_caller -fsyslog_inject-c -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" shutdown_when_empty wait_shutdown export EXPECTED=" test 1#0112" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-dflt-tpl.sh0000644000000000000000000000013115132733117020114 xustar0029 mtime=1768666703.95462095 30 atime=1782715518.887790523 30 ctime=1787067805.784937297 rsyslog-8.2608.0/tests/clickhouse-dflt-tpl.sh0000777000175000017500000000155515132733117017574 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" bulkmode="off" user="default" pwd="") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.SystemEvents ( severity Int8, facility Int8, timestamp DateTime, hostname String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity order by tuple()" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="SELECT * FROM rsyslog.SystemEvents FORMAT CSV" > $RSYSLOG_OUT_LOG clickhouse-client --query="DROP TABLE rsyslog.SystemEvents" content_check --regex '7,20,"20..-03-01 01:00:00","192.0.2.8","tag"," msgnum:00000000:"' exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-neither_rule_rulebase-vg.sh0000644000000000000000000000013215171370365023561 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.889790557 30 ctime=1787067807.080961447 rsyslog-8.2608.0/tests/pmnormalize-neither_rule_rulebase-vg.sh0000775000175000017500000000023015171370365023223 0ustar00rgerrger#!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/pmnormalize-neither_rule_rulebase.sh rsyslog-8.2608.0/tests/PaxHeaders/imbeats-json-trailing-data.sh0000644000000000000000000000013215241075234021351 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.683579755 30 ctime=1787067806.469950061 rsyslog-8.2608.0/tests/imbeats-json-trailing-data.sh0000775000175000017500000000621615241075234021025 0ustar00rgerrger#!/bin/bash # Regression coverage for strict JSON-frame consumption. A real imbeats # listener receives frames whose declared payload is a valid object followed # by either non-whitespace garbage or a second JSON value, plus non-object and # malformed controls. A two-event window with a valid first event and malformed # second event proves the entire batch is validated before any submission. The # peer closing without an ACK is the rejection oracle; a timeout is a failure # because it would leave the malformed session alive. A fresh, legitimate # object must then be submitted and cumulatively ACKed, proving strict rejection # did not damage normal Lumberjack v2 traffic. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%$!message%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" if ! $PYTHON - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys port = int(sys.argv[1]) def wire(payload, seq=1): return ( b"2W" + struct.pack(">I", 1) + b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload ) def batch_wire(payloads): frames = [b"2W" + struct.pack(">I", len(payloads))] for seq, payload in enumerate(payloads, 1): frames.append( b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload ) return b"".join(frames) def require_wire_rejected(frame): with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(5) sock.sendall(frame) try: data = sock.recv(6) except (ConnectionResetError, BrokenPipeError): return except socket.timeout as exc: raise SystemExit("malformed JSON session was not closed") from exc if data: raise SystemExit(f"unexpected ACK for malformed JSON: {data.hex()}") def require_rejected(payload): require_wire_rejected(wire(payload)) valid_prefix = b'{"message":"must-not-submit"}' require_rejected(valid_prefix + b"garbage") require_rejected(valid_prefix + b'{"message":"second-value"}') require_rejected(b"[]") require_rejected(b'"scalar"') require_rejected(b'{"message":') require_wire_rejected(batch_wire([b'{"message":"must-not-partially-submit"}', b'{"message":'])) payload = b" \t" + json.dumps({"message": "strict-json-control"}, separators=(",", ":")).encode() + b"\r\n" with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(5) sock.sendall(wire(payload)) ack = sock.recv(6) if ack != b"2A" + struct.pack(">I", 1): raise SystemExit(f"unexpected control ACK: {ack.hex()}") print(ack.hex()) PY then error_exit 1 fi shutdown_when_empty wait_shutdown EXPECTED='strict-json-control' cmp_exact export EXPECTED='324100000001' cmp_exact "$RSYSLOG_DYNNAME.imbeats.ack" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-kafkarest-retry-vg.sh0000644000000000000000000000013115171370365022364 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.889790557 30 ctime=1787067806.186944788 rsyslog-8.2608.0/tests/omhttp-batch-kafkarest-retry-vg.sh0000775000175000017500000000012515171370365022032 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-batch-kafkarest-retry.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-missing-checkpoint.sh0000644000000000000000000000013215241075234024004 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.733899078 rsyslog-8.2608.0/tests/segmented-diskqueue-missing-checkpoint.sh0000775000175000017500000000367015241075234023461 0ustar00rgerrger#!/bin/bash # Verify corrupting both fixed-size state slots fails the queue immediately. # A backlog is created first; the oracle is prompt startup failure with the # offline-recovery diagnostic, never a synchronous segment scan. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" write_conf() { generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'"$SPOOL_DIR"'") main_queue( queue.type="segmentedDisk" queue.filename="mainq" queue.maxFileSize="32k" queue.dequeueBatchSize="32" queue.saveOnShutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") '"$1"' if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' } write_conf ':omtesting:sleep 0 10000' startup wait_rsyslog_instance_pid injectmsg 0 "$NUMMESSAGES" . "$srcdir/diag.sh" kill-immediate wait_shutdown if [ "$(wc -c < "$SPOOL_DIR/mainq.segq/state")" -ne 512 ]; then echo "FAIL: phase one did not create the two-slot state file" error_exit 1 fi dd if=/dev/zero of="$SPOOL_DIR/mainq.segq/state" bs=512 count=1 conv=notrunc status=none write_conf '# startup must fail before processing the backlog' fail_log="${RSYSLOG_DYNNAME}.invalid-state.log" ../tools/rsyslogd -C -n -i"${RSYSLOG_DYNNAME}.invalid.pid" \ -M../runtime/.libs:../.libs -f"${TESTCONF_NM}.conf" >"$fail_log" 2>&1 & invalid_pid=$! state_error_seen=0 for _ in {1..50}; do if grep -q "no valid state slot; offline recovery is required" "$fail_log"; then state_error_seen=1 break fi sleep .1 done kill -KILL "$invalid_pid" 2>/dev/null || true wait "$invalid_pid" 2>/dev/null || true rm -f "${RSYSLOG_DYNNAME}.invalid.pid" if [ "$state_error_seen" -ne 1 ]; then echo "FAIL: invalid-state offline recovery diagnostic was not reported" cat "$fail_log" error_exit 1 fi rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-single-instance-vg.sh0000644000000000000000000000013115171370365021242 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.889790557 30 ctime=1787067806.105943278 rsyslog-8.2608.0/tests/omprog-single-instance-vg.sh0000775000175000017500000000020615171370365020710 0ustar00rgerrger#!/bin/bash # addd 2019-04-15 by RGerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/omprog-single-instance.sh rsyslog-8.2608.0/tests/PaxHeaders/template-property-timereceived.sh0000644000000000000000000000013215241075234022400 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.695579979 30 ctime=1787067805.851938545 rsyslog-8.2608.0/tests/template-property-timereceived.sh0000775000175000017500000000227415241075234022054 0ustar00rgerrger#!/bin/bash # This focused template/property test proves that timereceived is accepted as a # message property alias for timegenerated and formats the same received-time # value under deterministic faketime. . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST+02:00 generate_conf add_conf ' template(name="outfmt" type="list") { constant(value="generated=") property(name="timegenerated" dateformat="rfc3339" date.inUTC="on") constant(value="\nreceived=") property(name="timereceived" dateformat="rfc3339" date.inUTC="on") constant(value="\nlegacy=") property(name="timegenerated" dateformat="unixtimestamp") constant(value="\nalias=") property(name="timereceived" dateformat="unixtimestamp") constant(value="\n") } local4.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' export FAKETIME='2016-03-01 12:34:56' startup injectmsg_literal '<167>1 2003-08-24T05:14:15.000003-07:00 host app proc msgid - trigger' wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" 4 shutdown_when_empty wait_shutdown export EXPECTED='generated=2016-03-01T14:34:56.000000+00:00 received=2016-03-01T14:34:56.000000+00:00 legacy=1456842896 alias=1456842896' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/validate_json_shell.sh0000644000000000000000000000013215132733117020251 xustar0030 mtime=1768666703.970621192 30 atime=1782715518.889790557 30 ctime=1787067808.226982803 rsyslog-8.2608.0/tests/validate_json_shell.sh0000666000175000017500000000754115132733117017726 0ustar00rgerrger#!/bin/bash # JSON equality validator using shell tools as fallback # This script provides a simpler validation when Python is not available validate_json_with_jq() { local input_file="$1" local output_file="$2" local cookie="$3" echo "Using jq for JSON validation..." local line_num=1 local all_passed=true while IFS= read -r input_line && IFS= read -r output_line <&3; do # Extract JSON from input (remove cookie) local input_json="${input_line#*$cookie}" input_json="${input_json# }" # remove leading space # Skip empty lines if [ -z "$input_json" ] && [ -z "$output_line" ]; then continue fi # Validate both are valid JSON and compare local input_normalized local output_normalized if input_normalized=$(echo "$input_json" | jq -S -c . 2>/dev/null) && \ output_normalized=$(echo "$output_line" | jq -S -c . 2>/dev/null); then if [ "$input_normalized" = "$output_normalized" ]; then echo "Line $line_num: ✓ JSON semantically equal" else echo "Line $line_num: ✗ JSON differs" echo " Expected: $input_normalized" echo " Actual: $output_normalized" all_passed=false fi else echo "Line $line_num: ✗ JSON parsing failed" echo " Input: $input_json" echo " Output: $output_line" all_passed=false fi ((line_num++)) done < "$input_file" 3< "$output_file" if [ "$all_passed" = true ]; then echo "✓ All JSON validations passed with jq!" return 0 else echo "✗ JSON validation failed with jq!" return 1 fi } basic_field_check() { local input_file="$1" local output_file="$2" local cookie="$3" echo "Performing basic field presence check..." # Extract some key fields that should be present local expected_fields=("name" "version" "type" "src" "dst" "payload") local all_found=true for field in "${expected_fields[@]}"; do if grep -q "\"$field\":" "$input_file" && grep -q "\"$field\":" "$output_file"; then echo "✓ Field '$field' found in both input and output" else echo "✗ Field '$field' missing or mismatched" all_found=false fi done if [ "$all_found" = true ]; then echo "✓ Basic field validation passed!" return 0 else echo "✗ Basic field validation failed!" return 1 fi } main() { local input_file="$1" local output_file="$2" local cookie="${3:-<01> @cee:}" if [ $# -lt 2 ]; then echo "Usage: $0 [cookie]" echo "Example: $0 testsuites/qradar_json rsyslog.out.log '<01> @cee:'" exit 1 fi echo "Validating JSON equality between $input_file and $output_file" echo "Using cookie: $cookie" echo "--------------------------------------------------" # Check if jq is available and decide validation method if command -v jq >/dev/null 2>&1; then # jq is available, use it for validation (exit immediately if it fails) if validate_json_with_jq "$input_file" "$output_file" "$cookie"; then exit 0 else echo "✗ JSON validation failed with jq!" exit 1 fi else # jq not available, use basic validation echo "jq not available, using basic field validation..." if basic_field_check "$input_file" "$output_file" "$cookie"; then echo "Note: Used basic validation due to jq unavailability" exit 0 else echo "✗ JSON validation failed!" exit 1 fi fi } main "$@"rsyslog-8.2608.0/tests/PaxHeaders/omfwd-lb-2target-impstats.sh0000644000000000000000000000013215132411300021142 xustar0030 mtime=1768559296.289886004 30 atime=1782715518.889790557 30 ctime=1787067806.729954907 rsyslog-8.2608.0/tests/omfwd-lb-2target-impstats.sh0000777000175000017500000000346615132411300020624 0ustar00rgerrger#!/bin/bash # added 2024-02-24 by rgerhards. Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf export NUMMESSAGES=1000 # MUST be an EVEN number! export STATSFILE="$RSYSLOG_DYNNAME.stats" # starting minitcpsrvr receives so that we can obtain their port # numbers start_minitcpsrvr $RSYSLOG_OUT_LOG 1 start_minitcpsrvr $RSYSLOG2_OUT_LOG 2 # regular startup add_conf ' $MainMsgQueueTimeoutShutdown 10000 module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1" ruleset="stats") template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="builtin:omfwd" template="outfmt") if $msg contains "msgnum:" then { action(type="omfwd" target=["127.0.0.1", "127.0.0.1"] port=["'$MINITCPSRVR_PORT1'", "'$MINITCPSRVR_PORT2'"] protocol="tcp" pool.resumeInterval="10" action.resumeRetryCount="-1" action.resumeInterval="5") } ' # now do the usual run startup injectmsg shutdown_when_empty wait_shutdown if [ "$(wc -l < $RSYSLOG_OUT_LOG)" != "$(( NUMMESSAGES / 2 ))" ]; then echo "ERROR: RSYSLOG_OUT_LOG has invalid number of messages $(( NUMMESSAGES / 2 ))" error_exit 100 fi if [ "$(wc -l < $RSYSLOG2_OUT_LOG)" != "$(( NUMMESSAGES / 2 ))" ]; then echo "ERROR: RSYSLOG2_OUT_LOG has invalid number of messages $(( NUMMESSAGES / 2 ))" error_exit 100 fi # combine both files to check for correct message content export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.log-combined" cat "$RSYSLOG_OUT_LOG" "$RSYSLOG2_OUT_LOG" > "$SEQ_CHECK_FILE" seq_check export MSGS_PER_TARGET="$((NUMMESSAGES / 2))" echo msg per target $MSGS_PER_TARGET # check pstats - that's our prime test target echo content_check --regex "TCP-.*origin=omfwd .*messages.sent=$MSGS_PER_TARGET" "$STATSFILE" content_check --regex "TCP-.*origin=omfwd .*messages.sent=$MSGS_PER_TARGET" "$STATSFILE" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-logrotate-multiple.sh0000644000000000000000000000013215171370365021341 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.889790557 30 ctime=1787067808.020978964 rsyslog-8.2608.0/tests/imfile-logrotate-multiple.sh0000775000175000017500000000401415171370365021007 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . $srcdir/diag.sh check-inotify-only . ${srcdir:=.}/diag.sh init check_command_available logrotate export IMFILEROTATES="10" export TESTMESSAGES=10000 export TESTMESSAGESFULL=$((IMFILEROTATES * TESTMESSAGES-1)) generate_conf add_conf ' global( workDirectory="'$RSYSLOG_DYNNAME'.spool" /* Filter out busy debug output */ debug.whitelist="off" debug.files=["omfile.c", "queue.c", "rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"] ) module(load="../plugins/imfile/.libs/imfile" mode="inotify") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" Severity="error" Facility="local7" addMetadata="on") $template outfmt,"%msg:F,58:2%\n" if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' # Write logrotate config file echo '"./'$RSYSLOG_DYNNAME'.input" { su '"$(id -un)"' '"$(id -gn)"' create daily missingok rotate 14 notifempty compress delaycompress }' > $RSYSLOG_DYNNAME.logrotate display_file() { printf '\nFILE %s content:\n' $1 cat -n $1 } startup TESTMESSAGESSTART=0 for i in $(seq 1 $IMFILEROTATES); do #printf 'PRESS ENTER TO CONTINUE\n' #read printf '\n\nNEW RUN:\n' ./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGESSTART > $RSYSLOG_DYNNAME.input ls -li $RSYSLOG_DYNNAME.input* echo ls ${RSYSLOG_DYNNAME}.spool: ls -li ${RSYSLOG_DYNNAME}.spool echo STATE FILE CONTENT: shopt -s extglob for filename in "$RSYSLOG_DYNNAME.spool"/imfile-state:*; do display_file $filename; done # Wait until testmessages are processed by imfile! msgcount=$((i * TESTMESSAGES-1)) # echo "TESTMESSAGESSTART: $TESTMESSAGESSTART - TotalMsgCount: $msgcount" wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES # Logrotate on logfile logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate TESTMESSAGESSTART=$((TESTMESSAGESSTART+TESTMESSAGES)) done shutdown_when_empty wait_shutdown seq_check 0 $TESTMESSAGESFULL exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmkubernetes-basic-vg.sh0000644000000000000000000000013115216464436020441 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.889790557 30 ctime=1787067808.154981461 rsyslog-8.2608.0/tests/mmkubernetes-basic-vg.sh0000775000175000017500000002446115216464436020120 0ustar00rgerrger#!/bin/bash # added 2018-04-06 by richm, released under ASL 2.0 # # Note: on buildbot VMs (where there is no environment cleanup), the # kubernetes test server may be kept running if the script aborts or # is aborted (buildbot master failure!) for some reason. As such we # execute it under "timeout" control, which ensure it always is # terminated. It's not a 100% great method, but hopefully does the # trick. -- rgerhards, 2018-07-21 # # Valgrind variant of mmkubernetes-basic.sh. It keeps the same enrichment and # statistics oracle while checking the mmkubernetes path under Valgrind. #export RSYSLOG_DEBUG="debug" USE_VALGRIND=true . ${srcdir:=.}/diag.sh init check_command_available timeout pwd=$( pwd ) k8s_srv_port_file="${RSYSLOG_DYNNAME}mmk8s-test-server.port" generate_conf testsrv=mmk8s-test-server echo starting kubernetes \"emulator\" timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py 0 ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started ${k8s_srv_port_file} > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_file_exists "$k8s_srv_port_file" k8s_srv_port="$(cat "$k8s_srv_port_file")" wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started echo background mmkubernetes_test_server.py process id is $BGPROCESS add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") module(load="../plugins/impstats/.libs/impstats" interval="1" log.file="'"$RSYSLOG_DYNNAME.spool"'/mmkubernetes-stats.log" log.syslog="off" format="cee") module(load="../plugins/imfile/.libs/imfile") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../contrib/mmkubernetes/.libs/mmkubernetes") template(name="mmk8s_template" type="list") { property(name="$!all-json-plain") constant(value="\n") } input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on") action(type="mmjsonparse" cookie="") action(type="mmkubernetes" busyretryinterval="1" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'" filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:.%.%container_hash:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log", "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"] ) action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="mmk8s_template") ' cat > ${RSYSLOG_DYNNAME}.spool/pod-error1.log < ${RSYSLOG_DYNNAME}.spool/pod-error2.log < ${RSYSLOG_DYNNAME}.spool/pod-name1_namespace-name1_container-name1-id1.log < ${RSYSLOG_DYNNAME}.spool/pod-name2.container-hash2_namespace-name2_container-name2-id2.log < ${RSYSLOG_DYNNAME}.spool/pod-name3.log < ${RSYSLOG_DYNNAME}.spool/pod-name4.log < ${RSYSLOG_DYNNAME}.spool/pod-name5.log < ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-error.log <= 0: hsh = json.loads(line[jstart:]) if hsh["origin"] == "mmkubernetes": actual = hsh assert(expected == actual) ' $k8s_srv_port || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log; } else echo error: stats file ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log not found rc=1 fi if [ ${rc:-0} -ne 0 ]; then echo echo "FAIL: expected data not found. $RSYSLOG_OUT_LOG is:" cat ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log cat $RSYSLOG_OUT_LOG cat ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_re_match_i.sh0000644000000000000000000000013115241075234020077 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067804.795918868 rsyslog-8.2608.0/tests/rscript_re_match_i.sh0000775000175000017500000000125415241075234017551 0ustar00rgerrger#!/bin/bash # added 2015-09-29 by singh.janmejay # test re_match rscript-fn, using single quotes for the match # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="*Matched*\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if (re_match_i($msg, "RANDOM NUMBER")) then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m 1 -I $srcdir/testsuites/date_time_msg shutdown_when_empty wait_shutdown content_check "*Matched*" exit_test rsyslog-8.2608.0/tests/PaxHeaders/uxsock_action_isolation.sh0000644000000000000000000000013215241075234021172 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.696579998 30 ctime=1787067807.652972106 rsyslog-8.2608.0/tests/uxsock_action_isolation.sh0000775000175000017500000000637115241075234020650 0ustar00rgerrger#!/bin/bash # Regression test for omuxsock action isolation. One Unix datagram receiver is # intentionally left unread until the test releases it, which can block that # action's send path. Success is proven by a second omuxsock action continuing # to deliver messages to an independent receiver before the slow receiver is # released. The fast receiver only needs to reach FAST_MIN_LINES because Unix # datagram delivery can drop under burst pressure; the isolation invariant is # that it still makes substantial progress while the slow action is blocked. . ${srcdir:=.}/diag.sh init if [ "$(uname)" != "Linux" ]; then echo "This test requires Linux AF_UNIX datagram socket behavior." exit 77 fi if ! command -v python3 >/dev/null 2>&1; then echo "This test requires python3." exit 77 fi FAST_SOCKET="${RSYSLOG_DYNNAME}-fast.sock" SLOW_SOCKET="${RSYSLOG_DYNNAME}-slow.sock" FAST_READY="${RSYSLOG_DYNNAME}.fast.ready" SLOW_READY="${RSYSLOG_DYNNAME}.slow.ready" SLOW_RELEASE="${RSYSLOG_DYNNAME}.slow.release" NUMMESSAGES=5000 FAST_MIN_LINES=1000 test_error_exit_handler() { touch "$SLOW_RELEASE" if [ -n "${FAST_PID:-}" ]; then kill "$FAST_PID" 2>/dev/null || true fi if [ -n "${SLOW_PID:-}" ]; then kill "$SLOW_PID" 2>/dev/null || true fi } wait_ready_file() { ready_file="$1" count=1 max_attempts=$((TB_TIMEOUT_STARTSTOP * 10)) while [ "$count" -le "$max_attempts" ]; do if [ -r "$ready_file" ]; then return fi $TESTTOOL_DIR/msleep 100 count=$((count + 1)) done echo "receiver did not report ready file $ready_file" error_exit 1 } python3 - "$SLOW_SOCKET" "$SLOW_READY" "$SLOW_RELEASE" <<'PY' & import os import socket import sys import time path, ready, release = sys.argv[1:4] try: os.unlink(path) except FileNotFoundError: pass sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 4096) sock.bind(path) with open(ready, "w", encoding="ascii") as fh: fh.write("ready\n") while not os.path.exists(release): time.sleep(0.05) sock.settimeout(0.05) deadline = time.time() + 3 while time.time() < deadline: try: sock.recv(65535) except socket.timeout: pass PY SLOW_PID=$! wait_ready_file "$SLOW_READY" ./uxsockrcvr -s"$FAST_SOCKET" -o "$RSYSLOG_OUT_LOG" -r "$FAST_READY" -t 60 & FAST_PID=$! wait_ready_file "$FAST_READY" generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 module(load="../plugins/omuxsock/.libs/omuxsock") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" { action( type="omuxsock" SocketName="'$SLOW_SOCKET'" template="outfmt" queue.type="LinkedList" queue.timeoutEnqueue="0" queue.size="10000" ) action( type="omuxsock" SocketName="'$FAST_SOCKET'" template="outfmt" queue.type="LinkedList" queue.timeoutEnqueue="0" queue.size="10000" ) } ' startup injectmsg 0 "$NUMMESSAGES" wait_file_lines "$RSYSLOG_OUT_LOG" "$FAST_MIN_LINES" 20 touch "$SLOW_RELEASE" wait_queueempty shutdown_when_empty wait_shutdown kill "$FAST_PID" wait "$FAST_PID" wait "$SLOW_PID" seq_check 0 $((NUMMESSAGES - 1)) -d -m$((NUMMESSAGES - FAST_MIN_LINES)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/discard-rptdmsg-vg.sh0000644000000000000000000000013115171370365017745 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.890790574 29 ctime=1787067805.19692634 rsyslog-8.2608.0/tests/discard-rptdmsg-vg.sh0000775000175000017500000000021315171370365017411 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/discard-rptdmsg.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_http_request-vg.sh0000644000000000000000000000013215171370365021154 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.889790557 30 ctime=1787067805.952940428 rsyslog-8.2608.0/tests/rscript_http_request-vg.sh0000775000175000017500000000015515171370365020624 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export TB_TEST_MAX_RUNTIME=1500 . ${srcdir:-.}/rscript_http_request.sh rsyslog-8.2608.0/tests/PaxHeaders/omstdout-empty-template.sh0000644000000000000000000000013115241075234021062 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.690579886 29 ctime=1787067807.04996087 rsyslog-8.2608.0/tests/omstdout-empty-template.sh0000775000175000017500000000150315241075234020531 0ustar00rgerrger#!/bin/bash # Regression coverage for empty rendered templates reaching omstdout with # ensureLFEnding enabled. The stimulus is a real action invocation whose # configured string template renders to the empty C string. The oracle is # rsyslogd's proper-termination marker: before the guard in omstdout, ASan # reports a one-byte under-read in the trailing-LF check and rsyslogd aborts # before writing this marker. . ${srcdir:=.}/diag.sh init set_proper_termination_file generate_conf add_conf ' module(load="../plugins/omstdout/.libs/omstdout") template(name="empty" type="string" string="") if $rawmsg contains "trigger-empty-template" then { action(type="omstdout" template="empty" ensurelfending="on") } ' startup injectmsg_literal 'trigger-empty-template' shutdown_when_empty wait_shutdown check_proper_termination exit_test rsyslog-8.2608.0/tests/PaxHeaders/inputname-imtcp.sh0000644000000000000000000000013215241075234017352 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067803.653897587 rsyslog-8.2608.0/tests/inputname-imtcp.sh0000775000175000017500000000225615241075234017026 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1" name="l1") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="ruleset1" name="l2") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" ruleset="ruleset1" name="l3") template(name="outfmt" type="string" string="%inputname%\n") ruleset(name="ruleset1") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2" assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3" tcpflood -p $TCPFLOOD_PORT -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\"" tcpflood -p $TCPFLOOD_PORT2 -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\"" tcpflood -p $RS_PORT -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: MSG\"" shutdown_when_empty wait_shutdown export EXPECTED='l1 l2 l3' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-basic-ha-vg.sh0000644000000000000000000000013215132733117016726 xustar0030 mtime=1768666703.955620965 30 atime=1782715518.889790557 30 ctime=1787067803.962903345 rsyslog-8.2608.0/tests/es-basic-ha-vg.sh0000777000175000017500000000140215132733117016374 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 export ES_PORT=19200 ensure_elasticsearch_ready init_elasticsearch generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") :msg, contains, "msgnum:" action(type="omelasticsearch" template="tpl" serverport=`echo $ES_PORT` searchIndex="rsyslog_testbench" bulkmode="on") ' startup_vg injectmsg wait_queueempty shutdown_when_empty wait_shutdown_vg es_getdata $NUMMESSAGES $ES_PORT seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_delete_params.sh0000644000000000000000000000013115035412264023345 xustar0030 mtime=1752569012.390820233 29 atime=1782715518.88879054 30 ctime=1787067808.110980641 rsyslog-8.2608.0/tests/imbatchreport_errmsg_delete_params.sh0000777000175000017500000000066715035412264023030 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" reports="*.done" delete=".done$") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "'delete' must specify TWO parameters separated by spaces or tabs" exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-const-jsonf.sh0000644000000000000000000000013115035412264020312 xustar0030 mtime=1752569012.416639571 29 atime=1782715518.88879054 30 ctime=1787067804.281909289 rsyslog-8.2608.0/tests/template-const-jsonf.sh0000777000175000017500000000070615035412264017767 0ustar00rgerrger#!/bin/bash # added 2018-02-10 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { constant(outname="@version" value="1" format="jsonf") constant(value="\n") } local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='"@version": "1"' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-bulk.sh0000644000000000000000000000013115035412264017322 xustar0030 mtime=1752569012.385854976 29 atime=1782715518.88879054 30 ctime=1787067805.792937446 rsyslog-8.2608.0/tests/clickhouse-bulk.sh0000777000175000017500000000304415035412264016775 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.bulk (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, ' add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" user="default" pwd="" template="outfmt") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.bulk ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="SELECT id, severity, facility, ipaddress, tag, message FROM rsyslog.bulk ORDER BY id" > $RSYSLOG_OUT_LOG export EXPECTED='0 7 20 127.0.0.1 tag msgnum:00000000: 1 7 20 127.0.0.1 tag msgnum:00000001: 2 7 20 127.0.0.1 tag msgnum:00000002: 3 7 20 127.0.0.1 tag msgnum:00000003: 4 7 20 127.0.0.1 tag msgnum:00000004: 5 7 20 127.0.0.1 tag msgnum:00000005: 6 7 20 127.0.0.1 tag msgnum:00000006: 7 7 20 127.0.0.1 tag msgnum:00000007: 8 7 20 127.0.0.1 tag msgnum:00000008: 9 7 20 127.0.0.1 tag msgnum:00000009:' cmp_exact $RSYSLOG_OUT_LOG clickhouse-client --query="DROP TABLE rsyslog.bulk" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-missing-target.sh0000644000000000000000000000013215216464436020317 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.887790523 30 ctime=1787067804.146906774 rsyslog-8.2608.0/tests/omfwd-missing-target.sh0000775000175000017500000000156615216464436017776 0ustar00rgerrger#!/bin/bash # Regression test for issue #5057: omfwd actions without target or targetSrv # must fail during config validation instead of reaching runtime connection # setup. The oracle is rsyslogd -N1 exiting with failure and emitting the # actionable missing-destination diagnostic. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") action(type="omfwd" protocol="tcp" port="1514" template="outfmt" TCP_Framing="octet-counted") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -eq 0 ]; then echo "FAIL: expected config validation failure for omfwd without target or targetSrv" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi content_check "omfwd: either target or targetSrv must be specified" "${RSYSLOG_DYNNAME}.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl-oversizeMsg-split.sh0000644000000000000000000000013215035412264020623 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.887790523 30 ctime=1787067807.717973318 rsyslog-8.2608.0/tests/glbl-oversizeMsg-split.sh0000777000175000017500000000366215035412264020303 0ustar00rgerrger#!/bin/bash # add 2018-05-03 by PascalWithopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./have_relpSrvSetOversizeMode if [ $? -eq 1 ]; then echo "imrelp parameter oversizeMode not available. Test stopped" exit 77 fi; generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") global(maxMessageSize="230" oversizemsg.input.mode="split") input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="300") template(name="outfmt" type="string" string="%rawmsg%\n") action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # TODO: add tcpflood option to specific EXACT test message size! startup tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end # because otherwise we won't know if it was truncated at the right length. #First part of message is checked grep "^<167>Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi #Split part of message is checked grep "^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi #Error message is checked grep "message too long.*begin of message is:" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmlastmsg-udp.sh0000644000000000000000000000013115035412264017033 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.887790523 29 ctime=1787067807.86297602 rsyslog-8.2608.0/tests/pmlastmsg-udp.sh0000777000175000017500000000333715035412264016513 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/pmlastmsg/.libs/pmlastmsg") module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="ruleset1" parser=["rsyslog.lastline","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times\"" tcpflood -m1 -T "udp" -M "\"<13>last message repeated 0090909787348927349875 times\"" tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times\"" tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5 times -- more data\"" tcpflood -m1 -T "udp" -M "\"<13>last message repeated 5.2 times\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG long message ================================================================================\"" tcpflood -m1 -T "udp" -M "\"<34>1 2003-11-11T22:14:15.003Z mymachine.example.com su - ID47 last message repeated 5 times\"" shutdown_when_empty wait_shutdown echo 'last message repeated 5 times last message repeated 0090909787348927349875 times repeated 5 times repeated 5 times -- more data repeated 5.2 times Rest of message... long message ================================================================================ last message repeated 5 times' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/tcp_forwarding_retries.sh0000644000000000000000000000013215035412264021004 xustar0030 mtime=1752569012.416639571 30 atime=1782715518.887790523 30 ctime=1787067804.356910687 rsyslog-8.2608.0/tests/tcp_forwarding_retries.sh0000777000175000017500000000233215035412264020455 0ustar00rgerrger#!/bin/bash # added 2016-06-21 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init messages=20000 # how many messages to inject? # Note: we need to inject a somewhat larger number of messages in order # to ensure that we receive some messages in the actual output file, # as batching can (validly) cause a larger loss in the non-writable # file generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="TCP" action.resumeRetryCount="10" template="outfmt") } ' # we start a small receiver process ./minitcpsrv -t127.0.0.1 -p$TCPFLOOD_PORT -f $RSYSLOG_OUT_LOG -s4 & BGPROCESS=$! echo background minitcpsrvr process id is $BGPROCESS startup injectmsg 0 $messages shutdown_when_empty wait_shutdown # note: minitcpsrvr shuts down automatically if the connection is closed, but # we still try to kill it in case the test did not connect to it! Note that we # do not need an extra wait, as the rsyslog shutdown process should have taken # far long enough. echo waiting on background process kill $BGPROCESS &> /dev/null wait $BGPROCESS seq_check 0 $(($messages-1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-readmode2-with-persists.sh0000644000000000000000000000013215035412264022167 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.886790506 30 ctime=1787067807.903976784 rsyslog-8.2608.0/tests/imfile-readmode2-with-persists.sh0000777000175000017500000000474315035412264021650 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 echo ====================================================================== echo [imfile-readmode2-with-persists.sh] . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing sleep 1 # now stop and restart rsyslog so that the file info must be # persisted and read again on startup. Results should still be # correct ;) echo stopping rsyslog shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! echo spool: ls -l ${RSYSLOG_DYNNAME}.spool echo restarting rsyslog startup echo restarted rsyslog, continuing with test # write some more lines (see https://github.com/rsyslog/rsyslog/issues/144) echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2 # give it time to finish sleep 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! # give it time to write the output file sleep 1 ## check if we have the correct number of messages NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" cat $RSYSLOG_OUT_LOG exit 1 else if [ ! $NUMLINES -eq 3 ]; then echo "ERROR: expecting 3 headers, got $NUMLINES" cat $RSYSLOG_OUT_LOG exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {1..4}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" cat $RSYSLOG_OUT_LOG exit 1 fi done ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-no-dcr-id.sh0000644000000000000000000000013215171370365020155 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.892790608 30 ctime=1787067806.290946726 rsyslog-8.2608.0/tests/omazuredce-no-dcr-id.sh0000775000175000017500000000171315171370365017626 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin "omazuredce" generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omazuredce/.libs/omazuredce") template(name="tplAzureDceNoDcrId" type="list" option.jsonftree="on") { property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf") property(outname="host" name="hostname" format="jsonf") property(outname="message" name="msg" format="jsonf") } local4.* action( type="omazuredce" template="tplAzureDceNoDcrId" client_id="dummy-client-id" client_secret=`echo dummy-client-secret` tenant_id="dummy-tenant-id" dce_url="https://example.com" table_name="Custom-Test_CL" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "omazuredce: parameter 'dcr_id' required but not specified" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_anon_ipv4.sh0000644000000000000000000000013215132733117021436 xustar0030 mtime=1768666703.967621147 30 atime=1782715518.891790591 30 ctime=1787067807.517969591 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_anon_ipv4.sh0000777000175000017500000000433515132733117021114 0ustar00rgerrger#!/bin/bash # testing sending and receiving via TLS with anon auth using bare ipv4, no SNI # rgerhards, 2011-04-04 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # Force IPv4 only when not explicitly running the IPv6 variant if [ "${TARGET:=127.0.0.1}" != "[::1]" ]; then export RSTB_FORCE_IPV4=1 fi if [ "${TARGET:=127.0.0.1}" == "[::1]" ]; then . $srcdir/diag.sh check-ipv6-available fi export NUMMESSAGES=10000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="ossl" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="ossl" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@'${TARGET}':'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_wrap2.sh0000644000000000000000000000013215241075234017041 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 30 ctime=1787067804.784918662 rsyslog-8.2608.0/tests/rscript_wrap2.sh0000775000175000017500000000157315241075234016516 0ustar00rgerrger#!/bin/bash # added 2014-11-03 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_wrap2.sh\]: a test for wrap\(2\) script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.replaced_msg%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.replaced_msg = wrap("foo says" & $msg, "*" & "*"); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 -I $srcdir/testsuites/date_time_msg echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "**foo says at Thu Oct 30 13:20:18 IST 2014 random number is 19597**" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-NUL.sh0000644000000000000000000000013215241075234016010 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067805.511932209 rsyslog-8.2608.0/tests/imtcp-NUL.sh0000775000175000017500000000131515241075234015457 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message <167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > $RSYSLOG_DYNNAME.input tcpflood -B -I $RSYSLOG_DYNNAME.input shutdown_when_empty wait_shutdown seq_check 0 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-pure-json.sh0000644000000000000000000000013215132733117017773 xustar0030 mtime=1768666703.968621162 30 atime=1782715518.891790591 30 ctime=1787067804.257908842 rsyslog-8.2608.0/tests/template-pure-json.sh0000777000175000017500000000177415132733117017455 0ustar00rgerrger#!/bin/bash # added 2018-02-10 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list" option.jsonftree="on") { property(outname="message" name="msg" format="jsonf") constant(outname="@version" value="1" format="jsonf") } local4.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED_JSON='{"message":" msgnum:00000000:", "@version": "1"}' python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import os import sys expected = json.loads(os.environ['EXPECTED_JSON']) with open(sys.argv[1], 'r', encoding='utf-8') as fh: actual = json.loads(fh.read()) if actual != expected: print('invalid response generated') print('################# actual JSON is:') print(json.dumps(actual, indent=2, sort_keys=True)) print('################# expected JSON was:') print(json.dumps(expected, indent=2, sort_keys=True)) sys.exit(1) PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_ruleset_call-recursion-limit.sh0000644000000000000000000000013015216464436023615 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.891790591 29 ctime=1787067804.76491829 rsyslog-8.2608.0/tests/rscript_ruleset_call-recursion-limit.sh0000775000175000017500000000212515216464436023266 0ustar00rgerrger#!/bin/bash # This covers runaway synchronous ruleset recursion. The test deliberately # creates a self-calling ruleset and proves that rsyslog logs the recursion # guard diagnostic through its configured omfile destination after synchronized # shutdown instead of crashing or relying on stdout/stderr. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") template(name="counter" type="string" string="%$.counter%\n") ruleset(name="recurse") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="counter") set $.counter = $.counter + 1; call recurse } if $msg contains "msgnum:" then { set $.counter = 1; call recurse } syslog.* { action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`) } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown content_check "1024" "$RSYSLOG_OUT_LOG" custom_assert_content_missing "1025" "$RSYSLOG_OUT_LOG" content_check "ruleset call nesting limit of 1024 reached" "$RSYSLOG2_OUT_LOG" custom_assert_content_missing "Segmentation fault" "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_parse_time.sh0000644000000000000000000000013115241075234020135 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067804.873920321 rsyslog-8.2608.0/tests/rscript_parse_time.sh0000775000175000017500000001070615241075234017611 0ustar00rgerrger#!/bin/bash # Added 2017-10-28 by Stephen Workman, released under ASL 2.0 # Because this script tests functionality that depends on the current date, # we cannot use static values for the expected results. They have to be # calculated. Also, because we cannot depend on the GNU version of the # 'date' command on all of our test systems (think FreeBSD, and Solaris), # we need a method of converting given date/time strings to UNIX timestamps. # For that we use an external Python 2.x script to do the job. . ${srcdir:=.}/diag.sh init getts="$PYTHON $srcdir/rscript_parse_time_get-ts.py" # Run the Python script's self-tests $getts selftest if [[ $? -ne 0 ]]; then printf "Failed own self-test(s)!\n" error_exit 1 fi # Since the RFC 3164 date/time format does not include a year, we need to # try to "guess" an appropriate one based on the incoming date and the # current date. So, we'll use a reasonable spread of RFC 3164 date/time # strings to ensure that we test as much of our year "guessing" as # possible. Since this uses the CURRENT DATE (as in, the date this) # script was invoked, we need to calculate our expected results to # compare them with the values returned by the parse_time() RainerScript # function. rfc3164_1="Oct 5 01:10:11" rfc3164_1_r=$($getts "$rfc3164_1") rfc3164_2="Jan 31 13:00:00" rfc3164_2_r=$($getts "$rfc3164_2") rfc3164_3="Feb 28 14:35:00" rfc3164_3_r=$($getts "$rfc3164_3") rfc3164_4="Mar 1 14:00:00" rfc3164_4_r=$($getts "$rfc3164_4") rfc3164_5="Apr 3 15:00:00" rfc3164_5_r=$($getts "$rfc3164_5") rfc3164_6="May 5 16:00:00" rfc3164_6_r=$($getts "$rfc3164_6") rfc3164_7="Jun 11 03:00:00" rfc3164_7_r=$($getts "$rfc3164_7") rfc3164_8="Jul 15 05:00:00" rfc3164_8_r=$($getts "$rfc3164_8") rfc3164_9="Aug 17 08:00:00" rfc3164_9_r=$($getts "$rfc3164_9") rfc3164_10="Sep 20 18:00:00" rfc3164_10_r=$($getts "$rfc3164_10") rfc3164_11="Nov 23 19:00:00" rfc3164_11_r=$($getts "$rfc3164_11") rfc3164_12="Dec 25 20:00:00" rfc3164_12_r=$($getts "$rfc3164_12") generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omstdout/.libs/omstdout") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # $DebugLevel 2 # RFC 3164 Parse Tests (using fixed input values - see above) set $!datetime!rfc3164_1 = parse_time("'"$rfc3164_1"'"); set $!datetime!rfc3164_2 = parse_time("'"$rfc3164_2"'"); set $!datetime!rfc3164_3 = parse_time("'"$rfc3164_3"'"); set $!datetime!rfc3164_4 = parse_time("'"$rfc3164_4"'"); set $!datetime!rfc3164_5 = parse_time("'"$rfc3164_5"'"); set $!datetime!rfc3164_6 = parse_time("'"$rfc3164_6"'"); set $!datetime!rfc3164_7 = parse_time("'"$rfc3164_7"'"); set $!datetime!rfc3164_8 = parse_time("'"$rfc3164_8"'"); set $!datetime!rfc3164_9 = parse_time("'"$rfc3164_9"'"); set $!datetime!rfc3164_10 = parse_time("'"$rfc3164_10"'"); set $!datetime!rfc3164_11 = parse_time("'"$rfc3164_11"'"); set $!datetime!rfc3164_12 = parse_time("'"$rfc3164_12"'"); # RFC 3339 Parse Tests (these provide their own year) set $!datetime!rfc3339 = parse_time("2017-10-05T01:10:11Z"); set $!datetime!rfc3339tz1 = parse_time("2017-10-05T01:10:11+04:00"); set $!datetime!rfc3339tz2 = parse_time("2017-10-05T01:10:11+00:00"); # Test invalid date strings, these should return 0 set $!datetime!inval1 = parse_time("not a date/time"); set $!datetime!inval2 = parse_time("2017-10-05T01:10:11"); set $!datetime!inval3 = parse_time("2017-SOMETHING: 42"); template(name="outfmt" type="string" string="%!datetime%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") local4.* :omstdout:;outfmt ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown # Our fixed and calculated expected results export EXPECTED='{ "rfc3164_1": '"$rfc3164_1_r"', "rfc3164_2": '"$rfc3164_2_r"', "rfc3164_3": '"$rfc3164_3_r"', "rfc3164_4": '"$rfc3164_4_r"', "rfc3164_5": '"$rfc3164_5_r"', "rfc3164_6": '"$rfc3164_6_r"', "rfc3164_7": '"$rfc3164_7_r"', "rfc3164_8": '"$rfc3164_8_r"', "rfc3164_9": '"$rfc3164_9_r"', "rfc3164_10": '"$rfc3164_10_r"', "rfc3164_11": '"$rfc3164_11_r"', "rfc3164_12": '"$rfc3164_12_r"', "rfc3339": 1507165811, "rfc3339tz1": 1507151411, "rfc3339tz2": 1507165811, "inval1": 0, "inval2": 0, "inval3": 0 }' # FreeBSD's cmp does not support reading from STDIN cmp <(echo "$EXPECTED") $RSYSLOG_OUT_LOG if [[ $? -ne 0 ]]; then printf "Invalid function output detected!\n" printf "Expected: $EXPECTED\n" printf "Got: " cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/ratelimit-persource-shard-eviction.sh0000644000000000000000000000013215241075234023154 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.691579904 30 ctime=1787067805.627934371 rsyslog-8.2608.0/tests/ratelimit-persource-shard-eviction.sh0000775000175000017500000000471415241075234022631 0ustar00rgerrger#!/bin/bash ## Regression test for sharded per-source ratelimit state eviction. ## The policy sets maxStates=1, which becomes an approximate shard-local cap. ## Sending many one-shot source keys forces shard-local LRU eviction. The ## oracle checks that eviction is visible through impstats and that an ## override-only key survives churn before later becoming active state. ## The short wait gives impstats one interval to publish the eviction counter ## before synchronized shutdown. . ${srcdir:=.}/diag.sh init require_plugin impstats export STATSFILE="$RSYSLOG_DYNNAME.stats" POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.persource-shard-eviction.yaml" INPUT_FILE="$(pwd)/${RSYSLOG_DYNNAME}.input" export POLICY_FILE INPUT_FILE cat > "$POLICY_FILE" < "$INPUT_FILE" for i in $(seq 1 96); do echo "<13>Jan 1 00:00:00 churn$i app: msgnum:$i" >> "$INPUT_FILE" done for i in $(seq 1 3); do echo "<13>Jan 1 00:00:00 specialhost app: msgnum:$i" >> "$INPUT_FILE" done tcpflood -p"$tcp_port" -I "$INPUT_FILE" sleep 2 shutdown_when_empty wait_shutdown special_count=$(grep -c "host=specialhost" "$RSYSLOG_OUT_LOG") evicted_count=$(grep "ratelimit.per_source.per_source" "$STATSFILE" | grep -o "per_source_evicted=[0-9]*" | tail -1 | sed 's/.*=//') echo "special_count: $special_count" echo "evicted_count: $evicted_count" if [ "$special_count" -ne 3 ]; then echo "FAIL: override-only specialhost entry was not preserved until activation" echo "output content:" cat "$RSYSLOG_OUT_LOG" error_exit 1 fi if [ "${evicted_count:-0}" -le 0 ]; then echo "FAIL: expected per_source_evicted counter after shard-local churn" echo "stats content:" cat "$STATSFILE" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-template-option-stdsql.sh0000644000000000000000000000013215216464436023030 xustar0030 mtime=1782212894.046266507 30 atime=1782715518.890790574 30 ctime=1787067805.773937092 rsyslog-8.2608.0/tests/clickhouse-template-option-stdsql.sh0000775000175000017500000000227715216464436022507 0ustar00rgerrger#!/usr/bin/env bash # Verify that omclickhouse accepts a custom INSERT template when the SQL # escaping requirement is expressed with the template-level option.stdsql # parameter. This covers the config-validation path from issue #6297 without # requiring a live ClickHouse service. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="CustomClickHouseFmt" type="string" option.stdsql="on" string="INSERT INTO rsyslog.SystemEvents (severity, facility, timestamp, hostname, fromhost_ip, tag, message) VALUES (%syslogseverity%, %syslogfacility%, '\''%timereported:::date-unixtimestamp%'\'', '\''%hostname%'\'', '\''%fromhost-ip%'\'', '\''%syslogtag:1:32%'\'', '\''%msg%'\'')") action(type="omclickhouse" server="127.0.0.1" user="writer" pwd="secret" usehttps="off" bulkmode="on" template="CustomClickHouseFmt") ' ../tools/rsyslogd -C -N1 -f "${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" > "$RSYSLOG_DYNNAME.log" 2>&1 content_check "End of config validation run" "$RSYSLOG_DYNNAME.log" check_not_present "Action disabled. To use this action" "$RSYSLOG_DYNNAME.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-persist.sh0000644000000000000000000000013215035412264017052 xustar0030 mtime=1752569012.409688211 30 atime=1782715518.892790608 30 ctime=1787067804.615915513 rsyslog-8.2608.0/tests/queue-persist.sh0000777000175000017500000000115115035412264016521 0ustar00rgerrger#!/bin/bash # Test for queue data persisting at shutdown. We use the actual driver # to carry out multiple tests with different queue modes # added 2009-05-27 by Rgerhards # This file is part of the rsyslog project, released ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/queue-persist-drvr.sh LinkedList . $srcdir/queue-persist-drvr.sh FixedArray # the disk test should not fail, however, the config is extreme and using # it more or less is a config error . $srcdir/queue-persist-drvr.sh Disk # we do not test Direct mode because this absolute can not work in direct mode # (maybe we should do a fail-type of test?) rsyslog-8.2608.0/tests/PaxHeaders/uxsock_multiple_netns.sh0000644000000000000000000000013215216464436020706 xustar0030 mtime=1782212894.090267219 30 atime=1782715518.891790591 30 ctime=1787067807.657972199 rsyslog-8.2608.0/tests/uxsock_multiple_netns.sh0000775000175000017500000001034615216464436020361 0ustar00rgerrger#!/bin/bash # This tests basic omuxsock functionality with namespaces. # Multiple socket receivers are started which sends all data # to an output file, then a rsyslog instance is started which # generates messages and sends them to multiple unix sockets. # Multiple socket types are being used. # Based on uxsock_simple.sh added 2010-08-06 by Rgerhards # Updated 2025-04-16 for abstract sockets and multiple socket # types. echo =============================================================================== echo \[uxsock_multiple_netns.sh\]: test for transmitting to another namespace echo This test must be run with CAP_SYS_ADMIN capabilities [network namespace creation/change required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi . ${srcdir:=.}/diag.sh init require_netns_capable check_command_available timeout uname if [ $(uname) != "Linux" ] ; then echo "This test requires Linux (AF_UNIX abstract addresses)" exit 77 fi NS_PREFIX=$(basename ${RSYSLOG_DYNNAME}) SOCKET_NAMES=( "$RSYSLOG_DYNNAME-testbench-dgram-uxsock.0" "$RSYSLOG_DYNNAME-testbench-dgram-uxsock.DGRAM" "$RSYSLOG_DYNNAME-testbench-dgram-uxsock.STREAM" "$RSYSLOG_DYNNAME-testbench-dgram-uxsock.SEQPACKET" ) # create the pipe and start a background process that copies data from # it to the "regular" work file generate_conf for name in "${SOCKET_NAMES[@]}"; do ext=${name##*.} NS=${NS_PREFIX}.${ext} if [ ${ext} == "0" ]; then add_conf ' $template outfmt,"%msg:F,58:2%\n" module( load = "../plugins/omuxsock/.libs/omuxsock" template = "outfmt" SocketName = "'${name}'" abstract = "1" NetworkNamespace="'${NS}'" ) :msg, contains, "msgnum:" { action( type = "omuxsock" ) ' else add_conf ' action( type = "omuxsock" SocketName = "'$name'" abstract = "1" SocketType = "'$ext'" NetworkNamespace="'${NS}'" ) action( type = "omuxsock" SocketName = "'$name'" abstract = "1" SocketType = "'$ext'" NetworkNamespace="'${NS}.fail'" ) ' fi done add_conf ' } ' BGPROCESS=() for name in "${SOCKET_NAMES[@]}"; do ext=${name##*.} NS=${NS_PREFIX}.${ext} ip netns add "${NS}" ip netns exec "${NS}" ip link set dev lo up ip netns delete "${NS}.fail" > /dev/null 2>&1 if [ "${ext}" == "0" ]; then type="" else type="-T${ext}" fi timeout 30s ip netns exec "${NS}" ./uxsockrcvr -a -s$name ${type} -o ${RSYSLOG_OUT_LOG}.${ext} -t 60 & PID=($!) BGPROCESS+=($PID) echo background uxsockrcvr ${name} process id is $PID done # now do the usual run RS_REDIR="> ${RSYSLOG_DYNNAME}.log 2>&1" startup # 10000 messages should be enough injectmsg 0 10000 wait_queueempty echo resetting uxsockrcvr for pid in "${BGPROCESS[@]}"; do kill -HUP "$pid" done injectmsg 10000 10000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # wait for the cp process to finish, do pipe-specific cleanup echo shutting down uxsockrcvr... # TODO: we should do this more reliable in the long run! (message counter? timeout?) for pid in "${BGPROCESS[@]}"; do kill "$pid" wait "$pid" done echo background processes have terminated, continue test... # Remove namespaces for name in "${SOCKET_NAMES[@]}"; do ext=${name##*.} NS=${NS_PREFIX}.${ext} ip netns delete "${NS}" > /dev/null 2>&1 done # and continue the usual checks. # For connected sockets, we expect a single message loss # which causes the SUSPEND state. Add it back here to # simplify the seq_check. BASE=${RSYSLOG_OUT_LOG} for name in "${SOCKET_NAMES[@]}"; do SEQ_CHECK_FILE=${BASE}.${name##*.} case ${name##*.} in STREAM|SEQPACKET) echo 10000 >> ${SEQ_CHECK_FILE} ;; esac seq_check 0 19999 done # Verify that we get messages for when our receiver reset # We don't redirect with valgrind if [ "${USE_VALGRIND}" != "YES" ]; then content_check "omuxsock suspending: send(), socket " ${RSYSLOG_DYNNAME}.log fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/smtradfile-vg.sh0000644000000000000000000000013215171370365017011 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.891790591 30 ctime=1787067805.140925296 rsyslog-8.2608.0/tests/smtradfile-vg.sh0000775000175000017500000000017215171370365016460 0ustar00rgerrger#!/bin/bash # addd 2019-04-15 by RGerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/smtradfile.sh rsyslog-8.2608.0/tests/PaxHeaders/dynfile_invld_sync.sh0000644000000000000000000000013215241075234020122 xustar0030 mtime=1787067036.617578519 30 atime=1787067036.766581309 30 ctime=1787067804.607915364 rsyslog-8.2608.0/tests/dynfile_invld_sync.sh0000775000175000017500000000366315241075234017601 0ustar00rgerrger#!/bin/bash # This test checks if omfile segfaults when a file open() in dynacache mode fails. # The test is mimiced after a real-life scenario (which, of course, was much more # complex). # # added 2010-03-09 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $template outfmt,"%msg:F,58:3%\n" $template dynfile,"%msg:F,58:2%.log" # complete name is in message $OMFileFlushOnTXEnd on $OMFileAsyncWriting off $DynaFileCacheSize 4 # This test deliberately uses /proc to make the open fail after dynafile cache # handling. The action-level compatibility option keeps that historic test # stimulus available while containment remains the default for other actions. local0.* action(type="omfile" dynafile="dynfile" template="outfmt" dynafile.dangerousPermitPathEscape="on") ' startup # Send the handcrafted messages in one imdiag session so the invalid open # and first following valid dynafile write can be processed in one batch. cat > "$RSYSLOG_DYNNAME.input" <Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3 <129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6 <129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7 EOF injectmsg_file "$RSYSLOG_DYNNAME.input" # done message generation shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG seq_check 0 7 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-stream-always-basic.sh0000644000000000000000000000013215216464436021412 xustar0030 mtime=1782212894.062266766 30 atime=1782715518.891790591 30 ctime=1787067806.857957292 rsyslog-8.2608.0/tests/imptcp-stream-always-basic.sh0000775000175000017500000000160015216464436021056 0ustar00rgerrger#!/bin/bash # added 2026-04-20 by Codex, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=20000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.stream.flushOnTXEnd="on") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/array_lookup_table-vg.sh0000644000000000000000000000013115171370365020534 xustar0029 mtime=1776677109.45691331 30 atime=1782715518.891790591 30 ctime=1787067805.274927793 rsyslog-8.2608.0/tests/array_lookup_table-vg.sh0000775000175000017500000000026315171370365020205 0ustar00rgerrger#!/bin/bash # added 2015-10-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/array_lookup_table.sh rsyslog-8.2608.0/tests/PaxHeaders/omotel-http-batch.sh0000644000000000000000000000013215145046113017570 xustar0030 mtime=1771326539.058014598 30 atime=1782715518.890790574 30 ctime=1787067806.201945067 rsyslog-8.2608.0/tests/omotel-http-batch.sh0000775000175000017500000000656215145046113017250 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-http-batch.sh -- smoke-test OTLP batching and retries ## ## Starts the omhttp test server, emits four messages through omotel with ## batching and gzip enabled, and verifies the collector captured two payloads ## with the expected retry behaviour and record order. . ${srcdir:=.}/diag.sh init # Check if omotel module is available require_plugin omotel omhttp_start_server 0 --decompress --fail-every 2 --fail-with 503 generate_conf add_conf ' module(load="../plugins/omotel/.libs/omotel") template(name="otlpBody" type="string" string="%msg%") # Process all messages through omotel action( name="omotel-http" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$omhttp_server_lstnport'" path="/v1/logs" batch.max_items="2" batch.timeout.ms="1000" compression="gzip" retry.initial.ms="10" retry.max.ms="100" retry.max_retries="3" headers='{ "X-Test-Header": "omotel" }' ) ' startup injectmsg_literal 'msg 1 msg 2 msg 3 msg 4' # Wait for batches to flush (batch.timeout.ms="1000" + retry time) # With batch.max_items="2", we expect 2 batches: # - Batch 1 (msg 1-2): should succeed immediately # - Batch 2 (msg 3-4): will fail with 503, then retry up to 3 times # Worst case retry time: 3 retries with exponential backoff up to 100ms = ~700ms # Add buffer for batch timeout (1000ms) + retries + network delays if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 3000 else sleep 3 fi shutdown_when_empty wait_shutdown # Give a bit more time for any final retries to complete if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi attempt=0 ret=1 while [ $attempt -lt 30 ]; do python3 - "$omhttp_server_lstnport" <<'PY' import json import sys import urllib.request port = int(sys.argv[1]) try: with urllib.request.urlopen(f"http://127.0.0.1:{port}/v1/logs") as resp: payloads = json.load(resp) except Exception as e: sys.stderr.write(f"failed to fetch payloads: {e}\n") sys.exit(1) if len(payloads) != 2: sys.stderr.write(f"expected 2 payloads, got {len(payloads)}\n") if len(payloads) > 0: sys.stderr.write(f"first payload preview: {str(payloads[0])[:200]}...\n") sys.exit(1) records = [] batch_sizes = [] for payload in payloads: try: document = json.loads(payload) logs = document["resourceLogs"][0]["scopeLogs"][0]["logRecords"] batch_sizes.append(len(logs)) for entry in logs: body = entry.get("body", {}).get("stringValue") if body: records.append(body) except (KeyError, json.JSONDecodeError) as e: sys.stderr.write(f"failed to parse payload: {e}\n") sys.stderr.write(f"payload: {payload[:200]}...\n") sys.exit(1) expected = [f"msg {i}" for i in range(1, 5)] if batch_sizes != [2, 2]: sys.stderr.write(f"unexpected batch sizes {batch_sizes}, expected [2, 2]\n") sys.exit(1) if records != expected: sys.stderr.write(f"unexpected bodies {records}, expected {expected}\n") sys.exit(1) PY ret=$? if [ $ret -eq 0 ]; then break fi attempt=$((attempt + 1)) if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 200 else sleep 0.2 fi done omhttp_stop_server exit_test $ret rsyslog-8.2608.0/tests/PaxHeaders/zstd.sh0000644000000000000000000000013215131231047015216 xustar0030 mtime=1768239655.726212941 30 atime=1782715518.890790574 30 ctime=1787067805.103924607 rsyslog-8.2608.0/tests/zstd.sh0000777000175000017500000000306515131231047014673 0ustar00rgerrger#!/bin/bash # This tests writing large data records in zst mode. We use up to 10K # record size. # # added 2022-06-21 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=${NUMMESSAGES:-50000} export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf # Note: we right now use the non-compressed file as indicator for "processing complete" #export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.zst add_conf ' $MaxMessageSize 10k $MainMsgQueueTimeoutShutdown 10000 module(load="builtin:omfile" compression.driver="zstd" compression.zstd.workers="5") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'.zst" template="outfmt" zipLevel="20" iobuffersize="64k" veryRobustZIP="off") local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # rgerhards, 2019-08-14: Note: veryRobustZip may need to be "on". Do this if the test # still prematurely terminates. In that case it is likely that gunzip got confused # by the missing zip close record. My initial testing shows that while gunzip emits an # error message, everything is properly extracted. Only stressed CI runs will show how # it works in reality. startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m$NUMMESSAGES -r -d10000 -P129 shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -E exit_test rsyslog-8.2608.0/tests/PaxHeaders/execonlywhenprevsuspended_multiwrkr.sh0000644000000000000000000000013015035412264023675 xustar0029 mtime=1752569012.38883413 30 atime=1782715518.892790608 29 ctime=1787067804.63291583 rsyslog-8.2608.0/tests/execonlywhenprevsuspended_multiwrkr.sh0000777000175000017500000000170715035412264023355 0ustar00rgerrger#!/bin/bash # rgerhards, 2013-12-05 echo ===================================================================================== echo \[execonlywhenprevsuspended_multiwrkr.sh\]: test execonly...suspended functionality multiworker case . ${srcdir:=.}/diag.sh init generate_conf add_conf ' # omtesting provides the ability to cause "SUSPENDED" action state $ModLoad ../plugins/omtesting/.libs/omtesting $MainMsgQueueTimeoutShutdown 100000 $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" :omtesting:fail 2 0 $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"';outfmt ' startup # we initially send only 10 messages. It has shown that if we send more, # we cannot really control which are the first two messages imdiag sees, # and so we do not know for sure which numbers are skipped. So we inject # those 10 to get past that point. injectmsg 0 10 ./msleep 500 injectmsg 10 990 shutdown_when_empty wait_shutdown seq_check 1 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/dynstats_prevent_premature_eviction-vg.sh0000644000000000000000000000013215131231047024244 xustar0030 mtime=1768239655.701212533 30 atime=1782715518.892790608 30 ctime=1787067806.762955522 rsyslog-8.2608.0/tests/dynstats_prevent_premature_eviction-vg.sh0000777000175000017500000000531715131231047023723 0ustar00rgerrger#!/bin/bash # added 2016-04-13 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[dynstats_prevent_premature_eviction-vg.sh\]: test for ensuring metrics are not evicted before unused-ttl with valgrind . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on") template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n") dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off") set $.msg_prefix = field($msg, 32, 1); if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then { set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix); } else { set $.increment_successful = -1; } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log . $srcdir/diag.sh block-stats-flush injectmsg_file $srcdir/testsuites/dynstats_input_1 . $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it injectmsg_file $srcdir/testsuites/dynstats_input_2 . $srcdir/diag.sh allow-single-stats-flush-after-block-and-wait-for-it injectmsg_file $srcdir/testsuites/dynstats_input_3 . $srcdir/diag.sh await-stats-flush-after-block wait_queueempty wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log content_check "foo 001 0" content_check "foo 006 0" echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg # because dyn-accumulators for existing metrics were posted-to under a second, they should not have been evicted custom_content_check 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log" custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log" custom_content_check 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log" # sum is high because accumulators were never reset, and we expect them to last specific number of cycles(when we posted before ttl expiry) first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 6 first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1 first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 0 first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-basic-vg.sh0000644000000000000000000000013215171370365020074 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.892790608 30 ctime=1787067806.315947192 rsyslog-8.2608.0/tests/omazuredce-basic-vg.sh0000775000175000017500000000011115171370365017534 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omazuredce-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/now_family_utc.sh0000644000000000000000000000013115241075234017256 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 29 ctime=1787067805.82693808 rsyslog-8.2608.0/tests/now_family_utc.sh0000775000175000017500000000163115241075234016727 0ustar00rgerrger#!/bin/bash # test $NOW family of system properties # addd 2016-01-12 by RGerhards, released under ASL 2.0 # requires faketime . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$hour%:%$minute%,%$hour-utc%:%$minute-utc%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' . $srcdir/faketime_common.sh export TZ=TEST+06:30 FAKETIME='2016-01-01 01:00:00' startup # what we send actually is irrelevant, as we just use system properties. # but we need to send one message in order to gain output! tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="01:00,07:30" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_relp_tls_prio.sh0000644000000000000000000000013215216464436020504 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.891790591 30 ctime=1787067807.732973597 rsyslog-8.2608.0/tests/sndrcv_relp_tls_prio.sh0000775000175000017500000000301715216464436020154 0ustar00rgerrger#!/bin/bash # added 2013-12-10 by Rgerhards # Verify RELP forwarding with TLS and a custom priority string. The receiver # binds an ephemeral IPv4 listener and the testbench discovers that bound port # after startup, avoiding the get_free_port race before the sender connects. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init echo testing sending and receiving via relp with TLS enabled and priority string set # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" address="127.0.0.1" port="0" tls="on" tls.prioritystring="NORMAL:+ANON-DH") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_single_tcp_listener_port PORT_RCVR export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' module(load="../plugins/omrelp/.libs/omrelp") action(type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on" tls.prioritystring="NORMAL:+ANON-DH") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 50000 # shut down sender shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 50000 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-feedback-vg.sh0000644000000000000000000000013115035412264017675 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.891790591 29 ctime=1787067806.09794313 rsyslog-8.2608.0/tests/omprog-feedback-vg.sh0000777000175000017500000000144015035412264017346 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Same test than 'omprog-feedback.sh', but checking for memory # problems using valgrind. Note it is not necessary to repeat the # rest of checks (this simplifies the maintenance of the tests). . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-feedback-bin.sh` template="outfmt" name="omprog_action" queue.type="Direct" confirmMessages="on" action.resumeInterval="1" ) } ' startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd_impstats-udp.sh0000644000000000000000000000012715131231047020064 xustar0030 mtime=1768239655.711212696 30 atime=1782715518.890790574 27 ctime=1787067806.734955 rsyslog-8.2608.0/tests/omfwd_impstats-udp.sh0000777000175000017500000000172415131231047017535 0ustar00rgerrger#!/bin/bash # This test tests impstats omfwd counters in UPD mode # added 2021-02-11 by rgerhards. Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf export STATSFILE="$RSYSLOG_DYNNAME.stats" add_conf ' $MainMsgQueueTimeoutShutdown 10000 module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1" ruleset="stats") ruleset(name="stats") { stop # nothing to do here } template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="builtin:omfwd" template="outfmt") if $msg contains "msgnum:" then action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="udp") ' # note: there must be no actual data - it's fine for this test if all data is lost # now do the usual run startup # 10000 messages should be enough injectmsg 0 10000 shutdown_when_empty wait_shutdown # check pstats - that's our prime test target content_check --regex "UDP-.*origin=omfwd .*bytes.sent=[1-9][0-9][0-9]" "$STATSFILE" exit_test rsyslog-8.2608.0/tests/PaxHeaders/chkseq_usage_output.sh0000644000000000000000000000013215216464436020332 xustar0030 mtime=1782212894.046266507 30 atime=1782715518.890790574 30 ctime=1787067804.021904444 rsyslog-8.2608.0/tests/chkseq_usage_output.sh0000775000175000017500000000067215216464436020006 0ustar00rgerrger#!/bin/bash # Covers the chkseq testbench helper usage path. The oracle is the diagnostic # text for an invalid option, proving the helper still prints actionable usage # output instead of failing silently. . ${srcdir:=.}/diag.sh init if ./chkseq -Z > "$RSYSLOG_OUT_LOG" 2>&1; then echo "chkseq unexpectedly succeeded with an invalid option" error_exit 1 fi content_check 'Invalid call of chkseq' content_check 'Usage: chkseq' exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_conflict3-vg.sh0000644000000000000000000000013215171370365022371 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.892790608 30 ctime=1787067806.913958335 rsyslog-8.2608.0/tests/rscript_unflatten_conflict3-vg.sh0000775000175000017500000000012415171370365022035 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_conflict3.sh rsyslog-8.2608.0/tests/PaxHeaders/imbeats-filebeat-omelasticsearch-docker.sh0000644000000000000000000000013215241075234024046 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.768581346 30 ctime=1787067806.490950453 rsyslog-8.2608.0/tests/imbeats-filebeat-omelasticsearch-docker.sh0000775000175000017500000001604615241075234023524 0ustar00rgerrger#!/bin/bash # Verify real Filebeat traffic received by imbeats is delivered through # omelasticsearch and becomes queryable in Elasticsearch. . ${srcdir:=.}/diag.sh init check_command_available docker if ! docker info >/dev/null 2>&1 ; then echo "docker daemon not available, skipping test" exit 77 fi export ES_PORT="${ES_PORT:-19200}" export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=imbeats_es_shutdown_empty_check export FB_IMAGE="${FB_IMAGE:-docker.elastic.co/beats/filebeat:9.2.0}" export FB_CONTAINER="fb-imbeats-es-${RSYSLOG_DYNNAME}" export FB_WORKDIR="${TESTTOOL_DIR}/${RSYSLOG_DYNNAME}.filebeat" if [ -z "$FB_DOCKER_MOUNT_SOURCE" ] && [ -n "$GITHUB_WORKSPACE" ] ; then case "$FB_WORKDIR" in /rsyslog/*) FB_DOCKER_MOUNT_SOURCE="${GITHUB_WORKSPACE}${FB_WORKDIR#/rsyslog}" ;; esac fi export FB_DOCKER_MOUNT_SOURCE="${FB_DOCKER_MOUNT_SOURCE:-$FB_WORKDIR}" export FB_INPUT="${FB_WORKDIR}/input.log" export FB_CONFIG="${FB_WORKDIR}/filebeat.yml" export FB_LOG="${FB_WORKDIR}/docker.log" export RAW_INDEX="rsyslog_testbench_beats_raw" export AMENDED_INDEX="rsyslog_testbench_beats_amended" export MARKER="imbeats-elasticsearch" cleanup_filebeat() { docker rm -f "$FB_CONTAINER" >/dev/null 2>&1 || true rm -rf "$FB_WORKDIR" } trap cleanup_filebeat EXIT es_count_index() { local base="$1" local index="$2" local response local http_status local body response=$(curl --silent --show-error --write-out '\n%{http_code}' \ "${base}/${index}/_count") http_status=$(printf '%s' "$response" | tail -n 1) body=$(printf '%s' "$response" | sed '$d') if [ "$http_status" = "404" ]; then printf '0\n' elif [ "$http_status" = "200" ]; then printf '%s' "$body" | "$PYTHON" -c ' import json import sys print(json.load(sys.stdin).get("count", 0)) ' else printf '%s es_count_index: unexpected Elasticsearch status %s for %s\n' \ "$(tb_timestamp)" "$http_status" "$index" >&2 return 1 fi } imbeats_es_shutdown_empty_check() { local base local raw_lines local amended_lines base=$(es_base_url) raw_lines=$(es_count_index "$base" "$RAW_INDEX") || return 1 amended_lines=$(es_count_index "$base" "$AMENDED_INDEX") || return 1 if [ "$raw_lines" -eq "$NUMMESSAGES" ] && [ "$amended_lines" -eq "$NUMMESSAGES" ]; then printf '%s imbeats_es_shutdown_empty_check: success, have %d raw and %d amended documents\n' \ "$(tb_timestamp)" "$raw_lines" "$amended_lines" return 0 fi printf '%s imbeats_es_shutdown_empty_check: have %d raw and %d amended documents, expecting %d each\n' \ "$(tb_timestamp)" "$raw_lines" "$amended_lines" "$NUMMESSAGES" return 1 } fetch_index() { local index="$1" local output="$2" local base base=$(es_base_url) curl --silent --show-error "${base}/${index}/_refresh" >/dev/null curl --silent --show-error "${base}/${index}/_search?size=${NUMMESSAGES}" > "$output" } ensure_elasticsearch_ready init_elasticsearch base=$(es_base_url) curl --silent --show-error -XDELETE "${base}/${RAW_INDEX}" >/dev/null || true curl --silent --show-error -XDELETE "${base}/${AMENDED_INDEX}" >/dev/null || true mkdir -p "$FB_WORKDIR/data" for i in $(seq 0 $((NUMMESSAGES - 1))) ; do printf 'msgnum:%08d:\n' "$i" done > "$FB_INPUT" generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") template(name="rawBeatEvent" type="string" string="%msg%") template(name="amendedBeatEvent" type="subtree" subtree="$!") ruleset(name="beats_to_es") { action(type="omelasticsearch" server="127.0.0.1" serverport="'$ES_PORT'" template="rawBeatEvent" searchIndex="'$RAW_INDEX'") set $!rsyslog!test!pipeline = "amended"; set $!rsyslog!test!marker = "'$MARKER'"; action(type="omelasticsearch" server="127.0.0.1" serverport="'$ES_PORT'" template="amendedBeatEvent" searchIndex="'$AMENDED_INDEX'") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="beats_to_es") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" cat > "$FB_CONFIG" </dev/null 2>&1 ; then if ! docker pull "$FB_IMAGE" ; then echo "docker pull for $FB_IMAGE failed, skipping test" exit 77 fi fi docker run -d --rm \ --name "$FB_CONTAINER" \ --network host \ --user root \ -v "$FB_DOCKER_MOUNT_SOURCE:/work" \ "$FB_IMAGE" \ filebeat -e --strict.perms=false -c /work/filebeat.yml > "$FB_LOG" shutdown_when_empty wait_shutdown docker rm -f "$FB_CONTAINER" >/dev/null 2>&1 || true fetch_index "$RAW_INDEX" "$RSYSLOG_DYNNAME.raw.work" fetch_index "$AMENDED_INDEX" "$RSYSLOG_DYNNAME.amended.work" "$PYTHON" - "$RSYSLOG_DYNNAME.raw.work" "$RSYSLOG_DYNNAME.amended.work" "$NUMMESSAGES" "$MARKER" <<'PY' || \ error_exit 1 import json import sys raw_path, amended_path, expected_count, marker = sys.argv[1], sys.argv[2], int(sys.argv[3]), sys.argv[4] def load_sources(path): with open(path, encoding="utf-8") as fh: data = json.load(fh) hits = data["hits"]["hits"] return sorted((hit["_source"] for hit in hits), key=lambda item: item.get("message", "")) raw = load_sources(raw_path) amended = load_sources(amended_path) if len(raw) != expected_count: raise SystemExit(f"raw index has {len(raw)} documents, expected {expected_count}") if len(amended) != expected_count: raise SystemExit(f"amended index has {len(amended)} documents, expected {expected_count}") for idx, (raw_doc, amended_doc) in enumerate(zip(raw, amended)): expected_message = f"msgnum:{idx:08d}:" if raw_doc.get("message") != expected_message: raise SystemExit(f"raw message mismatch at {idx}: {raw_doc.get('message')!r}") if amended_doc.get("message") != expected_message: raise SystemExit(f"amended message mismatch at {idx}: {amended_doc.get('message')!r}") if raw_doc.get("rsyslog_test_case") != marker: raise SystemExit(f"raw Filebeat marker missing at {idx}") if amended_doc.get("rsyslog_test_case") != marker: raise SystemExit(f"amended Filebeat marker changed at {idx}") if "rsyslog" in raw_doc: raise SystemExit(f"raw document unexpectedly contains rsyslog amendments at {idx}") rsyslog_meta = amended_doc.get("rsyslog", {}).get("test", {}) if rsyslog_meta.get("pipeline") != "amended" or rsyslog_meta.get("marker") != marker: raise SystemExit(f"amended rsyslog metadata missing at {idx}: {rsyslog_meta!r}") imbeats_meta = amended_doc.get("metadata", {}).get("imbeats", {}) if imbeats_meta.get("protocol") != "lumberjack-v2": raise SystemExit(f"imbeats protocol metadata missing at {idx}: {imbeats_meta!r}") if int(imbeats_meta.get("sequence", -1)) < 1: raise SystemExit(f"imbeats sequence metadata missing at {idx}: {imbeats_meta!r}") print("validated raw and amended Beats documents") PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-symlink-multi.sh0000644000000000000000000000013215216464436020331 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.891790591 30 ctime=1787067808.007978722 rsyslog-8.2608.0/tests/imfile-symlink-multi.sh0000775000175000017500000000560315216464436020004 0ustar00rgerrger#!/bin/bash # Verifies imfile wildcard handling for multiple symlinks to one target file. # The oracle is exact output metadata: rsyslog must report one record for the # original watched file and one record for each wildcard symlink, each with the # corresponding symlink filename and file offset. # This is part of the rsyslog testbench, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export IMFILEINPUTFILES="10" export IMFILECHECKTIMEOUT="60" mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' # comment out if you need more debug info: global( debug.whitelist="on" debug.files=["imfile.c"]) global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile" mode="inotify" normalizePath="off") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input-symlink.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value=", filename: ") property(name="$!metadata!filename") constant(value=", fileoffset: ") property(name="$!metadata!fileoffset") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt") ' # generate input files first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). imfilebefore="$RSYSLOG_DYNNAME.input-symlink.log" ./inputfilegen -m 1 > $imfilebefore mkdir $RSYSLOG_DYNNAME.targets # Start rsyslog now before adding more files startup cp $imfilebefore $RSYSLOG_DYNNAME.targets/target.log for i in $(seq 2 $IMFILEINPUTFILES); do ln -s $RSYSLOG_DYNNAME.targets/target.log $RSYSLOG_DYNNAME.input.$i.log # Let imfile observe each newly-created symlink before adding the next. ./msleep 50 done # Symlink creation is asynchronous from imfile's point of view. Wait until all # expected records are visible before shutdown, then keep the exact comparison. content_check_with_count "HEADER msgnum:000000" $IMFILEINPUTFILES $IMFILECHECKTIMEOUT shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! sort ${RSYSLOG_OUT_LOG} > ${RSYSLOG_OUT_LOG}.sorted echo HEADER msgnum:00000000:, filename: ./$RSYSLOG_DYNNAME.input-symlink.log, fileoffset: 0 > $RSYSLOG_DYNNAME.expected for i in $(seq 2 $IMFILEINPUTFILES) ; do echo HEADER msgnum:00000000:, filename: ./$RSYSLOG_DYNNAME.input.${i}.log, fileoffset: 0 >> $RSYSLOG_DYNNAME.expected done sort < $RSYSLOG_DYNNAME.expected | cmp - ${RSYSLOG_OUT_LOG}.sorted if [ ! $? -eq 0 ]; then echo "invalid output generated, ${RSYSLOG_OUT_LOG} is:" cat -n $RSYSLOG_OUT_LOG echo EXPECTED: cat -n $RSYSLOG_DYNNAME.expected error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/codex-pre-push-container-gate.sh0000644000000000000000000000013215241075234022001 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.682579736 30 ctime=1787067803.964903382 rsyslog-8.2608.0/tests/codex-pre-push-container-gate.sh0000775000175000017500000000642615241075234021460 0ustar00rgerrger#!/bin/sh # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Regression test for the Codex pre-push gate's explicit validation bypass. # It proves that direct, env-prefixed, and shell-wrapped inline overrides are # accepted, while ordinary and shell-wrapped pushes, false overrides, and # mixed command lists still produce the hook's deny decision. Empty output is # the allow oracle; the JSON permissionDecision=deny response is the block # oracle. The shell-wrapped blocked case proves wrapper push recognition. # This is intentionally standalone rather than a diag.sh scenario: it exercises # only hook command parsing and needs neither rsyslogd nor testbench helpers. # The hook is intentionally absent from release tarballs, so this test skips # there; source and CI checkouts retain the hook and run the assertions below. set -eu tmpdir="$(mktemp -d "${TMPDIR:-/tmp}/rsyslog-codex-push-gate.XXXXXX")" trap 'rm -rf "$tmpdir"' EXIT HUP INT TERM test_srcdir="${srcdir:-$(dirname "$0")}" gate_source="$test_srcdir/../.codex/pre_push_container_gate.sh" [ -f "$gate_source" ] || exit 77 command -v python3 >/dev/null 2>&1 || exit 77 mkdir -p "$tmpdir/.codex" cp "$gate_source" "$tmpdir/.codex/" gate="$tmpdir/.codex/pre_push_container_gate.sh" run_gate() { command_text="$1" python3 -c ' import json import sys print(json.dumps({ "hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": {"command": sys.argv[1]}, })) ' "$command_text" | "$gate" } assert_allowed() { command_text="$1" output="$(run_gate "$command_text")" if [ -n "$output" ]; then printf 'expected push command to be allowed: %s\n%s\n' "$command_text" "$output" >&2 exit 1 fi } assert_blocked() { command_text="$1" output="$(run_gate "$command_text")" case "$output" in *'"permissionDecision": "deny"'*) ;; *) printf 'expected push command to be blocked: %s\n%s\n' "$command_text" "$output" >&2 exit 1 ;; esac } assert_allowed 'SKIP_CONTAINER_VALIDATION=1 git push origin topic' assert_allowed 'env SKIP_CONTAINER_VALIDATION=1 git push origin topic' assert_allowed "bash -lc 'SKIP_CONTAINER_VALIDATION=1 git push origin topic'" assert_allowed "SKIP_CONTAINER_VALIDATION=1 bash -lc 'git push origin topic'" assert_allowed "env SKIP_CONTAINER_VALIDATION=1 sh -c 'git push origin topic'" assert_blocked 'git push origin topic' assert_blocked "bash -lc 'git push origin topic'" assert_blocked 'SKIP_CONTAINER_VALIDATION=0 git push origin topic' assert_blocked "SKIP_CONTAINER_VALIDATION=0 bash -lc 'git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'SKIP_CONTAINER_VALIDATION=0 git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'env -u SKIP_CONTAINER_VALIDATION git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'env --unset SKIP_CONTAINER_VALIDATION git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'env --unset=SKIP_CONTAINER_VALIDATION git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'env -uSKIP_CONTAINER_VALIDATION git push origin topic'" assert_blocked "SKIP_CONTAINER_VALIDATION=1 bash -lc 'unset SKIP_CONTAINER_VALIDATION; git push origin topic'" assert_blocked 'SKIP_CONTAINER_VALIDATION=1 git push origin topic; git push origin other' rsyslog-8.2608.0/tests/PaxHeaders/imrelp-sessionbreak-vg.sh0000644000000000000000000000013215131231047020622 xustar0030 mtime=1768239655.706212614 30 atime=1782715518.891790591 30 ctime=1787067807.761974138 rsyslog-8.2608.0/tests/imrelp-sessionbreak-vg.sh0000777000175000017500000000331115131231047020271 0ustar00rgerrger#!/bin/bash # added 2020-04-10 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000000 export USE_VALGRIND="YES" # TODO remote leak check skip and fix memory leaks caused by session break export RS_TESTBENCH_LEAK_CHECK=no mkdir $RSYSLOG_DYNNAME.workdir generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") global( workDirectory="'$RSYSLOG_DYNNAME.workdir'" maxMessageSize="256k" ) main_queue(queue.type="Direct") $LocalHostName test $AbortOnUncleanConfig on $PreserveFQDN on input( type="imrelp" name="imrelp" port="'$TCPFLOOD_PORT'" ruleset="spool" MaxDataSize="256k" KeepAlive="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="spool" queue.type="direct") { if $msg contains "msgnum:" then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } } ' startup # How many tcpfloods we run at the same tiem for ((i=1;i<=5;i++)); do # How many times tcpflood runs in each threads ./tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$NUMMESSAGES -s & tcpflood_pid=$! echo "started tcpflood instance $i (PID $tcpflood_pid)" # Give it time to actually connect ./msleep 500; kill -9 $tcpflood_pid # >/dev/null 2>&1; echo "killed tcpflood instance $i (PID $tcpflood_pid)" done; wait_queueempty netstatresult=$(netstat --all --program 2>&1 | grep "ESTABLISHED" | grep $(cat $RSYSLOG_PIDBASE.pid) | grep $TCPFLOOD_PORT) openfd=$(ls -l "/proc/$(cat $RSYSLOG_PIDBASE$1.pid)/fd" | wc -l) shutdown_when_empty wait_shutdown if [[ "$netstatresult" == "" ]] then echo "OK!" else echo "STILL OPENED Connections: " echo $netstatresult echo "Open files at the end: " echo $openfd error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-crash-seal-write.sh0000644000000000000000000000013215241075234023360 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.791900158 rsyslog-8.2608.0/tests/segmented-diskqueue-crash-seal-write.sh0000775000175000017500000000030415241075234023024 0ustar00rgerrger#!/bin/bash # Crash after writing a seal footer but before rename; restart salvages the tail. export SEGDISK_FAULT_POINT=seal-written . ${srcdir:=.}/testsuites/segmented-diskqueue-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/rfc5424parser-sp_at_msg_start.sh0000644000000000000000000000013215131231047021727 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.891790591 30 ctime=1787067804.318909979 rsyslog-8.2608.0/tests/rfc5424parser-sp_at_msg_start.sh0000777000175000017500000000156115131231047021403 0ustar00rgerrger#!/bin/bash # checks that in RFC5424 mode SP at beginning of MSG part is properly handled # This file is part of the rsyslog project, released under ASL 2.0 # rgerhards, 2019-05-17 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%--END\n") if $syslogtag == "tag" then action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - - nosd-nosp' injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - [abc@123 a="b"] sd-nosp' injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - - nosd-sp' injectmsg literal '<13>1 2019-05-15T11:21:57+03:00 domain.tld tag - - [abc@123 a="b"] sd-sp' shutdown_when_empty wait_shutdown export EXPECTED='nosd-nosp--END sd-nosp--END nosd-sp--END sd-sp--END' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs.sh0000644000000000000000000000013215241075234023571 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.600971137 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs.sh0000775000175000017500000000015115241075234023235 0ustar00rgerrger#!/bin/bash export PKCS11_SIGALG_VARIANT=cert_key . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-sigalgs-common.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-gtls-auto-sni.sh0000644000000000000000000000013215216464436020670 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.890790574 30 ctime=1787067807.347966422 rsyslog-8.2608.0/tests/omfwd-tls-gtls-auto-sni.sh0000775000175000017500000000133415216464436020340 0ustar00rgerrger#!/bin/bash # Author: John Cantu # Test that "localhost" is sent as SNI by omfwd, when connecting to a hostname and no SNI is configured . ${srcdir:=.}/diag.sh init port_file="$RSYSLOG_DYNNAME.sni-server.port" omfwd_sni_server "gnutls" "$port_file" port=$(cat "$port_file") generate_conf add_conf ' global(DefaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" \ net.ipprotocol="ipv4-only") action(type="omfwd" target="localhost" protocol="tcp" port="'$port'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon" ) ' startup omfwd_sni_check "localhost" shutdown_immediate wait_shutdown kill -9 $(cat "$RSYSLOG_DYNNAME.sni-server.pid") exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-healthcheck-api-key-auth.sh0000644000000000000000000000013215216464436022312 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.890790574 30 ctime=1787067806.414949037 rsyslog-8.2608.0/tests/imhttp-healthcheck-api-key-auth.sh0000775000175000017500000000164015216464436021762 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify the imhttp healthcheck endpoint while the HTTP listener uses an # OS-assigned port. The HTTP status or response body is the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'" healthCheckApiKeyFile="'$srcdir'/testsuites/imhttp-apikeys.txt") ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" ret=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:$IMHTTP_PORT/healthz) if [ "$ret" != "401" ]; then echo "ERROR: expected 401 without API key, got $ret" error_exit 1 fi curl -s -H 'Authorization: ApiKey secret-token-1' \ http://localhost:$IMHTTP_PORT/healthz > "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "OK" exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-scope-action.sh0000644000000000000000000000013215241075234020621 xustar0030 mtime=1787067036.617578519 30 atime=1787067036.682579736 30 ctime=1787067803.765899674 rsyslog-8.2608.0/tests/diskqueue-scope-action.sh0000775000175000017500000000027215241075234020271 0ustar00rgerrger#!/bin/bash # Classic Disk wrapper for the backend-neutral action-queue scope driver. export QUEUE_TYPE=Disk QUEUE_SCOPE=action . ${srcdir:=.}/testsuites/pure-disk-queue-scope-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-scope-main.sh0000644000000000000000000000013215241075234020270 xustar0030 mtime=1787067036.617578519 30 atime=1787067036.682579736 30 ctime=1787067803.761899599 rsyslog-8.2608.0/tests/diskqueue-scope-main.sh0000775000175000017500000000026615241075234017743 0ustar00rgerrger#!/bin/bash # Classic Disk wrapper for the backend-neutral main-queue scope driver. export QUEUE_TYPE=Disk QUEUE_SCOPE=main . ${srcdir:=.}/testsuites/pure-disk-queue-scope-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/omawslogshlc-event-too-large.sh0000644000000000000000000000013115241075234021747 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.686579811 29 ctime=1787067806.33194749 rsyslog-8.2608.0/tests/omawslogshlc-event-too-large.sh0000775000175000017500000000265515241075234021427 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Test that omawslogshlc rejects a rendered event over the CloudWatch HLC # 256 KiB per-event limit locally, before attempting HTTP delivery. The oracle # is the internal rsyslog diagnostic emitted after tcpflood sends one # deliberately oversized message through a larger global(maxMessageSize) # setting and a dynamically allocated imtcp listener. . ${srcdir:=.}/diag.sh init require_plugin "omawslogshlc" require_plugin "imtcp" generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info" maxMessageSize="300k") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omawslogshlc/.libs/omawslogshlc") template(name="omawslogshlc-plain" type="string" string="%msg%\n") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="send") ruleset(name="send") { action( type="omawslogshlc" region="us-west-2" bearer_token="fake-token" log_group="test-group" log_stream="test-stream" template="omawslogshlc-plain" action.resumeRetryCount="0" ) } *.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" tcpflood -p"$TCPFLOOD_PORT" -m1 -d 270000 -P129 shutdown_when_empty wait_shutdown content_check "omawslogshlc: single event size" content_check "exceeds 256 KiB limit" check_not_present "omawslogshlc: HTTP" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdtls-error-cert.sh0000644000000000000000000000013215241075234017616 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.769581365 30 ctime=1787067807.778974454 rsyslog-8.2608.0/tests/imdtls-error-cert.sh0000775000175000017500000000207115241075234017265 0ustar00rgerrger#!/bin/bash # added 2018-11-07 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 # Verify that imdtls reports TLS object load errors during startup. This # fixture intentionally pairs an invalid private key file with a certificate # path so startup fails before any listener becomes functional. No traffic is # sent; the configured rsyslog diagnostics are the pass/fail oracle. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-fail.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'" ) module( load="../plugins/imdtls/.libs/imdtls" ) input( type="imdtls" port="0") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # note: we do not need to generate any messages, config error occurs on startup startup sleep 5 # TODO: FIXME - just checking if we terminate too early shutdown_when_empty wait_shutdown content_check "Error: Key could not be accessed" content_check "OpenSSL Error Stack:" exit_test rsyslog-8.2608.0/tests/PaxHeaders/allowed-sender-tcp-ok.sh0000644000000000000000000000013215035412264020337 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.896790676 30 ctime=1787067804.399911488 rsyslog-8.2608.0/tests/allowed-sender-tcp-ok.sh0000777000175000017500000000134015035412264020006 0ustar00rgerrger#!/bin/bash # check that we are able to receive messages from allowed sender # added 2019-08-15 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5 # it's just important that we get any messages at all generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $AllowedSender TCP,127.0.0.1/16,[::1] template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsontransform-policy-watch.sh0000644000000000000000000000013115241075234022077 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 29 ctime=1787067807.23996441 rsyslog-8.2608.0/tests/mmjsontransform-policy-watch.sh0000775000175000017500000000534515241075234021556 0ustar00rgerrger#!/bin/bash # Validate mmjsontransform watch-based YAML policy reload, including # rename-over-save updates. . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify # port is assigned by diag.sh from listenPortFileName POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" export POLICY_FILE POLICY_TMP="$(pwd)/${RSYSLOG_DYNNAME}.policy.tmp.yaml" export POLICY_TMP cat > "$POLICY_FILE" <<'YAML' version: 1 mode: flatten map: rename: "usr": "user.name" "ctx.old": "ctx.new" YAML generate_conf add_conf ' global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmjsontransform/.libs/mmjsontransform") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!output%\n") local4.* { set $.ret = parse_json($msg, "\$!input"); action(type="mmjsontransform" policy="'$POLICY_FILE'" policyWatch="on" policyWatchDebounce="200ms" input="$!input" output="$!output") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' check_json() { python3 - "$1" "$2" <<'PY' import json import sys path = sys.argv[1] expected = json.loads(sys.argv[2]) with open(path, "r", encoding="utf-8") as fh: lines = [line.strip() for line in fh if line.strip()] if len(lines) != 1: print("expected 1 JSON line, got", len(lines)) sys.exit(1) obj = json.loads(lines[0]) if obj != expected: print("unexpected output:", obj) sys.exit(1) PY } startup ./msleep 1000 tcpflood -Ttcp -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"alice\", \"ctx\": { \"old\": 1 } }"' wait_file_lines "$RSYSLOG_OUT_LOG" 1 100 check_json "$RSYSLOG_OUT_LOG" '{"user.name":"alice","ctx.new":1}' if [ $? -ne 0 ]; then error_exit 1; fi : > "$RSYSLOG_OUT_LOG" cat > "$POLICY_FILE" <<'YAML' version: 1 mode: unflatten map: rename: "usr": "actor.name" "ctx.old": "ctx.after" YAML ./msleep 1000 tcpflood -Ttcp -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"bob\", \"ctx\": { \"old\": 2 }, \"debug\": true }"' wait_file_lines "$RSYSLOG_OUT_LOG" 1 100 check_json "$RSYSLOG_OUT_LOG" '{"actor":{"name":"bob"},"ctx":{"after":2},"debug":true}' if [ $? -ne 0 ]; then error_exit 1; fi : > "$RSYSLOG_OUT_LOG" cat > "$POLICY_TMP" <<'YAML' version: 1 mode: flatten map: rename: "usr": "user.name" "ctx.old": "ctx.new" YAML mv -f "$POLICY_TMP" "$POLICY_FILE" ./msleep 1000 tcpflood -Ttcp -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"carol\", \"ctx\": { \"old\": 3 } }"' wait_file_lines "$RSYSLOG_OUT_LOG" 1 100 check_json "$RSYSLOG_OUT_LOG" '{"user.name":"carol","ctx.new":3}' if [ $? -ne 0 ]; then error_exit 1; fi shutdown_when_empty wait_shutdown rm -f "$POLICY_FILE" "$POLICY_TMP" exit_test rsyslog-8.2608.0/tests/PaxHeaders/container-noise-drop.sh0000644000000000000000000000013215216464436020307 xustar0030 mtime=1782212894.047266524 30 atime=1782715518.895790659 30 ctime=1787067804.965922036 rsyslog-8.2608.0/tests/container-noise-drop.sh0000775000175000017500000000462115216464436017761 0ustar00rgerrger#!/bin/bash # Verify the container noise-drop lookup-table pattern. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="container_noise" file="'$RSYSLOG_DYNNAME'.noise-drop.lkp_tbl" reloadOnHUP="on") template(name="outfmt" type="string" string="%msg%\n") set $.container_noise_tag = lookup("container_noise", $rawmsg); if (strlen($.container_noise_tag) > 0) then { stop } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' printf '%s\n' \ '{ "version": 1, "nomatch": "", "type": "regex", "table": [] }' \ > "$RSYSLOG_DYNNAME.noise-drop.lkp_tbl" startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - empty-table-pass' wait_queueempty printf '%s\n' \ '{ "version": 1, "nomatch": "", "type": "regex", "table": [' \ ' { "regex": "drop-default", "tag": "drop" }' \ '] }' > "$RSYSLOG_DYNNAME.noise-drop.lkp_tbl" issue_HUP await_lookup_table_reload injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - keep-default' injectmsg_literal '<165>1 2003-03-01T01:00:01.000Z host app - - - drop-default' wait_queueempty shutdown_when_empty wait_shutdown content_check "empty-table-pass" content_check "keep-default" check_not_present "drop-default" generate_conf 2 add_conf ' lookup_table(name="container_noise" file="'$RSYSLOG_DYNNAME'.noise-drop-2.lkp_tbl" reloadOnHUP="on") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="rs-main" queue.type="direct") { set $.container_noise_tag = lookup("container_noise", $rawmsg); if (strlen($.container_noise_tag) > 0) then { stop } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt") } call rs-main ' 2 printf '%s\n' \ '{ "version": 1, "nomatch": "", "type": "regex", "table": [' \ ' { "regex": "drop-named", "tag": "drop" }' \ '] }' > "$RSYSLOG_DYNNAME.noise-drop-2.lkp_tbl" startup 2 injectmsg2_literal() { printf 'injecting msg payload into instance 2: %s\n' "$1" printf '%s\n' "$1" | sed -e 's/^/injectmsg literal /g' | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT2 || error_exit $? } injectmsg2_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - keep-named' injectmsg2_literal '<165>1 2003-03-01T01:00:01.000Z host app - - - drop-named' wait_queueempty 2 shutdown_when_empty 2 wait_shutdown 2 custom_content_check "keep-named" "$RSYSLOG2_OUT_LOG" check_not_present "drop-named" "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-logrotate.sh0000644000000000000000000000013115171370365017507 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.895790659 29 ctime=1787067808.01597887 rsyslog-8.2608.0/tests/imfile-logrotate.sh0000775000175000017500000000352415171370365017163 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . $srcdir/diag.sh check-inotify-only . ${srcdir:=.}/diag.sh init check_command_available logrotate export TESTMESSAGES=10000 export RETRIES=50 export TESTMESSAGESFULL=19999 generate_conf add_conf ' $WorkDirectory '$RSYSLOG_DYNNAME'.spool /* Filter out busy debug output */ global( debug.whitelist="off" debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"] ) module( load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on" ) $template outfmt,"%msg:F,58:2%\n" if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' # Write logrotate config file echo '"./'$RSYSLOG_DYNNAME'.input.*.log" { su '"$(id -un)"' '"$(id -gn)"' rotate 7 create daily missingok notifempty compress }' > $RSYSLOG_DYNNAME.logrotate # generate input file first. ./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log ls -l $RSYSLOG_DYNNAME.input* startup # Wait until testmessages are processed by imfile! wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES # Logrotate on logfile logrotate --state $RSYSLOG_DYNNAME.logrotate.state -f $RSYSLOG_DYNNAME.logrotate # generate more input after logrotate into new logfile ./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.1.log ls -l $RSYSLOG_DYNNAME.input* echo ls ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool msgcount=$((2* TESTMESSAGES)) wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! seq_check 0 $TESTMESSAGESFULL exit_test rsyslog-8.2608.0/tests/PaxHeaders/incltest.sh0000644000000000000000000000013215035412264016064 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.894790642 30 ctime=1787067804.941921588 rsyslog-8.2608.0/tests/incltest.sh0000777000175000017500000000043015035412264015532 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/include.conf " startup # 100 messages are enough - the question is if the include is read ;) injectmsg 0 100 shutdown_when_empty wait_shutdown seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-minbatch-queuefull.sh0000644000000000000000000000013215035412264021153 xustar0030 mtime=1752569012.409688211 30 atime=1782715518.894790642 30 ctime=1787067804.366910873 rsyslog-8.2608.0/tests/queue-minbatch-queuefull.sh0000777000175000017500000000123315035412264020623 0ustar00rgerrger#!/bin/bash # added 2019-01-14 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris - see https://github.com/rsyslog/rsyslog/issues/3513" export NUMMESSAGES=10000 generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" queue.type="linkedList" queue.size="2001" queue.dequeuebatchsize="2001" queue.mindequeuebatchsize="2001" queue.minDequeueBatchSize.timeout="2000" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmrm1stspace-basic.sh0000644000000000000000000000013115241075234017732 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067807.039960683 rsyslog-8.2608.0/tests/mmrm1stspace-basic.sh0000775000175000017500000000202515241075234017401 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") module(load="../plugins/mmrm1stspace/.libs/mmrm1stspace") template(name="outfmt" type="string" string="-%msg%-\n") action(type="mmrm1stspace") :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:3\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag4:\"" shutdown_when_empty wait_shutdown echo '-msgnum:1- - msgnum:2- -msgnum:3- --' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_split-vg.sh0000644000000000000000000000013115241075234017552 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067805.311928483 rsyslog-8.2608.0/tests/rscript_split-vg.sh0000775000175000017500000000446115241075234017227 0ustar00rgerrger#!/bin/bash # Added 2025-12-19 by 20syldev, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!result%\n") if $msg contains "msgnum:00000000" then { # Basic case: normal split with multi-char separator set $!input = "abc@example.com, def@example.com, ghi@example.com"; set $!result = split($!input, ", "); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000001" then { # Edge case: empty input string set $!result = split("", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000002" then { # Edge case: trailing separator set $!result = split("a,b,", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000003" then { # Edge case: leading separator set $!result = split(",a,b", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000004" then { # Edge case: multiple separators together (empty field) set $!result = split("a,,b", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000005" then { # Edge case: input string is just the separator set $!result = split(",", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000006" then { # Edge case: input string with no separators set $!result = split("abc", ","); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } if $msg contains "msgnum:00000007" then { # Edge case: empty separator string (returns empty array) set $!result = split("abc", ""); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup_vg tcpflood -m8 shutdown_when_empty wait_shutdown_vg check_exit_vg # Verify all test cases export EXPECTED='[ "abc@example.com", "def@example.com", "ghi@example.com" ] [ "" ] [ "a", "b", "" ] [ "", "a", "b" ] [ "a", "", "b" ] [ "", "" ] [ "abc" ] [ ]' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/omotel-basic.sh0000644000000000000000000000013215145046113016613 xustar0030 mtime=1771326539.057014582 30 atime=1782715518.893790625 30 ctime=1787067806.204945123 rsyslog-8.2608.0/tests/omotel-basic.sh0000775000175000017500000000675615145046113016300 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-basic.sh -- basic functionality test for omotel module ## ## Starts OTEL Collector, sends messages via omotel, and verifies ## messages are received and stored correctly in OTLP JSON format. . ${srcdir:=.}/diag.sh init # Check if omotel module is available # NOTE: The module must be enabled during configure with --enable-omotel # If the module fails to load with error -1001 (RS_RET_MISSING_INTERFACE), # the module was not built correctly and needs to be rebuilt with --enable-omotel require_plugin omotel export NUMMESSAGES=1000 export EXTRA_EXIT=otel export SEQ_CHECK_OPTIONS=-d # Download and prepare OTEL Collector download_otel_collector prepare_otel_collector start_otel_collector # Read the port from the port file if [ ! -f ${RSYSLOG_DYNNAME}.otel_port.file ]; then echo "ERROR: OTEL Collector port file not found: ${RSYSLOG_DYNNAME}.otel_port.file" error_exit 1 fi otel_port=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) if [ -z "$otel_port" ]; then echo "ERROR: OTEL Collector port is empty" error_exit 1 fi echo "Using OTEL Collector port: $otel_port" generate_conf add_conf ' template(name="otlpBody" type="string" string="msgnum:%msg:F,58:2%") module(load="../plugins/omotel/.libs/omotel") if $msg contains "msgnum:" then action( name="omotel-http" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port'" path="/v1/logs" batch.max_items="100" batch.timeout.ms="1000" ) ' startup injectmsg shutdown_when_empty wait_shutdown # Stop OTEL Collector to ensure file exporter flushes data # The file exporter may buffer data until collector shuts down stop_otel_collector # Give OTEL Collector a moment to flush the output file after shutdown if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi # Extract data from OTEL Collector output otel_collector_get_data python3 - "$RSYSLOG_DYNNAME.otel-output.json" <<'PY' import json import sys path = sys.argv[1] try: # OTEL Collector file exporter writes newline-delimited JSON (one JSON object per line) records = [] with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue payload = json.loads(line) if "resourceLogs" in payload: for resource_log in payload["resourceLogs"]: if "scopeLogs" in resource_log: for scope_log in resource_log["scopeLogs"]: if "logRecords" in scope_log: records.extend(scope_log["logRecords"]) except Exception as exc: sys.stderr.write(f"omotel-basic: failed to parse OTLP output: {exc}\n") sys.exit(1) if not records: sys.stderr.write("omotel-basic: OTLP output did not contain any logRecords\n") sys.exit(1) def has_hostname(attrs): for entry in attrs: if entry.get("key") == "log.syslog.hostname": val = entry.get("value", {}).get("stringValue", "") if val: return True return False for idx, record in enumerate(records): if record.get("severityNumber", 0) == 0: sys.stderr.write(f"omotel-basic: record {idx} missing severityNumber\n") sys.exit(1) if not has_hostname(record.get("attributes", [])): sys.stderr.write(f"omotel-basic: record {idx} missing log.syslog.hostname attribute\n") sys.exit(1) PY seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_key_truncated.sh0000644000000000000000000000013215241075234022727 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 30 ctime=1787067806.893957963 rsyslog-8.2608.0/tests/rscript_unflatten_key_truncated.sh0000775000175000017500000000340515241075234022400 0ustar00rgerrger#!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $!a.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb255ccccc.d = "bar"; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "a": { "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb255": { "d": "bar" } } }' cmp_exact "$RSYSLOG_OUT_LOG" EXPECTED='fmunflatten.c: warning: flat key "a.bbbbbbbbbbbbbbbbbb..." truncated at depth #1, buffer too small (max 256)' if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then echo "GREP FAILED" echo " => FILE: $RSYSLOG_DEBUGLOG" echo " => EXPECTED: $EXPECTED" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-error-cert.sh0000644000000000000000000000013215241075234021666 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.383967093 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-error-cert.sh0000775000175000017500000000167415241075234021345 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=3 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-fail.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # Begin actual testcase startup tcpflood --check-only -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown content_check "nsd mbedtls: error parsing crypto config" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdtls-basic-tlscommands.sh0000644000000000000000000000013215216464436021145 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.892790608 30 ctime=1787067807.773974361 rsyslog-8.2608.0/tests/imdtls-basic-tlscommands.sh0000775000175000017500000000277415216464436020626 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 # Verify that imdtls applies OpenSSL TLS config commands. The sender is # configured to fail the handshake, and the expected TLS diagnostic is the oracle. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imdtls/.libs/imdtls" ) input( type="imdtls" tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.1,-TLSv1.3 Options=Bugs" port="0" listenPortFileName="'$PORT_RCVR_FILE'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" # now inject the messages which will fail due protocol configuration tcpflood --check-only -k "Protocol=-ALL,TLSv1.3" -p$PORT_RCVR -m$NUMMESSAGES -Tdtls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown if content_check --check-only "TLS library does not support SSL_CONF_cmd" then echo "SKIP: TLS library does not support SSL_CONF_cmd" skip_test else if content_check --check-only "DTLSv1_listen" then # Found DTLSv1_listen error, no further check needed exit_test else # Check for OpenSSL Error Stack content_check "OpenSSL Error Stack:" fi fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-numstr.sh0000644000000000000000000000013215171370365022377 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.892790608 30 ctime=1787067804.848919855 rsyslog-8.2608.0/tests/rscript_compare_numstr-numstr.sh0000775000175000017500000000014415171370365022045 0ustar00rgerrger#!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='"2"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/mysql-basic-cnf6.sh0000644000000000000000000000013215035412264017315 xustar0030 mtime=1752569012.402736851 30 atime=1782715518.892790608 30 ctime=1787067805.911939664 rsyslog-8.2608.0/tests/mysql-basic-cnf6.sh0000777000175000017500000000072315035412264016770 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 generate_conf add_conf ' $ModLoad ../plugins/ommysql/.libs/ommysql if $msg contains "msgnum" then { action(type="ommysql" server="127.0.0.1" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench") } ' mysql_prep_for_test startup injectmsg shutdown_when_empty wait_shutdown mysql_get_data seq_check mysql_cleanup_test exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_12_ipv4.sh0000644000000000000000000000013215241075234020030 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.725936198 rsyslog-8.2608.0/tests/mmanon_zero_12_ipv4.sh0000775000175000017500000000155015241075234017500 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.bits="12") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255 <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.\"" shutdown_when_empty wait_shutdown export EXPECTED=' 1.1.0.0 0.0.0.0 172.0.224.0 111.1.0.0.' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-encryption-disk_keyfile.sh0000644000000000000000000000013215035412264022213 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.892790608 30 ctime=1787067805.111924756 rsyslog-8.2608.0/tests/queue-encryption-disk_keyfile.sh0000777000175000017500000000172415035412264021670 0ustar00rgerrger#!/bin/bash # addd 2018-09-30 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.filename="mainq" queue.type="disk" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutenqueue="300000" queue.lowwatermark="5000" queue.cry.provider="gcry" queue.cry.keyfile="'$RSYSLOG_DYNNAME.keyfile'" queue.saveonshutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :omtesting:sleep 0 5000 :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' printf "1234567890123456" > $RSYSLOG_DYNNAME.keyfile startup injectmsg 0 1000 shutdown_immediate wait_shutdown echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0* exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-key-mtls-sigalgs.sh0000644000000000000000000000013215241075234023424 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.609971305 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-key-mtls-sigalgs.sh0000775000175000017500000000015115241075234023070 0ustar00rgerrger#!/bin/bash export PKCS11_SIGALG_VARIANT=key_only . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-sigalgs-common.sh rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-cri-partial-bound.sh0000644000000000000000000000013215241075234022247 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067808.166981685 rsyslog-8.2608.0/tests/imkubernetes-cri-partial-bound.sh0000775000175000017500000000636715241075234021732 0ustar00rgerrger#!/bin/bash # Verify that unfinished CRI partial records are bounded before enqueue. # The closing F record after an oversized partial run still belongs to that # logical message and must not be emitted as a standalone tail record. # The API helper signals readiness after binding; its 2m timeout is hang # protection, while the explicit kill and wait below own normal cleanup. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes check_command_available timeout export NUMMESSAGES=2 pwd=$( pwd ) testsrv=imk8s-partial-bound-server k8s_srv_port=0 k8s_srv_port_file=${RSYSLOG_DYNNAME}${testsrv}.port logdir="${RSYSLOG_DYNNAME}.spool/pods/namespace-name1_pod-name1_uid1/container-a" logfile="${logdir}/0.log" mkdir -p "$logdir" echo starting kubernetes test server MMK8S_INCLUDE_NODE_NAME=1 timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py \ 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ $k8s_srv_port_file \ > ${RSYSLOG_DYNNAME}.spool/imkubernetes_partial_bound_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started assign_file_content k8s_srv_port "$k8s_srv_port_file" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'" maxMessageSize="128" oversizemsg.input.mode="truncate") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" KubernetesUrl="http://localhost:'$k8s_srv_port'" Token="dummy" cacheEntryTtl="60") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="pod_id" name="$!kubernetes!pod_id" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup { for i in $(seq 1 8); do printf '2026-04-20T10:00:%02d.000000000Z stdout P %s\n' "$i" \ 'partial-fragment-0123456789' done printf '%s\n' '2026-04-20T10:00:30.000000000Z stdout F closing-tail-must-not-standalone' printf '%s\n' '2026-04-20T10:00:31.000000000Z stdout F after partial cap' } > "$logfile" wait_file_lines "$RSYSLOG_OUT_LOG" 2 wait_queueempty shutdown_when_empty wait_shutdown kill $BGPROCESS wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid if ! $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "cri"] assert len(records) == 2, records expected_prefix = ("partial-fragment-0123456789" * 8)[:128] partial = records[0] assert partial["msg"] == expected_prefix, partial assert "closing-tail-must-not-standalone" not in partial["msg"], partial assert partial["stream"] == "stdout", partial assert partial["pod_id"] == "pod-name1-id", partial independent = records[1] assert independent["msg"] == "after partial cap", independent assert independent["stream"] == "stdout", independent assert independent["pod_id"] == "pod-name1-id", independent PY then error_exit 1 "imkubernetes did not preserve oversized CRI partial truncation semantics" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-maxdiskspace.sh0000644000000000000000000000013215241075234022662 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.752899432 rsyslog-8.2608.0/tests/segmented-diskqueue-maxdiskspace.sh0000775000175000017500000000343215241075234022333 0ustar00rgerrger#!/bin/bash # Fill a bounded segmentedDisk queue while the consumer is slowed, then drain # and enqueue a second wave. Complete delivery proves producer backpressure, # worker wakeup when a multi-submit blocks at the disk limit, and post-delete # reuse. Like the classic disk queue, the current record may cross the byte # limit; the oracle permits one bounded record/topology overshoot. . ${srcdir:=.}/diag.sh init require_plugin impstats export NUMMESSAGES=2000 STATS_FILE="$PWD/${RSYSLOG_DYNNAME}.stats.log" generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") module(load="../plugins/impstats/.libs/impstats" log.file="'$STATS_FILE'" interval="1") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.maxDiskSpace="64k" queue.maxFileSize="8k" queue.timeoutEnqueue="300000" queue.dequeueBatchSize="16") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" :omtesting:sleep 0 1000 if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -p"$TCPFLOOD_PORT" -m1000 -i0 wait_file_lines "$RSYSLOG_OUT_LOG" 1000 tcpflood -p"$TCPFLOOD_PORT" -m1000 -i1000 wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" shutdown_when_empty wait_shutdown seq_check max_usage=$(grep 'disk.usage=' "$STATS_FILE" | sed -E 's/.*disk\.usage=([0-9]+).*/\1/' | sort -n | tail -n 1) if [ "${max_usage:-0}" -gt 66560 ]; then printf 'FAIL: segmentedDisk sampled usage %s exceeds the 64 KiB limit plus one record\n' "$max_usage" cat "$STATS_FILE" error_exit 1 fi rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/gtls-absolute-module-path.sh0000644000000000000000000000013215241075234021242 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067807.271965007 rsyslog-8.2608.0/tests/gtls-absolute-module-path.sh0000775000175000017500000000164715241075234020721 0ustar00rgerrger#!/bin/bash # Regression test for loading the GnuTLS netstream driver by absolute path. # The issue report used module(load="/custom/path/lmnsd_gtls.so"), which caused # early driver initialization to dereference runConf before a config was active. # Oracle: rsyslogd -C -N1 must accept the config without crashing. # added 2026-06-23 by Codex # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init gtls_module="$(cd .. && pwd)/runtime/.libs/lmnsd_gtls.so" if [ ! -f "$gtls_module" ]; then echo "lmnsd_gtls module not built - skipping test" exit 77 fi generate_conf add_conf ' global( workDirectory="'$RSYSLOG_DYNNAME'.spool" debug.gnutls="1" defaultNetstreamDriver="gtls" ) module(load="'$gtls_module'") ' ../tools/rsyslogd -C -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 0 ]; then cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropuser.sh0000644000000000000000000000013115131231047016775 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.892790608 29 ctime=1787067804.22990832 rsyslog-8.2608.0/tests/privdropuser.sh0000777000175000017500000000111515131231047016445 0ustar00rgerrger#!/bin/bash # addd 2016-03-24 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) $PrivDropToUser '${TESTBENCH_TESTUSER[username]}' ' startup shutdown_when_empty wait_shutdown content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omsendertrack-statefile-vg.sh0000644000000000000000000000013215171370365021476 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.892790608 30 ctime=1787067805.101924569 rsyslog-8.2608.0/tests/omsendertrack-statefile-vg.sh0000775000175000017500000000012015171370365021136 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omsendertrack-statefile.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-subtree-tpl.sh0000644000000000000000000000013215216464436017630 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.893790625 30 ctime=1787067804.161907053 rsyslog-8.2608.0/tests/omfwd-subtree-tpl.sh0000775000175000017500000000142015216464436017274 0ustar00rgerrger#!/bin/bash # Verify omfwd forwards messages when using subtree-type templates. The oracle # is the received JSON subtree payload, and the receiver must be listening # before rsyslog starts so the single test message is not lost to startup # timing. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 template(name="csl-subtree" type="subtree" subtree="$!csl") if $msg contains "msgnum:" then { set $!csl!foo = "bar"; action(type="omfwd" template="csl-subtree" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp") } ' start_minitcpsrv_ready "$RSYSLOG_OUT_LOG" "$TCPFLOOD_PORT" startup injectmsg 0 1 shutdown_when_empty wait_shutdown content_check '{ "foo": "bar" }' "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/no-dynstats.sh0000644000000000000000000000013015131231047016513 xustar0029 mtime=1768239655.71021268 30 atime=1782715518.892790608 29 ctime=1787067806.69795431 rsyslog-8.2608.0/tests/no-dynstats.sh0000777000175000017500000000160415131231047016167 0ustar00rgerrger#!/bin/bash # added 2016-03-10 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[no-dynstats.sh\]: test for verifying stats are reported correctly in legacy format in absence of any dynstats buckets being configured . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown custom_content_check 'global: origin=dynstats' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock-NUL-vg.sh0000644000000000000000000000013215216464436017160 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.893790625 30 ctime=1787067805.127925054 rsyslog-8.2608.0/tests/imuxsock-NUL-vg.sh0000775000175000017500000000064115216464436016630 0ustar00rgerrger#!/usr/bin/env bash # Valgrind coverage for imuxsock-NUL.sh. The base test checks exact sanitized # output; this wrapper also detects the uninitialized-byte reads/writes reported # in issue #4941 without combining Valgrind with TSAN. export USE_VALGRIND="YES" if [ -z "${srcdir+x}" ] && [ ! -f ./diag.sh ] && [ -f "$(dirname "$0")/diag.sh" ]; then cd "$(dirname "$0")" || exit 1 fi . "${srcdir:=.}/imuxsock-NUL.sh" rsyslog-8.2608.0/tests/PaxHeaders/imbeats-filebeat-docker.sh0000644000000000000000000000013215216464436020712 xustar0030 mtime=1782212894.052266604 30 atime=1782715518.892790608 30 ctime=1787067806.472950117 rsyslog-8.2608.0/tests/imbeats-filebeat-docker.sh0000775000175000017500000000423115216464436020361 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init check_command_available docker if ! docker info >/dev/null 2>&1 ; then echo "docker daemon not available, skipping test" exit 77 fi export NUMMESSAGES=200 export SEQ_CHECK_FILE="${TESTTOOL_DIR}/${RSYSLOG_OUT_LOG}" export FB_IMAGE="${FB_IMAGE:-docker.elastic.co/beats/filebeat:9.2.0}" export FB_CONTAINER="fb-imbeats-${RSYSLOG_DYNNAME}" export FB_WORKDIR="${TESTTOOL_DIR}/${RSYSLOG_DYNNAME}.filebeat" if [ -z "$FB_DOCKER_MOUNT_SOURCE" ] && [ -n "$GITHUB_WORKSPACE" ] ; then case "$FB_WORKDIR" in /rsyslog/*) FB_DOCKER_MOUNT_SOURCE="${GITHUB_WORKSPACE}${FB_WORKDIR#/rsyslog}" ;; esac fi export FB_DOCKER_MOUNT_SOURCE="${FB_DOCKER_MOUNT_SOURCE:-$FB_WORKDIR}" export FB_INPUT="${FB_WORKDIR}/input.log" export FB_CONFIG="${FB_WORKDIR}/filebeat.yml" export FB_LOG="${FB_WORKDIR}/docker.log" cleanup_filebeat() { docker rm -f "$FB_CONTAINER" >/dev/null 2>&1 || true rm -rf "$FB_WORKDIR" } trap cleanup_filebeat EXIT mkdir -p "$FB_WORKDIR/data" for i in $(seq 0 $((NUMMESSAGES - 1))) ; do printf 'msgnum:%08d:\n' "$i" done > "$FB_INPUT" generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%$!message%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" cat > "$FB_CONFIG" </dev/null 2>&1 || docker pull "$FB_IMAGE" >/dev/null docker run -d --rm \ --name "$FB_CONTAINER" \ --network host \ --user root \ -v "$FB_DOCKER_MOUNT_SOURCE:/work" \ "$FB_IMAGE" \ filebeat -e --strict.perms=false -c /work/filebeat.yml > "$FB_LOG" wait_file_lines "$SEQ_CHECK_FILE" "$NUMMESSAGES" docker rm -f "$FB_CONTAINER" >/dev/null 2>&1 || true shutdown_when_empty wait_shutdown cmp "$FB_INPUT" "$SEQ_CHECK_FILE" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_dtls_certvalid_ciphers.sh0000644000000000000000000000013115216464436022346 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.891790591 30 ctime=1787067807.793974734 rsyslog-8.2608.0/tests/sndrcv_dtls_certvalid_ciphers.sh0000775000175000017500000000461315216464436022022 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verify that cert-valid DTLS reports a handshake failure when sender and # receiver ciphers do not overlap. The expected TLS diagnostic is the oracle. . ${srcdir:=.}/diag.sh init # start up the instances # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" export NUMMESSAGES=1 generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imdtls/.libs/imdtls" tls.AuthMode="anon") input( type="imdtls" tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_256_GCM_SHA384" port="0" listenPortFileName="'$PORT_RCVR_FILE'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/omdtls/.libs/omdtls" ) action( name="omdtls" type="omdtls" target="127.0.0.1" port="'$PORT_RCVR'" tls.tlscfgcmd="CipherString=ECDHE-RSA-AES128-GCM-SHA256\nCiphersuites=TLS_AES_128_GCM_SHA256" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg 0 $NUMMESSAGES shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # IMPORTANT: this test will generate many error messages. This is exactly it's # intent. So do not think something is wrong. The content_check below checks # these error codes. content_check --check-only "TLS library does not support SSL_CONF_cmd" ret=$? if [ $ret == 0 ]; then echo "SKIP: TLS library does not support SSL_CONF_cmd" skip_test else # Kindly check for a failed session content_check "OpenSSL Error Stack" content_check "no shared cipher" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl-invld-param.sh0000644000000000000000000000013215035412264017367 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.891790591 30 ctime=1787067804.087905674 rsyslog-8.2608.0/tests/glbl-invld-param.sh0000777000175000017500000000070615035412264017043 0ustar00rgerrger#!/bin/bash # make sure we do not abort on invalid parameter (we # once had this problem) # addd 2016-03-03 by RGerhards, released under ASL 2.0 echo \[glbl-invld-param\]: . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(invalid="off") global(debug.unloadModules="invalid") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup sleep 1 shutdown_when_empty wait_shutdown # if we reach this point, we consider this a success. exit_test rsyslog-8.2608.0/tests/PaxHeaders/minitcpsrv_usage_output.sh0000644000000000000000000000013215241075234021242 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.779581552 30 ctime=1787067804.023904482 rsyslog-8.2608.0/tests/minitcpsrv_usage_output.sh0000775000175000017500000000172315241075234020714 0ustar00rgerrger#!/bin/bash # Verify that minitcpsrv's failure usage includes required addressing and the # bounded receive-buffer option used by deterministic backpressure tests. The # oracle is the exact option text in the diagnostic output; no timing is used. # added 2018-11-15 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./minitcpsrv&> $RSYSLOG_DYNNAME.output grep -q -- "-t parameter missing" $RSYSLOG_DYNNAME.output if [ ! $? -eq 0 ]; then echo "invalid response generated" error_exit 1 fi; grep -q -- "-b receiveBufferBytes" $RSYSLOG_DYNNAME.output || error_exit 1 # The receive-buffer value must reject trailing junk instead of accepting the # numeric prefix. A nonzero exit plus the usage diagnostic is the oracle. if ./minitcpsrv -b 4096junk &> $RSYSLOG_DYNNAME.invalid-buffer; then error_exit 1 "minitcpsrv accepted a malformed receive buffer size" fi grep -q -- "-b receiveBufferBytes" $RSYSLOG_DYNNAME.invalid-buffer || error_exit 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_simple_mallformed_ipv4.sh0000644000000000000000000000013215241075234022242 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.739936458 rsyslog-8.2608.0/tests/mmanon_simple_mallformed_ipv4.sh0000775000175000017500000000265015241075234021714 0ustar00rgerrger#!/bin/bash # add 2022-07-28 by Andre Lorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init #export USE_VALGRIND="YES" # this test only makes sense with valgrind enabled #export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes" #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.bits="32" ipv4.mode="simple") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 165874883373.1.15599155266856607338.91@whatever <129>Mar 10 01:00:00 172.20.245.8 tag: 1.165874883373.15599155266856607338.91@whatever <129>Mar 10 01:00:00 172.20.245.8 tag: 15599155266856607338.165874883373.1.91@whatever <129>Mar 10 01:00:00 172.20.245.8 tag: 91.165874883373.1.15599155266856607338.@whatever\"" shutdown_when_empty wait_shutdown export EXPECTED=' 165874883373.1.15599155266856607338.91@whatever 1.165874883373.15599155266856607338.91@whatever 15599155266856607338.165874883373.1.91@whatever 91.165874883373.1.15599155266856607338.@whatever' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/action-tx-errfile-maxsize.sh0000644000000000000000000000013215131231047021244 xustar0030 mtime=1768239655.700212516 30 atime=1782715518.890790574 30 ctime=1787067805.926939943 rsyslog-8.2608.0/tests/action-tx-errfile-maxsize.sh0000777000175000017500000000203715131231047020717 0ustar00rgerrger#!/bin/bash # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50 # enough to generate big file export MAX_ERROR_SIZE=100 generate_conf add_conf ' $ModLoad ../plugins/ommysql/.libs/ommysql global(errormessagestostderr.maxnumber="5") template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on") if((not($msg contains "error")) and ($msg contains "msgnum:")) then { set $.num = field($msg, 58, 2); if $.num % 2 == 0 then { set $!facility = $syslogfacility; } else { set $/cntr = 0; } action(type="ommysql" name="mysql_action_errfile_maxsize" server="127.0.0.1" template="tpl" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" action.errorfile="'$RSYSLOG2_OUT_LOG'" action.errorfile.maxsize="'$MAX_ERROR_SIZE'") } ' mysql_prep_for_test startup injectmsg shutdown_when_empty wait_shutdown mysql_get_data check_file_exists ${RSYSLOG2_OUT_LOG} file_size_check ${RSYSLOG2_OUT_LOG} ${MAX_ERROR_SIZE} exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tcp-user-timeout.sh0000644000000000000000000000012615241075234020603 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 29 ctime=1787067804.15690696 rsyslog-8.2608.0/tests/omfwd-tcp-user-timeout.sh0000775000175000017500000000127515241075234020254 0ustar00rgerrger#!/bin/bash # Verify omfwd accepts tcp_user_timeout and still forwards over TCP. The oracle # is the message received by minitcpsrvr, proving the configured action wrote to # its destination after the socket option path was exercised. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfwd" template="outfmt" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp" tcp_user_timeout="10000") ' start_minitcpsrv_ready "$RSYSLOG_OUT_LOG" "$TCPFLOOD_PORT" startup injectmsg 0 1 shutdown_when_empty wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-error-ca.sh0000644000000000000000000000013115241075234020641 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.776581496 29 ctime=1787067807.48896905 rsyslog-8.2608.0/tests/imtcp-tls-ossl-error-ca.sh0000775000175000017500000000153515241075234020315 0ustar00rgerrger#!/bin/bash # added 2018-11-07 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca-fail.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # note: we do not need to generate any messages, config error occurs on startup startup shutdown_when_empty wait_shutdown content_check "Error: CA certificate '" content_check "could not be accessed" content_check "OpenSSL Error Stack:" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_lt.sh0000644000000000000000000000013215035412264016424 xustar0030 mtime=1752569012.411674314 30 atime=1782715518.890790574 30 ctime=1787067804.823919389 rsyslog-8.2608.0/tests/rscript_lt.sh0000777000175000017500000000131315035412264016073 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_lt.sh\]: testing rainerscript LT statement . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); if $!usr!msgnum < "00005000" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup injectmsg 0 8000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_certless_clientonly.sh0000644000000000000000000000013215216464436022575 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.897790693 30 ctime=1787067807.301965565 rsyslog-8.2608.0/tests/sndrcv_tls_certless_clientonly.sh0000775000175000017500000000364715216464436022256 0ustar00rgerrger#!/bin/bash # all we want to test is if certless communication works. So we do # not need to send many messages. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf # receiver add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" # sender export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global(defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'") # Note: no TLS for the listener, this is for tcpflood! $ModLoad ../plugins/imtcp/.libs/imtcp input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-error.sh0000644000000000000000000000013215241075234021361 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067808.207982449 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-error.sh0000775000175000017500000001543415241075234021037 0ustar00rgerrger#!/bin/bash # Verify that omfwd with the ossl driver reports a deterministic error when an # action-level TLS object is configured via a pkcs11: URI but the referenced # PKCS#11 object does not exist. The test is parameterized by # PKCS11_FAIL_KIND=ca|cert|key, provisions a temporary SoftHSM token with the # other required TLS objects, injects one message to force the outbound connect # path, and then waits for the expected rsyslog-internal startup/error log # message in the testbench .started file. . ${srcdir:=.}/diag.sh init check_command_available openssl check_command_available softhsm2-util check_command_available pkcs11-tool case "${PKCS11_FAIL_KIND:-}" in ca) bad_uri_label="missing-ca" # The CA error now includes the failing pkcs11: URI, so match the stable # prefix here and assert the generic access-failure wording separately. expected_error="Error: CA certificate '" ;; cert) bad_uri_label="missing-cert" expected_error="Error: Certificate file could not be accessed" ;; key) bad_uri_label="missing-key" expected_error="Error: Key could not be accessed" ;; *) printf 'info: skipping helper test %s - PKCS11_FAIL_KIND not set (use ca, cert, or key)\n' "$0" skip_test ;; esac find_first_existing() { for candidate in "$@"; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } workdir="$RSYSLOG_DYNNAME.omfwd-tls-ossl-pkcs11-error" softhsm_conf="$workdir/softhsm2.conf" openssl_conf="$workdir/openssl-pkcs11.cnf" token_dir="$workdir/tokens" token_label="rsyslog-test-token" token_pin="123456" token_so_pin="12345678" started_log="$RSYSLOG_DYNNAME.started" mkdir -p "$workdir" "$token_dir" provider_module=$(find_first_existing \ /usr/lib64/ossl-modules/pkcs11.so \ /usr/lib/ossl-modules/pkcs11.so \ /usr/lib/x86_64-linux-gnu/ossl-modules/pkcs11.so \ /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so \ /usr/local/lib64/ossl-modules/pkcs11.so \ /usr/local/lib/ossl-modules/pkcs11.so) || { printf 'info: skipping test - pkcs11 OpenSSL provider module not found\n' skip_test } softhsm_module=$(find_first_existing \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/pkcs11/libsofthsm2.so \ /usr/lib64/softhsm/libsofthsm2.so \ /usr/lib/softhsm/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib64/libsofthsm2.so \ /usr/lib/libsofthsm2.so) || { printf 'info: skipping test - SoftHSM PKCS#11 module not found\n' skip_test } cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 2048 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 2048 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 openssl x509 -in "$workdir/ca.pem" -outform DER -out "$workdir/ca.der" || error_exit 1 openssl x509 -in "$workdir/client.pem" -outform DER -out "$workdir/client.der" || error_exit 1 openssl pkey -in "$workdir/client.key" -pubout -outform DER -out "$workdir/client.pub.der" || \ error_exit 1 cat >"$softhsm_conf" <"$openssl_conf" <1 2003-03-01T01:00:00.000Z host app - - - omfwd-ossl-pkcs11-error' wait_content "$expected_error" "$started_log" shutdown_immediate wait_shutdown content_check "$expected_error" "$started_log" if [ "$PKCS11_FAIL_KIND" = "ca" ]; then content_check "could not be accessed" "$started_log" fi content_check "OpenSSL Error Stack:" "$started_log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_parse_time_get-ts.py0000644000000000000000000000013215216464436021447 xustar0030 mtime=1782212894.081267073 30 atime=1782715518.897790693 30 ctime=1787067808.216982616 rsyslog-8.2608.0/tests/rscript_parse_time_get-ts.py0000664000175000017500000001273215216464436021120 0ustar00rgerrger# call this via "python[3] script name" # Added 2017-11-05 by Stephen Workman, released under ASL 2.0 # # Produces a UNIX timestamp representing the specified RFC 3164 date/time # string. Since this date/time format does not include a year, a simple # algorithm is used to "guess" an appropriate one and append it to the # date/time string to calculate a timestamp value. # # If the incoming date is within one month in the future (from now), # it is assumed that it's either for the current year, or the next # year (depending on whether it is December or not). # - For example: # * If today is December 13th 2017 and we get passed the date/time # string "Jan 4 01:00:00", we assume that it is for the next # year (2018). # * If today is October 5th 2017, and we get passed the date/time # string "Nov 5 01:10:11", we assume that it is for this year. # If the incoming date has a month "before" the current month, or does # not fall into the situation above, it's assumed it's from the past. # - For example: # * If today is July 10th 2017, and the incoming date is for # a time in April, the year is assumed to be 2017. # * If today is July 10th 2017, and the incoming date is for # a time in September, the year is assumed to be 2016. # import re import sys from datetime import datetime, timedelta err = 0 # Make tests below a little easier to read. JAN = 1 FEB = 2 MAR = 3 APR = 4 MAY = 5 JUN = 6 JUL = 7 AUG = 8 SEP = 9 OCT = 10 NOV = 11 DEC = 12 # Run the provided expression and compare its result with the # expected value. The function expects the expression to be # passed in as a string so it can be printed to the screen # as-is when there is an error. def do_test(expr, val): global err # Run the expression and record the result result = eval(expr) # Print a message identifying the failing "test" if result != val: print("Error: %s. Expected %4d, got %4d!" % (expr, val, result)) err += 1 # Use a sliding 12-month window (offset by one month) # to determine the year that should be returned. # cy - Current Year # cm - Current Month # im - Incoming Month def estimate_year(cy, cm, im): im += 12 if (im - cm) == 1: if cm == 12 and im == 13: return cy + 1 if (im - cm) > 13: return cy - 1 return cy # A quick and dirty unit test to validate that our # estimate_year() function is working as it should. def self_test(): # Where the incoming month is within one month # in the future. Should be the NEXT year if # the current date is in December, or the SAME # year if it's not December. do_test("estimate_year(2017, DEC, JAN)", 2018) do_test("estimate_year(2017, NOV, DEC)", 2017) do_test("estimate_year(2017, OCT, NOV)", 2017) do_test("estimate_year(2017, SEP, OCT)", 2017) do_test("estimate_year(2017, AUG, SEP)", 2017) # These tests validate months that are MORE than # one month in the future OR are before the current # month. If, numerically, the month comes after the # current month, it's assumed to be for the year # PRIOR, otherwise it's assumed to be from THIS year. do_test("estimate_year(2017, NOV, JAN)", 2017) do_test("estimate_year(2017, NOV, FEB)", 2017) do_test("estimate_year(2017, AUG, OCT)", 2016) do_test("estimate_year(2017, AUG, MAR)", 2017) do_test("estimate_year(2017, APR, JUL)", 2016) do_test("estimate_year(2017, AUG, JAN)", 2017) do_test("estimate_year(2017, APR, FEB)", 2017) # Additional validations based on what was described # above. do_test("estimate_year(2017, JAN, DEC)", 2016) do_test("estimate_year(2017, JAN, FEB)", 2017) do_test("estimate_year(2017, JAN, MAR)", 2016) # Convert a datetime.timedelta object to a UNIX timestamp def get_total_seconds(dt): # timedelta.total_seconds() wasn't added until # Python 2.7, which CentOS 6 doesn't have. if hasattr(timedelta, "total_seconds"): return dt.total_seconds() return dt.seconds + dt.days * 24 * 3600 if __name__ == "__main__": if len(sys.argv) != 2: print("Invalid number of arguments!") sys.exit(1) if sys.argv[1] == "selftest": self_test() # Exit with non-zero if there were failures, # zero otherwise. sys.exit(err) months = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] current_datetime = datetime.utcnow() # The argument is expected to be an RFC 3164 timestamp # such as "Oct 5 01:10:11". incoming_datetime = sys.argv[1] # Get the name of the month from the date/time string that was passed in # and convert it to its ordinal number (1 for Jan, 10 for Oct, etc...) incoming_month = re.search(r"^([^ ]+) ", incoming_datetime).group(1) incoming_month = months.index(incoming_month) # Assume a year for the date/time passed in based off of today's date. estimated_year = estimate_year( current_datetime.year, current_datetime.month, incoming_month ) # Convert the date/time string (now with a year, e.g. "Oct 5 01:10:11 2017") to # a python datetime object that we can use to calculate a UNIX timestamp calculated_datetime = datetime.strptime("%s %d" % (incoming_datetime, estimated_year), "%b %d %H:%M:%S %Y") # Convert the datetime object to a UNIX timestamp by subtracting it from the epoch print(int(get_total_seconds(calculated_datetime - datetime(1970, 1, 1)))) rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_certless_clientonly_mbedtls.sh0000644000000000000000000000013215216464436024307 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.896790676 30 ctime=1787067807.408967559 rsyslog-8.2608.0/tests/sndrcv_tls_certless_clientonly_mbedtls.sh0000775000175000017500000000370215216464436023760 0ustar00rgerrger#!/bin/bash # Forward test with an Mbed TLS tls client. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf # receiver add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="mbedtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" # sender (mbedtls tls client) #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global(defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'") # Note: no TLS for the listener, this is for tcpflood! $ModLoad ../plugins/imtcp/.libs/imtcp input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 #echo attach gdb here #sleep 54321 || : # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-wrong-insert-syntax.sh0000644000000000000000000000013215131231047022343 xustar0030 mtime=1768239655.700212516 30 atime=1782715518.897790693 30 ctime=1787067805.809937763 rsyslog-8.2608.0/tests/clickhouse-wrong-insert-syntax.sh0000777000175000017500000000233115131231047022013 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init echo looks like clickhouse does no longer generate exceptions on error - skip until investigated exit 77 export NUMMESSAGES=1 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.wrongInsertSyntax (id, severity, facility, timestamp, ipaddress, tag, message) VLUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, ' add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" user="default" pwd="" template="outfmt" bulkmode="off" errorfile="'$RSYSLOG_OUT_LOG'") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.wrongInsertSyntax ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="DROP TABLE rsyslog.wrongInsertSyntax" content_check "DB::Exception: Syntax error" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_parsesuccess.sh0000644000000000000000000000013115035412264021353 xustar0030 mtime=1752569012.401743799 30 atime=1782715518.896790676 29 ctime=1787067807.10096182 rsyslog-8.2608.0/tests/mmnormalize_parsesuccess.sh0000777000175000017500000000151015035412264021022 0ustar00rgerrger#!/bin/bash # added 2019-04-11 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmnormalize/.libs/mmnormalize") action(type="mmnormalize" rule= ["rule=: %-:char-to{\"extradata\":\":\"}%:00000000:", "rule=: %-:char-to{\"extradata\":\":\"}%:00000010:"] ) if not ($rawmsg contains "rsyslog") then if $parsesuccess == "OK" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'") else action(type="omfile" file="'$RSYSLOG_DYNNAME'.failed") ' startup injectmsg 0 20 shutdown_when_empty wait_shutdown content_check "msgnum:00000000:" $RSYSLOG_OUT_LOG content_check "msgnum:00000010:" $RSYSLOG_OUT_LOG content_check "msgnum:00000001:" $RSYSLOG_DYNNAME.failed content_check "msgnum:00000012:" $RSYSLOG_DYNNAME.failed exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_tokenized.sh0000644000000000000000000000013215035412264020645 xustar0030 mtime=1752569012.401743799 30 atime=1782715518.896790676 30 ctime=1787067807.125962286 rsyslog-8.2608.0/tests/mmnormalize_tokenized.sh0000777000175000017500000000366615035412264020331 0ustar00rgerrger#!/bin/bash # added 2014-11-03 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[mmnormalize_tokenized.sh\]: test for mmnormalize tokenized field_type . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="ips" type="string" string="%$.ips%\n") template(name="paths" type="string" string="%$!fragments% %$!user%\n") template(name="numbers" type="string" string="nos: %$!some_nos%\n") module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmnormalize" rulebase=`echo $srcdir/testsuites/mmnormalize_tokenized.rulebase`) if ( $!only_ips != "" ) then { set $.ips = $!only_ips; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips") } else if ( $!local_ips != "" ) then { set $.ips = $!local_ips; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips") } else if ( $!external_ips != "" ) then { set $.ips = $!external_ips; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="ips") } else if ( $!some_nos != "" ) then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="numbers") } else { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="paths") } ' startup tcpflood -m 1 -I $srcdir/testsuites/tokenized_input echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown cp $RSYSLOG_OUT_LOG /tmp/ content_check '[ "10.20.30.40", "50.60.70.80", "90.100.110.120", "130.140.150.160" ]' content_check '[ "192.168.1.2", "192.168.1.3", "192.168.1.4" ]' content_check '[ "10.20.30.40", "50.60.70.80", "190.200.210.220" ]' content_check '[ "\/bin", "\/usr\/local\/bin", "\/usr\/bin" ] foo' content_check '[ [ [ "10" ] ], [ [ "20" ], [ "30", "40", "50" ], [ "60", "70", "80" ] ], [ [ "90" ], [ "100" ] ] ]' exit_test rsyslog-8.2608.0/tests/PaxHeaders/dynstats-json.sh0000644000000000000000000000013215131231047017052 xustar0030 mtime=1768239655.701212533 30 atime=1782715518.896790676 30 ctime=1787067806.707954497 rsyslog-8.2608.0/tests/dynstats-json.sh0000777000175000017500000000356715131231047016536 0ustar00rgerrger#!/bin/bash # added 2016-03-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[dynstats-json.sh\]: test for verifying stats are reported correctly in json format . ${srcdir:=.}/diag.sh init generate_conf add_conf ' dyn_stats(name="stats_one") dyn_stats(name="stats_two") ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="2" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json") template(name="outfmt" type="string" string="%msg%\n") set $.p = field($msg, 32, 1); if ($.p == "foo") then { set $.ign = dyn_inc("stats_one", $.p); set $.ign = dyn_inc("stats_two", $.p); } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log injectmsg_file $srcdir/testsuites/dynstats_input_1 wait_queueempty wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown custom_content_check '{ "name": "global", "origin": "dynstats", "values": { "stats_one.ops_overflow": 0, "stats_one.new_metric_add": 1, "stats_one.no_metric": 0, "stats_one.metrics_purged": 0, "stats_one.ops_ignored": 0, "stats_one.purge_triggered": 0, "stats_two.ops_overflow": 0, "stats_two.new_metric_add": 1, "stats_two.no_metric": 0, "stats_two.metrics_purged": 0, "stats_two.ops_ignored": 0, "stats_two.purge_triggered": 0 } }' "${RSYSLOG_DYNNAME}.out.stats.log" custom_content_check '{ "name": "stats_one", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log" custom_content_check '{ "name": "stats_two", "origin": "dynstats.bucket", "values": { "foo": 1 } }' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-tls-chainedcert.sh0000644000000000000000000000013215241075234020577 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.770581384 30 ctime=1787067807.746973858 rsyslog-8.2608.0/tests/imrelp-tls-chainedcert.sh0000775000175000017500000000235315241075234020251 0ustar00rgerrger#!/bin/bash # addd 2020-08-25 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_relpEngineVersion "1.7.0" export NUMMESSAGES=1000 # uncomment for debugging support: # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # export RSYSLOG_DEBUGLOG="log" # export TCPFLOOD_EXTRA_OPTS="-v" do_skip=0 generate_conf add_conf ' # uncomment for debugging support: # $DebugFile debug.log # $DebugLevel 2 module( load="../plugins/imrelp/.libs/imrelp" tls.tlslib="openssl" ) input(type="imrelp" port="'$TCPFLOOD_PORT'" tls="on" tls.mycert="'$srcdir'/tls-certs/certchained.pem" tls.myprivkey="'$srcdir'/tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -u openssl -Trelp-tls -acertvalid -p"$TCPFLOOD_PORT" -m"$NUMMESSAGES" -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/certchained.pem" -Ersyslog 2> "$RSYSLOG_DYNNAME.tcpflood" cat -n $RSYSLOG_DYNNAME.tcpflood shutdown_when_empty wait_shutdown # uncomment for debugging support: # cat debug.log if [ $do_skip -eq 1 ]; then skip_test fi seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-mmnormalize-turbo.sh0000644000000000000000000000013215241075234020663 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067807.111962025 rsyslog-8.2608.0/tests/yaml-mmnormalize-turbo.sh0000775000175000017500000000257015241075234020336 0ustar00rgerrger#!/bin/bash # Verify that the YAML front end passes turbo to mmnormalize and exposes the # normalized CEE field. The output file is the observable success oracle. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin mmnormalize generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"' add_yaml_conf ' - load: "../plugins/mmnormalize/.libs/mmnormalize"' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imtcp' add_yaml_conf ' port: "0"' add_yaml_conf ' listenPortFileName: "'$RSYSLOG_DYNNAME'.tcpflood_port"' add_yaml_conf ' ruleset: normalize' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf ' string: "%$!host% %$!tag%\n"' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: normalize' add_yaml_conf ' statements:' add_yaml_conf ' - type: mmnormalize' add_yaml_conf ' useRawMsg: on' add_yaml_conf ' turbo: on' add_yaml_conf ' rule: "rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%"' add_yaml_conf ' - type: omfile' add_yaml_conf ' file: "'$RSYSLOG_OUT_LOG'"' add_yaml_conf ' template: outfmt' startup tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\"" shutdown_when_empty wait_shutdown export EXPECTED='ubuntu tag1' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_trim-vg.sh0000644000000000000000000000013115241075234017372 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.793581814 30 ctime=1787067805.309928445 rsyslog-8.2608.0/tests/rscript_trim-vg.sh0000775000175000017500000000571315241075234017050 0ustar00rgerrger#!/bin/bash # add 2017-08-14 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!str!l1 = ltrim(""); set $!str!l2 = ltrim("test"); set $!str!l3 = ltrim(" test"); set $!str!l4 = ltrim("test "); set $!str!l5 = ltrim(" test "); set $!str!l6 = ltrim(" test"); set $!str!l7 = ltrim("test "); set $!str!l8 = ltrim(" "); set $!str!l9 = ltrim("te st"); set $!str!l10 = ltrim(" te st"); set $!str!l11 = ltrim(" a"); set $!str!l12 = ltrim("a "); set $!str!r1 = rtrim(""); set $!str!r2 = rtrim("test"); set $!str!r3 = rtrim(" test"); set $!str!r4 = rtrim("test "); set $!str!r5 = rtrim(" test "); set $!str!r6 = rtrim(" test"); set $!str!r7 = rtrim("test "); set $!str!r8 = rtrim(" "); set $!str!r9 = rtrim("te st"); set $!str!r10 = rtrim("te st "); set $!str!r11 = rtrim(" a"); set $!str!r12 = rtrim("a "); set $!str!b1 = ltrim(" "); set $!str!b1 = rtrim($!str!b1); set $!str!b2 = ltrim(" test "); set $!str!b2 = rtrim($!str!b2); set $!str!b3 = ltrim(" test "); set $!str!b3 = rtrim($!str!b3); set $!str!b4 = ltrim("te st"); set $!str!b4 = rtrim($!str!b4); set $!str!b5 = rtrim(" "); set $!str!b5 = ltrim($!str!b5); set $!str!b6 = rtrim(" test "); set $!str!b6 = ltrim($!str!b6); set $!str!b7 = rtrim(" test "); set $!str!b7 = ltrim($!str!b7); set $!str!b8 = rtrim("te st"); set $!str!b8 = ltrim($!str!b8); set $!str!b9 = rtrim(ltrim("test")); set $!str!b10 = rtrim(ltrim("te st")); set $!str!b11 = rtrim(ltrim(" test")); set $!str!b12 = rtrim(ltrim("test ")); set $!str!b13 = rtrim(ltrim(" test ")); set $!str!b14 = rtrim(ltrim(" te st ")); set $!str!b15 = ltrim(rtrim("test")); set $!str!b16 = ltrim(rtrim("te st")); set $!str!b17 = ltrim(rtrim(" test")); set $!str!b18 = ltrim(rtrim("test ")); set $!str!b19 = ltrim(rtrim(" test ")); set $!str!b20 = ltrim(rtrim(" te st ")); template(name="outfmt" type="string" string="%!str%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg tcpflood -m1 -y shutdown_when_empty wait_shutdown_vg check_exit_vg echo '{ "l1": "", "l2": "test", "l3": "test", "l4": "test ", "l5": "test ", "l6": "test", "l7": "test ", "l8": "", "l9": "te st", "l10": "te st", "l11": "a", "l12": "a ", "r1": "", "r2": "test", "r3": " test", "r4": "test", "r5": " test", "r6": " test", "r7": "test", "r8": "", "r9": "te st", "r10": "te st", "r11": " a", "r12": "a", "b1": "", "b2": "test", "b3": "test", "b4": "te st", "b5": "", "b6": "test", "b7": "test", "b8": "te st", "b9": "test", "b10": "te st", "b11": "test", "b12": "test", "b13": "test", "b14": "te st", "b15": "test", "b16": "te st", "b17": "test", "b18": "test", "b19": "test", "b20": "te st" }' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid function output detected, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/config_output-o-option.sh0000644000000000000000000000013215035412264020666 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.895790659 30 ctime=1787067804.918921159 rsyslog-8.2608.0/tests/config_output-o-option.sh0000777000175000017500000000127415035412264020343 0ustar00rgerrger#!/bin/bash # check that the -o command line option works # added 2019-04-26 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { include(file="'${srcdir}'/testsuites/include-std-omfile-actio*.conf") continue } ' ../tools/rsyslogd -N1 -f${TESTCONF_NM}.conf -o$RSYSLOG_DYNNAME.fullconf -M../runtime/.libs:../.libs content_check 'if $msg contains "msgnum:" then' $RSYSLOG_DYNNAME.fullconf content_check 'action(type="omfile"' $RSYSLOG_DYNNAME.fullconf content_check --regex "BEGIN CONFIG: .*include-std-omfile-action.conf" $RSYSLOG_DYNNAME.fullconf exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata.sh0000644000000000000000000000013115241075234016743 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067807.013960199 rsyslog-8.2608.0/tests/mmpstrucdata.sh0000775000175000017500000000131615241075234016414 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # rgerhards, 2013-11-22 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") module(load="../plugins/imtcp/.libs/imtcp") template(name="outfmt" type="string" string="%$!rfc5424-sd!tcpflood@32473!msgnum%\n") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmpstrucdata") if $msg contains "msgnum" then action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m100 -y shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omjournal-abort-template.sh0000644000000000000000000000013215035412264021163 xustar0030 mtime=1752569012.404722953 30 atime=1782715518.894790642 30 ctime=1787067805.996941247 rsyslog-8.2608.0/tests/omjournal-abort-template.sh0000777000175000017500000000120315035412264020630 0ustar00rgerrger#!/bin/bash # a very basic test for omjournal. Right now, we have no # reliable way of verifying that data was actually written # to the journal, but at least we check that rsyslog does # not abort when trying to use omjournal. Not high tech, # but better than nothing. # addd 2016-03-16 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omjournal/.libs/omjournal") template(name="outfmt" type="string" string="%msg%") action(type="omjournal" template="outfmt") ' startup ./msleep 500 shutdown_when_empty wait_shutdown # if we reach this, we have at least not aborted exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-error-key-vg.sh0000644000000000000000000000013215241075234022561 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.556970317 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-error-key-vg.sh0000775000175000017500000000013015241075234022222 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-error-key.sh rsyslog-8.2608.0/tests/PaxHeaders/imrelp-basic.sh0000644000000000000000000000013215216464436016617 xustar0030 mtime=1782212894.065266814 30 atime=1782715518.894790642 30 ctime=1787067807.678972591 rsyslog-8.2608.0/tests/imrelp-basic.sh0000775000175000017500000000162415216464436016271 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 # # Verify basic plain RELP input delivery from tcpflood through imrelp. The # receiver binds an ephemeral TCP port and the testbench discovers the actual # listener from the running rsyslog process, avoiding get_free_port races with # parallel tests. Success is the exact sequence check for all injected messages. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 # MUST be an even number! generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" address="127.0.0.1" port="0") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup assign_single_tcp_listener_port TCPFLOOD_PORT tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata-rfc3164-skip.sh0000644000000000000000000000013215216464436021006 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.894790642 30 ctime=1787067807.028960478 rsyslog-8.2608.0/tests/mmpstrucdata-rfc3164-skip.sh0000775000175000017500000000154315216464436020460 0ustar00rgerrger#!/bin/bash # Verify mmpstrucdata still ignores legacy messages without RFC5424 structured # data. The oracle is absence of configured omfile output after shutdown; if the # module created the no-SD JSON null for RFC3164 input, the output file would be # created. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") template(name="outfmt" type="string" string="%$!structured-data%\n") action(type="mmpstrucdata" jsonRoot="$!structured-data" container="custom-sd") if $!structured-data != "" then action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal '<85>May 22 08:00:00 host app: MMPSTRUCDATA legacy without sd' shutdown_when_empty wait_shutdown check_file_not_exists "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/now-utc-ymd.sh0000644000000000000000000000013215241075234016423 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 30 ctime=1787067805.830938154 rsyslog-8.2608.0/tests/now-utc-ymd.sh0000775000175000017500000000163215241075234016074 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # addd 2016-02-23 by RGerhards, released under ASL 2.0 # requires faketime . ${srcdir:=.}/diag.sh init echo \[now-utc-ymd\]: test \$year-utc, \$month-utc, \$day-utc . $srcdir/faketime_common.sh export TZ=TEST-02:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$year%-%$month%-%$day%,%$year-utc%-%$month-utc%-%$day-utc%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' FAKETIME='2016-01-01 01:00:00' startup # what we send actually is irrelevant, as we just use system properties. # but we need to send one message in order to gain output! tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="2016-01-01,2015-12-31" exit_test rsyslog-8.2608.0/tests/PaxHeaders/compat-configformat-yaml.sh0000644000000000000000000000013215241075234021137 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.762581234 30 ctime=1787067805.340929023 rsyslog-8.2608.0/tests/compat-configformat-yaml.sh0000775000175000017500000002366515241075234020622 0ustar00rgerrger#!/bin/bash # Validate compatibility.* global options from YAML configs. . ${srcdir:=.}/diag.sh init modpath="${RSYSLOG_MODDIR}" run_expect_success() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -ne 0 ]; then echo "FAIL: expected ${cfg} to validate" cat "${log}" error_exit 1 fi } run_expect_failure() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -eq 0 ]; then echo "FAIL: expected ${cfg} to fail validation" cat "${log}" error_exit 1 fi } write_yaml_action_config() { local cfg="$1" local extra_global="$2" cat >"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${cfg}" <"${RSYSLOG_DYNNAME}.strict-dirty.log" 2>&1 rc=$? if [ $rc -ne 2 ]; then echo "FAIL: expected secure strict mode to abort unclean config with rc 2" cat "${RSYSLOG_DYNNAME}.strict-dirty.log" error_exit 1 fi content_check 'global(AbortOnUncleanConfig="on") is set' "${RSYSLOG_DYNNAME}.strict-dirty.log" for mode in enable warn disable; do write_yaml_global_only "${RSYSLOG_DYNNAME}.legacy-${mode}.yaml" "${mode}" write_legacy_wrapper "${RSYSLOG_DYNNAME}.legacy-${mode}.conf" "${RSYSLOG_DYNNAME}.legacy-${mode}.yaml" done run_expect_success "${RSYSLOG_DYNNAME}.legacy-enable.conf" "${RSYSLOG_DYNNAME}.legacy-enable.log" run_expect_success "${RSYSLOG_DYNNAME}.legacy-warn.conf" "${RSYSLOG_DYNNAME}.legacy-warn.log" content_check 'obsolete $-directive syntax encountered' "${RSYSLOG_DYNNAME}.legacy-warn.log" run_expect_failure "${RSYSLOG_DYNNAME}.legacy-disable.conf" "${RSYSLOG_DYNNAME}.legacy-disable.log" content_check 'global(compatibility.configformat.legacy="enable")' "${RSYSLOG_DYNNAME}.legacy-disable.log" for mode in enable warn disable; do write_yaml_syslogd_config "${RSYSLOG_DYNNAME}.syslogd-${mode}.yaml" "${mode}" done run_expect_success "${RSYSLOG_DYNNAME}.syslogd-enable.yaml" "${RSYSLOG_DYNNAME}.syslogd-enable.log" run_expect_success "${RSYSLOG_DYNNAME}.syslogd-warn.yaml" "${RSYSLOG_DYNNAME}.syslogd-warn.log" content_check 'obsolete classic syslogd filter syntax encountered' "${RSYSLOG_DYNNAME}.syslogd-warn.log" run_expect_failure "${RSYSLOG_DYNNAME}.syslogd-disable.yaml" "${RSYSLOG_DYNNAME}.syslogd-disable.log" content_check 'global(compatibility.configformat.syslogd="enable")' "${RSYSLOG_DYNNAME}.syslogd-disable.log" for mode in enable warn disable; do write_yaml_property_config "${RSYSLOG_DYNNAME}.property-${mode}.yaml" "${mode}" done run_expect_success "${RSYSLOG_DYNNAME}.property-enable.yaml" "${RSYSLOG_DYNNAME}.property-enable.log" run_expect_success "${RSYSLOG_DYNNAME}.property-warn.yaml" "${RSYSLOG_DYNNAME}.property-warn.log" content_check 'obsolete classic property-based filter syntax encountered' "${RSYSLOG_DYNNAME}.property-warn.log" run_expect_failure "${RSYSLOG_DYNNAME}.property-disable.yaml" "${RSYSLOG_DYNNAME}.property-disable.log" content_check 'global(compatibility.configformat.property="enable")' "${RSYSLOG_DYNNAME}.property-disable.log" write_yaml_tls_warn_config "${RSYSLOG_DYNNAME}.tls-warn.yaml" run_expect_success "${RSYSLOG_DYNNAME}.tls-warn.yaml" "${RSYSLOG_DYNNAME}.tls-warn.log" content_check 'imtcp has TLS-related settings but streamdriver.mode="0"; mode 0 uses plain TCP so TLS is not active' "${RSYSLOG_DYNNAME}.tls-warn.log" content_check 'omfwd action uses protocol="udp" (without TLS)' "${RSYSLOG_DYNNAME}.tls-warn.log" write_yaml_omfwd_global_tls_warn_config "${RSYSLOG_DYNNAME}.omfwd-global-driver-warn.yaml" run_expect_success "${RSYSLOG_DYNNAME}.omfwd-global-driver-warn.yaml" \ "${RSYSLOG_DYNNAME}.omfwd-global-driver-warn.log" content_check 'omfwd has TLS-related settings but streamdriver.mode="0"; mode 0 uses plain TCP so TLS is not active' \ "${RSYSLOG_DYNNAME}.omfwd-global-driver-warn.log" write_yaml_omfwd_strict_explicit_mode0_config "${RSYSLOG_DYNNAME}.omfwd-strict-explicit-mode0.yaml" run_expect_failure "${RSYSLOG_DYNNAME}.omfwd-strict-explicit-mode0.yaml" \ "${RSYSLOG_DYNNAME}.omfwd-strict-explicit-mode0.log" content_check 'omfwd: compatibility.defaults.secure="strict" rejects explicit streamdriver.mode="0"' \ "${RSYSLOG_DYNNAME}.omfwd-strict-explicit-mode0.log" write_yaml_tls_anon_warn_config "${RSYSLOG_DYNNAME}.tls-anon-warn.yaml" run_expect_success "${RSYSLOG_DYNNAME}.tls-anon-warn.yaml" "${RSYSLOG_DYNNAME}.tls-anon-warn.log" content_check 'imtcp uses streamdriver.authmode="anon"; server identity is not authenticated, so MITM is possible' "${RSYSLOG_DYNNAME}.tls-anon-warn.log" content_check 'omfwd uses streamdriver.authmode="anon"; server identity is not authenticated, so MITM is possible' "${RSYSLOG_DYNNAME}.tls-anon-warn.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_trim.sh0000644000000000000000000000013115241075234016760 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.793581814 30 ctime=1787067804.865920172 rsyslog-8.2608.0/tests/rscript_trim.sh0000775000175000017500000000566715241075234016446 0ustar00rgerrger#!/bin/bash # add 2017-08-14 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!str!l1 = ltrim(""); set $!str!l2 = ltrim("test"); set $!str!l3 = ltrim(" test"); set $!str!l4 = ltrim("test "); set $!str!l5 = ltrim(" test "); set $!str!l6 = ltrim(" test"); set $!str!l7 = ltrim("test "); set $!str!l8 = ltrim(" "); set $!str!l9 = ltrim("te st"); set $!str!l10 = ltrim(" te st"); set $!str!l11 = ltrim(" a"); set $!str!l12 = ltrim("a "); set $!str!r1 = rtrim(""); set $!str!r2 = rtrim("test"); set $!str!r3 = rtrim(" test"); set $!str!r4 = rtrim("test "); set $!str!r5 = rtrim(" test "); set $!str!r6 = rtrim(" test"); set $!str!r7 = rtrim("test "); set $!str!r8 = rtrim(" "); set $!str!r9 = rtrim("te st"); set $!str!r10 = rtrim("te st "); set $!str!r11 = rtrim(" a"); set $!str!r12 = rtrim("a "); set $!str!b1 = ltrim(" "); set $!str!b1 = rtrim($!str!b1); set $!str!b2 = ltrim(" test "); set $!str!b2 = rtrim($!str!b2); set $!str!b3 = ltrim(" test "); set $!str!b3 = rtrim($!str!b3); set $!str!b4 = ltrim("te st"); set $!str!b4 = rtrim($!str!b4); set $!str!b5 = rtrim(" "); set $!str!b5 = ltrim($!str!b5); set $!str!b6 = rtrim(" test "); set $!str!b6 = ltrim($!str!b6); set $!str!b7 = rtrim(" test "); set $!str!b7 = ltrim($!str!b7); set $!str!b8 = rtrim("te st"); set $!str!b8 = ltrim($!str!b8); set $!str!b9 = rtrim(ltrim("test")); set $!str!b10 = rtrim(ltrim("te st")); set $!str!b11 = rtrim(ltrim(" test")); set $!str!b12 = rtrim(ltrim("test ")); set $!str!b13 = rtrim(ltrim(" test ")); set $!str!b14 = rtrim(ltrim(" te st ")); set $!str!b15 = ltrim(rtrim("test")); set $!str!b16 = ltrim(rtrim("te st")); set $!str!b17 = ltrim(rtrim(" test")); set $!str!b18 = ltrim(rtrim("test ")); set $!str!b19 = ltrim(rtrim(" test ")); set $!str!b20 = ltrim(rtrim(" te st ")); template(name="outfmt" type="string" string="%!str%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown echo '{ "l1": "", "l2": "test", "l3": "test", "l4": "test ", "l5": "test ", "l6": "test", "l7": "test ", "l8": "", "l9": "te st", "l10": "te st", "l11": "a", "l12": "a ", "r1": "", "r2": "test", "r3": " test", "r4": "test", "r5": " test", "r6": " test", "r7": "test", "r8": "", "r9": "te st", "r10": "te st", "r11": " a", "r12": "a", "b1": "", "b2": "test", "b3": "test", "b4": "te st", "b5": "", "b6": "test", "b7": "test", "b8": "te st", "b9": "test", "b10": "te st", "b11": "test", "b12": "test", "b13": "test", "b14": "te st", "b15": "test", "b16": "te st", "b17": "test", "b18": "test", "b19": "test", "b20": "te st" }' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid function output detected, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-redis-restart.sh0000644000000000000000000000013215131231047020775 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.893790625 30 ctime=1787067806.543951441 rsyslog-8.2608.0/tests/imhiredis-redis-restart.sh0000777000175000017500000000275615131231047020460 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init # Start redis once to be able to generate configuration start_redis redis_command "RPUSH mykey message1" redis_command "RPUSH mykey message2" redis_command "RPUSH mykey message3" generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mykey" mode="queue" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup wait_content '3 message1' # Stop Redis and wait a short moment for imhiredis to notice Redis went down stop_redis rst_msleep 1500 start_redis redis_command "RPUSH mykey message4" redis_command "RPUSH mykey message5" redis_command "RPUSH mykey message6" wait_content '4 message6' shutdown_when_empty wait_shutdown stop_redis content_check '1 message3' content_check '2 message2' content_check '3 message1' content_check 'sleeping 10 seconds before retrying' content_check '4 message6' content_check '5 message5' content_check '6 message4' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-close-unresponsive.sh0000644000000000000000000000013115035412264021402 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.893790625 29 ctime=1787067806.05394231 rsyslog-8.2608.0/tests/omprog-close-unresponsive.sh0000777000175000017500000000310415035412264021052 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test checks that omprog sends a TERM signal to the external # program when signalOnClose=on, closes the pipe, and kills the # child if unresponsive. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") main_queue( queue.timeoutShutdown="60000" # give time to omprog to wait for the child ) :msg, contains, "msgnum:" { action( type="omprog" binary="'$RSYSLOG_DYNNAME.'omprog-close-unresponsive-bin.sh" template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process confirmMessages="on" # facilitates sync with the child process signalOnClose="on" closeTimeout="1000" # ms #killUnresponsive="on" # default value: the value of signalOnClose ) } ' cp -f $srcdir/testsuites/omprog-close-unresponsive-bin.sh $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh startup injectmsg 0 10 shutdown_when_empty wait_shutdown . $srcdir/diag.sh ensure-no-process-exists $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh export EXPECTED="Starting Received msgnum:00000000: Received msgnum:00000001: Received msgnum:00000002: Received msgnum:00000003: Received msgnum:00000004: Received msgnum:00000005: Received msgnum:00000006: Received msgnum:00000007: Received msgnum:00000008: Received msgnum:00000009: Received SIGTERM Terminating unresponsively" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-jsonarray-compress-vg.sh0000644000000000000000000000013115171370365023107 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.894790642 30 ctime=1787067806.178944639 rsyslog-8.2608.0/tests/omhttp-batch-jsonarray-compress-vg.sh0000775000175000017500000000013015171370365022551 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-batch-jsonarray-compress.sh rsyslog-8.2608.0/tests/PaxHeaders/localvar-concurrency.sh0000644000000000000000000000013215241075234020373 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067804.214908041 rsyslog-8.2608.0/tests/localvar-concurrency.sh0000775000175000017500000000230115241075234020036 0ustar00rgerrger#!/bin/bash # Test concurrency of message variables # Added 2015-11-03 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[localvar-concurrency.sh\]: testing concurrency of local variables uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$.tree!here!nbr%\n") if $msg contains "msgnum:" then { set $.tree!here!nbr = field($msg, 58, 2); action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList") set $.tree!here!save = $.tree!here!nbr; set $.tree!here!nbr = ""; set $.tree!here!nbr = $.tree!here!save; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup sleep 1 tcpflood -m500000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 499999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-multiplehttpheaders.sh0000644000000000000000000000013215131231047021632 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.893790625 30 ctime=1787067806.163944359 rsyslog-8.2608.0/tests/omhttp-multiplehttpheaders.sh0000777000175000017500000000152415131231047021305 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 omhttp_start_server 0 generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../contrib/omhttp/.libs/omhttp") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" httpheaders=[ "X-Insert-Key: dummy-value", "X-Event-Source: logs" ] server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="off" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/NoExistFile.cfgtest0000644000000000000000000000013215035412264017455 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.893790625 30 ctime=1787067808.414986306 rsyslog-8.2608.0/tests/NoExistFile.cfgtest0000666000175000017500000000030415035412264017120 0ustar00rgerrgerrsyslogd: CONFIG ERROR: could not interpret master config file '/This/does/not/exist'. [try https://www.rsyslog.com/e/2013 ] rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file! rsyslog-8.2608.0/tests/PaxHeaders/imbeats-seq-reset-rejected.sh0000644000000000000000000000013215241075234021355 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.769581365 30 ctime=1787067806.450949707 rsyslog-8.2608.0/tests/imbeats-seq-reset-rejected.sh0000775000175000017500000000306415241075234021027 0ustar00rgerrger#!/bin/bash # Verify a sequence reset on an established connection is rejected without # submitting or acknowledging the invalid event. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%|%$!metadata!imbeats!sequence%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" python3 - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys port = int(sys.argv[1]) def frame(seq, message): payload = json.dumps({"message": message}, separators=(",", ":")).encode() return b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(5) sock.sendall(b"2W" + struct.pack(">I", 1) + frame(1, "first")) print(sock.recv(6).hex()) sock.sendall(b"2W" + struct.pack(">I", 1) + frame(1, "reset")) try: data = sock.recv(6) except (ConnectionResetError, TimeoutError, socket.timeout): data = b"" if data: raise SystemExit(f"unexpected ack for reset sequence: {data.hex()}") PY shutdown_when_empty wait_shutdown # shellcheck disable=SC2034 EXPECTED='{"message":"first"}|1' cmp_exact test "$(cat "$RSYSLOG_DYNNAME.imbeats.ack")" = "324100000001" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs-vg.sh0000644000000000000000000000013215241075234024325 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.567970522 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs-vg.sh0000775000175000017500000000014115241075234023770 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/omjournal-abort-no-template.sh0000644000000000000000000000013215035412264021575 xustar0030 mtime=1752569012.404722953 30 atime=1782715518.894790642 30 ctime=1787067805.998941285 rsyslog-8.2608.0/tests/omjournal-abort-no-template.sh0000777000175000017500000000107415035412264021250 0ustar00rgerrger#!/bin/bash # a very basic test for omjournal. Right now, we have no # reliable way of verifying that data was actually written # to the journal, but at least we check that rsyslog does # not abort when trying to use omjournal. Not high tech, # but better than nothing. # addd 2016-03-16 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omjournal/.libs/omjournal") action(type="omjournal") ' startup ./msleep 500 shutdown_when_empty wait_shutdown # if we reach this, we have at least not aborted exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmdarwin_errmsg_no_sock-vg.sh0000644000000000000000000000013215171370365021567 xustar0030 mtime=1776677109.464913434 30 atime=1782715518.894790642 30 ctime=1787067806.035941974 rsyslog-8.2608.0/tests/mmdarwin_errmsg_no_sock-vg.sh0000775000175000017500000000021415171370365021233 0ustar00rgerrger#!/bin/bash # add 2019-04-02 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/mmdarwin_errmsg_no_sock.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-duplicate-monitor-warning.sh0000644000000000000000000000013215241075234022605 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067807.994978479 rsyslog-8.2608.0/tests/imfile-duplicate-monitor-warning.sh0000775000175000017500000000371015241075234022255 0ustar00rgerrger#!/bin/bash # Verifies that imfile warns only for probably accidental duplicate file # monitors. The first config-check uses three identical monitors and must emit # one bounded warning per later duplicate, not every equivalent pair. The # second config-check uses the same file with distinct tags and a rate-limited # monitor; it must stay warning-free because this is a valid same-file fan-out # pattern. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init mkdir "$RSYSLOG_DYNNAME.work" touch "$RSYSLOG_DYNNAME.input" generate_conf add_conf ' global(workDirectory="./'$RSYSLOG_DYNNAME'.work") module(load="../plugins/imfile/.libs/imfile" mode="polling") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="dup:") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="dup:") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="dup:") ' export RS_REDIR=">${RSYSLOG_DYNNAME}.dup.log 2>&1" rsyslogd_config_check unset RS_REDIR content_check "imfile: duplicate file monitor for" "${RSYSLOG_DYNNAME}.dup.log" content_check "with tag 'dup:' has identical delivery parameters" "${RSYSLOG_DYNNAME}.dup.log" warning_count=$(grep -c -F "imfile: duplicate file monitor for" "${RSYSLOG_DYNNAME}.dup.log") if [ "$warning_count" -ne 2 ]; then echo "expected two bounded duplicate monitor warnings, got $warning_count" cat -n "${RSYSLOG_DYNNAME}.dup.log" error_exit 1 fi generate_conf add_conf ' global(workDirectory="./'$RSYSLOG_DYNNAME'.work") module(load="../plugins/imfile/.libs/imfile" mode="polling") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="first:") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="second:") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="limited:" maxLinesPerMinute="1") ' export RS_REDIR=">${RSYSLOG_DYNNAME}.distinct.log 2>&1" rsyslogd_config_check unset RS_REDIR check_not_present "imfile: duplicate file monitor for" "${RSYSLOG_DYNNAME}.distinct.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-basic-vg.sh0000644000000000000000000000013215171370365017203 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.895790659 30 ctime=1787067808.065979803 rsyslog-8.2608.0/tests/imfile-basic-vg.sh0000775000175000017500000000010515171370365016646 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imfile-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/omotel-proxy.sh0000644000000000000000000000013115216464436016725 xustar0030 mtime=1782212894.079267041 30 atime=1782715518.894790642 29 ctime=1787067806.21494531 rsyslog-8.2608.0/tests/omotel-proxy.sh0000775000175000017500000001627015216464436016403 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-proxy.sh -- proxy support test for omotel module ## ## Tests that omotel correctly uses HTTP proxy to forward requests to ## OTEL Collector, with and without proxy authentication. . ${srcdir:=.}/diag.sh init # Check if omotel module is available require_plugin omotel export NUMMESSAGES=100 export EXTRA_EXIT="otel proxy" export SEQ_CHECK_OPTIONS=-d # Check for Python 3 (required for proxy server) if ! command -v python3 &> /dev/null; then echo "ERROR: python3 not found - required for proxy server" error_exit 77 fi # Download and prepare OTEL Collector download_otel_collector prepare_otel_collector start_otel_collector # Read the OTEL Collector port if [ ! -f ${RSYSLOG_DYNNAME}.otel_port.file ]; then echo "ERROR: OTEL Collector port file not found" error_exit 1 fi otel_port=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) if [ -z "$otel_port" ]; then echo "ERROR: OTEL Collector port is empty" error_exit 1 fi echo "Using OTEL Collector port: $otel_port" # Start proxy server (no authentication) proxy_server_py="$srcdir/omotel_proxy_server.py" if [ ! -f "$proxy_server_py" ]; then echo "ERROR: Proxy server script not found: $proxy_server_py" error_exit 1 fi proxy_port_file="${RSYSLOG_DYNNAME}.proxy_port.file" proxy_data_file="${RSYSLOG_DYNNAME}.proxy_data.json" echo "Starting proxy server on a dynamic port..." python3 "$proxy_server_py" \ --port 0 \ --port-file "$proxy_port_file" \ --target-host 127.0.0.1 \ --target-port "$otel_port" \ --data-file "$proxy_data_file" \ > "${RSYSLOG_DYNNAME}.proxy.log" 2>&1 & proxy_pid=$! # Wait for proxy to start and verify port file wait_file_exists "$proxy_port_file" 10 if [ ! -f "$proxy_port_file" ]; then echo "ERROR: Proxy server did not create port file" kill $proxy_pid 2>/dev/null error_exit 1 fi proxy_port=$(cat "$proxy_port_file") if [ -z "$proxy_port" ]; then echo "ERROR: Proxy port is empty" kill $proxy_pid 2>/dev/null error_exit 1 fi echo "Proxy server started on port: $proxy_port (pid: $proxy_pid)" # Function to stop proxy server stop_proxy() { if [ -n "$proxy_pid" ] && kill -0 "$proxy_pid" 2>/dev/null; then echo "Stopping proxy server (pid: $proxy_pid)" kill "$proxy_pid" 2>/dev/null wait "$proxy_pid" 2>/dev/null || true fi } # Ensure proxy is stopped on exit trap 'stop_proxy' EXIT # Test 1: Proxy without authentication echo "=== Test 1: Proxy without authentication ===" generate_conf add_conf ' template(name="otlpBody" type="string" string="msgnum:%msg:F,58:2%") module(load="../plugins/omotel/.libs/omotel") if $msg contains "msgnum:" then action( name="omotel-proxy" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port'" path="/v1/logs" proxy="http://127.0.0.1:'$proxy_port'" batch.max_items="50" batch.timeout.ms="1000" ) ' startup injectmsg shutdown_when_empty wait_shutdown # Stop OTEL Collector to flush data stop_otel_collector # Give time for data to flush if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi # Verify proxy was used if [ -f "$proxy_data_file" ]; then proxy_requests=$(python3 -c "import json; f=open('$proxy_data_file'); data=json.load(f); print(len(data)); f.close()" 2>/dev/null || echo "0") if [ "$proxy_requests" -eq "0" ]; then echo "ERROR: Proxy server did not receive any requests" cat "${RSYSLOG_DYNNAME}.proxy.log" error_exit 1 fi echo "Proxy server received $proxy_requests requests" else echo "WARNING: Proxy data file not found, but continuing..." fi # Extract and verify OTEL Collector output otel_collector_get_data # Use the output file path set by prepare_otel_collector if [ -z "$OTEL_OUTPUT_FILE" ]; then # Fallback: construct path like other tests test_dir="${srcdir:-$(pwd)}" if [[ "$test_dir" != /* ]]; then test_dir="$(cd "$test_dir" && pwd)" fi otel_output_file="$test_dir/${RSYSLOG_DYNNAME}.otel-output.json" else otel_output_file="$OTEL_OUTPUT_FILE" fi python3 - "$otel_output_file" <<'PY' import json import sys path = sys.argv[1] try: records = [] with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue payload = json.loads(line) if "resourceLogs" in payload: for resource_log in payload["resourceLogs"]: if "scopeLogs" in resource_log: for scope_log in resource_log["scopeLogs"]: if "logRecords" in scope_log: records.extend(scope_log["logRecords"]) except Exception as exc: sys.stderr.write(f"omotel-proxy: failed to parse OTLP output: {exc}\n") sys.exit(1) if not records: sys.stderr.write("omotel-proxy: OTLP output did not contain any logRecords\n") sys.exit(1) sys.stdout.write(f"omotel-proxy: successfully received {len(records)} log records via proxy\n") PY seq_check # Test 2: Proxy with authentication echo "=== Test 2: Proxy with authentication ===" # Stop current proxy and start new one with auth stop_proxy sleep 1 # Restart OTEL Collector before creating the authenticated proxy so the proxy # forwards to the current dynamic collector port. prepare_otel_collector start_otel_collector otel_port2=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) proxy_port_file2="${RSYSLOG_DYNNAME}.proxy2_port.file" proxy_data_file2="${RSYSLOG_DYNNAME}.proxy2_data.json" echo "Starting authenticated proxy server on a dynamic port..." python3 "$proxy_server_py" \ --port 0 \ --port-file "$proxy_port_file2" \ --target-host 127.0.0.1 \ --target-port "$otel_port2" \ --require-auth \ --user "testuser" \ --password "testpass" \ --data-file "$proxy_data_file2" \ > "${RSYSLOG_DYNNAME}.proxy2.log" 2>&1 & proxy_pid2=$! wait_file_exists "$proxy_port_file2" 10 proxy_port2=$(cat "$proxy_port_file2") echo "Authenticated proxy server started on port: $proxy_port2 (pid: $proxy_pid2)" # Update trap to stop both proxies stop_proxy2() { stop_proxy if [ -n "$proxy_pid2" ] && kill -0 "$proxy_pid2" 2>/dev/null; then echo "Stopping authenticated proxy server (pid: $proxy_pid2)" kill "$proxy_pid2" 2>/dev/null wait "$proxy_pid2" 2>/dev/null || true fi } trap 'stop_proxy2' EXIT generate_conf add_conf ' template(name="otlpBody" type="string" string="msgnum:%msg:F,58:2%") module(load="../plugins/omotel/.libs/omotel") if $msg contains "msgnum:" then action( name="omotel-proxy-auth" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port2'" path="/v1/logs" proxy="http://127.0.0.1:'$proxy_port2'" proxy.user="testuser" proxy.password="testpass" batch.max_items="50" batch.timeout.ms="1000" ) ' startup injectmsg shutdown_when_empty wait_shutdown stop_otel_collector stop_proxy2 # Verify authenticated proxy was used if [ -f "$proxy_data_file2" ]; then proxy_requests2=$(python3 -c "import json; f=open('$proxy_data_file2'); data=json.load(f); print(len(data)); f.close()" 2>/dev/null || echo "0") if [ "$proxy_requests2" -eq "0" ]; then echo "ERROR: Authenticated proxy server did not receive any requests" cat "${RSYSLOG_DYNNAME}.proxy2.log" error_exit 1 fi echo "Authenticated proxy server received $proxy_requests2 requests" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/ruleset-direct-queue.sh0000644000000000000000000000013215131231047020307 xustar0030 mtime=1768239655.719212827 30 atime=1782715518.893790625 30 ctime=1787067804.394911395 rsyslog-8.2608.0/tests/ruleset-direct-queue.sh0000777000175000017500000000121015131231047017752 0ustar00rgerrger#!/bin/bash # check that ruleset is called synchronously when queue.type="direct" is # specified in ruleset. # added 2021-09-17 by rgerhards. Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf export STATSFILE="$RSYSLOG_DYNNAME.stats" add_conf ' template(name="outfmt" type="string" string="%msg%,%$.msg%\n") ruleset(name="rs1" queue.type="direct") { set $.msg = "TEST"; } if $msg contains "msgnum:" then { set $.msg = $msg; call rs1 action(type="omfile" name="main-action" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown content_check "msgnum:00000000:,TEST" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-stream-outfield.sh0000644000000000000000000000013215145046113021322 xustar0030 mtime=1771326539.055014549 30 atime=1782715518.893790625 30 ctime=1787067806.625952969 rsyslog-8.2608.0/tests/omhiredis-stream-outfield.sh0000775000175000017500000000317215145046113020774 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging # export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omhiredis/.libs/omhiredis") template(name="outfmt" type="string" string="%msg%") local4.* { action(type="omhiredis" name="omhiredis-stream-outfield" server="127.0.0.1" serverport="'$REDIS_RANDOM_PORT'" mode="stream" key="outStream" stream.outField="custom_field" template="outfmt") stop } action(type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'" template="outfmt") ' startup # Inject 2 messages injectmsg 1 2 shutdown_when_empty wait_shutdown # Should get '2' redis_command "XLEN outStream" >> $RSYSLOG_OUT_LOG # Should get 2 entries redis_command "XREAD COUNT 3 STREAMS outStream 0" >> $RSYSLOG_OUT_LOG # Cannot check for full reply as it includes entries' unix timestamp content_count_check "outStream" 1 $RSYSLOG_OUT_LOG content_count_check " msgnum:00000001:" 1 $RSYSLOG_OUT_LOG content_count_check " msgnum:00000002:" 1 $RSYSLOG_OUT_LOG # 2 data should be inserted in the 'custom_field' field inside every message content_count_check "custom_field" 2 $RSYSLOG_OUT_LOG content_count_check "msg" 2 $RSYSLOG_OUT_LOG content_count_check "msgnum" 2 $RSYSLOG_OUT_LOG content_check "omhiredis[omhiredis-stream-outfield]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkafka_multi_group.sh0000644000000000000000000000013215216464436020301 xustar0030 mtime=1782212894.058266701 30 atime=1782715518.897790693 30 ctime=1787067806.256946093 rsyslog-8.2608.0/tests/imkafka_multi_group.sh0000775000175000017500000000640315216464436017753 0ustar00rgerrger#!/bin/bash # added 2018-08-29 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init check_command_available kcat echo TEST unclear in regard to load balancing - currently skipping it. exit 77 export KEEP_KAFKA_RUNNING="YES" # False positive codefactor.io export RSYSLOG_OUT_LOG_1="${RSYSLOG_OUT_LOG:-default}.1" export RSYSLOG_OUT_LOG_2="${RSYSLOG_OUT_LOG:-default}.2" export TESTMESSAGES=100000 # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. #export EXTRA_EXITCHECK=dumpkafkalogs #export EXTRA_EXIT=kafka download_kafka stop_zookeeper stop_kafka start_zookeeper start_kafka RANDTOPIC="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC create_kafka_topic $RANDTOPIC '.dep_wrk' '22181' # Create FIRST rsyslog instance export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") /* Polls messages from kafka server!*/ input( type="imkafka" topic="'$RANDTOPIC'" broker="127.0.0.1:29092" consumergroup="rsysloggroup" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=5000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "enable.partition.eof=false" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) action( type="omfile" file=`echo $RSYSLOG_OUT_LOG_1` template="outfmt" ) } ' echo Starting first rsyslog instance [imkafka] startup # Create SECOND rsyslog instance export RSYSLOG_DEBUGLOG="log2" generate_conf 2 add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") /* Polls messages from kafka server!*/ input( type="imkafka" topic="'$RANDTOPIC'" broker="localhost:29092" consumergroup="rsysloggroup" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=5000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "enable.partition.eof=false" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) action( type="omfile" file=`echo $RSYSLOG_OUT_LOG_2` template="outfmt" ) } ' 2 echo Starting second rsyslog instance [imkafka] startup 2 TIMESTART=$(date +%s.%N) injectmsg_kcat # special case: number of test messages differs from file output wait_file_lines $RSYSLOG_OUT_LOG $((TESTMESSAGES)) ${RETRIES:-200} # Check that at least 25% messages are in both logfiles, otherwise load balancing hasn't worked wait_file_lines $RSYSLOG_OUT_LOG_1 $((TESTMESSAGES/4)) ${RETRIES:-200} wait_file_lines $RSYSLOG_OUT_LOG_2 $((TESTMESSAGES/4)) ${RETRIES:-200} echo Stopping first rsyslog instance [imkafka] shutdown_when_empty wait_shutdown echo Stopping second rsyslog instance [imkafka] shutdown_when_empty 2 wait_shutdown 2 TIMEEND=$(date +%s.%N) TIMEDIFF=$(echo "$TIMEEND - $TIMESTART" | bc) echo "*** imkafka time to process all data: $TIMEDIFF seconds!" delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181' seq_check 1 $TESTMESSAGES -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_servercert_mbedtls_clientanon.sh0000644000000000000000000000013215216464436024621 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.897790693 30 ctime=1787067807.430967969 rsyslog-8.2608.0/tests/sndrcv_tls_servercert_mbedtls_clientanon.sh0000775000175000017500000000353215216464436024273 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_re_match-dbl_quotes.sh0000644000000000000000000000013215035412264021726 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.897790693 30 ctime=1787067804.800918961 rsyslog-8.2608.0/tests/rscript_re_match-dbl_quotes.sh0000777000175000017500000000105315035412264021376 0ustar00rgerrger#!/bin/bash # Test that '$' in double-quoted string constants raise a meaningful # error message and do not cause rsyslog to segfault. # added 2019-12-30 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' action(type="omfile" file="'$RSYSLOG_OUT_LOG'") # order is important ... set $!test="test$" # ... as after this syntax error nothing is really taken up ' startup shutdown_when_empty wait_shutdown content_check '$-sign in double quotes must be escaped' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_ruleset.sh0000644000000000000000000000013215145046113021201 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.896790676 30 ctime=1787067804.663916408 rsyslog-8.2608.0/tests/imuxsock_logger_ruleset.sh0000775000175000017500000000143615145046113020654 0ustar00rgerrger#!/bin/bash # test imuxsock with ruleset definition # rgerhards, 2016-02-02 released under ASL 2.0 . ${srcdir:=.}/diag.sh init check_logger_has_option_d generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket" useSpecialParser="off" ruleset="testruleset" parseHostname="on") template(name="outfmt" type="string" string="%msg:%\n") ruleset(name="testruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup # send a message with trailing LF logger -d -u $RSYSLOG_DYNNAME-testbench_socket test # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty wait_shutdown export EXPECTED=" test" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropabortonidfaillegacy.sh0000644000000000000000000000013015131231047022020 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.896790676 28 ctime=1787067804.2449086 rsyslog-8.2608.0/tests/privdropabortonidfaillegacy.sh0000777000175000017500000000174615131231047021503 0ustar00rgerrger#!/bin/bash # add 2021-10-12 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" skip_platform "SunOS" "This test currently does not work on Solaris." export TESTBENCH_TESTUSER1="USER_${RSYSLOG_DYNNAME}_1" export TESTBENCH_TESTUSER2="USER_${RSYSLOG_DYNNAME}_2" generate_conf add_conf ' global( security.abortOnIDResolutionFail="off" ) template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } $FileOwner '${TESTBENCH_TESTUSER1}' $FileGroup '${TESTBENCH_TESTUSER1}' $DirOwner '${TESTBENCH_TESTUSER2}' $DirGroup '${TESTBENCH_TESTUSER2}' action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup shutdown_when_empty wait_shutdown content_check --regex "ID for user '${TESTBENCH_TESTUSER1}' could not be found" content_check --regex "ID for user '${TESTBENCH_TESTUSER2}' could not be found" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-module-mtls-vg.sh0000644000000000000000000000013215241075234023104 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.574970653 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-module-mtls-vg.sh0000775000175000017500000000013215241075234022547 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-module-mtls.sh rsyslog-8.2608.0/tests/PaxHeaders/yaml-statements-basic.sh0000644000000000000000000000013115241075234020445 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 29 ctime=1787067805.40193016 rsyslog-8.2608.0/tests/yaml-statements-basic.sh0000775000175000017500000000224315241075234020116 0ustar00rgerrger#!/bin/bash # Tests the YAML-native statements: block — basic if:/action: form. # Demonstrates clean separation: the filter condition is a RainerScript # expression string, but the action is expressed as a YAML mapping. # Equivalent to yaml-basic.sh but using statements: instead of script:. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" rulesets: - name: main statements: - if: '$msg contains "msgnum:"' action: type: omfile template: outfmt file: "${RSYSLOG_OUT_LOG}" YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_number_comparison_LT.sh0000644000000000000000000000013215131231047022121 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.895790659 30 ctime=1787067804.836919631 rsyslog-8.2608.0/tests/rscript_number_comparison_LT.sh0000777000175000017500000000104215131231047021567 0ustar00rgerrger#!/bin/bash # added 2022-01-27 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!result") constant(value="\n") } set $!lower_nr = 1111; set $!higher_nr = 2222; if $!higher_nr < $!lower_nr then { set $!result = "WRONG"; } else { set $!result = "RIGHT"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown content_check 'RIGHT' exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_errmsg_no_params-vg.sh0000644000000000000000000000013215171370365021572 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.896790676 30 ctime=1787067806.024941769 rsyslog-8.2608.0/tests/improg_errmsg_no_params-vg.sh0000775000175000017500000000022315171370365021236 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/improg_errmsg_no_params.sh rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream.sh0000644000000000000000000000013215131231047017500 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.896790676 30 ctime=1787067806.552951608 rsyslog-8.2608.0/tests/imhiredis-stream.sh0000777000175000017500000000246115131231047017154 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis # Won't be logged by Rsyslog redis_command "XADD mystream * msg message1" redis_command "XADD mystream * msg message2" redis_command "XADD mystream * msg message3" generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %$!msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mystream" mode="stream" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup redis_command "XADD mystream * msg message4" redis_command "XADD mystream * msg message5" redis_command "XADD mystream * msg message6" shutdown_when_empty wait_shutdown stop_redis check_not_present "message1" check_not_present "message2" check_not_present "message3" content_check '1 message4' content_check '2 message5' content_check '3 message6' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-multi-drvr-basic.sh0000644000000000000000000000013215241075234020536 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067807.356966591 rsyslog-8.2608.0/tests/imtcp-multi-drvr-basic.sh0000775000175000017500000000253415241075234020211 0ustar00rgerrger#!/bin/bash # This test checks imtcp functionality with multiple drivers running together. It is # a minimal test. # added 2021-04-27 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 # must be even number! export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2" tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2)) shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-if-error.sh0000644000000000000000000000013215131231047017260 xustar0030 mtime=1768239655.715212762 30 atime=1782715518.895790659 30 ctime=1787067806.084942887 rsyslog-8.2608.0/tests/omprog-if-error.sh0000777000175000017500000000227315131231047016735 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests omprog if omprog detects errors in the calling # interface, namely a missing LF on input messages . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%") if (prifilt("local4.*") and $msg contains "msgnum:") then { action(type="omprog" binary="'$srcdir'/testsuites/omprog-defaults-bin.sh p1 p2 p3" template="outfmt" name="omprog_action") } else { action(type="omfile" file="'$RSYSLOG_DYNNAME'.othermsg") } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown cat $RSYSLOG_DYNNAME.othermsg content_check 'must be terminated with \n' $RSYSLOG_DYNNAME.othermsg export EXPECTED="Starting with parameters: p1 p2 p3 Next parameter is \"p1\" Next parameter is \"p2\" Next parameter is \"p3\" Received msgnum:00000000: Received msgnum:00000001: Received msgnum:00000002: Received msgnum:00000003: Received msgnum:00000004: Received msgnum:00000005: Received msgnum:00000006: Received msgnum:00000007: Received msgnum:00000008: Received msgnum:00000009: Terminating normally" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_traillf_root.sh0000644000000000000000000000013215145046113020657 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.896790676 30 ctime=1787067805.960940576 rsyslog-8.2608.0/tests/imuxsock_traillf_root.sh0000775000175000017500000000216315145046113020330 0ustar00rgerrger#!/bin/bash # note: we must be root and no other syslogd running in order to # carry out this test echo \[imuxsock_traillf_root.sh\]: test trailing LF handling in imuxsock echo This test must be run as root with no other active syslogd if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi ./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imuxsock/.libs/imuxsock $template outfmt,"%msg:%\n" local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # send a message with trailing LF ./syslog_caller -fsyslog_inject-l -m1 # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_traillf.log if [ ! $? -eq 0 ]; then echo "imuxsock_traillf_root.sh failed" exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-x509name.sh0000644000000000000000000000013215241075234020476 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.473968771 rsyslog-8.2608.0/tests/imtcp-tls-ossl-x509name.sh0000775000175000017500000000231615241075234020147 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer=["/CN=rsyslog-client/OU=Adiscon GmbH/O=Adiscon GmbH/L=Grossrinderfeld/ST=BW/C=DE/DC=rsyslog.com","rsyslog.com"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-omprog-restart-save.sh0000644000000000000000000000013215241075234024127 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067806.066942552 rsyslog-8.2608.0/tests/segmented-diskqueue-omprog-restart-save.sh0000775000175000017500000000033715241075234023601 0ustar00rgerrger#!/bin/bash # Run the pure-disk negative-ack/restart regression unchanged against the # segmentedDisk backend, proving retry-before-commit parity. export QUEUE_TYPE=segmentedDisk . ${srcdir:=.}/omprog-diskq-restart-save.sh rsyslog-8.2608.0/tests/PaxHeaders/asynwr_timeout.sh0000644000000000000000000000013215241075234017331 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.762581234 30 ctime=1787067804.525913836 rsyslog-8.2608.0/tests/asynwr_timeout.sh0000775000175000017500000000222615241075234017002 0ustar00rgerrger#!/bin/bash # This test writes to the output buffers, let's the output # write timeout (and write data) and then continue. The conf file # has a 2 second timeout, so we wait 4 seconds to be on the save side. # # added 2010-03-09 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # send 35555 messages, make sure file size is not a multiple of # 10K, the buffer size! export NUMMESSAGES=15555 generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'") $OMFileFlushOnTXEnd off $OMFileFlushInterval 2 $OMFileIOBufferSize 10k $OMFileAsyncWriting on :msg, contains, "msgnum:" ?dynfile;outfmt ' startup tcpflood -m $NUMMESSAGES printf 'waiting for timeout to occur\n' sleep 15 # GOOD SLEEP - we wait for the timeout! long to take care of slow test machines... printf 'timeout should now have occurred - check file state\n' seq_check shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/msgvar-concurrency.sh0000644000000000000000000000013215241075234020067 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.782581608 30 ctime=1787067804.212908003 rsyslog-8.2608.0/tests/msgvar-concurrency.sh0000775000175000017500000000174715241075234017547 0ustar00rgerrger#!/bin/bash # Test concurrency of message variables # Added 2015-11-03 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!tree!here!nbr%\n") if $msg contains "msgnum:" then { set $!tree!here!nbr = field($msg, 58, 2); action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList") set $!tree!here!save = $!tree!here!nbr; set $!tree!here!nbr = ""; set $!tree!here!nbr = $!tree!here!save; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m500000 shutdown_when_empty wait_shutdown seq_check 0 499999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/unit0000644000000000000000000000013215241076633014612 xustar0030 mtime=1787067803.668897866 30 atime=1787067808.790993313 30 ctime=1787067803.668897866 rsyslog-8.2608.0/tests/unit/0000775000175000017500000000000015241076633014333 5ustar00rgerrgerrsyslog-8.2608.0/tests/unit/PaxHeaders/gss_token_util_test.c0000644000000000000000000000013115171370365021123 xustar0030 mtime=1776677109.472913557 29 atime=1782715518.89879071 30 ctime=1787067803.603896655 rsyslog-8.2608.0/tests/unit/gss_token_util_test.c0000664000175000017500000000521715171370365020575 0ustar00rgerrger#include "config.h" #include #include #include #include "rsyslog.h" #include "gss-token-util.h" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) static int test_decode_length_accepts_small_frame(void) { static const unsigned char lenbuf[4] = {0x00, 0x00, 0x01, 0x00}; size_t token_len = 0; CHECK(gssTokenDecodeLength(lenbuf, 512, &token_len) == RS_RET_OK); CHECK(token_len == 256); return 0; } static int test_decode_length_rejects_oversize_frame(void) { static const unsigned char lenbuf[4] = {0x00, 0x10, 0x00, 0x00}; size_t token_len = 0; CHECK(gssTokenDecodeLength(lenbuf, 4096, &token_len) == RS_RET_INVALID_VALUE); CHECK(token_len == 0x00100000U); return 0; } static int test_decode_length_rejects_null_output_pointer(void) { static const unsigned char lenbuf[4] = {0x00, 0x00, 0x00, 0x01}; CHECK(gssTokenDecodeLength(lenbuf, 1, NULL) == RS_RET_INVALID_PARAMS); return 0; } static int test_message_limit_adds_wrap_overhead(void) { CHECK(gssTokenGetMessageLimit(4096) == 4096 + GSS_TOKEN_MAX_WRAP_OVERHEAD_BYTES); return 0; } static int test_message_limit_saturates_on_overflow(void) { CHECK(gssTokenGetMessageLimit(SIZE_MAX) == SIZE_MAX); CHECK(gssTokenGetMessageLimit(SIZE_MAX - 1) == SIZE_MAX); return 0; } int main(void) { struct { const char *name; int (*fn)(void); } tests[] = { {"decode_length_accepts_small_frame", test_decode_length_accepts_small_frame}, {"decode_length_rejects_oversize_frame", test_decode_length_rejects_oversize_frame}, {"decode_length_rejects_null_output_pointer", test_decode_length_rejects_null_output_pointer}, {"message_limit_adds_wrap_overhead", test_message_limit_adds_wrap_overhead}, {"message_limit_saturates_on_overflow", test_message_limit_saturates_on_overflow}, }; size_t i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { if (tests[i].fn() != 0) { fprintf(stderr, "FAILED: %s\n", tests[i].name); return 1; } } printf("gss token util tests passed (%zu cases)\n", sizeof(tests) / sizeof(tests[0])); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/omazuredce_utils_test.c0000644000000000000000000000013215241075234021444 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.695579979 30 ctime=1787067803.617896916 rsyslog-8.2608.0/tests/unit/omazuredce_utils_test.c0000664000175000017500000001454015241075234021114 0ustar00rgerrger/* Unit coverage for omazuredce request-size and timer-stop helpers. * * The timer test freezes a waiter after it observed a false stop predicate. * The stop helper must block on the wait mutex until pthread_cond_wait() has * registered the waiter and released that mutex. A short 200 ms timed condition * wait first proves the stopper cannot complete while the waiter holds the * mutex without adding a fixed multi-second delay, then a conservative * two-second wait proves the paired wakeup completes. * Thread-creation error paths release and join any waiter already started. * * The size test verifies that a request which grows beyond its configured cap * is classified for retry rather than successful destructive completion. */ #include "config.h" #include #include #include #include #include "../../plugins/omazuredce/omazuredce_utils.h" typedef struct timer_test_state_s { pthread_mutex_t batchMutex; pthread_cond_t timerCond; signed char stopRequested; pthread_mutex_t gateMutex; pthread_cond_t gateCond; int waiterObservedPredicate; int stopperStarted; int stopperFinished; int releaseWaiter; int waiterExited; } timer_test_state_t; static void *timer_waiter(void *arg) { timer_test_state_t *const state = arg; int observedStop; (void)pthread_mutex_lock(&state->batchMutex); observedStop = state->stopRequested; (void)pthread_mutex_lock(&state->gateMutex); state->waiterObservedPredicate = 1; (void)pthread_cond_broadcast(&state->gateCond); while (!state->releaseWaiter) { (void)pthread_cond_wait(&state->gateCond, &state->gateMutex); } (void)pthread_mutex_unlock(&state->gateMutex); if (!observedStop) { (void)pthread_cond_wait(&state->timerCond, &state->batchMutex); } (void)pthread_mutex_unlock(&state->batchMutex); (void)pthread_mutex_lock(&state->gateMutex); state->waiterExited = 1; (void)pthread_cond_broadcast(&state->gateCond); (void)pthread_mutex_unlock(&state->gateMutex); return NULL; } static void *timer_stopper(void *arg) { timer_test_state_t *const state = arg; (void)pthread_mutex_lock(&state->gateMutex); state->stopperStarted = 1; (void)pthread_cond_broadcast(&state->gateCond); (void)pthread_mutex_unlock(&state->gateMutex); omazuredceRequestTimerStop(&state->batchMutex, &state->timerCond, &state->stopRequested); (void)pthread_mutex_lock(&state->gateMutex); state->stopperFinished = 1; (void)pthread_cond_broadcast(&state->gateCond); (void)pthread_mutex_unlock(&state->gateMutex); return NULL; } static int test_timer_stop_cannot_lose_wakeup(void) { timer_test_state_t state = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0, 0, 0, 0, }; pthread_t waiter; pthread_t stopper; struct timespec deadline; int waitRet = 0; if (pthread_create(&waiter, NULL, timer_waiter, &state) != 0) return 1; (void)pthread_mutex_lock(&state.gateMutex); while (!state.waiterObservedPredicate) { (void)pthread_cond_wait(&state.gateCond, &state.gateMutex); } (void)pthread_mutex_unlock(&state.gateMutex); if (pthread_create(&stopper, NULL, timer_stopper, &state) != 0) { (void)pthread_mutex_lock(&state.gateMutex); state.releaseWaiter = 1; (void)pthread_cond_broadcast(&state.gateCond); (void)pthread_mutex_unlock(&state.gateMutex); omazuredceRequestTimerStop(&state.batchMutex, &state.timerCond, &state.stopRequested); (void)pthread_join(waiter, NULL); return 1; } (void)pthread_mutex_lock(&state.gateMutex); while (!state.stopperStarted) { (void)pthread_cond_wait(&state.gateCond, &state.gateMutex); } (void)clock_gettime(CLOCK_REALTIME, &deadline); deadline.tv_nsec += 200000000L; if (deadline.tv_nsec >= 1000000000L) { deadline.tv_sec++; deadline.tv_nsec -= 1000000000L; } /* Timing out is the successful outcome here, so scheduler delay cannot make this phase fail. The window * only gives an incorrect non-locking implementation enough time to expose itself by completing. */ while (!state.stopperFinished && waitRet == 0) { waitRet = pthread_cond_timedwait(&state.gateCond, &state.gateMutex, &deadline); } if (state.stopperFinished) { state.releaseWaiter = 1; (void)pthread_cond_broadcast(&state.gateCond); (void)pthread_mutex_unlock(&state.gateMutex); (void)pthread_mutex_lock(&state.batchMutex); (void)pthread_cond_signal(&state.timerCond); (void)pthread_mutex_unlock(&state.batchMutex); (void)pthread_join(waiter, NULL); (void)pthread_join(stopper, NULL); fputs("timer stop helper completed without acquiring wait mutex\n", stderr); return 1; } state.releaseWaiter = 1; (void)pthread_cond_broadcast(&state.gateCond); (void)pthread_mutex_unlock(&state.gateMutex); waitRet = 0; (void)clock_gettime(CLOCK_REALTIME, &deadline); deadline.tv_sec += 2; (void)pthread_mutex_lock(&state.gateMutex); while (!state.waiterExited && waitRet == 0) { waitRet = pthread_cond_timedwait(&state.gateCond, &state.gateMutex, &deadline); } (void)pthread_mutex_unlock(&state.gateMutex); if (!state.waiterExited) { fprintf(stderr, "timer waiter did not receive stop wakeup: %d\n", waitRet); (void)pthread_mutex_lock(&state.batchMutex); (void)pthread_cond_signal(&state.timerCond); (void)pthread_mutex_unlock(&state.batchMutex); (void)pthread_join(waiter, NULL); (void)pthread_join(stopper, NULL); return 1; } (void)pthread_join(waiter, NULL); (void)pthread_join(stopper, NULL); if (!state.stopRequested) { fputs("timer stop predicate was not set\n", stderr); return 1; } return 0; } static int test_oversize_request_retries(void) { if (omazuredceClassifyRequestSize(4096, 4096) != OMAZUREDCE_REQUEST_FITS) return 1; if (omazuredceClassifyRequestSize(4097, 4096) != OMAZUREDCE_REQUEST_RETRY) return 1; return 0; } int main(void) { if (test_timer_stop_cannot_lose_wakeup() != 0) return 1; if (test_oversize_request_retries() != 0) return 1; return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/parser_pri_test.c0000644000000000000000000000013215216464436020244 xustar0030 mtime=1782212894.089267203 30 atime=1783339715.351941103 30 ctime=1787067803.622897009 rsyslog-8.2608.0/tests/unit/parser_pri_test.c0000664000175000017500000001105515216464436017712 0ustar00rgerrger#include "config.h" #include #include #include #include #include "rsyslog.h" #define LOG_MAXPRI 191 #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) /* Copy of compute_off_after_pri under test to ensure identical pure logic verification */ static int compute_off_after_pri(const uchar *buf, size_t len, int *pri) { if (len < 3 || buf[0] != '<') { return -1; } if (isdigit(buf[1]) && buf[2] == '>') { if (pri != NULL) { *pri = buf[1] - '0'; } return 3; } if (len >= 4 && isdigit(buf[1]) && isdigit(buf[2]) && buf[3] == '>') { if (pri != NULL) { *pri = (buf[1] - '0') * 10 + (buf[2] - '0'); } return 4; } if (len >= 5 && isdigit(buf[1]) && isdigit(buf[2]) && isdigit(buf[3]) && buf[4] == '>') { int val = (buf[1] - '0') * 100 + (buf[2] - '0') * 10 + (buf[3] - '0'); if (val <= LOG_MAXPRI) { if (pri != NULL) { *pri = val; } return 5; } } return -1; } static int test_rfc3164_valid(void) { const uchar buf[] = "<13>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == 4); CHECK(pri == 13); return 0; } static int test_rfc5424_valid(void) { const uchar buf[] = "<165>1 2026-05-25..."; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == 5); CHECK(pri == 165); return 0; } static int test_missing_greater_than(void) { const uchar buf[] = "<13hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_non_digit_in_pri(void) { const uchar buf[] = "<1a>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_too_many_digits(void) { const uchar buf[] = "<1234>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_no_leading_less_than(void) { const uchar buf[] = "13>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_empty_pri(void) { const uchar buf[] = "<>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_out_of_range(void) { const uchar buf[] = "<192>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, strlen((const char *)buf), &pri) == -1); return 0; } static int test_very_short_buffers(void) { int pri = -1; CHECK(compute_off_after_pri((const uchar *)"", 0, &pri) == -1); CHECK(compute_off_after_pri((const uchar *)"<", 1, &pri) == -1); CHECK(compute_off_after_pri((const uchar *)"<1", 2, &pri) == -1); CHECK(compute_off_after_pri((const uchar *)"<1>", 3, &pri) == 3); CHECK(pri == 1); return 0; } static int test_leading_nuls_or_garbage(void) { const uchar buf[] = "\0<13>hello"; int pri = -1; CHECK(compute_off_after_pri(buf, 10, &pri) == -1); return 0; } int main(void) { struct { const char *name; int (*fn)(void); } tests[] = { {"rfc3164_valid", test_rfc3164_valid}, {"rfc5424_valid", test_rfc5424_valid}, {"missing_greater_than", test_missing_greater_than}, {"non_digit_in_pri", test_non_digit_in_pri}, {"too_many_digits", test_too_many_digits}, {"no_leading_less_than", test_no_leading_less_than}, {"empty_pri", test_empty_pri}, {"out_of_range", test_out_of_range}, {"very_short_buffers", test_very_short_buffers}, {"leading_nuls_or_garbage", test_leading_nuls_or_garbage}, }; size_t i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { if (tests[i].fn() != 0) { fprintf(stderr, "FAILED: %s\n", tests[i].name); return 1; } } printf("parser_pri unit tests passed (%zu cases)\n", sizeof(tests) / sizeof(tests[0])); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/queue_da_test.c0000644000000000000000000000013215241075234017656 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.696579998 30 ctime=1787067803.624897047 rsyslog-8.2608.0/tests/unit/queue_da_test.c0000664000175000017500000001753315241075234017333 0ustar00rgerrger/* SPDX-License-Identifier: Apache-2.0 */ /* * Copyright 2026 Rainer Gerhards and Adiscon GmbH. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 */ /** * @file queue_da_test.c * @brief Unit coverage for disk-assisted engine selection and its durable marker. * * Each case builds an exact temporary spool layout; the oracle is the chosen * engine or an explicit rejection, so no daemon timing is involved. */ #include "config.h" #include #include #include #include #include #include #include "queue_da.h" /* Keep this internal helper unit-testable without linking the queue runtime. */ #include "../../runtime/queue_da.c" #define CHECK(condition) \ do { \ if (!(condition)) { \ fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #condition); \ exit(1); \ } \ } while (0) static void touch_file(const char *dir, const char *name, const char *contents) { char path[512]; CHECK(snprintf(path, sizeof(path), "%s/%s", dir, name) < (int)sizeof(path)); const int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600); CHECK(fd >= 0); if (contents != NULL) CHECK(write(fd, contents, strlen(contents)) == (ssize_t)strlen(contents)); CHECK(close(fd) == 0); } static void check_file_contents(const char *dir, const char *name, const char *expected) { char path[512]; char contents[128]; CHECK(snprintf(path, sizeof(path), "%s/%s", dir, name) < (int)sizeof(path)); const int fd = open(path, O_RDONLY); CHECK(fd >= 0); const ssize_t len = read(fd, contents, sizeof(contents) - 1); CHECK(len >= 0); contents[len] = '\0'; CHECK(close(fd) == 0); CHECK(strcmp(contents, expected) == 0); } static qda_engine_result_t resolve( const char *dir, qda_engine_mode_t requested, sbool auto_upgrade, sbool classic_features, rsRetVal expected) { const qda_engine_config_t config = { .spool_dir = dir, .file_prefix = "queue", .requested = requested, .auto_upgrade = auto_upgrade, .requires_classic_features = classic_features, }; qda_engine_result_t result; /* Callers may ignore the returned result for rejection cases because this * helper itself makes the return-code expectation a fatal test oracle. */ CHECK(qdaEngineResolve(&config, &result) == expected); return result; } int main(void) { char root[] = "/tmp/rsyslog-qda-unit-XXXXXX"; CHECK(mkdtemp(root) != NULL); const qda_lifecycle_config_t lifecycle = { .engine = QDA_ENGINE_AUTO, .auto_upgrade = 0, .idle_timeout = 60000, }; qda_lifecycle_config_t changed = lifecycle; CHECK(qdaLifecycleConfigEqual(&lifecycle, &changed)); changed.engine = QDA_ENGINE_DISK; CHECK(!qdaLifecycleConfigEqual(&lifecycle, &changed)); changed = lifecycle; changed.auto_upgrade = 1; CHECK(!qdaLifecycleConfigEqual(&lifecycle, &changed)); changed = lifecycle; changed.idle_timeout = -1; CHECK(!qdaLifecycleConfigEqual(&lifecycle, &changed)); CHECK(!qdaLifecycleConfigEqual(NULL, &changed)); qda_engine_result_t result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_SEGMENTED_DISK); CHECK(result.reason == QDA_REASON_FRESH_DEFAULT); result = resolve(root, QDA_ENGINE_AUTO, 0, 1, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK); CHECK(result.reason == QDA_REASON_CLASSIC_FEATURE); resolve(root, QDA_ENGINE_SEGMENTED_DISK, 0, 1, RS_RET_INVALID_VALUE); touch_file(root, "queue.qi", "classic"); result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK && result.classic_data); CHECK(resolve(root, QDA_ENGINE_SEGMENTED_DISK, 0, 0, RS_RET_INVALID_VALUE).classic_data); char path[512]; CHECK(snprintf(path, sizeof(path), "%s/queue.qi", root) < (int)sizeof(path)); CHECK(unlink(path) == 0); touch_file(root, "queue.0000001", "classic segment"); result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK && result.classic_data); CHECK(snprintf(path, sizeof(path), "%s/queue.0000001", root) < (int)sizeof(path)); CHECK(unlink(path) == 0); CHECK(qdaEngineWriteMarker(root, "queue", QDA_ENGINE_DISK) == RS_RET_OK); CHECK(qdaEngineWriteMarker(root, "queue", QDA_ENGINE_AUTO) == RS_RET_PARAM_ERROR); CHECK(qdaEngineWriteMarker(root, "queue", (qda_engine_mode_t)99) == RS_RET_PARAM_ERROR); result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK && result.reason == QDA_REASON_MARKER); /* A marker without state or segments records an empty former engine, not * a backlog. An explicit selector may therefore replace it for the next * materialization; the data-conflict cases above and below must reject. */ result = resolve(root, QDA_ENGINE_SEGMENTED_DISK, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_SEGMENTED_DISK && result.reason == QDA_REASON_CONFIGURED); result = resolve(root, QDA_ENGINE_AUTO, 1, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_SEGMENTED_DISK && result.reason == QDA_REASON_AUTO_UPGRADE); /* Model a crash-left temporary marker from this process. The atomic * replacement helper must remove it, durably replace the live marker, and * leave no temporary name that could confuse a later restart. */ char tmp_name[128]; CHECK(snprintf(tmp_name, sizeof(tmp_name), "queue.da-engine.tmp.%ld", (long)getpid()) < (int)sizeof(tmp_name)); touch_file(root, tmp_name, "incomplete marker"); CHECK(qdaEngineWriteMarker(root, "queue", QDA_ENGINE_SEGMENTED_DISK) == RS_RET_OK); check_file_contents(root, "queue.da-engine", "RSYSLOG-DA-ENGINE-V1 segmentedDisk\n"); CHECK(snprintf(path, sizeof(path), "%s/%s", root, tmp_name) < (int)sizeof(path)); CHECK(access(path, F_OK) != 0); result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_SEGMENTED_DISK && result.marker_present); result = resolve(root, QDA_ENGINE_AUTO, 0, 1, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK && result.reason == QDA_REASON_CLASSIC_FEATURE); result = resolve(root, QDA_ENGINE_DISK, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_DISK && result.reason == QDA_REASON_CONFIGURED); CHECK(snprintf(path, sizeof(path), "%s/queue.segq", root) < (int)sizeof(path)); CHECK(mkdir(path, 0700) == 0); result = resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_OK); CHECK(result.effective == QDA_ENGINE_SEGMENTED_DISK && result.segmented_data); resolve(root, QDA_ENGINE_DISK, 0, 0, RS_RET_INVALID_VALUE); touch_file(root, "queue.1", "classic segment"); resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_INVALID_VALUE); CHECK(snprintf(path, sizeof(path), "%s/queue.1", root) < (int)sizeof(path)); CHECK(unlink(path) == 0); CHECK(snprintf(path, sizeof(path), "%s/queue.segq", root) < (int)sizeof(path)); CHECK(rmdir(path) == 0); touch_file(root, "queue.da-engine", "bad marker\n"); resolve(root, QDA_ENGINE_AUTO, 0, 0, RS_RET_INVALID_VALUE); CHECK(snprintf(path, sizeof(path), "%s/queue.da-engine", root) < (int)sizeof(path)); CHECK(unlink(path) == 0); CHECK(rmdir(root) == 0); puts("disk-assisted engine resolver tests passed"); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/linkedlist_test.c0000644000000000000000000000013215171370365020235 xustar0030 mtime=1776677109.472913557 30 atime=1783339715.351941103 30 ctime=1787067803.612896823 rsyslog-8.2608.0/tests/unit/linkedlist_test.c0000664000175000017500000001604115171370365017703 0ustar00rgerrger#include "config.h" #include #include #include #include "rsyslog.h" #include "linkedlist.h" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) struct destroy_counters { int data; int key; }; struct exec_state { int seen; int sum; int delete_value; }; static rsRetVal int_destructor(void *ptr) { free(ptr); return RS_RET_OK; } static rsRetVal counted_data_destructor(void *ptr) { struct destroy_counters *ctx = ptr; ctx->data++; return RS_RET_OK; } static rsRetVal counted_key_destructor(void *ptr) { struct destroy_counters *ctx = ptr; ctx->key++; return RS_RET_OK; } static int int_cmp(void *lhs, void *rhs) { const int l = *(int *)lhs; const int r = *(int *)rhs; return (l > r) - (l < r); } static rsRetVal exec_sum_or_delete(void *pData, void *pParam) { struct exec_state *state = pParam; const int value = *(int *)pData; state->seen++; state->sum += value; if (value == state->delete_value) { return RS_RET_OK_DELETE_LISTENTRY; } return RS_RET_OK; } static int *new_int(int value) { int *ptr = malloc(sizeof(*ptr)); if (ptr == NULL) { fprintf(stderr, "malloc failed\n"); exit(2); } *ptr = value; return ptr; } static int test_init_and_empty_state(void) { linkedList_t list; int count = -1; CHECK(llInit(&list, int_destructor, NULL, NULL) == RS_RET_OK); CHECK(list.pRoot == NULL); CHECK(list.pLast == NULL); CHECK(list.iNumElts == 0); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 0); CHECK(llDestroyRootElt(&list) == RS_RET_EMPTY_LIST); CHECK(llDestroy(&list) == RS_RET_OK); return 0; } static int test_append_iterate_and_count(void) { linkedList_t list; linkedListCookie_t cookie = NULL; void *data = NULL; int count = -1; CHECK(llInit(&list, int_destructor, NULL, NULL) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(1)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(2)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(3)) == RS_RET_OK); CHECK(list.pRoot != NULL); CHECK(list.pLast != NULL); CHECK(list.pRoot != list.pLast); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 3); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_OK); CHECK(*(int *)data == 1); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_OK); CHECK(*(int *)data == 2); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_OK); CHECK(*(int *)data == 3); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_END_OF_LINKEDLIST); CHECK(llDestroy(&list) == RS_RET_OK); CHECK(list.pRoot == NULL); CHECK(list.pLast == NULL); CHECK(list.iNumElts == 0); return 0; } static int test_destroy_root_variants(void) { linkedList_t list; int count = -1; CHECK(llInit(&list, int_destructor, NULL, NULL) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(11)) == RS_RET_OK); CHECK(llDestroyRootElt(&list) == RS_RET_OK); CHECK(list.pRoot == NULL); CHECK(list.pLast == NULL); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 0); CHECK(llAppend(&list, NULL, new_int(21)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(22)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(23)) == RS_RET_OK); CHECK(llDestroyRootElt(&list) == RS_RET_OK); CHECK(list.pRoot != NULL); CHECK(*(int *)list.pRoot->pData == 22); CHECK(*(int *)list.pLast->pData == 23); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 2); CHECK(llDestroy(&list) == RS_RET_OK); return 0; } static int test_find_and_delete_keyed_entries(void) { linkedList_t list; void *data = NULL; int count = -1; int key = 202; CHECK(llInit(&list, int_destructor, int_destructor, int_cmp) == RS_RET_OK); CHECK(llAppend(&list, new_int(101), new_int(1)) == RS_RET_OK); CHECK(llAppend(&list, new_int(202), new_int(2)) == RS_RET_OK); CHECK(llAppend(&list, new_int(303), new_int(3)) == RS_RET_OK); CHECK(llFind(&list, &key, &data) == RS_RET_OK); CHECK(*(int *)data == 2); CHECK(llFindAndDelete(&list, &key) == RS_RET_OK); CHECK(llFind(&list, &key, &data) == RS_RET_NOT_FOUND); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 2); CHECK(llDestroy(&list) == RS_RET_OK); return 0; } static int test_destroy_callbacks(void) { linkedList_t list; struct destroy_counters counters = {0}; CHECK(llInit(&list, counted_data_destructor, counted_key_destructor, NULL) == RS_RET_OK); CHECK(llAppend(&list, &counters, &counters) == RS_RET_OK); CHECK(llAppend(&list, &counters, &counters) == RS_RET_OK); CHECK(llDestroy(&list) == RS_RET_OK); CHECK(counters.data == 2); CHECK(counters.key == 2); return 0; } static int test_exec_func_delete_entry(void) { linkedList_t list; struct exec_state state = {.seen = 0, .sum = 0, .delete_value = 2}; void *data = NULL; linkedListCookie_t cookie = NULL; int count = -1; CHECK(llInit(&list, int_destructor, NULL, NULL) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(1)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(2)) == RS_RET_OK); CHECK(llAppend(&list, NULL, new_int(3)) == RS_RET_OK); CHECK(llExecFunc(&list, exec_sum_or_delete, &state) == RS_RET_OK); CHECK(state.seen == 3); CHECK(state.sum == 6); CHECK(llGetNumElts(&list, &count) == RS_RET_OK); CHECK(count == 2); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_OK); CHECK(*(int *)data == 1); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_OK); CHECK(*(int *)data == 3); CHECK(llGetNextElt(&list, &cookie, &data) == RS_RET_END_OF_LINKEDLIST); CHECK(llDestroy(&list) == RS_RET_OK); return 0; } int main(void) { struct { const char *name; int (*fn)(void); } tests[] = { {"init_and_empty_state", test_init_and_empty_state}, {"append_iterate_and_count", test_append_iterate_and_count}, {"destroy_root_variants", test_destroy_root_variants}, {"find_and_delete_keyed_entries", test_find_and_delete_keyed_entries}, {"destroy_callbacks", test_destroy_callbacks}, {"exec_func_delete_entry", test_exec_func_delete_entry}, }; size_t i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { if (tests[i].fn() != 0) { fprintf(stderr, "FAILED: %s\n", tests[i].name); return 1; } } printf("linkedlist tests passed (%zu cases)\n", sizeof(tests) / sizeof(tests[0])); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/msg_replace_test.c0000644000000000000000000000013215216464436020357 xustar0030 mtime=1782212894.089267203 30 atime=1783339715.351941103 30 ctime=1787067803.615896879 rsyslog-8.2608.0/tests/unit/msg_replace_test.c0000664000175000017500000000635215216464436020031 0ustar00rgerrger#include "config.h" #include #include #include #include "rsyslog.h" #include "msg_replace_helper.h" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) static int test_stack_to_heap_growth(void) { /* Replacing a stack-backed MSG with a longer value must preserve the suffix * after moving storage to the heap. The exact raw message content is the * oracle. */ static const uchar initialRawMsg[] = "prefix old suffix"; static const uchar replacement[] = "much longer replacement"; static const uchar expectedRawMsg[] = "prefix much longer replacement suffix"; uchar stackBuf[CONF_RAWMSG_BUFSIZE]; uchar *rawMsg = stackBuf; int lenRawMsg = sizeof(initialRawMsg) - 1; rsRetVal ret; memcpy(stackBuf, initialRawMsg, sizeof(initialRawMsg) - 1); ret = msgReplaceRawMsgSegment(&rawMsg, stackBuf, sizeof(stackBuf), sizeof("prefix ") - 1, sizeof("old") - 1, &lenRawMsg, replacement, sizeof(replacement) - 1); CHECK(ret == RS_RET_OK); CHECK(lenRawMsg == (int)sizeof(expectedRawMsg) - 1); CHECK(memcmp(rawMsg, expectedRawMsg, sizeof(expectedRawMsg) - 1) == 0); CHECK(memcmp(rawMsg + sizeof("prefix ") - 1 + sizeof(replacement) - 1, " suffix", sizeof(" suffix") - 1) == 0); if (rawMsg != stackBuf) { free(rawMsg); } return 0; } static int test_heap_realloc_growth(void) { /* Replacing a heap-backed MSG with a longer value must realloc when the new * length exceeds the current heap allocation even if it still fits inside * CONF_RAWMSG_BUFSIZE. The preserved suffix and final full raw message are * the oracle. */ static const uchar initialRawMsg[] = "prefix old suffix"; static const uchar replacement[] = "much longer replacement"; static const uchar expectedRawMsg[] = "prefix much longer replacement suffix"; uchar stackBuf[CONF_RAWMSG_BUFSIZE]; uchar *rawMsg = malloc(sizeof(initialRawMsg)); int lenRawMsg = sizeof(initialRawMsg) - 1; rsRetVal ret; CHECK(rawMsg != NULL); memcpy(rawMsg, initialRawMsg, sizeof(initialRawMsg) - 1); ret = msgReplaceRawMsgSegment(&rawMsg, stackBuf, sizeof(stackBuf), sizeof("prefix ") - 1, sizeof("old") - 1, &lenRawMsg, replacement, sizeof(replacement) - 1); CHECK(ret == RS_RET_OK); CHECK(lenRawMsg == (int)sizeof(expectedRawMsg) - 1); CHECK(memcmp(rawMsg, expectedRawMsg, sizeof(expectedRawMsg) - 1) == 0); CHECK(memcmp(rawMsg + sizeof("prefix ") - 1 + sizeof(replacement) - 1, " suffix", sizeof(" suffix") - 1) == 0); free(rawMsg); return 0; } int main(void) { int ret; ret = test_stack_to_heap_growth(); if (ret != 0) { return ret; } return test_heap_realloc_growth(); } rsyslog-8.2608.0/tests/unit/PaxHeaders/README.md0000644000000000000000000000013215171370365016147 xustar0030 mtime=1776677109.472913557 30 atime=1782715518.897790693 30 ctime=1787067803.668897866 rsyslog-8.2608.0/tests/unit/README.md0000664000175000017500000000267515171370365015625 0ustar00rgerrger# Unit Tests This directory contains source files and notes for fast C unit tests covering small, isolated rsyslog-owned helpers. ## Scope - `tests/` is the single Automake-owned test subtree for the project. - `tests/unit/` organizes in-process unit-test sources that do not require daemon startup, `diag.sh`, module loading, or the wider testbench runtime. - Unit tests should target helpers that can be exercised directly with explicit inputs and local state. - Keep source organization here, but do not add a separate `tests/unit` Automake harness. In recursive Automake trees, a second test-owning subdir makes top-level `make check TESTS=...` selection brittle. ## Build and run From the repository root: ```sh make check ``` This runs the unit tests together with the rest of the Automake test suite. To run one unit test binary through the shared harness from the repository root: ```sh make check TESTS='runtime_unit_linkedlist' ``` ## Conventions - Prefer one test binary per production helper or component. - Keep tests self-contained and deterministic. - Do not depend on `tests/diag.sh` or the shell testbench helpers here. - Keep `tests/` as the only recursive test-owning subtree. Organize sources under `tests/unit/` rather than introducing a second Automake test harness. - Avoid broad runtime stubbing. If a candidate needs substantial global runtime setup, it probably belongs in integration coverage instead of `tests/unit/`. rsyslog-8.2608.0/tests/unit/PaxHeaders/imbeats_parser_test.c0000644000000000000000000000013215241075234021066 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.695579979 30 ctime=1787067803.605896692 rsyslog-8.2608.0/tests/unit/imbeats_parser_test.c0000664000175000017500000002765515241075234020551 0ustar00rgerrger/* * Exercise imbeats' transport-independent Lumberjack parser resource and * framing invariants. The deterministic oracle is the parser return code, * parsed event content, and an exact reserve/release balance after batch * cleanup; no timing or live listener behavior is involved. */ #include "config.h" #include #include #include #include #include #include #include "rsyslog.h" #include "plugins/imbeats/lj_parser.h" /* Compile the parser into this test translation unit. Keeping all test * sources below tests/ avoids Automake dependency-file paths that are not * portable to older make versions, while still exercising production code. */ #include "../../plugins/imbeats/lj_parser.c" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) struct resource_account_s { size_t current; size_t peak; size_t reserved; size_t released; size_t limit; }; static rsRetVal reserve_bytes(void *const ctx, const size_t bytes) { struct resource_account_s *const account = ctx; if (bytes > account->limit - account->current) { return RS_RET_OUT_OF_MEMORY; } account->current += bytes; account->reserved += bytes; if (account->current > account->peak) account->peak = account->current; return RS_RET_OK; } static void release_bytes(void *const ctx, const size_t bytes) { struct resource_account_s *const account = ctx; if (bytes > account->current) { fprintf(stderr, "resource accounting underflow: current=%zu release=%zu\n", account->current, bytes); abort(); } account->current -= bytes; account->released += bytes; } static rsRetVal init_batch(struct lj_batch_s *const batch, struct resource_account_s *const account, const uint32_t window_size, const size_t max_payload_len) { memset(account, 0, sizeof(*account)); account->limit = SIZE_MAX; return lj_batch_alloc(batch, window_size, window_size, max_payload_len, reserve_bytes, release_bytes, account); } static size_t put_json_frame(unsigned char *const dst, const uint32_t seq, const unsigned char *const payload, const size_t payload_len) { const uint32_t net_seq = htonl(seq); const uint32_t net_len = htonl((uint32_t)payload_len); dst[0] = LJ_VERSION_V2; dst[1] = LJ_FRAME_JSON; memcpy(dst + 2, &net_seq, sizeof(net_seq)); memcpy(dst + 6, &net_len, sizeof(net_len)); memcpy(dst + 10, payload, payload_len); return 10 + payload_len; } static int compress_bytes(const unsigned char *const input, const size_t input_len, unsigned char **const output, size_t *const output_len) { uLongf compressed_len = compressBound(input_len); *output = malloc(compressed_len); if (*output == NULL) return 1; if (compress2(*output, &compressed_len, input, input_len, Z_BEST_COMPRESSION) != Z_OK) { free(*output); *output = NULL; return 1; } *output_len = compressed_len; return 0; } static int test_lazy_allocation_and_cleanup(void) { struct lj_batch_s batch; struct resource_account_s account; static const unsigned char payload[] = "one"; const size_t descriptor_bytes = 3 * sizeof(struct lj_event_s); CHECK(init_batch(&batch, &account, 3, 64) == RS_RET_OK); CHECK(batch.events == NULL); CHECK(account.current == 0); CHECK(lj_append_json_event(&batch, 1, payload, sizeof(payload) - 1) == RS_RET_OK); CHECK(batch.events_capacity == 3); CHECK(batch.events_alloc_len == descriptor_bytes); CHECK(batch.events[0].payload_alloc_len == sizeof(payload)); CHECK(account.current == descriptor_bytes + sizeof(payload)); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); return 0; } static int test_budget_rejection_is_balanced(void) { struct lj_batch_s batch; struct resource_account_s account; static const unsigned char payload[] = "budget"; const size_t descriptor_bytes = sizeof(struct lj_event_s); CHECK(init_batch(&batch, &account, 1, 64) == RS_RET_OK); account.limit = descriptor_bytes + sizeof(payload) - 1; CHECK(lj_append_json_event(&batch, 1, payload, sizeof(payload) - 1) == RS_RET_OUT_OF_MEMORY); CHECK(batch.count == 0); CHECK(account.current == descriptor_bytes); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); return 0; } static int test_owned_transfer_and_failure_contract(void) { struct lj_batch_s batch; struct resource_account_s account; unsigned char *owned; unsigned char *rejected; const size_t alloc_len = 6; CHECK(init_batch(&batch, &account, 1, 64) == RS_RET_OK); CHECK(reserve_bytes(&account, alloc_len) == RS_RET_OK); owned = malloc(alloc_len); CHECK(owned != NULL); memcpy(owned, "owned", alloc_len); CHECK(lj_append_json_event_owned(&batch, 9, owned, 5, alloc_len) == RS_RET_OK); CHECK(batch.events[0].payload == owned); CHECK(batch.events[0].payload_alloc_len == alloc_len); CHECK(reserve_bytes(&account, 2) == RS_RET_OK); rejected = malloc(2); CHECK(rejected != NULL); memcpy(rejected, "x", 2); CHECK(lj_append_json_event_owned(&batch, 10, rejected, 1, 2) == RS_RET_INVALID_VALUE); /* Failure retains caller ownership, so this free is required and is also * the oracle that the parser did not consume the second allocation. */ free(rejected); release_bytes(&account, 2); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); return 0; } static int test_valid_compressed_batch(void) { struct lj_batch_s batch; struct resource_account_s account; unsigned char frames[128]; unsigned char *compressed = NULL; size_t frames_len = 0; size_t compressed_len = 0; frames_len += put_json_frame(frames + frames_len, 1, (const unsigned char *)"{\"a\":1}", 7); frames_len += put_json_frame(frames + frames_len, 2, (const unsigned char *)"{\"b\":2}", 7); CHECK(compress_bytes(frames, frames_len, &compressed, &compressed_len) == 0); CHECK(init_batch(&batch, &account, 2, 128) == RS_RET_OK); CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 128, 4096, 64) == RS_RET_OK); CHECK(batch.count == 2); CHECK(batch.events[0].seq == 1 && batch.events[1].seq == 2); CHECK(memcmp(batch.events[0].payload, "{\"a\":1}", 7) == 0); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); /* A stream ending at the exact decompressed-size limit must consume its * zlib trailer and terminate. Success is the oracle against a boundary * spin or an off-by-one rejection. */ CHECK(init_batch(&batch, &account, 2, 128) == RS_RET_OK); CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 128, frames_len, 64) == RS_RET_OK); CHECK(batch.count == 2); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); CHECK(init_batch(&batch, &account, 2, 128) == RS_RET_OK); compressed = realloc(compressed, compressed_len + 1); CHECK(compressed != NULL); compressed[compressed_len++] = 0; CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 128, 4096, 64) == RS_RET_INVALID_VALUE); free(compressed); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); return 0; } static int test_high_ratio_and_scratch_budget_rejection(void) { struct lj_batch_s batch; struct resource_account_s account; unsigned char *frames; unsigned char *compressed = NULL; unsigned char payload[8192]; size_t compressed_len = 0; const size_t frames_len = sizeof(payload) + 10; memset(payload, 'A', sizeof(payload)); frames = malloc(frames_len); CHECK(frames != NULL); CHECK(put_json_frame(frames, 1, payload, sizeof(payload)) == frames_len); CHECK(compress_bytes(frames, frames_len, &compressed, &compressed_len) == 0); free(frames); CHECK(frames_len > compressed_len * 2); CHECK(init_batch(&batch, &account, 1, 16384) == RS_RET_OK); CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 16384, 16384, 2) == RS_RET_INVALID_VALUE); CHECK(batch.count == 0); CHECK(account.current == 0); lj_batch_free(&batch); CHECK(init_batch(&batch, &account, 1, 16384) == RS_RET_OK); account.limit = 32; CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 16384, 16384, 1000) == RS_RET_OUT_OF_MEMORY); CHECK(batch.count == 0); CHECK(account.current == 0); free(compressed); lj_batch_free(&batch); CHECK(account.reserved == account.released); return 0; } static int expect_invalid_compressed(const unsigned char *const frames, const size_t frames_len) { struct lj_batch_s batch; struct resource_account_s account; unsigned char *compressed = NULL; size_t compressed_len = 0; CHECK(compress_bytes(frames, frames_len, &compressed, &compressed_len) == 0); CHECK(init_batch(&batch, &account, 2, 128) == RS_RET_OK); CHECK(lj_parse_compressed_frames(&batch, compressed, compressed_len, 128, 4096, 128) == RS_RET_INVALID_VALUE); free(compressed); lj_batch_free(&batch); CHECK(account.current == 0); CHECK(account.reserved == account.released); return 0; } static int test_truncation_and_invalid_framing(void) { static const unsigned char invalid_version[] = {'1', LJ_FRAME_JSON}; static const unsigned char nested[] = {LJ_VERSION_V2, LJ_FRAME_COMPRESSED}; unsigned char valid[32]; unsigned char valid_with_trailing[32]; size_t valid_len; size_t prefix_len; valid_len = put_json_frame(valid, 1, (const unsigned char *)"{}", 2); /* Every strict prefix is a distinct truncated-frame boundary. Each must * fail, while test_valid_compressed_batch supplies the positive control. */ for (prefix_len = 0; prefix_len < valid_len; ++prefix_len) { CHECK(expect_invalid_compressed(valid, prefix_len) == 0); } CHECK(expect_invalid_compressed(invalid_version, sizeof(invalid_version)) == 0); CHECK(expect_invalid_compressed(nested, sizeof(nested)) == 0); valid_len = put_json_frame(valid_with_trailing, 1, (const unsigned char *)"{}", 2); valid_with_trailing[valid_len++] = LJ_VERSION_V2; CHECK(expect_invalid_compressed(valid_with_trailing, valid_len) == 0); return 0; } int main(void) { struct { const char *name; int (*fn)(void); } tests[] = { {"lazy_allocation_and_cleanup", test_lazy_allocation_and_cleanup}, {"budget_rejection_is_balanced", test_budget_rejection_is_balanced}, {"owned_transfer_and_failure_contract", test_owned_transfer_and_failure_contract}, {"valid_compressed_batch", test_valid_compressed_batch}, {"high_ratio_and_scratch_budget_rejection", test_high_ratio_and_scratch_budget_rejection}, {"truncation_and_invalid_framing", test_truncation_and_invalid_framing}, }; size_t i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { if (tests[i].fn() != 0) { fprintf(stderr, "FAILED: %s\n", tests[i].name); return 1; } } printf("imbeats parser tests passed (%zu cases)\n", sizeof(tests) / sizeof(tests[0])); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/ommongodb_date_test.c0000644000000000000000000000013215241075234021044 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.696579998 30 ctime=1787067803.619896953 rsyslog-8.2608.0/tests/unit/ommongodb_date_test.c0000664000175000017500000000434015241075234020511 0ustar00rgerrger#include "config.h" /* Verify ommongodb's ISODate parser preserves BSON millisecond precision. * The oracle is direct epoch-millisecond comparison for UTC, numeric-offset, * fractional-second, legacy :UTC, and invalid-input cases. */ #include #include #include "ommongodb_date.h" /* * Pull the implementation into this test translation unit so Automake does not * need to manage dependency files for sources outside tests/ during distcheck. */ #include "../../plugins/ommongodb/ommongodb_date.c" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) static int expect_date(const char *date, int64_t expected) { int64_t actual; actual = -1; CHECK(ommongodbParseIsoDateMs(date, &actual) == 1); CHECK(actual == expected); return 0; } static int expect_invalid(const char *date) { int64_t actual; actual = -1; CHECK(ommongodbParseIsoDateMs(date, &actual) == 0); CHECK(actual == -1); return 0; } int main(void) { CHECK(expect_date("2019-10-20T12:00:19Z", 1571572819000LL) == 0); CHECK(expect_date("2019-10-20T12:00:19.1Z", 1571572819100LL) == 0); CHECK(expect_date("2019-10-20T12:00:19.123Z", 1571572819123LL) == 0); CHECK(expect_date("2019-10-20T12:00:19.123456Z", 1571572819123LL) == 0); CHECK(expect_date("2019-10-20T12:00:19.123+02:00", 1571565619123LL) == 0); CHECK(expect_date("2019-10-20T12:00:19.123+0200", 1571565619123LL) == 0); CHECK(expect_date("2019-10-20T12:00:19:UTC", 1571572819000LL) == 0); CHECK(expect_invalid("2019-10-20T12:00:19.Z") == 0); CHECK(expect_invalid("2019-02-29T12:00:19Z") == 0); CHECK(expect_invalid("2019-10-20T12:00:19") == 0); CHECK(expect_invalid("2019") == 0); CHECK(expect_invalid("2019-10-20T12:00:19U") == 0); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/impcap_arp_parser_test.c0000644000000000000000000000013215241075234021555 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.695579979 30 ctime=1787067803.610896785 rsyslog-8.2608.0/tests/unit/impcap_arp_parser_test.c0000664000175000017500000002075115241075234021226 0ustar00rgerrger/* Regression test for contrib/impcap ARP/RARP address-length handling. * * impcap is optional and only exposes this path when configured to process * captured L2 traffic. Malformed ARP/RARP frames can still be attacker-provided * on such interfaces, so the parser must not trust packet-controlled * hwAddrLen/pAddrLen fields to form offsets beyond the captured packet. * * The malformed cases below use minimal captured ARP/RARP payloads with either * oversized address lengths or Ethernet/IPv4 lengths that are too short for the * fixed-width address converters. Before the fix, guard-page mode made the real * parser crash while converting the destination Ethernet address. The oracle * here is that malformed packets return without address metadata, while a * normal Ethernet/IPv4 ARP and RARP packet still produces the expected parsed * fields. The demonstrated impact is crash/DoS; this test does not claim code * execution or information disclosure. */ #define _GNU_SOURCE #include "config.h" #include #include #include #include #include #include #include "contrib/impcap/parsers.h" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ exit(1); \ } \ } while (0) int Debug = 0; void r_dbgprintf(const char *srcname, const char *fmt, ...) { (void)srcname; (void)fmt; } static void set_u16(unsigned char *packet, size_t off, unsigned value) { packet[off] = (unsigned char)(value >> 8); packet[off + 1] = (unsigned char)value; } static void fill_arp_header(unsigned char *packet, unsigned opCode) { memset(packet, 0, 28); set_u16(packet, 0, 1); /* hardware type: Ethernet */ set_u16(packet, 2, ETHERTYPE_IP); /* protocol type: IPv4 */ packet[4] = 6; /* Ethernet address length */ packet[5] = 4; /* IPv4 address length */ set_u16(packet, 6, opCode); } static void fill_valid_arp(unsigned char *packet, unsigned opCode) { fill_arp_header(packet, opCode); const unsigned char hwSrc[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; const unsigned char pSrc[4] = {192, 0, 2, 1}; const unsigned char hwDst[6] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; const unsigned char pDst[4] = {198, 51, 100, 2}; memcpy(packet + 8, hwSrc, sizeof(hwSrc)); memcpy(packet + 14, pSrc, sizeof(pSrc)); memcpy(packet + 18, hwDst, sizeof(hwDst)); memcpy(packet + 24, pDst, sizeof(pDst)); } static void fill_malformed_arp(unsigned char *packet) { fill_arp_header(packet, 1); packet[4] = 250; /* attacker-controlled length exceeds captured packet */ } static long guarded_page_size(void) { const long page = sysconf(_SC_PAGESIZE); CHECK(page > 28); return page; } static unsigned char *make_guarded_malformed_packet(void) { const long page = guarded_page_size(); unsigned char *map = mmap(NULL, (size_t)page * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); CHECK(map != MAP_FAILED); CHECK(mprotect(map + page, (size_t)page, PROT_NONE) == 0); unsigned char *packet = map + page - 28; fill_malformed_arp(packet); return packet; } static void free_guarded_packet(unsigned char *packet) { const long page = guarded_page_size(); unsigned char *map = packet + 28 - page; CHECK(munmap(map, (size_t)page * 2) == 0); } static int object_has_key(struct json_object *obj, const char *key) { struct json_object *tmp = NULL; return json_object_object_get_ex(obj, key, &tmp); } static void check_json_string(struct json_object *obj, const char *key, const char *expected) { struct json_object *value = NULL; CHECK(json_object_object_get_ex(obj, key, &value)); const char *actual = json_object_get_string(value); if (strcmp(actual, expected) != 0) { fprintf(stderr, "%s: expected '%s', got '%s'\n", key, expected, actual); exit(1); } } static void check_no_address_fields(struct json_object *obj, const char *prefix) { char key[32]; snprintf(key, sizeof(key), "%s_hwSrc", prefix); CHECK(!object_has_key(obj, key)); snprintf(key, sizeof(key), "%s_hwDst", prefix); CHECK(!object_has_key(obj, key)); snprintf(key, sizeof(key), "%s_pSrc", prefix); CHECK(!object_has_key(obj, key)); snprintf(key, sizeof(key), "%s_pDst", prefix); CHECK(!object_has_key(obj, key)); } typedef data_ret_t *(*arp_test_parser_t)(const uchar *, int, struct json_object *); static void run_short_fixed_width_length_case( arp_test_parser_t parse, const char *prefix, unsigned opCode, unsigned hwAddrLen, unsigned pAddrLen) { unsigned char packet[28]; struct json_object *j = json_object_new_object(); CHECK(j != NULL); fill_valid_arp(packet, opCode); packet[4] = (unsigned char)hwAddrLen; packet[5] = (unsigned char)pAddrLen; data_ret_t *ret = parse(packet, sizeof(packet), j); CHECK(ret != NULL); CHECK(ret->size == 0); free(ret); check_no_address_fields(j, prefix); json_object_put(j); } static void test_malformed_lengths_do_not_parse_addresses(void) { unsigned char *packet = make_guarded_malformed_packet(); struct json_object *j = json_object_new_object(); CHECK(j != NULL); data_ret_t *ret = arp_parse(packet, 28, j); CHECK(ret != NULL); CHECK(ret->size == 0); free(ret); CHECK(object_has_key(j, "ARP_hwType")); CHECK(object_has_key(j, "ARP_pType")); CHECK(object_has_key(j, "ARP_op")); CHECK(!object_has_key(j, "ARP_hwSrc")); CHECK(!object_has_key(j, "ARP_hwDst")); CHECK(!object_has_key(j, "ARP_pSrc")); CHECK(!object_has_key(j, "ARP_pDst")); json_object_put(j); free_guarded_packet(packet); } static void test_malformed_rarp_lengths_do_not_parse_addresses(void) { unsigned char *packet = make_guarded_malformed_packet(); struct json_object *j = json_object_new_object(); CHECK(j != NULL); data_ret_t *ret = rarp_parse(packet, 28, j); CHECK(ret != NULL); CHECK(ret->size == 0); free(ret); CHECK(object_has_key(j, "RARP_hwType")); CHECK(object_has_key(j, "RARP_pType")); CHECK(object_has_key(j, "RARP_op")); CHECK(!object_has_key(j, "RARP_hwSrc")); CHECK(!object_has_key(j, "RARP_hwDst")); CHECK(!object_has_key(j, "RARP_pSrc")); CHECK(!object_has_key(j, "RARP_pDst")); json_object_put(j); free_guarded_packet(packet); } static void test_short_fixed_width_lengths_do_not_parse_addresses(void) { run_short_fixed_width_length_case(arp_parse, "ARP", 1, 5, 4); run_short_fixed_width_length_case(arp_parse, "ARP", 1, 6, 3); run_short_fixed_width_length_case(rarp_parse, "RARP", 3, 5, 4); run_short_fixed_width_length_case(rarp_parse, "RARP", 3, 6, 3); } static void test_valid_arp_still_parses_addresses(void) { unsigned char packet[28]; struct json_object *j = json_object_new_object(); CHECK(j != NULL); fill_valid_arp(packet, 1); data_ret_t *ret = arp_parse(packet, sizeof(packet), j); CHECK(ret != NULL); CHECK(ret->size == 0); free(ret); check_json_string(j, "ARP_hwSrc", "0:11:22:33:44:55"); check_json_string(j, "ARP_hwDst", "aa:bb:cc:dd:ee:ff"); check_json_string(j, "ARP_pSrc", "192.0.2.1"); check_json_string(j, "ARP_pDst", "198.51.100.2"); json_object_put(j); } static void test_valid_rarp_still_parses_addresses(void) { unsigned char packet[28]; struct json_object *j = json_object_new_object(); CHECK(j != NULL); fill_valid_arp(packet, 3); data_ret_t *ret = rarp_parse(packet, sizeof(packet), j); CHECK(ret != NULL); CHECK(ret->size == 0); free(ret); check_json_string(j, "RARP_hwSrc", "0:11:22:33:44:55"); check_json_string(j, "RARP_hwDst", "aa:bb:cc:dd:ee:ff"); check_json_string(j, "RARP_pSrc", "192.0.2.1"); check_json_string(j, "RARP_pDst", "198.51.100.2"); json_object_put(j); } #include "../../contrib/impcap/arp_parser.c" int main(void) { test_malformed_lengths_do_not_parse_addresses(); test_malformed_rarp_lengths_do_not_parse_addresses(); test_short_fixed_width_lengths_do_not_parse_addresses(); test_valid_arp_still_parses_addresses(); test_valid_rarp_still_parses_addresses(); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/segdisk_state_test.c0000644000000000000000000000013215241075234020717 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.696579998 30 ctime=1787067803.626897084 rsyslog-8.2608.0/tests/unit/segdisk_state_test.c0000664000175000017500000001144215241075234020365 0ustar00rgerrger/* * Unit coverage for the segmentedDisk two-slot state selector. The oracle is * exact slot selection or rejection for CRC, version, UUID, and wraparound * generation cases; no filesystem or daemon timing is involved. */ #include "config.h" #include #include #include #include #include "segdisk_crc.h" #include "segdisk_state.h" /* Keep the unit binary's dependency files in the test-owning subtree. This * also avoids recursive distclean ordering dependencies on runtime/.deps. */ #include "../../runtime/segdisk_crc.c" #include "../../runtime/segdisk_state.c" #define CHECK(condition) \ do { \ if (!(condition)) { \ fprintf(stderr, "CHECK failed at %s:%d: %s\n", __FILE__, __LINE__, #condition); \ exit(1); \ } \ } while (0) static void repair_crc(unsigned char slot[SEGDISK_STATE_SLOT_LEN]) { const uint32_t crc = segdiskCrc32c(slot, SEGDISK_STATE_SLOT_LEN - 4); slot[SEGDISK_STATE_SLOT_LEN - 4] = (unsigned char)(crc >> 24); slot[SEGDISK_STATE_SLOT_LEN - 3] = (unsigned char)(crc >> 16); slot[SEGDISK_STATE_SLOT_LEN - 2] = (unsigned char)(crc >> 8); slot[SEGDISK_STATE_SLOT_LEN - 1] = (unsigned char)crc; } static void init_state(segdisk_state_image_t *state, unsigned char uuid_byte) { memset(state, 0, sizeof(*state)); memset(state->uuid, uuid_byte, sizeof(state->uuid)); state->committed_offset = 52; state->next_segment = 1; state->delete_first = 2; state->delete_last = 4; state->delete_bytes = 12345; state->delete_segments = 3; } static void expect_selected(const unsigned char slot0[SEGDISK_STATE_SLOT_LEN], const unsigned char slot1[SEGDISK_STATE_SLOT_LEN], int expected) { segdisk_state_image_t selected; int selected_slot = -1; CHECK(segdiskStateSelect(slot0, 1, slot1, 1, &selected, &selected_slot) == RS_RET_OK); CHECK(selected_slot == expected); CHECK(selected.delete_first == 2); CHECK(selected.delete_last == 4); CHECK(selected.delete_bytes == 12345); CHECK(selected.delete_segments == 3); } int main(void) { /* RFC 3720's canonical CRC32C vector detects polynomial, reflection, and * lookup-table regressions independently of the state-slot test data. The * empty, zero, ramp, and 32-KiB patterned vectors also cover table-index * boundaries and the large-message path used by queue records. */ CHECK(segdiskCrc32c("123456789", 9) == UINT32_C(0xe3069283)); CHECK(segdiskCrc32c("", 0) == UINT32_C(0)); unsigned char vector[32768] = {0}; CHECK(segdiskCrc32c(vector, 32) == UINT32_C(0x8a9136aa)); for (size_t i = 0; i < 256; ++i) vector[i] = (unsigned char)i; CHECK(segdiskCrc32c(vector, 256) == UINT32_C(0x9c44184b)); for (size_t i = 0; i < sizeof(vector); ++i) vector[i] = (unsigned char)(i * 37 + 11); CHECK(segdiskCrc32c(vector, sizeof(vector)) == UINT32_C(0xff0064c4)); segdisk_state_image_t state; unsigned char slot0[SEGDISK_STATE_SLOT_LEN]; unsigned char slot1[SEGDISK_STATE_SLOT_LEN]; init_state(&state, 0x11); segdiskStateEncode(&state, 10, slot0); segdiskStateEncode(&state, 11, slot1); expect_selected(slot0, slot1, 1); slot1[200] ^= 1; expect_selected(slot0, slot1, 0); slot0[201] ^= 1; CHECK(segdiskStateSelect(slot0, 1, slot1, 1, &state, NULL) == RS_RET_INVALID_VALUE); segdiskStateEncode(&state, UINT64_MAX, slot0); segdiskStateEncode(&state, 0, slot1); expect_selected(slot0, slot1, 1); segdiskStateEncode(&state, 0, slot0); segdiskStateEncode(&state, UINT64_C(1) << 63, slot1); CHECK(segdiskStateSelect(slot0, 1, slot1, 1, &state, NULL) == RS_RET_INVALID_VALUE); segdiskStateEncode(&state, 20, slot0); segdiskStateEncode(&state, 21, slot1); slot1[8] = 0; slot1[9] = 1; repair_crc(slot1); expect_selected(slot0, slot1, 0); segdiskStateEncode(&state, 21, slot1); slot1[10] = 0; slot1[11] ^= 1; repair_crc(slot1); expect_selected(slot0, slot1, 0); segdiskStateEncode(&state, 21, slot1); slot1[12] ^= 1; /* Recalculate the CRC by encoding a second valid image with another UUID. */ segdisk_state_image_t other = state; memset(other.uuid, 0x22, sizeof(other.uuid)); segdiskStateEncode(&other, 21, slot1); CHECK(segdiskStateSelect(slot0, 1, slot1, 1, &state, NULL) == RS_RET_INVALID_VALUE); puts("segmentedDisk state-slot tests passed"); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/stringbuf_test.c0000644000000000000000000000013215241075234020071 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.800581945 30 ctime=1787067803.628897121 rsyslog-8.2608.0/tests/unit/stringbuf_test.c0000664000175000017500000002141015241075234017533 0ustar00rgerrger#include "config.h" #include #include #include #include #include "rsyslog.h" #include "obj.h" #include "srUtils.h" #include "stringbuf.h" #include "unicode-helper.h" #define CHECK(cond) \ do { \ if (!(cond)) { \ fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, __LINE__, #cond); \ return 1; \ } \ } while (0) void LogError(const int iErrno __attribute__((unused)), const int iErrCode __attribute__((unused)), const char *fmt __attribute__((unused)), ...) {} rsRetVal objGetObjInterface(obj_if_t *pIf) { memset(pIf, 0, sizeof(*pIf)); return RS_RET_OK; } rsRetVal srUtilItoA(char *pBuf, int iLenBuf, number_t iToConv) { int r = snprintf(pBuf, iLenBuf, "%lld", (long long)iToConv); /* Keep the stub strict: truncation and rare encoding errors are both failures. */ return (r < 0 || r >= iLenBuf) ? RS_RET_INVALID_VALUE : RS_RET_OK; } /* * Pull the implementation into this test translation unit so Automake does not * need to manage dependency files for sources outside tests/ during distcheck. */ #include "../../runtime/stringbuf.c" #include "../../compat/asprintf.c" static int test_append_parts(void) { cstr_t *str = NULL; uchar *buf = NULL; const rs_cstr_part_t parts[] = { {(const uchar *)"alpha", strlen("alpha")}, {(const uchar *)"", 0}, {(const uchar *)"-", 1}, {(const uchar *)"beta", strlen("beta")}, }; CHECK(rsCStrConstruct(&str) == RS_RET_OK); CHECK(rsCStrAppendParts(str, parts, sizeof(parts) / sizeof(parts[0])) == RS_RET_OK); cstrFinalize(str); CHECK(cstrConvSzStrAndDestruct(&str, &buf, 0) == RS_RET_OK); CHECK(strcmp((char *)buf, "alpha-beta") == 0); free(buf); CHECK(rsCStrConstruct(&str) == RS_RET_OK); CHECK(rsCStrAppendParts(str, NULL, 0) == RS_RET_OK); cstrFinalize(str); CHECK(cstrConvSzStrAndDestruct(&str, &buf, 0) == RS_RET_OK); CHECK(strcmp((char *)buf, "") == 0); free(buf); return 0; } static int test_vasprintf_helper(char **buf, const char *fmt, ...) #if defined(__GNUC__) __attribute__((format(printf, 2, 3))) #endif ; static int test_vasprintf_helper(char **buf, const char *fmt, ...) { va_list ap; int ret; va_start(ap, fmt); ret = vasprintf(buf, fmt, ap); va_end(ap); return ret; } static int test_asprintf_compat(void) { char *buf = NULL; CHECK(asprintf(&buf, "%s:%d", "value", 42) == (int)strlen("value:42")); CHECK(strcmp(buf, "value:42") == 0); free(buf); buf = NULL; CHECK(test_vasprintf_helper(&buf, "%s/%s", "left", "right") == (int)strlen("left/right")); CHECK(strcmp(buf, "left/right") == 0); free(buf); return 0; } static int test_cstr_copy_helper(void) { char dst[5]; char raw_src[5] = {'a', 'b', 'c', 'd', 'e'}; uchar udst[4]; uchar uraw_src[4] = {'x', 'y', 'z', 'w'}; CHECK(rs_cstr_copy(dst, "hi", sizeof(dst)) == 2); CHECK(strcmp(dst, "hi") == 0); CHECK(rs_cstr_copy(dst, "abcdef", sizeof(dst)) == sizeof(dst) - 1); CHECK(strcmp(dst, "abcd") == 0); CHECK(rs_cstr_copy(dst, raw_src, sizeof(dst)) == sizeof(dst) - 1); CHECK(memcmp(dst, "abcd", sizeof(dst) - 1) == 0); CHECK(dst[sizeof(dst) - 1] == '\0'); CHECK(u_cstr_copy(udst, (const uchar *)"ok", sizeof(udst)) == 2); CHECK(strcmp((char *)udst, "ok") == 0); CHECK(u_cstr_copy(udst, uraw_src, sizeof(udst)) == sizeof(udst) - 1); CHECK(memcmp(udst, "xyz", sizeof(udst) - 1) == 0); CHECK(udst[sizeof(udst) - 1] == '\0'); CHECK(rs_cstr_copy(dst, "ignored", 0) == 0); return 0; } static int test_empty_finalize_and_getsz(void) { cstr_t *str = NULL; CHECK(rsCStrConstruct(&str) == RS_RET_OK); cstrFinalize(str); CHECK(rsCStrLen(str) == 0); CHECK(strcmp((char *)rsCStrGetSzStrNoNULL(str), "") == 0); rsCStrDestruct(&str); CHECK(str == NULL); return 0; } static int test_destructive_convert_semantics(void) { cstr_t *str = NULL; uchar *buf = NULL; CHECK(rsCStrConstruct(&str) == RS_RET_OK); CHECK(rsCStrAppendStr(str, (uchar *)"ab") == RS_RET_OK); CHECK(cstrAppendChar(str, 'c') == RS_RET_OK); cstrFinalize(str); CHECK(cstrConvSzStrAndDestruct(&str, &buf, 0) == RS_RET_OK); CHECK(str == NULL); CHECK(strcmp((char *)buf, "abc") == 0); free(buf); CHECK(rsCStrConstruct(&str) == RS_RET_OK); cstrFinalize(str); CHECK(cstrConvSzStrAndDestruct(&str, &buf, 0) == RS_RET_OK); CHECK(str == NULL); CHECK(strcmp((char *)buf, "") == 0); free(buf); CHECK(rsCStrConstruct(&str) == RS_RET_OK); cstrFinalize(str); CHECK(cstrConvSzStrAndDestruct(&str, &buf, 1) == RS_RET_OK); CHECK(str == NULL); CHECK(buf == NULL); return 0; } static int test_setszstr_requires_finalize(void) { cstr_t *str = NULL; /* Empty non-NULL input must remain valid even when no backing buffer has * been allocated yet. UBSan rejects passing that NULL buffer to memcpy, * including when the requested copy length is zero. */ CHECK(rsCStrConstruct(&str) == RS_RET_OK); CHECK(rsCStrSetSzStr(str, (uchar *)"") == RS_RET_OK); cstrFinalize(str); CHECK(rsCStrLen(str) == 0); CHECK(strcmp((char *)rsCStrGetSzStrNoNULL(str), "") == 0); CHECK(rsCStrSetSzStr(str, (uchar *)"new-value") == RS_RET_OK); cstrFinalize(str); CHECK(rsCStrLen(str) == strlen("new-value")); CHECK(strcmp((char *)rsCStrGetSzStrNoNULL(str), "new-value") == 0); /* Reusing the allocated buffer for an empty string must not expose the * previous value through the NUL-terminated string view. */ CHECK(rsCStrSetSzStr(str, (uchar *)"") == RS_RET_OK); cstrFinalize(str); CHECK(rsCStrLen(str) == 0); CHECK(strcmp((char *)rsCStrGetSzStrNoNULL(str), "") == 0); CHECK(rsCStrSetSzStr(str, NULL) == RS_RET_OK); cstrFinalize(str); CHECK(rsCStrLen(str) == 0); CHECK(strcmp((char *)rsCStrGetSzStrNoNULL(str), "") == 0); rsCStrDestruct(&str); return 0; } static int test_locate_in_szstr_basic_cases(void) { cstr_t *needle = NULL; CHECK(rsCStrConstructFromszStr(&needle, (uchar *)"needle") == RS_RET_OK); CHECK(rsCStrLocateInSzStr(needle, (uchar *)"hayneedlehay") == 3); CHECK(rsCStrLocateInSzStr(needle, (uchar *)"haystack") == -1); rsCStrDestruct(&needle); CHECK(rsCStrConstruct(&needle) == RS_RET_OK); CHECK(rsCStrLocateInSzStr(needle, (uchar *)"anything") == 0); rsCStrDestruct(&needle); return 0; } static int test_locate_in_szstr_needle_longer_than_haystack(void) { cstr_t *needle = NULL; CHECK(rsCStrConstructFromszStr(&needle, (uchar *)"much-longer-needle") == RS_RET_OK); CHECK(rsCStrLocateInSzStr(needle, (uchar *)"short") == -1); rsCStrDestruct(&needle); return 0; } static int test_prefix_suffix_helpers(void) { cstr_t *pattern = NULL; CHECK(rsCStrConstructFromszStr(&pattern, (uchar *)"prefix") == RS_RET_OK); CHECK(rsCStrSzStrStartsWithCStr(pattern, (uchar *)"prefix-value", strlen("prefix-value")) == 0); CHECK(rsCStrSzStrStartsWithCStr(pattern, (uchar *)"value-prefix", strlen("value-prefix")) != 0); rsCStrDestruct(&pattern); CHECK(rsCStrConstructFromszStr(&pattern, (uchar *)".log") == RS_RET_OK); CHECK(rsCStrSzStrEndsWithCStr(pattern, (uchar *)"app.log", strlen("app.log")) == 0); CHECK(rsCStrSzStrEndsWithCStr(pattern, (uchar *)"app.txt", strlen("app.txt")) != 0); rsCStrDestruct(&pattern); return 0; } int main(void) { struct { const char *name; int (*fn)(void); } tests[] = { {"empty_finalize_and_getsz", test_empty_finalize_and_getsz}, {"destructive_convert_semantics", test_destructive_convert_semantics}, {"setszstr_requires_finalize", test_setszstr_requires_finalize}, {"locate_in_szstr_basic_cases", test_locate_in_szstr_basic_cases}, {"locate_in_szstr_needle_longer_than_haystack", test_locate_in_szstr_needle_longer_than_haystack}, {"prefix_suffix_helpers", test_prefix_suffix_helpers}, {"append_parts", test_append_parts}, {"asprintf_compat", test_asprintf_compat}, {"cstr_copy_helper", test_cstr_copy_helper}, }; size_t i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { if (tests[i].fn() != 0) { fprintf(stderr, "FAILED: %s\n", tests[i].name); return 1; } } printf("stringbuf tests passed (%zu cases)\n", sizeof(tests) / sizeof(tests[0])); return 0; } rsyslog-8.2608.0/tests/unit/PaxHeaders/imbeats_seq_test.c0000644000000000000000000000013115241075234020361 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.695579979 29 ctime=1787067803.60789673 rsyslog-8.2608.0/tests/unit/imbeats_seq_test.c0000664000175000017500000000256215241075234020033 0ustar00rgerrger#include "config.h" #include #include #include #include "plugins/imbeats/seqnum.h" static void expect_seq(const uint32_t lastAckedSeq, const size_t batchIndex, const uint32_t actualSeq, const int expected, const char *const label) { const int actual = imbeats_seq_is_expected(lastAckedSeq, batchIndex, actualSeq); if (actual != expected) { fprintf(stderr, "%s: last=%u index=%zu actual=%u expected result=%d got=%d\n", label, lastAckedSeq, batchIndex, actualSeq, expected, actual); exit(1); } } int main(void) { /* The imbeats Lumberjack sequence check is intentionally uint32 modulo * arithmetic. These cases document the wraparound invariant without sending * a huge protocol batch to drive the live session state to UINT32_MAX. */ expect_seq(0, 0, 1, 1, "initial sequence"); expect_seq(1, 0, 2, 1, "next one-event batch"); expect_seq(1, 1, 3, 1, "second event in batch"); expect_seq(1, 0, 1, 0, "reset rejected"); expect_seq(UINT32_MAX, 0, 0, 1, "wrap from UINT32_MAX to zero"); expect_seq(UINT32_MAX - 1u, 0, UINT32_MAX, 1, "pre-wrap event"); expect_seq(UINT32_MAX - 1u, 1, 0, 1, "wrap within batch"); expect_seq(UINT32_MAX, 0, 1, 0, "wrap gap rejected"); return 0; } rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-checkpoint-1.sh0000644000000000000000000000013215241075234022473 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.780899953 rsyslog-8.2608.0/tests/segmented-diskqueue-checkpoint-1.sh0000775000175000017500000000033415241075234022142 0ustar00rgerrger#!/bin/bash # Verify checkpointInterval=1 publishes each single-record frontier advance. export CHECKPOINT_INTERVAL=1 export EXPECTED_PERIODIC_WRITES=12 . ${srcdir:=.}/testsuites/segmented-diskqueue-checkpoint-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/mmanon_ipv6_port.sh0000644000000000000000000000013215131231047017527 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.896790676 30 ctime=1787067805.765936943 rsyslog-8.2608.0/tests/mmanon_ipv6_port.sh0000777000175000017500000000342315131231047017202 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv6.anonmode="zero") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f:4024:d991:ec2e:4922 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f:4024:d991:ec2e <129>Mar 10 01:00:00 172.20.245.8 tag: [1a00:c820:1180:c84c:ad3f:4024:d991:ec2e]:4922 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f::d991:ec2e:4922 <129>Mar 10 01:00:00 172.20.245.8 tag: [1a00:c820:1180:c84c:ad3f::d991:ec2e]:4922 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:1180:c84c:ad3f::d991:ec2e:49225 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:4922:4922:c84c:ad3f::d991:ec2e:49225 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:4922:1180:c84c:ad3f::d991:4922:49225 <129>Mar 10 01:00:00 172.20.245.8 tag: 1a00:c820:49225:c84c:ad3f::d991:ec2e:49225\"" # see this github comment on limits of IP address detection: # https://github.com/rsyslog/rsyslog/issues/4856#issuecomment-1108445473 shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk 1a00:c820:0:0:0:0:0:0:4922 1a00:c820:0:0:0:0:0:0 [1a00:c820:0:0:0:0:0:0]:4922 1a00:c820:1180:0:0:0:0:0:0 [1a00:c820:0:0:0:0:0:0]:4922 1a00:c820:0:0:0:0:0:0:49225 1a00:4922:0:0:0:0:0:0:49225 1a00:4922:0:0:0:0:0:0:49225 1a00:c820:49225:c84c:0:0:0:0:0:0:49225' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-transactions.sh0000644000000000000000000000013215035412264020250 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.897790693 30 ctime=1787067806.079942794 rsyslog-8.2608.0/tests/omprog-transactions.sh0000777000175000017500000001001215035412264017713 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests omprog with the confirmMessages=on and useTransactions=on # parameters, with the external program successfully confirming all messages # and transactions. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh` template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process queue.dequeueBatchSize="6" confirmMessages="on" useTransactions="on" beginTransactionMark="BEGIN TRANSACTION" commitTransactionMark="COMMIT TRANSACTION" action.resumeRetryCount="10" action.resumeInterval="1" ) } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown # Since the transaction boundaries are not deterministic, we cannot check for # an exact expected output. We must check the output programmatically. transaction_state="NONE" status_expected=true messages_to_commit=() messages_processed=() line_num=1 error= while IFS= read -r line; do if [[ $status_expected == true ]]; then case "$transaction_state" in "NONE") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi ;; "STARTED") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi transaction_state="ACTIVE" ;; "ACTIVE") if [[ "$line" != "<= DEFER_COMMIT" ]]; then error="expecting a DEFER_COMMIT status from script" break fi ;; "COMMITTED") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi messages_processed+=("${messages_to_commit[@]}") messages_to_commit=() transaction_state="NONE" ;; esac status_expected=false; else if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then if [[ "$transaction_state" != "NONE" ]]; then error="unexpected transaction start" break fi transaction_state="STARTED" elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected transaction commit" break fi transaction_state="COMMITTED" else if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected message outside a transaction" break fi if [[ "$line" != "=> msgnum:"* ]]; then error="unexpected message contents" break fi prefix_to_remove="=> " messages_to_commit+=("${line#$prefix_to_remove}") fi status_expected=true; fi ((line_num++)) done < $RSYSLOG_OUT_LOG if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then error="unexpected end of file (transaction state: $transaction_state)" fi if [[ -n "$error" ]]; then echo "$RSYSLOG_OUT_LOG: line $line_num: $error" cat $RSYSLOG_OUT_LOG error_exit 1 fi expected_messages=( "msgnum:00000000:" "msgnum:00000001:" "msgnum:00000002:" "msgnum:00000003:" "msgnum:00000004:" "msgnum:00000005:" "msgnum:00000006:" "msgnum:00000007:" "msgnum:00000008:" "msgnum:00000009:" ) if [[ "${messages_processed[*]}" != "${expected_messages[*]}" ]]; then echo "unexpected set of processed messages:" printf '%s\n' "${messages_processed[@]}" echo "contents of $RSYSLOG_OUT_LOG:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-dynrestpath.sh0000644000000000000000000000013215131231047021167 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.896790676 30 ctime=1787067806.168944452 rsyslog-8.2608.0/tests/omhttp-batch-dynrestpath.sh0000777000175000017500000000203515131231047020640 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" omhttp_start_server 0 generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") template(name="dynrestpath" type="string" string="my/endpoint") module(load="../contrib/omhttp/.libs/omhttp") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" dynrestpath = "on" restpath="dynrestpath" batch="on" batch.format="jsonarray" batch.maxsize="1000" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_conflict1.sh0000644000000000000000000000013215241075234021750 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 30 ctime=1787067806.886957832 rsyslog-8.2608.0/tests/rscript_unflatten_conflict1.sh0000775000175000017500000000247015241075234021422 0ustar00rgerrger#!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $!a!b = "foo"; set $!a.b.c = "bar"; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "a": { "b": { "c": "bar" } } }' cmp_exact "$RSYSLOG_OUT_LOG" EXPECTED='fmunflatten.c: warning: while processing flat key "a.b.c" at depth #1 (intermediate node), overriding existing value of type string by an object' if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then echo "GREP FAILED" echo " => FILE: $RSYSLOG_DEBUGLOG" echo " => EXPECTED: $EXPECTED" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-template.sh0000644000000000000000000000013215145046113020031 xustar0030 mtime=1771326539.056014566 30 atime=1782715518.895790659 30 ctime=1787067806.608952652 rsyslog-8.2608.0/tests/omhiredis-template.sh0000775000175000017500000000250115145046113017476 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging # export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omhiredis/.libs/omhiredis") template(name="outfmt" type="string" string="%msg%") template(name="redis_command" type="string" string="INCRBY counter 3") local4.* { action(type="omhiredis" name="omhiredis-template" server="127.0.0.1" serverport="'$REDIS_RANDOM_PORT'" mode="template" template="redis_command") stop } action(type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'" template="outfmt") ' # Should get 'none' redis_command "TYPE counter" > $RSYSLOG_OUT_LOG startup # Inject 3 messages injectmsg 1 3 # Should get 'string' redis_command "TYPE counter" >> $RSYSLOG_OUT_LOG shutdown_when_empty wait_shutdown # Should get '9' redis_command "GET counter" >> $RSYSLOG_OUT_LOG # The first get is before inserting, the second is after export EXPECTED="none string 9" cmp_exact $RSYSLOG_OUT_LOG content_check "omhiredis[omhiredis-template]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/proprepltest-rfctag.sh0000644000000000000000000000013215241075234020247 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.789581739 30 ctime=1787067803.666897829 rsyslog-8.2608.0/tests/proprepltest-rfctag.sh0000775000175000017500000000213415241075234017716 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="+%syslogtag:1:32%+\n") :pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\"" shutdown_when_empty wait_shutdown echo '+TAG:+ +0+ +01234567890123456789012345678901+ +01234567890123456789012345678901+' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_random.sh0000644000000000000000000000013115241075234017265 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067806.843957031 rsyslog-8.2608.0/tests/rscript_random.sh0000775000175000017500000000206615241075234016741 0ustar00rgerrger#!/bin/bash # added 2015-06-22 by singh.janmejay # Verifies that random(max) emits bounded non-negative values. The oracle is # the omfile output after synchronized shutdown, so the check covers the value # that rsyslog delivered to the configured action destination. # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_random.sh\]: test for random-number-generator script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.random_no% %$.random_neg%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.random_no = random(10); set $.random_neg = random(-10); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 200 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown . $srcdir/diag.sh content-pattern-check "^[0-9] [0-9]$" exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_prog_simple-vg.sh0000644000000000000000000000013215171370365020554 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.897790693 30 ctime=1787067806.026941806 rsyslog-8.2608.0/tests/improg_prog_simple-vg.sh0000775000175000017500000000021615171370365020222 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/improg_prog_simple.sh rsyslog-8.2608.0/tests/PaxHeaders/abort-uncleancfg-goodcfg-check.sh0000644000000000000000000000013215035412264022132 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.897790693 30 ctime=1787067804.575914768 rsyslog-8.2608.0/tests/abort-uncleancfg-goodcfg-check.sh0000777000175000017500000000070715035412264021607 0ustar00rgerrger#!/bin/bash # Copyright 2015-01-29 by Tim Eifler # This file is part of the rsyslog project, released under ASL 2.0 # The configuration test should pass because of the good config file. . ${srcdir:=.}/diag.sh init echo "testing a good Configuration verification run" ../tools/rsyslogd -C -N1 -f$srcdir/testsuites/abort-uncleancfg-goodcfg.conf -M../runtime/.libs:../.libs if [ $? -ne 0 ]; then echo "Error: config check fail" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/perctile-simple-vg.sh0000644000000000000000000000013215171370365017755 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.897790693 30 ctime=1787067806.745955205 rsyslog-8.2608.0/tests/perctile-simple-vg.sh0000775000175000017500000000011015171370365017414 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/perctile-simple.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-endregex-save-lf.sh0000644000000000000000000000013115131231047020630 xustar0030 mtime=1768239655.703212565 29 atime=1782715518.89879071 30 ctime=1787067807.909976895 rsyslog-8.2608.0/tests/imfile-endregex-save-lf.sh0000777000175000017500000000313015131231047020277 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # This test mimics the test imfile-readmode2.sh, but works via # endmsg.regex. It's kind of a base test for the regex functionality. echo ====================================================================== echo [imfile-endregex-save-lf.sh] . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" startmsg.regex="^[^ ]") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1 msgnum:2' > $RSYSLOG_DYNNAME.input # the next line terminates our test. It is NOT written to the output file, # as imfile waits whether or not there is a follow-up line that it needs # to combine. echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing ./msleep 500 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! printf 'HEADER msgnum:0\\\\n msgnum:1\\\\n msgnum:2\n' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-bulk-load.sh0000644000000000000000000000013215035412264020240 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.896790676 30 ctime=1787067805.794937483 rsyslog-8.2608.0/tests/clickhouse-bulk-load.sh0000777000175000017500000000171615035412264017716 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100000 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.bulkLoad (id, ipaddress, message) VALUES (%msg:F,58:2%, ' add_conf "'%fromhost-ip%', '%msg:F,58:2%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" user="default" pwd="" template="outfmt") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.bulkLoad ( id Int32, ipaddress String, message String ) ENGINE = MergeTree() PARTITION BY ipaddress Order By id" startup injectmsg shutdown_when_empty wait_shutdown clickhouse-client --query="SELECT message FROM rsyslog.bulkLoad ORDER BY id" > $RSYSLOG_OUT_LOG clickhouse-client --query="DROP TABLE rsyslog.bulkLoad" seq_check 0 $(( NUMMESSAGES - 1 )) exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize-turbo-hup-tsan.sh0000644000000000000000000000013215241075234021460 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.686579811 30 ctime=1787067807.109961988 rsyslog-8.2608.0/tests/mmnormalize-turbo-hup-tsan.sh0000775000175000017500000000604115241075234021130 0ustar00rgerrger#!/bin/bash # Reproduce concurrent access to an mmnormalize Turbo worker context while HUP # replaces that context. A large TCP flood keeps all main-queue workers inside # normalization while acknowledged HUPs repeatedly rebuild their private # liblognorm contexts. Under ThreadSanitizer, an unsafe implementation is # expected to report the ctxlnTurbo race and abort rsyslogd. The post-fix oracle # is that every sender completes, every message reaches the output, and rsyslogd # shuts down normally without a sanitizer report. The high message count keeps # work pending throughout the HUP loop; the HUP count supplies many independent # overlap opportunities without relying on a timing sleep. The 15-minute outer # timeout is only a deadlock guard for heavily instrumented CI hosts; normal # reproductions finish or raise the sanitizer report within seconds. export TEST_MAX_RUNTIME=900 . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin mmnormalize export NUMMESSAGES="${NUMMESSAGES:-500000}" HUP_COUNT="${HUP_COUNT:-50}" TSAN_LOG="$PWD/$RSYSLOG_DYNNAME.tsan" export TSAN_OPTIONS="${TSAN_OPTIONS:+$TSAN_OPTIONS:}log_path=$TSAN_LOG" # Clang 21's live symbolizer can block while resolving this dlopen()ed module, # hiding an already-detected race. Raw module offsets remain deterministic and # can be resolved offline with llvm-symbolizer or addr2line. if [[ "$TSAN_OPTIONS" != *"symbolize="* ]]; then export TSAN_OPTIONS="$TSAN_OPTIONS:symbolize=0" fi printf '%s\n' 'rule=:%payload:rest%' > "$RSYSLOG_DYNNAME.rulebase" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") main_queue( queue.type="FixedArray" queue.size="600000" queue.workerThreads="16" queue.workerThreadMinimumMessages="1" queue.dequeueBatchSize="1" ) input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="normalize") template(name="sequence" type="string" string="%msg:F,58:2%\n") ruleset(name="normalize") { action(type="mmnormalize" turbo="on" rulebase="'$RSYSLOG_DYNNAME'.rulebase") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="sequence" flushOnTXEnd="on") } ' dump_tsan_report() { if [ -n "${TSAN_REPORT:-}" ] && [ -s "$TSAN_REPORT" ]; then printf 'ThreadSanitizer report from rsyslogd:\n' cat "$TSAN_REPORT" fi } startup TSAN_REPORT="$TSAN_LOG.$(cat "$RSYSLOG_PIDBASE.pid")" trap dump_tsan_report EXIT start_tcpflood_async TCPFLOOD_PID TCPFLOOD_MARKER \ -c32 -m"$NUMMESSAGES" # Do not issue the first HUP until normalization is demonstrably active and # worker-local Turbo contexts have been created. wait_file_lines "$RSYSLOG_OUT_LOG" 100 60 for ((i = 1; i <= HUP_COUNT; ++i)); do printf 'issuing mmnormalize Turbo stress HUP %d/%d\n' "$i" "$HUP_COUNT" issue_HUP if [ -s "$TSAN_REPORT" ]; then printf 'ThreadSanitizer report detected after HUP %d\n' "$i" kill "$TCPFLOOD_PID" 2>/dev/null || true error_exit 1 fi done wait_tcpflood_async "$TCPFLOOD_PID" "$TCPFLOOD_MARKER" shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-rule_and_rulebase-vg.sh0000644000000000000000000000013115171370365022664 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.895790659 29 ctime=1787067807.07896141 rsyslog-8.2608.0/tests/pmnormalize-rule_and_rulebase-vg.sh0000775000175000017500000000022415171370365022332 0ustar00rgerrger#!/bin/bash # added 2019-04-10 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/pmnormalize-rule_and_rulebase.sh rsyslog-8.2608.0/tests/PaxHeaders/mmjsontransform-basic.sh0000644000000000000000000000013215241075234020556 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067807.231964261 rsyslog-8.2608.0/tests/mmjsontransform-basic.sh0000775000175000017500000000360615241075234020232 0ustar00rgerrger#!/bin/bash # Validate mmjsontransform restructures dotted JSON keys into nested containers. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmjsontransform/.libs/mmjsontransform") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!output%\n%$!flattened%\n") local4.* { set $.ret = parse_json("{ \"a.b\": \"value\", \"a\": { \"existing\": 1 }, \"simple\": \"text\", \"nested.level.deep\": true, \"arr\": [ { \"inner.key\": 1 }, { \"plain\": 2 } ] }", "\$!input"); action(type="mmjsontransform" input="$!input" output="$!output") action(type="mmjsontransform" mode="flatten" input="$!output" output="$!flattened") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m1 shutdown_when_empty wait_shutdown python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys with open(sys.argv[1], "r", encoding="utf-8") as fh: lines = [line.strip() for line in fh if line.strip()] if len(lines) != 2: print("expected 2 JSON lines, got", len(lines)) sys.exit(1) unflattened = json.loads(lines[0]) flattened = json.loads(lines[1]) expected_unflattened = { "a": { "b": "value", "existing": 1, }, "simple": "text", "nested": {"level": {"deep": True}}, "arr": [ {"inner": {"key": 1}}, {"plain": 2}, ], } expected_flattened = { "a.b": "value", "a.existing": 1, "simple": "text", "nested.level.deep": True, "arr": [ {"inner.key": 1}, {"plain": 2}, ], } if unflattened != expected_unflattened: print("unexpected unflattened output:", unflattened) sys.exit(1) if flattened != expected_flattened: print("unexpected flattened output:", flattened) sys.exit(1) PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/fac_ftp.sh0000644000000000000000000000013215241075234015642 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.296909569 rsyslog-8.2608.0/tests/fac_ftp.sh0000775000175000017500000000110315241075234015304 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n" ftp.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m$NUMMESSAGES -P 89 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omudpspoof-fragment-send-failure.sh0000644000000000000000000000013215241075234022610 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.690579886 30 ctime=1787067807.813975106 rsyslog-8.2608.0/tests/omudpspoof-fragment-send-failure.sh0000775000175000017500000000244315241075234022262 0ustar00rgerrger#!/bin/bash # Verifies that omudpspoof does not spin forever when libnet_write() fails # while sending a fragmented message. The oracle is successful shutdown after # injecting one oversized message while a preload shim forces every raw packet # write to fail. Older code retried the same fragment offset indefinitely. # This file is part of the rsyslog project, released under ASL 2.0. echo This test must be run as root [raw socket access required] if [ "$EUID" -ne 0 ]; then exit 77 fi . ${srcdir:=.}/diag.sh init skip_ASAN "LD_PRELOAD conflicts with ASan runtime load order" export RSYSLOG_PRELOAD=.libs/liboverride_libnet_write_fail.so export TCPFLOOD_EXTRA_OPTS="-b1 -W1" export NUMMESSAGES=1 export MESSAGESIZE=65000 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omudpspoof/.libs/omudpspoof") global(maxMessageSize="64k") input(type="imtcp" port="'$TCPFLOOD_PORT'") template(name="spoofaddr" type="string" string="127.0.0.1") template(name="payload" type="string" string="%msg%\n") if $msg contains "msgnum:" then { action(type="omudpspoof" Target="127.0.0.1" Port="514" SourceTemplate="spoofaddr" Template="payload" mtu="1500") } ' startup tcpflood -m "$NUMMESSAGES" -i1 -d "$MESSAGESIZE" shutdown_when_empty "" 10 wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-snare_ccoff_udp2.sh0000644000000000000000000000013115035412264021632 xustar0030 mtime=1752569012.406709056 29 atime=1782715518.89879071 30 ctime=1787067805.047923564 rsyslog-8.2608.0/tests/parsertest-snare_ccoff_udp2.sh0000777000175000017500000000537315035412264021314 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") $EscapeControlCharactersOnReceive off template(name="outfmt" type="string" string="insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (%msg:::space-cc%, %syslogfacility%, %HOSTNAME%,%syslogpriority%, 20100321185328, 20100321185328, %iut%, %syslogtag:::space-cc%)\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"test\"" tcpflood -m1 -T "udp" -M "\"UX=Abcd-efg-hij-klmno; XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111\"" tcpflood -m1 -T "udp" -M "\"windowsserver MSWinEventLog 1 Security 1167 Fri Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\\\n\"" shutdown_when_empty wait_shutdown export EXPECTED="insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values (, 1, test,5, 20100321185328, 20100321185328, 1, ) insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ( XXXXX=1111111111, Z123=192.12.231.245:11111, S1234=123456789, XXXXXX=111111111, 1, $RS_HOSTNAME,5, 20100321185328, 20100321185328, 1, UX=Abcd-efg-hij-klmno;) insert into windows (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ( Mar 19 15:33:30 2010 540 Security SYSTEM User Success Audit WINDOWSSERVER Logon/Logoff Successful Network Logon: User Name: WINDOWSSERVER$ Domain: DOMX Logon ID: (0x0,0xF88396) Logon Type: 3 Logon Process: Kerberos Authentication Package: Kerberos Workstation Name: Logon GUID: {79b6eb79-7bcc-8a2e-7dad-953c51dc00fd} Caller User Name: - Caller Domain: - Caller Logon ID: - Caller Process ID: - Transited Services: - Source Network Address: 10.11.11.3 Source Port: 3306 733\n, 1, $RS_HOSTNAME,5, 20100321185328, 20100321185328, 1, windowsserver MSWinEventLog 1 Security 1167 Fri)" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-from-beginning.sh0000644000000000000000000000013115131231047022376 xustar0030 mtime=1768239655.704212582 29 atime=1782715518.89879071 30 ctime=1787067806.554951645 rsyslog-8.2608.0/tests/imhiredis-stream-from-beginning.sh0000777000175000017500000000250715131231047022054 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis # WILL be logged by Rsyslog redis_command "XADD mystream * msg message1" redis_command "XADD mystream * msg message2" redis_command "XADD mystream * msg message3" generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %$!msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mystream" mode="stream" stream.readFrom="0-0" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup redis_command "XADD mystream * msg message4" redis_command "XADD mystream * msg message5" redis_command "XADD mystream * msg message6" shutdown_when_empty wait_shutdown stop_redis content_check '1 message1' content_check '2 message2' content_check '3 message3' content_check '4 message4' content_check '5 message5' content_check '6 message6' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zstd-basic.sh0000644000000000000000000000013015241075234022202 xustar0029 mtime=1787067036.62457865 29 atime=1787067036.77358144 30 ctime=1787067805.579933477 rsyslog-8.2608.0/tests/imtcp-stream-always-zstd-basic.sh0000775000175000017500000000222315241075234021652 0ustar00rgerrger#!/bin/bash # added 2026-05-17 by Codex, released under ASL 2.0 # Verifies that imtcp inflates a zstd stream:always TCP byte stream produced by # omfwd; the oracle is a complete, ordered sequence at the receiver. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime export NUMMESSAGES=20000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zstd") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.driver="zstd" compression.stream.flushOnTXEnd="on") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp_multi_line.sh0000644000000000000000000000013115131231047017746 xustar0030 mtime=1768239655.706212614 29 atime=1782715518.89879071 30 ctime=1787067806.809956397 rsyslog-8.2608.0/tests/imptcp_multi_line.sh0000777000175000017500000000220215131231047017414 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" multiline="on") template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n") ruleset(name="remote") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -B -I ${srcdir}/testsuites/imptcp_multi_line.testdata shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate export EXPECTED='NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test1 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test2 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012line1 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012l#012i#012n#012#012e2 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test3 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag multi#012line3 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test4 NEWMSG: <133>Mar 1 01:00:00 172.20.245.8 tag test end' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrabbitmq_params_missing2.sh0000644000000000000000000000013115035412264021551 xustar0030 mtime=1752569012.405716005 29 atime=1782715518.89879071 30 ctime=1787067806.500950639 rsyslog-8.2608.0/tests/omrabbitmq_params_missing2.sh0000777000175000017500000000060415035412264021223 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/omrabbitmq/.libs/omrabbitmq") action(type="omrabbitmq" exchange="in" routing_key="jk") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "parameter host must be specified" exit_testrsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-sysmon.sh0000644000000000000000000000013115132733117020262 xustar0030 mtime=1768666703.959621026 29 atime=1782715518.89879071 30 ctime=1787067805.072924029 rsyslog-8.2608.0/tests/mmsnareparse-sysmon.sh0000777000175000017500000001075115132733117017740 0ustar00rgerrger#!/bin/bash # Validate mmsnareparse parsing against Microsoft Sysmon events using definition file. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmsnareparse/.libs/mmsnareparse") template(name="outfmt" type="list") { property(name="$!win!Event!EventID") constant(value=",") property(name="$!win!Event!Channel") constant(value=",") property(name="$!win!Event!Category") constant(value=",") property(name="$!win!Event!Subtype") constant(value=",") property(name="$!win!EventData!ProcessId") constant(value=",") property(name="$!win!EventData!Image") constant(value=",") property(name="$!win!EventData!CommandLine") constant(value=",") property(name="$!win!EventData!User") constant(value=",") property(name="$!win!Network!SourceIp") constant(value=",") property(name="$!win!Network!SourcePort") constant(value=",") property(name="$!win!Network!DestinationIp") constant(value=",") property(name="$!win!Network!DestinationPort") constant(value=",") property(name="$!win!Network!Protocol") constant(value="\n") } action(type="mmsnareparse" definition.file="../plugins/mmsnareparse/sysmon_definitions.json") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup cat <<'MSG' > ${RSYSLOG_DYNNAME}.input <14>Nov 25 05:54:32 DC-01 MSWinEventLog 1 Microsoft-Windows-Sysmon/Operational 10448 Tue Nov 25 05:54:32 2025 1 Windows SYSTEM User Information DC-01 CORP\NETWORK SERVICE Process creation Sysmon Event ID 1 - Process creation: UtcTime: 2024-04-28 22:08:22.025 ProcessGuid: {b34fbf9a-ce67-6a14-1111-1121f0a06f11} ProcessId: 6228 Image: C:\Windows\System32\wbem\WmiPrvSE.exe FileVersion: 10.0.22621.1 (WinBuild.160101.0800) Description: WMI Provider Host Product: Microsoft® Windows® Operating System Company: Microsoft Corporation OriginalFileName: Wmiprvse.exe CommandLine: C:\Windows\system32\wbem\wmiprvse.exe -secured -Embedding CurrentDirectory: C:\Windows\system32\ User: CORP\NETWORK SERVICE LogonGuid: {d56hdh1c-eg89-8c36-3333-3343h2c28h33} LogonId: 0x7EB05 TerminalSessionId: 1 IntegrityLevel: System Hashes: SHA1=A3F7B2C8D9E1F4A5B6C7D8E9F0A1B2C3D4E5F6A7,MD5=8E4F2A1B3C5D6E7F8A9B0C1D2E3F4A5,SHA256=7B9C2D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2C3D4,IMPHASH=6A5B4C3D2E1F0A9B8C7D6E5F4A3B2C1D0E9F8A7B6C5 ParentProcessGuid: {c45gcg0b-df78-7b25-2222-2232g1b17g22} ParentProcessId: 580 ParentImage: C:\Windows\System32\svchost.exe ParentCommandLine: C:\Windows\system32\svchost.exe -k DcomLaunch -p ParentUser: NT INTERNAL\SYSTEM 10448 <14>Mar 10 22:36:54 SQL-01 MSWinEventLog 1 Microsoft-Windows-Sysmon/Operational 30692 Mon Mar 10 22:36:54 2025 3 Windows SYSTEM User Information SQL-01 LAB\Administrator Network connection detected Sysmon Event ID 3 - Network connection detected: RuleName: RDP UtcTime: 2017-04-28 22:12:22.557 ProcessGuid: {c45gcg0b-df78-7b25-2222-2232g1b17g22} ProcessId: 13220 Image: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe Description: Sysmon Event ID 3 User: LAB\Administrator SourceIp: 10.0.0.20 SourcePort: 3328 DestinationIp: 192.168.1.20 DestinationPort: 3389 Protocol: tcp Initiated: true SourceIsIpv6: 192.168.1.20 SourceHostname: DC-03 DestinationIsIpv6: 10.0.0.20 DestinationPortName: ms-wbt-server 30692 <14>Jun 27 04:55:00 SERVER-01 MSWinEventLog 1 Microsoft-Windows-Sysmon/Operational 50518 Fri Jun 27 04:55:00 2025 5 Windows SYSTEM User Information SERVER-01 Process terminated Sysmon Event ID 5 - Process terminated: UtcTime: 2017-04-28 22:13:20.895 ProcessGuid: {02de4fd3-bd56-5903-0000-0010e9d95e00} ProcessId: 12684 Image: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe Description: Sysmon Event ID 5 50518 MSG injectmsg_file ${RSYSLOG_DYNNAME}.input shutdown_when_empty wait_shutdown # Test Event ID 1 (Process Creation) content_check '1,Microsoft-Windows-Sysmon/Operational,Process,Creation,6228,C:\Windows\System32\wbem\WmiPrvSE.exe,C:\Windows\system32\wbem\wmiprvse.exe -secured -Embedding,CORP\NETWORK SERVICE,,,,,' $RSYSLOG_OUT_LOG # Test Event ID 3 (Network Connection) content_check '3,Microsoft-Windows-Sysmon/Operational,Network,Connection,13220,C:\Program Files (x86)\Google\Chrome\Application\chrome.exe,,LAB\Administrator,10.0.0.20,,192.168.1.20,,tcp' $RSYSLOG_OUT_LOG # Test Event ID 5 (Process Termination) content_check '5,Microsoft-Windows-Sysmon/Operational,Process,Termination,12684,C:\Program Files (x86)\Google\Chrome\Application\chrome.exe,,,,,,' $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbeats-submit-timeout.sh0000644000000000000000000000013215241075234020651 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.683579755 30 ctime=1787067806.467950024 rsyslog-8.2608.0/tests/imbeats-submit-timeout.sh0000775000175000017500000000423115241075234020320 0ustar00rgerrger#!/bin/bash # Regression test for imbeats timeout ownership while a complete batch is # submitted. A direct ruleset deliberately spends longer than idleTimeout on # each event, and starvation protection yields between the two submissions. # The cumulative ACK and both output lines prove that neither the timeout # scanner nor worker re-entry expired the session during local submission. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") module(load="../plugins/omtesting/.libs/omtesting") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="main" queue.type="Direct") { :omtesting:sleep 1 100000 action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main" idleTimeout="1" workerThreads="1" starvationProtection.maxReads="1") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" if ! $PYTHON - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys port = int(sys.argv[1]) events = [] def recv_exactly(sock, length): data = b"" while len(data) < length: chunk = sock.recv(length - len(data)) if not chunk: raise ConnectionError("connection closed before cumulative ACK") data += chunk return data for sequence in (1, 2): payload = json.dumps({"message": "submit-timeout-%d" % sequence}, separators=(",", ":")).encode() events.append(b"2J" + struct.pack(">I", sequence) + struct.pack(">I", len(payload)) + payload) with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(10) sock.sendall(b"2W" + struct.pack(">I", len(events)) + b"".join(events)) print(recv_exactly(sock, 6).hex()) PY then error_exit 1 fi shutdown_when_empty wait_shutdown # diag.sh's cmp_exact consumes this conventionally named variable. # shellcheck disable=SC2034 EXPECTED='{"message":"submit-timeout-1"} {"message":"submit-timeout-2"}' cmp_exact # shellcheck disable=SC2034 EXPECTED='324100000002' cmp_exact "$RSYSLOG_DYNNAME.imbeats.ack" exit_test rsyslog-8.2608.0/tests/PaxHeaders/cfg2.testin0000644000000000000000000000013115035412264015753 xustar0030 mtime=1752569012.384861924 29 atime=1782715518.89879071 30 ctime=1787067808.399986026 rsyslog-8.2608.0/tests/cfg2.testin0000666000175000017500000000003315035412264015416 0ustar00rgerrger$includeconfig cfg1.testin rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_rule_from_array.sh0000644000000000000000000000013215241075234022042 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067807.097961764 rsyslog-8.2608.0/tests/mmnormalize_rule_from_array.sh0000775000175000017500000000222215241075234021507 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="norm") template(name="outfmt" type="string" string="%hostname% %syslogtag%\n") ruleset(name="norm") { action(type="mmnormalize" rule=["rule=: no longer listening on %ip:ipv4%#%port:number%", "rule=: is sending messages on %ip:ipv4%", "rule=: apfelkuchen"]) action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m1 -M "\"<167>Mar 6 16:57:54 ubuntu tag1: no longer listening on 127.168.0.1#10514\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 debian tag2: is sending messages on 127.168.0.1\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 centos tag3: apfelkuchen\"" shutdown_when_empty wait_shutdown echo 'ubuntu tag1: debian tag2: centos tag3:' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-transactions-failed-messages.sh0000644000000000000000000000013115132733117023277 xustar0030 mtime=1768666703.965621117 29 atime=1782715518.89879071 30 ctime=1787067806.086942924 rsyslog-8.2608.0/tests/omprog-transactions-failed-messages.sh0000777000175000017500000001044315132733117022753 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests omprog with the confirmMessages=on and useTransactions=on # parameters, with the external program returning an error on certain # messages. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh --failed_messages` template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process queue.dequeueBatchSize="6" confirmMessages="on" useTransactions="on" action.resumeRetryCount="10" action.resumeInterval="1" ) } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown # Since the transaction boundaries are not deterministic, we cannot check for # an exact expected output. We must check the output programmatically. transaction_state="NONE" status_expected=true messages_to_commit=() messages_processed=() line_num=1 error= while IFS= read -r line; do if [[ $status_expected == true ]]; then case "$transaction_state" in "NONE") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi ;; "STARTED") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi transaction_state="ACTIVE" ;; "ACTIVE") if [[ "$line" == "<= Error: could not process log message" ]]; then messages_to_commit=() transaction_state="NONE" elif [[ "$line" != "<= DEFER_COMMIT" ]]; then error="expecting a DEFER_COMMIT status from script" break fi ;; "COMMITTED") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi messages_processed+=("${messages_to_commit[@]}") messages_to_commit=() transaction_state="NONE" ;; esac status_expected=false; else if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then if [[ "$transaction_state" != "NONE" ]]; then error="unexpected transaction start" break fi transaction_state="STARTED" elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected transaction commit" break fi transaction_state="COMMITTED" else if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected message outside a transaction" break fi if [[ "$line" != "=> msgnum:"* ]]; then error="unexpected message contents" break fi prefix_to_remove="=> " messages_to_commit+=("${line#$prefix_to_remove}") fi status_expected=true; fi ((line_num++)) done < $RSYSLOG_OUT_LOG if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then error="unexpected end of file (transaction state: $transaction_state)" fi if [[ -n "$error" ]]; then echo "$RSYSLOG_OUT_LOG: line $line_num: $error" cat $RSYSLOG_OUT_LOG error_exit 1 fi # Since the order in which failed messages are retried by rsyslog is not # deterministic, we sort the processed messages before checking them. IFS=$'\n' messages_sorted=($(sort <<<"${messages_processed[*]}")) unset IFS expected_messages=( "msgnum:00000000:" "msgnum:00000001:" "msgnum:00000002:" "msgnum:00000003:" "msgnum:00000004:" "msgnum:00000005:" "msgnum:00000006:" "msgnum:00000007:" "msgnum:00000008:" "msgnum:00000009:" ) if [[ "${messages_sorted[*]}" != "${expected_messages[*]}" ]]; then echo "unexpected set of processed messages:" printf '%s\n' "${messages_processed[@]}" echo "contents of $RSYSLOG_OUT_LOG:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/operatingstate-unclean.sh0000644000000000000000000000013115035412264020712 xustar0030 mtime=1752569012.406709056 29 atime=1782715518.89879071 30 ctime=1787067803.989903848 rsyslog-8.2608.0/tests/operatingstate-unclean.sh0000777000175000017500000000161315035412264020365 0ustar00rgerrger#!/bin/bash # added 2018-10-24 by Rainer Gerhards # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(operatingStateFile="'$RSYSLOG_DYNNAME.osf'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # create an unclean file err_osf_content="20180924-160109: STATE INITIALIZING 8.39.0.master 20180924-160110: STATE" printf '%s\n' "$err_osf_content" > $RSYSLOG_DYNNAME.osf startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! check_file_exists "$RSYSLOG_DYNNAME.osf.previous" export EXPECTED="$err_osf_content" cmp_exact "$RSYSLOG_DYNNAME.osf.previous" check_file_exists "$RSYSLOG_DYNNAME.osf" content_check "does not end with 'CLEAN CLOSE, instead it has '0110: STATE'" "$RSYSLOG_OUT_LOG" content_check "CLEAN CLOSE" "$RSYSLOG_DYNNAME.osf" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_rule_from_string.sh0000644000000000000000000000013115241075234022231 xustar0030 mtime=1787067036.629578744 29 atime=1787067036.78158159 30 ctime=1787067807.095961727 rsyslog-8.2608.0/tests/mmnormalize_rule_from_string.sh0000775000175000017500000000214715241075234021705 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="norm") template(name="outfmt" type="string" string="%hostname% %syslogtag%\n") ruleset(name="norm") { action(type="mmnormalize" useRawMsg="on" rule="rule=:%host:word% %tag:char-to:\\x3a%: no longer listening on %ip:ipv4%#%port:number%") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"ubuntu tag1: no longer listening on 127.168.0.1#10514\"" tcpflood -m1 -M "\"debian tag2: no longer listening on 127.168.0.2#10514\"" tcpflood -m1 -M "\"centos tag3: no longer listening on 192.168.0.1#10514\"" shutdown_when_empty wait_shutdown echo 'ubuntu tag1: debian tag2: centos tag3:' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/libdbi-basic-vg.sh0000644000000000000000000000013115171370365017162 xustar0030 mtime=1776677109.463913418 29 atime=1782715518.89879071 30 ctime=1787067805.947940334 rsyslog-8.2608.0/tests/libdbi-basic-vg.sh0000775000175000017500000000035415171370365016634 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 # this test is currently not included in the testbench as libdbi # itself seems to have a memory leak export USE_VALGRIND="YES" . ${srcdir:=.}/libdbi-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/Makefile.am0000644000000000000000000000013215241075234015740 xustar0030 mtime=1787067036.613578444 30 atime=1787067036.761581215 30 ctime=1787067803.530895295 rsyslog-8.2608.0/tests/Makefile.am0000664000175000017500000034467015241075234015422 0ustar00rgerrgerTEST_EXTENSIONS=.sh EXTRA_DIST = \ tabescape_dflt.sh \ tabescape_dflt-udp.sh \ tabescape_off.sh \ tabescape_off-udp.sh \ tabescape_on.sh \ inputname-imtcp.sh \ fieldtest.sh \ fieldtest-udp.sh \ proprepltest-nolimittag-udp.sh \ proprepltest-nolimittag.sh \ proprepltest-rfctag-udp.sh \ proprepltest-rfctag.sh \ unit/README.md TESTS_FUZZING = fuzz-syslog-message-smoke.sh TESTS_RELEASE_PACKAGING = rpm-baseline-patch-policy.sh FUZZING_CORPUS = \ fuzz/README.md \ fuzz/corpus/syslog-message/rfc3164-basic \ fuzz/corpus/syslog-message/rfc3164-no-pri \ fuzz/corpus/syslog-message/rfc3164-rfc3339 \ fuzz/corpus/syslog-message/rfc3164-short \ fuzz/corpus/syslog-message/rfc5424-basic \ fuzz/corpus/syslog-message/rfc5424-escaped-sd \ fuzz/corpus/syslog-message/rfc5424-nil EXTRA_DIST += $(TESTS_FUZZING) $(TESTS_RELEASE_PACKAGING) $(FUZZING_CORPUS) TESTS_JSON_OMITIFZERO = json-omitifzero.sh json-omitifzero-subtree.sh json-whitespace.sh EXTRA_DIST += $(TESTS_JSON_OMITIFZERO) TESTS_TEMPLATE_REGEX_BOUNDS = template-regex-index-bounds.sh TESTS_TEMPLATE_REGEX_BOUNDS_LIBYAML = yaml-template-regex-index-bounds.sh EXTRA_DIST += $(TESTS_TEMPLATE_REGEX_BOUNDS) $(TESTS_TEMPLATE_REGEX_BOUNDS_LIBYAML) TESTS_RSCRIPT_OBJECT_STRINGS = rscript-object-string-escapes.sh EXTRA_DIST += $(TESTS_RSCRIPT_OBJECT_STRINGS) TESTS_TEMPLATE_PARAMETER_ERRORS = template-parameter-errors.sh EXTRA_DIST += $(TESTS_TEMPLATE_PARAMETER_ERRORS) TESTS_SEGQUEUE_TOOL = rsyslog-segqueue-tool.py rsyslog-segqueue-runtime.sh EXTRA_DIST += $(TESTS_SEGQUEUE_TOOL) TESTS_SEGMENTED_DISK_QUEUE = \ segmented-diskqueue-config.sh \ segmented-diskqueue.sh \ segmented-diskqueue-restart.sh \ segmented-diskqueue-ruleset-fallback.sh \ segmented-diskqueue-event-properties.sh \ segmented-diskqueue-corruption.sh \ segmented-diskqueue-corruption-framing.sh \ segmented-diskqueue-corruption-codec.sh \ segmented-diskqueue-state-slots.sh \ segmented-diskqueue-missing-checkpoint.sh \ segmented-diskqueue-missing-state.sh \ segmented-diskqueue-empty-dir.sh \ segmented-diskqueue-v1-state.sh \ segmented-diskqueue-missing-segment.sh \ segmented-diskqueue-multiple-recovery.sh \ segmented-diskqueue-recovery-budget.sh \ segmented-diskqueue-multiworker-frontier.sh \ segmented-diskqueue-fsync.sh \ segmented-diskqueue-maxdiskspace.sh \ segmented-diskqueue-rfc5424.sh \ segmented-diskqueue-cee.sh \ segmented-diskqueue-fromhost-port.sh \ diskqueue-scope-main.sh \ diskqueue-scope-ruleset.sh \ diskqueue-scope-action.sh \ segmented-diskqueue-scope-main.sh \ segmented-diskqueue-scope-ruleset.sh \ segmented-diskqueue-scope-action.sh \ segmented-diskqueue-pipeaction.sh \ segmented-diskqueue-dircreate.sh \ segmented-diskqueue-checkpoint-0.sh \ segmented-diskqueue-checkpoint-1.sh \ segmented-diskqueue-checkpoint-5.sh \ segmented-diskqueue-crash-reservation.sh \ segmented-diskqueue-crash-reservation-repeat.sh \ segmented-diskqueue-crash-create.sh \ segmented-diskqueue-crash-seal-write.sh \ segmented-diskqueue-crash-seal-rename.sh \ segmented-diskqueue-crash-checkpoint.sh \ segmented-diskqueue-crash-checkpoint-repeat.sh \ segmented-diskqueue-crash-commit.sh \ segmented-diskqueue-crash-predelete.sh \ segmented-diskqueue-crash-unlink.sh \ segmented-da-config-errors.sh \ segmented-da-engine-transition.sh \ segmented-da-event-properties.sh \ segmented-da-event-properties-fixedarray.sh \ segmented-da-behavior.sh \ segmented-da-tcp-spill-exact.sh \ classic-da-behavior.sh \ segmented-da-persist.sh \ classic-da-persist.sh \ segmented-da-retry-restart.sh \ classic-da-retry-restart.sh \ segmented-da-multiworker-frontier.sh \ segmented-da-recovery-budget.sh \ segmented-da-idle-retry.sh \ segmented-da-idle-crash-state.sh \ segmented-da-idle-crash-segments.sh \ segmented-da-idle-crash-state-unlink.sh \ segmented-da-idle-crash-directory.sh TESTS_SEGMENTED_DISK_QUEUE_LIBYAML = yaml-segmented-diskqueue.sh yaml-segmented-da-config.sh \ yaml-segmented-da-config-errors.sh TESTS_SEGMENTED_DISK_QUEUE_IMPSTATS = segmented-diskqueue-startup-bounded.sh \ segmented-da-idle-dematerialize.sh \ segmented-da-idle-timeout-values.sh \ segmented-da-idle-cleanup-failure.sh \ segmented-da-maxdiskspace.sh \ segmented-da-maxdiskspace-fixedarray.sh EXTRA_DIST += $(TESTS_SEGMENTED_DISK_QUEUE) $(TESTS_SEGMENTED_DISK_QUEUE_LIBYAML) \ $(TESTS_SEGMENTED_DISK_QUEUE_IMPSTATS) segdisk-inspect.py \ testsuites/segmented-diskqueue-checkpoint-driver.sh \ testsuites/segmented-diskqueue-crash-driver.sh \ testsuites/segmented-da-idle-crash-driver.sh \ testsuites/da-engine-behavior-driver.sh \ testsuites/da-engine-persist-driver.sh \ testsuites/da-engine-retry-restart-driver.sh \ testsuites/segmented-diskqueue-invalid-state-driver.sh \ testsuites/pure-disk-queue-scope-driver.sh TESTS_IMFIFO = imfifo.sh imfifo-vg.sh yaml-imfifo.sh EXTRA_DIST += $(TESTS_IMFIFO) TESTS_GSSAPI = \ imgssapi-listen-port-file.sh \ imgssapi-maxsessions.sh TESTS_GSSAPI_LIBYAML = \ imgssapi-yaml-include-listen-port-file.sh EXTRA_DIST += $(TESTS_GSSAPI) $(TESTS_GSSAPI_LIBYAML) unit/gss_token_util_test.c EXTRA_DIST += unit/impcap_arp_parser_test.c EXTRA_DIST += unit/imbeats_seq_test.c EXTRA_DIST += unit/segdisk_state_test.c EXTRA_DIST += unit/omazuredce_utils_test.c EXTRA_DIST += unit/imbeats_parser_test.c TESTS_IMPTCP_TABESCAPE = \ tabescape_dflt.sh \ tabescape_dflt-udp.sh \ tabescape_off.sh \ tabescape_off-udp.sh \ tabescape_on.sh \ inputname-imtcp.sh \ fieldtest.sh \ fieldtest-udp.sh \ proprepltest-nolimittag-udp.sh \ proprepltest-nolimittag.sh \ proprepltest-rfctag-udp.sh \ proprepltest-rfctag.sh TESTS_ELASTICSEARCH_MINIMAL = \ es-duplicated-ruleset.sh \ es-basic.sh \ es-basic-bulk.sh \ elasticsearch-stop.sh TESTS_ELASTICSEARCH_MINIMAL_VALGRIND = \ es-duplicated-ruleset-vg.sh \ es-basic-vg.sh TESTS_ELASTICSEARCH_MINIMAL_HELGRIND = \ es-basic-vgthread.sh TESTS_ELASTICSEARCH_SERVER = \ es-basic-server.sh \ es-execOnlyWhenPreviousSuspended.sh \ es-maxbytes-bulk.sh \ es-basic-errfile-empty.sh \ es-basic-errfile-popul.sh \ es-bulk-errfile-empty.sh \ es-bulk-errfile-popul.sh \ diskqueue-multithread-es.sh \ es-writeoperation.sh TESTS_ELASTICSEARCH_IMPSTATS = \ es-basic-ha.sh \ es-bulk-retry.sh TESTS_ELASTICSEARCH_IMFILE = \ es-bulk-errfile-popul-def-format.sh \ es-bulk-errfile-popul-erronly.sh \ es-bulk-errfile-popul-erronly-interleaved.sh \ es-bulk-errfile-popul-def-interleaved.sh TESTS_ELASTICSEARCH_VALGRIND = \ es-basic-bulk-vg.sh \ es-basic-ha-vg.sh TESTS_DEFAULT = \ codex-pre-push-container-gate.sh \ backtick-cat-procfs.sh \ preservefqdn-localhostname-internal.sh \ net-enabledns-off-localhostname.sh \ immark.sh \ immark-inputname.sh \ immark-ruleset.sh \ immark-ruleset-custom-msg.sh \ operatingstate-basic.sh \ operatingstate-empty.sh \ operatingstate-unclean.sh \ smtradfile.sh \ loadbalance.sh \ empty-hostname.sh \ timestamp-3164.sh \ timestamp-3339.sh \ timestamp-isoweek.sh \ timestamp-mysql.sh \ timestamp-pgsql.sh \ timestamp-subseconds.sh \ msleep_usage_output.sh \ mangle_qi_usage_output.sh \ chkseq_usage_output.sh \ minitcpsrv_usage_output.sh \ diagtalker-retry.sh \ test_id_usage_output.sh \ uxsockrcvr_usage_output.sh \ prop-programname.sh \ prop-programname-with-slashes.sh \ hostname-with-slash-pmrfc5424.sh \ hostname-with-slash-pmrfc3164.sh \ hostname-with-slash-dflt-invld.sh \ func-substring-invld-startpos.sh \ func-substring-large-endpos.sh \ func-substring-large-neg-endpos.sh \ func-substring-relative-endpos.sh \ hostname-with-slash-dflt-slash-valid.sh \ empty-app-name.sh \ endswith-basic.sh \ contains-longer-needle.sh \ stop-localvar.sh \ stop-msgvar.sh \ glbl-ruleset-queue-defaults.sh \ glbl-internalmsg_severity-info-shown.sh \ glbl-internalmsg_severity-debug-shown.sh \ glbl-internalmsg_severity-debug-not_shown.sh \ glbl-internalmsg_severity-invalid-long.sh \ glbl-umask.sh \ glbl-unloadmodules.sh \ glbl-invld-param.sh \ glbl_setenv_2_vars.sh \ glbl_setenv_err.sh \ glbl_setenv_err_too_long.sh \ glbl_setenv.sh \ mmexternal-SegFault.sh \ mmexternal-set-msg-null-crash.sh \ mmexternal-set-syslogtag-null-crash.sh \ mmexternal-interface-output-none.sh \ mmexternal-single-instance.sh \ mmexternal-response-too-long.sh \ mmexternal-response-timeout.sh \ mmexternal-response-timeout-trickle.sh \ nested-call-shutdown.sh \ dnscache-TTL-0.sh \ invalid_nested_include.sh \ omfwd-lb-1target-retry-full_buf.sh \ omfwd-lb-1target-retry-1_byte_buf.sh \ omfwd-lb-1target-retry-1_byte_buf-TargetFail.sh \ omfwd-lb-susp.sh \ omfwd-lb-2target-basic.sh \ omfwd-lb-2target-retry.sh \ omfwd-lb-2target-one_fail.sh \ omfwd-missing-target.sh \ omfwd-suspended-no-early-commit.sh \ omfwd-tls-invalid-permitExpiredCerts.sh \ omfwd-keepalive.sh \ omfwd-tcp-user-timeout.sh \ yaml-omfwd-tcp-user-timeout.sh \ omfwd-subtree-tpl.sh \ omfwd-errfile-maxsize.sh \ omfwd-errfile-maxsize-filled.sh \ omfile-subtree-jsonf.sh \ omusrmsg-errmsg-no-params.sh \ omusrmsg-noabort.sh \ omusrmsg_ratelimit_name.sh \ omfile-module-params.sh \ omfile-dynafile-template-type-invalid.sh \ omfile-dynafile-template-type-list-default.sh \ omfile-dynafile-template-type-override.sh \ omfile-dynafilecachesize-invalid.sh \ omfile-dynafile-mmnormalize-property.sh \ omfile-read-only-errmsg.sh \ omfile-followsymlinks.sh \ omfile-null-filename.sh \ omfile-whitespace-filename.sh \ omfile-read-only.sh \ omfile-outchannel.sh \ omfile_both_files_set.sh \ omfile_hup.sh \ msgvar-concurrency.sh \ localvar-concurrency.sh \ exec_tpl-concurrency.sh \ rscript_privdropuser.sh \ rscript_privdropuserid.sh \ rscript_privdropgroup.sh \ rscript_privdropgroupid.sh \ privdropuser.sh \ privdropuserid.sh \ privdrop-setuid-fail.sh \ privdropgroup.sh \ privdropgroupid.sh \ privdropabortonidfail.sh \ privdropabortonidfaillegacy.sh \ json-nonstring.sh \ json-onempty-at-end.sh \ template-json.sh \ $(TESTS_RSCRIPT_OBJECT_STRINGS) \ template-property-transformations.sh \ $(TESTS_TEMPLATE_PARAMETER_ERRORS) \ template-pure-json.sh \ template-jsonf-nested.sh \ template-jsonf-nested-fallback-flat.sh \ template-jsonf-trailing-backslash.sh \ template-missing-jsonvars-queue.sh \ template-pos-from-to.sh \ template-pos-from-to-lowercase.sh \ template-pos-from-to-oversize.sh \ template-pos-from-to-oversize-lowercase.sh \ template-pos-from-to-missing-jsonvar.sh \ template-const-jsonf.sh \ $(TESTS_TEMPLATE_REGEX_BOUNDS) \ template-topos-neg.sh \ fac_authpriv.sh \ fac_local0.sh \ fac_local7.sh \ fac_mail.sh \ fac_news.sh \ fac_ftp.sh \ fac_ntp.sh \ fac_uucp.sh \ fac_invld1.sh \ fac_invld2.sh \ fac_invld3.sh \ fac_invld4_rfc5424.sh \ rfc5424parser-sp_at_msg_start.sh \ compresssp.sh \ compresssp-stringtpl.sh \ rawmsg-after-pri.sh \ rfc5424parser.sh \ pmrfc3164-msgFirstSpace.sh \ pmrfc3164-AtSignsInHostname.sh \ pmrfc3164-AtSignsInHostname_off.sh \ pmrfc3164-tagEndingByColon.sh \ pmrfc3164-parsehostnameandtag-off.sh \ pmrfc3164_force_tag_no_colon.sh \ pmrfc3164-defaultTag.sh \ pmrfc3164-headerless.sh \ pmrfc3164-drop.sh \ pmrfc3164-json.sh \ tcp_forwarding_tpl.sh \ tcp_forwarding_dflt_tpl.sh \ tcp_forwarding_retries.sh \ mainq_actq_DA.sh \ queue_warnmsg-oversize.sh \ queue-minbatch.sh \ queue-minbatch-queuefull.sh \ queue-direct-with-no-params.sh \ queue-direct-with-params-given.sh \ arrayqueue.sh \ global_vars.sh \ no-parser-errmsg.sh \ da-mainmsg-q.sh \ validation-run.sh \ msgdup.sh \ msgdup_props.sh \ empty-ruleset.sh \ ruleset-direct-queue.sh \ imtcp-listen-port-file-2.sh \ allowed-sender-tcp-ok.sh \ allowed-sender-tcp-fail.sh \ allowed-sender-tcp-zero-mask.sh \ allowed-sender-modern.sh \ allowed-sender-empty-array.sh \ allowed-sender-tcp-hostname-ok.sh \ allowed-sender-tcp-hostname-fail.sh \ allowed-sender-wildcard-invalid-bits.sh \ imtcp-discard-truncated-msg.sh \ da-queue-persist.sh \ daqueue-persist.sh \ daqueue-invld-qi.sh \ daqueue-dirty-shutdown-recovery.sh \ daqueue-truncated-segment-startup.sh \ diskq-rfc5424.sh \ diskqueue-truncated-segment-startup.sh \ diskqueue-final-symlink.sh \ diskqueue.sh \ diskqueue-fsync.sh \ diskqueue-full.sh \ diskqueue-fail.sh \ queue-invalid-spooldirectory-empty.sh \ queue-invalid-workerthreads-zero.sh \ diskqueue-oncorruption-missing-segment.sh \ diskqueue-non-unique-prefix.sh \ rulesetmultiqueue.sh \ rulesetmultiqueue-v6.sh \ manytcp.sh \ rsf_getenv.sh \ msg-deadlock-headerless-noappname.sh \ sndrcv.sh \ sndrcv_failover.sh \ sndrcv_gzip.sh \ sndrcv_udp_nonstdpt.sh \ sndrcv_udp_nonstdpt_v6.sh \ imudp_thread_hang.sh \ imudp-listenportfilename-secure.sh \ imudp-ratelimit-programname.sh \ imudp_ratelimit_name.sh \ omfwd_ratelimit_name.sh \ omelasticsearch_ratelimit_name.sh \ omelasticsearch-bulk-readonly-retry.sh \ omelasticsearch-dynsearch-template.sh \ omelasticsearch-bulk-metadata-escape.sh \ omelasticsearch-searchtype-deprecated.sh \ omhttp_ratelimit_name.sh \ imhttp_ratelimit_name.sh \ imjournal_ratelimit_name.sh \ imklog_ratelimit_name.sh \ imuxsock_ratelimit_name.sh \ asynwr_simple.sh \ asynwr_simple_2.sh \ asynwr_timeout.sh \ asynwr_timeout_2.sh \ asynwr_small.sh \ asynwr_tinybuf.sh \ wr_large_async.sh \ wr_large_sync.sh \ asynwr_deadlock.sh \ asynwr_deadlock_2.sh \ asynwr_deadlock2.sh \ asynwr_deadlock4.sh \ asynwr_dynfile_flushtxend-off.sh \ diag-core-classification.sh \ imdiag-modern-module-config.sh \ imdiag-proper-termination-core-ignore.sh \ imdiag-proper-termination-timeoutguard.sh \ tcpflood-proper-termination.sh \ global-maxopenfiles-rainerscript.sh \ global-systemd-notifyreadydelay-rainerscript.sh \ compat-configformat-rainerscript.sh \ compat-defaults-secure-dynafile-rainerscript.sh \ abort-uncleancfg-goodcfg.sh \ abort-uncleancfg-goodcfg-check.sh \ abort-uncleancfg-continue-nop.sh \ abort-uncleancfg-badcfg-check.sh \ abort-uncleancfg-badcfg-check_1.sh \ variable_leading_underscore.sh \ gzipwr_hup_multi_file.sh \ gzipwr_hup_single_file.sh \ gzipwr_rscript.sh \ gzipwr_flushInterval.sh \ gzipwr_flushOnTXEnd.sh \ gzipwr_large.sh \ gzipwr_large_dynfile.sh \ gzipwr_hup.sh \ dynfile_invld_async.sh \ dynfile_invld_sync.sh \ dynfile_invalid2.sh \ complex1.sh \ queue-persist.sh \ pipeaction.sh \ execonlyonce.sh \ execonlywhenprevsuspended.sh \ execonlywhenprevsuspended2.sh \ execonlywhenprevsuspended3.sh \ execonlywhenprevsuspended4.sh \ execonlywhenprevsuspended_multiwrkr.sh \ execonlywhenprevsuspended-queue.sh \ execonlywhenprevsuspended-nonsusp.sh \ execonlywhenprevsuspended-nonsusp-queue.sh \ pipe_noreader.sh \ dircreate_dflt.sh \ dircreate_off.sh \ imuxsock_legacy.sh \ imuxsock_missing_socket.sh \ imuxsock_logger.sh \ imuxsock_unlink_off_stale_socket.sh \ imuxsock_logger_ratelimit.sh \ imuxsock_logger_ruleset.sh \ imuxsock_logger_ruleset_ratelimit.sh \ imuxsock_logger_err.sh \ imuxsock_logger_parserchain.sh \ imuxsock_annotate_large.sh \ imuxsock-NUL.sh \ imuxsock_traillf.sh \ imuxsock_ccmiddle.sh \ imuxsock_logger_syssock.sh \ imuxsock_traillf_syssock.sh \ imuxsock_ccmiddle_syssock.sh \ discard-rptdmsg.sh \ discard-allmark.sh \ discard.sh \ stop.sh \ failover-async.sh \ failover-double.sh \ failover-basic.sh \ failover-rptd.sh \ failover-no-rptd.sh \ failover-no-basic.sh \ suspend-via-file.sh \ suspend-omfwd-via-file.sh \ externalstate-failed-rcvr.sh \ rcvr_fail_restore.sh \ snd-array-cmp-json.sh \ rscript_b64_decode.sh \ rscript_tocef.sh \ rscript_contains.sh \ rscript_bare_var_root.sh \ rscript_bare_var_root-empty.sh \ rscript_ipv42num.sh \ rscript_field.sh \ rscript_stop.sh \ rscript_stop2.sh \ rscript_prifilt.sh \ rscript_prifilt_negated_exact.sh \ rscript_optimizer1.sh \ rscript_optimizer_const_cmp.sh \ rscript_ruleset_call.sh \ rscript_ruleset_call-recursion-limit.sh \ rscript_ruleset_call_indirect-basic.sh \ rscript_ruleset_call_indirect-var.sh \ rscript_ruleset_call_indirect-invld.sh \ rscript_set_unset_invalid_var.sh \ rscript_set_modify.sh \ rscript_unaffected_reset.sh \ rscript_replace_complex.sh \ rscript_wrap2.sh \ rscript_wrap3.sh \ rscript_re_extract_i.sh \ rscript_re_extract.sh \ rscript_re_extract_loop.sh \ rscript_re_match_i.sh \ rscript_re_match.sh \ rscript_re_match-dbl_quotes.sh \ rscript_eq.sh \ rscript_eq_var.sh \ rscript_ge.sh \ rscript_ge_var.sh \ rscript_gt.sh \ rscript_gt_var.sh \ rscript_le.sh \ rscript_le_var.sh \ rscript_lt.sh \ rscript_lt_var.sh \ rscript_ne.sh \ rscript_ne_var.sh \ rscript_number_comparison_LE.sh \ rscript_number_comparison_LT.sh \ rscript_compare_str-numstr.sh \ rscript_compare_str-num.sh \ rscript_compare_numstr-str.sh \ rscript_compare_num-str.sh \ rscript_compare_numstr-numstr.sh \ rscript_compare_numstr-num.sh \ rscript_compare_num-numstr.sh \ rscript_compare_num-num.sh \ rscript_compare_str-str.sh \ rscript_num2ipv4.sh \ rscript_int2Hex.sh \ rscript_trim.sh \ rscript_substring.sh \ rscript_toupper.sh \ rscript_format_time.sh \ rscript_parse_time.sh \ rscript_is_time.sh \ rscript_is_in_subnet.sh \ rscript_script_error.sh \ rscript_parse_json.sh \ rscript_parse_json_issue.sh \ rscript_previous_action_suspended.sh \ rscript_str2num_negative.sh \ rscript_exists-yes.sh \ rscript_exists-yes2.sh \ rscript_exists-not1.sh \ rscript_exists-not2.sh \ rscript_exists-not3.sh \ rscript_exists-not4.sh \ rscript-config_enable-on.sh \ rscript_get_property.sh \ rscript_split.sh \ rscript_append_json.sh \ msg_json_set_regression.sh \ config_output-o-option.sh \ config_output-o-option-same-file.sh \ rs-cbool.sh \ rs-cnum.sh \ rs-substring.sh \ rs-int2hex.sh \ empty-prop-comparison.sh \ rs_optimizer_pri.sh \ cee_simple.sh \ cee_diskqueue.sh \ incltest.sh \ incltest_dir.sh \ incltest_dir_wildcard.sh \ incltest_dir_empty_wildcard.sh \ linkedlistqueue.sh \ lookup_table.sh \ lookup_table-daemon-shutdown.sh \ lookup_table-hup-backgrounded.sh \ lookup_table_no_hup_reload.sh \ container-noise-drop.sh \ debug-logfile-config-check.sh \ key_dereference_on_uninitialized_variable_space.sh \ array_lookup_table.sh \ sparse_array_lookup_table.sh \ lookup_table_duplicate.sh \ action-duplicate-name.sh \ lookup_table_bad_configs.sh \ lookup_table_rscript_reload.sh \ lookup_table_rscript_reload_without_stub.sh \ config_multiple_include.sh \ rscript_bool_constant_warning.sh \ config_enabled-off-action.sh \ include-obj-text-from-file.sh \ include-obj-text-from-file-noexist.sh \ multiple_lookup_tables.sh \ lookup_sparse_array_ipv4.sh \ parsertest-parse1.sh \ parsertest-parse1-udp.sh \ imudp-headerless-fromhost-ip.sh \ parsertest-parse2.sh \ parsertest-parse2-udp.sh \ parsertest-parse_8bit_escape.sh \ parsertest-parse_8bit_escape-udp.sh \ parsertest-parse3.sh \ parsertest-parse3-udp.sh \ parsertest-parse_invld_regex.sh \ parsertest-parse_invld_regex-udp.sh \ parsertest-parse-3164-buggyday.sh \ parsertest-parse-3164-buggyday-udp.sh \ parsertest-parse-nodate.sh \ parsertest-parse-nodate-udp.sh \ parsertest-snare_ccoff_udp.sh \ parsertest-snare_ccoff_udp2.sh TESTS_SKELETONS = \ omfwd-lb-1target-retry-test_skeleton.sh \ omfwd-lb-1target-retry-test_skeleton-TargetFail.sh TESTS_INACTIVE = \ prop-all-json-concurrency.sh TESTS_MMSNAREPARSE_MINIMAL = \ mmsnareparse-basic.sh \ mmsnareparse-json.sh \ mmsnareparse-syslog.sh \ mmsnareparse-comprehensive.sh \ mmsnareparse-value-types.sh \ mmsnareparse-enhanced-validation.sh \ mmsnareparse-sysmon.sh \ mmsnareparse-kerberos.sh \ mmsnareparse-custom.sh \ mmsnareparse-realworld-4624-4634-5140.sh \ mmsnareparse-trailing-extradata.sh \ mmsnareparse-trailing-extradata-regex.sh \ mmsnareparse-trailing-extradata-regex-anchor.sh TESTS_MMSNAREPARSE_VALGRIND = \ mmsnareparse-comprehensive-vg.sh TESTS_OMSENDERTRACK = \ omsendertrack-basic.sh \ omsendertrack-statefile.sh TESTS_OMSENDERTRACK_VALGRIND = \ omsendertrack-basic-vg.sh \ omsendertrack-statefile-vg.sh TESTS_LIBZSTD = \ zstd.sh TESTS_LIBZSTD_VALGRIND = \ zstd-vg.sh TESTS_LIBGCRYPT = \ queue-encryption-disk.sh \ queue-encryption-disk_keyfile.sh \ queue-encryption-disk_keyprog-invalid-len.sh \ queue-encryption-disk_keyprog.sh \ queue-encryption-da.sh TESTS_GNUTLS_WRONG_OPT = \ tcpflood_wrong_option_output.sh TESTS_OSSL_WRONG_OPT = \ tcpflood_wrong_option_output.sh TESTS_DEFAULT_VALGRIND = \ imuxsock-NUL-vg.sh \ omusrmsg-noabort-vg.sh \ omfile_hup-vg.sh \ gzipwr_hup-vg.sh \ imtcp-octet-framing-too-long-vg.sh \ smtradfile-vg.sh \ dnscache-TTL-0-vg.sh \ include-obj-outside-control-flow-vg.sh \ include-obj-in-if-vg.sh \ include-obj-text-vg.sh \ rscript_b64_decode-vg.sh \ rscript_parse_json-vg.sh \ rscript_backticks-vg.sh \ rscript_backticks_empty_envvar.sh \ rscript_backticks_static_text.sh \ rscript_backticks_braces_envvar.sh \ rscript-config_enable-off-vg.sh \ rscript_get_property-vg.sh \ prop-jsonmesg-vg.sh \ mmexternal-InvldProg-vg.sh \ internal-errmsg-memleak-vg.sh \ glbl-oversizeMsg-log-vg.sh \ rscript_set_memleak-vg.sh \ no-parser-vg.sh \ discard-rptdmsg-vg.sh \ discard-allmark-vg.sh \ failover-basic-vg.sh \ failover-rptd-vg.sh \ failover-no-basic-vg.sh \ failover-no-rptd-vg.sh \ timereported-utc-vg.sh \ udp-msgreduc-vg.sh \ udp-msgreduc-orgmsg-vg.sh \ tcp-msgreduc-vg.sh \ rscript_field-vg.sh \ rscript_number_comparison_LE-vg.sh \ rscript_compare_str-str-vg.sh \ rscript_compare_str-num-vg.sh \ rscript_compare_str-numstr-vg.sh \ rscript_compare_num-str-vg.sh \ rscript_compare_numstr-str-vg.sh \ rscript_compare_numstr-num-vg.sh \ rscript_compare_numstr-numstr-vg.sh \ rscript_compare_num-num-vg.sh \ rscript_compare_num-numstr-vg.sh \ unused_lookup_table-vg.sh \ lookup_table-vg.sh \ lookup_table_no_hup_reload-vg.sh \ array_lookup_table-vg.sh \ array_lookup_table_misuse-vg.sh \ sparse_array_lookup_table-vg.sh \ lookup_table_bad_configs-vg.sh \ lookup_table_rscript_reload-vg.sh \ lookup_table_rscript_reload_without_stub-vg.sh \ multiple_lookup_tables-vg.sh \ fac_local0-vg.sh \ badqi.sh \ threadingmq.sh \ threadingmqaq.sh \ func-substring-invld-startpos-vg.sh \ rscript_trim-vg.sh \ rscript_split-vg.sh \ rscript_append_json-vg.sh TESTS_LIBGCRYPT_VALGRIND = \ queue-encryption-disk_keyfile-vg.sh TESTS_LIBYAML = \ config-translate-rs-to-yaml.sh \ config-translate-rs-filter-actions.sh \ config-translate-rs-script-expressions.sh \ config-translate-rs-statements-to-yaml.sh \ config-translate-legacy-debian-default.sh \ config-translate-legacy-file-action.sh \ config-translate-yaml-to-rs.sh \ compat-configformat-yaml.sh \ compat-defaults-secure-dynafile-yaml.sh \ global-maxopenfiles-yaml.sh \ global-systemd-notifyreadydelay-yaml.sh \ action-ratelimit-drop.sh \ action-ratelimit-pace.sh \ action-ratelimit-reload.sh \ action-ratelimit-validation.sh \ ratelimit-many-named-configs.sh \ yaml-omfile-followsymlinks.sh \ ratelimit_hup.sh \ yaml-basic.sh \ yaml-basic-yamlonly.sh \ yaml-omfile-dynafilecachesize-invalid.sh \ yaml-include.sh \ yaml-ruleset-script.sh \ yaml-error.sh \ yaml-filter-actions.sh \ yaml-script-stop.sh \ yaml-script-call.sh \ yaml-script-localvar.sh \ yaml-script-msgvar.sh \ yaml-imfile-basic.sh \ yaml-propfilt-basic.sh \ yaml-propfilt-contains-longer-needle.sh \ yaml-statements-basic.sh \ yaml-statements-stop.sh \ yaml-statements-call.sh \ yaml-statements-unset.sh \ yaml-template-controlcharacters.sh \ yaml-template-list.sh \ $(TESTS_TEMPLATE_REGEX_BOUNDS_LIBYAML) \ yaml-template-subtree.sh \ yaml-allowed-sender-modern.sh \ yaml-statements-reload-lookup.sh \ yaml-lookup-table-duplicate.sh \ yaml-action-duplicate-name.sh TESTS_RATELIMIT_WATCH = \ ratelimit_policy_watch.sh \ ratelimit_policy_watch_debounce.sh \ ratelimit_policy_watch_invalid.sh \ ratelimit_policy_watch_multi.sh \ yaml-ratelimit-policywatch.sh TESTS_LIBYAML_IMPTCP_MMJSONPARSE = \ yaml-statements-foreach.sh \ yaml-statements-complex.sh TESTS_IMTCP = \ fromhost-port.sh \ fromhost-port-tuple.sh \ fromhost-port-async-ruleset.sh \ allowed-sender-tcp-ok.sh \ allowed-sender-tcp-fail.sh \ allowed-sender-tcp-zero-mask.sh \ allowed-sender-modern.sh \ allowed-sender-empty-array.sh \ allowed-sender-tcp-hostname-ok.sh \ allowed-sender-tcp-hostname-fail.sh \ allowed-sender-wildcard-invalid-bits.sh \ imtcp-discard-truncated-msg.sh \ imtcp-ruleset-no-queue-warning.sh \ imtcp-basic.sh \ rscript_parsehostnameandtag_off.sh \ imtcp_framing_regex.sh \ imtcp_framing_regex_maxmsg_overflow.sh \ imtcp-multiline.sh \ imtcp-spacelf-escape.sh \ imtcp-basic-hup.sh \ imtcp-shutdown-pending-accepts.sh \ imtcp-impstats-single-thread.sh \ imtcp-starvation-0.sh \ imtcp-starvation-1.sh \ imtcp-maxFrameSize.sh \ imtcp-msg-truncation-on-number.sh \ imtcp-msg-truncation-on-number2.sh \ imtcp-netns.sh \ imtcp-NUL.sh \ imtcp-NUL-rawmsg.sh \ parser-drop-trailing-cr.sh \ omfwd-rebind-tcp.sh \ imtcp_incomplete_frame_at_end.sh \ imtcp-multiport.sh \ imtcp-bigmessage-octetcounting.sh \ imtcp-bigmessage-octetstuffing.sh \ manytcp.sh \ imtcp_conndrop.sh \ imtcp_addtlframedelim.sh \ imtcp_no_octet_counted.sh \ imtcp_addtlframedelim_on_input.sh \ imtcp_spframingfix.sh \ imtcp-connection-msg-recieved.sh \ sndrcv.sh \ sndrcv_failover.sh \ sndrcv_gzip.sh \ sndrcv_udp_nonstdpt.sh \ sndrcv_udp_nonstdpt_v6.sh \ omfile-dynafile-traversal-default-template.sh \ omfile-dynafile-traversal-list-template.sh \ omfile-dynafile-traversal-permit-escape.sh \ omfile-dynafile-traversal-repro.sh \ omfile-dynafile-traversal-root-base.sh TESTS_IMTCP_STREAM_ALWAYS_ZLIB = \ imtcp-stream-always-zlib-basic.sh \ imtcp-stream-always-zlib-completion-release.sh \ imtcp-stream-always-zlib-flushoff.sh \ imtcp-stream-always-zlib-corrupt.sh \ imtcp-stream-always-zlib-truncated.sh \ imtcp-stream-always-zlib-fragmented-ratio.sh \ imtcp-stream-always-zlib-expansion-guard.sh \ imtcp-stream-always-zlib-z-prefix.sh TESTS_IMTCP_STREAM_ALWAYS_ZLIB_IMPSTATS = \ imtcp-stream-always-zlib-impstats.sh TESTS_IMTCP_STREAM_ALWAYS_ZSTD = \ imtcp-stream-always-zstd-basic.sh \ imtcp-stream-always-zstd-flushoff.sh \ imtcp-stream-always-zstd-corrupt.sh \ imtcp-stream-always-zstd-truncated.sh \ imtcp-stream-always-zstd-empty-close.sh \ imtcp-stream-always-zstd-window-guard.sh \ imtcp-stream-always-zstd-window-budget.sh \ imtcp-stream-always-zstd-secure-defaults.sh \ imtcp-stream-always-zstd-expansion-guard.sh \ imtcp-stream-always-zstd-to-zlib-mismatch.sh TESTS_IMTCP_STREAM_ALWAYS_ZSTD_YAML = \ yaml-imtcp-stream-always-zstd-secure-defaults.sh TESTS_IMTCP_STREAM_ALWAYS_ZSTD_IMPSTATS = \ imtcp-stream-always-zstd-impstats.sh TESTS_IMTCP_STREAM_ALWAYS_GNUTLS = \ imtcp-stream-always-zlib-tls-gtls.sh TESTS_IMTCP_STREAM_ALWAYS_MBEDTLS = \ imtcp-stream-always-zlib-tls-mbedtls.sh TESTS_IMTCP_STREAM_ALWAYS_OSSL = \ imtcp-stream-always-zlib-tls-ossl.sh TESTS_IMTCP_YAML = \ yaml-parser-drop-trailing-cr.sh \ yaml-imtcp-ruleset-no-queue-warning.sh \ yaml-imtcp-stream-always-zlib-basic.sh \ yaml-imtcp-spacelf-escape.sh \ yaml-omfile-dynafile-traversal-list-template.sh \ yaml-allowed-sender-modern.sh \ imtcp-persource-ratelimit.sh \ ratelimit-legacy-persource-discard.sh \ ratelimit-persource-shard-eviction.sh \ ratelimit-persource-repeat-summary.sh \ ratelimit-policy-persource-key-reload.sh \ ratelimit-policy-persource-topn-default-reload.sh \ ratelimit-policy-persource-mixed-invalid.sh TESTS_IMTCP_VALGRIND = \ imtcp-octet-framing-too-long-vg.sh \ omfwd-rebind-tcp-vg.sh TESTS_RATELIMIT = \ ratelimit_exclusivity.sh \ ratelimit_name.sh \ ratelimit_duplicate.sh \ omfwd_ratelimit_name.sh \ omelasticsearch_ratelimit_name.sh \ imklog_ratelimit_name.sh \ imuxsock_ratelimit_name.sh TESTS_RATELIMIT_YAML = \ imudp-persource-ratelimit-policy.sh \ imtcp-persource-port-keys.sh TESTS_RATELIMIT_IMPTCP_YAML = \ imptcp-persource-ratelimit-policy.sh \ imptcp-persource-port-keys.sh TESTS_IMPTCP_FROMHOST_PORT = \ imptcp-fromhost-port.sh TESTS_IMTCP_IMPSTATS = \ imtcp-impstats.sh TESTS_SNMP_MINIMAL = \ omsnmp_errmsg_no_params.sh TESTS_SNMP_FULL = \ sndrcv_omsnmpv1_udp.sh \ sndrcv_omsnmpv1_udp_dynsource.sh \ sndrcv_omsnmpv1_udp_invalidoid.sh TESTS_MMUTF8FIX = \ mmutf8fix_no_error.sh \ mmutf8fix_replacement_sequence.sh \ mmutf8fix_replacement_sequence_conflict.sh \ mmutf8fix_tag.sh TESTS_MMUTF8FIX_YAML = \ yaml-mmutf8fix-replacement-sequence.sh TESTS_MMUTF8FIX_SD = \ mmutf8fix_sd.sh TESTS_MMAITAG = \ mmaitag-basic.sh \ mmaitag-invalid-key.sh TESTS_MAIL = \ ommail_errmsg_no_params.sh \ ommail-smtp.sh \ ommail-sendmail.sh \ ommail-sendmail-body-off.sh \ ommail-sendmail-fail.sh \ ommail-sendmail-bad-binary.sh \ ommail-sendmail-exec-fail.sh \ ommail-sendmail-default-binary.sh TESTS_MAIL_MMJSONPARSE = \ ommail-subject-template-header-sendmail.sh \ ommail-subject-template-header-smtp.sh TESTS_MMANON = \ mmanon_with_debug.sh \ mmanon_random_32_ipv4.sh \ mmanon_random_cons_32_ipv4.sh \ mmanon_recognize_ipv4.sh \ mmanon_zero_12_ipv4.sh \ mmanon_zero_33_ipv4.sh \ mmanon_zero_8_ipv4.sh \ mmanon_simple_12_ipv4.sh \ mmanon_simple_33_ipv4.sh \ mmanon_simple_8_ipv4.sh \ mmanon_simple_mallformed_ipv4.sh \ mmanon_random_128_ipv6.sh \ mmanon_zero_128_ipv6.sh \ mmanon_zero_96_ipv6.sh \ mmanon_random_cons_128_ipv6.sh \ mmanon_zero_50_ipv6.sh \ mmanon_recognize_ipv6.sh \ mmanon_zero_64_ipv6.sh \ mmanon_both_modes_compatible.sh \ mmanon_recognize_ipembedded.sh \ mmanon_ipv6_port.sh \ mmanon_random_cons_128_ipembedded.sh \ mmanon_truncated_dotted_suffix.sh TESTS_CLICKHOUSE = \ clickhouse-template-option-stdsql.sh \ clickhouse-http-status-error.sh \ clickhouse-start.sh \ clickhouse-basic.sh \ clickhouse-dflt-tpl.sh \ clickhouse-retry-error.sh \ clickhouse-load.sh \ clickhouse-bulk.sh \ clickhouse-bulk-load.sh \ clickhouse-limited-batch.sh \ clickhouse-select.sh \ clickhouse-errorfile.sh \ clickhouse-wrong-quotation-marks.sh \ clickhouse-wrong-template-option.sh \ clickhouse-wrong-insert-syntax.sh \ clickhouse-stop.sh TESTS_CLICKHOUSE_VALGRIND = \ clickhouse-basic-vg.sh \ clickhouse-load-vg.sh \ clickhouse-bulk-vg.sh \ clickhouse-bulk-load-vg.sh TESTS_LIBFAKETIME = \ now_family_utc.sh \ now-utc.sh \ now-utc-ymd.sh \ now-utc-casecmp.sh \ now-unixtimestamp.sh \ timegenerated-ymd.sh \ timegenerated-uxtimestamp.sh \ timegenerated-uxtimestamp-invld.sh \ timegenerated-dateordinal.sh \ timegenerated-dateordinal-invld.sh \ template-property-timegenerated.sh \ template-property-timereceived.sh \ timegenerated-utc.sh \ timegenerated-utc-legacy.sh \ timereported-utc.sh \ timereported-utc-legacy.sh TESTS_MMNORMALIZE_FAKETIME = \ mmnormalize_processing_test1.sh \ mmnormalize_processing_test2.sh \ mmnormalize_processing_test3.sh \ mmnormalize_processing_test4.sh TESTS_PGSQL_CONFIG = \ pgsql-long-server-config.sh TESTS_PGSQL = \ pgsql-basic.sh \ pgsql-basic-cnf6.sh \ pgsql-basic-threads-cnf6.sh \ pgsql-template.sh \ pgsql-template-cnf6.sh \ pgsql-actq-mt-withpause.sh \ pgsql-template-threads-cnf6.sh TESTS_PGSQL_VALGRIND = \ pgsql-basic-vg.sh \ pgsql-template-vg.sh \ pgsql-basic-cnf6-vg.sh \ pgsql-template-cnf6-vg.sh \ pgsql-actq-mt-withpause-vg.sh TESTS_MYSQL = \ mysqld-start.sh \ mysql-basic.sh \ mysql-basic-cnf6.sh \ mysql-asyn.sh \ mysql-actq-mt.sh \ mysql-actq-mt-withpause.sh \ mysql-unavailable-transaction.sh \ action-tx-single-processing.sh \ action-tx-errfile-maxsize.sh \ action-tx-errfile.sh \ mysqld-stop.sh TESTS_MYSQL_VALGRIND = \ mysql-basic-vg.sh \ mysql-asyn-vg.sh \ mysql-actq-mt-withpause-vg.sh TESTS_LIBDBI = \ libdbi-basic.sh \ libdbi-asyn.sh TESTS_LIBDBI_VALGRIND = \ libdbi-basic-vg.sh TESTS_FMHTTP = \ rscript_http_request.sh TESTS_FMHTTP_VALGRIND = \ rscript_http_request-vg.sh TESTS_ROOT = \ sndrcv_udp.sh \ imuxsock_logger_root.sh \ imuxsock_traillf_root.sh \ imuxsock_ccmiddle_root.sh \ imklog_permitnonkernelfacility_root.sh TESTS_ROOT_IP = \ tcp_forwarding_ns_tpl.sh TESTS_ROOT_VALGRIND = \ mmexternal-SegFault-empty-jroot-vg.sh TESTS_OMHTTP_FLAKY = \ omhttp-batch-retry-metadata.sh TESTS_OMHTTP_FLAKY_VALGRIND = \ omhttp-batch-retry-metadata-vg.sh TESTS_IMJOURNAL = \ imjournal-basic.sh \ imjournal-namespace-remote-conflict.sh \ imjournal-statefile.sh \ imjournal-statefile-symlink.sh \ imjournal_ratelimit_name.sh TESTS_IMJOURNAL_VALGRIND = \ imjournal-basic-vg.sh \ imjournal-statefile-vg.sh TESTS_OMJOURNAL = \ omjournal-abort-template.sh \ omjournal-abort-no-template.sh \ omjournal-basic-template.sh \ omjournal-basic-no-template.sh TESTS_IMPROG = \ improg_errmsg_no_params.sh \ improg_child_killed.sh \ improg_prog_simple.sh \ improg_prog_confirm.sh \ improg_prog_confirm_killonclose.sh \ improg_prog_killonclose.sh \ improg_simple_multi.sh TESTS_IMPROG_VALGRIND = \ improg_errmsg_no_params-vg.sh \ improg_prog_simple-vg.sh TESTS_MMDARWIN = \ mmdarwin_errmsg_no_params.sh \ mmdarwin_errmsg_no_sock.sh TESTS_MMDARWIN_VALGRIND = \ mmdarwin_errmsg_no_sock-vg.sh TESTS_OMPROG = \ omprog-defaults.sh \ omprog-output-capture.sh \ omprog-output-capture-mt.sh \ omprog-feedback.sh \ omprog-feedback-mt.sh \ omprog-feedback-timeout.sh \ omprog-close-unresponsive.sh \ omprog-close-unresponsive-noterm.sh \ omprog-restart-terminated.sh \ omprog-restart-terminated-outfile.sh \ omprog-diskq-restart-save.sh \ segmented-diskqueue-omprog-restart-save.sh \ omprog-single-instance.sh \ omprog-single-instance-outfile.sh \ omprog-invalid-args.sh \ omprog-empty-template.sh \ omprog-transactions.sh \ omprog-resume-interval.sh \ omprog-if-error.sh \ omprog-transactions-failed-messages.sh \ omprog-transactions-failed-commits.sh TESTS_OMPROG_VALGRIND = \ omprog-defaults-vg.sh \ omprog-output-capture-vg.sh \ omprog-feedback-vg.sh \ omprog-close-unresponsive-vg.sh \ omprog-restart-terminated-vg.sh \ omprog-single-instance-vg.sh \ omprog-transactions-vg.sh TESTS_OMHTTP = \ omhttp-auth.sh \ omhttp-basic.sh \ omhttp-basic-ignorecodes.sh \ omhttp-datafail-continues.sh \ omhttp-datafail-continues-batch.sh \ omhttp-datafail-continues-batch-single.sh \ omhttp-batch-fail-with-400.sh \ omhttp-batch-jsonarray-compress.sh \ omhttp-batch-jsonarray-retry.sh \ omhttp-batch-jsonarray.sh \ omhttp-batch-kafkarest-retry.sh \ omhttp-batch-kafkarest.sh \ omhttp-batch-lokirest-retry.sh \ omhttp-batch-lokirest.sh \ omhttp-profile-loki.sh \ omhttp-batch-newline.sh \ omhttp-retry.sh \ omhttp-retry-ruleset-recovery.sh \ omhttp-retry-timeout.sh \ wti-shutdown-saveonshutdown-omhttp.sh \ omhttp-httpheaderkey.sh \ omhttp-multiplehttpheaders.sh \ omhttp-dynrestpath.sh \ omhttp-batch-dynrestpath.sh \ omhttp_ratelimit_name.sh TESTS_OMHTTP_VALGRIND = \ omhttp-auth-vg.sh \ omhttp-basic-vg.sh \ omhttp-basic-ignorecodes-vg.sh \ omhttp-batch-jsonarray-compress-vg.sh \ omhttp-batch-jsonarray-retry-vg.sh \ omhttp-batch-jsonarray-vg.sh \ omhttp-batch-kafkarest-retry-vg.sh \ omhttp-batch-lokirest-retry-vg.sh \ omhttp-retry-vg.sh \ omhttp-retry-timeout-vg.sh \ omhttp-batch-lokirest-vg.sh TESTS_OMHTTP_VICTORIALOGS = \ omhttp-victorialogs-jsonline.sh TESTS_OMOTEL = \ omotel-http-batch.sh \ omotel-basic.sh \ omotel-batch.sh \ omotel-compression.sh \ omotel-protobuf-basic.sh \ omotel-proxy.sh \ omotel-tls.sh \ omotel-trace-correlation.sh TESTS_KAFKA_SELFTEST = \ kafka-selftest.sh TESTS_OMKAFKA_NO_SERVICE = \ omkafka-failedmsg-malformed.sh \ omkafka-unreachable-shutdown.sh TESTS_KAFKA = \ omkafka.sh \ omkafkadynakey.sh \ omkafka-headers.sh \ imkafka.sh \ imkafka-backgrounded.sh \ imkafka-config-err-ruleset.sh \ imkafka-config-err-param.sh \ imkafka-hang-on-no-kafka.sh \ imkafka-hang-other-action-on-no-kafka.sh \ imkafka_multi_single.sh \ imkafka_multi_group.sh \ imkafka_multi_topic.sh \ sndrcv_kafka.sh \ sndrcv_kafka_multi_topics.sh TESTS_KAFKA_VALGRIND = \ omkafka-vg.sh \ imkafka-vg.sh TESTS_OMAZUREEVENTHUBS = \ omazureeventhubs-basic.sh \ omazureeventhubs-basic-url.sh \ omazureeventhubs-list.sh \ omazureeventhubs-stress.sh \ omazureeventhubs-interrupt.sh TESTS_OMAZUREEVENTHUBS_VALGRIND = \ omazureeventhubs-basic-vg.sh \ omazureeventhubs-interrupt-vg.sh TESTS_OMAZUREDCE = \ omazuredce-no-dcr-id.sh \ omazuredce-default-template.sh \ omazuredce-bad-template.sh \ omazuredce-good-template.sh \ omazuredce-basic.sh \ omazuredce-compression.sh \ omazuredce-basic-url.sh \ omazuredce-batch.sh \ omazuredce-interrupt.sh \ omazuredce-timer.sh TESTS_OMAZUREDCE_VALGRIND = \ omazuredce-basic-vg.sh TESTS_OMAZUREDCE_YAML = \ yaml-omazuredce-compression.sh TESTS_OMAWSLOGSHLC = \ omawslogshlc-missing-region.sh \ omawslogshlc-basic.sh \ omawslogshlc-batch.sh TESTS_OMAWSLOGSHLC_IMTCP = \ omawslogshlc-event-too-large.sh TESTS_IMDOCKER = \ imdocker-basic.sh \ imdocker-image-name.sh \ imdocker-since-deleted-anchor.sh \ imdocker-long-logline.sh \ imdocker-long-options.sh \ imdocker-new-logs-from-start.sh \ imdocker-multi-line.sh TESTS_IMDOCKER_VALGRIND = \ imdocker-basic-vg.sh \ imdocker-image-name-vg.sh \ imdocker-long-logline-vg.sh \ imdocker-new-logs-from-start-vg.sh \ imdocker-multi-line-vg.sh TESTS_IMCZMQ = \ imczmq-topic-too-long.sh TESTS_IMHTTP = \ imhttp-post-payload.sh \ imhttp-post-payload-basic-auth.sh \ imhttp-post-payload-api-key-auth.sh \ imhttp-post-payload-auth-header-limits.sh \ imhttp-post-payload-mixed-auth.sh \ imhttp-post-payload-query-params.sh \ imhttp-post-payload-large.sh \ imhttp-post-payload-content-length-limit.sh \ imhttp-post-payload-multi.sh \ imhttp-post-payload-multi-lf.sh \ imhttp-post-payload-compress.sh \ imhttp-post-payload-invalid-gzip.sh \ imhttp-post-payload-compress-size-limit.sh \ imhttp-post-payload-octet-oversize.sh \ imhttp-post-payload-basic-auth-challenge.sh \ imhttp-getrequest-file.sh \ imhttp-healthcheck.sh \ imhttp-metrics.sh \ imhttp-healthcheck-api-key-auth.sh \ imhttp-metrics-api-key-auth.sh \ imhttp_ratelimit_name.sh TESTS_IMHTTP_VALGRIND = \ imhttp-post-payload-vg.sh \ imhttp-post-payload-basic-auth-vg.sh \ imhttp-post-payload-query-params-vg.sh \ imhttp-post-payload-large-vg.sh \ imhttp-post-payload-multi-vg.sh \ imhttp-post-payload-multi-lf-vg.sh \ imhttp-post-payload-compress-vg.sh \ imhttp-getrequest-file-vg.sh TESTS_IMBEATS = \ imbeats-basic.sh \ imbeats-compressed.sh \ imbeats-seq-cumulative-two-windows.sh \ imbeats-seq-cumulative-after-multi-event-window.sh \ imbeats-seq-reset-rejected.sh \ imbeats-metadata-collision.sh \ imbeats-elastic-agent-windows-fixture.sh \ imbeats-limits.sh \ imbeats-shutdown-open-session.sh \ imbeats-maxsessions.sh \ imbeats-maxsessions-cap-warning.sh \ imbeats-multiplex-idle-sessions.sh \ imbeats-submit-timeout.sh \ imbeats-json-trailing-data.sh \ imbeats-filebeat-docker.sh TESTS_IMBEATS_OPENSSL = \ imbeats-tls-listener-rearm.sh TESTS_IMBEATS_IMPSTATS = \ imbeats-compressed-window-overflow.sh \ imbeats-compressed-malformed.sh \ imbeats-limits-impstats.sh \ imbeats-resource-budget.sh TESTS_IMBEATS_YAML = \ yaml-imbeats-basic.sh \ yaml-imbeats-session-timeouts.sh TESTS_IMBEATS_ELASTICSEARCH = \ imbeats-filebeat-omelasticsearch-docker.sh TESTS_OMRABBITMQ = \ omrabbitmq_no_params.sh \ omrabbitmq_params_missing0.sh \ omrabbitmq_params_missing1.sh \ omrabbitmq_params_missing2.sh \ omrabbitmq_params_invalid0.sh \ omrabbitmq_params_invalid1.sh \ omrabbitmq_params_invalid2.sh \ omrabbitmq_params_invalid3.sh \ omrabbitmq_data_1server.sh \ omrabbitmq_data_2servers.sh \ omrabbitmq_error_server0.sh \ omrabbitmq_error_server1.sh \ omrabbitmq_error_server2.sh \ omrabbitmq_error_server3.sh \ omrabbitmq_json.sh \ omrabbitmq_raw.sh TESTS_OMRABBITMQ_VALGRIND = \ omrabbitmq_data_1server-vg.sh TESTS_IMHIREDIS = \ imhiredis-stream-readfrom-too-long.sh \ imhiredis-queue.sh \ imhiredis-queue-lpop.sh \ imhiredis-redis-restart.sh \ imhiredis-redis-start-after.sh \ imhiredis-subscribe.sh \ imhiredis-stream.sh \ imhiredis-stream-from-beginning.sh \ imhiredis-stream-consumerGroup-ack.sh \ imhiredis-stream-consumerGroup-noack.sh \ imhiredis-stream-consumerGroup-reclaim.sh TESTS_IMHIREDIS_VALGRIND = \ imhiredis-queue-vg.sh \ imhiredis-queue-lpop-vg.sh \ imhiredis-redis-restart-vg.sh \ imhiredis-redis-start-after-vg.sh \ imhiredis-subscribe-vg.sh \ imhiredis-stream-vg.sh \ imhiredis-stream-from-beginning-vg.sh \ imhiredis-stream-consumerGroup-ack-vg.sh \ imhiredis-stream-consumerGroup-noack-vg.sh \ imhiredis-stream-consumerGroup-reclaim-vg.sh TESTS_OMHIREDIS = \ omhiredis-dynakey.sh \ omhiredis-publish.sh \ omhiredis-queue-rpush.sh \ omhiredis-queue.sh \ omhiredis-set.sh \ omhiredis-setex.sh \ omhiredis-template.sh \ omhiredis-withpass.sh \ omhiredis-wrongpass.sh \ omhiredis-stream-ack.sh \ omhiredis-stream-capped.sh \ omhiredis-stream-del.sh \ omhiredis-stream-dynack.sh \ omhiredis-stream-outfield.sh \ omhiredis-stream.sh TESTS_OMHIREDIS_VALGRIND = \ omhiredis-dynakey-vg.sh \ omhiredis-publish-vg.sh \ omhiredis-queue-rpush-vg.sh \ omhiredis-queue-vg.sh \ omhiredis-set-vg.sh \ omhiredis-setex-vg.sh \ omhiredis-template-vg.sh \ omhiredis-withpass-vg.sh \ omhiredis-wrongpass-vg.sh \ omhiredis-stream-ack-vg.sh \ omhiredis-stream-capped-vg.sh \ omhiredis-stream-del-vg.sh \ omhiredis-stream-dynack-vg.sh \ omhiredis-stream-outfield-vg.sh \ omhiredis-stream-vg.sh TESTS_IMPSTATS = \ impstats-hup.sh \ impstats-overwrite.sh \ impstats-no-overwrite.sh \ perctile-invalid-percentile.sh \ perctile-simple.sh \ dynstats.sh \ dynstats_overflow.sh \ dynstats_reset.sh \ dynstats_ctr_reset.sh \ dynstats_nometric.sh \ no-dynstats-json.sh \ no-dynstats.sh \ stats-json.sh \ stats-prometheus.sh \ stats-prometheus-escaping.sh \ dynstats-json.sh \ stats-cee.sh \ stats-json-es.sh \ dynstats_reset_without_pstats_reset.sh \ dynstats_prevent_premature_eviction.sh \ dynstats-persist.sh \ dynstats-duplicate-name.sh \ yaml-dynstats-duplicate-name.sh \ omfwd-lb-2target-impstats.sh \ omfwd_fast_imuxsock.sh \ omfwd_impstats-udp.sh \ omfwd_impstats-tcp.sh TESTS_IMPSTATS_PUSH = \ impstats-push-basic.sh \ impstats-push-tls-missing-key.sh TESTS_IMPSTATS_VALGRIND = \ perctile-simple-vg.sh \ dynstats-vg.sh \ dynstats_reset-vg.sh \ dynstats_overflow-vg.sh \ dynstats-json-vg.sh \ stats-json-vg.sh \ stats-cee-vg.sh \ dynstats_prevent_premature_eviction-vg.sh \ dynstats-persist-vg.sh TESTS_IMPTCP = \ manyptcp.sh \ imptcp-epoll-add-failure.sh \ imptcp_framing_regex.sh \ imptcp_framing_regex-oversize.sh \ imptcp_large.sh \ imptcp-connection-msg-disabled.sh \ imptcp-connection-msg-received.sh \ imptcp-discard-truncated-msg.sh \ imptcp-discard-truncated-msg-same-session.sh \ imptcp_addtlframedelim.sh \ imptcp_conndrop.sh \ imptcp_no_octet_counted.sh \ imptcp-oversize-errorfile-truncate.sh \ imptcp_multi_line.sh \ imptcp_spframingfix.sh \ imptcp_maxsessions.sh \ imptcp_nonProcessingPoller.sh \ imptcp_veryLargeOctateCountedMessages.sh \ imptcp-basic-hup.sh \ imptcp-NUL.sh \ imptcp-NUL-rawmsg.sh \ imptcp-compression-none-pmnull.sh \ imptcp-compression-none-legacy-single.sh \ imptcp-stream-compression-auto.sh \ imptcp-stream-compression-auto-zlib-prefix-plain.sh \ imptcp-stream-auto-z-prefix.sh \ imptcp-stream-auto-legacy-single.sh \ rscript_random.sh \ rscript_hash32.sh \ rscript_hash64.sh \ rscript_replace.sh \ omfile-sizelimitcmd-many.sh \ omfile-outchannel-many.sh TESTS_IMPTCP_STREAM_ALWAYS = \ imptcp-stream-always-basic.sh \ imptcp-stream-always-flushoff.sh \ imptcp-stream-always-corrupt.sh \ imptcp-stream-always-truncated.sh \ imptcp-stream-always-z-prefix.sh TESTS_IMPTCP_STREAM_ALWAYS_IMPSTATS = \ imptcp-stream-always-impstats.sh TESTS_IMPTCP_VALGRIND = \ imptcp-octet-framing-too-long-vg.sh \ imptcp_conndrop-vg.sh TESTS_IMPTCP_FMHASH_VALGRIND = \ rscript_hash32-vg.sh \ rscript_hash64-vg.sh TESTS_IMPTCP_FMUNFLATTEN = \ rscript_unflatten_arg1_unsuitable.sh \ rscript_unflatten_arg2_invalid.sh \ rscript_unflatten_conflict1.sh \ rscript_unflatten_conflict2.sh \ rscript_unflatten_conflict3.sh \ rscript_unflatten_key_truncated.sh \ rscript_unflatten_non_object.sh \ rscript_unflatten_object.sh \ rscript_unflatten_object_exclamation.sh TESTS_IMPTCP_FMUNFLATTEN_VALGRIND = \ rscript_unflatten_arg1_unsuitable-vg.sh \ rscript_unflatten_arg2_invalid-vg.sh \ rscript_unflatten_conflict1-vg.sh \ rscript_unflatten_conflict2-vg.sh \ rscript_unflatten_conflict3-vg.sh \ rscript_unflatten_key_truncated-vg.sh \ rscript_unflatten_non_object-vg.sh \ rscript_unflatten_object-vg.sh \ rscript_unflatten_object_exclamation-vg.sh TESTS_IMPTCP_FFAUP = \ rscript_faup_all.sh \ rscript_faup_all_2.sh \ rscript_faup_all_empty.sh \ rscript_faup_scheme.sh \ rscript_faup_credential.sh \ rscript_faup_subdomain.sh \ rscript_faup_domain.sh \ rscript_faup_domain_without_tld.sh \ rscript_faup_host.sh \ rscript_faup_tld.sh \ rscript_faup_port.sh \ rscript_faup_resource_path.sh \ rscript_faup_query_string.sh \ rscript_faup_fragment.sh \ rscript_faup_mozilla_tld.sh TESTS_IMPTCP_FFAUP_VALGRIND = \ rscript_faup_all_vg.sh \ rscript_faup_all_2_vg.sh \ rscript_faup_all_empty_vg.sh \ rscript_faup_scheme_vg.sh \ rscript_faup_credential_vg.sh \ rscript_faup_subdomain_vg.sh \ rscript_faup_domain_vg.sh \ rscript_faup_domain_without_tld_vg.sh \ rscript_faup_host_vg.sh \ rscript_faup_tld_vg.sh \ rscript_faup_port_vg.sh \ rscript_faup_resource_path_vg.sh \ rscript_faup_query_string_vg.sh \ rscript_faup_fragment_vg.sh \ rscript_faup_mozilla_tld_vg.sh TESTS_FMPCRE = \ ffmpcre-basic.sh TESTS_MMPSTRUCDATA = \ mmpstrucdata.sh \ mmpstrucdata-escaping.sh \ mmpstrucdata-case.sh \ mmpstrucdata-container-null.sh \ mmpstrucdata-large-sd.sh \ mmpstrucdata-max-sd-size.sh \ mmpstrucdata-rfc3164-skip.sh \ yaml-mmpstrucdata-container-null.sh TESTS_MMPSTRUCDATA_VALGRIND = \ mmpstrucdata-vg.sh \ mmpstrucdata-invalid-vg.sh TESTS_MMRFC5424ADDHMAC = \ mmrfc5424addhmac-long-sdid.sh TESTS_MMRM1STSPACE = \ mmrm1stspace-basic.sh TESTS_PMNULL = \ pmnull-basic.sh \ pmnull-withparams.sh TESTS_OMSTDOUT = \ omstdout-basic.sh \ omstdout-empty-template.sh TESTS_LIBYAML_IMTCP = \ config-translate-rs-roundtrip.sh \ config-translate-yaml-roundtrip.sh \ yaml-include-recursion.sh TESTS_LIBYAML_IMTCP_OSSL = \ yaml-imtcp-tls-ossl-prioritize-san-reject-cn.sh TESTS_LIBYAML_OSSL = \ yaml-omfwd-tls-ossl-pkcs11-module-defaults.sh TESTS_LIBYAML_IMHTTP = \ yaml-imhttp-apikeyfile.sh \ yaml-imhttp-metrics-apikeyfile.sh TESTS_LIBYAML_OMSTDOUT = \ config-translate-legacy-warning.sh TESTS_PMNORMALIZE = \ pmnormalize-basic.sh \ pmnormalize-invld-rulebase.sh \ pmnormalize-rule.sh \ pmnormalize-rule_and_rulebase.sh \ pmnormalize-neither_rule_rulebase.sh \ pmnormalize-rule_invld-data.sh TESTS_PMNORMALIZE_DEBUG = \ pmnormalize-debug.sh TESTS_PMNORMALIZE_YAML = \ yaml-pmnormalize-debug.sh TESTS_PMNORMALIZE_VALGRIND = \ pmnormalize-basic-vg.sh \ pmnormalize-invld-rulebase-vg.sh \ pmnormalize-rule-vg.sh \ pmnormalize-rule_and_rulebase-vg.sh \ pmnormalize-neither_rule_rulebase-vg.sh \ pmnormalize-rule_invld-data-vg.sh TESTS_MMNORMALIZE = \ msgvar-concurrency-array.sh \ msgvar-concurrency-array-event.tags.sh \ mmexternal-mmnormalize-json-tree.sh \ mmnormalize-hup-reload.sh \ mmnormalize_rule_from_string.sh \ mmnormalize_rule_from_array.sh \ mmnormalize_parsesuccess.sh TESTS_MMNORMALIZE_DEBUG = \ mmnormalize-debug.sh TESTS_MMNORMALIZE_YAML = \ yaml-mmnormalize-debug.sh TESTS_MMNORMALIZE_TURBO = \ mmnormalize-turbo-message-lifecycle.sh \ mmnormalize-turbo-hup-tsan.sh TESTS_MMNORMALIZE_TURBO_YAML = \ yaml-mmnormalize-turbo.sh TESTS_MMNORMALIZE_VALGRIND = \ mmnormalize_parsesuccess-vg.sh TESTS_MMNORMALIZE_IMPTCP = \ mmnormalize_regex_defaulted.sh \ mmnormalize_regex_disabled.sh \ mmnormalize_variable.sh \ mmnormalize_tokenized.sh TESTS_MMNORMALIZE_REGEX = \ mmnormalize_regex.sh TESTS_MMLEEFPARSE = \ mmleefparse_basic.sh TESTS_MMJSONPARSE_PART1 = \ mmjsonparse_qradar.sh \ mmjsonparse-w-o-cookie.sh \ mmjsonparse-w-o-cookie-multi-spaces.sh \ mmjsonparse-find-json-basic.sh \ mmjsonparse-find-json-trailing.sh \ mmjsonparse-find-json-scan-limit.sh \ mmjsonparse-find-json-invalid.sh \ mmjsonparse-find-json-invalid-mode.sh \ mmjsonparse-find-json-conflict.sh \ mmjsonparse-find-json-parser-validation.sh TESTS_MMJSONPARSE_IMPSTATS = \ mmjsonparse-invalid-containerName.sh \ wtpShutdownAll-assertionFailure.sh TESTS_MMJSONPARSE_IMPTCP = \ mmjsonparse_simple.sh \ imptcp-oversize-message-display.sh \ imptcp-msg-truncation-on-number.sh \ imptcp-msg-truncation-on-number2.sh \ imtcp-netns.sh \ imptcp-maxFrameSize-parameter.sh \ mmjsonparse_cim.sh \ mmjsonparse_cim2.sh \ mmjsonparse_localvar.sh \ json_array_subscripting.sh \ json_array_looping.sh \ json_object_looping.sh \ json_nonarray_looping.sh TESTS_MMJSONPARSE_VALGRIND = \ mmjsonparse_extra_data-vg.sh \ mmjsonparse-find-json-conflict-vg.sh \ json_null_array-vg.sh \ json_object_looping-vg.sh \ json_array_looping-vg.sh \ json_object_suicide_in_loop-vg.sh \ json_null-vg.sh TESTS_MMJSONPARSE_PART2 = \ stop_when_array_has_element.sh \ json_null_array.sh \ json_null.sh \ json_var_cmpr.sh \ json_var_case.sh TESTS_MMJSONTRANSFORM_IMTCP = \ mmjsontransform-basic.sh TESTS_MMJSONTRANSFORM_LIBYAML = \ mmjsontransform-policy-basic.sh TESTS_MMJSONTRANSFORM_WATCH = \ mmjsontransform-policy-watch.sh \ mmjsontransform-policy-watch-invalid.sh \ yaml-mmjsontransform-policywatch.sh TESTS_MMJSONTRANSFORM_MMJSONPARSE = \ data_pipeline-qradar.sh TESTS_MMDBLOOKUP = \ mmdb-open-missing.sh \ mmdb.sh \ mmdb-space.sh \ mmdb-container.sh \ mmdb-container-empty.sh \ mmdb-compound.sh \ mmdb-multilevel.sh TESTS_MMDBLOOKUP_VALGRIND = \ mmdb-open-missing-vg.sh \ mmdb-vg.sh \ mmdb-multilevel-vg.sh TESTS_GNUTLS = \ gtls-absolute-module-path.sh \ imtcp-tls-basic.sh \ tcpflood-gtls-priority-invalid.sh \ imtcp-tls-input-basic.sh \ imtcp-tls-input-2certs.sh \ imtcp-tls-basic-verifydepth.sh \ imtcp-tls-gtls-revocationcheck-error.sh \ imtcp_conndrop_tls.sh \ imtcp-tls-gibberish.sh \ sndrcv_tls_anon_rebind.sh \ sndrcv_tls_anon_hostname.sh \ sndrcv_tls_anon_ipv4.sh \ sndrcv_tls_anon_ipv6.sh \ sndrcv_tls_certless_clientonly.sh \ sndrcv_tls_gtls_servercert_gtls_clientanon.sh \ sndrcv_tls_gtls_servercert_gtls_clientanon_legacy.sh \ sndrcv_tls_gtls_serveranon_gtls_clientanon.sh \ sndrcv_tls_priorityString.sh \ sndrcv_tls_certvalid.sh \ sndrcv_tls_certvalid_action_level.sh \ sndrcv_tls_certvalid_expired.sh \ sndrcv_tls_certvalid_expired_defaultmode.sh \ sndrcv_tls_certvalid_revoked.sh \ imtcp-tls-gtls-crl.sh \ sndrcv_tls_client_missing_cert.sh \ imtcp-tls-no-lstn-startup.sh \ imtcp-tls-gtls-x509fingerprint-invld.sh \ imtcp-tls-gtls-x509fingerprint.sh \ imtcp-tls-gtls-x509name-invld.sh \ imtcp-tls-gtls-x509name-nul-san.sh \ imtcp-tls-gtls-x509name.sh \ imtcp-tls-gtls-x509name-legacy.sh \ omfwd-tls-gtls-no-sni.sh \ omfwd-tls-gtls-auto-sni.sh \ omfwd-tls-gtls-configured-sni.sh \ sndrcv_tls_gtls_native_pq_group.sh \ imtcp-drvr-in-input-basic.sh \ imtcp-multi-drvr-basic.sh \ imtcp-multi-drvr-basic-parallel.sh TESTS_GNUTLS_VALGRIND = \ imtcp-tls-basic-vg.sh \ imtcp_conndrop_tls-vg.sh \ manytcp-too-few-tls-vg.sh TESTS_GNUTLS_OPENSSL = \ omfwd-tls-gtls-module-files-mtls.sh \ omfwd-tls-gtls-module-pkcs11-defaults-isolation.sh \ imtcp-multi-drvr-basic-ptcp_gtls_ossl.sh TESTS_MBEDTLS = \ imtcp-multi-drvr-basic-ptcp_gtls_mbedtls.sh \ imtcp-tls-mbedtls-basic.sh \ imtcp-tls-mbedtls-basic-verifydepth.sh \ imtcp-tls-mbedtls-error-ca.sh \ imtcp-tls-mbedtls-error-cert.sh \ imtcp-tls-mbedtls-error-key2.sh \ imtcp-tls-mbedtls-error-key.sh \ imtcp-tls-mbedtls-input-basic.sh \ imtcp-tls-mbedtls-x509invalid.sh \ imtcp-tls-mbedtls-x509name_invalid.sh \ imtcp-tls-mbedtls-x509name.sh \ imtcp-tls-mbedtls-x509valid.sh \ imtcp-tls-mbedtls-x509fingerprint-invld.sh \ imtcp-tls-mbedtls-x509fingerprint.sh \ imtcp-tls-mbedtls-x509name-multi-wildcard.sh \ sndrcv_tls_certless_clientonly_mbedtls.sh \ sndrcv_tls_gtls_serveranon_mbedtls_clientanon.sh \ sndrcv_tls_gtls_servercert_mbedtls_clientanon.sh \ sndrcv_tls_mbedtls_certvalid_action_level.sh \ sndrcv_tls_mbedtls_certvalid_expired.sh \ sndrcv_tls_mbedtls_certvalid_revoked.sh \ sndrcv_tls_mbedtls_certvalid.sh \ sndrcv_tls_mbedtls_servercert_clientcert.sh \ sndrcv_tls_mbedtls_servercert_mbedtls_clientanon.sh \ sndrcv_tls_servercert_mbedtls_clientanon.sh \ sndrcv_tls_mbedtls_certvalid_expired_autrzd.sh \ sndrcv_tls_mbedtls_gnutlspriorityString_no_suite_in_common.sh \ sndrcv_tls_mbedtls_gnutlspriorityString_suite_in_common.sh \ sndrcv_tls_servercert_bad_eku_chk_mbedtls_clientanon.sh \ sndrcv_tls_servercert_bad_eku_no_chk_mbedtls_clientanon.sh TESTS_MBEDTLS_VALGRIND = \ imtcp-tls-mbedtls-basic-vg.sh \ imtcp-tls-mbedtls-basic-brokenhandshake-vg.sh TESTS_OSSL = \ imtcp-tls-ossl-input-2certs.sh \ imtcp-tls-ossl-basic-verifydepth.sh \ imtcp-tls-ossl-revocationcheck-off.sh \ imtcp-tls-ossl-invalid-verifydepth.sh \ sndrcv_tls_ossl_certvalid.sh \ sndrcv_tls_ossl_certvalid_action_level.sh \ sndrcv_tls_ossl_certvalid_tlscommand.sh \ sndrcv_tls_ossl_certvalid_ciphers.sh \ sndrcv_tls_ossl_intermediate_ca_chain.sh \ imtcp-tls-ossl-x509valid.sh \ imtcp-tls-ossl-x509name.sh \ imtcp-tls-ossl-prioritize-san-cn-fallback.sh \ imtcp-tls-ossl-prioritize-san-reject-cn.sh \ imtcp-tls-ossl-manycon.sh \ imtcp-tls-ossl-x509name-wildcard.sh \ imtcp-tls-ossl-x509name-wildcard-invld.sh \ imtcp-tls-ossl-x509fingerprint.sh \ imtcp-tls-ossl-error-ca.sh \ imtcp-tls-ossl-error-cert.sh \ imtcp-tls-ossl-error-key.sh TESTS_OSSL_OPENSSL = \ imtcp-tls-ossl-crl.sh \ imtcp-tls-ossl-basic.sh \ imtcp-tls-ossl-basic-stress.sh \ imtcp-tls-ossl-input-basic.sh \ imtcp-tls-ossl-basic-tlscommands.sh \ imtcp-tls-ossl-error-key2.sh \ omfwd-tls-ossl-pkcs11-error-ca.sh \ omfwd-tls-ossl-pkcs11-error-cert.sh \ omfwd-tls-ossl-pkcs11-error-key.sh \ sndrcv_tls_ossl_native_pq_group.sh \ sndrcv_tls_ossl_anon_ipv4.sh \ sndrcv_tls_ossl_anon_ipv6.sh \ sndrcv_tls_ossl_anon_rebind.sh \ sndrcv_tls_ossl_anon_ciphers.sh \ sndrcv_tls_ossl_serveranon_ossl_clientanon.sh \ sndrcv_tls_ossl_servercert_ossl_clientanon.sh \ sndrcv_tls_ossl_certvalid_expired.sh \ sndrcv_tls_ossl_certvalid_revoked.sh TESTS_OSSL_OPENSSL_VALGRIND = \ omfwd-tls-ossl-files-mtls-vg.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-ecdsa-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-negative-vg.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-ecdsa-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-negative-vg.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-error-ca-vg.sh \ omfwd-tls-ossl-pkcs11-error-cert-vg.sh \ omfwd-tls-ossl-pkcs11-error-key-vg.sh \ omfwd-tls-ossl-pkcs11-key-mtls-ecdsa-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-key-mtls-vg.sh \ omfwd-tls-ossl-pkcs11-key-mtls-sigalgs-negative-vg.sh \ omfwd-tls-ossl-pkcs11-key-mtls-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-mtls-sigalgs-negative-vg.sh \ omfwd-tls-ossl-pkcs11-mtls-sigalgs-vg.sh \ omfwd-tls-ossl-pkcs11-module-mtls-vg.sh \ omfwd-tls-ossl-pkcs11-module-precedence-vg.sh \ omfwd-tls-ossl-pkcs11-mtls-vg.sh \ omfwd-tls-ossl-pkcs11-recover-mtls-vg.sh \ imtcp-tls-ossl-basic-vg.sh \ imtcp-tls-ossl-basic-brokenhandshake-vg.sh TESTS_OSSL_OPENSSL_SNI = \ omfwd-tls-ossl-files-mtls.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-ecdsa-sigalgs.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-negative.sh \ omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-ecdsa-sigalgs.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-negative.sh \ omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs.sh \ omfwd-tls-ossl-pkcs11-key-mtls-ecdsa-sigalgs.sh \ omfwd-tls-ossl-pkcs11-key-mtls.sh \ omfwd-tls-ossl-pkcs11-key-mtls-sigalgs-negative.sh \ omfwd-tls-ossl-pkcs11-key-mtls-sigalgs.sh \ omfwd-tls-ossl-pkcs11-module-mtls.sh \ omfwd-tls-ossl-pkcs11-module-precedence.sh \ omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs.sh \ omfwd-tls-ossl-pkcs11-mtls.sh \ omfwd-tls-ossl-pkcs11-mtls-sigalgs-negative.sh \ omfwd-tls-ossl-pkcs11-mtls-sigalgs.sh \ omfwd-tls-ossl-pkcs11-recover-mtls.sh \ omfwd-tls-ossl-no-sni.sh \ omfwd-tls-ossl-auto-sni.sh \ omfwd-tls-ossl-configured-sni.sh TESTS_OSSL_WOLFSSL = \ imtcp-tls-ossl-wolfssl-crl-der.sh TESTS_GNUTLS_OPENSSL_INTEROP = \ sndrcv_tls_ossl_servercert_gtls_clientanon.sh \ sndrcv_tls_ossl_serveranon_gtls_clientanon.sh \ sndrcv_tls_gtls_servercert_ossl_clientanon.sh \ sndrcv_tls_gtls_serveranon_ossl_clientanon.sh TESTS_OMUXSOCK = \ uxsock_simple.sh \ uxsock_simple_abstract.sh \ uxsock_action_isolation.sh \ uxsock_multiple.sh \ uxsock_multiple_netns.sh TESTS_OMUXSOCK_VALGRIND = \ uxsock_simple_abstract-vg.sh \ uxsock_multiple-vg.sh \ uxsock_multiple_netns-vg.sh TESTS_RELP = \ sndrcv_relp.sh \ sndrcv_relp_rebind.sh \ omrelp_errmsg_no_connect.sh \ omrelp-shutdown-partial-session.sh \ imrelp-basic.sh \ imrelp-basic-oldstyle.sh \ imrelp-basic-hup.sh \ imrelp-manyconn.sh \ imrelp-maxDataSize-error.sh \ imrelp-long-msg.sh \ imrelp-oversizeMode-truncate.sh \ imrelp-oversizeMode-accept.sh \ imrelp-invld-tlslib.sh \ imrelp-bigmessage.sh \ imrelp_ratelimit_name.sh \ omrelp-invld-tlslib.sh \ sndrcv_relp_dflt_pt.sh \ glbl-oversizeMsg-log.sh \ glbl-oversizeMsg-truncate.sh \ glbl-oversizeMsg-split.sh TESTS_RELP_YAML = \ imrelp-persource-ratelimit-policy.sh TESTS_RELP_OPENSSL = \ omrelp-tls-ossl-authfail-no-cacert.sh \ omrelp-tls-ossl-authfail-suspend.sh TESTS_RELP_GNUTLS = \ sndrcv_relp_tls.sh \ sndrcv_relp_tls_certvalid.sh \ sndrcv_tls_certvalid_action_level.sh \ sndrcv_relp_tls_prio.sh \ sndrcv_relp_tls_chainedcert.sh \ relp_tls_certificate_not_found.sh \ omrelp_wrong_authmode.sh \ imrelp-tls.sh \ imrelp-tls-randconn-drop.sh \ imrelp-tls-chainedcert.sh \ imrelp-tls-mixed-chainedcert.sh \ imrelp-tls-mixed-chainedcert2.sh TESTS_RELP_GNUTLS_CFG = \ imrelp-tls-cfgcmd.sh \ sndrcv_relp_tls-cfgcmd.sh TESTS_RELP_VALGRIND = \ imrelp-basic-vg.sh \ imrelp-sessionbreak-vg.sh \ imrelp-manyconn-vg.sh \ sndrcv_relp-vg-rcvr.sh \ sndrcv_relp-vg-sender.sh TESTS_IMDTLS = \ imdtls-basic.sh \ imdtls-basic-tlscommands.sh \ imdtls-basic-timeout.sh \ imdtls-error-cert.sh \ imdtls-sessionbreak.sh TESTS_IMDTLS_VALGRIND = \ imdtls-basic-vg.sh \ imdtls-sessionbreak-vg.sh TESTS_IMDTLS_OMDTLS = \ sndrcv_dtls_certvalid.sh \ sndrcv_dtls_anon_ciphers.sh \ sndrcv_dtls_certvalid_ciphers.sh \ sndrcv_dtls_certvalid_permitted.sh \ sndrcv_dtls_certvalid_missing.sh \ sndrcv_dtls_anon_ciphers.sh TESTS_IMDTLS_OMDTLS_VALGRIND = \ sndrcv_dtls_certvalid-vg.sh TESTS_OMUDPSPOOF = \ omudpspoof_errmsg_no_params.sh \ sndrcv_omudpspoof.sh \ sndrcv_omudpspoof-bigmsg.sh \ sndrcv_omudpspoof_nonstdpt.sh TESTS_OMUDPSPOOF_IMTCP = \ omudpspoof-fragment-send-failure.sh TESTS_OMRULESET = \ omruleset.sh \ omruleset-queue.sh TESTS_PMDB2DIAG = \ pmdb2diag_parse.sh \ pmdb2diag_malformed_tail.sh TESTS_PMCISCOIOS = \ pmciscoios_truncated_input.sh TESTS_PMSNARE = \ pmsnare-default.sh \ pmsnare-default-udp.sh \ pmsnare-ccoff.sh \ pmsnare-ccoff-udp.sh \ pmsnare-ccdefault.sh \ pmsnare-ccdefault-udp.sh \ pmsnare-cccstyle.sh \ pmsnare-cccstyle-udp.sh \ pmsnare-ccbackslash.sh \ pmsnare-ccbackslash-udp.sh \ pmsnare_malformed_tag_tail.sh \ pmsnare-modoverride.sh \ pmsnare-modoverride-udp.sh TESTS_PMLASTMSG = \ pmlastmsg.sh \ pmlastmsg-udp.sh TESTS_IMFILE_EXTENDED = \ imfile-basic-2GB-file.sh \ imfile-truncate-2GB-file.sh TESTS_IMFILE = \ imfile-basic.sh \ imfile-basic-legacy.sh \ imfile-delay-message.sh \ imfile-discard-truncated-line.sh \ imfile-truncate-line.sh \ imfile-file-not-found-error.sh \ imfile-fileNotFoundError-parameter.sh \ imfile-error-not-repeated.sh \ imfile-truncate.sh \ imfile-truncate-multiple.sh \ imfile-readmode2.sh \ imfile-readmode2-polling.sh \ imfile-readmode2-with-persists-data-during-stop.sh \ imfile-readmode2-with-persists.sh \ imfile-endregex.sh \ imfile-endregex-save-lf.sh \ imfile-endregex-save-lf-persist.sh \ imfile-endregex-timeout-none-polling.sh \ imfile-endregex-timeout-polling.sh \ imfile-endregex-timeout.sh \ imfile-endregex-timeout-none.sh \ imfile-endregex-timeout-with-shutdown.sh \ imfile-endregex-timeout-with-shutdown-polling.sh \ imfile-endmsg.regex.sh \ imfile-escapelf.replacement.sh \ imfile-escapelf.replacement-empty.sh \ imfile-statefile-no-file_id.sh \ imfile-statefile-no-file_id-TO-file_id.sh \ imfile-statefile-directory.sh \ imfile-metadata-line-number.sh \ imfile-no-monitor-config-check.sh \ imfile-bad-state-file.sh \ imfile-statefile-delete.sh \ imfile-statefile-no-delete.sh \ imfile-persist-state-1.sh \ imfile-freshStartTail1.sh \ imfile-freshStartTail2.sh \ imfile-freshStartTail3.sh \ imfile-wildcards.sh \ imfile-wildcards-dirs.sh \ imfile-wildcards-dirs2.sh \ imfile-wildcards-dirs-multi.sh \ imfile-wildcards-dirs-multi2.sh \ imfile-wildcards-dirs-multi3.sh \ imfile-wildcards-dirs-multi4.sh \ imfile-wildcards-dirs-multi5.sh \ imfile-wildcards-dirs-multi5-polling.sh \ imfile-same-file-monitors.sh \ imfile-duplicate-monitor-warning.sh \ imfile-old-state-file.sh \ imfile-rename-while-stopped.sh \ imfile-rename.sh \ imfile-symlink.sh \ imfile-symlink-multi.sh \ imfile-inotify-fd-release-on-delete.sh \ imfile-symlink-ext-tmp-dir-tree.sh \ imfile-logrotate.sh \ imfile-logrotate-async.sh \ imfile-logrotate-multiple.sh \ imfile-logrotate-copytruncate.sh \ imfile-logrotate-nocopytruncate.sh \ imfile-logrotate-state-files.sh \ imfile-growing-file-id.sh \ imfile-ignore-old-file-1.sh \ imfile-ignore-old-file-2.sh \ imfile-ignore-old-file-3.sh \ imfile-ignore-old-file-4.sh \ imfile-ignore-old-file-5.sh \ imfile-ignore-old-file-6.sh \ imfile-ignore-old-file-7.sh \ glbl-oversizeMsg-truncate-imfile.sh \ config_enabled-on.sh \ config_enabled-off.sh # These imfile tests stress dynamic inotify watch changes. Keep each high-churn # subcluster ordered while allowing independent chains to run in parallel: # freshStartTail state handling, wildcard directory expansion, rename/symlink # handling, and logrotate/truncate handling. This preserves the individual test # coverage and assertions without making all imfile inotify stress tests wait # behind one long serial chain. imfile-freshStartTail2.log: imfile-freshStartTail1.log imfile-freshStartTail3.log: imfile-freshStartTail2.log imfile-wildcards-dirs.log: imfile-wildcards.log imfile-wildcards-dirs2.log: imfile-wildcards-dirs.log imfile-wildcards-dirs-multi.log: imfile-wildcards-dirs2.log imfile-wildcards-dirs-multi2.log: imfile-wildcards-dirs-multi.log imfile-wildcards-dirs-multi3.log: imfile-wildcards-dirs-multi2.log imfile-wildcards-dirs-multi4.log: imfile-wildcards-dirs-multi3.log imfile-wildcards-dirs-multi5.log: imfile-wildcards-dirs-multi4.log imfile-wildcards-dirs-multi5-polling.log: imfile-wildcards-dirs-multi5.log imfile-rename-while-stopped.log: imfile-old-state-file.log imfile-rename.log: imfile-rename-while-stopped.log imfile-symlink.log: imfile-rename.log imfile-symlink-multi.log: imfile-symlink.log imfile-symlink-ext-tmp-dir-tree.log: imfile-symlink-multi.log imfile-logrotate-async.log: imfile-logrotate.log imfile-logrotate-multiple.log: imfile-logrotate-async.log imfile-logrotate-copytruncate.log: imfile-logrotate-multiple.log imfile-logrotate-nocopytruncate.log: imfile-logrotate-copytruncate.log imfile-logrotate-state-files.log: imfile-logrotate-nocopytruncate.log # Keep imtcp listener-heavy tests serialized. macOS TSAN runners are prone to # transient EADDRINUSE failures when many dynamic TCP listeners start in # parallel. fromhost-port-tuple.log: fromhost-port.log fromhost-port-async-ruleset.log: fromhost-port-tuple.log allowed-sender-tcp-ok.log: fromhost-port-async-ruleset.log allowed-sender-tcp-fail.log: allowed-sender-tcp-ok.log allowed-sender-tcp-zero-mask.log: allowed-sender-tcp-fail.log allowed-sender-modern.log: allowed-sender-tcp-zero-mask.log allowed-sender-empty-array.log: allowed-sender-modern.log allowed-sender-tcp-hostname-ok.log: allowed-sender-empty-array.log allowed-sender-tcp-hostname-fail.log: allowed-sender-tcp-hostname-ok.log imtcp-discard-truncated-msg.log: allowed-sender-tcp-hostname-fail.log imtcp-basic.log: imtcp-discard-truncated-msg.log imtcp_framing_regex.log: imtcp-basic.log imtcp_framing_regex_maxmsg_overflow.log: imtcp_framing_regex.log imtcp-multiline.log: imtcp_framing_regex_maxmsg_overflow.log imtcp-basic-hup.log: imtcp-multiline.log imtcp-impstats-single-thread.log: imtcp-basic-hup.log imtcp-starvation-0.log: imtcp-impstats-single-thread.log imtcp-starvation-1.log: imtcp-starvation-0.log imtcp-maxFrameSize.log: imtcp-starvation-1.log imtcp-msg-truncation-on-number.log: imtcp-maxFrameSize.log imtcp-msg-truncation-on-number2.log: imtcp-msg-truncation-on-number.log imtcp-netns.log: imtcp-msg-truncation-on-number2.log imtcp-NUL.log: imtcp-netns.log imtcp-NUL-rawmsg.log: imtcp-NUL.log imtcp_incomplete_frame_at_end.log: imtcp-NUL-rawmsg.log imtcp-multiport.log: imtcp_incomplete_frame_at_end.log imtcp-bigmessage-octetcounting.log: imtcp-multiport.log imtcp-bigmessage-octetstuffing.log: imtcp-bigmessage-octetcounting.log manytcp.log: imtcp-bigmessage-octetstuffing.log imtcp_conndrop.log: manytcp.log imtcp_addtlframedelim.log: imtcp_conndrop.log imtcp_no_octet_counted.log: imtcp_addtlframedelim.log imtcp_addtlframedelim_on_input.log: imtcp_no_octet_counted.log imtcp_spframingfix.log: imtcp_addtlframedelim_on_input.log imtcp-connection-msg-recieved.log: imtcp_spframingfix.log sndrcv.log: imtcp-connection-msg-recieved.log sndrcv_failover.log: sndrcv.log sndrcv_gzip.log: sndrcv_failover.log sndrcv_udp_nonstdpt.log: sndrcv_gzip.log sndrcv_udp_nonstdpt_v6.log: sndrcv_udp_nonstdpt.log imtcp-stream-always-zlib-basic.log: sndrcv_udp_nonstdpt_v6.log imtcp-stream-always-zlib-completion-release.log: imtcp-stream-always-zlib-basic.log imtcp-stream-always-zlib-flushoff.log: imtcp-stream-always-zlib-completion-release.log imtcp-stream-always-zlib-corrupt.log: imtcp-stream-always-zlib-flushoff.log imtcp-stream-always-zlib-truncated.log: imtcp-stream-always-zlib-corrupt.log imtcp-stream-always-zlib-fragmented-ratio.log: imtcp-stream-always-zlib-truncated.log imtcp-stream-always-zlib-expansion-guard.log: imtcp-stream-always-zlib-fragmented-ratio.log imtcp-stream-always-zstd-basic.log: imtcp-stream-always-zlib-expansion-guard.log imtcp-stream-always-zstd-flushoff.log: imtcp-stream-always-zstd-basic.log imtcp-stream-always-zstd-corrupt.log: imtcp-stream-always-zstd-flushoff.log imtcp-stream-always-zstd-truncated.log: imtcp-stream-always-zstd-corrupt.log imtcp-stream-always-zstd-empty-close.log: imtcp-stream-always-zstd-truncated.log imtcp-stream-always-zstd-window-guard.log: imtcp-stream-always-zstd-empty-close.log imtcp-stream-always-zstd-window-budget.log: imtcp-stream-always-zstd-window-guard.log imtcp-stream-always-zstd-secure-defaults.log: imtcp-stream-always-zstd-window-budget.log yaml-imtcp-stream-always-zstd-secure-defaults.log: imtcp-stream-always-zstd-secure-defaults.log imtcp-stream-always-zstd-expansion-guard.log: imtcp-stream-always-zstd-secure-defaults.log imtcp-stream-always-zstd-to-zlib-mismatch.log: imtcp-stream-always-zstd-expansion-guard.log imtcp-impstats.log: imtcp-stream-always-zlib-truncated.log imtcp-stream-always-zlib-impstats.log: imtcp-impstats.log imtcp-stream-always-zstd-impstats.log: imtcp-stream-always-zlib-impstats.log TESTS_IMFILE_MMNORMALIZE = \ imfile-endmsg.regex-with-example.sh TESTS_IMFILE_IMPSTATS = \ imfile-statistics.sh TESTS_IMFILE_VALGRIND = \ imfile-basic-vg.sh \ imfile-endregex-vg.sh \ imfile-endmsg.regex-vg.sh \ imfile-readmode0-vg.sh \ imfile-readmode2-vg.sh TESTS_IMFILE_HELGRIND = \ imfile-basic-vgthread.sh TESTS_IMFILE_MMNORMALIZE_VALGRIND = \ imfile-endmsg.regex-with-example-vg.sh TESTS_IMBATCHREPORT = \ imbatchreport_errmsg_no_params.sh \ imbatchreport_errmsg_glob_not_regular.sh \ imbatchreport_errmsg_glob_dir_fake.sh \ imbatchreport_errmsg_glob_dir_not_dir.sh \ imbatchreport_errmsg_regex.match.reject.sh \ imbatchreport_errmsg_regex.match.rename.sh \ imbatchreport_errmsg_regex.nomatch.sh \ imbatchreport_errmsg_not_supported1.sh \ imbatchreport_errmsg_not_supported2.sh \ imbatchreport_errmsg_not_supported3.sh \ imbatchreport_errmsg_delete_params.sh \ imbatchreport_errmsg_rename_params.sh \ imbatchreport_delete_success.sh \ imbatchreport_delete_structdata.sh \ imbatchreport_rename_success.sh \ imbatchreport_delete_toolarge.sh \ imbatchreport_rename_toolarge.sh TESTS_IMBATCHREPORT_VALGRIND = \ imbatchreport_errmsg_no_params-vg.sh TESTS_OMTCL = \ omtcl.sh TESTS_MMTAGHOSTNAME = \ mmtaghostname_tag.sh \ mmtaghostname_server.sh TESTS_MMKUBERNETES = \ mmkubernetes-basic.sh \ mmkubernetes-cache-expire.sh \ mmkubernetes-url-failover.sh \ mmkubernetes-namespace-metadata-off.sh \ yaml-mmkubernetes-namespace-metadata-off.sh \ mmkubernetes-token-reload.sh TESTS_MMKUBERNETES_VALGRIND = \ mmkubernetes-basic-vg.sh \ mmkubernetes-cache-expire-vg.sh \ mmkubernetes-token-reload-vg.sh TESTS_IMKUBERNETES = \ imkubernetes-cri-partial-accept.sh \ imkubernetes-cri-basic.sh \ imkubernetes-cri-partial-bound.sh \ imkubernetes-cri-partial-hard-cap.sh \ imkubernetes-cri-partial-split.sh \ imkubernetes-dockerjson-basic.sh \ yaml-imkubernetes-dockerjson-basic.sh TESTS_IMTUXEDOULOG = \ imtuxedoulog_errmsg_no_params.sh \ imtuxedoulog_data.sh TESTS_IMTUXEDOULOG_VALGRIND = \ imtuxedoulog_errmsg_no_params-vg.sh TESTS_OMAMQP1 = \ omamqp1-basic.sh TESTS_OMAMQP1_VALGRIND = \ omamqp1-basic-vg.sh TESTS_SRV_DISCOVERY = \ omfwd-srv-discovery-tcp.sh \ omfwd-srv-discovery-udp.sh \ omfwd-srv-discovery-errors.sh TESTS_ENVIRONMENT = RSYSLOG_MODDIR='$(abs_top_builddir)'/runtime/.libs/ TESTS_ENVIRONMENT+= TOP_BUILDDIR='$(top_builddir)' EXTRA_DIST += $(TESTS_ELASTICSEARCH_MINIMAL) EXTRA_DIST += $(TESTS_ELASTICSEARCH_MINIMAL_VALGRIND) EXTRA_DIST += $(TESTS_ELASTICSEARCH_MINIMAL_HELGRIND) EXTRA_DIST += $(TESTS_ELASTICSEARCH_SERVER) EXTRA_DIST += $(TESTS_ELASTICSEARCH_IMPSTATS) EXTRA_DIST += $(TESTS_ELASTICSEARCH_IMFILE) EXTRA_DIST += $(TESTS_ELASTICSEARCH_VALGRIND) EXTRA_DIST += $(TESTS_DEFAULT) EXTRA_DIST += $(TESTS_SKELETONS) EXTRA_DIST += $(TESTS_INACTIVE) EXTRA_DIST += $(TESTS_MMSNAREPARSE_MINIMAL) EXTRA_DIST += $(TESTS_MMSNAREPARSE_VALGRIND) EXTRA_DIST += $(TESTS_OMSENDERTRACK) EXTRA_DIST += $(TESTS_OMSENDERTRACK_VALGRIND) EXTRA_DIST += $(TESTS_LIBZSTD) EXTRA_DIST += $(TESTS_LIBZSTD_VALGRIND) EXTRA_DIST += $(TESTS_LIBGCRYPT) EXTRA_DIST += $(TESTS_GNUTLS_WRONG_OPT) EXTRA_DIST += $(TESTS_OSSL_WRONG_OPT) EXTRA_DIST += $(TESTS_DEFAULT_VALGRIND) EXTRA_DIST += $(TESTS_LIBGCRYPT_VALGRIND) EXTRA_DIST += $(TESTS_LIBYAML) EXTRA_DIST += $(TESTS_RATELIMIT_WATCH) EXTRA_DIST += $(TESTS_LIBYAML_IMPTCP_MMJSONPARSE) EXTRA_DIST += $(TESTS_LIBYAML_IMTCP) EXTRA_DIST += $(TESTS_LIBYAML_IMTCP_OSSL) EXTRA_DIST += $(TESTS_LIBYAML_OSSL) EXTRA_DIST += $(TESTS_LIBYAML_IMHTTP) EXTRA_DIST += $(TESTS_LIBYAML_OMSTDOUT) EXTRA_DIST += $(TESTS_IMTCP) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_ZLIB) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_ZLIB_IMPSTATS) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD_YAML) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD_IMPSTATS) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_GNUTLS) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_MBEDTLS) EXTRA_DIST += $(TESTS_IMTCP_STREAM_ALWAYS_OSSL) EXTRA_DIST += $(TESTS_IMTCP_YAML) EXTRA_DIST += $(TESTS_IMTCP_VALGRIND) EXTRA_DIST += $(TESTS_IMTCP_IMPSTATS) EXTRA_DIST += $(TESTS_RATELIMIT) EXTRA_DIST += $(TESTS_RATELIMIT_YAML) EXTRA_DIST += $(TESTS_RATELIMIT_IMPTCP_YAML) EXTRA_DIST += $(TESTS_IMPTCP_FROMHOST_PORT) EXTRA_DIST += ratelimit-persource-port-keys-common.sh EXTRA_DIST += $(TESTS_SNMP_MINIMAL) EXTRA_DIST += $(TESTS_SNMP_FULL) EXTRA_DIST += $(TESTS_MMUTF8FIX) EXTRA_DIST += $(TESTS_MMUTF8FIX_YAML) EXTRA_DIST += $(TESTS_MMUTF8FIX_SD) EXTRA_DIST += $(TESTS_MMAITAG) EXTRA_DIST += $(TESTS_MAIL) EXTRA_DIST += $(TESTS_MAIL_MMJSONPARSE) EXTRA_DIST += $(TESTS_MMANON) EXTRA_DIST += $(TESTS_CLICKHOUSE) EXTRA_DIST += $(TESTS_CLICKHOUSE_VALGRIND) EXTRA_DIST += $(TESTS_LIBFAKETIME) EXTRA_DIST += $(TESTS_MMNORMALIZE_FAKETIME) EXTRA_DIST += $(TESTS_PGSQL) EXTRA_DIST += $(TESTS_PGSQL_CONFIG) EXTRA_DIST += $(TESTS_PGSQL_VALGRIND) EXTRA_DIST += $(TESTS_MYSQL) EXTRA_DIST += $(TESTS_MYSQL_VALGRIND) EXTRA_DIST += $(TESTS_LIBDBI) EXTRA_DIST += $(TESTS_LIBDBI_VALGRIND) EXTRA_DIST += $(TESTS_FMHTTP) EXTRA_DIST += $(TESTS_FMHTTP_VALGRIND) EXTRA_DIST += $(TESTS_ROOT) EXTRA_DIST += $(TESTS_ROOT_IP) EXTRA_DIST += $(TESTS_ROOT_VALGRIND) EXTRA_DIST += $(TESTS_OMHTTP_FLAKY) EXTRA_DIST += $(TESTS_OMHTTP_FLAKY_VALGRIND) EXTRA_DIST += $(TESTS_IMJOURNAL) EXTRA_DIST += $(TESTS_IMJOURNAL_VALGRIND) EXTRA_DIST += $(TESTS_OMJOURNAL) EXTRA_DIST += $(TESTS_IMPROG) EXTRA_DIST += $(TESTS_IMPROG_VALGRIND) EXTRA_DIST += $(TESTS_MMDARWIN) EXTRA_DIST += $(TESTS_MMDARWIN_VALGRIND) EXTRA_DIST += $(TESTS_OMPROG) EXTRA_DIST += $(TESTS_OMPROG_VALGRIND) EXTRA_DIST += $(TESTS_OMHTTP) EXTRA_DIST += $(TESTS_OMHTTP_VALGRIND) EXTRA_DIST += $(TESTS_OMHTTP_VICTORIALOGS) EXTRA_DIST += $(TESTS_OMOTEL) EXTRA_DIST += $(TESTS_KAFKA_SELFTEST) EXTRA_DIST += $(TESTS_OMKAFKA_NO_SERVICE) EXTRA_DIST += $(TESTS_KAFKA) EXTRA_DIST += $(TESTS_KAFKA_VALGRIND) EXTRA_DIST += $(TESTS_OMAZUREEVENTHUBS) EXTRA_DIST += $(TESTS_OMAZUREEVENTHUBS_VALGRIND) EXTRA_DIST += $(TESTS_OMAZUREDCE) EXTRA_DIST += $(TESTS_OMAZUREDCE_VALGRIND) EXTRA_DIST += $(TESTS_OMAZUREDCE_YAML) EXTRA_DIST += omazuredce-env.sh EXTRA_DIST += testsuites/yaml-omazuredce-compression.yaml EXTRA_DIST += $(TESTS_OMAWSLOGSHLC) EXTRA_DIST += $(TESTS_OMAWSLOGSHLC_IMTCP) EXTRA_DIST += omawslogshlc-env.sh EXTRA_DIST += $(TESTS_IMDOCKER) EXTRA_DIST += $(TESTS_IMDOCKER_VALGRIND) EXTRA_DIST += $(TESTS_IMCZMQ) EXTRA_DIST += $(TESTS_IMHTTP) EXTRA_DIST += $(TESTS_IMHTTP_VALGRIND) EXTRA_DIST += $(TESTS_IMBEATS) EXTRA_DIST += $(TESTS_IMBEATS_OPENSSL) EXTRA_DIST += $(TESTS_IMBEATS_IMPSTATS) EXTRA_DIST += $(TESTS_IMBEATS_YAML) EXTRA_DIST += $(TESTS_IMBEATS_ELASTICSEARCH) EXTRA_DIST += $(TESTS_OMRABBITMQ) EXTRA_DIST += $(TESTS_OMRABBITMQ_VALGRIND) EXTRA_DIST += $(TESTS_IMHIREDIS) EXTRA_DIST += $(TESTS_IMHIREDIS_VALGRIND) EXTRA_DIST += $(TESTS_OMHIREDIS) EXTRA_DIST += $(TESTS_OMHIREDIS_VALGRIND) EXTRA_DIST += $(TESTS_IMPSTATS) EXTRA_DIST += $(TESTS_IMPSTATS_PUSH) EXTRA_DIST += $(TESTS_IMPSTATS_VALGRIND) EXTRA_DIST += $(TESTS_IMPTCP) EXTRA_DIST += $(TESTS_IMPTCP_STREAM_ALWAYS) EXTRA_DIST += $(TESTS_IMPTCP_STREAM_ALWAYS_IMPSTATS) EXTRA_DIST += $(TESTS_IMPTCP_VALGRIND) EXTRA_DIST += $(TESTS_IMPTCP_FMHASH_VALGRIND) EXTRA_DIST += $(TESTS_IMPTCP_FMUNFLATTEN) EXTRA_DIST += $(TESTS_IMPTCP_FMUNFLATTEN_VALGRIND) EXTRA_DIST += $(TESTS_IMPTCP_FFAUP) EXTRA_DIST += $(TESTS_IMPTCP_FFAUP_VALGRIND) EXTRA_DIST += $(TESTS_FMPCRE) EXTRA_DIST += $(TESTS_MMPSTRUCDATA) EXTRA_DIST += $(TESTS_MMPSTRUCDATA_VALGRIND) EXTRA_DIST += $(TESTS_MMRFC5424ADDHMAC) EXTRA_DIST += $(TESTS_MMRM1STSPACE) EXTRA_DIST += $(TESTS_PMNULL) EXTRA_DIST += $(TESTS_OMSTDOUT) EXTRA_DIST += $(TESTS_PMNORMALIZE) EXTRA_DIST += $(TESTS_PMNORMALIZE_DEBUG) EXTRA_DIST += $(TESTS_PMNORMALIZE_YAML) EXTRA_DIST += $(TESTS_PMNORMALIZE_VALGRIND) EXTRA_DIST += $(TESTS_MMNORMALIZE) EXTRA_DIST += $(TESTS_MMNORMALIZE_DEBUG) EXTRA_DIST += $(TESTS_MMNORMALIZE_YAML) EXTRA_DIST += $(TESTS_MMNORMALIZE_TURBO) EXTRA_DIST += $(TESTS_MMNORMALIZE_TURBO_YAML) EXTRA_DIST += $(TESTS_MMNORMALIZE_VALGRIND) EXTRA_DIST += $(TESTS_MMNORMALIZE_IMPTCP) EXTRA_DIST += $(TESTS_MMNORMALIZE_REGEX) EXTRA_DIST += $(TESTS_MMLEEFPARSE) EXTRA_DIST += $(TESTS_MMJSONPARSE_PART1) EXTRA_DIST += $(TESTS_MMJSONPARSE_IMPSTATS) EXTRA_DIST += $(TESTS_MMJSONPARSE_IMPTCP) EXTRA_DIST += $(TESTS_MMJSONPARSE_VALGRIND) EXTRA_DIST += $(TESTS_MMJSONPARSE_PART2) EXTRA_DIST += $(TESTS_MMJSONTRANSFORM_IMTCP) EXTRA_DIST += $(TESTS_MMJSONTRANSFORM_MMJSONPARSE) EXTRA_DIST += $(TESTS_MMJSONTRANSFORM_LIBYAML) EXTRA_DIST += $(TESTS_MMJSONTRANSFORM_WATCH) EXTRA_DIST += $(TESTS_MMDBLOOKUP) EXTRA_DIST += $(TESTS_MMDBLOOKUP_VALGRIND) EXTRA_DIST += $(TESTS_GNUTLS) EXTRA_DIST += $(TESTS_GNUTLS_VALGRIND) EXTRA_DIST += $(TESTS_GNUTLS_OPENSSL) EXTRA_DIST += $(TESTS_MBEDTLS) EXTRA_DIST += $(TESTS_MBEDTLS_VALGRIND) EXTRA_DIST += $(TESTS_OSSL) EXTRA_DIST += $(TESTS_OSSL_OPENSSL) EXTRA_DIST += $(TESTS_OSSL_OPENSSL_VALGRIND) EXTRA_DIST += $(TESTS_OSSL_OPENSSL_SNI) EXTRA_DIST += $(TESTS_OSSL_WOLFSSL) EXTRA_DIST += $(TESTS_GNUTLS_OPENSSL_INTEROP) EXTRA_DIST += $(TESTS_OMUXSOCK) EXTRA_DIST += $(TESTS_OMUXSOCK_VALGRIND) EXTRA_DIST += $(TESTS_RELP) EXTRA_DIST += $(TESTS_RELP_YAML) EXTRA_DIST += $(TESTS_RELP_OPENSSL) EXTRA_DIST += $(TESTS_RELP_GNUTLS) EXTRA_DIST += $(TESTS_RELP_GNUTLS_CFG) EXTRA_DIST += $(TESTS_RELP_VALGRIND) EXTRA_DIST += $(TESTS_IMDTLS) EXTRA_DIST += $(TESTS_IMDTLS_VALGRIND) EXTRA_DIST += $(TESTS_IMDTLS_OMDTLS) EXTRA_DIST += $(TESTS_IMDTLS_OMDTLS_VALGRIND) EXTRA_DIST += $(TESTS_OMUDPSPOOF) $(TESTS_OMUDPSPOOF_IMTCP) EXTRA_DIST += $(TESTS_OMRULESET) EXTRA_DIST += $(TESTS_PMDB2DIAG) EXTRA_DIST += $(TESTS_PMCISCOIOS) EXTRA_DIST += $(TESTS_PMSNARE) EXTRA_DIST += $(TESTS_PMLASTMSG) EXTRA_DIST += $(TESTS_IMFILE_EXTENDED) EXTRA_DIST += $(TESTS_IMFILE) EXTRA_DIST += $(TESTS_IMFILE_MMNORMALIZE) EXTRA_DIST += $(TESTS_IMFILE_IMPSTATS) EXTRA_DIST += $(TESTS_IMFILE_VALGRIND) EXTRA_DIST += $(TESTS_IMFILE_HELGRIND) EXTRA_DIST += $(TESTS_IMFILE_MMNORMALIZE_VALGRIND) EXTRA_DIST += $(TESTS_IMBATCHREPORT) EXTRA_DIST += $(TESTS_IMBATCHREPORT_VALGRIND) EXTRA_DIST += $(TESTS_OMTCL) EXTRA_DIST += $(TESTS_MMTAGHOSTNAME) EXTRA_DIST += $(TESTS_MMKUBERNETES) EXTRA_DIST += $(TESTS_MMKUBERNETES_VALGRIND) EXTRA_DIST += $(TESTS_IMKUBERNETES) EXTRA_DIST += $(TESTS_IMTUXEDOULOG) EXTRA_DIST += $(TESTS_IMTUXEDOULOG_VALGRIND) EXTRA_DIST += $(TESTS_OMAMQP1) EXTRA_DIST += $(TESTS_OMAMQP1_VALGRIND) EXTRA_DIST += $(TESTS_SRV_DISCOVERY) CLEANFILES=\ *_*.conf \ rsyslog*.started work-*.conf rsyslog.random.data \ rsyslog*.pid.save xlate*.lkp_tbl \ log log* *.log \ work \ test-spool test-logdir stat-file1 \ rsyslog.pipe rsyslog.input.* \ rsyslog.input rsyslog.input.* imfile-state:* omkafka-failed.data \ rsyslog.input-symlink.log rsyslog-link.*.log targets \ HOSTNAME \ rstb_* *.test_policy_hup.yaml \ zookeeper.pid \ tmp.qi nocert CLEANFILES+= \ IN_AUTO_DEBUG \ runtime_unit_imbeats_seq # IN_AUTO_DEBUG should be deleted each time make check is run, but # there exists no such hook. Se we at least delete it on make clean. # runtime_unit_imbeats_seq is conditional, but an outer build with imbeats # enabled can leave it for an inner distcheck configured without imbeats. check_LTLIBRARIES = # TODO: reenable TESTRUNS = rt_init rscript check_PROGRAMS = runtime_unit_linkedlist runtime_unit_stringbuf runtime_unit_parser_pri runtime_unit_msg_replace \ runtime_unit_ommongodb_date runtime_unit_segdisk_state runtime_unit_queue_da runtime_unit_omazuredce_utils TESTS = runtime_unit_linkedlist runtime_unit_stringbuf runtime_unit_parser_pri runtime_unit_msg_replace \ runtime_unit_ommongodb_date runtime_unit_segdisk_state runtime_unit_queue_da runtime_unit_omazuredce_utils if ENABLE_FUZZING TESTS += $(TESTS_FUZZING) endif runtime_unit_linkedlist_SOURCES = \ unit/linkedlist_test.c runtime_unit_stringbuf_SOURCES = \ unit/stringbuf_test.c runtime_unit_parser_pri_SOURCES = \ unit/parser_pri_test.c runtime_unit_msg_replace_SOURCES = \ unit/msg_replace_test.c runtime_unit_ommongodb_date_SOURCES = \ unit/ommongodb_date_test.c runtime_unit_segdisk_state_SOURCES = \ unit/segdisk_state_test.c runtime_unit_queue_da_SOURCES = \ unit/queue_da_test.c runtime_unit_omazuredce_utils_SOURCES = \ unit/omazuredce_utils_test.c runtime_unit_omazuredce_utils_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_omazuredce_utils_LDADD = $(PTHREADS_LIBS) $(SOL_LIBS) if ENABLE_IMPCAP check_PROGRAMS += runtime_unit_impcap_arp_parser TESTS += runtime_unit_impcap_arp_parser runtime_unit_impcap_arp_parser_SOURCES = \ unit/impcap_arp_parser_test.c runtime_unit_impcap_arp_parser_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_impcap_arp_parser_LDADD = $(LIBFASTJSON_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) endif if ENABLE_GSSAPI check_PROGRAMS += runtime_unit_gss_token_util TESTS += runtime_unit_gss_token_util runtime_unit_gss_token_util_SOURCES = \ unit/gss_token_util_test.c runtime_unit_gss_token_util_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_gss_token_util_LDADD = $(PTHREADS_LIBS) $(SOL_LIBS) endif if ENABLE_IMBEATS check_PROGRAMS += runtime_unit_imbeats_seq runtime_unit_imbeats_parser TESTS += runtime_unit_imbeats_seq runtime_unit_imbeats_parser runtime_unit_imbeats_seq_SOURCES = \ unit/imbeats_seq_test.c runtime_unit_imbeats_seq_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_imbeats_seq_LDADD = $(PTHREADS_LIBS) $(SOL_LIBS) runtime_unit_imbeats_parser_SOURCES = \ unit/imbeats_parser_test.c runtime_unit_imbeats_parser_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) \ $(ZLIB_CFLAGS) runtime_unit_imbeats_parser_LDADD = $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) endif runtime_unit_linkedlist_CPPFLAGS = \ -DSD_EXPORT_SYMBOLS \ -D_PATH_MODDIR=\"$(pkglibdir)/\" \ $(PTHREADS_CFLAGS) \ $(RSRT_CFLAGS) \ $(LIBUUID_CFLAGS) \ $(LIBFASTJSON_CFLAGS) \ ${LIBESTR_CFLAGS} \ $(LIBYAML_CFLAGS) \ -I$(top_builddir) \ -I$(top_srcdir) \ -I$(top_srcdir)/grammar \ -I$(top_srcdir)/runtime \ -I$(top_srcdir)/tools runtime_unit_stringbuf_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_parser_pri_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_msg_replace_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_ommongodb_date_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) \ -I$(top_srcdir)/plugins/ommongodb runtime_unit_segdisk_state_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_queue_da_CPPFLAGS = \ $(runtime_unit_linkedlist_CPPFLAGS) runtime_unit_linkedlist_LDADD = $(RSRT_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) runtime_unit_stringbuf_LDADD = $(LIBESTR_LIBS) $(LIBFASTJSON_LIBS) $(LIBSYSTEMD_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) runtime_unit_parser_pri_LDADD = $(LIBESTR_LIBS) $(LIBFASTJSON_LIBS) $(LIBSYSTEMD_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) runtime_unit_msg_replace_LDADD = $(runtime_unit_linkedlist_LDADD) runtime_unit_ommongodb_date_LDADD = $(runtime_unit_linkedlist_LDADD) runtime_unit_segdisk_state_LDADD = runtime_unit_queue_da_LDADD = if ENABLE_LIBLOGGING_STDLOG runtime_unit_linkedlist_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) runtime_unit_stringbuf_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) runtime_unit_parser_pri_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) runtime_unit_msg_replace_CPPFLAGS += $(LIBLOGGING_STDLOG_CFLAGS) endif TEST_LIBOVERRIDE_LDFLAGS = -module -shared -avoid-version -rpath $(abs_builddir) if ENABLE_TESTBENCH check_LTLIBRARIES += liboverride_gethostname.la liboverride_gethostname_la_SOURCES = override_gethostname.c liboverride_gethostname_la_CFLAGS = liboverride_gethostname_la_LDFLAGS = $(TEST_LIBOVERRIDE_LDFLAGS) check_LTLIBRARIES += liboverride_gethostname_nonfqdn.la liboverride_gethostname_nonfqdn_la_SOURCES = override_gethostname_nonfqdn.c liboverride_gethostname_nonfqdn_la_CFLAGS = liboverride_gethostname_nonfqdn_la_LDFLAGS = $(TEST_LIBOVERRIDE_LDFLAGS) check_LTLIBRARIES += liboverride_getaddrinfo.la liboverride_getaddrinfo_la_SOURCES = override_getaddrinfo.c liboverride_getaddrinfo_la_CFLAGS = liboverride_getaddrinfo_la_LDFLAGS = $(TEST_LIBOVERRIDE_LDFLAGS) if ENABLE_IMPTCP check_LTLIBRARIES += liboverride_epoll_ctl.la liboverride_epoll_ctl_la_SOURCES = override_epoll_ctl.c liboverride_epoll_ctl_la_CFLAGS = liboverride_epoll_ctl_la_LDFLAGS = $(TEST_LIBOVERRIDE_LDFLAGS) liboverride_epoll_ctl_la_LIBADD = $(DL_LIBS) endif if ENABLE_OMUDPSPOOF check_LTLIBRARIES += liboverride_libnet_write_fail.la liboverride_libnet_write_fail_la_SOURCES = override_libnet_write_fail.c liboverride_libnet_write_fail_la_CFLAGS = liboverride_libnet_write_fail_la_LDFLAGS = $(TEST_LIBOVERRIDE_LDFLAGS) endif check_PROGRAMS += $(TESTRUNS) ourtail tcpflood chkseq msleep randomgen \ diagtalker uxsockrcvr syslog_caller inputfilegen minitcpsrv \ omrelp_dflt_port \ mangle_qi \ have_relpSrvSetOversizeMode \ have_relpEngineSetTLSLibByName \ have_relpSrvSetTlsConfigCmd \ check_relpEngineVersion \ test_id if ENABLE_JOURNAL_TESTS if ENABLE_IMJOURNAL check_PROGRAMS += journal_print endif endif # if ENABLE_JOURNAL_TESTS TESTS += $(TESTRUNS) if ENABLE_GSSAPI TESTS += $(TESTS_GSSAPI) if HAVE_LIBYAML TESTS += $(TESTS_GSSAPI_LIBYAML) endif # HAVE_LIBYAML endif if ENABLE_ELASTICSEARCH_TESTS_MINIMAL TESTS += $(TESTS_ELASTICSEARCH_MINIMAL) es-basic-bulk.log: es-basic.log es-basic-server.log: es-basic-bulk.log # special "test" for stopping ES once all ES tests are done elasticsearch-stop.log: es-basic-bulk.log if HAVE_VALGRIND TESTS += $(TESTS_ELASTICSEARCH_MINIMAL_VALGRIND) es-basic-vg.log: es-basic-bulk.log # for next if block: es-basic-server.log: es-basic-vg.log elasticsearch-stop.log: es-basic-vg.log if ENABLE_HELGRIND TESTS += $(TESTS_ELASTICSEARCH_MINIMAL_HELGRIND) es-basic-vgthread.log: es-basic-vg.log # for next if block: es-basic-server.log: es-basic-vgthread.log elasticsearch-stop.log: es-basic-vgthread.log endif # ENABLE_HELGRIND endif # HAVE_VALGRIND endif # ENABLE_ELASTICSEARCH_TESTS_MINIMAL if ENABLE_ELASTICSEARCH_TESTS TESTS += $(TESTS_ELASTICSEARCH_SERVER) es-basic-server.log: es-basic-bulk.log es-execOnlyWhenPreviousSuspended.log: es-basic-server.log es-maxbytes-bulk.log: es-execOnlyWhenPreviousSuspended.log es-basic-errfile-empty.log: es-maxbytes-bulk.log es-basic-errfile-popul.log: es-basic-errfile-empty.log es-bulk-errfile-empty.log: es-basic-errfile-popul.log es-bulk-errfile-popul.log: es-bulk-errfile-empty.log diskqueue-multithread-es.log: es-bulk-errfile-popul.log es-writeoperation.log: diskqueue-multithread-es.log elasticsearch-stop.log: es-writeoperation.log if ENABLE_IMPSTATS TESTS += $(TESTS_ELASTICSEARCH_IMPSTATS) es-basic-ha.log: es-writeoperation.log es-bulk-retry.log: es-basic-ha.log elasticsearch-stop.log: es-bulk-retry.log endif if ENABLE_IMFILE TESTS += $(TESTS_ELASTICSEARCH_IMFILE) es-bulk-errfile-popul-def-format.log: es-bulk-retry.log es-bulk-errfile-popul-erronly.log: es-bulk-errfile-popul-def-format.log es-bulk-errfile-popul-erronly-interleaved.log: es-bulk-errfile-popul-erronly.log es-bulk-errfile-popul-def-interleaved.log: es-bulk-errfile-popul-erronly-interleaved.log elasticsearch-stop.log: es-bulk-errfile-popul-def-interleaved.log endif if HAVE_VALGRIND TESTS += $(TESTS_ELASTICSEARCH_VALGRIND) es-basic-bulk-vg.log: es-writeoperation.log es-basic-bulk-vg.log: es-bulk-retry.log es-basic-bulk-vg.log: es-bulk-errfile-popul-def-interleaved.log es-basic-ha-vg.log: es-basic-bulk-vg.log elasticsearch-stop.log: es-basic-ha-vg.log endif endif # if ENABLE_ELASTICSEARCH_TESTS # Helper skeletons which are required by other active tests but should not be run standalone # The following tests were found to be distributed (in EXTRA_DIST) but not executed # (missing from TESTS) in the main branch. They likely have pre-existing issues # (e.g. expired certificates, timing races) and should be audited before re-enabling. if ENABLE_DEFAULT_TESTS TESTS += $(TESTS_DEFAULT) TESTS += $(TESTS_JSON_OMITIFZERO) TESTS += $(TESTS_SEGMENTED_DISK_QUEUE) if ENABLE_SEGQUEUE_TOOL TESTS += $(TESTS_SEGQUEUE_TOOL) endif if ENABLE_IMPSTATS TESTS += $(TESTS_SEGMENTED_DISK_QUEUE_IMPSTATS) endif if HAVE_LIBYAML TESTS += $(TESTS_SEGMENTED_DISK_QUEUE_LIBYAML) endif if ENABLE_MMSNAREPARSE TESTS += $(TESTS_MMSNAREPARSE_MINIMAL) if HAVE_VALGRIND TESTS += $(TESTS_MMSNAREPARSE_VALGRIND) endif endif if ENABLE_OMSENDERTRACK TESTS += $(TESTS_OMSENDERTRACK) if HAVE_VALGRIND TESTS += $(TESTS_OMSENDERTRACK_VALGRIND) endif # if HAVE_VALGRIND endif if ENABLE_LIBZSTD TESTS += $(TESTS_LIBZSTD) if HAVE_VALGRIND TESTS += $(TESTS_LIBZSTD_VALGRIND) endif # if HAVE_VALGRIND endif if ENABLE_LIBGCRYPT TESTS += $(TESTS_LIBGCRYPT) endif # ENABLE_LIBGCRYPT if HAVE_VALGRIND # note if the same test is added multiple times, it still is only executed once! if ENABLE_GNUTLS_TESTS TESTS += $(TESTS_GNUTLS_WRONG_OPT) endif # ENABLE_GNUTLS_TESTS if ENABLE_OSSL TESTS += $(TESTS_OSSL_WRONG_OPT) endif # ENABLE_OSSL TESTS += $(TESTS_DEFAULT_VALGRIND) if ENABLE_LIBGCRYPT TESTS += $(TESTS_LIBGCRYPT_VALGRIND) endif # ENABLE_LIBGCRYPT endif # HAVE_VALGRIND if HAVE_LIBYAML TESTS += $(TESTS_LIBYAML) if ENABLE_INOTIFY TESTS += $(TESTS_RATELIMIT_WATCH) endif # ENABLE_INOTIFY if ENABLE_IMPTCP if ENABLE_MMJSONPARSE TESTS += $(TESTS_LIBYAML_IMPTCP_MMJSONPARSE) endif # ENABLE_MMJSONPARSE endif # ENABLE_IMPTCP if ENABLE_IMTCP_TESTS TESTS += $(TESTS_LIBYAML_IMTCP) if ENABLE_OSSL TESTS += $(TESTS_LIBYAML_IMTCP_OSSL) endif # ENABLE_OSSL endif # ENABLE_IMTCP_TESTS if ENABLE_OSSL TESTS += $(TESTS_LIBYAML_OSSL) endif # ENABLE_OSSL if ENABLE_IMHTTP TESTS += $(TESTS_LIBYAML_IMHTTP) endif # ENABLE_IMHTTP if ENABLE_OMSTDOUT TESTS += $(TESTS_LIBYAML_OMSTDOUT) endif # ENABLE_OMSTDOUT endif # HAVE_LIBYAML endif # ENABLE_DEFAULT_TESTS if ENABLE_OMHTTP TESTS += $(TESTS_OMHTTP) if HAVE_VALGRIND TESTS += $(TESTS_OMHTTP_VALGRIND) endif endif if ENABLE_IMFIFO TESTS += imfifo.sh if HAVE_VALGRIND TESTS += imfifo-vg.sh endif if HAVE_LIBYAML TESTS += yaml-imfifo.sh endif endif if ENABLE_EXTENDED_TESTS # random.sh is temporarily disabled as it needs some work # to rsyslog core to complete in reasonable time #TESTS += random.sh if ENABLE_IMFILE_TESTS TESTS += $(TESTS_IMFILE_EXTENDED) endif # ENABLE_IMFILE_TESTS endif if ENABLE_IMFILE_TESTS TESTS += $(TESTS_IMFILE) if ENABLE_MMNORMALIZE TESTS += $(TESTS_IMFILE_MMNORMALIZE) endif if ENABLE_IMPSTATS TESTS += $(TESTS_IMFILE_IMPSTATS) endif if HAVE_VALGRIND TESTS += $(TESTS_IMFILE_VALGRIND) if ENABLE_HELGRIND TESTS += $(TESTS_IMFILE_HELGRIND) endif # ENABLE_HELGRIND if ENABLE_MMNORMALIZE TESTS += $(TESTS_IMFILE_MMNORMALIZE_VALGRIND) endif # ENABLE_MMNORMALIZE endif # HAVE_VALGRIND endif # ENABLE_IMFILE_TESTS if ENABLE_IMTCP_TESTS TESTS += $(TESTS_IMTCP) TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_ZLIB) if ENABLE_LIBZSTD TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD) if HAVE_LIBYAML TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD_YAML) endif # HAVE_LIBYAML endif # ENABLE_LIBZSTD if HAVE_LIBYAML TESTS += $(TESTS_IMTCP_YAML) endif # HAVE_LIBYAML if ENABLE_IMPTCP TESTS += $(TESTS_RATELIMIT) endif # ENABLE_IMPTCP if HAVE_LIBYAML TESTS += $(TESTS_RATELIMIT_YAML) endif # HAVE_LIBYAML if HAVE_VALGRIND TESTS += $(TESTS_IMTCP_VALGRIND) endif # HAVE_VALGRIND if ENABLE_IMTCP_EPOLL if ENABLE_IMPSTATS TESTS += $(TESTS_IMTCP_IMPSTATS) TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_ZLIB_IMPSTATS) if ENABLE_LIBZSTD TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_ZSTD_IMPSTATS) endif # ENABLE_LIBZSTD endif # ENABLE_IMPSTATS endif # ENABLE_IMTCP_EPOLL endif # ENABLE_IMTCP_TESTS if ENABLE_SNMP TESTS += $(TESTS_SNMP_MINIMAL) if ENABLE_SNMP_TESTS TESTS += $(TESTS_SNMP_FULL) endif # if ENABLE_SNMP_TESTS endif # if ENABLE_SNMP if ENABLE_MMUTF8FIX TESTS += $(TESTS_MMUTF8FIX) endif # if ENABLE_MMUTF8FIX if ENABLE_MMUTF8FIX if HAVE_LIBYAML TESTS += $(TESTS_MMUTF8FIX_YAML) endif # HAVE_LIBYAML endif # if ENABLE_MMUTF8FIX if ENABLE_MMUTF8FIX if ENABLE_MMPSTRUCDATA TESTS += $(TESTS_MMUTF8FIX_SD) endif # if ENABLE_MMPSTRUCDATA endif # if ENABLE_MMUTF8FIX if ENABLE_MMAITAG TESTS += $(TESTS_MMAITAG) endif if ENABLE_MAIL TESTS += $(TESTS_MAIL) if ENABLE_MMJSONPARSE TESTS += $(TESTS_MAIL_MMJSONPARSE) endif # if ENABLE_MMJSONPARSE endif # if ENABLE_MAIL if ENABLE_MMANON TESTS += $(TESTS_MMANON) endif # if ENABLE_MMANON if ENABLE_CLICKHOUSE_TESTS TESTS += $(TESTS_CLICKHOUSE) clickhouse-basic.log: clickhouse-start.log clickhouse-dflt-tpl.log: clickhouse-basic.log clickhouse-retry-error.log: clickhouse-dflt-tpl.log clickhouse-load.log: clickhouse-retry-error.log clickhouse-bulk.log: clickhouse-load.log clickhouse-bulk-load.log: clickhouse-bulk.log clickhouse-limited-batch.log: clickhouse-bulk-load.log clickhouse-select.log: clickhouse-limited-batch.log clickhouse-errorfile.log: clickhouse-select.log clickhouse-wrong-quotation-marks.log: clickhouse-errorfile.log clickhouse-wrong-template-option.log: clickhouse-wrong-quotation-marks.log clickhouse-wrong-insert-syntax.log: clickhouse-wrong-template-option.log clickhouse-stop.log: clickhouse-wrong-insert-syntax.log if HAVE_VALGRIND TESTS += $(TESTS_CLICKHOUSE_VALGRIND) clickhouse-basic-vg.log: clickhouse-wrong-insert-syntax.log clickhouse-load-vg.log: clickhouse-basic-vg.log clickhouse-bulk-vg.log: clickhouse-load-vg.log clickhouse-bulk-load-vg.log: clickhouse-bulk-vg.log clickhouse-stop.log: clickhouse-bulk-load-vg.log endif # VALGRIND endif # CLICKHOUSE_TESTS if ENABLE_LIBFAKETIME TESTS += $(TESTS_LIBFAKETIME) # now come faketime tests that utilize mmnormalize - aka "no endif here" if ENABLE_MMNORMALIZE TESTS += $(TESTS_MMNORMALIZE_FAKETIME) endif endif if ENABLE_PGSQL TESTS += $(TESTS_PGSQL_CONFIG) if ENABLE_PGSQL_TESTS TESTS += $(TESTS_PGSQL) pgsql-basic-cnf6.log: pgsql-basic.log pgsql-basic-threads-cnf6.log: pgsql-basic-cnf6.log pgsql-template.log: pgsql-basic-threads-cnf6.log pgsql-template-cnf6.log: pgsql-template.log pgsql-actq-mt-withpause.log: pgsql-template-cnf6.log pgsql-template-threads-cnf6.log: pgsql-actq-mt-withpause.log if HAVE_VALGRIND TESTS += $(TESTS_PGSQL_VALGRIND) pgsql-basic-vg.log: pgsql-template-threads-cnf6.log pgsql-template-vg.log: pgsql-basic-vg.log pgsql-basic-cnf6-vg.log: pgsql-template-vg.log pgsql-template-cnf6-vg.log: pgsql-basic-cnf6-vg.log pgsql-actq-mt-withpause-vg.log: pgsql-template-cnf6-vg.log endif endif endif if ENABLE_MYSQL_TESTS TESTS += $(TESTS_MYSQL) MYSQL_PARALLEL_LOGS = \ $(filter-out mysqld-start.log mysqld-stop.log, $(TESTS_MYSQL:.sh=.log)) if HAVE_VALGRIND TESTS += $(TESTS_MYSQL_VALGRIND) MYSQL_PARALLEL_LOGS += $(TESTS_MYSQL_VALGRIND:.sh=.log) endif if ENABLE_OMLIBDBI # we piggy-back on MYSQL_TESTS as we need the same environment TESTS += $(TESTS_LIBDBI) MYSQL_PARALLEL_LOGS += $(TESTS_LIBDBI:.sh=.log) if HAVE_VALGRIND TESTS += $(TESTS_LIBDBI_VALGRIND) MYSQL_PARALLEL_LOGS += $(TESTS_LIBDBI_VALGRIND:.sh=.log) endif endif # MySQL tests use one shared server but each test creates its own database. # Start the server once, run independent database tests in parallel, then stop # the server only after all MySQL-backed tests have completed. $(MYSQL_PARALLEL_LOGS): mysqld-start.log mysqld-stop.log: $(MYSQL_PARALLEL_LOGS) endif # MYSQL_TESTS if ENABLE_FMHTTP TESTS += $(TESTS_FMHTTP) if HAVE_VALGRIND TESTS += $(TESTS_FMHTTP_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_FMHTTP if ENABLE_ROOT_TESTS TESTS += $(TESTS_ROOT) if ENABLE_IP TESTS += $(TESTS_ROOT_IP) endif if HAVE_VALGRIND TESTS += $(TESTS_ROOT_VALGRIND) endif endif # see comments in configure.ac on flaky tests for important details!!! if ENABLE_FLAKY_TESTS #TESTS += # if ENABLE_OMHTTP TESTS += $(TESTS_OMHTTP_FLAKY) if HAVE_VALGRIND TESTS += $(TESTS_OMHTTP_FLAKY_VALGRIND) endif # end if HAVE_VALGRIND endif # end if ENABLE_OMHTTP endif # end if ENABLE_FLAKY_TESTS if ENABLE_JOURNAL_TESTS if ENABLE_IMJOURNAL TESTS += $(TESTS_IMJOURNAL) if HAVE_VALGRIND TESTS += $(TESTS_IMJOURNAL_VALGRIND) endif endif if ENABLE_OMJOURNAL TESTS += $(TESTS_OMJOURNAL) endif endif #if ENABLE_JOURNAL_TESTS if ENABLE_IMPROG TESTS += $(TESTS_IMPROG) if HAVE_VALGRIND TESTS += $(TESTS_IMPROG_VALGRIND) endif # ENABLE_IMPROG endif if ENABLE_MMDARWIN TESTS += $(TESTS_MMDARWIN) if HAVE_VALGRIND TESTS += $(TESTS_MMDARWIN_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_IMPROG if ENABLE_OMPROG TESTS += $(TESTS_OMPROG) if HAVE_VALGRIND TESTS += $(TESTS_OMPROG_VALGRIND) endif endif if ENABLE_OMOTEL TESTS += $(TESTS_OMOTEL) endif if ENABLE_OMKAFKA TESTS += $(TESTS_OMKAFKA_NO_SERVICE) if ENABLE_IMKAFKA if ENABLE_KAFKA_TESTS TESTS += $(TESTS_KAFKA_SELFTEST) if HAVE_VALGRIND TESTS += $(TESTS_KAFKA_VALGRIND) endif TESTS += $(TESTS_KAFKA) if HAVE_VALGRIND omkafka-vg.log: kafka-selftest.log imkafka-vg.log: omkafka-vg.log omkafka.log: imkafka-vg.log else omkafka.log: kafka-selftest.log endif imkafka.log: omkafka.log imkafka-backgrounded.log: imkafka.log imkafka-config-err-ruleset.log: imkafka-backgrounded.log imkafka-config-err-param.log: imkafka-config-err-ruleset.log imkafka-hang-on-no-kafka.log: imkafka-config-err-param.log imkafka-hang-other-action-on-no-kafka.log: imkafka-hang-on-no-kafka.log imkafka_multi_single.log: imkafka-hang-other-action-on-no-kafka.log sndrcv_kafka.log: imkafka_multi_single.log imkafka_multi_group.log: sndrcv_kafka.log imkafka_multi_topic.log: imkafka_multi_group.log sndrcv_kafka_multi_topics.log: imkafka_multi_topic.log omkafkadynakey.log: sndrcv_kafka_multi_topics.log omkafka-headers.log: omkafkadynakey.log endif endif endif if ENABLE_OMAZUREEVENTHUBS if ENABLE_OMAZUREEVENTHUBS_TESTS TESTS += $(TESTS_OMAZUREEVENTHUBS) if HAVE_VALGRIND TESTS += $(TESTS_OMAZUREEVENTHUBS_VALGRIND) endif endif endif if ENABLE_OMAZUREDCE if ENABLE_OMAZUREDCE_TESTS TESTS += $(TESTS_OMAZUREDCE) if HAVE_LIBYAML TESTS += $(TESTS_OMAZUREDCE_YAML) endif if HAVE_VALGRIND TESTS += $(TESTS_OMAZUREDCE_VALGRIND) endif endif endif if ENABLE_OMAWSLOGSHLC if ENABLE_OMAWSLOGSHLC_TESTS TESTS += $(TESTS_OMAWSLOGSHLC) if ENABLE_IMTCP_TESTS TESTS += $(TESTS_OMAWSLOGSHLC_IMTCP) endif endif endif if ENABLE_IMDOCKER if ENABLE_IMDOCKER_TESTS TESTS += $(TESTS_IMDOCKER) if HAVE_VALGRIND TESTS += $(TESTS_IMDOCKER_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_IMDOCKER_TESTS endif # ENABLE_IMDOCKER if ENABLE_IMCZMQ TESTS += $(TESTS_IMCZMQ) endif # ENABLE_IMCZMQ if ENABLE_IMHTTP TESTS += $(TESTS_IMHTTP) if HAVE_VALGRIND TESTS += $(TESTS_IMHTTP_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_IMHTTP if ENABLE_IMBEATS if ENABLE_TESTBENCH TESTS += $(TESTS_IMBEATS) if ENABLE_OPENSSL TESTS += $(TESTS_IMBEATS_OPENSSL) endif # ENABLE_OPENSSL if ENABLE_IMPSTATS TESTS += $(TESTS_IMBEATS_IMPSTATS) endif # ENABLE_IMPSTATS if HAVE_LIBYAML TESTS += $(TESTS_IMBEATS_YAML) endif # HAVE_LIBYAML if ENABLE_ELASTICSEARCH_TESTS TESTS += $(TESTS_IMBEATS_ELASTICSEARCH) endif # ENABLE_ELASTICSEARCH_TESTS endif # ENABLE_TESTBENCH endif # ENABLE_IMBEATS if ENABLE_OMRABBITMQ check_PROGRAMS += miniamqpsrvr miniamqpsrvr_SOURCES = miniamqpsrvr.c miniamqpsrvr_CPPFLAGS = $(PTHREADS_CFLAGS) $(RABBITMQ_CFLAGS) $(RSRT_CFLAGS) miniamqpsrvr_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) TESTS += $(TESTS_OMRABBITMQ) if HAVE_VALGRIND TESTS += $(TESTS_OMRABBITMQ_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_OMRABBITMQ if ENABLE_REDIS_TESTS if ENABLE_IMHIREDIS TESTS += $(TESTS_IMHIREDIS) if HAVE_VALGRIND TESTS += $(TESTS_IMHIREDIS_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_IMHIREDIS if ENABLE_OMHIREDIS TESTS += $(TESTS_OMHIREDIS) if HAVE_VALGRIND TESTS += $(TESTS_OMHIREDIS_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_OMHIREDIS endif # ENABLE_REDIS_TESTS if ENABLE_IMPSTATS TESTS += $(TESTS_IMPSTATS) if ENABLE_IMPSTATS_PUSH TESTS += $(TESTS_IMPSTATS_PUSH) endif if HAVE_VALGRIND TESTS += $(TESTS_IMPSTATS_VALGRIND) endif endif if ENABLE_IMPTCP # note that some tests simply USE imptcp, but they also # need to be disabled if we do not have this module TESTS += $(TESTS_IMPTCP) TESTS += $(TESTS_IMPTCP_STREAM_ALWAYS) TESTS += $(TESTS_IMPTCP_FROMHOST_PORT) if HAVE_LIBYAML TESTS += $(TESTS_RATELIMIT_IMPTCP_YAML) endif # HAVE_LIBYAML if HAVE_VALGRIND TESTS += $(TESTS_IMPTCP_VALGRIND) if ENABLE_FMHASH TESTS += $(TESTS_IMPTCP_FMHASH_VALGRIND) endif # ENABLE_FMHASH endif # HAVE_VALGRIND if ENABLE_FMUNFLATTEN TESTS += $(TESTS_IMPTCP_FMUNFLATTEN) if HAVE_VALGRIND TESTS += $(TESTS_IMPTCP_FMUNFLATTEN_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_FMUNFLATTEN if ENABLE_FFAUP TESTS += $(TESTS_IMPTCP_FFAUP) if HAVE_VALGRIND TESTS += $(TESTS_IMPTCP_FFAUP_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_FFAUP if ENABLE_IMPSTATS TESTS += $(TESTS_IMPTCP_STREAM_ALWAYS_IMPSTATS) endif # ENABLE_IMPSTATS endif if ENABLE_FMPCRE TESTS += $(TESTS_FMPCRE) endif if ENABLE_MMPSTRUCDATA TESTS += $(TESTS_MMPSTRUCDATA) if HAVE_VALGRIND TESTS += $(TESTS_MMPSTRUCDATA_VALGRIND) endif endif if ENABLE_MMRFC5424ADDHMAC if ENABLE_IMTCP_TESTS TESTS += $(TESTS_MMRFC5424ADDHMAC) endif endif if ENABLE_MMRM1STSPACE TESTS += $(TESTS_MMRM1STSPACE) endif if ENABLE_PMNULL TESTS += $(TESTS_PMNULL) endif if ENABLE_OMSTDOUT TESTS += $(TESTS_OMSTDOUT) endif if ENABLE_PMNORMALIZE TESTS += $(TESTS_PMNORMALIZE) if HAVE_VALGRIND TESTS += $(TESTS_PMNORMALIZE_VALGRIND) endif if ENABLE_IMTCP_TESTS TESTS += $(TESTS_PMNORMALIZE_DEBUG) if HAVE_LIBYAML TESTS += $(TESTS_PMNORMALIZE_YAML) endif endif endif if ENABLE_MMNORMALIZE TESTS += $(TESTS_MMNORMALIZE) if HAVE_VALGRIND TESTS += $(TESTS_MMNORMALIZE_VALGRIND) endif if ENABLE_IMTCP_TESTS TESTS += $(TESTS_MMNORMALIZE_DEBUG) if HAVE_LIBYAML TESTS += $(TESTS_MMNORMALIZE_YAML) endif if LOGNORM_TURBO_SUPPORTED TESTS += $(TESTS_MMNORMALIZE_TURBO) if HAVE_LIBYAML TESTS += $(TESTS_MMNORMALIZE_TURBO_YAML) endif endif endif if ENABLE_IMPTCP TESTS += $(TESTS_MMNORMALIZE_IMPTCP) endif if LOGNORM_REGEX_SUPPORTED TESTS += $(TESTS_MMNORMALIZE_REGEX) endif endif # ENABLE_MMNORMALIZE if ENABLE_MMLEEFPARSE if ENABLE_IMPTCP TESTS += $(TESTS_MMLEEFPARSE) endif endif if ENABLE_MMJSONPARSE TESTS += $(TESTS_MMJSONPARSE_PART1) if ENABLE_IMPSTATS TESTS += $(TESTS_MMJSONPARSE_IMPSTATS) endif if ENABLE_IMPTCP TESTS += $(TESTS_MMJSONPARSE_IMPTCP) endif if HAVE_VALGRIND TESTS += $(TESTS_MMJSONPARSE_VALGRIND) endif TESTS += $(TESTS_MMJSONPARSE_PART2) endif if ENABLE_MMJSONTRANSFORM if ENABLE_IMTCP_TESTS TESTS += $(TESTS_MMJSONTRANSFORM_IMTCP) if HAVE_LIBYAML TESTS += $(TESTS_MMJSONTRANSFORM_LIBYAML) if ENABLE_INOTIFY TESTS += $(TESTS_MMJSONTRANSFORM_WATCH) endif endif endif if ENABLE_MMJSONPARSE TESTS += $(TESTS_MMJSONTRANSFORM_MMJSONPARSE) endif endif if ENABLE_MMDBLOOKUP TESTS += $(TESTS_MMDBLOOKUP) if HAVE_VALGRIND TESTS += $(TESTS_MMDBLOOKUP_VALGRIND) endif endif if ENABLE_GNUTLS_TESTS TESTS += $(TESTS_GNUTLS) if ENABLE_IMTCP_TESTS TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_GNUTLS) endif # ENABLE_IMTCP_TESTS if HAVE_VALGRIND TESTS += $(TESTS_GNUTLS_VALGRIND) endif if ENABLE_OPENSSL TESTS += $(TESTS_GNUTLS_OPENSSL) endif endif if ENABLE_MBEDTLS TESTS += $(TESTS_MBEDTLS) if ENABLE_IMTCP_TESTS TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_MBEDTLS) endif # ENABLE_IMTCP_TESTS if HAVE_VALGRIND TESTS += $(TESTS_MBEDTLS_VALGRIND) endif endif if ENABLE_OSSL TESTS += $(TESTS_OSSL) if ENABLE_OPENSSL TESTS += $(TESTS_OSSL_OPENSSL) if ENABLE_IMTCP_TESTS TESTS += $(TESTS_IMTCP_STREAM_ALWAYS_OSSL) endif # ENABLE_IMTCP_TESTS if HAVE_VALGRIND TESTS += $(TESTS_OSSL_OPENSSL_VALGRIND) endif endif if ENABLE_OPENSSL TESTS += $(TESTS_OSSL_OPENSSL_SNI) endif if ENABLE_WOLFSSL TESTS += $(TESTS_OSSL_WOLFSSL) endif endif if ENABLE_GNUTLS_TESTS if ENABLE_OPENSSL TESTS += $(TESTS_GNUTLS_OPENSSL_INTEROP) endif endif if ENABLE_OMUXSOCK TESTS += $(TESTS_OMUXSOCK) if HAVE_VALGRIND TESTS += $(TESTS_OMUXSOCK_VALGRIND) endif # HAVE_VALGRIND endif if ENABLE_RELP TESTS += $(TESTS_RELP) if HAVE_LIBYAML TESTS += $(TESTS_RELP_YAML) endif # HAVE_LIBYAML if ENABLE_OPENSSL TESTS += $(TESTS_RELP_OPENSSL) endif # ENABLE_OPENSSL if ENABLE_GNUTLS TESTS += $(TESTS_RELP_GNUTLS) if USE_RELPENGINESETTLSCFGCMD TESTS += $(TESTS_RELP_GNUTLS_CFG) endif # USE_RELPENGINESETTLSCFGCMD endif # ENABLE_GNUTLS if HAVE_VALGRIND TESTS += $(TESTS_RELP_VALGRIND) endif # HAVE_VALGRIND endif if ENABLE_IMDTLS TESTS += $(TESTS_IMDTLS) if HAVE_VALGRIND TESTS += $(TESTS_IMDTLS_VALGRIND) endif # HAVE_VALGRIND if ENABLE_OMDTLS TESTS += $(TESTS_IMDTLS_OMDTLS) if HAVE_VALGRIND TESTS += $(TESTS_IMDTLS_OMDTLS_VALGRIND) endif # HAVE_VALGRIND endif # ENABLE_OMDTLS endif # ENABLE_IMDTLS if ENABLE_OMUDPSPOOF TESTS += $(TESTS_OMUDPSPOOF) if ENABLE_IMTCP_TESTS TESTS += $(TESTS_OMUDPSPOOF_IMTCP) endif # ENABLE_IMTCP_TESTS endif #disabled as array-passing mode is no longer supported: omod-if-array.sh # omod-if-array.sh # omod-if-array-udp.sh if ENABLE_IMPTCP TESTS += $(TESTS_IMPTCP_TABESCAPE) endif if ENABLE_OMRULESET TESTS += $(TESTS_OMRULESET) endif if ENABLE_PMDB2DIAG TESTS += $(TESTS_PMDB2DIAG) endif if ENABLE_PMCISCOIOS TESTS += $(TESTS_PMCISCOIOS) endif if ENABLE_PMSNARE TESTS += $(TESTS_PMSNARE) endif if ENABLE_PMLASTMSG TESTS += $(TESTS_PMLASTMSG) endif if ENABLE_IMBATCHREPORT TESTS += $(TESTS_IMBATCHREPORT) if HAVE_VALGRIND TESTS += $(TESTS_IMBATCHREPORT_VALGRIND) endif # ENABLE_IMBATCHREPORT endif if ENABLE_OMTCL TESTS += $(TESTS_OMTCL) endif if ENABLE_MMTAGHOSTNAME TESTS += $(TESTS_MMTAGHOSTNAME) endif if ENABLE_MMKUBERNETES if ENABLE_MMJSONPARSE if ENABLE_IMFILE if ENABLE_IMPSTATS TESTS += $(TESTS_MMKUBERNETES) if HAVE_VALGRIND TESTS += $(TESTS_MMKUBERNETES_VALGRIND) endif endif endif endif endif if ENABLE_IMKUBERNETES TESTS += $(TESTS_IMKUBERNETES) endif if ENABLE_IMTUXEDOULOG TESTS += $(TESTS_IMTUXEDOULOG) if HAVE_VALGRIND TESTS += $(TESTS_IMTUXEDOULOG_VALGRIND) endif # ENABLE_IMTUXEDOULOG endif if ENABLE_OMAMQP1 TESTS += $(TESTS_OMAMQP1) if HAVE_VALGRIND TESTS += $(TESTS_OMAMQP1_VALGRIND) endif endif # ENABLE_OMAMQP1 if HAVE_SRV_DISCOVERY TESTS += $(TESTS_SRV_DISCOVERY) endif # HAVE_SRV_DISCOVERY TESTS += $(TESTS_RELEASE_PACKAGING) if ENABLE_GNUTLS check_PROGRAMS += gnutls_sni_server gnutls_sni_server_SOURCES = gnutls_sni_server.c gnutls_sni_server_CFLAGS = $(GNUTLS_CFLAGS) gnutls_sni_server_CPPFLAGS = $(GNUTLS_CFLAGS) gnutls_sni_server_LDADD = $(GNUTLS_LIBS) $(SOL_LIBS) endif if ENABLE_OPENSSL check_PROGRAMS += openssl_sni_server openssl_mtls_server openssl_sni_server_SOURCES = openssl_sni_server.c openssl_sni_server_CFLAGS = $(OPENSSL_CFLAGS) openssl_sni_server_CPPFLAGS = $(OPENSSL_CFLAGS) openssl_sni_server_LDADD = $(OPENSSL_LIBS) $(SOL_LIBS) openssl_mtls_server_SOURCES = openssl_mtls_server.c openssl_mtls_server_CFLAGS = $(OPENSSL_CFLAGS) openssl_mtls_server_CPPFLAGS = $(OPENSSL_CFLAGS) openssl_mtls_server_LDADD = $(OPENSSL_LIBS) $(SOL_LIBS) endif endif # if ENABLE_TESTBENCH TESTS_ENVIRONMENT+= TESTTOOL_DIR='$(abs_top_builddir)/tests' test_files = testbench.h runtime-dummy.c DISTCLEANFILES=rsyslog.pid testbench_test_failed_rsyslog distclean-local: rm -rf .dep_cache .dep_wrk EXTRA_DIST += \ faketime_common.sh \ privdrop_common.sh \ rscript_compare-common.sh \ omfwd-tls-ossl-pkcs11-error.sh \ omfwd-tls-ossl-pkcs11-ecdsa-sigalgs-common.sh \ omfwd-tls-ossl-pkcs11-sigalgs-negative-common.sh \ omfwd-tls-ossl-pkcs11-sigalgs-common.sh \ rscript_parse_time_get-ts.py \ queue-persist-drvr.sh \ daqueue-persist-drvr.sh \ snmptrapreceiverv2.py \ validate_json_shell.sh \ tls-check-for-certificate.sh \ set-envvars.in \ urlencode.py \ dns_srv_mock.py \ omrelp-keepalive.sh \ improg-simul.sh \ sndrcv_drvr.sh \ sndrcv_drvr_noexit.sh \ diag.sh \ testsuites/mmexternal-SegFault-mm-python.py \ testsuites/mmexternal-hang-no-reply.sh \ testsuites/mmexternal-no-output.sh \ testsuites/mmexternal-single-instance-bin.sh \ testsuites/mmexternal-null-prop-bin.sh \ testsuites/mmexternal-too-long-reply-bin.sh \ testsuites/mmexternal-trickle-no-lf.sh \ testsuites/mmsnareparse/sample-custom-pattern.data \ testsuites/mmsnareparse/sample-windows2022-security.data \ testsuites/mmsnareparse/sample-windows2025-security.data \ testsuites/mmsnareparse/sample-events.data \ 1.rstest 2.rstest 3.rstest err1.rstest \ testsuites/include-std1-omfile-action.conf \ testsuites/include-std2-omfile-action.conf \ tls-certs/ca-key.pem \ tls-certs/ca.pem \ tls-certs/cert.pem \ tls-certs/certchained.pem \ tls-certs/key.pem \ tls-certs/ca-fail.pem \ tls-certs/cert-fail.pem \ tls-certs/key-fail.pem \ testsuites/x.509/ca.srl \ testsuites/x.509/client-cert-new.pem \ testsuites/x.509/client-new.csr \ testsuites/x.509/client-revoked-key.pem \ testsuites/x.509/client-revoked-valid.pem \ testsuites/x.509/client-revoked.csr \ testsuites/x.509/client-revoked.pem \ testsuites/x.509/crl.pem \ testsuites/x.509/crl-expired.pem \ testsuites/x.509/index.txt \ testsuites/x.509/index.txt.attr \ testsuites/x.509/newcerts/01.pem \ testsuites/x.509/newcerts/02.pem \ testsuites/x.509/newcerts/03.pem \ testsuites/x.509/newcerts/04.pem \ testsuites/x.509/openssl-cmds.sh \ testsuites/x.509/openssl.cnf \ testsuites/x.509/serial \ testsuites/x.509/ca.pem \ testsuites/x.509/ca-key.pem \ testsuites/x.509/client-cert.pem \ testsuites/x.509/client-key.pem \ testsuites/x.509/machine-cert.pem \ testsuites/x.509/machine-key.pem \ testsuites/x.509/client-expired-cert.pem \ testsuites/x.509/client-expired-key.pem \ ratelimit_name.sh \ test_policy_hup.yaml \ ratelimit_duplicate.sh \ ratelimit-many-named-configs.sh \ cfg.sh \ cfg1.cfgtest \ cfg1.testin \ cfg2.cfgtest \ cfg2.testin \ cfg3.cfgtest \ cfg3.testin \ cfg4.cfgtest \ cfg4.testin \ DevNull.cfgtest \ err1.rstest \ NoExistFile.cfgtest \ killrsyslog.sh \ mmdb.rb \ test.mmdb \ with_space.mmdb \ GeoIP2-City-Test.mmdb \ testsuites/es.yml \ es_response_get_msgnum.py \ elasticsearch-error-format-check.py \ testsuites/imptcp_framing_regex.testdata \ testsuites/imtcp-multiline.testdata \ testsuites/imptcp_framing_regex-oversize.testdata \ testsuites/imptcp_multi_line.testdata \ testsuites/no_octet_counted.testdata \ testsuites/spframingfix.testdata \ bad_qi/dbq.qi \ testsuites/mysql-truncate.sql \ testsuites/mysql-select-msg.sql \ ../devtools/prep-mysql-db.sh \ ../devtools/prepare_clickhouse.sh \ testsuites/kafka-server.properties \ testsuites/kafka-server.dep_wrk1.properties \ testsuites/kafka-server.dep_wrk2.properties \ testsuites/kafka-server.dep_wrk3.properties \ testsuites/zoo.cfg \ testsuites/zoo.dep_wrk1.cfg \ testsuites/zoo.dep_wrk2.cfg \ testsuites/zoo.dep_wrk3.cfg \ testsuites/dynstats_empty_input \ testsuites/dynstats_input \ testsuites/dynstats_input_1 \ testsuites/dynstats_input_2 \ testsuites/dynstats_input_3 \ testsuites/dynstats_input_more_0 \ testsuites/dynstats_input_more_1 \ testsuites/dynstats_input_more_2 \ testsuites/mmnormalize_variable.rulebase \ testsuites/date_time_msg \ testsuites/mmnormalize_tokenized.rulebase \ testsuites/tokenized_input \ testsuites/complex_replace_input \ testsuites/wrap3_input\ testsuites/yaml_complex_input \ testsuites/json_array_input \ testsuites/json_object_input \ testsuites/json_nonarray_input \ testsuites/mmnormalize_regex.rulebase \ testsuites/regex_input \ testsuites/stop_when_array_has_elem_input \ testsuites/xlate.lkp_tbl \ testsuites/xlate_more.lkp_tbl \ testsuites/xlate_array.lkp_tbl \ testsuites/xlate_array_more.lkp_tbl \ testsuites/xlate_array_misuse.lkp_tbl \ testsuites/xlate_array_more_misuse.lkp_tbl \ testsuites/xlate_sparse_array.lkp_tbl \ testsuites/lookup_sparse_array_ipv4.lkp_tbl \ testsuites/xlate_sparse_array_more.lkp_tbl \ testsuites/xlate_array_empty_table.lkp_tbl \ testsuites/xlate_array_no_index.lkp_tbl \ testsuites/xlate_array_no_table.lkp_tbl \ testsuites/xlate_array_no_value.lkp_tbl \ testsuites/xlate_empty_file.lkp_tbl \ testsuites/xlate_incorrect_type.lkp_tbl \ testsuites/xlate_incorrect_version.lkp_tbl \ testsuites/xlate_sparseArray_empty_table.lkp_tbl \ testsuites/xlate_sparseArray_no_index.lkp_tbl \ testsuites/xlate_sparseArray_no_table.lkp_tbl \ testsuites/xlate_sparseArray_no_value.lkp_tbl \ testsuites/xlate_string_empty_table.lkp_tbl \ testsuites/xlate_string_no_index.lkp_tbl \ testsuites/xlate_string_no_table.lkp_tbl \ testsuites/xlate_string_no_value.lkp_tbl \ testsuites/xlate_invalid_json.lkp_tbl \ testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl \ testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl \ testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl \ known_issues.supp \ libmaxmindb.supp \ linux_localtime_r.supp \ CI/centos6-9.supp \ CI/centos7.supp \ CI/gcov.supp \ CI/ubuntu20.04.supp \ omtcl.tcl \ testsuites/pgsql-basic.sql \ testsuites/pgsql-select-msg.sql \ testsuites/pgsql-select-syslogtag.sql \ mmkubernetes_test_server.py \ mmkubernetes-basic.out.json \ mmkubernetes-cache-expire.out.expected \ mmkubernetes.supp \ testsuites/incltest.d/include.conf \ testsuites/abort-uncleancfg-goodcfg.conf \ testsuites/include-std-omfile-action.conf \ testsuites/invalid.conf \ testsuites/valid.conf \ testsuites/variable_leading_underscore.conf \ testsuites/action-tx-errfile.result \ improg-multiline-test.py \ testsuites/imhttp-large-data.txt \ testsuites/imhttp-apikeys.txt \ testsuites/docroot/file.txt \ testsuites/htpasswd \ omhttp_server.py \ omhttp-validate-response.py \ testsuites/omprog-defaults-bin.sh \ testsuites/omprog-output-capture-bin.sh \ testsuites/omprog-output-capture-mt-bin.py \ testsuites/improg-child-kill-bin.sh \ holdtcpopen.py \ testsuites/omprog-feedback-bin.sh \ testsuites/omprog-feedback-mt-bin.sh \ testsuites/omprog-feedback-timeout-bin.sh \ testsuites/omprog-close-unresponsive-bin.sh \ testsuites/omprog-diskq-restart-save-bin.sh \ testsuites/omprog-invalid-args-bin.sh \ testsuites/omprog-restart-terminated-bin.sh \ testsuites/omprog-single-instance-bin.sh \ testsuites/omprog-resume-interval-bin.sh \ testsuites/omprog-transactions-bin.sh \ omotel_proxy_server.py \ otel_collector_find_port.py \ testsuites/ommail-sendmail-bin.sh \ testsuites/ommail-smtp-server.py \ testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input \ imfile-endmsg.regex.crio.rulebase \ imfile-endmsg.regex.json.rulebase \ testsuites/msgvar-concurrency-array.rulebase \ testsuites/msgvar-concurrency-array-event.tags.rulebase \ testsuites/mmnormalize_processing_tests.rulebase \ testsuites/pmnormalize_basic.rulebase \ validate_json_equality.py \ testsuites/qradar_json \ testsuites/qradar_json-with-dots \ snmptrapreceiver.py \ omamqp1-common.sh ourtail_SOURCES = ourtail.c msleep_SOURCES = msleep.c omrelp_dflt_port_SOURCES = omrelp_dflt_port.c mangle_qi_SOURCES = mangle_qi.c chkseq_SOURCES = chkseq.c check_relpEngineVersion = check_relpEngineVersion.c have_relpSrvSetOversizeMode = have_relpSrvSetOversizeMode.c have_relpEngineSetTLSLibByName = have_relpEngineSetTLSLibByName.c have_relpSrvSetTlsConfigCmd = have_relpSrvSetTlsConfigCmd.c test_id_SOURCES = test_id.c uxsockrcvr_SOURCES = uxsockrcvr.c uxsockrcvr_LDADD = $(SOL_LIBS) tcpflood_SOURCES = tcpflood.c tcpflood_CFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS) tcpflood_CPPFLAGS = $(PTHREADS_CFLAGS) $(RELP_CFLAGS) tcpflood_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) $(RELP_LIBS) if ENABLE_GNUTLS tcpflood_CFLAGS += $(GNUTLS_CFLAGS) tcpflood_CPPFLAGS += $(GNUTLS_CFLAGS) tcpflood_LDADD += $(GNUTLS_LIBS) endif if ENABLE_OSSL if ENABLE_WOLFSSL tcpflood_CFLAGS += $(WOLFSSL_CFLAGS) tcpflood_CPPFLAGS += $(WOLFSSL_CFLAGS) tcpflood_LDADD += $(WOLFSSL_LIBS) else tcpflood_CFLAGS += $(OPENSSL_CFLAGS) tcpflood_CPPFLAGS += $(OPENSSL_CFLAGS) tcpflood_LDADD += $(OPENSSL_LIBS) endif endif minitcpsrv_SOURCES = minitcpsrvr.c minitcpsrv_LDADD = $(SOL_LIBS) syslog_caller_SOURCES = syslog_caller.c syslog_caller_CPPFLAGS = $(LIBLOGGING_STDLOG_CFLAGS) syslog_caller_LDADD = $(SOL_LIBS) $(LIBLOGGING_STDLOG_LIBS) journal_print_SOURCES = journal_print.c journal_print_CPPFLAGS = $(LIBSYSTEMD_JOURNAL_CFLAGS) journal_print_LDADD = $(LIBSYSTEMD_JOURNAL_LIBS) diagtalker_SOURCES = diagtalker.c diagtalker_LDADD = $(SOL_LIBS) randomgen_SOURCES = randomgen.c randomgen_LDADD = $(SOL_LIBS) inputfilegen_SOURCES = inputfilegen.c inputfilegen_LDADD = $(SOL_LIBS) # rtinit tests disabled for the moment - also questionable if they # really provide value (after all, everything fails if rtinit fails...) #rt_init_SOURCES = rt-init.c $(test_files) #rt_init_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) #rt_init_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) #rt_init_LDFLAGS = -export-dynamic # same for basic rscript tests #rscript_SOURCES = rscript.c getline.c $(test_files) #rscript_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) #rscript_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS) $(SOL_LIBS) #rscript_LDFLAGS = -export-dynamic rsyslog-8.2608.0/tests/PaxHeaders/glbl_setenv_err.sh0000644000000000000000000000013115035412264017412 xustar0030 mtime=1752569012.389827181 29 atime=1782715518.89879071 30 ctime=1787067804.092905767 rsyslog-8.2608.0/tests/glbl_setenv_err.sh0000777000175000017500000000121215035412264017060 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' # env var is missing equal sign and MUST trigger parsing error! global(environment="http_proxy ERROR") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! grep "http_proxy ERROR" < $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo echo "MESSAGE INDICATING ERROR ON ENVIRONMENT VARIABLE IS MISSING:" echo cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse_8bit_escape-udp.sh0000644000000000000000000000013115035412264022576 xustar0030 mtime=1752569012.406709056 29 atime=1782715518.89879071 30 ctime=1787067805.022923098 rsyslog-8.2608.0/tests/parsertest-parse_8bit_escape-udp.sh0000777000175000017500000000167415035412264022260 0ustar00rgerrger#!/bin/bash # add 2018-06-28 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") $Escape8BitCharactersOnReceive on template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<6>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\"" shutdown_when_empty wait_shutdown echo '6,kern,info,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: #303#244#303#266#303#274' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmkubernetes-basic.sh0000644000000000000000000000013215216464436020030 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.897790693 30 ctime=1787067808.139981181 rsyslog-8.2608.0/tests/mmkubernetes-basic.sh0000775000175000017500000002462415216464436017507 0ustar00rgerrger#!/bin/bash # added 2018-04-06 by richm, released under ASL 2.0 # # Note: on buildbot VMs (where there is no environment cleanup), the # kubernetes test server may be kept running if the script aborts or # is aborted (buildbot master failure!) for some reason. As such we # execute it under "timeout" control, which ensure it always is # terminated. It's not a 100% great method, but hopefully does the # trick. -- rgerhards, 2018-07-21 # # Verify basic mmkubernetes metadata enrichment for imfile records, including # normal namespace/pod lookups and expected not-found/busy/error responses. The # oracle compares enriched JSON output and module statistics against fixed # expectations. #export RSYSLOG_DEBUG="debug" USE_VALGRIND=false . ${srcdir:=.}/diag.sh init check_command_available timeout pwd=$( pwd ) k8s_srv_port_file="${RSYSLOG_DYNNAME}mmk8s-test-server.port" generate_conf testsrv=mmk8s-test-server echo starting kubernetes \"emulator\" timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py 0 ${RSYSLOG_DYNNAME}${testsrv}.pid ${RSYSLOG_DYNNAME}${testsrv}.started ${k8s_srv_port_file} > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_file_exists "$k8s_srv_port_file" k8s_srv_port="$(cat "$k8s_srv_port_file")" wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started echo background mmkubernetes_test_server.py process id is $BGPROCESS add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") module(load="../plugins/impstats/.libs/impstats" interval="1" log.file="'"$RSYSLOG_DYNNAME.spool"'/mmkubernetes-stats.log" log.syslog="off" format="cee") module(load="../plugins/imfile/.libs/imfile") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../contrib/mmkubernetes/.libs/mmkubernetes") template(name="mmk8s_template" type="list") { property(name="$!all-json-plain") constant(value="\n") } input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on") action(type="mmjsonparse" cookie="") action(type="mmkubernetes" busyretryinterval="1" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'" filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:.%.%container_hash:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log", "rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"] ) action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="mmk8s_template") ' cat > ${RSYSLOG_DYNNAME}.spool/pod-error1.log < ${RSYSLOG_DYNNAME}.spool/pod-error2.log < ${RSYSLOG_DYNNAME}.spool/pod-name1_namespace-name1_container-name1-id1.log < ${RSYSLOG_DYNNAME}.spool/pod-name2.container-hash2_namespace-name2_container-name2-id2.log < ${RSYSLOG_DYNNAME}.spool/pod-name3.log < ${RSYSLOG_DYNNAME}.spool/pod-name4.log < ${RSYSLOG_DYNNAME}.spool/pod-name5.log < ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-not-found-and-busy.log <> ${RSYSLOG_DYNNAME}.spool/pod-test-error.log <= 0: hsh = json.loads(line[jstart:]) if hsh["origin"] == "mmkubernetes": actual = hsh assert(expected == actual) ' $k8s_srv_port || { rc=$?; echo error: expected stats not found in ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log; } else echo error: stats file ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log not found rc=1 fi if [ ${rc:-0} -ne 0 ]; then echo echo "FAIL: expected data not found. $RSYSLOG_OUT_LOG is:" cat ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log cat $RSYSLOG_OUT_LOG cat ${RSYSLOG_DYNNAME}.spool/mmkubernetes-stats.log error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbeats-seq-cumulative-two-windows.sh0000644000000000000000000000013215241075234023125 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.769581365 30 ctime=1787067806.446949633 rsyslog-8.2608.0/tests/imbeats-seq-cumulative-two-windows.sh0000775000175000017500000000264715241075234022605 0ustar00rgerrger#!/bin/bash # Verify cumulative sequence tracking and ACKs across two Lumberjack windows # on one connection. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%|%$!metadata!imbeats!sequence%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" python3 - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys port = int(sys.argv[1]) def frame(seq, message): payload = json.dumps({"message": message}, separators=(",", ":")).encode() return b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(5) sock.sendall(b"2W" + struct.pack(">I", 1) + frame(1, "first")) print(sock.recv(6).hex()) sock.sendall(b"2W" + struct.pack(">I", 1) + frame(2, "second")) print(sock.recv(6).hex()) PY shutdown_when_empty wait_shutdown # shellcheck disable=SC2034 EXPECTED='{"message":"first"}|1 {"message":"second"}|2' cmp_exact EXPECTED_ACK='324100000001 324100000002' test "$(cat "$RSYSLOG_DYNNAME.imbeats.ack")" = "$EXPECTED_ACK" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-statements-foreach.sh0000644000000000000000000000013215171370365021001 xustar0030 mtime=1776677109.474913588 30 atime=1782715518.896790676 30 ctime=1787067805.441930905 rsyslog-8.2608.0/tests/yaml-statements-foreach.sh0000775000175000017500000000246415171370365020456 0ustar00rgerrger#!/bin/bash # Tests the YAML-native statements: foreach: construct. # Sends a message containing a JSON array, parses it with mmjsonparse, then # uses foreach: to iterate and write each element to the output log. # Mirrors the basic part of json_array_looping.sh using YAML config. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imptcp require_plugin mmjsonparse generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imptcp/.libs/imptcp" - load: "../plugins/mmjsonparse/.libs/mmjsonparse" templates: - name: quux type: string string: "quux: %$.quux%\n" rulesets: - name: freach statements: - type: mmjsonparse - foreach: var: "$.quux" in: "$!foo" do: - type: omfile file: "${RSYSLOG_OUT_LOG}" template: quux YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imptcp" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="freach") ' startup tcpflood -m 1 -I $srcdir/testsuites/json_array_input shutdown_when_empty wait_shutdown content_check 'quux: abc0' content_check 'quux: def1' content_check 'quux: ghi2' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp_addtlframedelim_on_input.sh0000644000000000000000000000013115241075234022464 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 29 ctime=1787067805.54093275 rsyslog-8.2608.0/tests/imtcp_addtlframedelim_on_input.sh0000775000175000017500000000113715241075234022136 0ustar00rgerrger#!/bin/bash # added 2010-08-11 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=20000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" addtlframedelimiter="0") template(name="outfmt" type="string" string="%msg:F,58:2%\n") local0.* ./'$RSYSLOG_OUT_LOG';outfmt ' startup tcpflood -m$NUMMESSAGES -F0 -P129 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_exists-not4.sh0000644000000000000000000000013215131231047020201 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.896790676 30 ctime=1787067804.905920917 rsyslog-8.2608.0/tests/rscript_exists-not4.sh0000777000175000017500000000103515131231047017651 0ustar00rgerrger#!/bin/bash # add 2020-10-02 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%!result%\n") set $.somevar = "test"; # this makes matters a bit more complicated if $msg contains "msgnum" then { if not exists($.p1!p2!val) then set $!result = "off"; else set $!result = "on"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='off' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-execOnlyWhenPreviousSuspended.sh0000644000000000000000000000013215132733117022665 xustar0030 mtime=1768666703.955620965 30 atime=1782715518.895790659 30 ctime=1787067803.923902618 rsyslog-8.2608.0/tests/es-execOnlyWhenPreviousSuspended.sh0000777000175000017500000000275515132733117022347 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 #10000 require_elasticsearch_restart_capability ensure_elasticsearch_ready init_elasticsearch generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") template(name="tpl2" type="string" string="%msg:F,58:2%\n") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") if $msg contains "msgnum:" then { action(type="omelasticsearch" server="127.0.0.1" serverport="19200" template="tpl" searchIndex="rsyslog_testbench" action.resumeInterval="2" action.resumeretrycount="1") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="tpl2" action.execOnlyWhenPreviousIsSuspended="on") # this action just to count processed messages action(type="omfile" file="'$RSYSLOG_DYNNAME'.syncfile") } ' startup injectmsg 0 $NUMMESSAGES wait_file_lines $RSYSLOG_DYNNAME.syncfile $NUMMESSAGES stop_elasticsearch ./msleep 1000 injectmsg $NUMMESSAGES 1 wait_file_lines $RSYSLOG_DYNNAME.syncfile $((NUMMESSAGES + 1)) wait_queueempty injectmsg $(( NUMMESSAGES + 1 )) $NUMMESSAGES wait_file_lines $RSYSLOG_DYNNAME.syncfile $((NUMMESSAGES + 1 + NUMMESSAGES)) start_elasticsearch shutdown_when_empty wait_shutdown seq_check $(( NUMMESSAGES + 1 )) $(( NUMMESSAGES * 2 )) es_getdata $NUMMESSAGES 19200 seq_check 0 $(( NUMMESSAGES - 1 )) exit_test rsyslog-8.2608.0/tests/PaxHeaders/gnutls_sni_server.c0000644000000000000000000000013215216464436017633 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.895790659 30 ctime=1787067803.564895928 rsyslog-8.2608.0/tests/gnutls_sni_server.c0000664000175000017500000001615215216464436017304 0ustar00rgerrger/* Very simple program to listen for a TLS connection and write the SNI received during the handshake. * Used for the rsyslog testbench. * Adapted from https://www.gnutls.org/manual/html_node/Echo-server-with-X_002e509-authentication.html * and https://wiki.openssl.org/index.php/Simple_TLS_Server * Author: John Cantu */ #include #include #include #include #include #include #include #include #include #include #include #include #define KEYFILE "tls-certs/key.pem" #define CERTFILE "tls-certs/cert.pem" #define MAX_FQDN_LENGTH 255 /* Defined in RFC 1035 (DNS) */ #define TRY(x) \ if (x == -1) { \ perror("Error in " #x); \ } /* these macros are GnuTLS specific */ #define GTLS_CHECK(x) \ do { \ int GTLS_RETVAL = x; \ if (GTLS_RETVAL != GNUTLS_E_SUCCESS) { \ fprintf(stderr, "error: " #x "returned %d", GTLS_RETVAL); \ } \ } while (0); #define LOOP_CHECK(rval, cmd) \ do { \ rval = cmd; \ fprintf(stderr, "LOOP_CHECK: " #cmd " returned %d\n", rval); \ } while (rval == GNUTLS_E_AGAIN || rval == GNUTLS_E_INTERRUPTED) static void write_listen_port_file(const int sock, const char *const port_file) { if (port_file == NULL) { return; } struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); char port[NI_MAXSERV]; FILE *fp; if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0) { perror("GTLS-SNI: getsockname failed"); exit(EXIT_FAILURE); } if (getnameinfo((struct sockaddr *)&addr, addrlen, NULL, 0, port, sizeof(port), NI_NUMERICSERV) != 0) { perror("GTLS-SNI: getnameinfo failed"); exit(EXIT_FAILURE); } fp = fopen(port_file, "w"); if (fp == NULL) { perror("GTLS-SNI: Unable to open port file"); exit(EXIT_FAILURE); } fprintf(fp, "%s\n", port); fclose(fp); } int create_socket(const char *port, const char *port_file) { struct addrinfo hints; struct addrinfo *res = NULL; struct addrinfo *rp; int s = -1; int optval = 1; int v6only = 0; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(NULL, port, &hints, &res) != 0) { perror("GTLS-SNI: getaddrinfo failed"); exit(EXIT_FAILURE); } for (rp = res; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s < 0) { continue; } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); if (rp->ai_family == AF_INET6) { setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)); } if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) { if (listen(s, 1) == 0) { write_listen_port_file(s, port_file); break; } } close(s); s = -1; } freeaddrinfo(res); if (s < 0) { perror("GTLS-SNI: Unable to bind or listen"); exit(EXIT_FAILURE); } return s; } void init_gnutls(gnutls_certificate_credentials_t *x509_cred, gnutls_priority_t *priority_cache, gnutls_session_t *session, char *cert_file_path, char *key_file_path) { /* for backwards compatibility with gnutls < 3.3.0 */ GTLS_CHECK(gnutls_global_init()); GTLS_CHECK(gnutls_certificate_allocate_credentials(x509_cred)); GTLS_CHECK(gnutls_certificate_set_x509_key_file(*x509_cred, cert_file_path, key_file_path, GNUTLS_X509_FMT_PEM)); GTLS_CHECK(gnutls_priority_init(priority_cache, NULL, NULL)); } int main(int argc, char **argv) { int listen_sd, ret; gnutls_certificate_credentials_t x509_cred; gnutls_priority_t priority_cache; gnutls_session_t session; setbuf(stdout, NULL); if (argc < 4) { printf("Usage: gnutls_sni_server PORT CERT_FILE_PATH KEY_FILE_PATH [PORT_FILE]\n"); exit(EXIT_SUCCESS); } init_gnutls(&x509_cred, &priority_cache, &session, argv[2], argv[3]); /* Socket operations */ listen_sd = create_socket(argv[1], argc > 4 ? argv[4] : NULL); fprintf(stderr, "GTLS-SNI: Server ready, listening on port %s\n", argv[1]); GTLS_CHECK(gnutls_init(&session, GNUTLS_SERVER)); GTLS_CHECK(gnutls_priority_set(session, priority_cache)); GTLS_CHECK(gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred)); gnutls_certificate_server_set_request(session, GNUTLS_CERT_IGNORE); #if GNUTLS_VERSION_NUMBER >= 0x030506 /* only available since GnuTLS 3.5.6, on previous versions see * gnutls_certificate_set_dh_params(). */ gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_MEDIUM); #endif /* Handle a single connection */ struct sockaddr_in addr; uint len = sizeof(addr); char sni[MAX_FQDN_LENGTH]; size_t sni_size = sizeof(sni); uint sni_type = GNUTLS_NAME_DNS; int client = accept(listen_sd, (struct sockaddr *)&addr, &len); fprintf(stderr, "GTLS-SNI: Accept() completed\n"); if (client < 0) { perror("GTLS-SNI: Unable to accept"); exit(EXIT_FAILURE); } fprintf(stderr, "GTLS-SNI: Accepted connection\n"); gnutls_transport_set_int(session, client); LOOP_CHECK(ret, gnutls_handshake(session)); if (ret < 0) { close(client); gnutls_deinit(session); fprintf(stderr, "GTLS-SNI: Handshake failed (%s)\n", gnutls_strerror(ret)); exit(EXIT_FAILURE); } fprintf(stderr, "GTLS-SNI: Handshake completed\n"); int name_retval = gnutls_server_name_get(session, sni, &sni_size, &sni_type, 0); if (name_retval == GNUTLS_E_SUCCESS) { fprintf(stderr, "GTLS-SNI: Received SNI: %s\n", sni); printf("SNI: %s\n", sni); } else if (name_retval == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { fprintf(stderr, "GTLS-SNI: Received SNI: (NULL)\n"); /* Use this to indicate null SNI */ printf("SNI: (NULL)\n"); } else { close(client); gnutls_deinit(session); fprintf(stderr, "GTLS-SNI: server_name_get failed with code: %d\n", name_retval); exit(EXIT_FAILURE); } fprintf(stderr, "GTLS-SNI: Starting teardown\n"); LOOP_CHECK(ret, gnutls_bye(session, GNUTLS_SHUT_WR)); fprintf(stderr, "GTLS-SNI: Closed connection\n"); TRY(close(client)); gnutls_deinit(session); TRY(close(listen_sd)); gnutls_certificate_free_credentials(x509_cred); gnutls_priority_deinit(priority_cache); gnutls_global_deinit(); return EXIT_SUCCESS; } rsyslog-8.2608.0/tests/PaxHeaders/imtcp_conndrop_tls.sh0000644000000000000000000000013215241075234020140 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.287965304 rsyslog-8.2608.0/tests/imtcp_conndrop_tls.sh0000775000175000017500000000252515241075234017613 0ustar00rgerrger#!/bin/bash # Test imtcp/TLS with many dropping connections # added 2011-06-09 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=${NUMMESSAGES:-50000} export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( maxMessageSize="10k" defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem" defaultNetstreamDriver="gtls" debug.whitelist="on" debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100" streamDriver.mode="1" streamDriver.authMode="anon") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # 100 byte messages to gain more practical data use tcpflood -c20 -p$TCPFLOOD_PORT -m$NUMMESSAGES -r -d100 -P129 -D -l0.995 -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown export SEQ_CHECK_OPTIONS=-E seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-oversizeMode-accept.sh0000644000000000000000000000013115035412264021434 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.894790642 30 ctime=1787067807.696972926 rsyslog-8.2608.0/tests/imrelp-oversizeMode-accept.sh0000777000175000017500000000245115035412264021110 0ustar00rgerrger#!/bin/bash # add 2018-04-25 by PascalWithopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./have_relpSrvSetOversizeMode if [ $? -eq 1 ]; then echo "imrelp parameter oversizeMode not available. Test stopped" exit 77 fi; generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="200" oversizeMode="accept") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end # because otherwise we won't know if it was truncated at the right length. grep "^ msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zlib-tls-ossl.sh0000644000000000000000000000013015241075234022655 xustar0029 mtime=1787067036.62457865 29 atime=1787067036.77358144 30 ctime=1787067805.609934036 rsyslog-8.2608.0/tests/imtcp-stream-always-zlib-tls-ossl.sh0000775000175000017500000000327315241075234022333 0ustar00rgerrger#!/bin/bash # added 2026-05-17 by Codex, released under ASL 2.0 # Verifies zlib stream:always decompression over an ossl imtcp listener fed by # omfwd; the oracle is the complete ordered message sequence after TLS transit. . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" compression.mode="stream:always" compression.driver="zlib") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" generate_conf 2 add_conf ' global(defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" compression.mode="stream:always" compression.driver="zlib" compression.stream.flushOnTXEnd="on" ) ' 2 startup 2 tcpflood -m$NUMMESSAGES -i1 wait_file_lines shutdown_when_empty 2 wait_shutdown 2 shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-maxdiskspace.sh0000644000000000000000000000013215241075234021247 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.861901463 rsyslog-8.2608.0/tests/segmented-da-maxdiskspace.sh0000775000175000017500000000400515241075234020715 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Fill a 64 KiB segmented DA child while a slow consumer keeps the 50-record # memory tier above its high watermark, drain it, and repeat. Exact delivery # proves producer backpressure without loss and reuse after segment reclamation; # impstats permits only the current-record/topology overshoot used by the pure # segmented store test. . ${srcdir:=.}/diag.sh init require_plugin impstats export NUMMESSAGES=2000 DA_QUEUE_TYPE=${DA_QUEUE_TYPE:-LinkedList} STATS_FILE="$PWD/${RSYSLOG_DYNNAME}.stats.log" generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") module(load="../plugins/impstats/.libs/impstats" log.file="'"$STATS_FILE"'" interval="1") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="'"$DA_QUEUE_TYPE"'" queue.filename="mainq" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.maxDiskSpace="64k" queue.maxFileSize="8k" queue.timeoutEnqueue="300000" queue.dequeueBatchSize="16" queue.diskQueueType="auto" queue.diskQueueIdleTimeout="-1") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" :omtesting:sleep 0 1000 if ($msg contains "msgnum:") then action(type="omfile" file="'"$RSYSLOG_OUT_LOG"'" template="outfmt") ' startup tcpflood -p"$TCPFLOOD_PORT" -m1000 -i0 wait_file_lines "$RSYSLOG_OUT_LOG" 1000 tcpflood -p"$TCPFLOOD_PORT" -m1000 -i1000 wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" shutdown_when_empty wait_shutdown seq_check max_usage=$(grep 'disk.usage=' "$STATS_FILE" | sed -E 's/.*disk\.usage=([0-9]+).*/\1/' | sort -n | tail -n 1) if [ "${max_usage:-0}" -gt 66560 ]; then printf 'FAIL: segmented DA sampled usage %s exceeds the 64 KiB limit plus one record\n' "$max_usage" cat "$STATS_FILE" error_exit 1 fi rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-sizelimitcmd-many.sh0000644000000000000000000000013215145046113021145 xustar0030 mtime=1771326539.049014452 30 atime=1782715518.894790642 30 ctime=1787067806.852957199 rsyslog-8.2608.0/tests/omfile-sizelimitcmd-many.sh0000775000175000017500000000336415145046113020622 0ustar00rgerrger#!/bin/bash # addd 2023-01-11 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 echo "echo \"\$1 \$2\" > $RSYSLOG_DYNNAME.rotate.args ls -l $RSYSLOG_DYNNAME.channel.* mv -f $RSYSLOG_DYNNAME.channel.log.prev.9 $RSYSLOG_DYNNAME.channel.log.prev.10 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.8 $RSYSLOG_DYNNAME.channel.log.prev.9 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.7 $RSYSLOG_DYNNAME.channel.log.prev.8 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.6 $RSYSLOG_DYNNAME.channel.log.prev.7 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.5 $RSYSLOG_DYNNAME.channel.log.prev.6 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.4 $RSYSLOG_DYNNAME.channel.log.prev.5 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.3 $RSYSLOG_DYNNAME.channel.log.prev.4 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.2 $RSYSLOG_DYNNAME.channel.log.prev.3 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev.1 $RSYSLOG_DYNNAME.channel.log.prev.2 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log.prev $RSYSLOG_DYNNAME.channel.log.prev.1 2>/dev/null mv -f $RSYSLOG_DYNNAME.channel.log $RSYSLOG_DYNNAME.channel.log.prev " > $RSYSLOG_DYNNAME.rotate.sh chmod +x $RSYSLOG_DYNNAME.rotate.sh generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { action(type="omfile" file="'$RSYSLOG_DYNNAME.channel.log'" template="outfmt" rotation.sizeLimit="50k" rotation.sizeLimitCommand="./'$RSYSLOG_DYNNAME.rotate.sh' arg1") } ' startup injectmsg shutdown_when_empty wait_shutdown ls -l $RSYSLOG_DYNNAME.channel.* cat $RSYSLOG_DYNNAME.channel.* > $RSYSLOG_OUT_LOG content_check "arg1 ./$RSYSLOG_DYNNAME.channel.log" $RSYSLOG_DYNNAME.rotate.args seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-close-unresponsive-vg.sh0000644000000000000000000000013215035412264022015 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.894790642 30 ctime=1787067806.100943185 rsyslog-8.2608.0/tests/omprog-close-unresponsive-vg.sh0000777000175000017500000000213415035412264021466 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Same test than 'omprog-close-unresponsive.sh', but checking for memory # problems using valgrind. Note it is not necessary to repeat the # rest of checks (this simplifies the maintenance of the tests). . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") main_queue( queue.timeoutShutdown="60000" # give time to omprog to wait for the child ) :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-close-unresponsive-bin.sh` template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process confirmMessages="on" # facilitates sync with the child process signalOnClose="on" closeTimeout="1000" # ms #killUnresponsive="on" # default value: the value of signalOnClose ) } ' startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg exit_test rsyslog-8.2608.0/tests/PaxHeaders/have_relpSrvSetTlsConfigCmd.c0000644000000000000000000000013215132411300021404 xustar0030 mtime=1768559296.283885909 30 atime=1782715518.894790642 30 ctime=1787067803.572896077 rsyslog-8.2608.0/tests/have_relpSrvSetTlsConfigCmd.c0000666000175000017500000000027415132411300021055 0ustar00rgerrger#include "config.h" int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) { #if defined(HAVE_RELPENGINESETTLSCFGCMD) return 0; #else return 1; #endif } rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_str-numstr.sh0000644000000000000000000000013215171370365021657 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.893790625 30 ctime=1787067804.838919669 rsyslog-8.2608.0/tests/rscript_compare_str-numstr.sh0000775000175000017500000000014415171370365021325 0ustar00rgerrger#!/bin/bash export LOWER_VAL='"-"' export HIGHER_VAL='"2"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/rs-int2hex.sh0000644000000000000000000000013215241075234016243 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.930921383 rsyslog-8.2608.0/tests/rs-int2hex.sh0000775000175000017500000000145215241075234015714 0ustar00rgerrger#!/bin/bash # add 2018-04-04 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!var = int2hex(61); set $!var2 = int2hex(-13); template(name="outfmt" type="string" string="-%$!var%- -%$!var2%-\n") :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" shutdown_when_empty wait_shutdown echo '-3d- -fffffffffffffff3-' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-v1-state.sh0000644000000000000000000000013215241075234021652 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.739899189 rsyslog-8.2608.0/tests/segmented-diskqueue-v1-state.sh0000775000175000017500000000026215241075234021321 0ustar00rgerrger#!/bin/bash # Experimental v1-state wrapper for explicit incompatibility coverage. export STATE_MUTATION=v1 . ${srcdir:=.}/testsuites/segmented-diskqueue-invalid-state-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/rawmsg-after-pri.sh0000644000000000000000000000013215241075234017427 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.324910091 rsyslog-8.2608.0/tests/rawmsg-after-pri.sh0000775000175000017500000000176415241075234017106 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(type="string" name="outfmt" string="%rawmsg-after-pri%\n") if $syslogfacility-text == "local0" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -P 129 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate NUMLINES=$(grep -c "^Mar 1 01:00:00 172.20.245.8 tag msgnum:00000000:$" $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: output file seems not to exist" ls -l $RSYSLOG_OUT_LOG cat $RSYSLOG_OUT_LOG error_exit 1 else if [ ! $NUMLINES -eq 1 ]; then echo "ERROR: output format does not match expectation" cat $RSYSLOG_OUT_LOG error_exit 1 fi fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_hash32.sh0000644000000000000000000000013215241075234017076 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.845957068 rsyslog-8.2608.0/tests/rscript_hash32.sh0000775000175000017500000000176415241075234016555 0ustar00rgerrger#!/bin/bash # added 2018-02-07 by Harshvardhan Shrivastava # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \rscript_hash32.sh\]: test for hash32 and hash64mod script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n") module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmhash/.libs/fmhash") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.hash_no_1 = hash32("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e"); set $.hash_no_2 = hash32mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m 20 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown . $srcdir/diag.sh content-pattern-check "^\(746581550 - 50\|3889673532 - 32\)$" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-event-properties.sh0000644000000000000000000000013215241075234022106 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 30 ctime=1787067803.811900531 rsyslog-8.2608.0/tests/segmented-da-event-properties.sh0000775000175000017500000000040415241075234021553 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Run the complete-event persistence oracle through a segmented DA child. export SEGDISK_EVENT_DA=1 . ${srcdir:=.}/segmented-diskqueue-event-properties.sh rsyslog-8.2608.0/tests/PaxHeaders/yaml-statements-unset.sh0000644000000000000000000000013115241075234020522 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 29 ctime=1787067805.40893029 rsyslog-8.2608.0/tests/yaml-statements-unset.sh0000775000175000017500000000477115241075234020203 0ustar00rgerrger#!/bin/bash # Tests the YAML-native statements: unset: and call_indirect: constructs. # rs1 sets a variable to a ruleset name, then uses call_indirect to dispatch # to that ruleset. The target ruleset (rs2) uses unset: to clear a variable # and then writes matching messages to the output. # # Verification: after unset:, %.scratch% is written to a separate file via # the verifyfmt template. The test fails if the pre-unset marker value # appears there, proving that unset: actually cleared the variable. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=200 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" - name: verifyfmt type: string string: "%.scratch%\n" rulesets: - name: rs2 statements: - unset: "$.scratch" - type: omfile template: verifyfmt file: "${RSYSLOG_DYNNAME}.scratch" - if: '$msg contains "msgnum:"' action: type: omfile template: outfmt file: "${RSYSLOG_OUT_LOG}" - stop: true - name: rs1 statements: - set: var: "$.scratch" expr: '"will be unset"' - set: var: "$.target" expr: '"rs2"' - call_indirect: "$.target" YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" sed -i "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="rs1") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check # Verify $.scratch was actually cleared by unset: — the pre-unset marker # must not appear in the verify file (each line should be empty after unset). # Explicitly fail when the file is absent so a missing write cannot produce # a false pass (grep exits 2 on read error, which would look like "no match"). if [ ! -f "${RSYSLOG_DYNNAME}.scratch" ]; then echo "FAIL: verify file '${RSYSLOG_DYNNAME}.scratch' was not created (unset write never ran)" exit 1 fi if grep -q "will be unset" "${RSYSLOG_DYNNAME}.scratch"; then echo "FAIL: unset: did not clear \$.scratch (marker 'will be unset' still present)" head -3 "${RSYSLOG_DYNNAME}.scratch" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/json-omitifzero-subtree.sh0000644000000000000000000000013215145046113021042 xustar0030 mtime=1771326539.043014354 30 atime=1782715518.901790761 30 ctime=1787067803.695898369 rsyslog-8.2608.0/tests/json-omitifzero-subtree.sh0000775000175000017500000000143515145046113020514 0ustar00rgerrger#!/bin/bash # added 2026-01-25 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list" option.jsonftree="on") { property(name="$!zero" outname="zero_omit" format="jsonf" dataType="number" omitIfZero="on") property(name="$!nonzero" outname="nonzero_omit" format="jsonf" dataType="number" omitIfZero="on") property(name="$!spacedzero" outname="spacedzero_omit" format="jsonf" dataType="number" omitIfZero="on") } set $!zero = 0; set $!nonzero = 42; set $!spacedzero = " 0 "; local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' rm -f "$RSYSLOG_OUT_LOG" startup injectmsg shutdown_when_empty wait_shutdown export EXPECTED='{"nonzero_omit":42}' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/parser-drop-trailing-cr.sh0000644000000000000000000000013215241075234020707 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 30 ctime=1787067805.516932303 rsyslog-8.2608.0/tests/parser-drop-trailing-cr.sh0000775000175000017500000000177515241075234020370 0ustar00rgerrger#!/bin/bash # Verify that parser.dropTrailingCROnReception removes an explicit carriage # return left in the message payload after the normal LF framing byte is # stripped. The oracle is the final omfile output after synchronized shutdown; # without the option, the CR would be escaped as #015 in %msg%. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(parser.dropTrailingCROnReception="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="rs") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port cr_msg=$(printf '"<167>Mar 6 16:57:54 172.20.245.8 test: payload\r"') tcpflood -m1 -M "$cr_msg" shutdown_when_empty wait_shutdown export EXPECTED=' payload' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv.sh0000644000000000000000000000013015241075234015535 xustar0030 mtime=1787067036.643579006 29 atime=1787067036.79658187 29 ctime=1787067804.47191283 rsyslog-8.2608.0/tests/sndrcv.sh0000775000175000017500000000275515241075234015217 0ustar00rgerrger#!/bin/bash # This tests two rsyslog instances. Instance # TWO sends data to instance ONE. A number of messages is injected into # the instance 2 and we finally check if all those messages # arrived at instance 1. # added 2009-11-11 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # start up the instances export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RCVR_PORT=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' action(type="omfwd" target="127.0.0.1" protocol="tcp" port="'$RCVR_PORT'") ' 2 startup 2 assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # do the final check seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskq-rfc5424.sh0000644000000000000000000000013115241075234016441 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.431912085 rsyslog-8.2608.0/tests/diskq-rfc5424.sh0000775000175000017500000000234715241075234016117 0ustar00rgerrger#!/bin/bash # detect queue corruption based on invalid property bag ordering. # Note: this mimics an issue actually seen in practice. # Triggering condition: "json" property (message variables) are present # and "structured-data" property is also present. Caused rsyslog to # thrash the queue file, getting messages stuck in it and loosing all # after the initial problem occurrence. # add 2017-02-08 by Rainer Gerhards, released under ASL 2.0 uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 QUEUE_TYPE=${QUEUE_TYPE:-disk} generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs") template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="rs2" queue.type="'$QUEUE_TYPE'" queue.filename="rs2_q" queue.spoolDirectory="'${RSYSLOG_DYNNAME}'.spool") { set $!tmp=$msg; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ruleset(name="rs") { set $!tmp=$msg; call rs2 } ' startup tcpflood -m$NUMMESSAGES -y shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/udp-msgreduc-vg.sh0000644000000000000000000000013215035412264017250 xustar0030 mtime=1752569012.420611777 30 atime=1782715518.901790761 30 ctime=1787067805.217926731 rsyslog-8.2608.0/tests/udp-msgreduc-vg.sh0000777000175000017500000000222115035412264016716 0ustar00rgerrger#!/bin/bash # check if valgrind violations occur. Correct output is not checked. # added 2011-03-01 by Rgerhards # This file is part of the rsyslog project, released under GPLv3 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi echo =============================================================================== echo \[udp-msgreduc-vg.sh\]: testing imtcp multiple listeners . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imudp/.libs/imudp $UDPServerRun '$TCPFLOOD_PORT' $RepeatedMsgReduction on $template outfmt,"%msg:F,58:2%\n" *.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") #:msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg tcpflood -t 127.0.0.1 -m 4 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...\"" tcpflood -t 127.0.0.1 -m 1 -r -Tudp -M "\"<133>2011-03-01T11:22:12Z host tag msgh ...x\"" shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown_vg if [ "$RSYSLOGD_EXIT" -eq "10" ] then echo "udp-msgreduc-vg.sh FAILED" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdtls-basic-vg.sh0000644000000000000000000000013215171370365017232 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.901790761 30 ctime=1787067807.783974547 rsyslog-8.2608.0/tests/imdtls-basic-vg.sh0000775000175000017500000000052415171370365016702 0ustar00rgerrger#!/bin/bash if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi export USE_VALGRIND="YES" export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes" . ${srcdir:-.}/imdtls-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-redis-start-after-vg.sh0000644000000000000000000000013215171370365022172 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.901790761 30 ctime=1787067806.574952018 rsyslog-8.2608.0/tests/imhiredis-redis-start-after-vg.sh0000775000175000017500000000030715171370365021641 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-redis-start-after.sh rsyslog-8.2608.0/tests/PaxHeaders/imptcp-discard-truncated-msg.sh0000644000000000000000000000013115035412264021714 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.900790744 30 ctime=1787067806.794956118 rsyslog-8.2608.0/tests/imptcp-discard-truncated-msg.sh0000777000175000017500000000321015035412264021362 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MaxMessageSize 128 global(processInternalMessages="on") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1" discardTruncatedMsg="on") template(name="outfmt" type="string" string="%rawmsg%\n") ruleset(name="ruleset1") { action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16\"" tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message\"" tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test14 test15 test16\"" tcpflood -m1 -M "\"<120> 2011-03-01T11:22:12Z host tag: this is a way to long message\"" shutdown_when_empty wait_shutdown export EXPECTED='<120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 t <120> 2011-03-01T11:22:12Z host tag: this is a way to long message <120> 2011-03-01T11:22:12Z host tag: this is a way to long message that has abcdefghijklmnopqrstuvwxyz test1 test2 test3 test4 t <120> 2011-03-01T11:22:12Z host tag: this is a way to long message' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_sparse_array_ipv4.sh0000644000000000000000000000012715145046113021267 xustar0029 mtime=1771326539.04401437 30 atime=1782715518.900790744 28 ctime=1787067805.0069228 rsyslog-8.2608.0/tests/lookup_sparse_array_ipv4.sh0000775000175000017500000000331415145046113020733 0ustar00rgerrger#!/bin/bash # Verification test for issue #4906: sparseArray lookup with ipv42num # This checks if the proposed documentation example strategy actually works. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="ip_lookup" file="'$RSYSLOG_DYNNAME'.lookup_sparse_array_ipv4.lkp_tbl") template(name="outfmt" type="string" string="%msg%: %$.lkp%\n") # Assuming msg contains the IP address set $.ip_num = ipv42num($msg); set $.lkp = lookup("ip_lookup", $.ip_num); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/lookup_sparse_array_ipv4.lkp_tbl $RSYSLOG_DYNNAME.lookup_sparse_array_ipv4.lkp_tbl startup inject_ip() { injectmsg_literal "<13>1 2025-01-01T00:00:00Z localhost mytag - - - $1" } # 10.0.0.0 -> NetA inject_ip "10.0.0.0" # 10.0.0.5 -> NetA (inside range) inject_ip "10.0.0.5" # 10.0.0.255 -> NetA (end of range) inject_ip "10.0.0.255" # 10.0.1.0 -> Gap (explicitly defined) inject_ip "10.0.1.0" # 10.0.1.5 -> Gap (inside gap) inject_ip "10.0.1.5" # 10.0.2.0 -> NetB inject_ip "10.0.2.0" # 10.0.2.100 -> NetB inject_ip "10.0.2.100" # 9.0.0.0 -> Should be nomatch (less than first entry) inject_ip "9.0.0.0" shutdown_when_empty wait_shutdown content_check "10.0.0.0: NetA" content_check "10.0.0.5: NetA" content_check "10.0.0.255: NetA" content_check "10.0.1.0: Gap" content_check "10.0.1.5: Gap" content_check "10.0.2.0: NetB" content_check "10.0.2.100: NetB" # For nomatch, lookup returns "nomatch" string if defined, or empty string? # The table file doesn't define "nomatch". Default is empty string? # Let's check documentation or code. # doc says: nomatch # So it should be empty. content_check "9.0.0.0: " exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-encryption-disk.sh0000644000000000000000000000013215035412264020503 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.899790727 30 ctime=1787067805.109924719 rsyslog-8.2608.0/tests/queue-encryption-disk.sh0000777000175000017500000000162415035412264020157 0ustar00rgerrger#!/bin/bash # addd 2018-09-28 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.filename="mainq" queue.type="disk" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutenqueue="300000" queue.lowwatermark="5000" queue.cry.provider="gcry" queue.cry.key="1234567890123456" queue.saveonshutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :omtesting:sleep 0 5000 :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 1000 shutdown_immediate wait_shutdown echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0* exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_is_in_subnet.sh0000644000000000000000000000013215216464436020477 xustar0030 mtime=1782212894.081267073 30 atime=1782715518.899790727 30 ctime=1787067804.878920414 rsyslog-8.2608.0/tests/rscript_is_in_subnet.sh0000775000175000017500000000360115216464436020146 0ustar00rgerrger#!/bin/bash # Test is_in_subnet() with IPv4, IPv6, invalid text, and binary strings. # The nul_* cases use b64_decode() to create length-counted strings with # embedded NUL bytes and valid textual prefixes. The oracle is rejection: the # function must not silently truncate at the C-string boundary and accept the # prefix as a complete IP or CIDR value. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # Basic IPv4 tests set $!res!v4_1 = is_in_subnet("192.168.1.5", "192.168.1.0/24"); set $!res!v4_2 = is_in_subnet("192.168.2.5", "192.168.1.0/24"); set $!res!v4_3 = is_in_subnet("192.168.1.1", "192.168.1.1/32"); set $!res!v4_4 = is_in_subnet("192.168.1.1", "0.0.0.0/0"); # Basic IPv6 tests set $!res!v6_1 = is_in_subnet("2001:db8::1", "2001:db8::/32"); set $!res!v6_2 = is_in_subnet("2001:db9::1", "2001:db8::/32"); set $!res!v6_3 = is_in_subnet("::1", "::1/128"); set $!res!v6_4 = is_in_subnet("::1", "::/0"); # Mixed / Invalid tests set $!res!inv_1 = is_in_subnet("192.168.1.1", "2001:db8::/32"); set $!res!inv_2 = is_in_subnet("invalid", "192.168.1.0/24"); set $!res!inv_3 = is_in_subnet("192.168.1.1", "invalid"); set $!res!inv_4 = is_in_subnet("192.168.1.1", "192.168.1.0/33"); # Invalid mask set $!res!nul_ip = is_in_subnet(b64_decode("MTkyLjE2OC4xLjUAZXZpbA=="), "192.168.1.0/24"); set $!res!nul_cidr = is_in_subnet("192.168.1.5", b64_decode("MTkyLjE2OC4xLjAvMjQAZXZpbA==")); template(name="outfmt" type="string" string="%!res%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown export EXPECTED='{ "v4_1": 1, "v4_2": 0, "v4_3": 1, "v4_4": 1, "v6_1": 1, "v6_2": 0, "v6_3": 1, "v6_4": 1, "inv_1": 0, "inv_2": 0, "inv_3": 0, "inv_4": 0, "nul_ip": 0, "nul_cidr": 0 }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/have_relpEngineSetTLSLibByName.c0000644000000000000000000000013215132411300021710 xustar0030 mtime=1768559296.283885909 30 atime=1782715518.899790727 30 ctime=1787067803.567895984 rsyslog-8.2608.0/tests/have_relpEngineSetTLSLibByName.c0000666000175000017500000000027715132411300021364 0ustar00rgerrger#include "config.h" int main(int argc __attribute__((unused)), char *argv[] __attribute__((unused))) { #if defined(HAVE_RELPENGINESETTLSLIBBYNAME) return 0; #else return 1; #endif } rsyslog-8.2608.0/tests/PaxHeaders/mmutf8fix_replacement_sequence_conflict.sh0000644000000000000000000000013215241075234024317 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.686579811 30 ctime=1787067805.678935322 rsyslog-8.2608.0/tests/mmutf8fix_replacement_sequence_conflict.sh0000775000175000017500000000213415241075234023766 0ustar00rgerrger#!/bin/bash # Validate mmutf8fix configuration rejects replacementChar and # replacementSequence on the same action. This is a startup validation test: # rsyslog must refuse the configuration before any normal message path exists. # The oracle is the startup diagnostic on stderr, captured in a test-instance # specific file so parallel negative config tests cannot overwrite it. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init if [ -z "$RSYSLOGD" ]; then export RSYSLOGD=../tools/rsyslogd fi STDOUT_LOG="${RSYSLOG_DYNNAME}.stdout.log" STDERR_LOG="${RSYSLOG_DYNNAME}.stderr.log" generate_conf add_conf ' module(load="../plugins/mmutf8fix/.libs/mmutf8fix") action(type="mmutf8fix" replacementChar="?" replacementSequence="[bad]") ' export CONF_FILE="${TESTCONF_NM}.conf" if $RSYSLOGD -N1 -M"$RSYSLOG_MODDIR" -f "$CONF_FILE" > "$STDOUT_LOG" 2> "$STDERR_LOG"; then echo "FAIL: invalid replacement configuration was accepted" error_exit 1 fi content_check "mmutf8fix: replacementChar and replacementSequence are mutually exclusive" "$STDERR_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-jsonarray.sh0000644000000000000000000000013215131231047020632 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.899790727 30 ctime=1787067806.132943782 rsyslog-8.2608.0/tests/omhttp-batch-jsonarray.sh0000777000175000017500000000155515131231047020311 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 omhttp_start_server 0 generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="2048") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.format="jsonarray" batch.maxsize="1000" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-encryption-disk_keyprog.sh0000644000000000000000000000013215035412264022243 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.899790727 30 ctime=1787067805.117924868 rsyslog-8.2608.0/tests/queue-encryption-disk_keyprog.sh0000777000175000017500000000207515035412264021720 0ustar00rgerrger#!/bin/bash # addd 2018-10-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.filename="mainq" queue.type="disk" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutenqueue="300000" queue.lowwatermark="5000" queue.cry.provider="gcry" queue.cry.keyprogram="./'$RSYSLOG_DYNNAME.keyprogram'" queue.saveonshutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :omtesting:sleep 0 5000 :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' echo '#!/bin/bash echo RSYSLOG-KEY-PROVIDER:0 echo 16 echo "1234567890123456"' >> $RSYSLOG_DYNNAME.keyprogram chmod +x $RSYSLOG_DYNNAME.keyprogram startup injectmsg 0 1000 shutdown_immediate wait_shutdown echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0* exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmrfc5424addhmac-long-sdid.sh0000644000000000000000000000013115241075234021042 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067807.037960646 rsyslog-8.2608.0/tests/mmrfc5424addhmac-long-sdid.sh0000775000175000017500000000165215241075234020516 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/mmrfc5424addhmac/.libs/mmrfc5424addhmac") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="rawfmt" type="string" string="%rawmsg%\n") action(type="mmrfc5424addhmac" key="secret" hashFunction="sha256" sd_id="hmac@32473") if $msg contains "LONGSDIDTEST" then action(type="omfile" template="rawfmt" file="'$RSYSLOG_OUT_LOG'") ' startup LONG_SDID=$(head -c 256 < /dev/zero | tr '\0' 'A') echo "<85>1 2026-05-08T00:00:00.000Z host app - - [${LONG_SDID} k=\"v\"] LONGSDIDTEST" > "$RSYSLOG_DYNNAME.input" tcpflood -B -I "$RSYSLOG_DYNNAME.input" rm -f "$RSYSLOG_DYNNAME.input" shutdown_when_empty wait_shutdown content_check "LONGSDIDTEST" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_intermediate_ca_chain.sh0000644000000000000000000000013215216464436024030 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.899790727 30 ctime=1787067807.469968696 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_intermediate_ca_chain.sh0000775000175000017500000001564715216464436023514 0ustar00rgerrger#!/bin/bash # Test for issue #5207: multiple intermediate CA certificates # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="log" # Prepare certificate workspace (dynamic, auto-cleaned by testbench) CERTDIR="$RSYSLOG_DYNNAME.certwork" mkdir -p "$CERTDIR" # Create minimal OpenSSL extfiles cat >"$CERTDIR/ca_ext.cnf" <<'EOF' [v3_ca] subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, cRLSign, keyCertSign EOF cat >"$CERTDIR/leaf_ext.cnf" <<'EOF' [server_cert] basicConstraints = CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth [client_cert] basicConstraints = CA:false keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth EOF # Generate root CA openssl genpkey -algorithm RSA -out "$CERTDIR/ca-root-key.pem" >/dev/null 2>&1 openssl req -new -key "$CERTDIR/ca-root-key.pem" -out "$CERTDIR/ca-root.csr" -subj "/C=US/ST=State/L=City/O=Org/OU=Unit/CN=Root-CA" >/dev/null 2>&1 openssl x509 -req -in "$CERTDIR/ca-root.csr" -signkey "$CERTDIR/ca-root-key.pem" -days 3650 \ -extfile "$CERTDIR/ca_ext.cnf" -extensions v3_ca -out "$CERTDIR/ca-root-cert.pem" >/dev/null 2>&1 # Create intermediate CA 1 openssl genpkey -algorithm RSA -out "$CERTDIR/intermediate-ca1-key.pem" >/dev/null 2>&1 openssl req -new -key "$CERTDIR/intermediate-ca1-key.pem" -out "$CERTDIR/intermediate-ca1.csr" -subj "/C=US/ST=State/L=City/O=Org/OU=Unit/CN=Intermediate-CA1" >/dev/null 2>&1 openssl x509 -req -in "$CERTDIR/intermediate-ca1.csr" -CA "$CERTDIR/ca-root-cert.pem" -CAkey "$CERTDIR/ca-root-key.pem" -CAcreateserial -days 1825 \ -extfile "$CERTDIR/ca_ext.cnf" -extensions v3_ca -out "$CERTDIR/intermediate-ca1-cert.pem" >/dev/null 2>&1 # Create intermediate CA 2 openssl genpkey -algorithm RSA -out "$CERTDIR/intermediate-ca2-key.pem" >/dev/null 2>&1 openssl req -new -key "$CERTDIR/intermediate-ca2-key.pem" -out "$CERTDIR/intermediate-ca2.csr" -subj "/C=US/ST=State/L=City/O=Org/OU=Unit/CN=Intermediate-CA2" >/dev/null 2>&1 openssl x509 -req -in "$CERTDIR/intermediate-ca2.csr" -CA "$CERTDIR/ca-root-cert.pem" -CAkey "$CERTDIR/ca-root-key.pem" -CAcreateserial -days 1825 \ -extfile "$CERTDIR/ca_ext.cnf" -extensions v3_ca -out "$CERTDIR/intermediate-ca2-cert.pem" >/dev/null 2>&1 # Create server certificate signed by intermediate CA 1 openssl genpkey -algorithm RSA -out "$CERTDIR/server-int1-key.pem" >/dev/null 2>&1 openssl req -new -key "$CERTDIR/server-int1-key.pem" -out "$CERTDIR/server-int1.csr" -subj "/C=US/ST=State/L=City/O=Org/OU=Unit/CN=rsyslogserver" >/dev/null 2>&1 openssl x509 -req -in "$CERTDIR/server-int1.csr" -CA "$CERTDIR/intermediate-ca1-cert.pem" -CAkey "$CERTDIR/intermediate-ca1-key.pem" -CAcreateserial -days 365 \ -extfile "$CERTDIR/leaf_ext.cnf" -extensions server_cert -out "$CERTDIR/server-int1-cert.pem" >/dev/null 2>&1 cat "$CERTDIR/server-int1-cert.pem" "$CERTDIR/intermediate-ca1-cert.pem" > "$CERTDIR/server-int1-chain.pem" # Create client certificate signed by intermediate CA 2 openssl genpkey -algorithm RSA -out "$CERTDIR/client-int2-key.pem" >/dev/null 2>&1 openssl req -new -key "$CERTDIR/client-int2-key.pem" -out "$CERTDIR/client-int2.csr" -subj "/C=US/ST=State/L=City/O=Org/OU=Unit/CN=rsyslogclient" >/dev/null 2>&1 openssl x509 -req -in "$CERTDIR/client-int2.csr" -CA "$CERTDIR/intermediate-ca2-cert.pem" -CAkey "$CERTDIR/intermediate-ca2-key.pem" -CAcreateserial -days 365 \ -extfile "$CERTDIR/leaf_ext.cnf" -extensions client_cert -out "$CERTDIR/client-int2-cert.pem" >/dev/null 2>&1 cat "$CERTDIR/client-int2-cert.pem" "$CERTDIR/intermediate-ca2-cert.pem" > "$CERTDIR/client-int2-chain.pem" # Debug: dump generated certificates and verify chains { echo "==== CERT DEBUG: Subjects/Issuers/Dates/Fingerprints ====" echo "-- Root CA --"; openssl x509 -in "$CERTDIR/ca-root-cert.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Intermediate CA 1 --"; openssl x509 -in "$CERTDIR/intermediate-ca1-cert.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Intermediate CA 2 --"; openssl x509 -in "$CERTDIR/intermediate-ca2-cert.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Server leaf --"; openssl x509 -in "$CERTDIR/server-int1-cert.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Server chain (top of file) --"; openssl x509 -in "$CERTDIR/server-int1-chain.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Client leaf --"; openssl x509 -in "$CERTDIR/client-int2-cert.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "-- Client chain (top of file) --"; openssl x509 -in "$CERTDIR/client-int2-chain.pem" -noout -subject -issuer -dates -serial -fingerprint -sha256; echo "==== OPENSSL VERIFY ====" echo "Verify server leaf against Root + Intermediate1"; openssl verify -CAfile "$CERTDIR/ca-root-cert.pem" -untrusted "$CERTDIR/intermediate-ca1-cert.pem" "$CERTDIR/server-int1-cert.pem"; echo "Verify client leaf against Root + Intermediate2"; openssl verify -CAfile "$CERTDIR/ca-root-cert.pem" -untrusted "$CERTDIR/intermediate-ca2-cert.pem" "$CERTDIR/client-int2-cert.pem"; } generate_conf export SERVER_CN="rsyslogserver" export CLIENT_CN="rsyslogclient" add_conf ' global( DefaultNetstreamDriver="ossl" DefaultNetstreamDriverCAFile="'$CERTDIR'/ca-root-cert.pem" DefaultNetstreamDriverCertFile="'$CERTDIR'/server-int1-chain.pem" DefaultNetstreamDriverKeyFile="'$CERTDIR'/server-int1-key.pem" NetstreamDriverCAExtraFiles="'$CERTDIR'/intermediate-ca1-cert.pem,'$CERTDIR'/intermediate-ca2-cert.pem" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" PermittedPeer="'$CLIENT_CN'" StreamDriver.AuthMode="x509/name" ) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$CERTDIR'/ca-root-cert.pem" defaultNetstreamDriverCertFile="'$CERTDIR'/client-int2-chain.pem" defaultNetstreamDriverKeyFile="'$CERTDIR'/client-int2-key.pem" ) $ModLoad ../plugins/imtcp/.libs/imtcp input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/name" StreamDriverPermittedPeers="'$SERVER_CN'" ) ' 2 startup 2 tcpflood -m$NUMMESSAGES -i1 wait_file_lines shutdown_when_empty 2 wait_shutdown 2 shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_key_truncated-vg.sh0000644000000000000000000000013215171370365023346 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.899790727 30 ctime=1787067806.916958391 rsyslog-8.2608.0/tests/rscript_unflatten_key_truncated-vg.sh0000775000175000017500000000013015171370365023007 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_key_truncated.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-basic-verifydepth.sh0000644000000000000000000000013215241075234023212 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.379967019 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-basic-verifydepth.sh0000775000175000017500000000176615241075234022673 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.TlsVerifyDepth="5" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # Begin actual testcase startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-retry-vg.sh0000644000000000000000000000013115171370365017334 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.900790744 30 ctime=1787067806.191944881 rsyslog-8.2608.0/tests/omhttp-retry-vg.sh0000775000175000017500000000010515171370365017000 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-retry.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-x509name-wildcard.sh0000644000000000000000000000013215241075234022265 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.482968938 rsyslog-8.2608.0/tests/imtcp-tls-ossl-x509name-wildcard.sh0000775000175000017500000000174415241075234021742 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer=["*.rsyslog.com"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp_conndrop.sh0000644000000000000000000000013215241075234017256 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067805.533932619 rsyslog-8.2608.0/tests/imtcp_conndrop.sh0000775000175000017500000000166715241075234016737 0ustar00rgerrger#!/bin/bash # Test imtcp with many dropping connections # added 2010-08-10 by Rgerhards # # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' $MaxMessageSize 10k module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! $OMFileFlushInterval 2 $OMFileIOBufferSize 256k local0.* ?dynfile;outfmt ' startup # 100 byte messages to gain more practical data use tcpflood -c20 -m$NUMMESSAGES -r -d100 -P129 -D shutdown_when_empty wait_shutdown export SEQ_CHECK_OPTIONS=-E seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_arg2_invalid-vg.sh0000644000000000000000000000013215171370365023046 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.899790727 30 ctime=1787067806.905958186 rsyslog-8.2608.0/tests/rscript_unflatten_arg2_invalid-vg.sh0000775000175000017500000000012715171370365022515 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_arg2_invalid.sh rsyslog-8.2608.0/tests/PaxHeaders/known_issues.supp0000644000000000000000000000013215241075234017344 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067808.613990014 rsyslog-8.2608.0/tests/known_issues.supp0000664000175000017500000000447715241075234017024 0ustar00rgerrger{ Memcheck:Leak ... fun:dlopen* ... } { Memcheck:Leak fun:malloc fun:CRYPTO_malloc fun:EC_KEY_new fun:EC_KEY_new_by_curve_name fun:SetAuthMode fun:LstnInit fun:create_tcp_socket fun:tcpsrvConstructFinalize fun:activate fun:initAll fun:main } { Memcheck:Param pselect6(sig) fun:pselect64_syscall fun:pselect fun:wait_timeout fun:mainloop fun:main } { Memcheck:Param pselect6(sig) fun:pselect fun:wait_timeout fun:mainloop fun:main } { Memcheck:Param pselect6(sig) fun:__pselect32 fun:__pselect64 fun:wait_timeout fun:mainloop fun:main } { Memcheck:Leak ... fun:checkInstance fun:activateCnf fun:tellModulesActivateConfig fun:activate fun:initAll } { Helgrind:Misc obj:/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so fun:_dl_fini fun:__run_exit_handlers fun:exit fun:(below main) } { Helgrind:Misc obj:/usr/lib/x86_64-linux-gnu/valgrind/vgpreload_helgrind-amd64-linux.so obj:/usr/lib/x86_64-linux-gnu/libp11-kit.so.0.3.0 fun:_dl_fini fun:__run_exit_handlers fun:exit fun:(below main) } { Helgrind:Race fun:SetGlobalInputTermination fun:deinitAll fun:main } { Helgrind:Race fun:GetGlobalInputTermState fun:RunEpoll fun:Run ... } { Memcheck:Leak match-leak-kinds: definite fun:malloc fun:UnknownInlinedFun fun:_dl_map_object_deps fun:dl_open_worker_begin fun:_dl_catch_exception fun:dl_open_worker fun:_dl_catch_exception fun:_dl_open fun:do_dlopen fun:_dl_catch_exception fun:_dl_catch_error fun:dlerror_run fun:__libc_dlopen_mode } rsyslog-8.2608.0/tests/PaxHeaders/es-basic-vg.sh0000644000000000000000000000013115171370365016344 xustar0030 mtime=1776677109.459913357 29 atime=1782715518.89879071 30 ctime=1787067803.916902488 rsyslog-8.2608.0/tests/es-basic-vg.sh0000775000175000017500000000010115171370365016004 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/es-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/imdocker-since-deleted-anchor.sh0000644000000000000000000000013215241075234022010 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067806.341947676 rsyslog-8.2608.0/tests/imdocker-since-deleted-anchor.sh0000775000175000017500000000275715241075234021472 0ustar00rgerrger#!/bin/bash # Regression test for imdocker container discovery after Docker rejects the # internal "since=" anchor. The oracle is that rsyslog first # reads a short-lived container, then still discovers and reads a second # container after the first one has been removed. # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init command -v docker >/dev/null 2>&1 || skip_test docker info >/dev/null 2>&1 || skip_test COOKIE=$(LC_ALL=C tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 10) OLD_CONTAINER="rsyslog-${COOKIE}-old" NEW_CONTAINER="rsyslog-${COOKIE}-new" cleanup_docker() { docker rm -f "$OLD_CONTAINER" "$NEW_CONTAINER" >/dev/null 2>&1 || true } trap cleanup_docker EXIT cleanup_docker generate_conf add_conf ' template(name="outfmt" type="string" string="%$!metadata!Names% %msg%\n") module(load="../contrib/imdocker/.libs/imdocker" PollingInterval="1" ListContainersOptions="all=true" GetContainerLogOptions="timestamps=0&follow=1&stdout=1&stderr=0&tail=all") if $!metadata!Names == "'$OLD_CONTAINER'" or $!metadata!Names == "'$NEW_CONTAINER'" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup docker run --name "$OLD_CONTAINER" alpine /bin/sh -c 'echo old-anchor' wait_content "old-anchor" docker rm "$OLD_CONTAINER" docker run --name "$NEW_CONTAINER" alpine /bin/sh -c 'echo new-after-deleted-anchor' wait_content "new-after-deleted-anchor" shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrabbitmq_error_server0.sh0000644000000000000000000000013215132733117021254 xustar0030 mtime=1768666703.965621117 30 atime=1782715518.900790744 30 ctime=1787067806.518950975 rsyslog-8.2608.0/tests/omrabbitmq_error_server0.sh0000777000175000017500000000317415132733117020732 0ustar00rgerrger#!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init cmd="./miniamqpsrvr -b 4 -f $RSYSLOG_DYNNAME.amqp.log -d" echo $cmd eval $cmd > $RSYSLOG_DYNNAME.source if [ ! $? -eq 0 ]; then exit 77 fi . $RSYSLOG_DYNNAME.source export OMRABBITMQ_TEST=1 generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omrabbitmq/.libs/omrabbitmq") template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%") # rfc5424 without Timestamp : unable to manage template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n") ruleset(name="rmq") { action(type="omrabbitmq" host="localhost" port="'$PORT_AMQP1'" user="mtr" password="mtr" exchange="in" expiration="5000" exchange_type="topic" durable="off" auto_delete="off" body_template="" content_type="rfc5424" virtual_host="/metrologie" routing_key_template="rkTpl" populate_properties="on" delivery_mode="transient" ) } if $msg contains "msgrmq" then { call rmq } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal "<167>Mar 1 01:00:00 192.0.2.8 tag msgrmq" shutdown_when_empty wait_shutdown export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:192.0.2.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 192.0.2.8 tag msgrmq' cmp_exact $RSYSLOG_DYNNAME.amqp.log content_check "exchange declare failed PRECONDITION_FAILED" exit_test rsyslog-8.2608.0/tests/PaxHeaders/pipeaction.sh0000644000000000000000000000013215241075234016373 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.787581702 30 ctime=1787067804.617915551 rsyslog-8.2608.0/tests/pipeaction.sh0000775000175000017500000000365415241075234016052 0ustar00rgerrger#!/bin/bash # Test the pipe output action with a disk-backed main queue. # # The test creates a FIFO, lets rsyslog write formatted messages to it, and # copies the FIFO stream into the normal sequence-check output file. Success # requires all injected messages to reach the external FIFO reader before # shutdown; main-queue-empty alone is not enough because the pipe reader is # outside rsyslog's queue accounting. # added 2009-11-05 by RGerhards # create the pipe and start a background process that copies data from # it to the "regular" work file . ${srcdir:=.}/diag.sh init export NUMMESSAGES=20000 generate_conf if [ "${QUEUE_TYPE:-disk}" = "segmentedDisk" ]; then add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then action(type="ompipe" pipe="rsyslog-testbench-fifo" template="outfmt") ' else add_conf ' $MainMsgQueueTimeoutShutdown 10000 # set spool locations and switch queue to disk-only mode $WorkDirectory '$RSYSLOG_DYNNAME'.spool $MainMsgQueueFilename mainq $MainMsgQueueType disk $template outfmt,"%msg:F,58:2%\n" # with pipes, we do not need to use absolute path names, so # we can simply refer to our working pipe via the usual relative # path name :msg, contains, "msgnum:" |rsyslog-testbench-fifo;outfmt ' fi rm -f rsyslog-testbench-fifo mkfifo rsyslog-testbench-fifo cp rsyslog-testbench-fifo $RSYSLOG_OUT_LOG & CPPROCESS=$! echo background cp process id is $CPPROCESS # now do the usual run startup injectmsg 0 $NUMMESSAGES wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" shutdown_when_empty wait_shutdown # wait for the cp process to finish, do pipe-specific cleanup echo waiting for background cp to terminate... wait $CPPROCESS rm -f rsyslog-testbench-fifo echo background cp has terminated, continue test... # and continue the usual checks seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh0000644000000000000000000000013215216464436025205 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.900790744 30 ctime=1787067807.527969777 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_serveranon_ossl_clientanon.sh0000775000175000017500000000313515216464436024656 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="anon" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/pgsql-basic-cnf6.sh0000644000000000000000000000013215035412264017276 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.900790744 30 ctime=1787067805.875938993 rsyslog-8.2608.0/tests/pgsql-basic-cnf6.sh0000777000175000017500000000123615035412264016751 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' module(load="../plugins/ompgsql/.libs/ompgsql") if $msg contains "msgnum" then { action(type="ompgsql" server="127.0.0.1" db="syslogtest" user="postgres" pass="testbench") }' startup injectmsg 0 5000 shutdown_when_empty wait_shutdown psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/rs-substring.sh0000644000000000000000000000013215241075234016702 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.928921346 rsyslog-8.2608.0/tests/rs-substring.sh0000775000175000017500000000137315241075234016355 0ustar00rgerrger#!/bin/bash # add 2018-04-04 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!var = substring($msg, 3, 2); template(name="outfmt" type="string" string="-%$!var%-\n") :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" shutdown_when_empty wait_shutdown echo '-gn-' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-rebind-tcp-vg.sh0000644000000000000000000000013215216464436020023 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.901790761 30 ctime=1787067805.639934595 rsyslog-8.2608.0/tests/omfwd-rebind-tcp-vg.sh0000775000175000017500000000033515216464436017473 0ustar00rgerrger#!/bin/bash # Valgrind wrapper for omfwd-rebind-tcp.sh. Keep the scenario in the base # test so the normal and Valgrind registrations exercise the same logic. export USE_VALGRIND="YES" . ${srcdir:=.}/omfwd-rebind-tcp.sh rsyslog-8.2608.0/tests/PaxHeaders/fromhost-port.sh0000644000000000000000000000013215241075234017063 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.767581328 30 ctime=1787067805.466931371 rsyslog-8.2608.0/tests/fromhost-port.sh0000775000175000017500000000136615241075234016540 0ustar00rgerrger#!/bin/bash ## fromhost-port.sh ## Check that fromhost-port property records sender port . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="list") { property(name="fromhost-port") constant(value="\n") } :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -m $NUMMESSAGES -w "${RSYSLOG_DYNNAME}.tcpflood-port" shutdown_when_empty wait_shutdown EXPECTED="$(cat "${RSYSLOG_DYNNAME}.tcpflood-port")" export EXPECTED cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_simple_multi.sh0000644000000000000000000000013115216464436020327 xustar0029 mtime=1782212894.06126675 30 atime=1782715518.900790744 30 ctime=1787067806.021941713 rsyslog-8.2608.0/tests/improg_simple_multi.sh0000775000175000017500000000122115216464436017773 0ustar00rgerrger#!/bin/bash # . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/improg/.libs/improg") template(name="outfmt" type="string" string="#%msg%#\n") input(type="improg" tag="tag" ruleset="ruleset" binary="'$PYTHON' '$srcdir'/improg-multiline-test.py" confirmmessages="off" closetimeout="2000" ) ruleset(name="ruleset") { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup wait_file_lines "$RSYSLOG_OUT_LOG" 10 shutdown_when_empty wait_shutdown NUM_ITEMS=10 echo "expected: $NUM_EXPECTED" echo "file: $RSYSLOG_OUT_LOG" content_check_with_count "#multi-line-string#" $NUM_EXPECTED $NUM_ITEMS exit_test rsyslog-8.2608.0/tests/PaxHeaders/mysql-asyn-vg.sh0000644000000000000000000000013215171370365016774 xustar0030 mtime=1776677109.465913449 30 atime=1782715518.900790744 30 ctime=1787067805.937940148 rsyslog-8.2608.0/tests/mysql-asyn-vg.sh0000775000175000017500000000020615171370365016441 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/mysql-asyn.sh rsyslog-8.2608.0/tests/PaxHeaders/execonlywhenprevsuspended4.sh0000644000000000000000000000013115035412264021642 xustar0029 mtime=1752569012.38883413 30 atime=1782715518.900790744 30 ctime=1787067804.630915793 rsyslog-8.2608.0/tests/execonlywhenprevsuspended4.sh0000777000175000017500000000204415035412264021314 0ustar00rgerrger#!/bin/bash # we test the execonly if previous is suspended directive. # This test checks if multiple backup actions can be defined. # rgerhards, 2010-06-24 echo =============================================================================== echo \[execonlywhenprevsuspended4.sh\]: test execonly..suspended multi backup action . ${srcdir:=.}/diag.sh init generate_conf add_conf ' # omtesting provides the ability to cause "SUSPENDED" action state $ModLoad ../plugins/omtesting/.libs/omtesting $MainMsgQueueTimeoutShutdown 100000 $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" :omtesting:fail 2 0 $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"';outfmt # note that $ActionExecOnlyWhenPreviousIsSuspended on is still active! & ./'"${RSYSLOG2_OUT_LOG}"';outfmt ' startup injectmsg 0 1000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 1 999 if [[ -s ${RSYSLOG2_OUT_LOG} ]] ; then echo failure: second output file has data where it should be empty exit 1 fi ; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-x509name_invalid.sh0000644000000000000000000000013215241075234022656 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.776581496 30 ctime=1787067807.394967299 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-x509name_invalid.sh0000775000175000017500000000203315241075234022323 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=3 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer="invalid name" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood --check-only -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown content_check "peer name not authorized" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtuxedoulog_data.sh0000644000000000000000000000013215035412264017755 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.900790744 30 ctime=1787067808.181981964 rsyslog-8.2608.0/tests/imtuxedoulog_data.sh0000777000175000017500000000435515035412264017435 0ustar00rgerrger#!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imtuxedoulog/.libs/imtuxedoulog") input(type="imtuxedoulog" ruleset="ruleset" severity="info" facility="local0" maxlinesatonce="100" persiststateinterval="10" maxsubmitatonce="100" tag="domain" ulogbase="./'$RSYSLOG_DYNNAME'") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format") } ' { echo '164313.15.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree' echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree' echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)' echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1' echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)' } > $RSYSLOG_DYNNAME.$(date "+%m%d%y") logdate=$(date "+%Y-%m-%d") startup shutdown_when_empty wait_shutdown { echo '<134>1 '${logdate}'T16:43:13.15 tst-tmsm1 domain ARTIMPP_UDB.40042721.1 - - TRACE:at: } tpfree' echo '<134>1 '${logdate}'T16:43:13.151 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003UF^"] TRACE:at: } tpfree' echo '<134>1 '${logdate}'T16:43:13.152 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02B003UF^"] TRACE:at: { tpcommit(0x0)' echo '<134>1 '${logdate}'T16:43:13.153 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003SF^"] TRACE:at: } tpcommit = 1' echo '<134>1 '${logdate}'T16:43:13.154 tst-tmsm1 domain ARTIMPP_UDB.40042722.1 - [ECID="000001833E1D4i^5pVl3iY00f02M003VF^"] TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)' } | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/openssl_mtls_server.c0000644000000000000000000000013115241075234020157 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.690579886 29 ctime=1787067803.59289645 rsyslog-8.2608.0/tests/openssl_mtls_server.c0000664000175000017500000002335315241075234017632 0ustar00rgerrger/* Very simple program to listen for a mutual-TLS connection, require a valid * client certificate, and capture application data to a file. * Used for the rsyslog testbench. * * Copyright 2026 Cisco Systems, Inc., and/or its affiliates. * Copyright 2026 Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include #include #include #include #include #include #include #include #include #include static void write_listen_port_file(const int sock, const char *const port_file) { if (port_file == NULL) { return; } struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); char port[NI_MAXSERV]; FILE *fp; if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0) { perror("OPENSSL-MTLS: getsockname failed"); exit(EXIT_FAILURE); } if (getnameinfo((struct sockaddr *)&addr, addrlen, NULL, 0, port, sizeof(port), NI_NUMERICSERV) != 0) { perror("OPENSSL-MTLS: getnameinfo failed"); exit(EXIT_FAILURE); } fp = fopen(port_file, "w"); if (fp == NULL) { perror("OPENSSL-MTLS: unable to open port file"); exit(EXIT_FAILURE); } fprintf(fp, "%s\n", port); fclose(fp); } static int create_socket(const char *const port, const char *const port_file) { struct addrinfo hints; struct addrinfo *res = NULL; struct addrinfo *rp; int s = -1; int optval = 1; int v6only = 0; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; if (getaddrinfo(NULL, port, &hints, &res) != 0) { perror("OPENSSL-MTLS: getaddrinfo failed"); exit(EXIT_FAILURE); } for (rp = res; rp != NULL; rp = rp->ai_next) { s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s < 0) { continue; } setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); if (rp->ai_family == AF_INET6) { setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)); } if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) { if (listen(s, 1) == 0) { write_listen_port_file(s, port_file); break; } } close(s); s = -1; } freeaddrinfo(res); if (s < 0) { perror("OPENSSL-MTLS: unable to bind or listen"); exit(EXIT_FAILURE); } return s; } static SSL_CTX *create_context(void) { const SSL_METHOD *method; SSL_CTX *ctx; #if OPENSSL_VERSION_NUMBER < 0x10100000L method = SSLv23_server_method(); #else method = TLS_server_method(); #endif ctx = SSL_CTX_new(method); if (ctx == NULL) { fprintf(stderr, "OPENSSL-MTLS: unable to create SSL context\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } return ctx; } static void apply_ssl_cfg(SSL_CTX *const ctx, const char *const cfg) { SSL_CONF_CTX *cctx = NULL; char *cfg_copy = NULL; char *cursor; if (cfg == NULL || *cfg == '\0') { return; } cctx = SSL_CONF_CTX_new(); if (cctx == NULL) { fprintf(stderr, "OPENSSL-MTLS: unable to allocate SSL_CONF_CTX\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE | SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); cfg_copy = strdup(cfg); if (cfg_copy == NULL) { perror("OPENSSL-MTLS: strdup failed"); SSL_CONF_CTX_free(cctx); exit(EXIT_FAILURE); } cursor = cfg_copy; while (cursor != NULL && *cursor != '\0') { char *line = cursor; char *sep; char *eq; int conf_ret; sep = strpbrk(cursor, "\n;"); if (sep != NULL) { *sep = '\0'; cursor = sep + 1; } else { cursor = NULL; } while (*line == ' ' || *line == '\t' || *line == '\r') { ++line; } if (*line == '\0') { continue; } eq = strchr(line, '='); if (eq == NULL) { fprintf(stderr, "OPENSSL-MTLS: invalid SSL config command '%s'\n", line); free(cfg_copy); SSL_CONF_CTX_free(cctx); exit(EXIT_FAILURE); } *eq = '\0'; ++eq; conf_ret = SSL_CONF_cmd(cctx, line, eq); if (conf_ret <= 0) { fprintf(stderr, "OPENSSL-MTLS: SSL_CONF_cmd failed for '%s=%s'\n", line, eq); ERR_print_errors_fp(stderr); free(cfg_copy); SSL_CONF_CTX_free(cctx); exit(EXIT_FAILURE); } } if (SSL_CONF_CTX_finish(cctx) != 1) { fprintf(stderr, "OPENSSL-MTLS: SSL_CONF_CTX_finish failed\n"); ERR_print_errors_fp(stderr); free(cfg_copy); SSL_CONF_CTX_free(cctx); exit(EXIT_FAILURE); } free(cfg_copy); SSL_CONF_CTX_free(cctx); } static void configure_context(SSL_CTX *const ctx, const char *const cert_file_path, const char *const key_file_path, const char *const ca_file_path) { if (SSL_CTX_use_certificate_file(ctx, cert_file_path, SSL_FILETYPE_PEM) <= 0) { fprintf(stderr, "OPENSSL-MTLS: unable to load server certificate\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } if (SSL_CTX_use_PrivateKey_file(ctx, key_file_path, SSL_FILETYPE_PEM) <= 0) { fprintf(stderr, "OPENSSL-MTLS: unable to load server private key\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } if (SSL_CTX_check_private_key(ctx) != 1) { fprintf(stderr, "OPENSSL-MTLS: server certificate/key mismatch\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } if (SSL_CTX_load_verify_locations(ctx, ca_file_path, NULL) != 1) { fprintf(stderr, "OPENSSL-MTLS: unable to load CA certificate\n"); ERR_print_errors_fp(stderr); exit(EXIT_FAILURE); } SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); apply_ssl_cfg(ctx, getenv("OPENSSL_MTLS_CFG")); } static FILE *open_output_file(const char *const output_file) { FILE *fp = fopen(output_file, "wb"); if (fp == NULL) { perror("OPENSSL-MTLS: unable to open output file"); exit(EXIT_FAILURE); } return fp; } int main(int argc, char **argv) { int sock = -1; int client = -1; int exit_status = EXIT_FAILURE; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); SSL_CTX *ctx = NULL; SSL *ssl = NULL; FILE *output = NULL; X509 *peer_cert = NULL; unsigned char buf[4096]; if (argc < 7) { fprintf(stderr, "Usage: %s PORT CERT_FILE KEY_FILE CA_FILE PORT_FILE OUTPUT_FILE\n", argv[0]); return EXIT_FAILURE; } SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); ctx = create_context(); configure_context(ctx, argv[2], argv[3], argv[4]); sock = create_socket(argv[1], argv[5]); output = open_output_file(argv[6]); client = accept(sock, (struct sockaddr *)&addr, &addrlen); if (client < 0) { perror("OPENSSL-MTLS: accept failed"); goto done; } ssl = SSL_new(ctx); if (ssl == NULL) { fprintf(stderr, "OPENSSL-MTLS: SSL_new failed\n"); ERR_print_errors_fp(stderr); goto done; } SSL_set_fd(ssl, client); if (SSL_accept(ssl) <= 0) { fprintf(stderr, "OPENSSL-MTLS: SSL_accept failed\n"); ERR_print_errors_fp(stderr); goto done; } if (SSL_get_verify_result(ssl) != X509_V_OK) { fprintf(stderr, "OPENSSL-MTLS: client certificate verification failed: %ld\n", SSL_get_verify_result(ssl)); goto done; } peer_cert = SSL_get_peer_certificate(ssl); if (peer_cert == NULL) { fprintf(stderr, "OPENSSL-MTLS: no client certificate presented\n"); goto done; } for (;;) { const int nread = SSL_read(ssl, buf, sizeof(buf)); if (nread > 0) { if (fwrite(buf, 1, (size_t)nread, output) != (size_t)nread) { perror("OPENSSL-MTLS: fwrite failed"); goto done; } fflush(output); continue; } if (nread == 0) { exit_status = EXIT_SUCCESS; break; } fprintf(stderr, "OPENSSL-MTLS: SSL_read failed\n"); ERR_print_errors_fp(stderr); goto done; } done: if (ssl != NULL) { SSL_shutdown(ssl); SSL_free(ssl); } if (peer_cert != NULL) { X509_free(peer_cert); } if (client >= 0) { close(client); } if (sock >= 0) { close(sock); } if (output != NULL) { fclose(output); } if (ctx != NULL) { SSL_CTX_free(ctx); } EVP_cleanup(); return exit_status; } rsyslog-8.2608.0/tests/PaxHeaders/imtcp-basic.sh0000644000000000000000000000013215241075234016433 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067805.476931557 rsyslog-8.2608.0/tests/imtcp-basic.sh0000775000175000017500000000112215241075234016076 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-jsonarray-retry.sh0000644000000000000000000000013215131231047021775 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.899790727 30 ctime=1787067806.129943726 rsyslog-8.2608.0/tests/omhttp-batch-jsonarray-retry.sh0000777000175000017500000000320315131231047021444 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 omhttp_start_server 0 --fail-every 100 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="2048") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") # Echo message as-is for retry template(name="tpl_echo" type="string" string="%msg%") ruleset(name="ruleset_omhttp_retry") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl_echo" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="jsonarray" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } ruleset(name="ruleset_omhttp") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="jsonarray" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/multiple_lookup_tables.sh0000644000000000000000000000013215035412264021015 xustar0030 mtime=1752569012.402736851 30 atime=1782715518.901790761 30 ctime=1787067805.003922744 rsyslog-8.2608.0/tests/multiple_lookup_tables.sh0000777000175000017500000000310415035412264020464 0ustar00rgerrger#!/bin/bash # test for multiple lookup-table and HUP based reloading of it # added 2016-01-20 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate_0" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl") lookup_table(name="xlate_1" file="'$RSYSLOG_DYNNAME'.xlate_1.lkp_tbl") template(name="outfmt" type="string" string="- %msg% 0_%$.lkp_0% 1_%$.lkp_1%\n") set $.lkp_0 = lookup("xlate_0", $msg); set $.lkp_1 = lookup("xlate_1", $msg); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate_1.lkp_tbl startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: 0_foo_old 1_foo_old" content_check "msgnum:00000001: 0_bar_old 1_bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: 0_foo_new 1_foo_old" content_check "msgnum:00000001: 0_bar_new 1_bar_old" content_check "msgnum:00000002: 0_baz" assert_content_missing "1_baz" cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_1.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: 0_foo_new 1_foo_new" content_check "msgnum:00000001: 0_bar_new 1_bar_new" content_check "msgnum:00000002: 0_baz 1_baz" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_dtls_certvalid.sh0000644000000000000000000000013015216464436020630 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.900790744 29 ctime=1787067807.78897464 rsyslog-8.2608.0/tests/sndrcv_dtls_certvalid.sh0000775000175000017500000000551315216464436020305 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verify successful omdtls-to-imdtls transfer with certificate validation. The # receiver must record the exact injected message sequence. . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls} export NUMMESSAGES=1000 export NUMMESSAGESFULL=$NUMMESSAGES export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" # debug.whitelist="on" # debug.files=["imdtls.c", "modules.c", "errmsg.c", "action.c"] ) module( load="../plugins/imdtls/.libs/imdtls" ) input( type="imdtls" port="0" listenPortFileName="'$PORT_RCVR_FILE'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" # debug.whitelist="on" # debug.files=["omdtls.c", "modules.c", "errmsg.c", "action.c"] ) # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") # Load modules module( load="../plugins/omdtls/.libs/omdtls" ) local4.* { action( name="omdtls" type="omdtls" target="127.0.0.1" port="'$PORT_RCVR'" action.resumeInterval="1" action.resumeRetryCount="2" queue.type="FixedArray" queue.size="10000" queue.dequeueBatchSize="1" queue.minDequeueBatchSize.timeout="1000" # 1 sec queue.timeoutWorkerthreadShutdown="1000" # 1 sec queue.timeoutshutdown="1000" # Slow down, do not lose UDP messages queue.dequeueSlowDown="1000" ) # action( type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-basic.sh0000644000000000000000000000013215131231047016624 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.899790727 30 ctime=1787067806.112943409 rsyslog-8.2608.0/tests/omhttp-basic.sh0000777000175000017500000000141015131231047016271 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 omhttp_start_server 0 generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../contrib/omhttp/.libs/omhttp") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="off" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_regex.match.rename.sh0000644000000000000000000000013215035412264024214 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.899790727 30 ctime=1787067808.097980399 rsyslog-8.2608.0/tests/imbatchreport_errmsg_regex.match.rename.sh0000777000175000017500000000072015035412264023664 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" rename=".done$ .s.done .r" reports="./*.done") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "Normal renaming leaves files in glob scope: Instance ignored to avoid loops." exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-impstats.sh0000644000000000000000000000013215241075234017216 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067805.641934632 rsyslog-8.2608.0/tests/imtcp-impstats.sh0000775000175000017500000000312715241075234016670 0ustar00rgerrger#!/bin/bash # added 2025-02-27 by RGerhards, released under ASL 2.0 # This checks primarily that impstats and imtcp work together. There is little # we can tell about the actual stats. . ${srcdir:=.}/diag.sh init export NUM_WORKERS=${NUM_WORKERS:-4} export NUMMESSAGES=40000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export STATSFILE="$RSYSLOG_DYNNAME.stats" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1") input(type="imtcp" address="127.0.0.1" name="pstats-test" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" workerthreads="'$NUM_WORKERS'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -m $NUMMESSAGES echo sleeping 2secs to ensure we have at least one stats interval sleep 2 shutdown_when_empty wait_shutdown cat -n $STATSFILE | grep 'w./pstats-test' NUM_STATS=$(grep 'w./pstats-test' "$STATSFILE" | wc -l) if [ "$NUM_WORKERS" -gt 1 ]; then EXPECTED_COUNT=$NUM_WORKERS else EXPECTED_COUNT=0 fi # Check if the count matches NUM_WORKERS if [ "$EXPECTED_COUNT" -gt 0 ]; then if [ "$NUM_STATS" -le "$EXPECTED_COUNT" ]; then echo "ERROR: Expected at most $EXPECTED_COUNT lines, but found $NUM_STATS in pstats" error_exit 1 fi else if [ "$NUM_STATS" -ne "$EXPECTED_COUNT" ]; then echo "ERROR: Expected $EXPECTED_COUNT lines, but found $NUM_STATS in pstats" error_exit 1 fi fi seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-queue-rpush-vg.sh0000644000000000000000000000013215171370365021123 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.901790761 30 ctime=1787067806.635953155 rsyslog-8.2608.0/tests/omhiredis-queue-rpush-vg.sh0000775000175000017500000000030115171370365020564 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-queue-rpush.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-fromhost-port.sh0000644000000000000000000000013215241075234023031 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.758899543 rsyslog-8.2608.0/tests/segmented-diskqueue-fromhost-port.sh0000775000175000017500000000033615241075234022502 0ustar00rgerrger#!/bin/bash # Run the asynchronous-ruleset sender-port persistence regression unchanged # against segmentedDisk. export QUEUE_TYPE=segmentedDisk export QUEUE_NEEDS_FILENAME=on . ${srcdir:=.}/fromhost-port-async-ruleset.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-key-mtls-sigalgs-vg.sh0000644000000000000000000000013215241075234024036 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.565970485 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-key-mtls-sigalgs-vg.sh0000775000175000017500000000013715241075234023506 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-key-mtls-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-basic.sh0000644000000000000000000000013115241075234017232 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.774581459 30 ctime=1787067807.274965063 rsyslog-8.2608.0/tests/imtcp-tls-basic.sh0000775000175000017500000000223615241075234016705 0ustar00rgerrger#!/bin/bash # added 2011-02-28 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export TB_TEST_MAX_RUNTIME=1500 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem") module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_ruleset_ratelimit.sh0000644000000000000000000000013215145046113023253 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.901790761 30 ctime=1787067804.665916445 rsyslog-8.2608.0/tests/imuxsock_logger_ruleset_ratelimit.sh0000775000175000017500000000222315145046113022721 0ustar00rgerrger#!/bin/bash # rgerhards, 2016-02-18 released under ASL 2.0 echo \[imuxsock_logger_ruleset_ratelimit.sh\]: test imuxsock with ruleset definition . ${srcdir:=.}/diag.sh init check_logger_has_option_d generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket" useSpecialParser="off" ruleset="testruleset" rateLimit.Interval="2" parseHostname="on") template(name="outfmt" type="string" string="%msg:%\n") ruleset(name="testruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup # send a message with trailing LF logger -d -u $RSYSLOG_DYNNAME-testbench_socket test # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! cmp $RSYSLOG_OUT_LOG $srcdir/resultdata/imuxsock_logger.log echo \"$(cat $RSYSLOG_OUT_LOG)\" if [ ! $? -eq 0 ]; then echo "imuxsock_logger.sh failed" echo "contents of $RSYSLOG_OUT_LOG:" echo \"$(cat $RSYSLOG_OUT_LOG)\" exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-vg.sh0000644000000000000000000000013015241075234023627 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.688579848 30 ctime=1787067807.543970075 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-vg.sh0000775000175000017500000000013615241075234023300 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/failover-rptd.sh0000644000000000000000000000013215035412264017015 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.900790744 30 ctime=1787067804.708917246 rsyslog-8.2608.0/tests/failover-rptd.sh0000777000175000017500000000100315035412264016460 0ustar00rgerrger#!/bin/bash # rptd test for failover functionality # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init NUMMESSAGES=5000 generate_conf add_conf ' $RepeatedMsgReduction on $template outfmt,"%msg:F,58:2%\n" # note: the target server shall not be available! :msg, contains, "msgnum:" @@127.0.0.1:'$TCPFLOOD_PORT' $ActionExecOnlyWhenPreviousIsSuspended on & ./'$RSYSLOG_OUT_LOG';outfmt ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imjournal-basic-vg.sh0000644000000000000000000000013215171370365017736 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.900790744 30 ctime=1787067805.990941136 rsyslog-8.2608.0/tests/imjournal-basic-vg.sh0000775000175000017500000000011015171370365017375 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imjournal-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_fragment.sh0000644000000000000000000000013215241075234020624 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.791581777 30 ctime=1787067806.964959286 rsyslog-8.2608.0/tests/rscript_faup_fragment.sh0000775000175000017500000000202215241075234020267 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://user:pass@www.rsyslog.com:443/doc/v8-stable/rainerscript/functions/mo-faup.html?param=value#faup"; set $.faup = faup_fragment($!url); set $.ret = script_error(); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 #faup' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-statefile-delete.sh0000644000000000000000000000013215131231047020715 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.899790727 30 ctime=1787067807.952977696 rsyslog-8.2608.0/tests/imfile-statefile-delete.sh0000777000175000017500000000263515131231047020374 0ustar00rgerrger#!/bin/bash # added 2019-02-28 # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init export TESTMESSAGES=1000 export TESTMESSAGESFULL=999 export RETRIES=50 # Uncomment fdor debuglogs #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' ./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input inode=$(get_inode "$RSYSLOG_DYNNAME.input") startup wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES rm $RSYSLOG_DYNNAME.input sleep_time_ms=0 while ls $RSYSLOG_DYNNAME.spool/imfile-state:$inode:* 1> /dev/null 2>&1; do ./msleep 100 ((sleep_time_ms+=100)) if [ $sleep_time_ms -ge 6000 ]; then touch $RSYSLOG_DYNNAME:.tmp fi if [ $sleep_time_ms -ge 30000 ]; then printf 'FAIL: state file still exists when it should have been deleted\nspool dir is:\n' ls -l $RSYSLOG_DYNNAME.spool error_exit 1 fi done shutdown_when_empty wait_shutdown seq_check 0 $TESTMESSAGESFULL # check we got the message correctly exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata-max-sd-size.sh0000644000000000000000000000013215216464436021113 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.899790727 30 ctime=1787067807.025960422 rsyslog-8.2608.0/tests/mmpstrucdata-max-sd-size.sh0000775000175000017500000000217315216464436020565 0ustar00rgerrger#!/bin/bash # Verify mmpstrucdata's maxStructuredDataSize guard skips oversized structured # data. The oracle uses configured omfile output after shutdown for the accepted # message; stderr/stdout are not used as proof. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") template(name="outfmt" type="string" string="%$!structured-data!custom-sd!small@32473!ok%\n") action(type="mmpstrucdata" jsonRoot="$!structured-data" container="custom-sd" maxStructuredDataSize="64") if $!structured-data!custom-sd!small@32473!ok == "yes" then action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal '<85>1 2026-05-22T08:00:00.000+00:00 host app proc msgid [large@32473 blob="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" tail="skip"] MMPSTRUCDATA too large' injectmsg literal '<85>1 2026-05-22T08:00:00.000+00:00 host app proc msgid [small@32473 ok="yes"] MMPSTRUCDATA accepted' shutdown_when_empty wait_shutdown export EXPECTED='yes' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/uxsock_simple.sh0000644000000000000000000000013215216464436017135 xustar0030 mtime=1782212894.090267219 30 atime=1782715518.899790727 30 ctime=1787067807.647972013 rsyslog-8.2608.0/tests/uxsock_simple.sh0000775000175000017500000000404015216464436016602 0ustar00rgerrger#!/bin/bash # This tests basic omuxsock functionality. A socket receiver is started which sends # all data to an output file, then a rsyslog instance is started which generates # messages and sends them to the unix socket. Datagram sockets are being used. # added 2010-08-06 by Rgerhards . ${srcdir:=.}/diag.sh init uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi wait_receiver_ready() { expected_generation=$1 ready_file=$2 count=1 while [ "$count" -le 100 ]; do if [ -r "$ready_file" ] && [ "$(cat "$ready_file")" = "$expected_generation" ]; then return fi $TESTTOOL_DIR/msleep 100 count=$((count + 1)) done echo "uxsockrcvr did not report ready generation $expected_generation for $ready_file" error_exit 1 } # create the pipe and start a background process that copies data from # it to the "regular" work file generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 $ModLoad ../plugins/omuxsock/.libs/omuxsock $template outfmt,"%msg:F,58:2%\n" $OMUXSockSocket '$RSYSLOG_DYNNAME'-testbench-dgram-uxsock :msg, contains, "msgnum:" :omuxsock:;outfmt ' RECEIVER_READY=$RSYSLOG_DYNNAME.uxsockrcvr.ready ./uxsockrcvr -s$RSYSLOG_DYNNAME-testbench-dgram-uxsock -o $RSYSLOG_OUT_LOG -r $RECEIVER_READY -t 60 & BGPROCESS=$! echo background uxsockrcvr process id is $BGPROCESS wait_receiver_ready 1 "$RECEIVER_READY" # now do the usual run startup # 10000 messages should be enough injectmsg 0 10000 wait_queueempty echo resetting uxsockrcvr... kill -HUP $BGPROCESS wait_receiver_ready 2 "$RECEIVER_READY" injectmsg 10000 10000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # wait for the cp process to finish, do pipe-specific cleanup echo shutting down uxsockrcvr... # TODO: we should do this more reliable in the long run! (message counter? timeout?) kill $BGPROCESS wait $BGPROCESS echo background process has terminated, continue test... # and continue the usual checks seq_check 0 19999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-queue.sh0000644000000000000000000000013215145046113017342 xustar0030 mtime=1771326539.054014533 30 atime=1782715518.899790727 30 ctime=1787067806.600952503 rsyslog-8.2608.0/tests/omhiredis-queue.sh0000775000175000017500000000260215145046113017011 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging # export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omhiredis/.libs/omhiredis") template(name="outfmt" type="string" string="%msg%") local4.* { action(type="omhiredis" name="omhiredis-queue" server="127.0.0.1" serverport="'$REDIS_RANDOM_PORT'" mode="queue" key="myKey" template="outfmt") stop } action(type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'" template="outfmt") ' startup # Inject 10 messages injectmsg 1 10 shutdown_when_empty wait_shutdown redis_command "LLEN myKey" > $RSYSLOG_OUT_LOG # try to get 11 (should get only 10) redis_command "LPOP myKey 11" >> $RSYSLOG_OUT_LOG # Messages should be retrieved in reverse order (as they were inserted using LPUSH) export EXPECTED="10 msgnum:00000010: msgnum:00000009: msgnum:00000008: msgnum:00000007: msgnum:00000006: msgnum:00000005: msgnum:00000004: msgnum:00000003: msgnum:00000002: msgnum:00000001:" cmp_exact $RSYSLOG_OUT_LOG content_check "omhiredis[omhiredis-queue]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/pgsql-basic-vg.sh0000644000000000000000000000013215035412264017056 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.902790778 30 ctime=1787067805.893939328 rsyslog-8.2608.0/tests/pgsql-basic-vg.sh0000777000175000017500000000116515035412264016532 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' $ModLoad ../plugins/ompgsql/.libs/ompgsql :msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench ' startup_vg injectmsg 0 5000 shutdown_when_empty wait_shutdown_vg check_exit_vg psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-compression.sh0000644000000000000000000000013215171370365020742 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.902790778 30 ctime=1787067806.303946968 rsyslog-8.2608.0/tests/omazuredce-compression.sh0000775000175000017500000000232615171370365020414 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . ${srcdir:=.}/omazuredce-env.sh require_plugin "omazuredce" export NUMMESSAGES=10 omazuredce_require_env generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omazuredce/.libs/omazuredce") template(name="tplAzureDceCompression" type="list" option.jsonftree="on") { property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf") property(outname="host" name="hostname" format="jsonf") property(outname="message" name="msg" format="jsonf") } local4.* action( type="omazuredce" template="tplAzureDceCompression" client_id="'$AZURE_DCE_CLIENT_ID'" client_secret=`echo $AZURE_DCE_CLIENT_SECRET` tenant_id="'$AZURE_DCE_TENANT_ID'" dce_url="'$AZURE_DCE_URL'" dcr_id="'$AZURE_DCE_DCR_ID'" table_name="'$AZURE_DCE_TABLE_NAME'" compression="default" max_batch_bytes="1048576" flush_timeout_ms="0" action.resumeInterval="1" action.resumeRetryCount="1" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown content_check "compression=default" exit_test rsyslog-8.2608.0/tests/PaxHeaders/diagtalker.c0000644000000000000000000000013115132733117016156 xustar0029 mtime=1768666703.95462095 30 atime=1782715518.901790761 30 ctime=1787067803.561895873 rsyslog-8.2608.0/tests/diagtalker.c0000666000175000017500000001127615132733117015634 0ustar00rgerrger/* A yet very simple tool to talk to imdiag (this replaces the * previous Java implementation in order to get fewer dependencies). * * Copyright 2010-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #endif static char *targetIP = "localhost"; static int targetPort = 13500; /* open a single tcp connection */ int openConn(int *fd) { char service[16]; struct addrinfo hints, *res = NULL, *rp = NULL; int retries = 0; int sock = -1; snprintf(service, sizeof(service), "%d", targetPort); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* Try IPv6, then IPv4 */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; for (;;) { if (res == NULL) { if (getaddrinfo(targetIP, service, &hints, &res) != 0 || res == NULL) { /* Fallback: try explicit loopback families */ if (getaddrinfo("127.0.0.1", service, &hints, &res) != 0 || res == NULL) { if (getaddrinfo("::1", service, &hints, &res) != 0 || res == NULL) { fprintf(stderr, "name resolution failed for 'localhost' and loopback addresses\n"); exit(1); } } } } for (rp = res; rp != NULL; rp = rp->ai_next) { sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sock == -1) { continue; } if (connect(sock, rp->ai_addr, rp->ai_addrlen) == 0) { *fd = sock; if (retries > 0) { fprintf(stderr, "[%d] connection established.\n", targetPort); } freeaddrinfo(res); return 0; } close(sock); sock = -1; } if (retries++ == 200) { perror("connect()"); fprintf(stderr, "[%d] connect() failed\n", targetPort); freeaddrinfo(res); exit(1); } else { fprintf(stderr, "[%d] connect failed, retrying...\n", targetPort); usleep(100000); } /* retry with same resolved list to keep overhead low */ } } /* send a string */ static void sendCmd(int fd, char *buf, int len) { int lenSend; lenSend = send(fd, buf, len, 0); if (lenSend != len) { perror("sending string"); exit(1); } } /* wait for a response from remote system */ static void waitRsp(int fd, char *buf, int len) { int ret; ret = recv(fd, buf, len - 1, 0); if (ret < 0) { perror("receiving response"); exit(1); } /* we assume the message was complete, it may be better to wait * for a LF... */ buf[ret] = '\0'; } /* do the actual processing */ static void doProcessing(void) { int fd; int len; char line[10 * 1024]; openConn(&fd); while (!feof(stdin)) { if (fgets(line, sizeof(line) - 1, stdin) == NULL) break; len = strlen(line); sendCmd(fd, line, len); waitRsp(fd, line, sizeof(line)); printf("imdiag[%d]: %s", targetPort, line); if (strstr(line, "imdiag::error") != NULL) { exit(1); } } } /* Run the test. * rgerhards, 2009-04-03 */ int main(int argc, char *argv[]) { int ret = 0; int opt; while ((opt = getopt(argc, argv, "t:p:")) != -1) { switch (opt) { case 't': targetIP = optarg; break; case 'p': targetPort = atoi(optarg); break; default: printf("invalid option '%c' or value missing - terminating...\n", opt); exit(1); break; } } doProcessing(); exit(ret); } rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-gtls-module-files-mtls.sh0000644000000000000000000000012715241075234022467 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067807.368966814 rsyslog-8.2608.0/tests/omfwd-tls-gtls-module-files-mtls.sh0000775000175000017500000000751715241075234022144 0ustar00rgerrger#!/bin/bash # Verify that builtin:omfwd module defaults for ordinary file-backed TLS # objects are inherited by an omfwd action that uses the gtls stream driver and # omits action-level StreamDriver.CAFile, StreamDriver.CertFile, and # StreamDriver.KeyFile. The oracle is that an OpenSSL helper requiring mutual # TLS captures exactly one forwarded payload line. . ${srcdir:=.}/diag.sh init check_command_available openssl if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi gtls_module="$(cd .. && pwd)/runtime/.libs/lmnsd_gtls.so" if [ ! -f "$gtls_module" ]; then echo "lmnsd_gtls module not built - skipping test" exit 77 fi workdir="$RSYSLOG_DYNNAME.omfwd-tls-gtls-module-files-mtls" port_file="$workdir/server.port" server_capture="$workdir/server.capture" server_stderr="$workdir/server.stderr" mkdir -p "$workdir" cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 2048 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 2048 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 2048 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 ./openssl_mtls_server 0 "$workdir/server.pem" "$workdir/server.key" "$workdir/ca.pem" \ "$port_file" "$server_capture" 2>"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf ' global( compatibility.defaults.secure="strict" net.ipprotocol="ipv4-only" ) module(load="'$gtls_module'") module( load="builtin:omfwd" StreamDriver.CAFile="'$workdir/ca.pem'" StreamDriver.CertFile="'$workdir/client.pem'" StreamDriver.KeyFile="'$workdir/client.key'" ) template(name="outfmt" type="string" string="%msg%\n") if $msg contains "omfwd-gtls-module-files-mtls" then { action( type="omfwd" target="127.0.0.1" protocol="tcp" port="'$server_port'" template="outfmt" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) } ' startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - omfwd-gtls-module-files-mtls' wait_file_lines "$server_capture" 1 shutdown_when_empty wait_shutdown wait $server_pid || { cat "$server_stderr" error_exit 1 } content_count_check --regex '^omfwd-gtls-module-files-mtls$' 1 "$server_capture" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-input-2certs.sh0000644000000000000000000000013215241075234020511 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.281965193 rsyslog-8.2608.0/tests/imtcp-tls-input-2certs.sh0000775000175000017500000000261315241075234020162 0ustar00rgerrger#!/bin/bash # added 2021-08-03 by Rgerhards # check that we do use the proper set of certificates # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' # The default shall NOT be used - if so, tcpflood would err out! global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/machine-cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/machine-key.pem") module(load="../plugins/imtcp/.libs/imtcp" permittedPeer="SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/fingerprint" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem" streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem" streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-gtls-x509fingerprint.sh0000644000000000000000000000013215241075234022076 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.333966162 rsyslog-8.2608.0/tests/imtcp-tls-gtls-x509fingerprint.sh0000775000175000017500000000230615241075234021546 0ustar00rgerrger#!/bin/bash # added 2018-12-22 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/fingerprint" PermittedPeer=["SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-gtls-x509name-legacy.sh0000644000000000000000000000013215131231047021723 xustar0030 mtime=1768239655.707212631 30 atime=1782715518.901790761 30 ctime=1787067807.342966329 rsyslog-8.2608.0/tests/imtcp-tls-gtls-x509name-legacy.sh0000777000175000017500000000221515131231047021374 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) # NOTE: we intentionally use legacy statements here! This *IS* what we want to test! $ModLoad ../plugins/imtcp/.libs/imtcp $DefaultNetstreamDriver gtls $inputTcpserverStreamdriverPermittedPeer rsyslog-client $InputTCPServerStreamDriverAuthMode x509/name $InputTCPServerStreamDriverPermittedPeer Log_Streaming_Client $InputTCPServerStreamDriverMode 1 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port $InputTCPServerRun 0 template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-basic-vg.sh0000644000000000000000000000013115171370365020627 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.902790778 29 ctime=1787067807.58397082 rsyslog-8.2608.0/tests/imtcp-tls-ossl-basic-vg.sh0000775000175000017500000000056615171370365020306 0ustar00rgerrger#!/bin/bash if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi export USE_VALGRIND="YES" # not working on CENTOS 7 export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes" . ${srcdir:-.}/imtcp-tls-ossl-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-basic.sh0000644000000000000000000000013215241075234020211 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.776581496 30 ctime=1787067807.497969218 rsyslog-8.2608.0/tests/imtcp-tls-ossl-basic.sh0000775000175000017500000000220315241075234017655 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "nsd_ptcp.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-syslog.sh0000644000000000000000000000013115241075234020252 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067805.062923843 rsyslog-8.2608.0/tests/mmsnareparse-syslog.sh0000775000175000017500000000265115241075234017726 0ustar00rgerrger#!/bin/bash # Validate mmsnareparse when receiving raw syslog messages over TCP. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmsnareparse/.libs/mmsnareparse") template(name="outfmt" type="list") { property(name="$!win!Event!EventID") constant(value=",") property(name="$!win!Event!Channel") constant(value=",") property(name="$!win!Event!EventType") constant(value=",") property(name="$!win!Event!CategoryText") constant(value=",") property(name="$!win!Event!Computer") constant(value="\n") } ruleset(name="winsec") { action(type="mmsnareparse") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="winsec") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port cat "$srcdir/testsuites/mmsnareparse/sample-windows2022-security.data" \ "$srcdir/testsuites/mmsnareparse/sample-windows2025-security.data" \ > ${RSYSLOG_DYNNAME}.payload tcpflood -m 1 -I ${RSYSLOG_DYNNAME}.payload rm -f ${RSYSLOG_DYNNAME}.payload shutdown_when_empty wait_shutdown content_check '4608,Security,Success Audit,Security State Change,WIN-5SB1I3G0V7U' $RSYSLOG_OUT_LOG content_check '4616,Security,Success Audit,Security State Change,WIN-5SB1I3G0V7U' $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-connection-msg-received.sh0000644000000000000000000000013215171402221022231 xustar0030 mtime=1776682129.619271137 30 atime=1782715518.902790778 30 ctime=1787067806.791956062 rsyslog-8.2608.0/tests/imptcp-connection-msg-received.sh0000775000175000017500000000201515171402221021676 0ustar00rgerrger#!/bin/bash # addd 2017-03-31 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" notifyonconnectionclose="on" notifyonconnectionopen="on") :msg, contains, "msgnum:" { action(type="omfile" file="'$RSYSLOG2_OUT_LOG'") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m1 -M"\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" shutdown_when_empty wait_shutdown grep "imptcp: connection established" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi grep "imptcp: session on socket.* closed" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrabbitmq_params_missing1.sh0000644000000000000000000000013215035412264021551 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.901790761 30 ctime=1787067806.498950602 rsyslog-8.2608.0/tests/omrabbitmq_params_missing1.sh0000777000175000017500000000062415035412264021224 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/omrabbitmq/.libs/omrabbitmq") action(type="omrabbitmq" exchange="in" host="host") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "routing_key or routing_key_template must be specified" exit_testrsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_regex.sh0000644000000000000000000000013215171370365017771 xustar0030 mtime=1776677109.465913449 30 atime=1782715518.901790761 30 ctime=1787067807.128962342 rsyslog-8.2608.0/tests/mmnormalize_regex.sh0000775000175000017500000000220115171370365017433 0ustar00rgerrger#!/bin/bash # added 2014-11-17 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[mmnormalize_regex.sh\]: test for mmnormalize regex field_type . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="hosts_and_ports" type="string" string="host and port list: %$!hps%\n") template(name="paths" type="string" string="%$!fragments% %$!user%\n") template(name="numbers" type="string" string="nos: %$!some_nos%\n") module(load="../plugins/mmnormalize/.libs/mmnormalize" allowRegex="on") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmnormalize" rulebase="'$srcdir/testsuites/mmnormalize_regex.rulebase'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="hosts_and_ports") ' startup tcpflood -m 1 -I $srcdir/testsuites/regex_input echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check 'host and port list: 192.168.1.2:80, 192.168.1.3, 192.168.1.4:443, 192.168.1.5' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-x509fingerprint.sh0000644000000000000000000000013215241075234022105 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.486969013 rsyslog-8.2608.0/tests/imtcp-tls-ossl-x509fingerprint.sh0000775000175000017500000000227715241075234021564 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/fingerprint" PermittedPeer=["SHA1:5C:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"] ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/compat-defaults-secure-dynafile-rainerscript.sh0000644000000000000000000000013215241075234025110 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067804.570914675 rsyslog-8.2608.0/tests/compat-defaults-secure-dynafile-rainerscript.sh0000775000175000017500000000341215241075234024557 0ustar00rgerrger#!/bin/bash # Validate RainerScript parity for secure dynafile template defaults. . ${srcdir:=.}/diag.sh init require_plugin imtcp modpath="${RSYSLOG_MODDIR}" run_expect_success() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -ne 0 ]; then echo "FAIL: expected ${cfg} to validate" cat "${log}" error_exit 1 fi } cat >"${RSYSLOG_DYNNAME}.mixed.conf" <Mar 10 01:00:00 172.20.245.8 tag secure-default:a/b:payload\"" shutdown_when_empty wait_shutdown printf 'payload\n' >"${RSYSLOG_DYNNAME}.expected" cmp_exact_file "${RSYSLOG_DYNNAME}.expected" "${RSYSLOG_DYNNAME}.rs_a_b.log" || { echo "FAIL: strict mode did not replace slash in RainerScript dynafile template" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-w-o-cookie-multi-spaces.sh0000644000000000000000000000013215241075234023151 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.780581571 30 ctime=1787067807.138962528 rsyslog-8.2608.0/tests/mmjsonparse-w-o-cookie-multi-spaces.sh0000775000175000017500000000136215241075234022622 0ustar00rgerrger#!/bin/bash # addd 2016-03-22 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' template(name="outfmt" type="string" string="%$!msgnum%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse" cookie="") if $parsesuccess == "OK" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' rm -f $RSYSLOG_OUT_LOG # do cleanup of previous subtest startup tcpflood -m $NUMMESSAGES "-j \" \"" shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-configured-sni.sh0000644000000000000000000000013215216464436022054 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.902790778 30 ctime=1787067807.632971733 rsyslog-8.2608.0/tests/omfwd-tls-ossl-configured-sni.sh0000775000175000017500000000134315216464436021524 0ustar00rgerrger#!/bin/bash # Author: John Cantu # Test that "custom-sni" is sent as SNI by omfwd, when configured . ${srcdir:=.}/diag.sh init port_file="$RSYSLOG_DYNNAME.sni-server.port" omfwd_sni_server "openssl" "$port_file" port=$(cat "$port_file") generate_conf add_conf ' global(DefaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" \ net.ipprotocol="ipv4-only") action(type="omfwd" target="localhost" protocol="tcp" port="'$port'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="anon" StreamDriverRemoteSNI="custom-sni" ) ' startup omfwd_sni_check "custom-sni" shutdown_immediate wait_shutdown kill -9 $(cat "$RSYSLOG_DYNNAME.sni-server.pid") exit_test rsyslog-8.2608.0/tests/PaxHeaders/dnscache-TTL-0-vg.sh0000644000000000000000000000013215171370365017225 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.902790778 30 ctime=1787067805.143925352 rsyslog-8.2608.0/tests/dnscache-TTL-0-vg.sh0000775000175000017500000000020515171370365016671 0ustar00rgerrger#!/bin/bash # added 2019-04-12 by Rainer Gerhards, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/dnscache-TTL-0.sh rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-non-unique-prefix.sh0000644000000000000000000000013115035412264021624 xustar0030 mtime=1752569012.386848027 30 atime=1782715518.902790778 29 ctime=1787067804.45691255 rsyslog-8.2608.0/tests/diskqueue-non-unique-prefix.sh0000777000175000017500000000173615035412264021305 0ustar00rgerrger#!/bin/bash # Test for config parser to check that disk queue file names are # unique. # added 2019-05-02 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") if 0 then { action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused" queue.filename="qf1" queue.type="linkedList") action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused" queue.filename="qf1" queue.type="linkedList") action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused" queue.filename="qf2" queue.type="linkedList") action(type="omfile" file="'$RSYSLOG_DYNNAME'.notused" queue.spooldirectory="'$RSYSLOG_DYNNAME'.spool2" queue.filename="qf2" queue.type="linkedList") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "and file name prefix 'qf1' already used" check_not_present "and file name prefix 'qf2' already used" exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg-simul.sh0000644000000000000000000000013215216464436016674 xustar0030 mtime=1782212894.058266701 30 atime=1782715518.902790778 30 ctime=1787067808.239983045 rsyslog-8.2608.0/tests/improg-simul.sh0000775000175000017500000000233515216464436016346 0ustar00rgerrger#! /bin/bash # add 2019-04-04 by Philippe DUVEAU, released under ASL 2.0 mysleep=./msleep ACK=0 SLEEP=0 DELAY=500 NB=1 MESSAGE="program datas" SIGNALED=0 ERR=$0.stderr while getopts "cd:e:s:n:m:g" OPTION; do case "${OPTION}" in g) SIGNALED=1 ;; c) ACK=1 ;; d) DELAY=${OPTARG} ;; e) ERR=${OPTARG} ;; s) SLEEP=${OPTARG} ;; n) NB=${OPTARG} ;; m) MESSAGE=${OPTARG} ;; *) exit 0 esac done trap 'echo "SIGTERM Received" >> '$ERR';echo $0" SIGTERM Received" >&2;exit 0' 15 if (( DELAY > 0 )); then $mysleep ${DELAY}; fi if [ ${ACK} == 1 ]; then while [ "$order" != "START" ]; do read -r order echo $order' Received' >> $ERR echo $0' '$order' Received' >&2 done while [ "$order" != "STOP" ]; do if (( NB > 0 )); then echo ${MESSAGE} echo "Message sent" >&2 (( NB-- )) fi unset order read -r order echo $order' Received' >> $ERR echo $0' '$order' Received' >&2 if (( SLEEP > 0 )); then $mysleep ${SLEEP}; fi done else while (( NB > 0 )); do echo ${MESSAGE} echo $0" Message sent" >&2 if (( SLEEP > 0 )); then $mysleep ${SLEEP}; fi (( NB-- )) done if [ ${SIGNALED} == 1 ]; then $mysleep 100000 & wait fi fi echo "Leaving improg_sender" >&2 rsyslog-8.2608.0/tests/PaxHeaders/imfile-readmode2-polling.sh0000644000000000000000000000013115035412264021005 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.901790761 29 ctime=1787067807.89897669 rsyslog-8.2608.0/tests/imfile-readmode2-polling.sh0000777000175000017500000000363015035412264020461 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( debug.whitelist="on" debug.files=["imfile.c"]) module(load="../plugins/imfile/.libs/imfile" mode="polling" PollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing sleep 2 # write some more lines (see https://github.com/rsyslog/rsyslog/issues/144) echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2 # give it time to finish sleep 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! # give it time to write the output file sleep 1 ## check if we have the correct number of messages NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" exit_test exit 1 else if [ ! $NUMLINES -eq 3 ]; then echo "ERROR: expecting 3 headers, got $NUMLINES" exit_test exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {1..4}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" exit_test exit 1 fi done ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/omtcl.tcl0000644000000000000000000000013115035412264015524 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.901790761 29 ctime=1787067808.63199035 rsyslog-8.2608.0/tests/omtcl.tcl0000666000175000017500000000036415035412264015176 0ustar00rgerrgerproc doAction {msg} { set fd [open $::env(RSYSLOG_OUT_LOG) a] puts $fd "message processed:" foreach {k v} $msg { puts $fd " $k: <<$v>>" } puts $fd " uppercase message: <<[string toupper [dict get $msg message]]>>" close $fd } rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_certvalid_tlscommand.sh0000644000000000000000000000013215241075234023737 xustar0030 mtime=1787067036.644579024 30 atime=1787067036.797581889 30 ctime=1787067807.464968603 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_certvalid_tlscommand.sh0000775000175000017500000000550715241075234023415 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" # start up the instances # export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="ossl" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.PermitExpiredCerts="off" gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2\nOptions=Bugs" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT # save this, will be rewritten with next config export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="ossl" ) action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" gnutlsPriorityString="Protocol=-ALL,TLSv1.2" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 0 1 shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # IMPORTANT: this test will generate many error messages. This is exactly it's # intent. So do not think something is wrong. The content_check below checks # these error codes. content_check --check-only "TLS library does not support SSL_CONF_cmd" ret=$? if [ $ret == 0 ]; then echo "SKIP: TLS library does not support SSL_CONF_cmd" skip_test elif [ "$(tls_backend)" = "wolfssl" ]; then # wolfSSL exposes SSL_CONF_cmd but the "Protocol" command is a stub # (returns -2 "cmd not yet implemented"); this test relies on protocol # filtering to force a handshake failure, which cannot happen there. echo "SKIP: wolfSSL SSL_CONF_cmd does not implement the Protocol command" skip_test else content_check --check-only "SSL_ERROR_SYSCALL" ret=$? if [ $ret == 0 ]; then # Found SSL_ERROR_SYSCALL errorcode, no further check needed exit_test else # Check for a SSL_ERROR_SSL error code content_check "SSL_ERROR_SSL" content_check "OpenSSL Error Stack:" fi fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrelp-shutdown-partial-session.sh0000644000000000000000000000013115171370365022526 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.901790761 30 ctime=1787067807.674972516 rsyslog-8.2608.0/tests/omrelp-shutdown-partial-session.sh0000775000175000017500000000157215171370365022203 0ustar00rgerrger#!/bin/bash # added 2026-04-14 to guard issue #6547, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin omrelp export ASAN_OPTIONS="detect_leaks=0${ASAN_OPTIONS:+:$ASAN_OPTIONS}" LISTENER_PORT_FILE="${RSYSLOG_DYNNAME}.holdtcpopen.port" LISTENER_ACCEPT_FILE="${RSYSLOG_DYNNAME}.holdtcpopen.accepted" $PYTHON ${srcdir}/holdtcpopen.py "${LISTENER_PORT_FILE}" "${LISTENER_ACCEPT_FILE}" 15 & HOLDTCP_PID=$! trap 'kill ${HOLDTCP_PID} 2>/dev/null || true' EXIT wait_file_exists "${LISTENER_PORT_FILE}" RELP_PORT=$(cat "${LISTENER_PORT_FILE}") generate_conf add_conf ' module(load="../plugins/omrelp/.libs/omrelp") main_queue(queue.type="Direct") action(type="omrelp" target="127.0.0.1" port="'${RELP_PORT}'") ' startup injectmsg_literal "issue-6547" wait_file_exists "${LISTENER_ACCEPT_FILE}" shutdown_immediate wait_shutdown wait ${HOLDTCP_PID} || true trap - EXIT exit_test rsyslog-8.2608.0/tests/PaxHeaders/prop-jsonmesg-vg.sh0000644000000000000000000000013215241075234017455 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067805.179926023 rsyslog-8.2608.0/tests/prop-jsonmesg-vg.sh0000775000175000017500000000114515241075234017125 0ustar00rgerrger#!/bin/bash # Added 2018-01-17 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="list"){ property(name="jsonmesg") constant(value="\n") } local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg tcpflood -m1 -y shutdown_when_empty wait_shutdown_vg check_exit_vg export EXPECTED='"msg": "msgnum:00000000:", ' . $srcdir/diag.sh grep-check exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmdb2diag_malformed_tail.sh0000644000000000000000000000013215241075234021130 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.787581702 30 ctime=1787067807.823975293 rsyslog-8.2608.0/tests/pmdb2diag_malformed_tail.sh0000775000175000017500000000214115241075234020575 0ustar00rgerrger#!/bin/bash # This test hardens pmdb2diag against malformed DB2-like tails. The oracle is # that unterminated PID/program delimiters do not trigger unbounded searches or # NULL pointer arithmetic, and a following marker message is still processed. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/pmdb2diag/.libs/pmdb2diag") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") parser(type="pmdb2diag" timeformat="%Y-%m-%d-%H.%M.%S." timepos="0" levelpos="59" pidstarttoprogstartshift="49" name="db2.diag.hardened") template(name="outfmt" type="string" string="valid-after\n") ruleset(name="testing" parser="db2.diag.hardened") { if $rawmsg contains "valid-after" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } }' startup tcpflood -m1 -M "\"<14>2015-05-06-16.53.26.989430+120 E1876227378A1702 LEVEL: Info PID :\"" tcpflood -m1 -M "\"<14>valid-after\"" shutdown_when_empty wait_shutdown export EXPECTED='valid-after' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_mbedtls_gnutlspriorityString_no_suite_in_common.sh0000644000000000000000000000013215216464436030473 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.901790761 30 ctime=1787067807.435968063 rsyslog-8.2608.0/tests/sndrcv_tls_mbedtls_gnutlspriorityString_no_suite_in_common.sh0000775000175000017500000000430315216464436030142 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer="rsyslog client" gnutlspriorityString="TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384") # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="x509/name" StreamDriverPermittedPeers="testbench.rsyslog.com" gnutlspriorityString="TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384,TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 # shut down sender when everything is sent, receiver continues to run concurrently #shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well #shutdown_when_empty wait_shutdown content_check --regex "\(no ciphersuites in common\|The handshake negotiation failed\)" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmleefparse_basic.sh0000644000000000000000000000013215132733117017701 xustar0030 mtime=1768666703.959621026 30 atime=1782715518.901790761 30 ctime=1787067807.131962398 rsyslog-8.2608.0/tests/mmleefparse_basic.sh0000777000175000017500000001270215132733117017354 0ustar00rgerrger#!/bin/bash # added 2025-09-?? by AI assistant, released under ASL 2.0 # Basic parsing test for the mmleefparse module using Palo Alto Networks samples. # The regression covers allow, drop and reset-both events provided with the task. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=3 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/mmleefparse/.libs/mmleefparse") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") #template(name="outfmt" type="subtree" subtree="$!leef" option.forceEndOfLine="on") template(name="outfmt" type="string" string="%$!leef!header!vendor%|%$!leef!header!productVersion%|%$!leef!fields!src%|%$!leef!fields!dst%|%$!leef!fields!action%|%$!leef!fields!cat%|%$!leef!fields!proto%|%$!leef!fields!SessionID%\n") if $syslogtag == "LEEF:" then { action(type="mmleefparse" container="!leef" delimiter="|") if $parsesuccess == "OK" then { action(name="write-leef" type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } else { action(name="write-non-leef" type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) } } ' startup tcpflood -m1 -M "\"<14>Sep 17 13:45:35 firewall.domain.local LEEF:1.0|Palo Alto Networks|PAN-OS Syslog Integration|11.1.6-h14|allow|cat=TRAFFIC|ReceiveTime=2025/09/17 13:45:34|SerialNumber=010108010025|Type=TRAFFIC|Subtype=start|devTime=Sep 17 2025 11:45:34 GMT|src=172.19.50.39|dst=172.19.5.50|srcPostNAT=0.0.0.157|dstPostNAT=0.0.0.157|RuleName=interzone-default|usrName=|SourceUser=|DestinationUser=|Application=ssl|VirtualSystem=vsys3|SourceZone=x-def|DestinationZone=z-def|IngressInterface=iu1.6751|EgressInterface=iu1.6723|LogForwardingProfile=default|SessionID=74879677|RepeatCount=1|srcPort=62126|dstPort=443|srcPostNATPort=0|dstPostNATPort=0|Flags=0x0|proto=tcp|action=allow|totalBytes=460|dstBytes=70|srcBytes=390|totalPackets=4|StartTime=2025/09/17 13:45:33|ElapsedTime=0|URLCategory=any|sequence=7548503197945820434|ActionFlags=0x8000000000000000|SourceLocation=172.0.0.20-172.255.255.1|DestinationLocation=172.0.0.20-172.255.255.1|dstPackets=1|srcPackets=3|SessionEndReason=n/a|DeviceGroupHierarchyL1=177|DeviceGroupHierarchyL2=235|DeviceGroupHierarchyL3=236|DeviceGroupHierarchyL4=239|vSrcName=firewall.domain.local|DeviceName=firewall.domain.local|ActionSource=from-policy|SrcUUID=|DstUUID=|TunnelID=0|MonitorTag=|ParentSessionID=0|ParentStartTime=|TunnelType=N/A\"" tcpflood -m1 -M "\"<14>Sep 17 13:48:38 firewall.domain.local LEEF:1.0|Palo Alto Networks|PAN-OS Syslog Integration|11.1.6-h14|deny|cat=TRAFFIC|ReceiveTime=2025/09/17 13:48:37|SerialNumber=010108010025|Type=TRAFFIC|Subtype=drop|devTime=Sep 17 2025 11:48:37 GMT|src=172.39.129.169|dst=172.224.141.39|srcPostNAT=0.0.0.157|dstPostNAT=0.0.0.157|RuleName=interzone-default|usrName=|SourceUser=|DestinationUser=|Application=not-applicable|VirtualSystem=vsys7|SourceZone=wan|DestinationZone=partner-gw|IngressInterface=zz8.2012|EgressInterface=|LogForwardingProfile=default|SessionID=0|RepeatCount=1|srcPort=63219|dstPort=3367|srcPostNATPort=0|dstPostNATPort=0|Flags=0x0|proto=tcp|action=deny|totalBytes=0|dstBytes=0|srcBytes=0|totalPackets=1|StartTime=2025/09/17 13:48:38|ElapsedTime=0|URLCategory=any|sequence=7548503197948374938|ActionFlags=0x8000000000000000|SourceLocation=172.0.0.20-172.255.255.1|DestinationLocation=172.0.0.20-172.255.255.1|dstPackets=0|srcPackets=1|SessionEndReason=policy-deny|DeviceGroupHierarchyL1=177|DeviceGroupHierarchyL2=235|DeviceGroupHierarchyL3=48936|DeviceGroupHierarchyL4=36126|vSrcName=firewall.domain.local|DeviceName=firewall.domain.local|ActionSource=from-policy|SrcUUID=|DstUUID=|TunnelID=0|MonitorTag=|ParentSessionID=0|ParentStartTime=|TunnelType=N/A\"" tcpflood -m1 -M "\"<14>Sep 17 13:47:11 firewall.domain.local LEEF:1.0|Palo Alto Networks|PAN-OS Syslog Integration|11.1.6-h14|reset-both|cat=TRAFFIC|ReceiveTime=2025/09/17 13:47:10|SerialNumber=010108000243|Type=TRAFFIC|Subtype=deny|devTime=Sep 17 2025 11:47:10 GMT|src=172.35.163.110|dst=172.42.1.234|srcPostNAT=0.0.0.157|dstPostNAT=0.0.0.157|RuleName=interzone-default|usrName=|SourceUser=|DestinationUser=|Application=ssl|VirtualSystem=vsys7|SourceZone=client-vpn|DestinationZone=gdcbb|IngressInterface=zz8.1083|EgressInterface=zz8.1001|LogForwardingProfile=default|SessionID=336519782|RepeatCount=1|srcPort=61567|dstPort=9997|srcPostNATPort=0|dstPostNATPort=0|Flags=0x100400|proto=tcp|action=reset-both|totalBytes=6689|dstBytes=5964|srcBytes=725|totalPackets=14|StartTime=2025/09/17 13:47:10|ElapsedTime=0|URLCategory=any|sequence=7548134123908109690|ActionFlags=0x8000000000000000|SourceLocation=172.0.0.20-172.255.255.1|DestinationLocation=172.0.0.20-172.255.255.1|dstPackets=7|srcPackets=7|SessionEndReason=policy-deny|DeviceGroupHierarchyL1=177|DeviceGroupHierarchyL2=235|DeviceGroupHierarchyL3=48936|DeviceGroupHierarchyL4=36126|vSrcName=firewall.domain.local|DeviceName=firewall.domain.local|ActionSource=from-application|SrcUUID=|DstUUID=|TunnelID=0|MonitorTag=|ParentSessionID=0|ParentStartTime=|TunnelType=N/A\"" shutdown_when_empty wait_shutdown EXPECTED=$'Palo Alto Networks|11.1.6-h14|172.19.50.39|172.19.5.50|allow|TRAFFIC|tcp|74879677\nPalo Alto Networks|11.1.6-h14|172.39.129.169|172.224.141.39|deny|TRAFFIC|tcp|0\nPalo Alto Networks|11.1.6-h14|172.35.163.110|172.42.1.234|reset-both|TRAFFIC|tcp|336519782' cmp_exact if [ -s "$RSYSLOG2_OUT_LOG" ]; then echo "unexpected data in secondary output log:" cat "$RSYSLOG2_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-consumerGroup-ack.sh0000644000000000000000000000013215131231047023102 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.901790761 30 ctime=1787067806.557951701 rsyslog-8.2608.0/tests/imhiredis-stream-consumerGroup-ack.sh0000777000175000017500000000304415131231047022554 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %$!msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mystream" mode="stream" stream.consumerGroup="mygroup" stream.consumerName="myName" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup redis_command "XADD mystream * msg message1" redis_command "XADD mystream * msg message2" redis_command "XADD mystream * msg message3" shutdown_when_empty wait_shutdown output="$(redis_command 'hello 3\nXINFO groups mystream' | grep 'pending')" if [ -z "$output" ]; then echo "Could not get group result from redis, cannot tell if entries ware acknowledged!" error_exit 1 fi if ! echo "$output" | grep -q "pending 0"; then echo "ERROR: entries werent acknowledged!" echo "ERROR: output from Redis is '$output'" echo "ERROR: expected 'pending 0'" error_exit 1 fi stop_redis content_check '1 message1' content_check '2 message2' content_check '3 message3' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/test_id.c0000644000000000000000000000013115132411300015465 xustar0030 mtime=1768559296.299886162 30 atime=1782715518.902790778 29 ctime=1787067803.63689727 rsyslog-8.2608.0/tests/test_id.c0000666000175000017500000000156315132411300015141 0ustar00rgerrger#include #include #include #include /* one provided by Aaaron Wiebe based on perl's hashing algorithm * (so probably pretty generic). Not for excessively large strings! */ #if defined(__clang__) #pragma GCC diagnostic ignored "-Wunknown-attributes" #endif static unsigned __attribute__((nonnull(1))) int #if defined(__clang__) __attribute__((no_sanitize("unsigned-integer-overflow"))) #endif hash_from_string(void *k) { char *rkey = (char *)k; unsigned hashval = 1; while (*rkey) hashval = hashval * 33 + *rkey++; return hashval; } int main(int argc, char *argv[]) { struct timeval tv; gettimeofday(&tv, NULL); if (argc != 2) { fprintf(stderr, "usage: test_id test-file-name\n"); exit(1); } printf("%06ld_%4.4x", tv.tv_usec, hash_from_string(argv[1])); return 0; } rsyslog-8.2608.0/tests/PaxHeaders/dynfile_invalid2.sh0000644000000000000000000000013015241075234017460 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 29 ctime=1787067804.61091542 rsyslog-8.2608.0/tests/dynfile_invalid2.sh0000775000175000017500000000372115241075234017134 0ustar00rgerrger#!/bin/bash # This test checks if omfile segfaults when a file open() in dynacache mode fails. # The test is mimiced after a real-life scenario (which, of course, was much more # complex). # # added 2010-03-22 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:3%\n" $template dynfile,"%msg:F,58:2%.log" # complete name is in message $OMFileFlushOnTXEnd off $DynaFileCacheSize 4 $omfileFlushInterval 1 local0.* ?dynfile;outfmt ' startup # we send handcrafted message. We have a dynafile cache of 4, and now send one message # each to fill up the cache. tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:0\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:3\"" # the next one has caused a segfault in practice # note that /proc/rsyslog.error.file must not be creatable tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:/proc/rsyslog.error.file:boom\"" # some more writes tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.0.log:4\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.1.log:5\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.2.log:6\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag msg:$RSYSLOG_DYNNAME.out.3.log:7\"" # done message generation shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # and wait for it to terminate cat $RSYSLOG_DYNNAME.out.*.log > $RSYSLOG_OUT_LOG seq_check 0 7 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmutf8fix_sd.sh0000644000000000000000000000013115241075234016654 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067805.685935452 rsyslog-8.2608.0/tests/mmutf8fix_sd.sh0000775000175000017500000000463715241075234016336 0ustar00rgerrger#!/bin/bash # Validate mmutf8fix structured data handling for invalid UTF-8. # mmutf8fix must sanitize pszStrucData so that mmpstrucdata # parses clean UTF-8 values into the $! property tree. # add 2026-04 Charles-Antoine Mathieu, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmutf8fix/.libs/mmutf8fix") module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") template(name="outfmt" type="string" string="%$!rfc5424-sd!test@32473!clean% | %$!rfc5424-sd!test@32473!dirty% | %msg%\n") ruleset(name="testing") { action(type="mmutf8fix" replacementChar="?") action(type="mmpstrucdata") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup # Test 1: Valid UTF-8 in SD should be preserved tcpflood -m1 -M "\"<134>1 2024-01-01T00:00:00Z host app 1 - [test@32473 clean=\\\"hello\\\" dirty=\\\"world\\\"] valid msg\"" # Test 2: Invalid 0xa0 (Latin-1 NBSP) in SD value — should be replaced with ? # use a file because raw bytes do not survive shell quoting printf '<134>1 2024-01-01T00:00:00Z host app 2 - [test@32473 clean="ok" dirty="Brain\xa0Twist"] invalid NBSP\n' \ > "$RSYSLOG_DYNNAME.tmp" tcpflood -m1 -I "$RSYSLOG_DYNNAME.tmp" rm "$RSYSLOG_DYNNAME.tmp" # Test 3: Invalid 0xed (Latin-1 accented char) in SD value — should be replaced printf '<134>1 2024-01-01T00:00:00Z host app 3 - [test@32473 clean="ok" dirty="Galer\xeda"] invalid latin1\n' \ > "$RSYSLOG_DYNNAME.tmp" tcpflood -m1 -I "$RSYSLOG_DYNNAME.tmp" rm "$RSYSLOG_DYNNAME.tmp" # Test 4: Valid multi-byte UTF-8 in SD should be preserved (ñ = 0xc3 0xb1) tcpflood -m1 -M "\"<134>1 2024-01-01T00:00:00Z host app 4 - [test@32473 clean=\\\"ok\\\" dirty=\\\"España\\\"] valid multibyte\"" # Test 5: No structured data — should not crash tcpflood -m1 -M "\"<134>1 2024-01-01T00:00:00Z host app 5 - - no SD at all\"" shutdown_when_empty wait_shutdown echo 'hello | world | valid msg ok | Brain?Twist | invalid NBSP ok | Galer?a | invalid latin1 ok | España | valid multibyte | | no SD at all' > "$RSYSLOG_OUT_LOG.expect" if ! cmp "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG; then echo "invalid response generated, $RSYSLOG_OUT_LOG diff:" LANG=C diff --text -u "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdiag-modern-module-config.sh0000644000000000000000000000013215216464436021512 xustar0030 mtime=1782212894.052266604 30 atime=1782715518.903790795 30 ctime=1787067804.554914377 rsyslog-8.2608.0/tests/imdiag-modern-module-config.sh0000775000175000017500000000266515216464436021172 0ustar00rgerrger#!/bin/bash # Verify all imdiag module parameters validate with legacy $-directives disabled # and the testbench startup path uses module-level serverRun/listenPortFileName. . ${srcdir:=.}/diag.sh init require_plugin imdiag modpath="${RSYSLOG_MODDIR}" cat >"${RSYSLOG_DYNNAME}.allparams.conf" <"${RSYSLOG_DYNNAME}.allparams.log" 2>&1 ret=$? if [ $ret -ne 0 ]; then echo "FAIL: expected imdiag module parameters to validate with legacy disabled" cat "${RSYSLOG_DYNNAME}.allparams.log" error_exit 1 fi generate_conf add_conf ' global(compatibility.configformat.legacy="disable") ' startup shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-retry-metadata-vg.sh0000644000000000000000000000013115171370365022171 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.903790795 30 ctime=1787067805.977940893 rsyslog-8.2608.0/tests/omhttp-batch-retry-metadata-vg.sh0000775000175000017500000000012415171370365021636 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-batch-retry-metadata.sh rsyslog-8.2608.0/tests/PaxHeaders/imrelp-basic-hup.sh0000644000000000000000000000013115035412264017377 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.902790778 30 ctime=1787067807.684972703 rsyslog-8.2608.0/tests/imrelp-basic-hup.sh0000777000175000017500000000121515035412264017050 0ustar00rgerrger#!/bin/bash # added 2019-07-30 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=4000 # MUST be an even number! generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" port="'$TCPFLOOD_PORT'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) issue_HUP tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2)) shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_gtls_servercert_ossl_clientanon.sh0000644000000000000000000000013115216464436025177 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.903790795 29 ctime=1787067807.64297192 rsyslog-8.2608.0/tests/sndrcv_tls_gtls_servercert_ossl_clientanon.sh0000775000175000017500000000355415216464436024656 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/linkedlistqueue.sh0000644000000000000000000000013215131231047017441 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.903790795 30 ctime=1787067804.953921812 rsyslog-8.2608.0/tests/linkedlistqueue.sh0000777000175000017500000000114315131231047017111 0ustar00rgerrger#!/bin/bash # Test for Linkedlist queue mode # added 2009-05-20 by rgerhards # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=40000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' # set spool locations and switch queue to disk-only mode $MainMsgQueueType LinkedList $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/no-dynstats-json.sh0000644000000000000000000000013115131231047017463 xustar0029 mtime=1768239655.71021268 30 atime=1782715518.903790795 30 ctime=1787067806.695954273 rsyslog-8.2608.0/tests/no-dynstats-json.sh0000777000175000017500000000166715131231047017147 0ustar00rgerrger#!/bin/bash # added 2016-03-10 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[no-dynstats-json.sh\]: test for verifying stats are reported correctly in json format in absence of any dynstats buckets being configured . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown custom_content_check '{ "name": "global", "origin": "dynstats", "values": { } }' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_privdropuser.sh0000644000000000000000000000013215131231047020544 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.903790795 30 ctime=1787067804.218908115 rsyslog-8.2608.0/tests/rscript_privdropuser.sh0000777000175000017500000000113015131231047020210 0ustar00rgerrger#!/bin/bash # added 2021-09-23 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.user.name="'${TESTBENCH_TESTUSER[username]}'") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-mtls-sigalgs.sh0000644000000000000000000000013215241075234022636 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.622971547 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-mtls-sigalgs.sh0000775000175000017500000000014515241075234022305 0ustar00rgerrger#!/bin/bash export PKCS11_SIGALG_VARIANT=full . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-sigalgs-common.sh rsyslog-8.2608.0/tests/PaxHeaders/pgsql-template.sh0000644000000000000000000000013215035412264017176 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.902790778 30 ctime=1787067805.880939086 rsyslog-8.2608.0/tests/pgsql-template.sh0000777000175000017500000000166515035412264016657 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' # putting the message in the SyslogTag field, so we know the template is actually used $template mytemplate,"insert into SystemEvents (SysLogTag) values ' add_conf "('%msg%')" add_conf '",STDSQL $ModLoad ../plugins/ompgsql/.libs/ompgsql :msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench;mytemplate ' startup injectmsg 0 5000 shutdown_when_empty wait_shutdown # we actually put the message in the SysLogTag field, so we know it doesn't use the default # template, like in pgsql-basic psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-key-mtls.sh0000644000000000000000000000013115241075234021774 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 29 ctime=1787067807.60597123 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-key-mtls.sh0000775000175000017500000001506015241075234021446 0ustar00rgerrger#!/bin/bash # Verify that omfwd with the ossl driver can establish a mutual-TLS session to # an OpenSSL-based remote peer when the CA certificate and client certificate # are loaded from PEM files but the client private key is loaded via a strict # pkcs11: URI. This matches the mixed deployment mode used in IOS XR. The # oracle is that the remote helper, which requires a valid client certificate, # captures exactly one forwarded payload line for the test message. If rsyslog # fails to bind the PEM certificate to the PKCS#11-backed key, the helper # aborts the handshake with "peer did not return a certificate" and this test # fails without matching the payload line. . ${srcdir:=.}/diag.sh init check_command_available openssl check_command_available softhsm2-util check_command_available pkcs11-tool if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi find_first_existing() { for candidate in "$@"; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } workdir="$RSYSLOG_DYNNAME.omfwd-tls-ossl-pkcs11-key-mtls" port_file="$workdir/server.port" server_capture="$workdir/server.capture" server_stderr="$workdir/server.stderr" softhsm_conf="$workdir/softhsm2.conf" openssl_conf="$workdir/openssl-pkcs11.cnf" token_dir="$workdir/tokens" token_label="rsyslog-test-token" token_pin="123456" token_so_pin="12345678" mkdir -p "$workdir" "$token_dir" provider_module=$(find_first_existing \ /usr/lib64/ossl-modules/pkcs11.so \ /usr/lib/ossl-modules/pkcs11.so \ /usr/lib/x86_64-linux-gnu/ossl-modules/pkcs11.so \ /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so \ /usr/local/lib64/ossl-modules/pkcs11.so \ /usr/local/lib/ossl-modules/pkcs11.so) || { printf 'info: skipping test - pkcs11 OpenSSL provider module not found\n' skip_test } softhsm_module=$(find_first_existing \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/pkcs11/libsofthsm2.so \ /usr/lib64/softhsm/libsofthsm2.so \ /usr/lib/softhsm/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib64/libsofthsm2.so \ /usr/lib/libsofthsm2.so) || { printf 'info: skipping test - SoftHSM PKCS#11 module not found\n' skip_test } cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 2048 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 2048 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 2048 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 openssl x509 -in "$workdir/client.pem" -outform DER -out "$workdir/client.der" || error_exit 1 openssl pkey -in "$workdir/client.key" -pubout -outform DER -out "$workdir/client.pub.der" || \ error_exit 1 cat >"$softhsm_conf" <"$openssl_conf" <"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf ' global( compatibility.defaults.secure="strict" net.ipprotocol="ipv4-only" ) module(load="builtin:omfwd") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "omfwd-ossl-pkcs11-key-mtls" then { action( type="omfwd" target="127.0.0.1" protocol="tcp" port="'$server_port'" template="outfmt" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" streamdriver.cafile="'$workdir/ca.pem'" streamdriver.certfile="'$workdir/client.pem'" streamdriver.keyfile="'$key_uri'" ) } ' startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - omfwd-ossl-pkcs11-key-mtls' wait_file_lines "$server_capture" 1 shutdown_when_empty wait_shutdown wait $server_pid || { cat "$server_stderr" error_exit 1 } content_count_check --regex '^omfwd-ossl-pkcs11-key-mtls$' 1 "$server_capture" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_gtls_native_pq_group.sh0000644000000000000000000000013115241075234022733 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.352966516 rsyslog-8.2608.0/tests/sndrcv_tls_gtls_native_pq_group.sh0000775000175000017500000000417415241075234022411 0ustar00rgerrger#!/bin/bash # Native GnuTLS PQ smoke test. Requires a GnuTLS build with # GROUP-X25519-MLKEM768 support. . ${srcdir:=.}/diag.sh init check_command_available gnutls-cli export GNUTLS_PQ_PRIO='NORMAL:-GROUP-ALL:+GROUP-X25519-MLKEM768:+GROUP-X25519' if ! gnutls-cli --priority "$GNUTLS_PQ_PRIO" --list >/dev/null 2>&1; then echo "SKIP: native GnuTLS PQ group GROUP-X25519-MLKEM768 is unavailable" skip_test fi export NUMMESSAGES=1000 export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" gnutlsPriorityString="'$GNUTLS_PQ_PRIO'") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port") $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon" gnutlsPriorityString="'$GNUTLS_PQ_PRIO'" ) ' 2 startup 2 tcpflood -m$NUMMESSAGES -i1 wait_file_lines shutdown_when_empty 2 wait_shutdown 2 shutdown_when_empty wait_shutdown content_check --check-only "Syntax error or unsupported option in Priority String" # shellcheck disable=SC2181 if [ $? -eq 0 ]; then echo "SKIP: native GnuTLS PQ group configuration was rejected" skip_test fi seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/libdbi-asyn.sh0000644000000000000000000000013215216464436016445 xustar0030 mtime=1782212894.072266928 30 atime=1782715518.902790778 30 ctime=1787067805.945940297 rsyslog-8.2608.0/tests/libdbi-asyn.sh0000775000175000017500000000135315216464436016116 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 # this test is veeeeery slow, value is a compromise generate_conf add_conf ' $ModLoad ../plugins/omlibdbi/.libs/omlibdbi $ActionQueueType LinkedList $ActionQueueTimeoutEnqueue 30000 $ActionLibdbiDriver mysql $ActionLibdbiHost 127.0.0.1 $ActionLibdbiUserName rsyslog $ActionLibdbiPassword testbench $ActionLibdbiDBName '$RSYSLOG_DYNNAME' :msg, contains, "msgnum:" { :omlibdbi: action(type="omfile" file="'$RSYSLOG_DYNNAME'.syncfile") } ' mysql_prep_for_test libdbi startup injectmsg wait_file_lines $RSYSLOG_DYNNAME.syncfile $NUMMESSAGES 2500 shutdown_when_empty wait_shutdown mysql_get_data seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-wildcards-dirs-multi5.sh0000644000000000000000000000013215216464436021643 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.902790778 30 ctime=1787067807.987978349 rsyslog-8.2608.0/tests/imfile-wildcards-dirs-multi5.sh0000775000175000017500000000540215216464436021313 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . ${srcdir:=.}/diag.sh init export IMFILEINPUTFILES="8" #"8" export IMFILEINPUTFILESSTEPS="5" #"5" #export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS)) export IMFILECHECKTIMEOUT="60" # Start rsyslog now before adding more files mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global( workDirectory="./'"$RSYSLOG_DYNNAME"'.work" debug.whitelist="on" debug.files=["imfile.c"]) module(load="../plugins/imfile/.libs/imfile" mode="inotify" pollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.dir?/*/*.logfile" Tag="file:" Severity="error" Facility="local7" addMetadata="on") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.alt/alt*file" Tag="file:" Severity="error" Facility="local7" addMetadata="on") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="'"'"', ") property(name="$!metadata!filename") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") #*.* action(type="omfile" file="rsyslog.debug") ' # create first directory and file before startup, so ensure we will NOT # get an initial inotify notify for it! mkdir $RSYSLOG_DYNNAME.input.alt #./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.alt/altfile.logfile mkdir $RSYSLOG_DYNNAME.input.dir1 # the following is INVALID, as this is a file, but must be a directory! ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input.dir0 startup for j in $(seq 1 $IMFILEINPUTFILESSTEPS); do echo "Loop Num $j" for i in $(seq 1 $IMFILEINPUTFILES); do mkdir $RSYSLOG_DYNNAME.input.dir$i mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$i ./inputfilegen -m 1 -i $(((j - 1) * IMFILEINPUTFILES + i - 1)) > \ $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.tmp mv $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.tmp \ $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile done ls -d $RSYSLOG_DYNNAME.input.* # Check correct amount of input files each time IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j)) content_check_with_count "HEADER msgnum:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT # Delete all but first! for i in $(seq 1 $IMFILEINPUTFILES); do # slow systems (NFS) do not reliably do rm -r (unfortunately...) rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i/file.logfile ./msleep 100 rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$i ./msleep 100 rm -vrf $RSYSLOG_DYNNAME.input.dir$i done # Helps in testbench parallel mode. # Otherwise sometimes directories are not marked deleted in imfile before they get created again. # This is properly a real issue in imfile when FILE IO is high. ./msleep 1000 done shutdown_when_empty wait_shutdown #echo rsyslog.debug: #cat rsyslog.debug exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnull-basic.sh0000644000000000000000000000013215241075234016626 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.787581702 30 ctime=1787067807.042960739 rsyslog-8.2608.0/tests/pmnull-basic.sh0000775000175000017500000000227015241075234016276 0ustar00rgerrger#!/bin/bash # add 2016-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/pmnull/.libs/pmnull") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") parser(name="custom.pmnull.withOrigin" type="pmnull") template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n") ruleset(name="ruleset" parser=["custom.pmnull.withOrigin", "rsyslog.pmnull"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test") } ' startup tcpflood -m1 -M "\"<189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\"" shutdown_when_empty wait_shutdown echo 'tag: , pri: 13, syslogfacility: 1, syslogseverity: 5 msg: <189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/msleep_usage_output.sh0000644000000000000000000000013215035412264020330 xustar0030 mtime=1752569012.402736851 30 atime=1782715518.902790778 30 ctime=1787067804.016904351 rsyslog-8.2608.0/tests/msleep_usage_output.sh0000777000175000017500000000042115035412264017776 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./msleep &> $RSYSLOG_DYNNAME.output grep "usage: msleep" $RSYSLOG_DYNNAME.output if [ ! $? -eq 0 ]; then echo "invalid response generated" error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-rule_and_rulebase.sh0000644000000000000000000000013215035412264022245 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.902790778 30 ctime=1787067807.058961037 rsyslog-8.2608.0/tests/pmnormalize-rule_and_rulebase.sh0000777000175000017500000000064615035412264021724 0ustar00rgerrger#!/bin/bash # add 2019-04-10 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/pmnormalize/.libs/pmnormalize") parser(name="custom.pmnormalize" type="pmnormalize" rule="" rulebase="") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "pmnormalize:.*you need to specify one of" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-empty-template.sh0000644000000000000000000000013215241075234020510 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067806.076942738 rsyslog-8.2608.0/tests/omprog-empty-template.sh0000775000175000017500000000143115241075234020156 0ustar00rgerrger#!/bin/bash # Regression coverage for empty rendered templates reaching omprog. The # stimulus is a real action invocation whose configured string template renders # to the empty C string. The oracle is rsyslogd's proper-termination marker: # before the guard in omprog, ASan reports a one-byte under-read in the # trailing-LF check and rsyslogd aborts before writing this marker. . ${srcdir:=.}/diag.sh init set_proper_termination_file generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="empty" type="string" string="") if $rawmsg contains "trigger-empty-template" then { action(type="omprog" binary="/bin/cat" template="empty") } ' startup injectmsg_literal 'trigger-empty-template' shutdown_when_empty wait_shutdown check_proper_termination exit_test rsyslog-8.2608.0/tests/PaxHeaders/omusrmsg-noabort.sh0000644000000000000000000000013215131231047017550 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.902790778 30 ctime=1787067804.174907295 rsyslog-8.2608.0/tests/omusrmsg-noabort.sh0000777000175000017500000000131315131231047017217 0ustar00rgerrger#!/bin/bash # same as omusrmsg-noabort, but with legacy syntax. # addd 2018-08-05 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { action(type="omusrmsg" users="nouser" template="outfmt") action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup injectmsg shutdown_when_empty wait_shutdown # while we cannot check if the messages arrived in user sessions, we # can check that all messages arrive in the file, which we consider as # an indication that everything went well. seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-numstr-vg.sh0000644000000000000000000000013215171370365023011 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.903790795 30 ctime=1787067805.253927402 rsyslog-8.2608.0/tests/rscript_compare_numstr-numstr-vg.sh0000775000175000017500000000017615171370365022464 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='"2"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/dynstats_reset-vg.sh0000644000000000000000000000013215131231047017717 xustar0030 mtime=1768239655.701212533 30 atime=1782715518.902790778 30 ctime=1787067806.750955298 rsyslog-8.2608.0/tests/dynstats_reset-vg.sh0000777000175000017500000000443315131231047017374 0ustar00rgerrger#!/bin/bash # added 2015-11-13 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[dynstats_reset-vg.sh\]: test for gathering stats with a known-dyn-metrics reset in-between . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on") template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n") dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off") set $.msg_prefix = field($msg, 32, 1); if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then { set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix); } else { set $.increment_successful = -1; } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log injectmsg_file $srcdir/testsuites/dynstats_input_1 rst_msleep 8100 #two seconds for unused-metrics to be kept under observation, another two them to be cleared off injectmsg_file $srcdir/testsuites/dynstats_input_2 rst_msleep 8100 injectmsg_file $srcdir/testsuites/dynstats_input_3 rst_msleep 8100 wait_queueempty content_check "foo 001 0" content_check "bar 002 0" content_check "baz 003 0" content_check "foo 004 0" content_check "baz 005 0" content_check "foo 006 0" echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg # because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that custom_assert_content_missing 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing 'foo=2' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log" # but actual reported stats (aggregate) should match first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1 first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2 exit_test rsyslog-8.2608.0/tests/PaxHeaders/incltest_dir_empty_wildcard.sh0000644000000000000000000000013215217451052022011 xustar0030 mtime=1782469162.532510767 30 atime=1782715518.902790778 30 ctime=1787067804.950921756 rsyslog-8.2608.0/tests/incltest_dir_empty_wildcard.sh0000775000175000017500000000206615217451052021464 0ustar00rgerrger#!/bin/bash # Verify that a non-optional $IncludeConfig wildcard that matches no files is # accepted silently. The oracle is successful config validation and runtime # message processing, with no include no-match, warning, or error diagnostic in # the captured rsyslogd output. . ${srcdir:=.}/diag.sh init generate_conf add_conf "\$IncludeConfig ${srcdir}/testsuites/incltest.d/*.conf-not-there " add_conf 'global(compatibility.defaults.secure="strict") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt")' DIAG_LOG="${RSYSLOG_DYNNAME}.rsyslog.log" : > "$DIAG_LOG" export RS_REDIR=">>\"$DIAG_LOG\" 2>&1" rsyslogd_config_check startup unset RS_REDIR # 100 messages are enough - the question is if the include is read ;) injectmsg 0 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown check_not_present "IncludeConfig pattern" "$DIAG_LOG" check_not_present "[Ww][Aa][Rr][Nn]" "$DIAG_LOG" check_not_present "[Ee][Rr][Rr][Oo][Rr]" "$DIAG_LOG" seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_no_params-vg.sh0000644000000000000000000000013215171370365023140 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.903790795 30 ctime=1787067808.129980995 rsyslog-8.2608.0/tests/imbatchreport_errmsg_no_params-vg.sh0000775000175000017500000000023215171370365022604 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/imbatchreport_errmsg_no_params.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-tcp-spill-exact.sh0000644000000000000000000000013215241075234021604 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.817900643 rsyslog-8.2608.0/tests/segmented-da-tcp-spill-exact.sh0000775000175000017500000000733515241075234021263 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Verify a segmented disk-assisted LinkedList main queue under TCP # backpressure. Four tcpflood generators send 10,000 independently numbered # records through imtcp. minitcpsrv opens the omfwd listener but delays reads # until the segmented DA child state file exists. That state file is the spill # oracle: it proves the child materialized before output is allowed to drain. # The standard sequence checker rejects loss, duplicates, and malformed # framing. This is a functionality regression test; it has no throughput or # elapsed-time oracle. . ${srcdir:=.}/diag.sh init NUMMESSAGES=10000 TCP_CONNECTIONS=4 PAYLOAD_BYTES=4096 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" RECEIVER_FILE="$PWD/${RSYSLOG_DYNNAME}.receiver" RECEIVER_PORT_FILE="$PWD/${RSYSLOG_DYNNAME}.receiver.port" RECEIVER_READY_FILE="$PWD/${RSYSLOG_DYNNAME}.receiver.ready" RECEIVER_RELEASE_FILE="$PWD/${RSYSLOG_DYNNAME}.receiver.release" RECEIVER_KEEP_FILE="$PWD/${RSYSLOG_DYNNAME}.receiver.keep" INPUT_PORT_FILE="$PWD/${RSYSLOG_DYNNAME}.input.port" SENDER_MARKER="$PWD/${RSYSLOG_DYNNAME}.sender.marker" rm -rf "$SPOOL_DIR" rm -f "$INPUT_PORT_FILE" "$SENDER_MARKER" "$RECEIVER_FILE" "$RECEIVER_PORT_FILE" "$RECEIVER_READY_FILE" "$RECEIVER_RELEASE_FILE" "$RECEIVER_KEEP_FILE" mkdir -p "$SPOOL_DIR" || error_exit 1 "cannot create spool directory" : >"$RECEIVER_KEEP_FILE" ./minitcpsrv -t127.0.0.1 -p0 -P "$RECEIVER_PORT_FILE" -L "$RECEIVER_READY_FILE" \ -Q "$RECEIVER_RELEASE_FILE" -K "$RECEIVER_KEEP_FILE" -f "$RECEIVER_FILE" & RECEIVER_PID=$! wait_file_exists "$RECEIVER_READY_FILE" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") global(workDirectory="'"$SPOOL_DIR"'") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$INPUT_PORT_FILE"'" workerthreads="4") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.size="400" queue.highWatermark="320" queue.lowWatermark="80" queue.fullDelayMark="400" queue.maxFileSize="64m" queue.maxDiskSpace="2g" queue.workerThreads="4" queue.workerThreadMinimumMessages="1" queue.dequeueBatchSize="1" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="-1" queue.checkpointInterval="0" queue.syncQueueFiles="off") template(name="tcpSpillFormat" type="string" string="%msg%\n") if ($msg contains "msgnum:") then action(type="omfwd" target="127.0.0.1" port="'"$(cat "$RECEIVER_PORT_FILE")"'" protocol="tcp" template="tcpSpillFormat") ' startup wait_file_exists "$INPUT_PORT_FILE" ./tcpflood -p"$(cat "$INPUT_PORT_FILE")" -c"$TCP_CONNECTIONS" -Y -m"$NUMMESSAGES" -d"$PAYLOAD_BYTES" -q "$SENDER_MARKER" & SENDER_PID=$! deadline=$((SECONDS + 60)) while [ ! -e "$SPOOL_DIR/mainq.segq/state" ]; do # This bounded wait is a liveness ceiling, not a performance assertion. # Output remains blocked until state proves the DA child was used. [ "$SECONDS" -lt "$deadline" ] || error_exit 1 "segmented DA child did not materialize" ./msleep 25 done touch "$RECEIVER_RELEASE_FILE" wait "$SENDER_PID" if [ $? -ne 0 ] || ! tcpflood_marker_is_valid "$SENDER_MARKER"; then print_tcpflood_marker_file "$SENDER_MARKER" error_exit 1 "tcpflood did not complete cleanly" fi wait_queueempty # Main-queue emptiness may precede completion of batches already owned by DA # child workers. Shutdown is the downstream completion barrier and also closes # omfwd's TCP stream, allowing the receiver to consume the final records. shutdown_when_empty wait_shutdown wait_file_lines --abort-on-oversize "$RECEIVER_FILE" "$NUMMESSAGES" 120 rm -f "$RECEIVER_KEEP_FILE" wait "$RECEIVER_PID" || error_exit 1 "minitcpsrv did not exit cleanly" cut -d: -f2 "$RECEIVER_FILE" >"$RSYSLOG_OUT_LOG" seq_check 0 $((NUMMESSAGES - 1)) rm -rf "$SPOOL_DIR" exit_test rsyslog-8.2608.0/tests/PaxHeaders/failover-rptd-vg.sh0000644000000000000000000000013215035412264017427 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.903790795 30 ctime=1787067805.204926489 rsyslog-8.2608.0/tests/failover-rptd-vg.sh0000777000175000017500000000140615035412264017101 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi echo =============================================================================== echo \[failover-rptd.sh\]: rptd test for failover functionality . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $RepeatedMsgReduction on $template outfmt,"%msg:F,58:2%\n" # note: the target server shall not be available! :msg, contains, "msgnum:" @@127.0.0.1:13514 $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"';outfmt ' startup_vg injectmsg 0 5000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_str2num_negative.sh0000644000000000000000000000013115241075234021301 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.793581814 30 ctime=1787067804.889920619 rsyslog-8.2608.0/tests/rscript_str2num_negative.sh0000775000175000017500000000125115241075234020750 0ustar00rgerrger#!/bin/bash # add 2017-02-09 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.n = "-1"; set $!ip!v1 = 1 + $.n; template(name="outfmt" type="string" string="%!ip%\n") local4.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m1 shutdown_when_empty wait_shutdown echo '{ "v1": 0 }' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid function output detected, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_traillf_syssock.sh0000644000000000000000000000013215145046113021372 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.904790812 30 ctime=1787067804.686916836 rsyslog-8.2608.0/tests/imuxsock_traillf_syssock.sh0000775000175000017500000000142015145046113021036 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test does not work on Solaris" ./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" SysSock.name="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup ./syslog_caller -fsyslog_inject-l -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" shutdown_when_empty wait_shutdown export EXPECTED=" test" cmp_exact rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-module-mtls.sh0000644000000000000000000000013215241075234022472 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.611971342 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-module-mtls.sh0000775000175000017500000002007715241075234022147 0ustar00rgerrger#!/bin/bash # Verify that builtin:omfwd module defaults can supply PKCS#11-backed TLS # objects for an omfwd action that omits action-level StreamDriver.CAFile, # StreamDriver.CAExtraFiles, StreamDriver.CertFile, and StreamDriver.KeyFile. # The server certificate is signed by an intermediate CA that is intentionally # not sent by the helper server, so the client handshake succeeds only if # omfwd loads the root CA via StreamDriver.CAFile and the missing intermediate # via StreamDriver.CAExtraFiles. The oracle is that the OpenSSL helper, which # also requires a valid client certificate, captures exactly one forwarded # payload line. All PKCS#11 state is created inside a per-test directory so # parallel runs do not collide. . ${srcdir:=.}/diag.sh init check_command_available openssl check_command_available softhsm2-util check_command_available pkcs11-tool if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi find_first_existing() { for candidate in "$@"; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } workdir="$RSYSLOG_DYNNAME.omfwd-tls-ossl-pkcs11-module-mtls" port_file="$workdir/server.port" server_capture="$workdir/server.capture" server_stderr="$workdir/server.stderr" softhsm_conf="$workdir/softhsm2.conf" openssl_conf="$workdir/openssl-pkcs11.cnf" token_dir="$workdir/tokens" token_label="rsyslog-test-token" token_pin="123456" token_so_pin="12345678" mkdir -p "$workdir" "$token_dir" provider_module=$(find_first_existing \ /usr/lib64/ossl-modules/pkcs11.so \ /usr/lib/ossl-modules/pkcs11.so \ /usr/lib/x86_64-linux-gnu/ossl-modules/pkcs11.so \ /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so \ /usr/local/lib64/ossl-modules/pkcs11.so \ /usr/local/lib/ossl-modules/pkcs11.so) || { printf 'info: skipping test - pkcs11 OpenSSL provider module not found\n' skip_test } softhsm_module=$(find_first_existing \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/pkcs11/libsofthsm2.so \ /usr/lib64/softhsm/libsofthsm2.so \ /usr/lib/softhsm/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib64/libsofthsm2.so \ /usr/lib/libsofthsm2.so) || { printf 'info: skipping test - SoftHSM PKCS#11 module not found\n' skip_test } cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints=critical,CA:TRUE,pathlen:1 keyUsage=critical,keyCertSign,cRLSign subjectKeyIdentifier=hash EOF cat >"$workdir/intermediate.ext" <<'EOF' basicConstraints=critical,CA:TRUE,pathlen:0 keyUsage=critical,keyCertSign,cRLSign subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer EOF openssl genrsa -out "$workdir/ca.key" 2048 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/intermediate.key" 2048 || error_exit 1 openssl req -new -key "$workdir/intermediate.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Intermediate-CA" \ -out "$workdir/intermediate.csr" || error_exit 1 openssl x509 -req -in "$workdir/intermediate.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/intermediate.ext" \ -out "$workdir/intermediate.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 2048 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/intermediate.pem" -CAkey "$workdir/intermediate.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 2048 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 openssl x509 -in "$workdir/ca.pem" -outform DER -out "$workdir/ca.der" || error_exit 1 openssl x509 -in "$workdir/intermediate.pem" -outform DER -out "$workdir/intermediate.der" || error_exit 1 openssl x509 -in "$workdir/client.pem" -outform DER -out "$workdir/client.der" || error_exit 1 openssl pkey -in "$workdir/client.key" -pubout -outform DER -out "$workdir/client.pub.der" || \ error_exit 1 cat >"$softhsm_conf" <"$openssl_conf" <"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf ' global( compatibility.defaults.secure="strict" net.ipprotocol="ipv4-only" ) module( load="builtin:omfwd" StreamDriver.CAFile="'$ca_uri'" StreamDriver.CAExtraFiles="'$extra_ca_uri'" StreamDriver.CertFile="'$cert_uri'" StreamDriver.KeyFile="'$key_uri'" ) template(name="outfmt" type="string" string="%msg%\n") if $msg contains "omfwd-ossl-pkcs11-module-mtls" then { action( type="omfwd" target="127.0.0.1" protocol="tcp" port="'$server_port'" template="outfmt" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) } ' startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - omfwd-ossl-pkcs11-module-mtls' wait_file_lines "$server_capture" 1 shutdown_when_empty wait_shutdown wait $server_pid || { cat "$server_stderr" error_exit 1 } content_count_check --regex '^omfwd-ossl-pkcs11-module-mtls$' 1 "$server_capture" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbeats-resource-budget.sh0000644000000000000000000000013215241075234020761 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.683579755 30 ctime=1787067806.484950341 rsyslog-8.2608.0/tests/imbeats-resource-budget.sh0000775000175000017500000001323215241075234020431 0ustar00rgerrger#!/bin/bash # Exercise imbeats' listener-wide in-flight budget and compression-ratio cap. # One connection declares an incomplete 6144-byte JSON body under an 8192-byte # aggregate budget. Bounded retries wait until a second 4096-byte reservation is # rejected by peer close (never ACK); this avoids assuming when the worker has # consumed the first header. Closing the holder must release its reservation, # proven by a legitimate direct event receiving an ACK within the same bounded # retry window. A high-ratio compressed frame must also close without an ACK, # while a low-ratio compressed control remains accepted. Five seconds permits # loaded CI scheduling without turning silence/timeouts into a passing oracle. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" interval="1" log.file="'$RSYSLOG_DYNNAME'.spool/imbeats-stats.log" log.syslog="off" format="cee") module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main" workerThreads="1" maxInFlightBytes="8192" maxCompressionRatio="4") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" if ! $PYTHON - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import select import socket import struct import sys import time import zlib port = int(sys.argv[1]) ack1 = b"2A" + struct.pack(">I", 1) def window(frame): return b"2W" + struct.pack(">I", 1) + frame def json_frame(payload, seq=1): return b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload def declared_json(length, partial=b""): return b"2J" + struct.pack(">I", 1) + struct.pack(">I", length) + partial def peer_closed(sock, timeout): readable, _, _ = select.select([sock], [], [], timeout) if not readable: return False try: return sock.recv(6) == b"" except (ConnectionResetError, BrokenPipeError): return True def retry_until_ack(frame, deadline): last = b"" while time.monotonic() < deadline: with socket.create_connection(("127.0.0.1", port), timeout=2) as sock: sock.settimeout(1) sock.sendall(window(frame)) try: last = sock.recv(6) except (ConnectionResetError, BrokenPipeError, socket.timeout): last = b"" if last == ack1: return last select.select([], [], [], 0.05) raise SystemExit(f"legitimate frame was not ACKed after budget release; last={last.hex()}") holder = socket.create_connection(("127.0.0.1", port), timeout=5) holder.settimeout(2) try: holder.sendall(window(declared_json(6144, b"{"))) # Admission and parsing are asynchronous. Retry the competing reservation # until the server's close proves the holder has been charged. deadline = time.monotonic() + 5 rejected = False while time.monotonic() < deadline and not rejected: with socket.create_connection(("127.0.0.1", port), timeout=2) as contender: contender.sendall(window(declared_json(4096, b"{"))) rejected = peer_closed(contender, 0.25) if not rejected: select.select([], [], [], 0.05) if not rejected: raise SystemExit("aggregate in-flight budget did not reject a competing reservation") finally: holder.close() direct = json.dumps({"message": "budget-released"}, separators=(",", ":")).encode() direct_ack = retry_until_ack(json_frame(direct), time.monotonic() + 5) high = json_frame(json.dumps({"message": "x" * 400}, separators=(",", ":")).encode()) high_compressed = zlib.compress(high) if len(high) <= 4 * len(high_compressed): raise SystemExit("test bug: high-ratio fixture does not exceed configured ratio") with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.sendall(window(b"2C" + struct.pack(">I", len(high_compressed)) + high_compressed)) if not peer_closed(sock, 5): raise SystemExit("high-ratio compressed frame was not rejected by peer close") normal = json_frame( json.dumps({"message": "compressed-control-0123456789abcdef"}, separators=(",", ":")).encode() ) normal_compressed = zlib.compress(normal) if len(normal) > 4 * len(normal_compressed): raise SystemExit("test bug: normal compressed fixture exceeds configured ratio") compressed_ack = retry_until_ack( b"2C" + struct.pack(">I", len(normal_compressed)) + normal_compressed, time.monotonic() + 5, ) print(direct_ack.hex()) print(compressed_ack.hex()) PY then error_exit 1 fi rst_msleep 1500 shutdown_when_empty wait_shutdown EXPECTED='{"message":"budget-released"} {"message":"compressed-control-0123456789abcdef"}' cmp_exact EXPECTED_ACK='324100000001 324100000001' export EXPECTED="$EXPECTED_ACK" cmp_exact "$RSYSLOG_DYNNAME.imbeats.ack" if ! $PYTHON - "$RSYSLOG_DYNNAME.spool/imbeats-stats.log" <<'PY' import json import sys stats = {} with open(sys.argv[1], encoding="utf-8") as fh: for line in fh: if "@cee: " in line: data = json.loads(line.split("@cee: ", 1)[1]) if data.get("name") == "imbeats": stats = data if stats.get("resource_bytes") != 0: raise SystemExit(f"resource accounting did not return to zero: {stats}") if stats.get("resource_rejected", 0) < 1: raise SystemExit(f"resource rejection counter did not advance: {stats}") if stats.get("protocol_errors") != 1: raise SystemExit(f"resource rejection was misclassified as a protocol error: {stats}") PY then error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_re_extract_loop.sh0000644000000000000000000000013015241075234021175 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 29 ctime=1787067804.79391883 rsyslog-8.2608.0/tests/rscript_re_extract_loop.sh0000775000175000017500000000220215241075234020642 0ustar00rgerrger#!/bin/bash # Test re_extract behavior with empty matches to prevent infinite loops/stuck behavior echo =============================================================================== echo \[rscript_re_extract_loop.sh\]: test re_extract empty match loop . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="*Result: %$.res%*\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")' # Regex: a? # Input: " a" (space then a) # Match 0: "" (at start, before space) # Match 1: "a" (after space) # We want Match 1. add_conf " set \$.res = re_extract(\$msg, 'a?', 1, 0, 'fail');" add_conf ' action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" startup # Send proper syslog message so $msg is populated # Double quoting for eval in diag.sh tcpflood -m 1 -M '"<166>Jan 1 00:00:00 localhost tag: a"' echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "*Result: a*" exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse3.sh0000644000000000000000000000013215241075234017627 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.787581702 30 ctime=1787067805.024923135 rsyslog-8.2608.0/tests/parsertest-parse3.sh0000775000175000017500000000217015241075234017276 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9]+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<175>Oct 16 2009 23:47:31 hostname tag This is a message\"" tcpflood -m1 -M "\"<175>Oct 16 2009 23:47:31 hostname tag[1234] This is a message\"" shutdown_when_empty wait_shutdown echo '"2009-10-16T23:47:31", "hostname", "tag", "", "7", " This is a message" "2009-10-16T23:47:31", "hostname", "tag", "1234", "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-basic-verifydepth.sh0000644000000000000000000000013015241075234021560 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.774581459 29 ctime=1787067807.28396523 rsyslog-8.2608.0/tests/imtcp-tls-basic-verifydepth.sh0000775000175000017500000000202415241075234021227 0ustar00rgerrger#!/bin/bash # added 2011-02-28 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.TlsVerifyDepth="5" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # Begin actual testcase startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmutf8fix_no_error.sh0000644000000000000000000000013115241075234020073 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067805.674935247 rsyslog-8.2608.0/tests/mmutf8fix_no_error.sh0000775000175000017500000001411715241075234017547 0ustar00rgerrger#!/bin/bash # add 2018-10-10 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmutf8fix/.libs/mmutf8fix") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmutf8fix" replacementChar="?") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: this is a test message <129>Mar 10 01:00:00 172.20.245.8 tag: valid mixed length UTF-8: foo bar řÃꙀ䆑ð�Œ°ð�ž¨ <129>Mar 10 01:00:00 172.20.245.8 tag: valid 2-byte UTF-8: řà <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x00) 0xC0 0x80: À€ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x2E) 0xC0 0xAE: À® <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong = 0x4E) 0xC1 0x8E: ÁŽ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation) 0xC0 0xEE: Àî <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0x2E: À. <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0xC2 0xA7: À§ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (overlong, not enough bytes) 0xC0: À <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation) 0xC2 0xEE: Âî <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0x2E: Â. <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0xC2 0xA7: § <129>Mar 10 01:00:00 172.20.245.8 tag: valid 3-byte UTF-8: Ꙁ䆑 <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (overlong = 0x2E) 0xE0 0x80 0xAE: à€® <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (overlong = 0x2E0) 0xE0 0x8B 0xA0: à‹  <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation) 0xE0 0xE2 0x81: àâ� <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0x41 0xA7: àA§ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0xC2 0xA7: à§ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation) 0xE1 0x85 0xE1: á…á <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0x41: á…A <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0xD5 0xB6: á…Õ¶ <129>Mar 10 01:00:00 172.20.245.8 tag: valid 4-byte UTF-8: ð�Œ°ð�ž¨ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E) 0xF0 0x80 0x80 0xAE: ð€€® <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E0) 0xF0 0x80 0x8B 0xA0: ð€‹  <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (overlong = 0x2E00) 0xF0 0x82 0xB8 0x80: ð‚¸€ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0x41 0xC5 0xB0: ðAŰ <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0xEC 0x8C 0xB0: ð쌰 <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xF0 0x90 0xC5 0xB0: ð�Ű <129>Mar 10 01:00:00 172.20.245.8 tag: invalid 4-byte UTF-8 (invalid 4rd continuation but valid utf8) 0xF0 0x90 0xC5 0x2E: ð�Œ. <129>Mar 10 01:00:00 172.20.245.8 tag: special characters: ??%%,,.. <129>Mar 10 01:00:00 172.20.245.8 tag: numbers: 1234567890\"" shutdown_when_empty wait_shutdown echo ' this is a test message valid mixed length UTF-8: foo bar řÃꙀ䆑ð�Œ°ð�ž¨ valid 2-byte UTF-8: řà invalid 2-byte UTF-8 (overlong = 0x00) 0xC0 0x80: ?? invalid 2-byte UTF-8 (overlong = 0x2E) 0xC0 0xAE: ?? invalid 2-byte UTF-8 (overlong = 0x4E) 0xC1 0x8E: ?? invalid 2-byte UTF-8 (overlong, invalid continuation) 0xC0 0xEE: ?? invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0x2E: ?. invalid 2-byte UTF-8 (overlong, invalid continuation but valid utf8) 0xC0 0xC2 0xA7: ?§ invalid 2-byte UTF-8 (overlong, not enough bytes) 0xC0: ? invalid 2-byte UTF-8 (invalid continuation) 0xC2 0xEE: ?? invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0x2E: ?. invalid 2-byte UTF-8 (invalid continuation but valid utf8) 0xC2 0xC2 0xA7: ?§ valid 3-byte UTF-8: Ꙁ䆑 invalid 3-byte UTF-8 (overlong = 0x2E) 0xE0 0x80 0xAE: ??? invalid 3-byte UTF-8 (overlong = 0x2E0) 0xE0 0x8B 0xA0: ??? invalid 3-byte UTF-8 (invalid 2nd continuation) 0xE0 0xE2 0x81: ??? invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0x41 0xA7: ?A? invalid 3-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xE0 0xC2 0xA7: ?§ invalid 3-byte UTF-8 (invalid 3rd continuation) 0xE1 0x85 0xE1: ??? invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0x41: ??A invalid 3-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xE1 0x85 0xD5 0xB6: ??Õ¶ valid 4-byte UTF-8: ð�Œ°ð�ž¨ invalid 4-byte UTF-8 (overlong = 0x2E) 0xF0 0x80 0x80 0xAE: ???? invalid 4-byte UTF-8 (overlong = 0x2E0) 0xF0 0x80 0x8B 0xA0: ???? invalid 4-byte UTF-8 (overlong = 0x2E00) 0xF0 0x82 0xB8 0x80: ???? invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0x41 0xC5 0xB0: ?AŰ invalid 4-byte UTF-8 (invalid 2nd continuation but valid utf8) 0xF0 0xEC 0x8C 0xB0: ?쌰 invalid 4-byte UTF-8 (invalid 3rd continuation but valid utf8) 0xF0 0x90 0xC5 0xB0: ??Ű invalid 4-byte UTF-8 (invalid 4rd continuation but valid utf8) 0xF0 0x90 0xC5 0x2E: ???. special characters: ??%%,,.. numbers: 1234567890' > "$RSYSLOG_OUT_LOG.expect" if ! cmp "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG; then echo "invalid response generated, $RSYSLOG_OUT_LOG diff:" # Use LANG=C for binary matching LANG=C diff --text -u "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test exit 0 rsyslog-8.2608.0/tests/PaxHeaders/imfile-file-not-found-error.sh0000644000000000000000000000013215035412264021457 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.903790795 30 ctime=1787067807.882976392 rsyslog-8.2608.0/tests/imfile-file-not-found-error.sh0000777000175000017500000000223115035412264021126 0ustar00rgerrger#!/bin/bash # add 2017-04-28 by Pascal Withopf, released under ASL 2.0 echo [imfile-file-not-found-error.sh] . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="tag1" ruleset="ruleset1") template(name="tmpl1" type="string" string="%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="tmpl1") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) ' startup ./msleep 2000 echo 'testmessage1 testmessage2 testmessage3' > $RSYSLOG_DYNNAME.input ./msleep 2000 shutdown_when_empty wait_shutdown grep "file.*$RSYSLOG_DYNNAME.input.*No such file or directory" ${RSYSLOG2_OUT_LOG} > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi printf 'testmessage1 testmessage2 testmessage3\n' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-checkpoint-5.sh0000644000000000000000000000013115241075234022476 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 29 ctime=1787067803.78289999 rsyslog-8.2608.0/tests/segmented-diskqueue-checkpoint-5.sh0000775000175000017500000000033215241075234022144 0ustar00rgerrger#!/bin/bash # Verify checkpointInterval=5 counts records and publishes after each five. export CHECKPOINT_INTERVAL=5 export EXPECTED_PERIODIC_WRITES=2 . ${srcdir:=.}/testsuites/segmented-diskqueue-checkpoint-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_privdropgroupid.sh0000644000000000000000000000013215131231047021237 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.902790778 30 ctime=1787067804.226908264 rsyslog-8.2608.0/tests/rscript_privdropgroupid.sh0000777000175000017500000000117015131231047020707 0ustar00rgerrger#!/bin/bash # added 2021-09-23 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.group.keepsupplemental="on" privdrop.group.id="'${TESTBENCH_TESTUSER[gid]}'") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbeats-maxsessions.sh0000644000000000000000000000013215241075234020236 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.768581346 30 ctime=1787067806.461949913 rsyslog-8.2608.0/tests/imbeats-maxsessions.sh0000775000175000017500000000441715241075234017713 0ustar00rgerrger#!/bin/bash # Verify maxSessions rejects excess peers and releases admission capacity after # an established session closes. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main" maxSessions="2") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" if ! $PYTHON - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys port = int(sys.argv[1]) def event_wire(seq, message): payload = json.dumps({"message": message}, separators=(",", ":")).encode() return ( b"2W" + struct.pack(">I", 1) + b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload ) sockets = [] try: for _ in range(2): sock = socket.create_connection(("127.0.0.1", port), timeout=5) sock.settimeout(5) sockets.append(sock) try: extra = socket.create_connection(("127.0.0.1", port), timeout=5) except OSError: extra = None if extra is not None: with extra: extra.settimeout(2) extra.sendall(event_wire(99, "rejected")) try: data = extra.recv(6) except (ConnectionResetError, TimeoutError, socket.timeout): data = b"" if data: raise SystemExit(f"unexpected ack from over-limit session: {data.hex()}") acks = [] for idx, sock in enumerate(sockets, start=1): sock.sendall(event_wire(1, f"accepted-{idx}")) acks.append(sock.recv(6).hex()) print("\n".join(acks)) finally: for sock in sockets: try: sock.close() except OSError: pass PY then error_exit 1 fi shutdown_when_empty wait_shutdown # shellcheck disable=SC2034 EXPECTED='{"message":"accepted-1"} {"message":"accepted-2"}' cmp_exact grep -Fx "324100000001" "$RSYSLOG_DYNNAME.imbeats.ack" >/dev/null || error_exit 1 test "$(grep -Fx "324100000001" "$RSYSLOG_DYNNAME.imbeats.ack" | wc -l)" -eq 2 || error_exit 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/config-translate-legacy-file-action.sh0000644000000000000000000000013215171370365023137 xustar0030 mtime=1776677109.457913326 30 atime=1782715518.905790829 30 ctime=1787067805.334928911 rsyslog-8.2608.0/tests/config-translate-legacy-file-action.sh0000775000175000017500000000207015171370365022605 0ustar00rgerrger#!/bin/bash # check translation of traditional file action shorthand into YAML filter/actions. # # Many distros still ship defaults like: # user.* -/var/log/user.log # so translation coverage for this legacy form is important. # # Part of the testbench for rsyslog. # # This file is part of rsyslog. # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init modpath="../runtime/.libs:../.libs" cat > "${RSYSLOG_DYNNAME}.conf" <<'RS_EOF' user.* -/var/log/user.log RS_EOF ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F yaml -o "${RSYSLOG_DYNNAME}.yaml" -M"$modpath" || error_exit $? cat -n "${RSYSLOG_DYNNAME}.yaml" cat > "${RSYSLOG_DYNNAME}.expected.yaml" <<'YAML_EOF' version: 2 rulesets: # TRANSLATION WARNING: top-level statements normalized into explicit RSYSLOG_DefaultRuleset - name: "RSYSLOG_DefaultRuleset" filter: "user.*" actions: - type: "omfile" file: "/var/log/user.log" YAML_EOF cmp_exact_file "${RSYSLOG_DYNNAME}.expected.yaml" "${RSYSLOG_DYNNAME}.yaml" echo SUCCESS: legacy file-action shorthand translation coverage exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-queue-vg.sh0000644000000000000000000000013215171370365017756 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.905790829 30 ctime=1787067806.566951869 rsyslog-8.2608.0/tests/imhiredis-queue-vg.sh0000775000175000017500000000027315171370365017427 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-queue.sh rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-large.sh0000644000000000000000000000013215216464436021257 xustar0030 mtime=1782212894.057266685 30 atime=1782715518.904790812 30 ctime=1787067806.384948478 rsyslog-8.2608.0/tests/imhttp-post-payload-large.sh0000775000175000017500000000264415216464436020734 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify this imhttp POST-payload variant while the HTTP listener uses an # OS-assigned port. The HTTP status and configured output checks are the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' #template(name="outfmt" type="string" string="%msg%\n") template(name="outfmt" type="string" string="%rawmsg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" NUMMESSAGES=25 DATA_SOURCE=$srcdir/testsuites/imhttp-large-data.txt for (( i=1; i<=NUMMESSAGES; i++ )) do curl -si -X POST -H Content-Type:application/json http://localhost:$IMHTTP_PORT/postrequest --data-binary @$DATA_SOURCE & pids[${i}]=$! done # wait for all pids for pid in ${pids[*]}; do wait $pid # echo "$pid cleaned up" done sleep 2 wait_queueempty echo "doing shutdown" shutdown_when_empty wait_shutdown # reference file for comparison TMPFILE=${RSYSLOG_DYNNAME}.tmp for (( i=1; i <= NUMMESSAGES; i++ )) do cat $DATA_SOURCE >> $TMPFILE done if diff -q $TMPFILE $RSYSLOG_OUT_LOG; then echo "files match!" exit_test else error_exit 1 fi rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh0000644000000000000000000000013215216464436025176 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.905790829 30 ctime=1787067807.640971883 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_serveranon_gtls_clientanon.sh0000775000175000017500000000354315216464436024652 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-basic-hup.sh0000644000000000000000000000013215035412264017404 xustar0030 mtime=1752569012.394792439 30 atime=1782715518.905790829 30 ctime=1787067806.822956639 rsyslog-8.2608.0/tests/imptcp-basic-hup.sh0000777000175000017500000000131315035412264017053 0ustar00rgerrger#!/bin/bash # added 2019-07-30 by RGerhards, released under ASL 2.0 export NUMMESSAGES=4000 # MUST be an even number! . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) issue_HUP tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2)) shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_stop2.sh0000644000000000000000000000013215035412264017054 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.904790812 30 ctime=1787067804.747917973 rsyslog-8.2608.0/tests/rscript_stop2.sh0000777000175000017500000000166515035412264016535 0ustar00rgerrger#!/bin/bash # added 2012-09-20 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_stop2.sh\]: testing rainerscript STOP statement, alternate method . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } if not ($msg contains "msgnum") then stop set $!usr!msgnum = field($msg, 58, 2); if cnum($!usr!msgnum) >= 5000 then stop /* We could use yet another method, but we like to have the action statement * without a filter in rsyslog.conf top level hierarchy - so this test, as * a side-effect, also tests this ability. */ action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg 0 8000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-basic-vg.sh0000644000000000000000000000013215171370365017251 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.904790812 30 ctime=1787067806.173944546 rsyslog-8.2608.0/tests/omhttp-basic-vg.sh0000775000175000017500000000010515171370365016714 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_object.sh0000644000000000000000000000013215241075234021334 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 30 ctime=1787067806.897958037 rsyslog-8.2608.0/tests/rscript_unflatten_object.sh0000775000175000017500000000270715241075234021011 0ustar00rgerrger#!/bin/bash # added 2020-08-16 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $!source.ip = "1.2.3.4"; set $!source.bytes = 3258; set $!source.geo.country_iso_code = "FR"; set $!destination.ip = "4.3.2.1"; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 3 wait_file_lines "$RSYSLOG_OUT_LOG" 3 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } } msgnum:00000001: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } } msgnum:00000002: 0 { "source": { "ip": "1.2.3.4", "bytes": 3258, "geo": { "country_iso_code": "FR" } }, "destination": { "ip": "4.3.2.1" } }' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/multiple_lookup_tables-vg.sh0000644000000000000000000000013215171370365021435 xustar0030 mtime=1776677109.465913449 30 atime=1782715518.904790812 30 ctime=1787067805.292928129 rsyslog-8.2608.0/tests/multiple_lookup_tables-vg.sh0000775000175000017500000000026715171370365021111 0ustar00rgerrger#!/bin/bash # added 2016-01-20 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/multiple_lookup_tables.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-module-precedence-vg.sh0000644000000000000000000000013115241075234024221 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 29 ctime=1787067807.57697069 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-module-precedence-vg.sh0000775000175000017500000000014015241075234023664 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-module-precedence.sh rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-env.sh0000644000000000000000000000013215171370365017171 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.904790812 30 ctime=1787067806.320947285 rsyslog-8.2608.0/tests/omazuredce-env.sh0000775000175000017500000000432215171370365016641 0ustar00rgerrger#!/bin/bash omazuredce_require_env() { if [[ -z "${AZURE_DCE_CLIENT_ID}" ]]; then echo "SKIP: AZURE_DCE_CLIENT_ID environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AZURE_DCE_CLIENT_SECRET}" ]]; then echo "SKIP: AZURE_DCE_CLIENT_SECRET environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AZURE_DCE_TENANT_ID}" ]]; then echo "SKIP: AZURE_DCE_TENANT_ID environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AZURE_DCE_URL}" ]]; then echo "SKIP: AZURE_DCE_URL environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AZURE_DCE_DCR_ID}" ]]; then echo "SKIP: AZURE_DCE_DCR_ID environment variable not set - SKIPPING" exit 77 fi if [[ -z "${AZURE_DCE_TABLE_NAME}" ]]; then echo "SKIP: AZURE_DCE_TABLE_NAME environment variable not set - SKIPPING" exit 77 fi } omazuredce_url_with_trailing_slash() { if [[ "${AZURE_DCE_URL}" == */ ]]; then printf '%s' "${AZURE_DCE_URL}" else printf '%s/' "${AZURE_DCE_URL}" fi } omazuredce_url_host() { local rest rest=${AZURE_DCE_URL#*://} rest=${rest%%/*} if [[ "${rest}" == \[*\] ]]; then printf '%s\n' "${rest#\[}" | sed 's/\]$//' elif [[ "${rest}" == \[*\]:* ]]; then rest=${rest#\[} printf '%s\n' "${rest%%]*}" else printf '%s\n' "${rest%%:*}" fi } omazuredce_url_port() { local rest explicit_port rest=${AZURE_DCE_URL#*://} rest=${rest%%/*} if [[ "${rest}" == \[*\]:* ]]; then explicit_port=${rest##*:} elif [[ "${rest}" == \[*\] ]]; then explicit_port= else explicit_port=${rest##*:} if [[ "${explicit_port}" == "${rest}" ]]; then explicit_port= fi fi if [[ -n "${explicit_port}" ]]; then printf '%s\n' "${explicit_port}" elif [[ "${AZURE_DCE_URL}" == https://* ]]; then printf '443\n' else printf '80\n' fi } omazuredce_url_ips_v4() { local host host=$(omazuredce_url_host) if [[ "${host}" == *:* ]]; then return fi if command -v getent >/dev/null 2>&1; then getent ahostsv4 "$host" | awk 'NR == 1 { print $1; exit }' fi } omazuredce_url_ips_v6() { local host host=$(omazuredce_url_host) if [[ "${host}" == *:* ]]; then printf '%s\n' "${host}" return fi if command -v getent >/dev/null 2>&1; then getent ahostsv6 "$host" | awk 'NR == 1 { print $1; exit }' fi } rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_failover.sh0000644000000000000000000000013115241075234017425 xustar0030 mtime=1787067036.643579006 29 atime=1787067036.79658187 30 ctime=1787067804.473912867 rsyslog-8.2608.0/tests/sndrcv_failover.sh0000775000175000017500000000424315241075234017100 0ustar00rgerrger#!/bin/bash # This tests failover capabilities. Data is sent to a local port, where # no process shall listen. Then it fails over to a second instance, then to # a file. The second instance is started. So all data should be received # there and none be logged to the file. # This builds on the basic sndrcv.sh test, but adds a first, failing, # location to the conf file. # added 2011-06-20 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export DEAD_PORT=4 # a port unassigned by IANA and very unlikely to be used export RSYSLOG_DEBUGLOG="log" # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" generate_conf add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" export PORT_RCVR=$TCPFLOOD_PORT generate_conf 2 add_conf ' *.* @@127.0.0.1:'$DEAD_PORT' # this must be DEAD $ActionExecOnlyWhenPreviousIsSuspended on & @@127.0.0.1:'$PORT_RCVR' & ./'${RSYSLOG_DYNNAME}'.empty $ActionExecOnlyWhenPreviousIsSuspended off ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # do the final check seq_check ls -l ${RSYSLOG_DYNNAME}.empty if [[ -s ${RSYSLOG_DYNNAME}.empty ]] ; then echo "FAIL: ${RSYSLOG_DYNNAME}.empty has data. Failover handling failed. Data is written" echo " even though the previous action (in a failover chain!) properly" echo " worked." error_exit 1 else echo "${RSYSLOG_DYNNAME}.empty is empty - OK" fi ; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-invalid-args.sh0000644000000000000000000000013215216464436020131 xustar0030 mtime=1782212894.080267057 30 atime=1782715518.905790829 30 ctime=1787067806.074942701 rsyslog-8.2608.0/tests/omprog-invalid-args.sh0000775000175000017500000000232415216464436017601 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Regression coverage for GitHub issue 5017. The omprog child exits during # initialization when it receives an invalid argument. Success is proven by # synchronized shutdown plus rsyslog's own diagnostic in the configured omfile # destination, not by rsyslogd stdout/stderr. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary="'$srcdir'/testsuites/omprog-invalid-args-bin.sh --invalid" template="outfmt" name="omprog_action" queue.type="Direct" confirmMessages="on" action.resumeRetryCount="0" ) } syslog.* { action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`) } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown expected_prog="${srcdir}/testsuites/omprog-invalid-args-bin.sh" content_check "omprog: program '$expected_prog' " "$RSYSLOG2_OUT_LOG" content_check "terminated; will be restarted" "$RSYSLOG2_OUT_LOG" custom_assert_content_missing "Segmentation fault" "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/hostname-with-slash-dflt-slash-valid.sh0000644000000000000000000000013215241075234023273 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.768581346 30 ctime=1787067804.055905078 rsyslog-8.2608.0/tests/hostname-with-slash-dflt-slash-valid.sh0000775000175000017500000000167715241075234022755 0ustar00rgerrger#!/bin/bash # addd 2016-07-11 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%hostname%\n") # note: we use the default parser chain, which includes RFC5424 and that parser # should be selected AND detect the hostname with slashes as valid. local4.debug action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup echo '<167>1 2003-03-01T01:00:00.000Z hostname1/hostname2 tcpflood - tag [tcpflood@32473 MSGNUM="0"] data' > $RSYSLOG_DYNNAME.input tcpflood -B -I $RSYSLOG_DYNNAME.input shutdown_when_empty wait_shutdown echo "hostname1/hostname2" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid hostname generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-followsymlinks.sh0000644000000000000000000000012715241075234020611 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067804.195907687 rsyslog-8.2608.0/tests/omfile-followsymlinks.sh0000775000175000017500000000346115241075234020260 0ustar00rgerrger#!/bin/bash # Validate omfile final-component symlink policy. The test covers the default # strict/warn compatibility modes plus an explicit action override. The oracle # is the symlink target content after synchronized shutdown, with warning text # asserted through the configured omfile output rather than rsyslogd stderr. . ${srcdir:=.}/diag.sh init require_plugin imtcp run_case() { local name="$1" local mode="$2" local action_extra="$3" local expect_target="$4" local expect_warning="$5" local link="${RSYSLOG_DYNNAME}.${name}.link" local target="${RSYSLOG_DYNNAME}.${name}.target" local normal="${RSYSLOG_DYNNAME}.${name}.normal" rm -f "$link" "$target" "$normal" : >"$target" ln -s "$target" "$link" || skip_test generate_conf add_conf ' global(compatibility.defaults.secure="'${mode}'") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { action(type="omfile" template="outfmt" file="'${link}'" '${action_extra}') } action(type="omfile" file="'${normal}'" template="outfmt") ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown if [ "$expect_target" = "yes" ]; then content_check "00000000" "$target" else if [ -s "$target" ]; then echo "FAIL: ${name} wrote through symlink target unexpectedly" cat "$target" error_exit 1 fi fi if [ "$expect_warning" = "yes" ]; then content_check "following symbolic link output file" "$normal" else check_not_present "following symbolic link output file" "$normal" fi } run_case strict strict '' no no run_case warn warn '' yes yes run_case explicit_on warn 'followSymlinks="on"' yes no run_case explicit_off backward-compatible 'followSymlinks="off"' no no exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_with_debug.sh0000644000000000000000000000013215241075234017726 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.717936048 rsyslog-8.2608.0/tests/mmanon_with_debug.sh0000775000175000017500000000520215241075234017374 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on all flavors of Solaris." export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" mode="zero" ipv4.bits="32") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: before 172.9.6.4 <129>Mar 10 01:00:00 172.20.245.8 tag: 75.123.123.0 after <129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after <129>Mar 10 01:00:00 172.20.245.8 tag: nothingnothingnothing <129>Mar 10 01:00:00 172.20.245.8 tag: before 181.23.1.4 after 172.1.3.4 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.9 <129>Mar 10 01:00:00 172.20.245.8 tag: 0.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.2.3.4.5.6.7.8.76 <129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.225.225.225 <129>Mar 10 01:00:00 172.20.245.8 tag: 172.0.234.255 <129>Mar 10 01:00:00 172.20.245.8 tag: 3.4.5.6 <129>Mar 10 01:00:00 172.20.245.8 tag: 256.0.0.0 <129>Mar 10 01:00:00 172.20.245.8 tag: 1....1....1....8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1..1..1..8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1..1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1..1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1..8 <129>Mar 10 01:00:00 172.20.245.8 tag: 1111.1.1.8.1 <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8.1 <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8. <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank1.1.1.9stillnoblank\"" shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk before 0.0.0.0 0.0.0.0 after before 0.0.0.0 after nothingnothingnothing before 0.0.0.0 after 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0.0.0.0.0.76 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 20.0.0.0 1....1....1....8 1..1..1..8 1..1.1.8 1.1..1.8 1.1.1..8 10.0.0.0.1 0.0.0.0.1 0.0.0.0. textnoblank0.0.0.0stillnoblank' cmp_exact if [ ! -e "$RSYSLOG_DEBUGLOG" ]; then echo "error: file '$RSYSLOG_DEBUGLOG' (Debuglog) not found (should be generated)" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-subtree-jsonf.sh0000644000000000000000000000013215132733117020277 xustar0030 mtime=1768666703.960621041 30 atime=1782715518.905790829 30 ctime=1787067804.169907202 rsyslog-8.2608.0/tests/omfile-subtree-jsonf.sh0000777000175000017500000000231515132733117017751 0ustar00rgerrger#!/bin/bash # Validate that subtree templates provide data to jsonf list templates unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 template(name="eventSubtree" type="subtree" subtree="$!event") template(name="jsonfList" type="list" option.jsonf="on") { property(outname="message" name="$.payload" format="jsonf") } if $msg contains "msgnum:" then { set $!event!level = "error"; set $!event!code = 500; set $.payload = exec_template("eventSubtree"); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="jsonfList") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys with open(sys.argv[1], 'r', encoding='utf-8') as fh: payload = json.load(fh) expected_message = '{ "level": "error", "code": 500 }' if payload.get("message") != expected_message: print('invalid JSON generated') print('################# actual JSON is:') print(json.dumps(payload, indent=2, sort_keys=True)) print('################# expected JSON was:') print(json.dumps({"message": expected_message}, indent=2, sort_keys=True)) sys.exit(1) PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp_conndrop_tls-vg.sh0000644000000000000000000000013215171370365020557 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.905790829 30 ctime=1787067807.364966739 rsyslog-8.2608.0/tests/imtcp_conndrop_tls-vg.sh0000775000175000017500000000035015171370365020224 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" export TB_TEST_MAX_RUNTIME=1500 export NUMMESSAGES=10000 # reduce for slower valgrind run . ${srcdir:-.}/imtcp_conndrop_tls.sh rsyslog-8.2608.0/tests/PaxHeaders/fuzz-syslog-message-smoke.sh0000644000000000000000000000013215241075234021312 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.683579755 30 ctime=1787067803.671897922 rsyslog-8.2608.0/tests/fuzz-syslog-message-smoke.sh0000775000175000017500000000140315241075234020757 0ustar00rgerrger#!/bin/sh # Smoke-test the opt-in syslog parser fuzzer against its seed corpus. A clean # fixed iteration run is the oracle; any crash, sanitizer report, or invariant # failure makes libFuzzer return non-zero. set -eu test_dir=$(CDPATH='' cd -- "$(dirname "$0")" && pwd) fuzzer="${abs_top_builddir:-"$test_dir/.."}/tools/fuzz_rsyslog_message" corpus="${srcdir:-"$test_dir"}/fuzz/corpus/syslog-message" test -x "$fuzzer" || exit 77 work_corpus="./fuzz-syslog-message-work.$$" mkdir "$work_corpus" cleanup_work_corpus() { rc=$? if test "$rc" -eq 0; then rm -rf -- "$work_corpus" fi } trap cleanup_work_corpus 0 "$fuzzer" \ -runs=1000 \ -max_len=65536 \ -timeout=5 \ -rss_limit_mb=2048 \ -artifact_prefix="$work_corpus/artifact-" \ "$work_corpus" \ "$corpus" rsyslog-8.2608.0/tests/PaxHeaders/array_lookup_table.sh0000644000000000000000000000013215035412264020115 xustar0030 mtime=1752569012.384861924 30 atime=1782715518.905790829 30 ctime=1787067804.972922166 rsyslog-8.2608.0/tests/array_lookup_table.sh0000777000175000017500000000335215035412264017571 0ustar00rgerrger#!/bin/bash # test for array lookup-table and HUP based reloading of it # added 2015-10-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate_array.lkp_tbl") template(name="outfmt" type="string" string="%msg% %$.lkp%\n") set $.num = field($msg, 58, 2); set $.lkp = lookup("xlate", $.num); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate_array.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_array_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: bar_new" content_check "msgnum:00000002: baz" cp -f $srcdir/testsuites/xlate_array_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 12 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: quux" content_check "msgnum:00000001: quux" content_check "msgnum:00000002: foo_latest" content_check "msgnum:00000003: baz_latest" content_check "msgnum:00000004: foo_latest" content_check "msgnum:00000005: foo_latest" content_check "msgnum:00000006: baz_latest" content_check "msgnum:00000007: foo_latest" content_check "msgnum:00000008: baz_latest" content_check "msgnum:00000009: baz_latest" content_check "msgnum:00000010: quux" content_check "msgnum:00000011: quux" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazureeventhubs-list.sh0000644000000000000000000000013215216464436020627 xustar0030 mtime=1782212894.076266993 30 atime=1782715518.905790829 30 ctime=1787067806.276946465 rsyslog-8.2608.0/tests/omazureeventhubs-list.sh0000775000175000017500000001126015216464436020276 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full export NUMMESSAGES=100 export NUMMESSAGESFULL=$NUMMESSAGES export WAITTIMEOUT=20 # REQUIRES EXTERNAL ENVIRONMENT VARIABLES if [[ -z "${AZURE_HOST}" ]]; then echo "SKIP: AZURE_HOST environment variable not SET! Example: .servicebus.windows.net - SKIPPING" exit 77 fi if [[ -z "${AZURE_PORT}" ]]; then echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY_NAME}" ]]; then echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY}" ]]; then echo "SKIP: AZURE_KEY environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_CONTAINER}" ]]; then echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: - SKIPPING" exit 77 fi export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME" export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME" # --- Create/Start omazureeventhubs sender config generate_conf add_conf ' # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") # Load mods module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs") # imtcp input( type="imtcp" port="0" ruleset="default" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # templates template(name="outfmt" type="string" string="%msg:F,58:2%\n") template(name="generic" type="list" option.jsonf="on") { property(outname="timestamp" name="timereported" dateFormat="rfc3339" format="jsonf") constant(value="\"source\": \"EventHubMessage\", ") property(outname="host" name="hostname" format="jsonf") property(outname="severity" name="syslogseverity" caseConversion="upper" format="jsonf" datatype="number") property(outname="facility" name="syslogfacility" format="jsonf" datatype="number") property(outname="appname" name="syslogtag" format="jsonf") property(outname="message" name="msg" format="jsonf" ) property(outname="etlsource" name="$myhostname" format="jsonf")} # ruleset ruleset(name="default") { if $msg contains "msgnum:" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") action(type="omfile" template="generic" file="'$RSYSLOG_OUT_LOG'-generic.log") action(name="omazureeventhubs" type="omazureeventhubs" azurehost="'$AZURE_HOST'" azureport="'$AZURE_PORT'" azure_key_name="'$AZURE_KEY_NAME'" azure_key="'$AZURE_KEY'" container="'$AZURE_CONTAINER'" template="generic" eventproperties=[ "Table=TestTable", "Format=JSON"] ) } else { action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") } stop } ' echo Starting sender instance [omazureeventhubs] startup echo Inject messages into rsyslog sender instance # injectmsg 1 $NUMMESSAGES tcpflood -m$NUMMESSAGES -i1 wait_file_lines $RSYSLOG_OUT_LOG $NUMMESSAGESFULL 100 # experimental: wait until kcat receives everything timeoutend=$WAITTIMEOUT timecounter=0 echo "CHECK $RSYSLOG_DYNNAME.pstats" while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then # Read IMPSTATS for verification IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5) SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2) FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2) ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2) if ! [[ $SUBMITTED_MSG =~ $re ]] ; then echo "**** omazureeventhubs WAITING FOR IMPSTATS" else if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then if [ "$ACCEPTED_MSG" -eq "$NUMMESSAGESFULL" ]; then echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" shutdown_when_empty wait_shutdown #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log exit_test else echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" fi else echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" fi fi fi $TESTTOOL_DIR/msleep 1000 done unset count shutdown_when_empty wait_shutdown error_exit 1 rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-basic-stress.sh0000644000000000000000000000013215241075234021532 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.776581496 30 ctime=1787067807.499969255 rsyslog-8.2608.0/tests/imtcp-tls-ossl-basic-stress.sh0000775000175000017500000000403315241075234021201 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 # # Stress anonymous imtcp over native OpenSSL with a TLSv1.3-only cipher suite. # Success is proved by receiving the full ordered message sequence; builds whose # native OpenSSL lacks the required TLSv1.3 SSL_CONF_cmd support must skip # instead of failing before traffic starts. # List available valid OpenSSL Engines for defaultopensslengine with this command: # openssl engine -t # . ${srcdir:=.}/diag.sh init check_command_available openssl if ! openssl ciphers -s -tls1_3 -ciphersuites TLS_AES_256_GCM_SHA384 >/dev/null 2>&1; then echo "SKIP: native OpenSSL build lacks TLSv1.3 ciphersuite support for this stress test" skip_test fi export NUMMESSAGES=100000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultopensslengine="rdrand" debug.whitelist="on" debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" gnutlsPriorityString="Protocol=-ALL,TLSv1.3,TLSv1.2 Ciphersuites=TLS_AES_256_GCM_SHA384 " ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # SignatureAlgorithms=RSA+SHA384 # Begin actual testcase startup tcpflood -p$TCPFLOOD_PORT -d8192 -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd_ratelimit_name.sh0000644000000000000000000000013115171370365020432 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.905790829 29 ctime=1787067804.49391324 rsyslog-8.2608.0/tests/omfwd_ratelimit_name.sh0000775000175000017500000000117615171370365020107 0ustar00rgerrger#!/bin/bash # Test named rate limits for omfwd (config-validation) # Verifies that omfwd accepts ratelimit.name without error. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ratelimit(name="omfwd_test_limit" interval="2" burst="5") module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr.port") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "msgnum:" then action(type="omfwd" target="127.0.0.1" port="514" protocol="udp" ratelimit.name="omfwd_test_limit" template="outfmt") ' startup shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/threadingmq.sh0000644000000000000000000000013215035412264016542 xustar0030 mtime=1752569012.419618726 30 atime=1782715518.905790829 30 ctime=1787067805.301928296 rsyslog-8.2608.0/tests/threadingmq.sh0000777000175000017500000000235615035412264016221 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # we send 100,000 messages in the hopes that his puts at least a little bit # of pressure on the threading subsystem. To really prove it, we would need to # push messages for several minutes, but that takes too long during the # automated tests (hint: do this manually after suspect changes). Thankfully, # in practice many threading bugs result in an abort rather quickly and these # should be covered by this test here. # rgerhards, 2009-06-26 echo \[threadingmq.sh\]: main queue concurrency . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 1 #$MainMsgQueueTimeoutShutdown 100000 $MainMsgQueueWorkerThreadMinimumMessages 10 $MainMsgQueueWorkerThreads 5 $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! # write quickly to the output file: $OMFileFlushOnTXEnd off $OMFileIOBufferSize 256k :msg, contains, "msgnum:" ?dynfile;outfmt ' startup injectmsg 0 100000 shutdown_when_empty # shut down rsyslogd when done processing messages # we give an extra seconds for things to settle, especially # important on slower test machines ./msleep 5000 wait_shutdown seq_check 0 99999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmsnare-modoverride-udp.sh0000644000000000000000000000013215035412264021007 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.905790829 30 ctime=1787067807.857975926 rsyslog-8.2608.0/tests/pmsnare-modoverride-udp.sh0000777000175000017500000001256615035412264020472 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/pmsnare/.libs/pmsnare") module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") global( parser.escapeControlCharactersOnReceive="off" parser.escapeControlCharacterTab="off" parser.escapeControlCharactersCStyle="on" parser.controlCharacterEscapePrefix="#" ) parser( name="modoverride.snare" type="pmsnare" parser.escapeControlCharactersOnReceive="on" parser.escapeControlCharacterTab="on" parser.escapeControlCharactersCStyle="off" parser.controlCharacterEscapePrefix="\\" ) template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1" parser=["modoverride.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\"" tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\"" tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\"" tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog\\\\0111\\\\011Security\\\\01100000000\\\\011Sun May 21 12:00:01.123\\\\0114624\\\\011Microsoft-Windows-Security-Auditing\\\\011N/A\\\\011N/A\\\\011Success Audit\\\\011hostname.domain\\\\011Logon\\\\011\\\\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\"" shutdown_when_empty wait_shutdown export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti 14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]}; 14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................ 14,user,info,MSWinEventLog,MSWinEventLog, 1\011Security\01100000000\011Sun May 21 12:00:01.123\0114624\011Microsoft-Windows-Security-Auditing\011N/A\011N/A\011Success Audit\011hostname.domain\011Logon\011\011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/impstats-push-basic.sh0000644000000000000000000000013215145046113020135 xustar0030 mtime=1771326539.040014305 30 atime=1782715518.905790829 30 ctime=1787067806.739955093 rsyslog-8.2608.0/tests/impstats-push-basic.sh0000775000175000017500000000273315145046113017611 0ustar00rgerrger#!/bin/bash # Test for impstats push support - basic compilation and load test # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "Solaris has limitations" # Use external VM if provided, otherwise expect push to fail if [ -n "$RSYSLOG_TESTBENCH_EXTERNAL_VM_URL" ]; then VM_URL="${RSYSLOG_TESTBENCH_EXTERNAL_VM_URL}/api/v1/write" echo "Using external VictoriaMetrics at: $VM_URL" else VM_URL="http://localhost:19999/api/v1/write" echo "No external VM configured, push will fail (expected)" echo "Tip: for a local VM+Grafana stack, see devtools/vm_grafana_stack/README.md" fi generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" interval="1" format="prometheus" log.file="'$RSYSLOG_OUT_LOG'" resetCounters="off" # Push config push.url="'$VM_URL'" push.labels=["test=impstats-push", "instance=ci-test"] push.timeout.ms="2000" push.label.instance="on" push.label.job="rsyslog-test" push.label.origin="on" push.label.name="on" ) action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) ' startup # Wait for impstats to generate and push at least 2-3 stats intervals # (interval is 1 second, so wait 3 seconds to ensure push happens) sleep 3 shutdown_when_empty wait_shutdown # Verify stats were generated locally content_check "resource-usage" "$RSYSLOG_OUT_LOG" content_check "origin" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_glob_dir_not_dir.sh0000644000000000000000000000013215035412264024040 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.904790812 30 ctime=1787067808.092980305 rsyslog-8.2608.0/tests/imbatchreport_errmsg_glob_dir_not_dir.sh0000777000175000017500000000070115035412264023507 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" rename=".done$ .s .r.done" reports="'$RSYSLOG_DYNNAME'_.conf/*.done") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "Configured directory is NOT a directory" exit_test rsyslog-8.2608.0/tests/PaxHeaders/now-unixtimestamp.sh0000644000000000000000000000013215241075234017750 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 30 ctime=1787067805.835938247 rsyslog-8.2608.0/tests/now-unixtimestamp.sh0000775000175000017500000000162515241075234017423 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # addd 2016-02-23 by RGerhards, released under ASL 2.0 # requires faketime echo \[now-utc\]: test \$NOW-UTC . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.tnow = $$now-unixtimestamp + 1; template(name="outfmt" type="string" string="%$now-unixtimestamp%,%$.tnow%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' . $srcdir/faketime_common.sh export TZ=TEST-02:00 FAKETIME='2016-01-01 01:00:00' startup # what we send actually is irrelevant, as we just use system properties. # but we need to send one message in order to gain output! tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="1451602800,1451602801" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-queue.sh0000644000000000000000000000013215131231047017331 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.904790812 30 ctime=1787067806.538951347 rsyslog-8.2608.0/tests/imhiredis-queue.sh0000777000175000017500000000204615131231047017004 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis redis_command "RPUSH mykey message1" redis_command "RPUSH mykey message2" redis_command "RPUSH mykey message3" generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mykey" mode="queue" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown stop_redis # Opposite order content_check '1 message3' content_check '2 message2' content_check '3 message1' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-queue-lpop.sh0000644000000000000000000000013215131231047020301 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.904790812 30 ctime=1787067806.541951403 rsyslog-8.2608.0/tests/imhiredis-queue-lpop.sh0000777000175000017500000000206715131231047017757 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis redis_command "RPUSH mykey message1" redis_command "RPUSH mykey message2" redis_command "RPUSH mykey message3" generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mykey" mode="queue" uselpop="on" ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown stop_redis # Same order content_check '1 message1' content_check '2 message2' content_check '3 message3' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkafka-hang-on-no-kafka.sh0000644000000000000000000000013215035412264020654 xustar0030 mtime=1752569012.394792439 30 atime=1782715518.903790795 30 ctime=1787067806.248945943 rsyslog-8.2608.0/tests/imkafka-hang-on-no-kafka.sh0000777000175000017500000000156715035412264020336 0ustar00rgerrger#!/bin/bash # added 2018-10-22 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . $srcdir/diag.sh init export RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT=5000 # 5sec generate_conf add_conf ' main_queue(queue.type="direct") module(load="../plugins/imkafka/.libs/imkafka") input( type="imkafka" ruleset="kafka" topic="irrelevant" broker="localhost:29092" consumergroup="default" confParam=[ "socket.timeout.ms=5000", "socket.keepalive.enable=true" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="kafka") { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) } action( type="omfile" file="'$RSYSLOG_OUT_LOG.syslog.log'" template="outfmt" ) ' export RSTB_DAEMONIZE="YES" startup shutdown_when_empty wait_shutdown # the main point is to see if we can terminate, so no further checks down here! exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-revocationcheck-off.sh0000644000000000000000000000013215241075234023047 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.454968417 rsyslog-8.2608.0/tests/imtcp-tls-ossl-revocationcheck-off.sh0000775000175000017500000000251115241075234022515 0ustar00rgerrger#!/bin/bash # Test for StreamDriver.TlsRevocationCheck parameter with explicit "off" setting # added 2026-01-19 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.TlsRevocationCheck="off" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # Begin actual testcase # This test verifies that TlsRevocationCheck can be set to "off" and # connections work normally (OCSP checking is disabled by default anyway, # but this ensures the parameter is properly parsed and has no adverse effects) startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/with_space.mmdb0000644000000000000000000000013215035412264016672 xustar0030 mtime=1752569012.420611777 30 atime=1782715518.903790795 30 ctime=1787067808.425986511 rsyslog-8.2608.0/tests/with_space.mmdb0000666000175000017500000000066015035412264016342 0ustar00rgerrger                     0 áDcityGBei ing«ÍïMaxMind.comé[binary_format_major_version¡[binary_format_minor_version Kbuild_epochUÑS Mdatabase_typeDMMDBKdescriptionáBen]Rsyslog MaxMindDB for testingJip_version¡IlanguagesJnode_countÁ Krecord_size¡rsyslog-8.2608.0/tests/PaxHeaders/pmnull-withparams.sh0000644000000000000000000000013215241075234017724 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.787581702 30 ctime=1787067807.044960776 rsyslog-8.2608.0/tests/pmnull-withparams.sh0000775000175000017500000000233115241075234017372 0ustar00rgerrger#!/bin/bash # add 2016-12-08 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/pmnull/.libs/pmnull") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") parser(name="custom.pmnull" type="pmnull" tag="mytag" syslogfacility="3" syslogseverity="1") template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n") ruleset(name="ruleset" parser=["custom.pmnull", "rsyslog.pmnull"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test") } ' startup tcpflood -m1 -M "\"<189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\"" shutdown_when_empty wait_shutdown echo 'tag: mytag, pri: 25, syslogfacility: 3, syslogseverity: 1 msg: <189>16261: May 28 16:09:56.185: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkafka-backgrounded.sh0000644000000000000000000000013215216464436020301 xustar0030 mtime=1782212894.057266685 30 atime=1782715518.903790795 30 ctime=1787067806.240945794 rsyslog-8.2608.0/tests/imkafka-backgrounded.sh0000775000175000017500000000305515216464436017753 0ustar00rgerrger#!/bin/bash # added 2018-10-24 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init check_command_available kcat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 RANDTOPIC="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka echo Check and Stop previous instances of kafka/zookeeper download_kafka stop_zookeeper stop_kafka echo Create kafka/zookeeper instance and $RANDTOPIC topic start_zookeeper start_kafka create_kafka_topic $RANDTOPIC '.dep_wrk' '22181' export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/imkafka/.libs/imkafka") input( type="imkafka" topic="'$RANDTOPIC'" broker="localhost:29092" consumergroup="default" confParam=[ "compression.codec=none", "session.timeout.ms=10000", "socket.timeout.ms=5000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "enable.partition.eof=false" ] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then { action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) } ' export RSTB_DAEMONIZE="YES" startup injectmsg_kcat --wait 1 $TESTMESSAGES -d shutdown_when_empty wait_shutdown # Delete topic to remove old traces before delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181' seq_check 1 $TESTMESSAGES -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_mbedtls_certvalid_action_level.sh0000644000000000000000000000013115171370365024720 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.905790829 29 ctime=1787067807.41596769 rsyslog-8.2608.0/tests/sndrcv_tls_mbedtls_certvalid_action_level.sh0000775000175000017500000000022515171370365024367 0ustar00rgerrger#!/bin/bash # added 2020-01-17 by RGerhards, released under ASL 2.0 export RS_TLS_DRIVER=mbedtls . ${srcdir:=.}/sndrcv_tls_certvalid_action_level.sh rsyslog-8.2608.0/tests/PaxHeaders/pmsnare-ccbackslash.sh0000644000000000000000000000013215241075234020144 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067807.848975759 rsyslog-8.2608.0/tests/pmsnare-ccbackslash.sh0000775000175000017500000001203415241075234017613 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../contrib/pmsnare/.libs/pmsnare") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") global(localHostname="localhost" parser.escapeControlCharactersCStyle="on") $EscapeControlCharactersOnReceive on template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\"" tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\"" shutdown_when_empty wait_shutdown export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti 14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]}; 14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................ 14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmsnare-cccstyle.sh0000644000000000000000000000013215241075234017514 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067807.843975666 rsyslog-8.2608.0/tests/pmsnare-cccstyle.sh0000775000175000017500000001432615241075234017171 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../contrib/pmsnare/.libs/pmsnare") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") $EscapeControlCharactersOnReceive on global( parser.escapeControlCharactersCStyle="on" ) template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\"" tcpflood -m1 -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\"" tcpflood -m1 -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]\"" tcpflood -m1 -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\"" shutdown_when_empty wait_shutdown export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti 14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................ 14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group local_in [0x0, 0x0] 14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]}; 14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................ 14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain 14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_client_missing_cert.sh0000644000000000000000000000013115241075234022524 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.326966031 rsyslog-8.2608.0/tests/sndrcv_tls_client_missing_cert.sh0000775000175000017500000000452115241075234022176 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verifies the receiver-side TLS diagnostic for clients that do not present a # certificate. The diagnostic must include the remote IP address so operators # can feed the event into IP-based tooling such as fail2ban. . ${srcdir:=.}/diag.sh init echo "This test is under review - it seems to have some issues" exit 77 printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls} # start up the instances # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="'$RS_TLS_DRIVER'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="'$RS_TLS_DRIVER'" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.PermitExpiredCerts="off" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( /* defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'" */ defaultNetstreamDriver="'$RS_TLS_DRIVER'" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown content_check --regex "peer 127\\.0\\.0\\.1 did not provide a certificate," exit_test rsyslog-8.2608.0/tests/PaxHeaders/stats-cee-vg.sh0000644000000000000000000000013215241075234016542 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.797581889 30 ctime=1787067806.760955484 rsyslog-8.2608.0/tests/stats-cee-vg.sh0000775000175000017500000000262015241075234016211 0ustar00rgerrger#!/bin/bash # added 2016-03-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 uname if [ "$(uname)" = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi echo =============================================================================== echo \[stats-cee-vg.sh\]: test for verifying stats are reported correctly cee format with valgrind . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="cee") if ($msg == "this condition will never match") then { action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`) } ' startup_vg injectmsg_file $srcdir/testsuites/dynstats_input_1 wait_queueempty wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg custom_content_check '@cee: { "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "batchesprocessed": 0, "failed": 0, "suspended": 0, "suspended.duration": 0, "resumed": 0, "ratelimit.allowed": 0, "ratelimit.dropped": 0, "ratelimit.paced": 0, "ratelimit.paced_usec": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-dematerialize.sh0000644000000000000000000000013215241075234022325 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.854901332 rsyslog-8.2608.0/tests/segmented-da-idle-dematerialize.sh0000775000175000017500000000637215241075234022004 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Exercise the complete segmented DA idle lifecycle on an action queue. A # deliberately slow, tiny memory tier makes each 2000-message burst spill. The # filesystem oracle proves lazy creation, grace-period dematerialization, and # transparent rematerialization; exact sequence output proves no loss or # reordering. The impstats oracle proves the final child worker terminated. # The reset probe uses a 3-second timeout, injects after 1 second, and checks # 2.25 seconds later: the check is past the original deadline but still 750 ms # before the reset deadline, leaving a substantial scheduler margin under SAN. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=4000 SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" SEG_DIR="$SPOOL_DIR/idle-action.segq" MARKER="$SPOOL_DIR/idle-action.da-engine" STATS_FILE="${RSYSLOG_DYNNAME}.stats" wait_path_state() { local mode="$1" local path="$2" local timeoutend=$((SECONDS + 30)) while true; do if [ "$mode" = present ] && [ -e "$path" ]; then return fi if [ "$mode" = absent ] && [ ! -e "$path" ]; then return fi if [ "$SECONDS" -ge "$timeoutend" ]; then echo "FAIL: path did not become $mode: $path" find "$SPOOL_DIR" -maxdepth 2 -print 2>/dev/null || true error_exit 1 fi ./msleep 50 done } generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") module(load="../plugins/impstats/.libs/impstats" interval="1" log.syslog="off" log.file="'"$STATS_FILE"'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" name="idle-action" file="'"$RSYSLOG_OUT_LOG"'" template="outfmt" queue.type="LinkedList" queue.filename="idle-action" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.dequeueSlowdown="2" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="3000" ) ' startup [ ! -e "$SEG_DIR" ] || error_exit 1 "segmented DA store materialized before the first spill" [ ! -e "$MARKER" ] || error_exit 1 "segmented DA engine marker was created before the first spill" injectmsg 0 2000 wait_path_state present "$SEG_DIR" [ -f "$MARKER" ] || error_exit 1 "segmented DA engine marker was not created with the first spill" wait_file_lines "$RSYSLOG_OUT_LOG" 2000 300 # A memory-tier-only enqueue during the grace period must wake the child and # restart the full timeout even though it does not itself spill to disk. ./msleep 1000 injectmsg 2000 1 wait_file_lines "$RSYSLOG_OUT_LOG" 2001 300 ./msleep 2250 [ -d "$SEG_DIR" ] || error_exit 1 "new traffic did not reset the segmented DA idle grace period" wait_path_state absent "$SEG_DIR" # A second burst must recreate the same child store and run through the same # lifecycle, proving that worker and store teardown are both reversible. injectmsg 2001 1999 wait_path_state present "$SEG_DIR" wait_file_lines "$RSYSLOG_OUT_LOG" 4000 300 wait_path_state absent "$SEG_DIR" wait_content 'store.idleDematerializations=2' "$STATS_FILE" wait_content 'workers.current=0' "$STATS_FILE" [ "$(cat "$MARKER")" = "RSYSLOG-DA-ENGINE-V1 segmentedDisk" ] || error_exit 1 "segmented DA marker changed during idle cleanup" shutdown_when_empty wait_shutdown seq_check 0 3999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_table-hup-backgrounded.sh0000644000000000000000000000013215131231047022132 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.906790846 30 ctime=1787067804.960921942 rsyslog-8.2608.0/tests/lookup_table-hup-backgrounded.sh0000777000175000017500000000320515131231047021603 0ustar00rgerrger#!/bin/bash # test for lookup-table and HUP based reloading of it # added 2015-09-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_TSAN generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl export RSTB_DAEMONIZE="YES" startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: bar_new" content_check "msgnum:00000002: baz" cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 10 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: foo_latest" content_check "msgnum:00000001: quux" content_check "msgnum:00000002: baz_latest" content_check "msgnum:00000003: foo_latest" content_check "msgnum:00000004: foo_latest" content_check "msgnum:00000005: baz_latest" content_check "msgnum:00000006: foo_latest" content_check "msgnum:00000007: baz_latest" content_check "msgnum:00000008: baz_latest" content_check "msgnum:00000009: quux" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_host_vg.sh0000644000000000000000000000013215171370365020477 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.906790846 30 ctime=1787067806.992959808 rsyslog-8.2608.0/tests/rscript_faup_host_vg.sh0000775000175000017500000000020515171370365020143 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_host.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-files-mtls-vg.sh0000644000000000000000000000012715241075234021625 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067807.536969945 rsyslog-8.2608.0/tests/omfwd-tls-ossl-files-mtls-vg.sh0000775000175000017500000000012215241075234021263 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-files-mtls.sh rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-basic-auth-vg.sh0000644000000000000000000000013215171370365022614 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.906790846 30 ctime=1787067806.422949186 rsyslog-8.2608.0/tests/imhttp-post-payload-basic-auth-vg.sh0000775000175000017500000000024515171370365022264 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" . ${srcdir:-.}/imhttp-post-payload-basic-auth.sh rsyslog-8.2608.0/tests/PaxHeaders/no-parser-vg.sh0000644000000000000000000000013215241075234016560 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 30 ctime=1787067805.194926303 rsyslog-8.2608.0/tests/no-parser-vg.sh0000775000175000017500000000123615241075234016231 0ustar00rgerrger#!/bin/bash # add 2017-03-06 by Rainer Gerhards, released under ASL 2.0 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") ruleset(name="ruleset" parser="rsyslog.rfc5424") { action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) } ' startup_vg tcpflood -m10 shutdown_when_empty wait_shutdown_vg # note: we just check the valgrind output, the log file itself does not # interest us exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_all_2_vg.sh0000644000000000000000000000013215171370365020513 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.905790829 30 ctime=1787067806.972959435 rsyslog-8.2608.0/tests/rscript_faup_all_2_vg.sh0000775000175000017500000000020615171370365020160 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_all_2.sh rsyslog-8.2608.0/tests/PaxHeaders/lookup_table.sh0000644000000000000000000000013215035412264016717 xustar0030 mtime=1752569012.399757696 30 atime=1782715518.904790812 30 ctime=1787067804.955921849 rsyslog-8.2608.0/tests/lookup_table.sh0000777000175000017500000000313715035412264016374 0ustar00rgerrger#!/bin/bash # test for lookup-table and HUP based reloading of it # added 2015-09-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: bar_new" content_check "msgnum:00000002: baz" cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 10 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: foo_latest" content_check "msgnum:00000001: quux" content_check "msgnum:00000002: baz_latest" content_check "msgnum:00000003: foo_latest" content_check "msgnum:00000004: foo_latest" content_check "msgnum:00000005: baz_latest" content_check "msgnum:00000006: foo_latest" content_check "msgnum:00000007: baz_latest" content_check "msgnum:00000008: baz_latest" content_check "msgnum:00000009: quux" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omstdout-basic.sh0000644000000000000000000000013215241075234017175 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 30 ctime=1787067807.046960814 rsyslog-8.2608.0/tests/omstdout-basic.sh0000775000175000017500000000132415241075234016644 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omstdout/.libs/omstdout") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="-%msg%-\n") action(type="omstdout" template="outfmt") ' startup > $RSYSLOG_OUT_LOG tcpflood -m1 shutdown_when_empty wait_shutdowna grep "msgnum:00000000:" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_hash64-vg.sh0000644000000000000000000000013115241075234017514 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 29 ctime=1787067806.88095772 rsyslog-8.2608.0/tests/rscript_hash64-vg.sh0000775000175000017500000000203615241075234017165 0ustar00rgerrger#!/bin/bash # added 2018-02-07 by Harshvardhan Shrivastava # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \rscript_hash64.sh\]: test for hash64 and hash64mod script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n") module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmhash/.libs/fmhash") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.hash_no_1 = hash64("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e"); set $.hash_no_2 = hash64mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg tcpflood -m 20 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg . $srcdir/diag.sh content-pattern-check "^\(-2574714428477944902 - 14\|-50452361579464591 - 25\)$" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-multiline.sh0000644000000000000000000000013215241075234017354 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067805.485931725 rsyslog-8.2608.0/tests/imtcp-multiline.sh0000775000175000017500000000136715241075234017032 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $EscapeControlCharactersOnReceive off module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" MultiLine="on") template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n") ruleset(name="remote") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -B -I ${srcdir}/testsuites/imtcp-multiline.testdata shutdown_when_empty wait_shutdown export EXPECTED='NEWMSG: <133>Msg 1 Line 2 NEWMSG: <133>Msg 2' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-consumerGroup-reclaim-vg.sh0000644000000000000000000000013215171370365024405 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.904790812 30 ctime=1787067806.589952298 rsyslog-8.2608.0/tests/imhiredis-stream-consumerGroup-reclaim-vg.sh0000775000175000017500000000032215171370365024051 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-stream-consumerGroup-reclaim.sh rsyslog-8.2608.0/tests/PaxHeaders/imptcp-oversize-errorfile-truncate.sh0000644000000000000000000000013115241075234023211 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.770581384 29 ctime=1787067806.80795636 rsyslog-8.2608.0/tests/imptcp-oversize-errorfile-truncate.sh0000775000175000017500000000336515241075234022670 0ustar00rgerrger#!/bin/bash # Regression test for oversizemsg.errorfile with imptcp truncation. # imptcp can detect and truncate an oversized TCP frame before core # submission sees rawmsg > maxMessageSize. The test passes only if that # pre-submit oversize detection writes the configured JSON errorfile with the # expanded message-field schema operators need for triage. This path runs # before parser-derived field values such as msg and syslogtag are known, so # the oracle checks that those fields exist while expecting imptcp-populated # fields to carry values. It also proves the legacy "input" alias is preserved # for consumers of the older two-field record. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MaxMessageSize 128 global(processInternalMessages="on" oversizemsg.input.mode="truncate" oversizemsg.errorfile="'$RSYSLOG2_OUT_LOG'") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup msg="<120> 2011-03-01T11:22:12Z host tag: this is a way too long message that has to be truncated test1 test2 test3 test4 test5 abcdefghijklmnopqrstuvwxyz" printf '%s %s' "${#msg}" "$msg" > $RSYSLOG_DYNNAME.inputfile tcpflood -I $RSYSLOG_DYNNAME.inputfile shutdown_when_empty wait_shutdown content_check --regex '"rawmsg":.*way too long message' "$RSYSLOG2_OUT_LOG" content_check '"msg":' "$RSYSLOG2_OUT_LOG" content_check '"inputname": "imptcp"' "$RSYSLOG2_OUT_LOG" content_check '"input": "imptcp"' "$RSYSLOG2_OUT_LOG" content_check '"fromhost-ip": "127.0.0.1"' "$RSYSLOG2_OUT_LOG" content_check '"timereported":' "$RSYSLOG2_OUT_LOG" content_check '"timegenerated":' "$RSYSLOG2_OUT_LOG" content_check '"syslogtag":' "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/timestamp-pgsql.sh0000644000000000000000000000013215131231047017361 xustar0030 mtime=1768239655.725212925 30 atime=1782715518.906790846 30 ctime=1787067804.011904258 rsyslog-8.2608.0/tests/timestamp-pgsql.sh0000777000175000017500000000076215131231047017037 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%timestamp:::date-pgsql%\n") :syslogtag, contains, "su" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg_literal "<34>1 2003-01-23T12:34:56.003Z mymachine.example.com su - ID47 - MSG\"" shutdown_when_empty wait_shutdown export EXPECTED='2003-01-23 12:34:56' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-truncate-2GB-file.sh0000644000000000000000000000013215216464436020625 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.906790846 30 ctime=1787067807.867976113 rsyslog-8.2608.0/tests/imfile-truncate-2GB-file.sh0000775000175000017500000000342715216464436020302 0ustar00rgerrger#!/bin/bash # written 2018-11-09 by Rainer Gerhards # this test checks that 2GiB (31 bit) file size region is handled correctly # it first generates a file that is 2GiB-64 bytes, processes it, and then # adds a couple of messages to get it over 2GiB. # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init export TB_TEST_MAX_RUNTIME=3600 # test is very slow as it works on large files generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" reopenOnTruncate="on") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' touch $RSYSLOG_DYNNAME.input startup # initial file: 2GiB - 1 message (54 byte) ./inputfilegen -s 2147483584 -d47 -M $RSYSLOG_DYNNAME.msgcnt > $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)" export NUMMESSAGES wait_file_lines --delay 2500 --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES 3000 # add one message --> exactly 2GB ./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input (( NUMMESSAGES++ )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES # add one more message --> now we go over 2GB ./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input (( NUMMESSAGES++ )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES # add even more messages ./inputfilegen -m10000 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input NUMMESSAGES=$(( NUMMESSAGES + 10000 )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check 0 $(( NUMMESSAGES - 1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_set_unset_invalid_var.sh0000644000000000000000000000013215035412264022374 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.905790829 30 ctime=1787067804.774918476 rsyslog-8.2608.0/tests/rscript_set_unset_invalid_var.sh0000777000175000017500000000226515035412264022052 0ustar00rgerrger#!/bin/bash # Check that invalid variable names are detected. # Copyright 2017-01-24 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="json" type="string" string="%$!%\n") ruleset(name="rcvr" queue.type="LinkedList") { set $@timestamp="test"; unset $@timestamp2; action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown grep "@timestamp" $RSYSLOG_OUT_LOG > /dev/null if [ ! $? -eq 0 ]; then echo "expected error message on \"@timestamp\" not found, output is:" echo "------------------------------------------------------------" cat $RSYSLOG_OUT_LOG echo "------------------------------------------------------------" error_exit 1 fi; grep "@timestamp2" $RSYSLOG_OUT_LOG > /dev/null if [ ! $? -eq 0 ]; then echo "expected error message on \"@timestamp2\" not found, output is:" echo "------------------------------------------------------------" cat $RSYSLOG_OUT_LOG echo "------------------------------------------------------------" error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/faketime_common.sh0000644000000000000000000000013215216464436017405 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.905790829 30 ctime=1787067808.199982299 rsyslog-8.2608.0/tests/faketime_common.sh0000664000175000017500000000450015216464436017050 0ustar00rgerrger#!/bin/bash # addd 2016-03-11 by Thomas D., released under ASL 2.0 # Several tests make use of faketime. They all need to know when # faketime is missing or the system isn't year-2038 complaint. # This script can be sourced to prevent duplicated code. rsyslog_testbench_preload_libfaketime() { local missing_requirements= if ! hash find 2>/dev/null ; then missing_requirements="'find' is missing in PATH; Make sure you have findutils/coreutils installed! Skipping test ..." fi if ! hash $RS_SORTCMD 2>/dev/null ; then missing_requirements="'sort' is missing in PATH; Make sure you have coreutils installed! Skipping test ..." fi if ! hash $RS_HEADCMD 2>/dev/null ; then missing_requirements="'head' is missing in PATH; Make sure you have coreutils installed! Skipping test ..." fi if [ -n "${missing_requirements}" ]; then printf '%s\n' "${missing_requirements}" exit 77 fi RSYSLOG_LIBFAKETIME=$(find /usr -name 'libfaketime.so*' -type f | $RS_SORTCMD --reverse | $RS_HEADCMD --lines 1) if [ -z "${RSYSLOG_LIBFAKETIME}" ]; then echo "Could not determine libfaketime library, skipping test!" exit 77 fi echo "Testing '${RSYSLOG_LIBFAKETIME}' library ..." local faketime_testtime faketime_testtime=$(LD_PRELOAD="${RSYSLOG_LIBFAKETIME}" FAKETIME="1991-08-25 20:57:08" TZ=GMT date +%s 2>/dev/null) if [ ${faketime_testtime} -ne 683153828 ] ; then echo "'${RSYSLOG_LIBFAKETIME}' failed sanity check, skipping test!" exit 77 else echo "Test passed! Will use '${RSYSLOG_LIBFAKETIME}' library!" export RSYSLOG_PRELOAD="${RSYSLOG_LIBFAKETIME}" fi # GMT-1 (POSIX TIME) is GMT+1 in "Human Time" faketime_testtime=$(LD_PRELOAD="${RSYSLOG_LIBFAKETIME}" FAKETIME="2040-01-01 16:00:00" TZ=GMT-1 date +%s 2>/dev/null) if [ ${faketime_testtime} -eq -1 ]; then echo "Note: System is not year-2038 compliant" RSYSLOG_TESTBENCH_Y2K38_INCOMPATIBLE="yes" else echo "Note: System is year-2038 compliant" fi } rsyslog_testbench_require_y2k38_support() { if [ -n "${RSYSLOG_TESTBENCH_Y2K38_INCOMPATIBLE}" ]; then echo "Skipping further tests because system doesn't support year 2038 ..." exit_test exit 0 fi } rsyslog_testbench_preload_libfaketime rsyslog-8.2608.0/tests/PaxHeaders/fromhost-port-async-ruleset.sh0000644000000000000000000000013215241075234021657 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067805.471931464 rsyslog-8.2608.0/tests/fromhost-port-async-ruleset.sh0000775000175000017500000000225115241075234021326 0ustar00rgerrger#!/bin/bash ## fromhost-port.sh ## Check that fromhost-port property records sender port and that it ## can properly be carried over to a second asnc ruleset. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 QUEUE_TYPE=${QUEUE_TYPE:-disk} QUEUE_EXTRA=${QUEUE_EXTRA:-} if [ "${QUEUE_NEEDS_FILENAME:-off}" = "on" ]; then QUEUE_EXTRA='queue.filename="asyncq" queue.spoolDirectory="'${RSYSLOG_DYNNAME}'.spool"' fi export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="list") { property(name="fromhost-port") constant(value="\n") } call async # Note: a disk-type queue is selected to test even more rsyslog core features ruleset(name="async" queue.type="'$QUEUE_TYPE'" '"$QUEUE_EXTRA"') { :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -m $NUMMESSAGES -w "${RSYSLOG_DYNNAME}.tcpflood-port" shutdown_when_empty wait_shutdown EXPECTED="$(cat "${RSYSLOG_DYNNAME}.tcpflood-port")" export EXPECTED cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_relp_tls_chainedcert.sh0000644000000000000000000000013215216464436022004 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.904790812 30 ctime=1787067807.735973653 rsyslog-8.2608.0/tests/sndrcv_relp_tls_chainedcert.sh0000775000175000017500000000425015216464436021454 0ustar00rgerrger#!/bin/bash # addd 2020-08-25 by alorbach, released under ASL 2.0 # Verify RELP forwarding with OpenSSL TLS certificate chains. The imrelp # receiver binds an ephemeral IPv4 listener and the testbench discovers that # bound port after startup, avoiding the get_free_port race before the omrelp # sender connects. Success is the full ordered delivery sequence. . ${srcdir:=.}/diag.sh init require_relpEngineVersion "1.7.0" export NUMMESSAGES=1000 export TB_TEST_MAX_RUNTIME=30 # uncomment for debugging support: # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' module( load="../plugins/imrelp/.libs/imrelp" tls.tlslib="openssl") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" address="127.0.0.1" port="0" tls="on" tls.mycert="'$srcdir'/tls-certs/certchained.pem" tls.myprivkey="'$srcdir'/tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_single_tcp_listener_port PORT_RCVR export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' module( load="../plugins/omrelp/.libs/omrelp" tls.tlslib="openssl") :msg, contains, "msgnum:" action(type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on" tls.mycert="'$srcdir'/tls-certs/certchained.pem" tls.myprivkey="'$srcdir'/tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog") action(type="omfile" file="'$RSYSLOG_DYNNAME.errmsgs'") ' 2 startup 2 if grep "omrelp error: invalid authmode" < "$RSYSLOG_DYNNAME.errmsgs" ; then echo "SKIP: librelp does not support certvalid auth mode" # mini-cleanup to not leave dangling processes shutdown_immediate 2 shutdown_immediate rm $RSYSLOG_DYNNAME* &> /dev/null exit 77 fi # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 $NUMMESSAGES # shut down sender shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/ommail-sendmail-body-off.sh0000644000000000000000000000013215216464436021023 xustar0030 mtime=1782212894.079267041 30 atime=1782715518.904790812 30 ctime=1787067805.700935732 rsyslog-8.2608.0/tests/ommail-sendmail-body-off.sh0000775000175000017500000000160315216464436020472 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/ommail/.libs/ommail") template(name="mailBody" type="string" string="body must not be present %msg%\\r\\n") if $msg contains "msgnum:" then { action( type="ommail" mode="sendmail" sendmail.binary="'$srcdir'/testsuites/ommail-sendmail-bin.sh" mailfrom="rsyslog@example.net" mailto="operator@example.net" subject.text="body disabled" body.enable="off" template="mailBody" ) } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown content_check "From: " content_check "To: " content_check "Subject: body disabled" if grep -F -- "body must not be present" "$RSYSLOG_OUT_LOG" >/dev/null; then error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_exists-yes2.sh0000644000000000000000000000013215131231047020177 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.906790846 30 ctime=1787067804.894920712 rsyslog-8.2608.0/tests/rscript_exists-yes2.sh0000777000175000017500000000075415131231047017656 0ustar00rgerrger#!/bin/bash # add 2020-10-02 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%!result%\n") set $.p1!p2!val="yes!"; if $msg contains "msgnum" then { if exists($.p1!p2!val) then set $!result = "on"; else set $!result = "off"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='on' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omelasticsearch-bulk-readonly-retry.sh0000644000000000000000000000013215241075234023317 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.686579811 30 ctime=1787067804.497913314 rsyslog-8.2608.0/tests/omelasticsearch-bulk-readonly-retry.sh0000775000175000017500000001003015241075234022760 0ustar00rgerrger#!/bin/bash # Regression test for Elasticsearch read-only-index bulk responses. A fake # Elasticsearch endpoint returns HTTP 200 with per-item status 403 and # cluster_block_exception, matching a read-only index. Success is proven by a # second POST to the fake endpoint before the normal startup/shutdown timeout. # The first POST returns only retryable per-item errors; the second succeeds, so # the action must suspend/retry the batch instead of treating the bulk item # failure as a handled permanent data error. The background helper writes its # port after bind and is killed on both failure and success paths. . ${srcdir:=.}/diag.sh init require_plugin omelasticsearch check_command_available python3 PORT_FILE="$RSYSLOG_DYNNAME.esfake.port" COUNT_FILE="$RSYSLOG_DYNNAME.esfake.count" test_error_exit_handler() { if [ -n "${SERVER_PID:-}" ]; then kill "$SERVER_PID" 2>/dev/null || true fi } python3 - "$PORT_FILE" "$COUNT_FILE" <<'PY' & import json import sys from http.server import BaseHTTPRequestHandler, HTTPServer port_file, count_file = sys.argv[1:3] post_count = 0 class Handler(BaseHTTPRequestHandler): def log_message(self, fmt, *args): pass def send_json(self, payload): data = json.dumps(payload).encode("utf-8") self.send_response(200) self.send_header("Content-Type", "application/json") self.send_header("Content-Length", str(len(data))) self.end_headers() self.wfile.write(data) def do_GET(self): self.send_json({ "version": { "number": "8.15.0", "distribution": "elasticsearch", } }) def do_POST(self): global post_count length = int(self.headers.get("Content-Length", "0")) body = self.rfile.read(length).decode("utf-8") ops = max(1, len([line for line in body.splitlines() if line.strip()]) // 2) post_count += 1 with open(count_file, "w", encoding="ascii") as fh: fh.write(f"{post_count}\n") if post_count >= 2: self.send_json({ "errors": False, "items": [{"index": {"status": 201}} for _ in range(ops)] }) else: self.send_json({ "errors": True, "items": [{ "index": { "status": 403, "error": { "type": "cluster_block_exception", "reason": "blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];", }, } } for _ in range(ops)] }) server = HTTPServer(("127.0.0.1", 0), Handler) with open(port_file, "w", encoding="ascii") as fh: fh.write(f"{server.server_port}\n") server.serve_forever() PY SERVER_PID=$! assign_file_content ES_PORT "$PORT_FILE" generate_conf add_conf ' module(load="../plugins/omelasticsearch/.libs/omelasticsearch") template(name="msgTpl" type="string" string="{\"msg\":\"%msg%\"}") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") action(type="omelasticsearch" server="127.0.0.1" serverport="'$ES_PORT'" bulkmode="on" searchIndex="rsyslog_testbench" template="msgTpl" action.reportSuspension="on" action.resumeRetryCount="1" action.resumeInterval="1") ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z host testprog - - - msgnum:0' count=0 retry_timeout_seconds=$((TB_TIMEOUT_STARTSTOP / 10)) if [ "$retry_timeout_seconds" -lt 1 ]; then retry_timeout_seconds=1 fi while [ "$count" -lt "$retry_timeout_seconds" ]; do if [ -r "$COUNT_FILE" ] && [ "$(cat "$COUNT_FILE")" -ge 2 ]; then break fi ./msleep 1000 count=$((count + 1)) done if [ ! -r "$COUNT_FILE" ] || [ "$(cat "$COUNT_FILE")" -lt 2 ]; then echo "omelasticsearch did not retry the read-only bulk response" error_exit 1 fi shutdown_when_empty wait_shutdown content_check "msgnum:0" "$RSYSLOG_OUT_LOG" kill "$SERVER_PID" 2>/dev/null || true wait "$SERVER_PID" 2>/dev/null || true exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger_ratelimit.sh0000644000000000000000000000013215145046113021510 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.906790846 30 ctime=1787067804.660916352 rsyslog-8.2608.0/tests/imuxsock_logger_ratelimit.sh0000775000175000017500000000253315145046113021162 0ustar00rgerrger#!/bin/bash echo \[imuxsock_logger_ratelimit.sh\]: test rate limiting with imuxsock . ${srcdir:=.}/diag.sh init ./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi export EXPECTED=" test message nbr 0, severity=6 test message nbr 1, severity=6 test message nbr 2, severity=6 test message nbr 3, severity=6 test message nbr 4, severity=6" for use_special_parser in on off; do echo \[imuxsock_logger_ratelimit.sh\]: test rate limiting with imuxsock with useSpecialParser="$use_special_parser" echo -n >"$RSYSLOG_OUT_LOG" generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input( type="imuxsock" socket="'$RSYSLOG_DYNNAME'-testbench_socket" useSpecialParser="'$use_special_parser'" ruleset="testruleset" ratelimit.interval="10" ratelimit.burst="5") template(name="outfmt" type="string" string="%msg:%\n") ruleset(name="testruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup ./syslog_caller -m20 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" -s6 # the sleep below is needed to prevent too-early termination of rsyslogd ./msleep 100 shutdown_when_empty wait_shutdown cmp_exact done exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-imhttp-metrics-apikeyfile.sh0000644000000000000000000000013215216464436022301 xustar0030 mtime=1782212894.092267251 30 atime=1782715518.906790846 30 ctime=1787067805.461931278 rsyslog-8.2608.0/tests/yaml-imhttp-metrics-apikeyfile.sh0000775000175000017500000000260515216464436021753 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify YAML imhttp metrics API-key authentication while the HTTP listener uses # an OS-assigned port. The HTTP status and metrics response are the oracle. . ${srcdir:=.}/diag.sh init require_yaml_support IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../contrib/imhttp/.libs/imhttp"' add_yaml_conf ' ports: "0"' add_yaml_conf ' listenPortFileName: "'$IMHTTP_PORT_FILE'"' add_yaml_conf ' metricsPath: "/metrics"' add_yaml_conf ' metricsApiKeyFile: "'$srcdir'/testsuites/imhttp-apikeys.txt"' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imhttp' add_yaml_conf ' endpoint: "/unused"' add_yaml_conf ' ruleset: "main"' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: main' add_yaml_conf ' script: |' add_yaml_conf ' action(type="omfile" file="'$RSYSLOG_OUT_LOG'.unused")' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" ret=$(curl -s -o /dev/null -w '%{http_code}' http://localhost:$IMHTTP_PORT/metrics) if [ "$ret" != "401" ]; then echo "ERROR: expected 401 without API key in YAML metrics config, got $ret" error_exit 1 fi curl -s -H 'Authorization: ApiKey secret-token-1' \ http://localhost:$IMHTTP_PORT/metrics > "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "imhttp_up 1" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_anon_ipv4.sh0000644000000000000000000000013115241075234020375 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.296965472 rsyslog-8.2608.0/tests/sndrcv_tls_anon_ipv4.sh0000775000175000017500000000401515241075234020045 0ustar00rgerrger#!/bin/bash # rgerhards, 2011-04-04 # testing sending and receiving via TLS with anon auth using bare ipv4, no SNI # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=25000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="gtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RCVR_PORT=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) # set up the action $DefaultNetstreamDriver gtls # use gtls netstream driver $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@127.0.0.1:'$RCVR_PORT' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-vg.sh0000644000000000000000000000013215241075234024203 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.549970187 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-vg.sh0000775000175000017500000000014015241075234023645 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/mysql-actq-mt.sh0000644000000000000000000000013215216464436016761 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.905790829 30 ctime=1787067805.916939757 rsyslog-8.2608.0/tests/mysql-actq-mt.sh0000775000175000017500000000356515216464436016441 0ustar00rgerrger#!/bin/bash # Verify that ommysql preserves all messages when a bounded linked-list action # queue is drained by multiple worker threads. The queue size is intentionally # small compared to the injected message count so the test covers backpressure. # Shutdown is synchronized on the final MySQL row count and sequence, not just # the main queue, because a slow CI database can still be draining the action # queue after imdiag reports the main queue empty. # The 80s enqueue timeout is a CI tolerance budget: if a stressed MySQL service # cannot drain the action queue in that time, the failure should be investigated # instead of silently turning the test into an unbounded wait. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=150000 mysql_actq_count_ready() { count=$(mysql -N -s --user=rsyslog --password=testbench \ --database "$RSYSLOG_DYNNAME" \ -e "select count(*) from SystemEvents;" \ 2> "$RSYSLOG_DYNNAME.mysqlerr") ret=$? grep -iv "Using a password on the command line interface can be insecure." \ < "$RSYSLOG_DYNNAME.mysqlerr" if [ "$ret" -ne 0 ]; then error_exit "$ret" fi [ "$count" -ge "$NUMMESSAGES" ] } mysql_actq_data_ready() { mysql_actq_count_ready || return 1 mysql_get_data seq_check --check-only } export QUEUE_EMPTY_CHECK_FUNC=mysql_actq_data_ready generate_conf add_conf ' module(load="../plugins/ommysql/.libs/ommysql") :msg, contains, "msgnum:" { action(type="ommysql" server="127.0.0.1" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" queue.size="10000" queue.type="linkedList" queue.workerthreads="5" queue.workerthreadMinimumMessages="500" queue.timeoutWorkerthreadShutdown="1000" queue.timeoutEnqueue="80000" queue.timeoutShutdown="30000" ) } ' mysql_prep_for_test startup injectmsg shutdown_when_empty wait_shutdown mysql_get_data seq_check mysql_cleanup_test exit_test rsyslog-8.2608.0/tests/PaxHeaders/dynstats_reset.sh0000644000000000000000000000013215131231047017305 xustar0030 mtime=1768239655.701212533 30 atime=1782715518.904790812 30 ctime=1787067806.687954124 rsyslog-8.2608.0/tests/dynstats_reset.sh0000777000175000017500000000460315131231047016761 0ustar00rgerrger#!/bin/bash # added 2015-11-13 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="4" severity="7" resetCounters="on" Ruleset="stats" bracketing="on") template(name="outfmt" type="string" string="%msg% %$.increment_successful%\n") dyn_stats(name="msg_stats" unusedMetricLife="1" resettable="off") set $.msg_prefix = field($msg, 32, 1); if (re_match($.msg_prefix, "foo|bar|baz|quux|corge|grault")) then { set $.increment_successful = dyn_inc("msg_stats", $.msg_prefix); } else { set $.increment_successful = -1; } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log injectmsg_file "$srcdir/testsuites/dynstats_input_1" rst_msleep 8100 injectmsg_file "$srcdir/testsuites/dynstats_input_2" rst_msleep 8100 injectmsg_file "$srcdir/testsuites/dynstats_input_3" rst_msleep 8100 wait_queueempty content_check "foo 001 0" content_check "bar 002 0" content_check "baz 003 0" content_check "foo 004 0" content_check "baz 005 0" content_check "foo 006 0" shutdown_when_empty wait_shutdown # because dyn-metrics would be reset before it can accumulate and report high counts, sleep between msg-injection ensures that custom_assert_content_missing 'baz=2' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing 'foo=2' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing 'foo=3' "${RSYSLOG_DYNNAME}.out.stats.log" # but actual reported stats (aggregate) should match first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'foo=' ${RSYSLOG_DYNNAME}.out.stats.log 3 first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'bar=' ${RSYSLOG_DYNNAME}.out.stats.log 1 first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'baz=' ${RSYSLOG_DYNNAME}.out.stats.log 2 first_column_sum_check 's/.*new_metric_add=\([0-9]*\)/\1/g' 'new_metric_add=' "${RSYSLOG_DYNNAME}.out.stats.log" 6 first_column_sum_check 's/.*ops_overflow=\([0-9]*\)/\1/g' 'ops_overflow=' "${RSYSLOG_DYNNAME}.out.stats.log" 0 first_column_sum_check 's/.*no_metric=\([0-9]*\)/\1/g' 'no_metric=' "${RSYSLOG_DYNNAME}.out.stats.log" 0 first_column_sum_check 's/.*metrics_purged=\([0-9]*\)/\1/g' 'metrics_purged=' "${RSYSLOG_DYNNAME}.out.stats.log" 6 exit_test rsyslog-8.2608.0/tests/PaxHeaders/override_getaddrinfo.c0000644000000000000000000000013215241075234020235 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 30 ctime=1787067803.545895574 rsyslog-8.2608.0/tests/override_getaddrinfo.c0000664000175000017500000000377715241075234017717 0ustar00rgerrger#include "config.h" #include #include #include #include #include #include #include #include #include #include static int make_passive_ipv4(const char *service, struct addrinfo **res) { struct addrinfo *ai = NULL; struct sockaddr_in *sa = NULL; char *endptr = NULL; const long port = (service == NULL) ? 0 : strtol(service, &endptr, 10); if (res == NULL || (service != NULL && (*service == '\0' || *endptr != '\0' || port < 0 || port > 65535))) { return EAI_NONAME; } ai = calloc(1, sizeof(*ai)); sa = calloc(1, sizeof(*sa)); if (ai == NULL || sa == NULL) { free(ai); free(sa); return EAI_MEMORY; } sa->sin_family = AF_INET; sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK); sa->sin_port = htons((uint16_t)port); ai->ai_family = AF_INET; ai->ai_socktype = SOCK_STREAM; ai->ai_protocol = IPPROTO_TCP; ai->ai_addrlen = sizeof(*sa); ai->ai_addr = (struct sockaddr *)sa; *res = ai; return 0; } int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints __attribute__((unused)), struct addrinfo **res) { if (node == NULL || strcmp(node, "**UNSPECIFIED**") == 0) { return make_passive_ipv4(service, res); } if (node != NULL && strcmp(node, "nonfqdn") == 0) { const char *marker = getenv("RSYSLOG_GETADDRINFO_MARKER"); if (marker != NULL && marker[0] != '\0') { const int fd = open(marker, O_CREAT | O_WRONLY | O_APPEND, 0600); if (fd >= 0) { const ssize_t written = write(fd, "nonfqdn\n", sizeof("nonfqdn\n") - 1); (void)written; (void)close(fd); } } if (res != NULL) { *res = NULL; } return EAI_MEMORY; } if (res != NULL) { *res = NULL; } return EAI_NONAME; } rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-num.sh0000644000000000000000000000013215171370365021646 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.904790812 30 ctime=1787067804.851919911 rsyslog-8.2608.0/tests/rscript_compare_numstr-num.sh0000775000175000017500000000014215171370365021312 0ustar00rgerrger#!/bin/bash export LOWER_VAL='"1"' export HIGHER_VAL='2' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/ratelimit_duplicate.sh0000644000000000000000000000013215241075234020264 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.789581739 30 ctime=1787067805.648934763 rsyslog-8.2608.0/tests/ratelimit_duplicate.sh0000775000175000017500000000207615241075234017740 0ustar00rgerrger#!/bin/bash # Test for duplicate named rate limits. # # The oracle is config-validation failure with the duplicate-name diagnostic on # stderr. Use a test-instance-specific stderr capture file because this # negative config test runs in parallel with other validation tests. . ${srcdir:=.}/diag.sh init if [ -z "$RSYSLOGD" ]; then export RSYSLOGD=../tools/rsyslogd fi STDERR_LOG="${RSYSLOG_DYNNAME}.stderr.log" generate_conf add_conf ' ratelimit(name="test_limit" interval="2" burst="5") ratelimit(name="test_limit" interval="1" burst="10") template(name="outfmt" type="string" string="%msg%\n") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # Check config only, redirect stderr export CONF_FILE="${TESTCONF_NM}.conf" $RSYSLOGD -N1 -M"$RSYSLOG_MODDIR" -f "$CONF_FILE" > /dev/null 2> "$STDERR_LOG" if grep -q "ratelimit: duplicate name 'test_limit' in current config set" "$STDERR_LOG"; then echo "SUCCESS: detected duplicate name error." exit_test else echo "FAIL: duplicate name error not found in:" cat "$STDERR_LOG" error_exit 1 fi rsyslog-8.2608.0/tests/PaxHeaders/imjournal-basic.sh0000644000000000000000000000013215145046113017314 xustar0030 mtime=1771326539.037014256 30 atime=1782715518.907790863 30 ctime=1787067805.980940949 rsyslog-8.2608.0/tests/imjournal-basic.sh0000775000175000017500000001116315145046113016765 0ustar00rgerrger#!/bin/bash # This test injects a message and checks if it is received by # imjournal. We use a special test string which we do not expect # to be present in the regular log stream. So we do not expect that # any other journal content matches our test message. We skip the # test in case message does not make it even to journal which may # sometimes happen in some environments. # addd 2017-10-25 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh require-journalctl generate_conf add_conf ' module(load="../plugins/imjournal/.libs/imjournal" IgnorePreviousMessages="on" RateLimit.Burst="1000000") template(name="outfmt" type="string" string="%msg%\n") # Filter to only process messages from this test instance to avoid interference # from other parallel journal tests writing to the same system journal if $msg contains "'"$RSYSLOG_DYNNAME"'" then { action(type="omfile" template="outfmt" file="'"$RSYSLOG_OUT_LOG"'") stop } ' TESTMSG="TestBenCH-RSYSLog imjournal This is a test message - $(date +%s) - $RSYSLOG_DYNNAME" startup printf 'a quick glimpse at journal content at rsyslog startup:\n' journalctl -n 20 --no-pager printf '\n\n' wait_for_out_log_contains() { needle="$1" timeout="$2" deadline=$(( $(date +%s) + timeout )) while [ "$(date +%s)" -le "$deadline" ]; do if [ -f "$RSYSLOG_OUT_LOG" ] && grep -Fq -- "$needle" "$RSYSLOG_OUT_LOG"; then return 0 fi $TESTTOOL_DIR/msleep 200 done return 1 } # If journal activity is extremely high, this test can become flaky due to # heavy contention/rotation churn outside the test's control. We retry to # absorb short bursts before deciding to skip. NOISE_WINDOW_SEC=${RSTB_JOURNAL_NOISE_WINDOW_SEC:-5} NOISE_MAX_LINES=${RSTB_JOURNAL_NOISE_MAX_LINES:-20000} NOISE_RETRIES=${RSTB_JOURNAL_NOISE_RETRIES:-2} NOISE_RETRY_SLEEP_MS=${RSTB_JOURNAL_NOISE_RETRY_SLEEP_MS:-1500} noise_try=0 while true; do noise_since=$(( $(date +%s) - NOISE_WINDOW_SEC )) journal_noise_lines=$(journalctl --since "@$noise_since" --no-pager 2>/dev/null | wc -l) if [ "$journal_noise_lines" -le "$NOISE_MAX_LINES" ]; then break fi if [ "$noise_try" -ge "$NOISE_RETRIES" ]; then printf 'SKIP: journal too noisy (%d lines in last %ds, limit %d) after %d retries\n' \ "$journal_noise_lines" "$NOISE_WINDOW_SEC" "$NOISE_MAX_LINES" "$NOISE_RETRIES" shutdown_when_empty wait_shutdown exit 77 fi printf 'journal noisy (%d lines in last %ds, limit %d), retrying (%d/%d)\n' \ "$journal_noise_lines" "$NOISE_WINDOW_SEC" "$NOISE_MAX_LINES" "$((noise_try+1))" "$NOISE_RETRIES" $TESTTOOL_DIR/msleep "$NOISE_RETRY_SLEEP_MS" (( noise_try=noise_try+1 )) done # Make sure imjournal has passed initial positioning (IgnorePreviousMessages) # before sending the actual test payload. On busy CI systems this may need # a few retries, so probe repeatedly with bounded waits. READY_TRIES=${RSTB_IMJOURNAL_READY_TRIES:-4} READY_TIMEOUT_PER_TRY=${RSTB_IMJOURNAL_READY_TIMEOUT_PER_TRY:-20} ready_ok=0 ready_try=1 while [ "$ready_try" -le "$READY_TRIES" ]; do READYMSG="TestBenCH-RSYSLog imjournal readiness probe - $(date +%s) - $RSYSLOG_DYNNAME - try$ready_try" ./journal_print "$READYMSG" journal_write_state=$? if [ $journal_write_state -ne 0 ]; then printf 'SKIP: journal_print returned state %d writing readiness probe: %s\n' "$journal_write_state" "$READYMSG" printf 'skipping test, journal probably not working\n' shutdown_when_empty wait_shutdown exit 77 fi if wait_for_out_log_contains "$READYMSG" "$READY_TIMEOUT_PER_TRY"; then ready_ok=1 break fi printf 'readiness probe not observed yet (%d/%d), retrying\n' "$ready_try" "$READY_TRIES" $TESTTOOL_DIR/msleep 500 (( ready_try=ready_try+1 )) done if [ "$ready_ok" -ne 1 ]; then printf 'SKIP: imjournal readiness probe not observed after %d attempts (%ds each)\n' \ "$READY_TRIES" "$READY_TIMEOUT_PER_TRY" shutdown_when_empty wait_shutdown exit 77 fi printf '++++++++++++++++++++++ Printing to the journal! +++++++++++++++++++++++++\n' # inject message into journal and check that it is recorded ./journal_print "$TESTMSG" journal_write_state=$? if [ $journal_write_state -ne 0 ]; then printf 'SKIP: journal_print returned state %d writing message: %s\n' "$journal_write_state" "$TESTMSG" printf 'skipping test, journal probably not working\n' exit 77 fi # check state later - we must not terminate the test until we have terminated rsyslog # give the journal ~5 minutes to forward the message, see # https://github.com/rsyslog/rsyslog/issues/2564#issuecomment-435849660 content_check_with_count "$TESTMSG" 1 300 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown check_journal_testmsg_received exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-msg-truncation-on-number2.sh0000644000000000000000000000013215132733117022466 xustar0030 mtime=1768666703.957620996 30 atime=1782715518.906790846 30 ctime=1787067807.178963273 rsyslog-8.2608.0/tests/imptcp-msg-truncation-on-number2.sh0000777000175000017500000000345115132733117022142 0ustar00rgerrger#!/bin/bash # addd 2017-03-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "Darwin" "Test fails on MacOS 13, TCP chunking causes false octet-counting detection with sequence 9876543210" generate_conf add_conf ' $MaxMessageSize 128 global(processInternalMessages="on" oversizemsg.input.mode="accept") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="templ1" type="string" string="%rawmsg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="templ1") } ' startup tcpflood -m2 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"2000000010 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"4000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"0 <120> 2011-03-01T11:22:12Z host msgnum:1\"" shutdown_when_empty wait_shutdown echo '<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 214000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 214000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 2000000010<120> 2011-03-01T11:22:12Z host msgnum:1 4000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/da-mainmsg-q.sh0000644000000000000000000000013215241075234016513 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067804.381911153 rsyslog-8.2608.0/tests/da-mainmsg-q.sh0000775000175000017500000000601115241075234016160 0ustar00rgerrger#!/bin/bash # Test disk-assisted mode on the main message queue. The test uses a very small # in-memory main queue so the 2000-message burst must spill to disk and then # drain back into the configured omfile action. imdiag injection is marked fully # delayable so the diagnostic injector does not overrun the intentionally tiny # queue. The disk-assisted path can drain slowly under sanitizer/Valgrind CI, so # the test allows up to four minutes per drain point and waits for the complete # expected sequence instead of only a line count. The oracle is the complete # output sequence 0..2099: first the pre-DA messages, then the DA-triggering # burst, then a final small post-DA burst that proves normal processing resumed. # added 2009-04-22 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full DA_MAINMSG_Q_TIMEOUT=${DA_MAINMSG_Q_TIMEOUT:-240} wait_da_mainmsg_q_seq() { local endnum="$1" local timeout="${2:-$DA_MAINMSG_Q_TIMEOUT}" local timeoutend=$(( SECONDS + timeout )) local count=0 while true ; do if seq_check --check-only 0 "$endnum" >/dev/null 2>&1 ; then printf 'wait_da_mainmsg_q_seq success, sequence 0..%s complete\n' "$endnum" return fi if [ -f "$RSYSLOG_OUT_LOG" ]; then count=$(wc -l < "$RSYSLOG_OUT_LOG") fi if [ "$SECONDS" -ge "$timeoutend" ]; then printf 'FAIL: wait_da_mainmsg_q_seq timed out waiting for sequence 0..%s, have %s lines\n' \ "$endnum" "$count" seq_check 0 "$endnum" error_exit 1 fi printf 'wait_da_mainmsg_q_seq waiting for sequence 0..%s, have %s lines\n' \ "$endnum" "$count" "$TESTTOOL_DIR"/msleep 500 done } da_mainmsg_q_complete() { seq_check --check-only 0 2099 >/dev/null 2>&1 } export QUEUE_EMPTY_CHECK_FUNC=da_mainmsg_q_complete generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set spool locations and switch queue to disk assisted mode $WorkDirectory '$RSYSLOG_DYNNAME'.spool $MainMsgQueueSize 200 # this *should* trigger moving on to DA mode... # note: we must set QueueSize sufficiently high, so that 70% (light delay mark) # is high enough above HighWatermark! $MainMsgQueueHighWatermark 80 $MainMsgQueueLowWatermark 40 $MainMsgQueueFilename mainq $MainMsgQueueType linkedlist $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup # part1: send first 50 messages (in memory, only) injectmsg 0 50 wait_da_mainmsg_q_seq 49 # let queue drain for this test case # part 2: send bunch of messages. This should trigger DA mode injectmsg 50 2000 ls -l ${RSYSLOG_DYNNAME}.spool # for manual review wait_da_mainmsg_q_seq 2049 # wait to ensure DA queue is "empty" # send another handful injectmsg 2050 50 wait_da_mainmsg_q_seq 2099 shutdown_when_empty wait_shutdown seq_check 0 2099 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmkubernetes-basic.out.json0000644000000000000000000000013215131231047021157 xustar0030 mtime=1768239655.709212663 30 atime=1782715518.906790846 30 ctime=1787067808.644990592 rsyslog-8.2608.0/tests/mmkubernetes-basic.out.json0000666000175000017500000002661415131231047020636 0ustar00rgerrger[{ "log": "not in right format", "testid": 1 }, { "message": "not in right format", "testid": 2 }, { "kubernetes": { "namespace_id": "namespace-name2-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name2-id", "labels": { "custom_label": "pod-name2-label-value", "deploymentconfig": "pod-name2-dc", "component": "pod-name2-component", "label_with_empty_value": "", "deployment": "pod-name2-deployment" }, "pod_name": "pod-name2", "namespace_name": "namespace-name2", "container_name": "container-name2", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id2" }, "testid": 4 }, { "message": "a message from container 4", "CONTAINER_NAME": "some-prefix_container-name4_pod-name4_namespace-name4_unused4_unused44", "CONTAINER_ID_FULL": "id4", "kubernetes": { "namespace_id": "namespace-name4-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name4-id", "labels": { "custom_label": "pod-name4-label-value", "deploymentconfig": "pod-name4-dc", "component": "pod-name4-component", "label_with_empty_value": "", "deployment": "pod-name4-deployment" }, "pod_name": "pod-name4", "namespace_name": "namespace-name4", "container_name": "container-name4", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id4" }, "testid": 6 }, { "kubernetes": { "namespace_id": "namespace-name1-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name1-id", "labels": { "custom_label": "pod-name1-label-value", "deploymentconfig": "pod-name1-dc", "component": "pod-name1-component", "label_with_empty_value": "", "deployment": "pod-name1-deployment" }, "pod_name": "pod-name1", "namespace_name": "namespace-name1", "container_name": "container-name1", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id1" }, "testid": 3 }, { "message": "a message from container 3", "CONTAINER_NAME": "some-prefix_container-name3.container-hash3_pod-name3_namespace-name3_unused3_unused33", "CONTAINER_ID_FULL": "id3", "kubernetes": { "namespace_id": "namespace-name3-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name3-id", "labels": { "custom_label": "pod-name3-label-value", "deploymentconfig": "pod-name3-dc", "component": "pod-name3-component", "label_with_empty_value": "", "deployment": "pod-name3-deployment" }, "pod_name": "pod-name3", "namespace_name": "namespace-name3", "container_name": "container-name3", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id3" }, "testid": 5 }, { "message": "a message from container 5", "CONTAINER_NAME": "some-prefix_container-name5_pod-name5.with.dot.in.pod.name_namespace-name5_unused5_unused55", "CONTAINER_ID_FULL": "id5", "kubernetes": { "namespace_id": "namespace-name5-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name5.with.dot.in.pod.name-id", "labels": { "custom_label": "pod-name5.with.dot.in.pod.name-label-value", "deploymentconfig": "pod-name5.with.dot.in.pod.name-dc", "component": "pod-name5.with.dot.in.pod.name-component", "label_with_empty_value": "", "deployment": "pod-name5.with.dot.in.pod.name-deployment" }, "pod_name": "pod-name5.with.dot.in.pod.name", "namespace_name": "namespace-name5", "container_name": "container-name5", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id5" }, "testid": 7 }, { "message":"this record should have no namespace metadata", "CONTAINER_NAME":"some-prefix_container-name-6_pod-name-6_namespace-name-6-not-found_unused6_unused66", "CONTAINER_ID_FULL":"id6", "kubernetes": { "pod_id":"pod-name-6-id", "labels": { "custom_label":"pod-name-6-label-value", "deploymentconfig":"pod-name-6-dc", "component":"pod-name-6-component", "label_with_empty_value":"", "deployment":"pod-name-6-deployment" }, "pod_name":"pod-name-6", "namespace_name":"namespace-name-6-not-found", "container_name":"container-name-6", "master_url":"http://localhost:{k8s_srv_port}" }, "docker": { "container_id":"id6" }, "testid": 8 }, { "message": "this record should have no pod metadata", "CONTAINER_NAME": "some-prefix_container-name-7_pod-name-7-not-found_namespace-name-7_unused7_unused77", "CONTAINER_ID_FULL": "id7", "kubernetes": { "namespace_id": "namespace-name-7-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_name": "pod-name-7-not-found", "namespace_name": "namespace-name-7", "container_name": "container-name-7", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id7" }, "testid": 9 }, { "message": "this record should have no namespace or pod metadata and retry", "CONTAINER_NAME": "some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88", "CONTAINER_ID_FULL": "id8", "kubernetes": { "pod_name": "pod-name-8", "namespace_name": "namespace-name-8-busy", "container_name": "container-name-8", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id8" }, "testid": 10 }, { "message": "this record should have namespace and pod metadata after retry", "CONTAINER_NAME": "some-prefix_container-name-8_pod-name-8_namespace-name-8-busy_unused8_unused88", "CONTAINER_ID_FULL": "id8", "kubernetes": { "namespace_id": "namespace-name-8-busy-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name-8-id", "labels": { "custom_label": "pod-name-8-label-value", "deploymentconfig": "pod-name-8-dc", "component": "pod-name-8-component", "label_with_empty_value": "", "deployment": "pod-name-8-deployment" }, "pod_name": "pod-name-8", "namespace_name": "namespace-name-8-busy", "container_name": "container-name-8", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id8" }, "testid": 11 }, { "message": "this record should have no pod metadata and retry", "CONTAINER_NAME": "some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99", "CONTAINER_ID_FULL": "id9", "kubernetes": { "namespace_id": "namespace-name-9-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_name": "pod-name-9-busy", "namespace_name": "namespace-name-9", "container_name": "container-name-9", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id9" }, "testid": 12 }, { "message": "this record should have pod metadata after retry", "CONTAINER_NAME": "some-prefix_container-name-9_pod-name-9-busy_namespace-name-9_unused9_unused99", "CONTAINER_ID_FULL": "id9", "kubernetes": { "namespace_id": "namespace-name-9-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name-9-busy-id", "labels": { "custom_label": "pod-name-9-busy-label-value", "deploymentconfig": "pod-name-9-busy-dc", "component": "pod-name-9-busy-component", "label_with_empty_value": "", "deployment": "pod-name-9-busy-deployment" }, "pod_name": "pod-name-9-busy", "namespace_name": "namespace-name-9", "container_name": "container-name-9", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id9" }, "testid": 13 }, { "message": "this record should process normally", "CONTAINER_NAME": "some-prefix_container-name-10_pod-name-10_namespace-name-10_unused10_unused100", "CONTAINER_ID_FULL": "id10", "kubernetes": { "namespace_id": "namespace-name-10-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name-10-id", "labels": { "custom_label": "pod-name-10-label-value", "deploymentconfig": "pod-name-10-dc", "component": "pod-name-10-component", "label_with_empty_value": "", "deployment": "pod-name-10-deployment" }, "pod_name": "pod-name-10", "namespace_name": "namespace-name-10", "container_name": "container-name-10", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id10" }, "testid": 14 }, { "message": "this record should have no pod metadata", "CONTAINER_NAME": "some-prefix_container-name-11_pod-name-11-error_namespace-name-11_unused11_unused111", "CONTAINER_ID_FULL": "id11", "kubernetes": { "namespace_id": "namespace-name-11-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_name": "pod-name-11-error", "namespace_name": "namespace-name-11", "container_name": "container-name-11", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id11" }, "testid": 15 }, { "message": "this record should process normally", "CONTAINER_NAME": "some-prefix_container-name-12_pod-name-12_namespace-name-12_unused12_unused112", "CONTAINER_ID_FULL": "id12", "kubernetes": { "namespace_id": "namespace-name-12-id", "namespace_labels": { "label_1_key": "label 1 value", "label_with_empty_value": "", "label_2_key": "label 2 value" }, "creation_timestamp": "2018-04-09T21:56:39Z", "pod_id": "pod-name-12-id", "labels": { "custom_label": "pod-name-12-label-value", "deploymentconfig": "pod-name-12-dc", "component": "pod-name-12-component", "label_with_empty_value": "", "deployment": "pod-name-12-deployment" }, "pod_name": "pod-name-12", "namespace_name": "namespace-name-12", "container_name": "container-name-12", "master_url": "http://localhost:{k8s_srv_port}" }, "docker": { "container_id": "id12" }, "testid": 16 }] rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-json.sh0000644000000000000000000000013215132733117017704 xustar0030 mtime=1768666703.959621026 30 atime=1782715518.906790846 30 ctime=1787067805.059923787 rsyslog-8.2608.0/tests/mmsnareparse-json.sh0000777000175000017500000001307715132733117017365 0ustar00rgerrger#!/bin/bash ## Test mmsnareparse module with JSON template output ## Validates that the module correctly parses Windows security events and outputs them in JSON format unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmsnareparse/.libs/mmsnareparse") template(name="jsonfmt" type="list" option.jsonf="on") { property(outname="EventID" name="$!win!Event!EventID" format="jsonf") property(outname="TimeCreatedNormalized" name="$!win!Event!TimeCreated!Normalized" format="jsonf") property(outname="LogonType" name="$!win!LogonInformation!LogonType" format="jsonf") property(outname="LogonTypeName" name="$!win!LogonInformation!LogonTypeName" format="jsonf") property(outname="LAPSPolicyVersion" name="$!win!LAPS!PolicyVersion" format="jsonf") property(outname="LAPSCredentialRotation" name="$!win!LAPS!CredentialRotation" format="jsonf") property(outname="TLSReason" name="$!win!TLSInspection!Reason" format="jsonf") property(outname="WDACPolicyVersion" name="$!win!WDAC!PolicyVersion" format="jsonf") property(outname="WDACPID" name="$!win!WDAC!PID" format="jsonf") property(outname="WUFBPolicyID" name="$!win!WUFB!PolicyID" format="jsonf") property(outname="RemoteCredentialGuard" name="$!win!Logon!RemoteCredentialGuard" format="jsonf") property(outname="NetworkSourcePort" name="$!win!Network!SourcePort" format="jsonf") } action(type="mmsnareparse") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="jsonfmt") ' startup cat <<'MSG' > ${RSYSLOG_DYNNAME}.input <13>1 2025-02-18T06:42:17.554128Z DC25-PREVIEW - - - - MSWinEventLog 1 Security 802301 Tue Feb 18 06:42:17 2025 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit DC25-PREVIEW Logon An account was successfully logged on. Subject: Security ID: S-1-5-18 Account Name: SYSTEM Account Domain: NT AUTHORITY Logon ID: 0x3E7 Logon Information: Logon Type: 2 Restricted Admin Mode: - Virtual Account: %%1843 Elevated Token: %%1843 New Logon: Security ID: S-1-5-21-88997766-1122334455-6677889900-500 Account Name: ADMIN-LAPS$ Account Domain: FABRIKAM Logon ID: 0x52F1A Linked Logon ID: 0x0 Network Account Name: - Network Account Domain: - Logon GUID: {5a8f0679-9b23-4cb7-a8c7-3d650c9b52ec} Process Information: Process ID: 0x66c Process Name: C:\Windows\System32\winlogon.exe Network Information: Workstation Name: CORE25-01 Source Network Address: 192.168.50.12 Source Port: 59122 Detailed Authentication Information: Logon Process: User32 Authentication Package: Negotiate Transited Services: - Package Name (NTLM only): - Key Length: 0 Remote Credential Guard: Enabled LAPS Context: PolicyVersion=2; CredentialRotation=True -802301 <13>1 2025-02-18T07:01:55.771903Z EDGE25-01 - - - - MSWinEventLog 1 Security 301221 Tue Feb 18 07:01:55 2025 5157 Microsoft-Windows-Security-Auditing N/A N/A Failure Audit EDGE25-01 Filtering Platform Packet Drop The Windows Filtering Platform has blocked a connection. Application Information: Process ID: 948 Application Name: C:\Program Files\Contoso\edgegateway.exe Network Information: Direction: Outbound Source Address: 10.15.5.20 Source Port: 57912 Destination Address: 104.45.23.110 Destination Port: 443 Protocol: 6 Filter Information: Filter Run-Time ID: 89041 Layer Name: %%14596 Layer Run-Time ID: 44 TLS Inspection: Reason: Unapproved Root Authority Policy: ContosoOutboundTLS -301221 <13>1 2025-02-18T07:05:44.888234Z APP25-API - - - - MSWinEventLog 1 Security 402991 Tue Feb 18 07:05:44 2025 6281 Microsoft-Windows-CodeIntegrity N/A N/A Error APP25-API Application Control Code Integrity determined that a process (\Device\HarddiskVolume4\Program Files\LegacyERP\erp.exe) attempted to load \Device\HarddiskVolume4\Temp\unsigned.dll that did not meet the Enterprise signing level requirements. Policy Name: FABRIKAM-WDAC-BaseV3 Policy Version: 3.2.0 Enforcement Mode: Audit+Enforce User: FABRIKAM\svc_batch PID: 4128 -402991 <13>1 2025-02-18T06:59:13.332719Z DC25-PREVIEW - - - - MSWinEventLog 1 Security 802340 Tue Feb 18 06:59:13 2025 1243 Microsoft-Windows-WindowsUpdateClient N/A N/A Information DC25-PREVIEW WUFB Deployment Windows Update for Business deployment policy enforced. Policy ID: 2f9c4414-3f71-4f2b-9a7e-cc98a6d96970 Ring: SecureBaseline From Service: Windows Update for Business deployment service Enforcement Result: Success -802340 MSG injectmsg_file ${RSYSLOG_DYNNAME}.input shutdown_when_empty wait_shutdown # Check JSON output format (field-by-field for robustness) # 4624 content_check '"eventid":"4624"' $RSYSLOG_OUT_LOG content_check '"timecreatednormalized":"2025-02-18T06:42:17' $RSYSLOG_OUT_LOG content_check '"logontype":"2"' $RSYSLOG_OUT_LOG content_check '"logontypename":"Interactive"' $RSYSLOG_OUT_LOG content_check '"lapspolicyversion":"2"' $RSYSLOG_OUT_LOG content_check '"lapscredentialrotation":"true"' $RSYSLOG_OUT_LOG content_check '"remotecredentialguard":"true"' $RSYSLOG_OUT_LOG content_check '"networksourceport":"59122"' $RSYSLOG_OUT_LOG # 5157 content_check '"eventid":"5157"' $RSYSLOG_OUT_LOG content_check '"tlsreason":"Unapproved Root Authority"' $RSYSLOG_OUT_LOG content_check '"networksourceport":"57912"' $RSYSLOG_OUT_LOG # 6281 content_check '"eventid":"6281"' $RSYSLOG_OUT_LOG content_check '"wdacpolicyversion":"3.2.0"' $RSYSLOG_OUT_LOG content_check '"wdacpid":"4128"' $RSYSLOG_OUT_LOG # 1243 content_check '"eventid":"1243"' $RSYSLOG_OUT_LOG content_check '"wufbpolicyid":"2f9c4414-3f71-4f2b-9a7e-cc98a6d96970"' $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/gzipwr_large.sh0000644000000000000000000000013215241075234016734 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.767581328 30 ctime=1787067804.599915215 rsyslog-8.2608.0/tests/gzipwr_large.sh0000775000175000017500000000244615241075234016411 0ustar00rgerrger#!/bin/bash # This tests writing large data records in gzip mode. We use up to 10K # record size. # # added 2010-03-10 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=4000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf export SEQ_CHECK_FILE=$RSYSLOG_OUT_LOG.gz add_conf ' $MaxMessageSize 10k $MainMsgQueueTimeoutShutdown 10000 module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") local0.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'.gz" template="outfmt" zipLevel="6" veryRobustZip="on") ' # rgerhards, 2019-08-14: Note: veryRobustZip may need to be "on". Do this if the test # still prematurely terminates. In that case it is likely that gunzip got confused # by the missing zip close record. My initial testing shows that while gunzip emits an # error message, everything is properly extracted. Only stressed CI runs will show how # it works in reality. startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m$NUMMESSAGES -r -d10000 -P129 shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -E exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-restart-terminated.sh0000644000000000000000000000013215035412264021356 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.907790863 30 ctime=1787067806.059942421 rsyslog-8.2608.0/tests/omprog-restart-terminated.sh0000777000175000017500000001065515035412264021036 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test checks that omprog restarts the external program when it # terminates prematurely, and that it does so without leaking file # descriptors. Two cases are checked: termination of the program when # omprog is going to write to the pipe (to send a message to the # program), and when omprog is going to read from the pipe (when it # is expecting the program to confirm the last message). . ${srcdir:=.}/diag.sh init check_command_available lsof generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary="'$RSYSLOG_DYNNAME'.omprog-restart-terminated-bin.sh" template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process confirmMessages="on" # facilitates sync with the child process action.resumeRetryCount="3" action.resumeInterval="1" action.reportSuspensionContinuation="on" signalOnClose="off" ) } syslog.* { action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG`) } ' # We need a test-specific program name, as the test needs to signal the child process cp -f $srcdir/testsuites/omprog-restart-terminated-bin.sh $RSYSLOG_DYNNAME.omprog-restart-terminated-bin.sh # On Solaris 10, the output of ps is truncated for long process names; use /usr/ucb/ps instead: if [[ $(uname) = "SunOS" && $(uname -r) = "5.10" ]]; then function get_child_pid { /usr/ucb/ps -awwx | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $1 }' } else function get_child_pid { ps -ef | grep "$RSYSLOG_DYNNAME.[o]mprog-restart-terminated-bin.sh" | awk '{ print $2 }' } fi startup injectmsg 0 1 wait_queueempty pid=$(getpid) echo PID: $pid start_fd_count=$(lsof -p $pid | wc -l) injectmsg 1 1 injectmsg 2 1 wait_queueempty child_pid_1=$(get_child_pid) kill -s USR1 $child_pid_1 ./msleep 100 injectmsg 3 1 injectmsg 4 1 wait_queueempty child_pid_2=$(get_child_pid) kill -s TERM $child_pid_2 ./msleep 100 injectmsg 5 1 injectmsg 6 1 injectmsg 7 1 wait_queueempty child_pid_3=$(get_child_pid) kill -s KILL $child_pid_3 ./msleep 100 injectmsg 8 1 injectmsg 9 1 wait_queueempty end_fd_count=$(lsof -p $pid | wc -l) child_pid_4=$(get_child_pid) child_lsof=$(lsof -a -d 0-65535 -p $child_pid_4 | awk '$4 != "255r" { print $4 " " $9 }') shutdown_when_empty wait_shutdown export EXPECTED="Starting Received msgnum:00000000: Received msgnum:00000001: Received msgnum:00000002: Received SIGUSR1, will terminate after the next message Received msgnum:00000003: Terminating without confirming the last message Starting Received msgnum:00000003: Received msgnum:00000004: Received SIGTERM, terminating Starting Received msgnum:00000005: Received msgnum:00000006: Received msgnum:00000007: Starting Received msgnum:00000008: Received msgnum:00000009: Terminating normally" cmp_exact $RSYSLOG_OUT_LOG if [[ "$start_fd_count" != "$end_fd_count" ]]; then echo "file descriptor leak: started with $start_fd_count open files, ended with $end_fd_count" error_exit 1 fi # Check that the child process does not inherit open fds from rsyslog # (apart from the pipes), and that stderr is redirected to /dev/null. # Ignore fd 255, which bash opens for internal use. EXPECTED_CHILD_LSOF="FD NAME 0r pipe 1w pipe 2w /dev/null" # On Solaris, lsof gives this alternate output: EXPECTED_CHILD_LSOF_2="FD NAME 0u (fifofs) 1u (fifofs) 2w " if [[ "$child_lsof" != "$EXPECTED_CHILD_LSOF" && "$child_lsof" != "$EXPECTED_CHILD_LSOF_2" ]]; then echo "unexpected open files for child process:" echo "$child_lsof" error_exit 1 fi # Check also that child process terminations are reported correctly. # When the reportChildProcessExits global parameter is "errors" (the default), # only non-zero exit codes are reported. content_check "(pid $child_pid_1) terminated; will be restarted" $RSYSLOG2_OUT_LOG custom_assert_content_missing "(pid $child_pid_1) exited with status" $RSYSLOG2_OUT_LOG content_check "(pid $child_pid_2) terminated; will be restarted" $RSYSLOG2_OUT_LOG content_check "(pid $child_pid_2) exited with status 1" $RSYSLOG2_OUT_LOG content_check "(pid $child_pid_3) terminated; will be restarted" $RSYSLOG2_OUT_LOG content_check "(pid $child_pid_3) terminated by signal 9" $RSYSLOG2_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-retry-timeout.sh0000644000000000000000000000013215216464436020412 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.906790846 30 ctime=1787067806.155944211 rsyslog-8.2608.0/tests/omhttp-retry-timeout.sh0000775000175000017500000000230315216464436020057 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Verify that omhttp retry handling copes with delayed failing responses when # restPathTimeout is shorter than the helper's failure delay. Success is that # retries eventually deliver the full sequence without duplicates or gaps. # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2500 export SEQ_CHECK_OPTIONS="-d" omhttp_start_server 0 --fail-every 1000 --fail-with-delay-secs 2 port="$omhttp_server_lstnport" generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="500") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") if $msg contains "msgnum:" then action( # Payload action.resumeRetryCount="-1" action.resumeInterval="1" name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$port'" restpath="my/endpoint" restpathtimeout="1000" checkpath="ping" batch="off" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $port my/endpoint omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse_localvar.sh0000644000000000000000000000013115216464436020470 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.906790846 30 ctime=1787067807.190963497 rsyslog-8.2608.0/tests/mmjsonparse_localvar.sh0000775000175000017500000000130115216464436020133 0ustar00rgerrger#!/bin/bash # added 2018-04-16 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' template(name="outfmt" type="string" string="%$.msgnum%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse" cookie="@cim:" container="$.") if $parsesuccess == "OK" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m $NUMMESSAGES -j "@cim: " shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imczmq-topic-too-long.sh0000644000000000000000000000013215171370365020415 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.906790846 30 ctime=1787067806.367948161 rsyslog-8.2608.0/tests/imczmq-topic-too-long.sh0000775000175000017500000000155115171370365020066 0ustar00rgerrger#!/bin/bash # Verify that imczmq rejects configured topics that exceed the supported limit. . ${srcdir:=.}/diag.sh init LONG_TOPIC=$(printf 'a%.0s' $(seq 1 256)) modpath="../runtime/.libs:../contrib/imczmq/.libs:../.libs" generate_conf add_conf ' module(load="../contrib/imczmq/.libs/imczmq") input(type="imczmq" endpoints="inproc://imczmq-topic-too-long" socktype="SUB" topics="'$LONG_TOPIC'") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$modpath" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 1 ]; then echo "FAIL: expected config validation failure for oversize imczmq topic" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi grep -F "configured topic exceeds maximum supported length" "${RSYSLOG_DYNNAME}.log" >/dev/null || { echo "FAIL: expected imczmq oversize topic validation error" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-mtls-vg.sh0000644000000000000000000000013215241075234021621 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.578970727 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-mtls-vg.sh0000775000175000017500000000012315241075234021264 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-mtls.sh rsyslog-8.2608.0/tests/PaxHeaders/fac_invld2.sh0000644000000000000000000000013215241075234016247 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.305909737 rsyslog-8.2608.0/tests/fac_invld2.sh0000775000175000017500000000116515241075234015721 0ustar00rgerrger#!/bin/bash # added 2014-10-01 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(type="string" name="outfmt" string="%msg:F,58:4%\n") invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m$NUMMESSAGES -P 3500000000 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-basic-2GB-file.sh0000644000000000000000000000013215216464436020061 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.907790863 30 ctime=1787067807.865976075 rsyslog-8.2608.0/tests/imfile-basic-2GB-file.sh0000775000175000017500000000340115216464436017526 0ustar00rgerrger#!/bin/bash # written 2018-11-09 by Rainer Gerhards # this test checks that 2GiB (31 bit) file size region is handled correctly # it first generates a file that is 2GiB-64 bytes, processes it, and then # adds a couple of messages to get it over 2GiB. # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init export TB_TEST_MAX_RUNTIME=3600 # test is very slow as it works on large files generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' touch $RSYSLOG_DYNNAME.input startup # initial file: 2GiB - 1 message (54 byte) ./inputfilegen -s 2147483584 -d47 -M $RSYSLOG_DYNNAME.msgcnt > $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input NUMMESSAGES="$(cat $RSYSLOG_DYNNAME.msgcnt)" export NUMMESSAGES wait_file_lines --delay 2500 --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES 3000 # add one message --> exactly 2GB ./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input (( NUMMESSAGES++ )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES # add one more message --> now we go over 2GB ./inputfilegen -m1 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input (( NUMMESSAGES++ )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES # add even more messages ./inputfilegen -m10000 -d47 -i$NUMMESSAGES>> $RSYSLOG_DYNNAME.input ls -lh $RSYSLOG_DYNNAME.input NUMMESSAGES=$(( NUMMESSAGES + 10000 )) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check 0 $(( NUMMESSAGES - 1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-imtcp-stream-always-zlib-basic.sh0000644000000000000000000000013215241075234023120 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.801581964 30 ctime=1787067805.616934166 rsyslog-8.2608.0/tests/yaml-imtcp-stream-always-zlib-basic.sh0000775000175000017500000000363215241075234022573 0ustar00rgerrger#!/bin/bash # added 2026-06-22 by Codex, released under ASL 2.0 # Verifies YAML parsing of imtcp stream compression input parameters. The # receiver is configured via YAML with compression.mode, compression.driver, # compression.maxExpansionRatio, and compression.maxDecompressedBytesPerReceive; # the sender uses omfwd to emit a zlib stream. The oracle is a complete, # ordered sequence at the receiver. . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=20000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"' add_yaml_conf '' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf " string: \"%msg:F,58:2%\\n\"" add_yaml_conf '' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imtcp' add_yaml_conf ' address: "127.0.0.1"' add_yaml_conf ' port: "0"' add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.tcpflood_port\"" add_yaml_conf ' compression.mode: "stream:always"' add_yaml_conf ' compression.driver: "zlib"' add_yaml_conf ' compression.maxExpansionRatio: "2048"' add_yaml_conf ' compression.maxDecompressedBytesPerReceive: "10485760"' add_yaml_conf ' ruleset: main' add_yaml_conf '' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: main' add_yaml_conf ' script: |' add_yaml_conf " :msg, contains, \"msgnum:\" action(type=\"omfile\"" add_yaml_conf " template=\"outfmt\" file=\"${RSYSLOG_OUT_LOG}\")" startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.driver="zlib" compression.stream.flushOnTXEnd="on") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazureeventhubs-basic-url.sh0000644000000000000000000000013215216464436021535 xustar0030 mtime=1782212894.076266993 30 atime=1782715518.906790846 30 ctime=1787067806.274946428 rsyslog-8.2608.0/tests/omazureeventhubs-basic-url.sh0000775000175000017500000000735215216464436021213 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full export NUMMESSAGES=100 export NUMMESSAGESFULL=$NUMMESSAGES export WAITTIMEOUT=20 # REQUIRES EXTERNAL ENVIRONMENT VARIABLES if [[ -z "${AZURE_HOST}" ]]; then echo "SKIP: AZURE_HOST environment variable not SET! Example: .servicebus.windows.net - SKIPPING" exit 77 fi if [[ -z "${AZURE_PORT}" ]]; then echo "SKIP: AZURE_PORT environment variable not SET! Example: 5671 - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY_NAME}" ]]; then echo "SKIP: AZURE_KEY_NAME environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_KEY}" ]]; then echo "SKIP: AZURE_KEY environment variable not SET! Example: - SKIPPING" exit 77 fi if [[ -z "${AZURE_CONTAINER}" ]]; then echo "SKIP: AZURE_CONTAINER environment variable not SET! Example: - SKIPPING" exit 77 fi export AMQPS_ADRESS="amqps://$AZURE_KEY_NAME:$AZURE_KEY@$AZURE_HOST:$AZURE_PORT/$AZURE_NAME" export AZURE_ENDPOINT="Endpoint=sb://$AZURE_HOST/;SharedAccessKeyName=$AZURE_KEY_NAME;SharedAccessKey=$AZURE_KEY;EntityPath=$AZURE_NAME" # --- Create/Start omazureeventhubs sender config generate_conf add_conf ' global( debug.whitelist="on" debug.files=["omazureeventhubs.c", "modules.c", "errmsg.c", "action.c"] ) # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") # Load mods module(load="../plugins/omazureeventhubs/.libs/omazureeventhubs") # templates template(name="outfmt" type="string" string="%msg:F,58:2%\n") local4.* { action( name="omazureeventhubs" type="omazureeventhubs" amqp_address="amqps://'$AZURE_KEY_NAME':'$AZURE_KEY'@'$AZURE_HOST'/'$AZURE_CONTAINER'" template="outfmt" action.resumeInterval="1" action.resumeRetryCount="2" ) action( type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") ' echo Starting sender instance [omazureeventhubs] startup echo Inject messages into rsyslog sender instance injectmsg 1 $NUMMESSAGES wait_file_lines $RSYSLOG_OUT_LOG $NUMMESSAGESFULL 100 # experimental: wait until kcat receives everything timeoutend=$WAITTIMEOUT timecounter=0 echo "CHECK $RSYSLOG_DYNNAME.pstats" while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) if [ -f "$RSYSLOG_DYNNAME.pstats" ] ; then # Read IMPSTATS for verification IMPSTATSLINE=$(cat $RSYSLOG_DYNNAME.pstats | grep "origin\=omazureeventhubs" | tail -1 | cut -d: -f5) SUBMITTED_MSG=$(echo $IMPSTATSLINE | grep "submitted" | cut -d" " -f2 | cut -d"=" -f2) FAILED_MSG=$(echo $IMPSTATSLINE | grep "failures" | cut -d" " -f3 | cut -d"=" -f2) ACCEPTED_MSG=$(echo $IMPSTATSLINE | grep "accepted" | cut -d" " -f4 | cut -d"=" -f2) if ! [[ $SUBMITTED_MSG =~ $re ]] ; then echo "**** omazureeventhubs WAITING FOR IMPSTATS" else if [ "$SUBMITTED_MSG" -ge "$NUMMESSAGESFULL" ]; then if [ "$ACCEPTED_MSG" -eq "$NUMMESSAGESFULL" ]; then echo "**** omazureeventhubs SUCCESS: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" shutdown_when_empty wait_shutdown #cp $RSYSLOG_DEBUGLOG DEBUGDEBUG.log exit_test else echo "**** omazureeventhubs FAIL: NUMMESSAGESFULL: $NUMMESSAGESFULL, SUBMITTED/WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" fi else echo "**** omazureeventhubs WAITING: SUBMITTED_MSG:$SUBMITTED_MSG, ACCEPTED_MSG: $ACCEPTED_MSG, FAILED_MSG: $FAILED_MSG" fi fi fi $TESTTOOL_DIR/msleep 1000 done unset count shutdown_when_empty wait_shutdown error_exit 1 rsyslog-8.2608.0/tests/PaxHeaders/func-substring-invld-startpos.sh0000644000000000000000000000013215131231047022172 xustar0030 mtime=1768239655.702212549 30 atime=1782715518.907790863 30 ctime=1787067804.045904891 rsyslog-8.2608.0/tests/func-substring-invld-startpos.sh0000777000175000017500000000102115131231047021635 0ustar00rgerrger#!/bin/bash # addd 2023-01-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="data:%$!my_struc_data%\n") set $!my_struc_data = substring($STRUCTURED-DATA, 2000, -3); local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data' shutdown_when_empty wait_shutdown export EXPECTED='data:' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/incltest_dir_wildcard.sh0000644000000000000000000000013215035412264020573 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.907790863 30 ctime=1787067804.946921681 rsyslog-8.2608.0/tests/incltest_dir_wildcard.sh0000777000175000017500000000050715035412264020246 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf add_conf "include(file=\"${srcdir}/testsuites/incltest.d/*.conf\") " startup # 100 messages are enough - the question is if the include is read ;) injectmsg 0 100 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-files-mtls.sh0000644000000000000000000000012715241075234021213 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067807.587970895 rsyslog-8.2608.0/tests/omfwd-tls-ossl-files-mtls.sh0000775000175000017500000000764415241075234020671 0ustar00rgerrger#!/bin/bash # Verify that omfwd with the ossl driver can establish a mutual-TLS session to # an OpenSSL-based remote peer when CA, certificate, and key are all loaded # from regular files. The oracle is that the remote helper, which requires a # valid client certificate, captures exactly one forwarded payload line for the # test message. The helper output may also contain rsyslog's own startup or # transport diagnostics, so the test matches the payload line rather than using # whole-file equality. All key material is created inside a per-test directory # to avoid collisions under parallel execution. . ${srcdir:=.}/diag.sh init check_command_available openssl if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi workdir="$RSYSLOG_DYNNAME.omfwd-tls-ossl-files-mtls" port_file="$workdir/server.port" server_capture="$workdir/server.capture" server_stderr="$workdir/server.stderr" mkdir -p "$workdir" cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 2048 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 2048 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 2048 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 ./openssl_mtls_server 0 "$workdir/server.pem" "$workdir/server.key" "$workdir/ca.pem" \ "$port_file" "$server_capture" 2>"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$workdir/ca.pem'" defaultNetstreamDriverCertFile="'$workdir/client.pem'" defaultNetstreamDriverKeyFile="'$workdir/client.key'" defaultNetstreamDriver="ossl" compatibility.defaults.secure="strict" net.ipprotocol="ipv4-only" ) module(load="builtin:omfwd") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "omfwd-ossl-files-mtls" then { action( type="omfwd" target="127.0.0.1" protocol="tcp" port="'$server_port'" template="outfmt" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) } ' startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - omfwd-ossl-files-mtls' wait_file_lines "$server_capture" 1 shutdown_when_empty wait_shutdown wait $server_pid || { cat "$server_stderr" error_exit 1 } content_count_check --regex '^omfwd-ossl-files-mtls$' 1 "$server_capture" exit_test rsyslog-8.2608.0/tests/PaxHeaders/pgsql-basic-cnf6-vg.sh0000644000000000000000000000013215035412264017710 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.906790846 30 ctime=1787067805.898939421 rsyslog-8.2608.0/tests/pgsql-basic-cnf6-vg.sh0000777000175000017500000000126015035412264017360 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' module(load="../plugins/ompgsql/.libs/ompgsql") if $msg contains "msgnum" then { action(type="ompgsql" server="127.0.0.1" db="syslogtest" user="postgres" pass="testbench") }' startup_vg injectmsg 0 5000 shutdown_when_empty wait_shutdown_vg check_exit_vg psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-msg.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_resource_path.sh0000644000000000000000000000013215241075234021664 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.959959192 rsyslog-8.2608.0/tests/rscript_faup_resource_path.sh0000775000175000017500000000210715241075234021333 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://user:pass@www.rsyslog.com:443/doc/v8-stable/rainerscript/functions/mo-faup.html?param=value#faup"; set $.faup = faup_resource_path($!url); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 /doc/v8-stable/rainerscript/functions/mo-faup.html' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/func-substring-large-neg-endpos.sh0000644000000000000000000000013215131231047022330 xustar0030 mtime=1768239655.702212549 30 atime=1782715518.907790863 30 ctime=1787067804.050904985 rsyslog-8.2608.0/tests/func-substring-large-neg-endpos.sh0000777000175000017500000000102415131231047021776 0ustar00rgerrger#!/bin/bash # addd 2023-01-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="data:%$!my_struc_data%\n") set $!my_struc_data = substring($STRUCTURED-DATA, 1, -9999999); local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data' shutdown_when_empty wait_shutdown export EXPECTED='data:' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imudp-listenportfilename-secure.sh0000644000000000000000000000013115216464436022553 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.907790863 29 ctime=1787067804.48691311 rsyslog-8.2608.0/tests/imudp-listenportfilename-secure.sh0000775000175000017500000000237015216464436022225 0ustar00rgerrger#!/bin/bash # Regression test for imudp listenPortFileName path handling. The listener # writes its bound port before privilege drop, so the oracle is an internal # diagnostic that rejects a symlink handoff path plus an unchanged symlink # target. The timeout only bounds the foreground daemon after config activation. . ${srcdir:=.}/diag.sh init TARGET_FILE="${RSYSLOG_DYNNAME}.target" PORT_FILE="${RSYSLOG_DYNNAME}.imudp_port" printf 'must-stay-intact\n' > "$TARGET_FILE" ln -s "$TARGET_FILE" "$PORT_FILE" generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_FILE'") ' startup_common set +e timeout 3 ../tools/rsyslogd -C -n -i"${RSYSLOG_PIDBASE}.pid" -M"$RSYSLOG_MODDIR" -f"$CONF_FILE" \ >"${RSYSLOG_DYNNAME}.startup.log" 2>&1 rc=$? set -e if [ "$rc" -eq 0 ]; then echo "FAIL: expected foreground rsyslogd to keep running or report an error after activation, rc=$rc" cat "${RSYSLOG_DYNNAME}.startup.log" error_exit 1 fi printf 'must-stay-intact\n' > "${RSYSLOG_DYNNAME}.expected" cmp_exact_file "${RSYSLOG_DYNNAME}.expected" "$TARGET_FILE" content_check "listenPortFileName: refusing to write to non-regular file" "${RSYSLOG_DYNNAME}.startup.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_set_memleak-vg.sh0000644000000000000000000000013215131231047020700 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.907790863 30 ctime=1787067805.191926247 rsyslog-8.2608.0/tests/rscript_set_memleak-vg.sh0000777000175000017500000000205715131231047020355 0ustar00rgerrger#!/bin/bash # A test that checks for memory leaks # created based on real world case: # https://github.com/rsyslog/rsyslog/issues/1376 # Copyright 2017-01-24 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 generate_conf add_conf ' template(name="json" type="string" string="%$!%\n") template(name="ts" type="string" string="%timestamp:::date-rfc3339%") ruleset(name="rcvr" queue.type="LinkedList" queue.timeoutShutdown="'$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT'") { set $.index="unknown"; set $.type="unknown"; set $.interval=$$now & ":" & $$hour; set $!host_forwarded=$hostname; set $!host_received=$$myhostname; set $!time_received=$timegenerated; set $!@timestamp=exec_template("ts"); action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="json" ) }' startup_vg injectmsg shutdown_when_empty wait_shutdown_vg check_exit_vg # note: we check only the valgrind result, we are not really interested # in the output data (non-standard format in any way...) exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmutf8fix_replacement_sequence.sh0000644000000000000000000000013215241075234022436 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.686579811 30 ctime=1787067805.676935284 rsyslog-8.2608.0/tests/mmutf8fix_replacement_sequence.sh0000775000175000017500000000472315241075234022113 0ustar00rgerrger#!/bin/bash # Validate mmutf8fix replacementSequence for invalid UTF-8 in message, tag, # and structured data fields. The oracle is the configured omfile destination # after synchronized shutdown, proving the rewritten fields reached the normal # output path. Invalid bytes are replaced once per byte with the configured # UTF-8 replacement sequence. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmutf8fix/.libs/mmutf8fix") module(load="../plugins/imtcp/.libs/imtcp") parser(name="custom.rfc3164" type="pmrfc3164" force.tagEndingByColon="on") template(name="sdoutfmt" type="string" string="%structured-data%|%msg%\n") template(name="tagoutfmt" type="string" string="%syslogtag%|%msg%\n") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_sd_port" ruleset="sdtest") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_tag_port" ruleset="tagtest") ruleset(name="sdtest") { action(type="mmutf8fix" replacementSequence="\xef\xbf\xbd") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="sdoutfmt") } ruleset(name="tagtest" parser="custom.rfc3164") { action(type="mmutf8fix" replacementSequence="\357\277\275") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="tagoutfmt") }' startup wait_file_exists "$RSYSLOG_DYNNAME.tcpflood_sd_port" wait_file_exists "$RSYSLOG_DYNNAME.tcpflood_tag_port" printf '<134>1 2026-06-01T00:00:00Z host app proc msgid [test@32473 dirty="Brain\xa0Twist"] bad\xc0\x80 utf8\n' \ > "$RSYSLOG_DYNNAME.input" tcpflood -p"$(cat "$RSYSLOG_DYNNAME.tcpflood_sd_port")" -m1 -I "$RSYSLOG_DYNNAME.input" printf '<134>1 2026-06-01T00:00:00Z host app proc msgid [test@32473 clean="ok"] split\xe0\xa0Xtail\n' \ > "$RSYSLOG_DYNNAME.input" tcpflood -p"$(cat "$RSYSLOG_DYNNAME.tcpflood_sd_port")" -m1 -I "$RSYSLOG_DYNNAME.input" printf '<129>Mar 10 01:00:00 host bad\xc0tag: tag payload\n' > "$RSYSLOG_DYNNAME.input" tcpflood -p"$(cat "$RSYSLOG_DYNNAME.tcpflood_tag_port")" -m1 -I "$RSYSLOG_DYNNAME.input" rm -f "$RSYSLOG_DYNNAME.input" shutdown_when_empty wait_shutdown { printf '[test@32473 dirty="Brain\357\277\275Twist"]|bad\357\277\275\357\277\275 utf8\n' printf '[test@32473 clean="ok"]|split\357\277\275\357\277\275Xtail\n' printf 'bad\357\277\275tag:| tag payload\n' } > "$RSYSLOG_OUT_LOG.expect" cmp_exact_file "$RSYSLOG_OUT_LOG.expect" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-script-call.sh0000644000000000000000000000013115241075234017414 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 29 ctime=1787067805.38692988 rsyslog-8.2608.0/tests/yaml-script-call.sh0000775000175000017500000000227615241075234017073 0ustar00rgerrger#!/bin/bash # Tests the "call" statement inside a YAML script: block. # Two rulesets (rs1 and rs2) are defined in the same YAML file. # Messages arrive on the input bound to rs1; rs1 calls rs2; rs2 writes # the message to the output file. # Mirrors rscript_ruleset_call.sh using YAML configuration. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=5000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" rulesets: - name: rs2 script: | action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}") stop - name: rs1 script: | if $msg contains "msgnum:" then call rs2 YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="rs1") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/config-translate-yaml-to-rs.sh0000644000000000000000000000013215171370365021507 xustar0030 mtime=1776677109.457913326 30 atime=1782715518.907790863 30 ctime=1787067805.337928967 rsyslog-8.2608.0/tests/config-translate-yaml-to-rs.sh0000775000175000017500000000166515171370365021166 0ustar00rgerrger#!/bin/bash # check canonical translation from YAML to RainerScript. # # Part of the testbench for rsyslog. # # This file is part of rsyslog. # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init modpath="../runtime/.libs:../plugins/omstdout/.libs:../.libs" cat > "${RSYSLOG_DYNNAME}.yaml" <<'YAML_EOF' version: 2 modules: - load: "omstdout" mainqueue: queue.type: "Direct" rulesets: - name: "main" script: | action(type="omstdout") YAML_EOF ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.yaml" -F rainerscript -o "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath" cat > "${RSYSLOG_DYNNAME}.expected.conf" <<'RS_EOF' main_queue(queue.type="Direct") module(load="omstdout") ruleset(name="main") { action(type="omstdout") } RS_EOF cmp_exact_file "${RSYSLOG_DYNNAME}.expected.conf" "${RSYSLOG_DYNNAME}.out.conf" ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath" echo SUCCESS: YAML to RainerScript translation exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtuxedoulog_errmsg_no_params-vg.sh0000644000000000000000000000013215171370365023022 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.905790829 30 ctime=1787067808.183982001 rsyslog-8.2608.0/tests/imtuxedoulog_errmsg_no_params-vg.sh0000775000175000017500000000023115171370365022465 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/imtuxedoulog_errmsg_no_params.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_mozilla_tld.sh0000644000000000000000000000013215241075234021333 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.966959323 rsyslog-8.2608.0/tests/rscript_faup_mozilla_tld.sh0000775000175000017500000000331715241075234021006 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/ffaup/.libs/ffaup") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.faup%\n") if (not($msg contains "msgnum:")) then stop set $!url = "https://www.testing.co.uk"; set $.faup = faup($!url); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 3 wait_file_lines "$RSYSLOG_OUT_LOG" 3 60 shutdown_when_empty wait_shutdown # if the FAUP module has access to its mozilla.tlds file listing second-degree TLDs, the tld here should be "co.uk" and not simply "uk" EXPECTED=' msgnum:00000000: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "testing.co.uk", "domain_without_tld": "testing", "host": "www.testing.co.uk", "tld": "co.uk", "port": "", "resource_path": "", "query_string": "", "fragment": "" } msgnum:00000001: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "testing.co.uk", "domain_without_tld": "testing", "host": "www.testing.co.uk", "tld": "co.uk", "port": "", "resource_path": "", "query_string": "", "fragment": "" } msgnum:00000002: 0 { "scheme": "https", "credential": "", "subdomain": "www", "domain": "testing.co.uk", "domain_without_tld": "testing", "host": "www.testing.co.uk", "tld": "co.uk", "port": "", "resource_path": "", "query_string": "", "fragment": "" }' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmexternal-single-instance.sh0000644000000000000000000000013115216464436021504 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.905790829 30 ctime=1787067804.110906103 rsyslog-8.2608.0/tests/mmexternal-single-instance.sh0000775000175000017500000000336715216464436021165 0ustar00rgerrger#!/bin/bash # This regression verifies that mmexternal forceSingleInstance="on" really # shares one helper across many workers. The oracle checks that the helper # writes exactly one Starting line, one Terminating line, and one Received line # per injected message while downstream omfile still receives every message. . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris" export NUMMESSAGES=10000 generate_conf add_conf ' module(load="../plugins/mmexternal/.libs/mmexternal") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="mmexternal" binary="'$srcdir'/testsuites/mmexternal-single-instance-bin.sh '$RSYSLOG_DYNNAME'.side" forceSingleInstance="on" queue.type="LinkedList" queue.workerThreads="10" queue.size="5000" queue.timeoutShutdown="30000" ) action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup injectmsg shutdown_when_empty wait_shutdown start_count=$(grep -c '^Starting$' "$RSYSLOG_DYNNAME.side" | awk '{print $1}') term_count=$(grep -c '^Terminating$' "$RSYSLOG_DYNNAME.side" | awk '{print $1}') recv_count=$(grep -c '^Received .*msgnum:' "$RSYSLOG_DYNNAME.side" | awk '{print $1}') line_count=$(wc -l < "$RSYSLOG_OUT_LOG" | awk '{print $1}') if (( start_count != 1 )); then echo "unexpected helper start count: $start_count" error_exit 1 fi if (( term_count != 1 )); then echo "unexpected helper termination count: $term_count" error_exit 1 fi if (( recv_count != NUMMESSAGES )); then echo "unexpected helper receive count: $recv_count (expected: $NUMMESSAGES)" error_exit 1 fi if (( line_count != NUMMESSAGES )); then echo "unexpected output line count: $line_count (expected: $NUMMESSAGES)" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_anon_ipv6.sh0000644000000000000000000000013215216464436020410 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.904790812 30 ctime=1787067807.299965528 rsyslog-8.2608.0/tests/sndrcv_tls_anon_ipv6.sh0000775000175000017500000000427615216464436020070 0ustar00rgerrger#!/bin/bash # rgerhards, 2011-04-04 # testing sending and receiving via TLS with anon auth using bare ipv6, no SNI # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-ipv6-available export NUMMESSAGES=25000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # start up the instances export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem" defaultNetstreamDriver="gtls" debug.whitelist="on" debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100" streamDriver.mode="1" streamDriver.authMode="anon") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup #unset RSYSLOG_DEBUG # suppress this debug log, if you want export PORT_RCVR=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" defaultNetstreamDriver="gtls" ) # set up the action $DefaultNetstreamDriver gtls # use gtls netstream driver $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@[::1]:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_drvr.sh0000644000000000000000000000013215035412264016573 xustar0030 mtime=1752569012.413660417 30 atime=1782715518.904790812 30 ctime=1787067808.241983082 rsyslog-8.2608.0/tests/sndrcv_drvr.sh0000777000175000017500000000006515035412264016245 0ustar00rgerrger#!/bin/bash . $srcdir/sndrcv_drvr_noexit.sh $1 $2 $3 rsyslog-8.2608.0/tests/PaxHeaders/pmrfc3164-tagEndingByColon.sh0000644000000000000000000000013215241075234021051 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067804.335910295 rsyslog-8.2608.0/tests/pmrfc3164-tagEndingByColon.sh0000775000175000017500000000224715241075234020525 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser") parser(name="custom.rfc3164" type="pmrfc3164" force.tagEndingByColon="on") template(name="outfmt" type="string" string="-%syslogtag%-%msg%-\n") ruleset(name="customparser" parser="custom.rfc3164") { :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 tag1: msgnum:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname2 tag2: msgnum:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag3 msgnum:3\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname4 tag4 :\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname5 tag5:msgnum:5\"" shutdown_when_empty wait_shutdown echo '-tag1:- msgnum:1- -tag2:- msgnum:2- -tag5:-msgnum:5-' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zstd-truncated.sh0000644000000000000000000000013115241075234023113 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.774581459 30 ctime=1787067805.585933589 rsyslog-8.2608.0/tests/imtcp-stream-always-zstd-truncated.sh0000775000175000017500000000370515241075234022570 0ustar00rgerrger#!/bin/bash # added 2026-05-17 by Codex, released under ASL 2.0 # Sends a truncated zstd stream that contains one syslog message; imtcp must # preserve that message and log the truncated stream. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime check_command_available python3 check_command_available zstd wait_truncated_stream_result() { content_check --check-only "imtcp: detected truncated compressed stream" "$RSYSLOG_OUT_LOG" || return 1 [ -f "$RSYSLOG2_OUT_LOG" ] || return 1 [ "$(wc -l < "$RSYSLOG2_OUT_LOG")" -eq 1 ] } export QUEUE_EMPTY_CHECK_FUNC=wait_truncated_stream_result generate_conf add_conf ' $MaxMessageSize 10k global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zstd") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $syslogtag contains "rsyslogd" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action(type="omfile" file="'$RSYSLOG2_OUT_LOG'" template="outfmt") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" printf '<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\n' > "$RSYSLOG_DYNNAME.rawmsg" zstd -q -c "$RSYSLOG_DYNNAME.rawmsg" > "$RSYSLOG_DYNNAME.zst" python3 - "$TCPFLOOD_PORT" "$RSYSLOG_DYNNAME.zst" <<'PY' import socket import sys port = int(sys.argv[1]) path = sys.argv[2] with open(path, "rb") as stream: payload = stream.read() sock = socket.create_connection(("127.0.0.1", port)) sock.sendall(payload[:-1]) sock.close() PY shutdown_when_empty wait_shutdown content_check "imtcp: detected truncated compressed stream" if [ ! -f "$RSYSLOG2_OUT_LOG" ] || [ "$(cat "$RSYSLOG2_OUT_LOG")" != "1" ]; then echo "FAIL: truncated compressed stream did not preserve already decompressed message" test -f "$RSYSLOG2_OUT_LOG" && cat "$RSYSLOG2_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_annotate_large.sh0000644000000000000000000000013215216464436021155 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.912790948 30 ctime=1787067804.673916594 rsyslog-8.2608.0/tests/imuxsock_annotate_large.sh0000775000175000017500000000152115216464436020623 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "trusted property annotation depends on Linux credentials/procfs behavior" export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global(maxMessageSize="8k") module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket" Annotate="on" ParseTrusted="off") template(name="outfmt" type="string" string="%rawmsg%\n") *.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup long_arg="$(printf 'quoted\\\\value\\"%.0s' {1..300})" ./syslog_caller -m1 -u "$RSYSLOG_DYNNAME-testbench_socket" -L 3900 -w 1000 -- "$long_arg" shutdown_when_empty wait_shutdown content_check "_PID=" content_check "_CMDLINE=\"" content_check "quoted" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmutf8fix_tag.sh0000644000000000000000000000013215241075234017022 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.782581608 30 ctime=1787067805.680935359 rsyslog-8.2608.0/tests/mmutf8fix_tag.sh0000775000175000017500000000260015241075234016467 0ustar00rgerrger#!/bin/bash ## Validate mmutf8fix tag handling for invalid UTF-8. # add 2021-01 Jan Jeronym Zvanovec , released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmutf8fix/.libs/mmutf8fix") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser") parser(name="custom.rfc3164" type="pmrfc3164" force.tagEndingByColon="on") template(name="outfmt" type="string" string="-%syslogtag%-%msg%-\n") ruleset(name="customparser" parser="custom.rfc3164") { action(type="mmutf8fix" replacementChar="?") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 řƒ:\"" tcpflood -m1 -M "\"<129>mar 10 01:00:00 hostname1 :\"" printf -v broken_utf '%b' '\xA0\xAA\x44\xE4\x5E\xC4\x7B\x28\x93\x68' tcpflood -m1 -M "\"<129>mar 10 01:00:00 hostname1 ${broken_utf}:\"" shutdown_when_empty wait_shutdown printf '%b' $'-\xC3\x85\xC2\x99\xC2\x83:--\n-\xC3\x80\xC2\x80:--\n-??D?^?{(?h:--\n' \ > "$RSYSLOG_OUT_LOG.expect" if ! cmp "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG; then echo "invalid response generated, $RSYSLOG_OUT_LOG diff:" # Use LANG=C for binary matching LANG=C diff --text -u "$RSYSLOG_OUT_LOG.expect" $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmsnare-ccoff.sh0000644000000000000000000000013215241075234016763 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067807.833975479 rsyslog-8.2608.0/tests/pmsnare-ccoff.sh0000775000175000017500000001314015241075234016431 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/pmsnare/.libs/pmsnare") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") global(localHostname="localhost") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\"" tcpflood -m1 -M "\"hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 5061 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain System Integrity Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0 -0000000000\"" shutdown_when_empty wait_shutdown echo '14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti 14,user,info,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0114624#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011Logon#011#011An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................ 13,user,notice,MSWinEventLog,MSWinEventLog, 1#011Security#01100000000#011Sun May 21 12:00:01.123#0115061#011Microsoft-Windows-Security-Auditing#011N/A#011N/A#011Success Audit#011hostname.domain#011System Integrity#011#011Cryptographic operation. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Cryptographic Parameters: Provider Name: Microsoft Software Key Storage Provider Algorithm Name: RSA Key Name: le-c6bdb786-1851-4159-b5ea-5e3966571698 Key Type: Machine key. Cryptographic Operation: Operation: Open Key. Return Code: 0x0#011-0000000000' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/fieldtest.sh0000644000000000000000000000013215241075234016223 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067803.655897624 rsyslog-8.2608.0/tests/fieldtest.sh0000775000175000017500000000170615241075234015676 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%msg:F,32:2%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: DROP_url_www.sina.com.cn:IN=eth1 OUT=eth0 SRC=192.168.10.78 DST=61.172.201.194 LEN=1182 TOS=0x00 PREC=0x00 TTL=63 ID=14368 DF PROTO=TCP SPT=33343 DPT=80 WINDOW=92 RES=0x00 ACK PSH URGP=0\"" shutdown_when_empty wait_shutdown echo 'DROP_url_www.sina.com.cn:IN=eth1' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_not_supported3.sh0000644000000000000000000000013215035412264023531 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.910790914 30 ctime=1787067808.107980585 rsyslog-8.2608.0/tests/imbatchreport_errmsg_not_supported3.sh0000777000175000017500000000061615035412264023205 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" reports="*.done") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "either 'rename' or 'delete' must be set" exit_test rsyslog-8.2608.0/tests/PaxHeaders/include-obj-text-vg.sh0000644000000000000000000000013215216464436020037 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.910790914 30 ctime=1787067805.151925501 rsyslog-8.2608.0/tests/include-obj-text-vg.sh0000775000175000017500000000106415216464436017507 0ustar00rgerrger#!/bin/bash # added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf INCLFILE="${srcdir}/testsuites/include-std-omfile-action.conf" CONF_SNIPPET=$(cat $INCLFILE) export CONF_SNIPPET printf "\nThis SNIPPET will be included via env var:\n$CONF_SNIPPET\n\nEND SNIPPET\n" add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { include(text=`echo $CONF_SNIPPET`) } ' startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg seq_check 0 9 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_exists-not2.sh0000644000000000000000000000013215131231047020177 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.910790914 30 ctime=1787067804.899920806 rsyslog-8.2608.0/tests/rscript_exists-not2.sh0000777000175000017500000000103115131231047017643 0ustar00rgerrger#!/bin/bash # add 2020-10-02 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%!result%\n") set $!somevar = "test"; # this makes matters a bit more complicated if $msg contains "msgnum" then { if exists($!p1!p2!val) then set $!result = "on"; else set $!result = "off"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='off' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmtaghostname_server.sh0000644000000000000000000000013115241075234020471 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067808.136981125 rsyslog-8.2608.0/tests/mmtaghostname_server.sh0000775000175000017500000000214115241075234020137 0ustar00rgerrger#!/bin/bash # add 2016-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/mmtaghostname/.libs/mmtaghostname") global(localhostname="frontAPP") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") template(name="test" type="string" string="tag: %syslogtag%, server: %hostname%, msg: %msg%\n") ruleset(name="ruleset") { action(type="mmtaghostname" forcelocalhostname="on") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="test") } ' startup tcpflood -m1 -M "\"<189>1 2019-03-03T16:09:56.185+00:00 server app 123.4 msgid - %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)\"" shutdown_when_empty wait_shutdown echo 'tag: app[123.4], server: frontAPP, msg: %SYS-5-CONFIG_I: Configured from console by adminsepp on vty0 (10.23.214.226)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_mbedtls_certvalid_expired_autrzd.sh0000644000000000000000000000013215241075234025301 xustar0030 mtime=1787067036.644579024 30 atime=1787067036.797581889 30 ctime=1787067807.432968007 rsyslog-8.2608.0/tests/sndrcv_tls_mbedtls_certvalid_expired_autrzd.sh0000775000175000017500000000363015241075234024752 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="mbedtls" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.PermitExpiredCerts="on" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export PORT_RCVR=$TCPFLOOD_PORT #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'" defaultNetstreamDriver="mbedtls" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-old-state-file.sh0000644000000000000000000000013215216464436020324 xustar0030 mtime=1782212894.055266653 30 atime=1782715518.909790897 30 ctime=1787067807.997978535 rsyslog-8.2608.0/tests/imfile-old-state-file.sh0000775000175000017500000000514715216464436020002 0ustar00rgerrger#!/bin/bash # this test checks that old (v1, pre 8.34.0) imfile state files are # properly read in. It is based on imfile-readmode2-with-persists.sh, # where the first part before the shutdown is removed, and an old state # file is populated. Note that in contrast to the original test the # initial set of lines from the input file is missing - this is # exactly what shall happen. # This is part of the rsyslog testbench, licensed under ASL 2.0 # added 2018-03-29 by rgerhards . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' # do mock-up setup echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input # we need to patch the state file to match the current inode number inode=$(ls -i $RSYSLOG_DYNNAME.input|awk '{print $1}') leninode=${#inode} newline="+inode:2:${leninode}:${inode}:" sed s/+inode:2:7:4464465:/${newline}/ <$srcdir/testsuites/imfile-old-state-file_imfile-state_.-rsyslog.input > ${RSYSLOG_DYNNAME}.spool/imfile-state:.-$RSYSLOG_DYNNAME.input printf "info: new input file: $(ls -i $RSYSLOG_DYNNAME.input)\n" printf "info: new inode line: ${newline}\n" printf "info: patched state file:\n" cat ${RSYSLOG_DYNNAME}.spool/imfile-state:.-$RSYSLOG_DYNNAME.input startup echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" cat $RSYSLOG_OUT_LOG error_exit 1 else # note: we expect only 2 headers as the first file part if NOT processed! if [ ! $NUMLINES -eq 2 ]; then echo "ERROR: expecting 2 headers, got $NUMLINES" cat $RSYSLOG_OUT_LOG error_exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {2..4}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" cat $RSYSLOG_OUT_LOG error_exit 1 fi done exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrelp-invld-tlslib.sh0000644000000000000000000000013115035412264020135 xustar0030 mtime=1752569012.406709056 29 atime=1782715518.90879088 30 ctime=1787067807.706973112 rsyslog-8.2608.0/tests/omrelp-invld-tlslib.sh0000777000175000017500000000070415035412264017610 0ustar00rgerrger#!/bin/bash # see that we can an error message if wrong tls lib is selected # addd 2019-02-09 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_relpEngineSetTLSLibByName generate_conf add_conf ' module(load="../plugins/omrelp/.libs/omrelp" tls.tlslib="invalid-tlslib-name") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty content_check --regex "omrelp.*invalid-tlslib-name.*not accepted" exit_test rsyslog-8.2608.0/tests/PaxHeaders/timereported-utc.sh0000644000000000000000000000013115131231047017525 xustar0030 mtime=1768239655.725212925 29 atime=1782715518.90879088 30 ctime=1787067805.858938676 rsyslog-8.2608.0/tests/timereported-utc.sh0000777000175000017500000000157615131231047017210 0ustar00rgerrger#!/bin/bash # addd 2016-03-22 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=3 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' template(name="outfmt" type="list") { property(name="timereported" dateformat="rfc3339" date.inUTC="on") constant(value="\n") } :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg_literal "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000" injectmsg_literal "<165>1 2016-03-01T12:00:00-02:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000" injectmsg_literal "<165>1 2016-03-01T12:00:00Z 192.0.2.1 tcpflood 8710 - - msgnum:0000000" shutdown_when_empty wait_shutdown export EXPECTED="2003-08-24T12:14:15.000003+00:00 2016-03-01T14:00:00.000000+00:00 2016-03-01T12:00:00.000000+00:00" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_both_modes_compatible.sh0000644000000000000000000000013015131231047022117 xustar0030 mtime=1768239655.708212647 29 atime=1782715518.90879088 29 ctime=1787067805.76093685 rsyslog-8.2608.0/tests/mmanon_both_modes_compatible.sh0000777000175000017500000000202315131231047021567 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.enable="on" ipv4.mode="zero" ipv4.bits="32" ipv6.bits="128" ipv6.anonmode="zero" ipv6.enable="on") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 tag: 1.1.1.8 space 61:34:ad::7:F <129>Mar 10 01:00:00 172.20.245.8 tag: 111.1.1.8 <129>Mar 10 01:00:00 172.20.245.8 tag: abf:3:002::500F:ce 1.1.1.9\"" shutdown_when_empty wait_shutdown export EXPECTED=' 0:0:0:0:0:0:0:0 0.0.0.0 space 0:0:0:0:0:0:0:0 0.0.0.0 0:0:0:0:0:0:0:0 0.0.0.0' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-basic-hup.sh0000644000000000000000000000013215241075234017225 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067805.490931818 rsyslog-8.2608.0/tests/imtcp-basic-hup.sh0000775000175000017500000000133715241075234016700 0ustar00rgerrger#!/bin/bash # added 2019-07-30 by RGerhards, released under ASL 2.0 export NUMMESSAGES=4000 # MUST be an even number! . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) issue_HUP tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 2)) -i$((NUMMESSAGES / 2)) shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-compress-size-limit.sh0000644000000000000000000000013215241075234024074 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067806.399948757 rsyslog-8.2608.0/tests/imhttp-post-payload-compress-size-limit.sh0000775000175000017500000000447315241075234023553 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify that imhttp applies the request body limit after gzip decompression, # not only to the compressed wire body. The request uses octet-counted framing # so a successful rejection cannot leave a partial message behind: the oracle is # HTTP 413 plus an empty output file. . ${srcdir:=.}/diag.sh init check_command_available python3 generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%rawmsg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" supportoctetcountedframing="on") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" response=$(python3 - "$IMHTTP_PORT" <<'PY' import gzip import socket import sys MAX_REQUEST_BODY_SIZE = 16 * 1024 * 1024 port = int(sys.argv[1]) payload = b"A" * (MAX_REQUEST_BODY_SIZE + 1) body = str(len(payload)).encode("ascii") + b" " + payload compressed = gzip.compress(body, compresslevel=9) if len(compressed) >= MAX_REQUEST_BODY_SIZE: raise SystemExit("compressed reproducer body unexpectedly exceeds the wire-size limit") request = b"".join( [ b"POST /postrequest HTTP/1.1\r\n", b"Host: localhost\r\n", b"Content-Encoding: gzip\r\n", b"Content-Length: " + str(len(compressed)).encode("ascii") + b"\r\n", b"Connection: close\r\n", b"\r\n", compressed, ] ) with socket.create_connection(("127.0.0.1", port), timeout=10) as sock: sock.settimeout(10) sock.sendall(request) response = b"" while True: chunk = sock.recv(4096) if not chunk: break response += chunk print(response.decode("latin1", "replace").splitlines()[0] if response else "") PY ) echo "response: $response" case "$response" in *" 413 "*) ;; *) echo "ERROR: gzip-expanded request body was not rejected with 413" error_exit 1 ;; esac wait_queueempty shutdown_when_empty wait_shutdown if [ -s "$RSYSLOG_OUT_LOG" ]; then echo "ERROR: gzip-expanded oversized request produced output" ls -l "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-basic-legacy.sh0000644000000000000000000000013215131231047020020 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.912790948 30 ctime=1787067807.872976206 rsyslog-8.2608.0/tests/imfile-basic-legacy.sh0000777000175000017500000000153015131231047017470 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init NUMMESSAGES=50000 mkdir WorkDirectory $RSYSLOG_DYNNAME.work generate_conf add_conf ' $WorkDirectory '$RSYSLOG_DYNNAME'.work $ModLoad ../plugins/imfile/.libs/imfile $InputFileName ./'$RSYSLOG_DYNNAME'.input $InputFileTag file: $InputFileStateFile stat-file1 $InputFileSeverity error $InputFileFacility local7 $InputFileMaxLinesAtOnce 100000 $InputRunFileMonitor $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' # generate input file first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). ./inputfilegen -m $NUMMESSAGES > $RSYSLOG_DYNNAME.input startup wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/action-ratelimit-pace.sh0000644000000000000000000000013215241075234020413 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.682579736 30 ctime=1787067805.353929265 rsyslog-8.2608.0/tests/action-ratelimit-pace.sh0000775000175000017500000000233215241075234020062 0ustar00rgerrger#!/bin/bash # Verify generic action-level output rate limiting in pace mode. # The linked-list action queue is required so pacing sleeps only the action # worker. Four messages with burst two must all be delivered, and elapsed time # must show that the second window was reached instead of dropping excess # messages. . ${srcdir:=.}/diag.sh init POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.output-pace.yaml" cat > "$POLICY_FILE" << 'YAMLEOF' scope: output mode: pace interval: 1 burst: 2 YAMLEOF generate_conf add_conf ' ratelimit(name="out_pace" policy="'$POLICY_FILE'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" queue.type="linkedlist" action.ratelimit.name="out_pace") ' startup start_time=$(date +%s) injectmsg 0 4 shutdown_when_empty wait_shutdown end_time=$(date +%s) wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" 4 1 seq_check 0 3 elapsed=$((end_time - start_time)) if [ "$elapsed" -lt 1 ]; then echo "FAIL: pace mode delivered all messages without observable pacing (elapsed ${elapsed}s)" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock-NUL.sh0000644000000000000000000000013115216464436016545 xustar0030 mtime=1782212894.071266911 30 atime=1782715518.912790948 29 ctime=1787067804.67691665 rsyslog-8.2608.0/tests/imuxsock-NUL.sh0000775000175000017500000000205515216464436016217 0ustar00rgerrger#!/usr/bin/env bash # Regression test for issue #4941: an imuxsock datagram containing an embedded # NUL byte must be processed using the received datagram length, sanitized as # "#000", and written without leaking uninitialized bytes from the receive # buffer. The oracle is exact raw-message output after synchronized shutdown. . "${srcdir:=.}/diag.sh" init export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%rawmsg%\n") if $rawmsg startswith "<1>a" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup ./syslog_caller -u "$RSYSLOG_DYNNAME-testbench_socket" -s 1 -m 1 -n shutdown_when_empty wait_shutdown content_check --regex '^<1>a#000b$' if [ "$(wc -l < "$RSYSLOG_OUT_LOG")" -ne 1 ]; then echo "unexpected extra output generated, $RSYSLOG_OUT_LOG is:" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl_setenv_2_vars.sh0000644000000000000000000000013215171402221020010 xustar0030 mtime=1776682129.619271137 30 atime=1782715518.912790948 30 ctime=1787067804.089905711 rsyslog-8.2608.0/tests/glbl_setenv_2_vars.sh0000775000175000017500000000143615171402221017463 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(environment=["http_proxy=http://127.0.0.1", "SECOND=OK OK"]) set $!prx = getenv("http_proxy"); set $!second = getenv("SECOND"); template(name="outfmt" type="string" string="%$!prx%, %$!second%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! echo 'http://127.0.0.1, OK OK' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid content seen, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/mysql-actq-mt-withpause.sh0000644000000000000000000000013215216464436020770 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.912790948 30 ctime=1787067805.919939812 rsyslog-8.2608.0/tests/mysql-actq-mt-withpause.sh0000775000175000017500000000452615216464436020446 0ustar00rgerrger#!/bin/bash # Verify that ommysql keeps multi-worker action queue delivery lossless across # worker idle timeout cycles. The test injects three batches separated by # queue-empty waits and short sleeps so action workers can time out and be # restarted. Each batch wait is synchronized on the corresponding MySQL row # count and sequence range, not just the main queue, because a slow CI database # can still be draining the action queue after imdiag reports the main queue # empty. # The 80s enqueue timeout is a CI tolerance budget: if a stressed # MySQL service cannot drain the action queue in that time, the failure should # be reevaluated instead of masking a persistent service or test issue. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=150000 mysql_actq_count_ready() { if [ "${MYSQL_ACTQ_LAST_MSG:-}" = "" ]; then printf 'FAIL: MYSQL_ACTQ_LAST_MSG is unset before MySQL sequence check\n' error_exit 1 fi expected_count=$((MYSQL_ACTQ_LAST_MSG + 1)) count=$(mysql -N -s --user=rsyslog --password=testbench \ --database "$RSYSLOG_DYNNAME" \ -e "select count(*) from SystemEvents;" \ 2> "$RSYSLOG_DYNNAME.mysqlerr") ret=$? grep -iv "Using a password on the command line interface can be insecure." \ < "$RSYSLOG_DYNNAME.mysqlerr" if [ "$ret" -ne 0 ]; then error_exit "$ret" fi [ "$count" -ge "$expected_count" ] } mysql_actq_data_ready() { mysql_actq_count_ready || return 1 mysql_get_data seq_check --check-only 0 "$MYSQL_ACTQ_LAST_MSG" } export QUEUE_EMPTY_CHECK_FUNC=mysql_actq_data_ready generate_conf add_conf ' module(load="../plugins/ommysql/.libs/ommysql") :msg, contains, "msgnum:" { action(type="ommysql" server="127.0.0.1" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench" queue.size="10000" queue.type="linkedList" queue.workerthreads="5" queue.workerthreadMinimumMessages="500" queue.timeoutWorkerthreadShutdown="1000" queue.timeoutEnqueue="80000" ) } ' mysql_prep_for_test startup injectmsg 0 50000 MYSQL_ACTQ_LAST_MSG=49999 wait_queueempty echo waiting for worker threads to timeout ./msleep 3000 injectmsg 50000 50000 MYSQL_ACTQ_LAST_MSG=99999 wait_queueempty echo waiting for worker threads to timeout ./msleep 2000 injectmsg 100000 50000 MYSQL_ACTQ_LAST_MSG=149999 shutdown_when_empty wait_shutdown mysql_get_data seq_check mysql_cleanup_test exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-resume-interval.sh0000644000000000000000000000013215241075234020663 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067806.081942831 rsyslog-8.2608.0/tests/omprog-resume-interval.sh0000775000175000017500000000316415241075234020336 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verify that omprog transaction commit failures do not spin in a tight retry # loop. The helper fails the first two transaction commits and records commit # timestamps with the transaction payload. The oracle checks retries of the # same suspended payload, not the next independent payload, because the next # message may be processed immediately after the suspended one succeeds. A # one-second lower bound is used for a two-second interval so the test tolerates # coarse scheduling while still catching immediate retry-loop resubmission. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-resume-interval-bin.sh` template="outfmt" name="omprog_action" queue.type="LinkedList" queue.dequeueBatchSize="2" confirmMessages="on" useTransactions="on" action.resumeRetryCount="-1" action.resumeInterval="2" ) } ' startup injectmsg 0 2 shutdown_when_empty wait_shutdown mapfile -t commit_times < <(awk '/^commit / && /msgnum:00000000:/ { print $3 }' "$RSYSLOG_OUT_LOG") if [[ ${#commit_times[@]} -lt 2 ]]; then echo "expected at least two commits for msgnum:00000000, got ${#commit_times[@]}" cat "$RSYSLOG_OUT_LOG" error_exit 1 fi retry_gap=$((commit_times[1] - commit_times[0])) if [[ $retry_gap -lt 1 ]]; then echo "commit retry happened before resume interval pacing" echo "retry gap: $retry_gap" cat "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/allowed-sender-modern.sh0000644000000000000000000000013015241075234020425 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.682579736 28 ctime=1787067804.4059116 rsyslog-8.2608.0/tests/allowed-sender-modern.sh0000775000175000017500000000657115241075234020107 0ustar00rgerrger#!/bin/bash # Verify modern allowedSender ACLs for imtcp and imudp. Module-level # allowedSender values act as defaults, input-level values override them, and # /0 masks remain non-allow-all. The oracle is deterministic: allowed inputs # must produce the expected file lines, blocked inputs must not create their # ruleset output files, and rsyslog must emit the disallowed-sender diagnostics. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin imudp export NUMMESSAGES=3 TCP_ALLOW_LOG="${RSYSLOG_DYNNAME}.tcp-allow.log" UDP_ALLOW_LOG="${RSYSLOG_DYNNAME}.udp-allow.log" TCP_BLOCK_LOG="${RSYSLOG_DYNNAME}.tcp-block.must-not-exist" TCP_ZERO_LOG="${RSYSLOG_DYNNAME}.tcp-zero.must-not-exist" UDP_BLOCK_LOG="${RSYSLOG_DYNNAME}.udp-block.must-not-exist" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp" allowedSender=["128.66.0.0/16"]) module(load="../plugins/imudp/.libs/imudp" allowedSender=["128.66.0.0/16"]) input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcp_block_port" ruleset="tcp_block") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcp_allow_port" allowedSender=["127.0.0.1/16","[::1]"] ruleset="tcp_allow") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcp_zero_port" allowedSender=["128.66.0.0/0"] ruleset="tcp_zero") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.udp_block_port" ruleset="udp_block") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.udp_allow_port" allowedSender=["127.0.0.1/16"] ruleset="udp_allow") template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="tcp_block") { action(type="omfile" template="outfmt" file="'$TCP_BLOCK_LOG'") } ruleset(name="tcp_allow") { action(type="omfile" template="outfmt" file="'$TCP_ALLOW_LOG'") } ruleset(name="tcp_zero") { action(type="omfile" template="outfmt" file="'$TCP_ZERO_LOG'") } ruleset(name="udp_block") { action(type="omfile" template="outfmt" file="'$UDP_BLOCK_LOG'") } ruleset(name="udp_allow") { action(type="omfile" template="outfmt" file="'$UDP_ALLOW_LOG'") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content TCP_BLOCK_PORT "${RSYSLOG_DYNNAME}.tcp_block_port" assign_file_content TCP_ALLOW_PORT "${RSYSLOG_DYNNAME}.tcp_allow_port" assign_file_content TCP_ZERO_PORT "${RSYSLOG_DYNNAME}.tcp_zero_port" assign_file_content UDP_BLOCK_PORT "${RSYSLOG_DYNNAME}.udp_block_port" assign_file_content UDP_ALLOW_PORT "${RSYSLOG_DYNNAME}.udp_allow_port" tcpflood --check-only -p"$TCP_BLOCK_PORT" -m1 -M "msgnum:tcp-block" tcpflood -p"$TCP_ALLOW_PORT" -m"$NUMMESSAGES" -M "msgnum:tcp-allow" tcpflood --check-only -p"$TCP_ZERO_PORT" -m1 -M "msgnum:tcp-zero" tcpflood -Tudp -p"$UDP_BLOCK_PORT" -m1 -M "msgnum:udp-block" tcpflood -Tudp -p"$UDP_ALLOW_PORT" -m"$NUMMESSAGES" -M "msgnum:udp-allow" wait_file_lines "$TCP_ALLOW_LOG" "$NUMMESSAGES" 100 wait_file_lines "$UDP_ALLOW_LOG" "$NUMMESSAGES" 100 shutdown_when_empty wait_shutdown content_check "You can not specify 0 bits of the netmask" content_check --regex "connection request from disallowed sender .* discarded" content_check "imudp: UDP message from disallowed sender discarded" check_file_not_exists "$TCP_BLOCK_LOG" check_file_not_exists "$TCP_ZERO_LOG" check_file_not_exists "$UDP_BLOCK_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_prog_confirm_killonclose.sh0000644000000000000000000000013115216464436022706 xustar0030 mtime=1782212894.059266718 30 atime=1782715518.912790948 29 ctime=1787067806.01694162 rsyslog-8.2608.0/tests/improg_prog_confirm_killonclose.sh0000775000175000017500000000140715216464436022360 0ustar00rgerrger#!/bin/bash # add 2019-04-04 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/improg/.libs/improg") input(type="improg" tag="tag" ruleset="ruleset" binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -c -n 1 -g" confirmmessages="on" signalonclose="on" killunresponsive="on" ) ruleset(name="ruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup wait_content "program data" "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "program data" if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then echo $RSYSLOG_DYNNAME'.stderr missing' error_exit 1 fi export EXPECTED='START Received ACK Received SIGTERM Received' cmp_exact $RSYSLOG_DYNNAME.stderr exit_test rsyslog-8.2608.0/tests/PaxHeaders/tcp_forwarding_ns_tpl.sh0000644000000000000000000000013215216464436020637 xustar0030 mtime=1782212894.085267138 30 atime=1782715518.911790931 30 ctime=1787067805.968940726 rsyslog-8.2608.0/tests/tcp_forwarding_ns_tpl.sh0000775000175000017500000000413515216464436020311 0ustar00rgerrger#!/bin/bash # Verify TCP forwarding with an action-level template into a network namespace. # The oracle is the complete 0..9999 forwarded sequence received by the helper # listener inside the namespace. The ready file is written after listen() # succeeds, avoiding a sender/listener startup race. # Released under GNU GPLv3+ echo =============================================================================== echo \[tcp_forwarding_ns_tpl.sh\]: test for tcp forwarding in a network namespace with assigned template echo This test must be run as root [network namespace creation/change required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi # create the pipe and start a background process that copies data from # it to the "regular" work file . ${srcdir:=.}/diag.sh init require_netns_capable generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfwd" template="outfmt" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp" networknamespace="rsyslog_test_ns") ' # create network namespace and bring it up ip netns add rsyslog_test_ns ip netns exec rsyslog_test_ns ip link set dev lo up # run server in namespace MINITCPSRV_READY="$RSYSLOG_DYNNAME.minitcpsrv.$TCPFLOOD_PORT.ready" rm -f "$MINITCPSRV_READY" ip netns exec rsyslog_test_ns ./minitcpsrv -t127.0.0.1 -p"$TCPFLOOD_PORT" \ -f "$RSYSLOG_OUT_LOG" -L "$MINITCPSRV_READY" & BGPROCESS=$! echo background minitcpsrvr process id is $BGPROCESS wait_file_exists "$MINITCPSRV_READY" # now do the usual run startup # 10000 messages should be enough injectmsg 0 10000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # note: minitcpsrvr shuts down automatically if the connection is closed! # (we still leave the code here in in case we need it later) #echo shutting down minitcpsrv... #kill $BGPROCESS #wait $BGPROCESS #echo background process has terminated, continue test... # remove network namespace ip netns delete rsyslog_test_ns # and continue the usual checks seq_check 0 9999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-input-basic.sh0000644000000000000000000000013215241075234021346 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.501969292 rsyslog-8.2608.0/tests/imtcp-tls-ossl-input-basic.sh0000775000175000017500000000215015241075234021013 0ustar00rgerrger#!/bin/bash # added 2011-02-28 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "nsd_ptcp.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" streamDriver.CAFile="'$srcdir'/tls-certs/ca.pem" streamDriver.CertFile="'$srcdir'/tls-certs/cert.pem" streamDriver.KeyFile="'$srcdir'/tls-certs/key.pem") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-pos-from-to.sh0000644000000000000000000000013215241075234020233 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.799581927 30 ctime=1787067804.270909084 rsyslog-8.2608.0/tests/template-pos-from-to.sh0000775000175000017500000000105515241075234017703 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # addd 2016-03-28 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:9:16:%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m9 shutdown_when_empty wait_shutdown seq_check 0 8 exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-allowed-sender-modern.sh0000644000000000000000000000013215241075234021367 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.696579998 30 ctime=1787067805.417930458 rsyslog-8.2608.0/tests/yaml-allowed-sender-modern.sh0000775000175000017500000000726315241075234021046 0ustar00rgerrger#!/bin/bash # Verify YAML parsing for modern imtcp/imudp allowedSender parameters. The # module default denies localhost while input-level overrides allow it; blocked # inputs prove the module default is active. Allowed paths synchronize on exact # output line counts, and blocked paths are checked by absent output files. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin imudp export NUMMESSAGES=3 TCP_ALLOW_LOG="${RSYSLOG_DYNNAME}.yaml-tcp-allow.log" UDP_ALLOW_LOG="${RSYSLOG_DYNNAME}.yaml-udp-allow.log" TCP_BLOCK_LOG="${RSYSLOG_DYNNAME}.yaml-tcp-block.must-not-exist" UDP_BLOCK_LOG="${RSYSLOG_DYNNAME}.yaml-udp-block.must-not-exist" generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"' add_yaml_conf ' allowedSender: ["128.66.0.0/16"]' add_yaml_conf ' - load: "../plugins/imudp/.libs/imudp"' add_yaml_conf ' allowedSender: ["128.66.0.0/16"]' add_yaml_conf '' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imtcp' add_yaml_conf ' port: "0"' add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.yaml_tcp_block_port\"" add_yaml_conf ' ruleset: tcp_block' add_yaml_conf ' - type: imtcp' add_yaml_conf ' port: "0"' add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.yaml_tcp_allow_port\"" add_yaml_conf ' allowedSender: ["127.0.0.1/16", "[::1]"]' add_yaml_conf ' ruleset: tcp_allow' add_yaml_conf ' - type: imudp' add_yaml_conf ' address: "127.0.0.1"' add_yaml_conf ' port: "0"' add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.yaml_udp_block_port\"" add_yaml_conf ' ruleset: udp_block' add_yaml_conf ' - type: imudp' add_yaml_conf ' address: "127.0.0.1"' add_yaml_conf ' port: "0"' add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.yaml_udp_allow_port\"" add_yaml_conf ' allowedSender: ["127.0.0.1/16"]' add_yaml_conf ' ruleset: udp_allow' add_yaml_conf '' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf ' string: "%msg:F,58:2%\n"' add_yaml_conf '' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: tcp_block' add_yaml_conf ' script: |' add_yaml_conf " action(type=\"omfile\" template=\"outfmt\" file=\"${TCP_BLOCK_LOG}\")" add_yaml_conf ' - name: tcp_allow' add_yaml_conf ' script: |' add_yaml_conf " action(type=\"omfile\" template=\"outfmt\" file=\"${TCP_ALLOW_LOG}\")" add_yaml_conf ' - name: udp_block' add_yaml_conf ' script: |' add_yaml_conf " action(type=\"omfile\" template=\"outfmt\" file=\"${UDP_BLOCK_LOG}\")" add_yaml_conf ' - name: udp_allow' add_yaml_conf ' script: |' add_yaml_conf " action(type=\"omfile\" template=\"outfmt\" file=\"${UDP_ALLOW_LOG}\")" add_yaml_conf ' - name: main' add_yaml_conf ' script: |' add_yaml_conf " action(type=\"omfile\" file=\"${RSYSLOG_OUT_LOG}\")" startup assign_file_content TCP_BLOCK_PORT "${RSYSLOG_DYNNAME}.yaml_tcp_block_port" assign_file_content TCP_ALLOW_PORT "${RSYSLOG_DYNNAME}.yaml_tcp_allow_port" assign_file_content UDP_BLOCK_PORT "${RSYSLOG_DYNNAME}.yaml_udp_block_port" assign_file_content UDP_ALLOW_PORT "${RSYSLOG_DYNNAME}.yaml_udp_allow_port" tcpflood --check-only -p"$TCP_BLOCK_PORT" -m1 -M "msgnum:yaml-tcp-block" tcpflood -p"$TCP_ALLOW_PORT" -m"$NUMMESSAGES" -M "msgnum:yaml-tcp-allow" tcpflood -Tudp -p"$UDP_BLOCK_PORT" -m1 -M "msgnum:yaml-udp-block" tcpflood -Tudp -p"$UDP_ALLOW_PORT" -m"$NUMMESSAGES" -M "msgnum:yaml-udp-allow" wait_file_lines "$TCP_ALLOW_LOG" "$NUMMESSAGES" 100 wait_file_lines "$UDP_ALLOW_LOG" "$NUMMESSAGES" 100 shutdown_when_empty wait_shutdown check_file_not_exists "$TCP_BLOCK_LOG" check_file_not_exists "$UDP_BLOCK_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-retry-error.sh0000644000000000000000000000013215035412264020662 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.910790914 30 ctime=1787067805.786937334 rsyslog-8.2608.0/tests/clickhouse-retry-error.sh0000777000175000017500000000127715035412264020342 0ustar00rgerrger#!/bin/bash # add 2018-12-31 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 generate_conf add_conf ' module(load="../plugins/omclickhouse/.libs/omclickhouse") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.retryerror (id, severity, message) VALUES (%msg:F,58:2%, %syslogseverity%, ' add_conf "'%msg%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" bulkmode="off" user="default" pwd="" template="outfmt") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg shutdown_when_empty wait_shutdown content_check "omclickhouse: checkConn failed." exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmaitag-invalid-key.sh0000644000000000000000000000013215241075234020071 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 30 ctime=1787067805.689935527 rsyslog-8.2608.0/tests/mmaitag-invalid-key.sh0000775000175000017500000000123515241075234017541 0ustar00rgerrger#!/bin/bash ## test gemini provider with invalid API key . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmaitag/.libs/mmaitag") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg% [%$.aitag%]\n") if($msg contains "msgnum:00") then { action(type="mmaitag" provider="gemini" apikey="dummy") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m 1 shutdown_when_empty wait_shutdown content_check "request for a message failed" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_parse_json.sh0000644000000000000000000000013215241075234020151 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.792581796 30 ctime=1787067804.882920489 rsyslog-8.2608.0/tests/rscript_parse_json.sh0000775000175000017500000000115315241075234017620 0ustar00rgerrger#!/bin/bash # Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!%\n") local4.* { set $.ret = parse_json("{ \"c1\":\"data\" }", "\$!parsed"); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED='{ "parsed": { "c1": "data" } }' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse-nodate-udp.sh0000644000000000000000000000013115035412264021600 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.909790897 29 ctime=1787067805.04292347 rsyslog-8.2608.0/tests/parsertest-parse-nodate-udp.sh0000777000175000017500000000215715035412264021257 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<27>xapi: [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)\"" tcpflood -m1 -T "udp" -M "\"This is a message!\"" shutdown_when_empty wait_shutdown export EXPECTED="27,daemon,err,$RS_HOSTNAME,xapi,xapi:, [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message) 13,user,notice,This,is,is, a message!" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-set-vg.sh0000644000000000000000000000013115171370365017432 xustar0030 mtime=1776677109.466913465 29 atime=1782715518.90879088 30 ctime=1787067806.640953248 rsyslog-8.2608.0/tests/omhiredis-set-vg.sh0000775000175000017500000000027115171370365017102 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-set.sh rsyslog-8.2608.0/tests/PaxHeaders/dircreate_dflt.sh0000644000000000000000000000013115241075234017212 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.645916072 rsyslog-8.2608.0/tests/dircreate_dflt.sh0000775000175000017500000000227615241075234016671 0ustar00rgerrger#!/bin/bash # Test for automatic creation of dynafile directories # note that we use the "'${RSYSLOG_DYNNAME}'.spool" directory, because it is handled by diag.sh # in any case, so we do not need to add any extra new test dir. # added 2009-11-30 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf if [ "${QUEUE_TYPE:-disk}" = "segmentedDisk" ]; then add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq") template(name="dynfile" type="string" string="'${RSYSLOG_DYNNAME}'.logdir/'$RSYSLOG_OUT_LOG'") action(type="omfile" dynaFile="dynfile") ' else add_conf ' # set spool locations and switch queue to disk-only mode $WorkDirectory '$RSYSLOG_DYNNAME'.spool $MainMsgQueueFilename mainq $MainMsgQueueType disk $template dynfile,"'$RSYSLOG_DYNNAME'.logdir/'$RSYSLOG_OUT_LOG'" *.* ?dynfile ' fi startup injectmsg 0 1 # a single message is sufficient shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown if [ ! -e $RSYSLOG_DYNNAME.logdir/$RSYSLOG_OUT_LOG ] then echo "$RSYSLOG_DYNNAME.logdir or logfile not created!" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/tabescape_dflt-udp.sh0000644000000000000000000000013115035412264017764 xustar0029 mtime=1752569012.41564652 30 atime=1782715518.907790863 30 ctime=1787067803.643897401 rsyslog-8.2608.0/tests/tabescape_dflt-udp.sh0000777000175000017500000000137415035412264017443 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\"" shutdown_when_empty wait_shutdown echo ' before HT#011after HT (do NOT remove TAB!)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmdb-container.sh0000644000000000000000000000013115035412264017135 xustar0030 mtime=1752569012.400750748 30 atime=1782715518.910790914 29 ctime=1787067807.25496469 rsyslog-8.2608.0/tests/mmdb-container.sh0000777000175000017500000000152115035412264016606 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$!mmdb_root%\n") module(load="../plugins/mmdblookup/.libs/mmdblookup" container="!mmdb_root") module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmnormalize" rulebase=`echo $srcdir/mmdb.rb`) action(type="mmdblookup" mmdbfile=`echo $srcdir/test.mmdb` key="$!ip" fields="city" ) action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m 1 -j "202.106.0.20\ " shutdown_when_empty wait_shutdown content_check '{ "city": "Beijing" }' exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmdb-multilevel-vg.sh0000644000000000000000000000013215035412264017750 xustar0030 mtime=1752569012.400750748 30 atime=1782715518.910790914 30 ctime=1787067807.269964969 rsyslog-8.2608.0/tests/mmdb-multilevel-vg.sh0000777000175000017500000000251615035412264017425 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # we libmaxminddb, in packaged versions, has a small cosmetic memory leak, # thus we need a suppressions file: export RS_TESTBENCH_VALGRIND_EXTRA_OPTS="$RS_TESTBENCH_VALGRIND_EXTRA_OPTS --suppressions=$srcdir/libmaxmindb.supp" generate_conf add_conf ' template(name="outfmt" type="string" string="%$!iplocation%\n") module(load="../plugins/mmdblookup/.libs/mmdblookup") module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmnormalize" rulebase="'$srcdir'/mmdb.rb") # Uncomment this action when using the real GeoLite2 city database; # we have not included it into the testbench for licensing concerns. # action(type="mmdblookup" mmdbfile="/home/USR/GeoLite2-City_20170502/GeoLite2-City.mmdb" key="$!ip" fields=":city:!city!names!en" ) action(type="mmdblookup" mmdbfile="'$srcdir'/test.mmdb" key="$!ip" fields=":city_name:city" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") }' startup_vg tcpflood -m 100 -j "202.106.0.20\ " shutdown_when_empty wait_shutdown_vg check_exit_vg content_check '{ "city_name": "Beijing" }' exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_certvalid.sh0000644000000000000000000000013115241075234020455 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.312965771 rsyslog-8.2608.0/tests/sndrcv_tls_certvalid.sh0000775000175000017500000000376215241075234020135 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls} export NUMMESSAGES=10000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="'$RS_TLS_DRIVER'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="'$RS_TLS_DRIVER'" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="'$RS_TLS_DRIVER'" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode x509/certvalid *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/manytcp-too-few-tls-vg.sh0000644000000000000000000000013215241075234020503 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.779581552 30 ctime=1787067807.366966777 rsyslog-8.2608.0/tests/manytcp-too-few-tls-vg.sh0000775000175000017500000000371215241075234020155 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test does not work on FreeBSD" export NUMMESSAGES=40000 # we unfortunately need many messages as we have many connections export TB_TEST_MAX_RUNTIME=1800 # this test is VERY slow, so we need to override max runtime generate_conf add_conf ' $MaxOpenFiles 200 global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem" defaultNetstreamDriver="gtls" debug.whitelist="on" debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module(load="../plugins/imtcp/.libs/imtcp" maxSessions="1100" streamDriver.mode="1" streamDriver.authMode="anon") input(type="imtcp" address="127.0.0.1" socketBacklog="1000" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup_vg # the config file specifies exactly 1100 connections tcpflood -c1000 -m$NUMMESSAGES -Ttls -x$srcdir/testsuites/x.509/ca.pem -Z$srcdir/testsuites/x.509/client-cert.pem -z$srcdir/testsuites/x.509/client-key.pem # the sleep below is needed to prevent too-early termination of the tcp listener # note: this must not be precise, as message loss is acceptable sleep 5 shutdown_when_empty wait_shutdown_vg check_exit_vg # we do not do a seq check, as of the design of this test some messages # will be lost. So there is no point in checking if all were received. The # point is that we look at the valgrind result, to make sure we do not # have a mem leak in those error cases (we had in the past, thus the test # to prevent that in the future). exit_test rsyslog-8.2608.0/tests/PaxHeaders/discard-rptdmsg.sh0000644000000000000000000000013115241075234017326 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.691916929 rsyslog-8.2608.0/tests/discard-rptdmsg.sh0000775000175000017500000000124615241075234017001 0ustar00rgerrger#!/bin/bash # testing discard-rptdmsg functionality when no repeated message is present # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") $RepeatedMsgReduction on :msg, contains, "00000001" ~ :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m10 -i1 shutdown_when_empty wait_shutdown seq_check 2 10 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_privdropuserid.sh0000644000000000000000000000013215131231047021061 xustar0030 mtime=1768239655.718212811 30 atime=1782715518.909790897 30 ctime=1787067804.221908171 rsyslog-8.2608.0/tests/rscript_privdropuserid.sh0000777000175000017500000000112115131231047020525 0ustar00rgerrger#!/bin/bash # added 2021-09-23 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.user.id="'${TESTBENCH_TESTUSER[uid]}'") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_relp_tls.sh0000644000000000000000000000013215216464436017453 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.909790897 30 ctime=1787067807.727973504 rsyslog-8.2608.0/tests/sndrcv_relp_tls.sh0000775000175000017500000000257615216464436017134 0ustar00rgerrger#!/bin/bash # added 2013-12-10 by Rgerhards # Verify RELP forwarding with TLS enabled. The imrelp receiver binds an # ephemeral IPv4 listener and the testbench discovers that bound port after # startup, avoiding the get_free_port race before the omrelp sender connects. # This file is part of the rsyslog project, released under ASL 2.0 # uncomment for debugging support: . ${srcdir:=.}/diag.sh init # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" address="127.0.0.1" port="0" tls="on") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_single_tcp_listener_port PORT_RCVR export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' module(load="../plugins/omrelp/.libs/omrelp") action(type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 50000 # shut down sender shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # do the final check seq_check 1 50000 exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-multiple-recovery.sh0000644000000000000000000000013215241075234023675 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.744899283 rsyslog-8.2608.0/tests/segmented-diskqueue-multiple-recovery.sh0000775000175000017500000000326715241075234023354 0ustar00rgerrger#!/bin/bash # Two consecutive dirty restarts create two recovery tails. The final start # must process them in segment-ID order before the new active segment; ordered # sequence validation permits checkpoint duplicates but no gaps or reordering. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=800 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" write_conf() { generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'$SPOOL_DIR'") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.maxFileSize="1m" queue.dequeueBatchSize="16" queue.checkpointInterval="64" queue.saveOnShutdown="on") template(name="outfmt" type="string" string="%msg:F,58:2%\n") '"$1"' if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' } dirty_phase() { write_conf ':omtesting:sleep 10 0' startup wait_rsyslog_instance_pid injectmsg "$1" 400 . "$srcdir/diag.sh" kill-immediate wait_shutdown } dirty_phase 0 dirty_phase 400 write_conf ':omtesting:sleep 10 0' export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check_dupes wait_seq_check_dupes() { wait_seq_check 0 $((NUMMESSAGES - 1)) -d } startup wait_rsyslog_instance_pid recovery_count=$(find "$SPOOL_DIR/mainq.segq" -maxdepth 1 -name 'segment-*.recover' -type f | wc -l) if [ "$recovery_count" -lt 2 ]; then printf 'FAIL: expected at least two recovery segments after repeated crashes, found %s\n' "$recovery_count" find "$SPOOL_DIR/mainq.segq" -maxdepth 1 -type f -print error_exit 1 fi . "$srcdir/diag.sh" kill-immediate wait_shutdown write_conf '# final recovery has no delay' startup shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -d rm -rf "$SPOOL_DIR" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omjournal-basic-no-template.sh0000644000000000000000000000013215241075234021550 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.785581664 30 ctime=1787067806.003941378 rsyslog-8.2608.0/tests/omjournal-basic-no-template.sh0000775000175000017500000000144415241075234021222 0ustar00rgerrger#!/bin/bash # a basic test for omjournal. # addd 2016-03-18 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh require-journalctl generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omjournal/.libs/omjournal") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omjournal") ' startup tcpflood -m1 -M "\"<133>2011-03-01T11:22:12Z host tag msgh RsysLoG-TESTBENCH $COOKIE\"" ./msleep 500 shutdown_when_empty wait_shutdown # if we reach this, we have at least not aborted journalctl -r -t rsyslogd: |grep "RsysLoG-TESTBENCH $COOKIE" if [ $? -ne 1 ]; then echo "error: cookie $COOKIE not found. Head of journal:" journalctl -r -t rsyslogd: | head exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_servercert_bad_eku_no_chk_mbedtls_clientanon.sh0000644000000000000000000000013215216464436027614 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.909790897 30 ctime=1787067807.442968193 rsyslog-8.2608.0/tests/sndrcv_tls_servercert_bad_eku_no_chk_mbedtls_clientanon.sh0000775000175000017500000000362115216464436027265 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-eku-invld.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" #export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="mbedtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" streamDriver.CheckExtendedKeyPurpose="off" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/manyptcp.sh0000644000000000000000000000013215132411300016056 xustar0030 mtime=1768559296.287885972 30 atime=1782715518.909790897 30 ctime=1787067806.768955633 rsyslog-8.2608.0/tests/manyptcp.sh0000777000175000017500000000122615132411300015530 0ustar00rgerrger#!/bin/bash # test imptcp with large connection count # test many concurrent tcp connections # released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=40000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' $MaxOpenFiles 2000 module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" SocketBacklog="1000" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -c1000 -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_omudpspoof.sh0000644000000000000000000000013115035412264020010 xustar0030 mtime=1752569012.414653468 29 atime=1782715518.90879088 30 ctime=1787067807.806974976 rsyslog-8.2608.0/tests/sndrcv_omudpspoof.sh0000777000175000017500000000420415035412264017462 0ustar00rgerrger#!/bin/bash # This runs sends and receives messages via UDP to the standard # ports. Note that with UDP we can always have message loss. While this is # less likely in a local environment, we strongly limit the amount of data # we send in the hope to not lose any messages. However, failure of this # test does not necessarily mean that the code is wrong (but it is very likely!) # added 2009-11-11 by Rgerhards # This file is part of the rsyslog project, released under GPLv3 echo =============================================================================== echo \[sndrcv_omudpspoof.sh\]: testing sending and receiving via omudp echo This test must be run as root [raw socket access required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi export TCPFLOOD_EXTRA_OPTS="-b1 -W1" # uncomment for debugging support: . ${srcdir:=.}/diag.sh init # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' $ModLoad ../plugins/imudp/.libs/imudp # then SENDER sends to this port (not tcpflood!) $UDPServerRun 514 $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp # this listener is for message generation by the test framework! $InputTCPServerRun '$TCPFLOOD_PORT' $ModLoad ../plugins/omudpspoof/.libs/omudpspoof $template spoofaddr,"127.0.0.1" #begin action definition $ActionOMUDPSpoofSourceNameTemplate spoofaddr $ActionOMUDPSpoofTargetHost 127.0.0.1 $ActionOMUDPSpoofSourcePortStart 514 $ActionOMUDPSpoofSourcePortEnd 514 *.* :omudpspoof: ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m50 -i1 sleep 5 # make sure all data is received in input buffers # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # do the final check seq_check 1 50 rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-timer.sh0000644000000000000000000000013115171370365017520 xustar0030 mtime=1776677109.466913465 29 atime=1782715518.90879088 30 ctime=1787067806.313947155 rsyslog-8.2608.0/tests/omazuredce-timer.sh0000775000175000017500000000302215171370365017165 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . ${srcdir:=.}/omazuredce-env.sh require_plugin "omazuredce" omazuredce_require_env export NUMMESSAGES=5 generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omazuredce/.libs/omazuredce") template(name="tplAzureDceTimer" type="list" option.jsonftree="on") { property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf") property(outname="host" name="hostname" format="jsonf") property(outname="message" name="msg" format="jsonf") } local4.* action( type="omazuredce" template="tplAzureDceTimer" client_id="'$AZURE_DCE_CLIENT_ID'" client_secret=`echo $AZURE_DCE_CLIENT_SECRET` tenant_id="'$AZURE_DCE_TENANT_ID'" dce_url="'$AZURE_DCE_URL'" dcr_id="'$AZURE_DCE_DCR_ID'" table_name="'$AZURE_DCE_TABLE_NAME'" max_batch_bytes="1048576" flush_timeout_ms="200" action.resumeInterval="1" action.resumeRetryCount="1" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 $NUMMESSAGES # Verify the timer thread flushes without needing shutdown-triggered cleanup. content_check_with_count "omazuredce: posted batch records=5" 1 5 shutdown_when_empty wait_shutdown post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG") if [ "${post_count:=0}" -ne 1 ]; then echo "FAIL: expected exactly one timer-driven omazuredce batch post, got $post_count" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_priorityString.sh0000644000000000000000000000013215241075234021551 xustar0030 mtime=1787067036.644579024 30 atime=1787067036.797581889 30 ctime=1787067807.310965733 rsyslog-8.2608.0/tests/sndrcv_tls_priorityString.sh0000775000175000017500000000443415241075234021225 0ustar00rgerrger#!/bin/bash # Pascal Withopf, 2017-07-25 # testing sending and receiving via TLS with anon auth # NOTE: When this test fails, it could be due to the priorityString being outdated! # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2500 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # start up the instances export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' # certificates global( defaultNetstreamDriverCAFile="'$srcdir'/testsuites/x.509/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/testsuites/x.509/client-cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/testsuites/x.509/client-key.pem" defaultNetstreamDriver="gtls" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" gnutlspriorityString="NORMAL:-MD5") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' #certificates global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="gtls" ) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfwd" Target="127.0.0.1" port="'$PORT_RCVR'" Protocol="tcp" streamdriver="gtls" StreamDriverAuthMode="anon" StreamDriverMode="1" gnutlsprioritystring="NORMAL:-MD5") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 wait_file_lines # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-basic.sh0000644000000000000000000000013215241075234017654 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.787581702 30 ctime=1787067807.051960907 rsyslog-8.2608.0/tests/pmnormalize-basic.sh0000775000175000017500000000272215241075234017326 0ustar00rgerrger#!/bin/bash # add 2016-12-08 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/pmnormalize/.libs/pmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") parser(name="custom.pmnormalize" type="pmnormalize" rulebase="'$srcdir'/testsuites/pmnormalize_basic.rulebase") template(name="test" type="string" string="host: %hostname%, ip: %fromhost-ip%, tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n") ruleset(name="ruleset" parser="custom.pmnormalize") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="test") } ' startup tcpflood -m1 -M "\"<189> ubuntu tag1: is no longer listening on 127.0.0.1 test\"" tcpflood -m1 -M "\"<112> debian tag2: is no longer listening on 255.255.255.255 test\"" tcpflood -m1 -M "\"<177> centos tag3: is no longer listening on 192.168.0.9 test\"" shutdown_when_empty wait_shutdown sort < $RSYSLOG_OUT_LOG > ${RSYSLOG_OUT_LOG}.sorted export EXPECTED='host: centos, ip: 192.168.0.9, tag: tag3, pri: 177, syslogfacility: 22, syslogseverity: 1 msg: test host: debian, ip: 255.255.255.255, tag: tag2, pri: 112, syslogfacility: 14, syslogseverity: 0 msg: test host: ubuntu, ip: 127.0.0.1, tag: tag1, pri: 189, syslogfacility: 23, syslogseverity: 5 msg: test' cmp_exact ${RSYSLOG_OUT_LOG}.sorted exit_test rsyslog-8.2608.0/tests/PaxHeaders/fac_invld3.sh0000644000000000000000000000013215241075234016250 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.307909774 rsyslog-8.2608.0/tests/fac_invld3.sh0000775000175000017500000000115615241075234015722 0ustar00rgerrger#!/bin/bash # added 2014-10-01 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(type="string" name="outfmt" string="%msg:F,58:4%\n") invld.=debug action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m$NUMMESSAGES -P x112 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_gt_var.sh0000644000000000000000000000013115035412264017266 xustar0030 mtime=1752569012.411674314 30 atime=1782715518.911790931 29 ctime=1787067804.81591924 rsyslog-8.2608.0/tests/rscript_gt_var.sh0000777000175000017500000000275715035412264016753 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_gt.sh\]: testing rainerscript GT statement for two JSON variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } set $!var1 = "43"; set $!var2 = "42"; if $!var1 > $!var2 then { if $!var2 > $!var1 then { # Failure stop } else { unset $!var1; unset $!var2; } } else { # Failure stop } set $.var1 = "43"; set $.var2 = "42"; if $.var1 > $.var2 then { if $.var2 > $.var1 then { # Failure stop } else { unset $.var1; unset $.var2; } } else { # Failure stop } set $/var1 = "43"; set $/var2 = "42"; if $/var1 > $/var2 then { if $/var2 > $/var1 then { # Failure stop } else { unset $/var1; unset $/var2; } } else { # Failure stop } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup injectmsg 0 1 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-netns.sh0000644000000000000000000000013215145046113016476 xustar0030 mtime=1771326539.041014321 30 atime=1782715518.911790931 30 ctime=1787067805.508932154 rsyslog-8.2608.0/tests/imtcp-netns.sh0000775000175000017500000000625215145046113016152 0ustar00rgerrger#!/bin/bash # This test tests listening on ports in another network namespace. echo =============================================================================== echo \[imtcp-netns.sh\]: test for listening in another network namespace echo This test must be run with CAP_SYS_ADMIN capabilities [network namespace creation/change required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi . ${srcdir:=.}/diag.sh init require_netns_capable generate_conf NS_PREFIX=$(basename ${RSYSLOG_DYNNAME}) NS_DEFAULT="${NS_PREFIX}.rsyslog_ns_default" NS_FAIL=( "${NS_PREFIX}.rsyslog_ns_a_fail" "${NS_PREFIX}.rsyslog_ns_b_fail" ) NS_GOOD=( "${NS_PREFIX}.rsyslog_ns_c" "${NS_PREFIX}.rsyslog_ns_d" ) add_conf ' $MainMsgQueueTimeoutShutdown 10000 module( load="../plugins/imtcp/.libs/imtcp" NetworkNamespace="'${NS_DEFAULT}'" ) input( Type="imtcp" Port="0" Address="127.0.0.1" ListenPortFileName="'${NS_DEFAULT}'.port" ) ' for ns in "${NS_GOOD[@]}" "${NS_FAIL[@]}"; do add_conf ' input( Type="imtcp" Port="0" Address="127.0.0.1" NetworkNamespace="'${ns}'" ListenPortFileName="'${ns}'.port" ) ' done add_conf ' input( Type="imtcp" Port="0" Address="127.0.0.1" NetworkNamespace="" ListenPortFileName="'$RSYSLOG_DYNNAME'.port" ) template(name="outfmt" type="string" string="%msg:%\n") :msg, contains, "imtcp-netns:" action( type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt" ) ' # # create network namespace and bring it up NS=( "${NS_DEFAULT}" "${NS_GOOD[@]}" ) for ns in "${NS[@]}"; do ip netns add "${ns}" ip netns exec "${ns}" ip link set dev lo up done for ns in "${NS_FAIL[@]}"; do ip netns delete "${ns}" > /dev/null 2>&1 done # now do the usual run RS_REDIR="> ${RSYSLOG_DYNNAME}.log 2>&1" startup wait_file_exists "${RSYSLOG_DYNNAME}.port" for ns in "${NS[@]}"; do wait_file_exists "${ns}.port" done MSGS=() function logmsg() { local ns=$1 local msg=$2 local logger_cmd=() local port_file=${RSYSLOG_DYNNAME}.port if [[ -n "${ns}" ]]; then logger_cmd+=(ip netns exec "${ns}") port_file="${ns}.port" fi logger_cmd+=( logger --tcp --server 127.0.0.1 --octet-count --tag "$0" --port "$(cat ${port_file})" -- "imtcp-netns: ${msg}" ) "${logger_cmd[@]}" MSGS+=("imtcp-netns: ${msg}") } # Inject a few messages logmsg "" "start message from local namespace" for ns in "${NS[@]}"; do logmsg "${ns}" "test message from namespace ${ns}" # Try to keep them ordered sleep 1 done logmsg "" "end message from local namespace" shutdown_when_empty wait_shutdown # remove network namespaces for ns in "${NS[@]}"; do ip netns delete "${ns}" done EXPECTED=$(printf "%s\n" "${MSGS[@]}") cmp_exact # Verify we have error messages for the missing namespaces # We don't redirect with valgrind, so skip this check with valgrind if [[ "${USE_VALGRIND}" != "YES" ]]; then for ns in "${NS_FAIL[@]}"; do content_check "netns_switch: could not open namespace '${ns}':" ${RSYSLOG_DYNNAME}.log done fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-negative-vg.sh0000644000000000000000000000013215241075234026003 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.547970149 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-negative-vg.sh0000775000175000017500000000015115241075234025447 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-cert-mtls-sigalgs-negative.sh rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-subscribe-vg.sh0000644000000000000000000000013215171370365020613 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.911790931 30 ctime=1787067806.576952055 rsyslog-8.2608.0/tests/imhiredis-subscribe-vg.sh0000775000175000017500000000027715171370365020270 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-subscribe.sh rsyslog-8.2608.0/tests/PaxHeaders/pmsnare_malformed_tag_tail.sh0000644000000000000000000000013215241075234021577 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067807.852975833 rsyslog-8.2608.0/tests/pmsnare_malformed_tag_tail.sh0000775000175000017500000000201615241075234021245 0ustar00rgerrger#!/bin/bash # This test hardens pmsnare against Snare tag matches without a following tab # representation. The oracle is that short tails do not underflow rewrite # lengths and a following marker message is still processed. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/pmsnare/.libs/pmsnare") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") template(name="outfmt" type="string" string="valid-after\n") ruleset(name="testing" parser=["rsyslog.snare", "rsyslog.rfc3164"]) { if $rawmsg contains "valid-after" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } }' startup tcpflood -m1 -M "\"<14>May 21 12:00:01 host MSWinEventLog\"" tcpflood -m1 -M "\"<14>May 21 12:00:01 host LinuxKAudit\"" tcpflood -m1 -M "\"<14>host MSWinEventLog\"" tcpflood -m1 -M "\"<14>valid-after\"" shutdown_when_empty wait_shutdown export EXPECTED='valid-after' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-timeout-values.sh0000644000000000000000000000013115241075234022470 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 29 ctime=1787067803.85690137 rsyslog-8.2608.0/tests/segmented-da-idle-timeout-values.sh0000775000175000017500000000656615241075234022155 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Verify the two boundary values of queue.diskQueueIdleTimeout. Identical slow # action queues force a spill; timeout 0 must remove its store immediately, # while -1 must retain its drained store and final worker until shutdown. Exact # output sequences prove both children drained without loss. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1500 SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" ZERO_OUT="${RSYSLOG_DYNNAME}.zero.log" DISABLED_OUT="${RSYSLOG_DYNNAME}.disabled.log" STATS_FILE="${RSYSLOG_DYNNAME}.stats" wait_path_state() { local mode="$1" path="$2" timeoutend=$((SECONDS + 30)) while true; do [ "$mode" = present ] && [ -e "$path" ] && return [ "$mode" = absent ] && [ ! -e "$path" ] && return [ "$SECONDS" -ge "$timeoutend" ] && error_exit 1 "path did not become $mode: $path" ./msleep 25 done } generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") module(load="../plugins/impstats/.libs/impstats" interval="1" log.syslog="off" log.file="'"$STATS_FILE"'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { action(type="omfile" name="idle-zero" file="'"$ZERO_OUT"'" template="outfmt" queue.type="LinkedList" queue.filename="idle-zero" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.dequeueSlowdown="10" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="0") action(type="omfile" name="idle-disabled" file="'"$DISABLED_OUT"'" template="outfmt" queue.type="LinkedList" queue.filename="idle-disabled" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.dequeueSlowdown="10" queue.workerThreads="3" queue.workerThreadMinimumMessages="1" queue.timeoutWorkerThreadShutdown="100" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="-1") } ' startup injectmsg wait_path_state present "$SPOOL_DIR/idle-disabled.segq" wait_file_lines "$ZERO_OUT" "$NUMMESSAGES" 300 wait_file_lines "$DISABLED_OUT" "$NUMMESSAGES" 300 wait_path_state absent "$SPOOL_DIR/idle-zero.segq" ./msleep 1000 [ -d "$SPOOL_DIR/idle-disabled.segq" ] || error_exit 1 "idle timeout -1 removed the store" # With a zero grace period, a producer scheduling gap may permit more than one # drain/rematerialize cycle during the burst. At least one completed cleanup, # an absent store, and zero child workers are the deterministic immediacy # oracle; requiring exactly one cleanup would make scheduler timing observable. wait_content 'store.idleDematerializations=' "$STATS_FILE" zero_dematerializations=$(grep 'idle-zero queue\[DA\]' "$STATS_FILE" | sed -E 's/.*store\.idleDematerializations=([0-9]+).*/\1/' | sort -n | tail -n 1) [ "${zero_dematerializations:-0}" -ge 1 ] || error_exit 1 "idle timeout 0 did not dematerialize its store" content_check --regex 'idle-zero queue\[DA\].*workers.current=0' "$STATS_FILE" # The 100ms generic worker timeout has elapsed several times by now. A live # worker proves that -1 protects slot zero while still leaving the generic # timeout available for any additional workers. content_check --regex 'idle-disabled queue\[DA\].*workers.current=1' "$STATS_FILE" shutdown_when_empty wait_shutdown RSYSLOG_OUT_LOG="$ZERO_OUT" seq_check 0 $((NUMMESSAGES - 1)) RSYSLOG_OUT_LOG="$DISABLED_OUT" seq_check 0 $((NUMMESSAGES - 1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-mtls-sigalgs-vg.sh0000644000000000000000000000013215241075234023250 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.572970615 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-mtls-sigalgs-vg.sh0000775000175000017500000000013315241075234022714 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-mtls-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/mysql-actq-mt-withpause-vg.sh0000644000000000000000000000013215171370365021377 xustar0030 mtime=1776677109.465913449 30 atime=1782715518.911790931 30 ctime=1787067805.940940204 rsyslog-8.2608.0/tests/mysql-actq-mt-withpause-vg.sh0000775000175000017500000000022315171370365021043 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:=.}/mysql-actq-mt-withpause.sh rsyslog-8.2608.0/tests/PaxHeaders/imrelp-manyconn-vg.sh0000644000000000000000000000013215171370365017767 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.911790931 30 ctime=1787067807.764974193 rsyslog-8.2608.0/tests/imrelp-manyconn-vg.sh0000775000175000017500000000057615171370365017446 0ustar00rgerrger#!/bin/bash if [ "$CI_ENV" == "Centos7VM" ]; then # we give up, for some reason we see errors in this env but in no other Centos 7 env # this is a hack for rsyslog official CI - sorry for that -- rgerhards, 2019-01-24 echo "SKIP test, as for some reason it does not work here - this should be investigated" exit 77 fi export USE_VALGRIND="YES" . ${srcdir:=.}/imrelp-manyconn.sh rsyslog-8.2608.0/tests/PaxHeaders/uxsock_multiple-vg.sh0000644000000000000000000000013215216464436020111 xustar0030 mtime=1782212894.090267219 30 atime=1782715518.911790931 30 ctime=1787067807.662972293 rsyslog-8.2608.0/tests/uxsock_multiple-vg.sh0000775000175000017500000000013015216464436017552 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . "${srcdir:-$(dirname "$0")}/uxsock_multiple.sh" rsyslog-8.2608.0/tests/PaxHeaders/template-property-timegenerated.sh0000644000000000000000000000013115216464436022557 xustar0030 mtime=1782212894.086267154 30 atime=1782715518.911790931 29 ctime=1787067805.84893849 rsyslog-8.2608.0/tests/template-property-timegenerated.sh0000775000175000017500000000636715216464436022243 0ustar00rgerrger#!/bin/bash # This focused template/property test uses faketime to make generated-time # MsgGetProp formatting deterministic. It covers UTC conversion and generated # timestamp date-part variants without depending on wall-clock time. . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST+02:00 generate_conf add_conf ' template(name="outfmt" type="list") { constant(value="generated_utc=") property(name="timegenerated" date.inUTC="on") constant(value="\ngenerated_local=") property(name="timegenerated") constant(value="\ngenerated_local_formats=") property(name="timegenerated" dateformat="mysql") constant(value="/") property(name="timegenerated" dateformat="pgsql") constant(value="/") property(name="timegenerated" dateformat="rfc3164") constant(value="/") property(name="timegenerated" dateformat="rfc3339") constant(value="/") property(name="timegenerated" dateformat="unixtimestamp") constant(value="/") property(name="timegenerated" dateformat="wdayname") constant(value="/") property(name="timegenerated" dateformat="wday") constant(value="/") property(name="timegenerated" dateformat="ordinal") constant(value="/") property(name="timegenerated" dateformat="week") constant(value="\ngenerated_utc_formats=") property(name="timegenerated" dateformat="mysql" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="pgsql" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="rfc3164" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="rfc3339" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="unixtimestamp" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="wdayname" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="wday" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="ordinal" date.inUTC="on") constant(value="/") property(name="timegenerated" dateformat="week" date.inUTC="on") constant(value="\ngenerated_parts=") property(name="timegenerated" dateformat="year" date.inUTC="on") constant(value="-") property(name="timegenerated" dateformat="month" date.inUTC="on") constant(value="-") property(name="timegenerated" dateformat="day" date.inUTC="on") constant(value="T") property(name="timegenerated" dateformat="hour" date.inUTC="on") constant(value=":") property(name="timegenerated" dateformat="minute" date.inUTC="on") constant(value=":") property(name="timegenerated" dateformat="second" date.inUTC="on") constant(value="\n") } local4.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' export FAKETIME='2016-03-01 12:34:56' startup injectmsg_literal '<167>1 2003-08-24T05:14:15.000003-07:00 host app proc msgid - trigger' wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" 5 shutdown_when_empty wait_shutdown export EXPECTED='generated_utc=Mar 1 14:34:56 generated_local=Mar 1 12:34:56 generated_local_formats=20160301123456/2016-03-01 12:34:56/Mar 1 12:34:56/2016-03-01T12:34:56.000000-02:00/1456842896/Tue/2/061/10 generated_utc_formats=20160301143456/2016-03-01 14:34:56/Mar 1 14:34:56/2016-03-01T14:34:56.000000+00:00/1456842896/Tue/2/061/10 generated_parts=2016-03-01T14:34:56' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-readmode2-vg.sh0000644000000000000000000000013215035412264017756 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.910790914 30 ctime=1787067808.076980007 rsyslog-8.2608.0/tests/imfile-readmode2-vg.sh0000777000175000017500000000335015035412264017430 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup_vg # write the beginning of the file echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input wait_file_lines $RSYSLOG_OUT_LOG 1 # write some more lines (see https://github.com/rsyslog/rsyslog/issues/144) echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2 wait_file_lines $RSYSLOG_OUT_LOG 3 shutdown_when_empty wait_shutdown_vg check_exit_vg ## check if we have the correct number of messages NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" cat $RSYSLOG_OUT_LOG error_exit 1 else if [ ! $NUMLINES -eq 3 ]; then echo "ERROR: expecting 3 headers, got $NUMLINES" cat $RSYSLOG_OUT_LOG error_exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {1..4}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" cat $RSYSLOG_OUT_LOG error_exit 1 fi done ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-num-vg.sh0000644000000000000000000000013215171370365022260 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.910790914 30 ctime=1787067805.249927327 rsyslog-8.2608.0/tests/rscript_compare_numstr-num-vg.sh0000775000175000017500000000017415171370365021731 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='2' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/imrelp-persource-ratelimit-policy.sh0000644000000000000000000000013215216464436023032 xustar0030 mtime=1782212894.065266814 30 atime=1782715518.909790897 30 ctime=1787067807.719973355 rsyslog-8.2608.0/tests/imrelp-persource-ratelimit-policy.sh0000775000175000017500000000443115216464436022503 0ustar00rgerrger#!/bin/bash ## Test that imrelp inherits per-source limiting through ratelimitAddMsg(). ## The oracle also covers discard handling: rate-limited RELP messages must not ## make librelp treat the receive callback as a session-level failure. ## The submitted counter must match the delivered message count, proving RELP ## maps per-source discard to callback success only after preserving regular ## ratelimiter discard semantics for module accounting. ## The impstats sleep gives the one-second stats interval time to publish that ## submitted counter before shutdown. . ${srcdir:=.}/diag.sh init require_plugin impstats skip_ARM "ratelimit timing flaky on ARM" export SENDMESSAGES=20 export NUMMESSAGES=5 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export STATSFILE="$RSYSLOG_DYNNAME.stats" POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" export POLICY_FILE cat > "$POLICY_FILE" < $RSYSLOG_OUT_LOG startup # Inject 2 messages injectmsg 1 2 shutdown_when_empty wait_shutdown # Should get an empty string (no ERR) redis_command "XINFO GROUPS outStream" >> $RSYSLOG_OUT_LOG # Should get '2' redis_command "XLEN outStream" >> $RSYSLOG_OUT_LOG # Should get 2 entries redis_command "XREAD COUNT 3 STREAMS outStream 0" >> $RSYSLOG_OUT_LOG # Cannot check for full reply as it includes entries' unix timestamp content_count_check "ERR no such key" 1 $RSYSLOG_OUT_LOG content_count_check "outStream" 1 $RSYSLOG_OUT_LOG content_count_check " msgnum:00000001:" 1 $RSYSLOG_OUT_LOG content_count_check " msgnum:00000002:" 1 $RSYSLOG_OUT_LOG # 2 for the name of the field where the message was inserted, 2 for the 'msgnum' part content_count_check "msg" 4 $RSYSLOG_OUT_LOG content_count_check "msgnum" 2 $RSYSLOG_OUT_LOG content_check "omhiredis: no stream.outField set, using 'msg' as default" ${RSYSLOG_DYNNAME}.started content_check "omhiredis[omhiredis-stream]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdocker-new-logs-from-start.sh0000644000000000000000000000013215216464436021672 xustar0030 mtime=1782212894.053266621 30 atime=1782715518.909790897 30 ctime=1787067806.349947825 rsyslog-8.2608.0/tests/imdocker-new-logs-from-start.sh0000775000175000017500000000320415216464436021340 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # imdocker unit tests are enabled with --enable-imdocker-tests . ${srcdir:=.}/diag.sh init COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1) export COOKIE generate_conf add_conf ' #template(name="template_msg_only" type="string" string="%msg%\n") template(name="outfmt" type="string" string="%$!metadata!Names% %msg%\n") module(load="../contrib/imdocker/.libs/imdocker" PollingInterval="1" ListContainersOptions="all=true" GetContainerLogOptions="tail=1×tamps=0&follow=1&stdout=1&stderr=0&tail=1" RetrieveNewLogsFromStart="on" ) action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") if $!metadata!Names == "'$COOKIE'" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' #NUM_ITEMS=1000 # launch a docker runtime to generate some logs. # these log items should be tailed. docker run \ --rm \ -e seq_start=101 \ -e seq_end=200 \ alpine \ /bin/sh -c 'for i in `seq $seq_start $seq_end`; do echo "tailed item $i"; sleep .01; done' > /dev/null & sleep 1 #export RS_REDIR=-d startup NUMMESSAGES=1000 # launch a docker runtime to generate some logs. # These logs started after start-up should get from beginning docker run \ --name $COOKIE \ -e NUMMESSAGES=$NUMMESSAGES \ alpine \ /bin/sh -c 'for i in `seq 1 $NUMMESSAGES`; do echo "log item $i"; done' > /dev/null shutdown_when_empty wait_shutdown echo "file name: $RSYSLOG_OUT_LOG" echo "\"tailed item\" occurred: $(grep -c 'tailed item ' $RSYSLOG_OUT_LOG)/100 (expect less)." docker container rm $COOKIE exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_table_rscript_reload.sh0000644000000000000000000000013215241075234022014 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067804.985922408 rsyslog-8.2608.0/tests/lookup_table_rscript_reload.sh0000775000175000017500000000377315241075234021475 0ustar00rgerrger#!/bin/bash # Test lookup-table reload by the RainerScript reload_lookup_table statement. # The second reload uses uppercase hex escapes in procedure-call strings; the # output oracle proves those strings parsed to the intended table and stub # values before the reload failure fallback is applied. # Added 2015-12-18 by singh.janmejay. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); if ($msg == " msgnum:00000002:") then { reload_lookup_table("\x78\x6C\x61\x74\x65", "\x72\x65\x6C\x6F\x61\x64\x5F\x66\x61\x69\x6C\x65\x64"); } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup # the last message ..002 should cause successful lookup-table reload cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl injectmsg 0 3 await_lookup_table_reload wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl injectmsg 0 3 await_lookup_table_reload wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: bar_new" content_check "msgnum:00000002: baz" rm -f $RSYSLOG_DYNNAME.xlate.lkp_tbl # this should lead to unsuccessful reload injectmsg 0 3 await_lookup_table_reload wait_queueempty injectmsg 0 2 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: foo_latest" content_check "msgnum:00000001: quux" content_check "msgnum:00000002: baz_latest" content_check "msgnum:00000000: reload_failed" content_check "msgnum:00000000: reload_failed" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-crash-state.sh0000644000000000000000000000013215241075234021724 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.692579923 30 ctime=1787067803.837901015 rsyslog-8.2608.0/tests/segmented-da-idle-crash-state.sh0000775000175000017500000000043115241075234021371 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Crash immediately after the durable empty-state publication. export SEGDISK_IDLE_FAULT_POINT=idle-empty-published . ${srcdir:=.}/testsuites/segmented-da-idle-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse1-udp.sh0000644000000000000000000000013115035412264020411 xustar0030 mtime=1752569012.406709056 29 atime=1782715518.90879088 30 ctime=1787067805.011922892 rsyslog-8.2608.0/tests/parsertest-parse1-udp.sh0000777000175000017500000001434615035412264020073 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") global(localHostname="localhost") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 %PIX-7-710005: UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 27 19:06:53 source_server sshd(pam_unix)[12750]: session opened for user foo by (uid=0)\"" tcpflood -m1 -T "udp" -M "\"<167>Apr 6 15:07:10 lxcvs07 sshd(pam_unix)[31738]: session closed for user cvsadmin\"" tcpflood -m1 -T "udp" -M "\"<167>Jul 31 21:39:21 example-b example-gw[10538]: disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0\"" tcpflood -m1 -T "udp" -M "\"<167>AUG 10 22:18:24 host tag This msg contains 8-bit European chars: äöü\"" tcpflood -m1 -T "udp" -M "\"<167> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 7 2008 19:06:53: example tag: testmessage (only date actually tested)\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 7 2008 19:06:53 example tag: testmessage (only date actually tested)\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 7 19:06:53: example tag: testmessage (only date actually tested)\"" tcpflood -m1 -T "udp" -M "\"<14>Jan 6 2009 15:22:26 localhost\"" tcpflood -m1 -T "udp" -M "\"<167>Oct 8 23:05:06 10.321.1.123 05\\\",result_code=200,b\"" tcpflood -m1 -T "udp" -M "\"<167>Feb 18 16:01:59 serverX -- MARK --\"" tcpflood -m1 -T "udp" -M "\"Feb 18 16:01:59 serverX -- MARK --\"" tcpflood -m1 -T "udp" -M "\"<38>Mar 27 19:06:53 source_server 0123456789012345678901234567890123456789: MSG part\"" tcpflood -m1 -T "udp" -M "\"<29>Oct 16 20:47:24 example-p exam-pl[12345]: connect host= /192.0.2.1\"" tcpflood -m1 -T "udp" -M "\"<34>Oct 11 22:14:15 mymachine su: su root failed for lonvick on /dev/pts/8\"" tcpflood -m1 -T "udp" -M "\"<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - BOMsu root failed for lonvick on /dev/pts/8\"" tcpflood -m1 -T "udp" -M "\"<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 myproc 8710 - - %% Its time to make the do-nuts.\"" tcpflood -m1 -T "udp" -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"][examplePriority@32473 class=\\\"high\\\"]\"" tcpflood -m1 -T "udp" -M "\"<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut=\\\"3\\\" eventSource= \\\"Application\\\" eventID=\\\"1011\\\"] BOMAn application event log entry...\"" tcpflood -m1 -T "udp" -M "\"<6>AUG 10 22:18:24 2009 netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset\"" tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"" tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711 \"" tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 X4711\"" tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05 \"" tcpflood -m1 -T "udp" -M "\"<14>Aug 30 23:00:05\"" tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"" tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711 \"" tcpflood -m1 -T "udp" -M "\"<14>2010-08-30T23:00:05Z X4711\"" shutdown_when_empty wait_shutdown export EXPECTED="167,local4,debug,Mar 6 16:57:54,172.20.245.8,%PIX-7-710005,%PIX-7-710005:, UDP request discarded from SERVER1/2741 to test_app:255.255.255.255/61601 167,local4,debug,Mar 27 19:06:53,source_server,sshd(pam_unix),sshd(pam_unix)[12750]:, session opened for user foo by (uid=0) 167,local4,debug,Apr 6 15:07:10,lxcvs07,sshd(pam_unix),sshd(pam_unix)[31738]:, session closed for user cvsadmin 167,local4,debug,Jul 31 21:39:21,example-b,example-gw,example-gw[10538]:, disconnect host=/192.0.2.1 destination=192.0.2.2/11282 in=3274 out=1448 duration=0 167,local4,debug,Aug 10 22:18:24,host,tag,tag, This msg contains 8-bit European chars: äöü 167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested) 167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested) 167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested) 167,local4,debug,Mar 7 19:06:53,example,tag,tag:, testmessage (only date actually tested) 14,user,info,Jan 6 15:22:26,localhost,,, 167,local4,debug,Oct 8 23:05:06,10.321.1.123,05\",result_code=200,b,05\",result_code=200,b, 167,local4,debug,Feb 18 16:01:59,serverX,--,--, MARK -- 13,user,notice,Feb 18 16:01:59,serverX,--,--, MARK -- 38,auth,info,Mar 27 19:06:53,source_server,0123456789012345678901234567890123456789,0123456789012345678901234567890123456789:, MSG part 29,daemon,notice,Oct 16 20:47:24,example-p,exam-pl,exam-pl[12345]:, connect host= /192.0.2.1 34,auth,crit,Oct 11 22:14:15,mymachine,su,su:, su root failed for lonvick on /dev/pts/8 34,auth,crit,Oct 11 22:14:15,mymachine.example.com,su,su,BOMsu root failed for lonvick on /dev/pts/8 165,local4,notice,Aug 24 05:14:15,192.0.2.1,myproc,myproc[8710],%% Its time to make the do-nuts. 165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog, 165,local4,notice,Oct 11 22:14:15,mymachine.example.com,evntslog,evntslog,BOMAn application event log entry... 6,kern,info,Aug 10 22:18:24,2009,,, netips-warden2-p [audit] user=[*SMS] src=192.168.11.11 iface=5 access=9 Update State Reset 14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, 14,user,info,Aug 30 23:00:05,X4711,,, 14,user,info,Aug 30 23:00:05,X4711,,, 14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,, 14,user,info,Aug 30 23:00:05,$RS_HOSTNAME,,, 14,user,info,Aug 30 23:00:05,X4711,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, 14,user,info,Aug 30 23:00:05,X4711,,, 14,user,info,Aug 30 23:00:05,X4711,,," cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_exists-not1.sh0000644000000000000000000000013115131231047020175 xustar0030 mtime=1768239655.717212794 29 atime=1782715518.90879088 30 ctime=1787067804.897920768 rsyslog-8.2608.0/tests/rscript_exists-not1.sh0000777000175000017500000000102315131231047017643 0ustar00rgerrger#!/bin/bash # add 2020-10-02 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%!result%\n") # ensure that in this test there is NO variable define at all if $msg contains "msgnum" then { if exists($!p1!p2!val) then set $!result = "on"; else set $!result = "off"; action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown export EXPECTED='off' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-statefile-no-delete.sh0000644000000000000000000000013215131231047021327 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.909790897 30 ctime=1787067807.955977752 rsyslog-8.2608.0/tests/imfile-statefile-no-delete.sh0000777000175000017500000000227415131231047021005 0ustar00rgerrger#!/bin/bash # Added 2019-02-28 # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init export TESTMESSAGES=1000 export TESTMESSAGESFULL=999 export RETRIES=50 generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" tag="file:" file="./'$RSYSLOG_DYNNAME'.input" deleteStateOnFileDelete="off") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' ./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input inode=$(get_inode "$RSYSLOG_DYNNAME.input") startup wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES rm $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to notice the deleted file ./msleep 2000 shutdown_when_empty wait_shutdown seq_check 0 $TESTMESSAGESFULL # check we got the message correctly if ! ls $RSYSLOG_DYNNAME.spool/imfile-state:$inode:* 1> /dev/null 2>&1; then printf 'FAIL: state file was deleted when it should not have been\nspool dir is:\n' ls -l $RSYSLOG_DYNNAME.spool error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imudp-headerless-fromhost-ip.sh0000644000000000000000000000013115241075234021737 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.685579792 29 ctime=1787067805.01392293 rsyslog-8.2608.0/tests/imudp-headerless-fromhost-ip.sh0000775000175000017500000000216715241075234021415 0ustar00rgerrger#!/bin/bash # Regression test for lazy UDP source-address handling used by headerless # messages. The fromhost-ip property resolves through the sockaddr stored at # receive time. The oracle is that normal UDP loopback traffic produces stable # loopback source properties and never exposes the internal ?error.obtaining.ip? # DNS-cache sentinel reported in issue #5461. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=20 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global(net.enableDNS="off") module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'") template(name="outfmt" type="string" string="host=%hostname% from=%fromhost-ip% raw=%rawmsg%\n") if $rawmsg contains "headerless message" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -m "$NUMMESSAGES" -T udp -M "\"headerless message\"" shutdown_when_empty wait_shutdown wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" content_check "host=headerless from=127.0.0.1 raw=headerless message" "$RSYSLOG_OUT_LOG" check_not_present "?error.obtaining.ip?" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_udp_nonstdpt.sh0000644000000000000000000000013015131231047020330 xustar0030 mtime=1768239655.721212859 29 atime=1782715518.90879088 29 ctime=1787067804.47891296 rsyslog-8.2608.0/tests/sndrcv_udp_nonstdpt.sh0000777000175000017500000000266615131231047020015 0ustar00rgerrger#!/bin/bash # This runs sends and receives messages via UDP to the non-standard port 2514 # Note that with UDP we can always have message loss. While this is # less likely in a local environment, we strongly limit the amount of data # we send in the hope to not lose any messages. However, failure of this # test does not necessarily mean that the code is wrong (but it is very likely!) # added 2009-11-11 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export TCPFLOOD_EXTRA_OPTS="-b1 -W1" export NUMMESSAGES=50 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' $ModLoad ../plugins/imudp/.libs/imudp # then SENDER sends to this port (not tcpflood!) $UDPServerRun '$TCPFLOOD_PORT' $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup export RSYSLOG_DEBUGLOG="log2" export PORT_RCVR="$TCPFLOOD_PORT" #valgrind="valgrind" generate_conf 2 add_conf ' *.* @127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-drvr-in-input-basic.sh0000644000000000000000000000013215241075234021147 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067807.354966553 rsyslog-8.2608.0/tests/imtcp-drvr-in-input-basic.sh0000775000175000017500000000175315241075234020624 0ustar00rgerrger#!/bin/bash # added 2021-04-27 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5000 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_64_ipv6.sh0000644000000000000000000000013115131231047020032 xustar0030 mtime=1768239655.709212663 29 atime=1782715518.90879088 30 ctime=1787067805.757936794 rsyslog-8.2608.0/tests/mmanon_zero_64_ipv6.sh0000777000175000017500000000232015131231047017501 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv6.bits="64" ipv6.anonmode="zero") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0 <129>Mar 10 01:00:00 172.20.245.8 tag: :: <129>Mar 10 01:00:00 172.20.245.8 tag: 0:: <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45: <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\"" shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk ffff:ffff:ffff:ffff:0:0:0:0 61:34:ad:0:0:0:0:0 aa:ff43:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 13:abd:45: textnoblank72:8374:adc7:47ff:0:0:0:0stillnoblank' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-bad-state-file.sh0000644000000000000000000000013115216464436020273 xustar0030 mtime=1782212894.054266637 29 atime=1782715518.90879088 30 ctime=1787067807.950977659 rsyslog-8.2608.0/tests/imfile-bad-state-file.sh0000775000175000017500000000223315216464436017743 0ustar00rgerrger#!/bin/bash # Verify that imfile ignores a malformed state file and falls back to a fresh read. # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" PersistStateInterval="1") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' ./inputfilegen -m5 > "$RSYSLOG_DYNNAME.input" startup shutdown_when_empty wait_shutdown seq_check 0 4 statefile=$(find "$RSYSLOG_DYNNAME.spool" -maxdepth 1 -name 'imfile-state*' | head -n 1) if [ -z "$statefile" ]; then printf 'FAIL: expected imfile state file in %s.spool\n' "$RSYSLOG_DYNNAME" ls -la "$RSYSLOG_DYNNAME.spool" error_exit 1 fi printf '{"curr_offs":\n' > "$statefile" rm -f "$RSYSLOG_OUT_LOG" startup shutdown_when_empty wait_shutdown seq_check 0 4 content_check "imfile: error reading state file" "$RSYSLOG_DYNNAME.started" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-error-cert.sh0000644000000000000000000000013215241075234021214 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.776581496 30 ctime=1787067807.490969087 rsyslog-8.2608.0/tests/imtcp-tls-ossl-error-cert.sh0000775000175000017500000000161415241075234020665 0ustar00rgerrger#!/bin/bash # added 2018-11-07 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert-fail.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # note: we do not need to generate any messages, config error occurs on startup startup sleep 5 # TODO: FIXME - just checking if we terminate too early shutdown_when_empty wait_shutdown content_check "Error: Certificate file could not be accessed" content_check "OpenSSL Error Stack:" exit_test rsyslog-8.2608.0/tests/PaxHeaders/config-translate-rs-script-expressions.sh0000644000000000000000000000013215216464436024014 xustar0030 mtime=1782212894.047266524 30 atime=1782715518.910790914 30 ctime=1787067805.326928762 rsyslog-8.2608.0/tests/config-translate-rs-script-expressions.sh0000775000175000017500000000450315216464436023465 0ustar00rgerrger#!/bin/bash # Check canonical RainerScript emission for complex script statements. # # This is a cheap -N1 translation test for runtime/translate.c's script # serializer. It covers escaped strings, arrays, unary minus, set/reset/unset, # boolean/comparison expressions, exists(), foreach, call, call_indirect, and # if/else block formatting. The translated RainerScript is validated again so # the exact-output oracle proves the emitted config remains parseable. # # Part of the testbench for rsyslog. # # This file is part of rsyslog. # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init modpath="../runtime/.libs:../.libs" target_out="/tmp/${RSYSLOG_DYNNAME}.target.log" cat > "${RSYSLOG_DYNNAME}.conf" <<'RS_EOF' ruleset(name="target") { action(type="omfile" file="@TARGET_OUT@") } ruleset(name="main") { set $.n = -7; set $.s = "line\nquote\"tab\tbackslash\\"; set $.arr = ["one", "two"]; reset $.scratch = $.arr; unset $.arr; if not exists($!missing) and (($msg contains_i "ERR") or ($msg startswith " start")) then { foreach ($.item in $!items) do { call target } } else { call_indirect "tar" & "get"; } } RS_EOF sed "s|@TARGET_OUT@|${target_out}|g" "${RSYSLOG_DYNNAME}.conf" >"${RSYSLOG_DYNNAME}.conf.tmp" && mv "${RSYSLOG_DYNNAME}.conf.tmp" "${RSYSLOG_DYNNAME}.conf" ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F rainerscript -o "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath" || error_exit $? cat > "${RSYSLOG_DYNNAME}.expected.conf" <<'RS_EOF' ruleset(name="target") { action(type="omfile" file="@TARGET_OUT@") } ruleset(name="main") { set $.n = -7; set $.s = "line\nquote\"tab\tbackslash\\"; set $.arr = ["one", "two"]; reset $.scratch = $.arr; unset $.arr; if (not exists($!missing) and (($msg contains_i "ERR") or ($msg startswith " start"))) then { foreach ($.item in $!items) do { call target } } else { call_indirect ("tar" & "get"); } } RS_EOF sed "s|@TARGET_OUT@|${target_out}|g" "${RSYSLOG_DYNNAME}.expected.conf" >"${RSYSLOG_DYNNAME}.expected.conf.tmp" && mv "${RSYSLOG_DYNNAME}.expected.conf.tmp" "${RSYSLOG_DYNNAME}.expected.conf" cmp_exact_file "${RSYSLOG_DYNNAME}.expected.conf" "${RSYSLOG_DYNNAME}.out.conf" ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath" || error_exit $? echo SUCCESS: RainerScript script expression translation exit_test rsyslog-8.2608.0/tests/PaxHeaders/ommail-smtp.sh0000644000000000000000000000013215216464436016507 xustar0030 mtime=1782212894.079267041 30 atime=1782715518.909790897 30 ctime=1787067805.695935638 rsyslog-8.2608.0/tests/ommail-smtp.sh0000775000175000017500000000372515216464436016165 0ustar00rgerrger#!/bin/bash # This test covers ommail's SMTP mode against a deterministic local SMTP # helper. The helper writes its port file only after listen() succeeds and # writes a done file after QUIT, so success is proven by synchronized shutdown # plus the captured SMTP transcript instead of fixed sleeps. . ${srcdir:=.}/diag.sh init if ! command -v python3 >/dev/null 2>&1; then echo "python3 not available, skipping ommail SMTP helper test" skip_test fi PORT_FILE="$RSYSLOG_DYNNAME.ommail-smtp.port" SMTP_OUT="$RSYSLOG_DYNNAME.ommail-smtp.out" SMTP_DONE="$RSYSLOG_DYNNAME.ommail-smtp.done" python3 "$srcdir/testsuites/ommail-smtp-server.py" \ --port-file "$PORT_FILE" \ --output "$SMTP_OUT" \ --done-file "$SMTP_DONE" & SMTP_PID=$! trap 'kill "$SMTP_PID" 2>/dev/null' EXIT wait_file_exists "$PORT_FILE" SMTP_PORT=$(cat "$PORT_FILE") generate_conf add_conf ' module(load="../plugins/ommail/.libs/ommail") template(name="mailBody" type="string" string="smtp alert %msg%\\r\\n") if $msg contains "msgnum:" then { action( type="ommail" mode="smtp" server="127.0.0.1" port="'$SMTP_PORT'" mailfrom="rsyslog@example.net" mailto=["operator@example.net", "admin@example.net"] subject.text="rsyslog smtp alert" body.enable="on" template="mailBody" ) } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown wait_file_exists "$SMTP_DONE" wait "$SMTP_PID" trap - EXIT content_check "CMD:HELO" "$SMTP_OUT" content_check "CMD:MAIL FROM:" "$SMTP_OUT" content_check "CMD:RCPT TO:" "$SMTP_OUT" content_check "CMD:RCPT TO:" "$SMTP_OUT" content_check "CMD:DATA" "$SMTP_OUT" content_check "DATA_BEGIN" "$SMTP_OUT" content_check "From: " "$SMTP_OUT" content_check "Subject: rsyslog smtp alert" "$SMTP_OUT" content_check "smtp alert msgnum:00000000:" "$SMTP_OUT" content_check "DATA_END" "$SMTP_OUT" content_check "CMD:QUIT" "$SMTP_OUT" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-profile-loki.sh0000644000000000000000000000013215132733117020145 xustar0030 mtime=1768666703.963621086 30 atime=1782715518.909790897 30 ctime=1787067806.145944024 rsyslog-8.2608.0/tests/omhttp-profile-loki.sh0000777000175000017500000000261715132733117017624 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Test the profile="loki" configuration # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 # Start a mock Loki server (enable decompression as profile enables compression) omhttp_start_server 0 --decompress generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") # Simplified loki payload to match test harness lokirest parser template(name="loki_template" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") ruleset(name="ruleset_omhttp_loki") { action( name="action_omhttp_loki" type="omhttp" # Use the Loki profile profile="loki" template="loki_template" server="localhost" serverport="'$omhttp_server_lstnport'" # The profile should set these defaults: # - batch.format="lokirest" # - restpath="loki/api/v1/push" # - batch="on" # - compress="on" # Our mock server is plain HTTP usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp_loki ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown # Verify data was sent to the Loki endpoint; parse as lokirest omhttp_get_data $omhttp_server_lstnport loki/api/v1/push lokirest omhttp_stop_server # Verify all messages were sent seq_check 0 $(( NUMMESSAGES - 1 )) exit_test rsyslog-8.2608.0/tests/PaxHeaders/omrelp_wrong_authmode.sh0000644000000000000000000000013215131231047020632 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.909790897 30 ctime=1787067807.740973746 rsyslog-8.2608.0/tests/omrelp_wrong_authmode.sh0000777000175000017500000000116015131231047020301 0ustar00rgerrger#!/bin/bash # add 2018-09-13 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omrelp/.libs/omrelp") ruleset(name="ruleset") { action(type="omrelp" target="127.0.0.1" port="'$TCPFLOOD_PORT'" tls="on" tls.authMode="INVALID_AUTH_MODE" tls.caCert="tls-certs/ca.pem" tls.myCert="tls-certs/cert.pem" tls.myPrivKey="tls-certs/key.pem" tls.permittedPeer=["rsyslog-test-root-ca"]) } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "omrelp.* invalid auth.*mode .*INVALID_AUTH_MODE" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_stop.sh0000644000000000000000000000013215035412264016772 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.909790897 30 ctime=1787067804.745917936 rsyslog-8.2608.0/tests/rscript_stop.sh0000777000175000017500000000132615035412264016445 0ustar00rgerrger#!/bin/bash # added 2012-09-20 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_stop.sh\]: testing rainerscript STOP statement . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); if cnum($!usr!msgnum) >= 5000 then stop action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup injectmsg 0 8000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-find-json-conflict-vg.sh0000644000000000000000000000013015216464436022702 xustar0029 mtime=1782212894.07426696 29 atime=1782715518.90879088 30 ctime=1787067807.206963795 rsyslog-8.2608.0/tests/mmjsonparse-find-json-conflict-vg.sh0000775000175000017500000000071015216464436022351 0ustar00rgerrger#!/bin/bash # Valgrind wrapper for mmjsonparse-find-json-conflict.sh. The base test creates # a msgAddJSON failure after ownership transfer; Valgrind is the oracle that the # parsed JSON object is released exactly once on that negative path. # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" if [ -z "${srcdir:-}" ]; then cd "$(dirname "$0")" || exit 1 srcdir=. fi . "$srcdir/mmjsonparse-find-json-conflict.sh" rsyslog-8.2608.0/tests/PaxHeaders/rscript_append_json-vg.sh0000644000000000000000000000013115171370365020724 xustar0030 mtime=1776677109.468913495 29 atime=1782715518.90879088 30 ctime=1787067805.314928539 rsyslog-8.2608.0/tests/rscript_append_json-vg.sh0000775000175000017500000000020315171370365020367 0ustar00rgerrger#!/bin/bash # Added 2025-12-26 by 20syldev, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_append_json.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-truncate-line.sh0000644000000000000000000000013215035412264020254 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.911790931 30 ctime=1787067807.880976355 rsyslog-8.2608.0/tests/imfile-truncate-line.sh0000777000175000017500000000547215035412264017735 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # This test mimics the test imfile-readmode2.sh, but works via # endmsg.regex. It's kind of a base test for the regex functionality. echo ====================================================================== # Check if inotify header exist echo [imfile-truncate-line.sh] . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MaxMessageSize 128 global(oversizemsg.input.mode="accept" oversizemsg.report="on") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" discardTruncatedMsg="off" Tag="file:" startmsg.regex="^[^ ]" ruleset="ruleset") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt") ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1 msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb msgnum:4 cccccccccccccccccccccccccccccccccccccccccccc msgnum:5 dddddddddddddddddddddddddddddddddddddddddddd msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff msgnum:8 gggggggggggggggggggggggggggggggggggggggggggg msgnum:9' > $RSYSLOG_DYNNAME.input # the next line terminates our test. It is NOT written to the output file, # as imfile waits whether or not there is a follow-up line that it needs # to combine. echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing ./msleep 500 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! printf 'HEADER msgnum:0 HEADER msgnum:1 HEADER msgnum:2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\\n msgnum:3 bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\\\n msgnum:4 ccccccc HEADER ccccccccccccccccccccccccccccccccccccc\\\\n msgnum:5 dddddddddddddddddddddddddddddddddddddddddddd HEADER msgnum:6 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\\\\n msgnum:7 ffffffffffffffffffffffffffffffffffffffffffff\\\\n msgnum:8 ggggggg HEADER ggggggggggggggggggggggggggggggggggggg HEADER msgnum:9\n' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; grep "imfile error:.*message will be split and processed" ${RSYSLOG2_OUT_LOG} > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message from missing input file not found. ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/stop-localvar.sh0000644000000000000000000000013215241075234017026 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.798581908 30 ctime=1787067804.064905246 rsyslog-8.2608.0/tests/stop-localvar.sh0000775000175000017500000000167415241075234016505 0ustar00rgerrger#!/bin/bash # Test for "stop" statement # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[stop-localvar.sh\]: testing stop statement together with local variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.nbr%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if $msg contains "msgnum:" then { set $.nbr = field($msg, 58, 2); if cnum($.nbr) < 100 then stop /* check is intentionally more complex than needed! */ else if not (cnum($.nbr) > 999) then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } } ' startup sleep 1 tcpflood -m2000 -i1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 100 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-bigmessage-octetstuffing.sh0000644000000000000000000000013215241075234022342 xustar0030 mtime=1787067036.622578613 30 atime=1787067036.771581402 30 ctime=1787067805.530932564 rsyslog-8.2608.0/tests/imtcp-bigmessage-octetstuffing.sh0000775000175000017500000000301215241075234022005 0ustar00rgerrger#!/bin/bash # add 2020-05-14 by alorbach, released under ASL 2.0 export NUMMESSAGES=10 export TEST_BYTES_SENDSIZE=4037 export TEST_BYTES_EXPECTED=$(((TEST_BYTES_SENDSIZE/2 - 420) * NUMMESSAGES)) # 262152 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( workDirectory="'$RSYSLOG_DYNNAME.spool'" maxMessageSize="4k" ) module( load="../plugins/imtcp/.libs/imtcp" MaxSessions="10000" discardTruncatedMsg="on" ) input( type="imtcp" name="imtcp" port="'$TCPFLOOD_PORT'" ruleset="print" ) template(name="print_message" type="list"){ constant(value="inputname: ") property(name="inputname") constant(value=", strlen: ") property(name="$!strlen") constant(value=", message: ") property(name="msg") constant(value="\n") } ruleset(name="print") { set $!strlen = strlen($msg); action( type="omfile" template="print_message" file=`echo $RSYSLOG_OUT_LOG` ) } ' startup tcpflood -m$NUMMESSAGES -d $TEST_BYTES_SENDSIZE shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown content_count_check --regex "inputname: imtcp, strlen:" ${NUMMESSAGES} count=$(wc -c < $RSYSLOG_OUT_LOG) if [ $count -lt $TEST_BYTES_EXPECTED ]; then echo echo "FAIL: expected bytes count $count did not match $TEST_BYTES_EXPECTED. " echo echo "First 100 bytes of $RSYSLOG_OUT_LOG are: " head -c 100 $RSYSLOG_OUT_LOG echo echo "Last 100 bytes of $RSYSLOG_OUT_LOG are: " tail -c 100 $RSYSLOG_OUT_LOG error_exit 1 else echo "Found $count bytes (Expected $TEST_BYTES_EXPECTED) in $RSYSLOG_OUT_LOG" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_optimizer_const_cmp.sh0000644000000000000000000000013215216464436022105 xustar0030 mtime=1782212894.081267073 30 atime=1782715518.910790914 30 ctime=1787067804.759918197 rsyslog-8.2608.0/tests/rscript_optimizer_const_cmp.sh0000775000175000017500000000213015216464436021550 0ustar00rgerrger#!/bin/bash # Verify that the RainerScript optimizer folds constant comparisons. # The oracle intentionally checks the internal debug log because this test is # about a config-optimizer transformation, not a message-processing diagnostic. # It also checks the normal output file to ensure the optimized-out branch did # not emit anything. # This file is part of the rsyslog project, released under ASL 2.0. echo =============================================================================== echo \[rscript_optimizer_const_cmp.sh\]: testing rainerscript constant comparison optimizer . ${srcdir:=.}/diag.sh init export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") if "a" == "b" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown touch "$RSYSLOG_OUT_LOG" check_not_present "msgnum:" "$RSYSLOG_OUT_LOG" content_check "optimizer: if with constant false expression and no else - remove" "$RSYSLOG_DEBUGLOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-errorfile.sh0000644000000000000000000000013215241075234020360 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.762581234 30 ctime=1787067805.802937632 rsyslog-8.2608.0/tests/clickhouse-errorfile.sh0000775000175000017500000000262215241075234020031 0ustar00rgerrger#!/bin/bash # add 2018-12-07 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init echo looks like clickhouse does no longer generate exceptions on error - skip until investigated exit 77 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omclickhouse/.libs/omclickhouse") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" option.stdsql="on" type="string" string="INSERT INTO rsyslog.errorfile (id, severity, facility, timestamp, ipaddress, tag, message) VALUES (%msg:F,58:2%, %syslogseverity%, %syslogfacility%, ' add_conf "'%timereported:::date-unixtimestamp%', '%fromhost-ip%', '%syslogtag%', '%msg%')" add_conf '") :syslogtag, contains, "tag" action(type="omclickhouse" server="localhost" port="8443" user="default" pwd="" template="outfmt" bulkmode="off" errorfile="'$RSYSLOG_OUT_LOG'") ' clickhouse-client --query="CREATE TABLE IF NOT EXISTS rsyslog.errorfile ( id Int32, severity Int8, facility Int8, timestamp DateTime, ipaddress String, tag String, message String ) ENGINE = MergeTree() PARTITION BY severity Order By id" startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:NoInteger\"" shutdown_when_empty wait_shutdown content_check --regex "msgnum:NoInteger.*DB::Exception:" clickhouse-client --query="DROP TABLE rsyslog.errorfile" exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmrfc3164-msgFirstSpace.sh0000644000000000000000000000013215241075234020435 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067804.329910184 rsyslog-8.2608.0/tests/pmrfc3164-msgFirstSpace.sh0000775000175000017500000000211515241075234020103 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser") parser(name="custom.rfc3164" type="pmrfc3164" remove.msgFirstSpace="on") template(name="outfmt" type="string" string="-%msg%-\n") ruleset(name="customparser" parser="custom.rfc3164") { :syslogtag, contains, "tag" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag:msgnum:3\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag4:\"" shutdown_when_empty wait_shutdown echo '-msgnum:1- - msgnum:2- -msgnum:3- --' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-oversizeMode-truncate.sh0000644000000000000000000000013115035412264022022 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.910790914 30 ctime=1787067807.694972889 rsyslog-8.2608.0/tests/imrelp-oversizeMode-truncate.sh0000777000175000017500000000241015035412264021471 0ustar00rgerrger#!/bin/bash # add 2018-04-19 by PascalWithopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ./have_relpSrvSetOversizeMode if [ $? -eq 1 ]; then echo "imrelp parameter oversizeMode not available. Test stopped" exit 77 fi; generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") global(maxMessageSize="150" oversizemsg.input.mode="accept") input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="200" oversizeMode="truncate") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m1 -d 240 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # We need the ^-sign to symbolize the beginning and the $-sign to symbolize the end # because otherwise we won't know if it was truncated at the right length. grep "^ msgnum:00000000:240:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-httpheaderkey.sh0000644000000000000000000000013215131231047020404 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.910790914 30 ctime=1787067806.160944303 rsyslog-8.2608.0/tests/omhttp-httpheaderkey.sh0000777000175000017500000000150515131231047020056 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 omhttp_start_server 0 generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../contrib/omhttp/.libs/omhttp") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" httpheaderkey="X-Insert-Key" httpheadervalue="dummy-value" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="off" # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omawslogshlc-basic.sh0000644000000000000000000000013215241075234020021 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.686579811 30 ctime=1787067806.327947415 rsyslog-8.2608.0/tests/omawslogshlc-basic.sh0000775000175000017500000000212615241075234017471 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Test basic functionality of omawslogshlc: send a small number of messages # to CloudWatch Logs via the HLC endpoint. The oracle is that rsyslog # processes all injected messages through the local omfile action and emits no # CloudWatch HTTP/authentication diagnostics while the HLC action runs. . ${srcdir:=.}/diag.sh init . ${srcdir:=.}/omawslogshlc-env.sh require_plugin "omawslogshlc" export NUMMESSAGES=5 omawslogshlc_require_env generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omawslogshlc/.libs/omawslogshlc") local4.* action( type="omawslogshlc" region="'$AWS_CWL_REGION'" bearer_token="'$AWS_CWL_BEARER_TOKEN'" log_group="'$AWS_CWL_LOG_GROUP'" log_stream="'$AWS_CWL_LOG_STREAM'" action.resumeInterval="1" action.resumeRetryCount="2" ) *.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) check_not_present "omawslogshlc: HTTP" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-retry.sh0000644000000000000000000000013215241075234020653 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.692579923 30 ctime=1787067803.835900978 rsyslog-8.2608.0/tests/segmented-da-idle-retry.sh0000775000175000017500000000333715241075234020330 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Keep a segmented DA action in retry state for longer than its 100 ms idle # timeout. The store must remain materialized while retry-before-commit owns # records; after the output directory appears, exact drain plus store removal # proves cleanup begins only after the retry batch is durably completed. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" SEG_DIR="$SPOOL_DIR/retryq.segq" OUTPUT_DIR="$PWD/${RSYSLOG_DYNNAME}.missing" OUTPUT_FILE="$OUTPUT_DIR/output.log" wait_path_state() { local mode="$1" path="$2" deadline=$((SECONDS + 30)) while true; do [ "$mode" = present ] && [ -e "$path" ] && return [ "$mode" = absent ] && [ ! -e "$path" ] && return [ "$SECONDS" -lt "$deadline" ] || error_exit 1 "path did not become $mode: $path" ./msleep 25 done } generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'"$OUTPUT_FILE"'" template="outfmt" createDirs="off" action.resumeRetryCount="-1" action.resumeInterval="1" queue.type="LinkedList" queue.filename="retryq" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.diskQueueType="segmentedDisk" queue.diskQueueIdleTimeout="100") ' startup injectmsg wait_path_state present "$SEG_DIR" ./msleep 500 [ -d "$SEG_DIR" ] || error_exit 1 "idle cleanup removed a store with retry records" mkdir "$OUTPUT_DIR" wait_file_lines "$OUTPUT_FILE" "$NUMMESSAGES" 300 wait_path_state absent "$SEG_DIR" shutdown_when_empty wait_shutdown RSYSLOG_OUT_LOG="$OUTPUT_FILE" seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-manycon.sh0000644000000000000000000000013215241075234020574 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.480968901 rsyslog-8.2608.0/tests/imtcp-tls-ossl-manycon.sh0000775000175000017500000000251015241075234020241 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100000 ulimit -n 2048 # may or may not work ;-) generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "nsd_ptcp.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/name" PermittedPeer=["/CN=rsyslog-client/OU=Adiscon GmbH/O=Adiscon GmbH/L=Grossrinderfeld/ST=BW/C=DE/DC=rsyslog.com","rsyslog.com"] ) input(type="imtcp" address="127.0.0.1" socketBacklog="1000" maxsessions="1000" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase startup tcpflood -c-1000 -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_truncated_dotted_suffix.sh0000644000000000000000000000013215216464436022535 xustar0030 mtime=1782212894.073266944 30 atime=1782715518.909790897 30 ctime=1787067805.771937055 rsyslog-8.2608.0/tests/mmanon_truncated_dotted_suffix.sh0000775000175000017500000000230715216464436022206 0ustar00rgerrger#!/bin/bash # This test hardens mmanon against truncated dotted IPv4-looking suffixes. # The oracle is normal shutdown plus exact output: malformed suffixes at the # end of a rewritten message must be preserved and must not read past the # message buffer while IPv4 and embedded-IPv4 scanners continue. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv4.mode="zero" ipv4.bits="32" ipv6.enable="off" embeddedipv4.anonmode="zero" embeddedipv4.bits="128") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") }' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: 1.2.3. <129>Mar 10 01:00:00 172.20.245.8 tag: 1.2. <129>Mar 10 01:00:00 172.20.245.8 tag: 1. <129>Mar 10 01:00:00 172.20.245.8 tag: 10.20.30.40 1.2.3. <129>Mar 10 01:00:00 172.20.245.8 tag: aa:bb::1.2.3.\"" shutdown_when_empty wait_shutdown export EXPECTED=' 1.2.3. 1.2. 1. 0.0.0.0 1.2.3. aa:bb::1.2.3.' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-omfwd-tls-ossl-pkcs11-module-defaults.sh0000644000000000000000000000013215241075234024262 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.697580017 30 ctime=1787067805.456931185 rsyslog-8.2608.0/tests/yaml-omfwd-tls-ossl-pkcs11-module-defaults.sh0000775000175000017500000000275315241075234023740 0ustar00rgerrger#!/bin/bash # Verify that the YAML frontend accepts omfwd PKCS#11 TLS module defaults plus # an action-level StreamDriver.CAExtraFiles override for the ossl driver. The # oracle is successful -N1 config validation, which proves the YAML parser and # shared omfwd config backend accept the new module/action parameter family # without requiring PKCS#11 runtime setup during the test. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "builtin:omfwd" streamdriver.cafile: "pkcs11:token=rsyslog;object=ca-cert;type=cert" streamdriver.caextrafiles: "pkcs11:token=rsyslog;object=intermediate-ca-cert;type=cert" streamdriver.certfile: "pkcs11:token=rsyslog;object=client-cert;type=cert" streamdriver.keyfile: "pkcs11:token=rsyslog;object=client-key;type=private" rulesets: - name: main actions: - type: omfwd target: "127.0.0.1" port: "6514" protocol: "tcp" streamdriver.name: "ossl" streamdriver.mode: 1 streamdriver.authmode: "x509/certvalid" streamdriver.caextrafiles: "pkcs11:token=rsyslog;object=override-intermediate-ca-cert;type=cert" YAMLEOF ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$RSYSLOG_MODDIR" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 0 ]; then echo "FAIL: expected YAML config validation to accept omfwd PKCS#11 module defaults" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdocker-long-options.sh0000644000000000000000000000013115216464436020472 xustar0030 mtime=1782212894.053266621 29 atime=1782715518.90879088 30 ctime=1787067806.346947769 rsyslog-8.2608.0/tests/imdocker-long-options.sh0000775000175000017500000000173615216464436020151 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # imdocker unit tests are enabled with --enable-imdocker-tests . ${srcdir:=.}/diag.sh init NUMMESSAGES=50 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines COOKIE=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 10 | head -n 1) export COOKIE LONG_PREFIX=$(printf 'noop=1&%.0s' $(seq 1 80)) generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imdocker/.libs/imdocker" ListContainersOptions="all=true" GetContainerLogOptions="'$LONG_PREFIX'timestamps=0&follow=1&stdout=1&stderr=0") if $!metadata!Names == "'$COOKIE'" then { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' docker run \ --name $COOKIE \ -e NUMMESSAGES=$NUMMESSAGES \ alpine \ /bin/sh -c 'for i in $(seq 0 $((NUMMESSAGES-1))); do echo "$i"; done' > /dev/null startup shutdown_when_empty wait_shutdown seq_check docker container rm $COOKIE exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-datafail-continues-batch-single.sh0000644000000000000000000000013215241075234023661 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067806.122943595 rsyslog-8.2608.0/tests/omhttp-datafail-continues-batch-single.sh0000775000175000017500000000246515241075234023337 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Regression test for rsyslog/rsyslog#4348 in omhttp batch mode with # batch.maxsize="1". A single HTTP 400 is still a permanent data failure for # only that HTTP request payload; it must not leave the action in DATAFAIL state # and block later good events. The mock server rejects message 00000002 and the # oracle is that messages after it still arrive, with only message 2 missing. # shellcheck disable=SC2034,SC2154 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 omhttp_start_server 0 --fail-msgnum-400 00000002 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") if $msg contains "msgnum:" then action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.format="jsonarray" batch.maxsize="1" usehttps="off" ) ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray omhttp_stop_server EXPECTED='00000000 00000001 00000003 00000004 00000005 00000006 00000007 00000008 00000009' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-omfile-followsymlinks.sh0000644000000000000000000000013215241075234021545 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.697580017 30 ctime=1787067805.362929433 rsyslog-8.2608.0/tests/yaml-omfile-followsymlinks.sh0000775000175000017500000000266615241075234021226 0ustar00rgerrger#!/bin/bash # Validate YAML frontend parity for omfile followSymlinks. The config uses # backward-compatible global defaults but sets followSymlinks false on the # action, so the symlink target must remain empty after synchronized shutdown. . ${srcdir:=.}/diag.sh init require_plugin imtcp link="${RSYSLOG_DYNNAME}.yaml.link" target="${RSYSLOG_DYNNAME}.yaml.target" normal="${RSYSLOG_DYNNAME}.yaml.normal" rm -f "$link" "$target" "$normal" : >"$target" ln -s "$target" "$link" || skip_test cat >"${RSYSLOG_DYNNAME}.omfile-follow.yaml" <: TRACE:at: { tpcommit(0x0)' echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree' echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)' echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree' echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)' echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1' } > $RSYSLOG_DYNNAME.dsu.done case $(uname) in FreeBSD) datelog=$(date -r $(stat -f %m $RSYSLOG_DYNNAME.dsu.done) "+%Y-%m-%dT%H:%M:%S") ;; *) datelog=$(date "+%Y-%m-%dT%H:%M:%S" -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.dsu.done)) ;; esac echo "Batch report to consume ${RSYSLOG_DYNNAME}.dsu.done for ${datelog}" startup shutdown_when_empty wait_shutdown export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - 164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree\n164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree\n164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)\n164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1' cmp_exact if [ -e $RSYSLOG_DYNNAME.dsu.sent ] || [ -e $RSYSLOG_DYNNAME.dsu.rejected ] || [ -e $RSYSLOG_DYNNAME.dsu.done ]; then echo "The batch report was not deleted" ls $RSYSLOG_DYNNAME* error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/minitcpsrvr.c0000644000000000000000000000013115241075234016427 xustar0030 mtime=1787067036.628578725 30 atime=1787067036.779581552 29 ctime=1787067803.58589632 rsyslog-8.2608.0/tests/minitcpsrvr.c0000664000175000017500000004337615241075234016111 0ustar00rgerrger/* a very simplistic tcp receiver for the rsyslog testbench. * * Copyright 2016,2024 Rainer Gerhards and Adiscon GmbH. * * This file is part of the rsyslog project. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #endif #define MAX_CONNECTIONS 10 /* Keep complete testbench records buffered per connection. The segmented DA * TCP spill regression deliberately uses multi-kilobyte messages so TCP * backpressure cannot be hidden by buffers. The historic 1 KiB buffer treated * a fragmented larger record as a closed connection. */ #define BUFFER_SIZE (64 * 1024) /* OK, we use a lot of global. But after all, this is "just" a small * testing ... that has evolved a bit ;-) */ char wrkBuf[4096]; ssize_t nRead; size_t nRcv = 0; int nConnDrop; /* how often has the connection already been dropped? */ int abortListener = 0; /* act like listener was totally aborted */ int sleepAfterConnDrop = 0; /* number of seconds to sleep() when a connection was dropped */ int dropConnection_NbrRcv = 0; int dropConnection_MaxTimes = 0; int opt; int sleepStartup = 0; int useReusePort = 0; int receiveBufferSize = 0; char *targetIP = NULL; int targetPort = -1; char *portFileName = NULL; char *waitListenFileName = NULL; char *waitReadFileName = NULL; char *keepRunningFileName = NULL; char *listenReadyFileName = NULL; char *acceptReadyFileName = NULL; char *fixedResponse = NULL; size_t totalWritten = 0; int listen_fd, conn_fd, fd, file_fd, nfds, port = 8080; struct sockaddr_in server_addr; struct pollfd fds[MAX_CONNECTIONS + 1]; // +1 for the listen socket char buffer[MAX_CONNECTIONS + 1][BUFFER_SIZE]; int buffer_offs[MAX_CONNECTIONS + 1]; static void errout(char *reason) { perror(reason); fprintf(stderr, "minitcpsrv ABORTS!!!\n\n\n"); exit(1); } static void usage(void) { fprintf(stderr, "usage: minitcpsrv [-R] [-b receiveBufferBytes] [-r response] [-w listenFile] [-L listenReadyFile] " "[-A acceptReadyFile] " "[-Q readReleaseFile] [-K keepRunningFile] -t ip-addr -p port -P portFile -f outfile\n"); exit(1); } static void sendFixedResponse(int fd) { const char *response; size_t len; if (fixedResponse == NULL) return; response = fixedResponse; len = strlen(fixedResponse); while (len > 0) { const ssize_t nSent = send(fd, response, len, 0); if (nSent <= 0) { errout("send fixed response"); } response += nSent; len -= (size_t)nSent; } } static void writeListenReadyMarker(void) { FILE *fp; int ret; if (listenReadyFileName == NULL) return; if ((fp = fopen(listenReadyFileName, "w")) == NULL) { errout(listenReadyFileName); } ret = fprintf(fp, "listening\n"); if (fclose(fp) != 0 || ret < 0) { errout(listenReadyFileName); } } static void writeAcceptReadyMarker(void) { FILE *fp; int ret; if (acceptReadyFileName == NULL) return; if ((fp = fopen(acceptReadyFileName, "w")) == NULL) { errout(acceptReadyFileName); } ret = fprintf(fp, "accepted\n"); if (fclose(fp) != 0 || ret < 0) { errout(acceptReadyFileName); } } static void writePortFileMarker(void) { FILE *fp; if (portFileName == NULL) return; if ((fp = fopen(portFileName, "w+")) == NULL) { errout(portFileName); } if (fprintf(fp, "%d", targetPort) < 0) { errout(portFileName); } if (fclose(fp) != 0) { errout(portFileName); } } static void waitForListenRelease(void) { if (waitListenFileName == NULL) return; fprintf(stderr, "minitcpsrv waits for listen release file %s\n", waitListenFileName); while (access(waitListenFileName, F_OK) != 0) { sleep(1); } fprintf(stderr, "minitcpsrv listen release file %s found\n", waitListenFileName); } /* Keep the TCP listener available while deliberately withholding reads. This * lets testbench clients establish connections and eventually apply normal TCP * backpressure without provoking connection failures or retry duplicates. */ static void waitForReadRelease(void) { if (waitReadFileName == NULL) return; fprintf(stderr, "minitcpsrv waits for read release file %s\n", waitReadFileName); while (access(waitReadFileName, F_OK) != 0) { usleep(10000); } fprintf(stderr, "minitcpsrv read release file %s found\n", waitReadFileName); } static void setReceiveBuffer(int socket_fd) { if (receiveBufferSize > 0 && setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &receiveBufferSize, sizeof(receiveBufferSize)) != 0) { errout("setsockopt SO_RCVBUF"); } } static void createListenSocket(void) { struct sockaddr_in srvAddr; unsigned int srvAddrLen; int r; listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) { errout("Failed to create listen socket"); } /* Set before listen() for TCP window negotiation, then repeat on accepted * sockets so the helper does not rely on platform-specific inheritance. */ setReceiveBuffer(listen_fd); /* SO_REUSEADDR is enough for the test helper's restart use cases. */ int opt = 1; if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { errout("setsockopt failed for SO_REUSEADDR"); } if (useReusePort) { #ifdef SO_REUSEPORT if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) { errout("setsockopt failed for SO_REUSEPORT"); } #else fprintf(stderr, "SO_REUSEPORT requested but not supported on this platform\n"); exit(1); #endif } fprintf(stderr, "listen on target port %d\n", targetPort); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(targetIP); // htonl(INADDR_ANY); server_addr.sin_port = htons(targetPort); srvAddrLen = sizeof(server_addr); int sockBound = 0; int try = 0; do { r = bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (r < 0) { if (errno == EADDRINUSE) { perror("minitcpsrv bind listen socket"); if (try++ < 10) { sleep(1); } else { fprintf(stderr, "minitcpsrv could not bind socket " "after trying hard - terminating\n\n"); exit(2); } } else { errout("bind"); } } else { sockBound = 1; } } while (!sockBound); if (getsockname(listen_fd, (struct sockaddr *)&srvAddr, &srvAddrLen) == -1) { errout("getsockname"); } targetPort = ntohs(srvAddr.sin_port); /* The socket is bound but not listening while this waits. TCP connects fail * with connection refused, while the selected port remains reserved. * Publish the port before this wait so tests can configure a sender while * intentionally keeping the receiver offline. Normal starts publish it only * after listen() succeeds so port-file users do not race the listener. */ if (waitListenFileName != NULL) writePortFileMarker(); waitForListenRelease(); if (listen(listen_fd, MAX_CONNECTIONS) < 0) { errout("Listen failed"); } if (waitListenFileName == NULL) writePortFileMarker(); writeListenReadyMarker(); fds[0].fd = listen_fd; fds[0].events = POLLIN; } int main(int argc, char *argv[]) { int fdc; int fdf = -1; struct sockaddr_in cliAddr; unsigned int cliAddrLen; memset(fds, 0, sizeof(fds)); memset(buffer_offs, 0, sizeof(buffer_offs)); while ((opt = getopt(argc, argv, "aA:b:B:D:K:L:Q:Rr:t:p:P:f:s:S:w:")) != -1) { switch (opt) { case 'a': // abort listener: act like the server has died (shutdown and re-open listen socket) abortListener = 1; break; case 'A': acceptReadyFileName = optarg; break; case 'b': { char *endptr; errno = 0; const long value = strtol(optarg, &endptr, 10); if (errno != 0 || *endptr != '\0' || value <= 0 || value > INT_MAX) usage(); receiveBufferSize = (int)value; break; } case 'R': useReusePort = 1; break; case 'r': fixedResponse = optarg; break; case 'S': // sleep time after connection drop sleepAfterConnDrop = atoi(optarg); break; case 's': // sleep time immediately after startup sleepStartup = atoi(optarg); break; case 'B': // max number of time the connection shall be dropped dropConnection_MaxTimes = atoi(optarg); break; case 'D': // drop connection after this number of recv() operations (not messages) dropConnection_NbrRcv = atoi(optarg); break; case 'L': listenReadyFileName = optarg; break; case 'K': keepRunningFileName = optarg; break; case 'Q': waitReadFileName = optarg; break; case 't': targetIP = optarg; break; case 'p': targetPort = atoi(optarg); break; case 'P': portFileName = optarg; break; case 'f': if (!strcmp(optarg, "-")) { fdf = 1; } else { fprintf(stderr, "writing to file %s\n", optarg); fdf = open(optarg, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fdf == -1) errout(argv[3]); } break; case 'w': waitListenFileName = optarg; break; default: fprintf(stderr, "invalid option '%c' or value missing - terminating...\n", opt); usage(); break; } } if (targetIP == NULL) { fprintf(stderr, "-t parameter missing -- terminating\n"); usage(); } if (targetPort == -1) { fprintf(stderr, "-p parameter missing -- terminating\n"); usage(); } if (fdf == -1) { fprintf(stderr, "-f parameter missing -- terminating\n"); usage(); } if (fixedResponse != NULL) { signal(SIGPIPE, SIG_IGN); } if (sleepStartup) { printf("minitcpsrv: deliberate sleep of %d seconds\n", sleepStartup); sleep(sleepStartup); printf("minitcpsrv: end sleep\n"); } createListenSocket(); waitForReadRelease(); nfds = 1; int bKeepRunning; while (1) { /* A keep-running file turns the receiver into a durable listener for * tests whose clients may briefly disconnect between action batches. * Poll with a short timeout only in that opt-in mode so removal of the * file is noticed even when no sockets are active. */ int poll_count = poll(fds, nfds, keepRunningFileName == NULL ? -1 : 100); if (poll_count < 0) { errout("poll"); } bKeepRunning = keepRunningFileName != NULL && access(keepRunningFileName, F_OK) == 0; /* Without -K, terminate on the last connection close as before. */ for (int i = 0; i < nfds; i++) { if (fds[i].revents == 0) continue; if (!(fds[i].revents & POLLIN)) { if (fds[i].fd == listen_fd) { fprintf(stderr, "Error! listener revents = %d\n", fds[i].revents); exit(EXIT_FAILURE); } /* POLLHUP/POLLERR is a normal end-of-stream indication for * an omfwd action connection. It may accompany POLLIN, in * which case the readable data below is still consumed. */ close(fds[i].fd); fds[i].fd = -1; continue; } if (fds[i].fd == listen_fd) { // Accept new connection fprintf(stderr, "minitcpsrv: NEW CONNECT\n"); conn_fd = accept(listen_fd, (struct sockaddr *)NULL, NULL); if (conn_fd < 0) { perror("Accept failed"); continue; } if (nfds >= MAX_CONNECTIONS + 1) { fprintf(stderr, "minitcpsrv connection limit reached\n"); close(conn_fd); continue; } setReceiveBuffer(conn_fd); writeAcceptReadyMarker(); fds[nfds].fd = conn_fd; fds[nfds].events = POLLIN; buffer_offs[nfds] = 0; nfds++; } else { // Handle data from a client fd = fds[i].fd; const size_t bytes_to_read = sizeof(buffer[i]) - buffer_offs[i] - 1; int read_bytes = read(fd, &(buffer[i][buffer_offs[i]]), bytes_to_read); nRcv += read_bytes; if (read_bytes < 0) { perror("Read error"); close(fd); fds[i].fd = -1; // Remove from poll set } else if (read_bytes == 0) { // Connection closed close(fd); fds[i].fd = -1; // Remove from poll set } else { // last valid char in rcv buffer const int last_byte = read_bytes + buffer_offs[i] - 1; int last_lf = last_byte; while (last_lf > -1 && buffer[i][last_lf] != '\n') { --last_lf; } if (last_lf == -1) { /* no LF found at all */ buffer_offs[i] = last_byte + 1; } else { const int bytes_to_write = last_lf + 1; const int written_bytes = write(fdf, buffer[i], bytes_to_write); if (written_bytes != bytes_to_write) errout("write"); totalWritten += bytes_to_write; sendFixedResponse(fd); if (bytes_to_write == last_byte + 1) { buffer_offs[i] = 0; } else { /* keep data in buffer, move it to start * and adjust offset. */ int unfinished_bytes = last_byte - bytes_to_write + 1; memmove(buffer[i], &(buffer[i][bytes_to_write]), unfinished_bytes); buffer_offs[i] = unfinished_bytes; } } } /* simulate connection abort, if requested */ if ((buffer_offs[i] == 0) && (dropConnection_NbrRcv > 0) && (nRcv >= dropConnection_NbrRcv) && (dropConnection_MaxTimes > 0) && (nConnDrop < dropConnection_MaxTimes)) { nConnDrop++; nRcv = 0; if (abortListener) { fprintf(stderr, "minitcpsrv: simulating died client\n"); shutdown(listen_fd, SHUT_RDWR); } close(fd); fds[i].fd = -1; // Remove from poll set if (sleepAfterConnDrop > 0) { sleep(sleepAfterConnDrop); } if (abortListener) { /* we hope that when we close and immediately re-open, we will * can use the some port again. */ close(listen_fd); createListenSocket(); fprintf(stderr, "minitcpsrv: reactivated\n"); } bKeepRunning = 1; /* do not abort if sole connection! */ } } } // Compact the array of monitored file descriptors for (int i = 0; i < nfds; i++) { if (fds[i].fd == -1) { for (int j = i; j < nfds - 1; j++) { fds[j] = fds[j + 1]; memcpy(buffer[j], buffer[j + 1], buffer_offs[j + 1]); buffer_offs[j] = buffer_offs[j + 1]; } i--; nfds--; } } // terminate if all connections have been closed if (nfds == 1 && !bKeepRunning) break; } /* -------------------------------------------------- */ /* let the OS do the cleanup */ fprintf(stderr, "minitcpsrv on port %d terminates itself, %zu bytes written\n", targetPort, totalWritten); return 0; } rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_non_object-vg.sh0000644000000000000000000000013215171370365022625 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.912790948 30 ctime=1787067806.918958428 rsyslog-8.2608.0/tests/rscript_unflatten_non_object-vg.sh0000775000175000017500000000012515171370365022272 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_non_object.sh rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_errmsg_regex.match.reject.sh0000644000000000000000000000013215035412264024221 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.911790931 30 ctime=1787067808.094980343 rsyslog-8.2608.0/tests/imbatchreport_errmsg_regex.match.reject.sh0000777000175000017500000000072015035412264023671 0ustar00rgerrger#!/bin/bash # add 2019-02-26 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/imbatchreport/.libs/imbatchreport") input(type="imbatchreport" tag="t" rename=".done$ .s .r.done" reports="./*.done") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check "Reject renaming leaves files in glob scope: Instance ignored to avoid loops." exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-error-ca-vg.sh0000644000000000000000000000013215241075234022354 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.552970243 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-error-ca-vg.sh0000775000175000017500000000012715241075234022023 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-error-ca.sh rsyslog-8.2608.0/tests/PaxHeaders/failover-no-rptd-vg.sh0000644000000000000000000000013215216464436020052 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.912790948 30 ctime=1787067805.210926601 rsyslog-8.2608.0/tests/failover-no-rptd-vg.sh0000775000175000017500000000126115216464436017521 0ustar00rgerrger#!/bin/bash # rptd test for failover functionality - no failover # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $RepeatedMsgReduction on # second action should never execute :msg, contains, "msgnum:" /dev/null $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"' ' startup_vg injectmsg 0 5000 shutdown_when_empty wait_shutdown_vg check_exit_vg # now we need our custom logic to see if the result file is empty # (what it should be!) if [ -f "$RSYSLOG_OUT_LOG" ] && [ "$(cat "$RSYSLOG_OUT_LOG")" != "" ]; then echo "ERROR, output file not empty" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-listen-port-file-2.sh0000644000000000000000000000013215241075234020706 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.771581402 30 ctime=1787067804.396911432 rsyslog-8.2608.0/tests/imtcp-listen-port-file-2.sh0000775000175000017500000000235415241075234020361 0ustar00rgerrger#!/bin/bash # This test checks if more than one port file names work correctly for # imtcp. See also: # https://github.com/rsyslog/rsyslog/issues/3817 # added 2019-08-14 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ruleset="rs1") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port2" ruleset="rs2") ruleset(name="rs1") { action(type="omfile" file="'$RSYSLOG_DYNNAME.1.log'" template="outfmt") } ruleset(name="rs2") { action(type="omfile" file="'$RSYSLOG_DYNNAME.2.log'" template="outfmt") } ' startup assign_file_content RCVR_PORT "$RSYSLOG_DYNNAME.rcvr_port" assign_file_content RCVR_PORT2 "$RSYSLOG_DYNNAME.rcvr_port2" tcpflood -p "$RCVR_PORT" -m10 tcpflood -p "$RCVR_PORT2" -m10 -i10 shutdown_when_empty wait_shutdown printf 'checking receiver 1\n' export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.1.log" seq_check 0 9 printf 'checking receiver 2\n' export SEQ_CHECK_FILE="$RSYSLOG_DYNNAME.2.log" seq_check 10 19 exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-pos-from-to-missing-jsonvar.sh0000644000000000000000000000013215241075234023362 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.799581927 30 ctime=1787067804.278909233 rsyslog-8.2608.0/tests/template-pos-from-to-missing-jsonvar.sh0000775000175000017500000000130615241075234023031 0ustar00rgerrger#!/bin/bash # addd 2016-03-28 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="-%$!non!existing!var:109:116:%-\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 shutdown_when_empty wait_shutdown echo "--" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid output generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG echo "expected was:" echo "--" exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/allowed-sender-tcp-fail.sh0000644000000000000000000000013215241075234020642 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.761581215 30 ctime=1787067804.401911525 rsyslog-8.2608.0/tests/allowed-sender-tcp-fail.sh0000775000175000017500000000174615241075234020321 0ustar00rgerrger#!/bin/bash # check that we are able to receive messages from allowed sender # added 2019-08-15 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=5 # it's just important that we get any messages at all generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs") $AllowedSender TCP,128.66.0.0/16 # this IP range is reserved by RFC5737 template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="rs") { action(type="omfile" template="outfmt" file="'$RSYSLOG_DYNNAME.must-not-be-created'") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood --check-only -m$NUMMESSAGES shutdown_when_empty wait_shutdown content_check --regex "connection request from disallowed sender .* discarded" check_file_not_exists "$RSYSLOG_DYNNAME.must-not-be-created" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp_ratelimit_name.sh0000644000000000000000000000013215171370365020607 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.911790931 30 ctime=1787067807.704973075 rsyslog-8.2608.0/tests/imrelp_ratelimit_name.sh0000775000175000017500000000233215171370365020256 0ustar00rgerrger#!/bin/bash # Test named rate limits for imrelp # added 2025-07-15 by Copilot, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_ARM "ratelimit timing flaky on ARM" export SENDMESSAGES=20 export NUMMESSAGES=5 # used by wait_file_lines (QUEUE_EMPTY_CHECK_FUNC); matches burst export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' ratelimit(name="imrelp_test_limit" interval="2" burst="5") module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" port="'$TCPFLOOD_PORT'" ratelimit.name="imrelp_test_limit") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "msgnum:" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup tcpflood -Trelp-plain -p$TCPFLOOD_PORT -m $SENDMESSAGES shutdown_when_empty wait_shutdown content_count=$(grep -c "msgnum:" $RSYSLOG_OUT_LOG) echo "content_count: $content_count" if [ $content_count -eq $SENDMESSAGES ]; then echo "FAIL: No rate limiting occurred (received all $content_count messages)" error_exit 1 fi if [ $content_count -eq 0 ]; then echo "FAIL: All messages lost or dropped (received 0)" error_exit 1 fi echo "SUCCESS: Rate limiting occurred (received $content_count/$SENDMESSAGES)" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata-vg.sh0000644000000000000000000000013115241075234017355 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067807.033960572 rsyslog-8.2608.0/tests/mmpstrucdata-vg.sh0000775000175000017500000000173715241075234017035 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # rgerhards, 2013-11-22 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi echo =============================================================================== echo \[mmpstrucdata.sh\]: testing mmpstrucdata . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") module(load="../plugins/imtcp/.libs/imtcp") template(name="outfmt" type="string" string="%$!rfc5424-sd!tcpflood@32473!msgnum%\n") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmpstrucdata") if $msg contains "msgnum" then action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup_vg sleep 1 tcpflood -m100 -y shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown_vg check_exit_vg seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbeats-shutdown-open-session.sh0000644000000000000000000000013215241075234022155 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.769581365 30 ctime=1787067806.459949875 rsyslog-8.2608.0/tests/imbeats-shutdown-open-session.sh0000775000175000017500000000716615241075234021636 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init # This checks that imbeats shutdown closes client sessions that are already # accepted and left open in idle or partial-frame protocol states. The client # first completes one valid Lumberjack batch on each socket and waits for the # expected ack; that ack is the oracle that the session is owned by imbeats # before the test starts rsyslog shutdown. generate_conf add_conf ' module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" rm -f "$RSYSLOG_DYNNAME.imbeats.ready" "$RSYSLOG_DYNNAME.imbeats.client-result" ${PYTHON:-python3} - "$RS_PORT" \ "$RSYSLOG_DYNNAME.imbeats.ready" \ "$RSYSLOG_DYNNAME.imbeats.client-result" <<'PY' & import json import os import socket import struct import sys port = int(sys.argv[1]) ready_file = sys.argv[2] result_file = sys.argv[3] sockets = [] def event_wire(seq, message): payload = json.dumps({"message": message}, separators=(",", ":")).encode() return ( b"2W" + struct.pack(">I", 1) + b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload ) def recv_exact(sock, size): data = b"" while len(data) < size: chunk = sock.recv(size - len(data)) if not chunk: raise SystemExit("server closed session before ack") data += chunk return data try: for idx in range(3): sock = socket.create_connection(("127.0.0.1", port), timeout=5) sock.settimeout(10) sock.sendall(event_wire(1, f"accepted-{idx}")) ack = recv_exact(sock, 6) if ack != b"2A" + struct.pack(">I", 1): raise SystemExit(f"unexpected ack before shutdown: {ack.hex()}") sockets.append(sock) if idx == 1: sock.sendall(b"2W" + struct.pack(">I", 1)) elif idx == 2: sock.sendall(b"2W" + struct.pack(">I", 1) + b"2J" + struct.pack(">I", 1)) with open(ready_file, "w", encoding="ascii") as fh: fh.write("ready\n") for sock in sockets: try: data = sock.recv(1) except socket.timeout: raise SystemExit("server did not close open session during shutdown") except (ConnectionResetError, OSError): data = b"" if data: raise SystemExit(f"unexpected data from server during shutdown: {data!r}") with open(result_file, "w", encoding="ascii") as fh: fh.write("closed\n") finally: for sock in sockets: try: sock.close() except OSError: pass if not os.path.exists(result_file): with open(result_file, "w", encoding="ascii") as fh: fh.write("failed\n") PY client_pid=$! i=0 ready_timeout="${TB_TIMEOUT_STARTSTOP:-600}" while [ "$i" -lt "$ready_timeout" ]; do if [ -f "$RSYSLOG_DYNNAME.imbeats.ready" ]; then break fi if ! kill -0 "$client_pid" 2>/dev/null; then wait "$client_pid" || true cat "$RSYSLOG_DYNNAME.imbeats.client-result" 2>/dev/null || true error_exit 1 fi $TESTTOOL_DIR/msleep 100 i=$((i + 1)) done if [ ! -f "$RSYSLOG_DYNNAME.imbeats.ready" ]; then kill "$client_pid" 2>/dev/null || true cat "$RSYSLOG_DYNNAME.imbeats.client-result" 2>/dev/null || true error_exit 1 fi shutdown_when_empty wait_shutdown "" 10 wait "$client_pid" || error_exit 1 test "$(cat "$RSYSLOG_DYNNAME.imbeats.client-result")" = "closed" || error_exit 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-neither_rule_rulebase.sh0000644000000000000000000000013215035412264023141 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.911790931 30 ctime=1787067807.061961093 rsyslog-8.2608.0/tests/pmnormalize-neither_rule_rulebase.sh0000777000175000017500000000062215035412264022612 0ustar00rgerrger#!/bin/bash # add 2019-04-10 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/pmnormalize/.libs/pmnormalize") parser(name="custom.pmnormalize" type="pmnormalize") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex "pmnormalize:.*you need to specify either" exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata-large-sd.sh0000644000000000000000000000013115241075234020437 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 30 ctime=1787067807.023960385 rsyslog-8.2608.0/tests/mmpstrucdata-large-sd.sh0000775000175000017500000000241415241075234020110 0ustar00rgerrger#!/bin/bash # Verify mmpstrucdata handles RFC5424 structured data larger than 65535 bytes. # The oracle is a small field after the large value. If the cached structured # data length wraps or the parser stops early, that trailing field is not written # to the configured omfile destination. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(maxMessageSize="100k") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!structured-data!custom-sd!large@32473!tail%\n") action(type="mmpstrucdata" jsonRoot="$!structured-data" container="custom-sd") if $msg contains "MMPSTRUCDATA" then action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup { printf '%s' '<85>1 2026-05-22T08:00:00.000+00:00 host app proc msgid [large@32473 blob="' awk 'BEGIN { for (i = 0; i < 70000; ++i) printf "x" }' printf '%s\n' '" tail="ok"] MMPSTRUCDATA large sd' } >"$RSYSLOG_DYNNAME.input" tcpflood -m1 -I "$RSYSLOG_DYNNAME.input" shutdown_when_empty wait_shutdown export EXPECTED='ok' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript-object-string-escapes.sh0000644000000000000000000000013215241075234022117 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.691579904 30 ctime=1787067803.705898556 rsyslog-8.2608.0/tests/rscript-object-string-escapes.sh0000775000175000017500000000247215241075234021573 0ustar00rgerrger#!/bin/bash # Verify that RainerScript object/action parameter strings and expression # strings accept the same documented byte escapes that the unescape layer # decodes. The oracle is the configured omfile output after synchronized # shutdown, proving hex and octal forms reached the normal template/action path # as the intended bytes. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' set $.expr_hex_upper = "\x5A"; set $.expr_hex_upper_digits = "\x4A"; template(name="outfmt" type="list") { constant(value="hex_lower=\x41\n") constant(value="hex_upper=\x5a\n") constant(value="hex_upper_digits=\x5A\n") constant(value="expr_hex_upper=") property(name="$.expr_hex_upper") constant(value="\n") constant(value="expr_hex_upper_digits=") property(name="$.expr_hex_upper_digits") constant(value="\n") constant(value="octal=\101\n") constant(value="literal=\\\\x41\n") } :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown cat > "$RSYSLOG_OUT_LOG.expect" <<'EOF' hex_lower=A hex_upper=Z hex_upper_digits=Z expr_hex_upper=Z expr_hex_upper_digits=J octal=A literal=\x41 EOF cmp_exact_file "$RSYSLOG_OUT_LOG.expect" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdrop_common.sh0000644000000000000000000000013215216464436017465 xustar0030 mtime=1782212894.081267073 30 atime=1782715518.911790931 30 ctime=1787067808.202982355 rsyslog-8.2608.0/tests/privdrop_common.sh0000775000175000017500000000643015216464436017137 0ustar00rgerrger#!/bin/bash # added 2016-04-15 by Thomas D., released under ASL 2.0 # Several tests need another user/group to test impersonation. # This script can be sourced to prevent duplicated code. # To support /dev/null) if [ -z "${testusername}" ]; then echo "'id' did not find user \"${testuser}\" ... skipping, trying next user!" continue fi testgroupname=$(id --group --name "${testuser}" 2>/dev/null) if [ -z "${testgroupname}" ]; then echo "'id' did not find a primary group for \"${testuser}\" ... skipping, trying next user!" continue fi has_testuser="${testuser}" break done if [ -z "${has_testuser}" ]; then echo "ERROR: running as root and no suiteable testuser found - skipping test" echo 'You mas set a testuser via the RSYSLOG_TESTUSER environment variable' exit 77 fi echo "WARNING: making work directory world-writable, as we need this to be able to" echo " open and process files after privilege drop. This is NOT automatically" echo " undone." chmod a+w . fi if [ -z "${has_testuser}" ]; then testgroupname=$(id --group --name ${EUID} 2>/dev/null) if [ -z "${testgroupname}" ]; then echo "Skipping ... please set RSYSLOG_TESTUSER or make sure the user running the testbench has a primary group!" exit_test exit 0 else has_testuser="${EUID}" fi fi _rsyslog_testbench_declare_testuser ${has_testuser} } _rsyslog_testbench_declare_testuser() { local testuser=$1 local testusername testusername=$(id --user --name "${testuser}" 2>/dev/null) if [ -z "${testusername}" ]; then # Should never happen echo "FATAL ERROR: Could not get username for user \"${testuser}\"!" exit 1 fi local testuid testuid=$(id --user "${testuser}" 2>/dev/null) if [ -z "${testuid}" ]; then # Should never happen echo "FATAL ERROR: Could not get uid for user \"${testuser}\"!" exit 1 fi local testgroupname testgroupname=$(id --group --name "${testuser}" 2>/dev/null) if [ -z "${testgroupname}" ]; then # Should never happen echo "FATAL ERROR: Could not get uid of user \"${testuser}\"!" exit 1 fi local testgid testgid=$(id --group "${testuser}" 2>/dev/null) if [ -z "${testgid}" ]; then # Should never happen echo "FATAL ERROR: Could not get primary gid of user \"${testuser}\"!" exit 1 fi echo "Will use user \"${testusername}\" (#${testuid}) and group \"${testgroupname}\" (#${testgid})" TESTBENCH_TESTUSER[username]=${testusername} TESTBENCH_TESTUSER[uid]=${testuid} TESTBENCH_TESTUSER[groupname]=${testgroupname} TESTBENCH_TESTUSER[gid]=${testgid} } rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-cri-partial-accept.sh0000644000000000000000000000013115241075234022376 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 29 ctime=1787067808.16298161 rsyslog-8.2608.0/tests/imkubernetes-cri-partial-accept.sh0000775000175000017500000000633615241075234022056 0ustar00rgerrger#!/bin/bash # Verify that CRI partial assembly honors oversizemsg.input.mode="accept". # A properly closed P...F record that is larger than maxMessageSize but below # the imkubernetes partial hard cap must reach the core submit path intact. # The API helper signals readiness after binding; its 2m timeout is hang # protection, while the explicit kill and wait below own normal cleanup. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes check_command_available timeout export NUMMESSAGES=2 pwd=$( pwd ) testsrv=imk8s-partial-accept-server k8s_srv_port=0 k8s_srv_port_file=${RSYSLOG_DYNNAME}${testsrv}.port logdir="${RSYSLOG_DYNNAME}.spool/pods/namespace-name1_pod-name1_uid1/container-a" logfile="${logdir}/0.log" mkdir -p "$logdir" echo starting kubernetes test server MMK8S_INCLUDE_NODE_NAME=1 timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py \ 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ $k8s_srv_port_file \ > ${RSYSLOG_DYNNAME}.spool/imkubernetes_partial_accept_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started assign_file_content k8s_srv_port "$k8s_srv_port_file" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'" maxMessageSize="128" oversizemsg.input.mode="accept") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" KubernetesUrl="http://localhost:'$k8s_srv_port'" Token="dummy" cacheEntryTtl="60") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="pod_id" name="$!kubernetes!pod_id" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup { for i in $(seq 1 8); do printf '2026-04-20T10:00:%02d.000000000Z stdout P %s\n' "$i" \ 'partial-fragment-0123456789' done printf '%s\n' '2026-04-20T10:00:30.000000000Z stdout F closing-tail-kept' printf '%s\n' '2026-04-20T10:00:31.000000000Z stdout F after accepted partial' } > "$logfile" wait_file_lines "$RSYSLOG_OUT_LOG" 2 wait_queueempty shutdown_when_empty wait_shutdown kill $BGPROCESS wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid if ! $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "cri"] assert len(records) == 2, records expected = ("partial-fragment-0123456789" * 8) + "closing-tail-kept" partial = records[0] assert partial["msg"] == expected, partial assert len(partial["msg"]) > 128, partial assert partial["stream"] == "stdout", partial assert partial["pod_id"] == "pod-name1-id", partial independent = records[1] assert independent["msg"] == "after accepted partial", independent assert independent["stream"] == "stdout", independent assert independent["pod_id"] == "pod-name1-id", independent PY then error_exit 1 "imkubernetes truncated CRI partial despite oversizemsg.input.mode=accept" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_zero_128_ipv6.sh0000644000000000000000000000013215131231047020114 xustar0030 mtime=1768239655.709212663 30 atime=1782715518.909790897 30 ctime=1787067805.744936552 rsyslog-8.2608.0/tests/mmanon_zero_128_ipv6.sh0000777000175000017500000000273215131231047017571 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv6.bits="129" ipv6.anonmode="zero") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`)' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: asdfghjk <129>Mar 10 01:00:00 172.20.245.8 tag: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 tag: 61:34:ad::7:F aa:ff43::756:99:0 <129>Mar 10 01:00:00 172.20.245.8 tag: :: <129>Mar 10 01:00:00 172.20.245.8 tag: 0:: <129>Mar 10 01:00:00 172.20.245.8 tag: 13:abd:45: <129>Mar 10 01:00:00 172.20.245.8 tag: textnoblank72:8374:adc7:47FF::43:0:1AFEstillnoblank\"" shutdown_when_empty wait_shutdown export EXPECTED=' asdfghjk 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 0:0:0:0:0:0:0:0 13:abd:45: textnoblank0:0:0:0:0:0:0:0stillnoblank' cmp_exact grep 'invalid number of ipv6.bits (129), corrected to 128' ${RSYSLOG2_OUT_LOG} > /dev/null if [ $? -ne 0 ]; then echo "invalid correction of bits parameter generated, ${RSYSLOG2_OUT_LOG} is:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-defaults.sh0000644000000000000000000000013115131231047017341 xustar0030 mtime=1768239655.715212762 30 atime=1782715518.912790948 29 ctime=1787067806.03894203 rsyslog-8.2608.0/tests/omprog-defaults.sh0000777000175000017500000000405415131231047017016 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests omprog using the default values for all non-mandatory # settings. It also checks that command-line parameters are correctly # passed to the external program. # NOTE: Because the omprog feedback mode is not used in this test # (confirmMessages=off), it is difficult to synchronize the execution # of the external program with the test code. For this reason, it would # be difficult to test for negative cases (e.g. restart of the program # if it terminates prematurely) without making the test racy. So, we # only test a happy case: the program processes all logs received and # exits when the pipe is closed. After closing the pipe, omprog will # wait for the program to terminate during a timeout of 5 seconds # (default value of closeTimeout), which should be sufficient for the # program to write its output. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary="'$srcdir'/testsuites/omprog-defaults-bin.sh \"p1 with spaces\"'\ ' p2 \"\" --p4=\"middle quote\" \"--p6=\"proper middle quote\"\" \"p7 is last\"" template="outfmt" name="omprog_action" ) } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown export EXPECTED="Starting with parameters: p1 with spaces p2 --p4=\"middle quote\" --p6=\"proper middle quote\" p7 is last Next parameter is \"p1 with spaces\" Next parameter is \"p2\" Next parameter is \"\" Next parameter is \"--p4=\"middle\" Next parameter is \"quote\"\" Next parameter is \"--p6=\"proper middle quote\"\" Next parameter is \"p7 is last\" Received msgnum:00000000: Received msgnum:00000001: Received msgnum:00000002: Received msgnum:00000003: Received msgnum:00000004: Received msgnum:00000005: Received msgnum:00000006: Received msgnum:00000007: Received msgnum:00000008: Received msgnum:00000009: Terminating normally" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/tcp_forwarding_dflt_tpl.sh0000644000000000000000000000013215216464436021150 xustar0030 mtime=1782212894.085267138 30 atime=1782715518.912790948 30 ctime=1787067804.354910649 rsyslog-8.2608.0/tests/tcp_forwarding_dflt_tpl.sh0000775000175000017500000000255515216464436020626 0ustar00rgerrger#!/bin/bash # Verify TCP forwarding uses the module-level default omfwd template. The # oracle is the complete 0..9999 forwarded message sequence rendered by that # default template. The receiver readiness wait avoids losing the first batch to # a listener startup race under high-concurrency test runs. # Added 2015-05-30 by rgerhards. Released under ASL 2.0. # create the pipe and start a background process that copies data from # it to the "regular" work file . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 template(name="outfmt" type="string" string="%msg:F,58:2%\n") #this is what we want to test: setting the default template module(load="builtin:omfwd" template="outfmt") if $msg contains "msgnum:" then action(type="omfwd" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp") ' start_minitcpsrv_ready "$RSYSLOG_OUT_LOG" "$TCPFLOOD_PORT" # now do the usual run startup # 10000 messages should be enough injectmsg 0 10000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # note: minitcpsrv shuts down automatically if the connection is closed! # (we still leave the code here in in case we need it later) #echo shutting down minitcpsrv... #kill $BGPROCESS #wait $BGPROCESS #echo background process has terminated, continue test... # and continue the usual checks seq_check 0 9999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/perctile-invalid-percentile.sh0000644000000000000000000000013215216464436021633 xustar0030 mtime=1782212894.080267057 30 atime=1782715518.912790948 30 ctime=1787067806.676953919 rsyslog-8.2608.0/tests/perctile-invalid-percentile.sh0000775000175000017500000000141715216464436021305 0ustar00rgerrger#!/usr/bin/env bash # Verify percentile_stats rejects malformed percentile entries during config # validation. The oracle is rsyslogd -N1 failing with the perctile validation # diagnostic, proving non-numeric trailing text is not silently accepted as a # valid percentile. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' percentile_stats(name="bad_bucket" percentiles=["95abc"] windowsize="1000" delimiter="|" ) ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M../runtime/.libs:../.libs >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 1 ]; then echo "FAIL: expected config validation failure for malformed percentile" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi content_check "perctile: percentile value '95abc' is invalid" "${RSYSLOG_DYNNAME}.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-logrotate-state-files.sh0000644000000000000000000000013215216464436021731 xustar0030 mtime=1782212894.055266653 30 atime=1782715518.911790931 30 ctime=1787067808.028979113 rsyslog-8.2608.0/tests/imfile-logrotate-state-files.sh0000775000175000017500000001140415216464436021400 0ustar00rgerrger#!/bin/bash . $srcdir/diag.sh check-inotify-only . ${srcdir:=.}/diag.sh init export TESTMESSAGES=1000 export RETRIES=50 TESTMESSAGESFULL=$((3 * $TESTMESSAGES - 1)) export TESTMESSAGESFULL # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" # export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' $WorkDirectory '$RSYSLOG_DYNNAME'.spool # Enable debug for state file operations global( debug.whitelist="on" debug.files=["imfile.c"] ) module( load="../plugins/imfile/.libs/imfile" mode="inotify" ) input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on" PersistStateInterval="100" deleteStateOnFileMove="on" ) $template outfmt,"%msg:F,58:2%\n" if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' print_state_files() { local round=$1 echo "=== State files after round $round ===" if [ -d "$RSYSLOG_DYNNAME.spool" ]; then echo "State files in spool directory:" local state_count state_count=$(ls -1 "$RSYSLOG_DYNNAME.spool/"imfile-state* 2>/dev/null | wc -l) echo "Total state files found: $state_count" if [ $state_count -eq 0 ]; then echo "No state files found" else ls -la "$RSYSLOG_DYNNAME.spool/"imfile-state* 2>/dev/null echo "" for statefile in "$RSYSLOG_DYNNAME.spool/"imfile-state*; do if [ -f "$statefile" ]; then echo "State file: $(basename "$statefile")" echo " Size: $(stat -c%s "$statefile" 2>/dev/null || echo "unknown") bytes" echo " Modified: $(stat -c%y "$statefile" 2>/dev/null || echo "unknown")" echo " Contents:" if [ -r "$statefile" ]; then cat "$statefile" 2>/dev/null | jq . 2>/dev/null | sed 's/^/ /' || { echo " Raw contents (not valid JSON):" cat "$statefile" 2>/dev/null | sed 's/^/ /' } else echo " Cannot read file (permissions?)" fi echo "" fi done fi else echo "Spool directory does not exist" fi echo "" } print_inode_info() { local round=$1 echo "=== Inode information after round $round ===" for file in "$RSYSLOG_DYNNAME".input.log*; do if [ -f "$file" ]; then local inode inode=$(stat -c%i "$file" 2>/dev/null || echo "N/A") local size size=$(stat -c%s "$file" 2>/dev/null || echo "N/A") echo "File: $file - Inode: $inode - Size: $size bytes" fi done echo "" } write_log_lines() { local round=$1 local start_num start_num=$((($round - 1) * $TESTMESSAGES)) echo "Writing $TESTMESSAGES log lines for round $round (starting from msgnum $start_num)" ./inputfilegen -m $TESTMESSAGES -i $start_num >> "$RSYSLOG_DYNNAME.input.log" } rotate_logs() { echo "Rotating logs..." if [ -f "$RSYSLOG_DYNNAME.input.log.3" ]; then echo " Removing $RSYSLOG_DYNNAME.input.log.3" rm -f "$RSYSLOG_DYNNAME.input.log.3" fi if [ -f "$RSYSLOG_DYNNAME.input.log.2" ]; then echo " Moving $RSYSLOG_DYNNAME.input.log.2 to $RSYSLOG_DYNNAME.input.log.3" mv "$RSYSLOG_DYNNAME.input.log.2" "$RSYSLOG_DYNNAME.input.log.3" fi if [ -f "$RSYSLOG_DYNNAME.input.log.1" ]; then echo " Moving $RSYSLOG_DYNNAME.input.log.1 to $RSYSLOG_DYNNAME.input.log.2" mv "$RSYSLOG_DYNNAME.input.log.1" "$RSYSLOG_DYNNAME.input.log.2" fi if [ -f "$RSYSLOG_DYNNAME.input.log" ]; then echo " Moving $RSYSLOG_DYNNAME.input.log to $RSYSLOG_DYNNAME.input.log.1" mv "$RSYSLOG_DYNNAME.input.log" "$RSYSLOG_DYNNAME.input.log.1" fi } # Create initial empty input file touch "$RSYSLOG_DYNNAME.input.log" startup echo "Started rsyslog, waiting 1 second for initialization..." ./msleep 1000 # Perform 3 rounds of write->rotate cycle for round in 1 2 3; do echo "" echo "=== ROUND $round ===" # Write log lines write_log_lines $round # Print inode information print_inode_info "round $round (after write)" # Wait for processing echo "Waiting 1 second for processing..." ./msleep 1000 # Rotate logs rotate_logs # Wait after rotation echo "Waiting 1 second after rotation..." ./msleep 1000 # Check state files print_state_files $round # Print inode information after rotation print_inode_info "round $round (after rotation)" done # Verify we got the expected number of messages expected_messages=$((3 * $TESTMESSAGES)) wait_file_lines $RSYSLOG_OUT_LOG $expected_messages $RETRIES shutdown_when_empty wait_shutdown seq_check 0 $TESTMESSAGESFULL print_state_files "after shutdown" # Validate that there is exactly one state file after shutdown state_count=$(ls -1 "$RSYSLOG_DYNNAME.spool/"imfile-state* 2>/dev/null | wc -l) if [ $state_count -gt 1 ]; then echo "FAIL: Multiple state files found ($state_count) - expected max 1" error_exit 1 fi # Cleanup echo "" echo "=== CLEANUP ===" echo "Removing generated files..." rm -f "$RSYSLOG_DYNNAME".input.log* rm -rf "$RSYSLOG_DYNNAME.spool" echo "Cleanup completed" exit_test rsyslog-8.2608.0/tests/PaxHeaders/uxsock_multiple_netns-vg.sh0000644000000000000000000000013115171370365021314 xustar0030 mtime=1776677109.472913557 30 atime=1782715518.911790931 29 ctime=1787067807.66497233 rsyslog-8.2608.0/tests/uxsock_multiple_netns-vg.sh0000775000175000017500000000011615171370365020762 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/uxsock_multiple_netns.sh rsyslog-8.2608.0/tests/PaxHeaders/include-obj-text-from-file.sh0000644000000000000000000000013115035412264021271 xustar0030 mtime=1752569012.398764645 30 atime=1782715518.911790931 29 ctime=1787067804.99892265 rsyslog-8.2608.0/tests/include-obj-text-from-file.sh0000777000175000017500000000061415035412264020744 0ustar00rgerrger#!/bin/bash # added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then {' add_conf " include(text=\`cat ${srcdir}/testsuites/include-std-omfile-action.conf\`) } " startup injectmsg 0 10 shutdown_when_empty wait_shutdown seq_check 0 9 exit_test rsyslog-8.2608.0/tests/PaxHeaders/tabescape_on.sh0000644000000000000000000000013215241075234016663 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.798581908 30 ctime=1787067803.651897549 rsyslog-8.2608.0/tests/tabescape_on.sh0000775000175000017500000000136715241075234016341 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(parser.EscapeControlCharacterTab="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") $ErrorMessagesToStderr off template(name="outfmt" type="string" string="%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 test: before HT after HT (do NOT remove TAB!)\"" shutdown_when_empty wait_shutdown export EXPECTED=' before HT#011after HT (do NOT remove TAB!)' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/snmptrapreceiver.py0000644000000000000000000000013215216464436017657 xustar0030 mtime=1782212894.085267138 30 atime=1782715518.910790914 30 ctime=1787067808.764992828 rsyslog-8.2608.0/tests/snmptrapreceiver.py0000664000175000017500000001132715216464436017327 0ustar00rgerrger# call this via "python[3] script name" import sys from pysnmp.entity import engine, config from pysnmp.carrier.asyncore.dgram import udp from pysnmp.entity.rfc3413 import ntfrcv from pysnmp.smi import builder, view, compiler, rfc1902 from pyasn1.type.univ import OctetString # Global variables snmpport = 10162 snmpip = "127.0.0.1" szOutputfile = "snmp.out" szSnmpLogfile = "snmp_server.log" # For vrebose output bDebug = False # Read command line params if len(sys.argv) > 1: snmpport = int(sys.argv[1]) if len(sys.argv) > 2: snmpip = sys.argv[2] if len(sys.argv) > 3: szOutputfile = sys.argv[3] if len(sys.argv) > 4: szSnmpLogfile = sys.argv[4] # Create output files with open(szOutputfile, "w+") as outputFile: with open(szSnmpLogfile, "a+") as logFile: # Assemble MIB viewer mibBuilder = builder.MibBuilder() compiler.addMibCompiler(mibBuilder, sources=['file:///usr/share/snmp/mibs', 'file:///var/lib/snmp/mibs', '/usr/local/share/snmp/mibs/']) mibViewController = view.MibViewController(mibBuilder) # Pre-load MIB modules we expect to work with try: mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB', 'SYSLOG-MSG-MIB') except Exception: print("Failed loading MIBs") # Create SNMP engine with autogenernated engineID and pre-bound to socket transport dispatcher snmpEngine = engine.SnmpEngine() # Transport setup # UDP over IPv4, add listening interface/port config.addTransport( snmpEngine, udp.domainName + (1,), udp.UdpTransport().openServerMode((snmpip, snmpport)) ) # SNMPv1/2c setup # SecurityName <-> CommunityName mapping config.addV1System(snmpEngine, 'my-area', 'public') print("Started SNMP Trap Receiver: %s, %s, Output: %s" % (snmpport, snmpip, szOutputfile)) logFile.write("Started SNMP Trap Receiver: %s, %s, Output: %s" % (snmpport, snmpip, szOutputfile)) logFile.flush() # Add PID file creation after startup message import os with open(szSnmpLogfile + ".started", "w") as f: f.write(str(os.getpid())) # Callback function for receiving notifications # noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal def cbReceiverSnmp(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx): transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference) if (bDebug): szDebug = str( "Notification From: %s, Domain: %s, SNMP Engine: %s, Context: %s" % (transportAddress, transportDomain, contextEngineId.prettyPrint(), contextName.prettyPrint())) print(szDebug) logFile.write(szDebug) logFile.flush() # Create output String szOut = "Trap Source{}, Trap OID {}".format(transportAddress, transportDomain) varBinds = [rfc1902.ObjectType(rfc1902.ObjectIdentity( x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds] for name, val in varBinds: # Append to output String szOut = szOut + ", Oid: {}, Value: {}".format(name.prettyPrint(), val.prettyPrint()) if isinstance(val, OctetString): if (name.prettyPrint() != "SNMP-COMMUNITY-MIB::snmpTrapAddress.0"): szOctets = val.asOctets() # .rstrip('\r').rstrip('\n') szOut = szOut + ", Octets: {}".format(szOctets) if (bDebug): print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) outputFile.write(szOut) if "\n" not in szOut: outputFile.write("\n") outputFile.flush() # Register SNMP Application at the SNMP engine ntfrcv.NotificationReceiver(snmpEngine, cbReceiverSnmp) # this job would never finish snmpEngine.transportDispatcher.jobStarted(1) def cleanup_started_file(): try: os.remove(szSnmpLogfile + ".started") except OSError: # The marker is best-effort cleanup; shutdown must continue if it # is already gone or cannot be removed. pass # Run I/O dispatcher which would receive queries and send confirmations try: snmpEngine.transportDispatcher.runDispatcher() except KeyboardInterrupt: print("Received keyboard interrupt, shutting down") finally: cleanup_started_file() snmpEngine.transportDispatcher.closeDispatcher() rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-key-mtls-ecdsa-sigalgs-vg.sh0000644000000000000000000000013215241075234025113 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.688579848 30 ctime=1787067807.558970355 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-key-mtls-ecdsa-sigalgs-vg.sh0000775000175000017500000000014515241075234024562 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-key-mtls-ecdsa-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_hash64.sh0000644000000000000000000000013215241075234017103 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.847957106 rsyslog-8.2608.0/tests/rscript_hash64.sh0000775000175000017500000000201215241075234016545 0ustar00rgerrger#!/bin/bash # added 2018-02-07 by Harshvardhan Shrivastava # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \rscript_hash64.sh\]: test for hash64 and hash64mod script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n") module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmhash/.libs/fmhash") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.hash_no_1 = hash64("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e"); set $.hash_no_2 = hash64mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 20 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown . $srcdir/diag.sh content-pattern-check "^\(-2574714428477944902 - 14\|-50452361579464591 - 25\)$" exit_test rsyslog-8.2608.0/tests/PaxHeaders/daqueue-invld-qi.sh0000644000000000000000000000013215241075234017412 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067804.424911954 rsyslog-8.2608.0/tests/daqueue-invld-qi.sh0000775000175000017500000000364315241075234017067 0ustar00rgerrger#!/bin/bash # Exercise classic DA recovery from a deliberately mangled .qi file. This test # inspects classic state directly, so the modern queue configuration pins the # classic engine; restart must recover the full sequence, allowing duplicates. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on all flavors of Solaris." generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $ModLoad ../plugins/omtesting/.libs/omtesting # Configure a classic disk-assisted main queue. Keep this fully in the modern # frontend because diskQueueType intentionally has no legacy directive alias. global(workDirectory="'$RSYSLOG_DYNNAME'.spool") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.timeoutShutdown="1" queue.saveOnShutdown="on" queue.diskQueueType="disk") $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt $IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf ' #export RSYSLOG_DEBUG="debug nologfuncflow nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf # Phase 1: inject enough messages to hit the high watermark and persist DA state. startup injectmsg 0 10000 shutdown_immediate wait_shutdown check_mainq_spool ./mangle_qi -d -q ${RSYSLOG_DYNNAME}.spool/mainq.qi > tmp.qi mv tmp.qi ${RSYSLOG_DYNNAME}.spool/mainq.qi echo "Enter phase 2, rsyslogd restart" # Phase 2: remove the artificial delay and verify the mangled .qi recovers. echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 9999 -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/rsyslog-segqueue-tool.py0000644000000000000000000000013115241075234020553 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 29 ctime=1787067803.70989863 rsyslog-8.2608.0/tests/rsyslog-segqueue-tool.py0000775000175000017500000002563415241075234020235 0ustar00rgerrger#!/usr/bin/env python3 """Exercise segmented queue inspection, export, and offline repair. The test builds a small deterministic format-v2 store without starting rsyslogd. Exact issue codes, JSONL selection, repair backups, and post-repair validation are the oracle; no timing or external service is involved. """ import importlib.machinery import importlib.util import json import os import shutil import stat import struct import subprocess import sys import tempfile SCRIPT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "tools", "rsyslog-segqueue")) LOADER = importlib.machinery.SourceFileLoader("rsyslog_segqueue", SCRIPT) SPEC = importlib.util.spec_from_loader(LOADER.name, LOADER) TOOL = importlib.util.module_from_spec(SPEC) LOADER.exec_module(TOOL) def check(condition, message): if not condition: raise AssertionError(message) def tlv(field, field_type, value): return struct.pack(">HBBI", field, field_type, 0, len(value)) + value def payload(number, invalid_utf8=False): raw = b"<13>msgnum:%08d" % number if invalid_utf8: raw += b"\xff" return b"".join( ( tlv(9, TOOL.TLV_BYTES, raw), tlv(10, TOOL.TLV_BYTES, b"testhost"), tlv(16, TOOL.TLV_BYTES, json.dumps({"number": number}).encode("utf-8")), tlv(23, TOOL.TLV_U32, struct.pack(">I", 4)), tlv(24, TOOL.TLV_U32, struct.pack(">I", 4)), ) ) def create_store(path, count=2): os.mkdir(path) uuid_bytes = bytes(range(16)) segment_path = os.path.join(path, "segment-00000000000000000001.seg") boundaries = [TOOL.SEG_HEADER_LEN] with open(segment_path, "wb") as stream: TOOL.write_segment_header(stream, uuid_bytes, 1) rolling_crc = 0 for sequence in range(1, count + 1): rolling_crc ^= TOOL.write_clean_record(stream, payload(sequence, sequence == count), sequence) boundaries.append(stream.tell()) TOOL.write_footer(stream, 1, count, rolling_crc) stream.flush() os.fsync(stream.fileno()) segment_bytes = os.path.getsize(segment_path) state = TOOL.make_replay_state(uuid_bytes, 1, segment_bytes, count) with open(os.path.join(path, "state"), "wb") as stream: stream.write(TOOL.encode_state(state, 0)) stream.write(TOOL.encode_state(state, 1)) return boundaries def corrupt_payload(path, offset): segment_path = os.path.join(path, "segment-00000000000000000001.seg") with open(segment_path, "r+b") as stream: stream.seek(offset + TOOL.RECORD_HEADER_LEN) byte = stream.read(1) stream.seek(offset + TOOL.RECORD_HEADER_LEN) stream.write(bytes((byte[0] ^ 1,))) def run_cli(*arguments): return subprocess.run( [sys.executable, SCRIPT] + list(arguments), check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, ) def main(): check(TOOL.crc32c(b"123456789") == 0xE3069283, "CRC32C canonical vector failed") sentinel_values = TOOL.decode_codec( tlv(9, TOOL.TLV_BYTES, b"unparsed") + struct.pack(">HBBI", 99, TOOL.TLV_BYTES, 0, 2) + b"\x00\xff" + tlv(23, TOOL.TLV_U32, struct.pack(">I", TOOL.UINT32_UNSET)) ) sentinel_json = TOOL.message_json(sentinel_values) check(sentinel_json["msg"] == "unparsed", "unset message offset did not preserve the raw message") check(sentinel_json["msg_offset_unset"], "unset message offset was not marked") check( sentinel_json["unknown_optional_tlvs"] == [{"field": 99, "type": TOOL.TLV_BYTES, "flags": 0, "value": {"encoding": "base64", "data": "AP8="}}], "unknown optional TLV was not exported losslessly", ) root = tempfile.mkdtemp(prefix="rsyslog-segqueue-test-") try: queue = os.path.join(root, "mainq.segq") boundaries = create_store(queue) report = TOOL.inspect_store(queue, full=True) check(report["error_count"] == 0, "fresh store did not validate: {}".format(report["issues"])) check(report["summary"]["valid_record_count"] == 2, "fresh record count is wrong") status = run_cli("status", queue, "--json") check(status.returncode == 0, "JSON status failed: {}".format(status.stderr)) check(json.loads(status.stdout)["state"]["selected"]["generation"] == 1, "wrong state selected") state_path = os.path.join(queue, "state") state_data = bytearray(open(state_path, "rb").read()) selected = TOOL.decode_state(state_data[TOOL.STATE_SLOT_LEN:]) selected["committed_offset"] = boundaries[1] selected["committed_record_sequence"] = 1 state_data[: TOOL.STATE_SLOT_LEN] = TOOL.encode_state(selected, 2) with open(state_path, "wb") as stream: stream.write(state_data) exported = os.path.join(root, "live.jsonl") result = run_cli("export", queue, "--output", exported) check(result.returncode == 0, "live export failed: {}".format(result.stderr)) lines = [json.loads(line) for line in open(exported, encoding="utf-8")] check(len(lines) == 1 and lines[0]["queue"]["record_sequence"] == 2, "live frontier filtering failed") check(lines[0]["message"]["rawmsg"]["encoding"] == "base64", "invalid UTF-8 was not lossless") corrupt_queue = os.path.join(root, "corrupt.segq") shutil.copytree(queue, corrupt_queue) corrupt_payload(corrupt_queue, boundaries[1]) corrupt_report = TOOL.inspect_store(corrupt_queue, full=True) codes = {issue["code"] for issue in corrupt_report["issues"]} check("record.payload_crc" in codes, "payload corruption was not reported") refused = run_cli("export", corrupt_queue, "--output", os.path.join(root, "refused.jsonl")) check(refused.returncode == 2, "corrupt export was not refused") partial_path = os.path.join(root, "partial.jsonl") partial = run_cli("export", corrupt_queue, "--scope", "all", "--salvage", "--output", partial_path) check(partial.returncode == 2, "salvage export did not report partial success") check(sum(1 for _ in open(partial_path, encoding="utf-8")) == 1, "salvage export count is wrong") entries_before_plan = sorted(os.listdir(root)) plan = TOOL.run_repair(corrupt_queue, "salvage", False, False) check(not plan["repair"]["apply"], "repair plan unexpectedly applied") check(sorted(os.listdir(root)) == entries_before_plan, "repair plan wrote a staging artifact") applied = TOOL.run_repair(corrupt_queue, "salvage", True, True) check(os.path.isdir(applied["repair"]["backup"]), "salvage backup was not retained") repaired_report = TOOL.inspect_store(corrupt_queue, full=True) check(repaired_report["error_count"] == 0, "salvaged store is invalid") check(repaired_report["summary"]["valid_record_count"] == 1, "salvage retained the wrong records") rebuild_queue = os.path.join(root, "rebuild.segq") create_store(rebuild_queue) os.chmod(rebuild_queue, 0o750) # nosec B103 - intentional queue directory permissions os.chmod(os.path.join(rebuild_queue, "state"), 0o640) os.chmod(os.path.join(rebuild_queue, "segment-00000000000000000001.seg"), 0o640) os.unlink(os.path.join(rebuild_queue, "state")) original_chown = TOOL.os.chown original_fchown = TOOL.os.fchown def deny_chown(*_args): raise PermissionError("simulated ownership change denial") TOOL.os.chown = deny_chown TOOL.os.fchown = deny_chown try: rebuilt = TOOL.run_repair(rebuild_queue, "rebuild", True, True) finally: TOOL.os.chown = original_chown TOOL.os.fchown = original_fchown check(os.path.isdir(rebuilt["repair"]["backup"]), "rebuild backup was not retained") check(TOOL.inspect_store(rebuild_queue, full=True)["error_count"] == 0, "rebuilt store is invalid") check(stat.S_IMODE(os.stat(rebuild_queue).st_mode) == 0o750, "rebuild changed the queue directory mode") rebuilt_segment = os.path.join(rebuild_queue, "segment-00000000000000000001.seg") backup_segment = os.path.join(rebuilt["repair"]["backup"], "segment-00000000000000000001.seg") check( (os.stat(rebuilt_segment).st_uid, os.stat(rebuilt_segment).st_gid, stat.S_IMODE(os.stat(rebuilt_segment).st_mode)) == (os.stat(backup_segment).st_uid, os.stat(backup_segment).st_gid, 0o640), "rebuild did not preserve segment ownership and mode", ) mismatch_queue = os.path.join(root, "mismatch.segq") create_store(mismatch_queue) mismatch_segment = os.path.join(mismatch_queue, "segment-00000000000000000001.seg") with open(mismatch_segment, "r+b") as stream: stream.seek(12) stream.write(b"different-uuid!!") try: TOOL.run_repair(mismatch_queue, "salvage", True, True) except TOOL.QueueToolError as error: check(mismatch_segment in str(error), "UUID mismatch did not name the segment path") else: raise AssertionError("UUID mismatch salvage was not refused") slot_queue = os.path.join(root, "slot.segq") create_store(slot_queue) slot_state_path = os.path.join(slot_queue, "state") slot_data = bytearray(open(slot_state_path, "rb").read()) slot_data[TOOL.STATE_SLOT_LEN + 200] ^= 1 with open(slot_state_path, "wb") as stream: stream.write(slot_data) slot_result = TOOL.run_repair(slot_queue, "state-slot", True, True) check(os.path.isfile(slot_result["repair"]["backup"]), "state-slot backup was not retained") slot_report = TOOL.inspect_store(slot_queue, full=False) check(all(slot["valid"] for slot in slot_report["_internal"]["state"]["slots"]), "slot repair failed") equal_state = TOOL.make_replay_state(bytes(range(16)), 0, 0, 0) equal_state["known_queue_size"] = 11 slot0 = TOOL.encode_state(equal_state, 7) equal_state["known_queue_size"] = 22 slot1 = TOOL.encode_state(equal_state, 7) with open(slot_state_path, "wb") as stream: stream.write(slot0 + slot1) equal_report = TOOL.inspect_store(slot_queue, full=False) check(equal_report["state"]["selected_slot"] == 0, "equal generations did not select slot 0") check(equal_report["state"]["selected"]["known_queue_size"] == 11, "slot 0 state was not selected") tui = subprocess.run( [sys.executable, SCRIPT, "tui", slot_queue], input="1\n5\n", check=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, ) check(tui.returncode == 0 and "Selected slot/generation" in tui.stdout, "guided TUI smoke test failed") finally: shutil.rmtree(root) print("rsyslog-segqueue tool tests passed") return 0 if __name__ == "__main__": sys.exit(main()) rsyslog-8.2608.0/tests/PaxHeaders/rsf_getenv.sh0000644000000000000000000000013215131231047016374 xustar0030 mtime=1768239655.719212827 30 atime=1782715518.909790897 30 ctime=1787067804.466912737 rsyslog-8.2608.0/tests/rsf_getenv.sh0000777000175000017500000000133715131231047016051 0ustar00rgerrger#!/bin/bash # Test for the getenv() rainerscript function # this is a quick test, but it guarantees that the code path is # at least progressed (but we do not check for unset envvars!) # added 2009-11-03 by Rgerhards # This file is part of the rsyslog project, released under GPLv3 # uncomment for debugging support: export NUMMESSAGES=10000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export MSGNUM="msgnum:" . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! if $msg contains getenv("MSGNUM") then ?dynfile;outfmt ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/msgvar-concurrency-array-event.tags.sh0000644000000000000000000000013215241075234023257 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.782581608 30 ctime=1787067807.088961596 rsyslog-8.2608.0/tests/msgvar-concurrency-array-event.tags.sh0000775000175000017500000000263415241075234022733 0ustar00rgerrger#!/bin/bash # Test concurrency of message variables # Added 2015-11-03 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 export TCPFLOOD_EXTRA_OPTS="-M'msg:msg: 1:2, 3:4, 5:6, 7:8 b test'" echo =============================================================================== echo \[msgvar-concurrency-array-event.tags.sh\]: testing concurrency of local variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmnormalize/.libs/mmnormalize") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!%\n") #action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList") action(type="mmnormalize" ruleBase="testsuites/msgvar-concurrency-array-event.tags.rulebase") if $msg contains "msg:" then { # set $!tree!here!nbr = field($msg, 58, 2); # Delimiter = : action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="outfmt" queue.type="linkedList") set $!tree!here!save = $!tree!here!nbr; set $!tree!here!nbr = ""; set $!tree!here!nbr = $!tree!here!save; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" queue.type="linkedList") } ' startup sleep 1 tcpflood -m500000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown #seq_check 0 499999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/json_array_looping.sh0000644000000000000000000000013015035412264020133 xustar0030 mtime=1752569012.398764645 29 atime=1782715518.90879088 29 ctime=1787067807.19596359 rsyslog-8.2608.0/tests/json_array_looping.sh0000777000175000017500000000421615035412264017611 0ustar00rgerrger#!/bin/bash # added 2014-11-11 by singh.janmejay # basic test for looping over json array # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="garply" type="string" string="garply: %$.garply%\n") template(name="grault" type="string" string="grault: %$.grault%\n") template(name="prefixed_grault" type="string" string="prefixed_grault: %$.grault%\n") template(name="quux" type="string" string="quux: %$.quux%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse") set $.garply = ""; ruleset(name="prefixed_writer" queue.type="linkedlist" queue.workerthreads="5") { action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.prefixed.log" template="prefixed_grault" queue.type="linkedlist") } foreach ($.quux in $!foo) do { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="quux") foreach ($.corge in $.quux!bar) do { reset $.grault = $.corge; action(type="omfile" file="'$RSYSLOG_DYNNAME'.out.async.log" template="grault" queue.type="linkedlist" action.copyMsg="on") call prefixed_writer if ($.garply != "") then set $.garply = $.garply & ", "; reset $.garply = $.garply & $.grault!baz; } } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="garply") ' startup tcpflood -m 1 -I $srcdir/testsuites/json_array_input echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check 'quux: abc0' content_check 'quux: def1' content_check 'quux: ghi2' content_check 'quux: { "bar": [ { "baz": "important_msg" }, { "baz": "other_msg" } ] }' custom_content_check 'grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.async.log custom_content_check 'grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.async.log custom_content_check 'prefixed_grault: { "baz": "important_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log custom_content_check 'prefixed_grault: { "baz": "other_msg" }' $RSYSLOG_DYNNAME.out.prefixed.log content_check 'garply: important_msg, other_msg' exit_test rsyslog-8.2608.0/tests/PaxHeaders/ommail_errmsg_no_params.sh0000644000000000000000000000013115035412264021132 xustar0030 mtime=1752569012.404722953 29 atime=1782715518.90879088 30 ctime=1787067805.692935582 rsyslog-8.2608.0/tests/ommail_errmsg_no_params.sh0000777000175000017500000000066315035412264020611 0ustar00rgerrger#!/bin/bash # add 2018-09-25 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../plugins/ommail/.libs/ommail") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") action(type="ommail") ' startup shutdown_when_empty wait_shutdown content_check "parameter 'mailto' required but not specified" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-imkubernetes-dockerjson-basic.sh0000644000000000000000000000013215241075234023113 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067808.175981852 rsyslog-8.2608.0/tests/yaml-imkubernetes-dockerjson-basic.sh0000775000175000017500000000326115241075234022564 0ustar00rgerrger#!/bin/bash # Verify imkubernetes can be configured through the YAML frontend. The test # tails a Kubernetes /var/log/containers-style Docker json-file record with API # enrichment disabled; output metadata proves the YAML module parameters reached # imkubernetes and the parsed record flowed through the regular queue. . ${srcdir:=.}/diag.sh init require_yaml_support require_plugin imkubernetes ../contrib/imkubernetes pwd=$( pwd ) logdir="${RSYSLOG_DYNNAME}.spool/containers" logfile="${logdir}/pod-name3_namespace-name3_container-c-feedface.log" generate_conf --yaml-only add_yaml_conf 'modules:' add_yaml_conf ' - load: "../contrib/imkubernetes/.libs/imkubernetes"' add_yaml_conf 'inputs:' add_yaml_conf ' - type: imkubernetes' add_yaml_conf ' logfileglob: "'$pwd/$logdir'/*.log"' add_yaml_conf ' pollinginterval: 1' add_yaml_conf ' enrichkubernetes: off' add_yaml_conf ' ruleset: main' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf ' string: "%msg%|%$!kubernetes!namespace_name%|%$!kubernetes!pod_name%|%$!kubernetes!container_name%|%$!kubernetes!stream%|%$!kubernetes!log_format%|%$!docker!container_id%\n"' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: main' add_yaml_conf ' script: |' add_yaml_conf ' action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")' mkdir -p "$logdir" startup cat > "$logfile" <<'EOF' {"log":"yaml docker line\n","stream":"stdout","time":"2026-04-20T10:02:00.123456789Z"} EOF wait_file_lines "$RSYSLOG_OUT_LOG" 1 wait_queueempty shutdown_when_empty wait_shutdown content_check 'yaml docker line|namespace-name3|pod-name3|container-c|stdout|docker_json|feedface' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-maxFrameSize.sh0000644000000000000000000000013215241075234017745 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.771581402 30 ctime=1787067805.501932023 rsyslog-8.2608.0/tests/imtcp-maxFrameSize.sh0000775000175000017500000000141515241075234017415 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp" maxFrameSize="100") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 -M "\"1005 <120> 2011-03-01T11:22:12Z host tag: this is a way too long message\"" shutdown_when_empty wait_shutdown grep "Framing Error.*change to octet stuffing" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message from imtcp not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_conflict2.sh0000644000000000000000000000013115241075234021750 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.793581814 29 ctime=1787067806.88895787 rsyslog-8.2608.0/tests/rscript_unflatten_conflict2.sh0000775000175000017500000000247315241075234021426 0ustar00rgerrger#!/bin/bash # added 2021-03-09 by Julien Thomas, released under ASL 2.0 . "${srcdir:=.}/diag.sh" init export RSYSLOG_DEBUG="debug nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debug" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmunflatten/.libs/fmunflatten") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port") template(name="outfmt" type="string" string="%msg% %$.ret% %$.unflatten%\n") if (not($msg contains "msgnum:")) then stop set $.x!a = 21; set $!a!b = "foo"; set $!a.b = $.x; set $.unflatten = unflatten($!, "."); set $.ret = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m 1 wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown # this test may need changes to produce a more deterministic # output by sorting keys EXPECTED=' msgnum:00000000: 0 { "a": { "b": { "a": 21 } } }' cmp_exact "$RSYSLOG_OUT_LOG" EXPECTED='fmunflatten.c: warning: while processing flat key "a.b" at depth #1 (final node), overriding existing value of type string by an object' if ! grep -F "$EXPECTED" "$RSYSLOG_DEBUGLOG"; then echo "GREP FAILED" echo " => FILE: $RSYSLOG_DEBUGLOG" echo " => EXPECTED: $EXPECTED" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_table-daemon-shutdown.sh0000644000000000000000000000013215216464436022042 xustar0030 mtime=1782212894.073266944 30 atime=1782715518.914790982 30 ctime=1787067804.958921905 rsyslog-8.2608.0/tests/lookup_table-daemon-shutdown.sh0000775000175000017500000000226415216464436021515 0ustar00rgerrger#!/bin/bash # Regression coverage for lookup-table shutdown in daemon mode. # # Issues #1071 and #5301 reported crashes or hangs while rsyslog shut down # with lookup tables configured. This test keeps the setup intentionally small: # one lookup table, one lookup() expression, daemonized startup, then a normal # TERM shutdown. The oracle is wait_shutdown returning successfully; a stuck # lookup reloader thread, recursive lookup rwlock deadlock, or invalid pthread # teardown causes the testbench shutdown wait to fail. # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_TSAN generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl export RSTB_DAEMONIZE="YES" startup injectmsg 0 3 wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/gzipwr_hup-vg.sh0000644000000000000000000000013215171370365017055 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.914790982 30 ctime=1787067805.135925203 rsyslog-8.2608.0/tests/gzipwr_hup-vg.sh0000775000175000017500000000017615171370365016530 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export NUMMESSAGES=200000 # reduce for slower valgrind run . ${srcdir:-.}/gzipwr_hup.sh rsyslog-8.2608.0/tests/PaxHeaders/threadingmqaq.sh0000644000000000000000000000013215035412264017064 xustar0030 mtime=1752569012.419618726 30 atime=1782715518.913790965 30 ctime=1787067805.303928333 rsyslog-8.2608.0/tests/threadingmqaq.sh0000777000175000017500000000310215035412264016531 0ustar00rgerrger#!/bin/bash # test many concurrent tcp connections # we send 100,000 messages in the hopes that his puts at least a little bit # of pressure on the threading subsystem. To really prove it, we would need to # push messages for several minutes, but that takes too long during the # automated tests (hint: do this manually after suspect changes). Thankfully, # in practice many threading bugs result in an abort rather quickly and these # should be covered by this test here. # rgerhards, 2009-06-26 uname if [ $(uname) = "SunOS" ] ; then echo "This test currently does not work on all flavors of Solaris." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MainMsgQueueTimeoutShutdown 10000 $MainMsgQueueWorkerThreadMinimumMessages 10 $MainMsgQueueWorkerThreads 5 $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! # write quickly to the output file: $OMFileFlushOnTXEnd off $OMFileIOBufferSize 256k # This time, also run the action queue detached $ActionQueueWorkerThreadMinimumMessages 10 $ActionQueueWorkerThreads 5 $ActionQueueTimeoutEnqueue 10000 $ActionQueueType LinkedList :msg, contains, "msgnum:" ?dynfile;outfmt ' startup #tcpflood -c2 -m100000 #shutdown_when_empty # shut down rsyslogd when done processing messages injectmsg 0 100000 # we need to sleep a bit on some environments, as imdiag can not correctly # diagnose when the action queues are empty... sleep 3 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 99999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-consumerGroup-reclaim.sh0000644000000000000000000000013215131231047023760 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.913790965 30 ctime=1787067806.563951813 rsyslog-8.2608.0/tests/imhiredis-stream-consumerGroup-reclaim.sh0000777000175000017500000000432215131231047023432 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/imhiredis/.libs/imhiredis") template(name="outfmt" type="string" string="%$/num% %$!msg%\n") input(type="imhiredis" server="127.0.0.1" port="'$REDIS_RANDOM_PORT'" key="mystream" mode="stream" stream.consumerGroup="mygroup" stream.consumerName="myName" stream.autoclaimIdleTime="5000" #5 seconds ruleset="redis") ruleset(name="redis") { set $/num = cnum($/num + 1); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' redis_command "XADD mystream * msg message1" redis_command "XADD mystream * msg message2" redis_command "XADD mystream * msg message3" redis_command "XADD mystream * msg message4" redis_command "XADD mystream * msg message5" redis_command "XADD mystream * msg message6" redis_command "XGROUP CREATE mystream mygroup 0-0" # Read and claim message1 and message2 redis_command "XREADGROUP GROUP mygroup otherConsumer COUNT 2 STREAMS mystream >" rst_msleep 5500 # Read and claim message3 and message4 redis_command "XREADGROUP GROUP mygroup otherConsumer COUNT 2 STREAMS mystream >" startup shutdown_when_empty wait_shutdown output="$(redis_command 'hello 3\nXINFO groups mystream' | grep 'pending')" if [ -z "$output" ]; then echo "Could not get group result from redis, cannot tell if entries ware acknowledged!" error_exit 1 fi # Should still have 2 pending messages: message3 and message4 if ! echo "$output" | grep -q "pending 2"; then echo "ERROR: entries weren't acknowledged!" echo "ERROR: output from Redis is '$output'" echo "ERROR: expected 'pending 2'" error_exit 1 fi stop_redis # Should reclaim message1 and message2 # then claim and acknowledge message5 and message6 normally content_check '1 message1' content_check '2 message2' content_check '3 message5' content_check '4 message6' # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/rcvr_fail_restore.sh0000644000000000000000000000013215241075234017752 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.723917526 rsyslog-8.2608.0/tests/rcvr_fail_restore.sh0000775000175000017500000001461615241075234017431 0ustar00rgerrger#!/bin/bash # Verify classic DA reactivation across receiver outages. The filesystem oracle # compares the classic numeric segment before and after drain, so the sender # pins diskQueueType="disk" through the modern main-queue frontend. # Copyright (C) 2011 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test does not work on FreeBSD - problems with os utility option switches" skip_ARM "disk-assisted queue receiver restore timing is flaky on ARM CI" MAINQ_SEGMENT="${RSYSLOG_DYNNAME}.spool/mainq.00000001" sender_mainqueuesize() { response="$(echo getmainmsgqueuesize | $TESTTOOL_DIR/diagtalker -p$IMDIAG_PORT2)" || error_exit $? echo "$response" | awk '{print $NF}' } mainq_segment_size() { if [ -f "$MAINQ_SEGMENT" ]; then stat -c%s "$MAINQ_SEGMENT" else echo 0 fi } wait_sender_queues_outage_data() { initial_segment_size="$1" echo "waiting for sender queue and DA segment growth from $initial_segment_size bytes" i=0 # Use the standard startup bound so a loaded CI host has time to append; # queue-size plus segment growth is the deterministic readiness oracle. while [ $i -le $TB_TIMEOUT_STARTSTOP ]; do qsize="$(sender_mainqueuesize)" segment_size="$(mainq_segment_size)" if [ "${qsize:-0}" -gt 0 ] 2>/dev/null && [ "${segment_size:-0}" -gt "${initial_segment_size:-0}" ]; then echo "sender queue size $qsize, DA segment size $segment_size" return fi $TESTTOOL_DIR/msleep 100 i=$((i + 1)) done echo "FAIL: sender did not queue outage data before receiver restart" echo "last sender queue size: $qsize" echo "last DA segment size: $segment_size, expected > $initial_segment_size" ls -l ${RSYSLOG_DYNNAME}.spool error_exit 1 } # # STEP1: start both instances and send 1000 messages. # Note: receiver is instance 1, sender instance 2. # # start up the instances. Note that the environment settings can be changed to # set instance-specific debugging parameters! #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="log2" echo starting receiver generate_conf add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" ./'$RSYSLOG_OUT_LOG';outfmt ' startup export PORT_RCVR="$TCPFLOOD_PORT" #export RSYSLOG_DEBUG="debug nostdout" #export RSYSLOG_DEBUGLOG="log" #valgrind="valgrind" echo starting sender generate_conf 2 add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME'.spool") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.size="2000" queue.lowWatermark="800" queue.highWatermark="1000" queue.dequeueBatchSize="1" queue.maxFileSize="1g" queue.workerThreads="1" queue.diskQueueType="disk") # we use the shortest resume interval a) to let the test not run too long # and b) make sure some retries happen before the reconnect $ActionResumeInterval 1 $ActionSendResendLastMsgOnReconnect on $ActionResumeRetryCount -1 *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # re-set params so that new instances do not thrash it... #unset RSYSLOG_DEBUG #unset RSYSLOG_DEBUGLOG # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 1000 wait_queueempty ./msleep 1000 # let things settle down a bit # # Step 2: shutdown receiver, then send some more data, which then # needs to go into the queue. # echo step 2 shutdown_when_empty wait_shutdown INITIALFILESIZE="$(mainq_segment_size)" injectmsg2 1001 10000 wait_sender_queues_outage_data "$INITIALFILESIZE" get_mainqueuesize 2 ls -l ${RSYSLOG_DYNNAME}.spool # # Step 3: restart receiver, wait that the sender drains its queue # echo step 3 #export RSYSLOG_DEBUGLOG="log2" generate_conf add_conf ' # then SENDER sends to this port (not tcpflood!) module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="'$PORT_RCVR'") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" ./'$RSYSLOG_OUT_LOG';outfmt ' startup echo waiting for sender to drain queue [may need a short while] wait_queueempty 2 ls -l ${RSYSLOG_DYNNAME}.spool OLDFILESIZE=$(stat -c%s ${RSYSLOG_DYNNAME}.spool/mainq.00000001) echo file size to expect is $OLDFILESIZE # # Step 4: send new data. Queue files are not permitted to grow now # (but one file continuous to exist). # echo step 4 injectmsg2 11001 10 wait_queueempty 2 # at this point, the queue file shall not have grown. Note # that we MUST NOT shut down the instance right now, because it # would clean up the queue files! So we need to do our checks # first (here!). ls -l ${RSYSLOG_DYNNAME}.spool NEWFILESIZE=$(stat -c%s ${RSYSLOG_DYNNAME}.spool/mainq.00000001) if [ $NEWFILESIZE != $OLDFILESIZE ] then echo "file sizes do not match, expected $OLDFILESIZE, actual $NEWFILESIZE" echo this means that data has been written to the queue file where it echo no longer should be written. # abort will happen below, because we must ensure proper system shutdown # HOWEVER, during actual testing it may be useful to do an exit here (so # that e.g. the debug log is pointed right at the correct spot). # exit 1 fi # # We now do an extra test (so this is two in one ;)) to see if the DA # queue can be reactivated after its initial shutdown. In essence, we # redo steps 2 and 3. # # Step 5: stop receiver again, then send some more data, which then # needs to go into the queue. # echo step 5 echo "*** done primary test *** now checking if DA can be restarted" shutdown_when_empty wait_shutdown INITIALFILESIZE="$(mainq_segment_size)" injectmsg2 11011 10000 wait_sender_queues_outage_data "$INITIALFILESIZE" get_mainqueuesize 2 ls -l ${RSYSLOG_DYNNAME}.spool # # Step 6: restart receiver, wait that the sender drains its queue # echo step 6 startup echo waiting for sender to drain queue [may need a short while] wait_queueempty 2 ls -l ${RSYSLOG_DYNNAME}.spool # # Queue file size checks done. Now it is time to terminate the system # and see if everything could be received (the usual check, done here # for completeness, more or less as a bonus). # shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # now abort test if we need to (due to filesize predicate) if [ $NEWFILESIZE != $OLDFILESIZE ]; then error_exit 1 fi # do the final check export SEQ_CHECK_OPTIONS=-d seq_check 1 21010 -m 100 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-wildcards-dirs-multi3.sh0000644000000000000000000000013215216464436021641 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.913790965 30 ctime=1787067807.982978256 rsyslog-8.2608.0/tests/imfile-wildcards-dirs-multi3.sh0000775000175000017500000000557615216464436021325 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . ${srcdir:=.}/diag.sh init export IMFILEINPUTFILES="1" export IMFILEINPUTFILESSTEPS="5" #export IMFILEINPUTFILESALL=$(($IMFILEINPUTFILES * $IMFILEINPUTFILESSTEPS)) export IMFILECHECKTIMEOUT="60" mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' /* Filter out busy debug output, comment out if needed */ global( debug.whitelist="off" debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"] ) global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module( load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*/*/testdir/*/file.logfile" Tag="file:" Severity="error" Facility="local7" addMetadata="on" ) template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value=", ") property(name="$!metadata!filename") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' # generate input files first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). for i in $(seq 1 $IMFILEINPUTFILES); do echo "Make $RSYSLOG_DYNNAME.input.dir$i" mkdir $RSYSLOG_DYNNAME.input.dir$i echo created! done # Start rsyslog now before adding more files startup # sleep a little to give rsyslog a chance to begin processing sleep 2 for j in $(seq 1 $IMFILEINPUTFILESSTEPS); do echo "Loop Num $j" for i in $(seq 1 $IMFILEINPUTFILES); do echo "Make $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir" mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir mkdir $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j ./inputfilegen -m 1 -i $(((j - 1) * IMFILEINPUTFILES + i - 1)) > \ $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.tmp mv $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.tmp \ $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile ls -l $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile done ls -d $RSYSLOG_DYNNAME.input.* # Check correct amount of input files each time IMFILEINPUTFILESALL=$((IMFILEINPUTFILES * j)) content_check_with_count "HEADER msgnum:" $IMFILEINPUTFILESALL $IMFILECHECKTIMEOUT # Delete all but first! for i in $(seq 1 $IMFILEINPUTFILES); do rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j/testdir/subdir$j/file.logfile rm -rf $RSYSLOG_DYNNAME.input.dir$i/dir$j done # Helps in testbench parallel mode. # Otherwise sometimes directories are not marked deleted in imfile before they get created again. # This is properly a real issue in imfile when FILE IO is high. ./msleep 1000 done shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! exit_test rsyslog-8.2608.0/tests/PaxHeaders/nested-call-shutdown.sh0000644000000000000000000000013215241075234020304 xustar0030 mtime=1787067036.630578762 30 atime=1787067036.782581608 30 ctime=1787067804.120906289 rsyslog-8.2608.0/tests/nested-call-shutdown.sh0000775000175000017500000000170315241075234017754 0ustar00rgerrger#!/bin/bash # addd 2017-10-18 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="rs3" queue.type="linkedList") { action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ruleset(name="rs2" queue.type="linkedList") { call rs3 } ruleset(name="rs1" queue.type="linkedList") { call rs2 :omtesting:sleep 0 1000 } if $msg contains "msgnum:" then call rs1 ' startup #tcpflood -p'$TCPFLOOD_PORT' -m10000 injectmsg 0 1000 shutdown_immediate wait_shutdown # wo do not check reception - the main point is that we do not abort. The actual # message count is unknown (as the point is to shut down while still in processing). exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-transactions-failed-commits.sh0000644000000000000000000000013215035412264023143 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.914790982 30 ctime=1787067806.089942981 rsyslog-8.2608.0/tests/omprog-transactions-failed-commits.sh0000777000175000017500000001122415035412264022614 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests omprog with the confirmMessages=on and useTransactions=on # parameters, with the external program returning an error on certain # transaction commits. . ${srcdir:=.}/diag.sh init uname if [ $(uname) = "SunOS" ] ; then # On Solaris, this test causes rsyslog to hang. This is presumably due # to issue #2356 in the rsyslog core, which doesn't seem completely # corrected. TODO: re-enable this test when the issue is corrected. echo "Solaris: FIX ME" exit 77 fi generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-transactions-bin.sh --failed_commits` template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process queue.dequeueBatchSize="6" confirmMessages="on" useTransactions="on" action.resumeRetryCount="10" action.resumeInterval="1" ) } ' startup injectmsg 0 10 shutdown_when_empty wait_shutdown # Since the transaction boundaries are not deterministic, we cannot check for # an exact expected output. We must check the output programmatically. transaction_state="NONE" status_expected=true messages_to_commit=() messages_processed=() line_num=1 error= while IFS= read -r line; do if [[ $status_expected == true ]]; then case "$transaction_state" in "NONE") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi ;; "STARTED") if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi transaction_state="ACTIVE" ;; "ACTIVE") if [[ "$line" != "<= DEFER_COMMIT" ]]; then error="expecting a DEFER_COMMIT status from script" break fi ;; "COMMITTED") if [[ "$line" == "<= Error: could not commit transaction" ]]; then messages_to_commit=() transaction_state="NONE" else if [[ "$line" != "<= OK" ]]; then error="expecting an OK status from script" break fi messages_processed+=("${messages_to_commit[@]}") messages_to_commit=() transaction_state="NONE" fi ;; esac status_expected=false; else if [[ "$line" == "=> BEGIN TRANSACTION" ]]; then if [[ "$transaction_state" != "NONE" ]]; then error="unexpected transaction start" break fi transaction_state="STARTED" elif [[ "$line" == "=> COMMIT TRANSACTION" ]]; then if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected transaction commit" break fi transaction_state="COMMITTED" else if [[ "$transaction_state" != "ACTIVE" ]]; then error="unexpected message outside a transaction" break fi if [[ "$line" != "=> msgnum:"* ]]; then error="unexpected message contents" break fi prefix_to_remove="=> " messages_to_commit+=("${line#$prefix_to_remove}") fi status_expected=true; fi ((line_num++)) done < $RSYSLOG_OUT_LOG if [[ -z "$error" && "$transaction_state" != "NONE" ]]; then error="unexpected end of file (transaction state: $transaction_state)" fi if [[ -n "$error" ]]; then echo "$RSYSLOG_OUT_LOG: line $line_num: $error" cat $RSYSLOG_OUT_LOG error_exit 1 fi # Since the order in which failed messages are retried by rsyslog is not # deterministic, we sort the processed messages before checking them. IFS=$'\n' messages_sorted=($(sort <<<"${messages_processed[*]}")) unset IFS expected_messages=( "msgnum:00000000:" "msgnum:00000001:" "msgnum:00000002:" "msgnum:00000003:" "msgnum:00000004:" "msgnum:00000005:" "msgnum:00000006:" "msgnum:00000007:" "msgnum:00000008:" "msgnum:00000009:" ) if [[ "${messages_sorted[*]}" != "${expected_messages[*]}" ]]; then echo "unexpected set of processed messages:" printf '%s\n' "${messages_processed[@]}" echo "contents of $RSYSLOG_OUT_LOG:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-comprehensive.sh0000644000000000000000000000013015241075234021600 xustar0030 mtime=1787067036.630578762 29 atime=1787067036.78158159 29 ctime=1787067805.06492388 rsyslog-8.2608.0/tests/mmsnareparse-comprehensive.sh0000775000175000017500000002414515241075234021257 0ustar00rgerrger#!/bin/bash # Comprehensive test for mmsnareparse module field extraction capabilities # This test validates the module's ability to extract structured fields from # Windows Security Event Log description sections using dynamic test data from # sample-windows2022-security.data and sample-windows2025-security.data files. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmsnareparse/.libs/mmsnareparse") # Template to extract comprehensive structured JSON output template(name="jsonfmt" type="list" option.jsonf="on") { # Event fields property(outname="eventid" name="$!win!Event!EventID" format="jsonf") property(outname="channel" name="$!win!Event!Channel" format="jsonf") property(outname="eventtype" name="$!win!Event!EventType" format="jsonf") property(outname="categorytext" name="$!win!Event!CategoryText" format="jsonf") property(outname="computer" name="$!win!Event!Computer" format="jsonf") property(outname="provider" name="$!win!Event!Provider" format="jsonf") # Subject fields property(outname="subjectsecurityid" name="$!win!Subject!SecurityID" format="jsonf") property(outname="subjectaccountname" name="$!win!Subject!AccountName" format="jsonf") property(outname="subjectaccountdomain" name="$!win!Subject!AccountDomain" format="jsonf") property(outname="subjectlogonid" name="$!win!Subject!LogonID" format="jsonf") # LogonInformation fields property(outname="logontype" name="$!win!LogonInformation!LogonType" format="jsonf") property(outname="logontypename" name="$!win!LogonInformation!LogonTypeName" format="jsonf") property(outname="restrictedadminmode" name="$!win!LogonInformation!RestrictedAdminMode" format="jsonf") property(outname="virtualaccount" name="$!win!LogonInformation!VirtualAccount" format="jsonf") property(outname="elevatedtoken" name="$!win!LogonInformation!ElevatedToken" format="jsonf") property(outname="impersonationlevel" name="$!win!LogonInformation!ImpersonationLevel" format="jsonf") # NewLogon fields property(outname="newlogonsecurityid" name="$!win!NewLogon!SecurityID" format="jsonf") property(outname="newlogonaccountname" name="$!win!NewLogon!AccountName" format="jsonf") property(outname="newlogonaccountdomain" name="$!win!NewLogon!AccountDomain" format="jsonf") property(outname="newlogonlogonid" name="$!win!NewLogon!LogonID" format="jsonf") property(outname="linkedlogonid" name="$!win!NewLogon!LinkedLogonID" format="jsonf") property(outname="networkaccountname" name="$!win!NewLogon!NetworkAccountName" format="jsonf") property(outname="logonguid" name="$!win!NewLogon!LogonGUID" format="jsonf") # Process fields property(outname="processid" name="$!win!Process!ProcessID" format="jsonf") property(outname="processname" name="$!win!Process!ProcessName" format="jsonf") property(outname="processcommandline" name="$!win!Process!ProcessCommandLine" format="jsonf") property(outname="tokenelevationtype" name="$!win!Process!TokenElevationType" format="jsonf") property(outname="mandatorylabel" name="$!win!Process!MandatoryLabel" format="jsonf") # Network fields property(outname="workstationname" name="$!win!Network!WorkstationName" format="jsonf") property(outname="sourcenetworkaddress" name="$!win!Network!SourceNetworkAddress" format="jsonf") property(outname="sourceport" name="$!win!Network!SourcePort" format="jsonf") # DetailedAuthentication fields property(outname="logonprocess" name="$!win!DetailedAuthentication!LogonProcess" format="jsonf") property(outname="authenticationpackage" name="$!win!DetailedAuthentication!AuthenticationPackage" format="jsonf") property(outname="transitedservices" name="$!win!DetailedAuthentication!TransitedServices" format="jsonf") property(outname="packagename" name="$!win!DetailedAuthentication!PackageName" format="jsonf") property(outname="keylength" name="$!win!DetailedAuthentication!KeyLength" format="jsonf") # Privileges fields property(outname="privilegelist" name="$!win!Privileges!PrivilegeList" format="jsonf") } # Template for basic field extraction (for comparison) template(name="basicfmt" type="list") { property(name="$!win!Event!EventID") constant(value=",") property(name="$!win!Event!Channel") constant(value=",") property(name="$!win!Event!EventType") constant(value=",") property(name="$!win!Event!CategoryText") constant(value=",") property(name="$!win!Event!Computer") constant(value=",") property(name="$!win!Event!Provider") constant(value="\n") } ruleset(name="winsec") { action(type="mmsnareparse") action(type="omfile" file="'$RSYSLOG_OUT_LOG'.json" template="jsonfmt") action(type="omfile" file="'$RSYSLOG_OUT_LOG'.basic" template="basicfmt") } input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="winsec") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port # Use dynamic test data from sample files echo "Using Windows 2022 sample data..." tcpflood -m 1 -I ${srcdir}/testsuites/mmsnareparse/sample-windows2022-security.data echo "Using Windows 2025 sample data..." tcpflood -m 1 -I ${srcdir}/testsuites/mmsnareparse/sample-windows2025-security.data echo "Using sample events with detailed field information..." tcpflood -m 1 -I ${srcdir}/testsuites/mmsnareparse/sample-events.data shutdown_when_empty wait_shutdown # Validate basic fields are extracted correctly from Windows 2022 data content_check '4624,Security,Success Audit,Logon,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4634,Security,Success Audit,Logoff,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4647,Security,Success Audit,Logoff,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4648,Security,Success Audit,Logon,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4672,Security,Success Audit,Special Logon,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4688,Security,Success Audit,Process Creation,WIN-5SB1I3G0V7U,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic # Validate basic fields are extracted correctly from Windows 2025 data content_check '4624,Security,Success Audit,Audit Policy Change,WIN-IKCCUTRJI52,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4647,Security,Success Audit,Audit Policy Change,WIN-IKCCUTRJI52,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4648,Security,Success Audit,Audit Policy Change,WIN-IKCCUTRJI52,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4672,Security,Success Audit,Audit Policy Change,WIN-IKCCUTRJI52,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic content_check '4688,Security,Success Audit,Audit Policy Change,WIN-IKCCUTRJI52,Microsoft-Windows-Security-Auditing' $RSYSLOG_OUT_LOG.basic # Validate that both Windows versions are properly parsed content_check 'WIN-5SB1I3G0V7U' $RSYSLOG_OUT_LOG.json content_check 'WIN-IKCCUTRJI52' $RSYSLOG_OUT_LOG.json # Validate structured JSON extraction from Windows 2022 data # Check for complete records with specific field combinations that actually exist content_check '"eventid":"4624"' $RSYSLOG_OUT_LOG.json content_check '"categorytext":"Logon"' $RSYSLOG_OUT_LOG.json content_check '"computer":"DC25-PREVIEW"' $RSYSLOG_OUT_LOG.json content_check '"subjectaccountname":"WIN-IKCCUTRJI52$"' $RSYSLOG_OUT_LOG.json content_check '"logontype":"5"' $RSYSLOG_OUT_LOG.json content_check '"logontypename":"Service"' $RSYSLOG_OUT_LOG.json content_check '"processname":"C:\\Windows\\System32\\services.exe"' $RSYSLOG_OUT_LOG.json content_check '"newlogonaccountname":"SYSTEM"' $RSYSLOG_OUT_LOG.json content_check '"newlogonaccountdomain":"NT AUTHORITY"' $RSYSLOG_OUT_LOG.json content_check '"logonprocess":"Advapi"' $RSYSLOG_OUT_LOG.json content_check '"authenticationpackage":"Negotiate"' $RSYSLOG_OUT_LOG.json # Placeholder tokens such as "-" should now be dropped entirely by the parser. # The JSON template still emits empty strings when a property is missing, so we # assert that hyphen placeholders never surface in the flattened output. check_not_present '"restrictedadminmode":"-"' "$RSYSLOG_OUT_LOG.json" check_not_present '"networkaccountname":"-"' "$RSYSLOG_OUT_LOG.json" check_not_present '"sourcenetworkaddress":"-"' "$RSYSLOG_OUT_LOG.json" check_not_present '"sourceport":"-"' "$RSYSLOG_OUT_LOG.json" check_not_present '"transitedservices":"-"' "$RSYSLOG_OUT_LOG.json" check_not_present '"packagename":"-"' "$RSYSLOG_OUT_LOG.json" # Validate structured JSON extraction from Windows 2025 data content_check '"categorytext":"Audit Policy Change"' $RSYSLOG_OUT_LOG.json content_check '"computer":"WIN-IKCCUTRJI52"' $RSYSLOG_OUT_LOG.json content_check '"subjectaccountname":"WIN-IKCCUTRJI52$"' $RSYSLOG_OUT_LOG.json content_check '"subjectaccountdomain":"WORKGROUP"' $RSYSLOG_OUT_LOG.json # Validate privileges extraction for 4672 events content_check '"privilegelist":"SeAssignPrimaryTokenPrivilege' $RSYSLOG_OUT_LOG.json # Validate that DWM-1 account is extracted correctly for virtual accounts content_check '"newlogonaccountname":"DWM-1"' $RSYSLOG_OUT_LOG.json content_check '"newlogonaccountdomain":"Window Manager"' $RSYSLOG_OUT_LOG.json # Validate that Administrator account is extracted correctly content_check '"subjectaccountname":"Administrator"' $RSYSLOG_OUT_LOG.json content_check '"subjectaccountdomain":"WIN-5SB1I3G0V7U"' $RSYSLOG_OUT_LOG.json # Validate various logon types are present content_check '"virtualaccount":"No"' $RSYSLOG_OUT_LOG.json content_check '"elevatedtoken":"Yes"' $RSYSLOG_OUT_LOG.json # Validate different event types have appropriate fields content_check '"eventid":"4634"' $RSYSLOG_OUT_LOG.json content_check '"eventid":"4647"' $RSYSLOG_OUT_LOG.json content_check '"eventid":"4648"' $RSYSLOG_OUT_LOG.json content_check '"eventid":"4672"' $RSYSLOG_OUT_LOG.json content_check '"eventid":"4688"' $RSYSLOG_OUT_LOG.json exit_test rsyslog-8.2608.0/tests/PaxHeaders/stop_when_array_has_element.sh0000644000000000000000000000013215241075234022010 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.798581908 30 ctime=1787067807.220964056 rsyslog-8.2608.0/tests/stop_when_array_has_element.sh0000775000175000017500000000203715241075234021461 0ustar00rgerrger#!/bin/bash # added 2015-05-22 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[stop_when_array_has_element.sh\]: loop detecting presence of an element and stopping ruleset execution . ${srcdir:=.}/diag.sh init stop_when_array_has_element.sh generate_conf add_conf ' template(name="foo" type="string" string="%$!foo%\n") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmjsonparse") foreach ($.quux in $!foo) do { if ($.quux == "xyz0") then stop } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="foo") ' startup tcpflood -m 1 -I $srcdir/testsuites/stop_when_array_has_elem_input echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check '"abc0"' content_check '"abc2"' assert_content_missing 'xyz0' exit_test rsyslog-8.2608.0/tests/PaxHeaders/empty-ruleset.sh0000644000000000000000000000013215241075234017057 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.392911358 rsyslog-8.2608.0/tests/empty-ruleset.sh0000775000175000017500000000206715241075234016533 0ustar00rgerrger#!/bin/bash # Copyright 2014-11-20 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init custom_wait_file_lines() { wait_file_lines "$RSYSLOG_OUT_LOG" 10000 } export QUEUE_EMPTY_CHECK_FUNC=custom_wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="real") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2" ruleset="empty") $template outfmt,"%msg:F,58:2%\n" ruleset(name="empty") { } ruleset(name="real") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup assign_tcpflood_port2 "${RSYSLOG_DYNNAME}.tcpflood_port2" tcpflood -p$TCPFLOOD_PORT2 -m5000 -i0 # these should NOT show up tcpflood -p$TCPFLOOD_PORT -m10000 -i5000 tcpflood -p$TCPFLOOD_PORT2 -m500 -i15000 # these should NOT show up shutdown_when_empty wait_shutdown seq_check 5000 14999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmrfc3164-drop.sh0000644000000000000000000000013215241075234016627 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067804.346910501 rsyslog-8.2608.0/tests/pmrfc3164-drop.sh0000775000175000017500000000164015241075234016277 0ustar00rgerrger#!/bin/bash # added 2025-07-18 by Codex, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="input") parser(name="p3164" type="pmrfc3164" detect.headerless="on" headerless.errorfile="'$RSYSLOG_OUT_LOG'.err" headerless.drop="on") ruleset(name="input" parser="p3164") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -p $TCPFLOOD_PORT -m1 -M "\"this is not syslog\"" tcpflood -p $TCPFLOOD_PORT -m1 -M "\"<13>Oct 11 22:14:15 host tag: normal\"" shutdown_when_empty wait_shutdown ! grep -q 'this is not syslog' $RSYSLOG_OUT_LOG grep -q 'normal' $RSYSLOG_OUT_LOG || { cat $RSYSLOG_OUT_LOG; error_exit 1; } grep -q 'this is not syslog' ${RSYSLOG_OUT_LOG}.err || { cat ${RSYSLOG_OUT_LOG}.err; error_exit 1; } exit_test rsyslog-8.2608.0/tests/PaxHeaders/proprepltest-rfctag-udp.sh0000644000000000000000000000013215241075234021035 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.789581739 30 ctime=1787067803.664897792 rsyslog-8.2608.0/tests/proprepltest-rfctag-udp.sh0000775000175000017500000000271715241075234020513 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 # Verify UDP RFC-tag truncation to 32 characters via property replacer. # The imudp listener owns an OS-assigned port before tcpflood sends, preventing # parallel UDP tests from sharing a preselected port; the ordered truncated tag # output is the pass/fail oracle. . ${srcdir:=.}/diag.sh init generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imudp.port" add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_RCVR_FILE'") template(name="outfmt" type="string" string="+%syslogtag:1:32%+\n") :pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup assign_tcpflood_port "$PORT_RCVR_FILE" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\"" tcpflood -m1 -T "udp" -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\"" shutdown_when_empty wait_shutdown echo '+TAG:+ +0+ +01234567890123456789012345678901+ +01234567890123456789012345678901+' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_backticks-vg.sh0000644000000000000000000000013115132733117020355 xustar0030 mtime=1768666703.966621132 30 atime=1782715518.913790965 29 ctime=1787067805.15992565 rsyslog-8.2608.0/tests/rscript_backticks-vg.sh0000777000175000017500000000056215132733117020032 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if `echo $DO_WORK` == "on" and $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' export DO_WORK=on startup_vg injectmsg 0 1000 shutdown_when_empty wait_shutdown_vg seq_check 0 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafile-mmnormalize-property.sh0000644000000000000000000000013215241075234023516 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.783581627 30 ctime=1787067804.190907593 rsyslog-8.2608.0/tests/omfile-dynafile-mmnormalize-property.sh0000775000175000017500000000324615241075234023172 0ustar00rgerrger#!/usr/bin/env bash # Regression reproducer for issue #3488: mmnormalize populates a JSON property # used by an omfile dynafile template. The old crash happened while resolving # that property during action processing. The oracle is clean shutdown and the # expected dynafile write; any SIGSEGV or failed template lookup fails the test. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin mmnormalize generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="writeData") template(name="LogFormat" type="string" string="%msg%\n") template(name="WriteFile" type="string" string="'$RSYSLOG_DYNNAME'.%$!clientIP%.log") ruleset(name="writeData" queue.type="fixedArray" queue.size="10000" queue.dequeueBatchSize="2048" queue.workerThreads="2" queue.workerThreadMinimumMessages="10000") { action(type="mmnormalize" rule="rule=:<%pri:number%>%clientIP:ipv4% %other:rest%" userawmsg="on") if $parsesuccess == "OK" then { action(type="omfile" DynaFile="WriteFile" template="LogFormat") } } ' startup tcpflood -m1 -O -M "\"<13>192.0.2.15 - - \\\"GET / HTTP/1.1\\\" 200 17 \\\"-\\\" \\\"-\\\" \\\"-\\\"\"" shutdown_when_empty wait_shutdown printf ' - "GET / HTTP/1.1" 200 17 "-" "-" "-"\n' > "${RSYSLOG_DYNNAME}.expected" cmp_exact_file "${RSYSLOG_DYNNAME}.expected" "${RSYSLOG_DYNNAME}.192.0.2.15.log" || { echo "FAIL: dynafile write did not use the normalized clientIP property" cat "${RSYSLOG_DYNNAME}.192.0.2.15.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-empty-dir.sh0000644000000000000000000000013215241075234022120 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.737899152 rsyslog-8.2608.0/tests/segmented-diskqueue-empty-dir.sh0000775000175000017500000000141215241075234021565 0ustar00rgerrger#!/bin/bash # An existing empty segmented queue directory has no backlog to reconstruct. # The oracle is successful startup and clean shutdown: missing state is fatal # only when queue files exist, while this case must create fresh state. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" mkdir -p "$SPOOL_DIR/mainq.segq" generate_conf add_conf ' global(workDirectory="'$SPOOL_DIR'") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.saveOnShutdown="on") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then action(type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-cri-basic.sh0000644000000000000000000000013215241075234020567 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067808.164981647 rsyslog-8.2608.0/tests/imkubernetes-cri-basic.sh0000775000175000017500000000731615241075234020245 0ustar00rgerrger#!/bin/bash # Verify CRI parsing, CRI partial-message merge, and Kubernetes API enrichment. # The helper API server binds an OS-assigned port and writes it to a readiness # file; the parsed/enriched JSON output is the success oracle. The timeout is # only a fail-safe around the helper because readiness is file-based. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes check_command_available timeout export NUMMESSAGES=2 pwd=$( pwd ) testsrv=imk8s-test-server k8s_srv_port=0 k8s_srv_port_file=${RSYSLOG_DYNNAME}${testsrv}.port logdir="${RSYSLOG_DYNNAME}.spool/pods/namespace-name1_pod-name1_uid1/container-a" logfile="${logdir}/0.log" mkdir -p "$logdir" echo starting kubernetes test server MMK8S_INCLUDE_NODE_NAME=1 timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py \ 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ $k8s_srv_port_file \ > ${RSYSLOG_DYNNAME}.spool/imkubernetes_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started assign_file_content k8s_srv_port "$k8s_srv_port_file" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" KubernetesUrl="http://localhost:'$k8s_srv_port'" Token="dummy" cacheEntryTtl="60") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="namespace" name="$!kubernetes!namespace_name" format="jsonf") property(outname="pod" name="$!kubernetes!pod_name" format="jsonf") property(outname="pod_uid" name="$!kubernetes!pod_uid" format="jsonf") property(outname="container" name="$!kubernetes!container_name" format="jsonf") property(outname="restart_count" name="$!kubernetes!restart_count" format="jsonf" dataType="number") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="pod_id" name="$!kubernetes!pod_id" format="jsonf") property(outname="pod_ip" name="$!kubernetes!pod_ip" format="jsonf") property(outname="host" name="$!kubernetes!host" format="jsonf") property(outname="label_component" name="$!kubernetes!labels!component" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup { printf '%s\n' '2026-04-20T10:00:00.123456789Z stdout F hello from cri' printf '%s \n' '2026-04-20T10:00:01.000000000Z stderr P partial one' printf '%s\n' '2026-04-20T10:00:02.000000000Z stderr F partial two' } > "$logfile" wait_file_lines "$RSYSLOG_OUT_LOG" 2 wait_queueempty shutdown_when_empty wait_shutdown kill $BGPROCESS wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "cri"] assert len(records) == 2, records by_msg = {item["msg"]: item for item in records} cri = by_msg["hello from cri"] assert cri["namespace"] == "namespace-name1" assert cri["pod"] == "pod-name1" assert cri["pod_uid"] == "uid1" assert cri["container"] == "container-a" assert cri["restart_count"] == 0 assert cri["stream"] == "stdout" assert cri["format"] == "cri" assert cri["pod_id"] == "pod-name1-id" assert cri["pod_ip"] == "10.128.0.14" assert cri["host"] == "pod-name1-node" assert cri["label_component"] == "pod-name1-component" partial = by_msg["partial one partial two"] assert partial["stream"] == "stderr" assert partial["format"] == "cri" assert partial["pod_id"] == "pod-name1-id" PY exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-error.sh0000644000000000000000000000013115171370365016335 xustar0030 mtime=1776677109.473913572 30 atime=1782715518.912790948 29 ctime=1787067805.37992975 rsyslog-8.2608.0/tests/yaml-error.sh0000775000175000017500000000162515171370365016011 0ustar00rgerrger#!/bin/bash # Tests that an invalid YAML config file produces a clean error message and # that rsyslog exits with a non-zero status (does not crash or hang). # # Added 2025 by contributors, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}_bad'.yaml" optional="off") ' # Write deliberately malformed YAML cat > "${RSYSLOG_DYNNAME}_bad.yaml" << 'BADEOF' global: workdirectory: "/tmp" modules: - load: [unclosed array param: value BADEOF # Use config-check mode (-N1) which exits non-zero on any config error ../tools/rsyslogd -C -N1 \ -M"${RSYSLOG_MODDIR}" \ -f"${TESTCONF_NM}.conf" \ > "${RSYSLOG_DYNNAME}.error.log" 2>&1 rc=$? if [ $rc -eq 0 ]; then echo "FAIL: rsyslogd should have reported a config error for invalid YAML" error_exit 1 fi echo "PASS: rsyslogd correctly reported error (exit $rc) for invalid YAML" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omsendertrack-basic-vg.sh0000644000000000000000000000013115171370365020576 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.914790982 30 ctime=1787067805.098924514 rsyslog-8.2608.0/tests/omsendertrack-basic-vg.sh0000775000175000017500000000017615171370365020252 0ustar00rgerrger#!/bin/bash set -x pwd ls -l omsender*sh echo srcdir: $srcdir export USE_VALGRIND="YES" . ${srcdir:-.}/omsendertrack-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/sparse_array_lookup_table.sh0000644000000000000000000000013115145046113021467 xustar0029 mtime=1771326539.06301468 30 atime=1782715518.913790965 30 ctime=1787067804.975922222 rsyslog-8.2608.0/tests/sparse_array_lookup_table.sh0000775000175000017500000000473215145046113021145 0ustar00rgerrger#!/bin/bash # test for sparse-array lookup-table and HUP based reloading of it # added 2015-10-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate_array.lkp_tbl") template(name="outfmt" type="string" string="%msg% %$.lkp%\n") set $.num = field($msg, 58, 2); set $.lkp = lookup("xlate", $.num); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate_sparse_array.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl startup injectmsg 0 1 wait_queueempty assert_content_missing "foo" injectmsg 0 5 wait_queueempty content_check "msgnum:00000001: foo_old" content_check "msgnum:00000002: foo_old" content_check "msgnum:00000003: bar_old" content_check "msgnum:00000004: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_sparse_array_more.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 6 wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: foo_new" content_check "msgnum:00000002: bar_new" content_check "msgnum:00000003: bar_new" content_check "msgnum:00000004: baz" content_check "msgnum:00000005: baz" cp -f $srcdir/testsuites/xlate_sparse_array_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate_array.lkp_tbl issue_HUP await_lookup_table_reload injectmsg 0 15 injectmsg 2147483647 3 injectmsg 2999999999 3 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "msgnum:00000000: quux" content_check "msgnum:00000001: quux" content_check "msgnum:00000002: foo_latest" content_check "msgnum:00000003: baz_latest" content_check "msgnum:00000004: foo_latest" content_check "msgnum:00000005: foo_latest" content_check "msgnum:00000006: foo_latest" content_check "msgnum:00000007: foo_latest" content_check "msgnum:00000008: baz_latest" content_check "msgnum:00000009: baz_latest" content_check "msgnum:00000010: baz_latest" content_check "msgnum:00000011: baz_latest" content_check "msgnum:00000012: foo_latest" content_check "msgnum:00000013: foo_latest" content_check "msgnum:00000014: foo_latest" content_check "msgnum:2147483647: foo_latest" content_check "msgnum:2147483648: gte_int_max" content_check "msgnum:2147483649: gte_int_max" content_check "msgnum:2999999999: gte_int_max" content_check "msgnum:3000000000: gte_3B" content_check "msgnum:3000000001: gte_3B" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-lb-1target-retry-1_byte_buf-TargetFail.sh0000644000000000000000000000013215216464436024524 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.913790965 30 ctime=1787067804.132906513 rsyslog-8.2608.0/tests/omfwd-lb-1target-retry-1_byte_buf-TargetFail.sh0000775000175000017500000000223715216464436024177 0ustar00rgerrger#!/bin/bash # This wrapper retries the shared target-failure skeleton once more when TCP # timing races trigger the known omfwd load-balancer flake. The second attempt # keeps the same forced receiver-close scenario and bounded-loss oracle; it # only avoids failing the suite on one unlucky reconnect timing window. export srcdir="${srcdir:=.}" export OMFWD_IOBUF_SIZE=1000 # triggers edge cases skeleton="$srcdir/omfwd-lb-1target-retry-test_skeleton-TargetFail.sh" max_attempts=2 attempt=1 result=1 while [ "$attempt" -le "$max_attempts" ]; do if [ "$attempt" -gt 1 ]; then echo "Retrying omfwd 1-byte target-failure test (attempt $attempt of $max_attempts) to mitigate TCP buffer timing races." fi if [ "$attempt" -lt "$max_attempts" ]; then TESTBENCH_SUPPRESS_FAIL_MARKER=YES bash "$skeleton" else bash "$skeleton" fi result=$? if [ "$result" -eq 0 ]; then if [ "$attempt" -gt 1 ]; then echo "omfwd 1-byte target-failure test passed on retry." fi exit 0 fi attempt=$((attempt + 1)) done echo "omfwd 1-byte target-failure test failed after $max_attempts attempts." exit "$result" rsyslog-8.2608.0/tests/PaxHeaders/queue-direct-with-no-params.sh0000644000000000000000000000013215035412264021477 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.912790948 30 ctime=1787067804.369910929 rsyslog-8.2608.0/tests/queue-direct-with-no-params.sh0000777000175000017500000000045115035412264021150 0ustar00rgerrger#!/bin/bash # added 2019-11-14 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown check_not_present "queue is in direct mode, but parameters have been set" exit_test rsyslog-8.2608.0/tests/PaxHeaders/impstats-overwrite.sh0000644000000000000000000000013215145046113020125 xustar0030 mtime=1771326539.040014305 30 atime=1782715518.913790965 30 ctime=1787067806.671953826 rsyslog-8.2608.0/tests/impstats-overwrite.sh0000775000175000017500000000154115145046113017575 0ustar00rgerrger#!/bin/bash # test if log.file.overwrite works for impstats # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" log.file=`echo $RSYSLOG_OUT_LOG` log.file.overwrite="on" interval="1") ' startup # Wait for at least two emissions ./msleep 2500 shutdown_when_empty wait_shutdown # Check how many times "resource-usage" appears in the log file. # It should appear exactly once if overwrite is working correctly. NUM_EMISSIONS=$(grep -c "resource-usage" $RSYSLOG_OUT_LOG) cat -n $RSYSLOG_OUT_LOG echo "Number of resource-usage entries found: $NUM_EMISSIONS" if [ "$NUM_EMISSIONS" -ne 1 ]; then echo "FAIL: expected 1 emission in log file, but found $NUM_EMISSIONS" exit 1 fi echo "SUCCESS: log.file.overwrite worked as expected" exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse_invld_regex.sh0000644000000000000000000000013215241075234022132 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.787581702 30 ctime=1787067805.029923228 rsyslog-8.2608.0/tests/parsertest-parse_invld_regex.sh0000775000175000017500000000177315241075234021611 0ustar00rgerrger#!/bin/bash # add 2018-06-28 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<175>Feb 08 2008 23:47:31 hostname tag This is a message\"" shutdown_when_empty wait_shutdown echo '"2008-02-08T23:47:31", "hostname", "tag", **NO MATCH** **BAD REGULAR EXPRESSION**, "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/include-obj-outside-control-flow-vg.sh0000644000000000000000000000013215035412264023141 xustar0030 mtime=1752569012.397771593 30 atime=1782715518.912790948 30 ctime=1787067805.145925389 rsyslog-8.2608.0/tests/include-obj-outside-control-flow-vg.sh0000777000175000017500000000104515035412264022612 0ustar00rgerrger#!/bin/bash # added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") if not ($msg contains "msgnum:") then { stop } # Note: the point of this test is to have this include outside of # a control flow construct -- this the "strange" if above.' add_conf " include(file=\"${srcdir}/testsuites/include-std-omfile-actio*.conf\") " startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg seq_check 0 9 exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse-nodate.sh0000644000000000000000000000013215241075234021014 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 30 ctime=1787067805.039923414 rsyslog-8.2608.0/tests/parsertest-parse-nodate.sh0000775000175000017500000000222715241075234020466 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<27>xapi: [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message)\"" tcpflood -m1 -M "\"This is a message!\"" shutdown_when_empty wait_shutdown export EXPECTED="27,daemon,err,$RS_HOSTNAME,xapi,xapi:, [error|xen3|15|Guest liveness monitor D:bca30ab3f1c1|master_connection] Connection to master died. I will continue to retry indefinitely (suppressing future logging of this message) 13,user,notice,This,is,is, a message!" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/cfg3.cfgtest0000644000000000000000000000013215131231047016101 xustar0030 mtime=1768239655.700212516 30 atime=1782715518.914790982 30 ctime=1787067808.401986063 rsyslog-8.2608.0/tests/cfg3.cfgtest0000666000175000017500000000072515131231047015553 0ustar00rgerrgerrsyslogd: error accessing config file or directory 'file-does-not-exist': No such file or directory [try https://www.rsyslog.com/e/2040 ] rsyslogd: the last error occurred in ./cfg3.testin, line 1 rsyslogd: CONFIG ERROR: there are no active actions configured. Inputs will run, but no output whatsoever is created. [try https://www.rsyslog.com/e/2103 ] rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file! rsyslogd: End of config validation run. Bye. rsyslog-8.2608.0/tests/PaxHeaders/linux_localtime_r.supp0000644000000000000000000000013215035412264020325 xustar0030 mtime=1752569012.398764645 30 atime=1782715518.914790982 30 ctime=1787067808.618990107 rsyslog-8.2608.0/tests/linux_localtime_r.supp0000666000175000017500000000436515035412264020003 0ustar00rgerrger{ linux-localtime_r-apparently-modifies-TZ Helgrind:Race ... fun:__tz_convert fun:timeval2syslogTime ... } { linux-localtime_r-apparently-modifies-TZ Helgrind:Race fun:strlen fun:__tzset_parse_tz fun:__tzfile_compute fun:__tz_convert ... } { linux-localtime_r-apparently-modifies-TZ Helgrind:Race ... fun:__tzstring fun:__tzfile_compute fun:__tz_convert ... } { linux-localtime_r-apparently-modifies-TZ-2 Helgrind:Race fun:__GI_strcmp fun:__tzfile_compute fun:__tz_convert ... } { CENTOS_6_only_report Helgrind:Misc fun:pthread_cond_destroy_WRK fun:pthread_cond_destroy@* fun:modExit fun:modUnlinkAndDestroy fun:Release fun:ReleaseObj fun:modExit ... } { CENTOS_6_only_report Helgrind:Misc fun:pthread_cond_destroy_WRK fun:pthread_cond_destroy@* fun:qqueueDestruct fun:actionDestruct fun:cnfstmtDestruct fun:cnfstmtDestructLst fun:cnfstmtDestruct fun:cnfstmtDestructLst fun:rulesetDestruct fun:rulesetDestructForLinkedList fun:llDestroyElt fun:llDestroy } { CENTOS_6_only_report Helgrind:Misc fun:pthread_cond_destroy_WRK fun:pthread_cond_destroy@* fun:modExit fun:modUnlinkAndDestroy fun:modUnloadAndDestructAll fun:main } { CENTOS_7_github_rsyslog_issue_2012 Helgrind:Race fun:GetLocalHostIP fun:logmsgInternalSubmit fun:logmsgInternal fun:doLogMsg.constprop.0 fun:LogMsg fun:wtpAdviseMaxWorkers fun:qqueueAdviseMaxWorkers fun:qqueueMultiEnqObjNonDirect fun:multiSubmitMsg2 fun:ratelimitAddMsg fun:enqLine fun:pollFileReal fun:pollFile fun:doPolling fun:runInput fun:thrdStarter } { CENTOS_7_github_rsyslog_issue_2012 Helgrind:Race fun:AddRef fun:MsgSetRcvFromIP fun:logmsgInternalSubmit fun:logmsgInternal fun:doLogMsg.constprop.0 fun:LogMsg fun:wtpAdviseMaxWorkers fun:qqueueAdviseMaxWorkers fun:qqueueMultiEnqObjNonDirect fun:multiSubmitMsg2 fun:ratelimitAddMsg fun:enqLine fun:pollFileReal fun:pollFile fun:doPolling fun:runInput } { CENTOS_7_github_rsyslog_issue_2012 Helgrind:Race fun:thrdDestruct fun:llDestroyElt fun:llDestroy fun:thrdTerminateAll fun:deinitAll fun:main } rsyslog-8.2608.0/tests/PaxHeaders/pmrfc3164-defaultTag.sh0000644000000000000000000000013215241075234017743 xustar0030 mtime=1787067036.636578875 30 atime=1787067036.788581721 30 ctime=1787067804.342910426 rsyslog-8.2608.0/tests/pmrfc3164-defaultTag.sh0000775000175000017500000000207015241075234017411 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="customparser") parser(name="custom.rfc3164" type="pmrfc3164" permit.AtSignsInHostname="off" force.tagEndingByColon="on") template(name="outfmt" type="string" string="?%hostname%?%syslogtag%?%msg%?\n") ruleset(name="customparser" parser="custom.rfc3164") { :hostname, contains, "Hostname" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname1 msgnum:1\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname2 msgnum:2\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname3 tag msgnum:3\"" tcpflood -m1 -M "\"<129>Mar 10 01:00:00 Hostname4 tag: msg\"" shutdown_when_empty wait_shutdown export EXPECTED='?Hostname1?-? msgnum:1? ?Hostname2?-? msgnum:2? ?Hostname3?-? tag msgnum:3? ?Hostname4?tag:? msg?' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-parameter-errors.sh0000644000000000000000000000013215241075234021343 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.695579979 30 ctime=1787067803.707898593 rsyslog-8.2608.0/tests/template-parameter-errors.sh0000775000175000017500000000456615241075234021025 0ustar00rgerrger#!/bin/bash # Exercise malformed legacy property-replacer parameters one configuration at # a time. Each case must make rsyslogd -N1 fail under abortOnUncleanConfig and # emit its specific parser diagnostic; separate invocations prove that an # earlier rejected template cannot hide later cases. # The long decimal literals deliberately overflow parser integers; they are # configuration data, not fixed network ports. . ${srcdir:=.}/diag.sh init run_invalid_parameter() { local name="$1" local parameter="$2" local expected="$3" local cfg="${RSYSLOG_DYNNAME}.${name}.conf" local log="${RSYSLOG_DYNNAME}.${name}.log" cat >"$cfg" <"$log" 2>&1; then error_exit 1 "config check unexpectedly succeeded for $name" fi content_check "$expected" "$log" } while IFS='|' read -r name parameter expected; do run_invalid_parameter "$name" "$parameter" "$expected" done <<'CASES' invalid_option|%msg:::bogus-option%|template error: invalid field option 'bogus-option' specified - ignored conflict_csv|%msg:::json,csv%|one option out of (json, jsonf, jsonr, jsonfr, csv) - csv ignored conflict_json|%msg:::csv,json%|one option out of (json, jsonf, jsonr, jsonfr, csv) - json ignored conflict_jsonf|%msg:::csv,jsonf%|one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonf ignored conflict_jsonr|%msg:::csv,jsonr%|one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonr ignored conflict_jsonfr|%msg:::csv,jsonfr%|one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonfr ignored delimiter_nondigit|%msg:F,x:2%|invalid character in frompos after "F," delimiter_overflow|%msg:F,999999999999999999999999:2%|delimiter value in template is too large delimiter_nonascii|%msg:F,256:2%|non-USASCII delimiter character value 256 delimiter_tail|%msg:F,44x:2%|invalid character 'x' in frompos after "F," invalid_after_f|%msg:Fx:2%|invalid character in frompos after "F" frompos_overflow|%msg:999999999999999999999999:2%|frompos value in template is too large field_number_overflow|%msg:F,44:999999999999999999999999%|field number in template is too large field_topos_overflow|%msg:F,44:2,999999999999999999999999%|topos value in template is too large topos_overflow|%msg:1:999999999999999999999999%|topos value in template is too large CASES exit_test rsyslog-8.2608.0/tests/PaxHeaders/omazuredce-bad-template.sh0000644000000000000000000000013215171370365020740 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.913790965 30 ctime=1787067806.295946819 rsyslog-8.2608.0/tests/omazuredce-bad-template.sh0000775000175000017500000000242615171370365020413 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . ${srcdir:=.}/omazuredce-env.sh require_plugin "omazuredce" omazuredce_require_env export NUMMESSAGES=1 generate_conf add_conf ' global(processInternalMessages="on" internalmsg.severity="info") module(load="../plugins/omazuredce/.libs/omazuredce") template(name="tplAzureDceBroken" type="string" string="{\"message\":\"%msg:::json%\"} trailing-garbage") local4.* action( type="omazuredce" template="tplAzureDceBroken" client_id="'$AZURE_DCE_CLIENT_ID'" client_secret=`echo $AZURE_DCE_CLIENT_SECRET` tenant_id="'$AZURE_DCE_TENANT_ID'" dce_url="'$AZURE_DCE_URL'" dcr_id="'$AZURE_DCE_DCR_ID'" table_name="'$AZURE_DCE_TABLE_NAME'" max_batch_bytes="1048576" flush_timeout_ms="0" action.resumeInterval="1" action.resumeRetryCount="1" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown content_check "omazuredce: message template must render a JSON object" post_count=$(grep -c -F "omazuredce: posted batch records=" < "$RSYSLOG_OUT_LOG") if [ "${post_count:=0}" -ne 0 ]; then echo "FAIL: malformed template unexpectedly produced a successful batch post" cat -n "$RSYSLOG_OUT_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imgssapi-maxsessions.sh0000644000000000000000000000013215171370365020433 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.913790965 30 ctime=1787067803.897902134 rsyslog-8.2608.0/tests/imgssapi-maxsessions.sh0000775000175000017500000000422715171370365020107 0ustar00rgerrger#!/bin/bash # Verify that imgssapi forwards its configured max session count to tcpsrv. . ${srcdir:=.}/diag.sh init require_plugin imgssapi skip_platform "FreeBSD" "This test currently does not work on FreeBSD" export NUMMESSAGES=500 MAXSESSIONS=10 CONNECTIONS=20 EXPECTED_DROPS=$((CONNECTIONS - MAXSESSIONS)) # This test only needs to prove that the configured cap is enforced at all. # Under slower or coverage-instrumented builds, accepted sessions may churn # while tcpflood is still opening later sockets, so the exact drop count is # not stable. MIN_EXPECTED_DROPS=1 EXPECTED_STR='too many tcp sessions - dropping incoming request' STARTED_LOG="${RSYSLOG_DYNNAME}.started" count_dropped_sessions() { if [ -f "$STARTED_LOG" ]; then grep -F -c -- "$EXPECTED_STR" "$STARTED_LOG" || true else printf '0\n' fi } wait_for_drop_logs() { wait_tries=${1:-15} wait_i=1 while [ "$wait_i" -le "$wait_tries" ]; do count=$(count_dropped_sessions) if [ "$count" -ge "$MIN_EXPECTED_DROPS" ] && [ "$count" -le "$EXPECTED_DROPS" ]; then return 0 fi $TESTTOOL_DIR/msleep 1000 wait_i=$((wait_i + 1)) done return 1 } generate_conf add_conf ' $MaxMessageSize 10k module(load="../plugins/imgssapi/.libs/imgssapi") $InputGSSServerPermitPlainTCP on $InputGSSServerTokenIOTimeout 10 $InputGSSListenPortFileName '$RSYSLOG_DYNNAME'.gss_port $InputGSSServerMaxSessions '$MAXSESSIONS' $InputGSSServerRun 0 action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup assign_file_content GSS_PORT "$RSYSLOG_DYNNAME.gss_port" export TCPFLOOD_PORT="$GSS_PORT" tcpflood -c"$CONNECTIONS" -m"$NUMMESSAGES" -r -d100 -P129 -A # Wait briefly for rsyslog's own session-drop diagnostics to land, but do not # hold shutdown open on an exact drop count. That makes the test hang on slow # coverage runners even when the main queue is already empty. wait_for_drop_logs 15 || true shutdown_when_empty wait_shutdown count=$(count_dropped_sessions) if [ "$count" -lt "$MIN_EXPECTED_DROPS" ] || [ "$count" -gt "$EXPECTED_DROPS" ]; then echo "FAIL: expected between $MIN_EXPECTED_DROPS and $EXPECTED_DROPS dropped sessions, got $count" echo "STARTED_LOG contents:" cat "$STARTED_LOG" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_certvalid_expired.sh0000644000000000000000000000013115241075234022175 xustar0030 mtime=1787067036.644579024 29 atime=1787067036.79658187 30 ctime=1787067807.317965864 rsyslog-8.2608.0/tests/sndrcv_tls_certvalid_expired.sh0000775000175000017500000000410215241075234021642 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init printf 'using TLS driver: %s\n' ${RS_TLS_DRIVER:=gtls} # start up the instances # export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-key.pem'" defaultNetstreamDriver="'$RS_TLS_DRIVER'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="'$RS_TLS_DRIVER'" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" StreamDriver.PermitExpiredCerts="off" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup export PORT_RCVR=$TCPFLOOD_PORT export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/testsuites/x.509/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/testsuites/x.509/client-expired-cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/testsuites/x.509/client-expired-key.pem'" defaultNetstreamDriver="'$RS_TLS_DRIVER'" ) # set up the action $ActionSendStreamDriverMode 1 # require TLS for the connection $ActionSendStreamDriverAuthMode anon *.* @@127.0.0.1:'$PORT_RCVR' ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown content_check --regex "not permitted to talk to peer '.*', certificate invalid: certificate expired" exit_test rsyslog-8.2608.0/tests/PaxHeaders/ratelimit-policy-persource-key-reload.sh0000644000000000000000000000013215241075234023566 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.691579904 30 ctime=1787067805.632934464 rsyslog-8.2608.0/tests/ratelimit-policy-persource-key-reload.sh0000775000175000017500000000440215241075234023235 0ustar00rgerrger#!/bin/bash ## HUP reload must atomically replace the per-source key policy while input ## workers are active. The oracle first observes one allowance for each of two ## hostname keys, then reloads to fromhost-ip and observes one shared allowance ## for two new hostnames arriving from the same TCP peer address. . ${srcdir:=.}/diag.sh init export PORT_RCVR_FILE="${RSYSLOG_DYNNAME}.tcp_port" POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" export POLICY_FILE INPUT_FILE="$(pwd)/${RSYSLOG_DYNNAME}.input" export INPUT_FILE write_policy() { local key_template="$1" cat > "$POLICY_FILE" < "$INPUT_FILE" for i in $(seq 1 "$count"); do echo "<13>Jan 1 00:00:00 $host app: msgnum:$host:$i" >> "$INPUT_FILE" done tcpflood -p"$PORT_RCVR" -I "$INPUT_FILE" } write_policy "PerSourceHostname" generate_conf add_conf ' template(name="PerSourceHostname" type="string" string="%hostname%") template(name="PerSourceAddress" type="string" string="%fromhost-ip%") ratelimit(name="key_reload" policy="'$POLICY_FILE'") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_RCVR_FILE'" ratelimit.name="key_reload") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "msgnum:" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" send_host_messages alpha 2 send_host_messages beta 2 wait_file_lines "$RSYSLOG_OUT_LOG" 2 100 write_policy "PerSourceAddress" issue_HUP send_host_messages gamma 2 send_host_messages delta 2 wait_queueempty shutdown_when_empty wait_shutdown content_count=$(grep -c "msgnum:" "$RSYSLOG_OUT_LOG" || true) if [ "$content_count" -ne 3 ]; then echo "FAIL: expected two hostname allowances and one shared address allowance, got $content_count" cat "$RSYSLOG_OUT_LOG" error_exit 1 fi content_check "msgnum:alpha:1" "$RSYSLOG_OUT_LOG" content_check "msgnum:beta:1" "$RSYSLOG_OUT_LOG" content_check "msgnum:gamma:1" "$RSYSLOG_OUT_LOG" check_not_present "msgnum:delta:" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-ruleset-fallback.sh0000644000000000000000000000013215241075234023426 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 30 ctime=1787067803.720898835 rsyslog-8.2608.0/tests/segmented-diskqueue-ruleset-fallback.sh0000775000175000017500000000427415241075234023104 0ustar00rgerrger#!/bin/bash # Persist events that entered through a named ruleset, then restart without # that ruleset. Complete sequence recovery proves that a configuration rename # falls back to the current default ruleset instead of classifying otherwise # valid serialized events as corrupt. Duplicates are allowed because the first # daemon is killed with an in-flight batch before its commit frontier advances. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" write_conf() { generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") module(load="../plugins/imtcp/.libs/imtcp") global(workDirectory="'"$SPOOL_DIR"'") main_queue( queue.type="segmentedDisk" queue.filename="mainq" queue.maxFileSize="4k" queue.workerThreads="1" queue.dequeueBatchSize="1" queue.saveOnShutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") '"$1"' ' } write_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'"$RSYSLOG_DYNNAME"'.tcpflood_port" ruleset="retired") ruleset(name="retired") { :msg, contains, "msgnum:" :omtesting:sleep 10 0 } ' startup tcpflood -p"$TCPFLOOD_PORT" -m"$NUMMESSAGES" # The sleeping single-record batch keeps one event in flight. Seeing the other # 99 in the queue proves that imtcp handed the complete input to the durable # store before the deliberate SIGKILL; tcpflood completion alone only proves # delivery to the kernel socket buffer. for _ in {1..100}; do queued=$(get_mainqueuesize | awk '{print $NF}') if ((queued >= NUMMESSAGES - 1)); then break fi "$TESTTOOL_DIR/msleep" 100 done if ((queued < NUMMESSAGES - 1)); then echo "FAIL: only $queued of $((NUMMESSAGES - 1)) queued messages became durable" error_exit 1 fi shutdown_immediate . "$srcdir/diag.sh" kill-immediate wait_shutdown write_conf ' if ($msg contains "msgnum:") then action(type="omfile" file="'"$RSYSLOG_OUT_LOG"'" template="outfmt") ' export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check_dupes wait_seq_check_dupes() { wait_seq_check 0 $((NUMMESSAGES - 1)) -d } startup shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -d rm -rf "$SPOOL_DIR" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-jsonarray-vg.sh0000644000000000000000000000013115171370365021256 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.912790948 30 ctime=1787067806.183944732 rsyslog-8.2608.0/tests/omhttp-batch-jsonarray-vg.sh0000775000175000017500000000011715171370365020725 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:=.}/omhttp-batch-jsonarray.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-endregex.sh0000644000000000000000000000013215131231047017276 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.914790982 30 ctime=1787067807.906976839 rsyslog-8.2608.0/tests/imfile-endregex.sh0000777000175000017500000000434215131231047016752 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # This test mimics the test imfile-readmode2.sh, but works via # endmsg.regex. It's kind of a base test for the regex functionality. echo ====================================================================== echo [imfile-endregex.sh] . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" startmsg.regex="^[^ ]") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing sleep 1 # write some more lines (see https://github.com/rsyslog/rsyslog/issues/144) echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo 'msgnum:5' >> $RSYSLOG_DYNNAME.input # this one shouldn't be written to the output file because of ReadMode 2 # give it time to finish sleep 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! # give it time to write the output file sleep 1 ## check if we have the correct number of messages NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" cat $RSYSLOG_OUT_LOG exit 1 else if [ ! $NUMLINES -eq 3 ]; then echo "ERROR: expecting 3 headers, got $NUMLINES" cat $RSYSLOG_OUT_LOG exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {1..4}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" cat $RSYSLOG_OUT_LOG exit 1 fi done ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-datafail-continues-batch.sh0000644000000000000000000000013215241075234022402 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067806.119943539 rsyslog-8.2608.0/tests/omhttp-datafail-continues-batch.sh0000775000175000017500000000323115241075234022050 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Regression test for rsyslog/rsyslog#4348 in omhttp batch mode. A permanent # HTTP 400 rejects the whole HTTP request payload; for a multi-message batch, # that means all events in that batch are failed together. The mock server # rejects the batch containing message 00000002. The neighboring message in # that failed HTTP payload can vary with transaction boundaries, so the oracle # checks the stable behavior: message 2 is absent, later batches are still sent, # and messages known to be outside the rejected payload are not duplicated. # shellcheck disable=SC2034,SC2154 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 omhttp_start_server 0 --fail-msgnum-400 00000002 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") main_queue(queue.dequeueBatchSize="10") if $msg contains "msgnum:" then action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.format="jsonarray" batch.maxsize="2" usehttps="off" ) ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint jsonarray omhttp_stop_server content_count_check "00000000" 1 check_not_present "00000002" content_count_check "00000004" 1 content_count_check "00000005" 1 content_count_check "00000006" 1 content_count_check "00000007" 1 content_count_check "00000008" 1 content_count_check "00000009" 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-read-only.sh0000644000000000000000000000013215216464436017413 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.915790999 30 ctime=1787067804.203907836 rsyslog-8.2608.0/tests/omfile-read-only.sh0000775000175000017500000000335015216464436017063 0ustar00rgerrger#!/bin/bash # addd 2016-06-16 by RGerhards, released under ASL 2.0 # Verifies that omfile suspends a read-only primary file action and then uses # the fallback action. The oracle requires the current user and filesystem to # reject appends to a 0400 file; if the platform still permits that write, the # test environment cannot exercise the intended failure path and is skipped. . ${srcdir:=.}/diag.sh init skip_ASAN "omfile read-only suspend behavior differs under ASan" messages=20000 # how many messages to inject? # Note: we need to inject a somewhat larger number of messages in order # to ensure that we receive some messages in the actual output file, # as batching can (validly) cause a larger loss in the non-writable # file generate_conf add_conf ' template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { action(type="omfile" template="outfmt" file="'$RSYSLOG2_OUT_LOG'") action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'" action.execOnlyWhenPreviousIsSuspended="on" ) } ' touch ${RSYSLOG2_OUT_LOG} chmod 0400 ${RSYSLOG2_OUT_LOG} if (: >> "${RSYSLOG2_OUT_LOG}") 2>/dev/null; then echo "SKIP: environment can append to a 0400 file; read-only omfile failure path is not testable" skip_test fi ls -l rsyslog.ou* startup injectmsg 0 $messages shutdown_when_empty wait_shutdown # we know that the output file is missing some messages, but it # MUST have some more, and these be in sequence. So we now read # the first message number and calculate based on it what must be # present in the output file. presort firstnum=$((10#$($RS_HEADCMD -n1 $RSYSLOG_DYNNAME.presort))) echo "info: first message expected to be number $firstnum, using that value." seq_check $firstnum $((messages-1)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/timegenerated-utc-legacy.sh0000644000000000000000000000013115241075234021107 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.800581945 29 ctime=1787067805.85593862 rsyslog-8.2608.0/tests/timegenerated-utc-legacy.sh0000775000175000017500000000217315241075234020562 0ustar00rgerrger#!/bin/bash # added 2016-03-22 by RGerhards, released under ASL 2.0 # # NOTE: faketime does NOT properly support subseconds, # so we must ensure we do not use them. Actually, what we # see is uninitialized data value in tv_usec, which goes # away as soon as we do not run under faketime control. # FOR THE SAME REASON, there is NO VALGRIND EQUIVALENT # of this test, as valgrind would abort with reports # of faketime. # # IMPORTANT: we use legacy style for the template to ensure # that subseconds works properly for this as well. This is # a frequent use case. # . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST+02:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%timegenerated:::date-utc%\n" :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' echo "***SUBTEST: check 2016-03-01" FAKETIME='2016-03-01 12:00:00' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED="Mar 1 14:00:00" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmsnareparse-trailing-extradata-regex-anchor.sh0000644000000000000000000000013215216464436025107 xustar0030 mtime=1782212894.075266976 30 atime=1782715518.915790999 30 ctime=1787067805.088924328 rsyslog-8.2608.0/tests/mmsnareparse-trailing-extradata-regex-anchor.sh0000775000175000017500000000351115216464436024556 0ustar00rgerrger#!/bin/bash # Validate that mmsnareparse regex trailing extra-data detection does not let # the search-window boundary act as the end of the trailing token. The oracle is # that an end-anchored pattern must not match only the bounded prefix of a longer # non-matching token, so the final token remains parsed data and no # extradata_section is emitted for it. unset RSYSLOG_DYNNAME . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmsnareparse/.libs/mmsnareparse") template(name="outfmt" type="list") { property(name="$!win!Event!EventID") constant(value=",") property(name="$!win!Event!Channel") constant(value=",") property(name="$!win!EventData!User") constant(value=",") property(name="$!extradata_section") constant(value="\n") } action(type="mmsnareparse" definition.file="../plugins/mmsnareparse/sysmon_definitions.json" ignoreTrailingPattern.regex="^[0-9]+$" ignoreTrailingPattern.searchWindow="3") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup cat <<'MSG' > ${RSYSLOG_DYNNAME}.input <14>Mar 22 08:47:23 testhost MSWinEventLog 1 Microsoft-Windows-Sysmon/Operational 20977 Mon Mar 22 08:47:23 2025 13 Windows SYSTEM User SetValue testhost Registry value set (rule: RegistryEvent) Registry value set: RuleName: Default RegistryEvent EventType: SetValue UtcTime: 2025-03-22 08:47:23.284 ProcessGuid: {fd4d0da6-d589-6916-eb03-000000000000} ProcessId: 4 Image: System TargetObject: HKLM\System\CurrentControlSet\Services\TestService\ImagePath Details: "C:\Program Files\TestAgent\TestService.exe" User: NT AUTHORITY\SYSTEM 123abc MSG injectmsg_file ${RSYSLOG_DYNNAME}.input shutdown_when_empty wait_shutdown content_check --regex '^13,Microsoft-Windows-Sysmon/Operational,NT AUTHORITY\\SYSTEM 123abc,$' "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropgroup.sh0000644000000000000000000000013215131231047017154 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.914790982 30 ctime=1787067804.237908469 rsyslog-8.2608.0/tests/privdropgroup.sh0000777000175000017500000000147115131231047016630 0ustar00rgerrger#!/bin/bash # addd 2016-03-24 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' global(privdrop.group.keepsupplemental="on") template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) $PrivDropToGroup '${TESTBENCH_TESTUSER[groupname]}' ' startup shutdown_when_empty wait_shutdown content_check --regex "groupid.*${TESTBENCH_TESTUSER[gid]}" if [ ! $? -eq 0 ]; then echo "message indicating drop to group \"${TESTBENCH_TESTUSER[groupname]}\" (#${TESTBENCH_TESTUSER[gid]}) is missing:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl_setenv.sh0000644000000000000000000000013215035412264016543 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.915790999 30 ctime=1787067804.097905861 rsyslog-8.2608.0/tests/glbl_setenv.sh0000777000175000017500000000131515035412264016214 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(environment="http_proxy=http://127.0.0.1") set $!prx = getenv("http_proxy"); template(name="outfmt" type="string" string="%$!prx%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! echo 'http://127.0.0.1' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid content seen, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-queue-lpop-vg.sh0000644000000000000000000000013215171370365020726 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.914790982 30 ctime=1787067806.568951906 rsyslog-8.2608.0/tests/imhiredis-queue-lpop-vg.sh0000775000175000017500000000030015171370365020366 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-queue-lpop.sh rsyslog-8.2608.0/tests/PaxHeaders/rscript_gt.sh0000644000000000000000000000013215241075234016420 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067804.813919203 rsyslog-8.2608.0/tests/rscript_gt.sh0000775000175000017500000000131315241075234016065 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_gt.sh\]: testing rainerscript GT statement . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); if $!usr!msgnum > "00004999" then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 8000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 5000 7999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/action-tx-single-processing.sh0000644000000000000000000000013215132411300021562 xustar0030 mtime=1768559296.281885878 30 atime=1782715518.914790982 30 ctime=1787067805.924939906 rsyslog-8.2608.0/tests/action-tx-single-processing.sh0000777000175000017500000000240215132411300021231 0ustar00rgerrger#!/bin/bash # part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_TSAN # for some reason, this test is extremely slow under tsan, causing timeout fail export NUMMESSAGES=2000 export SEQ_CHECK_OPTIONS=-i2 check_sql_data_ready() { mysql_get_data seq_check --check-only 0 $((NUMMESSAGES - 2)) } export QUEUE_EMPTY_CHECK_FUNC=check_sql_data_ready generate_conf add_conf ' module(load="../plugins/ommysql/.libs/ommysql") global(errormessagestostderr.maxnumber="50") template(type="string" name="tpl" string="insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)" option.sql="on") template(type="string" name="tpl2" string="%$.num%|%$!facility%|insert into SystemEvents (Message, Facility) values (\"%msg%\", %$!facility%)\n" option.sql="on") if($msg contains "msgnum:") then { set $.num = field($msg, 58, 2); if $.num % 2 == 0 then { set $!facility = $syslogfacility; } else { set $/cntr = 0; } action(type="ommysql" name="mysql_action" server="127.0.0.1" template="tpl" db="'$RSYSLOG_DYNNAME'" uid="rsyslog" pwd="testbench") } action(type="omfile" file="'$RSYSLOG2_OUT_LOG'") ' mysql_prep_for_test startup injectmsg shutdown_when_empty wait_shutdown mysql_get_data seq_check 0 $((NUMMESSAGES - 2)) exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-imtcp-stream-always-zstd-secure-defaults.sh0000644000000000000000000000013215241075234025156 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067805.601933887 rsyslog-8.2608.0/tests/yaml-imtcp-stream-always-zstd-secure-defaults.sh0000775000175000017500000001126515241075234024632 0ustar00rgerrger#!/bin/bash # added 2026-07-20 by Codex, released under ASL 2.0 # Provides YAML parity for the aggregate zstd window limit and secure-default # policy. Configuration-validation status and diagnostics are the oracle. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin lmzstdw ../runtime modpath="${RSYSLOG_MODDIR}" run_expect_success() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -ne 0 ]; then echo "FAIL: expected ${cfg} to validate" cat "${log}" error_exit 1 fi } run_expect_failure() { local cfg="$1" local log="$2" ../tools/rsyslogd -C -N1 -M"${modpath}" -f"${cfg}" >"${log}" 2>&1 local rc=$? if [ $rc -eq 0 ]; then echo "FAIL: expected ${cfg} to fail validation" cat "${log}" error_exit 1 fi } write_input_config() { local cfg="$1" local policy="$2" local mode="$3" local driver="$4" local limit="$5" cat >"${cfg}" <"${RSYSLOG_DYNNAME}.yaml-strict-module-inherit.yaml" <<'YAML_EOF' version: 2 global: compatibility.defaults.secure: "strict" modules: - load: "../plugins/imtcp/.libs/imtcp" compression.mode: "stream:always" compression.driver: "zstd" compression.maxTotalZstdWindowBytes: "2097152" inputs: - type: imtcp port: "0" ruleset: sink rulesets: - name: sink statements: - type: omfile file: "/dev/null" YAML_EOF run_expect_success "${RSYSLOG_DYNNAME}.yaml-strict-module-inherit.yaml" \ "${RSYSLOG_DYNNAME}.yaml-strict-module-inherit.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/contains-longer-needle.sh0000644000000000000000000000013215171370365020601 xustar0030 mtime=1776677109.458913341 30 atime=1782715518.915790999 30 ctime=1787067804.062905208 rsyslog-8.2608.0/tests/contains-longer-needle.sh0000775000175000017500000000124115171370365020246 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init UNEXPECTED_LOG="${RSYSLOG_DYNNAME}.unexpected.log" generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") if $msg contains "this-needle-is-clearly-longer-than-the-message-under-test" then { action(type="omfile" template="outfmt" file="'$UNEXPECTED_LOG'") } if $syslogtag == "app" then { action(type="omfile" template="outfmt" file="'${RSYSLOG_OUT_LOG}'") } ' startup injectmsg_literal '<165>1 2003-03-01T01:00:00.000Z host app - - - short' shutdown_when_empty wait_shutdown export EXPECTED="short" cmp_exact if test -e "$UNEXPECTED_LOG"; then test ! -s "$UNEXPECTED_LOG" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-basic-ignorecodes.sh0000644000000000000000000000013215216464436021141 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.914790982 30 ctime=1787067806.115943465 rsyslog-8.2608.0/tests/omhttp-basic-ignorecodes.sh0000775000175000017500000000215415216464436020612 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Verify that omhttp treats configured HTTP status codes as ignorable. The test # server fails requests after the first half of the message stream; success is # that only the accepted first half remains and the ignored failures do not # break shutdown or sequence validation. # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 omhttp_start_server 0 --fail-with-401-or-403-after 5000 port="$omhttp_server_lstnport" generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../contrib/omhttp/.libs/omhttp") if $msg contains "msgnum:" then action( # Payload name="my_http_action" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$port'" restpath="my/endpoint" batch="off" httpignorablecodes=["401", "NA", "403"] # Auth usehttps="off" ) ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $port my/endpoint omhttp_stop_server seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/no-parser-errmsg.sh0000644000000000000000000000013215241075234017443 xustar0030 mtime=1787067036.631578781 30 atime=1787067036.782581608 30 ctime=1787067804.378911097 rsyslog-8.2608.0/tests/no-parser-errmsg.sh0000775000175000017500000000157715241075234017124 0ustar00rgerrger#!/bin/bash # add 2017-03-06 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset") template(name="test" type="string" string="tag: %syslogtag%, pri: %pri%, syslogfacility: %syslogfacility%, syslogseverity: %syslogseverity% msg: %msg%\n") ruleset(name="ruleset" parser="rsyslog.rfc5424") { action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG` template="test") } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -m1 shutdown_when_empty wait_shutdown grep 'one message could not be processed by any parser' $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omtcl.sh0000644000000000000000000000013215132733117015356 xustar0030 mtime=1768666703.965621117 30 atime=1782715518.914790982 30 ctime=1787067808.131981032 rsyslog-8.2608.0/tests/omtcl.sh0000777000175000017500000000132215132733117015025 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../contrib/omtcl/.libs/omtcl $template tcldict, "message \"%msg:::json%\" fromhost \"%HOSTNAME:::json%\" facility \"%syslogfacility-text%\" priority \"%syslogpriority-text%\" timereported \"%timereported:::date-rfc3339%\" timegenerated \"%timegenerated:::date-rfc3339%\" raw \"%rawmsg:::json%\" tag \"%syslogtag:::json%\"" ' add_conf "*.* :omtcl:$srcdir/omtcl.tcl,doAction;tcldict " startup echo 'injectmsg literal <167>Mar 1 01:00:00 192.0.2.8 tag hello world' | \ ./diagtalker -p$IMDIAG_PORT || error_exit $? echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check 'HELLO WORLD' cat $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_backticks_static_text.sh0000644000000000000000000000013215132733117022357 xustar0030 mtime=1768666703.966621132 30 atime=1782715518.914790982 30 ctime=1787067805.165925762 rsyslog-8.2608.0/tests/rscript_backticks_static_text.sh0000777000175000017500000000106715132733117022034 0ustar00rgerrger#!/bin/bash ## Validate that backticks with `echo` expand environment variables even ## when punctuation is directly attached to the name. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" field.delimiter="58" field.number="2") constant(value="\n") } if `echo Prefix-$MYVAR!` == "Prefix-42!" and $msg contains "msgnum" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' export MYVAR=42 startup injectmsg 0 1 shutdown_when_empty wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_processing_test2.sh0000644000000000000000000000013215241075234022147 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067805.865938806 rsyslog-8.2608.0/tests/mmnormalize_processing_test2.sh0000775000175000017500000000652215241075234021623 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST+02:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n") template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n") template(name="t_fromhost-ip" type="string" string="%fromhost-ip%") template(name="t_analytics_msg_default" type="string" string="%$!v_analytics_prefix%%rawmsg-after-pri%") template(name="t_analytics_tag_prefix" type="string" string="%$!v_tag%: ") template(name="t_analytics_msg_normalized" type="string" string="%timereported% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%") template(name="t_analytics_msg_normalized_vc" type="string" string="%timereported:1:6% %$year% %timereported:8:$% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%") template(name="t_analytics" type="string" string="[][][%$!v_fromhost-ip%][%timestamp:::date-unixtimestamp%][] %$!v_analytics_msg%\n") ruleset(name="ruleset1") { action(type="mmnormalize" rulebase="'$srcdir/testsuites/mmnormalize_processing_tests.rulebase'" useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_record") action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_path") set $!v_forward="PCI"; if ($!v_forward contains "PCI") then { if ($!v_fromhost-ip == "") then { set $!v_fromhost-ip=exec_template("t_fromhost-ip"); } if ($!v_msg == "" or $!v_tag == "") then { set $!v_analytics_msg=exec_template("t_analytics_msg_default"); } else { if ($!v_analytics_prefix == "") then { set $!v_analytics_prefix=exec_template("t_analytics_tag_prefix"); } if ($!v_hostname == "") then { # needed for vCenter logs with custom hostname set $!v_hostname=exec_template("t_fromhost-ip"); } if ($!v_exception == "VC") then { set $!v_analytics_msg=exec_template("t_analytics_msg_normalized_vc"); } else { set $!v_analytics_msg=exec_template("t_analytics_msg_normalized"); } } action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_analytics") } } ' FAKETIME='2017-03-08 12:18:47' startup tcpflood -m1 -M "\"<166>2017-03-08T12:18:47.165Z Host2.domain.com Process1: [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback\"" shutdown_when_empty wait_shutdown echo '2017-03-08T12:18:47.165Z 2017-03-08T12:18:47.165Z Host2.domain.com Process1 [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback /sb/logs/incoming/2017/03/08/svc_SER2/ret_Y01/os_ESX/127.0.0.1/r_relay1/esx.gz [][][127.0.0.1][1488975527][] Mar 8 12:18:47 127.0.0.1 Process1: [FFB87B70 verbose Process1HalCnxHostagent opID=WFU-abfbbece] [WaitForUpdatesDone] Completed callback' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-stream-dynack-vg.sh0000644000000000000000000000013115171370365021401 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.915790999 29 ctime=1787067806.66195364 rsyslog-8.2608.0/tests/omhiredis-stream-dynack-vg.sh0000775000175000017500000000030315171370365021045 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-stream-dynack.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-escapelf.replacement.sh0000644000000000000000000000013215035412264021562 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.916791016 30 ctime=1787067807.932977324 rsyslog-8.2608.0/tests/imfile-escapelf.replacement.sh0000777000175000017500000000154515035412264021240 0ustar00rgerrger#!/bin/bash # Written in 2019 by Rainer Gerhards # This is part of the rsyslog testbench, licensed under ASL 2.0 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" ruleset="output" escapelf.replacement="[LF]" File="./'$RSYSLOG_DYNNAME'.input" tag="file:" startmsg.regex="^msg") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="output") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' # make sure file exists when rsyslog starts up echo 'msg 1 part 1 msg 1 part 2 msg 2 msg INVISIBLE by design' > $RSYSLOG_DYNNAME.input startup export NUMMESSAGES=2 shutdown_when_empty wait_shutdown export EXPECTED='msg 1 part 1[LF] msg 1 part 2 msg 2' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-compress.sh0000644000000000000000000000013215216464436022020 xustar0030 mtime=1782212894.057266685 30 atime=1782715518.915790999 30 ctime=1787067806.395948682 rsyslog-8.2608.0/tests/imhttp-post-payload-compress.sh0000775000175000017500000000242415216464436021471 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify this imhttp POST-payload variant while the HTTP listener uses an # OS-assigned port. The HTTP status and configured output checks are the oracle. #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUG="debug" . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") #input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" disablelfdelimiter="on") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" NUMMESSAGES=50 for (( i=1; i<=NUMMESSAGES; i++ )) do echo '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' | gzip | curl -si --data-binary @- -H "Content-Encoding: gzip" http://localhost:$IMHTTP_PORT/postrequest done wait_queueempty shutdown_when_empty echo "file name: $RSYSLOG_OUT_LOG" content_count_check '[{"foo":"bar","bar":"foo"},{"one":"two","three":"four"}]' $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/daqueue-persist-drvr.sh0000644000000000000000000000013215241075234020333 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.763581253 30 ctime=1787067808.221982709 rsyslog-8.2608.0/tests/daqueue-persist-drvr.sh0000775000175000017500000000326715241075234020012 0ustar00rgerrger#!/bin/bash # Test for queue data persisting at shutdown. The # plan is to start an instance, emit some data, do a relatively # fast shutdown and then re-start the engine to process the # remaining data. # added 2009-05-27 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 # uncomment for debugging support: . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 1 $MainMsgQueueSaveOnShutdown on input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $ModLoad ../plugins/omtesting/.libs/omtesting # set spool locations and switch queue to disk-only mode $WorkDirectory '$RSYSLOG_DYNNAME'.spool $MainMsgQueueFilename mainq $IncludeConfig '${RSYSLOG_DYNNAME}'work-queuemode.conf $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt $IncludeConfig '${RSYSLOG_DYNNAME}'work-delay.conf ' #export RSYSLOG_DEBUG="debug nologfuncflow nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" # prepare config echo \$MainMsgQueueType $1 > ${RSYSLOG_DYNNAME}work-queuemode.conf echo "*.* :omtesting:sleep 0 1000" > ${RSYSLOG_DYNNAME}work-delay.conf # inject 10000 msgs, so that DO hit the high watermark startup injectmsg 0 10000 shutdown_immediate wait_shutdown check_mainq_spool echo "Enter phase 2, rsyslogd restart" # restart engine and have rest processed #remove delay echo "#" > ${RSYSLOG_DYNNAME}work-delay.conf startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 9999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-long-msg.sh0000644000000000000000000000013115035412264017247 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.915790999 30 ctime=1787067807.691972833 rsyslog-8.2608.0/tests/imrelp-long-msg.sh0000777000175000017500000000113615035412264016722 0ustar00rgerrger#!/bin/bash # adddd 2018-04-16 by PascalWithopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(maxMessageSize="214800") module(load="../plugins/imrelp/.libs/imrelp") input(type="imrelp" port="'$TCPFLOOD_PORT'" maxdatasize="214800") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup tcpflood -Trelp-plain -p'$TCPFLOOD_PORT' -m2 -d 204800 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/timereported-utc-legacy.sh0000644000000000000000000000013215131231047020770 xustar0030 mtime=1768239655.725212925 30 atime=1782715518.915790999 30 ctime=1787067805.860938713 rsyslog-8.2608.0/tests/timereported-utc-legacy.sh0000777000175000017500000000146015131231047020442 0ustar00rgerrger#!/bin/bash # addd 2016-03-22 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%timereported:::date-rfc3339,date-utc%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' echo "*** SUBTEST 2003 ****" startup injectmsg_literal "<165>1 2003-08-24T05:14:15.000003-07:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000" injectmsg_literal "<165>1 2016-03-01T12:00:00-02:00 192.0.2.1 tcpflood 8710 - - msgnum:0000000" injectmsg_literal "<165>1 2016-03-01T12:00:00Z 192.0.2.1 tcpflood 8710 - - msgnum:0000000" shutdown_when_empty wait_shutdown export EXPECTED="2003-08-24T12:14:15.000003+00:00 2016-03-01T14:00:00.000000+00:00 2016-03-01T12:00:00.000000+00:00" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/stop.sh0000644000000000000000000000013115241075234015224 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.798581908 29 ctime=1787067804.69891706 rsyslog-8.2608.0/tests/stop.sh0000775000175000017500000000142115241075234014672 0ustar00rgerrger#!/bin/bash # Test for "stop" statement # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[stop.sh\]: testing stop statement . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if $msg contains "00000001" then stop template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup sleep 1 tcpflood -m10 -i1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 2 10 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafile-traversal-root-base.sh0000644000000000000000000000013115241075234023175 xustar0030 mtime=1787067036.631578781 29 atime=1787067036.68757983 30 ctime=1787067805.556933048 rsyslog-8.2608.0/tests/omfile-dynafile-traversal-root-base.sh0000775000175000017500000000266615241075234022657 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Ensure a dynafile template rooted at / retains / as its containment base. # The template's first directory is message-derived; a unique /tmp output # proves the root base accepts absolute children rather than using the fallback # guard, which rejects every absolute rendered path. . ${srcdir:=.}/diag.sh init require_plugin imtcp export ROOT_APP="${RSYSLOG_DYNNAME}-omfile-root-base" export ROOT_OUT="/tmp/${ROOT_APP}.log" rm -f "$ROOT_OUT" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="dynfile" type="string" string="/%HOSTNAME%/%APP-NAME%.log") template(name="outfmt" type="string" string="%msg%\n") $rulesetparser rsyslog.rfc5424 local4.debug action(type="omfile" dynafile="dynfile" template="outfmt") ' startup printf '<167>1 2003-03-01T01:00:00.000Z tmp %s - - - root-base-output\n' "$ROOT_APP" \ > "${RSYSLOG_DYNNAME}.input" tcpflood -B -I "${RSYSLOG_DYNNAME}.input" shutdown_when_empty wait_shutdown if [ ! -f "$ROOT_OUT" ]; then echo "FAIL: dynafile template rooted at / did not create: $ROOT_OUT" error_exit 1 fi if ! grep -Fqx 'root-base-output' "$ROOT_OUT"; then echo "FAIL: dynafile template rooted at / wrote unexpected content" cat "$ROOT_OUT" rm -f "$ROOT_OUT" error_exit 1 fi rm -f "$ROOT_OUT" exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse_invld_regex-udp.sh0000644000000000000000000000013215035412264022717 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.915790999 30 ctime=1787067805.032923284 rsyslog-8.2608.0/tests/parsertest-parse_invld_regex-udp.sh0000777000175000017500000000171115035412264022370 0ustar00rgerrger#!/bin/bash # add 2018-06-28 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") template(name="outfmt" type="string" string="%timereported:1:19:date-rfc3339,csv%, %hostname:::csv%, %programname:::csv%, %syslogtag:R,ERE,0,BLANK:[0-9+--end:csv%, %syslogseverity:::csv%, %msg:::drop-last-lf,csv%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<175>Feb 08 2008 23:47:31 hostname tag This is a message\"" shutdown_when_empty wait_shutdown echo '"2008-02-08T23:47:31", "hostname", "tag", **NO MATCH** **BAD REGULAR EXPRESSION**, "7", " This is a message"' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-persource-ratelimit.sh0000644000000000000000000000013215241075234021351 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067805.623934297 rsyslog-8.2608.0/tests/imtcp-persource-ratelimit.sh0000775000175000017500000000372615241075234021030 0ustar00rgerrger#!/bin/bash ## Test per-source ratelimiting for imtcp using the canonical ratelimit ## policy YAML. The oracle is that the shared ratelimit API drops the noisy ## sender while allowing the override sender through; imtcp itself does not ## compute or pass a per-source key. . ${srcdir:=.}/diag.sh init POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.persource.yaml" export POLICY_FILE INPUT_FILE="$(pwd)/${RSYSLOG_DYNNAME}.input" export INPUT_FILE cat > "$POLICY_FILE" < "$INPUT_FILE" for i in $(seq 1 20); do echo "<13>Jan 1 00:00:00 noisyhost app: msgnum:$i" >> "$INPUT_FILE" done for i in $(seq 1 5); do echo "<13>Jan 1 00:00:00 quiethost app: msgnum:$i" >> "$INPUT_FILE" done tcpflood -p"$tcp_port" -I "$INPUT_FILE" shutdown_when_empty wait_shutdown noisy_count=$(grep -c "host=noisyhost" "$RSYSLOG_OUT_LOG") quiet_count=$(grep -c "host=quiethost" "$RSYSLOG_OUT_LOG") echo "noisy_count: $noisy_count" echo "quiet_count: $quiet_count" if [ "$quiet_count" -ne 5 ]; then echo "FAIL: expected 5 quiethost messages, got $quiet_count" error_exit 1 fi if [ "$noisy_count" -ge 20 ]; then echo "FAIL: per-source ratelimit did not drop noisyhost messages" error_exit 1 fi if [ "$noisy_count" -le 0 ]; then echo "FAIL: per-source ratelimit dropped all noisyhost messages" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafile-traversal-list-template.sh0000644000000000000000000000013115241075234024066 xustar0030 mtime=1787067036.631578781 29 atime=1787067036.68757983 30 ctime=1787067805.549932918 rsyslog-8.2608.0/tests/omfile-dynafile-traversal-list-template.sh0000775000175000017500000000416515241075234023544 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Check dynafile traversal when the dynafile template is a list template. A # valid sibling message must be written once, proving the input was processed # rather than simply dropped before the dynafile action. . ${srcdir:=.}/diag.sh init require_plugin imtcp export TRAVERSAL_APP="${RSYSLOG_DYNNAME}-omfile-list-template-traversal" export VALID_APP="${RSYSLOG_DYNNAME}-omfile-list-template-valid" export TRAVERSAL_ROOT="${RSYSLOG_DYNNAME}.jail" export TRAVERSAL_OUT="${TRAVERSAL_ROOT}/escape/${TRAVERSAL_APP}.log" export VALID_OUT="${TRAVERSAL_ROOT}/base/goodhost/${VALID_APP}.log" rm -rf "$TRAVERSAL_ROOT" mkdir -p "${TRAVERSAL_ROOT}/base" "${TRAVERSAL_ROOT}/escape" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="dynfile" type="list") { constant(value="'$TRAVERSAL_ROOT'/base/") property(name="hostname") constant(value="/") property(name="app-name") constant(value=".log") } template(name="outfmt" type="string" string="%msg%\n") $rulesetparser rsyslog.rfc5424 local4.debug action(type="omfile" dynafile="dynfile" template="outfmt") ' startup { printf '<167>1 2003-03-01T01:00:00.000Z ../escape %s - - - traversal-list-template\n' \ "$TRAVERSAL_APP" printf '<167>1 2003-03-01T01:00:00.000Z goodhost %s - - - valid-after-blocked-traversal\n' \ "$VALID_APP" } > "${RSYSLOG_DYNNAME}.input" tcpflood -B -I "${RSYSLOG_DYNNAME}.input" shutdown_when_empty wait_shutdown if [ -f "$TRAVERSAL_OUT" ]; then echo "FAIL: list dynafile traversal created output outside template base: $TRAVERSAL_OUT" rm -rf "$TRAVERSAL_ROOT" error_exit 1 fi if [ ! -f "$VALID_OUT" ]; then echo "FAIL: valid list dynafile message did not create: $VALID_OUT" rm -rf "$TRAVERSAL_ROOT" error_exit 1 fi if [ "$(grep -Fc 'valid-after-blocked-traversal' "$VALID_OUT")" -ne 1 ]; then echo "FAIL: valid list dynafile record was not written exactly once" cat "$VALID_OUT" rm -rf "$TRAVERSAL_ROOT" error_exit 1 fi rm -rf "$TRAVERSAL_ROOT" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-datafail-continues.sh0000644000000000000000000000013215241075234021323 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067806.117943502 rsyslog-8.2608.0/tests/omhttp-datafail-continues.sh0000775000175000017500000000245415241075234020777 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Regression test for rsyslog/rsyslog#4348: a permanent omhttp data # failure such as HTTP 400 must drop only the rejected event and must not # leave the action in DATAFAIL state so later good events stop flowing. # The mock server rejects message 00000002 with HTTP 400 and accepts all # other payloads. The oracle is that messages after the rejected payload # still arrive, with only message 2 missing from the accepted sequence. # shellcheck disable=SC2034,SC2154 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 omhttp_start_server 0 --fail-msgnum-400 00000002 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") if $msg contains "msgnum:" then action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="off" usehttps="off" ) ' startup injectmsg 0 $NUMMESSAGES shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint omhttp_stop_server EXPECTED='00000000 00000001 00000003 00000004 00000005 00000006 00000007 00000008 00000009' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-negative-vg.sh0000644000000000000000000000012715241075234025435 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067807.541970038 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-negative-vg.sh0000775000175000017500000000014715241075234025102 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs-negative.sh rsyslog-8.2608.0/tests/PaxHeaders/omprog-close-unresponsive-noterm.sh0000644000000000000000000000013215035412264022705 xustar0030 mtime=1752569012.404722953 30 atime=1782715518.915790999 30 ctime=1787067806.056942366 rsyslog-8.2608.0/tests/omprog-close-unresponsive-noterm.sh0000777000175000017500000000311715035412264022360 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test checks that omprog does NOT send a TERM signal to the # external program when signalOnClose=off, closes the pipe, and kills # the unresponsive child if killUnresponsive=on. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") main_queue( queue.timeoutShutdown="60000" # give time to omprog to wait for the child ) :msg, contains, "msgnum:" { action( type="omprog" binary="'$RSYSLOG_DYNNAME.'omprog-close-unresponsive-bin.sh" template="outfmt" name="omprog_action" queue.type="Direct" # the default; facilitates sync with the child process confirmMessages="on" # facilitates sync with the child process signalOnClose="off" closeTimeout="1000" # ms killUnresponsive="on" # default value: the value of signalOnClose ) } ' cp -f $srcdir/testsuites/omprog-close-unresponsive-bin.sh $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh startup injectmsg 0 10 shutdown_when_empty wait_shutdown . $srcdir/diag.sh ensure-no-process-exists $RSYSLOG_DYNNAME.omprog-close-unresponsive-bin.sh export EXPECTED="Starting Received msgnum:00000000: Received msgnum:00000001: Received msgnum:00000002: Received msgnum:00000003: Received msgnum:00000004: Received msgnum:00000005: Received msgnum:00000006: Received msgnum:00000007: Received msgnum:00000008: Received msgnum:00000009: Terminating unresponsively" cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmnormalize-debug.sh0000644000000000000000000000013215241075234017661 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.690579886 30 ctime=1787067807.065961168 rsyslog-8.2608.0/tests/pmnormalize-debug.sh0000775000175000017500000000221615241075234017331 0ustar00rgerrger#!/bin/bash # Verify that pmnormalize directs enabled liblognorm tracing to its configured # file. A non-empty trace file after parsing a message is the success oracle. . ${srcdir:=.}/diag.sh init require_plugin pmnormalize DEBUG_LOG="${RSYSLOG_DYNNAME}.pmnormalize-debug.log" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/pmnormalize/.libs/pmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="normalize") parser(name="custom.pmnormalize" type="pmnormalize" debug="on" debugFile="'$DEBUG_LOG'" rule="rule=:<%pri:number%> %fromhost-ip:ipv4% %hostname:word% %syslogtag:char-to:\\x3a%: %msg:rest%") ruleset(name="normalize" parser="custom.pmnormalize") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -m1 -M "\"<189> 127.0.0.1 ubuntu tag1: this is a test message\"" shutdown_when_empty wait_shutdown if [ ! -s "$RSYSLOG_OUT_LOG" ]; then echo "expected pmnormalize to parse the test message" error_exit 1 fi if [ ! -s "$DEBUG_LOG" ]; then echo "expected liblognorm trace output in $DEBUG_LOG" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-compression-none-legacy-single.sh0000644000000000000000000000013215241075234023551 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 30 ctime=1787067806.831956807 rsyslog-8.2608.0/tests/imptcp-compression-none-legacy-single.sh0000775000175000017500000000234515241075234023224 0ustar00rgerrger#!/bin/bash # Backward compatibility test for imptcp with compression.mode="none". # omfwd's legacy "@@(zN)" mode compresses each message independently and # prefixes the compressed payload with "z"; imptcp must still allow the # built-in legacy transport-frame decompression when no stream decompression is # active. The oracle is sequence-complete delivery of legacy-compressed messages # through an imptcp receiver explicitly configured for no stream decompression. # # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="none") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' *.* @@(z5)127.0.0.1:'$RCVR_PORT' ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines "$RSYSLOG_OUT_LOG" "$NUMMESSAGES" shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp_ratelimit_name.sh0000644000000000000000000000013115171370365020631 xustar0029 mtime=1776677109.46791348 30 atime=1782715518.914790982 30 ctime=1787067804.507913501 rsyslog-8.2608.0/tests/omhttp_ratelimit_name.sh0000775000175000017500000000114215171370365020277 0ustar00rgerrger#!/bin/bash # Test named rate limits for omhttp (config-validation) # Verifies that omhttp accepts ratelimit.name without error. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ratelimit(name="omhttp_test_limit" interval="2" burst="5") module(load="../contrib/omhttp/.libs/omhttp") template(name="outfmt" type="string" string="%msg%\n") action(type="omhttp" server="localhost" serverport="19280" ratelimit.name="omhttp_test_limit" retryfailures="on" template="outfmt") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse-3164-buggyday-udp.sh0000644000000000000000000000013215035412264022535 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.913790965 30 ctime=1787067805.037923377 rsyslog-8.2608.0/tests/parsertest-parse-3164-buggyday-udp.sh0000777000175000017500000000213515035412264022207 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp:::date-rfc3164-buggyday%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<38> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\"" tcpflood -m1 -T "udp" -M "\"<38> Mar 17 19:06:53 example tag: testmessage (only date actually tested)\"" shutdown_when_empty wait_shutdown echo '38,auth,info,Mar 07 19:06:53,example,tag,tag:, testmessage (only date actually tested) 38,auth,info,Mar 17 19:06:53,example,tag,tag:, testmessage (only date actually tested)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-NUL.sh0000644000000000000000000000013215216464436016200 xustar0030 mtime=1782212894.062266766 30 atime=1782715518.913790965 30 ctime=1787067806.824956677 rsyslog-8.2608.0/tests/imptcp-NUL.sh0000775000175000017500000000127615216464436015655 0ustar00rgerrger#!/bin/bash # added 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup echo '<167>Mar 6 16:57:54 172.20.245.8 test: msgnum:0 X test message <167>Mar 6 16:57:54 172.20.245.8 Xtest: msgnum:1 test message' | tr X '\000' > "$RSYSLOG_DYNNAME.input" tcpflood -B -I "$RSYSLOG_DYNNAME.input" shutdown_when_empty wait_shutdown seq_check 0 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsonparse-find-json-conflict.sh0000644000000000000000000000013115216464436022271 xustar0029 mtime=1782212894.07426696 30 atime=1782715518.913790965 30 ctime=1787067807.156962864 rsyslog-8.2608.0/tests/mmjsonparse-find-json-conflict.sh0000775000175000017500000000220515216464436021740 0ustar00rgerrger#!/bin/bash # Regression test for mmjsonparse find-json ownership on msgAddJSON failure. # The action targets a nested JSON path whose parent is already a scalar, so # msgAddJSON rejects the insertion after consuming the parsed object. Success is # rsyslog staying alive and continuing to the following omfile action; under the # Valgrind wrapper this also proves the object is not released a second time. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmjsonparse/.libs/mmjsonparse") template(name="outfmt" type="string" string="%msg% parsesuccess=%parsesuccess% json=%$!%\n") if $msg contains "CONFLICT" then { set $!conflict = "scalar"; action(type="mmjsonparse" mode="find-json" container="$!conflict!parsed") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg_literal '<167>Jan 16 16:57:54 host.example.net TAG: CONFLICT prefix {"field":"value"}' shutdown_when_empty wait_shutdown export EXPECTED=' CONFLICT prefix {"field":"value"} parsesuccess=FAIL json={ "conflict": "scalar" }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-ca-mtls-ecdsa-sigalgs-vg.sh0000644000000000000000000000012715241075234024712 xustar0028 mtime=1787067036.6325788 29 atime=1787067036.68757983 30 ctime=1787067807.538969982 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-ca-mtls-ecdsa-sigalgs-vg.sh0000775000175000017500000000014415241075234024354 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-ca-mtls-ecdsa-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/mmjsontransform-policy-basic.sh0000644000000000000000000000013215241075234022053 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067807.236964354 rsyslog-8.2608.0/tests/mmjsontransform-policy-basic.sh0000775000175000017500000000700515241075234021524 0ustar00rgerrger#!/bin/bash # Validate mmjsontransform YAML policy rename/drop preprocessing, mode, HUP reload, # and malformed dotted-key conflict handling without leaking or double-freeing values. . ${srcdir:=.}/diag.sh init policy_file="$RSYSLOG_DYNNAME.policy.yaml" cat > "$policy_file" <<'YAML' version: 1 mode: flatten map: rename: "usr": "user.name" "ctx.old": "ctx.new" drop: - "debug" YAML generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmjsontransform/.libs/mmjsontransform") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!output%\n") local4.* { set $.ret = parse_json($msg, "\$!input"); action(type="mmjsontransform" policy="'$policy_file'" input="$!input" output="$!output") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup tcpflood -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"alice\", \"debug\": true, \"ctx\": { \"old\": 1 } }"' # Ensure mtime change is visible on filesystems with coarse timestamp granularity. sleep 2 cat > "$policy_file" <<'YAML' version: 1 mode: unflatten map: rename: "usr": "actor.name" "ctx.old": "ctx.after" YAML issue_HUP tcpflood -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"bob\", \"debug\": true, \"ctx\": { \"old\": 2 } }"' sleep 2 cat > "$policy_file" <<'YAML' version: 1 mode: sideways map: rename: "usr": "broken.name" YAML issue_HUP tcpflood -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"carol\", \"debug\": true, \"ctx\": { \"old\": 3 } }"' # Regression coverage for conflict-path ownership: policy preprocessing passes # JSON values to dotted insertion, which consumes them even when malformed keys # such as a trailing-empty dotted path conflict. The oracle is that rsyslogd # stays alive through shutdown, keeps the malformed message out of the output, # and logs the hierarchy conflict instead of double-freeing the input child. tcpflood -m1 -M '"<166>Mar 10 01:00:00 host app: { \"a.\": \"bad\" }"' shutdown_when_empty wait_shutdown if [ ! -f "$RSYSLOG_OUT_LOG" ]; then echo "FAIL: expected output file '$RSYSLOG_OUT_LOG' was not created" error_exit 1 fi python3 - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys with open(sys.argv[1], "r", encoding="utf-8") as fh: lines = [line.strip() for line in fh if line.strip()] if len(lines) != 3: print("expected 3 JSON lines, got", len(lines)) sys.exit(1) first = json.loads(lines[0]) second = json.loads(lines[1]) third = json.loads(lines[2]) expected_first = { "user.name": "alice", "ctx.new": 1, } expected_second = { "actor": {"name": "bob"}, "ctx": {"after": 2}, "debug": True, } expected_third = { "actor": {"name": "carol"}, "ctx": {"after": 3}, "debug": True, } if first != expected_first: print("unexpected first output:", first) sys.exit(1) if second != expected_second: print("unexpected second output:", second) sys.exit(1) if third != expected_third: print("unexpected third output:", third) sys.exit(1) PY if [ $? -ne 0 ]; then error_exit 1 fi if ! grep -q "failed to reload policy file" "$RSYSLOG_DYNNAME.started"; then echo "FAIL: expected reload failure to be logged for invalid policy mode" error_exit 1 fi if ! grep -q "dotted path 'a.' ends with an empty segment" "$RSYSLOG_DYNNAME.started"; then echo "FAIL: expected malformed dotted key conflict to be logged" error_exit 1 fi rm -f "$policy_file" exit_test rsyslog-8.2608.0/tests/PaxHeaders/immark.sh0000644000000000000000000000013215035412264015517 xustar0030 mtime=1752569012.394792439 30 atime=1782715518.912790948 30 ctime=1787067803.974903569 rsyslog-8.2608.0/tests/immark.sh0000777000175000017500000000103615035412264015170 0ustar00rgerrger#!/bin/bash # very basic check for immark module - nevertheless, there is not # much more to test for... # add 2019-08-20 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/immark/.libs/immark" interval="1") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup printf 'sleeping a bit so we get mark messages...\n' sleep 3 # this should be good even on slow machines - we need just one shutdown_when_empty wait_shutdown content_check "rsyslogd: -- MARK --" exit_test rsyslog-8.2608.0/tests/PaxHeaders/improg_prog_killonclose.sh0000644000000000000000000000013215216464436021172 xustar0030 mtime=1782212894.059266718 30 atime=1782715518.917791033 30 ctime=1787067806.018941657 rsyslog-8.2608.0/tests/improg_prog_killonclose.sh0000775000175000017500000000135015216464436020640 0ustar00rgerrger#!/bin/bash # add 2019-04-04 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../contrib/improg/.libs/improg") input(type="improg" tag="tag" ruleset="ruleset" binary="'${srcdir:=.}'/improg-simul.sh -e '$RSYSLOG_DYNNAME'.stderr -n 1 -g" confirmmessages="off" signalonclose="on" killunresponsive="on" ) ruleset(name="ruleset") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'") } ' startup wait_content "program data" "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "program data" if [ ! -e $RSYSLOG_DYNNAME.stderr ]; then echo $RSYSLOG_DYNNAME'.stderr missing' error_exit 1 fi export EXPECTED='SIGTERM Received' cmp_exact $RSYSLOG_DYNNAME.stderr exit_test rsyslog-8.2608.0/tests/PaxHeaders/tcpflood.c0000644000000000000000000000013215241075234015662 xustar0030 mtime=1787067036.646579062 30 atime=1787067036.798581908 30 ctime=1787067803.633897214 rsyslog-8.2608.0/tests/tcpflood.c0000664000175000017500000026725715241075234015351 0ustar00rgerrger/* Opens a large number of tcp connections and sends * messages over them. This is used for stress-testing. * * NOTE: the following part is actually the SPEC (or call it man page). * It's not random comments. So if the code behavior does not match what * is written here, it should be considered a bug. * * Params * -h hostname to use inside message * -t target address (default 127.0.0.1) * -p target port(s) (default 13514), multiple via port1:port2:port3... * -n number of target ports (all target ports must be given in -p!) * Note -c must also be set to at LEAST the number of -n! * -c number of connections (default 1), use negative number * to set a "soft limit": if tcpflood cannot open the * requested number of connections, gracefully degrade to * whatever number could be opened. This is useful in environments * where system config constraints cannot be overriden (e.g. * vservers, non-admin users, ...) * -m number of messages to send (connection is random) * -i initial message number (optional) * -P PRI to be used for generated messages (default is 167). * Specify the plain number without leading zeros * -d amount of extra data to add to message. If present, the * number itself will be added as third field, and the data * bytes as forth. Add -r to randomize the amount of extra * data included in the range 1..(value of -d). * -r randomize amount of extra data added (-d must be > 0) * -s (silent) do not show progress indicator (never done on non-tty) * -f support for testing dynafiles. If given, include a dynafile ID * in the range 0..(f-1) as the SECOND field, shifting all field values * one field to the right. Zero (default) disables this functionality. * -M the message to be sent. Disables all message format options, as * only that exact same message is sent. * -I read specified input file, do NOT generate own test data. The test * completes when eof is reached. * -B The specified file (-I) is binary. No data processing is done by * tcpflood. If multiple connections are specified, data is read in * chunks and spread across the connections without taking any record * delimiters into account. * -C when input from a file is read, this file is transmitted -C times * (C like cycle, running out of meaningful option switches ;)) * -D randomly drop and re-establish connections. Useful for stress-testing * the TCP receiver. * -F USASCII value for frame delimiter (in octet-stuffing mode), default LF * -K keep still-open plain TCP sockets open after sending. -K0 holds until * terminated, -K holds for N seconds before closing connections. * -R number of times the test shall be run (very useful for gathering performance * data and other repetitive things). Default: 1 * -S number of seconds to sleep between different runs (-R) Default: 30 * -X generate sTats data records. Default: off * -e encode output in CSV (not yet everywhere supported) * for performance data: * each inidividual line has the runtime of one test * the last line has 0 in field 1, followed by numberRuns,TotalRuntime, * Average,min,max * -T transport to use. Currently supported: "udp", "tcp" (default), "tls" (tcp+tls), relp-plain, relp-tls * Note: UDP supports a single target port, only * -H * initiate a TLS ClientHello and exit once it is sent (requires -Ttls) * -u Set RELP TLS Library to gnutls or openssl * -W wait time between sending batches of messages, in microseconds (Default: 0) * -b number of messages within a batch (default: 100,000,000 millions) * -Y use multiple threads, one per connection (which means 1 if one only connection * is configured!) * -y use RFC5424 style test message * -x CA Cert File for verification (TLS Mode / OpenSSL only) * -z private key file for TLS mode * -Z cert (public key) file for TLS mode * -a Authentication Mode for relp-tls * -A do NOT abort if an error occured during sending messages * -E Permitted Peer for relp-tls * -L loglevel to use for GnuTLS troubleshooting (0-off to 10-all, 0 default) * -g GnuTLS priority string for TLS mode when tcpflood is built with GnuTLS * -j format message in json, parameter is JSON cookie * -o number of threads to use for connection establishment (default: 25) * -O Use octet-count framing * -v verbose output, possibly useful for troubleshooting. Most importantly, * this gives insight into librelp actions (if relp is selected as protocol). * -k Custom Configuration string passwed through the TLS library. * Currently only OpenSSL is supported, possible configuration commands and values can be found here: * https://www.openssl.org/docs/man1.0.2/man3/SSL_CONF_cmd.html * Sample: -k"Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.1" * Works for LIBRELP now as well! * -w write the locally used port number to the specified file. The file * contains the port number followed by a line feed and is only valid * when a single connection is created. Works with TCP and UDP transports; * using it with RELP results in an error. * -q write a proper-termination marker to the specified file as the final * normal action before exiting. Used by the testbench to distinguish a * clean tcpflood run from a crash or abort. * * Part of the testbench for rsyslog. * * Copyright 2009-2025 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog 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. * * Rsyslog 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 Rsyslog. If not, see . * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_RELP #include #endif #include #include #include #ifdef ENABLE_GNUTLS #include #if GNUTLS_VERSION_NUMBER <= 0x020b00 #include GCRY_THREAD_OPTION_PTHREAD_IMPL; #endif #endif #ifdef ENABLE_OSSL #ifdef ENABLE_WOLFSSL #include #include #include #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif #endif #ifndef ENABLE_WOLFSSL #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif #endif #ifdef ENABLE_WOLFSSL #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT) #else /* OpenSSL API differences */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L #define RSYSLOG_X509_NAME_oneline(X509CERT) X509_get_subject_name(X509CERT) #define RSYSLOG_BIO_method_name(SSLBIO) BIO_method_name(SSLBIO) #define RSYSLOG_BIO_number_read(SSLBIO) BIO_number_read(SSLBIO) #define RSYSLOG_BIO_number_written(SSLBIO) BIO_number_written(SSLBIO) #else #define RSYSLOG_X509_NAME_oneline(X509CERT) (X509CERT != NULL ? X509CERT->cert_info->subject : NULL) #define RSYSLOG_BIO_method_name(SSLBIO) SSLBIO->method->name #define RSYSLOG_BIO_number_read(SSLBIO) SSLBIO->num #define RSYSLOG_BIO_number_written(SSLBIO) SSLBIO->num #endif #endif /* ENABLE_WOLFSSL */ #endif char *test_rs_strerror_r(int errnum, char *buf, size_t buflen) { #ifndef HAVE_STRERROR_R char *pszErr; pszErr = strerror(errnum); if (buflen > 0) { const size_t err_len = strlen(pszErr); const size_t copy_len = err_len < buflen - 1 ? err_len : buflen - 1; memcpy(buf, pszErr, copy_len); buf[copy_len] = '\0'; } #else #ifdef STRERROR_R_CHAR_P char *p = strerror_r(errnum, buf, buflen); if (p != buf) { if (buflen > 0) { const size_t err_len = strlen(p); const size_t copy_len = err_len < buflen - 1 ? err_len : buflen - 1; memcpy(buf, p, copy_len); buf[copy_len] = '\0'; } } #else strerror_r(errnum, buf, buflen); #endif #endif /* #ifdef __hpux */ return buf; } #define INVALID_SOCKET -1 /* Name of input file, must match $IncludeConfig in test suite .conf files */ #define NETTEST_INPUT_CONF_FILE "nettest.input.conf" /* name of input file, must match $IncludeConfig in .conf files */ #define MAX_EXTRADATA_LEN 512 * 1024 #define MAX_SENDBUF 2 * MAX_EXTRADATA_LEN #define MAX_RCVBUF 16 * 1024 + 1 /* TLS RFC 8449: max size of buffer for message reception */ #ifndef O_CLOEXEC #define O_CLOEXEC 0 #endif #ifdef O_NOFOLLOW #define TCPFLOOD_MARKER_OPEN_FLAGS O_NOFOLLOW #else #define TCPFLOOD_MARKER_OPEN_FLAGS 0 #endif static int nThreadsConnOpen = 25; /* Number for threads for openeing the connections */ static char *targetIP = "127.0.0.1"; static char *msgPRI = "167"; static int targetPort[5] = {13514}; static int numTargetPorts = 1; static int verbose = 0; static int dynFileIDs = 0; static int extraDataLen = 0; /* amount of extra data to add to message */ static int useRFC5424Format = 0; /* should the test message be in RFC5424 format? */ static int bRandomizeExtraData = 0; /* randomize amount of extra data added */ static int numMsgsToSend = 1; /* number of messages to send */ static int numConnections = 1; /* number of connections to create */ static int softLimitConnections = 0; /* soft connection limit, see -c option description */ static int *sockArray; /* array of sockets to use */ #ifdef ENABLE_RELP static relpClt_t **relpCltArray; /* array of sockets to use */ #endif static int msgNum = 0; /* initial message number to start with */ static int bShowProgress = 1; /* show progress messages */ static int bSilent = 0; /* completely silent operation */ static int bRandConnDrop = 0; /* randomly drop connections? */ static double dbRandConnDrop = 0.95; /* random drop probability */ static int holdOpenSeconds = -1; /* keep plain TCP sockets open after sending? */ static char *MsgToSend = NULL; /* if non-null, this is the actual message to send */ static char *hostname = "172.20.245.8"; /* this is the "tratditional" default, as bad is it is... */ static int bBinaryFile = 0; /* is -I file binary */ static char *dataFile = NULL; /* name of data file, if NULL, generate own data */ static char *portFile = NULL; /* file to store local port number */ static char *properTerminationFile = NULL; /* file to prove tcpflood reached normal main exit */ static int numFileIterations = 1; /* how often is file data to be sent? */ static char frameDelim = '\n'; /* default frame delimiter */ FILE *dataFP = NULL; /* file pointer for data file, if used */ static long nConnDrops = 0; /* counter: number of time connection was dropped (-D option) */ static int numRuns = 1; /* number of times the test shall be run */ static int sleepBetweenRuns = 30; /* number of seconds to sleep between runs */ static int bStatsRecords = 0; /* generate stats records */ static int bCSVoutput = 0; /* generate output in CSV (where applicable) */ static long long batchsize = 100000000ll; static int waittime = 0; static int runMultithreaded = 0; /* run tests in multithreaded mode */ static int numThrds = 1; /* number of threads to use */ static int abortOnSendFail = 1; /* abort run if sending fails? */ static char *tlsCAFile = NULL; static char *tlsCertFile = NULL; static char *tlsKeyFile = NULL; static char *tlsPriorityString = NULL; static char *relpAuthMode = NULL; static char *relpPermittedPeer = NULL; #if defined(HAVE_RELPENGINESETTLSLIBBYNAME) static char *relpTlsLib = NULL; #endif static int tlsLogLevel = 0; static char *jsonCookie = NULL; /* if non-NULL, use JSON format with this cookie */ static int octateCountFramed = 0; static char *customConfig = NULL; /* Stores a string with custom configuration passed through the TLS driver */ static bool handshakeOnly = false; #ifdef ENABLE_GNUTLS static gnutls_session_t *sessArray; /* array of TLS sessions to use */ static gnutls_certificate_credentials_t tlscred; static gnutls_priority_t tlsPriorityCache = NULL; #endif #ifdef ENABLE_OSSL /* Main OpenSSL CTX pointer */ static SSL_CTX *ctx; static SSL **sslArray; #ifndef ENABLE_WOLFSSL static struct sockaddr_in dtls_client_addr; /* socket address sender for receiving DTLS data */ static int udpsockin; /* socket for receiving messages in DTLS mode */ #endif #endif /* serialize TLS session setup to avoid races inside the TLS library */ static pthread_mutex_t tlsSessInitMutex = PTHREAD_MUTEX_INITIALIZER; /* variables for managing multi-threaded operations */ int runningThreads; /* number of threads currently running */ int doRun; /* shall sender thread begin to run? */ pthread_mutex_t thrdMgmt; /* mutex for controling startup/shutdown */ pthread_cond_t condStarted; pthread_cond_t condDoRun; /* the following struct provides information for a generator instance (thread) */ struct instdata { /* lower and upper bounds for the thread in question */ unsigned long long lower; unsigned long long numMsgs; /* number of messages to send */ unsigned long long numSent; /* number of messages already sent */ unsigned idx; /**< index of fd to be used for sending */ int failed; /**< set when this generator saw a send error */ pthread_t thread; /**< thread processing this instance */ } *instarray = NULL; /* the following structure is used to gather performance data */ struct runstats { unsigned long long totalRuntime; unsigned long minRuntime; unsigned long maxRuntime; int numRuns; }; static int udpsockout; /* socket for sending in UDP mode */ static struct sockaddr_in udpRcvr; /* remote receiver in UDP mode */ static enum { TP_UDP, TP_TCP, TP_TLS, TP_RELP_PLAIN, TP_RELP_TLS, TP_DTLS } transport = TP_TCP; /* forward definitions */ static void initTLSSess(int); static int sendTLS(int i, char *buf, size_t lenBuf); static void closeTLSSess(int __attribute__((unused)) i); static void initDTLSSess(void); static int sendDTLS(char *buf, size_t lenBuf); static void closeDTLSSess(void); #ifdef ENABLE_RELP static void relp_dbgprintf(char __attribute__((unused)) * fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } static relpEngine_t *pRelpEngine; #define CHKRELP(f) \ if (f != RELP_RET_OK) { \ fprintf(stderr, "%s\n", #f); \ exit(1); \ } static void onErr(void *pUsr, char *objinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) { fprintf(stderr, "tcpflood: onErr '%s'\n", errmesg); } static void onGenericErr(char *objinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) { fprintf(stderr, "tcpflood: onGenericErr '%s'\n", errmesg); } static void onAuthErr(void *pUsr, char *authinfo, char *errmesg, __attribute__((unused)) relpRetVal errcode) { fprintf(stderr, "tcpflood: onAuthErr '%s' peer '%s'\n", errmesg, authinfo); } static void initRELP_PLAIN(void) { CHKRELP(relpEngineConstruct(&pRelpEngine)); CHKRELP(relpEngineSetDbgprint(pRelpEngine, verbose ? relp_dbgprintf : NULL)); CHKRELP(relpEngineSetEnableCmd(pRelpEngine, (unsigned char *)"syslog", eRelpCmdState_Required)); /* Error output support */ CHKRELP(relpEngineSetOnErr(pRelpEngine, onErr)); CHKRELP(relpEngineSetOnGenericErr(pRelpEngine, onGenericErr)); CHKRELP(relpEngineSetOnAuthErr(pRelpEngine, onAuthErr)); } #endif /* #ifdef ENABLE_RELP */ /* prepare send subsystem for UDP send */ static int setupUDP(void) { struct sockaddr_in lcl; if ((udpsockout = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return 1; memset(&lcl, 0, sizeof(lcl)); lcl.sin_family = AF_INET; lcl.sin_addr.s_addr = htonl(INADDR_ANY); lcl.sin_port = htons(0); if (bind(udpsockout, (struct sockaddr *)&lcl, sizeof(lcl)) == -1) { perror("bind()"); return 1; } memset((char *)&udpRcvr, 0, sizeof(udpRcvr)); udpRcvr.sin_family = AF_INET; udpRcvr.sin_port = htons(targetPort[0]); if (inet_aton(targetIP, &udpRcvr.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); return (1); } return 0; } #if defined(ENABLE_OSSL) && !defined(ENABLE_WOLFSSL) static int setupDTLS(void) { // Setup receiving Socket for DTLS if ((udpsockin = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return 1; memset(&dtls_client_addr, 0, sizeof(dtls_client_addr)); dtls_client_addr.sin_family = AF_INET; dtls_client_addr.sin_port = htons(0); dtls_client_addr.sin_addr.s_addr = INADDR_ANY; if (bind(udpsockin, (struct sockaddr *)&dtls_client_addr, sizeof(dtls_client_addr)) < 0) { perror("bind()"); fprintf(stderr, "Unable to bind DTLS CLient socket\n"); return (1); } memset((char *)&udpRcvr, 0, sizeof(udpRcvr)); udpRcvr.sin_family = AF_INET; udpRcvr.sin_port = htons(targetPort[0]); if (inet_aton(targetIP, &udpRcvr.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); return (1); } // Init Socket Connection (Which technically does not connect but prepares socket for DTLS) printf("[DEBUG] Init Session to %s:%d ...\n", targetIP, targetPort[0]); udpsockout = socket(AF_INET, SOCK_DGRAM, 0); // Connect the UDP socket to the server's address if (connect(udpsockout, (const struct sockaddr *)&udpRcvr, sizeof(udpRcvr)) < 0) { perror("connect()"); fprintf(stderr, "connect to %s:%d failed\n", targetIP, targetPort[0]); return (1); } sockArray[0] = -1; return 0; } #else static int setupDTLS(void) { fprintf(stderr, "DTLS transport not supported with wolfSSL\n"); return 1; } #endif /* open a single tcp connection */ int openConn(const int connIdx) { int sock; struct sockaddr_in addr; int port; int retries = 0; int rnd; /* randomize port if required */ if (numTargetPorts > 1) { rnd = rand(); /* easier if we need value for debug messages ;) */ port = targetPort[(rnd % numTargetPorts)]; } else { port = targetPort[0]; } if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { #ifdef ENABLE_RELP relpRetVal relp_r; relpClt_t *relpClt; char relpPort[16]; snprintf(relpPort, sizeof(relpPort), "%d", port); CHKRELP(relpEngineCltConstruct(pRelpEngine, &relpClt)); if (transport == TP_RELP_TLS) { #if defined(HAVE_RELPENGINESETTLSLIBBYNAME) if (relpTlsLib != NULL && relpEngineSetTLSLibByName(pRelpEngine, relpTlsLib) != RELP_RET_OK) { fprintf(stderr, "relpTlsLib not accepted by librelp, using default\n"); } #endif if (relpCltEnableTLS(relpClt) != RELP_RET_OK) { fprintf(stderr, "error while enabling TLS for relp\n"); exit(1); } if (relpAuthMode != NULL && relpCltSetAuthMode(relpClt, relpAuthMode) != RELP_RET_OK) { fprintf(stderr, "could not set Relp Authentication mode: %s\n", relpAuthMode); exit(1); } if (tlsCAFile != NULL && relpCltSetCACert(relpClt, tlsCAFile) != RELP_RET_OK) { fprintf(stderr, "could not set CA File: %s\n", tlsCAFile); exit(1); } if (tlsCertFile != NULL && relpCltSetOwnCert(relpClt, tlsCertFile) != RELP_RET_OK) { fprintf(stderr, "could not set Cert File: %s\n", tlsCertFile); exit(1); } if (tlsKeyFile != NULL && relpCltSetPrivKey(relpClt, tlsKeyFile) != RELP_RET_OK) { fprintf(stderr, "could not set Key File: %s\n", tlsKeyFile); exit(1); } if (relpPermittedPeer != NULL && relpCltAddPermittedPeer(relpClt, relpPermittedPeer) != RELP_RET_OK) { fprintf(stderr, "could not set Permitted Peer: %s\n", relpPermittedPeer); exit(1); } #if defined(HAVE_RELPENGINESETTLSCFGCMD) /* Check for Custom Config string */ if (customConfig != NULL && relpCltSetTlsConfigCmd(relpClt, customConfig) != RELP_RET_OK) { fprintf(stderr, "could not set custom tls command: %s\n", customConfig); exit(1); } #endif } relpCltArray[connIdx] = relpClt; relp_r = relpCltConnect(relpCltArray[connIdx], 2, (unsigned char *)relpPort, (unsigned char *)targetIP); if (relp_r != RELP_RET_OK) { fprintf(stderr, "relp connect failed with return %d\n", relp_r); return (1); } sockArray[connIdx] = 1; /* mimic "all ok" state TODO: this looks invalid! */ #endif } else { /* TCP, with or without TLS */ memset((char *)&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); if (inet_aton(targetIP, &addr.sin_addr) == 0) { fprintf(stderr, "inet_aton() failed\n"); return (1); } while (1) { /* loop broken inside */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { return (1); } if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { break; } else { fprintf(stderr, "warning: connect failed, retrying... %s\n", strerror(errno)); close(sock); if (retries++ == 50) { perror("connect()"); fprintf(stderr, "connect(%d) failed\n", port); return (1); } else { usleep(100000); /* ms = 1000 us! */ } } } sockArray[connIdx] = sock; if (transport == TP_TLS) { pthread_mutex_lock(&tlsSessInitMutex); initTLSSess(connIdx); pthread_mutex_unlock(&tlsSessInitMutex); } } return 0; } static int progressCounter = 0; static pthread_mutex_t counterLock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t reportedConnOpenErrLock = PTHREAD_MUTEX_INITIALIZER; typedef struct { int startIdx; int endIdx; } ThreadArgsOpen; /* Thread function to handle a range of connections */ void *connectionWorker(void *arg) { ThreadArgsOpen *args = (ThreadArgsOpen *)arg; int i; static int reportedConnOpenErr = 0; for (i = args->startIdx; i <= args->endIdx; i++) { if (openConn(i) != 0) { pthread_mutex_lock(&reportedConnOpenErrLock); if (reportedConnOpenErr++ == 0) { fprintf(stderr, "Error opening connection %d; %s\n", i, strerror(errno)); } pthread_mutex_unlock(&reportedConnOpenErrLock); pthread_exit(NULL); } /* Update progress counter */ pthread_mutex_lock(&counterLock); const int ctr_fixed = progressCounter++; pthread_mutex_unlock(&counterLock); if (bShowProgress && i % 10 == 0) { printf("\r%5.5d", ctr_fixed); } } pthread_exit(NULL); } /* open all requested tcp connections * this includes allocating the connection array */ int openConnections(void) { int i; char msgBuf[128]; size_t lenMsg; pthread_t threads[nThreadsConnOpen]; ThreadArgsOpen threadArgs[nThreadsConnOpen]; int threadCount = nThreadsConnOpen; if (transport == TP_UDP) return setupUDP(); #if defined(ENABLE_OSSL) sslArray = calloc(numConnections, sizeof(SSL *)); #elif defined(ENABLE_GNUTLS) sessArray = calloc(numConnections, sizeof(gnutls_session_t)); #endif sockArray = malloc(numConnections * sizeof(int)); if (sockArray == NULL) { fprintf(stderr, "tcpflood: could not allocate sockArray, OOM.\n"); return 1; } /* use for loop based init for portability - no time critical code */ for (i = 0; i < numConnections; ++i) { sockArray[i] = -1; } #if defined(ENABLE_OSSL) // Use setupDTLS on DTLS if (transport == TP_DTLS) return setupDTLS(); #endif #ifdef ENABLE_RELP if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) relpCltArray = calloc(numConnections, sizeof(relpClt_t *)); #endif // Adjust the number of threads if there are fewer connections if (numConnections < threadCount) { threadCount = numConnections; } if (bShowProgress) if (write(1, " open connections", sizeof(" open connections") - 1)) { } // Divide connections among threads int connectionsPerThread = numConnections / threadCount; int remainder = numConnections % threadCount; int startIdx = 0; for (i = 0; i < threadCount; i++) { int endIdx = startIdx + connectionsPerThread - 1; endIdx += remainder; remainder = 0; threadArgs[i].startIdx = startIdx; threadArgs[i].endIdx = endIdx; if (pthread_create(&threads[i], NULL, connectionWorker, &threadArgs[i]) != 0) { fprintf(stderr, "Error creating thread: %s\n", strerror(errno)); return 1; } startIdx = endIdx + 1; } /* Wait for all connection open threads to finish */ for (i = 0; i < threadCount; i++) { pthread_join(threads[i], NULL); } return 0; } /* we also close all connections because otherwise we may get very bad * timing for the syslogd - it may not be able to process all incoming * messages fast enough if we immediately shut down. * TODO: it may be an interesting excercise to handle that situation * at the syslogd level, too * rgerhards, 2009-04-14 */ void closeConnections(void) { int i; size_t lenMsg; struct linger ling; char msgBuf[128]; if (transport == TP_UDP) { return; } #if defined(ENABLE_OSSL) else if (transport == TP_DTLS) { closeDTLSSess(); return; } #endif if (bShowProgress) if (write(1, " close connections", sizeof(" close connections") - 1)) { } for (i = 0; i < numConnections; ++i) { if (i % 10 == 0 && bShowProgress) { lenMsg = snprintf(msgBuf, sizeof(msgBuf), "\r%5.5d", i); if (write(1, msgBuf, lenMsg)) { } } if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { #ifdef ENABLE_RELP relpRetVal relpr; if (sockArray[i] != -1) { relpr = relpEngineCltDestruct(pRelpEngine, relpCltArray + i); if (relpr != RELP_RET_OK) { fprintf(stderr, "relp error %d on close\n", relpr); } sockArray[i] = -1; } #endif } else { /* TCP and TLS modes */ if (sockArray[i] != -1) { /* we try to not overrun the receiver by trying to flush buffers * *during* close(). -- rgerhards, 2010-08-10 */ ling.l_onoff = 1; ling.l_linger = 1; setsockopt(sockArray[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); if (transport == TP_TLS) { closeTLSSess(i); } close(sockArray[i]); } } } if (bShowProgress) { lenMsg = snprintf(msgBuf, sizeof(msgBuf), "\r%5.5d close connections\n", i); if (write(1, msgBuf, lenMsg)) { } } } static void holdOpenConnections(void) { int i; int openSockets = 0; unsigned int secondsRemaining; if (holdOpenSeconds < 0) { return; } for (i = 0; i < numConnections; ++i) { if (sockArray[i] != -1) { ++openSockets; } } if (openSockets == 0) { if (!bSilent) { printf("no open TCP connections to hold\n"); } return; } if (!bSilent) { if (holdOpenSeconds == 0) { printf("holding %d TCP connections until terminated\n", openSockets); } else { printf("holding %d TCP connections for %d seconds\n", openSockets, holdOpenSeconds); } } if (holdOpenSeconds == 0) { while (1) { pause(); } } secondsRemaining = (unsigned int)holdOpenSeconds; while (secondsRemaining > 0) { secondsRemaining = sleep(secondsRemaining); } } /* generate the message to be sent according to program command line parameters. * this has been moved to its own function as we now have various different ways * of constructing test messages. -- rgerhards, 2010-03-31 */ static void genMsg(char *buf, size_t maxBuf, size_t *pLenBuf, struct instdata *inst) { int edLen; /* actual extra data length to use */ const unsigned long long messageNumber = inst->lower + inst->numSent; char extraData[MAX_EXTRADATA_LEN + 1]; char dynFileIDBuf[128] = ""; int done; char payloadLen[32]; int payloadStringLen; if (dataFP != NULL) { /* get message from file */ do { done = 1; *pLenBuf = fread(buf, 1, MAX_EXTRADATA_LEN + 1024, dataFP); if (*pLenBuf == 0) { if (--numFileIterations > 0) { rewind(dataFP); done = 0; /* need new iteration */ } else { *pLenBuf = 0; goto finalize_it; } } } while (!done); /* Attention: do..while()! */ } else if (jsonCookie != NULL) { if (useRFC5424Format) { *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z mymachine.example.com " "tcpflood - tag [tcpflood@32473 MSGNUM" "=\"%8.8llu\"] %s{\"msgnum\":%llu}%c", msgPRI, messageNumber, jsonCookie, messageNumber, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 %s tag %s{\"msgnum\":%llu}%c", msgPRI, hostname, jsonCookie, messageNumber, frameDelim); } } else if (MsgToSend == NULL) { if (dynFileIDs > 0) { snprintf(dynFileIDBuf, sizeof(dynFileIDBuf), "%d:", rand() % dynFileIDs); } if (extraDataLen == 0) { if (useRFC5424Format) { *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z " "mymachine.example.com tcpflood - tag [tcpflood@32473 " "MSGNUM=\"%8.8llu\"] msgnum:%s%8.8llu:%c", msgPRI, messageNumber, dynFileIDBuf, messageNumber, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 %s tag " "msgnum:%s%8.8llu:%c", msgPRI, hostname, dynFileIDBuf, messageNumber, frameDelim); } } else { if (bRandomizeExtraData) edLen = ((unsigned long)rand() + extraDataLen) % extraDataLen + 1; else edLen = extraDataLen; memset(extraData, 'X', edLen); extraData[edLen] = '\0'; if (useRFC5424Format) { *pLenBuf = snprintf(buf, maxBuf, "<%s>1 2003-03-01T01:00:00.000Z " "mymachine.example.com tcpflood - tag [tcpflood@32473 " "MSGNUM=\"%8.8llu\"] msgnum:%s%8.8llu:%c", msgPRI, messageNumber, dynFileIDBuf, messageNumber, frameDelim); } else { *pLenBuf = snprintf(buf, maxBuf, "<%s>Mar 1 01:00:00 %s tag msgnum" ":%s%8.8llu:%d:%s%c", msgPRI, hostname, dynFileIDBuf, messageNumber, edLen, extraData, frameDelim); } } } else { /* use fixed message format from command line */ *pLenBuf = snprintf(buf, maxBuf, "%s%c", MsgToSend, frameDelim); } if (octateCountFramed == 1) { size_t actual_len; /* when using octet-counted framing, omit the delimiter from the * payload itself. the delimiter is included in the default message * format to support traditional plain TCP framing. remove it here * before we prefix the payload length. */ actual_len = *pLenBuf; if (actual_len > 0 && buf[actual_len - 1] == frameDelim) { buf[--actual_len] = '\0'; } payloadStringLen = snprintf(payloadLen, sizeof(payloadLen), "%zu ", actual_len); if (payloadStringLen < 0 || payloadStringLen >= sizeof(payloadLen)) { fprintf(stderr, "tcpflood: payloadLen buffer too short or error - cannot continue " "(internal error), snprintf return %d\n", payloadStringLen); exit(1); } memmove(buf + payloadStringLen, buf, actual_len); memcpy(buf, payloadLen, payloadStringLen); *pLenBuf = actual_len + payloadStringLen; } ++inst->numSent; finalize_it: /*EMPTY to keep the compiler happy */; } static int sendPlainTCP(const int socknum, const char *const buf, const size_t lenBuf, int *const ret_errno) { size_t lenSent; int r; lenSent = 0; while (lenSent != lenBuf) { r = send(sockArray[socknum], buf + lenSent, lenBuf - lenSent, 0); if (r > 0) { lenSent += r; } else { *ret_errno = errno; goto finalize_it; } } finalize_it: return lenSent; } /* send messages to the tcp connections we keep open. We use * a very basic format that helps identify the message * (via msgnum:: e.g. msgnum:00000001:). This format is suitable * for extracton to field-based properties. * The first numConnection messages are sent sequentially, as are the * last. All messages in between are sent over random connections. * Note that message numbers start at 0. */ int sendMessages(struct instdata *inst) { unsigned i = 0; int socknum; size_t lenBuf; size_t lenSend = 0; char *statusText = ""; char buf[MAX_EXTRADATA_LEN + 1024]; char sendBuf[MAX_SENDBUF]; int offsSendBuf = 0; char errStr[1024]; int error_number = 0; unsigned show_progress_interval = 100; if (!bSilent) { if (dataFile == NULL) { printf("Sending %llu messages.\n", inst->numMsgs); statusText = "messages"; if ((inst->numMsgs / 100) > show_progress_interval) { show_progress_interval = inst->numMsgs / 100; } } else { printf("Sending file '%s' %d times.\n", dataFile, numFileIterations); statusText = "kb"; } } if (bShowProgress) printf("\r%8.8d %s sent", 0, statusText); while (i < inst->numMsgs) { if (runMultithreaded) { socknum = inst->idx; } else { if ((int)i < numConnections) socknum = i; else if (i >= inst->numMsgs - numConnections) { socknum = i - (inst->numMsgs - numConnections); } else { int rnd = rand(); socknum = rnd % numConnections; } } genMsg(buf, sizeof(buf), &lenBuf, inst); /* generate the message to send according to params */ if (lenBuf == 0) break; /* terminate when no message could be generated */ if (transport == TP_TCP) { if (sockArray[socknum] == -1) { /* connection was dropped, need to re-establish */ if (openConn(socknum) != 0) { printf("error in trying to re-open connection %d\n", socknum); exit(1); } } lenSend = sendPlainTCP(socknum, buf, lenBuf, &error_number); } else if (transport == TP_UDP) { lenSend = sendto(udpsockout, buf, lenBuf, 0, &udpRcvr, sizeof(udpRcvr)); error_number = errno; } else if (transport == TP_TLS) { if (sockArray[socknum] == -1) { /* connection was dropped, need to re-establish */ if (openConn(socknum) != 0) { printf("error in trying to re-open connection %d\n", socknum); exit(1); } } if (offsSendBuf + lenBuf < MAX_SENDBUF) { memcpy(sendBuf + offsSendBuf, buf, lenBuf); offsSendBuf += lenBuf; lenSend = lenBuf; /* simulate "good" call */ } else { lenSend = sendTLS(socknum, sendBuf, offsSendBuf); lenSend = (lenSend == offsSendBuf) ? lenBuf : -1; memcpy(sendBuf, buf, lenBuf); offsSendBuf = lenBuf; } #if defined(ENABLE_OSSL) } else if (transport == TP_DTLS) { if (sockArray[0] == -1) { // Init DTLS Session (Bind local listener) initDTLSSess(); } lenSend = sendDTLS(buf, lenBuf); #endif } else if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { #ifdef ENABLE_RELP relpRetVal relp_ret; if (sockArray[socknum] == -1) { /* connection was dropped, need to re-establish */ if (openConn(socknum) != 0) { printf("error in trying to re-open connection %d\n", socknum); exit(1); } } relp_ret = relpCltSendSyslog(relpCltArray[socknum], (unsigned char *)buf, lenBuf); if (relp_ret == RELP_RET_OK) { lenSend = lenBuf; /* mimic ok */ } else { lenSend = 0; /* mimic fail */ printf("\nrelpCltSendSyslog() failed with relp error code %d\n", relp_ret); } #endif } if (lenSend != lenBuf) { printf("\r%5.5u\n", i); fflush(stdout); test_rs_strerror_r(error_number, errStr, sizeof(errStr)); if (lenSend == 0) { printf("tcpflood: socket %d, index %u, msgNum %lld CLOSED REMOTELY (%s)\n", sockArray[socknum], i, inst->numSent, errStr); } else { printf( "tcpflood: send() failed \"%s\" at socket %d, index %u, " "msgNum %lld, lenSend %zd, lenBuf %zd\n", errStr, sockArray[socknum], i, inst->numSent, lenSend, lenBuf); } fflush(stderr); if (abortOnSendFail) { printf("tcpflood terminates due to send failure\n"); return (1); } } if (i % show_progress_interval == 0) { if (bShowProgress) printf("\r%8.8u", i); } if (!runMultithreaded && bRandConnDrop) { /* if we need to randomly drop connections, see if we * are a victim */ if (rand() > (int)(RAND_MAX * dbRandConnDrop)) { if (transport == TP_TLS && offsSendBuf != 0) { /* send remaining buffer */ lenSend = sendTLS(socknum, sendBuf, offsSendBuf); if (lenSend != offsSendBuf) { fprintf(stderr, "tcpflood: error in send function for conn %d " "causes potential data loss lenSend %zd, " "offsSendBuf %d\n", sockArray[socknum], lenSend, offsSendBuf); } offsSendBuf = 0; } ++nConnDrops; close(sockArray[socknum]); sockArray[socknum] = -1; } } if (inst->numSent % batchsize == 0) { usleep(waittime); } ++i; } if (transport == TP_TLS && offsSendBuf != 0) { /* send remaining buffer */ lenSend = sendTLS(socknum, sendBuf, offsSendBuf); } if (!bSilent) printf("\r%8.8u %s sent\n", i, statusText); return 0; } /* this is the thread that starts a generator */ static void *thrdStarter(void *arg) { struct instdata *inst = (struct instdata *)arg; pthread_mutex_lock(&thrdMgmt); runningThreads++; pthread_cond_signal(&condStarted); while (doRun == 0) { pthread_cond_wait(&condDoRun, &thrdMgmt); } pthread_mutex_unlock(&thrdMgmt); if (sendMessages(inst) != 0) { inst->failed = 1; printf("error sending messages\n"); } return NULL; } /* This function initializes the actual traffic generators. The function sets up all required * parameter blocks and starts threads. It returns when all threads are ready to run * and the main task must just enable them. */ static void prepareGenerators(void) { int i; long long msgsThrd; unsigned long long starting = (unsigned long long)msgNum; pthread_attr_t thrd_attr; if (runMultithreaded) { bSilent = 1; numThrds = numConnections; } else { numThrds = 1; } pthread_attr_init(&thrd_attr); pthread_attr_setstacksize(&thrd_attr, 4096 * 1024); runningThreads = 0; doRun = 0; pthread_mutex_init(&thrdMgmt, NULL); pthread_cond_init(&condStarted, NULL); pthread_cond_init(&condDoRun, NULL); if (instarray != NULL) { free(instarray); } instarray = calloc(numThrds, sizeof(struct instdata)); msgsThrd = numMsgsToSend / numThrds; for (i = 0; i < numThrds; ++i) { instarray[i].lower = starting; instarray[i].numMsgs = msgsThrd; instarray[i].numSent = 0; instarray[i].idx = i; pthread_create(&(instarray[i].thread), &thrd_attr, thrdStarter, instarray + i); /*printf("started thread %x\n", (unsigned) instarray[i].thread);*/ starting += msgsThrd; } } /* Let all generators run. Threads must have been started. Here we wait until * all threads are initialized and then broadcast that they can begin to run. */ static void runGenerators(void) { pthread_mutex_lock(&thrdMgmt); while (runningThreads != numThrds) { pthread_cond_wait(&condStarted, &thrdMgmt); } doRun = 1; pthread_cond_broadcast(&condDoRun); pthread_mutex_unlock(&thrdMgmt); } /* Wait for all traffic generators to stop. */ static int waitGenerators(void) { int i; int failed = 0; for (i = 0; i < numThrds; ++i) { pthread_join(instarray[i].thread, NULL); if (instarray[i].failed) { failed = 1; } /*printf("thread %x stopped\n", (unsigned) instarray[i].thread);*/ } pthread_mutex_destroy(&thrdMgmt); pthread_cond_destroy(&condStarted); pthread_cond_destroy(&condDoRun); return failed; } /* functions related to computing statistics on the runtime of a test. This is * a separate function primarily not to mess up the test driver. * rgerhards, 2010-12-08 */ static void endTiming(struct timeval *tvStart, struct runstats *stats) { long sec, usec; unsigned long runtime; struct timeval tvEnd; gettimeofday(&tvEnd, NULL); if (tvStart->tv_usec > tvEnd.tv_usec) { tvEnd.tv_sec--; tvEnd.tv_usec += 1000000; } sec = tvEnd.tv_sec - tvStart->tv_sec; usec = tvEnd.tv_usec - tvStart->tv_usec; runtime = sec * 1000 + (usec / 1000); stats->totalRuntime += runtime; if (runtime < stats->minRuntime) stats->minRuntime = runtime; if (runtime > stats->maxRuntime) stats->maxRuntime = runtime; if (!bSilent || bStatsRecords) { if (bCSVoutput) { printf("%lu.%3.3ld\n", runtime / 1000, runtime % 1000); } else { printf("runtime: %lu.%3.3ld\n", runtime / 1000, runtime % 1000); } } } /* generate stats summary record at end of run */ static void genStats(struct runstats *stats) { long unsigned avg; avg = stats->totalRuntime / stats->numRuns; if (bCSVoutput) { printf("#numRuns,TotalRuntime,AvgRuntime,MinRuntime,MaxRuntime\n"); printf("%d,%llu.%3.3d,%lu.%3.3lu,%lu.%3.3lu,%lu.%3.3lu\n", stats->numRuns, stats->totalRuntime / 1000, (int)stats->totalRuntime % 1000, avg / 1000, avg % 1000, stats->minRuntime / 1000, stats->minRuntime % 1000, stats->maxRuntime / 1000, stats->maxRuntime % 1000); } else { printf("Runs: %d\n", stats->numRuns); printf("Runtime:\n"); printf(" total: %llu.%3.3d\n", stats->totalRuntime / 1000, (int)stats->totalRuntime % 1000); printf(" avg: %lu.%3.3lu\n", avg / 1000, avg % 1000); printf(" min: %lu.%3.3lu\n", stats->minRuntime / 1000, stats->minRuntime % 1000); printf(" max: %lu.%3.3lu\n", stats->maxRuntime / 1000, stats->maxRuntime % 1000); printf("All times are wallclock time.\n"); } } /* Run the actual test. This function handles various meta-parameters, like * a specified number of iterations, performance measurement and so on... * rgerhards, 2010-12-08 */ static int runTests(void) { struct timeval tvStart; struct runstats stats; int run; stats.totalRuntime = 0; stats.minRuntime = 0xffffffffllu; stats.maxRuntime = 0; stats.numRuns = numRuns; run = 1; while (1) { /* loop broken inside */ if (!bSilent) printf("starting run %d\n", run); prepareGenerators(); gettimeofday(&tvStart, NULL); runGenerators(); if (waitGenerators() != 0) { endTiming(&tvStart, &stats); return 1; } /* Generators use disjoint, immutable ranges so -Y has no shared * counter race. Advance the base once, after all threads complete, * to preserve the existing consecutive numbering across -R runs. */ msgNum += numMsgsToSend; endTiming(&tvStart, &stats); if (run == numRuns) break; if (!bSilent) printf("sleeping %d seconds before next run\n", sleepBetweenRuns); sleep(sleepBetweenRuns); ++run; } if (bStatsRecords) { genStats(&stats); } return 0; } #if defined(ENABLE_OSSL) /* OpenSSL implementation of TLS funtions. * alorbach, 2018-06-11 */ #ifndef ENABLE_WOLFSSL #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) long BIO_debug_callback_ex(BIO *bio, int cmd, const char __attribute__((unused)) * argp, size_t __attribute__((unused)) len, int argi, long __attribute__((unused)) argl, int ret, size_t __attribute__((unused)) * processed) #else long BIO_debug_callback( BIO *bio, int cmd, const char __attribute__((unused)) * argp, int argi, long __attribute__((unused)) argl, long ret) #endif { long r = 1; if (BIO_CB_RETURN & cmd) { r = ret; } printf("tcpflood: openssl debugmsg: BIO[%p]: ", (void *)bio); switch (cmd) { case BIO_CB_FREE: printf("Free - %s\n", RSYSLOG_BIO_method_name(bio)); break; /* Disabled due API changes for OpenSSL 1.1.0+ */ #if OPENSSL_VERSION_NUMBER < 0x10100000L case BIO_CB_READ: if (bio->method->type & BIO_TYPE_DESCRIPTOR) { printf("read(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_read(bio)); } else { printf("read(%d,%lu) - %s\n", RSYSLOG_BIO_number_read(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); } break; case BIO_CB_WRITE: if (bio->method->type & BIO_TYPE_DESCRIPTOR) { printf("write(%d,%lu) - %s fd=%d\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio), RSYSLOG_BIO_number_written(bio)); } else { printf("write(%d,%lu) - %s\n", RSYSLOG_BIO_number_written(bio), (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); } break; #else case BIO_CB_READ: printf("read %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_WRITE: printf("write %s\n", RSYSLOG_BIO_method_name(bio)); break; #endif case BIO_CB_PUTS: printf("puts() - %s\n", RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_GETS: printf("gets(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_CTRL: printf("ctrl(%lu) - %s\n", (unsigned long)argi, RSYSLOG_BIO_method_name(bio)); break; case BIO_CB_RETURN | BIO_CB_READ: printf("read return %d\n", (int)ret); break; case BIO_CB_RETURN | BIO_CB_WRITE: printf("write return %d\n", (int)ret); break; case BIO_CB_RETURN | BIO_CB_GETS: printf("gets return %d\n", (int)ret); break; case BIO_CB_RETURN | BIO_CB_PUTS: printf("puts return %d\n", (int)ret); break; case BIO_CB_RETURN | BIO_CB_CTRL: printf("ctrl return %d\n", (int)ret); break; default: printf("bio callback - unknown type (%d)\n", cmd); break; } return r; } #endif /* !ENABLE_WOLFSSL */ void osslLastSSLErrorMsg(int ret, SSL *ssl, const char *pszCallSource) { unsigned long un_error = 0; char psz[256]; if (ssl == NULL) { /* Output Error Info*/ printf("tcpflood: Error in '%s' with ret=%d\n", pszCallSource, ret); } else { long iMyRet = SSL_get_error(ssl, ret); /* Check which kind of error we have */ printf("tcpflood: openssl error '%s' with error code=%ld\n", pszCallSource, iMyRet); if (iMyRet == SSL_ERROR_SYSCALL) { iMyRet = ERR_get_error(); if (ret == 0) { iMyRet = SSL_get_error(ssl, iMyRet); if (iMyRet == 0) { *psz = '\0'; } else { ERR_error_string_n(iMyRet, psz, 256); } printf("tcpflood: Errno %d, SysErr: %s\n", errno, psz); } } else { printf("tcpflood: Unknown SSL Error in '%s' (%d), SSL_get_error: %ld\n", pszCallSource, ret, iMyRet); } } /* Loop through errors */ while ((un_error = ERR_get_error()) > 0) { ERR_error_string_n(un_error, psz, 256); printf("tcpflood: %s Errorstack: %s\n", pszCallSource, psz); } } int verify_callback(int status, X509_STORE_CTX *store) { char szdbgdata1[256]; char szdbgdata2[256]; if (status == 0) { printf("tcpflood: verify_callback certificate validation failed!\n"); X509 *cert = X509_STORE_CTX_get_current_cert(store); int depth = X509_STORE_CTX_get_error_depth(store); int err = X509_STORE_CTX_get_error(store); X509_NAME_oneline(X509_get_issuer_name(cert), szdbgdata1, sizeof(szdbgdata1)); X509_NAME_oneline(RSYSLOG_X509_NAME_oneline(cert), szdbgdata2, sizeof(szdbgdata2)); /* Log Warning only on EXPIRED */ if (err == X509_V_OK || err == X509_V_ERR_CERT_HAS_EXPIRED) { printf( "tcpflood: Certificate warning at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err)); /* Set Status to OK*/ status = 1; } else { printf( "tcpflood: Certificate error at depth: %d \n\t" "issuer = %s\n\t" "subject = %s\n\t" "err %d:%s\n", depth, szdbgdata1, szdbgdata2, err, X509_verify_cert_error_string(err)); exit(1); } } return status; } /* global init OpenSSL */ static void initTLS(const SSL_METHOD *method) { #ifdef ENABLE_WOLFSSL if (!SSL_library_init()) { #else #if OPENSSL_VERSION_NUMBER < 0x10100000L /* Setup OpenSSL library < 1.1.0 */ if (!SSL_library_init()) { #else /* Setup OpenSSL library >= 1.1.0 with system default settings */ if (OPENSSL_init_ssl(0, NULL) == 0) { #endif #endif printf("tcpflood: error openSSL initialization failed!\n"); exit(1); } #if defined(ENABLE_WOLFSSL) && defined(DEBUG_WOLFSSL) wolfSSL_Debugging_ON(); #endif /* Load readable error strings */ SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) /* * ERR_load_*(), ERR_func_error_string(), ERR_get_error_line(), ERR_get_error_line_data(), ERR_get_state() * OpenSSL now loads error strings automatically so these functions are not needed. * SEE FOR MORE: * https://www.openssl.org/docs/manmaster/man7/migration_guide.html * */ #else /* Load error strings into mem*/ ERR_load_BIO_strings(); ERR_load_crypto_strings(); #endif // Create OpenSSL Context ctx = SSL_CTX_new(method); #if defined(ENABLE_WOLFSSL) && OPENSSL_VERSION_NUMBER >= 0x10100000L SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION); #endif if (tlsCAFile != NULL && SSL_CTX_load_verify_locations(ctx, tlsCAFile, NULL) != 1) { printf( "tcpflood: Error, Failed loading CA certificate" " Is the file at the right path? And do we have the permissions?"); exit(1); } #ifndef ENABLE_WOLFSSL SSL_CTX_set_ecdh_auto(ctx, 1); #endif if (SSL_CTX_use_certificate_chain_file(ctx, tlsCertFile) != 1) { printf("tcpflood: error cert file could not be accessed -- have you mixed up key and certificate?\n"); printf("If in doubt, try swapping the files in -z/-Z\n"); printf("Certifcate is: '%s'\n", tlsCertFile); printf("Key is: '%s'\n", tlsKeyFile); exit(1); } if (SSL_CTX_use_PrivateKey_file(ctx, tlsKeyFile, SSL_FILETYPE_PEM) != 1) { printf("tcpflood: error key file could not be accessed -- have you mixed up key and certificate?\n"); printf("If in doubt, try swapping the files in -z/-Z\n"); printf("Certifcate is: '%s'\n", tlsCertFile); printf("Key is: '%s'\n", tlsKeyFile); exit(1); } /* Set CTX Options */ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2); /* Disable insecure SSLv2 Protocol */ SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3); /* Disable insecure SSLv3 Protocol */ SSL_CTX_sess_set_cache_size(ctx, 1024); /* Check for Custom Config string */ if (customConfig != NULL) { #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) && !defined(ENABLE_WOLFSSL) char *pCurrentPos; char *pNextPos; char *pszCmd; char *pszValue; int iConfErr; printf("tcpflood: custom config set to '%s'\n", customConfig); /* Set working pointer */ pCurrentPos = (char *)customConfig; if (strlen(pCurrentPos) > 0) { pNextPos = index(pCurrentPos, '='); if (pNextPos != NULL) { pszCmd = strndup(pCurrentPos, pNextPos - pCurrentPos); pszValue = strdup(++pNextPos); // Create CTX Config Helper SSL_CONF_CTX *cctx; cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SHOW_ERRORS); SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); /* Add SSL Conf Command */ iConfErr = SSL_CONF_cmd(cctx, pszCmd, pszValue); if (iConfErr > 0) { printf("tcpflood: Successfully added Command %s:%s\n", pszCmd, pszValue); } else { printf( "tcpflood: error, adding Command: %s:%s " "in SSL_CONF_cmd with error '%d'\n", pszCmd, pszValue, iConfErr); osslLastSSLErrorMsg(0, NULL, "initTLS"); } /* Finalize SSL Conf */ iConfErr = SSL_CONF_CTX_finish(cctx); if (!iConfErr) { printf("tcpflood: error, setting openssl command parameters: %s\n", customConfig); } free(pszCmd); free(pszValue); } else { printf("tcpflood: error, invalid value for -k: %s\n", customConfig); } } else { printf("tcpflood: error, invalid value for -k: %s\n", customConfig); } #else printf("tcpflood: TLS library does not support SSL_CONF_cmd API (maybe it is too old?)."); #endif } /* DO ONLY SUPPORT DEFAULT CIPHERS YET * SSL_CTX_set_cipher_list(ctx,"ALL"); Support all ciphers */ /* // Create Extra Length DH! pDH = DH_new(); if ( !DH_generate_parameters_ex(pDH, 768, DH_GENERATOR_2, NULL) ) { if(pDH) DH_free(pDH); fprintf(stderr, "Failed to generated dynamic DH\n"); exit(1); } else { int iErrCheck = 0; if ( !DH_check( pDH, &iErrCheck) ) { fprintf(stderr, "Failed to generated dynamic DH - iErrCheck=%d\n", iErrCheck); exit(1); } } */ /* Set default VERIFY Options for OpenSSL CTX - and CALLBACK */ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_callback); SSL_CTX_set_timeout(ctx, 30); /* Default Session Timeout, TODO: Make configureable */ SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); } static void exitTLS(void) { SSL_CTX_free(ctx); #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static void initTLSSess(const int i) { int res; BIO *bio_client; SSL *pNewSsl = SSL_new(ctx); sslArray[i] = pNewSsl; if (!sslArray[i]) { osslLastSSLErrorMsg(0, sslArray[i], "initTLSSess1"); } SSL_set_verify(sslArray[i], SSL_VERIFY_NONE, verify_callback); /* Create BIO from socket array! */ const int bioCloseFlag = handshakeOnly ? BIO_NOCLOSE : BIO_CLOSE; bio_client = BIO_new_socket(sockArray[i], bioCloseFlag); if (bio_client == NULL) { osslLastSSLErrorMsg(0, sslArray[i], "initTLSSess2"); exit(1); } else { // printf("initTLSSess: Init client BIO[%p] done\n", (void *)bio_client); } if (tlsLogLevel > 0) { #ifndef ENABLE_WOLFSSL /* Set debug Callback for client BIO as well! */ #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) BIO_set_callback_ex(bio_client, BIO_debug_callback_ex); #else BIO_set_callback(bio_client, BIO_debug_callback); #endif // OPENSSL_VERSION_NUMBER >= 0x10100000L #endif } BIO_set_nbio(bio_client, handshakeOnly ? 1 : 0); SSL_set_bio(sslArray[i], bio_client, bio_client); SSL_set_connect_state(sslArray[i]); /*sets ssl to work in client mode.*/ /* Perform the TLS handshake */ if ((res = SSL_do_handshake(sslArray[i])) <= 0) { const int err = SSL_get_error(sslArray[i], res); if (handshakeOnly) { int allow = 0; switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: #ifdef SSL_ERROR_WANT_CONNECT case SSL_ERROR_WANT_CONNECT: #endif #ifdef SSL_ERROR_WANT_ACCEPT case SSL_ERROR_WANT_ACCEPT: #endif case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: allow = 1; break; default: break; } if (!allow) { osslLastSSLErrorMsg(res, sslArray[i], "initTLSSess3"); exit(1); } if (verbose) { switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: #ifdef SSL_ERROR_WANT_CONNECT case SSL_ERROR_WANT_CONNECT: #endif #ifdef SSL_ERROR_WANT_ACCEPT case SSL_ERROR_WANT_ACCEPT: #endif break; default: osslLastSSLErrorMsg(res, sslArray[i], "initTLSSess3"); break; } } ERR_clear_error(); } else { osslLastSSLErrorMsg(res, sslArray[i], "initTLSSess3"); exit(1); } } if (handshakeOnly) { SSL_free(sslArray[i]); sslArray[i] = NULL; if (sockArray[i] != -1) { close(sockArray[i]); } sockArray[i] = -1; } } #pragma GCC diagnostic pop static int sendTLS(int i, char *buf, size_t lenBuf) { size_t lenSent; int r, err; lenSent = 0; while (lenSent != lenBuf) { r = SSL_write(sslArray[i], buf + lenSent, lenBuf - lenSent); if (r > 0) { lenSent += r; } else { err = SSL_get_error(sslArray[i], r); if (err != SSL_ERROR_ZERO_RETURN && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { /*SSL_ERROR_ZERO_RETURN: TLS connection has been closed. This * result code is returned only if a closure alert has occurred * in the protocol, i.e. if the connection has been closed cleanly. *SSL_ERROR_WANT_READ/WRITE: The operation did not complete, try * again later. */ printf("Error while sending data: [%d] %s", err, ERR_error_string(err, NULL)); printf("Error is: %s", ERR_reason_error_string(err)); } else { /* Check for SSL Shutdown */ if (SSL_get_shutdown(sslArray[i]) == SSL_RECEIVED_SHUTDOWN) { printf("received SSL_RECEIVED_SHUTDOWN!\n"); } else { printf("[ERROR] while sending data: [%d] %s", err, ERR_error_string(err, NULL)); printf("[ERROR] Reason: %s", ERR_reason_error_string(err)); } } exit(1); } } return lenSent; } static void closeTLSSess(int i) { if (sslArray == NULL || sslArray[i] == NULL) { return; } int r; r = SSL_shutdown(sslArray[i]); if (r <= 0) { /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more: * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html */ char rcvBuf[MAX_RCVBUF]; SSL_read(sslArray[i], rcvBuf, MAX_RCVBUF); } SSL_free(sslArray[i]); sslArray[i] = NULL; } #ifndef ENABLE_WOLFSSL #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static void initDTLSSess(void) { int res; BIO *bio_client; // Create new SSL SSL *pNewSsl = SSL_new(ctx); // set to array variables sslArray[0] = pNewSsl; sockArray[0] = udpsockout; if (!sslArray[0]) { fprintf(stderr, "Unable to create SSL\n"); osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess1"); exit(1); } SSL_set_verify(sslArray[0], SSL_VERIFY_NONE, verify_callback); /* Create BIO from socket array! */ bio_client = BIO_new_dgram(udpsockout, BIO_NOCLOSE); if (!bio_client) { fprintf(stderr, "Unable to create BIO\n"); osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess2"); exit(1); } BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &dtls_client_addr); SSL_set_bio(sslArray[0], bio_client, bio_client); if (tlsLogLevel > 0) { #ifndef ENABLE_WOLFSSL /* Set debug Callback for client BIO as well! */ #if OPENSSL_VERSION_NUMBER >= 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER) BIO_set_callback_ex(bio_client, BIO_debug_callback_ex); #else BIO_set_callback(bio_client, BIO_debug_callback); #endif // OPENSSL_VERSION_NUMBER >= 0x10100000L #endif } /* Blocking socket */ // BIO_set_nbio( bio_client, 0 ); // SSL_set_bio(sslArray[0], bio_client, bio_client); // SSL_set_connect_state(sslArray[0]); /*sets ssl to work in client mode.*/ printf("[DEBUG] Starting DTLS session ...\n"); /* Perform handshake */ if (SSL_connect(sslArray[0]) <= 0) { fprintf(stderr, "SSL_connect failed\n"); osslLastSSLErrorMsg(0, sslArray[0], "initDTLSSess3"); exit(1); } // Print Cipher info const SSL_CIPHER *cipher = SSL_get_current_cipher(sslArray[0]); if (tlsLogLevel > 0) { printf("[DEBUG] Cipher used: %s\n", SSL_CIPHER_get_name(cipher)); } // Print Peer Certificate info if (tlsLogLevel > 0) { X509 *cert = SSL_get_peer_certificate(sslArray[0]); if (cert != NULL) { char *line; line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf("[DEBUG] Subject: %s\n", line); OPENSSL_free(line); line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf("[DEBUG] Issuer: %s\n", line); OPENSSL_free(line); X509_free(cert); } else { printf("[DEBUG] No certificates.\n"); } } /* Set and activate timeouts */ struct timeval timeout; timeout.tv_sec = 3; timeout.tv_usec = 0; BIO_ctrl(bio_client, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); } #pragma GCC diagnostic pop static int sendDTLS(char *buf, size_t lenBuf) { size_t lenSent; int r, err; lenSent = 0; r = SSL_write(sslArray[0], buf + lenSent, lenBuf - lenSent); if (r > 0) { lenSent += r; } else { err = SSL_get_error(sslArray[0], r); switch (err) { case SSL_ERROR_SYSCALL: printf("[ERROR] SSL_write (SSL_ERROR_SYSCALL): %s\n", strerror(errno)); break; default: printf("[ERROR] while sending data: [%d] %s", err, ERR_error_string(err, NULL)); printf("[ERROR] Reason: %s", ERR_reason_error_string(err)); } exit(1); } return lenSent; } static void closeDTLSSess(void) { printf("closeDTLSSess ENTER\n"); int r; r = SSL_shutdown(sslArray[0]); if (r <= 0) { /* Shutdown not finished, call SSL_read to do a bidirectional shutdown, see doc for more: * https://www.openssl.org/docs/man1.1.1/man3/SSL_shutdown.html */ char rcvBuf[MAX_RCVBUF]; SSL_read(sslArray[0], rcvBuf, MAX_RCVBUF); } SSL_free(sslArray[0]); close(udpsockout); close(udpsockin); printf("closeDTLSSess EXIT\n"); } #else static void initDTLSSess(void) {} static int sendDTLS(__attribute__((unused)) char *buf, __attribute__((unused)) size_t lenBuf) { return 0; } static void closeDTLSSess(void) {} #endif #elif defined(ENABLE_GNUTLS) /* This defines a log function to be provided to GnuTLS. It hopefully * helps us track down hard to find problems. * rgerhards, 2008-06-20 */ static void tlsLogFunction(int level, const char *msg) { printf("GnuTLS (level %d): %s", level, msg); } static void exitTLS(void) { if (tlsPriorityCache != NULL) { gnutls_priority_deinit(tlsPriorityCache); tlsPriorityCache = NULL; } gnutls_certificate_free_credentials(tlscred); gnutls_global_deinit(); } /* global init GnuTLS */ static void initTLS(void) { int r; /* order of gcry_control and gnutls_global_init matters! */ #if GNUTLS_VERSION_NUMBER <= 0x020b00 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif gnutls_global_init(); /* set debug mode, if so required by the options */ if (tlsLogLevel > 0) { gnutls_global_set_log_function(tlsLogFunction); gnutls_global_set_log_level(tlsLogLevel); } r = gnutls_certificate_allocate_credentials(&tlscred); if (r != GNUTLS_E_SUCCESS) { printf("error allocating credentials\n"); gnutls_perror(r); exit(1); } r = gnutls_certificate_set_x509_key_file(tlscred, tlsCertFile, tlsKeyFile, GNUTLS_X509_FMT_PEM); if (r != GNUTLS_E_SUCCESS) { printf("error setting certificate files -- have you mixed up key and certificate?\n"); printf("If in doubt, try swapping the files in -z/-Z\n"); printf("Certifcate is: '%s'\n", tlsCertFile); printf("Key is: '%s'\n", tlsKeyFile); gnutls_perror(r); r = gnutls_certificate_set_x509_key_file(tlscred, tlsKeyFile, tlsCertFile, GNUTLS_X509_FMT_PEM); if (r == GNUTLS_E_SUCCESS) { printf( "Tried swapping files, this seems to work " "(but results may be unpredictable!)\n"); } else { exit(1); } } if (tlsPriorityString != NULL) { const char *err_pos = NULL; r = gnutls_priority_init(&tlsPriorityCache, tlsPriorityString, &err_pos); if (r != GNUTLS_E_SUCCESS) { fprintf(stderr, "tcpflood: invalid GnuTLS priority string '%s': %s", tlsPriorityString, gnutls_strerror(r)); if (err_pos != NULL && *err_pos != '\0') { fprintf(stderr, " near '%s'", err_pos); } fputc('\n', stderr); exit(1); } } } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" static void initTLSSess(const int i) { int r; gnutls_init(sessArray + i, GNUTLS_CLIENT); if (tlsPriorityCache != NULL) { r = gnutls_priority_set(sessArray[i], tlsPriorityCache); } else { r = gnutls_set_default_priority(sessArray[i]); } if (r != GNUTLS_E_SUCCESS) { fprintf(stderr, "Setting GnuTLS priority failed\n"); gnutls_perror(r); exit(1); } /* put our credentials to the current session */ r = gnutls_credentials_set(sessArray[i], GNUTLS_CRD_CERTIFICATE, tlscred); if (r != GNUTLS_E_SUCCESS) { fprintf(stderr, "Setting credentials failed\n"); gnutls_perror(r); exit(1); } /* NOTE: the following statement generates a cast warning, but there seems to * be no way around it with current GnuTLS. Do NOT try to "fix" the situation! */ gnutls_transport_set_ptr(sessArray[i], (gnutls_transport_ptr_t)sockArray[i]); if (handshakeOnly) { int flags = fcntl(sockArray[i], F_GETFL, 0); if (flags != -1) { fcntl(sockArray[i], F_SETFL, flags | O_NONBLOCK); } } /* Perform the TLS handshake */ r = gnutls_handshake(sessArray[i]); if (r < 0) { if (handshakeOnly) { int allow = 0; switch (r) { case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: #ifdef GNUTLS_E_PREMATURE_TERMINATION case GNUTLS_E_PREMATURE_TERMINATION: #endif #ifdef GNUTLS_E_FATAL_ALERT_RECEIVED case GNUTLS_E_FATAL_ALERT_RECEIVED: #endif #ifdef GNUTLS_E_UNEXPECTED_PACKET_LENGTH case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: #endif #ifdef GNUTLS_E_PUSH_ERROR case GNUTLS_E_PUSH_ERROR: #endif #ifdef GNUTLS_E_PULL_ERROR case GNUTLS_E_PULL_ERROR: #endif #ifdef GNUTLS_E_HANDSHAKE_FAILED case GNUTLS_E_HANDSHAKE_FAILED: #endif allow = 1; break; default: break; } if (!allow) { fprintf(stderr, "TLS Handshake failed\n"); gnutls_perror(r); exit(1); } if (verbose && r != GNUTLS_E_AGAIN && r != GNUTLS_E_INTERRUPTED) { fprintf(stderr, "TLS handshake ended early: %s\n", gnutls_strerror(r)); } } else { fprintf(stderr, "TLS Handshake failed\n"); gnutls_perror(r); exit(1); } } if (handshakeOnly) { gnutls_deinit(sessArray[i]); sessArray[i] = NULL; if (sockArray[i] != -1) { close(sockArray[i]); } sockArray[i] = -1; return; } if (r < 0) { fprintf(stderr, "TLS Handshake failed\n"); gnutls_perror(r); exit(1); } } #pragma GCC diagnostic pop static int sendTLS(int i, char *buf, size_t lenBuf) { int lenSent; int r; lenSent = 0; while (lenSent != lenBuf) { r = gnutls_record_send(sessArray[i], buf + lenSent, lenBuf - lenSent); if (r < 0) break; lenSent += r; } return lenSent; } static void closeTLSSess(int i) { if (sessArray == NULL || sessArray[i] == NULL) { return; } gnutls_bye(sessArray[i], GNUTLS_SHUT_RDWR); gnutls_deinit(sessArray[i]); sessArray[i] = NULL; } #else /* NO TLS available */ static void initTLS(void) {} static void exitTLS(void) {} static void initTLSSess(int __attribute__((unused)) i) {} static int sendTLS(int __attribute__((unused)) i, char __attribute__((unused)) * buf, size_t __attribute__((unused)) lenBuf) { return 0; } static void closeTLSSess(int __attribute__((unused)) i) {} static void initDTLSSess(void) {} static int sendDTLS(__attribute__((unused)) char *buf, __attribute__((unused)) size_t lenBuf) { return 0; } static void closeDTLSSess(void) {} #endif static void setTargetPorts(const char *const port_arg) { int i = 0; char *saveptr; char *ports = strdup(port_arg); char *port; if (ports == NULL) { perror("strdup"); exit(1); } port = strtok_r(ports, ":", &saveptr); while (port != NULL) { char *endptr; long parsed_port; if (i == sizeof(targetPort) / sizeof(int)) { fprintf(stderr, "too many ports specified, max %d\n", (int)(sizeof(targetPort) / sizeof(int))); exit(1); } errno = 0; parsed_port = strtol(port, &endptr, 10); if (errno != 0 || *port == '\0' || *endptr != '\0' || parsed_port < 1 || parsed_port > 65535) { fprintf(stderr, "invalid target port '%s'\n", port); exit(1); } targetPort[i] = (int)parsed_port; i++; port = strtok_r(NULL, ":", &saveptr); } if (i == 0) { fprintf(stderr, "empty target port list\n"); exit(1); } free(ports); } static int writeAll(const int fd, const char *buf, const size_t len) { size_t done = 0; while (done < len) { ssize_t written = write(fd, buf + done, len - done); if (written < 0) { if (errno == EINTR) { continue; } return -1; } if (written == 0) { errno = EIO; return -1; } done += (size_t)written; } return 0; } static int writeProperTerminationFile(void) { char content[256]; int fd; int len; int saved_errno; if (properTerminationFile == NULL) { return 0; } #ifndef O_NOFOLLOW fprintf(stderr, "tcpflood: proper termination marker is not supported without O_NOFOLLOW\n"); return 1; #endif len = snprintf(content, sizeof(content), "status=ok\n" "pid=%ld\n" "version=%s\n" "phase=main-exit\n", (long)getpid(), VERSION); if (len < 0 || (size_t)len >= sizeof(content)) { fprintf(stderr, "tcpflood: proper termination marker content too large\n"); return 1; } fd = open(properTerminationFile, O_WRONLY | O_CREAT | O_TRUNC | TCPFLOOD_MARKER_OPEN_FLAGS | O_CLOEXEC, 0600); if (fd < 0) { saved_errno = errno; fprintf(stderr, "tcpflood: cannot open proper termination marker '%s': %s\n", properTerminationFile, strerror(saved_errno)); return 1; } if (writeAll(fd, content, (size_t)len) != 0) { saved_errno = errno; fprintf(stderr, "tcpflood: cannot write proper termination marker '%s': %s\n", properTerminationFile, strerror(saved_errno)); close(fd); return 1; } if (close(fd) != 0) { saved_errno = errno; fprintf(stderr, "tcpflood: cannot close proper termination marker '%s': %s\n", properTerminationFile, strerror(saved_errno)); return 1; } return 0; } /* Run the test. * rgerhards, 2009-04-03 */ int main(int argc, char *argv[]) { int opt; struct sigaction sigAct; struct rlimit maxFiles; static char buf[1024]; struct rlimit limit; int os_max_fds; if (getrlimit(RLIMIT_NOFILE, &limit) != 0) { perror("Failed to get RLIMIT_NOFILE"); exit(1); } os_max_fds = limit.rlim_cur; // Soft limit srand(time(NULL)); /* seed is good enough for our needs */ /* on Solaris, we do not HAVE MSG_NOSIGNAL, so for this reason * we block SIGPIPE (not an issue for this program) */ memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sigAct, NULL); setvbuf(stdout, buf, _IONBF, 48); while ((opt = getopt(argc, argv, "a:ABb:c:C:d:DeE:f:F:g:h:i:I:j:K:k:l:L:m:M:n:o:OP:p:rR:" "q:sS:t:T:u:vW:w:x:XyYz:Z:H")) != -1) { switch (opt) { case 'b': batchsize = atoll(optarg); break; case 't': targetIP = optarg; break; case 'p': setTargetPorts(optarg); break; case 'n': numTargetPorts = atoi(optarg); break; case 'c': numConnections = atoi(optarg); if (numConnections < 0) { numConnections *= -1; softLimitConnections = 1; } break; case 'C': numFileIterations = atoi(optarg); break; case 'm': numMsgsToSend = atoi(optarg); break; case 'i': msgNum = atoi(optarg); break; case 'P': msgPRI = optarg; break; case 'j': jsonCookie = optarg; break; case 'K': { char *endptr; long parsed; errno = 0; parsed = strtol(optarg, &endptr, 10); if (errno != 0 || *optarg == '\0' || *endptr != '\0' || parsed < 0 || parsed > INT_MAX) { fprintf(stderr, "-K requires a non-negative seconds value\n"); exit(1); } holdOpenSeconds = (int)parsed; break; } case 'd': extraDataLen = atoi(optarg); if (extraDataLen > MAX_EXTRADATA_LEN) { fprintf(stderr, "-d max is %d!\n", MAX_EXTRADATA_LEN); exit(1); } break; case 'D': bRandConnDrop = 1; break; case 'l': dbRandConnDrop = atof(optarg); printf("RandConnDrop Level: '%lf' \n", dbRandConnDrop); break; case 'r': bRandomizeExtraData = 1; break; case 'f': dynFileIDs = atoi(optarg); break; case 'g': tlsPriorityString = optarg; break; case 'F': frameDelim = atoi(optarg); break; case 'h': hostname = optarg; break; case 'L': tlsLogLevel = atoi(optarg); break; case 'M': MsgToSend = optarg; break; case 'I': dataFile = optarg; /* in this mode, we do not know the num messages to send, so * we set a (high) number to keep the code happy. */ numMsgsToSend = 1000000; break; case 's': bSilent = 1; break; case 'B': bBinaryFile = 1; break; case 'R': numRuns = atoi(optarg); break; case 'S': sleepBetweenRuns = atoi(optarg); break; case 'X': bStatsRecords = 1; break; case 'e': bCSVoutput = 1; break; case 'T': if (!strcmp(optarg, "udp")) { transport = TP_UDP; } else if (!strcmp(optarg, "tcp")) { transport = TP_TCP; } else if (!strcmp(optarg, "tls")) { #if defined(ENABLE_OSSL) transport = TP_TLS; #elif defined(ENABLE_GNUTLS) transport = TP_TLS; #else fprintf(stderr, "compiled without gnutls/openssl TLS support: " "\"-Ttls\" not supported!\n"); exit(1); #endif } else if (!strcmp(optarg, "relp-plain")) { #if defined(ENABLE_RELP) transport = TP_RELP_PLAIN; #else fprintf(stderr, "compiled without RELP support: " "\"-Trelp-plain\" not supported!\n" "(add --enable-relp to ./configure options " "if desired)\n"); exit(1); #endif } else if (!strcmp(optarg, "relp-tls")) { #if defined(ENABLE_RELP) transport = TP_RELP_TLS; #else fprintf(stderr, "compiled without RELP support: " "\"-Trelp-tls\" not supported!\n" "(add --enable-relp to ./configure options " "if desired)\n"); exit(1); #endif } else if (!strcmp(optarg, "dtls")) { #if defined(ENABLE_OSSL) transport = TP_DTLS; #else fprintf(stderr, "compiled without openssl TLS support: " "\"-Tdtls\" not supported!\n"); exit(1); #endif } else { fprintf(stderr, "unknown transport '%s'\n", optarg); exit(1); } break; case 'a': relpAuthMode = optarg; break; case 'A': abortOnSendFail = 0; break; case 'E': relpPermittedPeer = optarg; break; case 'u': #if defined(HAVE_RELPENGINESETTLSLIBBYNAME) relpTlsLib = optarg; #endif break; case 'W': waittime = atoi(optarg); break; case 'Y': runMultithreaded = 1; break; case 'y': useRFC5424Format = 1; break; case 'x': tlsCAFile = optarg; break; case 'z': tlsKeyFile = optarg; break; case 'Z': tlsCertFile = optarg; break; case 'o': nThreadsConnOpen = atoi(optarg); break; case 'O': octateCountFramed = 1; break; case 'v': verbose = 1; break; case 'k': customConfig = optarg; break; case 'w': portFile = optarg; break; case 'q': properTerminationFile = optarg; break; case 'H': handshakeOnly = true; break; default: printf("invalid option '%c' or value missing - terminating...\n", opt); exit(1); break; } } const char *const ci_env = getenv("CI"); if (ci_env != NULL && !strcmp(ci_env, "true")) { bSilent = 1; /* auto-apply silent option during CI runs */ } if (numConnections >= (os_max_fds - 20)) { fprintf(stderr, "We are asked to use %d connections, but the OS permits only %d " "open file descriptors.\n", numConnections, os_max_fds); if (softLimitConnections) { numConnections = os_max_fds - 20; fprintf(stderr, "We reduced the actual number of connections to %d. " "This leaves some room for opening files.\n", numConnections); } else { fprintf(stderr, "Connection count is hard requirement, so we " "error-terminate\n"); exit(1); } } if (handshakeOnly && transport != TP_TLS) { fprintf(stderr, "-H requires TLS transport (-Ttls)\n"); exit(1); } if (handshakeOnly && portFile != NULL) { fprintf(stderr, "-H cannot be combined with -w\n"); exit(1); } if (tlsPriorityString != NULL) { if (transport != TP_TLS) { fprintf(stderr, "-g requires TLS transport (-Ttls)\n"); exit(1); } #if !defined(ENABLE_GNUTLS) || defined(ENABLE_OSSL) fprintf(stderr, "-g requires tcpflood to use the GnuTLS TLS implementation\n"); exit(1); #endif } if (holdOpenSeconds >= 0) { if (transport != TP_TCP) { fprintf(stderr, "-K is only supported with plain TCP transport\n"); exit(1); } if (numRuns != 1) { fprintf(stderr, "-K cannot be combined with multiple runs (-R must be 1)\n"); exit(1); } if (bRandConnDrop) { fprintf(stderr, "-K cannot be combined with random connection drops (-D)\n"); exit(1); } } if (portFile != NULL && numConnections != 1) { fprintf(stderr, "-w requires exactly one connection\n"); exit(1); } if (portFile != NULL && (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS)) { fprintf(stderr, "-w not supported with RELP\n"); exit(1); } if (tlsCAFile != NULL && transport != TP_RELP_TLS) { #if !defined(ENABLE_OSSL) fprintf(stderr, "-x CAFile not supported in GnuTLS mode - ignored.\n" "Note: we do NOT VERIFY the remote peer when compiled for GnuTLS.\n" "When compiled for OpenSSL, we do.\n"); #endif } if (bStatsRecords && waittime) { fprintf(stderr, "warning: generating performance stats and using a waittime " "is somewhat contradictory!\n"); } if (!isatty(1) || bSilent) bShowProgress = 0; if (numConnections > 20) { /* if we use many (whatever this means, 20 is randomly picked) * connections, we need to make sure we have a high enough * limit. -- rgerhards, 2010-03-25 */ maxFiles.rlim_cur = numConnections + 20; maxFiles.rlim_max = numConnections + 20; if (setrlimit(RLIMIT_NOFILE, &maxFiles) < 0) { perror("setrlimit to increase file handles failed"); fprintf(stderr, "could not set sufficiently large number of " "open files for required connection count!\n"); if (!softLimitConnections) { exit(1); } } } if (dataFile != NULL) { if ((dataFP = fopen(dataFile, "r")) == NULL) { perror(dataFile); exit(1); } } if (tlsKeyFile != NULL || tlsCertFile != NULL) { if (transport != TP_TLS && transport != TP_DTLS && transport != TP_RELP_TLS) { printf( "error: TLS certificates were specified, but TLS is NOT enabled: " "To enable TLS use parameter -Ttls\n"); exit(1); } } if (transport == TP_TLS) { if (tlsKeyFile == NULL || tlsCertFile == NULL) { printf( "error: transport TLS is specified (-Ttls), -z and -Z must also " "be specified\n"); exit(1); } /* Create main CTX Object. Use SSLv23_method for < Openssl 1.1.0 and TLS_method for newer versions! */ #if defined(ENABLE_OSSL) #if OPENSSL_VERSION_NUMBER < 0x10100000L initTLS(SSLv23_method()); #else initTLS(TLS_method()); #endif #else initTLS(); #endif } else if (transport == TP_DTLS) { if (tlsKeyFile == NULL || tlsCertFile == NULL) { printf( "error: transport DTLS is specified (-Tdtls), -z and -Z must also " "be specified\n"); exit(1); } #if defined(ENABLE_OSSL) #ifdef ENABLE_WOLFSSL printf("error: transport DTLS is specified (-Tdtls) but not supported with wolfSSL\n"); exit(1); #else initTLS(DTLS_client_method()); #endif #else printf("error: transport DTLS is specified (-Tdtls) but not supported in GnuTLS driver\n"); exit(1); #endif } else if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { #ifdef ENABLE_RELP initRELP_PLAIN(); #endif } if (openConnections() != 0) { printf("error opening connections\n"); exit(1); } if (portFile != NULL) { int portSock; struct sockaddr_in sin; socklen_t slen = sizeof(sin); portSock = (transport == TP_UDP) ? udpsockout : sockArray[0]; if (getsockname(portSock, (struct sockaddr *)&sin, &slen) != 0) { perror("getsockname()"); exit(1); } FILE *pf = fopen(portFile, "w"); if (pf == NULL) { perror(portFile); exit(1); } if (fprintf(pf, "%u\n", ntohs(sin.sin_port)) < 0) { perror("fprintf to port file"); exit(1); } fclose(pf); } if (!handshakeOnly) { if (runTests() != 0) { printf("error running tests\n"); exit(1); } } holdOpenConnections(); closeConnections(); /* this is important so that we do not finish too early! */ #ifdef ENABLE_RELP if (transport == TP_RELP_PLAIN || transport == TP_RELP_TLS) { CHKRELP(relpEngineDestruct(&pRelpEngine)); } #endif if (nConnDrops > 0 && !bSilent) printf("-D option initiated %ld connection closures\n", nConnDrops); if (!bSilent) printf("End of tcpflood Run\n"); if (transport == TP_TLS) { exitTLS(); } if (writeProperTerminationFile() != 0) { exit(1); } exit(0); } rsyslog-8.2608.0/tests/PaxHeaders/global-maxopenfiles-yaml.sh0000644000000000000000000000013215216464436021140 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.916791016 30 ctime=1787067805.345929116 rsyslog-8.2608.0/tests/global-maxopenfiles-yaml.sh0000775000175000017500000000140515216464436020607 0ustar00rgerrger#!/bin/bash # Validate YAML parity for the modern global maxOpenFiles setting. The config # check includes a YAML singleton global section and verifies that the shared # global-parameter backend accepts the value without activating setrlimit. . ${srcdir:=.}/diag.sh init modpath="${RSYSLOG_MODDIR}" cat >"${RSYSLOG_DYNNAME}.conf" <"${RSYSLOG_DYNNAME}.yaml" <"${RSYSLOG_DYNNAME}.log" 2>&1 rc=$? if [ $rc -ne 0 ]; then echo "FAIL: expected YAML global maxOpenFiles to validate" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-fsync.sh0000644000000000000000000000013215241075234021330 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.750899394 rsyslog-8.2608.0/tests/segmented-diskqueue-fsync.sh0000775000175000017500000000200715241075234020776 0ustar00rgerrger#!/bin/bash # Exercise segmentedDisk with syncQueueFiles enabled. Exact sequence delivery # plus forced-state-write statistics prove the synchronous durability path is # active without relying on timing. . ${srcdir:=.}/diag.sh init require_plugin impstats export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines STATS_FILE="$PWD/${RSYSLOG_DYNNAME}.stats.log" generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" log.file="'$STATS_FILE'" interval="1") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.syncQueueFiles="on" queue.timeoutShutdown="10000" queue.maxFileSize="32k" queue.checkpointInterval="64") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check wait_content 'state.forcedWrites=' "$STATS_FILE" rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_servercert_gtls_clientanon.sh0000644000000000000000000000013215216464436025200 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.915790999 30 ctime=1787067807.637971827 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_servercert_gtls_clientanon.sh0000775000175000017500000000355615216464436024660 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmpstrucdata-invalid-vg.sh0000644000000000000000000000013115241075234021001 xustar0030 mtime=1787067036.629578744 29 atime=1787067036.78158159 30 ctime=1787067807.035960609 rsyslog-8.2608.0/tests/mmpstrucdata-invalid-vg.sh0000775000175000017500000000417715241075234020462 0ustar00rgerrger#!/bin/bash # Verify malformed RFC5424 structured data is rejected without invalid memory # reads or leaks. The oracle is Valgrind; the malformed cases include # delimiter errors plus truncated wire messages so this CI path keeps covering # the module's invalid-SD handling. # This file is part of the rsyslog project, released under ASL 2.0 # rgerhards, 2015-04-30 . ${srcdir:=.}/diag.sh init #skip_platform "FreeBSD" "This test currently does not work on FreeBSD." export USE_VALGRIND="YES" # this test only makes sense with valgrind enabled # uncomment below to set special valgrind options #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" generate_conf add_conf ' module(load="../plugins/mmpstrucdata/.libs/mmpstrucdata") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="mmpstrucdata") if $msg contains "msgnum" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup # we use different message counts as this hopefully aids us # in finding which sample is leaking. For this, check the number # of blocks lost and see what set they match. tcpflood -m100 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM] invalid structured data!\"" tcpflood -m200 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM ] invalid structured data!\"" tcpflood -m300 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM= ] invalid structured data!\"" tcpflood -m400 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 = ] invalid structured data!\"" tcpflood -m500 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM\"" tcpflood -m600 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM=\"" tcpflood -m700 -M "\"<161>1 2003-03-01T01:00:00.000Z mymachine.example.com tcpflood - tag [tcpflood@32473 MSGNUM=\\\"unterminated\"" shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/fac_authpriv.sh0000644000000000000000000000013215241075234016713 xustar0030 mtime=1787067036.618578538 30 atime=1787067036.766581309 30 ctime=1787067804.286909383 rsyslog-8.2608.0/tests/fac_authpriv.sh0000775000175000017500000000124215241075234016361 0ustar00rgerrger#!/bin/bash # This tests proper processing of the authpriv facility. # added 2014-09-16 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n" authpriv.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m$NUMMESSAGES -P 81 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-stream-capped-vg.sh0000644000000000000000000000013215171370365021365 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.916791016 30 ctime=1787067806.655953527 rsyslog-8.2608.0/tests/omhiredis-stream-capped-vg.sh0000775000175000017500000000030315171370365021030 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-stream-capped.sh rsyslog-8.2608.0/tests/PaxHeaders/syslog_caller.c0000644000000000000000000000013215216464436016722 xustar0030 mtime=1782212894.085267138 30 atime=1782715518.916791016 30 ctime=1787067803.631897177 rsyslog-8.2608.0/tests/syslog_caller.c0000664000175000017500000002035415216464436016372 0ustar00rgerrger/* A testing tool that just emits a number of * messages to the system log socket. * * Options * * -s severity (0..7 according to syslog spec, r "rolling", default 6) * -m number of messages to generate (default 500) * -C liblognorm-stdlog channel description * -f message format to use * -u Unix datagram socket path * -L generated message length for Unix datagram mode * -n send a short Unix datagram message with an embedded NUL byte * -w milliseconds to wait after sending messages * * Part of the testbench for rsyslog. * * Copyright 2010-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * -or- * see COPYING.ASL20 in the source distribution * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #if defined(_AIX) #include #else #include #endif #include #include #include #include #include #include #ifdef HAVE_LIBLOGGING_STDLOG #include #endif static enum { FMT_NATIVE, FMT_SYSLOG_INJECT_L, FMT_SYSLOG_INJECT_C } fmt = FMT_NATIVE; static void usage(void) { fprintf(stderr, "usage: syslog_caller [-m messages] [-s severity] [-u socket] [-L length] [-w milliseconds]\n"); exit(1); } /* * Generate a raw syslog message with a priority prefix in `buf`. * * Parameters: * - buf: destination buffer to receive the generated message. * - buflen: size of `buf` in bytes. * - sev: severity value; only the low syslog severity range is used via (sev % 8). * - iRun: message index used in the formatted test message variant. * - msgLen: if greater than zero, generate a fixed-length payload (after "") * filled with 'A' bytes and truncated to fit `buf`; if zero, generate * a formatted test message including run number and severity. * * Returns the generated message length in bytes. */ static size_t genRawMsg( char *buf, const size_t buflen, const int sev, const int iRun, const size_t msgLen, const int embeddedNul) { if (buflen == 0) return 0; buf[0] = '\0'; if (embeddedNul) { const int n = snprintf(buf, buflen, "<%d>", sev % 8); buf[buflen - 1] = '\0'; if (n < 0) return 0; const size_t prefixLen = (size_t)n; if (prefixLen >= buflen || buflen - prefixLen < 4) return prefixLen < buflen ? prefixLen : buflen - 1; buf[prefixLen] = 'a'; buf[prefixLen + 1] = '\0'; buf[prefixLen + 2] = 'b'; return prefixLen + 3; } if (msgLen > 0) { const int n = snprintf(buf, buflen, "<%d>", sev % 8); buf[buflen - 1] = '\0'; if (n < 0) return 0; const size_t prefixLen = (size_t)n; if (prefixLen >= buflen) return buflen - 1; const size_t avail = buflen - prefixLen - 1; const size_t len = msgLen < avail ? msgLen : avail; memset(buf + prefixLen, 'A', len); buf[prefixLen + len] = '\0'; return prefixLen + len; } else { const int n = snprintf(buf, buflen, "<%d>test message nbr %d, severity=%d", sev % 8, iRun, sev % 8); buf[buflen - 1] = '\0'; if (n < 0) return 0; return (size_t)n < buflen ? (size_t)n : buflen - 1; } } /* Send one raw syslog message to a Unix domain datagram socket. * sockName: path to the destination Unix socket. * sev: syslog severity value used when generating the PRI part. * iRun: message sequence number used by the generated text format. * msgLen: payload length for raw/fill mode; 0 uses formatted text mode. */ static void sendRawUnix( const char *sockName, const int sev, const int iRun, const size_t msgLen, const int embeddedNul) { int sock; struct sockaddr_un sa; char msgbuf[4096]; size_t lenMsg; if (sockName == NULL || strlen(sockName) >= sizeof(sa.sun_path)) { fprintf(stderr, "Unix socket path invalid or too long: %s\n", sockName ? sockName : "(null)"); exit(1); } if ((sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { perror("socket"); exit(1); } memset(&sa, 0, sizeof(sa)); sa.sun_family = AF_UNIX; strncpy(sa.sun_path, sockName, sizeof(sa.sun_path) - 1); sa.sun_path[sizeof(sa.sun_path) - 1] = '\0'; lenMsg = genRawMsg(msgbuf, sizeof(msgbuf), sev, iRun, msgLen, embeddedNul); if (sendto(sock, msgbuf, lenMsg, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) { perror("sendto"); close(sock); exit(1); } close(sock); } #ifdef HAVE_LIBLOGGING_STDLOG /* buffer must be large "enough" [4K?] */ static void genMsg(char *buf, const int sev, const int iRun) { switch (fmt) { case FMT_NATIVE: snprintf(buf, 4096, "test message nbr %d, severity=%d", iRun, sev); break; case FMT_SYSLOG_INJECT_L: snprintf(buf, 4096, "%s", "test\n"); break; case FMT_SYSLOG_INJECT_C: snprintf(buf, 4096, "%s", "test 1\t2"); break; } } #endif int main(int argc, char *argv[]) { int i; int opt; int bRollingSev = 0; int sev = 6; int msgs = 500; const char *unixSockName = NULL; size_t msgLen = 0; int waitMs = 0; int embeddedNul = 0; #ifdef HAVE_LIBLOGGING_STDLOG stdlog_channel_t logchan = NULL; const char *chandesc = "syslog:"; char msgbuf[4096]; #endif #ifdef HAVE_LIBLOGGING_STDLOG stdlog_init(STDLOG_USE_DFLT_OPTS); while ((opt = getopt(argc, argv, "m:s:C:f:u:L:nw:")) != -1) { #else while ((opt = getopt(argc, argv, "m:s:u:L:nw:")) != -1) { #endif switch (opt) { case 's': if (*optarg == 'r') { bRollingSev = 1; sev = 0; } else #ifdef HAVE_LIBLOGGING_STDLOG sev = atoi(optarg) % 8; #else sev = atoi(optarg); #endif break; case 'm': msgs = atoi(optarg); break; case 'u': unixSockName = optarg; break; case 'L': msgLen = (size_t)atoi(optarg); if (msgLen >= 4096) msgLen = 4095; break; case 'w': waitMs = atoi(optarg); break; case 'n': embeddedNul = 1; break; #ifdef HAVE_LIBLOGGING_STDLOG case 'C': chandesc = optarg; break; case 'f': if (!strcmp(optarg, "syslog_inject-l")) fmt = FMT_SYSLOG_INJECT_L; else if (!strcmp(optarg, "syslog_inject-c")) fmt = FMT_SYSLOG_INJECT_C; else usage(); break; #endif default: usage(); break; } } if (unixSockName != NULL) { for (i = 0; i < msgs; ++i) { sendRawUnix(unixSockName, sev, i, msgLen, embeddedNul); if (bRollingSev) sev++; } if (waitMs > 0) usleep((unsigned int)waitMs * 1000U); return 0; } #ifdef HAVE_LIBLOGGING_STDLOG if ((logchan = stdlog_open(argv[0], 0, STDLOG_LOCAL1, chandesc)) == NULL) { fprintf(stderr, "error opening logchannel '%s': %s\n", chandesc, strerror(errno)); exit(1); } #endif for (i = 0; i < msgs; ++i) { #ifdef HAVE_LIBLOGGING_STDLOG genMsg(msgbuf, sev, i); if (stdlog_log(logchan, sev, "%s", msgbuf) != 0) { perror("error writing log record"); exit(1); } #else syslog(sev % 8, "test message nbr %d, severity=%d", i, sev % 8); #endif if (bRollingSev) #ifdef HAVE_LIBLOGGING_STDLOG sev = (sev + 1) % 8; #else sev++; #endif } return (0); } rsyslog-8.2608.0/tests/PaxHeaders/dynstats_ctr_reset.sh0000644000000000000000000000013115131231047020154 xustar0030 mtime=1768239655.701212533 30 atime=1782715518.916791016 29 ctime=1787067806.69095418 rsyslog-8.2608.0/tests/dynstats_ctr_reset.sh0000777000175000017500000000476315131231047017640 0ustar00rgerrger#!/bin/bash # added 2015-11-16 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo \[dynstats_ctr_reset.sh\]: test to ensure correctness of stats-ctr reset . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on") template(name="outfmt" type="string" string="%msg%\n") dyn_stats(name="msg_stats_resettable_on" resettable="on") dyn_stats(name="msg_stats_resettable_off" resettable="off") dyn_stats(name="msg_stats_resettable_default") set $.msg_prefix = field($msg, 32, 1); set $.x = dyn_inc("msg_stats_resettable_on", $.msg_prefix); set $.y = dyn_inc("msg_stats_resettable_off", $.msg_prefix); set $.z = dyn_inc("msg_stats_resettable_default", $.msg_prefix); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg_file $srcdir/testsuites/dynstats_input_1 injectmsg_file $srcdir/testsuites/dynstats_input_2 wait_queueempty sleep 1 injectmsg_file $srcdir/testsuites/dynstats_input_3 wait_queueempty sleep 1 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check "foo 006" custom_content_check 'bar=1' "${RSYSLOG_DYNNAME}.out.stats.log" first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1 first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_on.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2 . $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 . $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1 . $srcdir/diag.sh assert-first-column-sum-greater-than 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_off.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2 first_column_sum_check 's/.*foo=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*foo=' "${RSYSLOG_DYNNAME}.out.stats.log" 3 first_column_sum_check 's/.*bar=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*bar=' "${RSYSLOG_DYNNAME}.out.stats.log" 1 first_column_sum_check 's/.*baz=\([0-9]*\)/\1/g' 'msg_stats_resettable_default.*baz=' "${RSYSLOG_DYNNAME}.out.stats.log" 2 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_int2Hex.sh0000644000000000000000000000013215241075234017327 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067804.863920135 rsyslog-8.2608.0/tests/rscript_int2Hex.sh0000775000175000017500000000144715241075234017004 0ustar00rgerrger#!/bin/bash # add 2017-02-09 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $!ip!v0 = int2hex(""); set $!ip!v1 = int2hex("0"); set $!ip!v2 = int2hex("1"); set $!ip!v4 = int2hex("375894"); set $!ip!v6 = int2hex("16"); set $!ip!v8 = int2hex("4294967295"); set $!ip!e1 = int2hex("a"); template(name="outfmt" type="string" string="%!ip%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown export EXPECTED='{ "v0": "0", "v1": "0", "v2": "1", "v4": "5bc56", "v6": "10", "v8": "ffffffff", "e1": "NAN" }' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_omudpspoof-bigmsg.sh0000644000000000000000000000013215216464436021270 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.915790999 30 ctime=1787067807.809975032 rsyslog-8.2608.0/tests/sndrcv_omudpspoof-bigmsg.sh0000775000175000017500000003436615216464436020753 0ustar00rgerrger#!/bin/bash # This runs sends and receives big messages via OMUDPSPOOF # added 2020-04-07 alorbach # This file is part of the rsyslog project, released under GPLv3 echo This test must be run as root [raw socket access required] if [ "$EUID" -ne 0 ]; then exit 77 # Not root, skip this test fi export TCPFLOOD_EXTRA_OPTS="-b1 -W1" export NUMMESSAGES=1 export MESSAGESIZE=65000 #65000 #32768 #16384 #export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" #export RSYSLOG_DEBUGLOG="log" . ${srcdir:=.}/diag.sh init # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf export PORT_UDP_FILE="${RSYSLOG_DYNNAME}.imudp_port" add_conf ' module(load="../plugins/imudp/.libs/imudp") global ( maxMessageSize="64k" ) input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_UDP_FILE'" ruleset="rsImudp") $template outfmt,"%msg%\n" ruleset(name="rsImudp") { action( name="UDPOUT" type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content PORT_UDP "$PORT_UDP_FILE" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omudpspoof/.libs/omudpspoof") global ( maxMessageSize="64k" ) # this listener is for message generation by the test framework! input(type="imtcp" port="'$TCPFLOOD_PORT'" ruleset="rsImtcp") $template spoofaddr,"127.0.0.1" ruleset(name="rsImtcp") { action( name="MTUTEST" type="omudpspoof" Target="127.0.0.1" Port="'$PORT_UDP'" SourceTemplate="spoofaddr" mtu="1500") # for comparison only -> action(name="MTUTEST" type="omfwd" Target="127.0.0.1" Port="'$PORT_UDP'") } ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. # tcpflood -m$NUMMESSAGES -i1 -d 1024 tcpflood -m$NUMMESSAGES -i1 -d $MESSAGESIZE sleep 5 # make sure all data is received in input buffers # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # do the final check content_count_check "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ${NUMMESSAGES} rsyslog-8.2608.0/tests/PaxHeaders/failover-no-basic-vg.sh0000644000000000000000000000013215035412264020151 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.915790999 30 ctime=1787067805.207926545 rsyslog-8.2608.0/tests/failover-no-basic-vg.sh0000777000175000017500000000160715035412264017626 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi echo =============================================================================== echo \[failover-no-basic.sh\]: basic test for failover functionality - no failover . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $RepeatedMsgReduction off # second action should never execute :msg, contains, "msgnum:" /dev/null $ActionExecOnlyWhenPreviousIsSuspended on & ./'"${RSYSLOG_OUT_LOG}"' ' startup_vg injectmsg 0 5000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg # now we need our custom logic to see if the result file is empty # (what it should be!) cmp $RSYSLOG_OUT_LOG /dev/null if [ $? -eq 1 ] then echo "ERROR, output file not empty" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/queue-encryption-disk_keyfile-vg.sh0000644000000000000000000000013215035412264022625 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.915790999 30 ctime=1787067805.317928595 rsyslog-8.2608.0/tests/queue-encryption-disk_keyfile-vg.sh0000777000175000017500000000207615035412264022303 0ustar00rgerrger#!/bin/bash # addd 2018-09-30 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.filename="mainq" queue.type="disk" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutshutdown="20000" queue.timeoutenqueue="300000" queue.lowwatermark="5000" queue.cry.provider="gcry" queue.cry.keyfile="'$RSYSLOG_DYNNAME.keyfile'" queue.saveonshutdown="on" ) template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") :omtesting:sleep 0 5000 :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' printf "1234567890123456" > $RSYSLOG_DYNNAME.keyfile startup_vg_noleak # we WILL leak due to the immediate shutdown injectmsg 0 1000 shutdown_immediate wait_shutdown_vg check_exit_vg echo INFO: queue files in ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool check_not_present "msgnum:0000" ${RSYSLOG_DYNNAME}.spool/mainq.0* exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-mmutf8fix-replacement-sequence.sh0000644000000000000000000000013215241075234023232 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.696579998 30 ctime=1787067805.683935415 rsyslog-8.2608.0/tests/yaml-mmutf8fix-replacement-sequence.sh0000775000175000017500000000267215241075234022710 0ustar00rgerrger#!/bin/bash # Verify mmutf8fix replacementSequence in a YAML-loaded configuration. The # ruleset body is supplied via YAML script so message-modification action # ordering matches the RainerScript action path, and success is proven by the # configured omfile output after synchronized shutdown. # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_yaml_support require_plugin imtcp export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' cat > "${RSYSLOG_DYNNAME}.yaml" << YAMLEOF modules: - load: "../plugins/mmutf8fix/.libs/mmutf8fix" - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg%\\n" rulesets: - name: main script: | action(type="mmutf8fix" replacementSequence="\xef\xbf\xbd") action(type="omfile" file="${RSYSLOG_OUT_LOG}" template="outfmt") YAMLEOF startup printf '<129>Mar 10 01:00:00 host tag: has\xc0invalid\n' > "$RSYSLOG_DYNNAME.input" tcpflood -m1 -I "$RSYSLOG_DYNNAME.input" rm -f "$RSYSLOG_DYNNAME.input" wait_file_lines "$RSYSLOG_OUT_LOG" 1 60 shutdown_when_empty wait_shutdown printf ' has\357\277\275invalid\n' > "$RSYSLOG_OUT_LOG.expect" cmp_exact_file "$RSYSLOG_OUT_LOG.expect" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-symlink.sh0000644000000000000000000000013215131231047017163 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.915790999 30 ctime=1787067808.005978684 rsyslog-8.2608.0/tests/imfile-symlink.sh0000777000175000017500000000501515131231047016635 0ustar00rgerrger#!/bin/bash # This test creates multiple symlinks (all watched by rsyslog via wildcard) # chained to target files via additional symlinks and checks that all files # are recorded with correct corresponding metadata (name of symlink # matching configuration). # This is part of the rsyslog testbench, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export IMFILEINPUTFILES="10" export IMFILELASTINPUTLINES="3" export IMFILECHECKTIMEOUT="60" # generate input files first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). mkdir $RSYSLOG_DYNNAME.statefiles generate_conf add_conf ' # comment out if you need more debug info: global( debug.whitelist="on" debug.files=["imfile.c"]) module(load="../plugins/imfile/.libs/imfile" statefile.directory="'${RSYSLOG_DYNNAME}'.statefiles" mode="inotify" normalizePath="off") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input-symlink.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value=", filename: ") property(name="$!metadata!filename") constant(value=", fileoffset: ") property(name="$!metadata!fileoffset") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file="'${RSYSLOG_OUT_LOG}'" template="outfmt") ' ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input-symlink.log mkdir $RSYSLOG_DYNNAME.targets # Start rsyslog now before adding more files startup for i in $(seq 2 $IMFILEINPUTFILES); do printf '\ncreating %s\n' $RSYSLOG_DYNNAME.targets/$i.log ./inputfilegen -m 1 -i $((i-1)) > $RSYSLOG_DYNNAME.targets/$i.log ls -l $RSYSLOG_DYNNAME.targets/$i.log ln -sv $RSYSLOG_DYNNAME.targets/$i.log $RSYSLOG_DYNNAME.link.$i.log ln -sv $RSYSLOG_DYNNAME.link.$i.log $RSYSLOG_DYNNAME.input.$i.log printf '%s generated file %s\n' "$(tb_timestamp)" "$i" ls -l $RSYSLOG_DYNNAME.link.$i.log # wait until this file has been processed content_check_with_count "HEADER msgnum:000000" $i $IMFILECHECKTIMEOUT done ./inputfilegen -m $IMFILELASTINPUTLINES > $RSYSLOG_DYNNAME.input.$((IMFILEINPUTFILES + 1)).log ls -l $RSYSLOG_DYNNAME.input.* $RSYSLOG_DYNNAME.link.* $RSYSLOG_DYNNAME.targets # Content check with timeout content_check_with_count "input.11.log" $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/json_var_case.sh0000644000000000000000000000013215241075234017054 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.778581533 30 ctime=1787067807.229964224 rsyslog-8.2608.0/tests/json_var_case.sh0000775000175000017500000000275515241075234016534 0ustar00rgerrger#!/bin/bash # added 2015-11-24 by portant # This file is part of the rsyslog project, released under ASL 2.0 echo =========================================================================================== echo \[json_var_case.sh\]: test for JSON upper and lower case variables, and leading underscores . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(variables.casesensitive="on") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # we must make sure the template contains references to the variables template(name="outfmt" type="string" string="abc:%$!abc% ABC:%$!ABC% aBc:%$!aBc% _abc:%$!_abc% _ABC:%$!_ABC% _aBc:%$!_aBc%\n" option.casesensitive="on") template(name="outfmt-all-json" type="string" string="%$!all-json%\n") action(type="mmjsonparse") set $!_aBc = "7"; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") if $!_aBc != "7" then action(type="omfile" file="./'"${RSYSLOG2_OUT_LOG}"'" template="outfmt-all-json") ' startup tcpflood -m 1 -M "\"<167>Nov 6 12:34:56 172.0.0.1 test: @cee: { \\\"abc\\\": \\\"1\\\", \\\"ABC\\\": \\\"2\\\", \\\"aBc\\\": \\\"3\\\", \\\"_abc\\\": \\\"4\\\", \\\"_ABC\\\": \\\"5\\\", \\\"_aBc\\\": \\\"6\\\" }\"" echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown # NOTE: conf file updates _aBc to "7" content_check "abc:1 ABC:2 aBc:3 _abc:4 _ABC:5 _aBc:7" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-rename.sh0000644000000000000000000000013215216464436016762 xustar0030 mtime=1782212894.055266653 30 atime=1782715518.916791016 30 ctime=1787067808.002978628 rsyslog-8.2608.0/tests/imfile-rename.sh0000775000175000017500000000414215216464436016432 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . $srcdir/diag.sh check-inotify-only . ${srcdir:=.}/diag.sh init export TESTMESSAGES=10000 export RETRIES=50 export TESTMESSAGESFULL=19999 generate_conf add_conf ' $WorkDirectory '$RSYSLOG_DYNNAME'.spool /* Filter out busy debug output */ global( debug.whitelist="off" debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"] ) module( load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on" ) input(type="imfile" File="/does/not/exist/*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on" ) $template outfmt,"%msg:F,58:2%\n" if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) if $msg contains "imfile:" then action( type="omfile" file="'$RSYSLOG_DYNNAME.errmsgs'" ) ' # generate input file first. ./inputfilegen -m $TESTMESSAGES > $RSYSLOG_DYNNAME.input.1.log ls -l $RSYSLOG_DYNNAME.input* startup # sleep a little to give rsyslog a chance to begin processing wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGES $RETRIES # Move to another filename mv $RSYSLOG_DYNNAME.input.1.log rsyslog.input.2.log ./msleep 500 # Write into the renamed file echo 'testmessage1 testmessage2' >> rsyslog.input.2.log ./msleep 500 if grep "imfile: internal error? inotify provided watch descriptor" < "$RSYSLOG_DYNNAME.errmsgs" ; then echo "Error: inotify event from renamed file" exit 1 fi # generate some more input into moved file ./inputfilegen -m $TESTMESSAGES -i $TESTMESSAGES >> $RSYSLOG_DYNNAME.input.2.log ls -l $RSYSLOG_DYNNAME.input* echo ls ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool ./msleep 500 msgcount=$((2 * TESTMESSAGES)) wait_file_lines $RSYSLOG_OUT_LOG $msgcount $RETRIES shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! seq_check 0 $TESTMESSAGESFULL exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-retry-metadata.sh0000644000000000000000000000013215216464436021563 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.916791016 30 ctime=1787067805.975940856 rsyslog-8.2608.0/tests/omhttp-batch-retry-metadata.sh0000775000175000017500000000462715216464436021243 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # # Verify omhttp batch retry metadata. The helper returns retryable HTTP 207 # responses at a fixed cadence; success is complete sequence delivery plus # metadata output that records the response for retried messages. # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 omhttp_start_server 0 --fail-every 100 --fail-with 207 port="$omhttp_server_lstnport" generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="2048") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") # Echo message as-is for retry template(name="tpl_echo" type="string" string="%msg%\n") # Echo response as-is for retry template(name="tpl_response" type="string" string="{ \"message\": %msg%, \"response\": %$!omhttp!response% }\n") ruleset(name="ruleset_omhttp_retry") { #action(type="omfile" file="'$RSYSLOG_DYNNAME/omhttp.message.log'" template="tpl_echo") # log the response action(type="omfile" file="'$RSYSLOG_DYNNAME/omhttp.response.log'" template="tpl_response") action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl_echo" server="localhost" serverport="'$port'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="kafkarest" httpretrycodes=["207","500"] retry="on" retry.ruleset="ruleset_omhttp_retry" retry.addmetadata="on" # Auth usehttps="off" ) & stop } ruleset(name="ruleset_omhttp") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$port'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="kafkarest" httpretrycodes=["207", "500"] retry="on" retry.ruleset="ruleset_omhttp_retry" retry.addmetadata="on" # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $port my/endpoint kafkarest omhttp_stop_server seq_check cat -n ${RSYSLOG_DYNNAME}/omhttp.response.log omhttp_validate_metadata_response exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-x509valid.sh0000644000000000000000000000013215241075234020655 xustar0030 mtime=1787067036.626578688 30 atime=1787067036.777581515 30 ctime=1787067807.471968733 rsyslog-8.2608.0/tests/imtcp-tls-ossl-x509valid.sh0000775000175000017500000000226315241075234020327 0ustar00rgerrger#!/bin/bash # added 2018-04-27 by alorbach # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/certvalid" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_unflatten_arg1_unsuitable-vg.sh0000644000000000000000000000013115171370365023571 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.916791016 29 ctime=1787067806.90295813 rsyslog-8.2608.0/tests/rscript_unflatten_arg1_unsuitable-vg.sh0000775000175000017500000000013215171370365023235 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_unflatten_arg1_unsuitable.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-rebind-tcp.sh0000644000000000000000000000013015241075234017377 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.783581627 30 ctime=1787067805.519932359 rsyslog-8.2608.0/tests/omfwd-rebind-tcp.sh0000775000175000017500000000217115241075234017051 0ustar00rgerrger#!/bin/bash # Verify that TCP rebind preserves forwarding while repeatedly tearing down # and reconnecting the target transport. The tiny rebind interval forces the # rebind path for every message; the receiver sequence check proves all data # still arrives. When sourced by the -vg wrapper, Valgrind is the oracle for # leaked rebind-side allocations. This guards # https://github.com/rsyslog/rsyslog/issues/6663. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=40 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' action(type="omfwd" target="127.0.0.1" protocol="tcp" port="'$RCVR_PORT'" rebindinterval="1") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp_framing_regex.sh0000644000000000000000000000013215241075234020251 xustar0030 mtime=1787067036.627578706 30 atime=1787067036.777581515 30 ctime=1787067805.480931632 rsyslog-8.2608.0/tests/imtcp_framing_regex.sh0000775000175000017500000000232415241075234017721 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $EscapeControlCharactersOnReceive off module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="remote" framing.delimiter.regex="^<[0-9]{2}>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)") template(name="outfmt" type="string" string="NEWMSG: %rawmsg%\n") ruleset(name="remote") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -B -I ${srcdir}/testsuites/imptcp_framing_regex.testdata shutdown_when_empty wait_shutdown export EXPECTED='NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test1 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test xml-ish NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test2 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi line1 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi l i n e2 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test3 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag multi line3 NEWMSG: <33>Mar 1 01:00:00 172.20.245.8 tag test4' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-multi-drvr-basic-ptcp_gtls_mbedtls.sh0000644000000000000000000000013215241075234024245 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.772581421 30 ctime=1787067807.375966945 rsyslog-8.2608.0/tests/imtcp-multi-drvr-basic-ptcp_gtls_mbedtls.sh0000775000175000017500000000342215241075234023715 0ustar00rgerrger#!/bin/bash # This test checks imtcp functionality with multiple drivers running together. It is # a minimal test. # added 2021-04-27 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=60000 # must be evenly dividable by 3 export QUEUE_EMPTY_CHECK_FUNC=wait_seq_check generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" name="i1" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" name="i2" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port2") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port3" name="i3" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2" assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3" tcpflood -p$TCPFLOOD_PORT -m$((NUMMESSAGES / 3)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem tcpflood -p$TCPFLOOD_PORT2 -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3)) tcpflood -p$RS_PORT -m$((NUMMESSAGES / 3)) -i$((NUMMESSAGES / 3 * 2)) -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-consumerGroup-noack-vg.sh0000644000000000000000000000013215171370365024064 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.916791016 30 ctime=1787067806.586952242 rsyslog-8.2608.0/tests/imhiredis-stream-consumerGroup-noack-vg.sh0000775000175000017500000000032015171370365023526 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/imhiredis-stream-consumerGroup-noack.sh rsyslog-8.2608.0/tests/PaxHeaders/yaml-segmented-da-config-errors.sh0000644000000000000000000000013215241075234022312 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.697580017 30 ctime=1787067803.850901258 rsyslog-8.2608.0/tests/yaml-segmented-da-config-errors.sh0000775000175000017500000000421315241075234021761 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Verify YAML uses the same DA parameter validation as RainerScript. A # segmented-only queue is an invalid context: permissive validation must retain # startup compatibility while reporting the dirty configuration, and strict # validation must reject it. Explicit classic options that have no effect are # likewise rejected in strict mode. . ${srcdir:=.}/diag.sh init assert_contains() { grep -Fq "$2" "$1" || { cat "$1" error_exit 1 "missing expected YAML diagnostic: $2" } } write_loader() { generate_conf add_conf 'include(file="'${TESTCONF_NM}'.yaml")' rm -f "${TESTCONF_NM}.yaml" } validate_permissive_context() { write_loader add_yaml_conf 'global:' add_yaml_conf ' workDirectory: "'${RSYSLOG_DYNNAME}'.spool"' add_yaml_conf 'mainqueue:' add_yaml_conf ' queue.type: segmentedDisk' add_yaml_conf ' queue.filename: mainq' add_yaml_conf ' queue.diskQueueType: disk' add_yaml_conf ' queue.diskQueueAutoUpgrade: on' add_yaml_conf ' queue.diskQueueIdleTimeout: 25' local out="${RSYSLOG_DYNNAME}.yaml-permissive.log" export RS_REDIR=">\"$out\" 2>&1" startup shutdown_when_empty wait_shutdown unset RS_REDIR assert_contains "$out" 'apply only to FixedArray or LinkedList disk-assisted queues' } validate_strict_options() { write_loader add_yaml_conf 'global:' add_yaml_conf ' abortOnUncleanConfig: on' add_yaml_conf ' workDirectory: "'${RSYSLOG_DYNNAME}'.spool"' add_yaml_conf 'mainqueue:' add_yaml_conf ' queue.type: FixedArray' add_yaml_conf ' queue.filename: mainq' add_yaml_conf ' queue.diskQueueType: disk' add_yaml_conf ' queue.diskQueueAutoUpgrade: on' add_yaml_conf ' queue.diskQueueIdleTimeout: 25' local out="${RSYSLOG_DYNNAME}.yaml-strict.log" if ../tools/rsyslogd -C -N1 -f"${TESTCONF_NM}.conf" -M../runtime/.libs:../.libs >"$out" 2>&1; then error_exit 1 "strict meaningless YAML DA options unexpectedly passed" fi assert_contains "$out" 'queue.diskQueueAutoUpgrade applies only' assert_contains "$out" 'queue.diskQueueIdleTimeout does not apply' } validate_permissive_context validate_strict_options exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zlib-z-prefix.sh0000644000000000000000000000013115241075234022642 xustar0029 mtime=1787067036.62457865 30 atime=1787067036.685579792 30 ctime=1787067805.574933383 rsyslog-8.2608.0/tests/imtcp-stream-always-zlib-z-prefix.sh0000775000175000017500000000343315241075234022315 0ustar00rgerrger#!/bin/bash # Regression test for the generic imtcp zlib stream decompression path with a # decompressed payload that begins with literal "z". Legacy single-message # compression also uses a leading "z" in built-in transport frame handling, but # stream:always has already selected zlib stream decompression and must not run # legacy-z handling on decoded bytes. The oracle is delivery of the raw # z-prefixed message and absence of the legacy decompression-error diagnostic. # # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp check_command_available python3 generate_conf add_conf ' global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zlib") template(name="rawline" type="string" string="%rawmsg%\n") if $syslogtag contains "rsyslogd" then { action(type="omfile" file="'$RSYSLOG2_OUT_LOG'") stop } *.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="rawline") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" python3 - <<'PY' import os import socket import zlib port = int(os.environ["TCPFLOOD_PORT"]) payload = b"zimtcp stream payload starts z after zlib inflate\n" compressor = zlib.compressobj() wire = compressor.compress(payload) + compressor.flush() with socket.create_connection(("127.0.0.1", port), timeout=10) as sock: sock.sendall(wire) PY wait_file_lines "$RSYSLOG_OUT_LOG" 1 shutdown_when_empty wait_shutdown content_check "zimtcp stream payload starts z after zlib inflate" "$RSYSLOG_OUT_LOG" check_not_present "Uncompression of a message failed" "$RSYSLOG2_OUT_LOG" check_not_present "received invalid compressed stream" "$RSYSLOG2_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-final-symlink.sh0000644000000000000000000000013215241075234021012 xustar0030 mtime=1787067036.617578519 30 atime=1787067036.682579736 30 ctime=1787067804.436912178 rsyslog-8.2608.0/tests/diskqueue-final-symlink.sh0000775000175000017500000000400715241075234020462 0ustar00rgerrger#!/bin/bash # Verify that a persistent disk queue rejects a symlinked segment file. The # first phase saves a real segmented queue; the second replaces its newest # final-path-component segment with a link to a copy. A legacy queue would # resume through the link and append the new message to that copied segment. # The oracle is the target checksum after shutdown, so a daemon diagnostic or # timing-dependent failure cannot make the test pass. The 20ms action delay # makes the 100-message setup batch remain on disk long enough to preserve # multiple 16KiB segments before the deliberately immediate shutdown. # added 2026-07-24 by Codex, released under ASL 2.0 . ${srcdir:=.}/diag.sh init SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" TARGET_FILE="${RSYSLOG_DYNNAME}.queue-target" TARGET_SUM="${RSYSLOG_DYNNAME}.queue-target.sum" write_conf() { generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") global(workDirectory="'"$SPOOL_DIR"'") main_queue( queue.type="disk" queue.filename="mainq" queue.maxFileSize="16k" queue.saveOnShutdown="on" queue.timeoutShutdown="1" ) template(name="outfmt" type="string" string="%msg:F,58:2%\\n") :omtesting:sleep 0 20000 if ($msg contains "msgnum:") then { action(type="omfile" template="outfmt" file="'"$RSYSLOG_OUT_LOG"'") } ' } rm -rf "$SPOOL_DIR" rm -f "$TARGET_FILE" "$TARGET_SUM" write_conf startup injectmsg 0 100 shutdown_immediate wait_shutdown SEGMENT_FILE=$(find "$SPOOL_DIR" -maxdepth 1 -type f -name 'mainq.[0-9]*' | sort | tail -n 1) if [ -z "$SEGMENT_FILE" ]; then echo "FAIL: first phase did not preserve a disk queue segment" ls -l "$SPOOL_DIR" error_exit 1 fi cp "$SEGMENT_FILE" "$TARGET_FILE" || error_exit 1 cksum "$TARGET_FILE" > "$TARGET_SUM" || error_exit 1 rm -f "$SEGMENT_FILE" ln -s "../$TARGET_FILE" "$SEGMENT_FILE" || error_exit 1 write_conf startup injectmsg 100 1 shutdown_immediate wait_shutdown if ! cksum "$TARGET_FILE" | cmp -s - "$TARGET_SUM"; then echo "FAIL: disk queue followed final-component segment symlink" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_script_error.sh0000644000000000000000000000013115241075234020522 xustar0029 mtime=1787067036.64057895 30 atime=1787067036.792581796 30 ctime=1787067804.880920452 rsyslog-8.2608.0/tests/rscript_script_error.sh0000775000175000017500000000175615241075234020203 0ustar00rgerrger#!/bin/bash # Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!%\n") local4.* { set $!valid!serial = parse_time("2017-10-05T01:10:11Z"); set $!valid!error = script_error(); set $!invalid!serial = parse_time("not a date/time"); set $!invalid!error = script_error(); set $!valid2!serial = parse_time("2017-10-05T01:10:11Z"); set $!valid2!error = script_error(); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 shutdown_when_empty wait_shutdown # Our fixed and calculated expected results export EXPECTED='{ "valid": { "serial": 1507165811, "error": 0 }, "invalid": { "serial": 0, "error": 1 }, "valid2": { "serial": 1507165811, "error": 0 } }' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/suspend-omfwd-via-file.sh0000644000000000000000000000013215216464436020535 xustar0030 mtime=1782212894.085267138 30 atime=1782715518.916791016 30 ctime=1787067804.718917433 rsyslog-8.2608.0/tests/suspend-omfwd-via-file.sh0000775000175000017500000000337515216464436020214 0ustar00rgerrger#!/bin/bash # Verify omfwd action suspension and resumption controlled by an external state # file. The oracle is the complete forwarded sequence after the action is first # active, then suspended, then resumed. The receiver readiness wait keeps this # focused on external-state suspension instead of listener startup timing. # This file is part of the rsyslog project, released under ASL 2.0 # Written 2019-07-10 by Rainer Gerhards . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 #export NUMMESSAGES=100 #00 generate_conf add_conf ' /* Filter out busy debug output, comment out if needed */ global( debug.whitelist="on" debug.files=["ruleset.c", "../action.c", "omfwd.c"] ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" { action(name="forwarder" type="omfwd" template="outfmt" target="127.0.0.1" port="'$TCPFLOOD_PORT'" protocol="tcp" action.externalstate.file="'$RSYSLOG_DYNNAME'.STATE" action.resumeRetryCount="-1" action.resumeinterval="1") } ' start_minitcpsrv_ready "$RSYSLOG_OUT_LOG" "$TCPFLOOD_PORT" startup injectmsg 0 5000 #injectmsg 0 5 printf '\n%s %s\n' "$(tb_timestamp)" \ 'checking that action becomes suspended via external state file' printf "%s" "SUSPENDED" > $RSYSLOG_DYNNAME.STATE ./msleep 2000 # ensure ResumeInterval expired (NOT sensitive to slow machines --> absolute time!) injectmsg 5000 1000 #injectmsg 5 5 printf '\n%s %s\n' "$(tb_timestamp)" \ 'checking that action becomes resumed again via external state file' ./msleep 2000 # ensure ResumeInterval expired (NOT sensitive to slow machines --> absolute time!) printf "%s" "READY" > $RSYSLOG_DYNNAME.STATE injectmsg 6000 4000 #export QUEUE_EMPTY_CHECK_FUNC=check_q_empty_log2 wait_queueempty seq_check shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/ommail-sendmail.sh0000644000000000000000000000013215216464436017320 xustar0030 mtime=1782212894.079267041 30 atime=1782715518.916791016 30 ctime=1787067805.697935676 rsyslog-8.2608.0/tests/ommail-sendmail.sh0000775000175000017500000000233615216464436016773 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/ommail/.libs/ommail") template(name="mailBody" type="string" string="alert %msg%\\r\\n.second line\\r\\n") if $msg contains "msgnum:" then { action( type="ommail" mode="sendmail" sendmail.binary="'$srcdir'/testsuites/ommail-sendmail-bin.sh" mailfrom="rsyslog@example.net" mailto=["operator@example.net", "admin@example.net"] subject.text="rsyslog alert" body.enable="on" template="mailBody" ) } ' startup injectmsg 0 1 shutdown_when_empty wait_shutdown content_check "ARGV_BEGIN" content_check "ARG:-i" content_check "ARG:-f" content_check "ARG:rsyslog@example.net" content_check "ARG:--" content_check "ARG:operator@example.net" content_check "ARG:admin@example.net" content_check "STDIN_BEGIN" content_check "Date: " content_check "From: " content_check "To: , " content_check "Subject: rsyslog alert" content_check "X-Mailer: rsyslog-ommail" content_check "alert msgnum:00000000:" content_check ".second line" content_check "STDIN_END" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-queue-vg.sh0000644000000000000000000000013215171370365017764 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.915790999 30 ctime=1787067806.638953211 rsyslog-8.2608.0/tests/omhiredis-queue-vg.sh0000775000175000017500000000027315171370365017435 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-queue.sh rsyslog-8.2608.0/tests/PaxHeaders/mainq_actq_DA.sh0000644000000000000000000000013215035412264016720 xustar0030 mtime=1752569012.399757696 30 atime=1782715518.915790999 30 ctime=1787067804.359910743 rsyslog-8.2608.0/tests/mainq_actq_DA.sh0000777000175000017500000000145315035412264016374 0ustar00rgerrger#!/bin/bash # Test to check that mainq and actionq can be disk assisted without # any problems. This was created to reproduce a segfault issue: # https://github.com/rsyslog/rsyslog/issues/3681 # added 2019-06-03 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 # we just need a handful - we primarily test startup generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.fileName="main" queue.type="LinkedList") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" queue.type="linkedList" queue.fileName="action") ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/tls-check-for-certificate.sh0000644000000000000000000000013115241075234021160 xustar0030 mtime=1787067036.647579081 30 atime=1787067036.800581945 29 ctime=1787067808.22898284 rsyslog-8.2608.0/tests/tls-check-for-certificate.sh0000775000175000017500000000153415241075234020633 0ustar00rgerrger#!/bin/bash # add 2017-05-05 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( defaultNetstreamDriver="gtls" defaultNetstreamDriverKeyFile="tls-certs/key.pem" defaultNetstreamDriverCertFile="tls-certs/cert.pem" defaultNetstreamDriverCaFile="tls-certs/ca.pem" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum" then { action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) } ' startup tcpflood -m1000 -Ttls -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown seq_check 0 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_omsnmpv1_udp.sh0000644000000000000000000000013115216464436020256 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.917791033 30 ctime=1787067805.666935098 rsyslog-8.2608.0/tests/sndrcv_omsnmpv1_udp.sh0000775000175000017500000000221215216464436017723 0ustar00rgerrger#!/bin/bash # alorbach, 2019-11-27 # Required Packages # pip install pysnmp # # Ubuntu 18 Packages needed # apt install snmp libsnmp-dev snmp-mibs-downloader # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export TESTMESSAGES=10 generate_conf PORT_SNMP="$(get_free_port)" export PORT_SNMP # Start SNMP Trap Receiver snmp_start_trapreceiver ${PORT_SNMP} ${RSYSLOG_OUT_LOG} add_conf ' module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) module( load="../plugins/omsnmp/.libs/omsnmp" ) # set up the action template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omsnmp" name="name" server="127.0.0.1" port="'${PORT_SNMP}'" version="0" community="public" enterpriseOID="1.3.6.1.2.1.192.0.1" messageOID="1.3.6.1.2.1.192.1.2.1.11" TrapType="6" specificType="0" ) ' startup tcpflood -p$TCPFLOOD_PORT -m${TESTMESSAGES} netstat -l shutdown_when_empty wait_shutdown snmp_stop_trapreceiver content_count_check "msgnum:" ${TESTMESSAGES} exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp_maxsessions.sh0000644000000000000000000000013115216464436020177 xustar0030 mtime=1782212894.064266798 30 atime=1782715518.918791051 29 ctime=1787067806.81495649 rsyslog-8.2608.0/tests/imptcp_maxsessions.sh0000775000175000017500000000572115216464436017654 0ustar00rgerrger#!/bin/bash # Test imtcp with many dropping connections # added 2010-08-10 by Rgerhards # # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" export NUMMESSAGES=500 MAXSESSIONS=10 CONNECTIONS=20 EXPECTED_DROPS=$((CONNECTIONS - MAXSESSIONS)) EXPECTED_STR='too many tcp sessions - dropping incoming request' STARTED_LOG="${RSYSLOG_DYNNAME}.started" HOLDER_PID= stop_holder() { if [ -n "$HOLDER_PID" ]; then if kill -0 "$HOLDER_PID" 2>/dev/null; then kill "$HOLDER_PID" 2>/dev/null || true fi wait "$HOLDER_PID" 2>/dev/null || true HOLDER_PID= fi } test_error_exit_handler() { stop_holder } count_dropped_sessions() { if [ -f "$STARTED_LOG" ]; then count=$(grep -F -c -- "$EXPECTED_STR" "$STARTED_LOG" || true) case "$count" in ''|*[!0-9]*) printf '0\n' ;; *) printf '%s\n' "$count" ;; esac else printf '0\n' fi } wait_for_exact_drops() { wait_tries=${1:-20} wait_i=1 while [ "$wait_i" -le "$wait_tries" ]; do count=$(count_dropped_sessions) if [ "$count" -eq "$EXPECTED_DROPS" ]; then return 0 fi if [ "$count" -gt "$EXPECTED_DROPS" ]; then break fi $TESTTOOL_DIR/msleep 1000 wait_i=$((wait_i + 1)) done return 1 } start_holder() { ./tcpflood -p"$TCPFLOOD_PORT" -c"$MAXSESSIONS" -m"$MAXSESSIONS" -P129 -K0 & HOLDER_PID=$! } generate_conf add_conf ' $MaxMessageSize 10k module(load="../plugins/imptcp/.libs/imptcp" maxsessions="'$MAXSESSIONS'") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" if $msg contains "msgnum:" then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } $OMFileFlushInterval 2 $OMFileIOBufferSize 256k ' startup echo "INFO: RSYSLOG_OUT_LOG: $RSYSLOG_OUT_LOG" echo "Opening $MAXSESSIONS held sessions" start_holder wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" "$MAXSESSIONS" echo "About to run tcpflood for $EXPECTED_DROPS extra sessions" tcpflood -c$EXPECTED_DROPS -m$EXPECTED_DROPS -i$MAXSESSIONS -P129 -A echo "-------> NOTE: CLOSED REMOTELY messages are expected and OK! <-------" echo "done run tcpflood" if ! wait_for_exact_drops 20; then count=$(count_dropped_sessions) echo "FAIL: expected exactly $EXPECTED_DROPS dropped sessions, got $count" echo "STARTED_LOG contents:" if [ -f "$STARTED_LOG" ]; then cat "$STARTED_LOG" else echo "$STARTED_LOG does not exist" fi error_exit 1 fi wait_file_lines --abort-on-oversize "$RSYSLOG_OUT_LOG" "$MAXSESSIONS" 2 stop_holder shutdown_when_empty wait_shutdown count=$(count_dropped_sessions) if [ "$count" -ne "$EXPECTED_DROPS" ]; then echo "FAIL: expected exactly $EXPECTED_DROPS dropped sessions, got $count" echo "STARTED_LOG contents:" if [ -f "$STARTED_LOG" ]; then cat "$STARTED_LOG" else echo "$STARTED_LOG does not exist" fi exit 1 fi seq_check 0 $((MAXSESSIONS - 1)) echo "Got expected drops: $EXPECTED_DROPS, looks good!" exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-fail.sh0000644000000000000000000000013115241075234017147 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067804.446912364 rsyslog-8.2608.0/tests/diskqueue-fail.sh0000775000175000017500000000153615241075234016624 0ustar00rgerrger#!/bin/bash # checks that nothing bad happens if a DA (disk) queue runs out # of configured disk space # addd 2017-02-07 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 generate_conf add_conf ' module( load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="queuefail") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") ruleset( name="queuefail" queue.type="Disk" queue.filename="fssailstocreate" queue.maxDiskSpace="4m" queue.maxfilesize="1m" queue.timeoutenqueue="300000" queue.lowwatermark="5000" ) { action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") } ' startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_numstr-str-vg.sh0000644000000000000000000000013215171370365022271 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.918791051 30 ctime=1787067805.246927271 rsyslog-8.2608.0/tests/rscript_compare_numstr-str-vg.sh0000775000175000017500000000020015171370365021730 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='"1"' export HIGHER_VAL='"abc"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/parsertest-parse-3164-buggyday.sh0000644000000000000000000000013215241075234021750 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 30 ctime=1787067805.034923321 rsyslog-8.2608.0/tests/parsertest-parse-3164-buggyday.sh0000775000175000017500000000220615241075234021417 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%timestamp:::date-rfc3164-buggyday%,%hostname%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -M "\"<38> Mar 7 19:06:53 example tag: testmessage (only date actually tested)\"" tcpflood -m1 -M "\"<38> Mar 17 19:06:53 example tag: testmessage (only date actually tested)\"" shutdown_when_empty wait_shutdown echo '38,auth,info,Mar 07 19:06:53,example,tag,tag:, testmessage (only date actually tested) 38,auth,info,Mar 17 19:06:53,example,tag,tag:, testmessage (only date actually tested)' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/diskqueue-multithread-es.sh0000644000000000000000000000013115241075234021163 xustar0030 mtime=1787067036.617578519 29 atime=1787067036.76558129 30 ctime=1787067803.938902898 rsyslog-8.2608.0/tests/diskqueue-multithread-es.sh0000775000175000017500000000404115241075234020632 0ustar00rgerrger#!/bin/bash # This test stresses the DA queue disk subsystem with multiple threads. # To do so, the in-memory queues are deliberately sized very small. # NOTE: depending on circumstances, this test frequently starts the # DAWorkerPool, which shuffles messages over from the main queue to # the DA queue. It terminates when we reach low water mark. This can # happen in our test. So the DA worker pool thread is, depending on # timing, started and shut down multiple times. This is not a problem # indication! # The pstats display is for manual review - it helps to see how many # messages actually went to the DA queue. # Copyright (C) 2019-10-28 by Rainer Gerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_PORT=19200 export NUMMESSAGES=25000 export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check ensure_elasticsearch_ready generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME'.spool") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") main_queue(queue.size="2000") module(load="../plugins/impstats/.libs/impstats" log.syslog="off" log.file="'$RSYSLOG_DYNNAME'.pstats" interval="1") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") :msg, contains, "msgnum:" { action(type="omelasticsearch" name="act-es" template="tpl" server="127.0.0.1" serverport="'$ES_PORT'" searchIndex="rsyslog_testbench" bulkmode="on" queue.lowwatermark="250" queue.highwatermark="1500" queue.type="linkedList" queue.size="2000" queue.dequeueBatchSize="64" queue.workerThreads="4" queue.fileName="actq" queue.workerThreadMinimumMessages="64") } ' startup tcpflood -m$NUMMESSAGES # use tcpflood to get better async processing than injectmsg! shutdown_when_empty wait_shutdown echo FOR MANUAL REVIEW: pstats tail $RSYSLOG_DYNNAME.pstats | grep maxqsize es_getdata $NUMMESSAGES $ES_PORT seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-endmsg.regex.crio.rulebase0000644000000000000000000000013215035412264022213 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.917791033 30 ctime=1787067808.739992362 rsyslog-8.2608.0/tests/imfile-endmsg.regex.crio.rulebase0000666000175000017500000000116415035412264021663 0ustar00rgerrgerversion=2 rule=:%{"name":"multilinecrio", "type":"repeat", "parser":[ {"type":"word", "name":"time"}, {"type":"literal", "text":" "}, {"type":"word", "name":"stream"}, {"type":"literal", "text":" "}, {"type":"word", "name":"partial"}, {"type":"literal", "text":" "}, {"type":"char-sep", "name":"log", "extradata":"\n"} ], "while":[ {"type":"literal", "text":"\n"}, ] }% rsyslog-8.2608.0/tests/PaxHeaders/allowed-sender-tcp-hostname-ok.sh0000644000000000000000000000013215241075234022154 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.761581215 30 ctime=1787067804.410911693 rsyslog-8.2608.0/tests/allowed-sender-tcp-hostname-ok.sh0000775000175000017500000000140515241075234021623 0ustar00rgerrger#!/bin/bash # check that we are able to receive messages from allowed sender # added 2019-08-15 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME export NUMMESSAGES=5 # it's just important that we get any messages at all generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $AllowedSender TCP,*'$RS_HOSTNAME'* template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood -m$NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/cfg4.testin0000644000000000000000000000013215035412264015756 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.918791051 30 ctime=1787067808.409986213 rsyslog-8.2608.0/tests/cfg4.testin0000666000175000017500000000216015035412264015423 0ustar00rgerrger# This is more or less the sample config, but without imklog being # active. imklog must not always be present and as such may spoil # our testing result. The core point at this test is that a valid # config file should not lead to any error messages. # It may be a good idea to update this file from time to time, so that # it contains a reasonable complex config sample. # if you experience problems, check # https://www.rsyslog.com/troubleshoot for assistance # rsyslog v3: load input modules # If you do not load inputs, nothing happens! # You may need to set the module load path if modules are not found. # ######### Receiving Messages from Remote Hosts ########## # TCP Syslog Server: # provides TCP syslog reception and GSS-API (if compiled to support it) #$ModLoad imtcp.so # load module #$InputTCPServerRun 514 # start up TCP listener at port 514 # UDP Syslog Server: $ModLoad imudp.so # provides UDP syslog reception $ModLoad omoracle.so $UDPServerRun 514 # start a UDP syslog server at standard port 514 $IncludeConfig /home/munoz/logging/rsyslog/20*conf $IncludeConfig /home/munoz/logging/rsyslog/30*conf #*.* ~ rsyslog-8.2608.0/tests/PaxHeaders/config_enabled-off-action.sh0000644000000000000000000000013215241075234021202 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.682579736 30 ctime=1787067804.995922594 rsyslog-8.2608.0/tests/config_enabled-off-action.sh0000775000175000017500000000304515241075234020653 0ustar00rgerrger#!/bin/bash # check that an action disabled via config.enabled="off" is not instantiated at # all - in both the RainerScript and YAML frontends (YAML parsing produces the # same nvlst and calls the same cnfstmtNewAct() path). Its parameters must not be # processed, so no "parameter not known" message is emitted for them (an enabled # action would report it - see config_enabled-on.sh). This also guarantees module # side effects such as omelasticsearch probing its server in checkCnf never run # for a disabled action. The oracle is rsyslogd config-check output. # added 2026-07-18, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # --- RainerScript frontend --- generate_conf add_conf ' action(type="omfile" file="'$RSYSLOG_OUT_LOG'" invalid.param="error" config.enabled="off") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' export RS_REDIR=">${RSYSLOG_DYNNAME}.rsyslog.log 2>&1" rsyslogd_config_check unset RS_REDIR check_not_present 'parameter.*invalid.param.*not known' "${RSYSLOG_DYNNAME}.rsyslog.log" # --- YAML frontend (same cnfstmtNewAct() path) --- cat >"${RSYSLOG_DYNNAME}.disabled.yaml" <"${RSYSLOG_DYNNAME}.yaml.log" 2>&1 check_not_present 'parameter.*invalid.param.*not known' "${RSYSLOG_DYNNAME}.yaml.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-tls-cfgcmd.sh0000644000000000000000000000013215216464436017561 xustar0030 mtime=1782212894.065266814 30 atime=1782715518.918791051 30 ctime=1787067807.753973988 rsyslog-8.2608.0/tests/imrelp-tls-cfgcmd.sh0000775000175000017500000000362415216464436017235 0ustar00rgerrger#!/bin/bash # addd 2019-11-14 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_relpEngineSetTLSLibByName export NUMMESSAGES=1000 export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf add_conf ' module( load="../plugins/imrelp/.libs/imrelp" tls.tlslib="openssl") input(type="imrelp" port="'$TCPFLOOD_PORT'" tls="on" tls.cacert="'$srcdir'/tls-certs/ca.pem" tls.mycert="'$srcdir'/tls-certs/cert.pem" tls.myprivkey="'$srcdir'/tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog" tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2 CipherString=ECDHE-RSA-AES256-GCM-SHA384 Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2,-TLSv1.3 MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup export TCPFLOOD_EXTRA_OPTS='-k "Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2 CipherString=DHE-RSA-AES256-SHA Protocol=ALL,-SSLv2,-SSLv3,-TLSv1.1,-TLSv1.2,-TLSv1.3 MinProtocol=TLSv1.1 MaxProtocol=TLSv1.1"' tcpflood --check-only -u "openssl" -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -x "$srcdir/tls-certs/ca.pem" -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/cert.pem" -Ersyslog 2> ${RSYSLOG_DYNNAME}.tcpflood shutdown_when_empty wait_shutdown content_check --check-only "relpTcpTLSSetPrio_gtls" ${RSYSLOG_DEBUGLOG} ret=$? if [ $ret == 0 ]; then echo "SKIP: LIBRELP was build without OPENSSL Support" skip_test fi content_check --check-only "OpenSSL Version too old" ${RSYSLOG_DEBUGLOG} ret=$? if [ $ret == 0 ]; then echo "SKIP: OpenSSL Version too old" skip_test else # Check for a failed session - possible ecodes are 10031 and 10040 content_check "librelp: generic error: ecode" $RSYSLOG_DEBUGLOG fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-json.sh0000644000000000000000000000013215035412264017021 xustar0030 mtime=1752569012.416639571 30 atime=1782715518.918791051 30 ctime=1787067804.252908749 rsyslog-8.2608.0/tests/template-json.sh0000777000175000017500000000153315035412264016474 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' set $!backslash = "a \\ \"b\" c / d"; # '/' must not be escaped! template(name="json" type="list" option.json="on") { constant(value="{") constant(value="\"backslash\":\"") property(name="$!backslash") constant(value="\"}\n") } :msg, contains, "msgnum:" action(type="omfile" template="json" file=`echo $RSYSLOG_OUT_LOG`) ' startup injectmsg 0 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! printf '{"backslash":"a \\\\ \\"b\\" c / d"}\n' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid JSON generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/3.rstest0000644000000000000000000000013215035412264015313 xustar0030 mtime=1752569012.383868873 30 atime=1782715518.917791033 30 ctime=1787067808.284983883 rsyslog-8.2608.0/tests/3.rstest0000666000175000017500000000071015035412264014757 0ustar00rgerrger# a simple RainerScript test result: 0 in: strlen($msg & strlen('abc')) > 20 +30 + -40 then $$$ out: 00000000: push_msgvar msg[cstr] 00000001: push_const abc[cstr] 00000002: push_const 1[nbr] 00000003: func_call strlen 00000004: strconcat 00000005: push_const 1[nbr] 00000006: func_call strlen 00000007: push_const 20[nbr] 00000008: push_const 30[nbr] 00000009: add 00000010: push_const 40[nbr] 00000011: unary_minus 00000012: add 00000013: cmp_> $$$ rsyslog-8.2608.0/tests/PaxHeaders/diag-core-classification.sh0000644000000000000000000000013215241075234021063 xustar0030 mtime=1787067036.615578481 30 atime=1787067036.682579736 30 ctime=1787067804.550914302 rsyslog-8.2608.0/tests/diag-core-classification.sh0000775000175000017500000000443415241075234020537 0ustar00rgerrger#!/usr/bin/env bash # Verify core-dump helper classification stays conservative. Generic core files # must not be accepted unless ownership can be attributed, while test-specific # names remain a weak fallback for platforms where metadata extraction is not # available. The external-collector override models systemd-coredump/apport # policies that make local generic core scanning unreliable. . ${srcdir:=.}/diag.sh init # Keep synthetic core files out of the shared tests directory: parallel tests # run broad core* cleanup during diag.sh init. core_classification_dir="${PWD}/${RSYSLOG_DYNNAME}.core-classification.$$" core_scan_log="${PWD}/${RSYSLOG_DYNNAME}.core-scan.log" test_error_exit_handler() { rm -rf "$core_classification_dir" } rm -rf "$core_classification_dir" mkdir "$core_classification_dir" || error_exit 1 touch "$core_classification_dir/core.foreign" if core_candidate_owner_matches "$core_classification_dir/core.foreign" ../tools/rsyslogd 424242; then echo "FAIL: generic core without pid/executable ownership was accepted" error_exit 1 fi touch "$core_classification_dir/core.rsyslogd.424242" if ! core_candidate_owner_matches "$core_classification_dir/core.rsyslogd.424242" ../tools/rsyslogd 424242; then echo "FAIL: pid/executable filename hint was not accepted" error_exit 1 fi touch "$core_classification_dir/core.${RSYSLOG_DYNNAME}.weak" if ! core_candidate_owner_matches "$core_classification_dir/core.${RSYSLOG_DYNNAME}.weak" ../tools/rsyslogd ""; then echo "FAIL: test-specific core name fallback was not accepted" error_exit 1 fi export RSTB_CORE_PATTERN_OVERRIDE='|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h' if ! core_policy_uses_external_collector; then echo "FAIL: piped core_pattern was not recognized as external collector" error_exit 1 fi core_dumps_found=0 oldpwd="$PWD" cd "$core_classification_dir" || error_exit 1 analyze_owned_core_candidates ../../tools/rsyslogd "" rsyslogd > "$core_scan_log" 2>&1 cd "$oldpwd" || error_exit 1 if [ "$core_dumps_found" -ne 1 ]; then echo "FAIL: external-collector scan should analyze only the test-specific fallback core" cat "$core_scan_log" error_exit 1 fi content_check "skipping generic local core scan because core_pattern uses an external collector" \ "$core_scan_log" rm -rf "$core_classification_dir" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omotel_proxy_server.py0000644000000000000000000000013215216464436020414 xustar0030 mtime=1782212894.079267041 30 atime=1782715518.917791033 30 ctime=1787067808.727992139 rsyslog-8.2608.0/tests/omotel_proxy_server.py0000664000175000017500000002326615216464436020071 0ustar00rgerrger#!/usr/bin/env python3 """ Simple HTTP proxy server for omotel proxy testing. This proxy server: - Forwards HTTP requests to a target server - Supports basic authentication - Logs proxy usage for verification - Writes received data to a file for inspection """ import argparse import base64 import json import os import sys import urllib.parse import urllib.request try: from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer # Python 2 from SocketServer import ThreadingMixIn except ImportError: from http.server import BaseHTTPRequestHandler, HTTPServer # Python 3 from socketserver import ThreadingMixIn # Global state proxy_metadata = { 'requests': [], 'target_host': '127.0.0.1', 'target_port': 4318, 'require_auth': False, 'expected_user': '', 'expected_password': '', 'data_file': None } class ThreadingHTTPServer(ThreadingMixIn, HTTPServer): """Threading HTTP server to handle concurrent requests.""" pass class ProxyHandler(BaseHTTPRequestHandler): """HTTP proxy handler that forwards requests to target server.""" def validate_proxy_auth(self): """Validate Proxy-Authorization header if required.""" if not proxy_metadata['require_auth']: return True if 'Proxy-Authorization' not in self.headers: self.send_response(407) # Proxy Authentication Required self.send_header('Proxy-Authenticate', 'Basic realm="Proxy"') self.end_headers() self.wfile.write(b'Proxy authentication required') return False auth_header = self.headers['Proxy-Authorization'] if not auth_header.startswith('Basic '): self.send_response(407) self.send_header('Proxy-Authenticate', 'Basic realm="Proxy"') self.end_headers() self.wfile.write(b'Invalid proxy authentication method') return False try: _, b64userpwd = auth_header.split(' ', 1) userpwd = base64.b64decode(b64userpwd).decode('utf-8') user, password = userpwd.split(':', 1) expected_user = proxy_metadata['expected_user'] expected_password = proxy_metadata['expected_password'] if user != expected_user or password != expected_password: self.send_response(407) self.send_header('Proxy-Authenticate', 'Basic realm="Proxy"') self.end_headers() self.wfile.write(b'Invalid proxy credentials') return False except Exception as e: self.send_response(407) self.send_header('Proxy-Authenticate', 'Basic realm="Proxy"') self.end_headers() self.wfile.write(f'Proxy auth error: {e}'.encode('utf-8')) return False return True def log_message(self, format, *args): """Override to reduce noise in test output.""" # Only log errors if 'error' in format.lower() or args[1].startswith('4') or args[1].startswith('5'): super().log_message(format, *args) def do_CONNECT(self): """Handle CONNECT method for HTTPS tunneling.""" if not self.validate_proxy_auth(): return # For HTTPS, we'd need to implement SSL tunneling # For simplicity in tests, we'll just return an error # Most tests will use HTTP, not HTTPS through proxy self.send_response(501) self.end_headers() self.wfile.write(b'CONNECT method not fully implemented (use HTTP for testing)') def do_POST(self): """Handle POST requests by forwarding to target server.""" if not self.validate_proxy_auth(): return # Record this request content_length = int(self.headers.get('Content-Length', 0)) body = self.rfile.read(content_length) if content_length > 0 else b'' # When using HTTP proxy, libcurl sends the full URL in the path # e.g., "http://127.0.0.1:50101/v1/logs" instead of just "/v1/logs" # Parse the path to extract the actual target path target_path = self.path if self.path.startswith('http://') or self.path.startswith('https://'): # Full URL provided - parse it try: parsed = urllib.parse.urlparse(self.path) target_path = parsed.path if parsed.query: target_path += '?' + parsed.query except Exception: # If parsing fails, use the path as-is pass request_info = { 'method': 'POST', 'path': self.path, 'target_path': target_path, 'headers': dict(self.headers), 'body': body.decode('utf-8', errors='replace'), 'client': self.client_address[0] } proxy_metadata['requests'].append(request_info) # Forward request to target server target_url = f"http://{proxy_metadata['target_host']}:{proxy_metadata['target_port']}{target_path}" try: # Create request with original headers (except Host and Connection) # When forwarding through proxy, we need to set the Host header to the target req_headers = {} for header, value in self.headers.items(): header_lower = header.lower() if header_lower not in ('host', 'connection', 'proxy-authorization'): req_headers[header] = value # Set Host header to target server req_headers['Host'] = f"{proxy_metadata['target_host']}:{proxy_metadata['target_port']}" req = urllib.request.Request(target_url, data=body, headers=req_headers, method='POST') with urllib.request.urlopen(req, timeout=10) as response: # Forward response self.send_response(response.getcode()) for header, value in response.headers.items(): if header.lower() not in ('connection', 'transfer-encoding'): self.send_header(header, value) self.end_headers() response_body = response.read() self.wfile.write(response_body) except urllib.error.HTTPError as e: # Forward error response self.send_response(e.code) for header, value in e.headers.items(): if header.lower() not in ('connection', 'transfer-encoding'): self.send_header(header, value) self.end_headers() error_body = e.read() self.wfile.write(error_body) except Exception as e: # Log the error for debugging import traceback error_msg = f'Proxy error: {e}\n{traceback.format_exc()}' print(f"Proxy error: {error_msg}", file=sys.stderr) self.send_response(502) # Bad Gateway self.end_headers() self.wfile.write(f'Proxy error: {e}'.encode('utf-8')) def do_GET(self): """Handle GET requests (for health checks, data retrieval).""" if self.path == '/proxy/requests': # Return list of proxied requests self.send_response(200) self.send_header('Content-Type', 'application/json') self.end_headers() response = json.dumps(proxy_metadata['requests'], indent=2) self.wfile.write(response.encode('utf-8')) elif self.path == '/proxy/clear': # Clear request log proxy_metadata['requests'] = [] self.send_response(200) self.end_headers() self.wfile.write(b'OK') else: self.send_response(404) self.end_headers() self.wfile.write(b'Not found') if __name__ == '__main__': parser = argparse.ArgumentParser(description='Simple HTTP proxy for omotel testing') parser.add_argument('-p', '--port', type=int, default=0, help='Listen port (0 = auto)') parser.add_argument('--port-file', type=str, default='', help='File to write listen port') parser.add_argument('--target-host', type=str, default='127.0.0.1', help='Target server host') parser.add_argument('--target-port', type=int, default=4318, help='Target server port') parser.add_argument('--require-auth', action='store_true', help='Require proxy authentication') parser.add_argument('--user', type=str, default='', help='Expected proxy username') parser.add_argument('--password', type=str, default='', help='Expected proxy password') parser.add_argument('--data-file', type=str, default='', help='File to save request data') args = parser.parse_args() proxy_metadata['target_host'] = args.target_host proxy_metadata['target_port'] = args.target_port proxy_metadata['require_auth'] = args.require_auth proxy_metadata['expected_user'] = args.user proxy_metadata['expected_password'] = args.password proxy_metadata['data_file'] = args.data_file server = ThreadingHTTPServer(('127.0.0.1', args.port), ProxyHandler) listen_port = server.server_address[1] pid = os.getpid() print(f'Starting proxy server on 127.0.0.1:{listen_port} (pid {pid})') print(f'Forwarding to {args.target_host}:{args.target_port}') if args.require_auth: print(f'Proxy authentication required: {args.user}:***') if args.port_file: with open(args.port_file, 'w') as f: f.write(str(listen_port)) try: server.serve_forever() except KeyboardInterrupt: print('\nShutting down proxy server...') server.shutdown() # Save request data if requested if args.data_file and proxy_metadata['requests']: with open(args.data_file, 'w') as f: json.dump(proxy_metadata['requests'], f, indent=2) rsyslog-8.2608.0/tests/PaxHeaders/config-translate-rs-to-yaml.sh0000644000000000000000000000013215171370365021507 xustar0030 mtime=1776677109.457913326 30 atime=1782715518.919791067 30 ctime=1787067805.319928632 rsyslog-8.2608.0/tests/config-translate-rs-to-yaml.sh0000775000175000017500000000160515171370365021160 0ustar00rgerrger#!/bin/bash # check canonical translation from RainerScript to YAML. # # Part of the testbench for rsyslog. # # This file is part of rsyslog. # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init modpath="../runtime/.libs:../.libs" cat > "${RSYSLOG_DYNNAME}.conf" <<'RS_EOF' main_queue(queue.type="Direct") ruleset(name="main") { action(type="omfile" file="/var/log/sample.log") } RS_EOF ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F yaml -o "${RSYSLOG_DYNNAME}.yaml" -M"$modpath" cat > "${RSYSLOG_DYNNAME}.expected.yaml" <<'YAML_EOF' version: 2 mainqueue: queue.type: "Direct" rulesets: - name: "main" actions: - type: "omfile" file: "/var/log/sample.log" YAML_EOF cmp_exact_file "${RSYSLOG_DYNNAME}.expected.yaml" "${RSYSLOG_DYNNAME}.yaml" ../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.yaml" -M"$modpath" echo SUCCESS: RainerScript to YAML translation exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropabortonidfail.sh0000644000000000000000000000013215131231047020635 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.919791067 30 ctime=1787067804.242908563 rsyslog-8.2608.0/tests/privdropabortonidfail.sh0000777000175000017500000000207715131231047020314 0ustar00rgerrger#!/bin/bash # add 2021-10-12 by alorbach, released under ASL 2.0 . ${srcdir:=.}/diag.sh init #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.debuglog" skip_platform "SunOS" "This test currently does not work on Solaris." export TESTBENCH_TESTUSER1="USER_${RSYSLOG_DYNNAME}_1" export TESTBENCH_TESTUSER2="USER_${RSYSLOG_DYNNAME}_2" generate_conf add_conf ' global( security.abortOnIDResolutionFail="off" ) template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action( type="omfile" template="outfmt" file="'${RSYSLOG_OUT_LOG}'" ) action( type="omfile" template="outfmt" file="'${RSYSLOG_DYNNAME}'.dummy.log" FileOwner="'${TESTBENCH_TESTUSER1}'" FileGroup="'${TESTBENCH_TESTUSER1}'" DirOwner="'${TESTBENCH_TESTUSER2}'" DirGroup="'${TESTBENCH_TESTUSER2}'" ) ' startup shutdown_when_empty wait_shutdown content_check --regex "ID for user '${TESTBENCH_TESTUSER1}' could not be found" content_check --regex "ID for user '${TESTBENCH_TESTUSER2}' could not be found" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-include-recursion.sh0000644000000000000000000000013215241075234020632 xustar0030 mtime=1787067036.648579099 30 atime=1787067036.801581964 30 ctime=1787067805.451931091 rsyslog-8.2608.0/tests/yaml-include-recursion.sh0000775000175000017500000000212015241075234020274 0ustar00rgerrger#!/bin/bash # Regression test: YAML include recursion must be detected and ignored. # Setup: root YAML includes itself and also defines a ruleset that writes to # RSYSLOG_OUT_LOG. Oracle: rsyslog starts and processes messages (no crash / # stack exhaustion), proving the self-include was ignored rather than recursed. . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=20 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << YAMLEOF include: - path: "${RSYSLOG_DYNNAME}.yaml" modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\\n" rulesets: - name: main script: | :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}") YAMLEOF add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omkafka.sh0000644000000000000000000000013215216464436015661 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.918791051 30 ctime=1787067806.230945608 rsyslog-8.2608.0/tests/omkafka.sh0000775000175000017500000000702215216464436015331 0ustar00rgerrger#!/bin/bash # added 2017-05-03 by alorbach # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export RSTB_IMDIAG_INJECT_DELAY_MODE=full test_status unreliable 'https://github.com/rsyslog/rsyslog/issues/3197' check_command_available kcat export KEEP_KAFKA_RUNNING="YES" export TESTMESSAGES=100000 export TESTMESSAGESFULL=$TESTMESSAGES RANDTOPIC="$(printf '%08x' "$(( (RANDOM<<16) ^ RANDOM ))")" export RANDTOPIC # Set EXTRA_EXITCHECK to dump kafka/zookeeperlogfiles on failure only. export EXTRA_EXITCHECK=dumpkafkalogs export EXTRA_EXIT=kafka echo Check and Stop previous instances of kafka/zookeeper download_kafka stop_zookeeper stop_kafka echo Create kafka/zookeeper instance and $RANDTOPIC topic start_zookeeper start_kafka create_kafka_topic $RANDTOPIC '.dep_wrk' '22181' # --- Create/Start omkafka sender config export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' # impstats in order to gain insight into error cases module(load="../plugins/impstats/.libs/impstats" log.file="'$RSYSLOG_DYNNAME.pstats'" interval="1" log.syslog="off") main_queue(queue.timeoutactioncompletion="60000" queue.timeoutshutdown="60000") module(load="../plugins/omkafka/.libs/omkafka") template(name="outfmt" type="string" string="%msg:F,58:2%\n") local4.* { action( name="kafka-fwd" type="omkafka" topic="'$RANDTOPIC'" broker="127.0.0.1:29092" template="outfmt" confParam=[ "compression.codec=none", "socket.timeout.ms=10000", "socket.keepalive.enable=true", "reconnect.backoff.jitter.ms=1000", "queue.buffering.max.messages=10000", "enable.auto.commit=true", "message.send.max.retries=1"] topicConfParam=["message.timeout.ms=10000"] partitions.auto="on" errorFile="'$RSYSLOG_OUT_LOG'-kafka_errors.log" closeTimeout="60000" resubmitOnFailure="on" keepFailedMessages="on" failedMsgFile="'$RSYSLOG_OUT_LOG'-failed-'$RANDTOPIC'.data" action.resumeInterval="1" action.resumeRetryCount="2" queue.saveonshutdown="on" ) action( type="omfile" file="'$RSYSLOG_OUT_LOG'") stop } action( type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'") ' echo Starting sender instance [omkafka] startup echo Inject messages into rsyslog sender instance injectmsg 1 $TESTMESSAGES wait_file_lines $RSYSLOG_OUT_LOG $TESTMESSAGESFULL 100 # experimental: wait until kcat receives everything timeoutend=100 timecounter=0 while [ $timecounter -lt $timeoutend ]; do (( timecounter++ )) kcat -b 127.0.0.1:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG count=$(wc -l < ${RSYSLOG_OUT_LOG}) if [ $count -eq $TESTMESSAGESFULL ]; then printf '**** wait-kafka-lines success, have %d lines ****\n\n' "$TESTMESSAGESFULL" break else if [ "$timecounter" == "$timeoutend" ]; then echo wait-kafka-lines failed, expected $TESTMESSAGESFULL got $count shutdown_when_empty wait_shutdown error_exit 1 else echo wait-file-lines not yet there, currently $count lines printf 'pstats data:\n' cat $RSYSLOG_DYNNAME.pstats printf '\n' $TESTTOOL_DIR/msleep 1000 fi fi done unset count #end experimental echo Stopping sender instance [omkafka] shutdown_when_empty wait_shutdown #kcat -b 127.0.0.1:29092 -e -C -o beginning -t $RANDTOPIC -f '%s' > $RSYSLOG_OUT_LOG #kcat -b 127.0.0.1:29092 -e -C -o beginning -t $RANDTOPIC -f '%p@%o:%k:%s' > $RSYSLOG_OUT_LOG.extra # Delete topic to remove old traces before delete_kafka_topic $RANDTOPIC '.dep_wrk' '22181' # Dump Kafka log | uncomment if needed # dump_kafka_serverlog kafka_check_broken_broker $RSYSLOG_DYNNAME.othermsg seq_check 1 $TESTMESSAGESFULL -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-error-key.sh0000644000000000000000000000013215241075234021521 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.388967187 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-error-key.sh0000775000175000017500000000174215241075234021174 0ustar00rgerrger#!/bin/bash # check error message on cert as key file # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=3 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/cert.pem'" ) module(load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' # Begin actual testcase startup tcpflood --check-only -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown content_check "nsd mbedtls: error parsing crypto config" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imkubernetes-cri-partial-hard-cap.sh0000644000000000000000000000013115241075234022616 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.684579773 29 ctime=1787067808.16998174 rsyslog-8.2608.0/tests/imkubernetes-cri-partial-hard-cap.sh0000775000175000017500000000636015241075234022273 0ustar00rgerrger#!/bin/bash # Verify that non-truncate oversize modes still have an imkubernetes partial # hard cap, so an unfinished CRI P run cannot grow without bound. # The API helper signals readiness after binding; its 2m timeout is hang # protection, while the explicit kill and wait below own normal cleanup. . ${srcdir:=.}/diag.sh init require_plugin imkubernetes ../contrib/imkubernetes check_command_available timeout export NUMMESSAGES=2 pwd=$( pwd ) testsrv=imk8s-partial-hard-cap-server k8s_srv_port=0 k8s_srv_port_file=${RSYSLOG_DYNNAME}${testsrv}.port logdir="${RSYSLOG_DYNNAME}.spool/pods/namespace-name1_pod-name1_uid1/container-a" logfile="${logdir}/0.log" mkdir -p "$logdir" echo starting kubernetes test server MMK8S_INCLUDE_NODE_NAME=1 timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py \ 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ $k8s_srv_port_file \ > ${RSYSLOG_DYNNAME}.spool/imkubernetes_partial_hard_cap_srv.log 2>&1 & BGPROCESS=$! wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started assign_file_content k8s_srv_port "$k8s_srv_port_file" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'" maxMessageSize="128" oversizemsg.input.mode="accept") module(load="../contrib/imkubernetes/.libs/imkubernetes" LogFileGlob="'$pwd/$logdir'/*.log" PollingInterval="1" KubernetesUrl="http://localhost:'$k8s_srv_port'" Token="dummy" cacheEntryTtl="60") template(name="outfmt" type="list" option.jsonf="on") { property(outname="msg" name="msg" format="jsonf") property(outname="stream" name="$!kubernetes!stream" format="jsonf") property(outname="format" name="$!kubernetes!log_format" format="jsonf") property(outname="pod_id" name="$!kubernetes!pod_id" format="jsonf") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup { for i in $(seq 1 50); do printf '2026-04-20T10:00:%02d.000000000Z stdout P %s\n' "$i" \ 'partial-fragment-0123456789' done printf '%s\n' '2026-04-20T10:01:00.000000000Z stdout F closing-tail-must-not-standalone' printf '%s\n' '2026-04-20T10:01:01.000000000Z stdout F after partial hard cap' } > "$logfile" wait_file_lines "$RSYSLOG_OUT_LOG" 2 wait_queueempty shutdown_when_empty wait_shutdown kill $BGPROCESS wait_pid_termination ${RSYSLOG_DYNNAME}${testsrv}.pid if ! $PYTHON - "$RSYSLOG_OUT_LOG" <<'PY' import json import sys path = sys.argv[1] records = [json.loads(line) for line in open(path)] records = [item for item in records if item.get("format") == "cri"] assert len(records) == 2, records hard_cap = 128 * 10 expected_prefix = ("partial-fragment-0123456789" * 50)[:hard_cap] partial = records[0] assert partial["msg"] == expected_prefix, partial assert len(partial["msg"]) == hard_cap, partial assert "closing-tail-must-not-standalone" not in partial["msg"], partial assert partial["stream"] == "stdout", partial assert partial["pod_id"] == "pod-name1-id", partial independent = records[1] assert independent["msg"] == "after partial hard cap", independent assert independent["stream"] == "stdout", independent assert independent["pod_id"] == "pod-name1-id", independent PY then error_exit 1 "imkubernetes did not enforce the CRI partial hard cap" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-gtls-configured-sni.sh0000644000000000000000000000013115216464436022044 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.918791051 29 ctime=1787067807.34996646 rsyslog-8.2608.0/tests/omfwd-tls-gtls-configured-sni.sh0000775000175000017500000000134115216464436021513 0ustar00rgerrger#!/bin/bash # Author: John Cantu # Test that "custom-sni" is sent as SNI by omfwd, when configured . ${srcdir:=.}/diag.sh init port_file="$RSYSLOG_DYNNAME.sni-server.port" omfwd_sni_server "gnutls" "$port_file" port=$(cat "$port_file") generate_conf add_conf ' global(DefaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" \ net.ipprotocol="ipv4-only") action(type="omfwd" target="localhost" protocol="tcp" port="'$port'" StreamDriver="gtls" StreamDriverMode="1" StreamDriverAuthMode="anon" StreamDriverRemoteSNI="custom-sni" ) ' startup omfwd_sni_check "custom-sni" shutdown_immediate wait_shutdown kill -9 $(cat "$RSYSLOG_DYNNAME.sni-server.pid") exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-diskq-restart-save.sh0000644000000000000000000000013215241075234021272 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.786581683 30 ctime=1787067806.064942514 rsyslog-8.2608.0/tests/omprog-diskq-restart-save.sh0000775000175000017500000000426715241075234020752 0ustar00rgerrger#!/bin/bash # Regression coverage for GitHub issue #5364. An omprog action with a pure disk # action queue receives a negative acknowledgement, then rsyslog is restarted # before the action can drain. The oracle is that the message is still retried # after restart and is acknowledged once the helper switches to success mode. # QUEUE_TYPE lets the segmentedDisk wrapper run the identical retry oracle. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 QUEUE_TYPE=${QUEUE_TYPE:-Disk} export RSYSLOG_OMPROG_RESTART_OK="$PWD/$RSYSLOG_DYNNAME.allow-ok" export RSYSLOG_OMPROG_RESTART_OUT="$PWD/$RSYSLOG_OUT_LOG" if [ ! -f ../plugins/omprog/.libs/omprog.so ]; then echo "omprog module not built - skipping test" exit 77 fi cp -f "$srcdir/testsuites/omprog-diskq-restart-save-bin.sh" \ "$RSYSLOG_DYNNAME.omprog-diskq-restart-save-bin.sh" chmod +x "$RSYSLOG_DYNNAME.omprog-diskq-restart-save-bin.sh" generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME'.spool") module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") if $msg contains "msgnum:" then { action( type="omprog" binary="'$RSYSLOG_DYNNAME'.omprog-diskq-restart-save-bin.sh" template="outfmt" name="omprog_action" confirmMessages="on" confirmTimeout="1000" reportFailures="on" action.resumeRetryCount="-1" action.resumeInterval="1" queue.type="'$QUEUE_TYPE'" queue.filename="'$RSYSLOG_DYNNAME'.actq" queue.syncqueuefiles="on" queue.checkpointInterval="1" queue.workerThreads="1" queue.timeoutShutdown="1000" queue.timeoutActionCompletion="1000" queue.saveOnShutdown="on" ) } ' startup injectmsg for _ in {1..30}; do if content_check --check-only "<= ERROR"; then break fi $TESTTOOL_DIR/msleep 1000 done content_check "<= ERROR" shutdown_immediate wait_shutdown touch "$RSYSLOG_OMPROG_RESTART_OK" startup for _ in {1..90}; do ok_count=0 if [ -f "$RSYSLOG_OMPROG_RESTART_OUT" ]; then ok_count=$(grep -c -F -- "<= OK" "$RSYSLOG_OMPROG_RESTART_OUT") fi if [ "$ok_count" -ge 3 ]; then break fi $TESTTOOL_DIR/msleep 1000 done shutdown_when_empty wait_shutdown content_check "=> msgnum:00000000:" content_check "<= ERROR" content_count_check "<= OK" 3 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-ossl-basic-brokenhandshake-vg.sh0000644000000000000000000000013215241075234023750 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.776581496 30 ctime=1787067807.585970858 rsyslog-8.2608.0/tests/imtcp-tls-ossl-basic-brokenhandshake-vg.sh0000775000175000017500000000272415241075234023424 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi . ${srcdir:=.}/diag.sh init export USE_VALGRIND="YES" export NUMMESSAGES=1 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase | send one msg without TLS to force a handshake failure, send second msg with TLS to make the test PASS startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp_veryLargeOctateCountedMessages.sh0000644000000000000000000000013215216464436023736 xustar0030 mtime=1782212894.065266814 30 atime=1782715518.918791051 30 ctime=1787067806.819956584 rsyslog-8.2608.0/tests/imptcp_veryLargeOctateCountedMessages.sh0000775000175000017500000000227215216464436023410 0ustar00rgerrger#!/bin/bash # Test imptcp with poller not processing any messages # test imptcp with very large messages while poller driven processing is disabled # added 2015-10-17 by singh.janmejay # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init # The 32-thread/100k payload stress case overloads TSAN instrumentation; non-TSAN # lanes still cover it, and TSAN still covers lighter imptcp tests. skip_TSAN "the 32-thread/100k payload imptcp stress case overloads TSAN instrumentation" export NUMMESSAGES=20000 generate_conf add_conf '$MaxMessageSize 100k # Intentionally allow 100k payloads to exercise large octet-counted frames. template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") module(load="../plugins/imptcp/.libs/imptcp" threads="32" processOnPoller="off") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if (prifilt("local0.*")) then { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' export RS_REDIR="2>/dev/null" startup tcpflood -c1 -m$NUMMESSAGES -r -d100000 -P129 -O wait_file_lines shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -E -T exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_backticks_empty_envvar.sh0000644000000000000000000000013215132733117022543 xustar0030 mtime=1768666703.966621132 30 atime=1782715518.919791067 30 ctime=1787067805.162925706 rsyslog-8.2608.0/tests/rscript_backticks_empty_envvar.sh0000777000175000017500000000057015132733117022216 0ustar00rgerrger#!/bin/bash # added 2018-11-02 by rgerhards # see also https://github.com/rsyslog/rsyslog/issues/3006 # released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' if `echo $DOES_NOT_EXIST` == "" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup shutdown_when_empty wait_shutdown check_exit content_check --regex "rsyslogd: .*start" exit_test rsyslog-8.2608.0/tests/PaxHeaders/proprepltest-nolimittag.sh0000644000000000000000000000013215241075234021150 xustar0030 mtime=1787067036.637578893 30 atime=1787067036.789581739 30 ctime=1787067803.661897736 rsyslog-8.2608.0/tests/proprepltest-nolimittag.sh0000775000175000017500000000213715241075234020622 0ustar00rgerrger#!/bin/bash # add 2018-06-27 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="+%syslogtag%+\n") :pri, contains, "167" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 TAG: Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 0 Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901 Rest of message...\"" tcpflood -m1 -M "\"<167>Mar 6 16:57:54 172.20.245.8 01234567890123456789012345678901-toolong Rest of message...\"" shutdown_when_empty wait_shutdown echo '+TAG:+ +0+ +01234567890123456789012345678901+ +01234567890123456789012345678901-toolong+' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdtls-sessionbreak.sh0000644000000000000000000000013215216464436020232 xustar0030 mtime=1782212894.054266637 30 atime=1782715518.918791051 30 ctime=1787067807.780974492 rsyslog-8.2608.0/tests/imdtls-sessionbreak.sh0000775000175000017500000000475015216464436017707 0ustar00rgerrger#!/bin/bash # added 2020-04-10 by alorbach, released under ASL 2.0 # # Exercise imdtls cleanup after repeated abrupt DTLS client termination. The # receiver binds an ephemeral UDP port and the testbench discovers the actual # port from the running rsyslog process, avoiding get_free_port races with # parallel tests. Success is proven by all killed tcpflood clients leaving no # established DTLS session owned by the receiver before shutdown. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 export DTLS_SESSIONBREAK_ROUNDS=${DTLS_SESSIONBREAK_ROUNDS:-16} export USE_VALGRIND="yes" # TODO remote leak check skip and fix memory leaks caused by session break export RS_TESTBENCH_LEAK_CHECK=no PORT_RCVR=0 export PORT_RCVR mkdir $RSYSLOG_DYNNAME.workdir generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir'/tls-certs/ca.pem" defaultNetstreamDriverCertFile="'$srcdir'/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="'$srcdir'/tls-certs/key.pem" workDirectory="'$RSYSLOG_DYNNAME.workdir'" maxMessageSize="256k") main_queue(queue.type="Direct") $LocalHostName test $AbortOnUncleanConfig on $PreserveFQDN on module( load="../plugins/imdtls/.libs/imdtls" tls.AuthMode="x509/certvalid") input( type="imdtls" port="'$PORT_RCVR'" ruleset="spool" ) template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="spool" queue.type="direct") { if $msg contains "msgnum:" then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } } ' startup assign_single_udp_listener_port PORT_RCVR # Stress repeated DTLS client churn to exercise session cleanup and fd reuse. for ((i=1;i<=DTLS_SESSIONBREAK_ROUNDS;i++)); do ./tcpflood -Tdtls -p$PORT_RCVR -m$NUMMESSAGES -W1000 -d102400 -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem -s & tcpflood_pid=$! echo "started tcpflood instance $i (PID $tcpflood_pid)" # Give it time to actually connect ./msleep 1000; kill -9 $tcpflood_pid >/dev/null 2>&1 || true wait $tcpflood_pid >/dev/null 2>&1 || true echo "killed tcpflood instance $i (PID $tcpflood_pid)" done; wait_queueempty netstatresult=$(netstat --all --program 2>&1 | grep "ESTABLISHED" | grep "$(cat "$RSYSLOG_PIDBASE.pid")" | grep "$PORT_RCVR") openfd=$(ls -l "/proc/$(cat $RSYSLOG_PIDBASE$1.pid)/fd" | wc -l) shutdown_when_empty wait_shutdown if [[ "$netstatresult" == "" ]] then echo "OK!" else echo "STILL OPENED Connections: " echo $netstatresult echo "Open files at the end: " echo $openfd error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare-common.sh0000644000000000000000000000013215131231047020714 xustar0030 mtime=1768239655.717212794 30 atime=1782715518.918791051 30 ctime=1787067808.205982411 rsyslog-8.2608.0/tests/rscript_compare-common.sh0000777000175000017500000000300615131231047020364 0ustar00rgerrger#!/bin/bash # added by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!result") constant(value="\n") } set $!lower_nr = '$LOWER_VAL'; set $!higher_nr = '$HIGHER_VAL'; if $!lower_nr <= $!higher_nr then { set $!result = "<= RIGHT"; } else { set $!result = "<= WRONG"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") if $!lower_nr < $!higher_nr then { set $!result = "< RIGHT"; } else { set $!result = "< WRONG"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") if $!higher_nr >= $!lower_nr then { set $!result = ">= RIGHT"; } else { set $!result = ">= WRONG"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") if $!higher_nr > $!lower_nr then { set $!result = "> RIGHT"; } else { set $!result = "> WRONG"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") if $!higher_nr != $!lower_nr then { set $!result = "!= RIGHT"; } else { set $!result = "!= WRONG"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") if $!higher_nr == $!lower_nr then { set $!result = "== WRONG"; } else { set $!result = "== RIGHT"; } action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown content_check '<= RIGHT' content_check '>= RIGHT' content_check '!= RIGHT' content_check '== RIGHT' content_check '< RIGHT' content_check '> RIGHT' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-auth-header-limits.sh0000644000000000000000000000013215216464436023653 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.917791033 30 ctime=1787067806.377948347 rsyslog-8.2608.0/tests/imhttp-post-payload-auth-header-limits.sh0000775000175000017500000000440715216464436023327 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify this imhttp POST-payload variant while the HTTP listener uses an # OS-assigned port. The HTTP status and configured output checks are the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" basicAuthFile="'$srcdir'/testsuites/htpasswd" apiKeyFile="'$srcdir'/testsuites/imhttp-apikeys.txt") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" LONG_AUTH_VALUE="$(python3 - <<'PY' print("A" * 20000) PY )" assert_rejected() { local header_name="$1" local header_value="$2" local ret ret=$(curl -s -o /dev/null -w '%{http_code}' \ -H "$header_name: $header_value" \ -H Content-Type:application/json \ http://localhost:$IMHTTP_PORT/postrequest \ -d '[{"msg":"rejected"}]') if [ "$ret" = "200" ]; then echo "ERROR: oversized $header_name unexpectedly succeeded" error_exit 1 fi } assert_rejected "Authorization" "ApiKey $LONG_AUTH_VALUE" assert_rejected "Authorization" "Basic $LONG_AUTH_VALUE" assert_rejected "X-API-Key" "$LONG_AUTH_VALUE" ret=$(curl -s -o /dev/null -w '%{http_code}' \ -H 'X-API-Key: secret-token-1' \ -H Content-Type:application/json \ http://localhost:$IMHTTP_PORT/postrequest \ -d '[{"msg":"whitespace-key"}]') if [ "$ret" != "200" ]; then echo "ERROR: expected 200 for whitespace-padded X-API-Key, got $ret" error_exit 1 fi ret=$(curl -s -o /dev/null -w '%{http_code}' \ --user user1:1234 \ -H Content-Type:application/json \ http://localhost:$IMHTTP_PORT/postrequest \ -d '[{"msg":"basic-ok"}]') if [ "$ret" != "200" ]; then echo "ERROR: expected 200 for valid basic auth after oversized headers, got $ret" error_exit 1 fi wait_queueempty shutdown_when_empty wait_shutdown content_count_check '[{"msg":"rejected"}]' 0 content_count_check '[{"msg":"whitespace-key"}]' 1 content_count_check '[{"msg":"basic-ok"}]' 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-batch-lokirest-retry.sh0000644000000000000000000000013215131231047021621 xustar0030 mtime=1768239655.712212713 30 atime=1782715518.917791033 30 ctime=1787067806.140943931 rsyslog-8.2608.0/tests/omhttp-batch-lokirest-retry.sh0000777000175000017500000000320015131231047021265 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Starting actual testbench . ${srcdir:=.}/diag.sh init export NUMMESSAGES=50000 omhttp_start_server 0 --fail-every 100 generate_conf add_conf ' module(load="../contrib/omhttp/.libs/omhttp") main_queue(queue.dequeueBatchSize="2048") template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") # Echo message as-is for retry template(name="tpl_echo" type="string" string="%msg%") ruleset(name="ruleset_omhttp_retry") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl_echo" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="lokirest" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } ruleset(name="ruleset_omhttp") { action( name="action_omhttp" type="omhttp" errorfile="'$RSYSLOG_DYNNAME/omhttp.error.log'" template="tpl" server="localhost" serverport="'$omhttp_server_lstnport'" restpath="my/endpoint" batch="on" batch.maxsize="100" batch.format="lokirest" retry="on" retry.ruleset="ruleset_omhttp_retry" # Auth usehttps="off" ) & stop } if $msg contains "msgnum:" then call ruleset_omhttp ' startup injectmsg shutdown_when_empty wait_shutdown omhttp_get_data $omhttp_server_lstnport my/endpoint lokirest omhttp_stop_server seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-sigalgs-negative-common.sh0000644000000000000000000000013215241075234024747 xustar0030 mtime=1787067036.634578837 30 atime=1787067036.690579886 30 ctime=1787067808.211982523 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-sigalgs-negative-common.sh0000775000175000017500000002113615241075234024421 0ustar00rgerrger#!/bin/bash # Common negative matrix for PKCS#11-backed omfwd mTLS signing algorithm tests. . ${srcdir:=.}/diag.sh init case "$(basename "$0")" in omfwd-tls-ossl-pkcs11-sigalgs-negative-common.sh) printf 'info: shared helper script; skipping direct execution\n' skip_test ;; esac check_command_available openssl check_command_available softhsm2-util check_command_available pkcs11-tool if [ ! -x ./openssl_mtls_server ]; then echo "openssl_mtls_server helper not built - skipping test" exit 77 fi find_first_existing() { for candidate in "$@"; do if [ -f "$candidate" ]; then printf '%s\n' "$candidate" return 0 fi done return 1 } setup_variant() { case "${PKCS11_SIGALG_VARIANT}" in key_only) TEST_SUFFIX="key-mtls-sigalgs-negative" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-key-mtls-sigalgs-negative" TEST_CA_REF="$workdir/ca.pem" TEST_CERT_REF="$workdir/client.pem" TEST_KEY_REF="$key_uri" ;; cert_key) TEST_SUFFIX="cert-mtls-sigalgs-negative" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-cert-mtls-sigalgs-negative" TEST_CA_REF="$workdir/ca.pem" TEST_CERT_REF="$cert_uri" TEST_KEY_REF="$key_uri" ;; ca_key) TEST_SUFFIX="ca-mtls-sigalgs-negative" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-ca-mtls-sigalgs-negative" TEST_CA_REF="$ca_uri" TEST_CERT_REF="$workdir/client.pem" TEST_KEY_REF="$key_uri" ;; full) TEST_SUFFIX="mtls-sigalgs-negative" TEST_MSG_PREFIX="omfwd-ossl-pkcs11-mtls-sigalgs-negative" TEST_CA_REF="$ca_uri" TEST_CERT_REF="$cert_uri" TEST_KEY_REF="$key_uri" ;; *) printf 'unknown PKCS11_SIGALG_VARIANT=%s\n' "${PKCS11_SIGALG_VARIANT}" >&2 error_exit 1 ;; esac } provider_module=$(find_first_existing \ /usr/lib64/ossl-modules/pkcs11.so \ /usr/lib/ossl-modules/pkcs11.so \ /usr/lib/x86_64-linux-gnu/ossl-modules/pkcs11.so \ /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so \ /usr/local/lib64/ossl-modules/pkcs11.so \ /usr/local/lib/ossl-modules/pkcs11.so) || { printf 'info: skipping test - pkcs11 OpenSSL provider module not found\n' skip_test } softhsm_module=$(find_first_existing \ /usr/lib64/pkcs11/libsofthsm2.so \ /usr/lib/pkcs11/libsofthsm2.so \ /usr/lib64/softhsm/libsofthsm2.so \ /usr/lib/softhsm/libsofthsm2.so \ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib/aarch64-linux-gnu/softhsm/libsofthsm2.so \ /usr/lib64/libsofthsm2.so \ /usr/lib/libsofthsm2.so) || { printf 'info: skipping test - SoftHSM PKCS#11 module not found\n' skip_test } token_label="rsyslog-test-token" token_pin="123456" token_so_pin="12345678" workdir="$RSYSLOG_DYNNAME.${PKCS11_SIGALG_VARIANT}.negative" softhsm_conf="$workdir/softhsm2.conf" openssl_conf="$workdir/openssl-pkcs11.cnf" token_dir="$workdir/tokens" started_log="$RSYSLOG_DYNNAME.started" mkdir -p "$workdir" "$token_dir" cat >"$workdir/server.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth subjectAltName=DNS:localhost,IP:127.0.0.1 EOF cat >"$workdir/client.ext" <<'EOF' basicConstraints=CA:FALSE keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=clientAuth EOF cat >"$workdir/ca.cnf" <<'EOF' [req] distinguished_name = req_distinguished_name x509_extensions = v3_ca prompt = no [req_distinguished_name] [v3_ca] basicConstraints = critical,CA:TRUE,pathlen:0 keyUsage = critical,keyCertSign,cRLSign subjectKeyIdentifier = hash EOF openssl genrsa -out "$workdir/ca.key" 3072 || error_exit 1 openssl req -new -key "$workdir/ca.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=Test-CA" \ -out "$workdir/ca.csr" || error_exit 1 openssl x509 -req -in "$workdir/ca.csr" -signkey "$workdir/ca.key" -sha256 -days 365 \ -extfile "$workdir/ca.cnf" -extensions v3_ca \ -out "$workdir/ca.pem" || error_exit 1 openssl genrsa -out "$workdir/server.key" 3072 || error_exit 1 openssl req -new -key "$workdir/server.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=localhost" \ -out "$workdir/server.csr" || error_exit 1 openssl x509 -req -in "$workdir/server.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/server.ext" \ -out "$workdir/server.pem" || error_exit 1 openssl genrsa -out "$workdir/client.key" 3072 || error_exit 1 openssl req -new -key "$workdir/client.key" \ -subj "/C=US/ST=CA/L=Test/O=rsyslog/OU=test/CN=rsyslog-client" \ -out "$workdir/client.csr" || error_exit 1 openssl x509 -req -in "$workdir/client.csr" -CA "$workdir/ca.pem" -CAkey "$workdir/ca.key" \ -CAcreateserial -sha256 -days 365 -extfile "$workdir/client.ext" \ -out "$workdir/client.pem" || error_exit 1 openssl x509 -in "$workdir/ca.pem" -outform DER -out "$workdir/ca.der" || error_exit 1 openssl x509 -in "$workdir/client.pem" -outform DER -out "$workdir/client.der" || error_exit 1 openssl pkey -in "$workdir/client.key" -pubout -outform DER -out "$workdir/client.pub.der" || \ error_exit 1 cat >"$softhsm_conf" <"$openssl_conf" <"$server_stderr" & server_pid=$! wait_file_exists_for_process "$port_file" "$server_pid" 10 "OpenSSL MTLS helper" "$server_stderr" server_port=$(cat "$port_file") generate_conf add_conf "$(cat <1 2003-03-01T01:00:00.000Z host app - - - ${msg}" if content_check --check-only "SSL_ERROR_SYSCALL" "$started_log"; then : else wait_content "SSL_ERROR_SSL" "$started_log" content_check "SSL_ERROR_SSL" "$started_log" content_check "OpenSSL Error Stack:" "$started_log" fi shutdown_immediate wait_shutdown wait $server_pid || true content_check "OPENSSL-MTLS: SSL_accept failed" "$server_stderr" content_check "peer did not return a certificate" "$server_stderr" content_count_check --regex "^${msg}\$" 0 "$server_capture" } run_negative_case \ "tls12-clientsig-ecdsa-only" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2" \ "MinProtocol=TLSv1.2 MaxProtocol=TLSv1.2 ClientSignatureAlgorithms=ECDSA+SHA256" run_negative_case \ "tls13-clientsig-ecdsa-only" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3" \ "MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 ClientSignatureAlgorithms=ecdsa_secp256r1_sha256" exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-basic-yamlonly.sh0000644000000000000000000000013215216464436020133 xustar0030 mtime=1782212894.092267251 30 atime=1782715518.917791033 30 ctime=1787067805.369929563 rsyslog-8.2608.0/tests/yaml-basic-yamlonly.sh0000775000175000017500000000321515216464436017603 0ustar00rgerrger#!/bin/bash # Tests that the YAML-only testbench mode works end-to-end: # - generate_conf --yaml-only writes a pure YAML preamble using # testbench_modules: for the imdiag setup (no RainerScript) # - test-specific modules go in a standard modules: section # - imdiag is configured as module-scoped testbench instrumentation # - rsyslogd starts and processes messages using only the YAML loader # # This test intentionally avoids any RainerScript or legacy-style directives # so that it exercises the yaml-only testbench path. # # Added 2025 by contributors, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=100 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf --yaml-only # Test-specific modules go in a standard modules: section. # Testbench infrastructure (imdiag) is in testbench_modules: written by the preamble. add_yaml_conf 'modules:' add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"' add_yaml_conf '' add_yaml_conf 'templates:' add_yaml_conf ' - name: outfmt' add_yaml_conf ' type: string' add_yaml_conf " string: \"%msg:F,58:2%\\n\"" add_yaml_conf '' add_yaml_conf 'inputs:' add_yaml_conf " - type: imtcp" add_yaml_conf " port: \"0\"" add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.tcpflood_port\"" add_yaml_conf " ruleset: main" add_yaml_conf '' add_yaml_conf 'rulesets:' add_yaml_conf ' - name: main' add_yaml_conf ' script: |' add_yaml_conf " :msg, contains, \"msgnum:\" action(type=\"omfile\"" add_yaml_conf " template=\"outfmt\" file=\"${RSYSLOG_OUT_LOG}\")" startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp_conndrop.sh0000644000000000000000000000013215131231047017430 xustar0030 mtime=1768239655.706212614 30 atime=1782715518.919791067 30 ctime=1787067806.802956267 rsyslog-8.2608.0/tests/imptcp_conndrop.sh0000777000175000017500000000165715131231047017112 0ustar00rgerrger#!/bin/bash # Test imptcp with many dropping connections # added 2010-08-10 by Rgerhards # # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=${NUMMESSAGES:-50000} # permit valgrind test to override value export TB_TEST_MAX_RUNTIME=${TB_TEST_MAX_RUNTIME:-700} # connection drops are very slow... generate_conf add_conf ' $MaxMessageSize 10k module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n" template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'") $OMFileFlushInterval 2 $OMFileIOBufferSize 256k local0.* ?dynfile;outfmt ' startup # 100 byte messages to gain more practical data use tcpflood -c20 -m$NUMMESSAGES -r -d100 -P129 -D wait_file_lines shutdown_when_empty wait_shutdown export SEQ_CHECK_OPTIONS=-E seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-stream-outfield-vg.sh0000644000000000000000000000013215171370365021744 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.919791067 30 ctime=1787067806.663953677 rsyslog-8.2608.0/tests/omhiredis-stream-outfield-vg.sh0000775000175000017500000000030515171370365021411 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-stream-outfield.sh rsyslog-8.2608.0/tests/PaxHeaders/inputfilegen.c0000644000000000000000000000013215132733117016541 xustar0030 mtime=1768666703.958621011 30 atime=1782715518.919791067 30 ctime=1787067803.575896133 rsyslog-8.2608.0/tests/inputfilegen.c0000666000175000017500000001561415132733117016216 0ustar00rgerrger/* generate an input file suitable for use by the testbench * Copyright (C) 2018-2022 by Rainer Gerhards and Adiscon GmbH. * Copyright (C) 2016-2018 by Pascal Withopf and Adiscon GmbH. * * usage: ./inputfilegen num-lines > file * -m number of messages * -i start number of message * -d extra data to add (all 'X' after the msgnum) * -s size of file to generate * cannot be used together with -m * size may be slightly smaller in order to be able to write * the last complete line. * -M "message count file" - contains number of messages to be written * This is especially useful with -s, as the testbench otherwise does * not know how to do a seq_check. To keep things flexible, can also be * used with -m (this may aid testbench framework generalization). * -f outputfile * Permits to write data to file "outputfile" instead of stdout. Also * enables support for SIGHUP. * -S sleep time * ms to sleep between sending message bulks (bulks size given by -B) * -B number of messages in bulk * number of messages to send without sleeping as specified in -S. * IGNORED IF -S is not also given! * Part of rsyslog, licensed under ASL 2.0 */ #include "config.h" #include #include #include #include #include #include #if defined(_AIX) #include #else #include #endif #if defined(__FreeBSD__) #include #else #include #endif #if defined(HAVE_SYS_SELECT_H) #include #endif #define DEFMSGS 5 #define NOEXTRADATA -1 static volatile int bHadHUP = 0; static void hdlr_sighup(int sig) { fprintf(stderr, "inputfilegen: had hup, sig %d\n", sig); bHadHUP = 1; } static void sighup_enable(void) { struct sigaction sigAct; memset(&sigAct, 0, sizeof(sigAct)); sigemptyset(&sigAct.sa_mask); sigAct.sa_handler = hdlr_sighup; sigaction(SIGHUP, &sigAct, NULL); } void msleep(const int sleepTime) { struct timeval tvSelectTimeout; tvSelectTimeout.tv_sec = sleepTime / 1000; tvSelectTimeout.tv_usec = (sleepTime % 1000) * 1000; /* micro seconds */ if (select(0, NULL, NULL, NULL, &tvSelectTimeout) == -1) { if (errno != EINTR) { perror("select"); exit(1); } } } static FILE *open_output(const char *fn) { FILE *fh_output = fopen(fn, "w"); if (fh_output == NULL) { perror(fn); exit(1); } return fh_output; } int main(int argc, char *argv[]) { int c, i; long long nmsgs = DEFMSGS; long long nmsgstart = 0; int nfinishedidle = 0; int nchars = NOEXTRADATA; int errflg = 0; long long filesize = -1; char *extradata = NULL; const char *msgcntfile = NULL; const char *outputfile = "-"; FILE *fh_output; int sleep_ms = 0; /* How long to sleep between message writes */ int sleep_msgs = 0; /* messages to xmit between sleeps (if configured) */ int sleep_hubreopen_ms = 5; /* Wait until new file is being reopened, logrotate may need some time */ int ctr = 0; while ((c = getopt(argc, argv, "m:M:i:I:h:d:s:f:S:B:")) != -1) { switch (c) { case 'm': nmsgs = atoi(optarg); break; case 'M': msgcntfile = optarg; break; case 'i': nmsgstart = atoi(optarg); break; case 'I': nfinishedidle = atoi(optarg); break; case 'd': nchars = atoi(optarg); break; case 's': filesize = atoll(optarg); break; case 'S': sleep_ms = atoi(optarg); break; case 'B': sleep_msgs = atoi(optarg); break; case 'h': sleep_hubreopen_ms = atoi(optarg); break; case 'f': outputfile = optarg; sighup_enable(); break; case ':': fprintf(stderr, "Option -%c requires an operand\n", optopt); errflg++; break; case '?': fprintf(stderr, "inputfilegen: Unrecognized option: -%c\n", optopt); errflg++; break; } } if (errflg) { fprintf(stderr, "invalid call\n"); exit(2); } if (filesize != -1) { const int linesize = (17 + nchars); /* 17 is std line size! */ nmsgs = filesize / linesize; fprintf(stderr, "inputfilegen: file size requested %lld, actual %lld with " "%lld lines, %lld bytes less\n", filesize, nmsgs * linesize, nmsgs, filesize - nmsgs * linesize); if (nmsgs > 100000000) { fprintf(stderr, "inputfilegen: number of lines exhaust 8-digit line numbers " "which are standard inside the testbench.\n" "Use -d switch to add extra data (e.g. -d111 for " "128 byte lines or -d47 for 64 byte lines)\n"); exit(1); } } if (msgcntfile != NULL) { FILE *const fh = fopen(msgcntfile, "w"); if (fh == NULL) { perror(msgcntfile); exit(1); } fprintf(fh, "%lld", nmsgs); fclose(fh); } if (strcmp(outputfile, "-")) { fh_output = open_output(outputfile); } else { fh_output = stdout; } if (nchars != NOEXTRADATA) { extradata = (char *)malloc(nchars + 1); memset(extradata, 'X', nchars); extradata[nchars] = '\0'; } for (i = nmsgstart; i < (nmsgs + nmsgstart); ++i) { if (sleep_ms > 0 && ctr++ >= sleep_msgs) { msleep(sleep_ms); ctr = 0; } if (bHadHUP) { fclose(fh_output); if (sleep_hubreopen_ms > 0) { /* Extra Sleep so logrotate or whatever can take place */ msleep(sleep_hubreopen_ms); } fh_output = open_output(outputfile); fprintf(stderr, "inputfilegen: %s reopened\n", outputfile); fprintf(stderr, "inputfilegen: current message number %d\n", i); bHadHUP = 0; } fprintf(fh_output, "msgnum:%8.8d:", i); if (nchars != NOEXTRADATA) { fprintf(fh_output, "%s", extradata); } fprintf(fh_output, "\n"); } if (nfinishedidle > 0) { /* Keep process open for nfinishedidle ms */ for (int x = 0; x < nfinishedidle; ++x) { if (bHadHUP) { /* Create empty file */ fh_output = open_output(outputfile); fclose(fh_output); fprintf(stderr, "inputfilegen: last message number was %d\n", i); bHadHUP = 0; } msleep(1); } } free(extradata); return 0; } rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-crash-reservation.sh0000644000000000000000000000013215241075234023645 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.785900046 rsyslog-8.2608.0/tests/segmented-diskqueue-crash-reservation.sh0000775000175000017500000000031215241075234023310 0ustar00rgerrger#!/bin/bash # Crash after durable next-segment reservation; restart must not reuse its ID. export SEGDISK_FAULT_POINT=reservation-published . ${srcdir:=.}/testsuites/segmented-diskqueue-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/include-obj-text-from-file-noexist.sh0000644000000000000000000000013215131231047022754 xustar0030 mtime=1768239655.708212647 30 atime=1782715518.919791067 30 ctime=1787067805.001922706 rsyslog-8.2608.0/tests/include-obj-text-from-file-noexist.sh0000777000175000017500000000063515131231047022431 0ustar00rgerrger#!/bin/bash # added 2018-01-22 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' if $msg contains "msgnum:" then { include(text=`cat '${srcdir}'/testsuites/DOES-NOT-EXIST`) } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check --regex 'file could not be accessed for `cat .*/testsuites/DOES-NOT-EXIST' exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmexternal-interface-output-none.sh0000644000000000000000000000013215216464436022655 xustar0030 mtime=1782212894.073266944 30 atime=1782715518.918791051 30 ctime=1787067804.107906047 rsyslog-8.2608.0/tests/mmexternal-interface-output-none.sh0000775000175000017500000000204715216464436022327 0ustar00rgerrger#!/bin/bash # added 2026-05-22 by Codex, released under ASL 2.0 # Regression coverage for issue #260: interface.output="none" lets an # external message modification helper consume messages without producing the # JSON response required by the default protocol. Because this mode has no # helper reply to synchronize on, the oracle waits for the helper side-effect # file before shutdown and then checks both that file and downstream omfile. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/mmexternal/.libs/mmexternal") template(name="outfmt" type="string" string="%msg%\n") action(type="mmexternal" interface.output="none" binary="'${srcdir}'/testsuites/mmexternal-no-output.sh '$RSYSLOG_DYNNAME'.side") action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal "<13>Mar 10 01:00:00 host tag:no-output-message" wait_file_lines "$RSYSLOG_DYNNAME.side" 1 shutdown_when_empty wait_shutdown content_check "no-output-message" content_check "no-output-message" "$RSYSLOG_DYNNAME.side" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-lb-1target-retry-test_skeleton-TargetFail.sh0000644000000000000000000000013215216464436025370 xustar0030 mtime=1782212894.077267008 30 atime=1782715518.917791033 30 ctime=1787067805.052923656 rsyslog-8.2608.0/tests/omfwd-lb-1target-retry-test_skeleton-TargetFail.sh0000775000175000017500000000435115216464436025042 0ustar00rgerrger#!/bin/bash # added 2024-02-19 by rgerhards. Released under ASL 2.0 # This test is not meant to be executed independently. It just permits # to be called by different drivers with different io buffer sizes. # This in turn is needed to test some edge cases. . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test is currently not supported on solaris due to too-different timing" generate_conf export NUMMESSAGES=2000 export OMFWD_TARGETFAIL_MAX_LOSS=250 export OMFWD_TARGETFAIL_MIN_RECEIVED=$((NUMMESSAGES - OMFWD_TARGETFAIL_MAX_LOSS)) export IMDIAG_INJECTMSG_DELAY_MS=10 # Start minitcpsrv with a forced receiver-side TCP session close and a # temporary listener restart. The test verifies that omfwd retries and # reconnects after that disruption. export MINITCPSRV_EXTRA_OPTS="-D900 -B2 -a -S5" start_minitcpsrvr $RSYSLOG_OUT_LOG 1 add_conf ' $MainMsgQueueTimeoutShutdown 10000 $MainMsgQueueDequeueBatchSize 100 global(allMessagesToStderr="on") template(name="outfmt" type="string" string="%msg:F,58:2%\n") module(load="builtin:omfwd" template="outfmt" iobuffer.maxSize="'$OMFWD_IOBUF_SIZE'") if $msg contains "msgnum:" then { action(type="omfwd" target=["127.0.0.1"] port="'$MINITCPSRVR_PORT1'" protocol="tcp" pool.resumeInterval="2" action.reportsuspensioncontinuation="on" action.resumeRetryCount="-1" action.resumeInterval="3") } ' echo Note: intentionally not started any local TCP receiver! # now do the usual run startup # Throttle imdiag injection so the forced close happens with less # burst-created data already accepted by omfwd, the kernel, or TCP buffers. # This keeps the scenario focused on retry/reconnect behavior. Some bounded # loss is still expected because a successful send() only proves kernel # acceptance, not that the receiver application persisted the message. injectmsg wait_file_lines "$RSYSLOG_OUT_LOG" "$OMFWD_TARGETFAIL_MIN_RECEIVED" shutdown_when_empty wait_shutdown # note: minitcpsrv shuts down automatically if the connection is closed! export SEQ_CHECK_OPTIONS=-d # Permit bounded message loss in this forced receiver-close test. The # pre-shutdown wait above keeps the assertion meaningful while the -m check # accepts the expected loss window. seq_check 0 $((NUMMESSAGES-1)) -m"$OMFWD_TARGETFAIL_MAX_LOSS" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_optimizer1.sh0000644000000000000000000000013215035412264020110 xustar0030 mtime=1752569012.411674314 30 atime=1782715518.917791033 30 ctime=1787067804.756918141 rsyslog-8.2608.0/tests/rscript_optimizer1.sh0000777000175000017500000000136515035412264017566 0ustar00rgerrger#!/bin/bash # added 2012-09-20 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_optimizer1.sh\]: testing rainerscript optimizer . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" field.delimiter="58" field.number="2") constant(value="\n") } /* tcpflood uses local4.=debug */ if prifilt("syslog.*") then stop # it actually does not matter what we do here else action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg 0 5000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmnormalize_processing_test3.sh0000644000000000000000000000013215241075234022150 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067805.867938844 rsyslog-8.2608.0/tests/mmnormalize_processing_test3.sh0000775000175000017500000000641615241075234021626 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init . $srcdir/faketime_common.sh export TZ=TEST+01:00 generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmnormalize/.libs/mmnormalize") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="t_file_record" type="string" string="%timestamp:::date-rfc3339% %timestamp:::date-rfc3339% %hostname% %$!v_tag% %$!v_msg%\n") template(name="t_file_path" type="string" string="/sb/logs/incoming/%$year%/%$month%/%$day%/svc_%$!v_svc%/ret_%$!v_ret%/os_%$!v_os%/%fromhost-ip%/r_relay1/%$!v_file:::lowercase%.gz\n") template(name="t_fromhost-ip" type="string" string="%fromhost-ip%") template(name="t_analytics_msg_default" type="string" string="%$!v_analytics_prefix%%rawmsg-after-pri%") template(name="t_analytics_tag_prefix" type="string" string="%$!v_tag%: ") template(name="t_analytics_msg_normalized" type="string" string="%timereported% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%") template(name="t_analytics_msg_normalized_vc" type="string" string="%timereported:1:6% %$year% %timereported:8:$% %$!v_hostname% %$!v_analytics_prefix%%$!v_msg%") template(name="t_analytics" type="string" string="[][][%$!v_fromhost-ip%][%timestamp:::date-unixtimestamp%][] %$!v_analytics_msg%\n") ruleset(name="ruleset1") { action(type="mmnormalize" rulebase="'$srcdir/testsuites/mmnormalize_processing_tests.rulebase'" useRawMsg="on") if ($!v_file == "") then { set $!v_file=$!v_tag; } action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_record") action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_file_path") set $!v_forward="PCI"; if ($!v_forward contains "PCI") then { if ($!v_fromhost-ip == "") then { set $!v_fromhost-ip=exec_template("t_fromhost-ip"); } if ($!v_msg == "" or $!v_tag == "") then { set $!v_analytics_msg=exec_template("t_analytics_msg_default"); } else { if ($!v_analytics_prefix == "") then { set $!v_analytics_prefix=exec_template("t_analytics_tag_prefix"); } if ($!v_hostname == "") then { # needed for vCenter logs with custom hostname set $!v_hostname=exec_template("t_fromhost-ip"); } if ($!v_exception == "VC") then { set $!v_analytics_msg=exec_template("t_analytics_msg_normalized_vc"); } else { set $!v_analytics_msg=exec_template("t_analytics_msg_normalized"); } } action(type="omfile" File="'$RSYSLOG_OUT_LOG'" template="t_analytics") } } ' FAKETIME='2017-03-08 14:23:51' startup tcpflood -m1 -M "\"<182>Mar 8 14:23:51 host3 audispd: {SER3.local6 Y01 LNX [SRCH ALRT DASH REPT ANOM]} node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721):\"" shutdown_when_empty wait_shutdown echo '2017-03-08T14:23:51-01:00 2017-03-08T14:23:51-01:00 host3 audispd node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721): /sb/logs/incoming/2017/03/08/svc_SER3/ret_Y01/os_LNX/127.0.0.1/r_relay1/local6.gz [][][127.0.0.1][1488986631][] Mar 8 14:23:51 host3 audispd: node=host3.domain.com type=SYSCALL msg=audit(1488975831.267:230190721):' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zlib-impstats.sh0000644000000000000000000000013015241075234022741 xustar0029 mtime=1787067036.62457865 29 atime=1787067036.77358144 30 ctime=1787067805.577933439 rsyslog-8.2608.0/tests/imtcp-stream-always-zlib-impstats.sh0000775000175000017500000000447015241075234022417 0ustar00rgerrger#!/bin/bash # added 2026-05-17 by Codex, released under ASL 2.0 # Verifies imtcp stream:always accounting for zlib traffic; compressed bytes # must be positive and decompressed bytes must exceed wire bytes. . ${srcdir:=.}/diag.sh init require_plugin imtcp require_plugin impstats export NUMMESSAGES=8000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export STATSFILE="$RSYSLOG_DYNNAME.stats" generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1") input(type="imtcp" address="127.0.0.1" name="streamstats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zlib") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.driver="zlib" compression.stream.flushOnTXEnd="on") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines sleep 2 shutdown_when_empty wait_shutdown content_check "origin=imtcp" "$STATSFILE" IMTCP_STATS=$(grep 'origin=imtcp' "$STATSFILE") MAX_RCV=$(printf '%s\n' "$IMTCP_STATS" | grep -o 'bytes.received=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_DECOMP=$(printf '%s\n' "$IMTCP_STATS" | grep -o 'bytes.decompressed=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_SUB=$(printf '%s\n' "$IMTCP_STATS" | grep -o 'submitted=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) if [ -z "$MAX_RCV" ] || [ -z "$MAX_DECOMP" ] || [ -z "$MAX_SUB" ]; then echo "FAIL: expected imtcp impstats counters missing" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_RCV" -le 0 ]; then echo "FAIL: expected bytes.received > 0, got $MAX_RCV" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_DECOMP" -le "$MAX_RCV" ]; then echo "FAIL: expected bytes.decompressed > bytes.received for stream compression, got $MAX_DECOMP <= $MAX_RCV" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_SUB" -lt "$NUMMESSAGES" ]; then echo "FAIL: expected submitted >= $NUMMESSAGES, got $MAX_SUB" cat "$STATSFILE" error_exit 1 fi seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/stop-msgvar.sh0000644000000000000000000000013215241075234016522 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.798581908 30 ctime=1787067804.067905301 rsyslog-8.2608.0/tests/stop-msgvar.sh0000775000175000017500000000167415241075234016201 0ustar00rgerrger#!/bin/bash # Test for "stop" statement # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[stop-msgvar.sh\]: testing stop statement together with message variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$!nbr%\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if $msg contains "msgnum:" then { set $!nbr = field($msg, 58, 2); if cnum($!nbr) < 100 then stop /* check is intentionally more complex than needed! */ else if not (cnum($!nbr) > 999) then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } } ' startup sleep 1 tcpflood -m2000 -i1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 100 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_le_var.sh0000644000000000000000000000013215035412264017255 xustar0030 mtime=1752569012.411674314 30 atime=1782715518.918791051 30 ctime=1787067804.821919352 rsyslog-8.2608.0/tests/rscript_le_var.sh0000777000175000017500000000330715035412264016731 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_le.sh\]: testing rainerscript LE statement for two JSON variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } set $!var1 = "42"; set $!var2 = "42"; set $!var3 = "43"; if $!var1 <= $!var2 and $!var1 <= $!var3 then { if $!var3 <= $!var1 then { # Failure stop } else { unset $!var1; unset $!var2; unset $!var3; } } else { # Failure stop } set $.var1 = "42"; set $.var2 = "42"; set $.var3 = "43"; if $.var1 <= $.var2 and $.var1 <= $.var3 then { if $.var3 <= $.var1 then { # Failure stop } else { unset $.var1; unset $.var2; unset $.var3; } } else { # Failure stop } set $/var1 = "42"; set $/var2 = "42"; set $/var3 = "43"; if $/var1 <= $/var2 and $/var1 <= $/var3 then { if $/var3 <= $/var1 then { # Failure stop } else { unset $/var1; unset $/var2; unset $/var3; } } else { # Failure stop } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup injectmsg 0 1 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/asynwr_tinybuf.sh0000644000000000000000000000013215241075234017323 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.762581234 30 ctime=1787067804.532913967 rsyslog-8.2608.0/tests/asynwr_tinybuf.sh0000775000175000017500000000262415241075234016776 0ustar00rgerrger#!/bin/bash # This tests async writing with a very small output buffer (1 byte!), # so it stresses output buffer handling. This also means operations will # be somewhat slow, so we send only a small amounts of data. # # added 2010-03-09 by Rgerhards # # This file is part of the rsyslog project, released under GPLv3 echo =============================================================================== echo TEST: \[asynwr_tinybuf.sh\]: test async file writing with 1-byte buffer . ${srcdir:=.}/diag.sh init export CI_SHUTDOWN_QUEUE_EMPTY_CHECKS=20 # this test is notoriously slow... generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp $MainMsgQueueTimeoutShutdown 10000 input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! $OMFileFlushOnTXEnd off $OMFileFlushInterval 2 $OMFileIOBufferSize 1 $OMFileAsyncWriting on :msg, contains, "msgnum:" ?dynfile;outfmt ' # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" #export RSYSLOG_DEBUGLOG="log" startup # send 1000 messages, fairly enough to trigger problems tcpflood -m1000 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # shut down rsyslogd when done processing messages seq_check 0 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/sparse_array_lookup_table-vg.sh0000644000000000000000000000013215171370365022112 xustar0030 mtime=1776677109.470913526 30 atime=1782715518.917791033 30 ctime=1787067805.280927905 rsyslog-8.2608.0/tests/sparse_array_lookup_table-vg.sh0000775000175000017500000000027215171370365021562 0ustar00rgerrger#!/bin/bash # added 2015-10-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/sparse_array_lookup_table.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-basic-vg.sh0000644000000000000000000000013215171370365017652 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.916791016 30 ctime=1787067807.361966684 rsyslog-8.2608.0/tests/imtcp-tls-basic-vg.sh0000775000175000017500000000011015171370365017311 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/imtcp-tls-basic.sh rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs.sh0000644000000000000000000000013015241075234023215 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.688579848 30 ctime=1787067807.594971025 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-ca-mtls-sigalgs.sh0000775000175000017500000000014715241075234022670 0ustar00rgerrger#!/bin/bash export PKCS11_SIGALG_VARIANT=ca_key . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-sigalgs-common.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-idle-crash-state-unlink.sh0000644000000000000000000000013115241075234023221 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 29 ctime=1787067803.84190109 rsyslog-8.2608.0/tests/segmented-da-idle-crash-state-unlink.sh0000775000175000017500000000043015241075234022666 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Crash after state unlink, when the queue directory is empty. export SEGDISK_IDLE_FAULT_POINT=idle-state-unlinked . ${srcdir:=.}/testsuites/segmented-da-idle-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_tls_ossl_servercert_ossl_clientanon.sh0000644000000000000000000000013215216464436025207 xustar0030 mtime=1782212894.084267122 30 atime=1782715518.916791016 30 ctime=1787067807.529969814 rsyslog-8.2608.0/tests/sndrcv_tls_ossl_servercert_ossl_clientanon.sh0000775000175000017500000000355615216464436024667 0ustar00rgerrger#!/bin/bash # alorbach, 2019-01-16 # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1000 # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="ossl" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) # then SENDER sends to this port (not tcpflood!) input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.rcvr_port" ) $template outfmt,"%msg:F,58:2%\n" $template dynfile,"'$RSYSLOG_OUT_LOG'" # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup assign_file_content PORT_RCVR "$RSYSLOG_DYNNAME.rcvr_port" export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" ) # Note: no TLS for the listener, this is for tcpflood! module( load="../plugins/imtcp/.libs/imtcp") input( type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) # set up the action action( type="omfwd" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" StreamDriver="ossl" StreamDriverMode="1" StreamDriverAuthMode="x509/certvalid" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. tcpflood -m$NUMMESSAGES -i1 wait_file_lines # shut down sender when everything is sent, receiver continues to run concurrently shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 $NUMMESSAGES exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-vg.sh0000644000000000000000000000013115171370365020575 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.919791067 29 ctime=1787067806.41994913 rsyslog-8.2608.0/tests/imhttp-post-payload-vg.sh0000775000175000017500000000023215171370365020242 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" . ${srcdir:-.}/imhttp-post-payload.sh rsyslog-8.2608.0/tests/PaxHeaders/arrayqueue.sh0000644000000000000000000000013215131231047016415 xustar0030 mtime=1768239655.700212516 30 atime=1782715518.918791051 30 ctime=1787067804.374911022 rsyslog-8.2608.0/tests/arrayqueue.sh0000777000175000017500000000107015131231047016064 0ustar00rgerrger#!/bin/bash # Test for fixedArray queue mode # added 2009-05-20 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=40000 generate_conf add_conf ' # set spool locations and switch queue to disk-only mode $MainMsgQueueType FixedArray $template outfmt,"%msg:F,58:2%\n" template(name="dynfile" type="string" string=`echo $RSYSLOG_OUT_LOG`) # trick to use relative path names! :msg, contains, "msgnum:" ?dynfile;outfmt ' startup injectmsg shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-set.sh0000644000000000000000000000013215145046113017011 xustar0030 mtime=1771326539.054014533 30 atime=1782715518.917791033 30 ctime=1787067806.603952559 rsyslog-8.2608.0/tests/omhiredis-set.sh0000775000175000017500000000243515145046113016464 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging # export RS_REDIR=-d . ${srcdir:=.}/diag.sh init start_redis generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omhiredis/.libs/omhiredis") template(name="outfmt" type="string" string="%msg%") local4.* { action(type="omhiredis" name="omhiredis-set" server="127.0.0.1" serverport="'$REDIS_RANDOM_PORT'" mode="set" key="outKey" template="outfmt") stop } action(type="omfile" file="'$RSYSLOG_DYNNAME.othermsg'" template="outfmt") ' # Should get 'none' redis_command "TYPE outKey" > $RSYSLOG_OUT_LOG startup # Inject 1 message injectmsg 1 1 shutdown_when_empty wait_shutdown # Should get 'string' redis_command "TYPE outKey" >> $RSYSLOG_OUT_LOG # Should get ' msgnum:00000001:' redis_command "GET outKey" >> $RSYSLOG_OUT_LOG # The first get is before inserting, the second is after export EXPECTED="none string msgnum:00000001:" cmp_exact $RSYSLOG_OUT_LOG content_check "omhiredis[omhiredis-set]: trying connect to '127.0.0.1'" ${RSYSLOG_DYNNAME}.started stop_redis # Removes generated configuration file, log and pid files cleanup_redis exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_hash32-vg.sh0000644000000000000000000000013215241075234017510 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067806.877957664 rsyslog-8.2608.0/tests/rscript_hash32-vg.sh0000775000175000017500000000201315241075234017153 0ustar00rgerrger#!/bin/bash # added 2018-02-07 by Harshvardhan Shrivastava # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \rscript_hash32.sh\]: test for hash32 and hash64mod script-function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$.hash_no_1% - %$.hash_no_2%\n") module(load="../plugins/imtcp/.libs/imtcp") module(load="../contrib/fmhash/.libs/fmhash") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") set $.hash_no_1 = hash32("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e"); set $.hash_no_2 = hash32mod("0f9a1d07-a8c9-43a7-a6f7-198dca3d932e", 100); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup_vg tcpflood -m 20 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown_vg check_exit_vg . $srcdir/diag.sh content-pattern-check "^\(746581550 - 50\|3889673532 - 32\)$" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_faup_tld_vg.sh0000644000000000000000000000013215171370365020305 xustar0030 mtime=1776677109.469913511 30 atime=1782715518.919791067 30 ctime=1787067806.995959863 rsyslog-8.2608.0/tests/rscript_faup_tld_vg.sh0000775000175000017500000000020415171370365017750 0ustar00rgerrger#!/bin/bash # added 2021-11-05 by Theo Bertin, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/rscript_faup_tld.sh rsyslog-8.2608.0/tests/PaxHeaders/imdocker-image-name-vg.sh0000644000000000000000000000013215216464436020455 xustar0030 mtime=1782212894.053266621 30 atime=1782715518.920791084 30 ctime=1787067806.356947956 rsyslog-8.2608.0/tests/imdocker-image-name-vg.sh0000775000175000017500000000013415216464436020122 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . "${srcdir:-$(dirname "$0")}/imdocker-image-name.sh" rsyslog-8.2608.0/tests/PaxHeaders/rscript_compare_num-str-vg.sh0000644000000000000000000000013215171370365021540 xustar0030 mtime=1776677109.468913495 30 atime=1782715518.919791067 30 ctime=1787067805.241927178 rsyslog-8.2608.0/tests/rscript_compare_num-str-vg.sh0000775000175000017500000000017415171370365021211 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" export LOWER_VAL='1' export HIGHER_VAL='"b"' . ${srcdir:-.}/rscript_compare-common.sh rsyslog-8.2608.0/tests/PaxHeaders/imptcp-stream-always-impstats.sh0000644000000000000000000000013215216464436022175 xustar0030 mtime=1782212894.062266766 30 atime=1782715518.918791051 30 ctime=1787067806.870957534 rsyslog-8.2608.0/tests/imptcp-stream-always-impstats.sh0000775000175000017500000000505715216464436021653 0ustar00rgerrger#!/bin/bash # added 2026-04-20 by Codex, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=8000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines export STATSFILE="$RSYSLOG_DYNNAME.stats" generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") module(load="../plugins/impstats/.libs/impstats" log.file="'$STATSFILE'" interval="1") input(type="imptcp" name="streamstats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup export RCVR_PORT=$TCPFLOOD_PORT generate_conf 2 add_conf ' module(load="builtin:omfwd") *.* action(type="omfwd" target="127.0.0.1" port="'$RCVR_PORT'" protocol="tcp" compression.mode="stream:always" compression.stream.flushOnTXEnd="on") ' 2 startup 2 injectmsg2 shutdown_when_empty 2 wait_shutdown 2 wait_file_lines sleep 2 shutdown_when_empty wait_shutdown content_check "origin=imptcp" "$STATSFILE" IMPTCP_STATS=$(grep 'origin=imptcp' "$STATSFILE") MAX_RCV=$(printf '%s\n' "$IMPTCP_STATS" | grep -o 'bytes.received=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_DECOMP=$(printf '%s\n' "$IMPTCP_STATS" | grep -o 'bytes.decompressed=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_SUB=$(printf '%s\n' "$IMPTCP_STATS" | grep -o 'submitted=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_OPENED=$(printf '%s\n' "$IMPTCP_STATS" | grep -o 'sessions.opened=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) MAX_CLOSED=$(printf '%s\n' "$IMPTCP_STATS" | grep -o 'sessions.closed=[0-9][0-9]*' | cut -d= -f2 | sort -n | tail -n1) if [ -z "$MAX_RCV" ] || [ -z "$MAX_DECOMP" ] || [ -z "$MAX_SUB" ] || [ -z "$MAX_OPENED" ] || [ -z "$MAX_CLOSED" ]; then echo "FAIL: expected imptcp impstats counters missing" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_RCV" -le 0 ]; then echo "FAIL: expected bytes.received > 0, got $MAX_RCV" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_DECOMP" -le "$MAX_RCV" ]; then echo "FAIL: expected bytes.decompressed > bytes.received for stream compression, got $MAX_DECOMP <= $MAX_RCV" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_SUB" -lt "$NUMMESSAGES" ]; then echo "FAIL: expected submitted >= $NUMMESSAGES, got $MAX_SUB" cat "$STATSFILE" error_exit 1 fi if [ "$MAX_OPENED" -lt 1 ] || [ "$MAX_CLOSED" -lt 1 ]; then echo "FAIL: expected imptcp session counters to record an open and close, got opened=$MAX_OPENED closed=$MAX_CLOSED" cat "$STATSFILE" error_exit 1 fi seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-script-localvar.sh0000644000000000000000000000013215241075234020305 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 30 ctime=1787067805.389929936 rsyslog-8.2608.0/tests/yaml-script-localvar.sh0000775000175000017500000000245415241075234017761 0ustar00rgerrger#!/bin/bash # Tests local ($.var) variables inside a YAML script: block combined with # a complex if/elseif/else chain. # Sends 2000 messages starting at sequence 1; messages with sequence number # < 100 or > 999 are dropped; messages 100-999 reach the output file. # Mirrors stop-localvar.sh using YAML configuration. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=900 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%.nbr%\n" rulesets: - name: main script: | if $msg contains "msgnum:" then { set $.nbr = field($msg, 58, 2); if cnum($.nbr) < 100 then stop else if not (cnum($.nbr) > 999) then action(type="omfile" file="${RSYSLOG_OUT_LOG}" template="outfmt") } YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m2000 -i1 shutdown_when_empty wait_shutdown seq_check 100 999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omsendertrack-basic.sh0000644000000000000000000000013115241075234020157 xustar0030 mtime=1787067036.635578856 30 atime=1787067036.786581683 29 ctime=1787067805.09392442 rsyslog-8.2608.0/tests/omsendertrack-basic.sh0000775000175000017500000000227715241075234017637 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10 # MUST be an even number! export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/omsendertrack/.libs/omsendertrack") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="hostname" type="string" string="%hostname%") action(type="omsendertrack" senderid="hostname" statefile="'$RSYSLOG_DYNNAME'.sendertrack") # The following is just to find a terminating condition for message injection template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -h sender1.example.net -m $(( NUMMESSAGES / 2 - 1 )) tcpflood -h sender2.example.net -m 1 -i $(( NUMMESSAGES / 2 - 1 )) # this sender must have firstseen <> lastseen sleep 2 tcpflood -h sender2.example.net -m $(( NUMMESSAGES / 2 )) -i $(( NUMMESSAGES / 2 )) ./msleep 20 shutdown_when_empty sleep 1 echo cat ${RSYSLOG_DYNNAME}.sendertrack echo wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-basic-bulk-vg.sh0000644000000000000000000000013215171370365017300 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.917791033 30 ctime=1787067803.959903289 rsyslog-8.2608.0/tests/es-basic-bulk-vg.sh0000775000175000017500000000010615171370365016744 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/es-basic-bulk.sh rsyslog-8.2608.0/tests/PaxHeaders/stats-json-es.sh0000644000000000000000000000013115241075234016751 xustar0030 mtime=1787067036.645579043 30 atime=1787067036.797581889 29 ctime=1787067806.71295459 rsyslog-8.2608.0/tests/stats-json-es.sh0000775000175000017500000000253415241075234016425 0ustar00rgerrger#!/bin/bash # added 2016-03-30 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[stats-json-es.sh\]: test for verifying stats are reported correctly json-elasticsearch format . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ruleset(name="stats") { action(type="omfile" file="'${RSYSLOG_DYNNAME}'.out.stats.log") } module(load="../plugins/impstats/.libs/impstats" interval="1" severity="7" resetCounters="on" Ruleset="stats" bracketing="on" format="json-elasticsearch") if ($msg == "this condition will never match") then { action(name="an_action_that_is_never_called" type="omfile" file=`echo $RSYSLOG_OUT_LOG`) } ' startup injectmsg_file $srcdir/testsuites/dynstats_input_1 wait_queueempty wait_for_stats_flush ${RSYSLOG_DYNNAME}.out.stats.log echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown custom_content_check '{ "name": "an_action_that_is_never_called", "origin": "core.action", "processed": 0, "batchesprocessed": 0, "failed": 0, "suspended": 0, "suspended!duration": 0, "resumed": 0, "ratelimit!allowed": 0, "ratelimit!dropped": 0, "ratelimit!paced": 0, "ratelimit!paced_usec": 0 }' "${RSYSLOG_DYNNAME}.out.stats.log" custom_assert_content_missing '@cee' "${RSYSLOG_DYNNAME}.out.stats.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/allowed-sender-tcp-hostname-fail.sh0000644000000000000000000000013115241075234022455 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.761581215 29 ctime=1787067804.41291173 rsyslog-8.2608.0/tests/allowed-sender-tcp-hostname-fail.sh0000775000175000017500000000247415241075234022134 0ustar00rgerrger#!/bin/bash # check that we are able to receive messages from allowed sender # added 2019-08-19 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init # Note: we need to know if CI supports DNS resolution. For this, we try to access # our rsyslog echo service. If that works, DNS obviously works. On the contrary # if we cannot access it, DNS might still work. But we prefer to skip the test in # that case (on rsyslog CI it will always work). rsyslog_testbench_test_url_access http://testbench.rsyslog.com/testbench/echo-get.php export NUMMESSAGES=5 # it's just important that we get any messages at all generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs") $AllowedSender TCP,www.rsyslog.com template(name="outfmt" type="string" string="%msg:F,58:2%\n") ruleset(name="rs") { action(type="omfile" template="outfmt" file="'$RSYSLOG_DYNNAME.must-not-be-created'") } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port tcpflood --check-only -m$NUMMESSAGES shutdown_when_empty wait_shutdown content_check --regex "connection request from disallowed sender .* discarded" check_file_not_exists "$RSYSLOG_DYNNAME.must-not-be-created" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-basic-auth-challenge.sh0000644000000000000000000000013115216464436024124 xustar0030 mtime=1782212894.056266669 30 atime=1782715518.923791135 29 ctime=1787067806.40494885 rsyslog-8.2608.0/tests/imhttp-post-payload-basic-auth-challenge.sh0000775000175000017500000000253215216464436023576 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify this imhttp POST-payload variant while the HTTP listener uses an # OS-assigned port. The HTTP status and configured output checks are the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" HEADERS=${RSYSLOG_DYNNAME}.headers add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'") input(type="imhttp" endpoint="/postrequest" ruleset="ruleset" basicauthfile="'$srcdir'/testsuites/htpasswd") ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" ret=$(curl -s -D "$HEADERS" -o /dev/null --write-out '%{http_code}' \ --user user1:badpass http://localhost:$IMHTTP_PORT/postrequest -d 'rejected') echo "response: $ret" if [ "$ret" != "401" ]; then echo "ERROR: invalid Basic auth credentials returned $ret instead of 401" error_exit 1 fi if ! grep -qi '^WWW-Authenticate: Basic ' "$HEADERS"; then echo "ERROR: Basic auth challenge header missing" error_exit 1 fi wait_queueempty shutdown_when_empty wait_shutdown if [ -f "$RSYSLOG_OUT_LOG" ]; then content_count_check 'rejected' 0 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_dtls_anon_ciphers.sh0000644000000000000000000000013115216464436021324 xustar0029 mtime=1782212894.08226709 30 atime=1782715518.923791135 30 ctime=1787067807.790974678 rsyslog-8.2608.0/tests/sndrcv_dtls_anon_ciphers.sh0000775000175000017500000000376715216464436021011 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Verify that omdtls-to-imdtls anonymous DTLS fails cleanly when the configured # cipher suites are incompatible. The expected OpenSSL diagnostic is the oracle. . ${srcdir:=.}/diag.sh init # start up the instances # uncomment for debugging support: #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog" generate_conf PORT_RCVR_FILE="$RSYSLOG_DYNNAME.imdtls.port" add_conf ' global( debug.whitelist="on" debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imdtls/.libs/imdtls" tls.AuthMode="anon") input( type="imdtls" tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_256_GCM_SHA384" port="0" listenPortFileName="'$PORT_RCVR_FILE'") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content PORT_RCVR "$PORT_RCVR_FILE" export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog" generate_conf 2 add_conf ' module( load="../plugins/omdtls/.libs/omdtls" ) action( name="omdtls" type="omdtls" target="127.0.0.1" port="'$PORT_RCVR'" tls.tlscfgcmd="CipherString=ECDHE-RSA-AES256-SHA384;Ciphersuites=TLS_AES_128_GCM_SHA256" ) ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg 0 1 shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown # IMPORTANT: this test will generate many error messages. This is exactly it's # intent. So do not think something is wrong. The content_check below checks # these error codes. content_check --check-only "TLS library does not support SSL_CONF_cmd" ret=$? if [ $ret == 0 ]; then echo "SKIP: TLS library does not support SSL_CONF_cmd" skip_test else # Kindly check for a failed session content_check "OpenSSL Error Stack" content_check "no shared cipher" fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmkubernetes-namespace-metadata-off.sh0000644000000000000000000000013215241075234023221 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.686579811 30 ctime=1787067808.146981312 rsyslog-8.2608.0/tests/mmkubernetes-namespace-metadata-off.sh0000775000175000017500000000562715241075234022702 0ustar00rgerrger#!/bin/bash # Verify includeNamespaceMetadata="off" skips the namespace API lookup while # retaining parsed namespace identity and pod metadata. The output fields and # absence of a namespace-only request in the test-server log are the oracle. # The two-minute server timeout is hang protection; readiness and cleanup use # PID/port files rather than timing assumptions. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init check_command_available timeout require_plugin mmkubernetes ../contrib/mmkubernetes pwd=$(pwd) testsrv=mmk8s-test-server k8s_srv_port_file="${RSYSLOG_DYNNAME}${testsrv}.port" generate_conf timeout 2m $PYTHON -u $srcdir/mmkubernetes_test_server.py 0 \ ${RSYSLOG_DYNNAME}${testsrv}.pid \ ${RSYSLOG_DYNNAME}${testsrv}.started \ ${k8s_srv_port_file} > ${RSYSLOG_DYNNAME}.spool/mmk8s_srv.log 2>&1 & BGPROCESS=$! wait_file_exists "$k8s_srv_port_file" k8s_srv_port="$(cat "$k8s_srv_port_file")" wait_process_startup ${RSYSLOG_DYNNAME}${testsrv} ${RSYSLOG_DYNNAME}${testsrv}.started add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") module(load="../plugins/imfile/.libs/imfile") module(load="../plugins/mmjsonparse/.libs/mmjsonparse") module(load="../contrib/mmkubernetes/.libs/mmkubernetes") input(type="imfile" file="'$RSYSLOG_DYNNAME.spool'/pod-*.log" tag="kubernetes" addmetadata="on") action(type="mmjsonparse" cookie="") action(type="mmkubernetes" token="dummy" kubernetesurl="http://localhost:'$k8s_srv_port'" includeNamespaceMetadata="off" filenamerules=["rule=:'$pwd/$RSYSLOG_DYNNAME.spool'/%pod_name:char-to:_%_%namespace_name:char-to:_%_%container_name_and_id:char-to:.%.log"]) template(name="outfmt" type="string" string="%$!all-json-plain%\n") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' cat > ${RSYSLOG_DYNNAME}.spool/pod-name2578_namespace-name2578_container-name2578-id2578.log < /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup # send a message with trailing LF ./syslog_caller -fsyslog_inject-c -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" shutdown_when_empty wait_shutdown export EXPECTED=" test 1#0112" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-corruption-framing.sh0000644000000000000000000000013215241075234024033 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.726898947 rsyslog-8.2608.0/tests/segmented-diskqueue-corruption-framing.sh0000775000175000017500000000024015241075234023476 0ustar00rgerrger#!/bin/bash # Run the segmentedDisk corruption driver with record-magic damage. export CORRUPTION_KIND=framing . ${srcdir:=.}/segmented-diskqueue-corruption.sh rsyslog-8.2608.0/tests/PaxHeaders/rulesetmultiqueue.sh0000644000000000000000000000013215131231047020035 xustar0030 mtime=1768239655.719212827 30 atime=1782715518.921791101 30 ctime=1787067804.459912606 rsyslog-8.2608.0/tests/rulesetmultiqueue.sh0000777000175000017500000000533215131231047017511 0ustar00rgerrger#!/bin/bash # Test for disk-only queue mode # This tests defines three rulesets, each one with its own queue. Then, it # sends data to them and checks the outcome. Note that we do need to # use some custom code as the test driver framework does not (yet?) # support multi-output-file operations. # added 2009-10-30 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test does not work on Solaris. The overall queue size check in imdiag requires atomics or mutexes on this platform, which we do not use for performance reasons." export NUMMESSAGES=60000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' $ModLoad ../plugins/imtcp/.libs/imtcp # general definition $template outfmt,"%msg:F,58:2%\n" # create the individual rulesets $ruleset file1 $RulesetCreateMainQueue on $template dynfile1,"'$RSYSLOG_OUT_LOG'1.log" # trick to use relative path names! :msg, contains, "msgnum:" { ?dynfile1;outfmt ./'$RSYSLOG_OUT_LOG' } $ruleset file2 $RulesetCreateMainQueue on $template dynfile2,"'$RSYSLOG_OUT_LOG'2.log" # trick to use relative path names! :msg, contains, "msgnum:" { ?dynfile2;outfmt ./'$RSYSLOG_OUT_LOG' } $ruleset file3 $RulesetCreateMainQueue on $template dynfile3,"'$RSYSLOG_OUT_LOG'3.log" # trick to use relative path names! :msg, contains, "msgnum:" { ?dynfile3;outfmt ./'$RSYSLOG_OUT_LOG' } # start listeners and bind them to rulesets $InputTCPServerBindRuleset file1 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port $InputTCPServerRun 0 $InputTCPServerBindRuleset file2 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port2 $InputTCPServerRun 0 $InputTCPServerBindRuleset file3 $InputTCPServerListenPortFile '$RSYSLOG_DYNNAME'.tcpflood_port3 $InputTCPServerRun 0 ' startup assign_tcpflood_port2 "$RSYSLOG_DYNNAME.tcpflood_port2" assign_rs_port "$RSYSLOG_DYNNAME.tcpflood_port3" # now fill the three files (a bit sequentially, but they should # still get their share of concurrency - to increase the chance # we use three connections per set). tcpflood -c3 -p$TCPFLOOD_PORT -m20000 -i0 tcpflood -c3 -p$TCPFLOOD_PORT2 -m20000 -i20000 tcpflood -c3 -p$RS_PORT -m20000 -i40000 # in this version of the imdiag, we do not have the capability to poll # all queues for emptiness. So we do a sleep in the hopes that this will # sufficiently drain the queues. This is race, but the best we currently # can do... - rgerhards, 2009-11-05 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # now consolidate all logs into a single one so that we can use the # regular check logic cat ${RSYSLOG_OUT_LOG}1.log ${RSYSLOG_OUT_LOG}2.log ${RSYSLOG_OUT_LOG}3.log > $RSYSLOG_OUT_LOG seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imptcp-stream-compression-auto-zlib-prefix-plain.sh0000644000000000000000000000013015216464436025672 xustar0030 mtime=1782212894.062266766 30 atime=1782715518.921791101 28 ctime=1787067806.8369569 rsyslog-8.2608.0/tests/imptcp-stream-compression-auto-zlib-prefix-plain.sh0000775000175000017500000000244015216464436025343 0ustar00rgerrger#!/bin/bash # Regression test for imptcp compression.mode="stream:auto" when a plain # octet-stuffed session starts with bytes that also look like a zlib header # (ASCII "x^"). The oracle is that the line reaches omfile and a second # line on the same connection is accepted; before the fix AUTO locked the # session into the compressed path and closed it on zlib Z_DATA_ERROR. # # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init if ! command -v python3 >/dev/null 2>&1; then echo "SKIP: python3 is unavailable" skip_test fi generate_conf add_conf ' module(load="../plugins/imptcp/.libs/imptcp") input(type="imptcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:auto") *.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_tcpflood_port $RSYSLOG_DYNNAME.tcpflood_port python3 - <<'PY' import os import socket port = int(os.environ["TCPFLOOD_PORT"]) payload = b"x^plain accepted by stream:auto\nsecond write after probe\n" with socket.create_connection(("127.0.0.1", port), timeout=10) as sock: sock.sendall(payload) PY wait_file_lines "$RSYSLOG_OUT_LOG" 2 shutdown_when_empty wait_shutdown content_check "x^plain accepted by stream:auto" "$RSYSLOG_OUT_LOG" content_check "second write after probe" "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_bare_var_root-empty.sh0000644000000000000000000000013215241075234021766 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.737917787 rsyslog-8.2608.0/tests/rscript_bare_var_root-empty.sh0000775000175000017500000000135515241075234021441 0ustar00rgerrger#!/bin/bash # addd 2018-01-01 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="empty-%$!%-\n") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="rs") ruleset(name="rs") { set $. = $!; set $! = $.; action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED='empty--' echo "$EXPECTED" | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "FAIL: $RSYSLOG_OUT_LOG content invalid:" cat $RSYSLOG_OUT_LOG echo "Expected:" echo "$EXPECTED" error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-query-params-vg.sh0000644000000000000000000000013215171370365023222 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.920791084 30 ctime=1787067806.424949223 rsyslog-8.2608.0/tests/imhttp-post-payload-query-params-vg.sh0000775000175000017500000000024715171370365022674 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" . ${srcdir:-.}/imhttp-post-payload-query-params.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-growing-file-id.sh0000644000000000000000000000013215035412264020465 xustar0030 mtime=1752569012.391813284 30 atime=1782715518.920791084 30 ctime=1787067808.031979169 rsyslog-8.2608.0/tests/imfile-growing-file-id.sh0000777000175000017500000000505515035412264020143 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify-only generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile" mode="inotify" PollingInterval="1") /* Filter out busy debug output */ global( debug.whitelist="off" debug.files=["rainerscript.c", "ratelimit.c", "ruleset.c", "main Q", "msg.c", "../action.c"]) input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" Severity="error" Facility="local7" addMetadata="on") template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' # generate small input file - state file must be inode only ./inputfilegen -m 1 > $RSYSLOG_DYNNAME.input ls -li $RSYSLOG_DYNNAME.input echo "STEP 1 - small input" startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! echo "STEP 2 - still small input" # add a bit to input file, but state file must still be inode only ./inputfilegen -m 1 -i1 >> $RSYSLOG_DYNNAME.input ls -li $RSYSLOG_DYNNAME.input* if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then echo FAIL: more than one state file in work directory: ls -l ${RSYSLOG_DYNNAME}.spool error_exit 1 fi startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! echo "STEP 3 - larger input, hash shall be used" ./inputfilegen -m 998 -i 2 >> $RSYSLOG_DYNNAME.input ls -li $RSYSLOG_DYNNAME.input* echo ls ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then echo FAIL: more than one state file in work directory: ls -l ${RSYSLOG_DYNNAME}.spool error_exit 1 fi echo "STEP 4 - append to larger input, hash state file must now be found" ./inputfilegen -m 1000 -i 1000 >> $RSYSLOG_DYNNAME.input ls -li $RSYSLOG_DYNNAME.input* echo ls ${RSYSLOG_DYNNAME}.spool: ls -l ${RSYSLOG_DYNNAME}.spool startup shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! if [ $(ls ${RSYSLOG_DYNNAME}.spool/* | wc -l) -ne 1 ]; then echo FAIL: more than one state file in work directory: ls -l ${RSYSLOG_DYNNAME}.spool error_exit 1 fi seq_check 0 1999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/template-topos-neg.sh0000644000000000000000000000013215131231047017756 xustar0030 mtime=1768239655.722212876 30 atime=1782715518.920791084 30 ctime=1787067804.283909327 rsyslog-8.2608.0/tests/template-topos-neg.sh0000777000175000017500000000107215131231047017427 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="out" type="list") { property(name="STRUCTURED-DATA" position.from="2" position.to="-1") constant(value="\n") } local4.debug action(type="omfile" template="out" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] msgnum:irrelevant' shutdown_when_empty wait_shutdown export EXPECTED='tcpflood@32473 MSGNUM="0"' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile_hup.sh0000644000000000000000000000013015241075234016365 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.783581627 30 ctime=1787067804.209907948 rsyslog-8.2608.0/tests/omfile_hup.sh0000775000175000017500000000214415241075234016037 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Written 2019-06-21 by Rainer Gerhards # Exercise omfile output while HUPs are issued during a long tcpflood send. The # background sender is validated by pid and proper-termination marker before the # final sequence oracle checks all messages. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=${NUMMESSAGES:-1000000} export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%,%msg:F,58:3%,%msg:F,58:4%\n") template(name="dynfile" type="string" string="'$RSYSLOG_OUT_LOG'") :msg, contains, "msgnum:" action(type="omfile" template="outfmt" dynafile="dynfile") ' startup start_tcpflood_async BGPROCESS TCPFLOOD_MARKER -m"$NUMMESSAGES" for i in $(seq 1 20); do printf '\nsending HUP %d\n' $i issue_HUP --sleep 100 done wait_tcpflood_async "$BGPROCESS" "$TCPFLOOD_MARKER" shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_append_json.sh0000644000000000000000000000013215241075234020306 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.914921085 rsyslog-8.2608.0/tests/rscript_append_json.sh0000775000175000017500000000222015241075234017751 0ustar00rgerrger#!/bin/bash # Added 2025-12-26 by 20syldev, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!arr%|%$!obj_new%|%$!chain%\n") if $msg contains "msgnum:" then { # Test 1: Append string to array set $.ret = parse_json('\''["a", "b"]'\'', "\$!arr"); set $!arr = append_json($!arr, "c"); # Test 2: Append key-value to object (use new variable to test) set $.ret = parse_json('\''{"name": "test"}'\'', "\$!obj"); set $!obj_new = append_json($!obj, "status", "active"); # Test 3: Chain multiple appends set $.ret = parse_json('\''[]'\'', "\$!chain"); set $!chain = append_json($!chain, "first"); set $!chain = append_json($!chain, "second"); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 shutdown_when_empty wait_shutdown export EXPECTED='[ "a", "b", "c" ]|{ "name": "test", "status": "active" }|[ "first", "second" ]' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_ratelimit_name.sh0000644000000000000000000000013215171370365021161 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.920791084 30 ctime=1787067804.517913687 rsyslog-8.2608.0/tests/imuxsock_ratelimit_name.sh0000775000175000017500000000125115171370365020627 0ustar00rgerrger#!/bin/bash # Test named rate limits for imuxsock # Verifies that imuxsock accepts ratelimit.name and # syssock.ratelimit.name without error. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' ratelimit(name="imuxsock_test_limit" interval="2" burst="5") ratelimit(name="imuxsock_syssock_limit" interval="3" burst="10") module(load="../plugins/imuxsock/.libs/imuxsock" SysSock.Use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-imuxsock.sock" ratelimit.name="imuxsock_test_limit") template(name="outfmt" type="string" string="%msg%\n") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/config_enabled-off.sh0000644000000000000000000000013215035412264017726 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.920791084 30 ctime=1787067808.057979653 rsyslog-8.2608.0/tests/config_enabled-off.sh0000777000175000017500000000111215035412264017372 0ustar00rgerrger#!/bin/bash # check disabling a config construct via config.enable. Most # importantly ensure that it does not emit any error messages # for object parameters. # addd 2019-05-09 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imfile/.libs/imfile") input(type="imfile" file="/tmp/notyet.txt" tag="testing-tag" config.enabled="off") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup shutdown_when_empty wait_shutdown content_check 'imfile: no files configured' check_not_present 'parameter .* not known' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-wildcards.sh0000644000000000000000000000013215131231047017451 xustar0030 mtime=1768239655.704212582 30 atime=1782715518.920791084 30 ctime=1787067807.969978013 rsyslog-8.2608.0/tests/imfile-wildcards.sh0000777000175000017500000000664415131231047017134 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under GPLv3 . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export IMFILEINPUTFILES="10" export IMFILELASTINPUTLINES="3" export IMFILECHECKTIMEOUT="60" mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' # comment out if you need more debug info: global( debug.whitelist="on" debug.files=["imfile.c"]) global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile" mode="inotify" normalizePath="off") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input.*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") input(type="imfile" File="/does/not/exist/*.log" Tag="file:" Severity="error" Facility="local7" addMetadata="on") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value=", filename: ") property(name="$!metadata!filename") constant(value=", fileoffset: ") property(name="$!metadata!fileoffset") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' # generate input files first. Note that rsyslog processes it as # soon as it start up (so the file should exist at that point). imfilebefore=$RSYSLOG_DYNNAME.input.01.log ./inputfilegen -m 1 > $imfilebefore # Start rsyslog now before adding more files startup for i in $(seq 2 $IMFILEINPUTFILES); do filnbr=$(printf "%2.2d" $i) cp $imfilebefore $RSYSLOG_DYNNAME.input.$filnbr.log imfilebefore=$RSYSLOG_DYNNAME.input.$filnbr.log done # Content check with timeout content_check_with_count "HEADER msgnum:00000000:" $IMFILEINPUTFILES $IMFILECHECKTIMEOUT # Add some extra lines to the last log ./inputfilegen -m $IMFILELASTINPUTLINES > $RSYSLOG_DYNNAME.input.$((IMFILEINPUTFILES + 1)).log ls -l $RSYSLOG_DYNNAME.input.* # Content check with timeout content_check_with_count "input.11.log" $IMFILELASTINPUTLINES $IMFILECHECKTIMEOUT shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! # Sort Output file now, and compare full file content presort printf 'HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.01.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.02.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.03.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.04.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.05.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.06.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.07.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.08.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.09.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.10.log, fileoffset: 0 HEADER msgnum:00000000:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 0 HEADER msgnum:00000001:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 17 HEADER msgnum:00000002:, filename: ./'$RSYSLOG_DYNNAME'.input.11.log, fileoffset: 34\n' | cmp - $RSYSLOG_DYNNAME.presort if [ ! $? -eq 0 ]; then echo "FAIL: invalid output generated, $RSYSLOG_DYNNAME.presort is:" echo "File contents:" cat -n $RSYSLOG_DYNNAME.presort error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/pgsql-template-cnf6-vg.sh0000644000000000000000000000013215035412264020442 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.919791067 30 ctime=1787067805.901939477 rsyslog-8.2608.0/tests/pgsql-template-cnf6-vg.sh0000777000175000017500000000177715035412264020127 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' template(name="pgtemplate" type="list" option.sql="on") { constant(value="INSERT INTO SystemEvents (SysLogTag) values ('"'"'") property(name="msg") constant(value="'"'"')") } module(load="../plugins/ompgsql/.libs/ompgsql") if $msg contains "msgnum" then { action(type="ompgsql" server="127.0.0.1" db="syslogtest" user="postgres" pass="testbench" template="pgtemplate") }' startup_vg injectmsg 0 5000 shutdown_when_empty wait_shutdown_vg check_exit_vg # we actually put the message in the SysLogTag field, so we know it doesn't use the default # template, like in pgsql-basic psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/pmsnare-cccstyle-udp.sh0000644000000000000000000000013215035412264020301 xustar0030 mtime=1752569012.408695159 30 atime=1782715518.920791084 30 ctime=1787067807.845975703 rsyslog-8.2608.0/tests/pmsnare-cccstyle-udp.sh0000777000175000017500000001353715035412264017763 0ustar00rgerrger#!/bin/bash # add 2018-06-29 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init setvar_RS_HOSTNAME generate_conf add_conf ' module(load="../contrib/pmsnare/.libs/pmsnare") module(load="../plugins/imudp/.libs/imudp") input(type="imudp" port="'$TCPFLOOD_PORT'" ruleset="ruleset1") global(parser.escapeControlCharactersCStyle="on") $EscapeControlCharactersOnReceive on template(name="outfmt" type="string" string="%PRI%,%syslogfacility-text%,%syslogseverity-text%,%programname%,%syslogtag%,%msg%\n") ruleset(name="ruleset1" parser=["rsyslog.snare","rsyslog.rfc5424","rsyslog.rfc3164"]) { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup tcpflood -m1 -T "udp" -M "\"<14> 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite \\\"AES-256-CBC-SHA TLSv1 Non-Export 256-bit\\\" - Session Reuse The authenti\"" tcpflood -m1 -T "udp" -M "\"<14>123456789: HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................\"" tcpflood -m1 -T "udp" -M "\"<14>May 21 2017 00:00:00: %ASA-4-102030: Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group "local_in" [0x0, 0x0]\"" tcpflood -m1 -T "udp" -M "\"<14>2017-05-21T00:00:01.123Z hostname.domain Hostd: verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]};\"" tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname CROND[12393]: pam_unix(crond:session): session closed for user root................\"" tcpflood -m1 -T "udp" -M "\"<14>May 21 12:00:01 hostname.domain MSWinEventLog 1 Security 00000000 Sun May 21 12:00:01.123 4624 Microsoft-Windows-Security-Auditing N/A N/A Success Audit hostname.domain Logon An account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................\"" shutdown_when_empty wait_shutdown export EXPECTED='14,user,info,,, 05/21/2017:00:00:00 GMT HOSTNAME 1-ABC-2 : default SSLLOG SSL_HANDSHAKE_SUCCESS 39672436 0 : SPCBId 6377757 - ClientIP 192.168.0.11 - ClientPort 55073 - VserverServiceIP 192.168.0.11 - VserverServicePort 443 - ClientVersion TLSv1.0 - CipherSuite "AES-256-CBC-SHA TLSv1 Non-Export 256-bit" - Session Reuse The authenti 14,user,info,123456789,123456789:, HOSTNAME: May 21 12:00:01.123 gmt: %IOSXE-6-PLATFORM: F0: cpp_cp: QFP:0.0 Thread:105 TS:00000000000000 %NAT-6-LOG_TRANSLATION: Created Translation UDP 192.168.0.11:44593 192.168.0.11:21129 192.168.0.11:53 192.168.0.11:53 0................ 14,user,info,%ASA-4-102030,%ASA-4-102030:, Deny udp src vlan_12302:192.168.0.11/514 dst vlan_1233:192.168.0.11/514 by access-group local_in [0x0, 0x0] 14,user,info,Hostd,Hostd:, verbose hostd[81480B70] [Originator@6876 sub=Hostsvc.StorageSystem] SendStorageInfoEvent: Notify: StorageSystemMsg{HBAs=[vmhba0, vmhba1, vmhba2, vmhba3, vmhba32, vmhba4, ]}; 14,user,info,CROND,CROND[12393]:, pam_unix(crond:session): session closed for user root................ 14,user,info,MSWinEventLog,MSWinEventLog, 1\tSecurity\t00000000\tSun May 21 12:00:01.123\t4624\tMicrosoft-Windows-Security-Auditing\tN/A\tN/A\tSuccess Audit\thostname.domain\tLogon\t\tAn account was successfully logged on. Subject: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon Type: 3 New Logon: Security ID: 0x000000000 Account Name: first.last Account Domain: domain Logon ID: 0x000000000 Logon GUID: 0x000000000 Process Information: Process ID: 0x000000000 Process Name: first.last Network Information: Workstation Name: Source Network Address: 192.168.0.11 Source Port: 51542 Detailed Authentication Information: Logon Process: Kerberos Authentication Package: Kerberos Transited Services: - Package Name (NTLM only): - Key Length: 0 This event is generated when a logon session is created. It is generated on the computer that was accessed. The subject fields indicate the account on the local system which requested the logon. This is most commonly a service such as the Server service, or a local process such as Winlogon.exe or Services.exe. The logon type field indicates the kind of logon that occurred. The most common types are 2 (interactive) and 3 (network). The New Logon fields indicate the account for whom the new logon was created, i.e. the account that wa................' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/impstats-no-overwrite.sh0000644000000000000000000000013215145046113020537 xustar0030 mtime=1771326539.040014305 30 atime=1782715518.920791084 30 ctime=1787067806.673953863 rsyslog-8.2608.0/tests/impstats-no-overwrite.sh0000775000175000017500000000144015145046113020205 0ustar00rgerrger#!/bin/bash # test if impstats appends by default (no log.file.overwrite) # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" log.file=`echo $RSYSLOG_OUT_LOG` interval="1") ' startup # Wait for at least two emissions ./msleep 2500 shutdown_when_empty wait_shutdown # Check how many times "resource-usage" appears in the log file. # It should appear at least twice. NUM_EMISSIONS=$(grep -c "resource-usage" $RSYSLOG_OUT_LOG) echo "Number of resource-usage entries found: $NUM_EMISSIONS" if [ "$NUM_EMISSIONS" -lt 2 ]; then echo "FAIL: expected at least 2 emissions in log file, but found $NUM_EMISSIONS" exit 1 fi echo "SUCCESS: impstats appended as expected" exit_test rsyslog-8.2608.0/tests/PaxHeaders/json-omitifzero.sh0000644000000000000000000000013215145046113017373 xustar0030 mtime=1771326539.043014354 30 atime=1782715518.920791084 30 ctime=1787067803.693898332 rsyslog-8.2608.0/tests/json-omitifzero.sh0000775000175000017500000000174315145046113017047 0ustar00rgerrger#!/bin/bash # added 2026-01-24 by Rainer Gerhards; Released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list" option.jsonf="on") { property(name="$!zero" outname="zero_default" format="jsonf" dataType="number") property(name="$!zero" outname="zero_omit" format="jsonf" dataType="number" omitIfZero="on") property(name="$!nonzero" outname="nonzero_omit" format="jsonf" dataType="number" omitIfZero="on") property(name="$!zero" outname="zero_string_omit" format="jsonf" dataType="string" omitIfZero="on") property(name="$!empty" outname="empty_omit" format="jsonf" dataType="number" omitIfZero="on" onEmpty="skip") } set $!zero = 0; set $!nonzero = 42; set $!empty = ""; local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg shutdown_when_empty wait_shutdown export EXPECTED='{"zero_default":0, "nonzero_omit":42, "zero_string_omit":"0"}' cmp_exact "$RSYSLOG_OUT_LOG" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs.sh0000644000000000000000000000013215241075234023713 xustar0030 mtime=1787067036.633578819 30 atime=1787067036.689579867 30 ctime=1787067807.616971435 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-mtls-ecdsa-sigalgs.sh0000775000175000017500000000015315241075234023361 0ustar00rgerrger#!/bin/bash export PKCS11_SIGALG_VARIANT=full . ${srcdir:=.}/omfwd-tls-ossl-pkcs11-ecdsa-sigalgs-common.sh rsyslog-8.2608.0/tests/PaxHeaders/lookup_table_rscript_reload_without_stub-vg.sh0000644000000000000000000000013215171370365025253 xustar0030 mtime=1776677109.463913418 30 atime=1782715518.920791084 30 ctime=1787067805.290928091 rsyslog-8.2608.0/tests/lookup_table_rscript_reload_without_stub-vg.sh0000775000175000017500000000031115171370365024715 0ustar00rgerrger#!/bin/bash # added 2015-12-18 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 export USE_VALGRIND="YES" . ${srcdir:-.}/lookup_table_rscript_reload_without_stub.sh rsyslog-8.2608.0/tests/PaxHeaders/imfile-endregex-timeout-none.sh0000644000000000000000000000013215131231047021717 xustar0030 mtime=1768239655.703212565 30 atime=1782715518.920791084 30 ctime=1787067807.921977119 rsyslog-8.2608.0/tests/imfile-endregex-timeout-none.sh0000777000175000017500000000317415131231047021375 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 echo ====================================================================== echo [imfile-endregex-timeout-none.sh] . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify mkdir "$RSYSLOG_DYNNAME.work" generate_conf add_conf ' global(workDirectory="./'"$RSYSLOG_DYNNAME"'.work") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" PersistStateInterval="1" startmsg.regex="^[^ ]") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # we need to sleep a bit between writes to give imfile a chance # to pick up the data (IN MULTIPLE ITERATIONS!) echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input ./msleep 5000 # wait 5 seconds - this shall cause a timeout echo ' msgnum:2 msgnum:3' >> $RSYSLOG_DYNNAME.input # the next line terminates our test. It is NOT written to the output file, # as imfile waits whether or not there is a follow-up line that it needs # to combine. echo 'END OF TEST' >> $RSYSLOG_DYNNAME.input ./msleep 200 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! printf 'HEADER msgnum:0\\\\n msgnum:1\\\\n msgnum:2\\\\n msgnum:3\n' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid multiline message generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_traillf.sh0000644000000000000000000000013215145046113017614 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.920791084 30 ctime=1787067804.678916687 rsyslog-8.2608.0/tests/imuxsock_traillf.sh0000775000175000017500000000137115145046113017265 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines ./syslog_caller -fsyslog_inject-l -m0 > /dev/null 2>&1 no_liblogging_stdlog=$? if [ $no_liblogging_stdlog -ne 0 ];then echo "liblogging-stdlog not available - skipping test" exit 77 fi generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") local1.* action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup ./syslog_caller -fsyslog_inject-l -m1 -C "uxsock:$RSYSLOG_DYNNAME-testbench_socket" shutdown_when_empty wait_shutdown export EXPECTED=" test" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/omotel-batch.sh0000644000000000000000000000013215145046113016613 xustar0030 mtime=1771326539.058014598 30 atime=1782715518.920791084 30 ctime=1787067806.206945161 rsyslog-8.2608.0/tests/omotel-batch.sh0000775000175000017500000000313615145046113016265 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 ## omotel-batch.sh -- batching test for omotel module ## ## Tests that omotel correctly batches multiple log records into ## single ExportLogsServiceRequest payloads. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=10000 export EXTRA_EXIT=otel # Download and prepare OTEL Collector download_otel_collector prepare_otel_collector start_otel_collector # Read the port from the port file if [ ! -f ${RSYSLOG_DYNNAME}.otel_port.file ]; then echo "ERROR: OTEL Collector port file not found: ${RSYSLOG_DYNNAME}.otel_port.file" error_exit 1 fi otel_port=$(cat ${RSYSLOG_DYNNAME}.otel_port.file) if [ -z "$otel_port" ]; then echo "ERROR: OTEL Collector port is empty" error_exit 1 fi echo "Using OTEL Collector port: $otel_port" generate_conf add_conf ' template(name="otlpBody" type="string" string="msgnum:%msg:F,58:2%") module(load="../plugins/omotel/.libs/omotel") if $msg contains "msgnum:" then action( name="omotel-http" type="omotel" template="otlpBody" endpoint="http://127.0.0.1:'$otel_port'" path="/v1/logs" batch.max_items="3" batch.timeout.ms="60000" ) ' startup injectmsg shutdown_when_empty wait_shutdown # Stop OTEL Collector to ensure file exporter flushes data # The file exporter may buffer data until collector shuts down stop_otel_collector # Give OTEL Collector a moment to flush the output file after shutdown if [ -n "$TESTTOOL_DIR" ] && [ -f "$TESTTOOL_DIR/msleep" ]; then $TESTTOOL_DIR/msleep 1000 else sleep 1 fi # Extract data from OTEL Collector output otel_collector_get_data seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-recovery-budget.sh0000644000000000000000000000013115241075234023313 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.694579961 29 ctime=1787067803.74689932 rsyslog-8.2608.0/tests/segmented-diskqueue-recovery-budget.sh0000775000175000017500000000572515241075234022774 0ustar00rgerrger#!/bin/bash # Corrupt more than the 1 MiB per-attempt recovery budget in a sealed segment. # Recovery must yield and retain its cursor, accept new producer data, keep the # queue non-empty, and eventually deliver records from later segments. Counter # values and delivery of the post-restart message are the deterministic oracle. . ${srcdir:=.}/diag.sh init check_command_available python3 require_plugin impstats export NUMMESSAGES=10000 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" STATS_FILE="$PWD/${RSYSLOG_DYNNAME}.stats.log" write_conf() { local queue_config='main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.maxFileSize="1200k" queue.dequeueBatchSize="32" queue.saveOnShutdown="on")' if [ "${SEGDISK_RECOVERY_DA:-0}" = 1 ] && [ "$2" = recovery ]; then queue_config='main_queue(queue.type="LinkedList" queue.filename="mainq" queue.size="50" queue.highWatermark="10" queue.lowWatermark="5" queue.maxFileSize="1200k" queue.dequeueBatchSize="32" queue.saveOnShutdown="on" queue.diskQueueType="auto" queue.diskQueueIdleTimeout="-1")' fi generate_conf add_conf ' module(load="../plugins/omtesting/.libs/omtesting") module(load="../plugins/impstats/.libs/impstats" log.file="'$STATS_FILE'" interval="1") global(workDirectory="'$SPOOL_DIR'") '"$queue_config"' template(name="outfmt" type="string" string="%msg:F,58:2%\n") '"$1"' if ($msg contains "msgnum:") then action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' } write_conf ':omtesting:sleep 10 0' seed startup wait_rsyslog_instance_pid injectmsg . "$srcdir/diag.sh" kill-immediate wait_shutdown python3 "$srcdir/segdisk-inspect.py" "$SPOOL_DIR/mainq.segq" >"${RSYSLOG_DYNNAME}.budget-before.json" target_id=$(python3 -c 'import json,os,sys; d=json.load(open(sys.argv[1])); c=[s for s in d["segments"] if s["sealed"] and os.path.getsize(s["path"])>1048576]; print(c[0]["id"])' \ "${RSYSLOG_DYNNAME}.budget-before.json") target_records=$(python3 -c 'import json,sys; d=json.load(open(sys.argv[1])); target=int(sys.argv[2]); print(len(next(s for s in d["segments"] if s["id"]==target)["records"]))' \ "${RSYSLOG_DYNNAME}.budget-before.json" "$target_id") python3 "$srcdir/segdisk-inspect.py" "$SPOOL_DIR/mainq.segq" --corrupt-segment-framing "$target_id" \ >"${RSYSLOG_DYNNAME}.budget-corrupt.json" : >"$STATS_FILE" write_conf '# no delay during bounded recovery' recovery startup injectmsg 10000 1 export NUMMESSAGES=$((10001 - target_records)) export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines shutdown_when_empty wait_shutdown content_check '00010000' "$RSYSLOG_OUT_LOG" pending=$(grep 'recovery.pending=' "$STATS_FILE" | tail -n 1 | sed -E 's/.*recovery\.pending=([0-9]+).*/\1/') bytes=$(grep 'recovery.bytes=' "$STATS_FILE" | tail -n 1 | sed -E 's/.*recovery\.bytes=([0-9]+).*/\1/') if [ "${pending:-0}" -lt 1 ] || [ "${bytes:-0}" -le 1048576 ]; then printf 'FAIL: bounded recovery counters pending=%s bytes=%s\n' "${pending:-missing}" "${bytes:-missing}" cat "$STATS_FILE" error_exit 1 fi rm -rf "$SPOOL_DIR" exit_test rsyslog-8.2608.0/tests/PaxHeaders/imrelp-maxDataSize-error.sh0000644000000000000000000000013115035412264021065 xustar0029 mtime=1752569012.39578549 30 atime=1782715518.919791067 30 ctime=1787067807.689972796 rsyslog-8.2608.0/tests/imrelp-maxDataSize-error.sh0000777000175000017500000000126415035412264020542 0ustar00rgerrger#!/bin/bash # add 2018-04-26 by Pascal Withopf, released under ASL 2.0 echo [imrelp-maxDataSize-error.sh] . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") global( maxMessageSize="300" ) input(type="imrelp" port="'$TCPFLOOD_PORT'" maxDataSize="250") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup ./msleep 2000 shutdown_when_empty wait_shutdown grep "error: maxDataSize.*smaller than global parameter maxMessageSize" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-mbedtls-basic-brokenhandshake-vg.sh0000644000000000000000000000013215241075234024422 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.448968305 rsyslog-8.2608.0/tests/imtcp-tls-mbedtls-basic-brokenhandshake-vg.sh0000775000175000017500000000307515241075234024076 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi . ${srcdir:=.}/diag.sh init export USE_VALGRIND="YES" RSYSLOG_PRELOAD=$(find /usr -name libmbed\*.so | sed ':start;N;s/\n\//:\//;t start;P;D') export RSYSLOG_PRELOAD export NUMMESSAGES=1 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["nsd_mbedtls.c", "tcpsrv.c", "nsdsel_mbedtls.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="mbedtls" StreamDriver.Mode="1" StreamDriver.AuthMode="anon" ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action( type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' # Begin actual testcase | send one msg without TLS to force a handshake failure, send second msg with TLS to make the test PASS startup tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES tcpflood -p$TCPFLOOD_PORT -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem wait_file_lines shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-tls-gtls-x509fingerprint-invld.sh0000644000000000000000000000013215241075234023210 xustar0030 mtime=1787067036.625578669 30 atime=1787067036.775581477 30 ctime=1787067807.331966124 rsyslog-8.2608.0/tests/imtcp-tls-gtls-x509fingerprint-invld.sh0000775000175000017500000000222215241075234022655 0ustar00rgerrger#!/bin/bash # added 2018-12-22 by Rainer Gerhards # check for INVALID fingerprint! # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export NUMMESSAGES=1 generate_conf add_conf ' global( defaultNetstreamDriverCAFile="'$srcdir/tls-certs/ca.pem'" defaultNetstreamDriverCertFile="'$srcdir/tls-certs/cert.pem'" defaultNetstreamDriverKeyFile="'$srcdir/tls-certs/key.pem'" # debug.whitelist="on" # debug.files=["net_ossl.c", "nsd_ossl.c", "tcpsrv.c", "nsdsel_ossl.c", "nsdpoll_ptcp.c", "dnscache.c"] ) module( load="../plugins/imtcp/.libs/imtcp" StreamDriver.Name="gtls" StreamDriver.Mode="1" StreamDriver.AuthMode="x509/fingerprint" PermittedPeer=["SHA1:FF:C6:62:D5:9D:25:9F:BC:F3:CB:61:FA:D2:B3:8B:61:88:D7:06:C3"] # INVALID! ) input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup tcpflood -p'$TCPFLOOD_PORT' -m$NUMMESSAGES -Ttls -x$srcdir/tls-certs/ca.pem -Z$srcdir/tls-certs/cert.pem -z$srcdir/tls-certs/key.pem shutdown_when_empty wait_shutdown content_check --regex "peer fingerprint .* unknown" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_ne_var.sh0000644000000000000000000000013115241075234017257 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.792581796 29 ctime=1787067804.83091952 rsyslog-8.2608.0/tests/rscript_ne_var.sh0000775000175000017500000000260315241075234016730 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_ne.sh\]: testing rainerscript NE statement for two JSON variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } set $!var1 = "value1"; set $!var2 = "value2"; if $!var1 != $!var2 then { set $!var1 = "value"; set $!var2 = "value"; if $!var1 != $!var2 then { # Failure stop } else { unset $!var1; unset $!var2; } } else { # Failure stop } set $.var1 = "value1"; set $.var2 = "value2"; if $.var1 != $.var2 then { set $.var1 = "value"; set $.var2 = "value"; if $.var1 != $.var2 then { # Failure stop } else { unset $.var1; unset $.var2; } } else { # Failure stop } set $/var1 = "value1"; set $/var2 = "value2"; if $/var1 != $/var2 then { set $/var1 = "value"; set $/var2 = "value"; if $/var1 != $/var2 then { # Failure stop } else { unset $/var1; unset $/var2; } } else { # Failure stop } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_bool_constant_warning.sh0000644000000000000000000000013215241075234022377 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.993922557 rsyslog-8.2608.0/tests/rscript_bool_constant_warning.sh0000775000175000017500000000203115241075234022042 0ustar00rgerrger#!/bin/bash # Verify that a common RainerScript boolean mistake logs a config warning: # `$msg contains "a" or "b"` keeps historical truthiness semantics, but the # bare string literal is probably a missing repeated comparison. The warning # must only fire on constants as written: comparisons that merely constant-fold # to a constant (e.g. backtick-expanded environment variables) are legitimate # and must stay silent. The oracle is rsyslogd config-check output. . ${srcdir:=.}/diag.sh init export MY_FEATURE="on" generate_conf add_conf ' if $msg contains "alpha" or "beta" then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) } if `echo $MY_FEATURE` == "on" and $msg contains "gamma" then { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) } ' export RS_REDIR=">${RSYSLOG_DYNNAME}.rsyslog.log 2>&1" rsyslogd_config_check unset RS_REDIR content_check "boolean operator 'OR' has constant right operand" "${RSYSLOG_DYNNAME}.rsyslog.log" check_not_present "boolean operator 'AND' has constant" "${RSYSLOG_DYNNAME}.rsyslog.log" exit_test rsyslog-8.2608.0/tests/PaxHeaders/rfc5424parser.sh0000644000000000000000000000013215241075234016546 xustar0030 mtime=1787067036.638578912 30 atime=1787067036.790581758 30 ctime=1787067804.326910128 rsyslog-8.2608.0/tests/rfc5424parser.sh0000775000175000017500000000135515241075234016221 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # rgerhards, 2013-11-22 echo =============================================================================== echo \[rfc5424parser.sh\]: testing mmpstrucdata . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") template(name="outfmt" type="string" string="%msg:F,58:2%\n") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") if $msg contains "msgnum" then action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) ' startup sleep 1 tcpflood -m100 -y shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown seq_check 0 99 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-defaults-vg.sh0000644000000000000000000000013215035412264017761 xustar0030 mtime=1752569012.405716005 30 atime=1782715518.920791084 30 ctime=1787067806.092943037 rsyslog-8.2608.0/tests/omprog-defaults-vg.sh0000777000175000017500000000131615035412264017433 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # Same test than 'omprog-defaults.sh', but checking for memory # problems using valgrind. Note it is not necessary to repeat the # rest of checks (this simplifies the maintenance of the tests). . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary=`echo $srcdir/testsuites/omprog-defaults-bin.sh p1 p2 p3` template="outfmt" name="omprog_action" ) } ' startup_vg injectmsg 0 10 shutdown_when_empty wait_shutdown_vg check_exit_vg exit_test rsyslog-8.2608.0/tests/PaxHeaders/glbl-internalmsg_severity-debug-not_shown.sh0000644000000000000000000000013215035412264024532 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.920791084 30 ctime=1787067804.077905488 rsyslog-8.2608.0/tests/glbl-internalmsg_severity-debug-not_shown.sh0000777000175000017500000000111215035412264024176 0ustar00rgerrger#!/bin/bash # check that info-severity messages are actually emitted; we use # lookup table as a simple sample to get such a message. # addd 2019-05-07 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl" reloadOnHUP="on") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup shutdown_when_empty wait_shutdown check_not_present "rsyslogd fully started up and initialized - begin actual processing" exit_test rsyslog-8.2608.0/tests/PaxHeaders/failover-double.sh0000644000000000000000000000013115035412264017315 xustar0029 mtime=1752569012.38883413 30 atime=1782715518.919791067 30 ctime=1787067804.703917153 rsyslog-8.2608.0/tests/failover-double.sh0000777000175000017500000000101415035412264016763 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export DEAD_PORT=4 # a port unassigned by IANA and very unlikely to be used generate_conf add_conf ' $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" @@127.0.0.1:'$DEAD_PORT' $ActionExecOnlyWhenPreviousIsSuspended on & @@127.0.0.1:1234 & ./'"${RSYSLOG_OUT_LOG}"';outfmt $ActionExecOnlyWhenPreviousIsSuspended off ' startup injectmsg 0 5000 shutdown_when_empty wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_ruleset_call.sh0000644000000000000000000000013215035412264020463 xustar0030 mtime=1752569012.412667365 30 atime=1782715518.923791135 30 ctime=1787067804.761918234 rsyslog-8.2608.0/tests/rscript_ruleset_call.sh0000777000175000017500000000170015035412264020132 0ustar00rgerrger#!/bin/bash # added 2012-10-29 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_ruleset_call.sh\]: testing rainerscript ruleset\(\) and call statement . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" field.delimiter="58" field.number="2") constant(value="\n") } # we deliberately include continue/stop to make sure we have more than # one statement. This catches grammar errors ruleset(name="rs2") { continue action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") stop } # this time we make sure a single statement is properly supported ruleset(name="rs1") { call rs2 } if $msg contains "msgnum" then call rs1 ' startup injectmsg 0 5000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmjsontransform-policy-watch-invalid.sh0000644000000000000000000000013215241075234023524 xustar0030 mtime=1787067036.629578744 30 atime=1787067036.780581571 30 ctime=1787067807.241964447 rsyslog-8.2608.0/tests/mmjsontransform-policy-watch-invalid.sh0000775000175000017500000000444415241075234023201 0ustar00rgerrger#!/bin/bash # Validate mmjsontransform keeps the previous policy when watch reload fails. . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.policy.yaml" export POLICY_FILE cat > "$POLICY_FILE" <<'YAML' version: 1 mode: flatten map: rename: "usr": "user.name" "ctx.old": "ctx.new" YAML generate_conf add_conf ' global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") module(load="../plugins/mmjsontransform/.libs/mmjsontransform") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!output%\n") local4.* { set $.ret = parse_json($msg, "\$!input"); action(type="mmjsontransform" policy="'$POLICY_FILE'" policyWatch="on" policyWatchDebounce="200ms" input="$!input" output="$!output") action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' check_json() { python3 - "$1" "$2" <<'PY' import json import sys path = sys.argv[1] expected = json.loads(sys.argv[2]) with open(path, "r", encoding="utf-8") as fh: lines = [line.strip() for line in fh if line.strip()] if len(lines) != 1: print("expected 1 JSON line, got", len(lines)) sys.exit(1) obj = json.loads(lines[0]) if obj != expected: print("unexpected output:", obj) sys.exit(1) PY } startup ./msleep 1000 tcpflood -Ttcp -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"alice\", \"ctx\": { \"old\": 1 } }"' wait_file_lines "$RSYSLOG_OUT_LOG" 1 100 check_json "$RSYSLOG_OUT_LOG" '{"user.name":"alice","ctx.new":1}' if [ $? -ne 0 ]; then error_exit 1; fi : > "$RSYSLOG_OUT_LOG" cat > "$POLICY_FILE" <<'YAML' version: 1 mode: sideways map: rename: "usr": "broken.name" YAML ./msleep 1000 tcpflood -Ttcp -m1 -M '"<166>Mar 10 01:00:00 host app: { \"usr\": \"bob\", \"ctx\": { \"old\": 2 }, \"debug\": true }"' wait_file_lines "$RSYSLOG_OUT_LOG" 1 100 check_json "$RSYSLOG_OUT_LOG" '{"user.name":"bob","ctx.new":2,"debug":true}' if [ $? -ne 0 ]; then error_exit 1; fi if ! grep -q "failed to reload policy file '.*' during watch, keeping previous policy" "$RSYSLOG_DYNNAME.started"; then echo "FAIL: expected watched mmjsontransform reload failure to be logged" error_exit 1 fi shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/mmanon_random_cons_128_ipv6.sh0000644000000000000000000000013215035412264021444 xustar0030 mtime=1752569012.399757696 30 atime=1782715518.922791118 30 ctime=1787067805.749936645 rsyslog-8.2608.0/tests/mmanon_random_cons_128_ipv6.sh0000777000175000017500000000610015035412264021112 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%msg%\n") template(name="filename" type="string" string="'${RSYSLOG_DYNNAME}'.%syslogtag%.log") module(load="../plugins/mmanon/.libs/mmanon") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="testing") ruleset(name="testing") { action(type="mmanon" ipv6.anonmode="random-consistent" ipv6.bits="128") action(type="omfile" dynafile="filename" template="outfmt") }' echo 'Since this test tests randomization, there is a theoretical possibility of it failing even if rsyslog works correctly. Therefore, if the test unexpectedly fails try restarting it.' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 file1 33:45:DDD::4 <129>Mar 10 01:00:00 172.20.245.8 file2 :: <129>Mar 10 01:00:00 172.20.245.8 file6 :: <129>Mar 10 01:00:00 172.20.245.8 file3 72:8374:adc7:47FF::43:0:1AFE <129>Mar 10 01:00:00 172.20.245.8 file4 FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF <129>Mar 10 01:00:00 172.20.245.8 file5 72:8374:adc7:47FF::43:0:1AFE\"" shutdown_when_empty wait_shutdown echo ' 33:45:DDD::4' | cmp - ${RSYSLOG_DYNNAME}.file1.log >/dev/null if [ ! $? -eq 1 ]; then echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file1.log is:" cat ${RSYSLOG_DYNNAME}.file1.log error_exit 1 fi; echo ' ::' | cmp - ${RSYSLOG_DYNNAME}.file2.log >/dev/null if [ ! $? -eq 1 ]; then echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file2.log is:" cat ${RSYSLOG_DYNNAME}.file2.log error_exit 1 fi; echo ' 72:8374:adc7:47FF::43:0:1AFE' | cmp - ${RSYSLOG_DYNNAME}.file3.log >/dev/null if [ ! $? -eq 1 ]; then echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file3.log is:" cat ${RSYSLOG_DYNNAME}.file3.log error_exit 1 fi; echo ' FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF' | cmp - ${RSYSLOG_DYNNAME}.file4.log >/dev/null if [ ! $? -eq 1 ]; then echo "invalidly equal ip-address generated, ${RSYSLOG_DYNNAME}.file4.log is:" cat ${RSYSLOG_DYNNAME}.file4.log error_exit 1 fi; cmp ${RSYSLOG_DYNNAME}.file3.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null if [ ! $? -eq 0 ]; then echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file3.log and ${RSYSLOG_DYNNAME}.file5.log are:" cat ${RSYSLOG_DYNNAME}.file3.log cat ${RSYSLOG_DYNNAME}.file5.log error_exit 1 fi; cmp ${RSYSLOG_DYNNAME}.file2.log ${RSYSLOG_DYNNAME}.file6.log >/dev/null if [ ! $? -eq 0 ]; then echo "invalidly unequal ip-addresses generated, ${RSYSLOG_DYNNAME}.file1.log and ${RSYSLOG_DYNNAME}.file6.log are:" cat ${RSYSLOG_DYNNAME}.file1.log cat ${RSYSLOG_DYNNAME}.file6.log error_exit 1 fi; cmp ${RSYSLOG_DYNNAME}.file4.log ${RSYSLOG_DYNNAME}.file5.log >/dev/null if [ ! $? -eq 1 ]; then echo "invalidly equal ip-addresses generated, ${RSYSLOG_DYNNAME}.file4.log and ${RSYSLOG_DYNNAME}.file5.log are:" cat ${RSYSLOG_DYNNAME}.file4.log cat ${RSYSLOG_DYNNAME}.file5.log error_exit 1 fi; rm -f ${RSYSLOG_DYNNAME}.*.log exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhiredis-stream-readfrom-too-long.sh0000644000000000000000000000013115171370365023043 xustar0030 mtime=1776677109.461913388 30 atime=1782715518.921791101 29 ctime=1787067806.53695131 rsyslog-8.2608.0/tests/imhiredis-stream-readfrom-too-long.sh0000775000175000017500000000166215171370365022520 0ustar00rgerrger#!/usr/bin/env bash # Verify that imhiredis rejects stream.readFrom values that exceed the fixed index buffer. . ${srcdir:=.}/diag.sh init LONG_STREAM_INDEX=$(printf '1%.0s' $(seq 1 44)) modpath="../runtime/.libs:../contrib/imhiredis/.libs:../.libs" generate_conf add_conf ' module(load="../contrib/imhiredis/.libs/imhiredis") input(type="imhiredis" key="mystream" mode="stream" stream.readFrom="'$LONG_STREAM_INDEX'") ' ../tools/rsyslogd -N1 -f"${TESTCONF_NM}.conf" -M"$modpath" >"${RSYSLOG_DYNNAME}.log" 2>&1 if [ $? -ne 1 ]; then echo "FAIL: expected config validation failure for oversize imhiredis stream.readFrom" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi grep -F "configured stream.readFrom value exceeds maximum supported stream index length" \ "${RSYSLOG_DYNNAME}.log" >/dev/null || { echo "FAIL: expected imhiredis stream.readFrom validation error" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 } exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-script-stop.sh0000644000000000000000000000013215241075234017467 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 30 ctime=1787067805.384929843 rsyslog-8.2608.0/tests/yaml-script-stop.sh0000775000175000017500000000220115241075234017131 0ustar00rgerrger#!/bin/bash # Tests the "stop" statement inside a YAML script: block. # Sends 10 messages starting at sequence 1; the script stops the very first # message (00000001) and lets messages 2-10 through. # Mirrors stop.sh using YAML configuration. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=9 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" rulesets: - name: main script: | if $msg contains "00000001" then stop if $msg contains "msgnum:" then action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}") YAMLEOF sed -i "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m10 -i1 shutdown_when_empty wait_shutdown seq_check 2 10 exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-bulk-errfile-popul-erronly.sh0000644000000000000000000000013115216464436022064 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.922791118 29 ctime=1787067803.95190314 rsyslog-8.2608.0/tests/es-bulk-errfile-popul-erronly.sh0000775000175000017500000000260115216464436021533 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init ensure_elasticsearch_ready init_elasticsearch echo '{ "name" : "foo" } {"name": bar"} {"name": "baz"} {"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") # Note: we must mess up with the template, because we can not # instruct ES to put further constraints on the data type and # values. So we require integer and make sure it is none. template(name="tpl" type="list") { constant(value="{\"") property(name="$!key") constant(value="\":") property(name="$!obj") constant(value="}") } module(load="../plugins/omelasticsearch/.libs/omelasticsearch") module(load="../plugins/imfile/.libs/imfile") ruleset(name="foo") { set $!key = "my_obj"; set $!obj = $msg; action(type="omelasticsearch" template="tpl" searchIndex="rsyslog_testbench" serverport="19200" bulkmode="on" errorFile="'${RSYSLOG_DYNNAME}'.errorfile" erroronly="on") } input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile" Tag="foo" Severity="info" ruleset="foo") ' startup shutdown_when_empty wait_shutdown $PYTHON $srcdir/elasticsearch-error-format-check.py erroronly ret=$? if [ "$ret" -ne 0 ] then echo "error: Format for error file different! " "$ret" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-metrics.sh0000644000000000000000000000013215241075234017211 xustar0030 mtime=1787067036.621578594 30 atime=1787067036.769581365 30 ctime=1787067806.412948999 rsyslog-8.2608.0/tests/imhttp-metrics.sh0000775000175000017500000000160115241075234016656 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 # Verify the imhttp metrics endpoint while the HTTP listener uses an # OS-assigned port. The HTTP status and metrics response are the oracle. . ${srcdir:=.}/diag.sh init generate_conf IMHTTP_PORT_FILE="$RSYSLOG_DYNNAME.imhttp.port" add_conf ' template(name="outfmt" type="string" string="%msg%\n") module(load="../contrib/imhttp/.libs/imhttp" ports="0" listenPortFileName="'$IMHTTP_PORT_FILE'" metricsPath="/metrics" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup assign_file_content IMHTTP_PORT "$IMHTTP_PORT_FILE" curl -s http://localhost:$IMHTTP_PORT/metrics > "$RSYSLOG_OUT_LOG" shutdown_when_empty wait_shutdown content_check "imhttp_up 1" content_check 'U__action_2D_0_2D_builtin:omfile__processed__total' assert_content_missing 'action-0-builtin:omfile_processed_total' exit_testrsyslog-8.2608.0/tests/PaxHeaders/func-substring-relative-endpos.sh0000644000000000000000000000013115131231047022301 xustar0030 mtime=1768239655.702212549 30 atime=1782715518.921791101 29 ctime=1787067804.05390504 rsyslog-8.2608.0/tests/func-substring-relative-endpos.sh0000777000175000017500000000103515131231047021752 0ustar00rgerrger#!/bin/bash # addd 2023-01-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%$!my_struc_data%\n") set $!my_struc_data = substring($STRUCTURED-DATA, 1, -2); local4.debug action(type="omfile" template="outfmt" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg_literal '<167>1 2003-03-01T01:00:00.000Z hostname1 sender - tag [tcpflood@32473 MSGNUM="0"] data' shutdown_when_empty wait_shutdown export EXPECTED='tcpflood@32473 MSGNUM="0"' cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/func-substring-invld-startpos-vg.sh0000644000000000000000000000013215171370365022617 xustar0030 mtime=1776677109.459913357 30 atime=1782715518.922791118 30 ctime=1787067805.306928389 rsyslog-8.2608.0/tests/func-substring-invld-startpos-vg.sh0000775000175000017500000000012615171370365022265 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/func-substring-invld-startpos.sh rsyslog-8.2608.0/tests/PaxHeaders/glbl-ruleset-queue-defaults.sh0000644000000000000000000000013215035412264021567 xustar0030 mtime=1752569012.389827181 30 atime=1782715518.921791101 30 ctime=1787067804.069905339 rsyslog-8.2608.0/tests/glbl-ruleset-queue-defaults.sh0000777000175000017500000000127015035412264021240 0ustar00rgerrger#!/bin/bash # check that global ruleset queue defaults can be specified. However, # we do not tests that they actually work - that's quite hard to # do reliably. # addd 2019-05-09 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global( default.ruleset.queue.timeoutshutdown="1000" default.ruleset.queue.timeoutactioncompletion="1000" default.ruleset.queue.timeoutenqueue="1000" default.ruleset.queue.timeoutworkerthreadshutdown="1000" ) action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup shutdown_when_empty wait_shutdown check_not_present 'parameter.*not known' exit_test rsyslog-8.2608.0/tests/PaxHeaders/sndrcv_relp_rebind.sh0000644000000000000000000000013215216464436020114 xustar0030 mtime=1782212894.083267106 30 atime=1782715518.921791101 30 ctime=1787067807.669972423 rsyslog-8.2608.0/tests/sndrcv_relp_rebind.sh0000775000175000017500000000345115216464436017566 0ustar00rgerrger#!/bin/bash # added 2017-09-29 by Rgerhards # This file is part of the rsyslog project, released under ASL 2.0 # Verify RELP forwarding while omrelp reconnects aggressively with # rebindinterval=1. The receiver binds an ephemeral IPv4 listener and the # testbench discovers that bound port after startup, avoiding the get_free_port # race before the sender connects. Success is the full ordered delivery # sequence. . ${srcdir:=.}/diag.sh init echo testing sending and receiving via relp w/ rebind interval # uncomment for debugging support: # start up the instances #export RSYSLOG_DEBUG="debug nostdout noprintmutexaction" export RSYSLOG_DEBUGLOG="log" generate_conf add_conf ' module(load="../plugins/imrelp/.libs/imrelp") # then SENDER sends to this port (not tcpflood!) input(type="imrelp" address="127.0.0.1" port="0") $template outfmt,"%msg:F,58:2%\n" :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_single_tcp_listener_port PORT_RCVR export RSYSLOG_DEBUGLOG="log2" #valgrind="valgrind" generate_conf 2 add_conf ' module(load="../plugins/omrelp/.libs/omrelp") # We know that a rebind interval of 1 is NOT what you would normally expect in # production. However, this stresses the code the most and we have seen that # some problems do not reliably occur if we use higher rebind intervals. Thus # we consider it to be a good, actually required, setting. action(type="omrelp" protocol="tcp" target="127.0.0.1" port="'$PORT_RCVR'" rebindinterval="1") ' 2 startup 2 # now inject the messages into instance 2. It will connect to instance 1, # and that instance will record the data. injectmsg2 1 1000 # shut down sender shutdown_when_empty 2 wait_shutdown 2 # now it is time to stop the receiver as well shutdown_when_empty wait_shutdown seq_check 1 1000 exit_test rsyslog-8.2608.0/tests/PaxHeaders/ratelimit_policy_watch_multi.sh0000644000000000000000000000013215216464436022221 xustar0030 mtime=1782212894.081267073 30 atime=1782715518.921791101 30 ctime=1787067805.436930812 rsyslog-8.2608.0/tests/ratelimit_policy_watch_multi.sh0000775000175000017500000000576715216464436021707 0ustar00rgerrger#!/bin/bash # Test shared watched-file scheduling across multiple ratelimit policies. . ${srcdir:=.}/diag.sh init . $srcdir/diag.sh check-inotify export PORT_A_FILE="${RSYSLOG_DYNNAME}.imudp_port_a" export PORT_B_FILE="${RSYSLOG_DYNNAME}.imudp_port_b" POLICY_A="$(pwd)/${RSYSLOG_DYNNAME}.policy-a.yaml" export POLICY_A POLICY_B="$(pwd)/${RSYSLOG_DYNNAME}.policy-b.yaml" export POLICY_B OUT_A="$(pwd)/${RSYSLOG_DYNNAME}.out-a.log" export OUT_A OUT_B="$(pwd)/${RSYSLOG_DYNNAME}.out-b.log" export OUT_B export SENDMESSAGES=20 cat > "$POLICY_A" <<'YAML' interval: 1 burst: 1000 severity: 0 YAML cat > "$POLICY_B" <<'YAML' interval: 1 burst: 1000 severity: 0 YAML generate_conf add_conf ' global(processInternalMessages="on") ratelimit(name="watch_a" policy="'$POLICY_A'" policyWatch="on" policyWatchDebounce="200ms") ratelimit(name="watch_b" policy="'$POLICY_B'" policyWatch="on" policyWatchDebounce="200ms") module(load="../plugins/imudp/.libs/imudp" batchSize="1") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_A_FILE'" ratelimit.name="watch_a" ruleset="a") input(type="imudp" address="127.0.0.1" port="0" listenPortFileName="'$PORT_B_FILE'" ratelimit.name="watch_b" ruleset="b") template(name="outfmt" type="string" string="RECEIVED RAW: %rawmsg%\n") ruleset(name="a") { action(type="omfile" file="'$OUT_A'" template="outfmt") } ruleset(name="b") { action(type="omfile" file="'$OUT_B'" template="outfmt") } ' count_msgs() { if [ -f "$1" ]; then grep -c "msgnum:" "$1" || true else echo 0 fi } startup assign_file_content PORT_A "$PORT_A_FILE" assign_file_content PORT_B "$PORT_B_FILE" tcpflood -Tudp -p"$PORT_A" -m "$SENDMESSAGES" -M "msgnum:" tcpflood -Tudp -p"$PORT_B" -m "$SENDMESSAGES" -M "msgnum:" wait_file_lines "$OUT_A" 20 100 wait_file_lines "$OUT_B" 20 100 : > "$OUT_A" : > "$OUT_B" cat > "$POLICY_A" <<'YAML' interval: 10 burst: 0 severity: 0 YAML cat > "$POLICY_B" <<'YAML' interval: 10 burst: 0 severity: 0 YAML ./msleep 1500 tcpflood -Tudp -p"$PORT_A" -m "$SENDMESSAGES" -M "msgnum:" tcpflood -Tudp -p"$PORT_B" -m "$SENDMESSAGES" -M "msgnum:" ./msleep 1000 wait_queueempty count_a=$(count_msgs "$OUT_A") count_b=$(count_msgs "$OUT_B") if [ "$count_a" -ne 0 ] || [ "$count_b" -ne 0 ]; then echo "FAIL: restrictive reload expected both watched policies to block, got A=$count_a B=$count_b" error_exit 1 fi cat > "$POLICY_A" <<'YAML' interval: 1 burst: 1000 severity: 0 YAML ./msleep 1500 tcpflood -Tudp -p"$PORT_A" -m "$SENDMESSAGES" -M "msgnum:" tcpflood -Tudp -p"$PORT_B" -m "$SENDMESSAGES" -M "msgnum:" wait_file_lines "$OUT_A" 20 100 ./msleep 1000 wait_queueempty count_a=$(count_msgs "$OUT_A") count_b=$(count_msgs "$OUT_B") if [ "$count_a" -ne 20 ]; then echo "FAIL: expected policy A to reload back to permissive mode, got $count_a messages" error_exit 1 fi if [ "$count_b" -ne 0 ]; then echo "FAIL: expected policy B to remain restrictive, got $count_b messages" error_exit 1 fi shutdown_when_empty wait_shutdown exit_test rsyslog-8.2608.0/tests/PaxHeaders/privdropuserid.sh0000644000000000000000000000013215131231047017313 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.922791118 30 ctime=1787067804.231908357 rsyslog-8.2608.0/tests/privdropuserid.sh0000777000175000017500000000111215131231047016757 0ustar00rgerrger#!/bin/bash # addd 2016-03-24 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris." . $srcdir/privdrop_common.sh rsyslog_testbench_setup_testuser generate_conf add_conf ' template(name="outfmt" type="list") { property(name="msg" compressSpace="on") constant(value="\n") } action(type="omfile" template="outfmt" file=`echo $RSYSLOG_OUT_LOG`) $PrivDropToUserID '${TESTBENCH_TESTUSER[uid]}' ' startup shutdown_when_empty wait_shutdown content_check --regex "userid.*${TESTBENCH_TESTUSER[uid]}" exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-crash-reservation-repeat.sh0000644000000000000000000000013215241075234025123 xustar0030 mtime=1787067036.642578987 30 atime=1787067036.693579942 30 ctime=1787067803.787900084 rsyslog-8.2608.0/tests/segmented-diskqueue-crash-reservation-repeat.sh0000775000175000017500000000042515241075234024573 0ustar00rgerrger#!/bin/bash # Repeat reservation publication crashes three times to prove ID reconciliation # remains idempotent across consecutive failures. export SEGDISK_FAULT_POINT=reservation-published SEGDISK_FAULT_REPEATS=3 . ${srcdir:=.}/testsuites/segmented-diskqueue-crash-driver.sh rsyslog-8.2608.0/tests/PaxHeaders/segmented-da-config-errors.sh0000644000000000000000000000013215241075234021352 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 30 ctime=1787067803.806900438 rsyslog-8.2608.0/tests/segmented-da-config-errors.sh0000775000175000017500000000565015241075234021027 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Queue DA engine parameters are intentionally limited to FixedArray and # LinkedList queues with a filename. The permissive oracle is a successful -N1 # validation plus the dirty-configuration diagnostic; the strict oracle is a # failed validation when abortOnUncleanConfig is enabled. . ${srcdir:=.}/diag.sh init assert_contains() { grep -Fq "$2" "$1" || { cat "$1" error_exit 1 "missing expected diagnostic: $2" } } check_permissive_invalid_context() { generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.diskQueueType="disk" queue.diskQueueAutoUpgrade="on" queue.diskQueueIdleTimeout="25") ' local out="${RSYSLOG_DYNNAME}.permissive.log" export RS_REDIR=">\"$out\" 2>&1" startup shutdown_when_empty wait_shutdown unset RS_REDIR assert_contains "$out" 'apply only to FixedArray or LinkedList disk-assisted queues' } check_strict_invalid_context() { generate_conf add_conf ' global(abortOnUncleanConfig="on" workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="segmentedDisk" queue.filename="mainq" queue.diskQueueType="disk") ' local out="${RSYSLOG_DYNNAME}.strict.log" if ../tools/rsyslogd -C -N1 -f"${TESTCONF_NM}.conf" -M../runtime/.libs:../.libs >"$out" 2>&1; then error_exit 1 "strict invalid-context configuration unexpectedly passed" fi assert_contains "$out" 'apply only to FixedArray or LinkedList disk-assisted queues' } check_strict_meaningless_options() { generate_conf add_conf ' global(abortOnUncleanConfig="on" workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.diskQueueType="disk" queue.diskQueueAutoUpgrade="on" queue.diskQueueIdleTimeout="25") ' local out="${RSYSLOG_DYNNAME}.meaningless.log" if ../tools/rsyslogd -C -N1 -f"${TESTCONF_NM}.conf" -M../runtime/.libs:../.libs >"$out" 2>&1; then error_exit 1 "strict meaningless DA options unexpectedly passed" fi assert_contains "$out" 'queue.diskQueueAutoUpgrade applies only' assert_contains "$out" 'queue.diskQueueIdleTimeout does not apply' } check_strict_invalid_values() { generate_conf add_conf ' global(abortOnUncleanConfig="on" workDirectory="'${RSYSLOG_DYNNAME}'.spool") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.diskQueueType="unknown" queue.diskQueueIdleTimeout="-2") ' local out="${RSYSLOG_DYNNAME}.invalid-values.log" if ../tools/rsyslogd -C -N1 -f"${TESTCONF_NM}.conf" -M../runtime/.libs:../.libs >"$out" 2>&1; then error_exit 1 "strict invalid DA values unexpectedly passed" fi assert_contains "$out" "queue.diskQueueType: invalid value 'unknown'" assert_contains "$out" 'queue.diskQueueIdleTimeout must be -1 or greater' } check_permissive_invalid_context check_strict_invalid_context check_strict_meaningless_options check_strict_invalid_values exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_field.sh0000644000000000000000000000013115035412264017067 xustar0030 mtime=1752569012.410681262 30 atime=1782715518.922791118 29 ctime=1787067804.74291788 rsyslog-8.2608.0/tests/rscript_field.sh0000777000175000017500000000126015035412264016540 0ustar00rgerrger#!/bin/bash # added 2012-09-20 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_field.sh\]: testing rainerscript field\(\) function . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup injectmsg 0 5000 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 4999 exit_test rsyslog-8.2608.0/tests/PaxHeaders/timestamp-3164.sh0000644000000000000000000000013215131231047016630 xustar0030 mtime=1768239655.725212925 30 atime=1782715518.921791101 30 ctime=1787067804.001904072 rsyslog-8.2608.0/tests/timestamp-3164.sh0000777000175000017500000000313215131231047016300 0ustar00rgerrger#!/bin/bash # add 2018-06-25 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="string" string="%timestamp:::date-rfc3164%\n") :syslogtag, contains, "TAG" action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup injectmsg_literal "<167>Jan 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Feb 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Mar 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Apr 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>May 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Jun 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Jul 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Aug 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Sep 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Oct 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Nov 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Dec 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Jan 6 16:57:54 172.20.245.8 TAG: MSG" injectmsg_literal "<167>Jan 16 16:57:54 172.20.245.8 TAG: MSG" shutdown_when_empty wait_shutdown echo 'Jan 6 16:57:54 Feb 6 16:57:54 Mar 6 16:57:54 Apr 6 16:57:54 May 6 16:57:54 Jun 6 16:57:54 Jul 6 16:57:54 Aug 6 16:57:54 Sep 6 16:57:54 Oct 6 16:57:54 Nov 6 16:57:54 Dec 6 16:57:54 Jan 6 16:57:54 Jan 16 16:57:54' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imuxsock_logger.sh0000644000000000000000000000013215145046113017436 xustar0030 mtime=1771326539.042014337 30 atime=1782715518.921791101 30 ctime=1787067804.655916259 rsyslog-8.2608.0/tests/imuxsock_logger.sh0000775000175000017500000000107415145046113017107 0ustar00rgerrger#!/bin/bash . ${srcdir:=.}/diag.sh init check_logger_has_option_d export NUMMESSAGES=1 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imuxsock/.libs/imuxsock" sysSock.use="off") input(type="imuxsock" Socket="'$RSYSLOG_DYNNAME'-testbench_socket") template(name="outfmt" type="string" string="%msg:%\n") *.=notice action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup logger -d -u $RSYSLOG_DYNNAME-testbench_socket test shutdown_when_empty wait_shutdown export EXPECTED=" test" cmp_exact exit_test rsyslog-8.2608.0/tests/PaxHeaders/lookup_table_rscript_reload_without_stub.sh0000644000000000000000000000013215035412264024633 xustar0030 mtime=1752569012.399757696 30 atime=1782715518.922791118 30 ctime=1787067804.987922445 rsyslog-8.2608.0/tests/lookup_table_rscript_reload_without_stub.sh0000777000175000017500000000323015035412264024302 0ustar00rgerrger#!/bin/bash # test for lookup-table reload by rscript-stmt without stub # added 2015-12-18 by singh.janmejay # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init skip_platform "FreeBSD" "This test currently does not work on FreeBSD" generate_conf add_conf ' lookup_table(name="xlate" file="'$RSYSLOG_DYNNAME'.xlate.lkp_tbl") template(name="outfmt" type="string" string="- %msg% %$.lkp%\n") set $.lkp = lookup("xlate", $msg); if ($msg == " msgnum:00000002:") then { reload_lookup_table("xlate") } action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' cp -f $srcdir/testsuites/xlate.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl startup # the last message ..002 should cause successful lookup-table reload cp -f $srcdir/testsuites/xlate_more.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl injectmsg 0 3 await_lookup_table_reload wait_queueempty content_check "msgnum:00000000: foo_old" content_check "msgnum:00000001: bar_old" assert_content_missing "baz" cp -f $srcdir/testsuites/xlate_more_with_duplicates_and_nomatch.lkp_tbl $RSYSLOG_DYNNAME.xlate.lkp_tbl injectmsg 0 3 await_lookup_table_reload wait_queueempty content_check "msgnum:00000000: foo_new" content_check "msgnum:00000001: bar_new" content_check "msgnum:00000002: baz" rm -f $RSYSLOG_DYNNAME.xlate.lkp_tbl # this should lead to unsuccessful reload injectmsg 0 3 await_lookup_table_reload wait_queueempty injectmsg 0 2 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown content_check_with_count "msgnum:00000000: foo_latest" 2 content_check_with_count "msgnum:00000001: quux" 2 content_check_with_count "msgnum:00000002: baz_latest" 1 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imtcp-stream-always-zlib-fragmented-ratio.sh0000644000000000000000000000013115241075234024326 xustar0030 mtime=1787067036.623578631 29 atime=1787067036.77358144 30 ctime=1787067805.570933309 rsyslog-8.2608.0/tests/imtcp-stream-always-zlib-fragmented-ratio.sh0000775000175000017500000000307015241075234023776 0ustar00rgerrger#!/bin/bash # added 2026-05-22 by Codex, released under ASL 2.0 # Verifies that imtcp applies the expansion-ratio guard to the cumulative # compressed stream, not each fragmented TCP receive. The oracle is that a # valid stream sent one byte at a time is accepted with a low-but-legitimate # ratio limit. . ${srcdir:=.}/diag.sh init require_plugin imtcp check_command_available python3 export NUMMESSAGES=2000 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" compression.mode="stream:always" compression.driver="zlib" compression.maxExpansionRatio="64") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") ' startup assign_tcpflood_port "$RSYSLOG_DYNNAME.tcpflood_port" python3 - "$TCPFLOOD_PORT" <<'PY' import socket import sys import time import zlib port = int(sys.argv[1]) payload = "".join( "<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:%08d AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" % i for i in range(0, 2000) ).encode("ascii") # Solaris' older Python accepts the compression level only positionally. compressed = zlib.compress(payload, 1) sock = socket.create_connection(("127.0.0.1", port)) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) for octet in compressed: sock.sendall(bytes((octet,))) time.sleep(0.0005) sock.close() PY shutdown_when_empty wait_shutdown seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_ipv42num.sh0000644000000000000000000000013215241075234017472 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.791581777 30 ctime=1787067804.739917824 rsyslog-8.2608.0/tests/rscript_ipv42num.sh0000775000175000017500000000346015241075234017144 0ustar00rgerrger#!/bin/bash # add 2017-02-09 by Jan Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") # in pre 8.1907.0 versions of rsyslog the code was misspelled as # "ip42num" (missing "v"). We check this is still supported as alias set $!ip!v0 = ip42num("0.0.0.0"); # use correct function name set $!ip!v1 = ipv42num("0.0.0.0"); set $!ip!v2 = ipv42num("0.0.0.1"); set $!ip!v3 = ipv42num("0.0.1.0"); set $!ip!v4 = ipv42num("0.1.0.0"); set $!ip!v5 = ipv42num("1.0.0.0"); set $!ip!v6 = ipv42num("0.0.0.135"); set $!ip!v7 = ipv42num("1.1.1.1"); set $!ip!v8 = ipv42num("225.33.1.10"); set $!ip!v9 = ipv42num("172.0.0.1"); set $!ip!v10 = ipv42num("255.255.255.255"); set $!ip!v11 = ipv42num("1.0.3.45 "); set $!ip!v12 = ipv42num(" 0.0.0.1"); set $!ip!v13 = ipv42num(" 0.0.0.1 "); set $!ip!e1 = ipv42num("a"); set $!ip!e2 = ipv42num(""); set $!ip!e3 = ipv42num("123.4.6.*"); set $!ip!e4 = ipv42num("172.0.0.1."); set $!ip!e5 = ipv42num("172.0.0..1"); set $!ip!e6 = ipv42num(".172.0.0.1"); set $!ip!e7 = ipv42num(".17 2.0.0.1"); template(name="outfmt" type="string" string="%!ip%\n") local4.* action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") ' startup tcpflood -m1 -y shutdown_when_empty wait_shutdown echo '{ "v0": 0, "v1": 0, "v2": 1, "v3": 256, "v4": 65536, "v5": 16777216, "v6": 135, "v7": 16843009, "v8": 3777036554, "v9": 2885681153, "v10": 4294967295, "v11": 16778029, "v12": 1, "v13": 1, "e1": -1, "e2": -1, "e3": -1, "e4": -1, "e5": -1, "e6": -1, "e7": -1 }' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid function output detected, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/internal-errmsg-memleak-vg.sh0000644000000000000000000000013215035412264021373 xustar0030 mtime=1752569012.398764645 30 atime=1782715518.921791101 30 ctime=1787067805.185926135 rsyslog-8.2608.0/tests/internal-errmsg-memleak-vg.sh0000777000175000017500000000245415035412264021051 0ustar00rgerrger#!/bin/bash # This tests a memory leak we have seen when processing internal error # message with the settings used in this test. We use imfile as it is # easist to reproduce this way. Note that we are only interested in # whether or not we have a leak, not any other functionality. Most # importantly, we do not care if the error message appears or not. This # is because it is not so easy to pick it up from the system log and other # tests already cover this scenario. # add 2017-05-10 by Rainer Gerhards, released under ASL 2.0 uname if [ $(uname) = "FreeBSD" ] ; then echo "This test currently does not work on FreeBSD." exit 77 fi . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(processInternalMessages="off") $RepeatedMsgReduction on # keep this on because many distros have set it module(load="../plugins/imfile/.libs/imfile") # mode="polling" pollingInterval="1") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="tag1" ruleset="ruleset1") template(name="tmpl1" type="string" string="%msg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="tmpl1") } action(type="omfile" file=`echo $RSYSLOG2_OUT_LOG`) ' startup_vg_waitpid_only ./msleep 500 # wait a bit so that the error message can be emitted shutdown_immediate wait_shutdown_vg exit_test rsyslog-8.2608.0/tests/PaxHeaders/yaml-script-msgvar.sh0000644000000000000000000000013215241075234020001 xustar0030 mtime=1787067036.649579118 30 atime=1787067036.802581983 30 ctime=1787067805.391929973 rsyslog-8.2608.0/tests/yaml-script-msgvar.sh0000775000175000017500000000340415241075234017451 0ustar00rgerrger#!/bin/bash # Tests a more complex inline RainerScript script: block in YAML: # - set $!nbr message variable from a field() extraction # - nested if expression using cnum() and arithmetic comparison # - two sequential actions (unconditional + conditional) # Sends 500 messages; all pass the outer if (contain "msgnum:"), but only # messages 0-199 reach the second action (the rest are stopped early to keep # the test fast). seq_check 0 499 verifies all 500 reach the first action. # # Added 2025, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imtcp export NUMMESSAGES=500 export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' include(file="'${RSYSLOG_DYNNAME}'.yaml") ' cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF' modules: - load: "../plugins/imtcp/.libs/imtcp" templates: - name: outfmt type: string string: "%msg:F,58:2%\n" - name: varfmt type: string string: "%$!nbr%\n" rulesets: - name: main script: | if $msg contains "msgnum:" then { action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}") set $!nbr = field($msg, 58, 2); if cnum($!nbr) >= 200 then stop action(type="omfile" template="varfmt" file="${RSYSLOG_DYNNAME}.detail") } YAMLEOF sed -i \ -e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \ -e "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" \ "${RSYSLOG_DYNNAME}.yaml" add_conf ' input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port" ruleset="main") ' startup tcpflood -m $NUMMESSAGES shutdown_when_empty wait_shutdown seq_check 0 499 # The detail file should contain exactly the first 200 messages (0-199) SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}.detail" seq_check 0 199 exit_test rsyslog-8.2608.0/tests/PaxHeaders/action-ratelimit-drop.sh0000644000000000000000000000013215241075234020447 xustar0030 mtime=1787067036.614578463 30 atime=1787067036.682579736 30 ctime=1787067805.350929209 rsyslog-8.2608.0/tests/action-ratelimit-drop.sh0000775000175000017500000000164415241075234020123 0ustar00rgerrger#!/bin/bash # Verify generic action-level output rate limiting in drop mode. # The policy allows five messages in a long window; the oracle is that exactly # the first five injected messages reach omfile and later matching messages are # intentionally discarded before the output module runs. . ${srcdir:=.}/diag.sh init POLICY_FILE="$(pwd)/${RSYSLOG_DYNNAME}.output-drop.yaml" cat > "$POLICY_FILE" << 'YAMLEOF' scope: output mode: drop interval: 60 burst: 5 YAMLEOF generate_conf add_conf ' ratelimit(name="out_drop" policy="'$POLICY_FILE'") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt" action.ratelimit.name="out_drop") ' startup injectmsg 0 20 shutdown_when_empty wait_shutdown content_count_check "000000" 5 "$RSYSLOG_OUT_LOG" seq_check 0 4 exit_test rsyslog-8.2608.0/tests/PaxHeaders/imdtls-sessionbreak-vg.sh0000644000000000000000000000013215171370365020641 xustar0030 mtime=1776677109.460913372 30 atime=1782715518.921791101 30 ctime=1787067807.785974585 rsyslog-8.2608.0/tests/imdtls-sessionbreak-vg.sh0000775000175000017500000000053315171370365020311 0ustar00rgerrger#!/bin/bash if [ "$(valgrind --version)" == "valgrind-3.11.0" ]; then printf 'This test does NOT work with valgrind-3.11.0 - valgrind always reports\n' printf 'a valgrind-internal bug. So we need to skip it.\n' exit 77 fi export USE_VALGRIND="YES" export RS_TEST_VALGRIND_EXTRA_OPTS="--keep-debuginfo=yes" . ${srcdir:-.}/imdtls-sessionbreak.sh rsyslog-8.2608.0/tests/PaxHeaders/omudpspoof_errmsg_no_params.sh0000644000000000000000000000013115035412264022047 xustar0030 mtime=1752569012.406709056 30 atime=1782715518.921791101 29 ctime=1787067807.80397492 rsyslog-8.2608.0/tests/omudpspoof_errmsg_no_params.sh0000777000175000017500000000056315035412264021525 0ustar00rgerrger#!/bin/bash # add 2019-04-15 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/omudpspoof/.libs/omudpspoof") action(type="omfile" file="'$RSYSLOG_OUT_LOG'") action(type="omudpspoof") ' startup shutdown_when_empty wait_shutdown content_check "parameter 'target' required but not specified" exit_test rsyslog-8.2608.0/tests/PaxHeaders/fuzz0000644000000000000000000000013215241076633014631 xustar0030 mtime=1787067803.675897997 30 atime=1787067808.794993387 30 ctime=1787067803.675897997 rsyslog-8.2608.0/tests/fuzz/0000775000175000017500000000000015241076633014352 5ustar00rgerrgerrsyslog-8.2608.0/tests/fuzz/PaxHeaders/corpus0000644000000000000000000000013015241076633016142 xustar0029 mtime=1787067803.52689522 30 atime=1787067808.794993387 29 ctime=1787067803.52689522 rsyslog-8.2608.0/tests/fuzz/corpus/0000775000175000017500000000000015241076633015665 5ustar00rgerrgerrsyslog-8.2608.0/tests/fuzz/corpus/PaxHeaders/syslog-message0000644000000000000000000000013215241076633021106 xustar0030 mtime=1787067803.690898276 30 atime=1787067808.794993387 30 ctime=1787067803.690898276 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/0000775000175000017500000000000015241076633020627 5ustar00rgerrgerrsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc3164-no-pri0000644000000000000000000000013215241075234023374 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.679898071 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc3164-no-pri0000664000175000017500000000010215241075234023031 0ustar00rgerrgerOct 11 22:14:15 host.example app[123]: legacy message without PRI rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc5424-escaped-sd0000644000000000000000000000013215241075234024201 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.688898239 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc5424-escaped-sd0000664000175000017500000000015215241075234023643 0ustar00rgerrger<34>1 2026-07-23T09:30:45+02:00 host app 123 msg [meta@32473 value="escaped\]bracket" quote="\""] payload rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc3164-rfc33390000644000000000000000000000013215241075234023264 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.682898127 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc3164-rfc33390000664000175000017500000000010115241075234022720 0ustar00rgerrger<13>2026-07-23T09:30:45.123+02:00 host daemon: timestamp variant rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc5424-basic0000644000000000000000000000013215241075234023252 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.686898202 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc5424-basic0000664000175000017500000000023315241075234022714 0ustar00rgerrger<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application"] An application event log entry rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc3164-short0000644000000000000000000000013215241075234023327 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.767581328 30 ctime=1787067803.684898165 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc3164-short0000664000175000017500000000000515241075234022766 0ustar00rgerrger<0>x rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc3164-basic0000644000000000000000000000013215241075234023251 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.677898034 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc3164-basic0000664000175000017500000000011515241075234022712 0ustar00rgerrger<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/PaxHeaders/rfc5424-nil0000644000000000000000000000013215241075234022753 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.767581328 30 ctime=1787067803.690898276 rsyslog-8.2608.0/tests/fuzz/corpus/syslog-message/rfc5424-nil0000664000175000017500000000003215241075234022412 0ustar00rgerrger<13>1 - - - - - - minimal rsyslog-8.2608.0/tests/fuzz/PaxHeaders/README.md0000644000000000000000000000013215241075234016161 xustar0030 mtime=1787067036.619578557 30 atime=1787067036.683579755 30 ctime=1787067803.675897997 rsyslog-8.2608.0/tests/fuzz/README.md0000664000175000017500000000313615241075234015630 0ustar00rgerrger# Syslog parser fuzzing The `fuzz_rsyslog_message` target sends every input independently through the core PRI parser and the built-in RFC 3164 and RFC 5424 parsers. The seed corpus contains both formats, with additional RFC 3164 cases because legacy syslog remains widely deployed. Build an instrumented target in a clean worktree: ```sh export CC=clang export CFLAGS="-O1 -g -fno-omit-frame-pointer \ -fsanitize=fuzzer-no-link,address,undefined -fno-sanitize=function" export LDFLAGS="-fsanitize=address,undefined -fno-sanitize=function" ./autogen.sh --enable-debug --enable-testbench --enable-fuzzing make -C tools -j"${RSYSLOG_LOCAL_BUILD_JOBS:-10}" fuzz_rsyslog_message ``` `LIB_FUZZING_ENGINE` may name an alternative fuzzer library or linker flags when the compiler's `-fsanitize=fuzzer` runtime cannot be linked directly. The function-type UBSan check is excluded because rsyslog's module ABI uses generic callback pointers; ASan and all other `undefined` checks remain active. Run a bounded local campaign: ```sh mkdir -p fuzz-corpus-work tools/fuzz_rsyslog_message \ -max_len=65536 \ -timeout=5 \ -rss_limit_mb=2048 \ fuzz-corpus-work \ tests/fuzz/corpus/syslog-message ``` libFuzzer writes newly interesting inputs to its first corpus directory, so the separate work directory keeps the checked-in seed corpus unchanged. The fuzzer treats crashes, sanitizer findings, timeouts, and invalid parser offsets as failures. Minimize any artifact before turning it into a permanent regression test: ```sh tools/fuzz_rsyslog_message \ -minimize_crash=1 \ -exact_artifact_path=minimized-input \ crash-input ``` rsyslog-8.2608.0/tests/PaxHeaders/rsyslog-segqueue-runtime.sh0000644000000000000000000000013215241075234021244 xustar0030 mtime=1787067036.641578968 30 atime=1787067036.691579904 30 ctime=1787067803.711898668 rsyslog-8.2608.0/tests/rsyslog-segqueue-runtime.sh0000775000175000017500000000464015241075234020717 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Exercise rsyslog-segqueue against a store written by the real queue engine. # A deliberately slow main queue is stopped with saveOnShutdown enabled, which # must leave a non-empty segmented queue. The tool must validate that store and # export structurally valid JSONL while rsyslog is offline. Restart and the # normal sequence oracle then prove that inspection did not alter replay data. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=2000 SPOOL_DIR="${RSYSLOG_DYNNAME}.spool" QUEUE_DIR="$SPOOL_DIR/mainq.segq" SEGQUEUE_TOOL="$srcdir/../tools/rsyslog-segqueue" EXPORT_FILE="${RSYSLOG_DYNNAME}.jsonl" command -v python3 >/dev/null 2>&1 || skip_platform "python3 not available" generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") main_queue(queue.type="LinkedList" queue.filename="mainq" queue.size="6000" queue.highWatermark="10" queue.lowWatermark="5" queue.dequeueBatchSize="1" queue.dequeueSlowdown="10000" queue.timeoutShutdown="1000" queue.saveOnShutdown="on" queue.diskQueueType="auto" queue.diskQueueIdleTimeout="-1") template(name="outfmt" type="string" string="%msg:F,58:2%\n") :msg, contains, "msgnum:" action(type="omfile" file="'"$RSYSLOG_OUT_LOG"'" template="outfmt") ' startup injectmsg shutdown_immediate wait_shutdown [ -s "$QUEUE_DIR/state" ] || error_exit 1 "segmented queue state was not persisted" python3 "$SEGQUEUE_TOOL" check "$QUEUE_DIR" || error_exit 1 "tool rejected a runtime-written queue" python3 "$SEGQUEUE_TOOL" status --json "$QUEUE_DIR" >"${RSYSLOG_DYNNAME}.status.json" || error_exit 1 "tool status failed for a runtime-written queue" python3 "$SEGQUEUE_TOOL" export --scope live --output "$EXPORT_FILE" "$QUEUE_DIR" || error_exit 1 "tool export failed for a runtime-written queue" python3 - "$EXPORT_FILE" <<'PY' || error_exit 1 "tool export was not valid JSONL" import json import sys count = 0 with open(sys.argv[1], "r", encoding="utf-8") as stream: for line in stream: record = json.loads(line) assert isinstance(record["queue"]["record_sequence"], int) assert isinstance(record["message"], dict) count += 1 assert count > 0 PY startup # Main-queue emptiness may be observed while the DA child is still draining. # Complete sequence recovery is the non-mutation oracle for the tool run. wait_seq_check 0 $((NUMMESSAGES - 1)) -d shutdown_when_empty wait_shutdown seq_check 0 $((NUMMESSAGES - 1)) -d exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-whitespace-filename.sh0000644000000000000000000000013115035412264021421 xustar0030 mtime=1752569012.402736851 30 atime=1782715518.921791101 29 ctime=1787067804.20090778 rsyslog-8.2608.0/tests/omfile-whitespace-filename.sh0000777000175000017500000000070315035412264021073 0ustar00rgerrger#!/bin/bash # addd 2018-04-03 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' action(type="omfile" file=" ") action(type="omfile" file=`echo $RSYSLOG_OUT_LOG`) ' startup shutdown_when_empty wait_shutdown grep "only of whitespace" $RSYSLOG_OUT_LOG > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-start.sh0000644000000000000000000000013215035412264017523 xustar0030 mtime=1752569012.385854976 30 atime=1782715518.922791118 30 ctime=1787067805.778937185 rsyslog-8.2608.0/tests/clickhouse-start.sh0000777000175000017500000000166715035412264017206 0ustar00rgerrger#!/bin/bash # This is not a real test, but a script to start clickhouse. It is # implemented as test so that we can start clickhouse at the time we need # it (do so via Makefile.am). # Copyright (C) 2018 Pascal Withopf and Adiscon GmbH # Released under ASL 2.0 . ${srcdir:=.}/diag.sh init set -x if [ "$CLICKHOUSE_START_CMD" == "" ]; then exit_test # no start needed fi test_error_exit_handler() { printf 'clickhouse startup failed, log is:\n' $SUDO cat /var/log/clickhouse-server/clickhouse-server.err.log } printf 'starting clickhouse...\n' $CLICKHOUSE_START_CMD & sleep 10 #wait_startup_pid /var/run/clickhouse-server/clickhouse-server.pid printf 'preparing clickhouse for testbench use...\n' $SUDO ${srcdir}/../devtools/prepare_clickhouse.sh clickhouse-client --query="select 1" rc=$? if [ $rc -ne 0 ]; then printf 'clickhouse failed to start, exit code %d\n' $rc error_exit 100 fi printf 'done, clickhouse ready for testbench\n' exit_test rsyslog-8.2608.0/tests/PaxHeaders/imbatchreport_rename_success.sh0000644000000000000000000000013215035412264022161 xustar0030 mtime=1752569012.390820233 30 atime=1782715518.922791118 30 ctime=1787067808.121980846 rsyslog-8.2608.0/tests/imbatchreport_rename_success.sh0000777000175000017500000000572515035412264021643 0ustar00rgerrger#!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' # 804/805 fail/sent with space dedup global(maxmessagesize="820") module(load="../contrib/imbatchreport/.libs/imbatchreport" pollinginterval="1") global(localhostname="server") input(type="imbatchreport" ruleset="ruleset" tag="batch" severity="info" facility="local0" reports="./'$RSYSLOG_DYNNAME'*.done" deduplicatespace="on" programkey="KSH" timestampkey="START" rename=".done$ .sent .rejected" ) ruleset(name="ruleset") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="RSYSLOG_SyslogProtocol23Format") } ' { echo '164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)' echo '164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree' echo '164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)' echo '164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree' echo '164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)' echo '164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1' } > $RSYSLOG_DYNNAME.rsu.done case $(uname) in FreeBSD) datelog=$(date -ur $(stat -f %m $RSYSLOG_DYNNAME.rsu.done) "+%Y-%m-%dT%H:%M:%S") ;; *) datelog=$(date "+%Y-%m-%dT%H:%M:%S" -ud @$(stat -c "%Y" $RSYSLOG_DYNNAME.rsu.done)) ;; esac echo "Batch report to consume ${RSYSLOG_DYNNAME}.rsu.done for ${datelog}" startup shutdown_when_empty wait_shutdown export EXPECTED='<134>1 '${datelog}'.000000+00:00 server batch - - - 164313.149.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.150.tst-tmsm1!ARTIMPP_UDB.40042721.1.0: gtrid x0 x5624ee75 x1c88a0f: TRACE:at: } tpfree\n164313.151.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02B003UF^>: TRACE:at: { tpcommit(0x0)\n164313.152.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: gtrid x0 x5624ee75 x1c88a0f: ECID <000001833E1D4i^5pVl3iY00f02M003UF^>: TRACE:at: } tpfree\n164313.153.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003VF^>: TRACE:at: { tpacall("ARTIGW_SVC_REPLY_00700_02101", 0x110405698, 0, 0xc)\n164313.154.tst-tmsm1!ARTIMPP_UDB.40042722.1.0: ECID <000001833E1D4i^5pVl3iY00f02M003SF^>: TRACE:at: } tpcommit = 1' cmp_exact if [ -e $RSYSLOG_DYNNAME.rsu.done ] || [ -e $RSYSLOG_DYNNAME.rsu.rejected ] || [ ! -e $RSYSLOG_DYNNAME.rsu.sent ]; then echo "The batch report could not be renamed" ls $RSYSLOG_DYNNAME* error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/imhttp-post-payload-compress-vg.sh0000644000000000000000000000013215171370365022427 xustar0030 mtime=1776677109.462913403 30 atime=1782715518.922791118 30 ctime=1787067806.435949428 rsyslog-8.2608.0/tests/imhttp-post-payload-compress-vg.sh0000775000175000017500000000024315171370365022075 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" #export RS_TEST_VALGRIND_EXTRA_OPTS="--leak-check=full --show-leak-kinds=all" . ${srcdir:-.}/imhttp-post-payload-compress.sh rsyslog-8.2608.0/tests/PaxHeaders/omrabbitmq_error_server3.sh0000644000000000000000000000013215132733117021257 xustar0030 mtime=1768666703.965621117 30 atime=1782715518.922791118 30 ctime=1787067806.526951124 rsyslog-8.2608.0/tests/omrabbitmq_error_server3.sh0000777000175000017500000000312615132733117020732 0ustar00rgerrger#!/bin/bash # add 2019-09-03 by Philippe Duveau, released under ASL 2.0 . ${srcdir:=.}/diag.sh init cmd="./miniamqpsrvr -b 2 -f $RSYSLOG_DYNNAME.amqp.log -w 500 -d" echo $cmd eval $cmd > $RSYSLOG_DYNNAME.source if [ ! $? -eq 0 ]; then exit 77 fi . $RSYSLOG_DYNNAME.source export OMRABBITMQ_TEST=2000 generate_conf add_conf ' global(localhostname="server") module(load="../contrib/omrabbitmq/.libs/omrabbitmq") template(name="rkTpl" type="string" string="%syslogtag%.%syslogfacility-text%.%syslogpriority-text%") # rfc5424 without Timestamp : unable to manage template(name="bodyTpl" type="string" string="<%PRI%>1 %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg:2:$%\n") ruleset(name="rmq") { action(type="omrabbitmq" host="localhost:'$PORT_AMQP1' localhost:'$PORT_AMQP2'" port="5672" user="mtr" password="mtr" exchange="in" expiration="5000" body_template="" content_type="rfc5424" virtual_host="/metrologie" routing_key_template="rkTpl" populate_properties="on" delivery_mode="transient" ) } if $msg contains "msgrmq" then { call rmq } action(type="omfile" file="'$RSYSLOG_OUT_LOG'") ' startup injectmsg literal "<167>Mar 1 01:00:00 192.0.2.8 tag msgrmq" shutdown_when_empty wait_shutdown export EXPECTED='Exchange:in, routing-key:tag.local4.debug, content-type:plain/text, facility:local4, severity:debug, hostname:192.0.2.8, fromhost:127.0.0.1, delivery-mode:transient, expiration:5000, timestamp:OK, app-id:tag, msg:<167>Mar 1 01:00:00 192.0.2.8 tag msgrmq' cmp_exact $RSYSLOG_DYNNAME.amqp.log content_check "Connection closed : reconnect" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhiredis-withpass-vg.sh0000644000000000000000000000013215171370365020502 xustar0030 mtime=1776677109.466913465 30 atime=1782715518.922791118 30 ctime=1787067806.648953397 rsyslog-8.2608.0/tests/omhiredis-withpass-vg.sh0000775000175000017500000000027615171370365020156 0ustar00rgerrger#!/usr/bin/env bash # added 2023-04-20 by Théo Bertin, released under ASL 2.0 ## Uncomment for debugging #export RS_REDIR=-d export USE_VALGRIND="YES" . ${srcdir:=.}/omhiredis-withpass.sh rsyslog-8.2608.0/tests/PaxHeaders/omfile_both_files_set.sh0000644000000000000000000000012715241075234020570 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.783581627 29 ctime=1787067804.20790791 rsyslog-8.2608.0/tests/omfile_both_files_set.sh0000775000175000017500000000234515241075234020237 0ustar00rgerrger#!/bin/bash # add 2016-11-22 by Pascal Withopf, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="dynafile" type="string" string=`echo $RSYSLOG_OUT_LOG`) template(name="outfmt" type="string" string="-%msg%-\n") :msg, contains, "msgnum:" { action(type="omfile" template="outfmt" file=`echo $RSYSLOG2_OUT_LOG` dynafile="dynafile") } action(type="omfile" file="'${RSYSLOG_DYNNAME}'.errorfile") ' startup tcpflood -m1 -M "\"<129>Mar 10 01:00:00 172.20.245.8 tag: msgnum:1\"" shutdown_when_empty wait_shutdown grep "will use dynafile" ${RSYSLOG_DYNNAME}.errorfile > /dev/null if [ $? -ne 0 ]; then echo echo "FAIL: expected error message not found. ${RSYSLOG_DYNNAME}.errorfile is:" cat ${RSYSLOG_DYNNAME}.errorfile error_exit 1 fi echo '- msgnum:1-' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "unexpected content in $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; if [ -f ${RSYSLOG2_OUT_LOG} ]; then echo "file exists, but should not: ${RSYSLOG2_OUT_LOG}; content:" cat ${RSYSLOG2_OUT_LOG} error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_parse_json-vg.sh0000644000000000000000000000013215241075234020563 xustar0030 mtime=1787067036.639578931 30 atime=1787067036.792581796 30 ctime=1787067805.156925594 rsyslog-8.2608.0/tests/rscript_parse_json-vg.sh0000775000175000017500000000117715241075234020240 0ustar00rgerrger#!/bin/bash # Added 2017-12-09 by Rainer Gerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port") template(name="outfmt" type="string" string="%$!%\n") local4.* { set $.ret = parse_json("{ \"c1\":\"data\" }", "\$!parsed"); action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt") } ' startup_vg tcpflood -m1 shutdown_when_empty wait_shutdown_vg check_exit_vg export EXPECTED='{ "parsed": { "c1": "data" } }' cmp_exact $RSYSLOG_OUT_LOG exit_test rsyslog-8.2608.0/tests/PaxHeaders/omhttp-validate-response.py0000644000000000000000000000013215216464436021224 xustar0030 mtime=1782212894.078267025 30 atime=1782715518.923791135 30 ctime=1787067808.685991356 rsyslog-8.2608.0/tests/omhttp-validate-response.py0000664000175000017500000001321715216464436020674 0ustar00rgerrgerimport json import argparse import sys from collections import defaultdict def parse_json_lines_to_memory(file, filename): """Read a file and reconstruct complete JSON objects into a list.""" buffer = "" line_number = 0 parsed_objects = [] for line in file: line_number += 1 buffer += line.strip() try: # Attempt to parse the JSON object parsed_objects.append(json.loads(buffer)) buffer = "" # Clear the buffer after successful parsing except json.JSONDecodeError: # If parsing fails, keep buffering lines continue if buffer: # If there's leftover data in the buffer, raise an error raise ValueError( f"Incomplete JSON object found at the end of the file '{filename}'. " f"Last buffered content: {buffer}" ) return parsed_objects if __name__ == '__main__': parser = argparse.ArgumentParser(description='Validate and process log files for errors and responses.') parser.add_argument('--error', action='store', type=str, required=True, help='Path to the error file.') parser.add_argument('--response', action='store', type=str, required=True, help='Path to the response file.') parser.add_argument('--max-errors', action='store', type=int, default=10, help='Maximum number of errors to display.') args = parser.parse_args() messages = defaultdict(dict) errors = [] # Collect errors for reporting at the end # Load the error file into memory try: with open(args.error, "r") as error_f: error_data = parse_json_lines_to_memory(error_f, args.error) for json_obj in error_data: try: records = json.loads(json_obj['request']['postdata']) if records: for i, val in enumerate(records['records']): msgnum = val['value']['msgnum'] messages[msgnum]['response'] = json_obj['response'] messages[msgnum]['index'] = i except KeyError as e: errors.append( f"Missing key {e} in error file '{args.error}'. " f"Problematic JSON object: {json_obj}" ) except json.JSONDecodeError as e: errors.append( f"Error decoding 'postdata' in error file '{args.error}'. " f"Content: {json_obj['request']['postdata']}. Error: {e}" ) except FileNotFoundError as e: errors.append(f"File not found: {args.error}. Please check the file path.") except ValueError as e: errors.append(str(e)) # Load the response file into memory try: with open(args.response, "r") as response_f: response_data = parse_json_lines_to_memory(response_f, args.response) for json_obj in response_data: try: msgnum = json_obj['message']['msgnum'] code = json_obj['response']['code'] body = json_obj['response']['body'] batch_index = json_obj['response']['batch_index'] if msgnum not in messages: errors.append( f"Message {msgnum} in response file '{args.response}' " f"does not exist in the error file '{args.error}'." ) continue if messages[msgnum]['response']['status'] != code: errors.append( f"Status code mismatch for message {msgnum}:\n" f" Expected: {messages[msgnum]['response']['status']}\n" f" Found: {code}\n" f" Context: {json_obj}" ) if messages[msgnum]['response']['message'] != body: errors.append( f"Message body mismatch for message {msgnum}:\n" f" Expected: {messages[msgnum]['response']['message']}\n" f" Found: {body}\n" f" Context: {json_obj}" ) if messages[msgnum]['index'] != batch_index: errors.append( f"Batch index mismatch for message {msgnum}:\n" f" Expected: {messages[msgnum]['index']}\n" f" Found: {batch_index}\n" f" Context: {json_obj}" ) except KeyError as e: errors.append( f"Missing key {e} in response file '{args.response}'. " f"Problematic JSON object: {json_obj}" ) except FileNotFoundError as e: errors.append(f"File not found: {args.response}. Please check the file path.") except ValueError as e: errors.append(str(e)) # Report errors, limited by --max-errors if errors: shown_errors = min(len(errors), args.max_errors) print(f"Validation completed with {len(errors)} errors. " f"Showing the first {shown_errors} errors:\n") for error in errors[:args.max_errors]: print(f"- {error}") # Exit with non-zero code to indicate errors sys.exit(1) else: print("Validation completed successfully. No errors found.") # Exit with zero code to indicate success sys.exit(0) rsyslog-8.2608.0/tests/PaxHeaders/imbeats-compressed-malformed.sh0000644000000000000000000000013215241075234021772 xustar0030 mtime=1787067036.620578575 30 atime=1787067036.768581346 30 ctime=1787067806.479950248 rsyslog-8.2608.0/tests/imbeats-compressed-malformed.sh0000775000175000017500000000532015241075234021441 0ustar00rgerrger#!/bin/bash # Verify malformed compressed input is rejected without an ACK and is counted # by the imbeats failure statistics. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' module(load="../plugins/impstats/.libs/impstats" interval="1" log.file="'$RSYSLOG_DYNNAME'.spool/imbeats-stats.log" log.syslog="off" format="cee") module(load="../plugins/imbeats/.libs/imbeats") template(name="outfmt" type="string" string="%msg%\n") ruleset(name="main") { action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } input(type="imbeats" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.imbeats.port" ruleset="main") ' startup assign_rs_port "$RSYSLOG_DYNNAME.imbeats.port" $PYTHON - "$RS_PORT" > "$RSYSLOG_DYNNAME.imbeats.ack" <<'PY' import json import socket import struct import sys import zlib port = int(sys.argv[1]) def frame(seq, message): payload = json.dumps({"message": message}, separators=(",", ":")).encode() return b"2J" + struct.pack(">I", seq) + struct.pack(">I", len(payload)) + payload def send_bad(compressed): wire = b"2W" + struct.pack(">I", 1) + b"2C" + struct.pack(">I", len(compressed)) + compressed with socket.create_connection(("127.0.0.1", port), timeout=5) as sock: sock.settimeout(5) sock.sendall(wire) try: data = sock.recv(6) except (ConnectionResetError, TimeoutError, socket.timeout): data = b"" if data: raise SystemExit(f"unexpected ack for malformed compressed frame: {data.hex()}") send_bad(b"not-a-zlib-stream") send_bad(zlib.compress(frame(1, "ok")) + b"trailing-garbage") nested = b"2C" + struct.pack(">I", len(zlib.compress(frame(1, "nested")))) + zlib.compress(frame(1, "nested")) send_bad(zlib.compress(nested)) send_bad(zlib.compress(b"")) zero = b"2J" + struct.pack(">I", 1) + struct.pack(">I", 0) send_bad(zlib.compress(zero)) PY rst_msleep 1500 shutdown_when_empty wait_shutdown test ! -s "$RSYSLOG_OUT_LOG" test ! -s "$RSYSLOG_DYNNAME.imbeats.ack" if ! $PYTHON - "$RSYSLOG_DYNNAME.spool/imbeats-stats.log" <<'PY' import json import sys stats = {} with open(sys.argv[1], encoding="utf-8") as fh: for line in fh: if "@cee: " not in line: continue line = line.split("@cee: ", 1)[1] data = json.loads(line) if data.get("name") == "imbeats": stats = data expected = { "compressed_frames": 5, "compressed.rejected": 5, "protocol_errors": 5, "events.submitted": 0, } missing = {key: (stats.get(key), value) for key, value in expected.items() if stats.get(key) != value} if missing: raise SystemExit(f"unexpected imbeats stats: {missing}; last stats={stats}") PY then error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfwd-tls-ossl-pkcs11-cert-mtls-ecdsa-sigalgs-vg.sh0000644000000000000000000000013015241075234025256 xustar0028 mtime=1787067036.6325788 30 atime=1787067036.688579848 30 ctime=1787067807.545970112 rsyslog-8.2608.0/tests/omfwd-tls-ossl-pkcs11-cert-mtls-ecdsa-sigalgs-vg.sh0000775000175000017500000000014615241075234024730 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/omfwd-tls-ossl-pkcs11-cert-mtls-ecdsa-sigalgs.sh rsyslog-8.2608.0/tests/PaxHeaders/imtcp-msg-truncation-on-number2.sh0000644000000000000000000000013215241075234022306 xustar0030 mtime=1787067036.623578631 30 atime=1787067036.771581402 30 ctime=1787067805.506932116 rsyslog-8.2608.0/tests/imtcp-msg-truncation-on-number2.sh0000775000175000017500000000323315241075234021756 0ustar00rgerrger#!/bin/bash # addd 2016-05-13 by RGerhards, released under ASL 2.0 . ${srcdir:=.}/diag.sh init generate_conf add_conf ' $MaxMessageSize 128 global(processInternalMessages="on") module(load="../plugins/imtcp/.libs/imtcp") input(type="imtcp" address="127.0.0.1" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port" ruleset="ruleset1") template(name="templ1" type="string" string="%rawmsg%\n") ruleset(name="ruleset1") { action(type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="templ1") } ' startup tcpflood -m2 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"214000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"41 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"2000000010 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"4000000000 <120> 2011-03-01T11:22:12Z host msgnum:1\"" tcpflood -m1 -M "\"0 <120> 2011-03-01T11:22:12Z host msgnum:1\"" shutdown_when_empty wait_shutdown echo '<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 214000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 214000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1 2000000010<120> 2011-03-01T11:22:12Z host msgnum:1 4000000000<120> 2011-03-01T11:22:12Z host msgnum:1 <120> 2011-03-01T11:22:12Z host msgnum:1' | cmp - $RSYSLOG_OUT_LOG if [ ! $? -eq 0 ]; then echo "invalid response generated, $RSYSLOG_OUT_LOG is:" cat $RSYSLOG_OUT_LOG error_exit 1 fi; exit_test rsyslog-8.2608.0/tests/PaxHeaders/es-bulk-errfile-popul-def-interleaved.sh0000644000000000000000000000013215216464436023431 xustar0030 mtime=1782212894.051266588 30 atime=1782715518.923791135 30 ctime=1787067803.957903252 rsyslog-8.2608.0/tests/es-bulk-errfile-popul-def-interleaved.sh0000775000175000017500000000262715216464436023107 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init require_plugin imfile ensure_elasticsearch_ready init_elasticsearch echo '{ "name" : "foo" } {"name": bar"} {"name": "baz"} {"name": foz"}' > $RSYSLOG_DYNNAME.inESData.inputfile generate_conf add_conf ' global(workDirectory="'$RSYSLOG_DYNNAME.spool'") # Note: we must mess up with the template, because we can not # instruct ES to put further constraints on the data type and # values. So we require integer and make sure it is none. template(name="tpl" type="list") { constant(value="{\"") property(name="$!key") constant(value="\":") property(name="$!obj") constant(value="}") } module(load="../plugins/omelasticsearch/.libs/omelasticsearch") module(load="../plugins/imfile/.libs/imfile") ruleset(name="foo") { set $!key = "my_obj"; set $!obj = $msg; action(type="omelasticsearch" template="tpl" searchIndex="rsyslog_testbench" serverport="19200" bulkmode="on" errorFile="./'${RSYSLOG_DYNNAME}'.errorfile" interleaved="on") } input(type="imfile" File="'$RSYSLOG_DYNNAME.'inESData.inputfile" Tag="foo" Severity="info" ruleset="foo") ' startup shutdown_when_empty wait_shutdown $PYTHON $srcdir/elasticsearch-error-format-check.py interleaved ret=$? if [ "$ret" -ne 0 ] then echo "error: Format for error file different! " "$ret" exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/imfile-readmode2-with-persists-data-during-stop.sh0000644000000000000000000000013215035412264025347 xustar0030 mtime=1752569012.392806336 30 atime=1782715518.923791135 30 ctime=1787067807.901976746 rsyslog-8.2608.0/tests/imfile-readmode2-with-persists-data-during-stop.sh0000777000175000017500000000474215035412264025027 0ustar00rgerrger#!/bin/bash # This is part of the rsyslog testbench, licensed under ASL 2.0 . $srcdir/diag.sh check-inotify . ${srcdir:=.}/diag.sh init generate_conf add_conf ' global(workDirectory="'${RSYSLOG_DYNNAME}'.spool") module(load="../plugins/imfile/.libs/imfile") input(type="imfile" File="./'$RSYSLOG_DYNNAME'.input" Tag="file:" ReadMode="2") template(name="outfmt" type="list") { constant(value="HEADER ") property(name="msg" format="json") constant(value="\n") } if $msg contains "msgnum:" then action( type="omfile" file=`echo $RSYSLOG_OUT_LOG` template="outfmt" ) ' startup # write the beginning of the file echo 'msgnum:0 msgnum:1' > $RSYSLOG_DYNNAME.input echo 'msgnum:2' >> $RSYSLOG_DYNNAME.input # sleep a little to give rsyslog a chance to begin processing sleep 1 # now stop and restart rsyslog so that the file info must be # persisted and read again on startup. Results should still be # correct ;) echo stopping rsyslog shutdown_when_empty wait_shutdown # write some more lines - we want to check here if the initial # polling loop properly picks up that data. Note that even in # inotify case we do have one polling loop at startup, as this # is required to find data written while we were stopped. ls -l ${RSYSLOG_DYNNAME}.spool echo 'msgnum:3 msgnum:4' >> $RSYSLOG_DYNNAME.input echo restarting rsyslog startup echo restarted rsyslog, continuing with test echo ' msgnum:5' >> $RSYSLOG_DYNNAME.input echo 'msgnum:6 msgnum:7 msgnum:8' >> $RSYSLOG_DYNNAME.input #msgnum:8 must NOT be written as it is unfinished # give it time to finish sleep 1 shutdown_when_empty # shut down rsyslogd when done processing messages wait_shutdown # we need to wait until rsyslogd is finished! # give it time to write the output file sleep 1 ## check if we have the correct number of messages NUMLINES=$(grep -c HEADER $RSYSLOG_OUT_LOG 2>/dev/null) if [ -z $NUMLINES ]; then echo "ERROR: expecting at least a match for HEADER, maybe $RSYSLOG_OUT_LOG wasn't even written?" cat $RSYSLOG_OUT_LOG error_exit 1 else if [ ! $NUMLINES -eq 4 ]; then echo "ERROR: expecting 4 headers, got $NUMLINES" cat $RSYSLOG_OUT_LOG error_exit 1 fi fi ## check if all the data we expect to get in the file is there for i in {1..7}; do grep msgnum:$i $RSYSLOG_OUT_LOG > /dev/null 2>&1 if [ ! $? -eq 0 ]; then echo "ERROR: expecting the string 'msgnum:$i', it's not there" cat $RSYSLOG_OUT_LOG error_exit 1 fi done ## if we got here, all is good :) exit_test rsyslog-8.2608.0/tests/PaxHeaders/rscript_ge_var.sh0000644000000000000000000000013215171402221017241 xustar0030 mtime=1776682129.620271151 30 atime=1782715518.922791118 30 ctime=1787067804.811919166 rsyslog-8.2608.0/tests/rscript_ge_var.sh0000775000175000017500000000333415171402221016713 0ustar00rgerrger#!/bin/bash # added 2014-01-17 by rgerhards # This file is part of the rsyslog project, released under ASL 2.0 echo =============================================================================== echo \[rscript_ge.sh\]: testing rainerscript GE statement for two JSON variables . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } set $!var1 = "42"; set $!var2 = "42"; set $!var3 = "41"; if $!var1 >= $!var2 and $!var1 >= $!var3 then { if $!var3 >= $!var1 then { # Failure stop } else { unset $!var1; unset $!var2; unset $!var3; } } else { # Failure stop } set $.var1 = "42"; set $.var2 = "42"; set $.var3 = "41"; if $.var1 >= $.var2 and $.var1 >= $.var3 then { if $.var3 >= $.var1 then { # Failure stop } else { unset $.var1; unset $.var2; unset $.var3; } } else { # Failure stop } set $/var1 = "42"; set $/var2 = "42"; set $/var3 = "41"; if $/var1 >= $/var2 and $/var1 >= $/var3 then { if $/var3 >= $/var1 then { # Failure stop } else { unset $/var1; unset $/var2; unset $/var3; } } else { # Failure stop } if $msg contains "msgnum" then { set $!usr!msgnum = field($msg, 58, 2); action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt") } ' startup injectmsg 0 1 echo doing shutdown shutdown_when_empty echo wait on shutdown wait_shutdown seq_check 0 0 exit_test rsyslog-8.2608.0/tests/PaxHeaders/omprog-single-instance.sh0000644000000000000000000000013215131231047020616 xustar0030 mtime=1768239655.716212778 30 atime=1782715518.922791118 30 ctime=1787067806.069942608 rsyslog-8.2608.0/tests/omprog-single-instance.sh0000777000175000017500000000364015131231047020272 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 # This test tests the omprog 'forceSingleInstance' flag by checking # that only one instance of the program is started when multiple # workers are in effect. . ${srcdir:=.}/diag.sh init skip_platform "SunOS" "This test currently does not work on Solaris " export NUMMESSAGES=10000 # number of logs to send export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines generate_conf add_conf ' module(load="../plugins/omprog/.libs/omprog") template(name="outfmt" type="string" string="%msg%\n") :msg, contains, "msgnum:" { action( type="omprog" binary="'$srcdir'/testsuites/omprog-single-instance-bin.sh" template="outfmt" name="omprog_action" confirmMessages="on" forceSingleInstance="on" queue.type="LinkedList" # use a dedicated queue queue.workerThreads="10" # ...with multiple workers queue.size="5000" # ...high capacity (default is 1000) queue.timeoutShutdown="30000" # ...and a long shutdown timeout ) } ' startup injectmsg shutdown_when_empty wait_shutdown EXPECTED_LINE_LENGTH=25 # example line: 'Received msgnum:00009880:' line_num=0 while IFS= read -r line; do ((line_num++)) if (( line_num == 1 )); then if [[ "$line" != "Starting" ]]; then echo "unexpected first line in output: $line" error_exit 1 fi elif (( line_num == NUMMESSAGES + 2 )); then if [[ "$line" != "Terminating" ]]; then echo "unexpected last line in output: $line" error_exit 1 fi elif [[ ${#line} != $EXPECTED_LINE_LENGTH ]]; then echo "unexpected line in output (line $line_num): $line" error_exit 1 fi done < $RSYSLOG_OUT_LOG if (( line_num != NUMMESSAGES + 2 )); then echo "unexpected line count in output: $line_num (expected: $((NUMMESSAGES + 2)))" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/segmented-diskqueue-event-properties.sh0000644000000000000000000000013215241075234023521 xustar0030 mtime=1787067036.643579006 30 atime=1787067036.693579942 30 ctime=1787067803.722898873 rsyslog-8.2608.0/tests/segmented-diskqueue-event-properties.sh0000775000175000017500000001213115241075234023166 0ustar00rgerrger#!/bin/bash # Verify segmentedDisk persists the complete event representation used by the # legacy MsgSerialize()/MsgDeserialize() path, plus receive port, post-PRI raw # message state, parse status, message JSON ($!), and local variables ($.). # Each event is rendered before enqueue and again after action-queue recovery; # exact file equality is the oracle, so type, value, ordering, or field loss is # detected without depending on timing. A deliberately missing omfile parent # directory keeps the action suspended until the first daemon is killed. # This file is part of the rsyslog project, released under ASL 2.0. . ${srcdir:=.}/diag.sh init export NUMMESSAGES=100 SPOOL_DIR="$PWD/${RSYSLOG_DYNNAME}.spool" REFERENCE_FILE="$PWD/${RSYSLOG_DYNNAME}.reference.log" RECOVERED_FILE="$PWD/${RSYSLOG_DYNNAME}.recovered.log" BLOCKED_FILE="$PWD/${RSYSLOG_DYNNAME}.missing/output.log" if [ "${SEGDISK_EVENT_DA:-0}" = 1 ]; then SEGDISK_DA_QUEUE_TYPE=${SEGDISK_DA_QUEUE_TYPE:-LinkedList} QUEUE_CONFIG='queue.type="'"$SEGDISK_DA_QUEUE_TYPE"'" queue.filename="eventq" queue.diskQueueType="segmentedDisk" queue.size="20" queue.highWatermark="5" queue.lowWatermark="2"' else QUEUE_CONFIG='queue.type="segmentedDisk" queue.filename="eventq"' fi write_conf() { generate_conf add_conf ' global(workDirectory="'"$SPOOL_DIR"'") template(name="eventSnapshot" type="list") { constant(value="{") property(format="jsonf" name="msg" field.number="2" field.delimiter="58" outname="sequence") constant(value=",") property(format="jsonf" name="protocol-version" outname="protocol_version") constant(value=",") property(format="jsonf" name="syslogseverity" outname="severity") constant(value=",") property(format="jsonf" name="syslogfacility" outname="facility") constant(value=",") property(format="jsonf" name="timegenerated" dateformat="unixtimestamp" outname="generated") constant(value=",") property(format="jsonf" name="timegenerated" dateformat="rfc3339" outname="received") constant(value=",") property(format="jsonf" name="timereported" dateformat="rfc3339" outname="timestamp") constant(value=",") property(format="jsonf" name="syslogtag" outname="tag") constant(value=",") property(format="jsonf" name="rawmsg" outname="raw_message") constant(value=",") property(format="jsonf" name="rawmsg-after-pri" outname="raw_after_pri") constant(value=",") property(format="jsonf" name="msg" outname="message") constant(value=",") property(format="jsonf" name="hostname" outname="hostname") constant(value=",") property(format="jsonf" name="inputname" outname="input_name") constant(value=",") property(format="jsonf" name="fromhost" outname="from_host") constant(value=",") property(format="jsonf" name="fromhost-ip" outname="from_host_ip") constant(value=",") property(format="jsonf" name="fromhost-port" outname="from_host_port") constant(value=",") property(format="jsonf" name="structured-data" outname="structured_data") constant(value=",") property(format="jsonf" name="app-name" outname="app_name") constant(value=",") property(format="jsonf" name="procid" outname="procid") constant(value=",") property(format="jsonf" name="msgid" outname="msgid") constant(value=",") property(format="jsonf" name="parsesuccess" outname="parse_success") constant(value=",") property(format="jsonf" name="$!" outname="message_variables") constant(value=",") property(format="jsonf" name="$." outname="local_variables") constant(value="}\n") } set $.parse_result = parse_json( "{\"text\":\"value\",\"integer\":9223372036854775807,\"real\":1.25,\"boolean\":true," & "\"null\":null,\"array\":[\"one\",2,false]}", "\$!event"); set $.parse_result = parse_json( "{\"text\":\"local-value\",\"integer\":7,\"boolean\":false}", "\$.local"); unset $.parse_result; if $msg contains "msgnum:" then { action(type="omfile" file="'"$REFERENCE_FILE"'" template="eventSnapshot") action(type="omfile" file="'"$1"'" template="eventSnapshot" createDirs="off" action.resumeRetryCount="-1" '"$QUEUE_CONFIG"' queue.maxFileSize="4k" queue.dequeueBatchSize="8" queue.saveOnShutdown="on") } ' } write_conf "$BLOCKED_FILE" startup injectmsg 0 "$NUMMESSAGES" wait_file_lines "$REFERENCE_FILE" "$NUMMESSAGES" shutdown_immediate if [ "${SEGDISK_EVENT_DA:-0}" != 1 ]; then . "$srcdir/diag.sh" kill-immediate fi wait_shutdown if [ "$(wc -c < "$SPOOL_DIR/eventq.segq/state")" -ne 512 ]; then echo "FAIL: segmented action queue was not persisted" error_exit 1 fi write_conf "$RECOVERED_FILE" startup wait_file_lines "$RECOVERED_FILE" "$NUMMESSAGES" shutdown_when_empty wait_shutdown if [ "${SEGDISK_EVENT_DA:-0}" = 1 ]; then # The DA shutdown path may append the final in-memory records after records # already spilled to disk. Sorting by the fixed-width leading sequence key # keeps this test focused on lossless full-event persistence, not on shutdown # transfer ordering, which is covered separately by the DA ordering tests. sort "$REFERENCE_FILE" > "${REFERENCE_FILE}.sorted" sort "$RECOVERED_FILE" > "${RECOVERED_FILE}.sorted" cmp_exact_file "${REFERENCE_FILE}.sorted" "${RECOVERED_FILE}.sorted" else cmp_exact_file "$REFERENCE_FILE" "$RECOVERED_FILE" fi rm -rf "${RSYSLOG_DYNNAME}.spool" exit_test rsyslog-8.2608.0/tests/PaxHeaders/omfile-dynafile-template-type-list-default.sh0000644000000000000000000000013115241075234024466 xustar0030 mtime=1787067036.631578781 29 atime=1787067036.68757983 30 ctime=1787067804.184907482 rsyslog-8.2608.0/tests/omfile-dynafile-template-type-list-default.sh0000775000175000017500000000143015241075234024134 0ustar00rgerrger#!/bin/bash # SPDX-License-Identifier: Apache-2.0 # # Copyright 2026 Rainer Gerhards and Adiscon GmbH. # # Ensure normal list dynafile templates are accepted by default. . ${srcdir:=.}/diag.sh init generate_conf add_conf ' template(name="dynfile" type="list") { constant(value="./") property(name="hostname") constant(value="/") property(name="app-name") constant(value=".log") } template(name="outfmt" type="string" string="%msg:F,58:2%\n") if $msg contains "msgnum:" then { action(type="omfile" dynafile="dynfile" template="outfmt") } ' if ! ../tools/rsyslogd -C -N1 -M"$RSYSLOG_MODDIR" -f"${TESTCONF_NM}.conf" \ >"${RSYSLOG_DYNNAME}.log" 2>&1; then echo "FAIL: expected list dynafile template to be accepted by default" cat "${RSYSLOG_DYNNAME}.log" error_exit 1 fi exit_test rsyslog-8.2608.0/tests/PaxHeaders/pgsql-template-vg.sh0000644000000000000000000000013215035412264017610 xustar0030 mtime=1752569012.407702108 30 atime=1782715518.923791135 30 ctime=1787067805.895939365 rsyslog-8.2608.0/tests/pgsql-template-vg.sh0000777000175000017500000000151215035412264017260 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under GPLv3 . ${srcdir:=.}/diag.sh init psql -h localhost -U postgres -f testsuites/pgsql-basic.sql generate_conf add_conf ' # putting the message in the SyslogTag field, so we know the template is actually used $template mytemplate,"insert into SystemEvents (SysLogTag) values ' add_conf "('%msg%')" add_conf '",STDSQL $ModLoad ../plugins/ompgsql/.libs/ompgsql :msg, contains, "msgnum:" :ompgsql:127.0.0.1,syslogtest,postgres,testbench;mytemplate ' startup_vg injectmsg 0 5000 shutdown_when_empty wait_shutdown_vg check_exit_vg psql -h localhost -U postgres -d syslogtest -f testsuites/pgsql-select-syslogtag.sql -t -A > $RSYSLOG_OUT_LOG seq_check 0 4999 echo cleaning up test database psql -h localhost -U postgres -c 'DROP DATABASE IF EXISTS syslogtest;' exit_test rsyslog-8.2608.0/tests/PaxHeaders/clickhouse-load-vg.sh0000644000000000000000000000013015171370365017723 xustar0029 mtime=1776677109.45691331 30 atime=1782715518.923791135 29 ctime=1787067805.81893793 rsyslog-8.2608.0/tests/clickhouse-load-vg.sh0000775000175000017500000000011015171370365017364 0ustar00rgerrger#!/bin/bash export USE_VALGRIND="YES" . ${srcdir:-.}/clickhouse-load.sh rsyslog-8.2608.0/tests/PaxHeaders/es-basic-vgthread.sh0000644000000000000000000000013215132733117017530 xustar0030 mtime=1768666703.955620965 30 atime=1782715518.923791135 30 ctime=1787067803.918902525 rsyslog-8.2608.0/tests/es-basic-vgthread.sh0000777000175000017500000000144315132733117017203 0ustar00rgerrger#!/bin/bash # This file is part of the rsyslog project, released under ASL 2.0 . ${srcdir:=.}/diag.sh init export ES_PORT=19200 export NUMMESSAGES=5000 # test is pretty slow, so use a low number export QUEUE_EMPTY_CHECK_FUNC=es_shutdown_empty_check ensure_elasticsearch_ready init_elasticsearch generate_conf add_conf ' template(name="tpl" type="string" string="{\"msgnum\":\"%msg:F,58:2%\"}") module(load="../plugins/omelasticsearch/.libs/omelasticsearch") if $msg contains "msgnum:" then { action(type="omelasticsearch" server="127.0.0.1" serverport=`echo $ES_PORT` template="tpl" searchIndex="rsyslog_testbench") } ' startup_vgthread injectmsg shutdown_when_empty wait_shutdown_vg check_exit_vg es_getdata seq_check exit_test rsyslog-8.2608.0/tests/PaxHeaders/elasticsearch-error-format-check.py0000644000000000000000000000013215216464436022570 xustar0030 mtime=1782212894.049266556 30 atime=1782715518.923791135 30 ctime=1787067808.438986753 rsyslog-8.2608.0/tests/elasticsearch-error-format-check.py0000664000175000017500000001043715216464436022241 0ustar00rgerrgerimport json import sys import os def checkDefaultErrorFile(): with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file: json_data = json.load(json_file) indexCount = 0 replyCount = 0 for item in json_data: if item == "request": for reqItem in json_data[item]: if reqItem == "url": print("url found") print(reqItem) elif reqItem == "postdata": print("postdata found") indexCount = str(json_data[item]).count('\"_index\":') print(reqItem) else: print(reqItem) print("Unknown item found") sys.exit(1) elif item == "reply": for replyItem in json_data[item]: if replyItem == "items": print(json_data[item][replyItem]) replyCount = str(json_data[item][replyItem]).count('_index') elif replyItem == "errors": print("error node found") elif replyItem == "took": print("took node found") else: print(replyItem) print("Unknown item found") sys.exit(3) else: print(item) print("Unknown item found") print("error") sys.exit(4) if replyCount == indexCount: return 0 else: sys.exit(7) return 0 def checkErrorOnlyFile(): with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file: json_data = json.load(json_file) indexCount = 0 replyCount = 0 for item in json_data: if item == "request": print(json_data[item]) indexCount = str(json_data[item]).count('\"_index\":') elif item == "url": print("url found") elif item == "reply": print(json_data[item]) replyCount = str(json_data[item]).count('\"_index\":') else: print(item) print("Unknown item found") print("error") sys.exit(4) if replyCount == indexCount: return 0 else: sys.exit(7) return 0 def checkErrorInterleaved(): with open(os.environ['RSYSLOG_DYNNAME'] + ".errorfile") as json_file: json_data = json.load(json_file) indexCount = 0 replyCount = 0 for item in json_data: print(item) if item == "response": for responseItem in json_data[item]: print(responseItem) for res in responseItem: print(res) if res == "request": print(responseItem[res]) indexCount = str(responseItem[res]).count('\"_index\":') print("request count ", indexCount) elif res == "reply": print(responseItem[res]) replyCount = str(responseItem[res]).count('\"_index\":') print("reply count ", replyCount) else: print(res) print("Unknown item found") sys.exit(9) if replyCount != indexCount: sys.exit(8) elif item == "url": print("url found") else: print(item) print("Unknown item found") sys.exit(4) return 0 def checkInterleaved(): return checkErrorInterleaved() if __name__ == "__main__": option = sys.argv[1] if option == "default": checkDefaultErrorFile() elif option == "erroronly": checkErrorOnlyFile() elif option == "errorinterleaved": checkErrorInterleaved() elif option == "interleaved": checkErrorInterleaved() else: print("Usage: \n?', '', content ) # 2. Remove type="module" from Mermaid UMD script (monkey-patched build) content = re.sub( r'\n )(?!\s*\n\s*', content, count=1 ) # Only write if content changed if content != original_content: with open(html_file, 'w', encoding='utf-8') as f: f.write(content) fixed_count += 1 print(f"Fixed: {html_file.relative_to(html_path)}") except Exception as e: print(f"Error processing {html_file}: {e}") print(f"\nFixed {fixed_count} HTML files for offline Mermaid viewing") print("Note: ELK layout functionality is not available in offline mode") return True def main(): if len(sys.argv) != 2: print("Usage: python3 doc/tools/fix-mermaid-offline.py ") print("Example: python3 doc/tools/fix-mermaid-offline.py doc/build") sys.exit(1) html_dir = sys.argv[1] if fix_mermaid_offline(html_dir): print("\n✅ Mermaid offline fix completed successfully!") print("You can now open HTML files directly in your browser without CORS issues.") else: print("\n� Mermaid offline fix failed!") sys.exit(1) if __name__ == "__main__": main() rsyslog-8.2608.0/doc/tools/PaxHeaders/test_validate_doc_samples.py0000644000000000000000000000013115241075234022221 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.67957968 30 ctime=1787067793.924716296 rsyslog-8.2608.0/doc/tools/test_validate_doc_samples.py0000775000175000017500000002117515241075234021677 0ustar00rgerrger#!/usr/bin/env python3 """Unit tests for validate-doc-samples.py.""" import importlib.util import os import subprocess import tempfile import textwrap import unittest from pathlib import Path SCRIPT = Path(__file__).with_name("validate-doc-samples.py") def load_validator(): spec = importlib.util.spec_from_file_location("validate_doc_samples", SCRIPT) module = importlib.util.module_from_spec(spec) assert spec.loader is not None spec.loader.exec_module(module) return module class ValidateDocSamplesTest(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.root = Path(self.tmp.name) self.source = self.root / "doc" / "source" self.source.mkdir(parents=True) self.build = self.root / "build" (self.build / "tools").mkdir(parents=True) (self.build / "runtime" / ".libs").mkdir(parents=True) (self.build / ".libs").mkdir(parents=True) self.rsyslogd = self.build / "tools" / "rsyslogd" self.rsyslogd.write_text( "#!/bin/sh\n" "config=\n" "for arg in \"$@\"; do\n" " case \"$arg\" in -f*) config=${arg#-f};; esac\n" "done\n" "if [ -n \"$config\" ] && grep -q hang \"$config\"; then sleep 5; fi\n" "if [ -n \"$config\" ] && grep -q invalid \"$config\"; then exit 1; fi\n" "if [ -n \"$config\" ] && grep -q 'module(load=\"ommissing\")' \"$config\"; then exit 1; fi\n" "if [ -n \"$config\" ] && grep -q 'module(load=\"omhanging\")' \"$config\"; then sleep 5; fi\n" "exit 0\n", encoding="utf-8", ) self.rsyslogd.chmod(0o755) def tearDown(self): self.tmp.cleanup() def write_rst(self, content): path = self.source / "sample.rst" path.write_text(textwrap.dedent(content), encoding="utf-8") return path def run_validator(self, *extra_args): return subprocess.run( [ "python3", str(SCRIPT), "--source-dir", str(self.source), "--build-dir", str(self.build), "--work-dir", str(self.root / "work"), *extra_args, ], text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False, ) def test_discovers_marked_rsyslog_block(self): self.write_rst( """ Title ===== .. rsyslog-doc-sample: validate-config .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) validator = load_validator() samples = validator.discover_samples(self.source) self.assertEqual(len(samples), 1) self.assertIn('property(name="msg")', samples[0].code) def test_discovers_nested_marked_rsyslog_block(self): self.write_rst( """ * List entry: .. rsyslog-doc-sample: validate-config .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) validator = load_validator() samples = validator.discover_samples(self.source) self.assertEqual(len(samples), 1) self.assertTrue(samples[0].code.startswith('template(name="example"')) self.assertIn(' property(name="msg")', samples[0].code) def test_ignores_unmarked_blocks(self): self.write_rst( """ .. code-block:: rsyslog invalid """ ) result = self.run_validator() self.assertNotEqual(result.returncode, 0) self.assertIn("No marked rsyslog documentation samples found", result.stderr) def test_required_plugin_skip(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config :require-plugin: ommissing .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) result = self.run_validator() self.assertEqual(result.returncode, 0) self.assertIn("1 skipped", result.stdout) def test_required_plugin_accepts_contrib_module(self): contrib_module = self.build / "contrib" / "omexample" / ".libs" contrib_module.mkdir(parents=True) (contrib_module / "omexample.so").write_text("", encoding="utf-8") self.write_rst( """ .. rsyslog-doc-sample: validate-config :require-plugin: omexample .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) result = self.run_validator() self.assertEqual(result.returncode, 0) self.assertIn("1 passed", result.stdout) def test_required_plugin_accepts_builtin_module(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config :require-plugin: ombuiltin .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) result = self.run_validator() self.assertEqual(result.returncode, 0) self.assertIn("1 passed", result.stdout) def test_required_plugin_timeout_is_skipped(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config :require-plugin: omhanging .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) result = self.run_validator("--timeout", "0.1") self.assertEqual(result.returncode, 0) self.assertIn("1 skipped", result.stdout) def test_validation_failure_is_reported(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config .. code-block:: rsyslog invalid """ ) result = self.run_validator() self.assertNotEqual(result.returncode, 0) self.assertIn("FAIL sample.rst", result.stderr) def test_validation_timeout_is_reported(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config .. code-block:: rsyslog hang """ ) result = self.run_validator("--timeout", "0.1") self.assertNotEqual(result.returncode, 0) self.assertIn("timed out", result.stderr) log = next((self.root / "work").glob("*.log")).read_text(encoding="utf-8") self.assertIn("timed out", log) def test_prepend_and_append_are_written(self): self.write_rst( """ .. rsyslog-doc-sample: validate-config :prepend: global(workDirectory="/tmp") :append: action(type="omfile" file="/dev/null") .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } """ ) result = self.run_validator() self.assertEqual(result.returncode, 0) config = next((self.root / "work").glob("*.conf")).read_text(encoding="utf-8") self.assertIn('global(workDirectory="/tmp")', config) self.assertIn('action(type="omfile" file="/dev/null")', config) def test_module_search_path_includes_plugin_and_contrib_libs(self): plugin_lib = self.build / "plugins" / "imtcp" / ".libs" contrib_lib = self.build / "contrib" / "fmhash" / ".libs" plugin_lib.mkdir(parents=True) contrib_lib.mkdir(parents=True) validator = load_validator() search_path = validator.module_search_path(self.build).split(os.pathsep) self.assertIn(str(self.build / "runtime" / ".libs"), search_path) self.assertIn(str(plugin_lib), search_path) self.assertIn(str(contrib_lib), search_path) def test_rsyslogd_command_omits_empty_module_path(self): empty_build = self.root / "empty-build" cfg = self.root / "sample.conf" cfg.write_text("", encoding="utf-8") validator = load_validator() cmd = validator.rsyslogd_check_command(self.rsyslogd, empty_build, cfg) self.assertNotIn("-M", cmd) self.assertEqual(cmd[-1], f"-f{cfg}") if __name__ == "__main__": unittest.main() rsyslog-8.2608.0/doc/tools/PaxHeaders/README.md0000644000000000000000000000013215171370365015733 xustar0030 mtime=1776677109.301910921 30 atime=1782715518.825789469 30 ctime=1787067793.890715663 rsyslog-8.2608.0/doc/tools/README.md0000664000175000017500000000064415171370365015403 0ustar00rgerrgerThis directory contains tools primarily of use for maintainers or people who want to build the doc (on a schedule). Useful checks: - `./doc/tools/check-html-links.py` Deterministically checks generated HTML in `doc/build` for invalid local links. Returns non-zero on failures. Optional flags: - `--check-anchors` to validate `#fragment` targets. - `--check-root-absolute` to validate links beginning with `/`. rsyslog-8.2608.0/doc/tools/PaxHeaders/buildenv0000644000000000000000000000013115241076621016202 xustar0030 mtime=1787067793.905715942 29 atime=1787067808.80699361 30 ctime=1787067793.905715942 rsyslog-8.2608.0/doc/tools/buildenv/0000775000175000017500000000000015241076621015724 5ustar00rgerrgerrsyslog-8.2608.0/doc/tools/buildenv/PaxHeaders/tools0000644000000000000000000000013115241076621017342 xustar0030 mtime=1787067793.919716203 29 atime=1787067808.80699361 30 ctime=1787067793.919716203 rsyslog-8.2608.0/doc/tools/buildenv/tools/0000775000175000017500000000000015241076621017064 5ustar00rgerrgerrsyslog-8.2608.0/doc/tools/buildenv/tools/PaxHeaders/git-clone0000644000000000000000000000013115171370365021227 xustar0030 mtime=1776677109.301910921 30 atime=1782715518.825789469 29 ctime=1787067793.91471611 rsyslog-8.2608.0/doc/tools/buildenv/tools/git-clone0000664000175000017500000000057715171370365020705 0ustar00rgerrgerif [ ! -e /rsyslog-doc ]; then echo "ERROR: /rsyslog-doc is either not mounted or does not point to correct path" . tools/help exit 1 fi if [ -e /rsyslog-doc/source ]; then echo "ERROR: /rsyslog-doc contains a source directory, so we cannot clone into it" . tools/help exit 1 fi cd / git clone https://github.com/rsyslog/rsyslog-doc.git (cd /rsyslog-doc; git checkout $BRANCH) rsyslog-8.2608.0/doc/tools/buildenv/tools/PaxHeaders/help0000644000000000000000000000013215132411300020255 xustar0030 mtime=1768559296.228885039 30 atime=1782715518.824789452 30 ctime=1787067793.917716166 rsyslog-8.2608.0/doc/tools/buildenv/tools/help0000666000175000017500000000312615132411300017725 0ustar00rgerrgerecho 'docker run -v /your/local/path:/rsyslog-doc command where command is one of: build-doc - generate documentation (currently HTML only) help - display this help message bash - start an interactive shell (-d terminates) version-info - outputs some information of component used in container git-clone - clone the official rsyslog-doc project into /rsyslog mount this is a quick way to populate /rsyslog, which must be empty before Environment variables (set with -eVAR=val on docker run): FORMAT - html (default) or another builder format STRICT - options to cause strict sphinx mode (default "-n -W") DEBUG - set to "on" to turn on some minimal container debugging SPHINX_EXTRA_OPTS - provides any option to sphinx the user wishes, e.g. -q for quiet builds bind mounts (mount with -v/local/path:/container on docker run): /output - output files will be placed here. If not mounted, output will be under /rsyslog-doc/output /rsyslog-doc - checked-out rsyslog doc project; if not mounted but /output is, an automatic git clone is done to a temporary volume An alternate way to specify extra options is by adding them, one per line, to the SPHINX_EXTRA_OPTS file. The name must be exactly as given, and it must be stored in the doc project home directory. This method is especially useful for complex options which otherwise might be hard to escape so that the shell does not misinterpret them. If both the file SPHINX_EXTRA_OPTS and the environment variable SPHINX_EXTRA_OPTS are given, both are used. ' rsyslog-8.2608.0/doc/tools/buildenv/tools/PaxHeaders/build-doc0000644000000000000000000000013215171370365021211 xustar0030 mtime=1776677109.301910921 30 atime=1782715518.824789452 30 ctime=1787067793.912716073 rsyslog-8.2608.0/doc/tools/buildenv/tools/build-doc0000664000175000017500000000141415171370365020655 0ustar00rgerrgerif [ ! -e /rsyslog-doc/source ]; then if [ -e /output ]; then . tools/git-clone else echo "ERROR: /rsyslog-doc is either not mounted or does not point to correct path" echo " and /output is also not present, so we do not know what to do" . tools/help exit 1 fi fi if [ -e /output ]; then export OUTPUT=/output else export OUTPUT=build fi cd /rsyslog-doc if [ -e SPHINX_EXTRA_OPTS ]; then export SPHINX_EXTRA_OPTS="$SPHINX_EXTRA_OPTS `cat SPHINX_EXTRA_OPTS`" fi eval sphinx-build $STRICT -b $FORMAT $SPHINX_EXTRA_OPTS source $OUTPUT RESULT=$? # we need to do the chown as we currently cannot select the right user # inside the Dockerfile. Once this is solved, this can go away. # chown -R rsyslog:rsyslog $OUTPUT - need to do this differently... exit $RESULT rsyslog-8.2608.0/doc/tools/buildenv/tools/PaxHeaders/version-info0000644000000000000000000000013215132411300021743 xustar0030 mtime=1768559296.228885039 30 atime=1782715518.823789435 30 ctime=1787067793.920716222 rsyslog-8.2608.0/doc/tools/buildenv/tools/version-info0000666000175000017500000000011015132411300021401 0ustar00rgerrgerecho "Versions used inside this container app:" sphinx-build --version rsyslog-8.2608.0/doc/tools/buildenv/tools/PaxHeaders/bash0000644000000000000000000000013215132411300020242 xustar0030 mtime=1768559296.228885039 30 atime=1782715518.823789435 30 ctime=1787067793.909716017 rsyslog-8.2608.0/doc/tools/buildenv/tools/bash0000666000175000017500000000005415132411300017707 0ustar00rgerrgerecho "You are now in Alpine's ash" /bin/ash rsyslog-8.2608.0/doc/tools/buildenv/PaxHeaders/.dockerignore0000644000000000000000000000013215132411300020716 xustar0030 mtime=1768559296.228885039 30 atime=1782317635.985295164 30 ctime=1787067793.898715812 rsyslog-8.2608.0/doc/tools/buildenv/.dockerignore0000666000175000017500000000002415132411300020360 0ustar00rgerrgertmp* *.tmp README.* rsyslog-8.2608.0/doc/tools/buildenv/PaxHeaders/README.md0000644000000000000000000000013215132411300017521 xustar0030 mtime=1768559296.228885039 30 atime=1782715518.821789401 30 ctime=1787067793.903715905 rsyslog-8.2608.0/doc/tools/buildenv/README.md0000666000175000017500000000042315132411300017166 0ustar00rgerrgerbuild: docker build -t rsyslog/rsyslog_doc_gen . where rsyslog/rsyslog_doc_gen is the tag and the location on dockerhub. Obviously, you need to use something else if you are not a maintainer of that repository. ENV VARS DEBUG - turn on some (minimal) container debugging rsyslog-8.2608.0/doc/tools/buildenv/PaxHeaders/Dockerfile0000644000000000000000000000013215132733117020251 xustar0030 mtime=1768666703.927620541 30 atime=1782715518.820789384 30 ctime=1787067793.900715849 rsyslog-8.2608.0/doc/tools/buildenv/Dockerfile0000666000175000017500000000066415132733117017725 0ustar00rgerrgerFROM alpine LABEL maintainer rgerhards@adiscon.com RUN apk add --no-cache py-pip git RUN pip install sphinx RUN adduser -s /bin/ash -D rsyslog rsyslog \ && echo "rsyslog ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers WORKDIR /home/appliance CMD ["build-doc"] ENTRYPOINT ["/home/appliance/starter.sh"] VOLUME /rsyslog-doc RUN chmod a+w /rsyslog-doc ENV BRANCH="main" \ FORMAT="html" \ STRICT="-n -W" COPY starter.sh ./ COPY tools/* ./tools/ rsyslog-8.2608.0/doc/tools/buildenv/PaxHeaders/starter.sh0000644000000000000000000000013215216464435020306 xustar0030 mtime=1782212893.990265602 30 atime=1782715518.820789384 30 ctime=1787067793.907715979 rsyslog-8.2608.0/doc/tools/buildenv/starter.sh0000775000175000017500000000033015216464435017751 0ustar00rgerrger#!/bin/ash if [ "$DEBUG" = "on" ]; then echo "container in debug mode, environment is: " env set -x fi if [ -f tools/$1 ]; then . tools/$1 else echo "ERROR: command not known: $*" echo . tools/help exit 1 fi rsyslog-8.2608.0/doc/tools/PaxHeaders/pages-robots.txt0000644000000000000000000000013215171370365017622 xustar0030 mtime=1776677109.302910936 30 atime=1782715518.819789367 30 ctime=1787067793.934716483 rsyslog-8.2608.0/doc/tools/pages-robots.txt0000664000175000017500000000017115171370365017265 0ustar00rgerrgerUser-agent: * Allow: /doc/ Disallow: / # Sitemap URL is injected by the doc_deploy_main workflow from github.repository rsyslog-8.2608.0/doc/tools/PaxHeaders/inside_docker_doc_html.sh0000644000000000000000000000013115171370365021462 xustar0030 mtime=1776677109.302910936 29 atime=1782715518.81878935 30 ctime=1787067793.929716389 rsyslog-8.2608.0/doc/tools/inside_docker_doc_html.sh0000775000175000017500000000160515171370365021134 0ustar00rgerrger#!/bin/bash # Build rsyslog documentation inside the rsyslog/rsyslog_dev_doc_base_ubuntu container. # Expects GOOGLE_ANALYTICS_ID in env when GA tracking is desired. # Run with: docker run -e GOOGLE_ANALYTICS_ID -v "$(pwd)":/rsyslog --entrypoint /rsyslog/doc/tools/inside_docker_doc_html.sh rsyslog/rsyslog_dev_doc_base_ubuntu:22.04 set -euo pipefail cd /rsyslog/doc # Use pre-built venv from image (prepared in Dockerfile; needed when running as -u uid:gid) VENV=/opt/rsyslog-doc-venv # Use env vars for version/release_type (conf.py reads RSYSLOG_DOC_* when .git not in container) export RSYSLOG_DOC_VERSION="${RSYSLOG_DOC_VERSION:-8}" export RSYSLOG_DOC_RELEASE_TYPE="${RSYSLOG_DOC_RELEASE_TYPE:-stable}" rm -rf build nice "$VENV/bin/sphinx-build" -j"$(nproc)" -t with_sitemap -b html -D html_theme=furo \ -W --keep-going source build "$VENV/bin/python3" tools/fix-mermaid-offline.py build rsyslog-8.2608.0/doc/PaxHeaders/requirements.txt0000644000000000000000000000013215171370365016600 xustar0030 mtime=1776677109.105907899 30 atime=1782715518.817789333 30 ctime=1787067790.952660913 rsyslog-8.2608.0/doc/requirements.txt0000664000175000017500000000023615171370365016245 0ustar00rgerrger # Align with conf.py needs_sphinx requirement sphinx>=4.5.0 furo sphinx_rtd_theme rst2pdf sphinxcontrib.mermaid sphinx-sitemap sphinxcontrib-googleanalytics rsyslog-8.2608.0/doc/PaxHeaders/source0000644000000000000000000000013115241076621014532 xustar0030 mtime=1787067793.765713333 29 atime=1787067808.80699361 30 ctime=1787067793.765713333 rsyslog-8.2608.0/doc/source/0000775000175000017500000000000015241076621014254 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/PaxHeaders/licensing.rst0000644000000000000000000000013115132411300017276 xustar0030 mtime=1768559296.190884438 30 atime=1787067672.114445962 29 ctime=1787067791.78267638 rsyslog-8.2608.0/doc/source/licensing.rst0000666000175000017500000000603615132411300016752 0ustar00rgerrgerLicensing ========= If you intend to use rsyslog inside a GPLv3 compatible project, you are free to do so. You don't even need to continue reading. If you intend to use rsyslog inside a non-GPLv3 compatible project, rsyslog offers you some liberties to do that, too. However, you then need to study the licensing details in depth. The project hopes this is a good compromise, which also gives a boost to fellow free software developers who release under GPLv3. And now on to the dirty and boring license details, still on a executive summary level. For the real details, check source files and the files COPYING and COPYING.LESSER inside the distribution. The rsyslog package contains several components: - the rsyslog core programs (like rsyslogd) - plugins (like imklog, omrelp, ...) - the rsyslog runtime library Each of these components can be thought of as individual projects. In fact, some of the plugins have different main authors than the rest of the rsyslog package. All of these components are currently put together into a single "rsyslog" package (tarball) for convenience: this makes it easier to distribute a consistent version where everything is included (and in the right versions) to build a full system. Platform package maintainers in general take the overall package and split off the individual components, so that users can install only what they need. In source installations, this can be done via the proper ./configure switches. However, while it is convenient to package all parts in a single tarball, it does not imply all of them are necessarily covered by the same license. Traditionally, GPL licenses are used for rsyslog, because the project would like to provide free software. GPLv3 has been used since around 2008 to help fight for our freedom. All rsyslog core programs are released under GPLv3. But, from the beginning on, plugins were separate projects and we did not impose and license restrictions on them. So even though all plugins that currently ship with the rsyslog package are also placed under GPLv3, this can not taken for granted. You need to check each plugins license terms if in question - this is especially important for plugins that do NOT ship as part of the rsyslog tarball. In order to make rsyslog technology available to a broader range of applications, the rsyslog runtime is, at least partly, licensed under LGPL. If in doubt, check the source file licensing comments. As of now, the following files are licensed under LGPL: - queue.c/.h - wti.c/.h - wtp.c/.h - vm.c/.h - vmop.c/.h - vmprg.c/.h - vmstk.c/.h - expr.c/.h - sysvar.c/.h - ctok.c/.h - ctok\_token.c/.h - regexp.c/.h - sync.c/.h - stream.c/.h - var.c/.h This list will change as time of the runtime modularization. At some point in the future, there will be a well-designed set of files inside a runtime library branch and all of these will be LGPL. Some select extras will probably still be covered by GPL. We are following a similar licensing model in GnuTLS, which makes effort to reserve some functionality exclusively to open source projects. rsyslog-8.2608.0/doc/source/PaxHeaders/getting_started0000644000000000000000000000013215241076617017727 xustar0030 mtime=1787067791.725675318 30 atime=1787067808.807993629 30 ctime=1787067791.725675318 rsyslog-8.2608.0/doc/source/getting_started/0000775000175000017500000000000015241076617017450 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/installation.rst0000644000000000000000000000013215132411300023214 xustar0030 mtime=1768559296.188884406 30 atime=1787067672.221447956 30 ctime=1787067791.719675206 rsyslog-8.2608.0/doc/source/getting_started/installation.rst0000666000175000017500000000140715132411300022664 0ustar00rgerrgerInstalling rsyslog ================== rsyslog is included by default in many Linux distributions. If it is not installed, you can add it with the following commands. On Debian/Ubuntu ---------------- .. code-block:: bash sudo apt update sudo apt install rsyslog rsyslog-doc On RHEL/CentOS -------------- .. code-block:: bash sudo dnf install rsyslog rsyslog-doc Enable and Start the Service ---------------------------- After installation, enable and start rsyslog: .. code-block:: bash sudo systemctl enable rsyslog sudo systemctl start rsyslog Validating the Setup -------------------- To verify your installation and configuration, run: .. code-block:: bash rsyslogd -N1 This checks the configuration syntax without starting the daemon. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/ai-assistants.rst0000644000000000000000000000013115132733117023312 xustar0030 mtime=1768666703.901620147 30 atime=1787067671.882441636 29 ctime=1787067791.69467474 rsyslog-8.2608.0/doc/source/getting_started/ai-assistants.rst0000666000175000017500000000447615132733117022774 0ustar00rgerrger.. _ai-assistants: AI Assistants ============= .. meta:: :audience: beginner :tier: entry :keywords: rsyslog AI assistant, chatgpt, configuration help, troubleshooting, documentation, development .. summary-start Specialized AI helpers for rsyslog tasks: configuration, troubleshooting, documentation, and development. .. summary-end As part of rsyslog’s :doc:`../about/ai_first` strategy, we provide several AI assistants to make setup, configuration, and contribution easier. They are currently implemented as **OpenAI ChatGPT custom GPTs**, which means you need a free OpenAI account to use them. Most users will find the free tier sufficient, but availability may depend on your subscription. The platform may change in the future. General-purpose assistant ------------------------- - **Rsyslog Assistant** – the first stop for all usage, configuration, and troubleshooting questions. � https://rsyslog.ai It can generate working config snippets, explain errors, and guide you through common tasks. While accuracy is usually high, always **verify the results**. Like any AI tool, it can occasionally produce mistakes. Other assistants ---------------- These are more specialized, and mainly interesting for contributors: - **Rsyslog Doc Assistant** Helps documentation writers maintain consistent style and structure. � https://www.rsyslog.com/tool_rsyslog-doc-assistant - **Rsyslog Dev Assistant** For developers, focused on onboarding and codebase exploration. Still experimental (as of Sept 2025). � https://www.rsyslog.com/tool_rsyslog-dev-assistant - **Rsyslog Commit Assistant** Guides developers in crafting commit messages that follow rsyslog’s conventions. � https://www.rsyslog.com/tool_rsyslog-commit-assistant Community feedback ------------------ We are continuously improving these assistants. Suggestions and feedback are very welcome in the `GitHub Discussions `_. If you would like to see a new assistant for a specific use case, please let us know there. Video tips ---------- Some tutorials reference short “🎬 video tips�. These will be added over time. If you would like to contribute tutorial videos to the project, please contact **rgerhards@adiscon.com** or post in the GitHub discussions. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/forwarding_logs.rst0000644000000000000000000000013215132411300023701 xustar0030 mtime=1768559296.188884406 30 atime=1787067672.190447378 30 ctime=1787067791.714675113 rsyslog-8.2608.0/doc/source/getting_started/forwarding_logs.rst0000666000175000017500000000433515132411300023354 0ustar00rgerrgerForwarding Logs =============== rsyslog can forward log messages to remote servers. This is often done to centralize logs, improve analysis, or send data to SIEM or monitoring systems. Minimal Forwarding Example (TCP) -------------------------------- Add the following snippet to your `/etc/rsyslog.conf` or to a file inside `/etc/rsyslog.d/`: .. code-block:: rsyslog # Forward all messages to a remote server using TCP. # The linked-list queue prevents blocking if the server is temporarily unreachable. action( type="omfwd" # Output module for forwarding messages protocol="tcp" # Use TCP (reliable transport) target="logs.example.com" # Destination server (replace with your host) port="514" # TCP port on the remote syslog server queue.type="linkedList" # Best practice for network forwarding ) Why use `queue.type="linkedList"`? ---------------------------------- When a remote server goes offline, a direct TCP forwarding action can block and delay local logging. Using a queue ensures that messages are stored temporarily and sent once the connection recovers. This is a recommended default for TCP-based forwarding. Forwarding via UDP ------------------ UDP is a connectionless protocol and does not block, so queues are not required in this case. To forward messages via UDP, modify the protocol: .. code-block:: rsyslog # Forward all messages to a remote server using UDP. action( type="omfwd" protocol="udp" # UDP (unreliable, but lower overhead) target="logs.example.com" port="514" ) Testing the Connection ---------------------- To verify that logs are reaching the remote server: 1. Send a test message locally: .. code-block:: bash logger "test message from $(hostname)" 2. Check the remote server's logs for the test message. Advanced Queue Tuning --------------------- The default queue parameters work for most cases. For high performance or large bursts of logs, you can adjust settings such as: - `queue.size` – Number of messages stored in the queue. - `queue.dequeueBatchSize` – Number of messages processed per batch. See :doc:`../rainerscript/queue_parameters` for details. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/basic_configuration.rst0000644000000000000000000000013115132411300024522 xustar0029 mtime=1768559296.18788439 30 atime=1787067671.900441972 30 ctime=1787067791.697674796 rsyslog-8.2608.0/doc/source/getting_started/basic_configuration.rst0000666000175000017500000000144515132411300024175 0ustar00rgerrgerBasic Configuration =================== rsyslog reads its main configuration from: ``/etc/rsyslog.conf`` Additional configuration snippets can be placed in: ``/etc/rsyslog.d/*.conf`` Minimal Example --------------- The following configuration logs all messages to `/var/log/syslog`: .. code-block:: rsyslog # Load the input modules for system and kernel logging. module(load="imuxsock") # Local system logs (e.g., from journald) module(load="imklog") # Kernel log capture # Traditionally, a *.* selector ("all logs") is added here. # This is unnecessary, as it is the default behavior. # Therefore, no filter is explicitly shown. action(type="omfile" file="/var/log/syslog") Apply changes by restarting rsyslog: .. code-block:: bash sudo systemctl restart rsyslog rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/beginner_tutorials0000644000000000000000000000013215241076617023626 xustar0030 mtime=1787067791.712675075 30 atime=1787067808.807993629 30 ctime=1787067791.712675075 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/0000775000175000017500000000000015241076617023347 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/05-order-matters.rst0000644000000000000000000000013215132733117027441 xustar0030 mtime=1768666703.901620147 30 atime=1787067672.096445626 30 ctime=1787067791.708675001 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/05-order-matters.rst0000666000175000017500000000570215132733117027113 0ustar00rgerrger.. _tut-05-order-matters: Order Matters: Config and Include Files ####################################### .. meta:: :audience: beginner :tier: entry :keywords: rsyslog order, config sequence, rsyslog.d, stop, discard .. summary-start Learn how rsyslog processes configuration **in order**, why file ordering in ``/etc/rsyslog.d/`` matters, and how earlier rules affect later ones. .. summary-end Goal ==== Understand that rsyslog executes rules **sequentially**. The order of actions and included files can change results. Key principle ============= - Rules in the same file run **top to bottom**. - Files in ``/etc/rsyslog.d/`` are processed in **lexical order** (e.g., ``10-first.conf`` runs before ``50-extra.conf``). - An earlier rule can **discard or modify messages**, so later rules may never see them. Hands-on example ================ 1) Create ``/etc/rsyslog.d/10-drop.conf``: .. code-block:: rsyslog if ($programname == "tut05") then { stop # discard these messages, no further actions } 2) Create ``/etc/rsyslog.d/20-log.conf``: .. code-block:: rsyslog if ($programname == "tut05") then { action(type="omfile" file="/var/log/tut05.log") } 3) Restart rsyslog: .. code-block:: bash sudo systemctl restart rsyslog 4) Send a test message: .. code-block:: bash logger -t tut05 "hello from tutorial 05" Expected result --------------- No file ``/var/log/tut05.log`` is created. The first snippet (`10-drop.conf`) discards the message before the logging rule runs. Switch the order ================ Rename the files to reverse order: .. code-block:: bash sudo mv /etc/rsyslog.d/10-drop.conf /etc/rsyslog.d/50-drop.conf sudo systemctl restart rsyslog logger -t tut05 "hello after reorder" Now ``/var/log/tut05.log`` will contain the message, because the logging rule ran first. If it’s not working… ===================== 1. **Still no log file** - Check snippet order with: ``ls -1 /etc/rsyslog.d/`` - Ensure ``20-log.conf`` comes **before** ``50-drop.conf``. 2. **File exists but is empty** - Confirm you used the correct tag: ``logger -t tut05 "…"`` 3. **Syntax errors** - Validate your config: ``sudo rsyslogd -N1`` Verification checkpoint ======================= By the end of this tutorial you should be able to: - Explain that rsyslog rules run **top to bottom, file by file**. - Use file naming (``10-…``, ``50-…``) to control execution order. - Predict why a later action might never see a message. See also / Next steps ===================== - :doc:`04-message-pipeline` – how messages flow through inputs, rulesets, and actions. - :doc:`../basic_configuration` – reference example of a simple config. - :doc:`../forwarding_logs` – adding network forwarding. ---- .. tip:: 🎬 *Video idea (3 min):* show two snippet files, run ``logger -t tut05 …``, then swap the file order and rerun. Visualize how rsyslog processes files in lexical order. rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/02-first-config.rst0000644000000000000000000000013115132733117027237 xustar0030 mtime=1768666703.901620147 30 atime=1787067671.963443147 29 ctime=1787067791.70167487 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/02-first-config.rst0000666000175000017500000000734115132733117026713 0ustar00rgerrger.. _tut-02-first-config: Your First Configuration ######################## .. meta:: :audience: beginner :tier: entry :keywords: rsyslog first config, logger, omfile, rsyslog.d .. summary-start Write a minimal RainerScript configuration that logs a specific test message to its own file, test it with ``logger``, and verify with ``tail -f`` — without changing distro-provided inputs. .. summary-end Goal ==== Create your first custom rsyslog configuration in modern **RainerScript** syntax. You will add a tiny rule that writes **only your test message** into a new file, so you don’t duplicate all system logs. .. important:: Most distributions already configure inputs (on Ubuntu this is often ``imjournal``, sometimes ``imuxsock``). **Do not load input modules here.** We’ll just add a safe, small rule in ``/etc/rsyslog.d/``. For background, see :doc:`03-default-config`. Steps ===== 1) Create a new config snippet ------------------------------ Create ``/etc/rsyslog.d/10-first.conf`` with this content: .. code-block:: rsyslog # Write only messages tagged "tut02" to a custom file if ($programname == "tut02") then { action(type="omfile" file="/var/log/myfirst.log") # no 'stop' here: allow normal distro handling to continue } Why this approach? ------------------ - We **don’t** touch inputs (distro already set them up). - We **filter by tag** so only your test message goes to the new file, keeping it clean. - We **don’t** use ``stop`` so normal logging continues unchanged. 2) Restart rsyslog ------------------ .. code-block:: bash sudo systemctl restart rsyslog systemctl status rsyslog --no-pager 3) Send a test message ---------------------- Use the ``logger`` command to generate a message with the tag ``tut02``: .. code-block:: bash logger -t tut02 "hello from rsyslog tutorial 02" 4) Verify the result -------------------- Check the new file: .. code-block:: bash sudo tail -f /var/log/myfirst.log You should see your message. The system’s regular logs (e.g., ``/var/log/syslog`` on Ubuntu or ``/var/log/messages`` on RHEL-like distros) continue to work as before. If it’s not working… ===================== 1. **No file created** - Service status: ``systemctl status rsyslog`` - Syntax check: ``sudo rsyslogd -N1`` - Ensure the snippet path is correct: ``/etc/rsyslog.d/10-first.conf`` 2. **File exists but no message inside** - Confirm you used the **exact tag**: ``logger -t tut02 "..."`` - Verify the filter matches: it checks ``$programname == "tut02"`` 3. **Permission denied** - Ensure rsyslog can write to ``/var/log/`` (default root-owned is fine). For custom paths, adjust ownership/permissions (``sudo chown`` / ``chmod``) as needed. 4. **Ubuntu-specific note** - Ubuntu typically uses ``imjournal`` by default. That’s fine — this rule still works. If you previously tried to load inputs manually, remove those lines and restart. Verification checkpoint ======================= By the end of this tutorial you should be able to: - Restart rsyslog without syntax errors. - Send a tagged test message with ``logger``. - See the message in your custom file without duplicating all system logs. See also / Next steps ===================== - :doc:`03-default-config` – why your distribution’s default config uses different syntax, and how to add modern snippets safely alongside it. - :doc:`04-message-pipeline` – understand the flow: input → ruleset → action. - Existing page: :doc:`../basic_configuration` – neutral reference example. ---- .. tip:: 🎬 *Video idea (3 min):* create ``10-first.conf``, restart rsyslog, run ``logger -t tut02 "…"`` and watch ``/var/log/myfirst.log`` update live with ``tail -f``. rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/03-default-config.rst0000644000000000000000000000013215132733117027536 xustar0030 mtime=1768666703.901620147 30 atime=1787067671.999443818 30 ctime=1787067791.703674908 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/03-default-config.rst0000666000175000017500000000712115132733117027205 0ustar00rgerrger.. _tut-03-default-config: Understanding the Default Configuration ####################################### .. meta:: :audience: beginner :tier: entry :keywords: rsyslog default config, imjournal, imuxsock, legacy syntax .. summary-start Why your distro’s default rsyslog config looks “old�, what those lines mean, and how to safely add modern snippets alongside it. .. summary-end Goal ==== Understand why the configuration you see in ``/etc/rsyslog.conf`` may look different from these tutorials, and learn the safe way to extend it without breaking your distribution’s setup. Why it looks different ====================== When you open ``/etc/rsyslog.conf`` on a freshly installed system, you might see directives like: .. code-block:: none *.* /var/log/syslog $FileCreateMode 0640 These come from how Linux distributions ship rsyslog. It is a **compatibility choice** to preserve behavior from older syslog systems. At the same time, the distro config often loads modern modules such as: .. code-block:: rsyslog module(load="imuxsock") module(load="imjournal") This mix of legacy and modern syntax can look confusing. The key point: **both styles work.** For new configs, always use **RainerScript**. Want to know what a legacy line like ``$FileCreateMode`` actually does? You don’t need to learn all of these right now, but if you’re curious, try the `AI rsyslog assistant `_. It can explain individual directives in detail and suggest the modern equivalent. How inputs are handled ====================== - **Ubuntu/Debian** usually load ``imjournal`` (reads from systemd’s journal). - **RHEL/CentOS/Rocky/Alma** often use ``imuxsock`` (reads from the traditional syslog socket). - Some distros load both for maximum compatibility. That is why you should **not reload those same inputs again** in your snippets — the distro already set them up. But if you need to use a **new kind of input**, such as monitoring a text file with ``imfile`` or receiving logs over TCP with ``imtcp``, then you *do* load that module yourself. Adding new inputs is normal; reloading the already configured system inputs is unnecessary. Safe way to add your rules ========================== - **Leave ``/etc/rsyslog.conf`` as it is.** Do not try to “modernize� the legacy lines — rsyslog understands them. - **Add your own rules under ``/etc/rsyslog.d/*.conf``** in RainerScript syntax. Example: .. code-block:: rsyslog # Log all messages from facility 'local3' to a custom log file if ($syslogfacility-text == "local3") then { action(type="omfile" file="/var/log/myapp.log") } Should you convert legacy lines? ================================ No — there is no need. Over time you may choose to migrate, but rsyslog will happily run mixed syntax. Verification checkpoint ======================= By the end of this tutorial you should: - Recognize legacy lines like ``*.* /var/log/syslog``. - Understand why they exist in distro configs. - Know that you should not remove or convert them. - Be confident adding new modern rules in ``/etc/rsyslog.d/``. See also / Next steps ===================== - :doc:`02-first-config` – your first modern snippet. - :doc:`04-message-pipeline` – learn how inputs, rulesets, and actions fit together. - Existing page: :doc:`../understanding_default_config` – neutral reference version. ---- .. tip:: 🎬 *Video idea (2–3 min):* open ``/etc/rsyslog.conf``, highlight the mix of old and new lines, explain why it’s safe, then add a small snippet under ``/etc/rsyslog.d/`` to show the correct workflow. rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/04-message-pipeline.rst0000644000000000000000000000013215132733117030077 xustar0030 mtime=1768666703.901620147 30 atime=1787067672.032444433 30 ctime=1787067791.706674963 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/04-message-pipeline.rst0000666000175000017500000001026715132733117027553 0ustar00rgerrger.. _tut-04-log-pipeline: The Log Pipeline: Inputs → Rulesets → Actions ############################################# .. meta:: :audience: beginner :tier: entry :keywords: rsyslog log pipeline, message pipeline, input, ruleset, action, kafka, output .. summary-start Understand rsyslog’s core architecture: logs enter through **inputs**, are processed by **rulesets**, and end up in one or more **actions** (outputs). This flow is called the **log pipeline** — historically known as the *message pipeline*. .. summary-end Goal ==== Build a correct mental model of rsyslog’s architecture using the **log pipeline**. This helps you predict where to add filters, which actions will run, and why your snippets behave as they do. The three core components ========================= 1. **Inputs** – how logs arrive. Examples: ``imuxsock`` (syslog socket), ``imjournal`` (systemd journal), ``imfile`` (text files). 2. **Rulesets** – the logic in between. They hold filters and actions and decide what happens to each message. 3. **Actions** – where logs go. Examples: files (``omfile``), remote syslog (``omfwd``), or modern targets like Kafka (``omkafka``). Visual model ============ .. mermaid:: flowchart LR A["Inputs"]:::input --> B["Ruleset"]:::ruleset B --> C1["Action 1"]:::action B --> C2["Action 2"]:::action classDef input fill:#d5e8d4,stroke:#82b366; classDef ruleset fill:#dae8fc,stroke:#6c8ebf; classDef action fill:#ffe6cc,stroke:#d79b00; Explanation =========== - **Inputs** feed messages into rsyslog. - Each message enters a **ruleset**, which decides what to do with it. - **Actions** are destinations that execute **in order by default** (serial). Concurrency is possible through per-action queues or worker threads, but that’s an advanced topic. Example: add a second destination ================================= Write messages tagged ``tut04`` to a file *and* forward them: .. code-block:: rsyslog if ($programname == "tut04") then { action(type="omfile" file="/var/log/mypipeline.log") action(type="omfwd" target="logs.example.com" port="514" protocol="udp") } Restart and test: .. code-block:: bash sudo systemctl restart rsyslog logger -t tut04 "hello from rsyslog tutorial 04" sudo tail -n 20 /var/log/mypipeline.log .. note:: Forwarding requires a **second machine** or another rsyslog instance listening on a port. Without a reachable target and without an action queue, rsyslog will retry and may appear “stuck� for a short time before the next attempt. For a proper walkthrough, see :doc:`../forwarding_logs`. Action order and config sequence ================================ - Actions execute **serially in the order they appear**. - Earlier actions can **modify or discard** messages before later ones run. - Include snippets in ``/etc/rsyslog.d/`` are processed in **lexical order** (e.g., ``10-first.conf`` runs before ``50-extra.conf``). - Concurrency can be introduced by giving an action its **own queue** (``action.queue.*``) or by using separate rulesets/workers. See :doc:`05-order-matters` for a hands-on demo of ordering effects. Verification checkpoint ======================= You should now be able to: - Sketch **Input → Ruleset → Actions** from memory. - Recognize where your distro-provided **inputs** attach to the flow. - Understand that **actions** are sequential by default. - Name at least one modern output (e.g., **Kafka**). See also / Next steps ===================== You now understand the basic architecture — the **log pipeline**. To explore more advanced pipeline concepts (branching, staging, queues), see: - :doc:`../../concepts/log_pipeline/stages` - :doc:`../../concepts/log_pipeline/design_patterns` - :doc:`../forwarding_logs` - how forwarding and queues interact. - :doc:`05-order-matters` - ordering and include file sequence. - :doc:`../../concepts/log_pipeline/index` - conceptual overview ---- .. tip:: 🎬 *Video idea (2–3 min):* show the diagram, then run ``logger -t tut04 "…"`` and watch the message hit both the file and the forwarder; highlight that actions execute sequentially by default. rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/index.rst0000644000000000000000000000013215132733117025536 xustar0030 mtime=1768666703.901620147 30 atime=1787067672.162446856 30 ctime=1787067791.712675075 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/index.rst0000666000175000017500000000402015132733117025200 0ustar00rgerrger.. _beginner_tutorials: Beginner Tutorials ################## .. meta:: :audience: beginner :tier: entry :keywords: rsyslog, tutorial, getting started, learning path, message pipeline .. summary-start A guided series of step-by-step tutorials for rsyslog beginners, built around the message pipeline (input → ruleset → action). .. summary-end Welcome to the **Beginner Tutorials**, a curated learning path designed to help you get from zero to a working rsyslog setup quickly and confidently. Each tutorial is: - **Goal-oriented** – solves a single, practical problem. - **Runnable** – includes commented configuration examples. - **Verifiable** – always shows how to test results (e.g., with ``logger``). - **Resilient** – ends with an *If it's not working…* section. We use the **message pipeline metaphor** throughout: rsyslog receives messages through an *input*, processes them in a *ruleset* (filters, parsers, queues), and delivers them to an *action* (e.g., write to file, forward, or database). .. mermaid:: flowchart LR A[Input] --> B[Ruleset] B --> C[Action] This pipeline is the foundation of every tutorial in this series. Some tutorials will also include: - **Optional Docker shortcuts** – useful if Docker is already on your system and you want a quick sandbox environment. - **Companion videos** – short screen-capture demos for steps that are easier to show than to describe (installation, first config, troubleshooting). Upcoming, not yet available. .. note:: The *video tips* included in tutorials exist because we plan to provide these short videos over time. We also highly appreciate community contributions — if you would like to record a companion video, please contact **rgerhards@adiscon.com** or post in the `GitHub discussions `_. ---- .. toctree:: :maxdepth: 1 :numbered: 01-installation 02-first-config 03-default-config 04-message-pipeline 05-order-matters 06-remote-server rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/06-remote-server.rst0000644000000000000000000000013215132733117027451 xustar0030 mtime=1768666703.901620147 30 atime=1787067672.126446185 30 ctime=1787067791.710675038 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/06-remote-server.rst0000666000175000017500000001031415132733117027116 0ustar00rgerrger.. _tut-06-remote-server: Your First Remote Log Server ############################ .. meta:: :audience: beginner :tier: entry :keywords: rsyslog remote server, imudp, log receiver, central logging .. summary-start Set up rsyslog to **receive logs from another machine** over UDP. Use a **dedicated ruleset** so only remote messages go into ``/var/log/remote.log``. .. summary-end Goal ==== Create a basic **remote log receiver**. You will configure rsyslog to listen on UDP/514 and process incoming messages with a separate ruleset, ensuring local logs remain unaffected. .. important:: This tutorial requires **two systems** (or two containers/VMs). One acts as the **server** (receiver), the other as the **client** (sender). Without a second machine, forwarding may appear “stuck� because rsyslog retries. Steps ===== 1) Configure the server (receiver) ---------------------------------- On the receiving system, create ``/etc/rsyslog.d/10-receiver.conf``: .. code-block:: rsyslog # Load UDP input module(load="imudp") # A ruleset just for messages received via this UDP listener ruleset(name="rs-from-udp") { action(type="omfile" file="/var/log/remote.log") # This ruleset is used only for the UDP input below. # Local system logs continue to use the default distro config. } # Assign the UDP input to the ruleset above input(type="imudp" port="514" ruleset="rs-from-udp") Restart rsyslog: .. code-block:: bash sudo systemctl restart rsyslog systemctl status rsyslog --no-pager 2) Configure the client (sender) -------------------------------- On the sending system, create ``/etc/rsyslog.d/10-forward.conf``: .. code-block:: rsyslog # Forward all messages via UDP to the server action( type="omfwd" target="server.example.com" # replace with server hostname or IP port="514" protocol="udp" ) Restart rsyslog on the client: .. code-block:: bash sudo systemctl restart rsyslog 3) Test the setup ----------------- From the **client**, send a test message: .. code-block:: bash logger -t tut06 "hello from the client" On the **server**, check the remote log file: .. code-block:: bash sudo tail -n 20 /var/log/remote.log You should see the test message. Only messages from the client appear here, because the UDP input uses its own ruleset. If it’s not working… ===================== 1. **No messages arrive** - Verify the server is listening on UDP/514: .. code-block:: bash sudo ss -ulpn | grep ':514' - Check firewall rules (``ufw`` or ``firewalld``) to allow UDP/514. - Ensure the client’s ``target=`` hostname/IP is correct (try an IP to rule out DNS). 2. **Messages appear only on the client** - Test network reachability: .. code-block:: bash ping server.example.com - If ICMP/ping is blocked, check with traceroute or review firewall/NAT. 3. **Permission denied on /var/log/remote.log** - Ensure rsyslog has permission to write under ``/var/log/``. - For testing, root-owned files in ``/var/log/`` are fine. 4. **Service won’t start** - Validate configuration on both systems: .. code-block:: bash sudo rsyslogd -N1 Verification checkpoint ======================= By the end of this tutorial you should be able to: - Restart rsyslog cleanly on both client and server. - Send a message with ``logger`` on the client. - See the message arrive in ``/var/log/remote.log`` on the server, without local logs mixed in. See also / Next steps ===================== - :doc:`04-message-pipeline` – how inputs, rulesets, and actions fit together. - :doc:`../forwarding_logs` – more on forwarding (UDP vs TCP) and queues. - Reference: :doc:`../../configuration/modules/imudp` - Reference: :doc:`../../configuration/modules/omfwd` ---- .. note:: Forwarding requires a **reachable** server. Without a valid target (and without an action queue), rsyslog may retry and appear “stuck� for a while. .. tip:: 🎬 *Video idea (3–4 min):* show two terminals (client/server), run ``logger`` on the client, and tail ``/var/log/remote.log`` on the server. Then point out the dedicated ruleset in the config that keeps local logs separate. rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/PaxHeaders/01-installation.rst0000644000000000000000000000013215132733117027346 xustar0030 mtime=1768666703.901620147 30 atime=1787067671.924442419 30 ctime=1787067791.699674833 rsyslog-8.2608.0/doc/source/getting_started/beginner_tutorials/01-installation.rst0000666000175000017500000000740315132733117027020 0ustar00rgerrger.. _tut-01-installation: Installing rsyslog ################## .. meta:: :audience: beginner :tier: entry :keywords: rsyslog install, rsyslog service, rsyslogd -N1, docker .. summary-start Install rsyslog via packages, verify the service, and (optionally) try a Docker sandbox. .. summary-end Goal ==== Get rsyslog installed and confirm it runs correctly on your system. If you prefer a zero-risk sandbox, try the optional Docker approach at the end. .. important:: **About default distro configs:** Many distributions ship legacy-style config lines in ``/etc/rsyslog.conf`` (e.g., ``*.* /var/log/syslog`` or ``$FileCreateMode``). That is **normal** and supported. In these tutorials we use **modern RainerScript**. **Do not rewrite the distro file.** Add your own rules under ``/etc/rsyslog.d/*.conf``. For a guided explanation, see :doc:`03-default-config`. Steps ===== 1) Install the packages ----------------------- On **Ubuntu/Debian**: .. code-block:: bash sudo apt update sudo apt install rsyslog On **RHEL / CentOS / Rocky / Alma**: .. code-block:: bash sudo dnf install rsyslog 2) Enable and start the service ------------------------------- .. code-block:: bash sudo systemctl enable --now rsyslog systemctl status rsyslog --no-pager 3) Validate configuration syntax -------------------------------- Run a dry-run parse to check syntax without launching a second daemon: .. code-block:: bash sudo rsyslogd -N1 You should see **“rsyslogd: End of config validation run.�** with no errors. Verification ============ Send a test message and ensure rsyslog is processing logs locally: .. code-block:: bash logger -t tut01 "hello from rsyslog tutorial 01" sudo tail -n 50 /var/log/syslog 2>/dev/null || sudo tail -n 50 /var/log/messages You should see a line containing ``tut01`` and your message. If it’s not working… ===================== 1. **Service not active** - Check: ``systemctl status rsyslog`` - Fix: ``sudo systemctl restart rsyslog`` 2. **Syntax errors** - Run: ``sudo rsyslogd -N1`` - Read the first error carefully; it points to the file/line. Remove the offending change or fix the typo, then re-run. 3. **Logs not visible** - Different distros write to different files. Try both: ``/var/log/syslog`` and ``/var/log/messages``. - Ensure your terminal command used ``logger`` (see above). 4. **Permission issues** - If you created custom log paths, ensure directory write permissions for the rsyslog service user. Use ``sudo chown`` / ``chmod`` appropriately. Optional: Try rsyslog in Docker (sandbox) ========================================= Use this if you want to **experiment without touching your host’s system logger**. .. code-block:: bash docker run --name rsyslog-sandbox -it --rm rsyslog/rsyslog In another terminal, exec a shell into the container to test: .. code-block:: bash docker exec -it rsyslog-sandbox bash logger -t tut01 "hello from inside container" tail -n 50 /var/log/syslog 2>/dev/null || tail -n 50 /var/log/messages .. note:: This container **does not replace** your host’s system logger. To receive host logs, you’d need volume mounts and socket plumbing; that is outside this beginner tutorial and covered later in best-practice guidance. See also / Next steps ===================== - :doc:`02-first-config` – write a message to a custom file using modern RainerScript. - :doc:`03-default-config` – why distro configs look “old�, and how to add your own rules safely. - Existing page: :doc:`../installation` – neutral installation reference. ---- .. tip:: 🎬 *Video idea:* a 2–3 min screen capture showing package install, service check, ``rsyslogd -N1``, a ``logger`` test, and the Docker sandbox run. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/understanding_default_config.rst0000644000000000000000000000013215132411300026411 xustar0030 mtime=1768559296.188884406 30 atime=1787067672.312449653 30 ctime=1787067791.725675318 rsyslog-8.2608.0/doc/source/getting_started/understanding_default_config.rst0000666000175000017500000000545015132411300026063 0ustar00rgerrgerUnderstanding the Default Configuration ======================================= When you open ``/etc/rsyslog.conf`` on a freshly installed Linux system, you might see a configuration that looks very different from the examples in this guide. Lines such as ``$FileOwner`` or ``*.* /var/log/syslog`` can look unusual or even cryptic to new users. This layout comes from how many Linux distributions package rsyslog. It’s not the default style of rsyslog itself, but a compatibility choice made by the distribution to keep older tools and setups working smoothly. Why It Looks Different ---------------------- Distributions like Ubuntu, Debian, or RHEL ship rsyslog with a **mixed configuration style**: - **Legacy lines** such as ``$FileCreateMode`` or ``*.*`` are left over from older syslog systems. - **Modern modules** (e.g., ``module(load="imuxsock")``) are included to add newer rsyslog features. rsyslog supports both styles, so the system works out of the box. For new configurations, we recommend **modern RainerScript syntax**, as shown throughout this guide. Why We Don’t Show ``*.*`` in Examples ------------------------------------- In older configurations, you will often see a line like: .. code-block:: none *.* /var/log/syslog This means: *“Send all messages, regardless of facility or priority, to /var/log/syslog.�* Modern RainerScript configurations **do not need this line** because logging everything to ``/var/log/syslog`` is already the default behavior. You can add explicit filters if needed, but a ``*.*`` filter is no longer necessary. For example: .. code-block:: rsyslog action(type="omfile" file="/var/log/syslog") is enough to log all messages to ``/var/log/syslog``. How to Work with the Default Config ----------------------------------- - **Keep the distribution’s default files as they are.** They ensure that standard system logging works correctly. - **Add your own rules in separate files** under ``/etc/rsyslog.d/``. This avoids conflicts with distro updates. For example, create ``/etc/rsyslog.d/10-myapp.conf``: .. code-block:: rsyslog # Log all messages from facility 'local3' to a custom log file. if ($syslogfacility-text == "local3") then { action( type="omfile" file="/var/log/myapp.log" ) } Should You Convert the Old Lines? --------------------------------- No, you don’t need to convert them. rsyslog understands both styles. Over time, you might choose to migrate to RainerScript for clarity, but it is not required. Key Takeaways ------------- - The default configuration is shaped by **distribution choices**, not by rsyslog itself. - Modern RainerScript is easier to read and is used in all new examples. - You can safely add your own rules in modern style without touching the existing legacy lines. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/index.rst0000644000000000000000000000013215171370365021644 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.206447677 30 ctime=1787067791.717675168 rsyslog-8.2608.0/doc/source/getting_started/index.rst0000664000175000017500000000351015171370365021307 0ustar00rgerrger.. _getting_started: Getting Started with rsyslog ############################ rsyslog is a modern, high-performance logging service and the default system logger on many Linux distributions. It extends traditional syslog with advanced features like structured logging, reliable TCP/TLS delivery, and integration with modern pipelines (e.g., Elasticsearch, Kafka, or cloud services). This guide helps you get up and running quickly. For a complete production deployment with dashboards and monitoring, see :doc:`../deployments/rosi_collector/index`. It includes: .. toctree:: :maxdepth: 1 beginner_tutorials/index rosi_for_beginners ai-assistants installation basic_configuration understanding_default_config forwarding_logs next_steps ---- **Quick Start (for experienced users):** .. code-block:: bash sudo apt install rsyslog sudo systemctl enable --now rsyslog The following pages explain these steps in more detail. .. _getting-started-versioning: Understanding rsyslog version numbers ===================================== Every regular rsyslog release is tagged ``8.yymm.0``. The constant ``8`` marks the current major series, ``yymm`` tells you the year and month of the build, and the trailing digit starts at ``0`` and only increments when a quick follow-up fix ships. Seeing a version such as ``8.2404.0`` instantly reveals it was published in April 2024 and is part of the same feature level as any other ``8.2404.x`` package. Stable builds arrive roughly every second month in even numbered months, typically on a Tuesday around mid-month, with an earlier December drop to avoid holiday downtime. If your installation shows a much older ``yymm`` value, plan an upgrade to keep up with supported features and fixes. Newcomers can read the full background and rationale in :ref:`about-release-versioning`. rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/rosi_for_beginners.rst0000644000000000000000000000013115171370365024412 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.271448888 29 ctime=1787067791.72367528 rsyslog-8.2608.0/doc/source/getting_started/rosi_for_beginners.rst0000664000175000017500000001630215171370365024061 0ustar00rgerrger.. _getting-started-rosi: ROSI for Beginners ================== .. meta:: :description: Beginner introduction to ROSI as an open, rsyslog-backed operations stack that reduces lock-in and complexity. :keywords: rsyslog, ROSI, vendor lock-in, observability, beginner, deployment .. summary-start ROSI (Rsyslog Operations Stack Initiative) gives beginners a concrete, deployable stack while keeping freedom of choice. It is built to reduce vendor lock-in and complexity, and to let teams evolve components over time. .. summary-end ROSI (Rsyslog Operations Stack Initiative) is the rsyslog approach to practical, modern observability: start with a concrete stack you can deploy now, but do not get trapped in one vendor or one fixed architecture. Today, the main ready-to-run ROSI artifact is :doc:`../deployments/rosi_collector/index`. That is the easiest way to get started, but ROSI itself is broader than that single profile. The larger ROSI picture includes additional backend choices, mixed-component deployments, and Windows-side collection options. Many of these architectures have been built with rsyslog for a long time already; what ROSI adds is a clearer formalization of that approach, better guidance, and a growing set of artifacts that make adoption easier. Why ROSI Exists --------------- Many teams run into the same pain points: - Logging stacks that are hard to deploy and operate - rsyslog configurations that feel too complex for a first production rollout - Tool choices that later create vendor lock-in ROSI addresses these with a beginner-friendly default that is: - **Easy to use**: a turnkey collector stack that works out of the box - **Concrete**: not a future promise, but a deployable stack available now - **Open and growing**: designed to expand over time as new stack profiles are added ROSI at a Glance ---------------- .. raw:: html
   flowchart LR
     P1["Complex setup"] --> R1["Turnkey ROSI stack"]
     P2["Vendor lock-in risk"] --> R2["Freedom of choice"]
     P3["High ingest and ops cost"] --> R3["Efficient rsyslog at ingestion"]

     R1 --> O1["Faster time to value"]
     R2 --> O2["Replaceable architecture"]
     R3 --> O3["Lower cost and energy use"]

     classDef pain fill:#fde2e2,stroke:#c0392b,color:#1f1f1f;
     classDef rosi fill:#e8f4fd,stroke:#2e86c1,color:#1f1f1f;
     classDef outcome fill:#e8f8f0,stroke:#1d8348,color:#1f1f1f;

     class P1,P2,P3 pain;
     class R1,R2,R3 rosi;
     class O1,O2,O3 outcome;
   
Efficiency First (FinOps and Green IT) -------------------------------------- ROSI also follows an efficiency-first mindset: - Use resource-efficient components (including rsyslog at ingestion) - Keep baseline operations practical for smaller and medium installations - Support "right-sized" observability, including homelab-scale deployments This helps align day-to-day operations with both **FinOps** goals (cost control) and **Green IT** goals (lower compute footprint). Freedom of Choice and Vendor Lock-In ------------------------------------ ROSI is intentionally built as a guard against vendor lock-in. The core idea is simple: your logging pipeline should stay under your control. In practice, that means: - rsyslog remains a strong routing and processing layer at the center - external components are selected for operational value, not lock-in - you can adapt outputs and destinations as your requirements evolve Today, rsyslog already supports multiple output targets and integration patterns, including modules such as: - :doc:`../configuration/modules/omhttp` for HTTP-based endpoints - :doc:`../configuration/modules/omelasticsearch` for Elasticsearch and OpenSearch - :doc:`../configuration/modules/omkafka` for Kafka - :doc:`../configuration/modules/omfwd` for syslog forwarding Common destination examples include Loki, Elasticsearch, OpenSearch, Kafka, Splunk (HEC-style HTTP), VictoriaLogs, and cloud endpoints exposed over HTTP or syslog. ROSI can also include Windows-side collection components where they fit the operational need, such as `rsyslog Windows Agent `_, `WinSyslog `_, `EventReporter `_, and `MonitorWare Agent `_. These complement the rsyslog-centered ingestion and routing model rather than replacing it. Some of these components come from `Adiscon `_, while others are third-party tools that fit the same freedom-of-choice model. In other words, ROSI does not invent freedom-of-choice logging around rsyslog. Users have long connected rsyslog to destinations such as Elasticsearch, Splunk, Kafka, syslog receivers, and HTTP-based services, sometimes in parallel. ROSI formalizes that long-standing practice and provides clearer guidance and more reusable artifacts around it. As ROSI grows, additional pre-packaged stack profiles can be added without changing this core principle: keep architectures replaceable. This is the foundation for sustainable operations: freedom of choice instead of forced rewrites. Where rsyslog at the edge is used, teams can often reduce downstream ingest volume and processing cost by routing, filtering, and shaping data before it reaches central backends. What ROSI Is and Is Not ----------------------- ROSI **is**: - A practical, rsyslog-backed observability approach - A concrete starter stack (ROSI Collector) for centralized logs and metrics - A formalization of long-standing rsyslog practices around replaceable architectures and parallel destinations - A guidance layer that makes proven rsyslog-based patterns easier to choose and operate well - A broader ecosystem direction that can incorporate additional backends and Windows-side components, with more turnkey artifacts being added over time - A path that can grow with your infrastructure over time - Container-based today, with Kubernetes-oriented evolution as a next target ROSI **is not**: - A closed product tied to a single vendor - A claim that one backend is always right for every team - A replacement for detailed implementation guides Current Starter Stack --------------------- The current ROSI starter deployment is :doc:`../deployments/rosi_collector/index`. It combines rsyslog with Loki, Grafana, Prometheus, and Traefik to deliver a production-ready baseline quickly. This baseline solves immediate operational pain while preserving future options. If you want a hands-on walkthrough, follow :doc:`../tutorials/deploy_rsyslog_rosi_stack`. What to Read Next ----------------- - :doc:`../deployments/rosi_collector/index` for deployment and operations - :doc:`../deployments/index` for deployment choices - :doc:`next_steps` for the broader beginner path For deeper follow-up: - :doc:`../deployments/rosi_for_platform_teams` for platform architecture and adoption - :doc:`../deployments/rosi_for_decision_makers` for sustainability and risk framing rsyslog-8.2608.0/doc/source/getting_started/PaxHeaders/next_steps.rst0000644000000000000000000000013215171370365022731 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.249448478 30 ctime=1787067791.721675243 rsyslog-8.2608.0/doc/source/getting_started/next_steps.rst0000664000175000017500000000325515171370365022402 0ustar00rgerrgerNext Steps ========== You have installed rsyslog, configured local logging, and optionally set up log forwarding. Here are some recommended next steps. Production Deployments ---------------------- For a complete log collection stack with dashboards and alerting, see ROSI Collector (:doc:`Rsyslog Operations Stack Initiative `): :doc:`../deployments/rosi_collector/index` For the beginner-level ROSI concepts (open approach, freedom of choice, and vendor lock-in guardrails), see: :doc:`rosi_for_beginners` ROSI Collector provides: - Centralized log aggregation from multiple hosts - Pre-built Grafana dashboards for log exploration - Prometheus metrics collection - Automatic TLS with Traefik Explore Modules --------------- rsyslog's modular design allows integrations such as: - `omelasticsearch` for Elasticsearch and OpenSearch - `omkafka` for Kafka - `imfile` for monitoring text log files Filtering and Templates ----------------------- Learn how to filter messages and format log output using templates. See: :doc:`../configuration/index` Debugging and Troubleshooting ----------------------------- Use `rsyslogd -N1` to check configuration syntax and discover issues with included snippets. Advanced Tutorials ------------------ For more examples and step-by-step guides, visit: :doc:`../tutorials/index` For impstats metrics push setup, see: :doc:`../tutorials/impstats_push_victoriametrics` Community and AI Assistant -------------------------- - Join the `GitHub Discussions `_ to ask questions and share knowledge. - Try the `AI rsyslog assistant `_ for quick configuration help. rsyslog-8.2608.0/doc/source/PaxHeaders/how2help.rst0000644000000000000000000000013215132411300017054 xustar0030 mtime=1768559296.189884422 30 atime=1787067671.809440276 30 ctime=1787067791.758675933 rsyslog-8.2608.0/doc/source/how2help.rst0000666000175000017500000000431315132411300016523 0ustar00rgerrgerHow you can Help ---------------- **You like rsyslog and would like to lend us a helping hand?** This page tells you how easy it is to help a little bit. You can contribute to the project even with a single mouse click! If you could pick a single item from the wish list, that would be awfully helpful! This is our wish list: - let others know how great rsyslog is - spread word about rsyslog in forums and newsgroups - place a link to `www.rsyslog.com `_ from your home page - let us know about rsyslog - we are eager for feedback - tell us what you like and what you not like - so that we can include that into development - tell us what you use rsyslog for - especially if you have high traffic volume or an otherwise "uncommon" deployment. We are looking for case studies and experience how rsyslog performs in unusual scenarios. - allow us to post your thoughts and experiences as a "user story" on the web site (so far, none are there ;)) - if you know how to create packages (rpm, deb, ...) - we would very much appreciate your help with package creation. We know that it is important to have good binary packages for a product to spread widely. Yet, we do not have the knowledge to do it all ourselves. `Drop Rainer a note `_\ if you could help us out. - if you have configured a device for sending syslog data, and that device is not in our `syslog configuration database `_, you might want to tell us how to configure it. - if you are a corporate user - you might consider `Adiscon `_'s commercial `MonitorWare products `_ for Windows, e.g. to deliver Windows Event Log data to rsyslogd (sales of the commercial products funds the open source development - and they also work very well). - you might be interested in `purchasing professional support or add-on development `_ for rsyslog **We appreciate your help very much.** A big thank you for anything you might do! rsyslog-8.2608.0/doc/source/PaxHeaders/tls_cert_100.jpg0000644000000000000000000000013215132411300017473 xustar0030 mtime=1768559296.224884976 30 atime=1782715518.807789163 30 ctime=1787067793.762713277 rsyslog-8.2608.0/doc/source/tls_cert_100.jpg0000666000175000017500000000072515132411300017145 0ustar00rgerrger--2014-01-22 12:50:33-- http://www.rsyslog.com/doc/tls_cert_100.jpg Resolving www.rsyslog.com (www.rsyslog.com)... 176.9.39.152 Connecting to www.rsyslog.com (www.rsyslog.com)|176.9.39.152|:80... connected. HTTP request sent, awaiting response... 200 OK Length: unspecified [image/jpg] Saving to: ‘tls_cert_100.jpg’ 0K .......... ...... 70.2K=0.2s 2014-01-22 12:50:34 (70.2 KB/s) - ‘tls_cert_100.jpg’ saved [16607] rsyslog-8.2608.0/doc/source/PaxHeaders/direct_queue_rsyslog.png0000644000000000000000000000013115132411300021537 xustar0030 mtime=1768559296.186884375 30 atime=1782715518.806789146 29 ctime=1787067791.65767405 rsyslog-8.2608.0/doc/source/direct_queue_rsyslog.png0000666000175000017500000002434115132411300021212 0ustar00rgerrger‰PNG  IHDR¬‘ŒÃåsBITÛáOà pHYsêe¤ IDATxœí�ytÅÚ‡Ÿ„l„û ‘EÙ¾Hà‚ ¢‚"•íƒ^P<^‘EE#² "²) *"—‚¢—v D ’��uêû£½¹aI2Cfº«gê99œ¡§ç­_×[Ý¿®îêj7!@ +„(ø`ë¿wýC“–«d»B¹J¶+”k"Ù�5:zô(·áݾ}{»«T(†ãææfë¿wñ~nëÊf”íˆrkÖ¬yÇ–ãáïïÿè£�štó”lW(WɾëŸ+w‡›:ÁWè‰ËW|Õ�~¾ø­E¡PÜw£(\ –µ¬mLãïøN¹‚B!3F P8?,ëX7�i'8áŽû6­H¡P‡2…±`ù†o¦2õ8ǵ%ÏðL#«J¡P�ºÇ p±� S™z”£î¸[°n¸EݘÆF«“�ˆ‚·üÝqyéWV\3BOz†VLkT=…�ˆoùvÓsØw@s µÞäMŒÞ+䌠wž&Ä 7íß[þ¬_¨-oHÃâ RÆ °Ž¼<Ž#&† HM%#ƒë×ÉÈ lY>ú¨ðŠ—¹¼‰MG9J!KÐH&y{JÙ¦ïb¡;Pz æ�`:ÁNÁ^{s‰¨KIŠ"¸~�ˆ¶oçÔ)NŸæüù;¯Ö°!'Nܾ8–Øwyw«òÈÓ–¸áæƒÏ9ÎU£šãT+ŠÒ£ŒAQ!øê+"#Ù³‡Ã‡ÑÚF­Z4lHp0 L�:T¨@¹røùáï_|¼3œy�÷>ã³{x…Wf1ËÑÛ¡P(Jƒ2'NðÙg¬ZõwÏ 8˜Î�ÿþ«U«”±Ïqî=Þ[ÉÊ\rµNCuªÛA³B¡p Ê\!ظ‘U«øö[€à`FŽdà@í^Tqïóþr–‡6‡9v�¯P(ì…2æûï™2…¨(4ˆ!ChÕÊÑe&�0�y“˜@€£ËR(w‡2—ä×_4ˆØXÊ—güxÆ�§B£5) YPÆàbdg3u*³fáãÃK/1q"•+­I¡PÈ…zŽÁ•8x�!CˆŽ¦kW–/§n]£) Q³«º ‹Ѫ±±ÌŸÏÎ�Ê EQ8­1„††¶iÓxï½÷/_¾¼gÏž   mÛ¶eff6nÜ8<<xî¹ç |øá‡íÛ·ÏÈÈØ»wo·nÝ"##SSS{÷î½bÅ `ܸq“&M–-[öüóÏçååEFF>üøñã)))aaaßÿ=0}úôÅ‹ëׯŸ:u*pðàÁéÓ§'&&¦¤¤Ìš5ë·ß~Ó‚|÷ÝwÀ®]»>ÿüsàäÉ“kÖ¬¹zõjjjêúõëcbbìY ¯¾JXÍšqö,cÇâ¦Þâ¢P@nn®"///999338wîÜùóç�˜˜˜¨¨(mIDD„ö­Q8­14oÞ¼E‹@�57nìåååããS§N___!„¿¿¿——`±Xrss�ŒŒŒË—/ׯ_�‰‰ÉÌÌÌÍÍ�ŠŠJLL"##ýõWàÀ�_ý5púôéeË–%%%¥¥¥-Z´H;â/]ºtݺuÀæÍ›ß{ï=à�?þ˜ËìÙôêÅÞ½TSO››ŒŒŒï¾ûîìÙ³ÀÁƒãââ€+W®\»v °X,%ü^a ‡š2eʹsç’““_~ùåmÛ¶&LÐN+ç̙ӯ_?`Ó¦M:t8vìXlll³fÍ´³ÉæÍ›:4h�öÍ9sæxyy9räСCU«VÕVkܸñ+¯¼Œ;ö±ÇÖ®]z¾¨¹ôA(î–üü|‹Åb±X222²³³…©©©×®]B¤¤¤$$$!ÒÒÒbbbnܸ‘��}ôèÑK—. !¢££O�:%„8yòä¾}û„ ;wîLKKKMMݺuë™3gì#1'G´o/@ .rsíSa(ÇŽf̘!„¨ZµjïÞ½…ýû÷÷÷÷BÌŸ?8tèPtttíÚµW¬X!„ ™4i’bêÔ©{÷î5R½ÙÐ:ô?üðùsç€iÓ¦ !êÖ­Û³gO!ĨQ£…k×® >xðàÙ³g[µjµjÕ*!Ä“O>9eÊ!Ä|ðâ‹/ !vìØ1räÈøøøÄÄĉ'þòË/Bˆ3f|ûí·BˆÍ›7k?6œœLÓ¦X,=J•*z”¨0”<ò y—‹Â‰qc¸ÈÅ5¬™À„·xë-Þ:ƱbˆiC›2”1Z�¾<õß|Ö-ôéc´…ø‹¿Nr2–Xí/‘Ä4Ò2ÈÈ #“̲”µ`I&¹`ýÛ_ûU•ª‰$¸ æå0‡ãˆ;Å©‚?<®sÝq%Ndâë¼î¸øVbzcH!%€€yq%+c‰-G9?ü|ñ5Z—A|þ9C†0bK–-Eq÷œæôöh¸P°Ü ·†4,G¹‚¿jTóÆ;�ô;¾kZûóÃo1‹ Üsq’“?ñ“öO|Áò@ÒÐO/¼Wú<ÇsŽ‹o%æ6†¬x‰—NqJ HhK[£Jj*õëS±"ÑÑ”+g´…ÍÄ÷ Ÿ¬fu €;îmhÓžöÁ7 AA�ª‹Eâ'V³z kÎq(C™V´êHÇxà!jBWšYΔ›šGÞT¦NcZ0Á=èaÁR‡:�ØÿÝ2&#<œ”V®T®`.b=ë²ð'~ˆ&4yžç;Ó¹#}ð1Z�““Kî§|ºŒe80‘‰ÝéÞ‰NÚpv×Ä”=†Õ¬Ìà…,ãµHÃùóÓ¢?ÿl´…µÄW|5‰Ig8Sžò8ŒaÚÐ8…£I%u æ2÷*WkPc 1¨W•)0S�!ŸüÌhF³A J&y4£�V$Ó¦qã3f­Ca-?óó˼|€,gù ¼àr% "Ÿüy̛” 2îçþ¬èK_£EÉÅ­=†#GެY³ÆÍêÙ7+V¬øÚk¯ÙTdxxøõë6ÜÖñÄ 4°~ýýû÷ÿòË/Ö¯_¿~ýþýû[¿~VVÖÂ… ‹YáöŠzñÅ+V¬XBÜ[¦ÈX¿~½õš€{î¹ÇÖY8ªW¯nS›7o¾*®¾$^ÊùgÅY‹°ÿí·ß¶)¾6–õ$''—ôfbccm*bÀ€6ÅßÓ²¥qø°•ñúé'›âûøøØ¤_Ñ´iS›ŠX¶l™Mñµéi­§E‹¶nB™2¶�¿ï߿ߚ°±"¶µh� Z\5jÚðàÁ6é?qâ„Mú�ÔÔT›ŠèÖ­›MñÃÃÃmŠÿÍ7ߨ¿N�:ÅDË™Äwáî/üWˆÚBmÞSëѦŸ²žwÞyǦø¡¡¡6Å¿råŠMñ�˜˜˜ÃÞÚcÈÊÊÒæïµww÷j6Îä|ñâÅâ'¾ER¥J•føÌx‹·~å×Ö´.1~zzzzzúCݟʶ¼ÞÒb±\¸p¡äõ Q£F ®Ú]¹rÅšÙØµ­sËÎlÓÆ-(ˆß~³2~vvváÓyJª(77·{î¹ÇÊà.\Èɱáaï*UªøùùY¿~zzºõ-„ðöö¶òt¾€3gÎÜ1TQë×®]Ûǧ„{Å;ØÑ—¾ùä¿Ë»C“‡¦^Kµ^�¿¿¿M'U9996�ÎAAAî¶<*Ÿ˜˜XTC½cEU­ZµR¥JÖÇOOO·iöi�¢Nç/p¡=Žr´=>åÓ{ø»=Ÿ>}://Ïú"ýýý­_?99ùÒ¥KŬpKEùùùÕµå%ZùùùÚ€5Ç:�ûî»O{é@1È~óùçüð«D¥�ììA£åHÉêÕ ÌÒ¥ f´Eq|ÇwOñTe*og{š-Ç…8ÌáÞô¾À…yÌ{‰—Œ–c¤6�¨G½k\K&ÙO£åÈJ‡DGsþ¼¥*3[ÙÚŸþÕ¨¶›ÝA-Ç…ø‘ã1�ø’/{ÓÛh9æ@ÞQIùä—¡Ìf6ã˜r…"‰�åçŸ S® 3?òãã<^“šÊt&’È^ôª@…-lQCQ­G^cx’'äÁ·yûA4Z‹ÄhÃ�žyÆhŠ"I ¡?ý«Påw~¯Žm#/¥!–ؾôõÆ{{ÒÐh9fBRcH'=‘D×�òÈz¾ÿž€BBŒÖ¡¸3¹ädà5®íd§r=¹Â•ÞôN%u;Û•+ØŠŒ“õŸå¬'žQD}ÆgFk‘›´4öî¥Glò¤Ð“ILÚǾiLëLg£µ¸xŠSËXfÇšÏÌdölly ˬHg ÑŸþ5©™GžCg1tvì '‡Þê~š¤üÁ³˜Õ�îoð†ÑZ\‹Ïøl';_â¥çyÞŽa}}IH n]Þ}—´4;–G%íf÷QŽªQe%3bË—sé¶<‡¡Ð�hG»C:Á‰‚Qó H"©1�8ÌárØyPFR÷ÞKV+ò꫌Kùòö-A äê1¤�Nx':)W°Šßçþû•+ÈÉ×|½Ÿý˜ \AgÆ0æ×–²Ôî®Ô¬É¨Q×®ñæ›Ô­ËôéNØ{�«Ç0‘‰³˜õ´¤¥ÑZ¤'+‹òå0€U«Œ–¢¸•,²Ñ(‹¬Sœòdže¥dûÚÑn8Ã?åS‘”Dýúdg¸¹!+òÊ+Œç<½‡’�aÕ*øûó×µãBK™Ü“Þhÿ°¢D9ZÀ],4JÀ½W~ŸöýÃ_´šóŸFãUµÈ¦*!tiô¸M|RgÛHyTI+ÀŽªŽÏ MoþãCOŸöºXÇqª(<Ï…óÙCÉ£Y¶mcíZ”Àô7Yÿó‡ý KirÇ 4‹šU³¨•GX˶øé�ÍaK¹PϲLªêÊŒEîWª^š9ärŽDªœ^@Vóý©G|9úÆ©:7©êŽ“½Y,äåÝù+ÓQr�!3“ÜÜ›「¦»¥Õö �7hiÎçŽ.ËðækF�âÓOII¡B‡•¡¸ö³?„�×y=œp£µ¸½èµ›Ý§9]‡:Ž+åâEêÕ#;!þî+”/Ïøñüë_”8›µY(¹Çà«ËCfå(ŸAF²G²¯‘o%Ç�S·®r YÄ¢2”Å(£…¸qÄE1„!u`æL²²þþìçÇøñŒï<– !Ũ¤l²3øÔ{›m 1‘:ŽÝwA&™ëX÷þQ�zFkq-V³Ú‚e(CZÊÅ‹,ZàïÏ”)ÄÅñÖ[Îæ Hb ûØ·šÕ?aÛÛc\!¸p�@å£Ò±•­ÙdÀ¶W-)JÏç|^ŸúèàÐRfÎÄËë–`ˋ̈́nºÐ%•T5…ª \¾Lv66¾yF¡ßñ]Êô¤§ÑB\‹H"Oqj2“ÝpÜm=nÜ reââœÿ ®ñ=†D§3=�ô²”5Z‹yHLT�A6,X¶±­-m+£ž:Ô• l1È¡¥”-Ë¿ÿíü®€ Æðþ3™ÉG8b´S¡½ïPƒdüʯ—¹Ü‡>F q9~à‡zÔS³¨Ú ã�aÃ~çw5÷¤mho¯ZÕhŠ›ØÍn@]GÒ™«\=ÈÁnt3Zˆó`°1ä’Nø½Üë�·±JL†6\®¤WÏ+t&Š(_|Õûœuf7»-XºÒÕh!΃Áưƒ“˜´žõÆÊ0š1x+7•‹(¢äÁ2”1Zˆkñ?¸á¦ŒÁŽ<*éQÝÊVõ.V›Q=ù¸Â•8âã1£…¸QDTƒF q î1ìgWºV£š±2̇2ùˆ" hA £…¸,G9ª.ßÙ#�A çñ'yÒ@ fE›óWƒLD <ÄCF q-Îqî:×›ÒÔh!N…‘—’òÉŸÍìœôÙA‡’—¨W=KE<ñ@}ê-ĵÐFº«ƒ}1òÈ’AÆ?ù§�LLÙ²™™êõmòO|yÊWÄéæÍ‘­£¦ŒÁ¾i 3™NøyΛÅbÉw$Ï<óLÙ²Å>®Íy›™ù¿%99xz:ršïÿqñâÅÙ³gëP�ÌtìØ±OŸ›dK ÁÑóz*n'� ˆ ÊŠˆˆøðÃ4hàåå%îpÇåÖ|ëèŸß²Â«¯¾úä“E^Æ÷жvæÌ™ö­Á´´´²eËnÙ²Åß¿È÷>ȃ}é[�êö-º„-Z´ÈÉÉ©R¥J1Çå¼¼¼â¿u´ÎG}ôVc8tˆûïÿßM…råà¿Æ`±°d »wóÕWަ±cÇ»7ÓqìØ±[Œ!žxÇ×effþë_ÿ hÕª•#+zþ¼J•*‹/nÙ²å·ß~[↧�⋯>BýòË/Û¶m+}·BÜòßÛ)å E}›­Ý§,àÚµk'Nœ(ýÖ&------99¹cxš§Ÿæiû–["‡òóóËÎÎ.s3^^^eƒ‡‡‡MëüñÇß~ûí˜1cnÒ]«AA„†2z4­[ÿÝcÈÈ 2’°0`½~Ï‚\¿~ؾ}{‹.:ç‰'žˆŽŽ.¼$‹¬d’ïá£$åää|ú©£Þr¬3÷Ýw_NNŽ•g`W¹Z‰J%®¶xñâ“'OÎ�;·ÔêøóÏ?Ksà.½Gã<óÌ3Ï<óŒ}ãNŸ>}òäÉ¢Ø×Ãu¡K!ïònñ¡Îž=[¶lÙ5ìp¹IKÉSO=µbÅŠÒGsO<ñ„âVc¨V�×_gÜ8V¬ eKZ¶˜>�ˆ„ F úöÕM¡»»;P¾|ù*UªèV¨Txyyݲä*W¢ 6TH»víÜÝÝ÷îÝkIZÛîׯߨQ£J:iìÏË”)dí¥¡«\µfKDDÄîÝ»íb •*•lE¦ÆQ÷´¬o Yd]ær‰¡š7oÞ­[·o¾ùÆ^ŠWe8E*=š¥K9|˜¨(¢¢¶oÿû«‘#ñÔoÒrk’ëÜÜž£tÒ?ü¬’‘‘¡Y¬½$õêÕëÕ«—½bš‚R ì¨9+Ž}Ž¡øcÇ~ö/a‰CÜŽ‰�ÁÃ�>ºÃíå2e1¢¨hK–,™7ož]*c¸CŽ®s�Á¾¸lR¬¼”¤° GC‰Íô,g_æåp�€¢0±1:0hÐ-kÓ·o1óo¯\¹rñâÅvèºÇ ”1HByi¤)c°;†ÃyÎÏgþA:H@Q˜Û€>ÀÏïý!=Za¸æ1¨0Ê$!…�PÉÚÃŒ¡-mSHqô—nÇôÆP³&o½…¶‚»;AAtï®›6 ×<æöe�”£œAŠ\4))¤ªÇ`w 3†‹\ÜÞTR$ (Lo Àر4j`±0z´>µÆ5�A…¹=GÚTÛ,)rѤ\å*Ê€aưŸýOðÄüá Eá ÆàéÉÂ…ÞÞ ª‹¨›pÍcPanÏ‘/¾@&™EüÂá¸fR4cP—’ìŽaÃUCÙÄ&ýŸucºtaÀ|| ™+É5�A…¹=Ge)‹2ݹÁ ½‚ç¬f ¨Ðžöú߬scæÏ'!Áñrî€kƒ £z ’ Í„‘E–ÑBœ Ã.%}Íו©I¤ƒ…óCµj?ÿ¬;®y *Œ2IÐ:jZ¿AaG 3†¦4}•WkQËAŠÂyŒÁ8\óT˜¢ŒÁÀ#”k&E3Õc°;†]JjIË–Üt»‘�=èáèË…¦8ìʯ×;Fõ$ÁT�Áè×cˆ'~Ó’HÒþETco`p’“¡„~Â':ÜD2ÅaW~…¸Þ1¨0êæ³$¨ƒƒÐÏîážxâïáž'y2‚O<ýðË'ÿu^oJÓ"þ�ÿs�˜[„I¾ó˜B!®w *Œ5=†,²Žs\OI¸^RÔ=¡ë=†÷yßß�l %´;ÝûÑo$#g0#—ÜÚÔîCŸ"‚ÙY˜ä;�)âzǠ¸¹¹‰2b7»W‚'žžxÃZÖ6¢QUªê) ×KŠõ—’ºuë6xð`Ç+rt½ÇP�jÓ™>ŽqÀe.Ob’?µ;ŠQº¼gÔ‡]ùâzǠ¸¹¹‰\±� #9œáCZ�ê¾øÞàÆ)N�aÌ.v d`ñ¯gX²d‰›]ŸZ—¿åØ�;^J:ÏùÚÔ¾eͰ°0ýd™½G%�ftSšºÿ·\í„Ë�á /*ÔÙ³g?ûì3; “|ç1…B”11�é×¹þ:¯×¦öSùßðÍU®Æ›K.DPº¢JçBuÆ�QŒêA� lÈ#ÏowܳÈJ'ý5^kF37ÜÐÀh™¦Ç€áªè0ˆA«Y­ýW F£ßÄÑòï<öU8cÆ {…*@CAŽžåÙ¥,-|³Ac$# .“ê¯Ê¹™Å¬F4ÚÁŽšÔÅ(|Nr²! µ�úŒaqzŒyÀí>ðÃÏ 77Üîã>=Ï­äßyL¡e ÿÝüE,òij° xà1„!ƪrbêPç Þ’HšÆ´L2#‰ü‹¿Ýư8=ÆCMj¾Å[¡uô<·’ç1…B”1üwóÒð5^+è1h—F«SÝXUÎÍ+¼D�{¡Ã—Vÿº�aqz ›c,cà�²”ÕùÜJþ�Ç QÆPhóßà�úÔ׎SQâmg}T91Þx/`Á-o¿(~ ‹Â& 3O<°àYžÕy.uùwS(DC¡Í/KÙ…,ÔŽSu©Û½ß©wGUÎM/zõ£_Áņǰ(lÂ0cºÒu³$ (äßyL¡e 7o~/zõ§?0‚îÛ­lUåÜÌe®^š7è<†Åé1Ò0âÕKòï<¦Pˆ2†Û6ÿC> àŸüÓI˜¡åØ—úÔƒ7´» :�aqz 6ý‘ç1…B¤L®nÜ1G�F¡ÿLòÈßrìÎk¼V�z€ÎcXœe Òa …H™\Ý(*Gú¿ª¶0ò·»ãƒÏ|æûâkÈø`'Fƒt˜B!R&W7äÌ‘œªÍc<¶�…ú_”vn”1H‡)"eruCÎÉ©J†2Ôh Ά2é0…B¤L®nÈ™#9U)̈2é0…B¤L®nÈYò·‰‹‹;zô¨Ñ*Lƒ2é0…B¤L®nØ¥æÏŸ¿`Á;)3´?~|ûöí�VaL` ýû÷ç�wJGCþ�Ç QÆPêX¾|ùŠ+ì¤ÌÐrfÁ€i·me×®]¥R€ü;�}&''[,–jÕªÙ+ Êd­ùÛ¶Â,˜Àì‹ü;�}öíÛ7%%åøq{¾•^Úäꆜ5 ÛV˜\J²/òï<¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\Ý�³äo9 ³ ŒAF$W(mruCÎ0EÛV˜e Òa …H™\Ý�³äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAM¢'¦Pˆ”ÉÕ »Ô@·nÝÜÝíyf&Ë1�¯¾úÊb±­Â4˜À&MšT¿~ýÒÇXkâuxIDATÑpss“¼}È¿{+c°K Ìž=ÛNrþFþ–c žžžFK0&0†‰'–>Hòï<¦Pˆ2ùj@þ–£0 &0û"ÿÎc_…›6m²{IÚäꆜ5 ÛV˜e Òa_…U«VµW¨¤M®nÈYò·m…YP£’¤Ã ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\Ý�³äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\ݰK üõ×_ýõ—��ZŽ�Lš4éÿø‡Ñ*Lƒ &ÑÛ¶m[•*UZ·n]úP˜aç1…B”1”ºzöìéîî~àÀ;‰2Á»F äøñãû÷ï7Z…i0A�áÙgŸ}ÿý÷KGÇ]ù¢ŒA¾�¿å(Ì‚ ŒÁ¾È¿óØWá¿ÿýï±cÇÚ+š†´ÉÕ 9k@þ¶­0 &¸”d_äßyì«ðÇLII±W4 i“«rÖ€üm[aT�A:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\ÝÐj@6äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡ü 5L!ÒAÈÙ¼ÍÒròãŠÆ`´„�÷–6¹º!g ÈßrfAÍ•$¦Pˆ”ÉÕ 9k@þ–c C‡íÖ­›Ñ*Lƒ£Œ¡råÊcÆŒy衇Jªzõê¥�£1bĈ޽{Û+š#�÷._¾ü‚ Z¶li´ÃhÖ¬Ù˜1cªT©Rš ;wî´oÿuìØ±ééév èLôíÛ×h fBöc� ²gÏžØØØaÆÙ%ZHHHJJÊñãÇíM¡Ð‡ÿüç?+VlÓ¦�ÑBnbêÔ©o¿ýv|||�:uŒÖâXÕcPÜ5�;wîܹ³½¢½ð 7nܰW4…Bzöìi´—Fõ …Â*.]ºtéÒ¥† zzz­Å±(cP( ÅM8j¸ªB¡P(LŠ2…B¡PÜ„2…B¡PÜ„2…B¡PÜ„1Æ0}úôªU«æääµÂœ9s´O?ýôÝ1{ölÿ»û­B¡P¸2ÆÃÆ�Ÿ{î¹Í›7µB�1¬[·î.â_½zuïÞ½*T¸K}ãPOýá‡Ú¶mÛ©S§-ZlÙ²åîUº$MÍáÇCBB:vìØºuë�;wÞ½J…„îìÝ»wĈ§OŸîÓ§�âäÉ“�:u éܹsRR’bÁ‚^^^�:uzýõ×k×®-„ˆŽŽnÛ¶mÛ¶mCBBŽ=ªÅ©U«VXXØ<0wîÜ[Š˜0aÂþýûµß:-Z´7nܺuëŠZ¡4[���­}HJJªW¯Þ]ÇqMšš‹/¦§§ !âãヂ‚î:ŽðÎ;ïT©R¥ ­ÞÎìÙ³µO=õÔ]ÄŸ;wnpp°¿¿ÿ]ês 0†aÆEFF !ºwïž””Ô¹sç;vh_åççk v!íCûöíüñG!Ä/¿üÒ¡Cí«Š+ž9s&55µAƒ…ãÇÆÆ8P”n?”÷Üs'NœÎh ŽöT!DDDD›6mªW¯åø rtH�ªoß¾kÖ¬qðÖÈ‹nì|G›ÐÛV­Z5mÚ4íóõë×[¶lÙ¹sç]»viKŠÚ…Úµk·wï^qó.T°Î-ÆðÈ#�hÆãííÝ¿‡nŽžèà©—+W®råÊC† ™6mÚäÉ“½½½¿øâ‹5jýúõ íÒ¥‹¶æÂ… G�åîî,Y²¤ø""##µ���ëׯwÔ–èΆ FŽ9uêT ##£S§N÷ßÿîÝ»»ví X,­~n!((èçŸnß¾ý¾}ûî½÷^maQ³=ggg{{{+VLMMuÔ–8:¤F1räȺuë¾úê«ÛÙÉÌÌܶm[bb"péÒ¥Õ«WŸ8q¢à- w¬d &&¦cÇŽ@HHÈ™3g´…¾¾¾õë×rssõ�n:Œv&…µtëÖí·ß~+øo�=Ö¬YÓ¡C‡���.]ºhýh!Ę1czôè®�ò:tè‘GѺÒÑÑÑÚ:Eu¶>þøãN�:µoß¾uëÖÛ·o×a£œR³qãFí I§N�ºvíªÃFIˆ× pñƒšDO¡P˜ƒîÝ»‡‡‡·nÝZûohhè�!C/^œŸŸ_øzCXXXLLL—.]>úè£ÄÄÄ?ÿü³ðõ†&Mš���ZÏ£^½zçÎ�+\Ê—_~¹téR­37|øð�ê¼™2 ŒA¡P(7¡¦ÄP( ÅM(cP( ÅM(cP( ÅM(cP( ÅM(cP( ÅM(cP( ÅMü?�Ùå^yV4IEND®B`‚rsyslog-8.2608.0/doc/source/PaxHeaders/queue_analogy_tv.png0000644000000000000000000000013215132411300020647 xustar0030 mtime=1768559296.190884438 30 atime=1782715518.811789231 30 ctime=1787067791.790676529 rsyslog-8.2608.0/doc/source/queue_analogy_tv.png0000666000175000017500000004445215132411300020326 0ustar00rgerrger‰PNG  IHDRë8ô;LwsBITÛáOà pHYsÐй‹çŸ IDATxœíÝw\S×ßðOKöRQdƒ7ÕZ«­J­uÕ]·uàh뮥\m©¨ÕÚV­£¿ÖV[[«m]åqTqáAPA�d„™�óüq1 ! ; |ß/ÿ8Üœ{ï ćs﹇Ç!ºC$Â’%HLĹsÚn !ºŽG NtKa!‘›‹‡áâ¢íÖ¢Ó ´ÝBÊ25EPÃÏ?k»)„è:Jp¢{F�@ NÈKÑ( Ñ=4�BHÕPœèH!¤j(Á‰N¢�Bª€FQˆN¢�Bª€úàD'Ñ@ !U@ Nt ¤ò24ŠBt ¤ò2Ô'ºŠRyJp¢Ã†h …� Ñ( ÑaÝ»#2< ¤¢õÁ‰ @)„T„œè°ž=K ”à„hB£(D‡=x4�BˆFÔ':ÌÝ ¤¢%8Ñm4�BHÅ(Á‰nëÑ£´p´ÚBt%8Ñm\ÜÛ¹¹01ÑvkÑ-t%“è¶¼8ÑmqqÊøp÷®öšBˆÎ¡'ºMíæ�;Zj!ºˆœè6µ ˜ 7WKM!DçP‚ݦ–àr9®^ÕRSÑ9”àD‡åä &F}#ÝVHÈ ”àD‡EF¢¤D}#%8!/P‚¦1¬/_ÝKJp¢Ó4Τ‹ßàM!DQ‚]ÅX…ÏB¡�BP‚݇ÌLÍ/ÑS®@ NtW%1M}pBP‚ÝUILß½Kóz%8Ñ]•$xI Íë!”àDG©Îåáñ4T �B(Á‰ŽR�Ë£q�cJpBA‚ @ÛM õ@5 ÍÍ5T y=„èo‚3°£8êWà·kµÝRToDQMp ‹ÒÍë!D¼4»süFlqgÁ�ð›ábˆµÝ(R§Ôæò¨&x‡Ê2 ¤�&OŸ\™ÝŸ�¸ûÅ]ó‰æþ_ùçý�÷9>×vÓH�R�Ëck[fÜ×WY¦y=¤ÉÓ�WËn§±N;Cvf8e|mø5Ï�GÝðÆF5š¹…êTœúà¤ÉÓõטÝ�ÎÆlc àͱoR7¼±Q�fµo×/>´4¯‡4yº›à•g·¢ZˆauÃÕ/,,sÏIf&,-KË4¯‡4y<¦{·d1°_ñë'9ŸÜÝ}8ÍpZå´j*¦ª·ª!²!'–ŸX¾ey(B¸©¤îåäÀƦÌÂÍš¡àÅ=£|~™—Ö­ÃÊ• Ú3ÓZ‚ëHv+„P7\ï¨Íå±±ÁÙ³èØ –y”Uj*Þ{¢¤††�ÉJ·ÿ÷%8©={û‚àà[ ÞÏ?÷Ìj°cmÇÁµ5Þ]9 ×?jsyâã1gärlÙ‚›7•ÕF�Â÷ßÃÐ àƒ”Ûi^i’jžàrÈu0»Bè¦ý¢6—ÇÆ;v 2={¢¸Xù’L†I“‹/¿Ä€Êít1“4I5Ea`31óÏœ?Ÿí~¦ c&•ކ¢‹—D$j»9äe4ÎåéÜ/ÂË ¥[ÄØ±¥en^�\¼˜×Sùí+„TGPÐÐú>ůåjÒ_„EßF}ûlÖ³VSZéT¿[ÕZ¬='=‡,<ŽyLÝp=PÑ\¯Ì})ª×zh^iòª�àÛ±=ü`8l7,°] ›Ù-”W‡¯.X_SæšÕèi8ÕšË£Šæõ�¦­z ¾ÛƒÃÃ�‡£6>ؘ‡¼zjY (²;ocžu�õ¶uÛà C6C3m7�TªZsyTѼÒ´U#Áñ½óÝ�GqÔ|йx�x'v¾|Ïú§šÝöAö_¬û"Ù5y*¦j»]¤jªø8”òÊÏë!¤)©j‚«Æ÷,̰\°\ºáå³;É5iQ¿[‹®]»V½ÔÖå©:Z¯‡4mUJðòñ `9–k·NÙ­³RRRz÷î}êÔ©*ծʺ<¡õzHÓöò×ßmuÃ)»u\PPPaaáÀ�«”ãªsyŒ�!•VãL±±xüXù%Íë!MÌK¼’ø†6ºá”Ýz�Çã}òÉ'.]ºôòW�Ýâbtìˆ1cý’s$%aêTtèP¦&õÁISY‚Wßœë†Svë—   Î�;så—ä¸ÚeLcc> ?¿ s<= ÂÛ{÷‚ÏÇŒ´^©Äÿý·aÆÜFúÁ¨0Á«ßh�n8e·>RtÃ*ÌqÕ_» 8¸LŽçç++|ý5Üݱu+d2LœˆØXìÞMózH%zôèñ믿º¸¸¬[·.;;[ÛÍ©k¬œóìü86Žw�ÇûoÛU¾‚šPŠm°M°•0ÉK+W˶F�+ÀV`%ìÚÁ¾ÈgùUß=�åá8L™Ü¾}›1&“É¢¢¢îܹ£(ß½{—1&•JÕÊÑÑÑŒ±ââbE¹¨¨(***&&FQ¾wïc¬°°P­Ë+((P”óóó£¢¢âââåû÷ï3ÆòòòÔÊñññŒ1‰D¢(çææFEE%$$(Ê<`Œåä䨕>|ÈËÎÎV”³²²¢¢¢=z¤('&&2Æž?®VNJJbŒeff*Êb±8**êñãÇŠò“'Ocjå§OŸ2ÆD"‘¢œžž•œœ,—Ëýüü4~êzõêõÏ?ÿ0ÆXv6ãóÀÆç³œœÒ^r2 f¦¦¥/©þãñØÛo³»w•?é™3•¯®[W�OiþüóOîƒgmmòüùs�ÕnÞdnnY¼Pþ£Wçÿçê×ïéÁƒ5yk|:›Ž?�§ðfÞ…¬°*G1—˜c¶°-5i‚&µÌnNËÃQ …Œ1îׯ¥¥%c,33€­­-cL$ppp`Œ={ö @‹-cOŸ>ЪU+ÆXRRÆØÃ‡¸»»3Æîß¿ÀËË‹1vïÞ=íÚµcŒÝ½{€¯¯/cìÖ­[:uêÄ»~ý:€.]º0Æ"##tïÞ�1ößÿq¹Æ;þ<€ÀÀ@ÆØ¿ÿþ  _¿~Œ±3gÎ0`cìŸþ0hÐ ÆØ‰' <˜1öÇ bŒýöÛo†Î;r䀑#G2Æ~úé'cÆŒaŒýðÃÆ�Ï;pà€I“&1ÆöíÛ`Ê”)Œ±o¿ýÀôéÓc_ý5€Ù³g3ƾúê+sçÎeŒ…‡‡fŒ………X´hclòäÉ•ô:vìxë믕g??õ!—ãÊ:ìòeõj{ö(+ RÝÏ i z¨ÜãdiiùñÇ‹Åbµ:ú˜àFQ,`�KÀAÄ}'LNÁ”|ä—¯¦ªGÃëxÌ„/®'ÈçóýýýU˾¾¾ ýýý;tèÀÈÈHcÙØØØßß¿]»vjeÿ¶mÛ055õ÷÷÷ññÑXööö`ff¦VöòòR”===…B�essswwwµ²………¢liiéïïïææ¦(»ººª•­­­ýýý]\\å6mÚ¨•mllüýý���ØÚÚª•[µjÀÎÎNQ¶··W+;99¨dðÑÅÅeîܹ>))ÊMåïoÙ[·¢kWå–íÛËÜ>X~Gš×C4 Q”³³³×®]ëêêºråÊŒŒ í5ª.”õ#ì>AÖÁ1Ó�OaøÔð=ö^Ë«äWAí»áuÒïV•Çòð'šE6«ÍAH�eeeY[[—ÿȹ¸¸ìÞ½»¨¨ˆ1ÆVvHöíÓ| ^½”u®\ÑPA.g66Ê:qqõø®ˆÞêÕ«WùO£P(\ºtizz:k4}pŽ|R¬S~\ú£Ï|ÙAÙ¾5û,“-+é�צN×*¥­[·>þ\u —Ýqqq3fÌ066®Õ\U5š×#—ËKJJ0ÆŠŠŠŠŠŠ¸�yyyyyy\9++‹|“Éd"‘H,�J¥)))éé銋‹“’’RRR%$$ýå—_._¾ ))éÿûߥK—<|øpÿþý.\¿gÏn€.66öë¯¿Žˆˆ½}ûösçθ}ûvXXØÙ³gܸqcóæÍÜÀ]dddhhèéÓ§ü÷ߟ~ú)w-úüùó«V­âôÎ�;·téÒ¿ÿþÀ©S§/^ü×_8qâÄüùó¹òï¿ÿþþûïså£G�NŸ>ýäÉ“~úé§É“'s僎7Ž+ïÝ»wÔ¨Q\y÷îÝo¿ý6WÞ±cÇСC¹ã|ùå—ƒ âÊ[¶léß¿?׆õë×rm éÑ£Ç?ÿüóé§Ÿ–ÿH$’M›6¹ºº~ôÑGb±ÖW«­ò¡ÎõÁG²‘Ü—%¬äGö£O¦ÏKûã5è†×y¿[õÁµH­^¦ß­pïž²7bkËärÍÇziœ1¶f�¢NÆ{ï™››s-RSSMMMÛ´iÃ{úô)ŸÏwvvfe/lpÙZõ QQQ¨Ý…�W_}•UçÂÆ[o½ÅöÂÆ¶mÛ éÂÆgŸ}à£�>bŒmÚ´ À²eËcëׯ°råJÆØš5k¬^½š1ÆÝ�´fÍÆØªU«¬_¿ž1¶lÙ27ndŒ}ôÑG¶lÙÂ[¼x1€°°0ÆØ‚ „‡‡3ÆæÎ� `ÇŽŒ±Ù³gصkclÆŒ¾ýö[ÆØÔ©SìÝ»—16iÒ$û÷ïgŒ�?À¡C‡222x/‡íêêºmÛŸz×ù 0ƒ1£¬Gý¼ôç�ç!±»c÷í;8íà§ ;°CõÁ­ËËW´X±ñÁÆ÷Ýß@Pùa×bí&ɦ¼=yH‡ý4ûå®Ëgc6uº EÜÅÅeÅŠ“'O66.÷bµxm›W ¿v-77×ÔÔ”ûª°°�ë_óx¼’’®ßÍãñø|>ŸÏÀçóMMM¹ú|>ßÜÜ\(044´±±±´´äÊŽŽŽ¶¶¶Œ��[µjåèèÀÄÄÄÅÅ…ô755õôôlݺ533³víÚq„BaÇŽ=<<XXXtíÚ•»øaiiÙ³gOµµu`` waÆÎήÿþ;vààà0hÐ Í›7:th×®]´lÙrøðáݺuкuëQ£FõìÙ“ûn�7Ž.pss›�+·mÛöý÷ßçÊ:tæÊ;v\¼xqŸ>}tîÜyéÒ¥ÜöîÝ»¯ZµŠ+÷êÕëÓO?åŽÿÊ+¯„††rçíß¿ÿ–-[¸«…477çʃ¶··ïÞ½;€·Þz«uëÖFŒáå厗wß}×ÏÏ�›=0a„nݺqïwÊ”)����:u0sæÌ�r±æÎ�ûÖ[oq¨.\8zôhî{øÑGMš4‰»È´råÊY³fq�>ýôÓàà`ww÷ÐÐP¦é‰‡‡ÇÇ<~üø;wøaaúv»aùPW냫zi¼*Ýðzíw«¢>¸¶ppÍýnUªw®YSaµªôÁ³³·¬Èù|Ijj~~>cL.—I¥R®–¼¢n>iìÒÒÒÌÌÔ× pssÛ³g�âãѨÆÁ5âúãÑÖÑ��W>NãÝMıcÇ6mÚ¤ﮈê€õ®]ؽEE59ßÍ›˜>½t¹5€WR"ˆŽnÖ¬�glllhXú·f%D“Æí³Ï>ËW™æââòÍ7ßÄÆÆN™2EññÐG5Ye­’_€§hRv7)“&MzIv£ìº<RR0kÜÝñå—e&aVîÒ% ‚.]ðóÏàó•Ûé)DEFFÆÎ�¥‰äìì¼k×®¸¸¸éÓ§i·aµWóµê5æ¸E²EA8)»á”ÝD3Õuy|}qø0:uBr2-‚‹ BCQùèÓ§ñê«èÝ'N@ À‡â³Ï”¯R‚Ÿþ¹D"iÕªÕŽ;îß¿?kÖ¬—t/ôGmÿ|(�ónÑ]L‡ø²x„ûˆIDážBºVI4P Ù^½0jFŽÄ‰ Å¥KX¹›7cÞ<,XPf/ÆpìBC ÖÖFp0ll‹E‹J«qózhÌ„b±ø×_ Ÿ1c†âúvUÔ~!ùP7@ê9þu,†ãïð¿ñ ö3µ“ÝrÈ·ad yNRå×åáñ0d† Á¿ÿbýzœ>�õëñå—°´TÖœ0 àèˆÅ‹ñþûÊE5¹õz¸G�sëõxy5Ð{!:,++ëîÝ»z=Ø]‰š�¢h:–ÁŒ‰±ŽùqÙ�<9B|°áƒ§®Ox̤%‡pÈ[ì½lÝ2܆k[×;5©ªÊçòôë‡S§på Þz ùùP�yŸ�gglÛ†G�°dI™5‘i½¢‰»»{c�oÔm‚sxà�Á�S,Æbc4Üx—Ý>bŸ ¡v&¸ÍrÛ·jß-á­k©*Õuylm5w–»uñc¸u vvÊ�«V!!óæ¡™¦>�ÚRiìɯ¦”üˆCÄ! _'@·Yn«íW�ÇxÃÆò›ªÏåñõ…—� B%÷¨&8õÁIõ=zdùÎ;ƒU·””ÔüjŠ¡!“É4ïn`ÀT?õ%%¼éÓktŠ5L‡Pvë%Õx­ñãPÊëÖ ¥7†sëõ¨³R©ŽQPÕ‘‰ ØíÛ‰'Þ«Ùß{ïõ�?Žôöî +ë”PXºì¿ÿ:%'·?t¨LFÕìÎF=Ž9Ên=¦¶²Z]±°@ûö¸sx±^OÿþuvpÒØñx01)³¥_?Þ¯¿ÚÉk|̜㘘›#/ϬmÛÒ½ÅÇÛ b¨v®š©ûqð >Þ=Ãmߪ}qöq“1™â[¨ÎåáóÑ­[]œRHÝéÖ ‚ââZådBbcËl‰�µéÝ»V Sг¼£~wc :—§mÛ:èèÑ»w—–)ÁI혙ÁÛ[~î\«V­$+$%™3¦y¤»U+ cÈÍ5nÞü*©Ô :Ú†+dd˜øúÖM õ&ø(»Õ`}ø;wbúôŽª‘HJ‡P84¯‡ÔÚ„ ¿üÒöúuͯFFº¸ä–ÿˆ%&šûú–…¼óçÛ•Ÿþ9iS}DmèAüQv76ª7¢äçcÎ|ñ֮Ř15OÛÂBì܉�‘ž®ÜHózH­-^l°xq…£(¦¦lË– åÊçÌyýçŸMÜÝÔQTW@§ÇÁi¼»R›Ë³};ÚµCBÆŽE×®øûïj°¸»vÁË#=½{—X§�R§¤R´i#oݺ„ûW\¬¹ÏÁëÓ§´Ž³³<:º¾ÚSa>ÁdÚ Jêw7ZjsyæÌÁìÙØ¿!!¸qo¼�W_ņ –3.O&ÃÁƒX³�@—.X»o¾‰µkKŸšàòeLž\?ï„4EŒáÙ3Þ®]ç[ 5Ü©²nÝÅ�ä¡¡½Š‹ëkRº†@4‚zãÊÂ+Ž —º.�‹¹/]p§Qv7råçòðù˜2cÇ⫯Šsçг'†ÇúõðñÑ|¹‡#$qqСÖ¬ÁÛo—ÂÐí(¤>Éå¼S§œ«^?+«³‹Ç4-;t§W¬þoïx ›©6K=ª�ãüX¾ü†ž?§y=¤®””`Æjï5}:š7¯‡Ö@Ó*k §Ø©žù=±X›x›Ml“„IªºöÏ=B2K®Je“d=2<°X ·t·}lŸ”I«x.¢O|}•kL�>­¹Î³glî\flÌÖ¬kÙR¹K»v¥¶g“Vð!Q=Ë™3õ÷nѮʜS³¯b‚Sv7-ÙÙŒÏ/ V>ŸåäTV9!��§XýRùÏɉíØÁ*Y~“•]�sݺº}„莗'8§º9þÒ§ìnŠN�R«Ÿ_•v¹y“Y[+÷Z°€åWa]ì={”» RËV“¦F nedÁ ¯¿þúæÍ›U«­X±bøðájû^¿~=00ÐÌÌL(úúú;vLã)âããAí›ZÕçT=Ç+IpÊî¦kÍe°ÎšUÕ½ª²V½š{÷”»ØÚ2Z¢žTŸZÈ~ÿý÷�:uR|)—Ë]\\Ž9¢º‹T*mÞ¼ù×_]\\,“É®\¹òÿ÷U9x�U/Á9UÉq� NÙÝÔ ¬ Ö}ûªºW \.g66ʽââjÜdÒd©…lnn®™™Ytt4÷å… ¬¬¬ UwIJJ244”Édj‡ÊËË›9s¦­­­••ÕÔ©S \]]üää*]/Ô¨&3z`À¥f—NÍ9Õóãž™ÿd.]±Ô9Áy36sKkDssÈKÖå©[<”_Ò=…¤Ö„Bá°aÃ:Ä}yèСQ£F™”}À “““““Ó»ï¾ûûï¿§¥¥)¶Ï›7/???11ñÉ“'b±8$$äŸþ‰D"‘´lYÕö4¨qös*ê�+úàÔï&¥TG66|8»v­J;V·ž“Ã6nd�r¯Ù³kÙvÒ•èøóÏ?]]]cR©ÔÎÎ.""¢ü^‰‰‰³gÏöððàñx½{÷Ž��ÏÏÏ766‰D\…ÈÈHwwwmŽ¢”§šã–ñ–›Ø&.Á¿b_µÉhCÙMclï^e¤rw¤ðxlð`véÒKv¬z‚gf²��2ã'Ü¿Žëð}�&¢|ÈJ¥R‡‹/?~¼M›6òJ¯¯¤¥¥�?¾OŸ>‰‰‰,_°°°°³³Ó­ç¨æ8îá ì&Jªwø-[Æ–.eææ¥_¾ö;{¶Â«’àéélùrfaQZ­_?öûïÊ;_zç"!åh ÙùóçÏ™3gìØ±Ë—/énݺecc#‘HLLLòËÞC•�� s Î9ÅNõ,ì‰`)ÚˆÛPv“RåçòˆÅlõjåÍ‚½{³“'5ìXy‚§¤°Å‹•c&o¼ÁΟ×pFš×CªIc‚_¹rÅÖÖVõ’¦*‘H´~ýúG�1Ʋ²²fÏžýúë¯3Æ&Nœ8kÖ¬¬¬,ÆXrrò™3gÄb±��AZZZ-Y÷ ÎéÈ:z2Ï$–TOÇ'z¦’¹<ÙÙlýzfo_új×®ì·ßÊÜÿWQ‚'%±9s˜©ié€Ì°a,2²ÌIi^©…Š:¼¼¼üýý5î’““3vìX''§fÍšY[[�1âéÓ§Œ±¼¼¼yóæ988…B//¯mÛ¶1ÆæÍ›gaaaiiY›{Qê+ÁåLÎ+a%õt|¢g^:—G"aŸÎZ´PÖùé'VR˜¦��gÓ¦•N»70`£G³[·4“æõ�Æ®¾žÎ€�n?œ4œ—.m,`ñb<|ˆíÛáìŒÛ·1f Ú·ÇþýP}øZb"&NDÛ¶øî;Èå˜8ÑÑøé'øùi8¦ê‰¸õzi\4?›��:6dNœ(-ïÛ÷’gvcÿ~l܈ÀÔ……¥/@.‡±1&OƲeps«ì8ŒÁÎNù8ò¸8Z¯‡42ÔG&õ¯ºsyŒ�1}:bc±?Ú¶UÆ7##Ì›‡„ìÞý’øÀã•Y)‚æõ�F‡œÔ?µuyªØ64Äĉ¸{ÞÞÊ�¿ý†mÛкuUO­6�BHãB Nê_ùuyªÎÀ¶¶Ê/mlªwjZ¯‡4j”à¤þ©F§©)¤Ò†;µP¨ü…q÷.rsîÔ„Ô?JpRÿTüÈxzbûvÔïI¯\ÁÛo£W/å-(%%¸zµ~OJHâ'õ,'11¥e´k‡¤$ÌŸlØ€ììº?ãéÓxí5ôè�cÇЬ:tP¾D)¤q¡'õ,2%%¥åp÷.~û°nÑ IDAT Ý»#=+V M¬X�ôô:8‘\^zä×_ÇÙ³°²ÂÊ•HLÄâÅÊ:”à¤q¡'õLm.�‡aÃpù2ΜÁ€ÈÎÆ† puEp0?®á)d28__ ŽÈH4oŽ�‘”„uë`oOózH#F Nê™ê�(ªaÚ¿?N�Bd$†Ga!¶mƒ‡¦LAll5^P€¯¾‚§'&MBL \\°c>ÄÒ¥°°(­ãí­¼ƒE,F||-ß!ºƒœÔ§—Îå ÀÑ£¸s“&�1ìÛ‡öí1r$®_É‘sr°iÜÜ0w.Ñ®öïG|<æÌA³fejÒ¼ÒxQ‚“úTŹ<íÚáûïKó×ÄGŽ kW „ˆ •E"|ü1Ú´Á²eHMUþ˜8†¬ØGózH#E NêSµæòpc �•Ž�üóúõCïÞxþ\Y', ..X·YYeÆa *ý$Ó¼ÒHQ‚“ú¤—U\򯄱ÌuÈK—pïžòÕDAA™k¡UÑ­›2âi^iDj˜àB¡P( �'|aàÀ�[¶lQ­¶råÊwÞyGmß7n¼òÊ+�ÀÜÜÜÏÏï÷ßOHH …Õj·ËÇ›7o^³·@ÂK*[++Œ�4tÛ[·ÆøñèÖ­G³°@ûö¥eš×C‘&¸D"‘H$·nÝ’&L˜ðÃ?(ê0Æ~øá‡ &¨î(“Ɇ 2a„¬¬¬¬¬¬o¿ýÖÚںƭwssKMM­ñî¤~©Îåáó«‘¹b1/†�þ÷? 7ÿ=~ŒÑ£Ñ£Î�«Fch …4JµYBm¢ÜÜ\Õåã.\¸`eeUXX¨ºKRR’¡¡¡L&SÝèêê @ ‚äädÕê–322†*¼¼¼vîÜ)Ô�‘‘1bÄ [[Û… J¥´>§V©®ËchÈÂÃYQÑKvÉËc¡¡ÌÒR}±ùŠþ½ù¦æÕyÔ\»ÆÚ·§õzHãS—ãàB¡pذa‡â¾Õ^ P–Õî69yþþ˜<IIšÛ�1c€èhåFš×C�ÚÄù•@ÿüóOWWWƘT*µ³³‹ˆˆ(¿WbbâìÙ³=<Ÿ¯XûùäÉ“ÞÞÞµyw¤¶Vv{-b~~Ê50�/SóèQæã£¡‹íêÊd={*·9ÂÆŒa<žzM¶x1ËÈP39™ÍšÅŒŒÀÌÌØ²eÌÚZY?.®�¿„Ô‡:Np©TêààpñâÅãÇ�·iÓF®ºâx9iiiãÇ�ïÓ§OUüÑ£G¦¦¦Š:÷îÝSKðò¬¬¬jóîH­ÈåÌÆF™˜±±¬¤„íßÏ\]K·² Øùóe2Vü³³c_~Y:êR~¥ã«WÙk¯iØËÊŠ…†²”¶l33+½™5‹qk�¿ù¦²æ¾}ÚüæRGêønBCCÃ1cÆ:tèСCãÆ�ãUzÿ¯ƒƒÃ’%KbbbÔª1Ƥ¿x摽½½T*U|™Tî¯f;;»ââbÕ ŽŽŽuò¦HM”ŸËc`€‰‹­[áà€óçѧqéR™¬Z…°`Œ�5¼kWœ>�¿þB§Ne¶geaÅ ´j…�QP€Ñ£�]»À ÍѼÒèÔýýà&Løé§ŸŽ;¦v '###44411@vvöÎ�;»tébmm]PP _'''�@ðÛo¿…‡‡sAPPÐ’%K D"ѺuëÔŽ, ‡ ¢¨2vìØ:w¤ª*šËclŒwÞÁ AæàbÖ,ÄÇcíZåSM*1h®_ÇÁƒpu-³�gwqÁرef�Òí(¤Ñ©ûïÖ­›­­­··w»víÊ¿jbbr÷îÝ>}ú˜™™¹ººŠD¢½{÷ÚØØÌ™3ÇÓÓÓÊÊ*%%…Ï燇‡O›6ÍËË«W¯^Š}wïÞ-‰ìííÇ�_þàß}÷]NNŽ£££��O@@ÀŠ+êüÝ‘ªÒ8—çùs,] //8 ~=ÓÀãÇcíZ´hQ�³`Ü8¬_õ—=ÂðáèÝ.”n¡y=¤ñÑö0i¤|}•ƒÎ§O³‚¶eK™‘qÅ¿îÝÙ›o2>ŸÌÜœ}ú)ËÉ)s¨òãà §O³€€Ò—<=Ù;ï0�@Ã)Þz‹q7¹ª¶êÌ™†ûnR?hV=©jsyâãáí��>RŽŒs|}qü8._ƉˆŠBPrsñÉ'ððÀ¶m(.®ìׯcà@ €«Wáä„Ý»ƒ#G�™3Õo:üýwøùaútøù)7Ò@ i´ý+„4FªsyLM5tŠ��ÙÞ½¬ìÄ.Æ»p�*o%ù�©¿dhˆiÓ°z5*ž¾[ÆñãX¾wïjx).®ÂG–¢hœÔ5µuyðxèß±±Ø´©Jñ ”¹yÜÈH¹}À€2·xWÅСˆŠÂ¦M(ÿüK 'zŽœÔµÇ�Õ¯X2†³gñÆ8p2Y5elŒà`té¢Ü²~}µ{Í11˜2+WB"Qé¥k¹¢Û(ÁI]kÓ—/#(H}ˆùÞ=Lš//ìÚ…¢¢j°òõw*qãFŽ„¯¯†ß­[#<›6ÕðÈ„èJpRºwÇï¿#* ï¾ >¿ÌK�áý÷áæ†/¾@^^}5à Œ®]qäˆúÔ!OO|û-0¾úšÈ„èJpRoüüð¿ÿ!&S§–Ë�’‚>P®xY‡þù}û"0'Oª?BÖ×?ü€{÷0mZ…O\!D¯P‚“zæå…ï¾CBæÍSïófdàã�áâ‚+ðâ©85$—ã·ß€Aƒ4Ü>Ø­Ží[;VýoBô%8iÎÎØ¶ �aɘ›—y);6ÀÕ âéÓjY&áCðóÃðá¸vMýÕ~ýpê®\Á[oѭߤñ¡' ÈÑ›6!) !!°±)óR~>¶n…»;fÌ@BB•ŽV\Œo¾��&L(³C†àâEœ;WÕõì ÑC”à¤ÁY[ã“O�”„-[мy™—Š‹ñí·ðñÁøñšçàpq?s&<(ó’�F�Â�8~*¶$¤Q¢9™D« ±g6oÖ°Ð%�‡aðb.T®qæ ®\AXD"õúFF7Ë–ÁǧޛMˆn ':@*Å¡Cظqq^µ²RÞ¯bn®á¹Þ¦¦˜2K–ÀÅ¥^›Iˆ®¡':C.Ç/¿`ÃDEUu¡³fც·.!�%8Ñ1ŒáÏ?ú’‡–X[cþ|ÃÖ¶¡ZFˆÎ¡'ºêÜ9¬_�3gÔ·;:bÑ"¼ÿ~•ÖÒ$¤Q£'ºíʬ_�ãÇÁZ·ÆGaútš O‡œèƒÔTüø#æÏ§•„¨¢'„}E3z!D_Q‚Bˆ¾¢'„}E N!úŠœÔJBB�Ç …fff]»v½yófµö …>l®ö|« …B¡P(¸3rjÚpBJpR[�@"‘H$’¡C‡Îš5«º»»¹¹¥¦¦V¥&w–[·n)Î()¿xqí×í ©W”à¤nŒ1â�ʳ^ÃÃÃ���AïÞ½¹�b±8((H(z{{Ÿ>}/z⊽ÄbñÈ‘#---íìì-Z$«tm{�•¿ùæ›qãÆ�J¥�`Íš5îß¿ïää ??Ö¬YvvvÖÖÖÓ¦M+,,äîääTƒß@„h%8©2™ìðáÃ�:uRlñööŽŠŠÊÊÊòòòZ´h·qæÌ™ÖÖÖ"‘èÂ… (œiÓ¦™™™¥¦¦ÆÄÄ\ºtiÆ •œTcåÀÀÀóçϸqㆣ£ã… œ?>00À¼yóòóóŸ}úœ?þüùó}ûöõóó»yó&×OOO/..öðð°²²²²²0`@vv6333KKË:ùnÒ�(ÁIÝ077ß²eKXX—‰YYY³gÏÞ·o_vvvDDc €½½½T*M±,}R¹uyìì슋‹U+(â¾¼J*FDDܼy³K—.���‡‹Å¾¾¾vvv&&&Ïž=ËÊÊÊÊÊÊÎΕ_ë‡ýA NêLÇŽ;vìÈuË‹‹KJJlllŠ‹‹·nÝÊUAAAK–,)((‰DëÖ­S;‚P(2dˆ¢BHHÈØ±c+:]%•þùg##£W^ye×®]½zõ200£G�^´h÷k&%%åìÙ³õò½ ¤AP‚“º4wîÜ;vÈår‡¥K—véÒÅÇÇÇ××WQa÷îÝ"‘ÈÞÞ>00püøñå�ðÝwßåää8::úøø¬X±¢’ÓUTÙßߟ1Ö§OR©”+صk—‘‘‘———¹¹ù«¯¾Sgož�GÏ&$„}E}pBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+Cm7€�—))Az:22 A$*-äçÃÑöö°·‡�]iA Ðv[ iP”àD'=x€Ó§�ˆ¤¤Tu/¡Ý»£o_ €=ÀãÕg Ñ>cLÛm ä…çÏñã�Ø»W¯*7òùppPv´¹‚™ÒÒÊôÊE"äå)÷jÞ&`Ê´k×ðïƒ�†A NtC^BC†‚°¶Æo o_ôí oïªö¦³²pî""ð÷߈�-ÝøúëØ¾^^õÕrB´‡œh›\Žýû±reéhÉk¯aÆ ¼ý6LLjuØ«W±w/~øÙÙ04ÄìÙ �­m�4™Á fÁÚnƒvÌÆì¶h«íV4y/báB\»½z!, ݺÕåñÅb„„`×.Èd°±Á'Ÿàý÷adT—§ Zuò$nÝÒv#´ÁÛÇ`MôßIv’-JNfcÆ0�ÌÙ™ýð“Ëëë\ÑÑlРҟ¼³3;w®¾NDÜôéÚŽ-ý1‚1Æ ðÀ G¸¶£4œ�؃m·¢iûë/LœˆŒ X²~3³z<]»vøë/üù'>øqqèß~ˆÐPÒ½X�ÄàÁèØQÛ�h(÷ïãÈÅW Ì@Û¿GÔ`6˜úàZ#•²+˜�ØàÁL"iг—”°-[ŸÏÖ»7{ò¤AÏNê×ÿö[m·£=ªìƒÓœLÒ€RR0`BCa`€�qüxCÏÁ10À‡âüy8;ãâEøû㯿´„Ô)JpÒPNŸ†¿?""à䄳g±t©ÖfÜôì‰70d220dV®„L¦�–R;”à¤þ•” $ƒ!=ƒáæMj¹I¶¶øãlÜ„†bÀ€jÌü$DgP‚“ú÷Ö[øôSðxX»'NÀÞ^Û ðxXºgÏ¢eKDDÀÇh»M„T%8©.€‰ <=a c¹–-á๹HHÐvk©ûïD%>òóñ;EEÚnÐ GŽ KDEÑC ‰ž¢'õ�»bSS|õz÷ÖþxEq1,À¨QÈÎÆ¨QèÕKËí!¤F(ÁICyï=ü÷<=qý:ºtQ�“ÐЈðpcûv>LS{ˆž¢' ¨S'\»VÚó9k×¢¤¤¡ÛðóÏðóCd$ÜÜpáæÎmèRw(ÁIò°ÀáÃØ¾&&X½nnøßÿÐ0ÈŒ‰Áo`ôhäæbøp\¿Ž®]⼄ÔJp¢ sçâÒ%´iƒÇ�1núôAdd=žN,ÆüùèØÿ �Û¶áèQXYÕã i”àDK:wÆÃ‡Ø»-ZàÒ%ôè�É“‘œ\Çg‘J//lßóæ!) óæÕñYÑJp¢=xï=Ü¿�+`b‚ýûѦ ¦NÅ�upð¬,„…¡}{,X€ÌL „[·°m-ò@Jp¢mB!֯ǽ{5 r9öîE—.èÔ Ÿ|‚³gQ\\�C1†»w±cÆ�ƒ­-/F|<¼½qü8þú‹Ì$�ÝDEtƒ‹ Ft4¾ûàÖ­Ò•Wx¾ªGppÀ A4£FÁظ>ÛJˆöQ‚ÝÃã!(AA ‘àÉ“2m®�ŸGÇ2½r“¶[OHá'ºM(DÛ¶hKkR¢]É$„}E NÑ9r¹\ÛMДà¤&ÒÓÓ/^üôéSm7„4NsæÌ ËÏÏ×vCt]µÿüó¼¼¼Ú0""bذaÓ§OOKKËÉÉ ;}út]µ¶ÎU=Íj>ŠÂçóÇŒ‹}êððp''§Y³f‰Åâ‘#GZZZÚÙÙ-Z´H&“‹ÅAAAB¡ÐÛÛ[ñ½S팫–³³³'Mšdmmmee5qâDnc~~þ¬Y³ìì쬭­§M›VXX¨vÞ¿RÎÎÎï½÷€ÂÂÂððpww÷E‹¥¦¦j»]¤‘øä“Ox<€´´´?üÐÍÍmË–-5Îñ%K–lÞ¼yôèÑÆÆÆ}úôùþûï”+EªØÙÙµiÓæ¿ÿþSd×®]ÎÎÎfffÍ›7 Ó_\aëÖ­®®®W¯^ýüóÏœ��/_¾ÌU.e(—¢U|_5Op™Löã�?úøø(Ú””””””´sçÎiÓ¦™™™¥¦¦ÆÄÄ\ºtiÆ fΜimm-‰.\¸ðÒ¿_fΜ)•J?~œ‘‘1÷ÅœçÍ›—ŸŸŸ˜˜øäɱX¢vÞ¿R3Ë—/722âÊ_~ù¥»»û|�––¦Ý†‘FÀßßÿí·ßV|™žž¾dÉWW×Í›7K$’j*77÷êÕ«#GŽ,ÿ’ư*((ÈÎÎNKK›2eÊÒ¥K¹šb±xþüù¿þúk~~~llì€*:]AAANNNjjêôéÓßyç�¼¼¼ÔÔÔ3f,[¶Œ« 1ÊPÃ4c0`¬ÊâããXZZZZZöîÝûÎ�;ÜF�—••ÅËÍÍåóùiii\ý“'Oz{{K$>ŸŸššªØ(¸¹‚jY"‘**sòóó���E"÷edd¤»»»êy«n0 †Ÿ3NMM-**bŒeee‰D¢ââbÆXNNNff¦T*åZ’��-“ɸH$’’’ÆXaaaAAW......–ËåŒ1™LÆUn:¦OŸ^þ3efföá‡*>ÌÆ†ìùs­¶´Ro¾Éö×_Ún)#**Šë†«±··ß¸qcnn.clút°o¿­ì8‰‰‰&&&å·k +.UòòòcwïÞµ¶¶æ^ÍÉÉ155=xð D"á¶hŒ/ÕÝ£££UeccÃ*ˆ2V6E+wô(؈Œ1VÃq𬬬¬¬¬ .tèÐAñŸÖÒÒ@FF†‘‘‘·þ7àââ’––&‰ŒŒŒ+9¾H$244TT椧§{xxXYYYYY 0 ;;[õ¼Õµiü¦æÍ›Ÿ;wÀèÑ£ííí#"" >ÜÆÆæüùó† biiyñâE …ÜßA¯¾új³fÍ®^½  wïÞÆÆÆ×¯_Э[7CCÛ7oèÔ©�Çã®ôvìØÑÐÐðÞ½{üüüLLLîß¿À×××ÌÌìáÇ\ÙÜÜ<)) @‡¬¬¬’““´oßÞÖÖ–�hß¾½ƒƒƒH$âÊ-Z´xþü9WnÕªUNN€víÚµiÓ†ûc³]»vnnnÜßhíÚµóôô”J¥\ÙÇLJ»a«]»víÛ· —Ë}}}ýýýÈd²N�:uëÖ @QQQ—.]úôé    àÕW_ ‘Hzôè§è†+äççöÙgnnnK—.åZ«VìÝ;hР7nX²dÉ믿`ñâÅýû÷¿}û6€ààà~ýúݽ{Àœ9s^y啘˜3gÎìÓ§7¨8uêÔ^½zq?âI“&õèÑ#!!Àرc»uëÆý¸G�ÕµkWîÇ=|øðÎ�;?yòÀСC;vìÈýèßxã ___îGÿÚk¯µoß>==À+¯¼Ò¶m[±X  W¯^ÞÞÞÜÇ ÀÓÓ“ûtêÔÉÝÝ�û´oßÞÕÕµ  €———³³37ÌêêêÚªU«’’­ZµjÙ²%ÆX‹-œœœH¥R‡V­Z(,,´³³kݺ5€¼¼<ggg999VVVmÚ´ðüùs îwFF†P(tuu�ššjffæææ 99ÙÔÔÔÃÃÀãÇ����===<|ø�Ïç{yy¸ÿ>�Çóññ騱£Æ®®H$Z¶l™‹‹Ë† ¤Ò—÷ÇmllŠ‹‹sssÕ¶k +ffffffLLLCÒæææG�ýþûï�œœúöí{åÊ•ŠN§ØÝØØXõPEEE¨8ÊP£4«û9™vvvÅÅÅéééÜ÷%))ÉÑÑÑÞÞ^*•ªnä*s½`�Ç}:ØÛÛËd2EeÅaMLLž={Ö¬Y3ÅFî?Fۘ͘·hÑÂÄÄ€•••ƒƒƒ±±1 [[[.•„B¡••W633377çóùLMMÍÌ̸²±±±‰‰‰��CCCCCC®Ì{@IIIÉ‹åĤR©â3Áõåcòòò¸ßírss³³³¹rvvvff&W‹Åܯnééé\ùÙ³gÏŸ?çÊÉÉÉ999\9)))??Ÿ+?|ø°èÅ"ññññÜÅ \èຠ†††ärù­[·LMM¹ò�7™LvíÚ5 ®|åÊkkk�Ã&yyyÛ¶m344\ÿ²ŸÅ¿ÿþ»zõꨨ(CCþ}ûnÙ²…ûÞÀn$$üsýú‡~àÆ�gΜÉÌÌpóæÍÿý—Kɨ¨¨óçÏsÿånݺuéÒ%.1oݺÉeÄíÛ·¯_¿Î¥ç�;w¢¢¢¸»)¢££ïܹÃ%ittô½{÷¸rLLÌýû÷¹ŸNll샸OH\\\bb"W¾ÿþÓ§O¹_À Ïž=ã~‚]>ÌÌÌäʉ‰‰ÙÙÙ\ùñãÇŠ�ÖÓ§O¹äädîoMÏž=SÜ‚�ššÊ}¶y<žH$2~ñx±X¬øß÷üùsÅG(;;[ÑSÎÍÍåê3Æòòò¸� €‚‚Åǯ¨¨ˆ{SŒ1©Tª8Ž\.çÚ ú‡U¼~S³fÍ,-- Ô;å™››üòË/S¦LQÝ®1¬*9Λo¾ùæ›oJ¥Ò­[·Ž?þìÙ³åãë¥4FY-T%Ó§ZµIDATEñ‡CEƒ‚‚&OžœŸŸŸžžÞ£G���ÆØÛo¿­ØØ§O®¾L&³´´­—ŸDEÞ|“×·o?uê”X,fŒ)œ1vóæÍsçÎq¿#£¢¢"""¸ß¯\šs¿/¹4çþ®¿}ûöåË—¹Ð¼sçNdd¤âïèk×®q¿S£££oܸÁ…é½{÷¢¢¢ c±±±·oßær!..îîÝ»ÜàÞýû÷cbb¸ÀMHHˆ‹‹ãÊ<à~³?bî#‘˜˜øèÑ#®üøñ㤤$îGÿäÉÅÇ#99999™û<{öìÙ³g\9---==�+‹D"®£ —ËÅb1÷M�ËåÏŸ?ç¾ r¹<;;›{ãr¹\"‘poV.—çççsoP.—roJ.—s�gŒÉd2Å ®Uª*EqrrÚ¾};÷«Ê( cìßÿµ³³;|øpQQQIIÉùóç'NœÈ4…•ƱÆXJJʉ'¸ÿ°»wïöððÐ_í®Z.e¬‚hÕHu¥^<==}øðáæææ666óçÏç>‚éééƒÞÞÞ;wîTÔÿþûï­­­���·nÝªØøüùó±cÇr£í“&Mâ6æååÍ›7ÏÁÁA(zyymÛ¶M_¼±***âþ|Veaa±råJî¿}©J< à›o¾QÝ2gΜ÷ß¿¢O^^ÞÌ™3mmm­¬¬¦N�ÊeDµ*k@ãà:é�wÞQûtµlÙ2<<\õçXÅgŒ]¼xqÀ€–––� k×®dšÂª¢ÏÒ“'OzõêennnffÖ¥K—‹/2MñU•/e¬Á¼ ¯+»víRýßeiiùñÇs}Ø2*Npîp®7§áééYѧÊ”)&LÈÍÍÍÍÍ6lØÒ¥KYÅÿU4VÖ€\÷ܺuKµÞ²eË­[·–ÿ\õo4TœžMHj¨¨¨(44”+[YY-X°`Á‚ÖÖÖÕ:Hff¦‰‰ 7°® ¸Z[^AAÁ¡C‡’““¹{oW®\9vìØ�7Ö¾2Ñ5kÖ¬aŒhÑ¢ÅÒ¥KgΜYGÇ� %8©¡={ö<~üØÚÚzáÂ…ÁÁÁV5Zú�»I ''G5ÄÓÓÓ+úM ¸ŽÏ}É3®x‡jU&:åÎ�;¿þúkóæÍ—,Y2{ölÊîŠP‚“š(**Úµkך5k‚ƒƒkv7'ÇÂÂ" àðáê÷•ÿôÓOýû÷×xŸRE×ñ«U™è¾Ý»woÙ²eöìÙÜ­x¤"ôlBRb±øêÕ«üqm⛳iÓ¦eË–=z´¤¤¤  `ëÖ­?üðòeËœœœÁo¿ýVTTÎU£G�^´hw?_JJÊÙ³gT«2Ñ}[·n]¼x1Å÷KQ‚“šhÙ²e]�HôíÛ÷èÑ£[·nå·qãÆÿý×ÃÃÏ燇‡O›6ÍËË«W¯^Šú»ví222òòò277õÕW¹ 5ÕªLt7©‚TÝ‹Bê[•gÕß¹sÇÚÚzÿþý Ш2è^½ÕÄïE¡_tD‡tèÐáäÉ“OŸ>UÌß#„T‚®dÝÒ½{÷îÝ»k»„èêƒBˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœ4”?Dq±¶¡ÉÉ“¸xQÛ� ¤&(ÁIýûì3˜˜à»ïл7=ÒvkTcÑ" ‚œ  •‹¢(ÁIý›2—.ÁÝ×®¡sgüú«¶HJÂ+¯àË/ad„ðpüñÌ͵Ý&Bª‡œ4ˆÎ�qý:FŒ@VFŒÀ¢EZQùãtîŒ+WàêŠ 0¾6CHMQ‚“†bi‰_~ÁÖ­02—_â•W�”¤…fH¥X²Æ!3Æáúuh¡„ÔCrÈ=á©í–4œ¤h» MXp0zöĘ1¸r�;#43f ÁEŒ�Å„ ¸~FFظ‹�Çk S“ú´y3öï×v#JF†²\ºFO´ÓÒàæMŒ�?ÿÄìÙøê+„…¡ÿú=ir2V¬À�` ­[ãèQtíZ¿g$ èþ}Ü¿¯íFhï{ í6hGs47ƒ™¶[Ñ´=Š%Kðà¼ý6¶l�‡GÝŸ¥ ŸŽ�‘—SS,^ŒåË!Öý‰ˆ6$$ 5UÛ�Ð;;øø€ÇÓvKHVT„/¿Dh(rr`d„… ñÑG°·¯›ƒ3†_~Ap0RSÁãaäHlÞ —º98!:€œè€´4¬\‰½{!—ÃÈAA˜9Ö|�úöm8€ï¿‡H]º , ��uØdBt%8ÑOŸâã�±?är06FŸ>èÛ^^pr‚�ìíak«ë¹¹‰�‘‘))8{ý…¬¬ÒWmm±d >úˆ®X’F‰œè±{÷âÈ\¾¬áU¯4Ê…B¤¤ %¥4îÕ´h�áÃñÞ{t§ iÜ(Á‰®ÊËéS8s))Ê^¶X µO¬¹9ìíKc½yst놾}áí­¥FÒ (Á‰^a¬4Ê%´l‰–-î^rBtÏÿª«S�ÿ#VæIEND®B`‚rsyslog-8.2608.0/doc/source/PaxHeaders/rsyslog_confgraph_complex.png0000644000000000000000000000013115132411300022557 xustar0029 mtime=1768559296.22388496 30 atime=1782715518.809789197 30 ctime=1787067793.753713109 rsyslog-8.2608.0/doc/source/rsyslog_confgraph_complex.png0000666000175000017500000042754415132411300022246 0ustar00rgerrger‰PNG  IHDRP—ómûbKGDÿÿÿ ½§“ pHYsHHFÉk> vpAgP XU°€IDATxÚìýw\÷þÿ?v—¥#UŠ(6°cÁ†½w±aÁ‚%±ÆÞMLb4‰-cbŒG�Æbï½WPQ¬  "* ½·Ý¹þø�ó½rò9ç$ꪼîÿxËì2ïç¼goáÉÌìŒJù'„BQb¨ @!„ož‘¡!Ä3¿g~Ïü`¿Ñ~£ýF�j�j�j ª‘ª‘ª‘€‚ÂÛ|œÒ[lA™­ÌVfƒEŠEŠE t×u\×qPubÕ‰U'‚ê¹ê¹ê¹¡Ã ñÿQÉ)!Ä›–=9{röd8ÔýP÷CÝá°ýaûÃöàvÀí€Û¨u¥Ö•ZW@å®rW¹™d’ièÔÿ‡F4¢èëëCL‡˜1 bJÄ”ˆ)Ðâ‹_´ø|³}³}³Áî˜Ý1»c†-J:)Bˆ×Ng¢3Ñ™ÀÕaW‡]Aß}ô=hÖjÖjÖ Aƒ ^#¼Fx�ÍÍÍC§þ\pÁîëîëîë °]`»Àv�0#aF è;¯ï¼¾ó µ}kûÖö`²Éd“É&C‡%�!Ä«W—ºÔ…˜f1ÍbšA`ëÀÖ�­á�É“&ÐóÇž?öü:÷ïÜ¿s0ûÐìC³!eqÊâ”Åp1ùbòÅdȘ•1+c¨WªWªWòÖ P:(”`z×ô®é]hfÖ̬™”©]¦v™ÚPÔ½¨{Qw¸Pp¡àBlÓnÓnÓ‚Ý&»Mv›`È€!† €_ÕøªÆW úLõ™ê3Co•xßIB¼2YͲše5ƒ}“÷MÞ7N,>±øÄb¨;§îœºsÀïŠß¿+à²Üe¹Ër(š^4½h:œß~ÿùý°½þöúÛëƒæ�æ�æ¸å¸å¸å¼üoå²rY¹lè­ü#UUUxžö<íy¤ú§ú§úC‡= ³®³®³Ìš/4_iåÒÊ¥•ƒ=c÷ŒÝ3Ο)>S Þ›¼7yo‚þ¾ý}ûûBéoJSúCo�x_IBüeEnEnEn21dbÈDØÚck�­=À"À"À";vì unÔ¹Q稂TAª ¸×è^£{� Ð%Ð%Ð’þ‘ô�¤@ß«}¯ö½ ­ú·êߪ?˜¤˜¤˜¤z+ÿ{Å{Š÷ï�ÐJ¡•B+ÁÖÎ[;oí êáêáêá0H=H=H ^ã¼Æy�µ³ÚYí �¶<Úòh > |øž9=szæ½§÷žÞ{:´Éh“Ñ&ÌUæ*s•¡·R¼/¤!þkÊfe³²¢—F/�^ åÊ”ƒ§6OmžÚ@oÓÞ¦½M¡½¦½¦½L×™®3]ÉaÉaÉa°Ój§ÕN+¸”{)÷R.´œÔrRËIàëçëçëvãìÆÙ�ƒÜ/r¿Èý”yPæAÈ3Ê3Ê3Õ(Õ(Õ(CÏÂïæc—²KÙÆ?ÿhü#Tʪ”U) l.Û\¶¹ 9Ãs†ç ‡Ce•=T�?tþÐy¨Y®f¹šå``ß�}ö…r½Ëõ.׊sŠsŠsà’ú’ú’¶®Þºzëj°p·p·pÿŠþý+‚ç Ïž3@}\}\}Üг ÞUR„ÿQzÿôþéýaOõ=Õ÷T‡ÓV§­N[AãøÆñ�ã¡ß'ý>é÷ 898989@¡}¡}¡=œúâÔ§¾€�ÝwvßÙ\×»®w]C̆˜ 1ƒ*ÙU²«dƒrU¹ª\…°åaËÖÖá[†o)­SZ§´ë@ë@ë@P"”%Âг¨P¡ÕBÕBÕBÈZ�µ:k5×7®o\–Xj`)hººéꦫA»V»V»b�b�b� hTШ Qp÷—»¿ÜýºÌè2£Ë èþA÷º–Û,·YnƒÌ#™G2�À>Í>Í> œ¨|¢ò‰ÊàuÖë¬×YÐd@“MÀ¥†K —†žñ®‘ „øƒÂ…= {ÀE“‹&M`{æöÌí™`jj ƒž z2è ÔxPãA�ÀÎpÂï‡ß¿�½{ö‚ŒmÛ2¶Aûþöýí¡ydóÈæ‘ =¬=¬= qÇ}÷1l­¼µòÖÊpÇìŽÙ3èäÜɹ“3ttêèÔÑ JÍ,5³ÔLP)‹”E†ž^€‘È;“w&ï \ìp±ÃŰ»öîÚ»kƒë×®#`pÚà´ÁiP¥s•ÎU:ƒî¶î¶î6ÜH¼‘x#¶tÙÒeK(6.6.6¿»~wýîB£'�ž4zFmŒÚµ�Ǿ�}ûBе kA×à¡î¡î¡zÔìQ³GMèЧCŸ}ÀbŒÅ‹1†ž$ñ¶“ „@Ñ):EQË¢–E-ƒ€À€À€@xÞýy÷çݡƒú‚¶ß´ý¦í7`¼Éx“ñ&Hì“Ø'±l7Þn¼Ý®Ö¿Zÿj}hÿCûÚÿ½2zeôÊë ë ë Èi’Ó$§ n{¸íá¶ppæÁ™gBõÀê�ÕaðóÁÏ?‡r_•ûªÜW†ž•¿.¹Mr›ä6°Ã{‡÷o111‡–m[¶mÙúô èv?Ùýd÷äõÏëŸ×Ž… 9ûÌö™í3÷8÷8÷8œ;8wp.T¨R¡J…* ;®;®;WG]uula [£›F7�nÂà&ƒ› nõÆÖ,hºhºhºzVÄÛF €%XÊÜ”¹)sa×Ï»~Þõ3\8zá腣ТA‹-€ïVß­¾[Á¾¯}_û¾�““'¾>ñõ‰¯ao�½uöÖ� ]*t©Ð6l •ÊT*S© èÑ£®/½¾ôúRèÐ%  ¨\T.*|lð±ÁÇ þ¶úÛêoÍ!Í!Í!CÏÊ«£ªª ÷ï;Þw„€Þ½z˵/Ö¾X ýû;öw„Ö¶þ°õ‡  ÐhàyìóØç±°íãmoûÂú†õ ë tttÐ3¹grÏd(5ºÔèR£!35353Ž4>ÒøHc8\|¸øp1xÖð¬áYÞxkà-p�u�u�5ô¬ˆ·…!J�ŸŸ8Wç\�su`çí�·wÞ§>N}œúÀàCƒ >ÕÎU;Wí(éJº’7»Ýìv³v ìØòªæUÍ« Æ ‡ÆF���vœvœvµvר]cw (W»\írµaÈÕ!W‡\÷Ûî·Ýoƒþ{ý÷úï!¬eX˰–°:`uÀêðJðJðJ€ ùò'äËXÆ2CφxÓ4_ü“¡ƒ!^¿“åO–?Y*׬\³rMÔgPŸA} h\Ѹ¢q°¿óþÎû;ÃjV³°�g;ÏvLº1鯤ÐB×B×BFéFéFéâââ ßýîèwG!±|bùÄò0:`tÀèè9µçÔžSÁº·uoëÞ†Þú·�™ÖLk¦¯k^×¼®�gˆgˆg_ ¾|v{ïöÞí ZµV­UC¥ó•ÎW:Õ÷TßS}4ñlâÙÄb2b2b2 °|`ùÀò�á”á”áîÝ/º_„ŠC+­84·4·4· *-*-* ZÎj9«å,P›«ÍÕæ†ž ñ¦ÉÓ…(A4Õ5Õ5ÕÁx¡ñBã…À&0.^¼xñâEØztëÑ­GaÚøiã§�‡†ÕVoX4&� <ªø¨â£Š49hrÐdxìöØí±ô íÚ3Úïh¿£ý0555ôÖ¾CV±ŠUà�À§e?-ûiY¸ôüÒóKÏa[Ýmu·Õ…ó{Îï9¿�4bШ•V+­VŒë<®ó¸ÎÐÚ¥µKkX~où½å÷@ÓAÓAÓ†2”¡€ö¦ö¦ö&m5Új´ÃÆð¯S ¢d‘ DI’DI ü ü üðrqVLVLV Ôq«ãVÇ ¼ã¼ã¼ã À¬À¬À ¶ßz|ëq86áØ„c Á„L€…çž[xœf9ÍršÌb³ ½‘ï¾ßÎå·¦5­�zëë­¯·ö=Ø÷`ßø¦÷7½¿é mÚ6´…á©ÃS‡§BÍû5ï׼͌š53‚”A)ƒRýnÅ1ÄJœ§Ä/xÁ Co­0µ¡! ï·Çîªïªïªï¾\~gÖ�YwfÁÞ�{îÓwMß5}L¨1¡Æ„à´Ëi—Ó.C§ÿY�´i=üCýCýCáónŸwû¼œÙxfã™�ª U…þþÁÎ8ã ªMªM*yÊ øR„ªà»‚ï ¾ÇŽ@�au†Õêöêöêö¯~¼a/Â^„Atqtqt1(þŠ¿âoèYx{¨¨¨€{k÷Öî­¡^ûzí뵇Â*…U «:�x×HBü¹V´¢ÿz¾= ¯ñ;CÁŸü)l´yÐæAPÔ·¨oQ_COèëêëêëB¾{¾{¾;/op`(7¸Á Pò•|%ßг#ÞUR„†WH!…Ðv[Ûmm·ÁDωž=Áè�Ñ£ ë«ë«ë :�‹ÎŠÚµ)jú²ú²ú²ÀyÎst_é¾Ò}ÅaÅaÅaPä\ä\ä ÅÅÅÅÅÅ/‡Ó�×�×�ÝGº�tÞxã ú†ú†ú† ›¥›¥ûݵ —\zpélûzÛ×Û¾]œ.NÜæ6·A×C×C× ,<ú•ú•ú•†žT!þor Âàô+ô+ô+àtÆéŒÓpÚî´Ýi;Wi\¥q•`õðÕÃW�<€‘…‘…‘ÄV‹­[ &L ˜î¸sà\Kº–t- ll°±ÁFˆÛ·)nøîöÝí»ŠÔEê"5üôóO?ÿô3Ì<2óÈÌ#�1.c\Æ8X7jݨu£`ôíÑ·G߆ )R6¤@êG©¥~îÏÝŸ»?ënÖݬ»Áž�ö|´ç#0›f6Íl”ïT¾SùNÐ;§wNy…x›È!„Á©g«g«gƒÛI·“n'án™»eî–�Rß—ú¾Ô÷�R1¥bJE°µµµµµ???ˆ<y:ò4Üȼ‘y#¬o[ß¶¾ ™¥3Kg–†!‡<òÜκ�u; ÿ¸÷�{ÿ¸.�]:»t†Ç<þàñ�}=ûzöupoáÞ½DO�ž=´ÿÐþCû(ëVÖ­¬Ô©]§v�ÚÐlJ³)ͦÀ¾zûêí«ñ·ãoÇ߆aµ‡ÕV<}<}<}€{Üãž¡gWˆO €â­¡IÔ$jA½L½L½ Ô±êXu,¨²TYª,0úÊè+£¯ÀRo©·Ôƒq3ãfÆÍ wYî²Üe ŽPG¨#Àh…Ñ £`êjêjê fffð¤Ã“O:@q|q|q<¨SÕ©êTP%©’TI >¤>¤>ª`U°*Ô¥Õ¥Õ¥AÝOÝOÝŒ-0Zð2o=Ïzžõ­Ú´jÓª ü°í‡m?lëëë˜å?Ë–?$x&x&xzR…ø÷¤!ÞÙÛ²·eoƒ‚ô‚ô‚tHë–Ö-­ä·Ëo—ßr»ävÉíE�Š:u‚‚Ç CîªÜU¹«@Y¦,S–A~ùüòùå!¾l|Ùø²ömØ·aßBƒ”) RÀÒÌÒÌÒ ´Í´Í´ÍàYýgõŸÕ‡ · · 7(šV4­hä×ɯ“_LT&*Äí‹Û·RN¦œL9 'žœxrâ YYYA{Óö¦íMÁøcã��?†â§ÅO‹ŸzV…ø÷ä"@!„Á´-h[ÐÒ§N; ÍmšÛ4·�È#Œüjͨ5£Ö °,oYÞ²<ÄùÆùÆùB� u6ÔÙV&V&V&�‘‘ ªU‚ ŽŒ;2îÈ8°«jWÕ®*t«Ú­j·ª`ínínícŠÇ�)†èºÑu£ë‚&H¤ ‚6 Û,l³”1Êe tÏêžÕ= v5ÝÕtWS¸¼òòÊË+Áv¾í|Ûùp±èbÑÅ"Py©¼T^0½ÙôfÓ›A™‚2e =»Bü{R„grÚä´ÉièF7ºݶtÛÒmËË×{Ñ‹^¿ÿ�–´¤%|>úóÑŸ�~¹xÛ�m7¶Ý€ §*œªp †Ž:nè8ÐZk­µÖ·G·ÝztûÝW\q…nm»µíÖö�ï¯Mmjÿ›ü¿Ý.sÌ1ç__Kâm&§„î·sâ¯ù@;æ\Ý\Ý\x¶éÙ¦g› ëJÖ•¬+ðäô“ÓON:Ýkàƒ>r«_ñ÷È!ÄŸRg¨3Ô�z2õdêIH¼˜x1ñâËkäÞ¿}[`ÄÚkG¬…ÁUW\l;Ûv¶í ô¦7ïÑãˆ3g,ÎX �n=ºõè4 oÞ0ÜЩĻFŽ!PN+§•Ó@#Ñèåòê‹«/®¾<{6öl s§Î�:w*J:”t( ò~Èû!<ì+óÛ_ÂöííÛÛ·7770�0�0�0tº¿¯h|Ñø¢ñpÑõ¢ëEWøÄùçOœÁ®µ]k»ÖPײ®e]Ë—ïW7Q7Q7%T Uä±ÌâOHB`tÎèœÑ9¸oußê¾<òlȳ!`Óܦ¹Ms˜•0+aVøÿâÿ‹ÿ/pÀâ€Å‹—O¥»}÷öÝÛwA¿H¿H¿ÈÐ[óîS6(” ðèÞ£{�îÁ"Õ"Õ"l8ºá膣Ð% K@—€—Ë]r]r]r!uNêœÔ9pÇåŽË0±1±1±ùýŠßîS9âÍ’ D ¢_¢_¢_úúú/—7û¼ÙçÍ>ÏIž“<'Á§‹?]üébØn·Ýn»ä7Ìo˜ßZ¶*lUKÛ.m»´-xnõÜê¹–]]vuÙUø!⇈" alÂØ„±†ÞÚwOzZzZzl²Ùd³É¾þ"ø‹`°Í´Í´Í„ESM]4|’}’}’AÝJÝJÝ Ž 8³ÊÎ*;«,X&Y&Y&�OªOªOêËõ+U”*JP¦(S”)@6Ùdz«…¡¨”2t!Äë·Îb�Å: 8Þáx‡ã`Ⴥ>�£G=Ž‚îÝ7ºo ¬_X¿°~°¥ý–ö[Úƒî¡î¡î! j;¨í ¶Ð0½azÃtммм€èMÑ›¢7AБ #AGàQ³GÍ5ƒž7{ÞìyÚOi?¥ý°ð´ð´�ãüKa\a\a\jq©Å¥°í̶3Û΀mÛ&¶M`PÄ ˆAP3§fNÍ „B "6"6"mmm!-#-#-úŸí¶ÿYh>¨ù æƒÀ¸¯q_ã¾ðÜë¹×s/XÑxEã�Á¦”M)›RðqÃ�~ÜT}U}UoÁSÅ›%@ˆ$õJê•Ô+°µxkñÖb¸Üër¯Ë½ 5­i ôZÞky¯å`7Ôn¨ÝPÈ«–W-¯™wdÞ‘y°¿Ïþ>ûû€‡‘‡‘‡ é6¤Û�nP¾zùê嫃n‚n‚n\i|¥ñ•ư¥ü–ò[ʃö²ö²ö2 >dø�áPwXÝau‡�¦£¦£¦£¡gå jG;ÚAT¥¨JQ• À<À<ÀâæÄ͉›}�ö=Ú÷(´mÚ¶iÛ¦`RÕ¤ªIUHê’Ô%© lwÜî¸Ý®L¹2åÊh»»íî¶»¡wtïèÞÑ`hh9ù9ù9ùp$äHÈ‘8Øë`¯ƒ½ ZnµÜj¹àç箎®Ž®Ž†ža(R„(�ôAú }Ü+u¯Ô½Rp*àTÀ)Hš24e(ôwéïÒßZílµ³ÕNЎ׎׎‡ç}ž÷yÞ¶žÛznë9¸©½©½©…Ï:<ëð z÷4îi VŠ•b¥@fÿÌþ™ýápåÕW†#;�ì<²jש]§vðã7Æo ¸vpíàÚáïo×Û*µjjÕÔª°K½K½K çÇž{~,4_Ù|eó•àââNNN�_%¿J~8ñʼn/N|{Gíµw¸ítÛ鶆,²pÈB¨S9¦r è;ë;ë;Ãõ�×7^ßÓ¦Lîr—»0hì ±ƒÆBýŠõ+Ö¯FµŒjÕ2ô¬C“ „  IA“‚&pnƹçfÀÎ;;ììŽ+W8®€Á&ƒM›@µnÕºUë,g9Ëá–Å-‹[˜˜˜¹r7än¿ñ~ãýƃ÷ïÞ@{L{L{ žV{Zíi5Z´6h-Ükt¯Ñ½FÐíÃnvûºôíÒ·K_°ìmÙÛòþÚ^~~~~~>œßq~Çù°kÍ®5»Ö@饔ƒsçÎ…j«u¬Ö˜Ç<æÁ­ž·zÞê �«W®‚\u®:W ~Q~Q~Qàíëíëí ÚMÚMÚMð´áÓ†OBÐÞ ½A{á^Á½‚{Ðmx·á݆C—y]æu™–í,ÛY¶3ô¬ˆ·�!ĤÖI­“ZvUÚUiW%8owÞî¼4?Úühó£Ð×¶¯m_[°¿k×þ.ä×ͯ›_N|zâӟž&{šìiåï–¿[þ. 5dÔ�QP9¡rBåÐ{é½ô^p½úõê׫C@ã€Æ�AùPùPùÏÓ|<ãÏ ½u¤4R)�@ó¡æC͇Ðq]Çu×A½õõÖ×[êPu¨:¦?L˜�Á�Á�Á÷CÜq?@ï*½«ô®mú´éÓ¦˜Í5›k6×Ð[%ÞwR„¯]VpVpV0ìß·ßþ}p<÷xîñ\¨S­Nµ:ÕÀ¯¾_}¿úPÆ»ŒwoC§}uRƒRƒRƒ`Ï{~ØóœÕœÕœÕ@“êMª7©ýõ?Ôÿ8Ä9Ä9¼Åßrï')Bˆ7çŸÏ±ý$úI4 <x ¢2¢2¢2 í…¶Ú^€·jܪq ˜Ît¦9ä�ó7Æ- €P·W·W·šÑŒf Ÿ£Ÿ£ŸØ`ƒÍßXuªS”^J/¥<«û¬î³ºpÌì˜Ù13°oc߯¾ ‰?$ª_®~¹úeP}«úVõ­¡wŠ(©¤! F7V7V7BcBcBc`‡²CÙ¡@þÃü‡ùA® W…ÅSü×ÇQmVmVm†§fOÍžšAÑ‚¢E À½·{o÷Þ Ÿ¯Ÿ¯ÿß.PUPUPUÝÝÝ0jjÔÔ¨)tŸÚ}j÷©Ðʾ•}+{0™l2Ùd²¡g]ˆÿ�!Ä[C÷L÷L÷ t: �PDE€ ª¿¾^µƒÚAí>ØðÁ† uTê¨ÔQ0Ûj¶Õl+(r.r.rþÁõèѦ˜b šAšAšA ™®™®™Î¿ž ÄÛÄÈЄâ7šršršr Aƒæ5¬ßÈËÈËÈ Œ† 1ªÇªÇªÇ`Œ1Ưr Ãæðš4!þ"µ¡!Ä£  Ç;…¤!„%’!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!D‰¡š©š©š ”¢¥ �FÃ’ „xïê u…:H\Ÿ¸>q=¼°xañÂÒï¥ßK¿YyYyYy�²1ecÊFH“8&q äµËk—×ÎÐé…x3TÊ?:ˆB¼*wMïšÞ5¿î~ÝýºCF¥ŒJ• §QN£œF OÓ§éÓÀj–Õ,«Y`ee+mWÚ®´…FŒ:z+„x½ä#.„x︪\U®*(g^μœ9„þMø7|_dµ}kûÖö…Z�k5®Õø†oøæUˆw‹œB¼wlólóló “k'×N®`ôØè±Ñã?û¾íû¶ï N*'•“ÊÐé…x3ä€â½Õ–¶´\º4tiÏxƳ߽nkk ²:duÈu5u5u5C§âÍ�#Bˆ÷–Ç_x|�5�5�5|½öîÚ»kúºúºzC§âÍ’ „xo™™˜™˜™@ë.Ö]¬A½Z½Z½T¦*S•)´ú±Õ�­~çÎ5œk:­o–!Ä{¯‰{÷&îà1Éc’Ç$°ÚhµÑj#t=ÓõL×3†N'„aÈ5Bˆ7¦0®0®0n=½õôÖSH³N³N³Uš*M•¨Pñ /ÂSõUõUõ…Âã…Ç �C©U¥V•ZŵŠkׂ¸Œ¸Œ¸ 8UæT™Se@¿S¿S¿ó5løINrLZ›´6i š7hÞ 9˜«ÍÕæòg˜0)Bˆ7&ø@ð�à°tçÒ�KwBÍ{5ïÕ¼ššš@"‰$¾Ââ'~µ§ÚSí îÝ/º_„ì¢ì¢ì"¸5áÖ„[@ÿ‹þý/¼ü^à«b‹-¶ Ú¨Ú¨Úaéaéaé0ìÖ°[ÃnÁ ‰ƒ&šø&÷€/É�€„¯]ÖŠ¬Y+`Nòœä9ÉÐIÕIÕI>·|nùܽJ¯Ò«€\rÉ}õã«n«n«nCš>MŸ¦‡LÿLÿL(ï^Þ½¼;({”=Êž×°áZ´hAõ™ê3ÕgÚ<´yhsøéÀO~:_�úzÔ×£À5Þ5Þ5þuï!þ_R„¯Ý¶úÛêo«¡ñ¡ñ¡ñðåÚ/×~¹Ì|Ì|Ì| �îÍÑÏÔÏÔÏ„¥ÉK“—&ƒiGÓŽ¦aJÄ”ˆ)À—|É—†N)J 9û$„xm⿈ÿ"þ 8b}Äúˆ5 ðà=À»äýâÿ�úõ7êo`€f€f€nøÝð»áwÝïºßu7t:QÒHB¼6»ï:¼ë0xÄzÄzÄ‚×~¯ý^û �Êð*®¯¸¾âzhÕ¡U‡V ¨{P÷ îP¸±pcáFC§%…!Ä+1&bLĸ}=úz4ø­ñ[ã·4:�N£3tº·G�9=æô˜‰J¢’¨@0Á:”(1¤!^™â-Å[Š·ÀÖò[Ëo-ÍM››67…Êm+·­ÜÖÐéÞ>íÚ;´‡Þ {7ìÝvì(ØQ™Ó3§gN7t:ñ¾“ „xeBrBrBr ^¯�×B� =.ô¸`èTo¿¶ËÚ.k» Lê™Ô3©ÇN;u씡S‰÷�!Äß–µ0kaÖBØæ¸Íq›#ôXßc}�õàXѱ¢cEC§{û™ùšùšù³fÌàÈ¥#—Ž\‚„2 eÊ:�x_IBümǦ›~l:Í5šk4Újw¨Ý!C§z÷4´mhÛÐ*i*i*i`ÇÒKw,Ô¨åÿÖâU“�”â/Kx‘ð"áiq¤Å‘0à耣Ž‚…»…»…|­í¦.§.§.~^~^~^úIè'¡ŸÀ½û÷îß»oètâ}#@ñ¿{Ä#ÁžN{:íéå生S~4®Ý¸vãÚ†÷îsuu…æ™Í3›gÂÖè­Ñ[£¡¸iqÓ⦆N'ÞR„ÿ³ÈŸ"Šü .Ç\޹¿øÅÀ/@�ªNU§:Ý{À , ÷²ÞËz/ƒØò±åcËÃå)—§\žbèpâ}!@ñ_+._\¾¸üË¿H½ïzßõ¾ ·=n{Ü6tº÷Oé‘¥G– >w|îøÜ�ƒw Þ1rkçÖΕ#-âo’ „ø¯]=põÀÕðÄø‰ñcèãÛÇ·�¯¡S½ÿ:tëЭC7PÍTÍTÍ„£7ŽÞ8zÃЩĻN €â?Êy�ó çl»}ìö±Ð=¢{D÷p q q 1tºW§(ª(ª( 2¿Ìü2óKPZ)­”V†NÐÿJÿ+ý¯À�¢EŠ É+É+ÉËÐéÄ»J €â?:yñäÅ“Aï¬wÖ;C§…�vZhèT¯Þ�~wúÝé_ø|áó…¤·Jo•þ€ß4œÕpVÃYP~PùAåÁî‘»GîièTâ]%@ñ§^¤¾H}‘ çœp>ô›Ûon¿¹`ÑÝ¢»EwC§{õܸ/p_cö�Ù7fXeYeYe:ÕKÚNÚNÚN0°ÖÀZkAHnHnH.D}õMÔ7†N'Þ5F† „x{íé»§ïž¾PƸŒqchr¾Éù&ç�úÔ§þëW—®Kץá‡:Z>hù %TN­œZ9¢NF�Œ: n*7•› LãMãMãáÑ7�¾yô t\ÐqAÇà9ßs¾ç|x¸àႇ àä‘“GN}”>Jå”oP¾tÊî”Ý)ï{¼ïñ>8yòäÉ“'¡‡S§Np¾êùªç«‚2X¬ k¬±âcâcâc ¿_¿þ~àÒÑ¥£KÇ׿_ªzWõ®ê �¯4¾Òø lËÞ–½-涘Ûbn P_P_PË-˜Å G„ððÙÃgŸÁÅЋ¡CÁ¯À¯À¯Œ¦M5šúúÇרhl46�~$ýHú‰ ‰ ‰ƒÆWh\ŠW¯.^ G¶Ùrd xû{û{ûCQó¢æEÍaCƆŒ /×—u"ëDÖ ¨v Ú�j Qq£âFŰfÑšEkÁc£ÇF�� ô†ÒJo€ƒ.]º@ö¦ìMÙ›àÁƒ<€‡þýúC‹ -.´¸·gÞžy{&ì»»ïî¾»opu¥+]¡÷„ÞzO€Ç¾�}ûBhHhHè{tM†x½¤!þEo£·ÑÛÀ¶Äm‰Û¡á ?høT^ýyõço>�i5Ój¦ÕÀt¿é~Óýàbëbëb îöîöîö ›¤›¤›Îõœë9×ƒŠ³+ή8^Œx1âÅ(ÞS¼§xTJ«”V) >søÌá3(Ø\°¹`3dÎÉœ“9²‡gÏ3-fZÌ###0l4Øh0˜L4™h2Ì{š÷4ï Î'œO8ŸçcÎÇœ�AÒá¤ÃI‡ßüü¸”v)íRº:uuêêAÓƒ¦M‡\×\×\×7ŸG¼[¤!þåÚ¶kÛ®mƒ‡ÕVXúzöõìë RH¡)((@4ÑDÿn¹ *Àlþ¸\µTµTµ 6l,Ø+-WZ®´„í·:Ü žn|ºñéF(jTÔ¨¨¨>U}ªúУGÿorSL1K,±¿[þÏöЂ´0ÀüüS§Å�wZ ÅÅÅp2ðdàÉ@Ãåï)BòÏåŸË?ÛömÛ·mtV:+�pé2ÒÅ€W™ëÓôiú4Ð5Ö5Ö5ý3ý3ý3ÐÇéãôq k¢k¢kŠ•b¥Xýnù�ºu?BÎÚœµ9ká|íóµÏ×ï™Þ3½gB—Ó]Nw9 f­ÍZ›µ†âàâàâ`ЫÿVÿ-èÓõéút(ÖkŠ5 ?¯?¯?:{�½Îþwù¬ôVz+Ðyè‚Ù}f÷™Ý†,²xÈbh}²õÉÖ' l3˜EcŠÆ�jPƒ ¾®¾®¾ú|}¾>ŸzW_S_S_}–>KŸ bƒÀ(Ù(Ù(¨Le*Ca�Â:…u@µLµLµ TZ•V¥uOuOuOPf(3” ¯«¯«¯ 8á„I$‘ º©º©º š'š'š' ;§;§;Le*SÁ¨•Q+£V ²TYª, 7}‡#G†%O–/óy™ÏË@åž•{VîiÀý*Þ*R„(Á6žÚxjã)xð݃ï|óÍ[4o˜Ô2©eRËÐéÄ_N8áðýåï/²_d¿È~³Sf§ÌNÍ7šo4r߀ONQEoŒÞ½Î8àütwÐÝAwåÿ{£&5© ¾¾¾ðpÉÃ%—@Øa„}`èpâm!@ˆè\ÿsýÏõ‡ *@õîÕ»WïìWÒ¹ötíéÚ* ©4¤ÒØÛdo“½M �J¼-¤Qyžó<çy’û$÷Iî   †N%^µÌ&™M2›@l™Ø2±eÀ[ñV¼å„¯ø')B”@^6^6^6PÕ¹ªsUgرvÇÚkAùXùXùØÐéÄ«rD}D}D ó,æỸöMÛ7mßÔЩÄÛBž D ¤nªnªn æ ˜3`|¾ùóÍŸo†ð‚ð‚ð¨E-äR€wW|™ø2ñeà襣—Ž^‚�L>2ùÈÌʘ•1+cètâm!G„(Á*.®¸¸âbhMkZ[£¶Fm�‚¢ÉE“‹& Ð<æ1ŠcŠcŠc H)RŠзззå‘òHyúŠúŠúŠ ôWú+ý�ø€@§Óét:P|_ÅÈ"‹ß=ÍOwCwCwŠë×-® t§;Ý�ºÔ¥.è u…ºBPî(w”; ¤)iJè’uɺdP®*W•«¿Ë{‚œ€âüâüâ|(Ž(Ž(Žnr“›˜¿žô¤'ì꾫û®îà±Ðc¡ÇB¨]?º~ôß_½x¿h¾ø'CBNùg埕ûÝÿëþ_Áæ[›om¾… ,*X¼þñõëôëôëàXü±øcñ°'aOžˆ54j(ü:ñ׉¿NãAƃŒÁÉïN~wò;8Þõx×ã]¡žªžªž Ö®/\_§ZŸj}ª54ÖlX³apÏúžõ=kؼoó¾Íû $3$3$žL|2ñÉDpNtNtN„Åî‹Ý»ÃócÏ�=?å*”«P®|­úZõµ Æ%ŒKµ‡×^{8œ{rîɹ'°«Ç®»z@ð÷Áß¹Cs‡æ…J[*m©´TMUMUoàÐ{D�ˆ=`Ç£�v<‚�¦~4õ£©`_þ†}�×?¾x·È!ö-í[Ú·„ž'zžèyví0ÚaÙ£²Ge�zýãßó¾ç}ÏÖkÖkÖk û³îϺ?ÿfþÍü›AâñÄã‰Ç!õTê©ÔS`û¥í—¶_Bx¿ð~áýÀòSËO-?»™v3ífB¸Y¸Y¸äŽÈ‘;~´þÑúGkp›ë6×m. »:ìê°«°çÙžg{žAܽ¸{q÷@ÕNÕNÕyxäá°s·s·sÅ]qWÜ!ºOtŸè>�8!qBâø©×O½~êí~n÷s»Ÿ¡ýÎö;Ûï„TþGåT†¤˜¤˜¤˜×?…ممÙÔ5¨kPWhîÑÜ£¹¸;»;»;¿þñÅ»I €â_Úµ5jk&ÓL¦™Lƒ#wŽÜ9òn%ûÀã�Ç0*kTÖ¨,¸ÏvŸí>L²M²M²AóLóLó Ô�Ô�Ô�@ÓJÓJÓ T«U«U«�RHÍÍÍPG©£ÔQ�?1bþDˆØ±/b$,MXš°®}{íÛkßBÖY_d}i™i™i™`ÔΨ�Q;P�P�P�x™Oc­±ÖXƒæœæœæ¼øâÅ/¾€Çæ�Í›Ãá‡> ‘Ý#»Gv‡Ô¥©KS—BN™œ29oàœû•ÙWf_™ ñÃã‡Ç‡^ù½ò{å¿þqÅ»M.Bü‹Y®Y®Y. x2àÉ€'°fÞšykæAsçæÎÍ�Á%Á%Á%áÕ�«úDõ‰êPÊ)å”rÀe.s™—OýûÃüs¹^xý›å®¸â ô =À¨³Qg£Î`3ÄfˆÍpÕ¸j\5°`Ò‚I &A�–5ZÖh §5§5§5`dmdmdý»õjÑ¢¬°Â TTT@ûLûLû lîÚܵ¹ ŽŽްlÁ²Ë@™Ae•ôúöWööìíÙÛaGÁŽ‚ÐsQÏE=Aé¨ÒQ¥£^߸âý G„Pߨ¾Q}#¨4­Ò´JÓ`×®]»víz}ãyTõ¨êQŠ»w-î a…a…a…�ªMÕ¦j¡hTѨ¢QÀö°,V[¬¶X Yg²Îd��¤¯“¾Núò&æMÌ›…³ gÎíTíTíT¨ST§¨NäææBy¥¼R^�š¹5skæ‚e+ËV–­ÀÒßÒßÒ^l}±õÅVȶ˶˶ƒüGù�òA^¿¼~yý t¯Ò½J÷‚Šùó+惮‡®‡®TÞTySåMPcT�Q5F�é*ÓU¦«^ß¼;xìృ Ù®Ù®Ù¦v˜ÚaêëO¼_ä"@!ĨK©K©K�k× ® È1È1ȪW® -Z:´|uã9ôrèåÐ àúæë›¯o~ù8Û�”�”�ð:àuÀë´ØÞb{‹í�1(cPÆ H0N0N0ÅB±P,ÀêœÕ9«sPG©£ÔQÀ«‰W¯&9,rXä0¸ïrßå¾ËËŸw)v)v)×T×T×Tˆû>îû¸ï!½gzÏôž@ºÐ*:Tt¨ œ87p†jí«µ¯ÖÂòÂòÂòà±Õc«ÇVPh]h]h .V.V.V ñÖxk¼_Ý|%^I¼’x~òýÉ÷'_útèÓ¡O¡â¢Š‹*.zÃñÎ’‡ !þ£µ³ÖÎZ; â·Åo‹ßŸ%|–ðYh 4š‚×8°3Î8ÃàòƒË.>Ù>Ù>ÙàîînèY1€¬`¬îµº×ê^�¼1ycòF˜»h‹@S¤)Ò:¤xWÈ)!ÄÔ«C¯½:@¬M¬M¬ \¶½l{Ùöõ�û¤å“–OZBVBVBV¼¨÷¢Þ‹z 7Ó›éÍ =+o^äØÈ±‘c!$"$"$ü¢ü¢ü¢ä¿øk¤!þ#ÇŽ;@÷;Ýït¿[c·Æn�…ìMÙ›²7½Æq×9®s\?Õú©ÖOµ`ðÕÁW_Õ:Õ:Õ:CÏÊ›£KÔ%êaÛØmc·�…&�štjÒ ª¸Vq­âjètâ]%§„ÿµì Ù²/À'µ?©ýImh�Ý:»u6ôqíãÚG~½6!Æ!Æ!ư>|}øúpXÔkQ¯E½À1Ü1ܱ$ž ¯„Bü×,[X¶°l~'üNø�€CŸúôЧ�Ø/±_b?C§{ÿäæææææÂ¶ÆÛok ÝÚtkÓ­�ü⯆!Äÿ¬ñ×�¿nü5¸Å¸Å¸ÅÀÞø½ñ{ã �êýsâ鉧'ž‚n…n…ntØÜas‡Í†N%ÞR„ÿ3Í Í Í ð‹ô‹ô‹„à Á‚'ÀƒVZ=heètᄂI’Àþãû�ï?ýK÷/Ý¿4Xµ±jcÕÆÐéÄûB €â/«_5¾j<4þ¼ñç�?‡ Û Û [(X<°x ¡Ó½»ö}³ï›}߀k€k€kx¯ò^åýo($J&)Bˆ¿­O~Ÿü>ùð¸Áã�Àµö×Ú_koèTïžGíµ{Ô.ú]ô»è~_ú}é÷%h¿Ñ~£ýÆÐéÄûF €âos~æüÌùt íÚ-¶ÏÝ>wû\Èž;Ê„È_"‰ü"ÊD”‰(EÖEÖEÖ/.cþÆü�¹>r}äz¸�w;ïvÄëãõñzPr•\%÷ÏÇÍõÎõÎõ†¨Q;¢v@⇉&~9s&æLÛ{¶÷lïAóÇÍ7 Fß}gôX.´\h¹´çµçµç¡èdÑÉ¢“àààë=Ö{¬÷€ûû{PÒ•t%ú%ôKè·ëÜ®s»D'F'F'‚îKÝ—º/!öYì³ØgÙ ²AdxRæI™'e Þ*Þ*Þ XÊR–zo‰×ÍÈЄâMь֌֌†ufëÌÖ™½,GvÙq$lŠÞ½)†Z µj�,:Yt²€��7vÞØò¯ç_Ï¿ÎcœÇ8��kß^ûöÚ·0tÇÐCw@�‹u.Ö¹øÇq³ïdßɾ¹¹¹€1ÆCÂü„ù ó¡8ª8ª8 fŽ™9fæøáÑ�~x妗›^n:I$‘PT©¨RQ%¸q9âr–),SX’¿Kþ.ù;È8˜q0ã ¬;¸î຃P«C­µ:ÀÍR7KÝ,}–÷YÞg9¤þšúk꯰|éò¥Ë— ƒF V'¬NX�€�×^x 4hÐz§‰×F €¢ÄPõVõVõ�«ÎUç ¥}Jû”ö�.Å]Š»Ã…M6]Ø7_Ü|qóT?TýPõCpäÊ‘+G®ÀÊ++¯¬¼uuuðäö“ÛOnÃŽQ;Fíu¨C�3®cŽcŽcT¸\ár…Ë`>Î|œù8¨W¿^ýzõ!¥FJ�” 5Ök�A¿H¿H¿pÄG  hÖ_Ziý%”=[ölÙ³`V`V`Vµ>«õY­Ïà»§ß=ýî)P‹ZÔ‚áû‡ï¾–™,3Yf‡*ªp¨ô?ÓÿLÿ3`œkœkœ =Œzõ0ëkÖ׬¯�z¨z¨z¨¡÷–xÝ䀢äУGd‘E@/_V¿P¿P¿}}}}}}Èþ<ûóìÏ¡ ¤ ¤ ̃̓̓_¾ß^m¯¶WC"‰$þ7ãGM4(m•¶JÛóúorÿÙŸÞ*T¨€§<å)(þŠ¿âÿòåDûDûD{ˆ58j0l¨º¡ê†ªðb‹ /&€K�K�K0‹YÌ#Œ0Lõ¦zS=XN°œ`9T¥T¥T¥ ½³Äë&@QrhÑ¢ÊQŽrÀv°ãw¯»ãŽ;PƒÔ‹\‹\‹\ÐŽÐŽÐŽ€ü&ùMò›¼|{z—ô.é]ÀAå rPýãW¤"AuBuBuâwË ( ˜Ît¦ƒj„j„j/‹Ê$&1 Æ0†;ÙÉNP†(C”!/WcçoçoçUW\e0ø÷?î>]øtáS˜â5ÅkŠè§é§é§�jªjªj*à�†Þ9âM“ „(1”�ÊFe#p—»Ü…¤ ¤ ¤ Hœ>8}0$vJì”Ø ’>Jú(é#°ÿÚþkû¯¡íçm?oû9ì²oȾ!°÷—½¿ìýbÆ>Œ}}êô©Ó§ÎŸ�›5.k\Ö8x>äù�çCàéæ§›Ÿn†¤åIË“–Ãã”Ç)�S c]ƺŒuð°æÃškÂÃ*«<¬þþþðä“'Ÿ<ùœÎ:�u: 7«Ý¬v³„……AûYígµŸ9Ýrºåtƒ]UwUÝU‚›7 nI{’ö$í�8ã8ã8cH›’6%m ÄæÆæÆæþws(Þ*åŸ D!^·�‹6.Ú¸®$]Iº’ãW�_=~5¸9¹9¹9Áƒ´iÒ@3P3P3jzÖô¬é E¾E¾E¾µ.j]Ô:(ø¨à£‚�À)Õ)Õ)*̯0¿Â|PmQmQmùã¸Ù‹³g/†ðkáׯñ¯¯#z8{8{8C¶]¶]¶ÄŒ�3œ>púÀé0�6�6�†§�žvzÚ Êx•ñ*ã6ŸÚ|jó)D4‰hÑ ê媗«^†§öOíŸÚÃóºÏë>¯ æ£ÍG›�†r?—û¹ÜÏ�žžžžž±»cwÇî÷_ÝuÿÊ|Sæ›2ßz/‰7E €¢ÄذzÃê «!uYê²Ôe0#zFôŒhC§Â0䀢ä(¢ˆ"@AAþì%œ!„¢’ „B”@R„BˆH €BQIB!J )B!D $@Qr´ -L01t! K €â½£©© Ù+³Wf¯„ÜÄÜÄÜD(˜]0»`6|UðUÁWPð¤àIÁÈÊËÊËʃ¢iEÓŠ¦:½o†<XñÞyxãá�‡7`æ�™Cf]Œ.F±mcÛÆ¶…¢�E‹ÂeÍeÍe ¨�«�«�ÃÌF3ÍlÍiNsCo„¯™!Ä{ÇZ±V¬H^�¼:y5„ìÙ²ã�ï»W|¯ø^1¸åþ•ûWà\ŹŠsÀ?ü ½B¼^r @ñÞqssƒNQ�¢:Eg9ËÙ? m m -T0©`RA® %„!Ä{«Ý¶vÛÚmÇ\Ç\Çó¸[ãŸ�6þº´èÒ¢K 0Zn´Üh¹¡S ñfÈ)!Ä{«NÝ:uëÔ…Úŵ‹kÃINròw¯W�«W=¤5Hk�fè´B¼Yr@ñ޲ʳʳʃ®C»í:ô�¯7ù¤É'M>� öì+Ø:­o–B¼÷Zjq¨Å!(»¹ìæ²›!uqêâÔÅàcâcâcªbU±ªØÐ)…x³¤!^»¤RI¥’JÁóÎÏ;?ï Üä&7l°y�ï`; ¨TQ©¢RàòƒË.?€º¬º¬º,¨Ôê¸ýøöãÛ�A  P¼Æh¯k¯k¯ƒå$ËI–“@­ŒVF¿Æ…RêuŽ:,_X¾°|êêêppÅÁW8ÀPâ”8%îõÅQ­V­V­†œ97rn@ŽkŽkŽ+Ly8åᔇÐ4¤iHÓ  MhòçE@¥ü“¡ƒ!Þ·¯Þ¾zû*|ÛÿÛþßö‡vOÚ=i÷|.ú\ô¹F£ŒF�e·²[Ùýúó¨ÜTn*7xÞôyÓçM!Õ.Õ.Õj�®5ºÖhÐ×Ó×Ó×^ãÿ U5T5T5@ÿµþký×p)øRð¥`¸p)àŒl7²ÝÈvÐfG›mvüýñ„ø¿HBü}ç8Ç9¸v÷ÚÝkwáûŠßWü¾"ôÜÜssÏÍЧEŸ}Z€ê#ÕGª� ˜ó)Oy <ä!�¶´¥­ó¨P¡‚óåÏ—?_Ö–Z[jm)ð7õ7õ7…NW;]ítÕ€ùÄ{M €âo îÜ7¸/ühú£é�¦àgægæg>Û}¶ûl2È ÃÐ)ß~—c/Ç^Ž…nÿpû‡Û0Àq€ãGðiãÓÆ§ ¨²TYª,C§ï ¹@ñ—�‰?&~ø9àçš24eh tÜÙqgÇ�À:Ö±ÎÐ)ßÞe½Ëz—­…ÖBk+.¯¸¼â2~QøEáÐǺ�ukPg¨3ÔR¨Äß$G„ÿ5ÅD1QLàXè±Ðc¡˜˜˜®ûp݇ë õúÖë[¯7tÊ÷Ç�‡wÞyË;,ï°¼t¸×á^‡{àçàçàçšlM¶&ÛÐ)Å»J €â?RF(#”°Ÿýìv$íHÚ‘ã“Æ'�O‚&¡MB›„:åû+²Md›È6°$cIÆ’ h~´ùÑæGÁ–ÿ,ÿY ýEû‹öC§ï¹ âO)s•¹Ê\ØytçÑ�Ga·õnëÝÖ0µÞÔzSëA“ÝMv7yWñ—tUÏT=Sõ |2ç“9ŸÌ��U!«BVÁÏ·¾ýóm(˜X0±`¢¡SŠw�BüAñòâåÅË!(*(*( ÎdŸÉ>“ SO=<õ0x¦y¦yʽó æIä“È'‘°$rIä’H¨ª®ª®ª†ÑcG�=ÌbÍbÍb �R¼í¤!þ¥èQÑ£¢G°)gSΦÞ¼'xÌšï{ø±ò�•¬ á«ÂW…¯‚¹óçΟ;ÿ¯ÿâ/W<®x<Ýýt÷ÓÝpcÍ�57Ö@ø’ð%áK b]ĺˆupwÔÝQwGÁ‹/^¼xaèÙxV±ŠU�®Mצk!<,<,< Ò'¥OJŸô×Wë¬rV9«àã~÷û¸ä̘?–¦-M[šisÓæ¦Í5ôÆ‹·�!J \Ç\Ç\Gø¾ô÷¥¿/ Ñ�£G?†¹“çNž;ܼݼݼÿúúõçõçõçáªùUó«æ0:xtðè`U…ªBUðhÊ£)�¦À‰èÑ'¢á”ë)×S®†ž•7`›ØiÓ.¦]„Ù�³gÂÙÃgŸ=ü÷WoŸoŸoŸ³gÍž5{hnhnhnÀ o,¼ÉÍ’›%Ë)ñOR„(A²Ü²Ü²ÜàÛ*ßVù¶ $5Ij’Ô>ùùÈÏGB™Æe—iü÷Ç177‡*õ«Ô¯RljÛÔ¶© �ëw®ß¹>øäøäøä€_Ž_Ž_T¶¬lYÙòåÏ+ã”qÊ8(Î(Î(Î}/}/}/ �<ò@IQR”P|ŨG=ê�>Z­�}¨>T ú}Œ>”�Ê@e ¼#¡:PV(+” _¦_¦_Æ¿nÑ«D+ÑJ4GGG‚~Œ~Œ~ÌïrNR&)“@9¡œPN€rE¹¢\¥¦RS© P@°žõ¬Ý*Ý*Ý*(w³ÜÍr7Ár…å ËP<¤xHñ�W·ŸKå”Ê)•ÓÇN;},Ø.µ]j»¾Îû:ïëÏ|ÅÝ‹»w‡Äs‰çÏÁ”ƒSN9Q_E}õ˜¿0aþJ�,=²ôHpâ2Äe”ëV®[¹n0¶ÁØc€³£³£³#üªÿUÿ«œs�s�sáÖœ[snÍ›"›"›"hü}ãï÷•ûÊ}Öu\×q]Gè–Þ-½[: 1xÄàà¼ÁyƒóÐ7Ó7Ó¿ÆCóæÌ7˜o€ k&¬™°ª¬¬²²ÊJø2åË”/S zwôîh¹ŸC‰#@ˆ÷QCÒ~Iþ%ù—dx|éñ¥Ç—`ZËi-§µëÅÖ‹­¿�s™Ë\(uºÔéR§¡©OSŸ¦>ÐxQãE��ŧŸZ|úòí7moÚÞ´…JC* ©4LÏšž5= Õ/T¿Pý$I8’pÒ¾Iû&í0¹drÉä”ý®ìwe¿ƒšík¶¯ÙjN¬9±æDð®ç]Ï»\˜taÒ…IðÐë¡×C/ÈHÉHÉH�S™§2OeÂcïÇÞ�½¡®¦®¦®4Ã4Ã4ÃÀNg§³ÓÁeíeíe-<;ÿìü³ó�ýUöWÙ_�ú;õwêïÀl¶Ùl³ÙP±cÅŽ;BÍñ5Ç×Ï:=ëô¬hii�‡ƒ‡ƒ‡˜55kjÖ4 5 5 �ÛÜæöëß&[M¶šl…Ñv£íFÛ�®¢®¢®",½`ô‚Ñ/¿ "J)B¼�B %Ú›µ7kofÍ*šU„£ŽN8:t5t5t5^ å´rZ9 &çLΙœssshP®A¹å �_¿6~/߯٥٥ÙzK½¥þw×èƒôAú `³˜ª�ª�ª�/·S9¬VþÍEt­Û´nÓº Ü©}§ö�Úììì c§Œ�2v \hv¡Ù…fðÐæ¡ÍC¨~¥ú•êWàòÎË;/ï„o3ø›Á`ô£ýÌ1ÇÀ /¼+¬°%X V‚A S”°ßèK_ú‚ª�ª�ªàŽ;‚Xb‰%à„Noàs±›Ý솋K/.½¸²wdïÈÞ~‡üùmUmUmÕ7�C¼ä!Þcõ¶×Û^o;̰�a;Ö&-MZšù=ò{ä÷€!K†,²ŒfÍ6šýêÇÏ Ë Ë ƒU�ª@™+3Wf®§ÙN³�fƒÝ5»kv×^¾ß;Ð;Ð;¢,£,£,!9 9 9®ï¼¾óúN¨T®R¹JåÀ6Ö6Ö6 ®\+¸¹þ¹þ¹þ¿ÖÚZkk­�£ÆQãd‘EtîÖ¹[çn°±ÛÆn»�Å]‹»wÁt·énÓÝ�¨JT%ª sjæÔÌ©à9Às€çxPöAÙe!Ü#Ü#Ürä,ÈYE­ŠZµ‚5úÔè£ÜG¹�rÓV¦­L[:¥ø«tÞ:o�7ì|ºóéΧphÌ¡1‡ÆÀ´ÃÓO; u¯Ô½R÷Š¡S C“k„(�*<ªð¨Â#˜ûáÜç~÷?½ÿéýOaUýUõWÕ‡¼áyÃó†:¥ø_·/n_ÜŸ> |G;ít´ÌIž“<'Y~ñ‹ÿ—B�èŸèŸè‹#G.ŽǾŽ}ûÂDÕDÕDXδœi9ÓÐ)ÅŸ)ì[Ø·°/üÒè—F¿4‚ÐÌÐÌÐL˜1rÆÈ#¡j…ªªV0tJñ¶‘ „ø—äŒäŒä Xú`郥Àâ‹O,>�Én“Ý&»�Íz›õ6ë �Rü&¿S~§üN°®ñºÆëCDZDZDÌt˜é0Ó*Í«4¯Òí<|SüMñ7Å úQõ£êG˜n3Ýfº Øýl÷³ÝφNYråÆäÆäÆÀ�ç<ÿãyx¶èÙ¢g‹`vöììÙÙàúÌõ™ë3C§o;)Bˆ?•96slæXø.÷»Üïr!;";";f|<ãャ¯£¯£¯¡S–Ù�Ù�Ù�°rÖÊY+gAJLJLJ ÌL�™:3\œ\œ\ÞÄýÄ{A €â?ÊNÎNÎN†UšUšUHXš°4a)Ì\2sÉÌ%àªwÕ»ê �òý•q1ãbÆEø6üÛðoáàFÁ�‚0�éLJ¯)½¦ôC§ïù€â?²t°t°t€É¡“C'‡Bùúåë—¯_g~�ùu&<­ð´ÂÓ †NùþI=Ÿz>õ<,*»¨ì¢² ·ÕÛêmaŽóç9Îò‹_ü=r@ñ?+h_о =lðÜà¹ÁnÞ¼yóæM˜í:Ûu¶+T ¨P)ÀÐ)ß]Iw’î$Ý�%éKÒ—¤ƒÍ¯6¿Úü “GN9y$”j\ªq©WðØfQ²IBüe… €%@ Pàb…‹.V€™a3Ãf†AõáÕ‡Wnè”ïŽç#Ÿ�|>–œ^rzÉipqwqwq‡ ê ê j°8jqÔ⨡SŠ÷…!ÄßV|ªøTñ)ØvnÛ¹mçàø•ãWŽ_�^3¼fx�ç"ÏEž‹ �òíõÛUü‹ª.ªº¨*xœö8íqÆùŒóç¦�L;™v2tJñ¾‘ „xeô�õ�õ�aw·ÝÝvwƒýßîÿvÿ·0¥þ”úSêƒ×N¯�^; �òíñhÍ£5�ÖÀ’fKš-iu‚ë× †‘åF–YLºšt5éjè”â}%@ñÊ)M”&J8èrÐå  lÌߘ¿1êÇÔ�©VŸX}bõ (­•ÖJë7(—\rA¬V¾øâ ú(}”>Š7ö8^ÕϪŸU?CNÙœ²9eáöšÛkn¯�ö~íýÚûÁPŸ¡>C}@[E[E[å Ì‹(Ѥ!^¥…ÒBi!î!î!îóòÆBhРyý9ÔžjOµ'\¾|9rŸä>É}íRÛ¥¶K]K]K]Ë70!e)KYÐ7Ñ7Ñ7�ò!åCʇ@Ûkm¯µ½F­ŒZÉC˜Ä"@Qbl,ÚX´±Rz§ôNé 3Î88ã ¡S ar!D‰¡¬VV+«�p 7t! K €BQIB!J )B!D $@!„(�¤!„%�!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!„xCô}õ}õ}áæ²›Ën.ƒK+/­¼´tYº,]0–±Œ‚ &”J¥(ÁJ° Üâ· ½â}!@!Þ��Ü�Ü�\صx×â]‹!ºvtíèÚpóÓ›ŸÞü–|°äƒ%@Zë´Öi­!øjðÕà«0©Â¤ “*Àã!�‡<bè­ï )Bˆ’Cƒ  B…êÍ¡ö…ÚjƒéBÓ…¦ aàÔ�SNç;Îwœï@�žuzÖé æµÌk™×‚Ê÷*ß«|Â3Â3Â3 Ó6Ó6ÓSSS!¬IX“°&†žTñ®22t!„xSÔ3Ô3Ô3àVï[½oõ† iÒ.¤;ÙÉNÈ�Ë�Ë�ƒf­šµjÖ ,ÛX¶±léÆéÆéÆpËö–í-[ȋɋɋ×®\@Íû5ï×¼ê(u”:ê�㦤¦¤¦¤BÄâˆÅ‹A=Q=Q=Ø>°}` &eLʘ”UgUgUgÈwÉwÉw­³ÖYë šGšGšG�ë–ë–ëÿ8ñ�ÿ8ÏÛ>oû¼-L91åÄ”à‘à‘à‘÷ŠîÝ+‚§ÇŸzl>°ùÀ樿³þÎú;!rjäÔÈ©�x<ñxâq°ùÞæ{›ïÁä¡ÉC“‡àéêéêé ÄO¼¡÷šx]䀢ÄÐh 4°ãÆŽ;nÀ¾ü}ùûòÁ|´ùhóÑðk̯1¿ÆÀÁõ×\ù;ówæï„•+#VFÀ#»Gv�ìÀtŒéÓ1°6hmÐÚ 8wëÜ­sÿǹyíííÐj µ…`ÜÀ¸�q0ícÚÇ´äyåyåyÁ×s¿žûõ\ˆ1�1�1M5M5M5à Oxš¾š¾š¾ð|ÁóÏ€ÞIï¤wó æÌ/Àõ%×—\_«¬n°ºhr5¹š\خڮڮ‚ÓO><â–Å-‹[s3æfÌÍ€ˆ9s"æÀï~õð+ÐM×M×M7ôÞ¯›!DÉQ‰JTqÄì~°ûÁÔWê+P±uÅÖ[Ãá‡> Ïæ?›ÿl>\±¿bÅ:.ãbhýkë_[ÿ •kU®U¹¼zðêÁ«>l©Ã¥—: N¡N¡N¡àö¥Û—n_Bʼn'VœÎë�×;¯“Ú&µMjÖXc ä“O>0•©L‹‹‹°o?Þ~<¸e»e»eC¹å”[§Êž*{ª,GGGBó:Íë4¯NþNþNþp6ôlèÙP(=ªô¨Ò£ÀúºõuëëÐåA—]€Ï8Ÿq>ã@“¬IÖ$zg‰×M €¢äУGd‘EpˆCúÝë™d’ xà�ä·ÏoŸßt³t³t³@k£µÑÚ¼|»Å0‹aà 볬ϲ>û/Æÿç_òJO¥§Òó/äÿíÚ…tÒI $ðwñã3ã3ãáq…ÇW€§vœÚq hE+ZAãq�Ç5ô¡}@5Z5Z5Ô+Ô+Ô+ÀÈÁÈÁÈXÄ"zg‰×M®B”¿]h‚ &@YÊRöw¯›bŠ)ЈF4kkk0»mvÛì6¤?Nœþœp xîûÜ÷¹/¸9¸9¸9üã›a†P�zÔûÝòߊ‰ .¸¥)Mi@‡ÿ:bñ¯?çs>‡¢šE5‹j¾\M™ü2ùeò!ß4ß4ßü¯ú_õ¿ ê`u°:øåûB¯†^ ½ú»<æ˜cnè�#Þ4)BˆCi®4Wšƒ©ÞToª‡äíÉÛ“·C¢*Q•¨‚ó^Ì{1ÌrÌrÌrÀz¾õ|ëùЯ _A¿ØóÉžOö|öÉöÉöÉPQQÃO ?1üÄŸ�›œœ Ï[=oõ¼hëkëkëÃSç§ÎO�áI§'�žt‚|×|×|W¿~?ü>dÌ̘™1 îÜ-¸ QÞQÞQÞP%³Jf•LØûpïýáH�#5ŽÔ€®Í»6ïÚÖ\[smÍ5ø±Ö�µ~¬åΖ;[î,xÅyÅyÅÁ“ÙOf?™ y³òfåÍ‚G6�lÙ€=öØz'‰7F¥ü“¡ƒ!Äë¶Ñr£åFKˆÚµ7j/L­4µÒÔJ`¥¶R[©!%%%%%ÔwÕwÕwÁé§_œ~ÅWñU|!isÒæ¤ÍPäUäUäÖݬ»Yw›t›t›t`Cø7ßÓ/ˆ,ˆ,ˆ„¤II“’&ñ¯Sö-í[Ú·„‚eË –AÆŒŒ3Àâ°Åa‹Ã`dndndßf|›ñ-Xݱºcű͋͋!qGâŽÄ`æiæiæ N7œn8Ý€ô-é[Ò·@ú­ô[é·Àx¤ñHã‘`Óʦ•M+ÈÛ“·'od É’5ìžÙ=³{¥ÂJ…• 3ô^oŠ!D‰±aÕ†UVAêòÔå©ËaÆã�g<6t*! C.B”¿�SBHB!J")B!D $@!„(�¤!„%�!„¢’ „B”@R„ïŸ/ø‚/@y¦¤û°égÓϦP›ÚÔ6ôFˆ·•!ô§?ýáÚ—×¾¼ö%l>¾ùøæã «« ýªö«Ú¯*4ˆlÙ ̵æZs­¡C—\IIIp7ànÀÝØ1wÇÜs!5=5=56Øh`#h™ß2¿e>h"5‘šHC§o)B”`¹º\]®¶>ßú|ës8÷�sÿ8÷ð)çSΧtvïìÞÙ,ÛZ¶µlkè´âÏŒ)S0ÎežË<— [7lݰuxîõÜë¹F”Q~Dy°ijÓÔ¦©¡ÓŠ·…!J Ì[™·2oÁªŽ«:®ê óæ'̇‰™3'f‚Ç,�Y³ �RüUñcãÇÆ�…Ÿ–ÿ´ü§å�÷uÞ×y_ÃŒ¼y3òÀy…ó ç†N) Mž D ’W>¯|^yXU¸ªpU!ä¯Ë_—¿æo˜¿aþ†ÿâ9ä€r^9¯œœp ˆ!†˜W°�B � l`p�{ÜÜpà ”o•o•o�½ìeïÿ±ž (~æg~æ_w |]2~Ìø1ãG8×ì\³sÍ z^ô¼èy¿{ÃyÎsøˆ�ø”qÊ8e°‚¬tèнºKŸ¥‡éÕ¦W›^ l¯Ú^µ½ú_¬ÇlàfÊÍ”›)0Ùw²ïd_x°ãÁŽ;þ~ÌüÞù½ó{Ãwß~÷íwß•òWÊ_)‰&„{ì]°[¶ lõçëÉËÍËÍË…Ê e…WG]uuÔ«ŸÖâKÅ—Š/Á¯Û~Ýöë¶—WíÇLŽ™3¶tÚÒiK'Øo´ßh¿d–É,“YV»®v]í Ë�—;/w½£ÞQïøêóY”¶(mQÆ 7xÜ`pZè´Ði!üìý³÷ÏÞ óÑùè|^ý¸âÝ @ˆàþÊû+﯄0ÿ0ÿ0øhÞGó>šÖU¬«XWùVTDEà¶Øm±Ûbˆø5â׈_!mTÚ¨´Wð V3P3P3jÖ(¬Q¥ƒJ•§%NKœ–@Áˆ‚# òzäõÈëP¬/ÖëárÒå¤ËI�åŸåŸåÚµj?„ujÔ©QJ?-ý´ôÓW?¯ÙU³«fW…³gÏž={Z o5¼ÕphYز°e!T¨W¡^…zP®a¹†åB©OK}ZêS°L±L±L�›ov¼Ùô[õ[õ[_}¾ßï3Þg¼FÞygäHÚœ´9i3\ît¹ÓåN¯o\ñv“ D pdù‘åG–Cƒ6 Ú4h厖;Zîè__ŸQ£>F}@ç¡óÐy@x™ð2áeàäù“çOž‡° aÂ6@Ö¦¬MY›àÔ¾SûNíƒðRá¥ÂKAöÅì‹Ùá䘓cNŽ�ð&áM›@á£ÂG…�À8Æ8Æ8òoçßοý»quF:#¨W«W«WÃå–—[^n __ÿúú××á\™seΕ�”­)[S¶‚I˜I˜Iä×ʯ•_ ¢’¢’¢’à°Ýa»Ãv:4thèP8Üæp›Ãm º}tûèöÿyûõóôóôó Ê-Ê-Ê bbbàö¸Ûãn�ƒÑ/¢_Dƒ¦¹¦¹¦9¿üyíJíJíJPPPÕÕÕÈÙ™³3g'\H¿�~!ަM=š у¢EúûŸ›96slæ@§�tZ‡Zjy¨%œ-8[pö5}øÄ[K €ï±Ô›©7SoÂýv÷ÛÝoMG7Ýtô+Xq.¹ä?ð?€q¸q¸q8h“´IÚ$Xc½Æz�5œÛynç¹�°/l_ؾ0Øž½={{6˜|lò±ÉǰÇh�Ñ#ØÞt{ÓíMÁ¸ºquãê°cÔŽQ;FÁ6ý6ý6ýïÆýç¹r•›ÊMåy½ózçõ†„�„�„0_a¾Â|˜39fr ¶·ÙÞf{ØYgý�õ!Î&Î&Ξ_x~áy(=ó)”êXªc©Ž ¬UÖ*kA{A{A{œœœA™¤LR&�¶¿¶¿¶?8¬uXë°H �„ß�›J*© Þ Þ ÞÎ�:Û�¶m7BÍ5oÔ¼6>6>6>`Àþ€ýP}§úNõØ/±_b¿̽ͽͽ¡Ú¢j‹ª-‚v9írÚå@LXLXLäŒË—3²ªfUͪ IÛ“¶'m‡•_T~Qtãuãuã¡ü½ò÷Êß›Ã6‡mCM�š5=À¶—m/Û^àô©Ó§NŸ‚ê”ê”êÔ§Q5]5]5²¼³¼³¼áØÞc{�í¯ ^¼&@³�f!ÍBàYì³Øg±iiiÿ÷wŸÍ-›[6·Àô±écÓÇ�Ô4©i’|=°Ä‘gñS¶)Û”m úEõ‹ê`Cò VüÛÍï�r”£€^xãÏx(5¾ÔøRã!ëqÖã¬Ç`ÚÏ´Ÿi?à1�yü 7Ð#Œ@ÙªlU¶þný5©IÍó~ 4 œTN*'�cãPžò”%P T?üðƒm¶Ûl·Ù­C·Ý:�¿ÆÆ´ÓnL;piäÒÈ¥(Ί³â J=¥žRïÈ_Žr”]˜.Li‡Ò¥‚à˜à˜àˆý8öãØ�¡n«º­ê¶—-.[\¶½éMï¿>m¿�rPuTuTuýAýAýÁW¸_Ä;A €ï1{c{c{cPn+·•Û�v4íhÚQ°ZgµÎjÝ+ Ÿ|ò� T ÂËÅ7=ÜôpTëY­gµž�Õ<«yVsÈWò•üßßuä·"Q–²”ýÝrSL1Ѐÿfy jPÈ@B±}±}±=èÝônz·ß½ß ,xy�|=zô¼¼EîU®r•—§š¨š¨šð¯;#ú‡û‡û‡Ã€Š*¨t¡ ]À¼‚yó �á—á—áÇ¿¾Þ‡;î¸ÿn|*Tÿf;~[þÏq�7o6Þ e‹Ê•-‚fšuhÖ:Ìï0¿ÃüßýÜ&0áïï¶ ¯ ¯ /È«˜W1¯"8¶qlãØæ|Ä;E €ï±Òö¥íKÛCÅ[Tl—+]®t¹Ò¿¾Vÿ—i‡k‡k‡ƒ»µ»µ»5\\|qñÅÅpgÄ�wF@‘o‘o‘/ôû¼ßçý>‡Û+n¯¸½‚6mÚ ‡¶Úrh ¤,LY˜²Œs�s�s!¦8¦8¦ž'>O|žœä$'!"5"5"’ÔIê$5¨[¨[¨[€þ¬þ¬þ,ØŽµk;öå×ñº¶éÚ¦kHÜž¸=q;¨»©»©»ÁÕ®W»^í M š4…§ƒŸ~:žœrþÉyȯ’_%¿ <Ÿ÷|Þóyàhåhåh&˜`ò»íWâ”8%¿êþ*È-Ÿ[>·<ÜýÇÝÜý¸Íq›ã6?.~\ é�Ò;¥w‚[Kn-¹µbnÅÜŠ¹éáéáéá�v-íZÚ5ÔuP×A]áø‘ãGŽ�„* Uª@ÙÑeG— �&4šÐhX˜Z˜Z˜þõý©ŠTEªÀz…õ ëàlælælfèO«xÓäN€B”7Rn¤ÜH�MúMúMz˜;mî´¹Ó ôæÒ›Koþ +lK[ÚBê©ÔS©§ §nNÝœº Û©Û©Û ¶ lØ.ëÍÖ›­7CÑ÷Eß} ³f'Ìõ]õ]õ]`0ƒ êºêºêº`ÕÕª«UWH[œ¶8m1EQPÊ£”G)È Ê Ê â_‡úKw)Ý¥tHßœ¾9}3ävËíöÿcï>㢸úþ�fwéM¥ƒ‚ˆ *XP,(Vì½÷D�51‰Fb,1jŒ±w�½ÄØ{ÃÞ°‚ A�"Ò{]Ø6ÿwüß¹r_IŒÙ¨ó~¢/v÷Ì÷œÝSÎ)íU~ªòS•Ÿ èvÑí¢Û n7ˆ@±@±@±Êë•×+¯616161 j®j®j… /^Û^¶½l{�y#óFæÿiu½YÌbä?ΜÿrÝrÝrÝÀ¬–Y-³Z`•n•n•¹B®�+€ª�ª�ªTšSiN¥9 LQ¦(S@¥R©T*°mcÛÆ¶ YYYBÆ�Œ7@å£òQù€i’i’iX?³~fý äáòpyøŸØ_?+••ÊJeðí¬og}; Z5kÕ¬U3èØ­c·ŽÝô}”JþiR ‘¼t}t}t}`Ó O6<�üYù³ògÁ”Ð)¡SBÁd­ÉZ“µúN)y]tN:'�l¾µùÖæ[�1,cXÆ0ø¢Ã¾è†s çÎyõíHÞ,ÒSÉ;@vDvDv†}7ì»aßAa»Âv…íàûÜïs¿ÏeUeUeÕWߎäßEýHýHývÛí¶Ûm}ú<ô�&|0რÒÿ»N: ‘¼ƒ2ëeÖˬ˯,¿²ü µ0jaÔ&ö˜Øcbp\â¸Äq‰¾SJþªü%ùKò—À¶Ûnl»1ícÚÇ´‡ A3‚f€{‰{‰{‰¾SJôM*$’wX~ïüÞù½aóªÍ«6¯‚èÈèÈèHþlø³áÏÀ_ç¯ó×�ᧆŸ~ªï´’ߣ� � �P±FÃ6ÇmŽÛ¡J@•€*ðá­o}x V8¬pX¡ï´’ ©�H$h«k«k«Ã¥”K)—R`cöާmNÛœ¶Á ¥ƒ–Z µ…ÚBmä“ä“äÃãh’¿F÷ƒîÝ�Ø ±Ab8°ôÀÒK!29292z¬é±¦Çèù^Ï÷z¾FO�ž=ÕwjÉ¿�TH$’ßÈ2È2È2€cŽÇ�9Â�¾7úÞè Õƒ«W†.^]¼ºxA=ÿzþõüÁxšñ4ãi¯¾]ÉöË<QžQžQžü øAðˆ9$rÔÿ¡þõ€þ7ûßìª:Tu¨ê‚—à%xé;½äßJ*$Éï;ÃÎ@JAJAJ\ØqaÇ…pÓø¦ñMc0~füÌø4Ó|Ló1Ðäh“£MŽ‚s¡s¡s!………ê»oMGMGMGH]˜º0u!<þ B\C\C\!oqÞâ¼Åà«öUûª¡ÓÌN3;Í„{kì­±„ÍÂfáoX+@òn� ‰DòÇ}Á|E{Šöí�°Ü°Ü°\¸6áÚ„k ¹mrÛä¶P© RA¥¨Y/²^$Ô¿RÿJý+P]Y]Y] fçÌΙ�…•ÂJaEÅŒ€o9� t”hK´%ZxaûÂö…-„«ÃÕájx4ìѰGÃ Ó Ó ÓìzÛõ¶ë -†¶Úb(4§9Í�*æUÌ«˜qħï^IÞTR ‘H^™¶½¶½¶=dÍËš—5"kEÖŠ¬÷¿¾ÿõý¯áùÎç;Ÿï��ÎGç–ý-û[öO;O;O;psssss§Ï�>wúì­í­í­ÁRc©±Ô€l¸l¸l8¿Nýû¯qŒcqŽ8Gœřřř�1-cZÆ4H”þ(ý$öMì›Øâ¢â¢â¢ «RV¥¬J k¨k¨kÕÚVk[­-ÔŸUVýYPÿ^ý{õï�}sûæöÍÁ`ªÁTƒ©úî¬äm#‰äµ+kXÖ°¬!ü`ôƒÑFpjý©õ§ÖCàØÀ±�c!'5'5'ò¶åmËÛb˜&†�Å·ßZ| U|ªøTñË`Ë`Ë`°ö¶ö¶ö[o[o[ïŠ)mM6˜l0ÙË –,E?E?E?V «…Õ ß,ß,ß Ìf6³AW_W_WtëuëuëA;O;O;ÔuÕuÕu¡LY¦,SB¡_¡_¡ä®È]‘»2÷eîËÜ 6l€Ü©¹Ss§BáâÂÅ…‹A(‚Õz«õVëÁÑÞÑÞÑ<7ynòÜ®Ç\�¹ƒê;ªï¨¾,÷Yî³Üǯ‹I$ÿéP“H$¯]t@t@tÜï¿ÿýþ0Ãü ó7@Ó°¦aMÃ@}Z}Z}ÊÇ—�/™Á™Á™Á�b”b”bT±@®e®e®eÅ= U#ªFT…âjÅÕŠ«�vŸvŸvˆ/Äâ ;‰�ÄNÀr–³ØÈF6‚ØWì+öaˆ0Dæ0‡A¨.Tªßò-ß‚b©b©b)èÎêÎêÎBè†Ð ¡ _P¿ ~AàèèÖqÖqÖqà¼Ùy³ófphíÐÚ¡5dü‘ñG`8ÕpªáT@Däå_·zÒ“žúÞ;’w•t@"‘¼6Iý“ú'õ‡yÙó²çeC·€nÝ ï ¾ƒú¼ñÆû¯·¯MÓ¦iÓ@m¤6R�ÆUãªq­XŒHÛ@Û@Û bù_]Œ.Fâ2q™¸ äååA¨,T*ƒ\!WÈ �)d YÅ©÷ŸíãëC_úú41ibÒÄúíî·»ßn}�²Dò×H€D"ùÛN(œP8¾nòu“¯›@õ‹Õ/V¿ZNh9¡%(&*&*&ê;åŸw§Ý�vwÚÁ§8ýÃiXä¶Èm‘إ٥٥é;�DòçHkH$’¿�V­UkÕ°uæÖ™[g‚Aƒ&M`t³ÑÍF7{s¿øÑx_ã}�÷AµøjñÕâá¨ßQ¿£~úN%‘ü5R ‘Hþ6§—�^vzD¼ñ^Ä{ðц�6|´L?6ýØôc}§{ur[¹­Ü¶Øj`+yò0ä!$¶Jl•ØJßé$’?Gº ‘H^Ù#ûGö�ìaiý¥õ—Ö‡O¯zýÓëà§ôSú)õ�îï'v»‰Ý`yŸå}–÷ªQ�j0ÕyªóTg¼oáîm�Hþ Ò‰Dò—e»d»d»Àúo×»þ[èÒ;¤wø-ð[à·@ßé^á”pJ8ý�ú;õw‚p�p�px²éɦ'›ô�N"ùc¤@"‘üiº.º.º.°m×¶]Ûv�s?ç~Îý W�^uzÕ>ã3>ÓwÊׯz×ê]«w…–ñ-ã[ÆÃ�¸qâ@×Q×Q×Qßé$’ÿ›TH$’?í¢ ‹.,‚˜b>ˆùÆŽ aaaúN÷Ïë5¿×ü^ó!ùAòƒäú,ôYè3}§’HþoR ‘Hþ°ô¾é}ÓûÂÞa{‡íÃZ k1¬8„9„9¼ƒ_ü¿°¿fÍþtÜqpÇÁ°¿ÕþVû[A™¬LV&ý/+ù—’M‰Dò_‰wÄ;âØýÞî÷v¿Ë<–y,ƒ–n-ÝZºé;Ý¿G§�N!�B Ø´Ø´ØB¾ ù2äK}§’Hþ3©�H$ÿÕÃ+¯<¼)))0<{xöðlPÌUÌUÌÕwº�Jw+Ý­tzuèÕ¡W8zíèµ£× hGÑŽ¢úN'‘üÿ¤@"‘ü.õ}õ}õ}Ø_yåý•¡ýŽö;Úï€jë ¯6\ßéþ½ÚÎn;»íl�¥ÉÒdipåÄ•WNè;•Dòÿ“ ‰Dò»î¯¼¿òþJÈžœ=9{2tžÞyzçéúNõïgnn=½W€IDAT½}zûôö�S½Nõ:Õ ( @ßá$’ŸI€D"ù õfõfõf8Þåx—ã] µGk�Ö`Óצ¯M_}§{s´xÚâi‹§`>Î|œù88·æÜšskô�J"ùR ‘H~#ºGt�èðbÏ‹=/ö@à¤ÀI�“ô�êÍcôØè±ÑcèÔ'¨OÇÇÇ@Îòœå9Ëõ�Nò®“ ‰DòÁ«ƒW¯??????pë0ÖaìßÐpI$)¤�òÇ?ölð³ÁÏÕFW]i%‘%‘%‘/½¡ˆ"Š@ÌsÄ u¨ä‘Gž¾G·iܦq°}jûÔö)œI>“|&Yß©þ€rÊ)žð„'@e”ý÷�•½_ö~Ùûp+öVì­Xxñ8âqÄKoH&™dà(G9 â�â�â�À1Žq P¡B¥ïοý¤@"‘üêùÎç;Ÿï„¨&QM¢š@× ]7tÝð74ìˆ#Žð“åO–?Y‘¢#EGŠþ@÷çîÏÝaKŸ-}¶ô�èuÑë¢×AüÊø•ñ+añ²ÅË/ƒDm¢6Q ±Q±Q±Qäää!½Bz…ôÒ÷¨‚Q{£öFí¡ÿ�þ7ú߀K/=¼ôÒ¦=L{¨ït¿/ý›ôoÒ¿�…XxRìSìSìÿûçŽÎ::ëè,¸øüâó‹Ï!>*>*> Î=wôÜQØâ¼Åy‹3ûûûÃÁSO<³²feÍÊ‚¢‚¢‚"éf‰×N*$ɯBlClClÁµŸk?×~P½EõÕ[ü �d$#¡zIõ’ê%àâãâãâóß?ö8úqôãhHOOOOO‡áý‡÷Þ\šº4ui µ§ÖžZ{*XÔ¶¨mQjÌ©1§ÆH6J6J6‚Ÿ¾øôŧ tT:*áΔ;SîLÍ<Í<ͼ~|ú4ôièÕüªùUóƒÓ§Nüó9þ(“““¨k_×¾®=˜7nú<ý¡Û«Û«Û »\ìr± ÔÙZgk�­Ð#¸Gp�`p r r ‚šv5íjÚ�¹�¹�¹8&:&:&Bظ°qaã@½Z½Z½bÅŠ=qKâ–Ä-Ñ÷h¼}ú ‘HôOYYYYYnu¹ÕåV¸vàÚ�k!Û;Û;Û»þîz°Xo±Þb=”û•û•û�GW�®]ÁÑÞÑÞÑn׿]ÿv}0›c6ÇlhGhGhG€³»³»³;60l`Ø´×µ×µ×A´-D Š„"á¥3eëËÖ—­‡È'‘O"ŸÀóGÏ=OÒŸ¤?I‡ªêªêªj0-3-3-åUåUåU°ö´ö´öùUùUùUg‰³ÄYpLvLvL‡—^vxµ jÔ |/û^ö½ iKÓ–¦-…èëÑ×£¯ƒ¡ƒ¡ƒ¡4šÛhn£¹�o‘o‘oQª(U” l/Û^¶½ +�•Æ <šy4óh�?xüÁãÀk�ׯ=`sÝæºÍõŠ~ÉïÈïÈï@ߤ¾I}“`åâ•‹W.†Îý:÷ëÜœ9r>ô×÷£n¡n¡n!„½{ör.ä\ȹ&ãMÆ›Œ¡«ÐUè ~Ûý¶ûm‡ìÙ-²[ÀÓ£O�>= ¶ŸØ~bû h7i7i7�Co‡Þ½Á4Í4Í4 ÊŽ—/;|Çw|÷Ò†ÛІ6�x$ñHâˆ;w$î<ûdì“±ÐØ¦±Mc’„$! „-Âa è~Ôý¨û >6øØàc�}*ûTö)dÎ<œy–w_Þ}yw¨q¯Æ½÷`”Ã(‡Q`½Ñz£õFxØæa›‡m wNîœÜ9PuxÕáU‡ƒ§è)zŠVVVô¦7½AÞRÞRÞâââA£‹ÑÅ@æ¥ÌK™— Qt£èFÑ Ÿ(Ÿ(Ÿ¨ï•¯Ÿt@"‘ðhÓ£M�6�ÖEë¢ußTßTßT(ý±ôÇÒaáü…ó·¤ÑI£“FCn|n|n<,깨碞�‘‘G><òá‘a퉵'Öž€øöñíãÛCúÚôµékáÎì;³ï̆UŠUŠU Ðøh|4ÿáL€ì„ì„ì(ÊeŠ2�m‘m‘mƒíÛ ¶ƒì¾ì¾ì>¬^¹zåê•pÃ÷†ï ß—øù²ÌCæ!󀜌œŒœ (˜[0·`.˜$™$™$AÊ•”+)W`Y�e=–õ€Â‹… /Â�¦7šÞh ›ý6ûmöƒâ�Å‹Âì.³»Ìî×b®Å\‹�§wžÞyzR>Jù(å#ØÕ~Wû]íá™Ç3�g¿?ÞõÞ¯÷~½÷Á³‘g#ÏFptæÑ™GgÙd“ý×÷£l†l†lÜè}£÷�Þ°ÁiƒÓ'0p1p1p�S·OÝ>uv·ÞÝzwk(T2¨d|©úRõ¥ B"B"B" úTô©èS tV:+�aÅÝwWÜ…;†w ïþ‡ Ûb‹-("Š�Õ“Õ“ÕKKK0úÐèC£!>4>4>¾éõM¯ozAñûÅï¿Bª�*¤™d’ Âmá¶pA±A±A±MMMáÄû'Þ?ñ>~pøÁá ‹ÓÅéâ`Í©5§Öœ‚'=ùèÉG V/X½`5Ä��;w¾âž’PÿPÿP8˜{0÷`.¨ž«ž«žëû_ã?G: ‘H™23d&4 lØ0Ì¿7ÿÞü{Ðiƒ´A`>Å|ŠùðêäÕÉ«ÔßTSýMppÔÁQGÁ³KÏ.=»¶!¶!¶!`.7—›Ëa¨0T*€à"¸.�œœ Âcá±ð°Ã»ßæ1ðÙï³ßg?œîºÿéþ�|+ùVò-hkÞÖ¼­9ºººÃ¦:›êlªýÝû»÷wóÏÌ?3ÿ Z|×â»ßAÃ9 ç4œâq‡¸–.-\Zf'ÍNš�üýñ. —…ËÐwpßÁ}Â; î,¸]kw­Ýµ6¸áƫ̰lÓÔ¦©MS¨Ò¯J¿*ý Eÿý[ô‡ÂF…� ÁöšÛkn¯ ]>èòA—À¼­y[ó¶Ð²VËZ-kA½%õ–Ô[ººº`þÌü™ù3ˆÄÿaƒ8ÀpŽuŽuŽ…*�ªtªÒ ¼¾ñúÆë°¿nÝþ:8ìpØá°d¶2[™-0�éLçׂM)ŽGB展ÇV •ÛUnW¹ÔÚQkG­`Óæ‡M8±üÄòËÁ_ë¯õ×Bë•­W¶^ û½÷{ï÷†EŠ�ÃF‡�ÁÞÛÞÛÞŽ8~àx«ˆUÄ* ë¡ë¡ë]’º$uI///}ÿküçHg$’wXÖá¬ÃY‡!Ê>Ê>ÊZ´mѶEÛ—Þ`€@0Á‡8Ä!�-‘-‘-y€<@¥—J/•^!LÂ@æ"s‘¹T|ñÿêw¸ó'jР±ƒØAìd�A ü‰v´hÑ‚¸^\/®šÓœæPâZâZâ é­Ó[§·†Ã>‡}û@|@|@|´ÜØrcË� ÿJþ•ü+ …B¡dé²tY:È2…LòMòMòM`9Ùr²åd�gÊ3å™ÿ=V-ÏZžµ<¡Þƒzê=€£ Ž68Úˆ!†˜Wر?�KYÊÒŠ·1ncÜ”ÔÔÃ@—¥ËÒe�`/Ø ö {!{!{²²² »$»$»¤‘FÚØî/ÇË/w÷O'‰åñQ9rä@8ᄇ9ÌኗóòòòòòàÑüGó͇ý-÷·ÜßªŽ«:®ê8¨y¼æñšÇA7H7H7¨b?ýÒ/ƒO >5øŒ¦M7š^Qàþr¯Ê»B*$’wX„C„C„˜×5¯k^j̨1£ÆŒ—ÞðËãX}èCö û„}PÜ ¸AqP¯T¯T¯û‰öí'‚¸X\,.¡¹Ð\hþ6(C† hK[ÚÆcüüåý=éIOÀSL:tüútMhB“—>÷Ë™o¼ñjS›Ú ™£™£™â|q¾8ª,ª²¨Ê"¨z©ê¥ª—`€ÏŸ>0ùÔäS“OÁ´zÓêM«F#ŒF� ¢ðø_¿¢«ÜTn*7ˆ<y8ò0-6(lPØvîݹwç^¨íWÛ¯¶Ô«W¯^½z°¾ßú~ëûÁÁ ƒAƒàɆ'žl€Än‰Ý»�òŠòŠò ĚŚŚUäÍ Î Î †EÇ_t"GEŽŠõÇ÷C�Oj|Rãh´¤Ñ’FKàèÄ£�N1SÌÿÀ™„ÿM8 @âáÄɇa×Õ]Ww]…>øðÁ‡0üÆðÃo@ÚÙ´³igA§ŒSÆAlÕØª±U�Où”O!6)6)6 •…ÊB%Äõ‰ë×Êæ•Í+ûOQ$ìHØ‘° >*ø¨à#ˆ>}>úQlÔ>¨}�(?qüÄñ¢˜\-¹Zr5Q,É.É.ÉEõ5õ5õ5QLª”T)©’(&&$&$&ˆbù˜ò1åcDQ]_]_]__ä¾È}‘+ŠÏ|žù<óÅ¢oо)úæ·ÛÕtÑtÑtÅ_\|qQã{Æ÷Œï)Šùòä?Å   Q|6ôÙÐgCEñŇ/>|ñ¡(æuÎëœ×YŸ•=+{V&Š)7Sn¦ÜEålålålQ|ø<ðy (&~™øeâ—¢¨Ù¤Ù¤Ù$ŠÅ“‹'OÅgžuxÖAŸW^ýyuQÌ_‘¿"…(|PðAÁ¢———!Š™]3»fvÅÿ¹¤ йF®‘‹bê™Ô3©gDQ9]9]9ýÏï—Äî‰Ý»‹âû3ߟùþLQŒ¬Y#²ÆŸog—÷.ï]Þ¢8àà€ƒŠb|ÿøþñýE1­FZ�´¢¨ ׆kÃE± }Aû‚ö¢&Š™‰™‰™‰¢(Öë‹õE±Ð¥Ð¥ÐEã ã ã E1eBÊ„” ¢¨ Ôj»Ý¢IE“Š&‰b|·ønñÝD19;9;9[KÕ¥êRµ(¦OOŸž>]ãíãíãíE1{vöììÙ¢˜žž.Šñ£ãGÇ�Åü#ùGò�ˆbþ½ü{ù÷D1æÓ˜Oc>Åœ¤œ¤œ$QÔÍÐÍÐÍÅôVé­Ò[‰büþøýñûE1Õ=Õ=Õ]KÅR±TÅ”í)ÛS¶‹â³¼gyÏòD±Ô«Ô«Ô«"o¡m¡m¡­(f|™ñeÆ—¢¨Û®Û®Ûþºÿõý{H€Dò ) ) )Å�eË>–‰¢²®²®²îoß—Ô>©}R{Ql‘Ü"¹E²(÷ îÜSßéß~ëCׇ®Åy·æÝšwK5Æc�ñÿüÚqkÇ­'Š}Ÿö}Ú÷©(æÊ?”Hß½’üÛH—$’wУ:�ê<ªµKj—Ô.ãããˆß¾¯ìnÙݲ»0xÍà5ƒ×€Ñh£ÑF£Aw[w[w[ß½x{õìÒ³KÏ.=þzüuxœ÷8ïñ˜ÒX¨T‚ëû®ï»¾�’:%uJ‚¢»Ew‹îê»W’á—J@ßA$Éë÷˵Û/²¾Èú" m´iÐ&ð/÷/÷/×w:Éÿ¶åΖ;[îÀóÄç‰Ïá«V_µúª(Ž G}§“¼é¤3É;$åqÊã”Ç ¼¦¼¦¼ž2O™§þÈMÌMÌM„¸Uq«âV�*[•­z… pÞV=:÷èÜ£3üϽðàûß?ø^ß©$o ©�HÞ!á«ÂW…¯‡µkÖ‚Í›;6æ¹üW”Ý%»KvØôÓ¦Ÿ6ýû|÷ùîó…¬mYÛ²¶ý÷Ï]-ºZtM<4ñÐDØ¿zÿêý«A×F×F×F_£úúØåÙåÙåA»Äv‰íáp³ÃÍ7ÍQÍQÍQ}§“¼é¤@"y‡DŸ‰>}¼Â½Â½Â�zÔ£Þ?·ý‡‘#FB\Õ¸ªqUáƒÃþà0ØÖ°­a[ã¿Þ"Ñ"Ñ"òîçÝÏ»GGqth{j{j{êkT_¿Î �:'@–{–{–;Ü�¹s÷U& ú«†0„!ð¢Á‹/@Á½‚{÷ô=:’¿J*$’w@A½‚zõ ùËä/“¿ssónûºÎºÎºÎW=®z\uȘ“1'c”,=Xzäµäµäµ ýdúÉô“ðDóDóD1{böÄì�²Ùe³Ëfïó>ïƒÅ‹;w@vKvKv „mÂ6a}[ômÑ·}-úZô5ˆ‘ÇÈcäPÚ¿´iÿŠz;4ßt|Óñbbòò¢A?OMûËT³ekËÖ–­…ës®Ï¹>¬»Yw³î#Œh0¢Ôµ¨kQ×’,’,’,àtãÓ�O7†f̘Aß}oô½çzœëq®üÏ„5úÞk¿U9¤rHåèêÐÕ¡«ó?æÌ”®JW¥ë«·ÿßT_^}yõåË!·ÞÑzGëФZ“jMª�¬³¬³¬3´nÜ"Æ=÷xÜcðºäuÉë”y—y—yƒI_“¾&}Áõ�ë!×C JV%«’¡àË‚/ ¾„ý;öïØ¿cccá½[ïÝzï=ÄbÒ„4! ¾(ø¢à ¸6äÚ�kC`ƒnƒnƒ®F^�¼ Ú³Ú³Ú³/µóóâââ`nnnnnã§�Ÿ>~:œ¬y²æÉš0¥ï”¾SúBĦˆM› ä@É�’�r(åPÊ!8zêè©£§àÌ…3Î\‡R‡R‡R�{È=ä¹—¯]`ïÀÞ�½¡ì~Ùý²û2+dVȬ׿]ÁH0Œ€U¬b°�}ìžò”§ 7•›ÊMÁ¤‘I#“F`ô™ÑgFŸ�ü‚ü‚üPB %/7øóÚ ƒÄ P�T�T�„”“)'SNÂÅŽ;^ì{ý÷úïõ‡JG+­tŒÂŒÂŒÂô½Þ|Ò%‰ä-¦Û¥Û¥ÛIý’ú%õƒ®�»6îÚ˜_¯µþã(P€pA¸ \E¨"T 747474pÄìˆÙ3Øn·Ýn»˜÷4ïiÞ‚7 nôR;?¯'l6 Ag«³ÕÙBÀå€Ë—¡k“®Mº6�/ÏyþËó°UÜ*na²ÁdƒÉ`·Ón§ÝNè6¸Ûànƒ¡Æ75¾©ñ ˆ^¢—è¹—¯�E„E„EôpîáÜÃŽçÏ?ž- Z´(ÓÏM?7ýüul ,@l(6‚ØDl"6á×ņèF7º�à/ø þT¬jXJ)¥ «¢«¢«òR{†bÂ(a”0 Æ c…1Ø4·inÓÚÚ·µok-,[X¶°„QÇGu Ò Ò Òõ½Þ|R ‘¼Å²§gOÏž¹¹¹à1Ìc˜Ç°>‡vžvžv$oMÞš¼2?Îü8ócH2K2K2‹­[-¶VÌ0xÏýžû=wH]�º uAÅ"1é©é©é©�¢JQ¥¨ g|Îøœñ�èšèšè ß;øÞÁ÷ ©wSï¦Þ`<Úx´ñhðøÂã �/ ÚgÕ>«ö4+lVجŽß=~÷ø]hr¨É¡&‡ÀÁÝÁÝÁjzÕôªéòKòKòKúÞ‹¿¯õÈÖ#[�„3–g,ÏX•ãWŽ_9]?ïúy××Pæææ€Y™Y™Yümð·P/½^z½t(t,t,t„¤[I·’nU,ÆXíDµÕN@^Q^Q^„4 iÒR R R  P, E�»È]ä.ÐIÖIÖI*_¨|¡2hii�Í{6ïÙ¼µšÔjR« a„‘¾wÂLš P"y‹…Í ›6vœÜqrÇIX¼mñ¶ÅÛÀÔÇÔÇÔçŸË¡Z«Z«Z �C‡>…ü¸ü¸ü8ð:ïuÞë<Øô²éeÓ ÂÛ†· o šÝšÝšÝ`4Ùh²Ñd(Qþ¢ü¸wuïêÞR¤ HæææàuÁë‚×Ho—Þ.½Ü,¸YpŒ§O1žÞVÞVÞV`¶Öl­ÙZÈwÏwÏw‡È!‘C"‡€PY¨,T»©vSí¦‚Ûf·Ín›A>F>F>Fß{ñ¿;w>î|ö9ìsØÛ/¶_l–‰–‰–‰ßvÄ�Å�Å�áÉ´'ÓžLƒ´–i-ÓZB•mU¶UٹŹŹÅP͸šq5c¨e]˺–5”e”e”eÀÃúë?¬²(Y”, ä“å“å“¡üaùÃò‡Ð`Iƒ% –½éMox\ü¸øq1¨OªOªO‚u±u±u1¸+Üî 0\b¸Äp‰¾GÿÍ%É[ìðõÃ×_‡ÈN‘�";Á—Æ_i B®�+äê;�äïR:¨tPé ˜á7Ão†´=Øö`ÛƒÐûvïÛ½¥5$¿Cº P"y‹%|�ðuÂ×woK_üo'Ó}¦ûL÷Amm-œñ9ãsÆò†å ËÓÃ%É›A*$’·�*^¯Š‡ M†&CUÛTmSµ�¾SI^7ÿ•þ+ýW‚ÅgŸY|çÇŸ~¼¾SIþ­¤@"y •••AAÍ‚š5Á>Õ>Õ>Uß©$¯›aºaºa:ô½Ù÷fß›pîĹçN@NNNNN޾ÓIþm¤@"y e̘=t�F§‡F�½z»’7ƒß¿!~CÀ6Ý6Ý6Τ�I;“¦ïT’©�HÞB   `9×r®å\¨Ü¬r³ÊÍô�JòO105050…¾}úÀÅŒ‹3 㓌O2>Ñw:É¿…TH$o¡” )R6€C{‡öíAˆ¢…h}§’üÓ j0¨Á pövövö†SCO =5Tß©$ÿR ‘¼…2b2b2bÀ®¿]»þ¯ÞžäÍd`e`e`ýû÷ïß¿?\ï½ÿõþ�2)eRÊ$}§“è›TH$oM¶&[“ ™O3Ÿf>­˜�Mònó™ç3ÏgÔð«áWÃN|}âë_W¼žR˜R˜RW¿¹úÍÕo@ÛSÛSÛSß©%¯›4°Dò)¹Ur«äÞ,¼Yx´Z­¾SIôMÞNÞNÞú9÷sîç ‹Æ-·hˆ)bŠ˜»/ì¾°û”Ý-»[v.̽0÷Â\¨D%*é;¼äµ‘ ‰ä-RÒ¿¤IÐåêru¹`þØü±ùc}§’蛺±º±ºqÅZ OO?=ýô4ìß¼óþÍPn^n^nn§ÜN¹�‚”)#RF@¥ÈJ‘•"õ�^òºH—$’·HQxQxQ8~‚ŸàævævævúN%Ñ—¢ïо+úf¹Îr�å C†„ ƒ»SïN½;Ê”(?PñþüjùÕò«A¢u¢u¢µ¾ÓK^7é €Dòɉ͉͉“N&�L:�™ƒ™ƒ™ƒ¾SIôÅ8È8È8\º>t}b7±›Ø xÈCþöýyóæ „DãDãDc}§—¼nÒ‰ä-’ö4íiÚS¨<¤ò�ÊCÀÈÔÈÔÈTß©$úb 4P(aBà„À �°vÊÚ)k§€ÛçnŸ»ý§å‚£‰&CCC@·M·M·Mß½�¼.Ò‰ä-’S�S�SUVYXe!p„#Ñw*‰¾É“åÉòdÔtPÓAM¡Ò�J7*Ý€iÉÓ’§%Cx�ð:áu€¯øŠ¯ ¡GB�„PRZRZR £,FYŒÒw/$7é €Dò)xTð¨àTž]yvåÙúN#ù×¹Ãî@§ÌN™�2aÓÁM7„€7nT¼-æFÌ�˜Pܯ¸_q?}‡–¼.Ò‰äm F�ò=ò=ò= n׺]ëvÒI']ßá$ÿ:N8áMÔMÔMÔ°1zcôÆh4,hܪ~«ú­ê�}=ûzöup<áxÂñ”Þ.½]z”Ó”Ó”Ó@}]}]}tž:O�'¨WªWªWFaU ªTá™ðLx��L¾6ùÚäk0v1v1v™�ÌGæB²�,$™ÈD}ÒÛO*$’·€6U›ªM…ÂÎ…� ;Cå�+\ùc}§’è�^xAI‡’% ß+ß+ß ò ò ò+îI]–º,uÔºXëb­‹u%êJÔ˜›07an8¦8¦8¦€ÚEí¢vmmmmmmŠŃ ¶[Š-Al$6ÖXc ÂûÂûÂû 8 ΂3 ……ÂB�••…‘ÂHaÆŸnü9X„X„X„€•ÖJk¥…J5+Õ¬Tª®z¸êapzâôÄé X5±jbÕ*=¬ô°ÒC0O7O7Ožð„'úô7‡ þLßA$É_W´¯h_Ñ>ºt%è |fõ™ÕgVPkQ­Eµé;�äuÑÞÖÞÖÞ†âóÅç‹ÏCƒ„  Ú9Ú9Ún'ÜN¸ )•S*§TÕIÕIÕI�×�×�׋Ç�-ƒ]¨]¨](ØxÙxÙx�EC‹† A¢Q„€c%ÇJŽ•À¢¹Es‹æ`öÜì¹Ùs0jjÔÔ¨)Èd²0Tª U@5ªQ ÔÓÔÓÔÓ@û�ö;íwPþ~ùûåïCɃ’% 8±8±8J®•\+¹ï¼Wðä�É“7rÇåŽË™f™f™fP`Z`Z` ºÕºÕºÕ P)T 8Îpœá8Üänr79x�÷ï5Ü]Ý]Ý]Á<Ä<Ä<f 3…™¾÷Ú¿‡TH$o�t÷t÷tw˜¹kæ®™»`ᜅsÎûóöçíÏë;�äUiŸjŸjŸBRpRpR0<ÿhü£ñ>.|\ø8H¿—~/ýÈ’eɲdpâ<Äy¸yºyºyB­/k}YëK°)²)²)‹“'-N‚¹Ò\i®E?E?E?ÀC õÝÛÿÐW­«ÖŠ÷ï-Þ Å-‹[·„ìžÙ=³{BLPLPL9õÉ©OàAñƒâÅ`gg-7¶ÜØr#4ÍmšÛ4l l l @^]^]^¨Nuªë»7ÿÆ{Œ÷ïO<ñ¤âÏ®­º¶êÚ r/ç^ν a7Ân„Ý€kæ×̯™ÃñÇ޶޶޶УA�=€ûF÷�îAÞDÞDÞDß½ûûHg$’7HÁ–‚-[àƒÍlþ`3\»síε; ë­ë­ë JC¥¡Ò,’,’,’€Câ,hµ Õ‚VðAì±Äê»’E/Š^Á�<à‘Û#·GnPw`Ý�uB· nAÝ‚ æÐšCkÃ]†» wé;õÛKU¨*TBâƒÄ‰àLÀ™€3ð`ôƒÑFƒ×÷^ß{}cÆ Œ� j4¨Ñ@ß©_�TH$o 9ò9ò9r˜_w~ÝùuA|,>ÿâ?N]œº8u�#qGâŽÄA“˜&1Mbô�þÝS–R–R–§N%œJ€–',OXB�yuæÕ™ý ûö7·Jn•Ü*�°^X/¬×wêwXšÐ’’“’“’áˆçÏ#žpßò¾å}Kèt¿ÓýN÷¡Wí^µ{Õ³ fÌ.è;ôŸ'ÉèÖù[ço�‡n‰Ý»%BÞ¸¼qyã~û¾îNÝ�º;Á¾žûzîë ¦ëM×›J_,ÿ˜Ì~™ý2ûÁ÷¿ŸøýDȘ’1%c Œöí9ÚMj4©Ñ$�µ•µ•µÕwZÉïLjcÄ1aaa›¼6ymòÓ»¦wMïÂ$&1 ¨º¥ê–ª[ô�ö�“f”HÞ@µÜj¹Õrƒ¦›^lzñ·¯+–*–*–BLJv|(}ñÿÓž‡={ .x¸à!˜M1›b6¾]ýíêoWƒß!¿C~‡¤/þ7…°YØ,lŸ•>+}VÂü„ù ó êðªÃ«‡oL¿1ýÆâêÅÕ‹«§ï´œTH$o *5«Ô¬RÚMo7½Ýt�M“M“M«xÝa³Ãf‡ÍÐnp»Áíë;í»#Ó&Ó&ÓVŬŠY>W|®ø\�OÆ~2ö“±P¹]åv•Ûé;å›§(´(´(â­â­â­@i«´UÚê/�Õ"«EV‹`‚áà †ÐÊ·•o+_X6pÙÀe!¹crÇäŽúµÿN*$’7X{ÿöþíýÁé¶Óm§Û?˜0;`6T_P}AõúNùöÓÞÑÞÑÞ�]vtÙѪ׬^³zMx_ù¾ò}%}bô‰Ñ' �Ÿ´?i‚kó¯Í¿6¶¬Ú²jË*(­SZ§´Î«çÌóËóËóƒ=½÷ôÞÓ²f5Ìjñ3ãgÆÏ„ï‡?üû᥉ÒDi~¿�ܹ7roÀß=¾{|!{eöÊì•ÿ¸–Ü-¹[r¶oÚ¾iû&غ;tw(D>Š|ùï>¼ûðnˆß¿1~#¤‡¦‡¦‡Âæ™›gnž !º]ˆîïÏõ E E E tvÐÙAgÁÏÂÏÂ϶šn5Ýj e§ÊN•�z}ÛUR ‘¼Áj÷­Ý·v_ð}äûÈ÷~kø­á·Ð>¼}xûp0kfÖ̬™¾S¾ýîÄ߉¿YYY0òۑߎü < < <ÿx;ò¡ò¡ò¡ ýRû¥öKØ“µ'kO”L(™P2áÕsª»¨»¨»@zŸô>é}@]S]S]l²ýÉö'<*xDEDEDE€ÖNk§µƒ„‚„‚„KÄ±Ô Õ Õ !}Dúˆô >¯>¯~ N%”'”'”ÃÍS7OÝ<Ã<ü1¸ tè6ÒìÒìÒì@ù©òSå§`íiíií a3Ãf†Í„ot¼ñü&.ß+ß+ß ƒG 1x¨‡ª‡ª‡Âõˆë×#^ÿöÿ*©�HÞ`&óMæ›Ì‡¦QM£šF�MW›®6]¡‘w#ïFÞúN÷öÓi‚4ApnܹqçÆAë¸Öq­ãÀê¨ÕQ«£½]ËË–—-/ƒÆCã¡ñ€¤â¤â¤bˆy/潘÷ ÿ£ü�ò?‚’g%ÏJžAÌõ˜ë1ס¨rQå¢Ê«øÅ¬ˆY³ŠêÕ-ª ¦ï™¾gút¯Ü½r÷Ê`QdQdQæ×̯™_ã{Æ÷Œï2dÈà‹ /.¼€•WW^]yž‡>} ƳŒgÏ‚îuÿ¨ûG`ºÝt»évx‘ö"íEÄËãåñrxð<ày<ÝûtïÓ½PÖ¾¬}YûÿÞ1QL!qGâŽÄ�ò(åQÊ#(Š-Š-ŠÃM†› 7Aç{�ïu¾ùùù``e`e`f§ÌN™�ÁSð^*À”}”}”} ®E\‹¸«ŒUÆ*A9J9Jù7,wlVŬŠYè0¬Ã°Ãà‚ .,ÕAÕAÕÁ×z(þ%R ‘¼Án½wë½[ïÁ¡ƒ‡:YYYðCì±?ÄB¾s¾s¾³¾S¾½òGæ�Ì )ÝSº§t‡º=êö¨ÛãÕÛz =…ž�ÆöˆíÛÎ9�s:çóGÏ=4DÙFÙFÙÂÔ½S÷NÝ W¼¯x_ñ†‚»w îÂùù9\ùþÊ÷W¾‡‚¢‚¢‚"˜l4Ùh²\™zeê•© s‘¹È\€zÔ£èšëšëšCh�С= Ü4Ü4ܽ½½!óÓÌO3?…Éq“ã&ÇÁõÃ×_? û¿Üÿåþ/aföÌì™Ù K:/鼤3ì­½·öÞÚÿ½ÿª0U˜* R›¥6KmÊe�bZÇ´Ži yòõ7êoÔêyÔó¨çNININIо^ûzíë�‹§‹§‹'ØlµÙj³Ê{•÷*ïõÛq”u“u“uƒgÕŸUV.¾pøÂaz~èù¡ç¡ÇÚk{¬…Sѧ¢OECvnvnvî«ï?s�¹Î\¦ûM÷›î‡Œ3>Ìøð:(ÿ©�HþÍ $ §N)œ�¿~üõã¯aKÏ-=·ô„{Æ÷Œïƒ0[˜-¼4g¹I¢I¢I"˜~gú�éwúîÄÛK~@~@~tÃtÃtÃ@÷©îSݧGÃÈ‘ƒxH<$qÄŒ-6Z Öµ­k[׆ÔüÔüÔ|À[l©˜óög‚¹`.˜vØa÷Rûf˜aö~þ¿©P¡Þã=Þ ( ÿC;Z´h�;ÜáÎKÝ9#?#?ÚvÚvÚvPüAñÅÀÂì…Ù ³!(-(-( æ¹Ìs™çEK‹–-ÁEp\€÷yŸ÷�‡<äáKù 0Àp §ßÆò„æã—ÚïD':�ð‘ð‘ð°‘�läׂS˜+Ìæ£Íh3Ä 1H!…@ƒ �…ÎBg ƒ„AÀ|ÁÀAòò5oSL1aª0U˜ &¶&¶&¶0¼Êð*뀺“º“º(Ú(Ú(Ú€Å`‹Áƒ©(hB %ð ¯—ÚuÇwv »„]ÀG|ÄG@ jP0Çs033‡ .@÷Ðî¡ÝC¡êüªó«ÎúÑ�~`ØÖ°­aÛ—úùe-ÍZšµÊ\Ë\Ë\¡ê”ªSªN6°� ¯õ�üS¤@"ù'e‘EäûåûåûAø©ðSá§àVÜ­¸[qWWW†w ïÞ�:fuÌê˜Á˜ªcªŽ© î;Üw¸ï€J�•+Vü†c·Ün¹Ýr¨ìPÙ¡²Œž5zÖèY`ll¬ïN¿½,'XN°œ³=f{̆ûŽ÷ï;‚—ÖKë¥ýëí·7noÜŒîÝ7ºwÞix§!yyy�y{óöæí!pfàÌÀ™Ù.²]d;u u u÷±îcÝÇBQFQFQäÔÉ©“S’/$_H¾yÃò†å ƒ$Ç$Ç$GH´N´N´†¼°¼°¼0Hþ.ù»äïÀ©®S]§º�R+¥VJ-¸`tÁ肸«ÜUî*È=�{:÷4ÄŒ? &L,˜¹Gs�æ­x\0½<½<½r{äöÈí¥ËK——.×£®G]�¾Ôñ"ˆ1WÌsáyæóÌç™�{8÷pîax¾íù¶çÛ€e,cdœÌ8™q4W4W4W %(%(%²/g_ξ̯SúZo±Þb½¤5Hk�'Fœqbøºøºøº€Ã ‡3Àý®û]÷»¯~&àÎÖ;[ïl—z.õ\ê�ƒ™ƒ™ƒ™¾�Öß’¦–H^‡‘Œd$Ü(¸Qp¢;GwŽî !'BN„œ€è�þŒ6 ¾};úv„Æ¡�C‡BMûšö5íÁä®É]“»ÿ}s¡kBׄ®�]·wÝÞu_]|uñU0I1I1y…ßd$ÌS³§fOÍà»”ïR¾K� A‚€ËX—±.cÿ|{åõËë—ׇ'»Ÿì~²”�”�”�@wLwLw > > �P-¡ZB5(î^ܽ¸;ø6òmäÛ,Ì-Ì-þéqí·Úoµß“€'O u@ê€Ôà‘ç‘ç‘–û-÷[î‡H×H×HWP„*B¡à²ße¿Ë~HÔ&jµ Ÿ!Ÿ!Ÿ F5Õ`(++Ó:Oê<©òRy©¼¼¼¼ zÝêu«×ÙVÙVÙÖ?¿ßÒóÒóÒó`‰Ã‡%0¼öðÚÃkƒïC߇¾õ}”þ–TH$¯â Oxª¶ª¶ª¶÷4îiÜS¸ºøêâ«‹áaÌØ‡1 |%|%| "D4ˆÿ*þUü«€çHÏ‘ž#Áx�ñã5À 1èÏÇ:.tì\µsÕÎU°Äu‰ëW0É2É2ÉÒ÷ ½;vÖÚYkg-ˆ‹‹ƒ™Wg^�y*u¯Ô½Rw}§“¼.ÅÏ‹Ÿ?‡åõ–×[^ì§ÙO³Ÿ㯌¿2þ ç…óÂk˜'áUI—$’?AÜ-îwCòµäkÉ×àŽÓ§;NpËé–Ó-'(ìWد°x™x™x™À˜ucÖ�Y^½z ‹»w-^þ�>ƒ 2ôÝ+Éße@ÝuÔ…´¡iCӆ²´eiËÒ`ʇS>œò!X'Y'Y'é;¥äïR0´`hÁPX·pÝÂu Ak¡µÐZÀÐAC Â,a–0Kß)Ÿô€DòŸSL1úúúà ù ù 9Ìš4?æ›;lî0þ<ü9tºØéb§‹°°Å [@ÐÉ “A'Á¯º_u¿êÿá‹ÿïöóMc¿þ) è{ß=&‡M›†½>ôúÐ ¬,­,­,aîÁ¹ç„'ÓŸL2ÄŸÄŸÄŸô�Vò§-a K .7.7.¾¶ÿÚþk{кiÝ´n0yâ䉓'‚eMËš–5õö¿“.H$€v«v«v+$''ÕW^\ywºßé~§;áB¸Í7;Üì0´ÞÝzwëÝPµ jAÕ��‘�‘�Ñ_þÐ�¡C7®ջVïZ ‹Ó§-N“\“\“¿á¹fÉ_S>¥|Jù”Š g‚KƒKƒK¡Kv—ì.ÙÐò‡eK°œi9Ór¦¾ÓJ~OéÞÒ½¥{á´æ´æ´Ž Ç„c´.h]к†.ºdè0M4M4MÔwÚ?Nº y'ççç½¼{y÷òàòùËç/Ÿ‡$¯$¯$/p3s3s3ƒ÷V½·ê½Uà]Ï»žw=°xdñÈâP›Úü�Íþ)ò~ò~ò~ /——ËËAì(v߀ÕÈÞvF+�V­„¡%CK†–€O3Ÿf>Í`Wý]õwÕ‡;oì¼±zG÷Žî -¾hñE‹/Àì˜Ù1³cúNÿîR–+Ë•åpG{G{G G<�xñ!@à“ÞŸôþ¤74ŽmÛ8„D!QHÔwê?O: y«‰#ÄâHLL„ku®Õ¹V®¥^K½– b ±…Ø …®…®…ªW ® ‚›à&¸é»ÿÝÃF=l;·ìܲs |SðMÁ7`ÚÚ´µik}§“üoÊpe¸2®ö¼ÚójO8±íĶÛ@0 CŒ Œ Œ„fîÍÜ›¹ƒýrûåöË+¦¶•ü=Ä¥âRq)dÿ�ýCöVVVg?9ûÉÙO ¬yYó²æÐùãÎwþgÎ œæC͇šÕwúW'’·Š&D¢ �¸}qûâöA°A°A°< ~ü(œÆ:�u =;zvô¿ý~ôûLš4ô¡}ôÝ‹?ï¡ýCû‡ö°µíÖ¶[Û¢ۋn/ºýæ�’|çä‘G”6-mZÚn¶½Ùöf[8ßô|ÓóM!+>+>+¼&zMôš-ÂZ„µïÝÞ»½wƒÅp‹áÃAÖKÖKÖëÕ㼭įůů¡hfÑÌ¢™mmm 7ÜpcDŒŠ1 ¬[5¶j �K—.©øÅÀÂÊÂÊŠ_çx[H€ä�VšUšUš¡×B¯…^ƒóÎ_8RW§®N] õ×o\¿1tl×±]ÇvPó`̓5‚Á ƒ/ô�þïóÐì¡ÙC3ر1bc,½¶ôÚÒk`ö¾Ùûfïë;�äÏ*¿R~¥ü $.K\–¸ BœBœBœ üiøÓð§P~§üNùp=âzÄõÔQoD½PóyÍç5ŸƒËr—å.ËÁdŠÉ“)€X¼jª±ŸoÚ-·.·.·†dËdËdKˆk×(®V>VBüÙø³ñgÁÀÞÀÞÀê¨{ îhÐ8 1¸7qoâÞŒãŒãŒãôÝ©×O*$o”_V_»ñù�Ïo|gãÏÆŸ��F£Ñh uTë¨ÖQÐêX«c­Ž�ãMÇ›Ž7Š·ùŽ—‡æÍšÃ&å&å&%,Ùµd×’]`6Ôl¨Ù[pªRò?ÊN–�,; ñ³ãgÇφÈÊ‘•#+Cd‡È‘ £ZFµŒj ''µj9Ô×Ö®­][ƒ{ˆ{ˆ{ØùÚùÚù‚eˆeˆe˜]6»lvL L L @î)÷”{¾zÞ¿J7O7O7”¾J_¥/w,îXÜŠ-(ZYƒ³g †x³x³x3x¾ûùîç»!í»´ïÒ¾õõõ°[h·Ðn!ÔîS»Oí>à½Á{ƒ÷¨ùSÍŸjþ¦¦¦úÞ«ú#’§ `äœÈ9‘s.´½ÐöB[¸tùÒåK—Á8Ö8Ö8ºt)èR-´<Ðò˜Ï3Ÿg>OßáÿyRðnÓŽÒŽÒŽ‚bM±¦X‰7$n€ø±ñcãÇBBqBqB1¼Xÿbý‹õPZPZPZbM±¦XäkåkåkÁj±Õb«ÅP¹såΕ;ƒU«V ÀÌÛÌÛÌÌvší4Û &·Ln™ÜC�¡ÆP²ë²ë²ë`0Ë`–Á,�ÇÉãäq ê ê êšMŒ&TkTkTk@iª4UšBé´Òi¥Ó D[¢-ÑB�G�G�ä�Ï;Ÿw ´Ú-h/k/k/W¹ÊU0™`2Ád8…9…9…�[°[°[0Ôì[³o;PýVõ[Õo�e?Ë~–ý@þBþBþ�ñû»¼Å¿IÞ(%”P/¾øb œË?—.n,»±ìÆ2°›b7Ån ¼÷Ù{Ÿ½÷44hhÐÐL½M½M½o¼ñÖw'ôG,‹ÅbKÅR±8ÊQŽê;•äŸ"ß&ß&ßVXaÔ§>õ�ú?Õÿ©þOÀMnrʋˋˋ¡xTñ¨âQPÔº¨uQk(”Ê å�Q'£NFȨŸQ?£>*÷}îƒ������¾ÓÿûG…£ÂQÔ‚ZPókA%‘à�?þ`„F€Ñ£;FwÀk¬ÿ¯ÏMe*Sÿ�×ÓH# È$“LÀgœaÑÕEW]×f®Í\›Á�à!ÁC^^”*Ž8þÌ5öŸWýc8îïÁ|{H€äŸñóÝõ)Y)Y)YpìÖ±[ÇnÁ�Jw*Ý©µ'ÕžT{|üEðÁàYìYìY ²²²úÿ律©˜©˜ +…•ŠŠeTÇ2–¿°�Dò‡8âˆãK®`+ÀØÙØÙعb"$zЃú+ùߤ@òZ¥ú§ú§úÃÉè“Ñ'£áæ‡7?¼ù!xzzÂôƒÓN?žåžåžå ÷‘ûÈ¥ßðÿ¼}ìc�N:éÀZÖ²Vß¡$ï*Ãñ†ã ǃR§Ô)u¯Þžäõ� ÉßcÓ˜iiipzØéa§‡AÈŠ�!+À½£{G÷޵ïÖ¾[û.È�åÆrc}‡ ¤’J*¨W¨W¨W€ØFl#¶Ñw(É»ÊÄËÄËÄ òîäÝÉ»£ï4’ß#’¿æ—¸¹µrkåÖ‚“‡N:y.�¸tâÒ pmîÚܵ9L¾7ùÞä{àÓÞ§½O{�í•í•íÕwø·Pe”�v§v§v'ЉNtf0ƒú'y×Xܶ¸mqR¦¤LI™¢ï4’ß#’?¥8¢8¢8.TºPéB%8p*àTØæÚæÚæÂ§?=øéAðžî=Ý{:Ô4¨iP8ÂŽè;ýÛOð<O µ¨¥ï4’w•¹Ü\n.åYåYåYÐÐÐÙYÙYÙY}§“üB*$ÿ§òíåÛË·Ã-Ý-Ý-xhà¡� [ [ [#"GDŽˆ„f×›]ov ;v4”¡ù版ˆ/ý)‘è‘yºyºy:(/*/*/‚æ´æ´æ4bˆ¡¾ÃI~%’ÿ�h&š‰f•••»“v'íN‚Œ°Œ°Œ0è5²×È^#¡½{ÿöþ`jbjbjt¤#Ò¿þü2Õë/wc ú%yWçç為™º™ºhghghgÛØÆ6}§“üB*$¤þ”úSêOpðãƒüîͽ7÷Þ\° ° °…Ï ?+ü¬¬eÖ2kÒc=ÿ2ò™ò™ò™ < �A,ËÄ2}§’¼« 40hºÛºÛºÛ i¤i¤i¤ïT’ÿM*ÞQ¥ãJÇ•ŽƒsCÎ 97Žõ?ÖÿXð¸îqÝã:|¥ùJó•ܹ/r_ÄŸD¢W²š²š²š MÐ&h|ðT¨Pé;�ä]cð™ÁgŸ�î¹î¹î9hnininé;•ä“ €w„ØDl"6�G)�R¥À®â]ŻС¬~Yý²ú0ÎiœÓ8'hr¤É‘&G@ž.O—§ë;µä�ª Õ„j@;ÚÑÄ=âq�¾SIÞU†] »vZЂ =¬=¬= |ÄG|¤ït’_Èô@òze©²TY*X×v]Ûumae핵WÖßk¾×|¯Á· ß&|›Ík5¯Õ¼–ôÅÿ¦’»ËÝåî .Š Al+¶Ûê;•ä]¥(V+ŠA×B×B×´*­J+�‰úבμeÔÛÔÛÔÛàºêºêº ö$ìIؓՖV[Zm)Ì�›77ÜÝÝ�e,c™¾SK^•pD8"m=m=m=*»”¿”è�b•b•bˆ·Ä[â-Ð\×\×\×w*Éÿ&oºŸ'€yqòÅÉ'aÇ¥—v\‚øVñ­â[Á�Cn ¹múµéצÔ0¨aP¨A jè;¼äï"/�È @/Œƃ¨¢ô¯[¢' #…‘ÂDÑF´��ÎGç”RJ©¾ÓI~!ýñ†R7V7V7† Á‚/þFûík>¶>¶>¶°°ÓÂN ;�}ª}ª}*P…*TÑwjÉë"L& “Aã¦qÓ¸2dÈøíò¨’¿&’H"AtÝD7DADÀ 3ÌôîßGá¯ðWøƒ8H$M²&Y“¬ïTÿbPP1�‡�/ä ù€+®¸¾¾ÍJ÷¼)®r•«�Z%µJjX¼cñŽÅ;àˆ÷ï#Þ0fܘqcÆÁä�“wNÞ öeöeöeH_üïY�¬@V2™ƒÌÄiâ4qš¾S½ùÄâ q\zýéõ§°¢óŠÎ+:Ó3OÎ<9S±öRñáâÃŇA9C9C9âÓãÓãÓ!«0«0«Pß½øç8àÚ�µk?Öwªß§j¡j¡jÏ­ž[=·‚ÔC©‡R{ØÃßp3mɘ’1%c %$%$%tótótó*^8îḇã`•Ë*—U.pÛê¶Õm«×ßo©ø—Ӟממ‡óUÏW=_fžyxæa0ŒcÌZ0kÁ,hy¾åù–çA¾E¾E¾Eß©%ÿ4ù ù ù LÁ444ô�꟣٨٨Ùb�$ý}í¦nNÝœº~üàÇ~üêß«¯þ=�GÈ#ä°"kEÖŠ,M M Me±²XY ‹Ú/j¿¨=lk½­õ¶Ö/å\¬Y¬Y â2q™øß{£h¬h¬h еее tV:+�õ�ê÷©ÜTn*7Ø:b눭#`aû…í¶q¢8QœøêíßßpÃý °üÈò#Ë�@éÒÒ¥¥K¡xHñ�â!°Åw‹ï_p‹u‹u‹››67mn¾þ~KÀ¿Tî¹Üs¹ç`ÍÍ57×Ü„½óöÎÛ;Þ¯ñ~�÷kÀ”€)SÀöcÛ�mÿÅ•µäŸ!dBˆ‡ÄCâ!ÐZh-´¯‹¾¢¯è t£ݨ¸4Кִ²È" XÊR–[ØÂË…äArÄ®bW±+ˆ;Ä⎗>÷ó*>á>>æc>~i»½éMïÿ¼�B A<%žO�8Gœ#Ί)¦˜Ë\æR±¼q $T|¼À§À§À¶ÚnµÝj ™ù™ù™ù/µM4ÑÀ—|É—ÀINr˜À&ƒÌàß׬#YG²Ž@òÆä�ÉÁûï¼?�Ù³=fÔSLYMn5¹ÕäTY[em•µ`W`W`WªpU¸* ;v,ì[Ÿm}¶õd�Í›5ö¥ ýÜ_ñ xP<â"q‘¸ˆ_ïñùuQ§�ld#C 1Àp†3\ßGßo)T •B†‹ .e]e]eÝ¿qa„âdq²8¹âO 'H$‘D`"™œãç@üLüLü ıD,©hÎüGóÍ—h—h—h(³(³(³ÑD4M€›Üä&ÇÑÏíDAT,¾¥D‰ò·q}ý|ý|ýàs«Ï­>·³‹fÍ.Báܹ…s!Ö1Ö1Ö<'zNôœ5»ÖìZ³ë?°Ÿ^ÿ&$„ø¹ø¹ø9<²~dýÈ6>Øø`ã°ûÊî+»¯`þ²ùËæ/''' ‡rô�Zòo¡°TX*,Aå¥òRyÁ⹋ç.ž 111à|Þù¼óy(]Yº²t% m0´ÁÐðXóXóXçÖŸ[n=ÔÛ_o½ý`|Êø”ñ)èÙ%²K$œ?|þðùÃ�r#åFÊ P?V?V?††‰ &Bã³�Ï6> k�­=¶ö”*K•¥Jpöröröe�2HC͆š 5»»»íÚ-´„ 9rtWtWtWÀÏÚÏÚÏjd×È®‘ ßµú®Õw­ fÝšukÖÝÝÝ(1*1*1‚]Mv5ÙÕtgugugAQ¨(TÂýÈû‘÷#a‚÷ï Þ`gegeg;Gî¹s$´Ö´Ö´Ö@SšÒô¥ñ,;Pv ìÜ^}{õíÕ�P?¡~B}8}"úD4´Ñ¶Ñ¶ÑÂþo÷»ÿ[ð|æùÌó `<ðÀtOuOuO!¸,¸,¸ 6´ßÐ~C{������€þ7úßèž.xºàé¸iqÓâ¦EÅ:MO6=Ùô$¸p=àzÖE®‹\ µ¢kE׊]¨.T íÆ·ßn<WWWƒO7Ÿn>Ý }¿öýÚ÷ÓÃñè¥ðRx�Áƒ%K ô‡ÒJxõvµ×´×´×àbÝ‹u/Ö…˜Ø˜Ø˜XÐÓÓh³ýÍö7awûÝíw·‡¤o“¾Mú¼“½“½“áa¯‡½ö‚¾ñ}ãûÆC£Ñ�F7 Ô¡u€œà\)»Rv¥ öÞÝ{wï]î7Üo¸ÔŸ[ný¹°«Î®:»ê€G”G”Gt2édÒɤ"¯øX|,>†‡=zÀ±-ǶÛúðЇ‡à‘æ‘æ‘G'ŽN]QŸV]it¥Ñà´Õi«ÓÖ×·Ÿ¤3z¦j«j«j {Oí=µ÷,k´¬Ñ²FÐvwÛÝmwÃŒof|3ãpÚæ´ÍIšC[ò{F1ŠQ`nenen¹.¹.¹.PæSæSæC[m9´%dª2U™*Ø›½7{o6ØØØÀµ×V\[Î}�û:÷�R�R�R¸réÊ¥+— 8"8"8ú'öOìŸí¶Øn ¬ÿtý§ë?…4¿4¿4?(½Vz­ô”÷/ï_Þ†Œ2fÈHÛ”¶)mìÕíÕíÕAŽyŽyŽ9¬>µúÔêSÐdz“éM¦C@Ç€ŽaݲuËÖ-ã×3ñ#âGÄ�€œs9çrÎA“ M&4™žÏ=Ÿ{>‡J#*�¨4º„w ïÍ5oÔ¼DäDäDä€.@  aŠ0E˜S ¦L…µjÔªñVM4`<Àx4¨Û nƒºà˜í˜í˜ Äb< = = ¡Ð±Ð±Ð"="="=^jà/xŠjŠjŠjàVÓ­¦[M¨´µÒÖJ[¡ÓG�>êô(W)W)WÁšëk®¯¹þ{ý÷úï…æ½š÷jÞ ÖM\7qÝD�ûÈ}ä>»0vaìBÈ÷È÷È÷€F¥�J•‚áxÃñ†ãÁæ‰Í›'`þØü±ùcýŽò=ò=ò=`nnʡʡʡ¯ÞnxëðÖá­a÷ÒÝKw/…n3»Íì6z�ì=²÷HØscÏ�=7 <*<*< D;ÑN´ƒçKŸ/}¾ºî뺯ë>0»fvÍììÙ²gËž—Ïtý|æ@è&tº�—»—»—;$&'&'&Cɺ’u%ëÀÀ×À×À4Aš Mx–y–yþ‡©·ÁGð�ªšªšª¸{ôîÑ»GA¹V¹V¹Z6´lh öþöþöþN»�v;í~ýûI*ô$#:#:#–”-)[R7Žß8~ã8|øEà�0`Ñ€E�Ñ£=FÒŒn’ÿB¾C¾C¾ä)òy ȳåÙòl0¼kx×ð.XDYDYDA­ãµŽ×:‘}#ûFöyGyGyG0?c~Æü xyyAýÚõkׯ �>„*ŽU«8‚}eûÊö•Á³À³À³t™ºL]&¿øü"T›VmZµi`kkkkkûûãjǪ̂™Q3PÜWÜWÜÓOL?1ý¤âuÅrÅrÅr�­”­”­|éƒ4høõRˆÁ"ƒE‹@¥ˆRD�Ù³ f ûtöéìÓðldzÏv@†o†o†/¤þ�úCê�n–n–n¥{J÷”Fs�æ‚ëc×Ç®�¡arÃä†ÉPÕ£ªGU~{øíá·¡éܦs›ÎÕ÷Q † ¥Z©Vª_½½'gŸœ}rOOOÁ%Õ%Õ%ªÇV�­ VÍ­š[5‡u„:B F+ŒV­ƒï ¾3øÌ›56k ö�í;Ûw†‚Ž ^^ÄL�50†1ŒÇ8Ç8Ç8èØ!°C \޽{9’Ì’Ì’ÌÀ*À*À*܌܌܌~?·ÁçŸ|òEòEòE ;,;,; FFF X¬X¬X ¦íLÛ™¶Ê)§üõï©ø‡=r}äúÈæ„Í › �B£ÐÀ¼çóžÏ{>‚�à#Pq­I"ùdr™\&äÈ‘ƒÚMí¦vÁOðü*Þ§¤¤2s™¹Ìœ_OUÿzîñ9Ïy^ñ~!GÈr@œ+Îç¾´Á<࿞*e?ûÙOÅsÞ`Pñv]]]�9ÊeŽ Æ‰qb‡„CÂ!�M–M–M»Oí>µû¾îõu¯¯{�3Î8º*º*º*À)Nqê¥&˜`¯ÿaÿr×¾¼ª¼ª¼*tìÞ±{Çîpkõ­Õ·VCÈœ�9!sÀ¯¯__¿¾b€×߬²øËÏ+Q‰J/ï�Ÿô +@‹mÅ< xâ‰'pžóœÙMÙMÙMüÁo:Þt¼ _¯ýzí×kÁ±¾c}Çú ö{Š=�`‚ ~i{¿¬ù/cxÅðŠáPå¨rTÃ%Ká¾p_¸ç8Ç©8^¾Eœ%Îg�*„ ¡@ %”ðÛÇ5(P]èB——7ðóþ� ‚ˆŠÇñÚ´7ho±«bWÅ®‚ã-�·<Þ|úô=$“ÌyÌñ—ÆcLÅs¿G¿7ÿ©xÍ4�5�5�áø�ãCŽ�e¥ËJ—•B‡>útèSã¦ÆM�ëöÖí­Ûë;­äM%L¦ Ó@HR…ÔŠÇË¿/ÿ¾ü{ÈŸŸ??><-|Zø´=iô¤ÑÐ\Ò\Ò\uœ:Nå-Ë[–·¬h×w¿ï~ßý�šš iSÓ¦¦M…¨…Q £‚¼º¼º¼:xxx€vŽvŽv”RþIù'�ß)¿S~'xzüéñ§ÇÁ_|»Fv�ìAõ°êaÕÃÀ,Û,Û,72nd -:µèÔ¢SÅõlõlõl(S”)Ê^ºsI>K>K> ”�Ê@e dŒÏŸ1´Úmø÷?îÊÍÊÍÊÍ ³[f·ÌnP5 j@Õ€ÿ>®åVåVåV š š šeš2M™¦âuÕPÕPÕP(__¾¾|=ˆ¡b¨ ª«ª«ª«P¾µ|kùV~½¶\]] éõÒë¥×ƒJ³*ͪ4 \» v ���ÐhT£Q�F�ÿuÿëþ×Áà ƒ/ ¾ÕNÕNÕN(ËÄ2±"GYRYRYlÿxûÇÛ?†[é·Òoý ¦ô6ênÔݨ;”'”'”'¼z{urêäÔÉõ9õ9õ9Hü<ñóÄÏ!þTü©øSPغ°uakðñ÷ñ÷ñ‡²Œ²Œ² PY¨,T N'ˆ@=Z=Z=Ô=Ô=Ô=@×U×U×Tö*{•=”ï,ßY¾TóTóTóÀ'À'À'¬s­s­s!jEÔŠ¨P£¨FQ�¢?pe–g–g‚º¥º¥º%”=*{TöÊ–,?êTuª:”­”­”­þ¹ý#Ÿû³n“ˆ’ˆ’زj˪-«àêÌ«3¯Î„O">‰ø$Ú·nߺ}k�/–/–/ÖwZÉ›N£Óè4:¸xìⱋǠئئØÒz¥õJëª*ª*ª*`Ó̦™M3è¿·ÿÞþ{!>->-> ² ² ²  Æ®»jìª8E^-¨ZPµ ²„,! nO¿=ýötH,H,H,€=z@Ó¦ Lár�Ë=.÷€ÇÓO<T6*• ؅؅؅@¿õýÖ÷[Ö3¬gXÏ€j[ªm©¶n»Ýv»í±Ç~û1(((]éJWˆ½{-öXåXåXå€ÏG>ù|fß™}göä ¹B®Ï<ðlxL÷˜î1lfÛ̶™ Ùk³×f¯_C_C_CðÜê¹Õóÿ¸¹J³W³W³×â^ È/É/É/çSΧœO�ì¾ì¾ì>D­‹Zµ®âR�åTË©–S!) ) )Œ��¡^ïz½ëõ†òŽåË;³Üg¹Ïr¡¡sCç†ÎP›ÚÔn)o)o)!Î-Î-Πʋʋʋ@¼/ÞïClnlnl.Tº[én¥»P×½®{]w`! Y!!!!!!`ýÜú¹õspëîÖÝ­»þŽËÐèÐèÐhP„*B¡à;Ìw˜ï°¿ÞžÝ»v#Àò¶åmËÛp+þVü­xˆ™3#f´QµQµQA“†M6iÔÔÔ ,–KÀc�Ç �Aû0öaìCN §…ÓPíLµ3ÕÎ@üœø9ñs@|$>�W W W Tq¨âPÅJÊKÊKÊ¡ª®ª®ªšŽm:¶éØßϫ֪µj-<Úøhã£��õ ëAÖ°_l¿Ø~1,:Xt2r2r2rÀ6Æ6Æ6Ü» v C…¡Âð5î Qò·J–>,}˜(Îr�å:ËU§)¦)¦)D1iaÒ¤…úN'y[•þXúcé�¢8)uRê¤TQì?¯ÿ¼þóDñËõ_®ÿrýKo<'žω¢¨Õ¢Zÿç±;QŸ‰ÏÄg¢ø?ϧ‹¢¨µ¢ö¥Ï%ˆ b‚(ê”:¥N)Šbg±³Øù·9æ,›³lÎ2QœÝuv×Ù]_zá‚xA¼ðt`¤8R)ŠºKºKºK¢(¶[Š-EQü^ü^ü^Åóâyñ¼(Š[Å­âVQŸŠOŧ/}>ULSEQ·N·N·Nó{æ÷Ìï)Š9ßå|—ó�(îè¿£ÿŽþ¢˜µ,kYÖ²?0 ™b¦˜)Šâ8qœ8Nÿç’…(þÏãf/�Ó:q�¸NÅ`1X Eq€8@ Šâfq³¸ù¥Ü¿¼þKÎR]©®TÅ‹âEñâKÛ"‡ˆ¢î²î²î²(þÏ¢N/mç’xI¼$Šâ&q“¸é¥\ÿRë²Öe­ËÅõ ëÖ'ü� çˆ9bŽ(ж¢­h+Šbu±ºX]¬8®“Åd1YÅÅâbq±(бb¬ûÒ¸-—ˆKDQLÅDQüŸK\¢(Îç‹ó+6SàPàPà ŠE׋®]Å“Lþ1Y[$¶Hlñrf‹Ùb¶(Š£ÄQâ(QcÄ1FÿçR…øëþ£Ä(1JÅ)âqÊK¹^3á—¿¼Æã�+'®œ¸r"Ôú¾Ö÷µ¾‡± Æ.»,šY4³h¦ï”’·•ÆKã¥ñ‚W~¸òÕî¥î¥î¥°äÓ%Ÿ.ù¬+YW²®ô÷o¿´yióÒæðY¿Ïú}ÖÔÕÕaiêÒÔ¥©P¥s•ÎU:ÿa�=ö°|ÙòeË—AùöòíåÛÁÿÿü€65ÛÔlSóÈ!`ã��6U†*C•“&Mš4i’¾Sýq[?ÜúáÖ!ùjòÕä««¨v?×ý\÷s †Cô�ò¯“ €WtëÀ­·À¦I›&mšÊ:”u(ƒþ»úïê¿ zô4è©ï”’·�x\<.‡eÊ>”A»¹íæ¶› ~þ~þ~þàø“ãOŽ?�Q¶Q¶Qöß¿}õQõQõQHù,å³”Ï@w@w@wœ—:/u^ F{�öíýçÆ#y_ò¾ä} z¤z¤z®m\Û¸¶EGEGEÇWn^òmóÛæ·Í â â âarîäÜɹúNõÇe8e8e8AA³‚fÍÀÕßÕßÕŒ‚Œ‚ŒþÆ'õE*þ$]ª.U— Á;ƒwï„ýyûóöçÁ°ãÃŽ;�~ø“„IÂTéJÞp}éK_˜ü|òóÉÏ¡ß÷ý¾ï÷=4 hÐôÕ›—HþŠ]»"vE@zrzrz2|Þåó.Ÿwyõv%i&À?H3T3T3ö¥îKÝ— çýÎû�÷ƒI�'užÔ/n¼¸±t3ŸD_ZÒ’– ˆWÄ+âA]K]K]ëÕ›•H^…ÁrƒåËAc¢1јðÛÇî$z%=ø_¨òTyª<ض|ÛòmËáºÑu£ëF0k÷¬Ý³vCãö�Û7–ß“è[sšÓqŠ8Eh>Ó|¦ùLß¡$ï:Å"Å"Å"ÐÖÖÖwýS�Q�Q��Gmx´ntºÑéF'PG©£ÔQ½]1RŒ#!eRʤ”IpqèÅ¡‡Bæ€Ì™~ÿsRð;”˔˔Ë`ãÌ�37΄ðKá—Â/Á¬u³ÖÍZ©©©úN)‘üì—ÀZa­°õgêÏÔop ^¡^¡^« V¬æ×õÒ%oƒÍ› 6ƒúõê¿a-€7�<@ €è:Ñu¢ëÀ7Ý¿éþMw(Ñ•èJt¯ÐðÏ˾k{i{i{Áâ‹O,>÷Ýï»ßwÿý�IÀÿRêQêQêß¹|çò� Ä÷�ïßfÎ œÕ<ªyTóxõíH$¯ƒÂEá¢pÍ6Í6Í›¸vD!„ÀÅ�7^Ü»fïš½k6”~PúAéPÒ§¤OI(¯Q^£¼”®+]WºJ_”¾(}%MKš–4�ŸÎOçªÆªÆªÆPbRbRbºÑºÑºÑ›S/S/S/ƒ‚ü‚ü‚|P.T.T.³é’Þ+355…²Ø²Ø²X(®W\¯¸*:Tt´Ú m”U*«TV Jw”î(Ýb (‚rµrµr5”n-ÝZºðÁÍD3Ñ Š2Š2Š2 ð‹Â/ ¿ÍÍÍP+Ô µŠeŲb%%%@aRaRah§k§k§ÿ6¯*S•©Ê„‚'O ž@Y½²zeõ€Ílf3”Û”Û”Û@qJqJq ”l.Ù\² C C C@k¯µ×Úÿ¶Ýò�åË7B¹¶\[®…*¦UL«˜‚l‘l‘lP�jT«xYµ²jeÕ  ¬ ¬ T·T·T·~Û®®µ®µ®5�/_<,FYŒ²ÆcŒÇ�.r‘‹¿¿¤{~V*+••Ê`Ýüuó×͇ܒܒܘi2Ód¦ ØÚÛÚÛÚ¿úv$’×IñXñXñÔÕÕõ�æÏ+Ú\´¹h3ìY°gÁž�×9¯s^gp?æ~Ìýœ~þùùç`8Ìp˜á0pŠuŠuŠƒÓ§ Nõ1ׯ\³—Ì^2{ ”Ô+©WR–å-Ë[–sWÏ]=wuÅâ>[3·fnͱ¦XS¬ …í Û¶ƒÁ™ƒ3gBí/jQû }�ʛ˸̸̸ ®_¾ k¾\óåš/A8#œÎ@�„ = òRä¥ÈKpîÇs?žû–*—*—*!x{ðöàíp±ëÅ®»ÂÊ¢•E+‹à’Å%‹KpÏþžý={0³7³7³‡æC›m>Ìæ™Í3›_ŸøúÄ×' CË-;´„üÜüÜü\pÒ8iœ4ðþñ÷�¿rçäÎÉ�;vìØ±cȼeÞ2o(ú¢è‹¢/`„ÿÿþ~7ünø]Ø×g_Ÿ}} ß¤~“úM‚;�wïB��uÖ£ÊG•�*‡ÄQ‰£GÁnÃ݆» Áº—u/ë^�\š\š\ º…º…º… //Ñ÷¢ïE߃6lØ€Ée“Ë&—AW_W_WÆN;iì$0{nöÜì9ìž´{ÒîI�^7½nz]°¹osßæ>d—e—e—�ÐJh%ü3 ¾ógJG•Ž*ßýý×ß ùyùyùy0­Ù´fÓš�mÛ¶=ô�R"ùcäéòty:h¾Ð|¡y¿¸,¶[l·Ø® ® ® ÐàLƒ3 Î@—¡]†v fáfáfáP¶°laÙBè¥ÿ•þW mö Û6„œ;9wrî€ò¡ò¡ò!Ô «V+ rkçÖέ å¥å¥å¥pÆåŒËH8�p áLž3yÎä9`qÚâ´ÅiøIñ“â'é×£WfXÓ°¦aMÈMËMËMƒÞ ¼xè’Q%£J ZZµ´jiP½kõ®Õ»Â‹e/–½XŠDE¢"Üû¸÷qï)gSΦœ•N¥Sé`o�½=ööÛ5¶kl×À>˜ðÁ¨¥©¥©¥�ª%UKª–@qIqIq ´ÛÔnS»Mð~»÷۽ߎE‹8±§bOÅž‚Ÿžøôħ�Ñ8£qFc˜ÒkJ¯)½@öPöPöm=´õÐVpã8Æq øøøB§ÜN¹�r¡ãÔŽS;N…ã#Ž�8> ³ ³ ³`‹Ù³-f`°Ú`µÁj˜ØgbŸ‰} k·®ÝºvÙ²d?Tœºß:j먭£ÀîžÝ=»{ðé„O'|:¢ò¢ò¢òàú{×ß»þ„Î �:N+N+N+àƒ ø`Œ 42¨bÙkq˜8Lü?f^|g €²€²€²øa÷»Ø =3zfô„©6Sm¦Ú@•ÚUjW©­ï”ÉŸc`e`e`ê/Ô_¨ßÀà a†0„}Â>aßK?o+´ÚB%ËJ–•,Áé¬ÓY§³`Öþ¬ýY –XbAø^ø^ø˜Ît¦ƒ&„ a ‹•ÅÊb!Î3Î3ÎRV¦¬LY GÝŽºuƒ”å)ËS–CqŸâ>Å}ô= o>í†[ ·‚B©P*”°êÇU?®ú6uÝÔuSW(P: t΂³à B±P,#ÁV+„‹òÈmå¶r[è4¬Ó°NÃàX±„c °Èe‘Ë"È”3(gAB�B¡ŠP+ÁJ°F #…‘�}9ûröeˆk×8®1¤K9–r Ž <�2:et‚bm±¶X L`@¨*Tª‚ì‘ì‘ì˜6l>T'U'U'AÝ_Ý_ÝbÖĬ‰Y^ݽº{½<%ó/‹Zbˆ!hkhkhkÀÓNO;=íñÆñÆñÆpl䱑ÇFBÉä’É%“+–Ž·ˆ·ˆ·€Jç*�«tl"l"l"€‰Ld"Ð�ntT¨Pýþþyç U *P›7%nJ„”ð”ð”pøÜþsûÏíÁzºõtë鯼‰D/äåòry9hvivivé;Í+0Çs~ûØØ/Ëì¦�BÊK?ÿeµ_Veûåõ_V[k@T¼ndidid ‰‰‰Ð¸Zãj�«Á'Û>ÙöÉ6˜<#xFðÌ*ù}7¹ÉMð_å¿Ê,ÈZ�µ ‡‡?ìýaï{A˜)ÌfOx ˆ"ЍØè@‡ŠÕ{ïソ÷~øáô§8 º‘º‘º‘ðíøoÇ;Ôaê0uÝ„nB7z ½„^ ½«½«½ ÚõÚõÚõ`tÏèžÑ=0r7r7rÇcŽÇ�Aã��76ÞAãƒÆ�‡)_MùjÊW ‹×Åëâ�Á f0àˆ#ŽüºŒ°°_Ø/ì¯è·b�b�b ¨}Õ¾jß—ÆE‡ЛÞô®è¿é2Óe¦Ë FíµkÔ†¦«›®nº—,.Y\=?êùQÏ�@øHøHø4-4-4-€žô¤'«NÖj µ�6´¡Íïïžw¦ÐžÒžÒž‚]ówÍß5bZÆ´Œi Ÿ›}nö¹ØÙÛÙÛI×ø%o8sssP�T�T�Ôwš¿Î¼�y;óv�p%áJÂxfýÌú™5–––@þÒü¥ùKA}V}V}  4¦Q¦Q¦QÝ#ºGtH“§ÉÓäPæQæQæQqÓX³ðfáÍ¡|iùÒò¥�ý(ûQö#P|¯ø^ñ=˜Í0›a6Cߣðæ“Ëä2¹ ÊN–�,; f7Ìn˜ÝÏ®ž]=»‚±¹±¹±9˜u7ënÖ´-´-´-àé¹§çžžƒì�Ù³BÙó²çeÏ¡xgñÎâ�°ÞþyûçA¹u¹u¹5x}çõ�×w`QÉ¢’E%` jGµ£Ú’…d!Y€«^W½®z�Óh§ÑN£Á}‹û÷-ÐlH³!͆@‘Q‘Q‘äzçþ?öî3.Šsÿûøg KïÒTŠX°#Fƒ{ï=ökb/±%±ÄKìF�=±E,X£ÆŠ‚Tªˆ´¥Ãî^÷ƒCîsþ9'‰e�™÷“äå3ß¹fa;s•ê™ÕÁ Ð Ð LË™–3-ê½ê½ê½PðEÁ_@n@n@n¨W©W©WAþ©üSù§ ärÉå’ËÐ( Q@£€²ccïÅÞ‹½iîiîiîPx¾ð|áy(ñ+ñ+ñƒ——HP$(Px´ðháQ0Œ3Œ3ŒÕ^Õ^Õ^¨y¼æñšÇ¡È¿È¿È.n»¸íâ6H8–p,áäßÌ¿™ríríríþËõyïWôÇ82ôÈÐ#CáböÅì‹Ù03jfÔÌ(pä2Èe�¾CJ$¯Ç­�·vÞÚ Zc­±Öü>ôûÐïÃWßïÛæXѱ¢cŲ?�ùwòïäßë¬?°þ?rüÈñ#¨t¥Ò•JWÀ2Ð2Ð2\æ¹Ìs™Ï;>ïø¼#ÈkÊkÊk‚“¥“¥“%x¬òXå± êµ¬×²^K°¶²¶²¶‚˜ó1çcÎCŽOŽOŽXl¶Øl±,{[ö¶ì­ïÖøûʸ”q)ã:t̆˜ 1å]Ë»–w…n³ºÍê6 œ69mrÚVQVQVQ�®MצkÁèK£/�¾×X×X×XðZäµÈkˆZ¢–¨1³cfÇÌÕ÷ªïUßC_u_u_5÷5îkÜv?Øý`÷p¸ãpÇᤤ¤B‡= ü�òwÊßwCwCwC0ÿÖü[óoá‘í#ÛG¶�{"÷Dî 0�4�4�„<§<§<'°Þe½ËzT¬[±nźPèYèYè 666à½Î{�÷:ø`ÉK>XŇŠ‚¤ÝI»“vƒj j j ¸7roäÞ< = = ¡Aå•T.{Dý$ïIÞ“<( * * ‚r.å\ʹ€{5÷jîÕÀµ·ko×Þe«.\8\ \ \ ÊúV¸-u[ê¶d­e­e­s�ÞüzCúuúÀé§1¨dPÉ !î=½÷ôÞS}§’HÞŒÍY›³6g ±ºduÉê}§‘üÓÝ1»cvÇLˆ1ÆcŒÇ ‘¿+Wþ®7ÜT×T×TW!šWm^µyU!¢vFíŒÚ©ïÖx÷¼·�Â… {£öFí�‚ÑõG×]ªºUu«ê¦ïtÉ›aàmàmà š)š)š÷`±Éß›ÜQî(w„-{ B#4Bóæ�w#îFÜ 0ªnTݨ:Ä,‹Y³ xÈCê»UÞï]�°3agÂNøfú7Ó¿™= ÉûB»K»K» bRcRcR¡ÀºÀºÀ^tyÑåEx1鍓à¶ÏmŸÛ>`]ǺŽu°TX*,à¡ñÐxh@v[v[&�Özkd/'Ðw�ÿåâõ‹×/^‡]�wuÞÕ6\ØpaCp9ìrØå°¾ÓI$oWÜ�¸!qC ÷ÀÞ{„yŠ Éû¢xañÂâ…0ÅŠÿøÞú{ëï­ùµÓŸZ£Ö¨5`ñÂâ…Å �)ÿRþ% 04>ßôù¦Ï7éû,þyÞù;é½Ó{§÷†Ý‹v/Ú½zMî5¹×dp™î2Ýåo¼Ú™Dò*»8vqì^ /…—›†7 oúŸÛ½\SÅþKû/í¿„ê?Wÿ¹úÏúN/yß~fø™ágP3©fRÍ$øÆüóoÌAg¥³ÒY•mWH!…€é Ó¦7À¹ÿr©O€Þ¼³�uÏtÏtÏ`Oñžâ=ÅPÞ·¼oy_h6¡Ù„fô�N"Ñ/ÓΦ�M;CËî-»·ìF³�fÍþýí[_o}½õu°km×Ú®õ?ŽDòg4Êi”Ó(<£<£<£~»*Ϫ<«ò üúûõ÷ëÿÇ÷/y½ÞÙàú¡ë‡®‚ˆM›"6Áàùƒçž*c•±ÊXßé$’wC¯&^M¼ ü�ò7ÊßøÏ×-²-²-²¡…e Ë– ?(?(—žýKÞ/ / / ð{â÷ÄïÉïo×rRËI-'�ý9ûsöçô�úŸë�+òÖç­Ï[{•{•{•Ðåj—«]®‚ÛL·™nÒòœÉÿÇm±Ûb·Å���ÿŸ¯×ø©ÆO5~‚ÚvµíjÛýùýK$†²¼²¼²Ï}POQOQO¡ïpÉ[vƒÜ€Ò€Ò€Ò(xPð àw)îRÜJJJ ¤SI§’N Ù£Ù£Ù¥.¥.¥.àìì ÚkÚkÚkPâZâZâ "D>ˆö°‡= ðWø+üÁ šA5ƒj Z­Z­Z ªUŽ*Œºu5ê Æ:c�±”^J/¥P›ÚÔÖw#IÞ6ííí(U8ªp-.Z\´J®”\)¹%ÝKº—t‡RãRãRc-EKÑÜ"Ü"Ü"Àº¶umëÚ`?Ý~ºýtxhôÐè¡èt º„²5[”½”½”½@µFµFµTÇTÇTÇÀpšá4Ãi`l`l`l†+ W®.q‰Kún�¿/½qÇ}÷1ÜŒ»w3æ.œ»pîBP4R4R4Òw:‰äՈꢺ¨źb]±rúäôÉé‰!‰!‰!�Ü6¹mr[H K K ƒôaéÃÒ‡Af~f~f>‚˜'æ‰y€:ÀSL�êT§:ÈêÈêÈê€Á×_| ö‹ìÙ/‚}>û|öù€¸%n‰[@8á„S¶hP6Ùd5©IMà)Oy ²Ú²Ú²Ú`~Þü¼ùy°imÓÚ¦5Ø÷µïkßœœœÀ5Ü5Ü5\“\“\“ÀôŽéÓ;```ð›ýKÞ ýèG?(X2°d \/¸^p½l‰Äá‰Ã‡CêÊÔ•©+!mvÚì´Ù�Ù*³Uf+P‡©ÃÔa 3Ôê �>ô¡O<ñüú~Ä_|¡0¡0¡0ªR•ªÀµ”k)×R ¬NX�°:ÀArÈ#�<às>çs 2•© d ;ì°###°q·q·q‡r�Ëu.×{9örì.w]îºÜ7™›ÌMVC¬†X £UF«ŒV�|£|£|£¾/»Cïm¾aø†á vW»«ÝaZä´Èi‘¿™ÒT"y—QDäeæeæeÂcícíc-<ªþ¨ú£ê���icÒÆ¤��ü‡ùó‚aeÃʆ•Áv¡íBÛ…àpÔá¨ÃQ°k`×À®888€Í|›ù6óÁ¨“Q'£N º§º§ºª`U°*”S•S•SA9W9W9 'N(œEW‹®]…r Ë5,×´‘ÚHm$ˆ‹â¢¸ÚXm¬6JÓJÓJÓ ä“’OJ>�’j%ÕJªAáˆÂ…# ½$½$½žõ}Ö÷Y_xîñÜã¹6}lúXHï‘Þ#½˜˜˜�I?“~&ýÀ®Ð®Ð®¼R¼R¼RÀ;Ù;Ù;<x4ðh–�-[>pÀAßWïíÑ[ð"óEæ‹L˜^<½xz1L œ81jÜ«q¯Æ=}7ËûKý¹úsõç�‘Ÿ‘Ÿ‘Î �:/CCC}§{w 7á&Ü }Wú®ô]ðð»‡ß=ü®_¼~ñúExüôñÓÇOA6C6C6œ›87qn•ÛTnS¹MÙ7—/\¾pùì?·ÿÜþs0P¨ þŽË£žãç ¨oQߢ¾�šœšœš Éw’ï$ß�'yOòžäAÌ¥˜K1—àùÞç{ŸïU7U7U7¨Ü½r÷ÊÝÁÿ¾ÿ}ÿûàêê V¶V¶V¶ü:µ±äwL0ä^ͽš{+++àÆÝwoÜ…ûù÷óïçC~J~J~ ذ`;¼¶xmñÚ•2+eVÊ—ñ.ã]ƃÓ§#NGÀÔÏÔÏÔØÌf6ëû$ÿ<ÍÍÍxQú¢ôE)¤ÌN™�2–$,IXÑÍ¢›E7ƒ¤EI‹’A©g©g©'”/-_Z¾üÎû�÷;Õ'WŸ\}28Lq˜â0——ï᣽§Ö�Zwjœ+ôûÐï!lYز°e i i i•å•å•åP÷“ºŸÔýª6¨Ú j°ò³ò³òå.å.å.þ±}9DUQUT…Â>…} û@b½Äz‰õàÖŠ[+n­€ÛgnŸ¹}2b3b3b¡ÂÔ S+L…f÷šÝkvjo«½­ö60mjÚÔ´©¾ÏæÕ½õ@[W[W[Ì[0oÁ<¨9¿æüšó¡û­î·ºßÒwsè�æKÍ—š/!ùVò­ä[àrßå¾Ë}PÞWÞWÞõý_S]S]SÁ†ÝvoØ _|üÅÇ_| Ê8eœ2ö}¼ïã}C‡vtØ®³\g¹Î‚áAÆA“NM:5é#ŒF�0‚„ 7n€K'—N.�@9J9J9Jß­ø×å-Ê[”·®˜_1¿b§'Ÿž|z2,/X^°êÞ©{§îh¼¸ñâÆ‹Á}¥ûJ÷•`¼Âx…ñ }§ÿú”Oùr›ä6Ém�î=º÷è\8uáÔ…Sp¯å½–÷Z‚Ë— . ýÚökÛ¯…:ñuâëăjªjªjª¾OâÍÑk�µÆ5?j~Ô|8¹íä¶“Ûà‘É#“G&PiM¥5•Ö@ó-Í·4ßUݪºUu«@«@«@ Íh¦ï³øû)µ.µ.µ†Ä–‰-[ÂÃ+†W áZ»kí®µÙ Ù Ù h±¾Åúë¡IA“‚&`3Ñf¢ÍD}§ÿóÞzðòâ¬#³ŽÌ:3ëά;³.x”z”z”–mWª(U”* quâêÄÕ@A�®µ®µ®5˜/4_h¾ì­í­í­!­BZ…´ Pú´ôiéSP ¦FL�˜`ö™ÙgfŸ�ë×®;þs»¢ÇE�‹ÃÜÊs+Ï­ v[í¶Úm…Z½jõªÕ Â,Ã,Ã,aܘqcÆ��ë®o¸¾öºîuÝë �®tºÒé Ø}c÷�Ý7PkZ­iµ¦ÁwAß}ž <x.€äÉÉ““'C¹Är‰å¡{•îUºW�Ù[go�½œ|�|�|¡5¨„-[¶Æ?düpŸà>Á}lHÜ�¸!ðÃ?Èû  |dùÈò‘ðaƒ|Ø>Ö|¬ùXÍ�›77CCCȨšQ5£*„U«Vb®Å\‹¹1ŸÇ|ó9GGGÖá[†oÚvÚvÚv°áîÂH›‘6#mÀ|~ÓŽ…õ ëÖ‡ä>É}’û@f�Ì:™uàA¯½ôåYåYåY˜á:Ãu†+´Ý~tûÑ0hï ½ƒöòkï[±El[ übøÅð‹6'lN؈]»,vØ.³]f» ¾úíÐo‡‚¢®¢®¢.äÈrd92ðâ1ÄcÔ/W¿\ýr0.l\ظ0\¸&p ˜>2}dúš?lþ°ùCXÑaE‡ ßž~{úí�Àn�Ý_C�òaʇ)¶çÛžo{��;=v‚®©]S»¦B‹�-6¶Ø&…&…&…oû·Còò΀#Ž8ý3úgôÏ€¶uÚÖi[~ þ1øÇ`Xî¾Ü}¹;|àþ�ûî0`Ø€a†�ù6ómæ£Î…Ï ž<‡c×�]?vNN<9ñäDðwöwöw†ÅsÏY<[:¶tl DEÔ+Vò'™œ79oršÓœæ@#ÑH4píɵ'מÀþVû[ío+_¬|±2Œ0a8Â<z>ô|T¤"õ}ÿñ–mˆÙ³!FˆµK×.]»ôo?váØ…c ±&xMðšà²Ÿ1vÆØc…Xyyåå•—…ݺ?t¿mú´éÓ¦�©#RG¤ŽB-SËÔ2!o\¼qñF!Ä,ˆYS¶Ÿøñ#âGÑÁ¡ƒC!b^ļˆy!ÄÇ]>îòq!Ö»¯w_ï^¶ý´±ÓÆN+ĪäUÉ«’…ˆ"BÑéD§�N‘––&ĵA×]T¶ßäëÉד¯ Ñnv»Ùíf 4?h~Ð|! ­ ­ ­…8Þéx§ã�„èúi×O»~*DáG…~$Dœkœkœ«í·_Ü~±wÞxw w†Þzg¨{òöäíÉB¥�ÒFý~;ž :t*Hˆn�»5îÖXˆüýùûó÷—½>|èð¡Ã‡ ±iƦ›füæßM†› 7â[×o]¿u"xIð’à%Bt¯Ù½f÷šB«‹ÕÅj!n˜ß0¿a.D—¡]†v*Dfvfvf¶—Ž_:~é¸�útêÓ©�)þ)þ)þB´>ÕúTëSBœÖ�Ö�Ö ¡nªnªn*Dþøüñùã…ˆv�v�v"»]v»ìv¯ð†.†‹áBÜȾ‘}#[ˆa®Ã\‡¹ ±Â|…ù s!ÒRÓRÓR…i"M¤½�ßÉ+¹+BÄ®Ž]»Zˆ™>3}fú1É}’û$w!þõ Zß!ÿ·´/Ó¾LûRˆ9½çôžÓ[ˆñÕÇW_]ˆ;ï ¼3PíIíIíI}§”üQYNYNYNBlŽÚµ9Jˆ�ü?òÿÈ_ˆ3çÏœ?s^ˆ ãÕwÊÿôöîÌe.s!Á.Á.ÁŒŒþÈ¢>/LJîg?û�V´¢X?²~dýžñü‹ç_ÛÙÎvPíRíRí³ŸÍ~6ûÌtf:3$·Jn•Ü ¼M½M½M/¼ðKKKÐ*µJ­²µÙÚl-È�!Ä~±_ì/‹cµÌj™Õ2Hßœ¾9}3äDäDäD@RpRpR0¼uðÖÁ[�?"Dþ(7§Üœrs@¶L¶L¶ ä#ä#ä#Àä²Ée“Ë`”i”i”Y6ŒFDŠH º]º]º]PÉ©’S%'¨º¡ê†ª èVЭ [P¹_å~•ûAåÈÊ‘•#AÞ@Þ@þßfÖúå„Ä`1X æ×ñÞ¿2à 3À<þ@á8FŒc@î"w‘»@VaVaV!$VH¬�XŒ<0òÀHÈÙ•³+gØõ²ëe× XÇ:Ö�âKÅ—Š/Átœé8Óq`kk[¶ï5Þk¼_Ãá¡GC�†…íý¶÷ÛÞúŒì3²ÏHh�Õ:«u(Ž Ç×ðþ–¼¿Œ/÷ðõðõð…¹6smæÚÀž�{îK —.5„‰ê‰ê‰j¨fXͰš¡¾C—Iü"ñ‹Ä/`Y«e­–µ‚Š™3+f”îSºOé–=-{Zö|õãHÞ.«««¾aø†á šc5Çjް¥Ê–*[ª@·9æ|ÝÖt[Óm È'È'Èß�UmßÚTÀÙå³Ëg—‡Ï_<ñ<¯x^ñ¼ò~ð—_øŸ@=J=J= ¬7Xo°Þœà'øufÁ—·®_²žh=Ñz"äW˯–_­ìߋ֭+Z4¢�Àt¥éJÓ• >Ÿ‰Ï@¶_¶_ö› wCî†Ü `-¬…µ#w#w#wpœï8ßq>tÚÙig§�0~ÖøYãgÁÆ{lìVu¬êXÕ†2”¡@ ZÐâ7çùòÚGøkıH!…hÛ¬m³¶Í 4"4"4„?Õ2«eVËüí(�ý(ûQö#¿>ëþÕ/½‚eßȾ‘}ó›¯E-j+YÉJ~í%/¼…·ðQCÔ5ÊfŒsjáÔ©tëÖ9 &ÚM´›hëG¯½~4X·8nqÄV±UlšÒ”¦¿‰9KÌ³Ê ±ÒV¥­J[ýù÷[øóðçáÏá»3ß�ùî ŒV�V�VA»Þíz·ë ЕЕЕÿ¥¹¢E´ˆ†ÂÝ…» wCQ—¢.E]€�lä5L$¢ûD÷‰î(Š)Š)Š1JŒ£ ¤aIÃ’†�;ÿvþmеӵӵû/û®®EQEQEQ žŠ§âéÏñ‡5  |Iø’ð%°·poáÞBÈ<‘y"ó'''�î´î´î4”ƕƕÆAþ‚üù @³_³_³ÿÕcü»—S…Ý?tÿÐýЪY«f­šÁºªëª®« ‰×¯'^íñ'e=Ëz–õ Vy­òZå¾½}{ûö†q�ûhÜGüƒ_WWWWWò‹ó‹ó‹¡$³$³ä�üþÿA/G”Ô-©[RÄD1QL„Bu¡ºP …� 6 0à¿ ÖTÑTÑT�’ê%ÕKªW¸Âù{ÿ'‡‡‡ÂÙîg»ŸíÇçŸ|>”¨KÔ%j(ö*ö*ö±T,K¡xJñ”â)PàVàV຺º¯/ÏË>d �6<Úð(L}0õÁÔpúðéçÃù3çÏœ‡F³¼½ ;;;;›_;ÍY…X…Xý�Î+b’˜$&A\j\j\*¯ ^¼2Úe´Ëh-í[Ú·´/›É*ëRÖ¥¬K�V”V”VT¶Ÿö�Û7nßÒ|Ò|Ò|àLè™Ð3¡p$ôHè‘P¨ß²~Ëú-¡Ri¥ÒJ¥ Qj”%Ä}÷QÜGp:ïtÞé<Èj›Õ6«-´ÜÛro˽àìì Þ—½/{_† þAýƒúí鷦ߚ©mRÛ¤¶�ô¾é}ÓûBv³ìfÙÍ é|Òù¤óeù¬|­|­|!»OvŸì>p6õlêÙT(t.t.t†ºßÕý®îw`‘d‘d‘nSܦ¸M£vFíŒþË„h&š‰f�41ibÒDx±èÅ¢‹ ñEâ‹Ä�^-½Zz5ȘŸ1?c>$?J~”ü’û&÷Mî[ÖY2Ù/Ù/ÙT-U-U-!«vVí¬ÚpzËé-§·€›‘›‘›x¬ñX㱂<ƒ<ƒ<á–ú–ú–ž9|øÀ¼‰ó&Λé¡é¡é¡pûèí£·�Âð¥Ã—_ ÷.Ý»tᅩ?¾ßá~‡û`Þ¤y“æM‚ÌÄÌÄÌÄWÏ÷ï¢ûD÷‰î{›ím¶·ì3Øg°’Ö$­IZŸy}æõ™ÄZÆZÆZÂÓVO[=mçœÿq>œÝqvÇÙ¯?×Kò>ò>ò>Ð-²[d·Hðëî×ݯ;ì²Ýe»ËŠ ‹ ‹õѧ㗂ÿÀŠ+¬—±.c]ÆÂ`»Ávƒí@å«òUùþñÝe�Î�=æLœ3qÎDØ‘»#wÇk\,-H¤RÃÚfk›­mùC󇿅#�Ž4:ÒÆM7mÜ4Ⱦ’}%û¿| />^|¼ÖnY»eíÐÔÔÔÔÔ|ýÍ{vÛÙmg·Áe×Ë®—]A¾L¾L¾ n6¿ÙüfsX¸eá–…[ kZÖ´¬iðóÏ?ÿüóÏ0lÀ°Ã”ÍŸð¦Tm^µyÕæ0ÆxŒñc8zñèÅ£á©ùSó§æoî¸Ô[{ ž§ž§žªïUß«¾Ã†= {ü�´Æk %-i &æ&æ&æ0Ñ|¢ùDsðêëÕ׫/(�)�)�Á¬àYÁ³‚Á(Ò(Ò(²l7õ[×o]¿5X·µnkÝ’‡'OµzÔêQ«T›Wm^µy`4Üh¸Ñp¹"Wäòko$SSS˜”1)cRxòä=dŸÈ>‘}3ªÏ¨>£:ܯ¿þýú ë¯ë¯ë¢›è&º�j»j»j;ÌVÍVÍV�ãeÇËŽ—AWCWCWj©q¤ÆX([([(mKmKmK ˜bŠÁ°ža=Ãz¨Tª¡á' ?iøÉÿn>Í*Í*Í*¨=²öÈÚ#Á¹šs5çj`xÜð¸áqÐÕÔÕÔÕ„±qcãÆÆ�qœqœqhNhNhNÀØÇc�} ¦L˜oGoGoGXðdÁ“O@ç§óÓù�ƒÒAé „�g4žÑî—»_î~9ÐÝÑÝÑÝñ¡øP|†¹†¹†¹0g朙sf‚s˜s˜s/á%¼ÀBg¡³ÐÁÐ>Cû í†W^a8P� Tøßçûcê�©?¦‚{#÷Fî� Ð7Ð7ðOü�}É Û Û œ®;]wº!“B&…LÝ÷ºïuß¿úïƒë<×y®ó wýÞõ{׫VV­¬ZA•§UžVy ™¶™¶™¶P0¤`HÁHl—Ø.±DýAô87pnà\pµuµuµ…Þ^½½z{�ùróåæË�ù�_=çK1þ1þ1þ�±*cUÆ*è0§Ãœs€³œå,ô:Üëp¯Ãàt×é®Ó]0¯f^ͼ”š•š•šAæžÌ=™{^_žß#O–'Ë“¡×Ù^g{�…Eb‘X$àêý«÷¯Þ‡¦u›ÖmZ÷Íçx)jpÔà¨Áð0ñaâÃD˜uiÖ¥Y—@UEUEUåÏïÏf„Í›`¨4T*áùØçcŸ�¥ìè+ªëPס®x{z{z{‚YM³šf5Á³ŽgÏ:°óã�ïü´K´K´Kàæ…›n^ƒŸ ~2ø j�¨u¢Ö ¨R7¤nT6«lVÙ �ö´§ýëkßÇn»q Ì/™_2¿í[µoÕ¾¼Hz‘ô" L˜40i–“-'[N†*±Ub«ÄBÚ–´-i[ (º(º(š_ïp½)u;×í\·3ÜKº—t/ 7:Üèp#˜”2)eR ÈœeÎ2ç7wüßóÖ €‚ùó æƒ²²²²²2<6xlðø¿üÀ.v± 455Ás”ç(ÏQp-àZÀµÿÜÜ÷¨ïQߣ¿>1ø²Ÿe?Ë~.ûøëÁ¿5õË£í<í<í<(?»üìò³!`VÀ¬€Y¿×!Ê!Ê!ê¿Ì$ùË~ÛІ6ÿÇËF-ŒZµ€Æ4¦1 ‰×Äkâ!bhÄЈ¡PúséÏ¥?ƒUºUºU:ThZ¡i…¦”Í™ý; jÔ2¨uoÔ½Q÷Æo^˜ÉLfþ&ÿ¿çîD':�;î¸Ld"¿çú2ç¯6°� e½·_þ÷÷ÚÁ 'œšÐ„&À#ñT¨PþøãÏ—U>«|Vy¸t#èFŒí7¶ßØ~ ·—ÛËíÿÄŽþ�¼³¼³¼3¤ÏJŸ•> NL91åÄÈËËËË˃:ª:ª:*0ò5ò5ò…ó¾ç}ÏûB»vì ÿ«ü¯ò¿‚ ¾|/øBÇÕWw\ Õ ªT‡[Q·¢nE�㇎:~ �…d+d+d+ ¿~ÿüþ°áð†ÃClilil)X(, 0;kvÖì,Üš{kî­¹`•a•a•áׯ…_ƒÒ’Ò’Ò0¿e~ËüVÙ0ÔŽöí;Úƒ½»½»½ûïŸ^H^H^„{†{†{£ó�Î?:÷]Üwqxß÷¾ï}î<¾óøÎc0Þn¼Ýx;T «V5 dÍdÍdÍ@ÖFÖFÖ°Å[ˆô�ô�ô‡ˆ*U"ª€ò åÊ/ Y�f=šõÇ«ŽW¯þõëfÖÒ¬¥YKh\¡q…Æ ¤RH¥�JÐøÓÆŸ6þäíåíå¯ñƒè÷„L ™2j^ªy©æ%°7´7´}~m·õ}ê ÝÜ»¹ws‡'¾O|ŸøÂÓÊO+?­ ^Î^Î^Î ûJö•ì+�Ÿ”Ÿ”Ÿ„¤¥IK“–ÂÒ K',�Ï<žy<“Ù&³MfóÙÏf?› I½’z%õ³D³D³D^¼>x=8w8îp &L.˜ ÊéÊéÊéÐñnÇ»ï‚a[ö†mÿô“Û'·OnQùQùQù`ÜÁ¸ƒq/^>¼<(ý”~J?¸p+àV¸}êö©Û§ ›#›#›²ë²ë²ë ‹“ÅÉâ@‹` ¯]¼vñ<ÝñtÇÓ`Óɦ“M'h1¾ÅøãÁd€É“ý²fffÀÂ¥ —.\ É^É^É^àšïšïšÿæß�ÿî­=(6,6,6åååPÎTÎTÎüýíÓ;¦wLïå¾+÷]¹ïʾçç翹œé é é `÷�Ýwvß�ÆCã¡ñõõõŽ·ÕZ Ü…»p‡ÐâÐâÐb6(l4qjâÔÄ •••_ý8ï‹Ô ©R+€ÖJk¥µ‚òËo,ÿžÕ¿ì«`æeæeæ5ª×¨^£:؅څڅ²šËj.« é Ó¦7„ïµßk¿×BB�„: uÀr†å ËpðöÁÛoC°„a ÃÀüˆùó#°×j¯Õ^«²©Jåqò8y°–µ¬ã>Æ}ŒûS™ÊT°mgÛζT\UqUÅUeì{ëí­··¤N?œ~îL½3õÎT¸ñã�oü¾Ç|�ùƒ«?_ýùêÏpèÆ¡‡nüïó7íiÚÓ´'8Ç;Ç;ǃM›þ6ý¡rÏÊ=+÷„rË=,÷N(O(O(á¶ÿmÿÛÿGå&·‘ÛÈm álÂÙ„³ðuÎ×9_ç@ÅÛoW¼ Y¡Y¡Y¡°®ûºî뺃¶²¶²ö5¼¿k/¯½¼örH©–R-¥<Ïžÿü-ü¡-¨\P¹ 2Äu�ë×|?õýÔ÷Ó×·YMYMYM(·­Ü¶rÛ ®¬®¬® ²²²`uÉê’Õ%�Ý<»yvsØ�º;uw*”4/i^Ò´»´»´»à» ßUø®”¶)mSÚJ®–\-¹ ;»ïì¾³;äÏÈŸ‘?d!²Yˆqbœ#-FZŒ„¢ÁEƒ‹CE³ŠfÍÀu�ë×5Pt¿è~Ñ}Ø‘º#uG*�L2Ép|Éñ%Ç—@æÎÌ�™;ÁÇßÇßÇvíܵs×NoÞ:¼õÿ>›i6Ól¦�­ÖVk«-›�¬ÂŽ ;*ì#c#c#cعcçŽ�; íQÚ£´G ß*ß*ßZ¶Ÿ—wŒB:†t éß÷ý¾ï÷}¡ö‚Ú j/€Ð¸Ð¸Ð88bÄþÈ+|‘xÉq‰ãÇ%`»Èv‘í"¸wøÞá{‡_ë[ïOyk€ÖNk§µ¥�Ò@ ò¶ò¶òÿRáÙ±;bw¾¬úeÕ/«ÂTÏ©žS=Áò¼åyËóü¸–ÝgvŸÙ}‹k-®µ¸LI˜’0%,--Þboq…�Â@SÚOi?¥=Œ?~üøñàxÉñ’ã{8'õ«Jߘ¾1}#˜Æ›Æ›Æƒ‰»‰»‰û«ï÷å-î—•¿n¸�ƒ<ñÄbbbÀHf$3’�L.“Ëä`Ù˲—e/PuVuVuY®,W– j µ…Tþ*•?pŠSœ2É$8ÎqŽƒÊIå¤róJæ•Ì+��ÒFi£» vì&€¥°– nÜ2¸2™�¬l)ÓOM?5ý*\¨p¡ÂpKqKqK�äÛÉ·“o—Í…~/ã^ƽ ¸«»«»«ƒGµÕzT d² YØö²íeÛ ÌW˜¯0_._»|íò5X\²¸dq Œ…±0 {${${ôŸÍ¨U„*Báþ¤û“îO‚gâ™x&À±Ø±Ø±lkÙÖ²­·ÜZpk¹¹½†ëgZ×´®i]P,Q,Q,�»»»WßïÿRr¨äPÉ!(j]Ôº¨5XtµèjÑõ5à—éVÝ­º[u÷ZîµÜkAÏžµú×ê_«?¨U�ª@xñÙ‹Ï^|¹›r7ån‚HûHûH{¸»íî¶»Û i{Òö¤í`Üĸ‰q°¬gYϲ”Ë.—].l½m½m½Á²ƒeË`�g�g�÷›ÎÜ9ä�SÖŒ²Á²Á²ÁpiÄ¥—F€Aƒ ÀvŸí>Û}`tÍèšÑ5¸Yp³àfÁ«_6y y y °x`ñÀâd6ÏlžÙüÍ¿Ï[{ðò߯½¨ÿW¯Ð—½åß¶Œ`ī捻°¤°¤4­5­5­Á$Á$Á$xžü‰½þ(ù¯LMMËzý–î-Ý[º”(_íMþËè qFœg€ñŒg<(3•™ÊL�-ÿZþ5h:h:h:€,\. Ù:Ù:Ù:~5ñÊäÈ‘å(G¹?°ý/}G¸Ë]îRöÌÅC AV_V_Vr,s,s,áPíCµÕ†Â�… ‚ãxÇñŽãaBð„à Á” ýåέiÍø¦ö’l¼l¼l<”4(iPÒr:ætÌé7�ß<~ó8hzizizAÿaý‡õªªª¯ÞlZs­¹Ö´½µ½µ½ÁÐÕÐÕЕ7>U®¢�¢�¢(‚AŠ (ù¸äã’�ùÏÑ?U.¹äþæ}ù ÕmÕmÕm·Åmq´3µ3µ3�v´£e ]ã×þâ±ËcŒ)ë«õ{^Ž«~Á ^±Äò›a¿Øc�}Ù#»Çv�íÛÁ¾ƒûî;b›Ø&¶�Ÿ±Ÿ±Ÿ1¸uê:H#�´²Oÿ,YYY(ü¡ð‡ÂàyÁó‚çpõÜÕsWÏAÅ›oV¼ îGÜ�¸ºÐ….½¹D±(ÅPÜ¡¸Cq0 1 1 áOÿ>½.o¯x.{.{¥~¥~¥~ »§»§» ¼ÁN˜o]Öò¬åYËañþâýÅð¯ n`ŒÇ�1`�ÿåçsãsãsã!r^ä¼Èy`ÑÍ¢›E7¨Þµz×ê¯óÄ{ÆQã¨qÔ@IQIQId,ËX–± \wºîtÝù ;þåƒ÷×?´¿tNx\ø¸ðq!×)®S\ª-¬¶°ÚB8¼åð–Ã[ È£È£È„¹0æ œ…³p¡j¡æ×W´-EK‡ÅaqÄ'âñ ˆKâ’¸â”8%N�ì¼ì¼ì<¼(xQðtž:O�'ˆ©bª˜ Â^Ø û²áN/ÿ Šeb™XƯ`ÄP1T mž6O›å:”ëP®ÌN��:;•_ïÈÊÊ–5ƒh#Úˆ6e£Å^ÎÃ@2Än±[ìÝeÝeÝeÉ"Y$ƒˆñ"tN:'�TjT©Q¥FPº­t[é6èÒ­K·.Ý@Y ,P}éKßW¿lEEE�îŸîŸî½*zUôzóïÇßóÖ UmUmUmÐÆiã´q } } }nnnúk€×-4?4?4âuñºxŒté<Ò +V4üSA*§(§(§À±ùÇæ›%á%á%á°ŠU¬Ò÷ɽÜ>wúÜéspûÈí#·�àÆÐCo W\q}…ýV¸^áz…ëàâëâëâ » wî*„LU¦*S½ì{Ù÷²‡zÕû¨ÞGX?°~`}8p&àLd÷Íî›Ý,W[®¶\ éÑéÑéцM ›6…‡Ë.¸´Úm•7*oTbbb Æ±ÇjƒÝ#v�Ø=ö�Û?nÿ8p©ìRÙ¥2­4Zi´Â&„M›Ï}Ÿû>÷e¾2_™É#’G$�€\Ó\Ó\S �tÒ!W“«ÉÕ€ùóæþóü‹lŠlŠlʆ-½5 j@Ô0¾k|×ø.ˆF¢‘h‰Y‰Y‰YpkÈ­!·†_ð_@bnbnb.N œ8 Z}Öê³VŸÁ&—M.›\À}©ûR÷¥P#»Fv�l¨Õ½V÷ZÝAVOVOö ñ…øB|\\pqÔû¹ÞÏõ~“Z&µLj½ù÷£²·²·²74Ûhl£±pÅëŠ×/ܸ'p¨ú«ú«úÿõý×I¯“^'nÙÞ²½e [ý·úoõ‡´®i]Ӻ¨®£ºŽê •ÆV[i,T¯T½RõJ°oð¾ÁûƒyŒyŒy X=±zbõžœxrâÉ xxöáÙ‡gÁ0Ü0Ü0ÂcÂcÂcàÙžg{ží£<£<£<ˆ_¿"~|¨ùPó¡B†‡ ¶¶¶�ò]Êw)ß�á|Ãù†óá” S.Lá×ÎÄ/†¾úb(Ä.�]»d‰²DY"dTɨ’Q´´´@q[q[qû?ÏÿYè³Ðg¡�›—›—›º*º*º*ðäÚ“kO®AìúØõ±ëÁx·ñnãÝp/ô^è½P°±±“Y&³LfAL˘–1-¡£OGŸŽ>ðbý‹õ/ÖÃê뫯¯¾å{–ïY¾'øòä?*t¨Ð¡B‡¿~Ý„Ƈ�33³7ÿ~ü]okÊÁð»áwÃï 1~ÄøãG‘;+wVî,}O„øú}uù«Ë_]bì¼±óÆÎ¢àQÁ£‚GBˆþ¢¿è/DáñÂã…Ç…Èž3˜ôÁ¤Êþ½ô|éùÒóB¨k¨k¨k‘W/¯^^=!t:�CÙvÚ0m˜6LˆÜª¹Us« ‘7 o@Þ!tStStSôÝJoNÔ¬¨YQ³„ï6Þm¼› ½z'ôþëûӭЭЭ¢àXÁ±‚cBäÜ̹™sSˆÜ‘¹#sG ¡½ª½ª½Z¶}é¦ÒM¥›„ȹ”s)ç’ù5òkä×"73737Sˆ¢EE‹Š Q4¬hXÑ0!ÔWÔWÔW„È�Í�Í�¢HV$+’ ¡ÎRg©³„(¸Up«à–Z/­—ÖKõõõ!rÏæžÍ=û›ícÔ1ê!òÖå­Ë['Dî”Ü)¹S„ÈÛ“·'o�¥;Jw”î({ä]λœwYm¶6[›ý_΀n€n€ùæùæùæB¨×©×©× Qܰ¸aqC!JìKìKì…ÈuËuËu+Ûï¿&Ø"wTî¨ÜQBä×ϯŸ__]{]{]{!41šMŒ9wsîæÜBÝPÝPÝPˆ¢Œ¢Œ¢ !þ5#æ_¿n×÷\ßs}�Ä1A‘ŸŸÿ–ߌBˆ¼ayÃò† 1cÜŒq3Æ qjÅ©§V¼ú~5©šTMªy1y1y1Bä É’3Dˆü”ü”ü!D;ÑNüf í¢öEí‹Ú ‘“™“™“)DþôüéùӅȳʳʳ¢Ä¸Ä¸ÄXˆ‚îÝ º ¡>§>§>'DáÌ™…3…øWo}!Ô±êXu¬ÅTü‘¥—~\ú±ÙÁÙÁÙÁe?_У GA!Ô�Õ�Õ�…ȋʋʋB�­ÎVg Q^^.DÉý’û%÷…È5Ë5Ë5¢PU¨*T !ºŠ®¢ë9ÿÖšÖšÖBävÊí”ÛIˆÜɹ“s' QêQêQê!Da\a\aœêÃêÃêÃB +V0LˆÂÕ…« W ¡ŽPG¨#„(œW8¯pžb»Ø.¶ Qü øAñ!²ó²ó²ó„Èý(÷£Ü�„(V:¬tØ_¿^s2ædÌâÓíŸnÿt»¡³Bg…¾Ÿo­ˆ&šh„U8ªpT¡Ó2¦eLÓ÷é¿>i¶i¶i¶B ¹7äÞ�{Bü«�ާ/Ÿ¾|ú²ÆÆÆB¬µrÔÊQB¬¶jتaBL2yÈä!B\éx¥ã•ŽeûûµÈ™”3)Gˆ‚ ±ºùêæ«› ±8pqàâ@!oZ¼iñ&!âìãìãì…Ðøj|5¾BìÙºgëž­B,öZìµØKˆù‡æšHˆÓÕOW?]]qPõÝjoÀ1D âÛ-ßnùv‹Ó¢§EO‹"c@Æ€Œú'yÓb£c£c£…]ytåÑ•…8åü•óWô�Jˆˆví"Ú 1lÁ°Ãîîî£ïT’7­ \A¹‚rB|!ûBö…LˆÝVt[ÑMˆ’oK¾-ùVßéÞb�:$uHê!†UVeX!’ÔIê$µ¾Oÿõ[eºÊt•©jL¨1¡†º(]”.JˆÒy¥óJç V¶ýâé‹§/ž.Äô^Ó{MïUöï/ €O|>ñùÄGˆ§§'!>ðÁ€ñSÂO ?%‘ôCÒI?¡¶P[¨-„ˆÜ¹!rƒÝ ºt7"¥0¥0¥PˆÐ�¡C ÑË«—W//!Ô=Ô=Ô=ôÝZoN¡A¡A¡�_•ÿªüWå…˜VeZ•iU„HŠLŠLz…o–’wÌqq\â^À½€{BŒh=¢õˆÖBìÞ¼;XÑEt]ôRQ*JE©§ãNÇ�ŽbÐ…A]âç.?wùù]È'y­²¿Îþ:ûk!- Z$Ĭ泚Ïj.DV\V\Vœ¾Ó•ykí’­’­’ÁÈÖÈÖÈÒÓÓÞÇEX^ö®ýe”ƒ¬š¬š¬”jKµ¥ZÈLÉLÉL�ïC¾ù>î}¸÷á^(^_¼¾xýîî_8ÀFa£°Q@Ã1 Ç4_îürç—;aÿäý“÷OÍ"Í"Í"H»‘v#í$^H¼�xBN„œ9·�nÝ6‚By¡¼Pš4?h~Ðwc½9F%F%F%0Öf¬ÍXpvqvqv�µÔ^PÂv‡íÛ b­X+Öê;­äÏÒ<Õ<Õ<…“óOÎ?9,X�Ë—.ƒ>gûœís8ÂŽè;-¿Giýeë/[ “& L‚oF3ú›Ñ°/|_ø¾pø×-w}‡•üi;ØÁxèõÐë¡ÌýxîÇs?Ý:Ý:Ý:˜:5tj(XU²ªdUéUöú¼µN€FÁFÁFÁà`à`à`ñAñAñA¿v:}ü2,F6\6\6œ_{¹žH:‘t" ‚F�  s.Ϲ<ç2ÜYygå�•�ÿSþOù?ÝèF7À#Œ@ì{Å^0J2J2J‚iݦu›Ö ž4~ÒøIcX0dÁ�CÀ`‰Áƒ%PGWGWGVÑVÑVÑPí†[ 70»gvÏìt+ìVØ­,?°üÀò}7Ö›gaacŒy0æœr:åtÊ Öú¯õ_ëþ]ý»úw…nÚnÚnZpT8*ß§a)ï‹_¦j�¯_7¾.ìMØ›°7‚‚‚`Læ˜Ì1™Ð ²AdƒH�%ÿJþ•¾Cÿ¶²•­e£íSíSíSaóÍÍ77ß„ˆ&M"šÀ€v ؾC}‡útèÐé;¼äßeOÏžž=އ= g‡žzv(´8Úâh‹£ÐKÙKÙK ÆZc­±VßiÿÓÛ[øå”?Pþ$œJ8•p ½�|Ý^{QQQ�ì´ì´ì´²‰@ò&çMΛ ÿêlS6Á„â™â™â$$$CQ\Q\QäžÎ=�{òä5ÈkO—>]út)œ9pæÀ™ÐêT«S­N�§‰§‰§ (z*z*zB¥é•¦WšNQNQNQ� HP$(À·À·À·,®X\±¸òhy´>øø Ü5¹kr×âžÄ=‰{Å{‹÷ï…Š… +‚ß¿3~g ¶Sm§ÚN`]ɺ’õ;ÔYê]“×"¯E^ ¸;é“àºúºúºbT1ª(Ž)Ž)ŽAÅJ+U¬¾æ¾æ¾æàyÕóªçU°Yk³Öf-X|eñ•ÅW _-_-_­ï³z�.r‘‹P´£hGÑȪ—U/«¤Z¤Z¤Z@dxdxd8D_Œ¾}Ò»¤wIïR6scÝ)u§Ô�~ƒüù ···�…ÊBe¡ú>¹×ç­/íܲsËÎ-�’’“÷MÞ7yŸ¾›C"ùc^αžÕ4«iVS87ôÜÐsCae½•õVÖ׎®];‚}¤}¤}$´5hkÐ\]]]]]ÁÕÊÕÊÕ œk;×v® ®«]W»®»-v[ì¶€ê–ê–ê(›+›+›ƒb–b–b(F(F(Fw¸Ã�×p"¿L±*¢E´ˆÝ0Ý0Ý0Ð4Ö4Ö4MŠ&E“E]‹ºu…gGžyv’Ï%ŸK>)Q)Q)Q�Ø1±cbGH]™º2ueÙÜû– K…¥¼;zwôîÕ½ª{U÷Ÿ(Ÿ(Ÿ(°øÔâS‹OAî+÷•û¾úéüS‰(%¢ Ï$Ï$Ïä×Õµ‰4‰4‰4�‡AƒAæðÌá™ÃAž*O•§‚ýXû±öcÁí¼Ûy·óà4ßi¾Ó|péçÒÏ¥8×s®ç\Œ2>J;¥�Ò”ϔϔÏ@¢Q„€lšlšleëy¿ªÉLf2èÎèÎè΀f·f·f7h²4Y𬲵>2/f^̼I�“'=†”Î)�S:CòÕä«ÉW!áQ£„GPpºàtÁi0Üf¸ÍpTÔUÔUÔAµgÕžU{¾|ø>{/{/{/PF)£”Qú¾ªožÞ €;#3¶¶ÚÚjk+XâºÄu‰+˜60m`Ú@ßÍ"‘ü1ÖÖÖ°)|Sø¦p¨ä\ɹ’3 \>pùÀå ]¯]¯]©­R[¥¶‚h]´.Zəəəð|ÛómÏ·�zŒzŒz h?Ö~¬ýŒ<Œ<Œ<ÀÄÀÄÀÄŒ4:†} ûösss0«lVÙ¬2ùùù‚ÂEá¢pÃ}†û ÷�n•n•n”X–X–X‚ÆNc§±ƒâÖÅ­‹[ÿfJ+ûFY²®d]É:(\8¸ppYçÔ’ %J&€Aƒ>}ÀÊÇÊÇÊì¯Ø_±¿î'ÝOºŸ¯Æ^�½ƒÝ@»�vÁv·ínÛÝ Z¡Z¡Z¡ï«õÏ¥1Õ˜jL!smæÚ̵ðâð‹Ã/Cì´Øi±ÓàI«'­ž´‚´eiËÒ–Af‡Ì™ ¤sIç’Î`ð�Á7߀ÉI““&'Á¸Ä¸Ä¸ 7n0ܦN¦N¦N`žjžjž F±F±F±`0Ò`¤ÁHPE¨"T HS¤)Ò ¸mqÛâ¶e‹@[[[@þóüçùÏ!÷aîÃ܇PdXdXdE_}QôÎ)œS8 s s sA–)Ë”e‚Ù:³ufëÀ~¤ýHû‘àlàlàlÞxã 8pà<lÛ>¶} f×Í®›]ç×á{ÿTz+Š,‹,‹,aFÇgt„þû?ìÿüÂüÂüÂôÝ,Éÿ­dVɬ’YÔ5¨kPW8,‹ÃºÎï:¿ë|èÕ)ªS$$$üïý‰ùb¾˜ÿšÚ2µ™ÚL-äTÉ©’SrLrLrL ïEÞ‹¼Pж mA[È]—».wä�É;“wŠÌŠÌŠÌ@g¯³×ÙC±w±w±7Ⱦ–}-ûT ªU(Rþ¤ü ŒÎ�1:æÎæÎæÎ`¶Ûl·Ùn0Ùa²Ãd˜™™�å Ë–7ÀÒÆÒÆÒloÚÞ´½ &-MZš´6±‰Mú¾*’׿ 9E?ýXô#d,ÊX”±rå Ê9n9n9n ^¬^¬^ ŽŽŽ�W’W’Wy#óFæ�„«…W ¯‚ö¡ö¡ö!D÷�îÝböÅì‹Ù­´>Ðú¨t*�J†™†™†™`šgšgšæýÌû™÷Óê¦ÕM«ƒé.Ó]¦»Àršå4ËieØ­G[�¶ –�-[>ù ù ù }7âß‡Þ €—¶šm5ÛjÅ�Š?‚��>vúØIßÍ"‘üÿ2§gNÏœ›¯m¾¶ùÄ;Ä;Ä;ÀØø±ñcã¡VX­°ZïBáúË*qÔ¦6µ�&4¡ e«üý²°Dò6]´¼hyÑÎŒ?3þÌxX´ hA(#”Ê}§ûçzk3þžTlP:?t~è Ù‡²eÒw*‰ä_î÷¼ßó~Oø,골Ϣ 8¬8¬8 4^ÐxAãwèƒÿ¥—ãà‹)¦8ÃÎ }ðKôë—å~™Â¦ ïP½Þ¼+xWããÆÇ��Ãí;·ïÜ~�›$’¿@ë®u׺ÃIï“Þ'½aIÌ’˜%1Ðàhƒ£ ŽÂŒ~3úÍèNãœÆ9�ÓwZ‰äo¢”RJ�<òÈÓwÉKz/TÇUÇUÇáà nøpœ¯q¾Æù i¦i¦i¦ït’ µ½Ú^mk£×F¯�†ïݾwûÞ Æ&�M›ýÕýÕýÕ`¸Åp‹á}§•H$’W§÷ॆ .l¸2Š ›}6(¡„}§“¼/^ŽO?ûüíó·aþ£ù�æ?‚jŽÕ«9ÂÜNs;Íí®>®>®>úN+‘H$oÎ;S¼¸5pkàVˆéÓ9¦3$}šôiÒ§úN%ù»+Ø[°·`/li¹¥å––°+{Wö®l¦¦¦†!û†ì²LBLBLBô�V"‘HÞ¼w®pïçÞϽx^ð¼ày‚·o ÞªïT’¿«DÏDÏDOX˜¿0a><²{d÷Èæ­˜·bÞ hêÜÔ¹©3ÈUr•üuÌ`&‘H$ï\Ànv³ÚŸi¦ý¸VñZÅk!éIÒ“¤'ú'yçýÒÛøFíµoÔ†ùæw˜ßœ¼œ¼œ¼`þÄùçO„JA•‚*é;¬D"‘è�Rß~�ÏTŸ©>SÁûCï½?„ã1ÇcŽÇÀ˜ c*Œ© ït’wMÉ ’A%ƒàhç£��v†cãŽ�;6úú÷õïëmk·­Ý¶6(J¥ŠR}§•H$ý{÷îüB¦”)eJèâ×ů‹„>žÜ}r÷É]}§“¼+2K2K2K`eÎÊœ•9pþÅùç_Àt£éFÓ� CõÕ;T—>ø%‰äß½³w^òÌòÌòÌ_µ¯ÚW Ç–[vlL,?±üÄòÀb³Xß)%oÍT¦2¢�£�£�aÝ…uÖ]€rŸ—û¼Üç°Ðj¡ÕB+p¨éPÓ¡¦¾ÃJ$É»ë�½ð’ÌIæ$s‚.á]»„Ã�ÅwßY ‘ޑޑŽúN'y[t×u×u×á¬ËY—³.°è“EŸ,úê=¬÷°ÞC˜qwÆÝw¥~‰D"ù£Þùà%wwwhѸEã�aoøÞð½áPœ\œ\œ¬ït’7¥À§À§À¶5ÙÖd[Øc³Çf� Œœ?rþÈù0°ÅÀ[€áxÃñ†ãõ�V"‘Hþ>ÞùGÿ®Cz‡ôépµùÕæW›Ã…µÖ^X m–´YÒf‰¾ÓI^—de²2Y ëo®¿¹þ&:::¼¦óšÎk £+FWŒÖwJ‰D"ùûúÛÜxÉ2Ï2Ï2zžìy²çI8Üýp÷ÃÝáÅ®»^ìÒw:É« O O Oƒ¹‘s#çFB9ûröåìaþ—ó¿œÿ¥ôÁ/‘H$¯Ëß®x©¡CC‡†àzÔõ¨ëQØŸ»?w.°�mlÓw:ÉUš\š\š ?DÿýC4¬Þ¾zûêíÐ9²sdçH˜à1Ác‚X®µ\k¹Vßi%‰äýñ·- Ö¬5X ƒüÓàŸà–Ë-—[.p½ñõÆ×ë;�äÉÊÉÊÉÊ�ÕíV·[ÝÎ,<³ðÌBø¤î'u?© �{uîÕ¹(‹”EÊ"}§•H$’÷Ïß¶xÉí’Û%·KÐùçÎ?wþv}»ëÛ]ßBN…œ 9ô�Nòïâ¢â¢â¢`~üüøùñ öP{¨=`Q›Emµ�Ú­j·ªÝJß)%‰äý÷·/^jÝ­u·ÖÝÀf�Í:›u°ßf¿Í~cÄ1Fßéþ¹Äz±^¬‡K-.µ¸ÔF/Œ^ ¾¾¾0Ë~–ý,{pè0Ða ¾ÓJ$’7¢)Mi ²%²%²%€è;”D&~¡ï ¯KÜå¸Ëq—aᣅ�>‚1SÇL3¼hð¢Á }§ûç(:Rt¤èÚ}h÷¡Ýpzïé½§÷ ”A)ƒR ™M3›f6 °TX*,õ�V"‘¼¥Á¥Á¥Á�Q-£ZF5�?‘?‘?�Ë·/ß¾|.6½ØôbS˜¢›¢›¢ÅÅÅ0[h¶Ðl!XD[D[DÎ8ã¬ï³yÿ½wÀK'U'U'UptÀÑG”ÝbvèåÐË¡—¾Ó½¿2ÎfœÍ8 ߸}ãö�¤vIí’Ú&¤NH�� >Ù>Ù>ÙúN)‘HÞ„´Ùi³ÓfÃxÿñþãý!®J\•¸*PP¯ ^A=Èù"狜/À%Û%Û%tëuëuëajÈÔ�©!ЧJŸ*}ªèû,þ9Þ›Gÿ®Õ�­~lõ#xÔõ¨ëQ¶¯Þ¾zûjÐLÑLÑLÑwº÷OôêèÕÑ«a^§y�æu æÎœ(}ðK$ÿå²Êe•Ëc c c ¸å}Ëû–7R|¤øH†{ ÷îÕwZ‰D¢ukÕ­U·Tö­ì[Ù÷?_WnRnRn‚æÍ#šG€y¢y¢y¢¾Sÿó¼÷ÀK~Ÿû}î÷9tèÕ¡W‡^°¡â†Š*Búžô=é{ô�îÝ—î‘î‘îKK—–.-…Û[no¹½>ûÙØÏÆBÓòMË7-²ÏdŸÉ>ÓwZ‰D¢OnÕܪ¹UƒÆ3Ïh<ã?_·7±7±7�À�'Oè;í?×?¦ ˆ ‚ [t·ènÑP~Xùaå‡Á¦]›vmÚÅ�Š?ÒwÈwϽ½÷öÞÛ sMæšÌ5U¶*[• j-¨µ xUòªäU 0ÄC}§•H$ïùSùSùShÕµU×V]Á²£eGËŽe¯øôç>…Šöí+Úë;í?×{; àÉ�eÈ2d0÷ë¹_Ïý–4,iXý‹û÷/ÙlÙlÙl}§|ût§t§t§àÜgç>;÷ì<¼óðÎÃÐ>±}bûDè1¶ÇØcA¡ŠPEè;­D"y—¥ßN¿�~ÚýÔî§v?A„g„g„'lœ·qÞÆy0,lXذ0}§üçúÛ­øºØ [a+`üüñóÇχÅO?Yüœ9r>Íg7ŸÝüTì)ØS°vOß=}÷t¸|5øj0Œ0vÀØÐÈ©‘S#' ‚"ô�V"ùg*\^¸¼p9dµËj—ÕDÑF´¬±ÆZßé~£ÝèÚGÚGÚGPç§:?Õù R?Hý õ¨8±âÄŠ!¥0¥0¥„¿ðþ€ 2}‡4hÐÏyÎs0J5J5J•�ÊF2�L'{ú�ýcïü»ŸFý4ê§Q°­â¶ŠÛ*´ÚÓjO« ÕZWk]­µ¾Ó½9©•R+¥V‚o ¿1üÆòŒóŒóŒaüˆñ#Æ�€Jc*�©$ͤ(‘¼‚ƒƒa›Ë6—m.`¥±ÒXi@4ÍD3}§û�_>Èå#å#å#!qâþÄý�Ô;©wRoðké×Ò¯%ÈËËù䓯ïпQ—ºÔ…’>%}Jú€}Š}Š} Ì_7Ýüu`5Èj�Õ }‡|uRðoöUÝWu_UÍ Í Í„ùËæ/›¿ œ>rúÈé#}§{ H î~p÷ƒ»À:Ÿu>ë|Àk„ׯ0²ÁÈ#€eË –ôV"‘üÖæ”Í)›S ý|úùôó0áᄇBiõÒê¥Õõ�î?ÉÎÉÎÉÎAîéÜÓ¹§Aí©öT{‚Ó*§UN«@öHöHöСãúF-«#«#«)ûRö¥ìƒÅ�7ZÜVXy`å°ßj¿Õ~«¾S¾ºì#€ßÓ}T÷QÝGAÊÉ”“)'a•r•r•æÌ ˜—,.Y\ÒwÊ?O©‰ÔDBp·ànÁÝ`諒—ö^‚.¹]r»äBçÐΡ�CAUAUAUAßi%ÉÿEÖGÖGÖLƘŒ1æ_˜aþ…¾Sý}éKßÿò„¢u¨£ï�¿¯p_á¾Â} ˆTD*"�V´â=Z¬ìŸ3 àRMTMTM„Ñ¡£CG‡‚¡·¡·¡7¬ËZ—µ. ŠjÕ(ª¡ï”\^h^h^(l:¹é䦓pÈï�ß!?˜Øhb£‰� ‡cÇŽeç-‘H$’©ø¦Å¦Å¦Å0éÇI?Núžïy¾çùؾ}ûöíÛAÛPÛPÛð?N³_³_³tßé¾Ó}§¿üÉñÉñÉñ°°ÉÂ& ›À“ÛOn?¹ ó;Ïï<¿3ÔO­ŸZ?d2™ƒþrJ$‰D?¤à°]h»Ðv!LÖNÖNÖBÄöˆíÛa¿|¿|¿„³pÎ�:+uVê,˜g:Ïtž)DUˆªUáõåÈËÌËÌ˄؎±c;òëòšÿ.\®WÀ¼ó^Ì{.U]ªºT…¹s æ€[o·Þn½õݪ‰D"Ñ7©øƒÜë¸×q¯“U“U“Up^}^}^ ;Âv„íƒY³ fÀ’3KÎ,9ûŠ÷ï+qDG^áÀg9ËYر'bO 4,<xºªºªºªp$äHÈ‘X½sõÎÕ;¡Ã½÷:܃qÝÇu×,¾³øÎB�w$$‰Dòn‘:þIUVWY]e5ôë߯¿þ0bÀˆ#@‚U‚U‚èŽèŽèŽÀÑíG·ÝE}õQT¡ e•Ë;?Üùáΰjܪq«ÆA4ÑD ’$/H†ºñuãëÆÃƒrÊ=(“£&GMŽ‚:]ët­Ó†è»Õ$‰Dò®‘ €?)µVj­ÔZ°O»O»O ɺd]²tttʶ‹þ1úÇèáPÌ¡˜C10»ÕìV³[ýfØËÿ�»9wsîfX¾~ùúåë!Ú Ú Ú ìõC¡‡B…‹¹/澘 [3·fnÍ„ *L¨0Aß­$‘H$’w�ôàÒ”Ó”Ó”ƒ­.[]¶ºÀžÏ÷|¾çs(½_z¿ôþn/E „ý“÷OÞ?â«ÅW‹¯ö¿�#6‰Mbì•í•í•Áᇇ~øäy¬y¬y F>ù`$ܯx¿âýŠún%‰D"‘ü]HÀ¤<¥<¥<ý¦õ›Öo,˜²`Ê‚)Pëv­Ûµnƒ²Ÿ²Ÿ²à„Ne?]7ºnt]øÁùçœÿ÷q"®G\�¸«ìWÙ¯²‡ßßßßß>¥CJ‡”°Äm‰Û7HZœ´8i±¾[K"‘¼Ë´•´•´•à6·¹ l-ØZ°µ^x¿ð~á ‰mÛ$¶�£ŽG�:B‘c‘c‘£¾Sÿqâ¬8+ÎBìϱ?Çþ [“·&oM†Ø5±kb×è;Ý»C*þ(?üð�&M<šÀ´øiñÓâáÈ´#ÓŽLƒ¯ž|õä«'àŸæŸæŸ……… Ù­Ù­Ù J”(…'ñOâŸÄÿçîsäÈ9_5ýªéWM!ºKt—è.¿ÙÀwÜÁæšÍ5›kÐHÛHÛH SÛLm3µ Ìm6·ÙÜf`ó±ÍÇ6ë»±$É»LÑUÑUÑÌ›6 ße}—õ]¤L˜:ò£ó£ó£á±ö±ö±4Ã5Ã5Ãõ�ú�“%Êe‰`ooG§�~t:Üw¿ï~ß]ßéÞR€¿H¦•ieZ¨@*“MZ4iô ìØ3‚rƒrƒraWæ®Ì]™p·ÜÝrwËÁžÇ{ïy 'œ8p"ÈzÊzÊzÂÁàƒÁƒáÇøãŒÇ*ŽU«€ÏŸ->[ e£–�Z6‚¶°ýƒíà›ê›ê› å”[Pn�¾[C"‘ü¨W«W«WCFqFqF1¨}Ô>j�eɲdY „ƒp—d—d—dèÚ²kË®-A©ŠTE‚ÎFg£³�”€”€”(ú²èË¢/Á¦­M[›¶`³Éf“Í&~]D'3(3(3²ÏeŸË>º5º5º5à0×a®Ã\0bþÄü <�zõ< Ô7Õ7Õ7Á`´ÁhƒÑàìâìâì­ Z´†ìÙ=²{€±£±£±#ˆÚ¢¶¨ ö­ì[Ù·‚¢Ò¢Ò¢Rx6âÙˆg#@÷µîkÝ×@<ñăü”ü”ü�Aú¾ú'¯Ë\æ2\pÁ¥¥¥„®Ãºë: Ž8q:âí7Úo´‡íÛ¶oÛ¾ dgdgdgÀÆÍÆÍÆ æl�³uÎVh6¸Ùàfƒ¡ê ªƒª³êfÕͪƒì¨ì¨ì¨¾OV"‘ü�¤6MmšÚÖ²þ“õŸ€óç ÎÀÐÀÐÀЊ½‹½‹½|ð�‡!C†À¬€Y³`m¥µ•ÖV‚§Ëž.{º N>9ùääðî3Üg8X˜X˜X˜@Ï>ž}<áA¥•T‚}“öMÚ7 ¼"¼"¼" åVÊ­”[PÙ¢²Ee èNwº»÷íÞ·{˜_7¿n~î4¿ÓüNsÈÈȆJ¢’¨$`Ú·Ó¾�ö-tJì”Ø) à à áKR—¤.I°Ûd·Én�ÙÉìdvP¾¤|IùPWWÙzÙzÙz}_�w‡T¼)¿,'i�=ö@ç�t߸~ãú�+Ä/�_¿8Æ1Ž�£«£«£+Œrå:ʬ¿³þÎú;`Ó˜¦ï“‘H$gǯ¿rü d]̺˜u´YÐfAÈÚ™µ3k'쫳¯Î¾: ³�YÈ,À£šG5�j "D„ˆ]w]w]w¸¾ùúæë›!{öþìýйSçN�;�Q=£zFõ@+‹•ÅÂÎØ�±;c¡ü€òÊ€ÁîƒÝ»ÃóóÏÏ??C3†f -Ë×9»svçlð8çqÎãl Ú´%.X_°¾` �W4^Ñxˆú¢¾¨�~lôc£¡ê�ªwªÞ�Ëc.�¹<nn¼¹ñæFØ:ëü­óÁ¬§YO³žð½ï÷¾ßû‚N¡Sèú¾ï©À[¢ì¦ì¦ì&L&˜üÃôL{˜ö0íÊpe¸2\ßi%ÉûäéÇO?~ú18¤9¤9¤�â”â”âˆÕbµXýüÀËÕù<ðÀt‘ºH]$t{ÔíQ·G {¬{¬{ ãÖŒ[3n =zôJ»–v-í ‰‰‰àúƒë®?”íÖ~¨ýPû¡PeR•IU&ANßœ¾9}áZܵ¸kq°åô–Ó[NÃÏ?{üìºiºiºi f‰Yb(((€iwÓî¦ÝÁl€Ù³�¶3mgÚN0ogÞμ˜'˜'˜'Ÿó9Ÿë»õß]Rð–”ëV®[¹nЫ_¯~½ú�gÏžÀû’÷%ïK8.p\à80/1/1/ÑwZ‰Dò>1ílÚÙ´3äËòeù²ß¼ @�d#d#d#@ÖUÖUÖÈ%—\`"™ô¤'=Ái¡ÓB§…ðMÖ7YßdAmm-|sè›Cß‚´‚´‚´°j5Ôj(dÅeÅeÅý~®óKÏ/=¿´¬ïSÏôžé=Ó¡þÝúwëß®r•«€9æ˜øâËoFG™ššB±g±g±'h‡i‡i‡†b4§9Í�)Laо¯Æ»C*Þ2]]]ø´ç§=?í k»¯í¾¶;Ä-�[·2údôÉè£ï”‰ä}Ø+°W`/x^ëy­çµ È È È"U‘ªHäÝÌ»™wž{=÷zî S¦$Lµ¿Ú_í)ÚmŠŽ/:¾èø"8õìÔ³SÏ pzáôÂéPÅ¿Š0w7w7w‡®Çºëz Â’Â’Â’àT‹S-Nµ€›#nޏ9^ô}Ñ÷E_0ýÐôCÓ¡ôQé£ÒGðàÒƒK.AÆÍŒ›7!7?7?7ž< xêGêGêG�\>¹|rù²óó›â7Åo ëŒuÆ:8xèࡃ‡ |Iø’ð% .R©‹ ccÆÆŒ�ú¾ï©À[R2¤dHÉHˆIˆIˆ�^›zmêµ ~Óð›†ßÀO«~ZõÓ*8zðèÁ£aæïЉä½àWÓ¯¦_M0b2Äd¤vJí”Ú L›.6] óÒç¥ÏK‡òOË?-ÿD�(0wÀÜs€Ë*—U.« ÒµJ×*]ƒÇ9�sç€ÌWæ+ó…ù…ó ç‚u¢u¢u"^ ¼x\|]|]|!ezÊô”éPšSšSš¥GJ�”�ƪƪÆ*0.5.5.…Ò“¥'KOB`ÏÀž�=¡ñµÆ×_‹‹‹øÌé3§ÏœÀõ�ë×À.p*l®°¹Âf˜õÁ¬f}±þ±þ±þ 3Õ™êLaꆩ¦n§H§H§HЭҭҭùdùdùd}_=’·"1'1'1Gˆ¡ ý`èB¤I’:¤ìõÈÐÈÐÈP!®¸vàZ!âââô�Z"‘¼K6lØ Äʽ+÷®Ü«ï4ï¿dïdïdo!>êöQ·�º ‘¶1mcÚF}§z}¤GoIL¯˜^1½ÀJi¥´R‚�…�…�EÙëÕÛVo[½-Ôɨ“Q'öwÜßqGІiôaúN/‘H$’÷�T¼%?üp0TJ©”R)«««³A@Ï[=oõ¼Ñ·£oG߆ÛA·ƒné;½D"‘HÞ7Rð†­/Z_´ýôè§G?�ïPß¡¾C{—c.Ç\ŽAëÂÖ…­ aàþÀý�P¬,VK=6$‰DòšHÀ–Ù7³of_P—ªKÕ¥à¾Ñ}£ûè…Ú¾iû¦í›BATATA„œ9rBßg#‘H$’÷…ô�ò ‹Û·9n3˜�1c6k8Öp¬ñ¿Îb½Åz‹õн {A÷8píÀµ× �mÛ¶`�a�a-Íe-‘H$’¿Hºð†EÞ�¼y<Ò<Ò<ÒÀp¼áxÃñüç?”}(ûP¶m;Úv„c-޵8ÖBßg%‘H$’¿;©xC´>Z­ĉ8' Úºj몭ûóû146464†¾ô¥/²3dgÈNxòõ“¯Ÿ|­ï³”H$Éß•T¼!©±©±©±�Ý"»Ev ¨ò´ÊÓ*Oÿúþ|‹}‹}‹¡æƒšj>€ƒŠƒŠƒ ŸˆOÄ'ú>[‰D"‘üÝH}Þ�„ 3f€iÓ¦Àú[ëo­¿ýëû“id™zm赡ט;sî̹3!"$"$"jS›Úú>i‰Dòfý²HObbbbb"Ü^{{ííµ IÕ¤jRõîÿM ˆ’ – E–|¼|<”¬×~¤ý¸Å3ž²W<Îk&3�È mpÚà´ÁP¬.V«�RHÑwº×G*Þ�û÷îß»<*{Tö¨ Æ9Æ9Æ9¯¾ßòcÊ�)?ƒƒƒ`ŸÓ>§}NPµ¨jQÕ"042424Ò÷ÙK$’7¡¢SE§ŠNp¹Åå—[ÀÕÕ0“™ÌÔwºÿ$ÎÉÜeîà0&=1=›¥¤@d�Ê]*w±M>A>Pþkùôw†^xAéîÒÝ¥»ÁÛÍÛÍÛ ŒÜŒÜŒÜôîõ‘½œPßAÞ­F«Ñ¬Ÿfý4ë'háÒÂ¥… ´öníÝÚûõ'K—¥ËÒÁÌë3¯Ï¼]Óº¦uMƒÖ]ZwiÝEß­ ‘HÞ$'âDÜË©ÜSL1ÕwªÿC‘ÜIî²U×ò¯åƒlÝ•W^€.k‚çO @ñBñø×Thï-Z´ «'«'«²ƒ²ƒ²ƒ@cÓXßá^éÀk–3/g^Î<ȼ˜y1ó"xUôªèUØÅ.v½¾ãXË­åÖrèÞ¶{ÛîmáÙ²dP?³~fýL°j=Ôzè«G"‘¼{d2™È�½kwÏÿokþµkj]­uä–Xb ¿üß»çÙ/�(ÞSR'À×,&8&8&Œ�Œ�Œ�ÀÕÅÕÅÕåÍ/à|Àù€ó`bbA©A©Aïâ³@‰Dò¦ˆUÄÙÙКÖúÎ$‘î¼f·>Üúp+¸á† ª©ª©ªùæŽgTר®Q]è÷E¿/ú}«3Vg¬Î€&FMŒš�[‘[‘[‘¾[E"‘H$ïéÀk¢©¯©¯©Ñ3£gFÏßM¾›|7½½ã× ªT+ª-©¶¤Ú8u0ê`ˆf¢™h¦ïÖ‘H$É»F*^“¬¯²¾Êú ^¬|±òÅJ¨4ªÒ¨J£Þb€«\å*ôÌè™Ñ3¢ªEU‹ªw»Þíz·«¾[G"‘ü³e$f$<Ì{˜ vˆúÎ$‘ €×$).).) ‚þչũԩԩôíç¨àTÁ©‚4—7—7—ÃÞV{[ímEQEQEQún%‰DòÏt?å~ Àþ°ýaÚ"­ôhRï¤à5‰Œ�Œ�Œ·Qn£ÜF�y=ózæõô—§ãŽŽ;:î€LËLËLK¸¼éò¦Ëoñ‘„D"‘”ñ¾ã} sÃÎ ÁŠ`}g’HÀ«zÈC£•�V>Z >—}.û\Öw(°îmÝÛº7t¿ÐýB÷ pxßá}‡÷AÎМ¡9Òð@‰DòV9Œt P[U[ ;";¢ïL©xEõ2êeÔƒÔìÔìÔl¨Þ¸zãêïÐDÍŒ›733S3S3S8|"ø„TyK$É?žT¼¢D—D—D0˜c0Ç`8:;:;:ë;Uî†] »Bï½ô~Á‚/_€¤“I'“Nê;�D"‘HôE*^QLó˜æ1ÍÁå;—ï\¾³efËÌ–é;Õª}²öÉÚ'¡ŠeË*–p°üÁò˃è%z‰^úN'‘HÞo¥ÊR%@Þ´¼i¬a�¾3I¤à/*¡*¸v?ì~T­YµfÕš %%{›Ãÿþ yyyèãÒÇ¥� Dˆ! raäÂÈ…úN'‘HÞo‘7"o|7ø»ÁÚ;Ú;úÎ$‘ €¿¨`iÁÒ‚¥�z8õpêaðí9Ús´¾Sýo444Ðì`³ƒÍÂþšûkî¯ ¥¥¥úN'‘HÞO†‘†‘–,;ðŸé;“D*þ¢§¹OsŸæ‚X%V‰UP1¼bxÅp}§úãºìí²·Ë^Ȱΰΰ†Ÿ–ý´ì§wðÑÅ{C À!qÈ%—\}‡’HÞŸ^>½z,è±@‘ª�Ö,Ñ;©ø‹bæÆÌ�™ jµƒÌlÍlÍlõ�ê�³Ž·Ž·Ž‡.‰]»$Â?xüàj™Z¦þ[,/ö'ýòœµ,kYÖ2Èú$듬O€<òÈ{ó‡�5�5�5…õ Ö/X¿B¢C¢C¢!gÎþœý�-Ë–eË@ÓGÓGÓRî¦ÜM¹ ©—R/¥^‘%²D–¾Q"ù«Æ cÕ@Õ@Ð@ß™$RðÅ�;<<<<<<@ö‰ìÙ'úNõç5MošÞ4LƒMƒMƒ!È$È$ÈDߩހ4ÒHƒýÁûƒ÷þÚûjï« |Ï÷|ÿ'ö³–µ¬ííí �tÒóÒ¥=J{À¶Ôm©ÛRÁòk˯-¿»svçìÎÁž–{Zîi >:ðÑ�� ô\é¹Òs°?räþH˜?;~v<”Î/�_:„¿ðþ »§»§»§ïF•H$gRð'å‡ä‡ä‡ÀÓ½O÷>Ý UVXe ¾SýuÆÎÆÎÆÎÐ÷iß§}ŸBð§ÁŸ ‰÷ï%¾Í˜Ãæ0°„%,ù/Û½\Ÿ{8ì`+øõžÜàÆÿñs…R=Œ{÷0†^“zMê5 ðÆoÊnÉË·|ËïQS£¦FM…C·Ý:t pÆg@ƒÍn_|¤øHñ¸ïwßï¾x|îñ¹Ççà;Ãw†ï è!ï!ï!‡îÝ=º{€ñ ãÆ/ b¿Šý*öƒ‚K— .�¦¹¦¹¦9üpþ‡ó?œ‡û“ïO¾?ùÿ8Ï$’HÖ±Žu@>ùäÿ¦ÝÂ#ì-^W‰DòÎ’–þ“²eÊTö‡Ù9Þ9Þ9pÅW}§ûëjM¯5½Öt¨ººêꪫá‡Þ?ôþ¡7LΘœ19H%•7ðÌ.jKÔ–¨-<8xpð`�È äPDZŽcGhò¬É³&ÏàŘc^Œ�OO<=ñ à à à Ç8Ç8ÇŠŠŠ!üVø­ð[ÀzÖ³ÌsÍsÍs¡jXÕ°ªa»:vuìjHß’¾%} Î œ8 ¶ïÛ¾oû>ðœä9És�G¶G¶G64Ðd@“°1mcÚÆ4x2ëɬ'³ÀaˆÃ‡!Ð4 i@S�_–_–_í!í!í!¸9ðæÀ›!þLü™ø3pjë©­§¶‚õbëÅÖ‹!Ì+Ì+Ì 2FeŒÊ™ÈD@ÖJÖJÖ d¥²RY)Üm|·ñÝÆ°êÒªK«.AËo[~Ûò[°üÁòË€Œ`ÙÙÙAqûâöÅí¡b�Š=*ö€ÆA�ƒÁ·U¾­òm0¬iXÓ°&˜ô7éoÒêÖ®[»nmˆsˆsˆs€¼ªyUóªÂíí-È d²}¿K%_OƒžÄŸ�? ФK“.òfriµR½‘îüI�ýû?ö³;fwÌî€Ã‡ô�êÕ)  è­ì­ì­„ïïoˆôŒôŒô|sÇݺqëÆ­¡`fÁÌ‚™Ðõ^×{]ï�õë)ÖS@»X»X»6�Þ4zÓhH+L+L+„~súÍé7üÛú·õo Ê…Ê…Ê…�»=w{îv;v.ìT_W}]õuPηœo9_0ô1ô1ô�K/]¼tlNÙœ²9w«Ý­v·x®ð\á¹ÚVl[±mEø®ùwÍ¿k òy‚;,vX ž½<{yö‚úíë·¯ßä]ä]ä]~Óž– K…%T?RýHõ#à sÐ9è ±wcïÆÞà3Óg¦ÏL0ð0ð0ð€+í¯´¿ÒtÁº`]0`‹-¶ މc┿PþBù `2ÍdšÉ4h¼¾ñúÆëÁÁÄÁÄÁÖëÖëÖë@µMµMµ ºEt‹èû£÷Gï�†§vOížÚAήœ]9»àV—[]nuߎ¾};‚±»±»±;ZZZ�Ñ7Fß}8à€ƒ¾ß�’¿¿Ä+‰W.…^ Ð%ë’õ�I"Ýø“îgÜϸŸ'UœTq¨òUùª|}§z}*L®0¹ÂdhæÞ̽™;ìÍÙ›³7Ú,´Yh™™™¯ïx•¾­ôm¥oáè•£WŽ^ëÖ¬@—»üØåG(iVÒ¬¤Üì}³÷ÍÞ0!{Bö„l°¸`qÁâ4ªÙ¨f£š ìªìªì ö\Øsa8Vq¬âXê9×s®ç œà'àÞÇ÷>¾÷1ȵr­\ ÎÎΠܠܠܦ�M›>ïÞ+¼W€Aƒ:uàiå§•ŸV£F+ŒV€Q®Q®Q.w6îlÜùÿ8±@ £Ï�>7ú”6J¥ ˜M2›d6©l3Æ €OŸú>ú>ú> f‹Ùb6hJ4%šˆ÷�÷�÷S7S7S7¨<­ò´ÊÓ@Ö_Ö_ÖrBrBrB ¨{Q÷¢î€/¾¼¤ Ô‹zQ/‚á¡á¡á!hNhNh~¶“~·~·~7èóõùú|Ð × × }Ž>GŸzk½µÞŒ®FW£+•F¥Q ™3f>F0‚PMYMYM 6Ø|`ó4^ÛxmãµÐÆØÆØÆ®½\{¹ö�—ÎKçº"]‘®pÁà‡8§RN¥œJ�ƒ�>:øÄ01L 3÷Ñ(‘Hþ Rð+¥†¦†¦†‚E„E„E¸ qâ6ÄÜ©þ|-η8ßâ<(w(w(wÀ‘ýGöÙÿêÚ×xj<5ž°µÞÖz[ëÁ½Ýû×½Áè°Ña£ÃÀYt�Eøðø‡Ç?<ÊÆÊÆÊÆ°©Æ¦›jÀ·nÜ ªOTŸ¨> ¨¨vìØ€¬‡Y³B‰K‰K‰ änÈÝ�»*l«°­Â6H—8.qhkkÙ¹gæž™ ‡px :?èü ót2èdÐIhÕ"ªEXí·ÚoµަM;š†å†å†å¥ý5¢FÔ@lýØú±õÁwŽïß9�\˜\˜\NNN�×"¯E^ ðªêUÕ«*Ü]~wùÝåPP£ FA ¨p¸Âá ‡!gzÎôœéУe�–=Z•¡W†^ ±§bOÅž‚Q¦Q¦Q¦ÒþmHÙ�²!N49ÑäDH«–V-­X�´i5¬}¬}¬} kjÖÔ¬©@':Ñ rå4Êi™µ3kgÖq±¸X\lî£P"‘ü)Dɯ²?þþ|Qœž5=kz–(›››™;Õ_çö“ÛOn?Åwn¼sã�¢˜d™d™dù Þ n7ˆ¢ñ}ãûÆ÷EѨ5j�ZQ�¢Q4¾dû1D Ec;c;c;Q4n7n7nÅ7ω¢Éd2™L¢hÒ˜4&�(ŠƒÅÁâ`QW‹«ÅÕ¢h:n:n:.ŠâXq¬8V Ož(�™›�%d YÐ{xï὇Ãý”û)÷S ªCT‡¨¿Á| ž1ž1ž1P>´|hùPhÚ´iÓ¦M¡}›ömÚ·µ�ÚFmò»ò»ò»Ðãh�£=ŽB½óõÎ×;‰Q‰Q‰Q ºŠ®¢+nܸ’ܓܓÜA®ׇÃöÛlƒÁ`0ÀØÈ±‘c#!ýlúÙô³p¸âኇ+š{oH$¯ZÍìšÙƒ|ùțɛ™;“D*~ÁÓÞO{?í ®V¸Zá*ØL±™bó7œèæ¯æ»Òw¥ïJh]к uì(¿£üŽò ë©ë©ëiîtÿ›ðXx,<a�°GØSúsE%E%E%pëèÖÑ­#x›¼MÞ&p™ê2Õe* GŽø’/ù„`!XÁOðüøiµ½è~Ñý¢ûAÊÑ”£)GápÜá¸Ãq�ïžïžïùùùÒò»’«æVÍk:¾øæ?—¹æÎ$‘.ü‚d‡d‡dðÞê½Õ{«¹ÓüýtÝet—Ñp-àZÀµ¸°öÂÚ káMÞäMs‡ûo*R‘Š ôz=€cãˆb�Xœâ§øÏÅJ(¡УG˜0aЀ@yÊS¬*ZU´ª^ ^ ^ Pkz­éµ¦CpApAp¸îsÝçºï7§–H$’ßLø à à à cBÆ„Œ àwÉï’ß%s§úûqºïtßé>t¿Ýýv÷Û°çæž›{nB�²@Y 4wº_f½Âz…õ ˆñŒñŒñ„äJÉ•’+�ºžºžºL+˜V0­t{›�6;mv‚°SØ)ì„g¹ÏrŸåBŽ,G–#m’6I›�F£Ñ@SUSUSäTÍ©šS   Ài™Ó2§eàpÏážÃ=sï‰DRHÀÿ“ãžãžãEˆ ¿¹~sý¤¡ªß­ù¶æÛšo‡3fÀÁo~sðs§úeﺽëö®8éü¥ó—pëØ­c·ŽAÓˆ¦M# Ü¼róÊÍõxõxõx¨Ð¢B‹ -à£-mùh ÄÆÄÆÄÆ@ARARAô¸ÓãN�;`J0%˜ ‡U«VÐrCË -7Àå›—o^¾ ·çÜžs{ä+ó•ù¯q�$‘ü>Ùõ³ë<ýp4€8KœeîLi5Àÿ'꣨�¢>ÅÔ¨?P‹bþ§ùŸæjîTwÞYxg¡(òä?È_§$NIœbîT‰ä¯q©Â¥ ¢(Š3GÍ%Š¢¨ß¨ßhîLiàÿÉø:ã댯Áþ¡ýCû‡`›o›o›oîT!÷Cî‡Ü‡î5Ük¸CøúðõáëA¼ ^/˜;�D"ùsååt[Úm)€ü¶ü¶¹3I¤Å€þŸuOÖ=Y÷´ñÚxm<Œj?ªý¨öæNõÏ‘XœXœX 3¾ŸñýŒïaÜúqëÇ­‡�ë!×C®›;�D"‘”ÒÀL·L·L· Õ*Õ*Õ |ßñ}Ç÷s§úçñUú*}•ÐzPëA­ÁŽG;íxº¡º¡º2¸Ì²D"‘˜‹Tü@¿W¿W¿²]²]²]Àk¹×r¯åæNõÏÕ©o§¾�úB~×ü®ù]áüÜósÏK7[J$É_F*~�›”›”›š0M˜& *4©Ð¤Bs§úçrÞí¼Ûy7t�ìÙ=öøïñßãùŠ|E¾4;…DòcúÒô%€>N@QæÎ$‘þÔþ iPÒ ¤A`ãdãdãnsÜæ¸ÍÖ±ŽuæN÷ÏÕ¼Mó6ÍÛÀiñ´xZ„C^‡¼yÁ@2ÐÜá$É+r§ò�Ê×][0"jD€ü²ü²¹³•]ÒÀÒê¤ÕI«î­Ü[¹·EEEs§úç³^j½Ôz)ôóèçÑÏÎÎÎ ñlâÙijæN'‘H^ ›6\º4`3›Í�I"?xþéóOŸ î5Ýkº×!TBÍ�ªì¨½¾öúÚ롆¼†¼†vÕÙUgW0L“âtqº8l½³õÎÖ; ^¯^¯^oîÔ‰äß©�¨�<Ž| p¿ÒýJú#ú#Á™Á™‡=pß÷¾/@úgéŸp©ðÿË”ùK¦K¦K¦K�ê”ê”ê�>hôA£Ì�ª Š#Ž8x[ö¶ìmÌHž‘<#æºÏuŸë{Ûîm»·-�)S<ZšZšZšÀg˜Ï0Ÿaæ/‘H^(nVÜ `Ò²IË"s"säå(¢€B „îBw€ "Þžõ¶4Cà_¦Ì�¨ƒ€Û·þË¡êêê7#nFÜ s§—H$/WK]K ’’ð²ß[ݳºж^ÛzÖ“¬'™;sÙSæïÈØ’±%c ععع€ýöoØ¿aîTe‡ì;Ùw²ï =íi¸½­ÞVo «V9¬‚)G§�rôwôwôwà ÷AïƒÞµ0jaÔB° ¶ ¶ ý—ú/õ_‚éˆéˆéˆÓÄiâ4@�5˜,M–&K“Åd1°ÄK��•�•�á°pX8 ä“O>�„GÂ#�5’5’5Y¾,_–r'¹“Ü ^ /…Èmä6r�+åJ¹òÅüfòË`!·�[ÈÁ"Ã"Ã",>°øÀân 7…›€ ™T†K^¦^¦^â^q/€´ú”••Á.Ü.Ü.”ß)¿S~à˜ã˜ã˜ŽÏŸ;>'£“ÑÉ.^.^.^àô™ÓgNŸ�¥µ¥µ¥5(J%ŠPLTLTLr�ƒæ>J$¯±‘Œ0 0 �}/û@¶TöÒÇjó?Ïÿà›sßœð\á¹ WÝ^uäEò¢{ÁÏùŸJ?•••r(ä@û í+xVóü·»þSv§ìX&,ºEt‹}?ô¥€æKÍ—çúŸë LT&4y»ÉÛòy‚¹wõë¯Ì*µJ­RƒÊ 2¨ à¶Ëm—Û.s§2ƒYÌb”$•$•$A¶W¶W¶d·Ìn™Ý²Ä,1K„TMª&UÏeÏeÏePø´ðiáS(©SR§¤¨�j£ÚB€ €…�…�… (]”.J°³³åyåyåyPWW‡rËÊ-+· Á1Ø1Ø1ìFÚ�´ qqq`QÛ¢¶EmP¤+Òé¼ø36t¶:[�-8�r:åt dMdMdM@^S^S^³ôüOßôd²�õ’õ’õzÑ‹^`’™d&˜››å(G9+‹•ÅÊ`ÔµF-˜œLN&'0\1\1\c#c#c#0ô5ô5ôC¬!Ö †­†­†­ ½¡½¡½%‡K—†‚'O ž@Á€‚ XY¬,VBöÑì£ÙG!¾y|óøæP\\\ºõuôuôu%J”`÷/»Ùý ”¢RTŠàÐÍ¡›C7ðœè9Ñs"x½åõ–×[à†n€›£›£›#¸Íu›ë6¬—Y/³^T¤"Í}Jþ:OÖ?Y°óà΃×w\P�z/Ý޲в a§†�ʯ-¿@ö­ìÛ—¾ÀG€®]»vèP©C%ù7òoBo…Þ°heÑ €K\¨è^Ñ`ªvªÀ~“ý&6°á¥ï³œå} úä?Ì`ªoª GþÒ—ÅŨ>U} ô(è€åBË…æþlþz‚øsù«eÍ<šy&§LN™œ³Sf§ÌNïÙÞ³½g›;ݧÓét:Ì)˜S0r;ævÌíq¾q¾q¾ççç©…©…©…�{<÷xîq0 `›b›b›öÍì›Ù7ƒòKÊ/)¿Êo(¿¡üp q q çsÎçœÏ�s[ç¶ÎmÁÙÊÙÊÙ ”ÙÊle6țɛɛ�à(8 ŽÀ¦0ÅÜ{ç5¤C‡Îp†—ŽLè·è·è·@QvQvQ6äåæåæåBÞ„¼ y ¯^^½¼z�»5wkîVH‹I‹I‹�,§,§,'(®]\»¸6¨ë¨ë¨ë€eË&–MÀí¶Ûm·Ûà£òQù¨ `wÀî€ÝàëãëãëÎöÎöÎöàøØñ±ãc�Ë‹åÅæÞI’ÿ¤R¨™V™VîÝ;Ø}o÷ý˶O_‘¾àq½Çõj6¬ÙÀ]î.ÿ5ï÷ÚùqfÁÛ¼x|¸9Í~éÒÚ¡7½ pó½›ïŒx6â€ç4ÏiæîÊ_¯ÌñOãŸÆ?…yÌû`Þ0ÿÊü+󯀛ÆMã¦1wºÿ⇙óô¹ú\}.äœÎ9�sbâbâbâ æTÌ©˜Sð´ÒÓJO+AþäüÉù“ùé­ë)×S®§ âÁŠ+„Š[+n­¸|×ø®ñ]<:xt›t›t›t°jnÕܪ9(ÒiŠ4Ào¼Í½$¿h›Øúæúæúæ }¦}¦}ªªª�f“f“fIg’Î$��ÄÆ‰�C²²²?ä7ÍošßäÃåÃåÃÁõ#×�\?‚Ày�óçAÐ¥ KA— ðaàÃÀ‡à´Êi•Ó*�?�?�?0wçË¢ÓOO?8¼ùðf€1ãÇŒ¨äRÉå4û�eìiì  m¯m`}Þú<¼x ùeÛ? yP¸¢p@íwj¿/Æ&ÍÝ—?®ÌÒ¤?H‡U™«2WeÂüÕóWÏ_ Žk×8®1wºRùÝó»çw‡g Ÿ-|¶ôyÐçAx4ùÑäG“!Lþ˜ü1`?ß~¾ý|ðËñËñË�ê7«ß¬~*~Vñ³ŠŸ�ëb×Å®‹Áñ�ãÇ ».».»nîÞI^†-†-†-�••9á9á9ággg�Ë=.÷¸$®O\Ÿ¸4Aš M¸·poáުϭ>·ú\¨î\ݹº3øò?ä”ã•ã•ãÍÝ»¿¥-lJWÍû…Er —.ÐÆhcÜÂÝ„L!ÓÜ]ø'¸¼üòr€#ïyà›l|EßÀY³Ì7ÎÞ8{ã,ìè´£ÓŽN0ïü¼óó΃mÛ¶ þ ‰$’ý úô‡è6Ñm¢ÛÀ•5WÖ\YOÝžº=uÅÅÅð/ð/ð/€�¸�¸�8ºt+è”Ï,ŸY>ä£ä£ä£p0÷^–ücüðT„~Œ~Œ~ ¤,OYž²žÄ=‰{÷zßë}¯7$ÖL¬™X„^B/¡Ô8^ãx�ãÐtWÓ]Mw�ÿ}ÿûþ÷AYEYEYÅÜ�zeîÈܰ§ÞžzÍC›‡TO©žbîleÒO…i“µÉББò(y”¹£ýqe¶8£;£;£ƒ N,8±æŽ�;vîX°PZ(-”Þûšô&½I‰S§$N�3ò3ò3r¸UÿVý[õA$’A-«ZVµ¬ ©eS˦–àßÕ¿«W°™b3Åf ½…ÞBosïE‰äÓMÓMÓM(™Q2£d�»4wiîRpÚä´ÉiXT¶¨lQèK_ú¾º÷1í4í4í„ÇÅ�‹Ã~ÇýŽû!6*6*6 ãããa¨õPë¡ÖÜ;¸wpoPÞWÞWÞªP…*À]îr×Ü{M"y9YCYCYC°?nÜþ8Ô§>õ�úsëÏ­?ò*çUΫ QU¢ªDU�S§NÀ©¾§úžê !C:†t„ÎÓ:Oë< *eWÊ®” t§;ÝÍÝ»¿Ru�êÕÕÕÕ|Žtâÿ�ùÈ|ÒÆ¥�ˆNŠNøÐãCùsùssgüOev`eñÊâ•Å ¨¯¨¯¨ïG¿ý~ô«k?ùJò•ä+°³æÎš;kƒº>º> �«�«� Ø`ƒ�¹ÃýŒ'žx‚f‘f‘f”¼[ònÉ» mªmªm „Nø¾L^]^]^‚݃݃Ýa쌱3ÆÎ€É™“3'gBbdbdb$L1}ÄôpG¼#Þù[Mɽœ{`éÂ¥ âóãó{+?.�­9®9®9†u†u†u¯.¥q¡q¡q!Ü n7/‹—ÅË “éd:h“´IÚ$ Œ0ÂþK;3Œ3Œ3Àà`p08�xÄ£W¿Wu™ºL]&œ»îþ¹ûpìÆ±Çn€ÁÖ`k°}7}7}7SÄ1ôžzO½'heZ™Vâ q†øJW•]•]PvUv^ÓÿOÄ2Æ8Æ8Æ8FgXͰša%ЇòåÊÿýí½8EqKì–Ø-±¢øNÊ;)龜â9å9å9¥(êô ús÷ºÔ¹£çŽž;*ŠŸ7ú¼Ñç�DQí®vW»›;•äÿÓŽÓŽÓŽŽå÷–ß[^‡ì²sÈNQÌœ�9!s‚¹Ó•ŠËŠËŠËÅù æ7˜ß@W8­pZá$Šs®Î¹:çª(^¯ˆW~G»êXu¬:V÷<ÚóhÏ#Q(Š¢x¼õñÖÇ[‹¢é]Ó»¦wÍÝûßâÉì'³EQ74ÝÐTE±È£Èã··’Ó!§CNQ:>t|¨(n¸´áÒ†K¯.å~q¿¸_ť喖[ZN‹N�(:!ŠÛ4Û4Û4¢8¼hxÑð"QÌÿWþ¿òÿõËíì3î3î3ŠâÒw—¾»ô]Q4Øì v¯~¯õ9êsÔG§ë¦ë¦ëDqÿÐýC÷Å+=¯ô¼ÒS§_�~uúUQÌmšÛ4·©(žíq¶ÇÙ¢8àÒ€K.‰blNlNlΫÏõËÔŸª?EQT¥ªRÿÊ÷}¹27` 5…šBA³Z³Z³ìªÚUµ«úûÛ;æ}Ìû˜7\­zµêÕª0}êô©Ó§BË¢–E-‹@á«ðUøš»×¥ªÜ©r§ÊxkÌ[cÞ–³,gY΂‡3fÀ ý ý�಺b¦˜)f•®Wº^é Ïv?Ûýl·¹Sý2Ë/-¿´ü÷î Ü 5j&ÔÝÝÝ€W¸_œEgÑJn•Ü*¹¦ë¦ë¦ßðx¨æºæºæú‹ÙWšå}”÷QT_R}Iõ%°²áʆ+‚æ ̶͚߰µ¿µ¿µ?t¯Ú½j÷ª0:ptàè@Ø%ß%ß%‡ë®¸þ ÷߯Š];€÷z¿×@™¡Ìøí­¸v9ìr)ŠE ¤�N�>úÕ¥ ù äƒ� ´Wh¯Ð^ l«l«l gΜ…xM¼&^†w ïÞ…;º;º;:¸¿äþ’ûK~ÖŽ"†ˆ:4thèP�͓͓Í{õ{õÚÅk¯]ûÛö·íoC—ð.á]¡r§Ê�*w‚NC; í4ì·Ùo³ßÁ¾Á¾Á¾�z'õNêP_U_U_}õ¹þKâã׎,ê·¨€!Úð /=ÿVeî&@SgSgSgЖӖӖ›Ý6»m~lj ¹yróäæp¢ß‰~'úÁÈé#§�œþþþ¿?ßC÷‡îÝáü§ç?=ÿ)4¬Û°núPYýeõ—�v±v±v1XºZºZºBü¤øIñ“àVŸ[}nõýýý°:guÎê8=szæô œª8UqªòŠòŠòŠóȧ1‚˧.Ÿº| K{-íµ´X °`5k;Öv¬ +V¬„ËŸ_þüòç�^+½Vz-(—P.¡\´¨Ó¢N‹:`‘`‘`‘ðëûùTþTþT·Êß*«<ð Ÿð 4nÛ¸mã¶�q%ãJƸ»õîÖ»[_Ìú>x´ôhéÑÎÌ=3÷Ì\Ì Ì Ì„r­Ëµ.×.Ö¿Xÿb}ÐËô2½ j=«õ¬Ö3°zßê}«÷aÞ¦y›æm‚æš_h~ÞúÎÐw†‚ÝWv_Ù}çûŸï¾?ª Õ…jjÔ.¨Ô¨R£J�*p¢Ï‰>'ú€fšfšfØ{Ù{Ù{Az`z`z TЍQ)T§T§T§ ×"×"×Úßh£ý (׸\ãr�ý~’} û@ö‘B¤YºX‘q•q•q\µ¾j}ÕÒ†¥ K–�-;[v†¦ò¦ò¦r(÷´ÜÓrOAã¢qѸÀÅ‚‹ '3'3'òæ7Ìo>×|®ù\ƒv}Úõi×çׯQ40h`Ð@~šhêGî)î)î)P (P(Ààdp28ýþÿ.ê?­ÿ´þS4{ÐìA³!Ü&Ü&ܪž©z¦êpjíÔÚ©õïoÿ/0Žq¯°µÖ|ˆ‹�‹�‹…ƒ£Ž:8 4O4O4Oà_£ÿ5ú_£!arÂä„É�žž�>éôI§O ò@ä�È�ê�ê�ê¿éøMÇo mLÚ˜´1�Ú<µyjs¨Ú«j¯ª½@–(K”%‚¼‡¼‡¼¤Nœ:ô[ÐoA?ðïâßÅ¿ Ø6·mnÛ2keÖʬiiiàÜȹ‘s#8»í춳۠ܦr›Êm‚’%-JZ€¥‡¥‡¥´÷oïßÞ,ß´|Óò¿¬ò™¶-m[Ú6xxÿáý‡÷Áv·ínÛÝ9'rNäP4S4S4ƒè®Ñ]£»Be¿Ê~•ý@v^v^v„d!YHá�ð@xœä$'áòÒËK//…¤öIí“Úƒ‹ÜEî"‡–1-cZÆ€uœuœõš¨Ò¹Jçžå<Ë0ºÝf9—¹±³ØYì švšvšv`;ÝvºíôßÞÎù›çož¿ B€ @uÿêþÕÿÀ‰ÿG¶cmÇÚŽ…2d@š2M™¦„ŸŸøüöç·?¿ 1bă 0( Ⴤ>ÕBÕBÕBX1gÅœs@õ‘ê#ÕGPdQdQdÆùÆùÆù°Æu�ëWЌՌՌµ�ÚNmç<Îyœƒò5Ê×(_ŽN::éè$8p0à`@é¼ûZíkµ¯œìw²ßÉ~¿¾º÷tïéÞƒùMç7�ßÔÅêbu1¸+Ý•îJ(Ì-Ì-ÌÅÅÅø¦ø›âoŠ!ÿPþ¡üC ˆb<ÞñxÇã`Ùβ�e;XsyÍå5—áшG#�? ? ? È»›w7ï.Ø~iû¥í—Püañ‡Å‚ïtßé¾ÓK×$Ø8jã¨�£àQñ£âGÅP)¼Rx¥pX±jŪ« naܸ…p»ÓíN·;ÁÅöÛ_lU«8Vq„ËC.¹<N«O«O«!x@ð€àp¹á冗Bx¥ðJá•þøñ!ë!ë!ëGÃ�† ‡CÓM?4ª»Vw­î y{óöæí…Å9‹s瀺¶º¶º6VVVÁ�jª¨U—W]^u9ÜØuc×�]�{#÷Fî °p·p·ø ËbËòdy²<�=‘=‘ýìf¶T§T§T'¨ÒµJ×*]Áº­u[ë¶¼ÿM¾nòu“¯Áz�õë5p{Üíq·_å‰õï"ðÅ*|.=]zºô„ê ª7¨ÞÒ–§-O[Ë–, €¬ŠY³*¦›lZÚÖÚÖÚÖ ¤¤lx°áh»k»k»CÉÜ’¹%sa]þºüuùPò¤äIÉ“ÒÕ+ÅÏÅÏÅÏA™¬LV&Cñ½â{Å÷À{©÷Rï¥à±Óc§ÇN(üªð«Â¯`ÝŽu;ÖíÓÓÓØ3lϰ=à ý«ô¯Ò¿¿[~·ünÁ†FmhwòîäÝÉûßÝwúÊé+§¯À9Á9Á9< x/÷^î½777aý¼õóÖσôyéóÒç�ìˆìˆìHi;²g²g²gp¾õùÖç[ÃŽ¯w|½ãkÊ Ê Ê‚“O^t9€U±•§Ø.s€~‚~‚~èCõ¡úP°­i[Ó¶æoh Õ¨q»âvÅí‚···W—¯Ò”JS*M�6�Û4nÓ¢¦EM‹šI““&'M†Ó‡O>}ΩΩΩ {böÄì‰Plý±õÇB¥}•öUÚ.3]fºÌ„6OÛ3}fŸ§>O}žÂ§ã?ÿéxر)bSXæ[æ[æCë¹­ç¶ž —¶^Úzi+\m~µùÕæPË£–G-�ÒvGî¹gähSЦ M,µlÔ²Q0¯É¼&óš€ÎZg­³¡³ÐYèÌ‹ÅÂä .—‹Ë¡duÉê’ÕÝ2ºetK¸ºùêæ«›!”PB�àÁ ‚€é3Óg¦Ï€‹\äç'Ì÷ß�(d�@¼‚ã;¾ã;PÇ©ãÔq`YͲšåÏ–UU„(B! n·‹ÛA_S_S_ÚÎk;¯í<ȱϱϱ‡oR¿Iý&µô’B«Þ­z·úKØØØÂž•{VîY ¡ÏBŸ…>ƒzMê5©×äôûGïò.ïBq§âNÅ�À¾�};ûv¯°ýWFÕIÕ `Iì’X€§¶Om_aóPâ>qŸø³‰f¬fZÍ´š ¦tSº)½tÙn¶³�í€?þøSz¼þQ&L˜ø�¿ÿáÇ嵟óœçüçSN8á²Éþ%û<»úì곫°)|Sø¦pذkî »àÒ—Þ¸ôó{I~\æ{®8WœûÛã ¡B¨ ªzªzªz�¶1mcÚF8ïrÞå¼ x=ôzèõÚ^m{µí+¹WàÅßgØÓvO[€;^w¼^E»¿O™+УУУøé´3Ù™ìL¿½�Fë­o´¢â£â£â¡øtñéâÓ¯.gí:µë郞 c�1¢§GO�ž½“{'÷N†Ì™2@VRVRV”ë]®w¹Þ öûŠ}A¬&V«7¸Á�Ÿ5\ôÃêY�éLgà'8¼É›¼ êêêêê꥛W:Pé@¥PqDÅG@ï½Oô>ÍÿhþGó¡•±•±•ñ×÷K÷H÷H÷²dÈÓ†L2mtVuVuVÁÕÉW'_� \æ2—¡ùèæ£›�†âuÅëŠ×AÄ•ˆ+W xQð¢àE¥íÆ×�¯_†›†›†›`ä[#ßùD$E$E$�:O�§Î+]¾WS_S_Sä:¹N®ƒJ•*@µäjÉÕ’¡Oã>�û4†1-Æ´Ó*+++++ÁØÀØÀØÄJb%ñgCúâcñ±ø¸tùàŸ<æ1�öyüV?~cùáó® ×…ë¨ Tª íLÚ™´3¥›§uNëœÖìÚ/´_Î=�{:÷SkSkSk¨™S3§fÔ\QsEÍð¡ï‡¾úBÝNu;ÕíôÛãô}±ëw ß%|—>®>®>®Ðp}Ãõ ׃zŠzŠz 0šÑ¼‚›ÕÒ«¤WI¯)Å)Å)ÅPgf�™ufþñv_=‹zõª7«Þ Àf–ͬWØüSžò¨E-j•þ8ªZTµ¨jà1Ãc†Ç ðŠðŠðŠ]º.]—Æ)Æ)Æ)@9䀨Xl,6qˆC”þ}hLcƒ.†‹áü´ÙOÛÿpB757575/} ô'Z´hAl$6»ÙÍn`#ÙbG±£ØñgÛÿðsãXãXãXÙ²!dÌí<·óÜÎ0?|~øüpè>¼ûðîÃK_öâ1 2•ùùw?öã=Þ㽟=î÷C® IÓÓÓð[æ·ÌoTH¯�^!z ê1¨Ç øpÿ‡û?ÜaýÃú‡½’y(„ï„ïÚ?jÿ öíÚ·_áqñ•¹›K:”t(éòuòuòu`ý±õÇÖÿövîm¸·á^8·åÜ–s[`›Ï6Ÿm>ðžë{®ï¹‚"G‘£Èùý9m»Ûv·í�;v ÛY¶³lgA…7+¼YáMèb×Å®‹øMò›ä7‰Ÿ¾$WL®˜\L‡M‡M‡!®{\÷¸î|%øJðx0÷ÁÜsAqFqFq¢+GWŽ® 6Ø` œïü{ç߃Ó×O_?}úTëS­O5øÆæ›ol`yÇå—wŸ!>C|†ÀçÞ8÷Æ9ðJðJðJøßýµ¢VÔÂù¦ç›žo wÂï„ß ‡çCžy>Þ^øö·òÓ7׆® ]B³øfñÍâÁ¥·Ko—Þ`·ßn¿ÝþÒvï¿wüÞq¸:æê˜«c ¤wIï’ÞÐob¿‰ý&‚k×&®M Á”SL�½ù{ó÷æ—.f3¬`XÁ°Ø?hÿ ýƒ Ï.Ï.Ï|³|³|³ ¶}mûÚö�g�g�g ªªªïï﹇sç­­ÖVk ñAñAñA�””úýúýúýP0³`fÁLpLpLpü/ûK?T?T?¢/G_޾ ý,úYôƒ˜ƒ1cBŸV}Zõi;ê쨳£¬j¸ªáª†�3*gTÎ(–6,mXxŒðá1îõ½×÷^_8_ó|Íó5!ncÜÆ¸� k¡k¡k~çýÎû�‡÷ƒß~?”J¥ÿST»¨vQíàÈ£#�Ž<‚Ê«*¯ª¼ N §„SxuõêêÕÆÕW{\íÒ¡Þߪ¤MI›’6°©å¦–›ZBõ°êaÕà heÐÊ •ÀR–ò[.Eýé,Ã,Ãú–ô- u^]ë!³Cf‡Ì†;µïÔ¾S6^ØxaãH»�v!í =tôÐѸ:puàjN N N�m¶=Øö”••ÁÞÏÞÏÞâ¯Ç_�¿Ñë£×G¯ÙSÙSÙS¸ÓáN‡; ý\ú¹ôs Ï•çÊs!îhÜѸ£Ð8¦qLã8õñ©�O} åœÊ9•s‚TÿTÿTPÌVÌV̆³ûÎî;» 5 5 5 sræäÌÉ›››¦`S°)2¯f^ͼ &k“µÉ,4‹—¬Îú¼ñóÆÏCþ¢üEù‹À0Â0Â0&LO§?�þt:(†+†+†CT—¨.Q]ÀuªëTש`1Àb€ÅˆéÓ'¦tŠéÓ)6žØxbã X^ny¹ååÀg£ÏFŸ�ÐhQ£E��o´o´ï»kÿÅH µ©ý…ÿK™› ðÚ…k®]€ù;òwäÃ’°%aKÂ@a¡°PXüööRû¥öKíó´ó´ó´¼5xkðV¼cðŽÁ;Àþ=û÷ìßûýy >2|âDq¢8,ü,ü,ü@Ÿ¨OÔ'‚p_¸/ÜE±¢XQ %ãKÆ—Œ½“ÞIï¶É¶É¶É`©²TYª $£$£$tqº8]X7±nbݤô¦™¢õEë‹ÖƒÕU««VWÁî„Ý » Þ©Þ©ÞY:ô¬ÈVd+²AV]V]V®G]�º :tADágG•è%z‰^PîT¹SåNAõ‘ÕGV ÄC Èäò°¯h_ѾbéÍF?Î1¿û»Ýßíþ´nкAk¨|§ò�ÊwJÛ×ÌÔÌÔÌ•µÊZe ²õ²õ²õ`/Ú‹ö"Èãäqò8ÐVÑVÑV�âÁŃ‹ƒr�r�rX}`õ�ÕP¼¯x_ñ>Ð�Ó�Ó�‹ví,Ú�uEëŠÖA=F=F=¦tÈÑf¾Í|›ù ¹¬¹¬¹ â)ñ”xêÅ÷=›Y )ÖkŠÁxÂxÂx¢öGí�ÚYÓ²¦eM¡›ÐMèö³ýôÃ7&ûnöÝì»AHnHnH.X]³ºfu ¬tV:+Ø8Ø8Ø8€f®f®f.¨º«º«ºƒ"@ ûûûª Õ„j°6}múÚt000€�·Þx î~¸ûán?cüŒñ3à³ ŸMøl¨ê¨ê¨ê”N<ó“,²ÈY‰¬DVÁí‚Û·÷î;Üw€±¯±¯±/°šÕ¬…�ÂGáΓœ'9OÁ^°ìýñŸ5(kPÖ X5tÕÐUCA§Óét:ø$ü“ðOÂÁa­ÃZ‡µ¯ìÏÃ߆a§a§a'¨BT!ª0¶3¶3¶‹Š-*‚ò†ò†ò�DI ŠWÅ«âA›ªMÕ¦‚â ÅŠ7ÀtÚtÚt¬åÖrk9è;ë;ë;ƒÞAï w«YV³¬f�¸R\)®½‹ÞEïÖßYgýÈÒdi²4(ªYT³¨&X‡Y‡Y‡�x]¼.^CSCSCS�»È]ä.`t6:�Á¢‚E‹ `ñ¦Å›o‚ê‚ê‚êX´²heÑ ìfØÍ°›Üç>÷_ÒÿO Ÿ>�âÅ#ŠG”åÛæÚæÚæÂ‹ùW@«ÕjµZ°¬bYŲ ó„yÂ<ÐÍÐÍÐÍË>–},û€­ÂVa«M?M?M?PTT¹£ÜQî¶wmïÚÞ‹mÛ,¶™ûÓuÊ\pfÑ™EgÁÉïO~ò{˜¯Ÿ¯Ÿ¯Ù=Ù=Ù½ßßnò…ä É`徕ûVîí¿´ÿÒþ Þëô^§÷:Aõ¼êyÕó@ð<„_ñÍêïÂØÄØÄØ’|’|’|@›¢MѦәÎÏŸ®øášÝ9»svçÀë[¯o½¾y_y_ùKÖ^ØÞd{“íM@ÛWÛWÛ”¹Ê\e.ô°éaÓÃd“d“d“ÌÝû_OüJüJü RW¤®H]EQEQEQ œÎ ç~¶ár–³¼ô„_áD…N”Þ;ñ{ÍÚ=k÷¬Ý k¥k¥k]žuyÖå<øâÁ¾€‡ýö{ØFÍ5kÔ,Ðn×n×n1MLÓ~ÖP %”€pA¸ \“‡ÉÃN+œV8­øãûéÇâÆä“oL†o;øÛÁPéJ¥+•®ÀûÞŸðþp^å¼Êy•™>L‰äW3)MJ“£É@‘ªx…7ƒþQe®8rñÈÅ#áFÂ�„ 0k³æ‚ðDx"¼‚9¹U_©¾R}{Çì³w œÜ~rûÉíP§C�u:@wßî¾Ý}¡¢[E·Šn <ž OͽW^?×]t}ä~šûiî§ÐÌÐÌÐÌ5j:ü–§6$äìÌÙ™³îV¸[án0­3­3­Ë©–S-§BÍG5Õ|.Ý]º»ü…‹ï‡‡‡@LŘŠ1!üãð�Ã?†¸Ëq—ã.CO‡ž= ÝúvëÛ­‹ï,¾³øÎÜ{ó�0¤RöïÚ¿ ÀgªÏT€FªF*sg“¼:ª-ª-åå!ï…¼Ð\Ó\óGÚ}µÊ\°/x_ð¾`ˆºu?ê>LO™ž2=Á_xÏñÿH\ .@üÖø­ñ[aw�Ý5v×€‡Š‡Š‡ чèCôжQÛFmAP“ &AMÀ¢±Ec‹ß0QŒDòw¢}Sû¦öM¸»ïî¾»ûà¤ËI—“.ð,ìYس0hÞ8¼q8tóîæÝÍÊ·.ߺ|kJïbÿûû¡'§ŸœW9®2À°”a)ò‡ò‡æŽ(ùã2�2�ŽZµ«V ÜùrçÍ�­T™+v^Úyiç%Hl›Ø6±-|²ù“ÍŸlÞæmÞþóÞ×xÁxÁxž5zÖèY#8µåÔ–S[àîÔ»SïN×q®ã\ÇAÓ M/4½µ»×î^»;xÇ{Ç{ǃl¾l¾l¾¹÷žDòëzzzAüàøÁñƒávÞí¼ÛypÝæºÍuÐL×L×L‡Æo4~£ñz?ô~è}ðiàÓÀ§«„UÂ?zˆ_œ NÐE뢬ܭ^LÀ$-ÎõÏ âňNº°‡=8à`îh¥Ê\°¥ú–ê[ªCÖ̬™Y3a|¯ñ½Æ÷2C�n~Ëú$듬OàFñ�âÅp=ázÂõÈpÍpÍpÏÙž³=gC½.õºÔë57ÕÜTs”ïV¾[ùn`gmgmgmî½*)s6³™ÍP´´hiÑRHÍNÍN͆»–w-ïZBäìÈÙ‘³!§^N½œzàìì M*4©Ð¤ÔßUWý]àø/Ç9þËÜ�y�eMÌš ^ ^à•ï• pQ¸˜;[YT¸¿p?À“ož|PuQÕEÊ*Ê*æÎöÛ•¹`ý¦õ›ÖoM”&J£–ŽZ:ê5z|Èl6CF—Œ.] âVÄ­ˆ[p÷‹»_ÜýÒ+¤WH¯¶ŸÚ~jû)lذ‚š5 jAõ‚êÕƒòËo,¿,ß±|Çò�²ð�Jò*™všvšv‚öíÚ %<%<%ž|ýäë'_ÓOj<© ‰ ‰ ‰`ØdØdؾn¾n¾nP{DíµG@]»ºvuíÀu¨ëPס ÷’{ÉÍ8ñÉßÏÕçWŸìX´cÀ(×Q®U>­ò©¹³•EG3�f\x÷»’'$¸ßsÿ7‘›K™+VèVèVèÀâ‹O,>�÷—¾¿ôýרø%¦ý¦ý¦ý�]=»zvuHHH€ûïW¼_b'ÅNŠ�9×r®å\›$›$›$(ߤ|“òM à«€¯¾‚Š+N¬8Êo(¿¡üðððððð›{6÷lþ†°ä7ºÃî@ñÔâ©ÅS!ãbÆÅŒ‹�Q7£nF]HpKpKpƒ¸�¸�¸x>àù€çÀ�kÈ5ä‚Ç2�eË ð|àùÀóPsWÍ]5w�ïw¾ßù~΂³à,ðÓc€’?ÊxÙx Ã.ÃÀ¹ƒsÛ4Û´—m¯©®y1‘×<æXw±îbî>¼Î^L9×s®8õrê`áoñÒ{Š+W²…l;•ÝßøæÍ2W,þtñ§‹?�‡ÆC—\:ðoPü¢Ëû‹ýÅþ�óQÎG9Aü—ñ_Æ Ž Ž Ž[+¶Vl-x^çy�çu dTɨ’Q h¤h¤hT:QŽÇu�ë×Ák¿×~¯ýà'÷“ûÉÁµ®k]׺`sÆæŒÍ°�l;Ùvriá ß+ß+ß Øa‡�¹wÊ?XD€>H¤µ\-WËA=G=G=T‡T‡T‡àyäóÈç‘�x6ñlâYH�M�M�…ço?ûùÛ�÷}Þ÷y߃8Oœ'Îûö=ì{€g¬g¬g,Ô¨PüÞö{Ûïm¨Ô©R§J�ÀÑÊÑÊÑ ˆ%–Xsï É:›~6à芣+F,±À_í¯þ#íþS� <p¸ÑáFò'äøö9lîl¾2WÌ­2·ÊÜ*´(hQÐ"èÙ¥g—že BˆÄ Qj”%¨>T}¨úR¥4JiIÑIÑIÑ�œœ éƒÓ§†¬>Y}²ú€îMÝ›º7Af-³–Y—.*bßÚ¾µ}kp÷s÷s÷×O\?qý>wøÜáspôwôwô§IN“œ&�ó]ç»ÎwÁÉÑÉÑɬ.X]°º2­L+Ó‚ÌOæ'ó+�H¦”)eJ† Ã…á  ABЉNüŽ©kÿ4KXŠŇ`úØô±éc0å™òLy`J5¥šRÁoŠ7Ńé–é–é¨>V}¬úòšå5Ëkùóòçåσ‚zõ êAÁÞ‚½{¡À©À©À rss!ëDÖ‰¬PÒ¹¤sIg0:�Ž Îg‰³Àú´õiëÓàñ±Çǃ§§§§§'xúxúxú€oC߆¾ Ás›ç6Ïm¥¨XeYeYeQ:E´äo¦äƒ’¢ý£ýáÅ$×.=\z¼lûçªç*€‹½/ö¨s¬Î1€ÊÆÊ/Ÿâ;žxñ²x@ø^ø€Ã¼Úæmnˆ«Å#I/Ö0@˜"Lyéöá„\lr± @f§ÌN,:XØÜ°¹ñ²—¥%§%èëx·ðn Ÿ!ŸñJûóZ*3S›f›f›fƒz±z±zqéjRtùé.Í4¡‹ÐEè6Ø`ØÄØÄØÄ€+®¸!„òóD¨³ÕÙêl(lPØ °Ÿ)>S|ŠfÍ*šY1Y1Y1�Z/µ^j=Èž7P®T®T®/w/w/whP®A¹åÀm©ÛR·¥ ¼§¼§¼ÊÏ”Ÿ)?‡.]º€Õ`«ÁVƒ�¡ eèKŒF4âL0$yݼXÝêQïWmoL4&¤·Ooà³Ëgðÿ¦Ö/¥uѺ@é= òyòyýmúÛÈÔ²—Ž4$%<�| P'³N&€«Ÿ«ß˶ÏÊÏÊØQ´£ x~ð|€7‡¼9@ð<ÿíŸó9@Î…œ ú} €PK¨ÅáåãåÀÎPæ”™CKCKCKø´ý§í?mNv8Ùá$´<Ûòl˳æN÷¢G�˜À&”.’c¬i¬i¬ %·Jn•Ü‚¢”¢”¢(9Yr²ä$¨�«�«�ƒzƒzƒz¨Ž«Ž«ŽƒÚBm¡¶Ý1Ý1Ý1ÐÓÓmymymyPŸPŸPŸÍZÍZÍZ0l3l3l½^¯×ë!kFÖŒ¬pÁpÁpÁ-Z8´pÛ�¶;mw‚X]¬.Vù—ò/å_‚E‰E‰E �J*© è¦è¦è-&ZL   °ncÝÆº ØÌ´™i3,çZεœ –C-‡Z«T«T«T°icÓÆ¦ ؄ڄڄ‚mÛ6¶mÀ¦³Mg›Î`;ÅvŠípXæ°ÌaØZÛZÛZ—Ž´ÁB° Œ`¯`9a‰äÜáÅÔÚ:^¬îÙ˜—ÎGbØkØ pµÓÕNbU±*À¿Âÿ «#{éš;²vd¬m¼¶1À†¤ I•õ•õ/Û¾ðXá1€ë箟ðîìÝ ÚÇÕ>à·þí?®nøããw¶¼X}ñÅ*„’—*3€®‡®‡®L´˜h1ÑzÓû›Þß@S›¦6MmÌ�NòÊü¸,© ˆôŽôŽô†uÖXw.Z¸há"PUU-]œHØ%ìv��%d Y?k¯?ýéÿ³%Éïð°ÕÃV‘]#»ô]Õw€ü‰üÌÀ*ù}ÊÌ%1YL“Ax,<ƒ|‰|‰| 0•©L5w:É+óÉÿGñµãkÇ×�P�P�P°/°/°/(ýý�Ë”Ó�t0wx‰äŸ*xrðd€À�?�o”o4w&‰ÌÜþ*¦1¦1¦1`¼a¼a¼²²2é&§¼··7ðòôòôòüãíI$’ßCÞNÞÀò±åcšÑÌÜ™$e¦OŠ'Å“ ,– Ë@¶D¶D¶ÄÜ©$¶Œqã2Æ�W]¯º^uÍ�F"‘H^e§Ø#î÷€i­i­i-ÈöËöËö›;•äÏ¢ª¨ª¨ª¹Ñ¹Ñ¹ÑP±uÅÖ[›;•D"‘¼>ÊL`šhšhšÌb³@6G6G6ÇÜ©$–ÌØÌØÌXÐêõ�à¥öR{I¡H$f’´*iÀ…öÚ˜"M‘æÎ$)3€øT|*>å§ELdÏdÏdÏÌ�JògÉ�=:{4Øî¶Ým»lFØŒ°‘£“HÌ$黤ïÎ;? ÀtÏ$M=nveæ)ÓÓÓ0µ0µ0µy]y]y] �B Í�NòªeÞμ�yŽ GXhý¡õ‡ÀZÖ²ÖÜé$’²¦ö°ÚÃÞ x@¡T(Ì`sg+»ÊL Æ‹ñb<‡„CÂ!�õ—õ—IÏuÿc%´Lh™Ð¼ßò~Ëû-�·’·’·2w*‰¤¬RQùù¿’×AÙ¹0[œ-Σ§ÑÓè B+¡• �þqŒÑÆhc4¤_L¿˜~¼y7ò–¦º•H$’ÿPv €t1]L/]ýŒ (øÃÍJ^3úÙúÙúÙ�ß5¿k~Wð˜è1Ñc¢¹SI$Éë§Ì‚L� 2À ,Ì�Fòg)ÙP²¡d¨¬UÖ*k('/'/'7w*‰¤¬ÓtÔtȽœ{�®ý¿ÊL€øÃb8àXc�µ¹CI^µôö/V5S8(àÞ˽—{/s§’HʺÛooXýñê� ïÞ1w&I™)Ä(1JŒE_E_E_�È dÒ%€œÔoS¿Mýœ:;uvê 6J¥�ÒÜ©$’²Î³™g3€ºWê^��“�3w&I™)xÆ3ž�üˆüˆüȾ’}%ûÊÜ¡þ:†C�¡ÒW¤¯H_ùkó׿ÿ‡Ë¨•Q+£¸ãŽ; Ôêuþp³‰äñêÿà-«·¬d³e³Í�IRv €©Q£¦tÝú¿Ø­Ž·:ÞêW¢¯D_‰B %ôÏßsžç<ÏyÂÖ°8ÝòtËÓ-áöíÛ·o߆k“®Mº6 TóUóUóáÔ¤S“NM‚ýWö_Ù à à Ãÿúýõ[¥�L™><çxÎñ”fz”H$’_Tö 3Kn›Ü6¹-$$'$'$ƒ¸Z\-®þõ¯×¨4*� Òj¥ÕJ«´¢ÿåqFÝÝÝ_¾(|4šÑhF£ÐzZëi­§Aâ–Ä-‰[ ¡mBÛ„¶`3Ëf–Í,Èl“Ù&³ |»üÛåß.Ý{º÷tïANýœú9õ!_ÌóEsïÍRÚ.Ú.Ú.��� ~?ƒŸÁÜ©$‰äõUf&úõ¨G=oŠ7Å›�Þ%½KzÐ××—î.Ý]ºƒC¬C¬C,0�ỹÜ~¹ýrûAÑÇE} âNq§¸\÷¸îqÝ%”|PòÈÈÈ€©�©�©ض·moÛšÞjz«é-0›ŠMÅ JV%«’!§CN‡œ //ÆcŽ1\Žºu9 Ê}Ê}Ê}püäñ“ÇO­ž·zÞê c¢ÇD�‰·ûn÷ÝîƒPK¨%ÔÚІ6�³4giÎRˆ;w.ªªªª‚õiëÓÖ§¡™¾™¾™Lz“Þ¤A#h ¸Ä¸Ä¸Ä€¬ž¬ž¬Á*ù*ù*9ÔíU·WÝ^V-¬ZX5°Üj¹Õr+d®Í\›¹Ô>jµ¸œq9ãrì‚í‚í‚áùÏßxþXܶ¸mqLßš¾5} ö5íkÚ׃ڠ6¨Áeˆ2D�‹¯‹¯‹/0ŸùÌÿå�³Ø±Ø±ØTsTsTsÀ-×-×-×Ü™D"yÁ„éÅ¿wMwv ; 4w¶²«ì?Üý/;/;/;‡ìÙ²ƒ [.l¹°|‹}‹}‹Ák¦×L¯™Ð³jϪ=«BäÕÈ«‘WaOážÂ=…P9¾r|åxH´M´M´…:ß×ù¾Î÷‘‘‘ Éß$“ü Ô^ox½á¼"xEð HØ�°;a7\¼|ñòÅËðÉŒOf|2Æí·oÜ>hóe›/Û| •,*YT‚Üþ¹ýsûÈ3#ÎŒ8g£ÏFŸ�†˜1-bZÀ“EO=Y.^.^.^ _,_,_ ¦¶¦¶¦¶�è’è’è9-rZä´€¨žQ=£zBí�Ú!µCàÔÑSGO…k+¯­¼¶6MÙ4eÓ…D!„]Â.a¤^M½šzŽß;~ïø=PÔWÔWÔ‡úƒêª?ââââââàDË-O´„òÃË/?²S³S³SaxÎðœá9ðUׯº~Õr–ç,ÏY!Y!Y!YP{oí½µ÷Âãk�¯=¾ÉÆdc²fœ9pæ@P ø¯k±¶X[¬±™ØLlŽFG££H%•TstIY÷´ÞÓzF<Ðmn·¹²8Yœ¹³•]e§°ÄK—‰ËÄe€-¶ØÂ…E]XÚ/µ_j¿„> û4ìÓ …B¡ÃdÃdÃdØ8uãÔ�S¡î³ºÏê>ƒÁ÷ß|RÆ¥ŒKúúú� OÐ'è!sbæÄ̉0ðÐÀC�E‹€E,bq=âzÄÊ)?¤ü°i5Òj$4ŒiÓ0Ñø‹Æ_À`§ÁNƒ�àñ'�?yü T¾RùJå+ h¥h¥hÍŠš5+úÏîÊ&É&É&AH¯�^!½Àk‡×¯•³*gU΂gÍž5{Ö N}pêƒS€h#Úˆ6@ $€8H$¿H¿H¿H(÷¼ÜórÏ!´ehËЖPa~…ùæÃg ?[øÙBèà×Á¯ƒtÜypçÁ0(zPô hx|âñ‰Ç' üíò·Ë߆¯¯/xgí;kßY âuñºx*¨t ÒÐxj<5ž o(o(oø¿?Þì³?Ìþ,¶[l·Ø¡¡Á½‰ä×(²*²H½Ÿz@t�Í�IRv €BÃÃÃ0F#ŒÐË£—G/X¼rñÊÅ+aäᑇG†¾î}ÝûºCûík´¯)>)>)>Ð¥S—N]:•6ë½Ä{‰÷’Òÿozjzjz 6�mÛ4§·œÞrz‹#`&~º=]Ø$l6ËYÎr~™/‰—ÄK`]Ùº²ue°‰·‰·‰‡,ë,ë,k�µ“µ“µqš8Mœö+úýãÄGÇ9Îqà׸Ìe.s)�!Œ0€ÛÜæöÿnG<$�±‘±‘±$^L¼˜xnl¼±ñÆF(Ì,Ì,Ì!LÂ@þ©üSù§ 4š ÍÀömÛ·mßÇ›Ž7o–¾�S7§nNÝ~ûÇ›à™à™à åüËù—óÛDÛDÛD³q‰ä'5ËÕ,Pybå‰r¹\š ËìÊL \® WAØ*l¶‚ñ{ã÷Æï!0(0(06 Ù4dÓ¿~+ü,‹^½,ÞØüÆæ76ƒò]å»Êw¡PW¨+Ôý—7úa¤�v´£ÝK~ÿã w%+YIéój=éIO&„ `êdêdêÚ m†6ìOÙŸ²?™2d³˜Å@ozÓû¿äÑ¡CÂa€0ˆ'žø—ìŸÕÂja5Ѓô ´`YÆ2–Dìb»€L2Éa†0C˜Îí�Û;·‡†£Žj8 Âv†í Û ={&öLûÇö�íÃ-ñ–xKs˜Ãÿ™C¢ ц€©’©’©Øl·Ùn³�ŸFl~IúÝô»éw¡¼oyßò¾f9Ä$É/²ÚoµÀ «?XÂ’?Мä•(3OÈ>•}*û„ B¡ˆÞ¢·è ûî컳ï\œqqÆÅ «)«)« UrªäTÉå)å)å)èZܵ¸k1\H¹�r!ÎÆŸ�?‘±‘±‘±�ù óAæÈ>™}2û$dŸÊ>•} c c cÀÔÞÔÞÔR3R3R3 Cþ†ü �Y1³bfEÐûëýõþÝ1ºctG88÷à܃sÁù ç/œ¿€zwëÝ­wœ>rúÈé#ˆ½{7ö.Ü(¾Q|£ŒmŒmŒm~ÖáCâS}J¥ƒÒ&.˜¸`âðxÓãM�7!ìNØ�°;à8Òq¤ãHÐkô½xÎsžÿ¬¿�yÌclÁÆå�Ë—ž.ž.ž. Þ©Þ©Þ U×V][u-Œ >*Œ;�;�;¡ÚØjc«�…Q_ŽúrÔ—`3Ãf†Í ˜æ>Í}š;ÄLˆ™3 û û û` ï@ß�¾q-âZÄ5(*)*)*«3Vg¬Î€ÖVk«µ…ö¾í}Ûû‚&\® Ãdž� —Ænº§éž¦{ ¤CI‡’ ?*?*?úË«f™f™fä¨sÔ9jð™ã3ÇGzþ_"‘Hþ'Aü�¹ƒüÙ ?)ü¤ð˜ºcꎩ;`¸ípÛá¶P3ºftÍhóå*©WR¯¤ô|»çÛ=߆ñúñúñzh3µÍÔ6Sͽ×^)}Sú¦ô…ëg¬Ÿ±æ?šÿhþ#ðhèÑÐãWÜ<(‘Hþ 9696™þ™þÁ‡ ›;[ÙUf.k…µÂZ0ùš|M¾`R˜¦×`ü#Ù6Ù6Ù*XU°ª`i Ò¤5ÃJÃJÃJs§{ýe É’5lŽØ±9vvvÒÉkæqÓÇMv­ÞµÀèl”ž0»²SÌæs@^,/–ƒé¤é¤é¤¹SAÐÌ ™A3aý±õÇÖƒ�]vØ!ŠEˆ¹Ó½þ²’³’³’Á¾»}wûî`=Ýzºõts§’H$ÿ®Jd•H€. º4�—7w&Ékðø¯ñã„6¦|S¾)L‘¦HS$à…^fÌÕZh-´ZÓšÖæÞK?I±I±I±àõÔë©×SP\W\W\7w*‰DòïÊå”Ë(G¹?ØÁsg’”�`¼0^ò•ò•ò• ˆâë0T<žñŒ‡øòñåãËCž6O›§…ZGj©u×××ÌòõcJ6%›’!õZêµÔkr7änÈ]à(G9úG[—H$’¾²s X‚Á´ß´ß´ŒaÆ0c˜¹SAôèèÑÑ£á›YßÌúf\­}µöÕÚ B…êW¼>{xöðìáðU÷¯ºÕ¶lØ`î^ýùô³õ³õ³!÷«Ü¯r¿�b�b�bs§’H$’¿�2SȲdY²,�EÉ¢dQ`zßô¾é}s§‚kS®M¹6Ô½Ô½Ô½`°Ã`‡Á ¡¡ñ¿_ï¶Îm�Û:(¹Sr§äÜly³åÍ–æîÕŸïÇÇ.K• *Ï=ž{<ÿãíJ$’?ƒ©ÈT/æb †sg’”�@&“Éd¥7×éºéºé~Ç”³¯Šj¹j¹j9<^ðxÁã�\�\�\i)i)i) †‹áb8<òäÿÈ.'\N¸œÃ"†E u#u#u£Òö¬|¬|¬|@vEvEv¥ôç)ÇSާ‡++®¬¸²"zEôŠè%'JN”œ(Ý.Gž#Ï‘ÃõÐë¡×Cá¦ú¦ú¦ŠÅŠâ×ðBQZ½´ziõ@¶V¶V¶Êm)·¥Üs§’H$/ùYägkÚ¯i`üØø±¹3IÊN� K�%€¥`)X  ]£]£]c¾<†Q†Q†Q ËÔeê2AwCwCwÔ#Ô#Ô#@»N»N»Ž·:Þêx+È��;!wl<·ñÜÆsÞ&¼Mx›ÿlWh%´ZA®³ùÌb®Å\‹¹‘§#OGž†ô+éWÒ¯@Á„‚ `±j±j± †> } gcÎÆœ��µóÖÎ[;ŒþF£¿ùö×ÿ—23efÊLp~Ëù-ç·À.Ó.Ó.ÓÜ©$ÉËY¾kù.€Ã ‡ALd¢¹3IÊN/‹—Ń¥h)ZŠ Ù¦Ù¦Ùf¾<2™ƒ |}}Áw†ï ß’’’ÖyÖyÖyÐçAŸ}@Ç®»vì •ÄJb%îº;èî —4¼”¥,ÕÕÕxØôaÓ‡M\p�®[»níºìììáa«‡­¶‚{ìy°º ì2°Ë@hÚ,´Y(œªwªÞ©zP¸¡pCáóí¯ÿ/mSÚ¦´Mà~Ãý†û : �„N¼]‰Dòg¨>½út€¾}-äNr'sg’¼†ƒ»aª0U˜ ––– ½®½®½Néâ7æ’K.¹ Öë‹õKœ¼5ykòVØ•¾+}W:8Ìt˜é0noº½éö&ð™à3Ág?Íùÿ#qŽ8Gœž=7zn„ ·&Üšp v÷ÛÝow?84þh>ûø,¼ÿìýgï?ƒF_4ú¢Ñ &‰IbÒÏÚ±Ç{n7„ m¨m¨mu—Ô]Rw l~¸ùáæ‡àpÉá’Ã%8øÖÁ·¾N{�ö:í… ©R+¤B¯£½Žö: ãú�ë?®?|‘ôEÒI ŒTF*_ƒ¿ÚEí¢v�ô–é-Ó[‚ŒŒ¿t3‘D"‘üfefàG?®Ö«}¤}¤}Ô¤&5ÿú%gKΖœ…¤Ô¤Ô¤TH•§ÊSå�””¾u|ëøÖ�óÏÏ??ÿŽÜÍÁ&Î&Î&âóâóâó€ŠT¤"ÈkÉkÉk_ó5_ƒ»µ»µ»5¸wvïìÞ… ÌX6FM4°Ä‰ÿX¸ pA 8Ÿp>á|â7/‘Hþ)ò9@B«„VM¶7Ù +'+gîleW™+6ÜÙpgÃPŪbU±0º×è^£{™;•ä×:~,üX8\8záè…£0ï£yÍûdõeõeõÿxû‰äÏpuÉÕ%çMçM“ZLj h h`îleWÙ»cc…Ó §NzÑ ©øÛH(J(J(o…·Â[!�ø%’¿‡;jìð¾í}@ž#Ï1w&IÙ» ðŒÕ«3 ›®›®›¬f5«Í�Jòk¥mNÛœ¶¼W{¯ö–>7‰äoÂ!Â! ¢©¢ @p¤å€Í®ìvVvVv  Ó†iÃ@ôýD?s§’ü/Å·Šo߂̭™[3·B@ý€úÒ7‰D"ùÝÊ\`}Ðú õA0  Ök‰µÌ�Jò¿d,ÎXœ±ŒÇ�Ç�ǡ¢ ‹*˜áæM‰D"ù§(s€åW–_Y~º]‰®¨K]êš;•äI·K·K·û¡öC퇂]»vÒcÉßDÉÆ’�Ï«<1ÿJ-¤/^fWæ «`«`«`ÐöÒöÒöÑWô}Í�Jò¿Ä5Œk×¼›x7ñnV:+�•ÎÜ©$ɯsÐýA›‡n `8f8fîL’2WX°`=ô½F¯±®XW”FÌï‡üM-M-M-/¼ðÓÓӈ߿+~T^QyEåæ+‘H~›òóËϨV' @vPvÐÜ™$eî1@«»Vw­î‚Þ]ï®wSSSs§’ŸŸŸÂ¦üMù›ò!õpêáÔÔ””1-bZÄ´€FµÕnTŒ��AÞYÞYÞÙÜé%É %ÕKªDΊœ Z¨Z +’Èä gΟ9 :ˆ>>•*àƒ�¹ûòÏWæ ëëÖ×­¯ƒÉßäoò­�ÖGëS:E°ÄOŸ§ÏÓUÓUÓUà!y¶ù¶ù¶ù ¼¦¼¦¼®]ºßS¾§|O�çUÏ«žW¡ü½ò÷ÊßÏ‘ž#=G‚ínÛݶ»�†4¤¡¹? ‰äÏ"îwX~gù€ÍE›‹/Û>'>'`e••Uü ~€þ–ý-äZ¹öß^PH!À¡§‡žÄô�éP;°v Àã �7|øö‡oÈÏËÏÄëãõkŽ®9 öiا-µxé½>ªîªî»–îZ `ÿ™ýg].w¹  x¦xfî}ýú+s÷-„B °Üe¹Ër¨+©+©+™;ÕŸOÌsÅ\(®Z\µ¸*dÔȨ‘Q¢NF�Œ: Ñ!Ñ!Ñ!�Ú.µ]j;ЯүүåUåUåUp™á2Ãeø¤ù¤ù¤Aµ¡Õ†V N›œ69m'''pNvNvNå`å`å`°ªmUÛª6]„.Bv »…Ý@?úѨHE*‚ÐUè*tñ�xH<yyy`gogogò&ò&ò& n7ŠAWOWOWŠ7(nyyyPм yAsÈ�7 o<{ö< b¾�ù6æ[¸Ztµèj”Ü,¹YräoÊß”¿ ž O…§ªÖ¬Z³jM¨q¹Æå—Á3Ë3Ë3 î:Üu¸ BO¡§ÐÓÜŸ¦Dò{E�‰°¡Ó†N}?èûÀ¼ñÒííÙ/x;àíÇZ޵ä'ä'^ú:µíÔ@|(>0T0ThTÔèÅŒ€½ä½~þ²JC* ˜Ÿ9?@øHøè¿õC1Q1 ’g%OC-ËŅÒIÿo¯»r3  £  Ù¡f‡lÚ”Á¿Ì�üh¥×J¯•^`1Ñb¢ÅD>vøØáÿ„çPW°‚PìPìPìj=¨õ D" xòÍ“ož|†C„!<¿õüÖó[¨Ú¢j‹ª- JA•‚*àý¹÷çÞŸƒr�r�rX9X9X9€pG¸#Ü1w';qž8OœÚrÚrÚrPbWbWb©bª˜*BÌØ˜±1c!ºFt�è�‘‘2™‹Ì[¶ l R¤6H…šÖü°æ‡àpÃá†Ã ` X`î^JÊžœé9Ó­|´ ú‚ê \†¹ {ÙöyEyE¹ýrûTØTa€µ»µ»¹ûòW¸PéB%€ˆüˆ|€m´(^>ÜÜÙþze¶ø®ïw}¿ë ÏO>?ùü$ŒÏŸ3>ÇÜ©~;S?S?S?ˆõ�õ�õ‡‹\üàâpË÷–ï-_Pø)ü~P}EõÕW@á ‡6 ¾ù~äû¸|ïò½Ë÷ Üî ÷ÌÝó�‰ÇÄc�ÿMþ7ùß@âèÄщ£!"'"'"¢ÞŒz3êMÐ^Ó^Ó^ƒº·êÞª{ š5jUTYPeȯɯɯ™»7’¾ÓgNŸ¸øùÅÏÞ�|? BA…sg{�‰ßŠßï ï`Äø²ínö¸Ù ýNú€Öï·~@9Y9ÙÜ}øãÊlpÄûˆ÷o¸1âÆˆ#`f§™�fvYMYMYMs§ûe†Ñ†Ñ†Ñð¨Õ£V�ZÁÁ÷¾ð}ˆ�;?v>TVuXÕaвzËê-«CÍ5Ô\6ímÚÛ´dÈÊÞ­Ÿ¯Žæ‡{œF?Œ~ Æ_a<c=ìuÛë¶× ®·¼ÞòzKèÛ!¶C,t íÚ%¬ ­ ­ Í�Vòúˆ_¿àéŧÞøä�OìkÚ¿Æ#“ƒ£Á`·çnO¿¿€Fg� ¯áM†e¶¸wõÞÕ{Waì ³6Ì‚yOç=�÷ìãìãì͸*UþìüÙù³a]Áº‚u»(vQì"viØ¥a— žXO¬'‚ÐRh)´4÷^”üOKX¸¿éþ¦û›`�n�n�< = = áà Nøp¸Mp›à&ÍG!‘üM//œxr @æ´ÌiÏ< Û&ÛfîŒÿ©Ì^ ¶­Ek — — —Á`c°1ؘ/OþðüáùÃañòÅË/‡â�Å‹7œªsªÎ© õ[ÔoQ¿…tâÿ­L L L @;A;A;Ä‹âEñâo÷WÇ8ÆA­µÔz³·ÏÞ>{;ȪʪʪÂÛ¶ l!Û!Û!ÛÁÜ{KòçË¿‘@÷¦îMsgù0a†þ†þ†þ ‹ÐEè"€Hø+ƒÈ›Ë›´¿Üþ2@ÿ¯û ¯ë‰ÿGe¶° ³ ³ CCCóº9º9º9°®ýºöëÚƒm;Ûv¶í`⬉³&Î÷'îOÜŸüïvŒ#�#�#!:(:(:îÕºWë^-0ùš|M¯àÚa±g±g±'DµŠjÕ 4�5�5�!MŸ¦OÓõÍ×6_Û ù±ù±ù±¿ÜNÑÝ¢»Ew!ªNT�¨: }¤}¤ýõÑ~¬ýXû1쪼«ò®Ê°ø»Åß-þâ†Ç �»<ìò° Õ.ª]Tr«æVÍ­ ×ß½þîõw!}Wú®ô]¯>—K}—ú.õaìÙ±gÇž/¥—ÒK «¬Z°j¨k¨k¨k¼ú÷•˜[Êê”ÕŸWû¼@ÜŒ¸¿½UgUgUgˆÐDh"4�Ð2¡eBËW—2mHÚ�´!ðÔö©íS[Ðí×í×í‡'›Ÿl~²n�¸=âöÐ_Ô_Ôÿ—B:Í6Í6ÍžZ>µ|jùâʸø'Ü4—1>c|ÆxX³wÍÞ5{aýùõçן‡Ìa™Ã2‡ÁÃj«=¬Z£Ö¨5BâÑÄ£‰Gáúþëû¯ï‡’+%WJ®¼ÊD‚�à ¸¯¸ÿêûûªý_{÷Eµ÷qü3»Én’MϦ��JB º€éU�^A¥ ˆ‘"ˆå"E¥H“* Ò!ô"Uz/¡†$„@éÙlʶìîó‡záQ¹Š{¹9ïx½6“9¿sfÂ~wgæœRbbbÀüŠùó+`}|úøô�@C !ЎÇ9Ö²–µpÆýŒûwX¼2xe0’ I†$]º(tL¸?áþ„ûàââ&“ƒÉŒ?4~ú$}’>éçÈ ›�Žt¤ã_�ÔüÔüÔ|ÈÛ�·;o7× ®\‚ׯ ^ã_ÿúø×!âZĵˆkà³Âg…Ï poäÞȽX:X:X:<ÜŸ5Ök�}]}]}]0¬1¬1¬bˆ!æïŸÎ;ìü1¼ñà�o<€Ã£�:< |pðÁÁçp" ÏI`¯À^­Þoõ>€½ÙÞüä{qºítÛé6¨•j¥Z Æ·�oßccc0l4l4l^åU^ÓVÓVÓV0Õ7Õ7Õk�µÀZ¦ö¦ö¦ö`zÅôŠé å(-Ç·ßr< ,;°ìÀ²àÐÛ¡·Coñ ñ ñÉ_ò—üÁ¼Ë¼Ë¼ ÖE¬‹X¿=øíÁoÁºÎºÎºZ�i5¦Õ˜Ÿg%x$GÉQrc}c}c}0Ž7Ž7޽J¯Ò«ÀTh*4>ùxĈ?#Œ0oÞ,¼ÔªZ«j­ª0¦`LÁ˜pè6Ðm '''�ýDû‰öùùýGîÒ7¯4¯4¯|¸Jl‰ªDU¢J(¡äiœ§sOçL•O•”|QòÅS<ÍžP©› øWNr'¹“':Ntœ9Ós¦çL~íŸ3œ3œ3€ª¢ª¢ª"DÞˆ¼yã)ìxÛØY5³jfÕ„­Ã·ß:¿úþj(Û¶lÛ²m¡ZrµäjÉ0Û~¶ýl{Ñ}D÷ÝÁþ{ûïí¿‡/{ÙûËÞ0j¨ £&€}Sû¦öMáË_ŽørŒœ6rÚÈiPij¥©•¦‚”)eJ™P8¡pBáصo×¾]û þõø×ã_‡ R©‚5ðö�·AsSsSs¢VF­ŒZ 'Ê�(w¢ômÞ·yßæP‡:ÔùÝ/h]к 5\�]�]�ARó¤æIÍaOù=å÷”‡¨³Qg£ÎÂìe³—Í^¯¾Zøj!´£íÙ�4@ k¸5Üvlرa$WJ®”\ Œ¹Æ\c.¼2õ•©¯L…F4¢Ñ?8l“#&GLßßß8ÕàTƒS  �èô|NIáb�e�e�·Žß:~ë8¬ö\í¹Ún¿~ûõÛ¯CÓð¦áMÃ!ghÎМ¡°ÑþEûÁ¿öükÏ¿öÀùù9Ú|hó¡Í0¹ýäö“ÛÃ�óÎ8‡:ê|¨3|üeð—Á ¹In’ÛÃS¥4JiKG,±tD6‰lÙ###àÆ¿nüëÆ¿àH¥#•ŽT‚¡aCƆÁŒÈ‘3"!*"*"*¨Le*CjßÔ¾©}a´Çh�Ñà½Ä{‰÷’Ç÷?ùXò±äcÿjü«ñ¯‚b¥b¥b%¿|üòñË`-¶[‹aÙÌe3—Í„OZÒú“ÖàÔØ©±Sc ‘DA:#�‘΀f¯f¯f/¬¼¾òúÊë`lglglÆÎÆÎÆÎðF·7º½Ñ ‚cƒcƒcÿÉ‘«1»ÆlS¦)À2Ë2ËvçQ©ý@~J~J~ T%ªU ä•É+“WæùµMsMsMÓ"¦EL»•v+íV>…7§9ÍÁÇÕÇÕǺé»é»é¡÷ë½_ïý:lß¼}óöÍ�ýSöOÙ?AvAvAvhWiWiWAÄ•ˆ+W ó­Ì·2ß‚üåùËó—C¹oÊ}SîÈè™Ñ3£'hÛhÛhÛ<ü²¶µ¶µ¶·¦nMÝšB°1Øl„Èj‘Õ"«AÓM{4íå_.ÿrù—!Ý;Ý;ÝÌÞfo³7Øo±ßb¿J®—\/¹½Jz•ô*�<Àí펿ð¸œË—=.{ æÑšGk…°„°„°xuÁ« ^]ëT¬S±èÒtiº4Ȩ‘Q#£ÆœGäGäGàÚ›×Þ¼ö&l Û¶1 úå÷Ëï—u^©óJ�W`ñ«‹_]ü*ýy}�#s”9Ê¡Â>¨ð\7\7\7üýý ÿÛ¤áÒpi8TŒ®]1úéw¤ßh°ªÁª«`‰y‰y‰8 p·­·­·­': � � �„¤±Ic“Æ‚,[–-ˆ�…! CB¢O¢O¢˜f˜f˜fmiK[°¦XS¬)Þxã 4Éh’Ñ$ªÖ¬Z³jMrrr€„c ÇŽ�çÏ9žs@§‰ÓÄ�sÿæþÍ¡ŸK?—~.psí͵7×Â…‚  þ¼ÿ¡ C†6„ò£Ë�.?ê(ê(ê( zbôÄ艱0baÄB¸~7ün8kŠ5Å�6H¤G¦ü•©d*™ ¶þkë¿¶þ îÔ¼SóNM9e䔑SÀxÁxÁxÖÝYwgÝ�§qä¼ý½ýÚUoW@á¯ð·ÝyTjÀ¯\2]2]2¡à�‚7 žã„ ; vì×®\üóýýÛ/SÕIAR�²BY¡¬‚{÷ î îÉîÉîÉ�ŸŸ²YŒ,¤[Ò-éH“¤IÒ$�õ“õ“õéªtUº ²Ñ²Ñ²Ñ {Sö¦ìM~¾ru‰Ÿ×þÒ @Z!­�V€4Eš"MY†,C–ÒYé¬tdkdkdk.ª#k(k(kR ©…Ôd!²YH“¥ÉÒdpþÒùKç/Þ§«« K..¹¸ä"Ìí4·ÓÜNðCÇ:þЬQÖ(kȇɇɇ�4L& yyy 3�é ÒHi¤4$wÉ]rÿý0JIR’”i÷Òî¥Ýƒ´OÓ>MûŽ•9VæX¸9ÿæü›óAÓAÓAÓJz—ô.ù—n~Ë-Û-Û- Ë–-, ¼Ë»¼ûlÏEáY0757¸5ëÖ,€â¦ÅMŸâî]^tG– K�%<|¹ú¬ê³ªÏ‚¼áyÃó†CVë¬ÖY­A~F~F~¤•ÒJi%ÈNÈNÈN€Ô^j/µ–°„% í“öIû@ê u�:<¼´ˆ#F �B .ª&U’*I•@~@~@~àa²]²]²] 5‘šHM@j.5—š?ü»—w’w’wçƒÎ�‚Ýq»ãvÇÁ8Ì8Ì8 §&NMœ s?œûáÜaN¯9½æô‚éÒ¤?ÒÎ"Ù"Ù"�5�5�5xøº´MÚ&m{ØÞ¯ý¦ˆ" êR–”%eÁ�n|pãÈLÎLÎL†½.{]öº@vvvvv6dÏÏžŸ=ÿ©¹C8S÷L]€øyñóžâyñ„DøÑåG—AÛBÛBûËqÚì´Ùi3Î)œS8ç4@À8Æ1ŒõŒõŒõ ävÉí’ÛàÒÒ¥¥KKà~à@�ÿžy�@ äß×1aÂÄÏŽF€TEª"UyøºTN*'•ãß_éဠ‘†HC–eµX-V Pžò”ªP…*€=öØMiÊ£ÿQºãŽûÃÕíœíœíœÁ?Ø?Ø?Êö(Û£lðK÷K÷KdMƒl²É©µÔZj 8ãŒó#ûýõ£KðȨQ£~8räÈ—•.+]VBX·°naÝ Uv«ìVÙ0#jFÔŒ(p6:��ÿü°î*ÜU¸ œÞszÏé=`‹Xô ÎáÓ�Ñ�XrhÉ!€Ä’ħr ùvØaÇÿó_Ž,Y8ñŠxE<8h4à3>ã3NnÅŠ¨Nuªn¸áÆ¿Ï{©¡ÔPjxá…ÿ~ÜŽú¿,øëö¿þýv¡ ]©ï×í£‰&ðÀ ,e) Ô¦6µÙ¾1�i Üà7Ài Ó@§�PöÕ²¯–}Ê.(» ìðœä9ÉsÒ#¿÷KRK©¥Ôò‘×ý,Š(¢ø÷=ÿþì׺ùÀdßо¡}CðªáUëD„E„E„Áàƒ #rFäŒx*kÅXMVÀá�‡$¼�ðöSäù��ÂÓ¦¼©¼ Ю^»z>}žâM�ö}íûÚ÷…¢ÊE•‹*ÃÀ�aÿàýƒ÷†¨ÝQ»£vCùºåë–¯ Fo£·Ñî̽3÷Î\Ðh4`|Ëø–ñ-(ªVT­¨hkhkhk€®’®’®h 5…šBÐŽÓŽÓŽÝ@Ý@Ý@(’É‹ä`_ξœ}9Hž04îw�;äœÿqþÇ`¨n¨n¨ùÕò«åWƒº?Ôý¡î +£+£+lb›À'Ù'Ù'Ônj7µÛÓ8rÒOÒOݼ»yÔßZëóN©� øWG_;úÚÑ× Ö7Ö7Ö¦wšÞiz'°kcׯ®Í³oã¢�‹6.‚«�®vºÚ b,1– ¨|U¾*_[�Žð¬éêꬹ³æÎš þeýËú—…>3úÌè3¨D%*ÙºJAþ•úK^#½Fz�„¢�¢�¢ÐéŠtÿànî'Õ¶¤mIÛàc>æcø®Üwå¾+†&†&†&¶áY1éL:“~8÷ùÎ�æ¶æ¶æ6tÐq@Lj7þÿ]Ó™`TU–æ–æ¶.IxvŠºu(*SôŸ2û«J}pŽwŽwŽóióióiЩt*�êùµï4ÄiˆÓTkP­Aµ qKâ–Ä-0gᜅsBÁ·ß|këQž–â ÅŠ'À¢r‹Ê-*/]¼tñ 9·¤[Ò- ø†oøÆÖ£&<©Ûñ·ãoÇÃg²ÏdŸÉàέ;·îÜ‚1•ÇTS¿ ü*ð+[W)<{r“ÜP5¦j €®†®€y‘Y<íñ?Dî'÷ˆ¾} öKµ_²uM¿'€›ÂMávj;µ�t7t7tOcF¾¿Éo‘ß"¿E0.|\ø¸p¨âUÅ«ŠüËù_Îÿr†3VÌX1r·æn͵áݣ¦‰ÕÄjbaÍŽ5;Öì€O?ýôÓO?…‡‡˜¸i⦉› pEàŠÀ¶®Vxþj_¨} ûáî‡äSäSl]“ðô¸Ut«Тf‹šðóe¶®é÷D0)L ÈÎËÎË΃î–î–î–­«UwUwUw跢ߊ~+ Æ!Æ!Æ®Ÿ¼~òúI›46ill*ÞT¼©òÆç�ÏÏ¿§ž“8âˆmOmOmOغ=t{(ŒÝ0vÃØ pnƹçfÀ{9ïå¼—ï^}÷ê»WÁµ¯k_Wqwiöó¼°‚ŸàÏÏÉÿNò¸äqgÎ$ÀÏëóÙºôÒì�Û7€MÇ7Ș7ÐÖ5ý}¥v-€_)’IŠ$PtStStƒ¢~EýŠúÙºª‡$�¤‘4P•ªT>U}ªúTg<Îxœñ€í—·_Þ~önÜ»qïF¨ëQ×£®DŒ>}ÊÍ,7³ÜL°Ûn·Ýn»­{óâ3eþÊü$7Hn�ÜŽ÷:Þëx/8"þD<8�p:átºevËì–ùpÞ§žN=�zÚºzáÅ“?'ÀÆÓO¸Öw­P±cÅŽ¶®­4ºÒçJ€ÛSoOh6¶ÙX[×ô÷•úðë"7¿>÷ž«ÊUå>Ç›Ÿ”C‘C‘CÑÃÅgê�­w¶ÞYˆsŠsŠs‚Cñ‡âÅÃôÄé‰ÓAí¡öP{@­:µêÔªµSk§ÖN?o?o?opòsòsò~äG~´uïþ |Îç|º£º£º£�á•á•á營~~8œ¿qþÆù�^7½nz]ˆèÑ=¢;ô[ßo}¿õP£{�î5ºƒƒƒƒƒƒƒ­;#¼øªß¯~ ‚K»Æv�ÿÓöù­ò[è4: €ºšº€Ýb»ç¸Úé‹ãç§¿ mTÚ(€ÀÄÀDÇ9Žÿ†ÖB š½×ì=€=Zô�^–^¶uþ¾R?À¯f}6ë³YŸ�ë@×�®¡¿oßþ/àsø–8Kœ%²œ³œ³œáÂÌ 3/Ì„³ûÏî?»R‡¥KŽï:¾ëø.”K)—R.*¹Vr­ä ោþ øÕñ«ãW”¾J_¥/È^‘½"{P¡â¿8 =Ö/SƒZb-±–X0~jüÔø)d4Ìh˜Ñ§$NIœ7Þ\xs!$êõ‰z(º\t¹è2”ñ,ãYÆj{Õöªíµ«Õ®V»ø.õ]ê»deebù^ÁæŸ:| `Ó‚M †·Þ  üëå_ÿÃ_˜Ílk k ©²TÙÖ}øG~yÌÒÒÐÒ@–,KøÿËþ>´ûÌî3{ûïíc�±\ ¸fë®<{"ü⻽ßíýn/h&j&j&¨3£ÎŒ:c몞Ë`Ë`Ë`ÈZŸµ>k=¤ÌO™Ÿ2®œ¹ræÊHè�Ð!¡äÎÏ�Ÿ;yŠÁ}À§•O+ŸV o)o)oùO;!ÏŠáÃ;™Ç3�xMðšàôºÓ€{Ÿßû`?/’ר»±7@ÍA5ýaƒ `:h: ÿXþ1€ì ÙÓ]Lm8ÃŒ½�?/²õË…Jñó�PBÿßö£ °)hS@º}º=@¿%ý–¨.¨þð1Km[m[€’µ%k˜|M¾&_°Ýþuû×AY ,P€Ë&—M.›.&RsÍý5÷CàÔÀ©�S!haР…à1ÇcŽÇ�U’U’U²È"ËÖGMž”r±r1ðËZ^N•¬J6@iVšÿÓöúú ®,¸ —‡ ýhèGòÉòÉô{—ú\êpüÊñ+¯9½æPöxÙã´ýƒw¼° Â‚ Q‰Q‰�·wÞ ½'½÷ÿ~!‰$?³Ÿ@ÝHÝÀ~Ÿý¾ÿÔ×]®»þÿ ¸>åCò_L€_¸×r¯å^ V¬(X–.–.–.WƒûŸõë²¢&™If‚‹ã/Ž¿8âNÆ�Œ; Ÿ…~úY(¼Tþ¥ò/•óÛæ·Íoƒ!Ç�cÈckckck0Š E�Û/·_n?È Ê Ê ‚ÂÖ…­ [Cq¿â~Åý@¿@¿@¿Jn•Ü*¹æíæíæí`þÑü£ùG�ÛËíåö Ÿ!Ÿ!ŸvûìöÙíe%e%e%pÊuÊuÊç=Î{œ÷€Ç;ïx¼žöžöžö ,¯,¯,Š E�"èa‘'Êå‰<\Åì>÷¹ÿÈ8´§=ím}0áyó\æ¹  #ÿÒöУУm7·Ý `J0%ÈîÈîü§ß³7Ù›8Á éséóÿ´½ûP÷¡Ý¢ºEx;{;ÃÏ ÿá/la À˼À—äŸ;q à—{_î}¹7,¨¹ æ‚šðÍžoö|³?*~T”‚›ãŽn=ºõèVX¹ rA$ n?¸ýàö}#úF´ çEAž�R?À¯¼ü¼ü¼ü äZɵ’k =¯=¯=o몞½SêSêSjøvË·[¾Ýoû¿íÿ¶?D‰>}ÄÖÕ ‚ ÏŠ¿poíÞÚ½5C 1�'Ï“çý÷~Ïù=ç÷ÀœŸæü4ç'ès®Ï¹>ç éõ¦×›^¼ñÆÛÖU ‚ ÏŠ¿PlSlSlG‹£ÅÑš*š*š*¶®êé»Üår—Ë]`ÖüYóg͇ž=#zF@«f­šµjÔ¦6µm]¥ ‚ð¬‰ð ùUùUùUpÎrÎrÎMš&M“f몞žGn¹qf¤ÎH�‘ �:têЩ´Kk—Ö. ˜Å,fÙºJAáyà¿Näâlv6;›Aó“æ'ÍO¶®êŸ»»ã;`Æç3>Ÿñ9´¼ÙòfË›ÐiI§%�–€,T*+Ï» ‚ ÿŸ¿���÷Ñî£ÝGCÞñ¼ãyÇÿñnm&Ý%Ý%ݦ{ún¨µ¦ÖšZk û©î§ºŸé”tJ:eë*A[à7|—û.÷]™�3g6zÓ›Þ¶®ê¯Ë+ŸW>¯<̰›a7š5 jýÜû¹÷sûJö•ì+ÙºJAÁÖDø õõõÈ?’$ÿ˜N™N™^€OÊEó‹æ͇Y/ÏzyÖËà¸Êq•ã*zf虡gÀÁÎÁÎALû$‚ üB€ßp‰u‰u‰C5C5C50ƒŒOcûgÄf3„Á¼éó¦Ï›:‹Î¢³À¨ £.Œºª©ª©ª©¶®RAøo#Ào8ëü­ó·`eeÆ{Æ{Æ{¶®ê÷LMMañžÅ{ïyx³ß>ø|àîÝ'ºO´u•‚ Â+ñ¥ðo¸^s½æz LɦdS2è.é.é.�xغ8Àz×z×zV½úëÕ_C\J\J\ Ll7±ÝÄvà³Øg±�X÷[Aø"ü†Û}·ûn÷A™®LW¦C–>KŸ¥•¿Ê_e»º¬C¬C¬C 6!6!6~ þ)ø§`»}ìö±Û!P¨TÛzôA„…¿á4Ûi¶Ólpí2Úe4<0<0<0@QDÙ°®}íöµÛ×bÝbÝbÝà}ãûÆ÷�P^]^]^¼ñ ‚ OHÜðžË=—{.‡ì·³ßÎ~Ûvuœ¬~²úÉê°2ceÆÊ ˜20e` ÔhZ£i�¦¶%AáE%¾x õRõRõRÈVd+²Ï¿ý+þWü¯øÃ‚á †/½›ônÒ» 4 lØ0ÐÖ£#‚ ¼èDx ïºÞu½ëÂóóóók7aÂþ„ýðµõkë×Vèð~‡÷;¼­•­•­•¶Aá…¸ðe>,óa™!onÞܼ¹ Oÿžþ½g×ÞÝ#w�Ü=Ó¦M›6m4oÞ8:]ît¹Óe[�† ‚ð¿F€Çð>â}ÄûèƒôAú ((SP¦ ÌÓoçþ¼ûóîσ©û§îŸºj­=´öPx#ö�Ø7bA^W^W^×Ö£!‚ ü¯à1œv9írÚò�ò�ò�PðrÁË/?½ýg¼�ñvÆÛ0¥Æ”Sj@Å£�V< ý×ö_Û-Ø«íÕöâî~Aᑬ¿°u!ÿm4r�\#‡±²±²±2h©n©n©åååÈÑçèsôÐá«_uø Ü/¹_r¿E9E9E9À4¦1 TÓUÓUÓî7·anÃ܆0Y?Y?Y¾|7øn€á>Ã}†û€£ÊQåhÃùA„ÒA€_ܺ~ëú­ë°gž {&À%÷Kî—Üa_¥}•öUK-K-K-(t-t-t…J©•R+¥Â¦ðMá›Â! J@•€*°jϪ=«öÀŽ“;Nî8 Ó‹¦M/7½›ÞMS›Om>µ9¨^V½¬zFùŽòå *‹Ê¢²ØzA„ÒB<ð‹ÔC©‡RÁ”ÎS:Oé éo¦¿™þæã·X° `xtòèäÑ Š,>;‡í¶s¬KZ—´. ´ µ µ ¡úçÕ?¯þ98¼éð¦Ã›ðžã{Žï9Š7~AÁ6Ä=¿xEþŠü9¼±è�Eo,úóí}Ûù¶ómNV'«“®~ýóëŸÃ¡)‡¦šòp»ÝºÝºÝ:Xzýéõ§¡~›úmê·WgWgWg[÷ZA(­Dø…|�|�|¼Óé�Nït‚jöÕì«ÙÿÁ†§8Å)ðÏðÏðÏxøòõõ5dÆgÆgÆ?²ýHF2’’’`䀑F€­Ÿlýdë'`ɵäZrmÝ{A¡´à7*Œª0ªÂ(8fà˜�cÀAí vxän|•·Ê[å a«ÃV‡­†ûƒîº?~<òã‘�€u¢u¢õ�–áíE/zAÞŠ¼y+ Ñ-Ñ-Ñ ,Í-Í-ÍmÝkA¡´à1zDöˆì M¶4ÙÒdËÃ׎9s8�%�%�%plî±¹ÇæÂå¶—Û^nûÈÜpà \ǸŽqo´{£Ýí`ãW¿Úø¼÷ò{/¿÷2Ø]°»`wÁÖ½AJqàcxõôêéÕF„�g÷ŸÝv?(++ƒç<Ïyžó`ÎÔ9SçLãwÆïŒß�£³£³£3¼¼úåÕ/¯†a]‡uÖš7-nZ .¸àbëÎ ‚ ¥ž¢ÉŠ&+š¬€v[Ûmm·Ž=rôÈQ¸´ôÒÒKKád¥“•NV‚jUªU©V¥J”݆uÖm¨‹ÕÅêb[÷BAþ?1ÀŸ¸YöfÙ›ea𗃿ü%œò;åwÊB7‡nÝ MÓš¦5Mƒ÷»¾ßõý®Ö7¬oX_À„ “­«A„?&îxœªT¥*¬²~Èú!pøõï~ôMõMõMávÉí’Û%ÐîT»SíNAØëa¯‡½ŽxãA^"<Îæ0ìííÿc;/;/;/�GË£åѶ.VAžŒ¸àqÓ˜ÆÐã\�s=ÎÁ¥J—*]ªÇ Ç Ç Ð§_Ÿ~}úÁKá/…¿nëbAáɈ{þ¢sŽçÏ9¢7½¹èMø‚/øP/R/Rÿ…™AΈøà/rôsôsôUeUeUePtUtUtµuU‚ ‚ð÷ˆðYÏYÏYÏ�Õ`5X @9äe)KY[W'‚ OFÜ(‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ð¢ËXÆBÊî”Ý)»á²ù²ù²Jv”ì(ÙaëâA„…/˜[Ën-¨¥p÷.KIDAT»µ –6_Ú|is8’}$ûH6ÄoŽß¿ôXÐcAÈNÈNÈN€8Ç8Ç8Gø´þ§õ?­·æßšk¾­{!‚ ØšOJŽ9 !!=ÿæ�·8Þâx Ð×Ô×Ôׄ·Ö¾µö­µàæêæêæ N“œ&9M;;; ‚•OT>Qîº?èþ (Ž,Ž,Ž„ëæëæëfÀGm=¸‚ Âó"À_$5‘šHMÀ¼Ä¼Ä¼®æ^ͽš w]Üuq\u¼êxÕδ9ÓæL(2™ŠL_Ÿ¢OѧÀ•”+)WRàtáéÂÓ…�¸>q}âz°¼fyÍòÚãÛ×uÑuÑu�›UoV½YR‡¦M K2–d,û(û(û(ˆÔFj#µ �“ÎIçÀÑßÑßÑì7Ùo²ßæææ°î•u¯¬{æ š7hÞ Hú*髤¯Àêmõ¶zÃý1÷Çܧ矞z>\Ñ\Ñ\Ñ€±ØXl,†{Y÷²îeÁ§ Nœ áÄ>„ĉ€5Äb ±õQAÇÎÖ¼0üðÃdQ²(Y¬ë°®Ãº�ÿnþ»ùïB»þvýí`Ùée§—�†&G›mrÞÔ¾©}S +]Vº¬tívívív(ÿVù·Ê¿ë—­_¶~¼zêÕS¯ž‚&4¡É4oüÔø©ñSÐ-Ô-Ô-ÝÝÝÈ?�:ÿ4”l)ÙR²>lðaƒÀ' ?YøÉB¨·¾Þúzë�V´¢X�Z�Z�Âõ¸ëq×ãà¾Ó}§ûNPì[ì[ì ·¿¿ýýíïa^�y=æõ€Zµ2jeÀ%å%å%%ÔïX¿cýŽ n¦n¦n1>1>1>зRßJ}+�Ê_å¯ò‡À�€%J[;AáwÄ7‘u�u�u (¿S~§üÔáêpu8¸Ww¯î^4*hTQŸF}õ)ĵ‹k×2ó2ó2ó`ÇÑGw…V Z5hÕ:Duˆê‘ŠHE¤Öç­Ï[ŸÖýÖýÖý¿oß­Š[·*20d`È@ ƒšN5�j:APvPvP68f8f8f€u¶u¶u6ÿþjßú™õ3ëgà´Êi•Ó*È È È‚°ýaûÃöCÕŒªU3à¨óQç£ÎPP¥ JAèáÐá‡Tz§Ò;•Þ��Ñ;£wFƒ_ ¿~-ÀñÇwß�–A-ƒZA©‡ÔCEEE[5AáqDxRf̘=zôÀ*V±êá�¥FR#©XNZNZN‚>SŸ©Ï„bm±¶X NÝ�º;u¸½ûf÷Íî›!¯R^¥¼J`mkmkmûÚÏ!‡°Ö²Ö²ÖúýÈ'Ÿ| ?ýéÿðå¼y-òZ@rTrTr,�[·<î�¿7þÞx¨P! BA ''ö~ö~ö~àPÑ¡¢CE�VJ+¥•¶>X‚ ÂãˆKOJ† àŠ+®Àְ摟{à�H ¥†RCp<ïxÞñ<8rä< îÜ/¸øã�?dk³µÙZðŽõŽõŽY5Y5YµÿÐþ¯û_*-•–½èE/À€H½¤^R/`£RH!H]¥®RW�"¥H)èNwºƒ¹›¹›¹ÛÃÝ{FyFyFAØõ°ëaסO`ŸÀ>� ¸¡¸¡¸ñ°½Dy¢Á}‚û€©�©�© ¤*R© p›ï6ßm>¨T*x`|`|`÷D÷D÷DP;©�ÔN�T1©bREpüÆñÇo "!"!"²eÊ÷Çß<(UJ•R¾�|;ùvÃ%Ã%Ã%¸¿âþŠû+Àÿ�ÿ!ÿCPFWFWFgë£%‚ üþ¢«9Ws®æÀÓÓ|–õYÖgYàZÕµªkU[W'‚ OF\xR,Xl]„ ‚ ü3"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"üER{©½Ô$³d–Ì@ÊPÆÖU ‚ Âß#Öø�U�ª@óZÏk=¯5ÄÿQüG�Ÿ–Ÿ–ŸñÚxm¼²·foÍÞ vkìÖØ­�–mZ¶iÙzlë±­Ç6��‘�‘�±uoAá�‰ðNŸ9}æô$:$:$:ÀòZËk-tÕ½*T¡ \ç:×y[y[y[hx¶áÙ†gÅ¿ ‚ðb—~C>Z>Z>:èp Ãp~ßù}ç÷¿}ùäòÉå“¡QÝFuÕµuõ‚ ‚ð׈µã�é�é� Ú»¶wmï çõçõçõ¿ß®ßõ~×û]‡¥­—¶^Úd)²YŠ­«A„ÿL|𾡾¡¾¡Ð|UóUÍWýþ犗/)^‚ví"ÚEˆ7~AáÅ"ÀcÈRe©²ThòZ“ך¼^2/™×#£UqzÅé§Cí-µ·ÔÞbëjAáɈð'êΩ;§î¨Ð¥B— ]¾Þhr£É�&CзAß}kë*AáɈ§~µ‘�lëyëyëy°ÚYí¬và¶Çm�ÛhÖºYëf­áZĵˆkЬQ³FÍ�ì#ÙG²�À²Ï²Ï²$wÉ]rI-©%5J(¡¶îœ ‚ üÿ3Àl ¶ƒ6H¤ ‚¼¢¼¢¼"Ð&i“´IP[[ š“š“š“�œœ ùó+æW�‹ÎEçFÉ(%(YR²¤d ð Ÿð Ül}³õÍÖ`Îþœý9Ø_e•ýUàÂù ç/œÙW²¯d_�}Š}Š} (f+f+fƒj¸j¸j8¸[Ü-îP‡«ÃÕáà–ê–ê– ÎùÎùÎùàVÝ­º[uð\ã¹Æs 8}äô‘ÓGÀP†2ÔÖ£+‚ ü¯ù¯ À°Ì°Ì° òßÏ?ÿ}xÐâA‹- áX±„c�ŸŸAAA ™©™©™ $“L2(¿S~§üì?·ÿÜþsPUTUTUÏž <€K´K´K48UqªâTÊ;”w(Š]Š]Š] /‘—ÈKÀàcð1ø@VxVxV8 0XÌbƒ¹•¹•¹C�¡ÆPÐètPt£èFÑ ÐžÑžÑž�Ü͹›s7ƒ~´~´~4kkk€a²a²a2(ª*ª*ª‚G�:uÀÿ´ÿiÿÓá–pK¸¼»zwõîú0HȳåÙòl[-AáEaó`íkíkí š›š›š›pÝåºËu¸žw=ïzÜê«ÿ­þ ¦¦vövövöà÷™ßg~ŸAЦ MA›  s@ç€Îäää ÑÑÑ ôQú(}@aQXP¬T¬T¬Ù@Ù@Ù@À<þB¡é¤“œá g€–´¤%à€á÷äG~óóó0Œ`TUFèVéVéVAæ¥ÌK™—àÞü{óï͇Ôz©õRëÁ]Ã]Ã]dgegeg�ì{Ù÷²ïÁ;Ø;Ø;*&TL¨˜‘ªHU¤ "ÖD¬‰XNó�æ;ÍV³šÕ¶:Ê‚ ›ç\pÁ2»evËì—¢.E]Š‚3µÏÔ>Sî�¼7òÞHpã4Æi „�>ªfWÍ®š AÊ e�¼Çz�õûð«udÈJíŒÖ¥Ö¥Ö¥�¿6mþZÈX”±(c$•K*—T®.¹ºäêH™–2-eHU¥ªRU_¾4|)ÔÛToS½MÙ6²md[pñsñsñ³u¯A[yfÀXÝXÝXnn»¹íæ6ø1óÇÌ3áfß›}oö­‡ÖC u:ÖéX§#TWUWUWAèêÐÕ¡«Á~‹ýû-@MjRÓÖÃô˜ÊT¦BQrQrQ2Ül{³íͶpAvAvA—†^zi(XG[G[GC­ µ*ÔªÍï7¿ßü>Nœ8dI²$Y’­;#‚ #ûŒì3^Þóòž—÷€ìCÙ‡²m]´ ‚ðwýå é¨é¨ésÍ4wdÈ8�qÞÕ¿«WUõUõUõüû±8áÅV2¢dDÉØ×{_ï}½aÍ»kÞ]ó.´Ò·Ò·ÒC÷sÝÏu?ö*{•½ÊÖÕ ‚ OêO@þ[ùoå¿ÓÚLk3­ 8ìuØë°†í¶gØðLóLóL³u7^<æ¹æ¹æ¹�äšäšä ÖvÖvÖvPa]…uÖCÂ[W QDÜŠ¾}+fš9hæ ¨=¸öàÚƒ¡_r¿ä~É ’Ƀl]¬ ‚ðW=öºk‰µÄ ‹‡/¾x8¨T*•JD}õAÔ“¿ñgÎÉœ“9¾¼þåõ/¯ÃÁï~ðû§×‘ý1ûcöÇÀ–k[®m¹E�‹:u†�»6îÚ¸ ¾™üÍäo&ƒ¡¦¡¦á?‚ ³õØpdú‘éG¦CæñÌã™Çah­¡µ†Ö§÷œÞszïÉR_Q_Q_�„š 5j•cWŽ]9öô:b?Å~ŠýPvRvRvÕfÕfÕfp˜î0Ýa:ìÛ°oþ `ºmºmº wÛÞm{·-<¨õ ÖƒZ÷£˜¯˜¯˜Š­Š­Š­<³Ç÷®Ù»fïð›à7ÁoôêÑ«G¯ Ë”eÊ2Ÿ^;ª}ª}ª} tR:)�`ßÔ}S÷M…’Å%‹KþÆ¥š² eÊ&ÀÐC; í{çì�³w¤´Ki—Òîé�“ ‚ðlü.EEEÁΑ;Gî ¯^3¼fw?w?÷0qŒl‘l‘lØÏµŸk?2×f®Í\ —k\®q¹Ä9Æ9Æ9‚ÞSï©÷„c‚1ÁW†_~e8WWWÀ­š·jÞª Wf_™}e6ïïï@À[o¼A#‚F�xØ®Óm§ÛN·A¶X¶X¶²ò³ò³òazÎôœé9°}ÝöuÛ×Aβœe9Ë  f@Í€š|0ø`ðAÈKÍKÍK…³ýÏö?Ûnt¸ÑáF8·îܺsëàÖ«·^½õ*àƒ>>¹“s'çN†[n ¸5RÝRÝRÝ ½Wz¯ô^pîö¹ÛçnÃåj—«]®úKúKúK�ì`ÛØ†E†E†Ep-æZ̵¸ãvÇ페n˜n˜n@Âü„ù óáR—K].u�ÔZ©µRk�ì�ì�ìЋ^ôúûÇ3r\ä¸ÈqP½yõæÕ›Ãö˜í1ÛcžîÉ)‚ <;¿ ñoÆ¿ÿ&˜BM¡¦PˆêÕ#ªÇSlñ{¾ç{(Š+Š+Šƒ¬È¬È¬HX•°*aU¬l¿²ýÊöpLwLwL‚'Oý!ý!ý!8QåD•U`‚Ç  wÐ;èàXçc��u†ñ•ÇW_ô)ú} °œå,jQ‹ZÎEÅEÅEhFjFjF‚Áßàoð‡£ÙG³�fÃGE|Ù²d€± Æ6ÛŽ}wì»cßÁ­n}p똰yÂæ ›ávÈí�Û!Þ}ÝÝÝÐÿ ÿAÿHR�ù³ógçφVTXQæ†Í ›–K‰¥Ž.;ºìè2ØSeO•=UÀzÕzÕz6ÝÜtsÓMHšŸ4?i>üXþÇò?–‡tXÐîW¼_ñ~EÈß�¿;7�C9€+Oaú§Æ>�}ûÀµ©×¦^› y²«™*˜*˜*€] »v5žA‹w¹Ë]`6³™ýðeŸ²>e}ÊBQbQbQ"èVèVèV€tN:'�œp‰þÉU�X7[7[73™ÉÌÿ°½9rà*W¹ lg;ÛAê#õ‘ú7¹ÉM�ý ûAö?üüñóðáâ¸b¤)F‚1;bv<ò¹õ¤õ¤õ$X[Z[Z[>|½jZÕ´ªi@_úÒv¶ÙÙfgú:èë ¯¡xUñªâU°Ç´Ç´ÇÞ ¼x7•§ÊSå ¹s'æNïsÞç¼Ï=Ò�_îæÚ¤0)L Yª,U– ¦Ž¦Ž¦ŽO¿Aáéú]ðOóOóOƒœWr^Éy̳ͳͳÿήà /¼x¸šÞ/’“““““ÁËÎËÎËÜ�îFw#”L+™V2 ¬/Y_²¾(Q¢ééé �@3fÌÀ V°ˆ ‚ˆG^_ÈBõ¨G=°î¶î¶îK}K}KýGêû%`H+¥•ÒÊGöß�ntÆ0†1<œ"w0ƒ £Åh1B�{uîÕ¹ÍúhÖG³`‚ÿÿ þмGó͹”"Õ–jKµAZ/­—Ö?|Ýãs�Ï=>‡º“êNª; ÖÎ_;í|¨Õ³VÏZ=¡f»šíj¶ƒXßXßX_®\/¸(†*†*†‚K+—V.­ ¯A^ƒ¼�ôë—U ¥yÒ$}”$—$—$ƒóç1Îc ´Fh�ÐÀ|Á�4(iPÒ Ð[ô½||| 8¦8¦8›6 l¹³sgçΆüåùËó—C™ì2Ùe²A§Ð)t ÐLÑLÑL�à’à’à0Þ4Þ4Þ„Ô¥©KS—B™OÊ|Ræ0X ƒòÝòÝòÝÀ5È5È5´=µ=µ=A½T½T½\’\’\’ yJò”ä)à=Ù{²÷d”¥@ ¤ R©Âïû_P¡ BAH I I »ùvóíæCXrXrX2¨š«š«šƒ©±©±©1d~�ùuæ×°4`iÀRÐËô2½ òìóìóì¡Ìƒ2Ê<Ö²–µ`Z`Z`ZIõ“ê'Õãaãaãa°¯j_Õ¾*KŒ%ÆKKK—a.Ã\†=ùqÌ=Ÿ{>÷š|4.^¼xñâE�Ê e…ðŠêÕ+*hZ¡i…¦@=P=P=ÐÖ�Ažµ§~Ë:É:É: rëäÖÉ­çcÎÇœ��£�n<ºÒÇ¥�Kµ†0„!¶îœ ‚ð¼<óð8æqæqæq�~:ýtúi¸™q3ãf\¨s¡Î…:�Ò)¥SJ'(ÙT²©døûûCðÜà¹Ás!bqÄâˆÅà7ÅoŠßðlíÙÚ³õÙôìÚ´;hëá}yä‘úïôß鿃¼Ny�ò:Aκœu9ë Mž&O“CÂO ?%ü÷‚ïß †¼Ì¼Ì¼Lpvvvvv†ð¯Ã¿ÿjׯ]¿v}(7´ÜÐrCÁ³¶gmÏÚ 5�H þy¹‚ ‹Ífà±:әΠWéUz¤ø¤ø¤ø@âáÄɇ!iBÒ„¤ po꽩÷¦BÁÉ‚“'¡d{Éö’íà|Öù¬óYPWWWWW¯ê^Õ½ªƒÇh�Ñ£ÁsˆçÏ! ÎRg©³Àm„Û· ,T* A¾\¾\¾äÊ?”R#©‘Ôd'e'e'A:/�—΃eŒeŒe X/[/[/ƒ¥¡¥¡¥!˜˜˜@‰¥ÄRbÝÝÝÐ8iœ4N�}*ûTö)ÈUä*r ±j¬+dÇdÇdÇ@NpNpN0è_Ó¿¦ ”””À½Ž{÷:º#tGès s sƒˆmÛ"¶A™žez–é vƒìÙ ºÐ….¶>˜‚ «ÿ¾ðg>á>C+C+C+(ò*ò*ò‚‚áà †Cª*U•ª‚´Vi­ÒZAöÛÙog¿ o�·Æ4w5w5w¡èZѵ¢k`hlhlh ÖUÖUÖU ##’BRH �&I“¤I`èaèaèÚ•Ú•Ú•àµÉk“×&�]‘]‘]Ë6Ë6Ë6°.³.³.ËËË��“�“�Ç•Ž+W‚sŒsŒs ¸¹¹�Ç1�cÇÀ»�wï>h 4ÁÏËÏËÏ œ—9/s^ª»ª»ª»`7Þn¼ÝxÀgœm}0A„Õ‹þ!k'k'k'Ð÷Õ÷Õ÷ÃÃÃ0L4L4LS9S9S90�2�2�i·´[Ú ×¢®E]‹‚u××]_wÞ_òþ’÷—€ëb×Å®‹AVAVAVìß°Ãþ PtPtPtåååPÎVÎVÎåDåDåD –Xbm=‚ BiUêÀßu­úµêתÒo–|³äø´Â§>­®¾®¾®¾¶®NAžŒ˜¼÷/²°°«Áj°€L2É|ñEAá#ûç»AáE#€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$Àoe“M6�Fi_–¤0) ¤÷¤÷¤÷*T�ü^ $zôèmÝ AAøÏ$ë/l]È‹b»b»b;Øí»Ûw·/dh3´Z¸ï~ßý¾;œH=‘z"ÚMh7¡ÝPöQöQö�ª?Tý¡ê-EKÑÈ&É&É&Ùº7‚ ‚ðÇDø c?c?c?è?¨ÿ þƒà‡ú?Ôÿ¡>°—½ì¶³�íÀ+¼Â+ ;&;&;³[În9»% k;¬í°¶¶î… ‚ ügâÀo(–+–+–CK]K]K8;;­hE+`.s™ t£Ý ¨jPÕ ªÐplñ ÇÚºzAAøkDxŒhÏhÏhOjÔ,¨Ùã·«q§Æ�w rbåÄʉ¶®ZAþ#`nÀÜ€¹ÐüBó Í/üþçvÕìªÙUƒW­¯Z_µ‚¢XQ¬(¶uÕ‚ ‚ð׈ðŠÅŠÅŠÅÐħ‰OP�Q�Q�yøó ø ø xh0£ÁŒ3l]­ ‚ <þDƒ 4hC#†F }øzÃà 7< ¡ýBû…ö³u•‚ ‚ðdìl]À»2õËÔ/Sš:6ulê   Ð*¿U~«|PÎWÎWηu•‚ ‚ðdž{¸k¼k¼k„ý¡ûC÷‡‚1ŘbL©—ÔKêeëáx„„„²Ã²Ã²Ã ¹¤¹¤¹v'ìNØ�€[Ëo-¿µ-^´xÑb°JVÉ*Ùºèß³¬´¬´¬¯W½^õzÚèÚèÚèÀå„Ë —¶®NA°•ç>Àކ;îhßzëý­7´­Þ¶zÛê`ýÎú�õ;[Çø‰Ÿø Š¿(þ¢ø H�I�I��àQÁ£‚G�Ü,7ËÍÀu®sÝÖÅ>ÂwÜA_[_[_t8Ðá@ø¦Á7 ¾iáêpu¸ÚÖE ‚ ¶òÜ¿°¼ayÃòTÝUuWÕ]0dÒ�IC&“˜ÄñÌy–w-ïZÞS¡©ÐTJ‹Ò¢´»ØÅ.[W÷xEYEYEYpåê•«W®‚5ÝšnMÔ¨@¡Ô÷üE²Z²Z²Z D‰`';ÙiëªAáïO‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B/l°¦ZS­©�¹8sqæb¸àuÁë‚äÏÈŸ‘?t t t àfÓ›Mo6ÃjÃjÃj[Wýä4ÿÒüKó/¸}1úb4¤I?’~ÄÖU ‚ /º60ŠQŒ�QcÔáÃ}îûp\èp¡Ã…�>+}Vú,˜7vÞØyc!gLΘœ1¶.úÉŽŽŽÁK¿XúÅRØþýöï·oëªA„Ý ¬·¬·¬·À´Î´Î´bbbÀQã¨qÔ€ù˜ù˜ùM š4 >vøØácðYí³Úç‘o̘?0�AgÐ�ù{ó÷æï=zô�´WÆZÆZŒc�c�cÁènt7ºƒåˆåˆå‘Oâ–ÖÖÃ`ô3úýÀ4Õ4Õ4˜Â¦€e‡e‡e˜CÍ¡æP°ô±ô±ô�K‰¥Ä¬`+€�ù˜�Á4×4×4ÔoªßT¿ î¹î¹î¹`~Ãü†ù [AáE÷ÂÌhz×ô®é]زyËæ-›!¹qrãäÆàºÔu©ëRÈÞœ½9{3H_J_J_BbNbNb|=çë9_Ï�Á!ƒC‡€z”z”z¬,\Y¸²”½”½”½@}B}B}zÕéU§W0Ž3Ž3Žƒ�u6ÖÙX´•´•´• xLñ˜â1öZØka¯A�¼y=ò`}ùõå×—‡Ô¦©MS›BþæüÍù›áå/·x¹„î ݺ¾nøuïBÍ÷k¾_ó}°¬¶¬¶¬†n»Mì6âfÄ͈›gLgLgLàÝØ»±wc¸�q;ãvÔñ¬ãYÇÓÖGCAxѽ0ßœ>qúÄé°±pcáÆBè5¥×”^S wãÞ�{7õ~õ~õ~°N·N·N‡PïPïPo¸Ÿr?å~ ä‡ç‡ç‡Ã�âÅŠ!nGÜŽ¸Ðç‹>_ôùêm­·µÞV�o—o—o‡Í 67ØÜ.Lº0éÂ$èÿzÿ×û¿}ä}ä}äà¶Ìm™Û²‡õï Þ¼_|eð¨1²ÆÈ#aÅÇ+>^ñ1¨·ª·ª·BÊK)/¥¼Î&g“³ Z,m±´ÅRH›š65m*Ì�›7?Z·*nU ýÇõׄº†º†º‚¥ÐRh)´õÑA^t/L¸ÞçzŸë}À#Ä#Ä#Êf—Í.› öÉöÉöÉ µ”ZJ-�<àÈ_’¿$ dñ²xYÌ�6wÚÜiP©C¥•:Àøã;Œï cÆ&Œå<å<å<(©]R»¤ö#uô–zK½Áî»wìÞ�k×®ÀäÚ“kO® ªxU¼*¼'zOôž,e)KÖñïeƒÏr–³�ì7NŠ“â€A b°ˆE,zdœqƨD%*Ùúh‚ /º&T-ªZTµ4:�N£ƒKÕ.U»T ²‹²‹²‹ÀpËpËp Š»w+î…µ kÖý6ý6ý6(îZܵ¸+¹väÚ‘k�¹ sAæh’Ý$»I6¸^s½æz LËMËMˡѵF×]ƒëšëšë¸1ãÆŒ3 Ë1Ë1Ëô3õ3õ3!ÿëü¯ó¿†¼!yCò†@ðõàëÁ×A}X}X}Œ)Æc ô)èSÐ 2ƒÌ ƒÂe…Ë ¹„Ò$¤IHpÀàÔW§¾:õä\ιœstMuMuMAwNwNwÎÖGCAxѽ07Ö)©SR§ú¥ôKé—Ç'Ÿp|” .\&Ýjt«Ñ-P,V,V,†äÓɧ“OC½µõÖÖ[ ¦–¦–¦–à<Ðy ó@8×õ\×s]A'‹“ÅÁЃC=Ök„Âß 'ü�í’í’í‚ïxçÀ;àeõ²zY¡rDåˆÊPe]•uUÖA×Ϻ~Öõ38xþàùƒçÁéªÓU§«Ð4¦iLÓHé•Ò+¥Ô�­[?JÚ”´)if…YaV@Ⱥ�u!ë`”ý(ûQöpöÒÙKg/�¦¢¦¢¦"T{©ÚKÕ^¿Ù~³ýfƒ¡º¡º¡:(£”QÊ([AáE#Yñ¼ܶ`Û‚m à䮓»Nî‚)Û§lŸ²ÝÖÃð¿«(«(«( †^zuèUøÈû#ï�¼!¢JD•ˆ*¶®NA°•æ€ ‚ O�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P =ÿGq@EÙºû¥€ 2 �4Ò€d’I¶uQ‚ ‚­=÷©€´Z-\Œ¹s1Æ{xìa Íhfëáø¢B… ' ' ' oTÞ¨¼Q`ï`ï`ï´§=ím]¤ ‚`+Ï}*àœ-9[r¶Àå —'\žú]ú]ú] u•ºJ]m=ÿC¬X±‚µ³µ³µ3xä{ä{äC�5vÔØW®:\µu‘‚ ‚­<÷ ‚ ‚퉛A¡ú?aî #˰.zTXtcreate-datexÚ320°Ô50Õ54 14·2°´26Ò60²20Aë4¼yð.zTXtmodify-datexÚ320°Ô50Õ54 14·2°´26Ò60²20AëV„ŽIEND®B`‚rsyslog-8.2608.0/doc/source/PaxHeaders/containers0000644000000000000000000000013215241076617016705 xustar0030 mtime=1787067791.557672187 30 atime=1787067808.807993629 30 ctime=1787067791.557672187 rsyslog-8.2608.0/doc/source/containers/0000775000175000017500000000000015241076617016426 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/containers/PaxHeaders/collector.rst0000644000000000000000000000013115216464435021502 xustar0030 mtime=1782212893.977265392 30 atime=1787067671.932442568 29 ctime=1787067791.54067187 rsyslog-8.2608.0/doc/source/containers/collector.rst0000664000175000017500000001655615216464435021164 0ustar00rgerrger.. _containers-user-collector: .. _container.image.rsyslog-collector: rsyslog/rsyslog-collector ========================= .. meta:: :description: Reference for the rsyslog collector container image, including enabled inputs, file outputs, Kafka module availability, RELP, and optional TLS settings. :keywords: rsyslog, collector, Docker, Kafka, RELP, TLS, syslog .. summary-start The ``rsyslog/rsyslog-collector`` image is the reusable central-receiver role in the rsyslog container family. By default it listens on UDP and TCP syslog, can optionally enable RELP and TLS, ships the ``omkafka`` module, and writes received messages to local files unless you mount additional rules. .. summary-end .. index:: pair: containers; rsyslog/rsyslog-collector pair: Docker images; rsyslog/rsyslog-collector Overview -------- The ``rsyslog-collector`` container image extends the standard :doc:`standard` base with modules for **centralised log aggregation**. It is preconfigured to receive logs via UDP, TCP, and optionally RELP or TLS. It also includes extra output modules such as ``omkafka`` for custom routing. The packaged configuration writes received messages to local files. Additional rules can be mounted into ``/etc/rsyslog.d/`` when you want to forward to other backends or reshape the pipeline. This image is the recommended starting point for building a log collector or relay service. The packaged collector still runs as root by default. Its shipped configuration binds privileged listener ports such as ``514`` and ``6514`` and writes files under ``/var/log``. The inherited regex lookup-table noise filter is applied before the packaged collector file outputs. See :doc:`minimal` for the ``/etc/rsyslog/noise-drop.lkp_tbl`` format and matching behavior. .. note:: - **UDP (514/udp)** and **TCP (514/tcp)** are enabled by default. - **RELP (2514/tcp)** is available but **disabled by default**. - **TLS syslog (6514/tcp)** is available but **disabled by default**. - External deployments usually map RELP to **20514/tcp** to avoid conflicts with the standard syslog port. Environment Variables --------------------- Runtime behaviour can be tuned with the following variables: These environment variables control the packaged collector snippets only. Included modules such as ``omkafka`` are available for custom rules, but the image does not expose Kafka output settings through built-in environment variables. To forward to Kafka, mount an additional rsyslog config snippet that loads or uses ``omkafka``. .. _containers-user-collector-enable_udp: .. envvar:: ENABLE_UDP Enable UDP syslog reception. Default ``on``. .. _containers-user-collector-enable_tcp: .. envvar:: ENABLE_TCP Enable TCP syslog reception. Default ``on``. .. _containers-user-collector-enable_relp: .. envvar:: ENABLE_RELP Enable RELP syslog reception (internal port ``2514/tcp``). Default ``off``. .. _containers-user-collector-enable_tls: .. envvar:: ENABLE_TLS Enable TLS-encrypted syslog reception on ``6514/tcp``. Default ``off``. .. _containers-user-collector-tls_ca_file: .. envvar:: TLS_CA_FILE CA certificate path for TLS listener validation. Empty by default. .. _containers-user-collector-tls_cert_file: .. envvar:: TLS_CERT_FILE Server certificate path for the TLS listener. Empty by default. .. _containers-user-collector-tls_key_file: .. envvar:: TLS_KEY_FILE Server private key path for the TLS listener. Empty by default. .. _containers-user-collector-tls_auth_mode: .. envvar:: TLS_AUTH_MODE Netstream authentication mode for the TLS listener. Default ``anon``. .. _containers-user-collector-write_all_file: .. envvar:: WRITE_ALL_FILE Write all messages to ``/var/log/all.log``. Default ``on``. .. _containers-user-collector-write_json_file: .. envvar:: WRITE_JSON_FILE Write JSON formatted messages to ``/var/log/all-json.log``. Default ``on``. Custom Kafka forwarding ----------------------- The collector image includes the Kafka plugin package, so ``omkafka`` is available for custom configurations. Kafka forwarding is not enabled by the packaged collector rules and is not configured via built-in environment variables. To use Kafka, mount an additional file into ``/etc/rsyslog.d/`` with an ``action(type="omkafka" ...)`` rule that fits your deployment. .. _containers-user-collector-rsyslog_hostname: .. envvar:: RSYSLOG_HOSTNAME :noindex: Hostname used inside rsyslog. Defaults to the value of ``/etc/hostname`` when unset. .. _containers-user-collector-permit_unclean_start: .. envvar:: PERMIT_UNCLEAN_START :noindex: Skip configuration validation when set. By default ``rsyslogd -N1`` validates the configuration. .. _containers-user-collector-rsyslog_role: .. envvar:: RSYSLOG_ROLE :noindex: Role name consumed by the entrypoint. Defaults to ``collector``. Port Mapping Reference ---------------------- +-----------+----------------+------------------+-----------------+ | Protocol | Container Port | Example External | Controlled by | +===========+================+==================+=================+ | UDP Syslog | 514/udp | 514/udp | ``ENABLE_UDP`` | +-----------+----------------+------------------+-----------------+ | TCP Syslog | 514/tcp | 514/tcp | ``ENABLE_TCP`` | +-----------+----------------+------------------+-----------------+ | RELP | 2514/tcp | 20514/tcp | ``ENABLE_RELP`` | +-----------+----------------+------------------+-----------------+ | TLS Syslog | 6514/tcp | 6514/tcp | ``ENABLE_TLS`` | +-----------+----------------+------------------+-----------------+ Example Deployment (docker-compose) ----------------------------------- A minimal configuration using `docker compose`: .. code-block:: yaml version: "3.9" services: rsyslog-collector: image: rsyslog/rsyslog-collector:latest environment: ENABLE_UDP: "on" ENABLE_TCP: "on" ENABLE_RELP: "on" ENABLE_TLS: "off" ports: - "514:514/udp" # Syslog UDP - "514:514/tcp" # Syslog TCP - "20514:2514/tcp" # RELP (external 20514 → internal 2514) - "6514:6514/tcp" # TLS syslog (optional) volumes: - ./data:/var/log # Optional: collect logs on host Verifying the Container ----------------------- To confirm that the collector is listening on the expected ports: .. code-block:: bash docker compose exec rsyslog-collector ss -tuln This should show listeners on ``514/udp`` and ``514/tcp`` by default, plus ``2514/tcp`` when RELP is enabled and ``6514/tcp`` when TLS is enabled. Production Deployments ---------------------- For a complete production deployment with dashboards, alerting, and log storage, see :doc:`../deployments/rosi_collector/index`. ROSI Collector builds on this container image to provide Grafana visualization, Loki log storage, and Prometheus metrics collection. In that deployment, Docker Compose mounts additional rsyslog snippets so the collector forwards to Loki and exposes the collector on external port ``10514`` for plain TCP clients. .. seealso:: - :doc:`../configuration/modules/omkafka` - Kafka action module reference - :doc:`../deployments/rosi_collector/index` - Complete log collection stack - `GitHub Discussions `_ for community support. - `rsyslog Assistant AI `_ for self-help and examples. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/standard.rst0000644000000000000000000000013015216464435021313 xustar0030 mtime=1782212893.978265408 29 atime=1787067672.10844585 29 ctime=1787067791.55567215 rsyslog-8.2608.0/doc/source/containers/standard.rst0000664000175000017500000000266715216464435020774 0ustar00rgerrger.. _containers-user-standard: .. _container.image.rsyslog-standard: rsyslog/rsyslog =============== .. index:: pair: containers; rsyslog/rsyslog pair: Docker images; rsyslog/rsyslog The general-purpose image builds on ``rsyslog-minimal`` and adds commonly used modules such as ``imhttp`` and ``omhttp``. Use it when you need a ready-to-run rsyslog with HTTP ingestion or forwarding capabilities. Runtime Notes ------------- Like :doc:`minimal`, this image runs as ``syslog:adm`` by default. That fits the packaged general-purpose role because the shipped configuration does not bind privileged ports. The inherited regex lookup-table noise filter from the minimal image is available at ``/etc/rsyslog/noise-drop.lkp_tbl``. It matches ``$rawmsg`` by default and drops events when the lookup result is non-empty. Environment Variables --------------------- The same entrypoint variables as the minimal image are available: .. _containers-user-standard-rsyslog_hostname: .. envvar:: RSYSLOG_HOSTNAME :noindex: Hostname used inside rsyslog. Defaults to the value of ``/etc/hostname`` when unset. .. _containers-user-standard-permit_unclean_start: .. envvar:: PERMIT_UNCLEAN_START :noindex: Skip configuration validation when set. By default ``rsyslogd -N1`` validates the configuration. .. _containers-user-standard-rsyslog_role: .. envvar:: RSYSLOG_ROLE :noindex: Role name consumed by the entrypoint. Defaults to ``standard``. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/etl.rst0000644000000000000000000000013215216464435020301 xustar0030 mtime=1782212893.977265392 30 atime=1787067671.991443668 30 ctime=1787067791.546671982 rsyslog-8.2608.0/doc/source/containers/etl.rst0000664000175000017500000001160515216464435017750 0ustar00rgerrger.. _containers-user-etl: .. _container.image.rsyslog-etl: rsyslog/rsyslog-etl =================== .. meta:: :description: Reference for the rsyslog ETL container image that receives syslog and forwards events to a Vespa HTTP API. :keywords: rsyslog, ETL, Vespa, Docker, omhttp, collector .. summary-start The ``rsyslog/rsyslog-etl`` image is a specialized ingestion role that accepts syslog over UDP, TCP, and RELP, then forwards events to a Vespa HTTP endpoint using ``omhttp``. .. summary-end .. index:: pair: containers; rsyslog/rsyslog-etl pair: Docker images; rsyslog/rsyslog-etl Overview -------- The ``rsyslog-etl`` image extends the standard :doc:`standard` base with a small ETL-oriented configuration. It receives network syslog and sends each message to a Vespa document API endpoint. The packaged rules use a simple JSON document template containing the original message text and generate the Vespa document path dynamically from environment variables. This image is a concrete example of rsyslog being used as an ETL transport and delivery component. It is optimized for Vespa-oriented pipelines, not presented here as a generic all-destinations ETL appliance. The inherited regex lookup-table noise filter is applied before the packaged Vespa output action. See :doc:`minimal` for the ``/etc/rsyslog/noise-drop.lkp_tbl`` format and matching behavior. .. warning:: ``rsyslog/rsyslog-etl`` is currently experimental. Treat it as a specialized example image for Vespa-oriented ETL pipelines rather than a broadly supported general-purpose container role. .. note:: - **UDP (514/udp)** and **TCP (514/tcp)** are enabled by default. - **RELP (2514/tcp)** is enabled by default. - The packaged ETL output is **HTTP to Vespa**, not a local file sink. - The packaged configuration is explicitly **unencrypted** on the input side. Environment Variables --------------------- .. _containers-user-etl-enable_udp: .. envvar:: ENABLE_UDP :noindex: Enable UDP syslog reception. Default ``on``. .. _containers-user-etl-enable_tcp: .. envvar:: ENABLE_TCP :noindex: Enable TCP syslog reception. Default ``on``. .. _containers-user-etl-enable_relp: .. envvar:: ENABLE_RELP :noindex: Enable RELP syslog reception on ``2514/tcp``. Default ``on``. .. _containers-user-etl-enable_vespa: .. envvar:: ENABLE_VESPA Enable the packaged Vespa HTTP action. Default ``on``. .. _containers-user-etl-vespa_namespace: .. envvar:: VESPA_NAMESPACE Vespa document namespace used in the generated REST path. .. _containers-user-etl-vespa_doctype: .. envvar:: VESPA_DOCTYPE Vespa document type used in the generated REST path. .. _containers-user-etl-vespa_server: .. envvar:: VESPA_SERVER Hostname or IP address of the Vespa HTTP endpoint. .. _containers-user-etl-vespa_port: .. envvar:: VESPA_PORT TCP port of the Vespa HTTP endpoint. .. _containers-user-etl-vespa_use_https: .. envvar:: VESPA_USE_HTTPS Use HTTPS for the Vespa HTTP action. Default ``on``. .. _containers-user-etl-vespa_allow_unsigned_certs: .. envvar:: VESPA_ALLOW_UNSIGNED_CERTS Disable Vespa HTTPS certificate validation when set to ``on``. Default ``off``; production deployments should keep certificate validation enabled and provide a trusted CA through the container trust store or a custom configuration. .. _containers-user-etl-rsyslog_hostname: .. envvar:: RSYSLOG_HOSTNAME :noindex: Hostname used inside rsyslog. Defaults to the value of ``/etc/hostname`` when unset. .. _containers-user-etl-permit_unclean_start: .. envvar:: PERMIT_UNCLEAN_START :noindex: Skip configuration validation when set. By default ``rsyslogd -N1`` validates the configuration. .. _containers-user-etl-rsyslog_role: .. envvar:: RSYSLOG_ROLE :noindex: Role name consumed by the entrypoint. The current image sets this to ``collector``. Port Mapping Reference ---------------------- +-----------+----------------+------------------+-----------------+ | Protocol | Container Port | Example External | Controlled by | +===========+================+==================+=================+ | UDP Syslog | 514/udp | 514/udp | ``ENABLE_UDP`` | +-----------+----------------+------------------+-----------------+ | TCP Syslog | 514/tcp | 514/tcp | ``ENABLE_TCP`` | +-----------+----------------+------------------+-----------------+ | RELP | 2514/tcp | 2514/tcp | ``ENABLE_RELP`` | +-----------+----------------+------------------+-----------------+ Consumption Model ----------------- The repository includes a sample Docker Compose deployment under ``packaging/docker/rsyslog/compose-etl/compose.yml``. That example persists the rsyslog spool directory, exposes UDP/TCP/RELP listener ports, and passes the Vespa connection variables as environment settings. Related Reading --------------- For the broader product positioning behind ETL use cases, see :doc:`../faq/etl_tool`. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/user_images.rst0000644000000000000000000000013215216464435022020 xustar0030 mtime=1782212893.978265408 30 atime=1787067672.133446316 30 ctime=1787067791.557672187 rsyslog-8.2608.0/doc/source/containers/user_images.rst0000664000175000017500000000502115216464435021462 0ustar00rgerrger.. _containers-user-images: User-Focused Images ------------------- .. meta:: :description: Official rsyslog container image variants for end users, including minimal, standard, collector, dockerlogs, and ETL roles. :keywords: rsyslog, containers, Docker, minimal, collector, dockerlogs, ETL, imbeats .. summary-start The official rsyslog image family provides layered container variants for custom builds, general-purpose forwarding, central collection, Docker log forwarding, and Vespa-oriented ETL pipelines. .. summary-end .. index:: pair: containers; user images pair: Docker; rsyslog images Official images are built on Ubuntu LTS releases and install the latest rsyslog packages from the Adiscon daily-stable PPA. Images are tagged ``rsyslog/rsyslog[-]:`` where ```` follows the ``YYYY-MM`` rsyslog release. Available variants include: * :doc:`rsyslog/rsyslog-minimal ` – rsyslog core only. * :doc:`rsyslog/rsyslog ` – standard image with common modules such as ``imhttp`` and ``omhttp``. * :doc:`rsyslog/rsyslog-collector ` – adds modules for centralized log collection, including RELP and optional TLS reception. * :doc:`rsyslog/rsyslog-dockerlogs ` – includes ``imdocker`` to process logs from the Docker daemon. * :doc:`rsyslog/rsyslog-etl ` – experimental image that receives syslog and forwards events to a Vespa HTTP endpoint using ``omhttp``. * ``rsyslog/rsyslog-debug`` – planned variant with troubleshooting tools. Sample container definitions include: * :doc:`rsyslog/rsyslog-imbeats ` – concrete sample for receiving Elastic Agent and Filebeat ``output.logstash`` traffic with ``imbeats``. This sample is not wired into published image builds yet. .. toctree:: :maxdepth: 1 minimal standard collector dockerlogs etl imbeats Images are built using the layered ``Makefile`` in ``packaging/docker/rsyslog``:: make all make standard make VERSION=2025-06 minimal Configuration snippets in each directory and environment variables allow enabling or disabling functionality at runtime. Consult the `packaging/docker README `_ for the latest details and feedback instructions. For a complete centralized logging stack with Loki, Grafana, Prometheus, and Traefik, see :doc:`../deployments/rosi_collector/index`. ROSI Collector uses the ``rsyslog/rsyslog-collector`` image as one component inside a larger Docker Compose deployment. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/development_images.rst0000644000000000000000000000013215132733117023355 xustar0030 mtime=1768666703.898620102 30 atime=1787067671.959443072 30 ctime=1787067791.542671907 rsyslog-8.2608.0/doc/source/containers/development_images.rst0000666000175000017500000000162615132733117023030 0ustar00rgerrger.. _containers-development-images: Development and Historical Images --------------------------------- .. index:: pair: containers; development images pair: containers; historical images Large images used by rsyslog's Continuous Integration live under ``packaging/docker/dev_env``. They provide all build dependencies for multiple distributions (Alpine, CentOS, Debian, Fedora, SUSE and Ubuntu) and are intended for contributors who need to reproduce the CI environment. Due to the many tools they include, these images are several gigabytes in size and are not meant for production use. The repository also retains some historical material for reference: * ``packaging/docker/appliance`` – deprecated attempt at an all-in-one logging appliance. * ``packaging/docker/base`` – obsolete base images (Alpine and CentOS 7). These directories are kept to document past work but are no longer maintained. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/minimal.rst0000644000000000000000000000013215216464435021143 xustar0030 mtime=1782212893.977265392 30 atime=1787067672.081445346 30 ctime=1787067791.553672112 rsyslog-8.2608.0/doc/source/containers/minimal.rst0000664000175000017500000000451415216464435020613 0ustar00rgerrger.. _containers-user-minimal: .. _container.image.rsyslog-minimal: rsyslog/rsyslog-minimal ======================= .. index:: pair: containers; rsyslog/rsyslog-minimal pair: Docker images; rsyslog/rsyslog-minimal A lean Ubuntu-based image containing the rsyslog core and a tiny configuration that writes logs to standard output. It serves as the foundation for the other rsyslog images and is suitable when you want to add your own modules or configuration. Runtime Notes ------------- The packaged default configuration uses ``/var/spool/rsyslog`` as the work directory and writes to standard output via ``omstdout``. The image also includes an empty native regex lookup table at ``/etc/rsyslog/noise-drop.lkp_tbl``. Replace or mount this file to drop known noisy events before packaged outputs process them. The shipped filter matches against ``$rawmsg`` because it preserves the full received event and is usually the most robust property for source-side filtering. If a regex table entry matches and returns any non-empty tag, rsyslog calls ``stop`` for that event. To match another property, such as ``$msg``, replace the shipped ``/etc/rsyslog.d/02-noise-drop.conf`` snippet with custom rsyslog configuration. The lookup table uses the standard rsyslog lookup-table JSON format and POSIX extended regular expressions. The first matching entry wins: .. code-block:: json { "version": 1, "nomatch": "", "type": "regex", "table": [ { "regex": "healthcheck succeeded", "tag": "drop" } ] } The image runs as ``syslog:adm`` by default. That fits simple container deployments that use unprivileged ports and do not depend on privileged inputs such as host log sockets or other root-only resources. Environment Variables --------------------- The entrypoint script recognizes the following variables: .. _containers-user-minimal-rsyslog_hostname: .. envvar:: RSYSLOG_HOSTNAME Hostname used inside rsyslog. Defaults to the value of ``/etc/hostname`` when unset. .. _containers-user-minimal-permit_unclean_start: .. envvar:: PERMIT_UNCLEAN_START Skip configuration validation when set. By default ``rsyslogd -N1`` validates the configuration. .. _containers-user-minimal-rsyslog_role: .. envvar:: RSYSLOG_ROLE Role name consumed by the entrypoint. Defaults to ``minimal`` and normally does not need to be changed. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/dockerlogs.rst0000644000000000000000000000013215216464435021651 xustar0030 mtime=1782212893.977265392 30 atime=1787067671.974443352 30 ctime=1787067791.544671944 rsyslog-8.2608.0/doc/source/containers/dockerlogs.rst0000664000175000017500000000405415216464435021320 0ustar00rgerrger.. _containers-user-dockerlogs: .. _container.image.rsyslog-dockerlogs: rsyslog/rsyslog-dockerlogs ========================== .. meta:: :description: Reference for the rsyslog Docker log forwarding image based on imdocker and omfwd. :keywords: rsyslog, dockerlogs, imdocker, Docker, forwarding .. summary-start The ``rsyslog/rsyslog-dockerlogs`` image reads Docker log events with ``imdocker`` and forwards them to a central rsyslog collector over TCP. .. summary-end .. index:: pair: containers; rsyslog/rsyslog-dockerlogs pair: Docker images; rsyslog/rsyslog-dockerlogs This variant includes the ``imdocker`` module to read logs from the Docker daemon and forward them to a central rsyslog instance. The packaged configuration uses ``omfwd`` over TCP with an in-memory queue and infinite retry so temporary collector outages do not immediately drop events. The packaged dockerlogs image still runs as root by default. Typical deployments rely on Docker daemon or socket access, which is commonly root-scoped. The inherited regex lookup-table noise filter is applied before the packaged forwarding action. See :doc:`minimal` for the ``/etc/rsyslog/noise-drop.lkp_tbl`` format and matching behavior. Environment Variables --------------------- .. _containers-user-dockerlogs-remote_server_name: .. envvar:: REMOTE_SERVER_NAME Required hostname or IP of the collector to forward logs to. .. _containers-user-dockerlogs-remote_server_port: .. envvar:: REMOTE_SERVER_PORT TCP port on the collector. Defaults to ``514`` when unset. .. _containers-user-dockerlogs-rsyslog_hostname: .. envvar:: RSYSLOG_HOSTNAME :noindex: Hostname used inside rsyslog. Defaults to the value of ``/etc/hostname`` when unset. .. _containers-user-dockerlogs-permit_unclean_start: .. envvar:: PERMIT_UNCLEAN_START :noindex: Skip configuration validation when set. By default ``rsyslogd -N1`` validates the configuration. .. _containers-user-dockerlogs-rsyslog_role: .. envvar:: RSYSLOG_ROLE :noindex: Role name consumed by the entrypoint. Defaults to ``docker``. rsyslog-8.2608.0/doc/source/containers/PaxHeaders/index.rst0000644000000000000000000000013215171370365020622 xustar0030 mtime=1776677109.112908007 30 atime=1787067672.066445067 30 ctime=1787067791.551672075 rsyslog-8.2608.0/doc/source/containers/index.rst0000664000175000017500000000200615171370365020264 0ustar00rgerrger.. _containers-index: Rsyslog Containers ================== .. meta:: :description: Overview of rsyslog container images and related deployment profiles. :keywords: rsyslog, containers, Docker, images, ROSI, collector .. summary-start This section covers the official rsyslog container images and points to higher-level deployment profiles built on top of them. .. summary-end .. index:: single: containers single: Docker images Rsyslog runs well inside containers and the project provides official Docker images for common logging scenarios. Dockerfiles and build recipes live under `packaging/docker `_. Since version 8.32.0 rsyslog also adjusts a few defaults when it detects that it is running as PID 1 inside a container: ``Ctrl-C`` is handled and no pid file is written. For complete production deployments with dashboards and monitoring, see :doc:`../deployments/index`. .. toctree:: :maxdepth: 2 user_images development_images rsyslog-8.2608.0/doc/source/containers/PaxHeaders/imbeats.rst0000644000000000000000000000013215216464435021141 xustar0030 mtime=1782212893.977265392 30 atime=1787067672.029444377 30 ctime=1787067791.548672019 rsyslog-8.2608.0/doc/source/containers/imbeats.rst0000664000175000017500000000653715216464435020620 0ustar00rgerrger.. _containers-sample-imbeats: .. _container.sample.rsyslog-imbeats: rsyslog/rsyslog-imbeats sample ============================== .. meta:: :description: Sample rsyslog container definition for receiving Elastic Agent and Filebeat Logstash output with imbeats. :keywords: rsyslog, containers, Docker, imbeats, Elastic Agent, Filebeat, Logstash output, Beats, TLS .. summary-start The ``rsyslog/rsyslog-imbeats`` sample container definition receives Elastic Agent and Filebeat ``output.logstash`` traffic with ``imbeats`` on port ``5044``. It is a repository sample and is not part of the published rsyslog container image family yet. .. summary-end .. index:: pair: containers; rsyslog-imbeats sample pair: Docker images; imbeats sample Status ------ The sample files live in ``packaging/docker/rsyslog/imbeats``. They are not wired into the container ``Makefile``, release builds, Docker Hub metadata, or ``latest`` tagging. Use them as a concrete starting point when you want to run an ``imbeats`` receiver in a container. The sample assumes that the base image or package source provides the package containing ``imbeats.so``. It installs ``rsyslog-gnutls`` as a concrete TLS stream-driver package example. Local build ----------- Build the sample directly from its directory: .. code-block:: bash docker build \ -t rsyslog-imbeats-sample:local \ packaging/docker/rsyslog/imbeats This direct build is separate from the official container image Makefile. Docker Compose example ---------------------- .. code-block:: yaml services: rsyslog-imbeats: image: rsyslog-imbeats-sample:local ports: - "5044:5044/tcp" environment: IMBEATS_PORT: "5044" TLS_AUTH_MODE: "anon" TLS_CA_FILE: /etc/rsyslog/tls/ca.pem TLS_CERT_FILE: /etc/rsyslog/tls/server-cert.pem TLS_KEY_FILE: /etc/rsyslog/tls/server-key.pem IMBEATS_OUTPUT_FILE: /var/log/imbeats.log volumes: - ./certs:/etc/rsyslog/tls:ro - ./logs:/var/log Elastic Agent output -------------------- Configure Elastic Agent to send Logstash output to the container: .. code-block:: yaml outputs: default: type: logstash hosts: ["rsyslog-imbeats.example.net:5044"] compression_level: 9 ssl.enabled: true ssl.certificate_authorities: - /etc/elastic-agent/certs/ca.pem For Filebeat standalone configuration, use the same settings under ``output.logstash``. Operational notes ----------------- - The container listens on ``5044/tcp`` by default. - TLS is configured through the mounted certificate paths. Install and load a TLS stream-driver package in images derived from this sample. - The default ``TLS_AUTH_MODE=anon`` lets Elastic Agent or Filebeat verify the rsyslog server certificate without requiring a client certificate. Use a stricter certificate-validation auth mode only after configuring client certificates on the sender. - Production deployments should use certificate verification. Avoid disabling verification except for isolated tests. - The sample writes received event JSON to ``/var/log/imbeats.log``. Mount a custom rsyslog snippet when you want to forward to another destination. .. seealso:: - :doc:`../configuration/modules/imbeats` - imbeats module reference - :doc:`user_images` - rsyslog user-focused container images rsyslog-8.2608.0/doc/source/PaxHeaders/includes0000644000000000000000000000013215241076617016346 xustar0030 mtime=1787067791.766676082 30 atime=1787067808.807993629 30 ctime=1787067791.766676082 rsyslog-8.2608.0/doc/source/includes/0000775000175000017500000000000015241076617016067 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/includes/PaxHeaders/container_dev_env.inc.rst0000644000000000000000000000013215132411300023372 xustar0030 mtime=1768559296.189884422 30 atime=1787067671.995443743 30 ctime=1787067791.762676007 rsyslog-8.2608.0/doc/source/includes/container_dev_env.inc.rst0000666000175000017500000000105615132411300023042 0ustar00rgerrger.. note:: The rsyslog project maintains multiple `rsyslog docker development environment images `_. These images have been configured specifically for use with rsyslog and are recommended over your own build environment. Rsyslog docker development images are named with the ``rsyslog_dev_`` prefix, followed by the distro name. .. warning:: If you plan to copy the binary for use outside of the container you need to make sure to use an image of the same distro/version when building rsyslog. rsyslog-8.2608.0/doc/source/includes/PaxHeaders/substitution_definitions.inc.rst0000644000000000000000000000013215171370365025073 xustar0030 mtime=1776677109.116908069 30 atime=1787067671.697438188 30 ctime=1787067791.766676082 rsyslog-8.2608.0/doc/source/includes/substitution_definitions.inc.rst0000664000175000017500000000636015171370365024544 0ustar00rgerrger .. This file is included by the common header file, which is itself included by means of the rst_prolog Sphinx build configuration file (source/conf.py). Add substitutions here instead of directly to the rst_prolog configuration option. .. |PRODUCT| replace:: ``Rsyslog`` .. |FmtBasicName| replace:: ``basic`` .. |FmtAdvancedName| replace:: ``advanced`` .. |FmtObsoleteName| replace:: ``obsolete legacy`` .. |FmtYamlName| replace:: ``yaml`` .. |FmtObsoleteDescription| replace:: ``Obsolete Format Equivalents`` .. |RsyslogDockerHub| replace:: official rsyslog Docker Hub .. _RsyslogDockerHub: https://hub.docker.com/u/rsyslog/ .. |GitHubDockerProject| replace:: rsyslog docker definitions .. _GitHubDockerProject: https://github.com/rsyslog/rsyslog/packaging/docker .. |DockerApplianceAlpineDockerHubRepo| replace:: Alpine rsyslog appliance Docker Hub repo .. _DockerApplianceAlpineDockerHubRepo: https://hub.docker.com/r/rsyslog/syslog_appliance_alpine/ .. |DockerApplianceAlpineName| replace:: ``rsyslog/syslog_appliance_alpine`` .. |DockerApplianceAlpineRUN| replace:: ``docker run -ti rsyslog/syslog_appliance_alpine`` .. |RsyslogPackageDownloads| replace:: rsyslog package downloads .. _RsyslogPackageDownloads: http://www.rsyslog.com/downloads/download-other/ .. |GitHubDocProject| replace:: rsyslog source documentation .. _GitHubDocProject: https://github.com/rsyslog/rsyslog/tree/main/doc .. |GitHubDocProjectREADME| replace:: rsyslog doc/ README .. _GitHubDocProjectREADME: https://github.com/rsyslog/rsyslog/blob/main/doc/README.md .. |GitHubDocProjectDevREADME| replace:: rsyslog doc/ BUILDS README .. _GitHubDocProjectDevREADME: https://github.com/rsyslog/rsyslog/blob/main/doc/BUILDS_README.md .. |GitHubDocProjectGoodFirstIssueLabel| replace:: rsyslog doc issues marked with Good First Issue label .. _GitHubDocProjectGoodFirstIssueLabel: https://github.com/rsyslog/rsyslog/labels/good%20first%20issue .. |GitHubDocProjectHelpWantedLabel| replace:: rsyslog-doc issues marked with Help Wanted label .. _GitHubDocProjectHelpWantedLabel: https://github.com/rsyslog/rsyslog-doc/labels/help%20wanted .. |RsyslogOfficialForums| replace:: Forum .. _RsyslogOfficialForums: http://kb.monitorware.com/rsyslog-f40.html .. |RsyslogStackExchangeAsk| replace:: Ask .. _RsyslogStackExchangeAsk: https://serverfault.com/questions/ask?tags=rsyslog .. |RsyslogStackExchangeView| replace:: View .. _RsyslogStackExchangeView: https://stackexchange.com/filters/327462/rsyslog .. |RsyslogOfficialMailingList| replace:: Mailing list .. _RsyslogOfficialMailingList: http://lists.adiscon.net/mailman/listinfo/rsyslog .. |GitHubSourceProject| replace:: rsyslog source project .. _GitHubSourceProject: https://github.com/rsyslog/rsyslog/ .. |GitHubSourceProjectREADME| replace:: rsyslog project README .. _GitHubSourceProjectREADME: https://github.com/rsyslog/rsyslog/blob/main/README.md .. |GitHubSourceProjectGoodFirstIssueLabel| replace:: rsyslog issues marked with Good First Issue label .. _GitHubSourceProjectGoodFirstIssueLabel: https://github.com/rsyslog/rsyslog/labels/good%20first%20issue .. |GitHubSourceProjectHelpWantedLabel| replace:: rsyslog issues marked with Help Wanted label .. _GitHubSourceProjectHelpWantedLabel: https://github.com/rsyslog/rsyslog/labels/help%20wanted rsyslog-8.2608.0/doc/source/includes/PaxHeaders/footer.inc.rst0000644000000000000000000000013115171370365021221 xustar0030 mtime=1776677109.116908069 29 atime=1787067671.71043843 30 ctime=1787067791.764676044 rsyslog-8.2608.0/doc/source/includes/footer.inc.rst0000664000175000017500000000061715171370365020672 0ustar00rgerrger---- **Support:** `rsyslog Assistant `_ | `GitHub Discussions `_ | GitHub Issues: |GitHubSourceProject|_ **Contributing:** Source & docs: |GitHubSourceProject|_ © 2008–2026 `Rainer Gerhards `_ and others. Licensed under the `Apache License 2.0 `_. rsyslog-8.2608.0/doc/source/PaxHeaders/reference0000644000000000000000000000013215241076616016475 xustar0030 mtime=1787067790.877659515 30 atime=1787067808.807993629 30 ctime=1787067790.877659515 rsyslog-8.2608.0/doc/source/reference/0000775000175000017500000000000015241076616016216 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/reference/PaxHeaders/parameters0000644000000000000000000000013015241076621020632 xustar0029 mtime=1787067793.62171065 30 atime=1787067808.807993629 29 ctime=1787067793.62171065 rsyslog-8.2608.0/doc/source/reference/parameters/0000775000175000017500000000000015241076621020355 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-parsehostname.rst0000644000000000000000000000013215132733117025714 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.982462143 30 ctime=1787067792.222684579 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-parsehostname.rst0000666000175000017500000000174415132733117025370 0ustar00rgerrger.. _param-imkafka-parsehostname: .. _imkafka.parameter.input.parsehostname: parseHostname ============= .. index:: single: imkafka; parseHostname single: parseHostname .. summary-start Controls whether imkafka parses the hostname from each received message. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: parseHostname :Scope: input :Type: boolean :Default: input=``off`` :Required?: no :Introduced: 8.38.0 Description ----------- If this parameter is set to on, imkafka will parse the hostname in log if it exists. The result can be retrieved from $hostname. If it's off, for compatibility reasons, the local hostname is used, same as the previous version. Input usage ----------- .. _imkafka.parameter.input.parsehostname-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="your-topic" parseHostname="on") See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-name.rst0000644000000000000000000000013215132733117026201 xustar0030 mtime=1768666703.909620269 30 atime=1787067673.999481102 30 ctime=1787067792.540690505 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-name.rst0000666000175000017500000000242215132733117025647 0ustar00rgerrger.. _param-imtcp-streamdriver-name: .. _imtcp.parameter.module.streamdriver-name: .. _imtcp.parameter.input.streamdriver-name: StreamDriver.Name ================= .. index:: single: imtcp; StreamDriver.Name single: StreamDriver.Name .. summary-start Selects the network stream driver for all inputs using this module. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.Name :Scope: module, input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Selects :doc:`network stream driver <../../concepts/netstrm_drvr>` for all inputs using this module. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-name: .. _imtcp.parameter.module.streamdriver-name-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.name="mydriver") Input usage ----------- .. _param-imtcp-input-streamdriver-name: .. _imtcp.parameter.input.streamdriver-name-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.name="mydriver") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-addtlframedelimiter.rst0000644000000000000000000000013215132733117026736 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.688475304 30 ctime=1787067792.317686349 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-addtlframedelimiter.rst0000666000175000017500000000516515132733117026413 0ustar00rgerrger.. _param-imptcp-addtlframedelimiter: .. _imptcp.parameter.input.addtlframedelimiter: AddtlFrameDelimiter =================== .. index:: single: imptcp; AddtlFrameDelimiter single: AddtlFrameDelimiter .. summary-start Defines an additional ASCII frame delimiter for non-standard senders. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: AddtlFrameDelimiter :Scope: input :Type: integer :Default: input=-1 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This directive permits to specify an additional frame delimiter for plain tcp syslog. The industry-standard specifies using the LF character as frame delimiter. Some vendors, notable Juniper in their NetScreen products, use an invalid frame delimiter, in Juniper's case the NUL character. This directive permits to specify the ASCII value of the delimiter in question. Please note that this does not guarantee that all wrong implementations can be cured with this directive. It is not even a sure fix with all versions of NetScreen, as I suggest the NUL character is the effect of a (common) coding error and thus will probably go away at some time in the future. But for the time being, the value 0 can probably be used to make rsyslog handle NetScreen's invalid syslog/tcp framing. For additional information, see this `forum thread `_. **If this doesn't work for you, please do not blame the rsyslog team. Instead file a bug report with Juniper!** Note that a similar, but worse, issue exists with Cisco's IOS implementation. They do not use any framing at all. This is confirmed from Cisco's side, but there seems to be very limited interest in fixing this issue. This directive **can not** fix the Cisco bug. That would require much more code changes, which I was unable to do so far. Full details can be found at the `Cisco tcp syslog anomaly `_ page. Input usage ----------- .. _param-imptcp-input-addtlframedelimiter: .. _imptcp.parameter.input.addtlframedelimiter-usage: .. code-block:: rsyslog input(type="imptcp" addtlFrameDelimiter="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserveraddtlframedelimiter: - $InputPTCPServerAddtlFrameDelimiter — maps to AddtlFrameDelimiter (status: legacy) .. index:: single: imptcp; $InputPTCPServerAddtlFrameDelimiter single: $InputPTCPServerAddtlFrameDelimiter See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmrfc5424addhmac-key.rst0000644000000000000000000000013215132733117025155 xustar0030 mtime=1768666703.914620344 30 atime=1787067673.009462646 30 ctime=1787067792.900697214 rsyslog-8.2608.0/doc/source/reference/parameters/mmrfc5424addhmac-key.rst0000666000175000017500000000150015132733117024617 0ustar00rgerrger.. _param-mmrfc5424addhmac-key: .. _mmrfc5424addhmac.parameter.action.key: key === .. index:: single: mmrfc5424addhmac; key single: key .. summary-start Specifies the key used to generate the HMAC. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmrfc5424addhmac`. :Name: key :Scope: action :Type: string :Default: none :Required?: yes :Introduced: 7.5.6 Description ----------- The key to be used to generate the HMAC. In production, this should be a cryptographically strong and secret key. Action usage ------------ .. _param-mmrfc5424addhmac-action-key: .. _mmrfc5424addhmac.parameter.action.key-usage: .. code-block:: rsyslog action(type="mmrfc5424addhmac" key="a-long-and-very-secret-key-phrase") See also -------- See also :doc:`../../configuration/modules/mmrfc5424addhmac`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-parsehostname.rst0000644000000000000000000000013215132733117027647 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.306486825 30 ctime=1787067792.644692443 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-parsehostname.rst0000666000175000017500000000220015132733117027307 0ustar00rgerrger.. _param-imuxsock-syssock-parsehostname: .. _imuxsock.parameter.module.syssock-parsehostname: SysSock.ParseHostname ===================== .. index:: single: imuxsock; SysSock.ParseHostname single: SysSock.ParseHostname .. summary-start Expects hostnames on the system log socket when special parsing is disabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.ParseHostname :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.9.0 Description ----------- .. note:: This option only has an effect if ``SysSock.UseSpecialParser`` is set to "off". Normally, the local log sockets do *not* contain hostnames. If set to on, parsers will expect hostnames just like in regular formats. If set to off (the default), the parser chain is instructed to not expect them. Module usage ------------ .. _param-imuxsock-module-syssock-parsehostname: .. _imuxsock.parameter.module.syssock-parsehostname-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.parseHostname="on") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-trimlineoverbytes.rst0000644000000000000000000000013215132733117026473 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.483452841 30 ctime=1787067792.124682753 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-trimlineoverbytes.rst0000666000175000017500000000215415132733117026143 0ustar00rgerrger.. _param-imfile-trimlineoverbytes: .. _imfile.parameter.input.trimlineoverbytes: .. _imfile.parameter.trimlineoverbytes: trimLineOverBytes ================= .. index:: single: imfile; trimLineOverBytes single: trimLineOverBytes .. summary-start Truncates lines longer than the specified number of bytes. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: trimLineOverBytes :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Tells rsyslog to truncate lines whose length exceeds the configured number of bytes. A positive value trims the line at that byte count. The default ``0`` means lines are never truncated. This option can be used when ``readMode`` is ``0`` or ``2``. Input usage ----------- .. _param-imfile-input-trimlineoverbytes: .. _imfile.parameter.input.trimlineoverbytes-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" trimLineOverBytes="0") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-usehttps.rst0000644000000000000000000000013115132733117024631 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.727457389 29 ctime=1787067793.32070504 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-usehttps.rst0000666000175000017500000000137615132733117024307 0ustar00rgerrger.. _param-omhttp-usehttps: .. _omhttp.parameter.input.usehttps: useHttps ======== .. index:: single: omhttp; useHttps single: useHttps .. summary-start Switches omhttp to use HTTPS instead of HTTP when sending requests. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: useHttps :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- When switched to ``on`` you will use ``https`` instead of ``http``. Input usage ----------- .. _omhttp.parameter.input.usehttps-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-serverstreamdriverauthmode.rst0000644000000000000000000000013215216464435030366 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.090445514 30 ctime=1787067791.958679659 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-serverstreamdriverauthmode.rst0000664000175000017500000000375315216464435030042 0ustar00rgerrger.. _param-imdiag-serverstreamdriverauthmode: .. _imdiag.parameter.module.serverstreamdriverauthmode: ServerStreamDriverAuthMode ========================== .. index:: single: imdiag; ServerStreamDriverAuthMode single: ServerStreamDriverAuthMode .. summary-start Accepts a stream driver authentication mode string, but imdiag always uses the plain TCP driver so the value has no effect. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ServerStreamDriverAuthMode :Scope: module :Type: string :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Selects the authentication mode for the active :doc:`network stream driver <../../concepts/netstrm_drvr>`. imdiag always uses the plain TCP driver (``ptcp``) and therefore lacks TLS or other authenticated stream implementations. The value is accepted for compatibility with the generic TCP listener framework but is ignored by the ``ptcp`` driver. Configure this parameter before :ref:`ServerRun ` if you need forward compatibility with a future build that supports alternate stream drivers. In current releases the setting does not change listener behavior. Module usage ------------ .. _param-imdiag-module-serverstreamdriverauthmode: .. _imdiag.parameter.module.serverstreamdriverauthmode-usage: .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/var/run/rsyslog/imdiag.port" serverStreamDriverAuthMode="anon" serverRun="19998") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagserverstreamdriverauthmode: - $IMDiagServerStreamDriverAuthMode — maps to ServerStreamDriverAuthMode (status: legacy) .. index:: single: imdiag; $IMDiagServerStreamDriverAuthMode single: $IMDiagServerStreamDriverAuthMode See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-listenportfilename.rst0000644000000000000000000000013215132733117026460 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.088482761 30 ctime=1787067792.487689517 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-listenportfilename.rst0000666000175000017500000000226715132733117026135 0ustar00rgerrger.. _param-imtcp-listenportfilename: .. _imtcp.parameter.input.listenportfilename: ListenPortFileName ================== .. index:: single: imtcp; ListenPortFileName single: ListenPortFileName .. summary-start Writes the listener's port number into the given file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: ListenPortFileName :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: 8.38.0 Description ----------- Specifies a file name into which the port number this input listens on is written. It is primarily intended for cases when ``port`` is set to ``0`` to let the OS assign a free port number. This parameter was introduced for testbench scenarios that use dynamic ports. .. note:: If this parameter is set, ``port="0"`` is permitted. Otherwise, the port defaults to ``514``. Input usage ----------- .. _param-imtcp-input-listenportfilename: .. _imtcp.parameter.input.listenportfilename-usage: .. code-block:: rsyslog input(type="imtcp" port="0" listenPortFileName="/tmp/imtcp.port") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-enable.rst0000644000000000000000000000013115132733117025034 xustar0030 mtime=1768666703.912620314 30 atime=1787067671.856441152 29 ctime=1787067792.72769399 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-enable.rst0000666000175000017500000000177615132733117024516 0ustar00rgerrger.. _param-mmanon-ipv6-enable: .. _mmanon.parameter.input.ipv6-enable: ipv6.enable =========== .. index:: single: mmanon; ipv6.enable single: ipv6.enable .. summary-start Enables or disables IPv6 address anonymization for the mmanon action. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.enable :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 7.3.7 Description ----------- This parameter controls whether ``mmanon`` will attempt to find and anonymize IPv6 addresses. If set to ``off``, all other ``ipv6.*`` parameters for this action are ignored. Note that this does not affect IPv6 addresses with embedded IPv4 parts, which are controlled by :ref:`embeddedIpv4.enable `. Input usage ----------- .. _mmanon.parameter.input.ipv6-enable-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.enable="off") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-serverport.rst0000644000000000000000000000013215145046112025350 xustar0030 mtime=1771326538.947012786 30 atime=1787067673.152465312 30 ctime=1787067793.421706923 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-serverport.rst0000664000175000017500000000257315145046112025023 0ustar00rgerrger.. _param-ommysql-serverport: .. _ommysql.parameter.input.serverport: ServerPort ========== .. index:: single: ommysql; ServerPort single: ServerPort .. summary-start Selects a non-standard port for the MariaDB/MySQL server connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: serverport :Scope: input :Type: integer :Default: input=0 (system default port) :Required?: no :Introduced: at least 7.x, possibly earlier Description ----------- Permits to select a non-standard port for the MariaDB/MySQL server. The default is 0, which means the system default port is used. There is no need to specify this parameter unless you know the server is running on a non-standard listen port. Input usage ----------- .. _ommysql.parameter.input.serverport-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" serverPort="1234" db="syslog_db" uid="user" pwd="pwd") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommysql.parameter.legacy.actionommysqlserverport: - $ActionOmmysqlServerPort — maps to ServerPort (status: legacy) .. index:: single: ommysql; $ActionOmmysqlServerPort single: $ActionOmmysqlServerPort See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-ruleset.rst0000644000000000000000000000013215132733117024241 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.715475808 30 ctime=1787067792.591691455 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-ruleset.rst0000666000175000017500000000221215132733117023704 0ustar00rgerrger.. _param-imudp-ruleset: .. _imudp.parameter.input.ruleset: Ruleset ======= .. index:: single: imudp; Ruleset single: Ruleset .. summary-start Assigns incoming messages to a specified ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Ruleset :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=RSYSLOG_DefaultRuleset :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Binds the listener to a specific :doc:`ruleset <../../concepts/multi_ruleset>`. Input usage ----------- .. _param-imudp-input-ruleset: .. _imudp.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imudp" Ruleset="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.inputudpserverbindruleset: - $InputUDPServerBindRuleset — maps to Ruleset (status: legacy) .. index:: single: imudp; $InputUDPServerBindRuleset single: $InputUDPServerBindRuleset See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-filecreatemode.rst0000644000000000000000000000013115171370365026414 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.840459496 29 ctime=1787067792.17768374 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-filecreatemode.rst0000664000175000017500000000215315171370365026062 0ustar00rgerrger.. _param-imjournal-filecreatemode: .. _imjournal.parameter.module.filecreatemode: .. meta:: :tag: module:imjournal :tag: parameter:FileCreateMode FileCreateMode ============== .. index:: single: imjournal; FileCreateMode single: FileCreateMode .. summary-start Sets the octal permission mode for the state file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: FileCreateMode :Scope: module :Type: integer :Default: module=0644 :Required?: no :Introduced: 8.2306.0 Description ----------- Defines access permissions for the state file using a four-digit octal value. Actual permissions also depend on the process ``umask``. If in doubt, use ``global(umask="0000")`` at the beginning of the configuration file to remove any restrictions. Module usage ------------ .. _param-imjournal-module-filecreatemode: .. _imjournal.parameter.module.filecreatemode-usage: .. code-block:: rsyslog module(load="imjournal" FileCreateMode="...") Notes ----- - Value is interpreted as an octal number. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-headerless-hostname.rst0000644000000000000000000000013215132411300027003 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.333450044 30 ctime=1787067793.608710407 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-headerless-hostname.rst0000666000175000017500000000211415132411300026447 0ustar00rgerrger.. _param-pmrfc3164-headerless-hostname: .. _pmrfc3164.parameter.module.headerless-hostname: .. _pmrfc3164.parameter.module.headerless.hostname: headerless.hostname =================== .. index:: single: pmrfc3164; headerless.hostname single: headerless.hostname .. summary-start Override the hostname assigned to headerless messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: headerless.hostname :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module= :Required?: no :Introduced: 8.2508.0 Description ----------- By default, rsyslog uses the sender's IP address as the hostname for headerless messages. Set this option to provide a different hostname. Module usage ------------ .. _param-pmrfc3164-module-headerless-hostname: .. _pmrfc3164.parameter.module.headerless-hostname-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" headerless.hostname="example.local") See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-permanentfailuredisablesactio0000644000000000000000000000013215216464435031026 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.785458471 30 ctime=1787067793.517708712 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-permanentfailuredisablesaction.rst0000664000175000017500000000377215216464435031470 0ustar00rgerrger.. _param-omrelp-tls-permanentfailuredisablesaction: .. _omrelp.parameter.action.tls-permanentfailuredisablesaction: .. meta:: :description: Configure whether omrelp disables or suspends an action after TLS authentication failure. :keywords: rsyslog, omrelp, RELP, TLS, authentication failure, action queue TLS.PermanentFailureDisablesAction ================================== .. index:: single: omrelp; TLS.PermanentFailureDisablesAction single: TLS.PermanentFailureDisablesAction .. summary-start Controls whether TLS authentication failures disable the action or suspend it for retry. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.PermanentFailureDisablesAction :Scope: action :Type: boolean :Default: on :Required?: no :Introduced: 8.2606.0 Description ----------- Controls how omrelp handles TLS authentication failures such as certificate validation or permitted peer mismatches. When enabled, the default, omrelp treats these failures as permanent and disables the action. This preserves the historical behavior and prevents continuous retry loops for configuration errors that usually need operator intervention. When disabled, omrelp suspends the action instead. This lets configured action queues continue accepting messages while rsyslog retries according to the action retry settings. Use this mode when certificate or CA changes may be temporary and queued messages should be retained until the TLS configuration is corrected. Action usage ------------ .. _param-omrelp-action-tls-permanentfailuredisablesaction: .. _omrelp.parameter.action.tls-permanentfailuredisablesaction-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls="on" tls.permanentFailureDisablesAction="off") YAML usage ---------- .. code-block:: yaml actions: - type: omrelp target: centralserv tls: "on" tls.permanentFailureDisablesAction: "off" See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-idletimeout.rst0000644000000000000000000000013215241075234025410 xustar0030 mtime=1787067036.579577808 30 atime=1787067036.676579624 30 ctime=1787067791.326667882 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-idletimeout.rst0000664000175000017500000000343115241075234025055 0ustar00rgerrger.. _param-imbeats-idletimeout: .. _imbeats.parameter.input.idletimeout: idleTimeout =========== .. meta:: :description: Close imbeats sessions that make no byte progress for a configured interval. :keywords: rsyslog, imbeats, idleTimeout, session timeout, Lumberjack .. index:: single: imbeats; idleTimeout single: idleTimeout .. summary-start Close an imbeats session when it makes no byte progress for the configured time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: idleTimeout :Scope: input :Type: nonnegative integer :Default: input=60 :Required?: no :Introduced: 8.2608.0 Description ----------- Set the maximum number of seconds that a client session may remain connected without receiving any new bytes. When the timeout expires, ``imbeats`` closes the session and does not acknowledge any incomplete batch. The value ``0`` disables the idle timeout. This progress-based timeout applies even when the session has not started a Lumberjack frame. It pauses while a complete, validated batch is submitted to rsyslog and resumes when ``imbeats`` prepares the acknowledgement, so slow local processing cannot turn a successfully submitted batch into an unacknowledged retransmission. The resumed interval also bounds a client that stops reading its acknowledgement. Use :ref:`param-imbeats-frametimeout` to place an absolute deadline on a partially received frame. Input usage ----------- .. _param-imbeats-input-idletimeout: .. _imbeats.parameter.input.idletimeout-usage: RainerScript: .. code-block:: rsyslog input(type="imbeats" port="5044" idleTimeout="60") YAML: .. code-block:: yaml inputs: - type: imbeats port: 5044 idleTimeout: 60 See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-server.rst0000644000000000000000000000013115132733117025432 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.651474615 30 ctime=1787067792.992698928 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-server.rst0000666000175000017500000000140115132733117025075 0ustar00rgerrger.. _param-omclickhouse-server: .. _omclickhouse.parameter.input.server: server ====== .. index:: single: omclickhouse; server single: server .. summary-start Specifies the address of the ClickHouse server that receives events from this action. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: server :Scope: input :Type: word :Default: localhost :Required?: no :Introduced: not specified Description ----------- The address of a ClickHouse server. Input usage ----------- .. _omclickhouse.parameter.input.server-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" server="clickhouse.example.com") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dynafile-restricttemplatetype.rst0000644000000000000000000000013215241075234031001 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.161702078 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dynafile-restricttemplatetype.rst0000664000175000017500000000365315241075234030454 0ustar00rgerrger.. _param-omfile-dynafile-restricttemplatetype: .. _omfile.parameter.module.dynafile-restricttemplatetype: dynafile.restrictTemplateType ============================= .. meta:: :description: Optionally restrict omfile dynafile templates to string and list types. :keywords: rsyslog, omfile, dynafile, template, path traversal, security .. index:: single: omfile; dynafile.restrictTemplateType single: dynafile.restrictTemplateType .. summary-start Optionally restricts dynafile templates to string and list templates so omfile can inspect their fixed path prefix before opening rendered paths. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dynafile.restrictTemplateType :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: not specified Description ----------- When enabled, omfile accepts only ``type="string"`` and ``type="list"`` templates for the :ref:`param-omfile-dynafile` parameter. These template types expose their constant and property entries to omfile, which lets omfile derive the trusted static directory prefix and block rendered paths that escape it. The default preserves plugin/string-generator and subtree dynafile templates. Those legacy forms use the fallback runtime guard: absolute paths and relative paths that lexically escape through ``..`` are rejected. Use ``dynafile.dangerousPermitPathEscape="on"`` only when an affected legacy configuration must retain that behavior. Enable this option when an installation can use only string or list templates and wants that stricter configuration-time policy. Module usage ------------ .. _param-omfile-module-dynafile-restricttemplatetype: .. _omfile.parameter.module.dynafile-restricttemplatetype-usage: .. code-block:: rsyslog module(load="builtin:omfile" dynafile.restrictTemplateType="on") See also -------- See also :doc:`../../configuration/modules/omfile` and :doc:`omfile-dynafile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-myprivkey.rst0000644000000000000000000000013115132733117025572 xustar0030 mtime=1768666703.903620178 29 atime=1787067672.03444447 30 ctime=1787067792.037681132 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-myprivkey.rst0000666000175000017500000000161115132733117025240 0ustar00rgerrger.. _param-imdtls-tls-myprivkey: .. _imdtls.parameter.input.tls-myprivkey: tls.myPrivKey ============= .. index:: single: imdtls; tls.myPrivKey single: tls.myPrivKey .. summary-start Points to the private key file paired with ``tls.myCert``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.myPrivKey :Scope: input :Type: string :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- The private key file corresponding to ``tls.myCert``. This key is used for the cryptographic operations in the DTLS handshake. Input usage ----------- .. _imdtls.parameter.input.tls-myprivkey-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.myCert="/etc/rsyslog/server.pem" tls.myPrivKey="/etc/rsyslog/server.key") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-conninfo.rst0000644000000000000000000000013115145046112024726 xustar0030 mtime=1771326538.948012803 30 atime=1787067673.316468369 29 ctime=1787067793.43070709 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-conninfo.rst0000664000175000017500000000222615145046112024375 0ustar00rgerrger.. _param-ompgsql-conninfo: .. _ompgsql.parameter.input.conninfo: Conninfo ======== .. index:: single: ompgsql; Conninfo single: Conninfo .. summary-start Defines PostgreSQL connection information as a URI or key-value pairs, taking precedence over ``server``, ``port``, ``db``, and ``pass`` parameters. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: Conninfo :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.32.0 Description ----------- The URI or set of key-value pairs that describe how to connect to the PostgreSQL server. This takes precedence over ``server``, ``port``, ``db``, and ``pass`` parameters. Required if ``server`` and ``db`` are not specified. The format corresponds to `standard PostgreSQL connection string format `_. Input usage ----------- .. _ompgsql.parameter.input.conninfo-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" conninfo="postgresql://rsyslog:test1234@localhost/syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-mode.rst0000644000000000000000000000013215132733117025623 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.577454593 30 ctime=1787067792.806695462 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-mode.rst0000666000175000017500000000245215132733117025274 0ustar00rgerrger.. _param-mmjsontransform-mode: .. _mmjsontransform.parameter.input.mode: mode ==== .. index:: single: mmjsontransform; mode single: mode .. summary-start Chooses whether dotted keys are expanded or flattened during processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: mode :Scope: input :Type: string :Default: unflatten :Required?: no :Introduced: 8.2410.0 Description ----------- Controls the transformation direction used by ``mmjsontransform``: ``unflatten`` (default) Expands dotted keys into nested containers. See :ref:`mmjsontransform-mode-unflatten` for details. ``flatten`` Collapses nested containers back into dotted keys. See :ref:`mmjsontransform-mode-flatten` for the full description. The comparison is case-insensitive. Omitting the parameter or providing an empty string selects ``unflatten``. Any other value triggers a configuration error. Input usage ----------- .. _param-mmjsontransform-mode-usage: .. _mmjsontransform.parameter.input.mode-usage: .. code-block:: rsyslog action(type="mmjsontransform" mode="flatten" input="$!normalized" output="$!normalized_flat") See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-maxframesize.rst0000644000000000000000000000013215132733117025427 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.676475081 30 ctime=1787067792.356687076 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-maxframesize.rst0000666000175000017500000000216015132733117025074 0ustar00rgerrger.. _param-imptcp-maxframesize: .. _imptcp.parameter.input.maxframesize: MaxFrameSize ============ .. index:: single: imptcp; MaxFrameSize single: MaxFrameSize .. summary-start Sets the maximum frame size when using octet counted mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: MaxFrameSize :Scope: input :Type: integer :Default: input=200000 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- When in octet counted mode, the frame size is given at the beginning of the message. With this parameter the max size this frame can have is specified and when the frame gets too large the mode is switched to octet stuffing. The max value this parameter can have was specified because otherwise the integer could become negative and this would result in a Segmentation Fault. (Max Value: 200000000) Input usage ----------- .. _param-imptcp-input-maxframesize: .. _imptcp.parameter.input.maxframesize-usage: .. code-block:: rsyslog input(type="imptcp" maxFrameSize="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-label-origin.rst0000644000000000000000000000013215145046112026621 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.504471874 30 ctime=1787067792.289685828 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-label-origin.rst0000664000175000017500000000156515145046112026274 0ustar00rgerrger.. _param-impstats-push-label-origin: .. _impstats.parameter.module.push-label-origin: push.label.origin ================= .. index:: single: impstats; push.label.origin single: push.label.origin .. summary-start Controls whether impstats adds the stats origin as an ``origin`` label. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.label.origin :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2602.0 Description ----------- When enabled, impstats injects the statsobj origin as the ``origin`` label unless one is already set via ``push.labels``. Module usage ------------ .. _impstats.parameter.module.push-label-origin-usage: .. code-block:: rsyslog module(load="impstats" push.label.origin="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-retry-addmetadata.rst0000644000000000000000000000012715132733117026353 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.149465256 28 ctime=1787067793.2917045 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-retry-addmetadata.rst0000666000175000017500000000201615132733117026014 0ustar00rgerrger.. _param-omhttp-retry-addmetadata: .. _omhttp.parameter.input.retry-addmetadata: retry.addmetadata ================= .. index:: single: omhttp; retry.addmetadata single: retry.addmetadata .. summary-start Adds HTTP response metadata to ``$!omhttp!response`` for messages handled by the retry logic. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: retry.addmetadata :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- When this option is enabled, omhttp will add the response metadata to ``$!omhttp!response``. There are three response metadata fields added: ``code``, ``body``, ``batch_index``. Input usage ----------- .. _omhttp.parameter.input.retry-addmetadata-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" retry="on" retryRuleSet="rs_omhttp_retry" retryAddMetadata="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhdfs-omhdfsdefaulttemplate.rst0000644000000000000000000000013215132733117027301 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.946461472 30 ctime=1787067793.219703158 rsyslog-8.2608.0/doc/source/reference/parameters/omhdfs-omhdfsdefaulttemplate.rst0000666000175000017500000000273415132733117026755 0ustar00rgerrger.. _param-omhdfs-omhdfsdefaulttemplate: .. _omhdfs.parameter.module.omhdfsdefaulttemplate: omhdfsDefaultTemplate ===================== .. index:: single: omhdfs; omhdfsDefaultTemplate single: omhdfsDefaultTemplate .. summary-start Sets the template omhdfs applies when no template is specified for an action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhdfs`. :Name: omhdfsDefaultTemplate :Scope: module :Type: word :Default: RSYSLOG_FileFormat :Required?: no :Introduced: Not documented Description ----------- Default template to be used when none is specified. This saves the work of specifying the same template repeatedly. Of course, the default template can be overwritten by specifying a template directly on an action. Module usage ------------ .. _omhdfs.parameter.module.omhdfsdefaulttemplate-usage: .. code-block:: none $ModLoad omhdfs $omhdfsFileName /var/log/hdfs/system.log $omhdfsDefaultTemplate RSYSLOG_FileFormat # write all messages to HDFS using the custom default template *.* :omhdfs: Legacy names (for reference) ---------------------------- Historic names/directives for compatibility. Do not use in new configs. .. _omhdfs.parameter.legacy.omhdfsdefaulttemplate: - ``$OMHDFSDefaultTemplate`` — maps to ``omhdfsDefaultTemplate`` (status: legacy) .. index:: single: omhdfs; $OMHDFSDefaultTemplate single: $OMHDFSDefaultTemplate See also -------- See also :doc:`../../configuration/modules/omhdfs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-port.rst0000644000000000000000000000013115132733117023734 xustar0030 mtime=1768666703.923620481 29 atime=1787067671.75443925 30 ctime=1787067793.546709252 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-port.rst0000666000175000017500000000202615132733117023403 0ustar00rgerrger.. _param-omsnmp-port: .. _omsnmp.parameter.module.port: Port ==== .. index:: single: omsnmp; Port single: Port .. summary-start Specifies the port used for sending SNMP traps. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Port :Scope: module :Type: integer :Default: module=162 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- The port which will be used, common values are port 162 or 161. Module usage ------------ .. _param-omsnmp-module-port: .. _omsnmp.parameter.module.port-usage: .. code-block:: rsyslog action(type="omsnmp" port="162") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmptargetport: - $actionsnmptargetport — maps to Port (status: legacy) .. index:: single: omsnmp; $actionsnmptargetport single: $actionsnmptargetport See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ignoreownmessages.rst0000644000000000000000000000013215132733117027041 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.014481382 30 ctime=1787067792.611691828 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ignoreownmessages.rst0000666000175000017500000000213615132733117026511 0ustar00rgerrger.. _param-imuxsock-ignoreownmessages: .. _imuxsock.parameter.input.ignoreownmessages: IgnoreOwnMessages ================= .. index:: single: imuxsock; IgnoreOwnMessages single: IgnoreOwnMessages .. summary-start Suppresses messages that originated from the same rsyslog instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: IgnoreOwnMessages :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 7.3.7 Description ----------- Ignore messages that originated from the same instance of rsyslogd. There usually is no reason to receive messages from ourselves. This setting is vital when writing messages to the systemd journal. .. seealso:: See :doc:`omjournal <../../configuration/modules/omjournal>` module documentation for a more in-depth description. Input usage ----------- .. _param-imuxsock-input-ignoreownmessages: .. _imuxsock.parameter.input.ignoreownmessages-usage: .. code-block:: rsyslog input(type="imuxsock" ignoreOwnMessages="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-name.rst0000644000000000000000000000013215132733117023654 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.906442084 30 ctime=1787067792.022680852 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-name.rst0000666000175000017500000000140715132733117023324 0ustar00rgerrger.. _param-imdtls-name: .. _imdtls.parameter.input.name: Name ==== .. index:: single: imdtls; name single: name .. summary-start Assigns a unique identifier to the imdtls input instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: name :Scope: input :Type: word :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Provides a unique name to the input module instance. This is useful for identifying the source of messages when multiple input modules are used. Input usage ----------- .. _imdtls.parameter.input.name-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" name="dtlsListener01") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-compression-driver.rst0000644000000000000000000000013115132411300026527 xustar0030 mtime=1768559296.209884738 29 atime=1787067672.38045092 30 ctime=1787067793.136701612 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-compression-driver.rst0000666000175000017500000000222215132411300026174 0ustar00rgerrger.. _param-omfile-compression-driver: .. _omfile.parameter.module.compression-driver: compression.driver ================== .. index:: single: omfile; compression.driver single: compression.driver .. summary-start For compressed operation ("zlib mode"), this permits to set the compression driver to be used. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: compression.driver :Scope: module :Type: word :Default: module=zlib :Required?: no :Introduced: 8.2208.0 Description ----------- For compressed operation ("zlib mode"), this permits to set the compression driver to be used. Originally, only zlib was supported and still is the default. Since 8.2208.0 zstd is also supported. It provides much better compression ratios and performance, especially with multiple zstd worker threads enabled. Possible values are: - zlib - zstd Module usage ------------ .. _param-omfile-module-compression-driver: .. _omfile.parameter.module.compression-driver-usage: .. code-block:: rsyslog module(load="builtin:omfile" compression.driver="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-keepalive-time.rst0000644000000000000000000000013215132733117025631 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.966480487 30 ctime=1787067792.403687952 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-keepalive-time.rst0000666000175000017500000000222315132733117025276 0ustar00rgerrger.. _param-imrelp-keepalive-time: .. _imrelp.parameter.input.keepalive-time: keepAlive.time ============== .. index:: single: imrelp; keepAlive.time single: keepAlive.time .. summary-start Controls how long a connection stays idle before the first keep-alive probe is sent. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: keepAlive.time :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: Not documented Description ----------- The interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked with keep-alive, this counter is not used any further. The default, 0, means that the operating system defaults are used. This only has an effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imrelp-input-keepalive-time-usage: .. _imrelp.parameter.input.keepalive-time-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" keepAlive="on" keepAlive.time="600") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdblookup-fields.rst0000644000000000000000000000013115132733117025056 xustar0030 mtime=1768666703.913620329 29 atime=1787067672.18944736 30 ctime=1787067792.760694605 rsyslog-8.2608.0/doc/source/reference/parameters/mmdblookup-fields.rst0000666000175000017500000000322515132733117024527 0ustar00rgerrger.. _param-mmdblookup-fields: .. _mmdblookup.parameter.input.fields: fields ====== .. index:: single: mmdblookup; fields single: fields .. summary-start Defines the list of database fields whose values are appended to the message. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdblookup`. :Name: fields :Scope: input :Type: array (word) :Default: none :Required?: yes :Introduced: 8.24.0 Description ----------- This parameter specifies the fields that will be appended to processed messages. The fields will always be appended in the container used by mmdblookup (which may be overridden by the ``container`` parameter on module load). By default, the lookup path (without a leading exclamation mark (``!``), if present) is used as the name for the resulting JSON property. This can be overridden by specifying a custom name. Use the following syntax to control the resulting variable name and lookup path: * ``:customName:!path!to!field`` — specify the custom variable name enclosed in colons, followed by the MaxMind DB path. * Exclamation marks (``!``) denote path levels within the database record. For example, to extract ``!city!names!en`` but rename it to ``cityname``, use ``:cityname:!city!names!en`` as the field value. Input usage ----------- .. _mmdblookup.parameter.input.fields-usage: .. code-block:: rsyslog action(type="mmdblookup" key="!clientip" mmdbFile="/etc/rsyslog.d/GeoLite2-City.mmdb" fields=[":continent:!continent!code", "!country!iso_code", ":loc:!location"]) See also -------- See also :doc:`../../configuration/modules/mmdblookup`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-uid.rst0000644000000000000000000000013215132733117023534 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.613455264 30 ctime=1787067793.317704985 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-uid.rst0000666000175000017500000000126315132733117023204 0ustar00rgerrger.. _param-omhttp-uid: .. _omhttp.parameter.input.uid: uid === .. index:: single: omhttp; uid single: uid .. summary-start Provides the username for HTTP basic authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: uid :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The username for basic auth. Input usage ----------- .. _omhttp.parameter.input.uid-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" uid="api-user" pwd="secret" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-fields.rst0000644000000000000000000000013115145046112024517 xustar0030 mtime=1771326538.943012721 29 atime=1787067672.13044626 30 ctime=1787067792.744694307 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-fields.rst0000664000175000017500000000372315145046112024171 0ustar00rgerrger.. _param-mmdarwin-fields: .. _mmdarwin.parameter.input.fields: fields ====== .. index:: single: mmdarwin; fields single: fields .. summary-start Defines the array of values that mmdarwin forwards to Darwin as parameters. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: fields :Scope: input :Type: array :Default: input=none :Required?: yes :Introduced: at least 8.x, possibly earlier Description ----------- Array containing values to be sent to Darwin as parameters. Two types of values can be set: * if it starts with a bang (``"!"``) or a dot (``"."``), mmdarwin will search in the JSON-parsed log line (``"!"``) or in rsyslog local variables (``"."``) for the associated value. For nested properties, use additional bangs as separators (for example, ``"!data!status"`` reads the ``"status"`` property inside the ``"data"`` object). * otherwise, the value is considered static, and will be forwarded directly to Darwin. For example, given the following log line: .. code-block:: json { "from": "192.168.1.42", "date": "2012-12-21 00:00:00", "status": "200", "data": { "status": true, "message": "Request processed correctly" } } and the ``"fields"`` array: .. code-block:: none ["!from", "!data!status", "rsyslog"] The parameters sent to Darwin would be ``"192.168.1.42"``, ``true`` and ``"rsyslog"``. .. note:: The order of the parameters is important and must match the order expected by the Darwin filter. Refer to `Darwin documentation`_ to see what each filter requires as parameters. .. _`Darwin documentation`: https://github.com/VultureProject/darwin/wiki Input usage ----------- .. _param-mmdarwin-input-fields-usage: .. _mmdarwin.parameter.input.fields-usage: .. code-block:: rsyslog action(type="mmdarwin" fields=["!from", "!data!status", "rsyslog"]) See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-framingfix-cisco-asa.rst0000644000000000000000000000013215132733117026726 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.789477187 30 ctime=1787067792.343686834 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-framingfix-cisco-asa.rst0000666000175000017500000000202415132733117026372 0ustar00rgerrger.. _param-imptcp-framingfix-cisco-asa: .. _imptcp.parameter.input.framingfix-cisco-asa: Framingfix.cisco.asa ==================== .. index:: single: imptcp; Framingfix.cisco.asa single: Framingfix.cisco.asa .. summary-start Ignores a leading space after a line feed to work around Cisco ASA framing issues. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Framingfix.cisco.asa :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Cisco very occasionally sends a space after a line feed, which thrashes framing if not taken special care of. When this parameter is set to "on", we permit space *in front of the next frame* and ignore it. Input usage ----------- .. _param-imptcp-input-framingfix-cisco-asa: .. _imptcp.parameter.input.framingfix-cisco-asa-usage: .. code-block:: rsyslog input(type="imptcp" framingfix.cisco.asa="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-usepidfromsystem.rst0000644000000000000000000000013215132733117026724 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.874478772 30 ctime=1787067792.670692928 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-usepidfromsystem.rst0000666000175000017500000000266215132733117026400 0ustar00rgerrger.. _param-imuxsock-usepidfromsystem: .. _imuxsock.parameter.input.usepidfromsystem: UsePIDFromSystem ================ .. index:: single: imuxsock; UsePIDFromSystem single: UsePIDFromSystem .. summary-start Obtains the process ID from the log socket instead of the message. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: UsePIDFromSystem :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies if the pid being logged shall be obtained from the log socket itself. If so, the TAG part of the message is rewritten. It is recommended to turn this option on, but the default is "off" to keep compatible with earlier versions of rsyslog. Input usage ----------- .. _param-imuxsock-input-usepidfromsystem: .. _imuxsock.parameter.input.usepidfromsystem-usage: .. code-block:: rsyslog input(type="imuxsock" usePidFromSystem="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketusepidfromsystem: - $InputUnixListenSocketUsePIDFromSystem — maps to UsePIDFromSystem (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketUsePIDFromSystem single: $InputUnixListenSocketUsePIDFromSystem See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-name.rst0000644000000000000000000000013215132733117023654 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.661474801 30 ctime=1787067792.363687207 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-name.rst0000666000175000017500000000245515132733117023330 0ustar00rgerrger.. _param-imptcp-name: .. _imptcp.parameter.input.name: Name ==== .. index:: single: imptcp; Name single: Name .. summary-start Sets the inputname property used for tagging messages and statistics. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Name :Scope: input :Type: string :Default: input=imptcp :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets a name for the inputname property. If no name is set "imptcp" is used by default. Setting a name is not strictly necessary, but can be useful to apply filtering based on which input the message was received from. Note that the name also shows up in :doc:`impstats <../../configuration/modules/impstats>` logs. Input usage ----------- .. _param-imptcp-input-name: .. _imptcp.parameter.input.name-usage: .. code-block:: rsyslog input(type="imptcp" name="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverinputname: - $InputPTCPServerInputName — maps to Name (status: legacy) .. index:: single: imptcp; $InputPTCPServerInputName single: $InputPTCPServerInputName See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-statefile.rst0000644000000000000000000000013215132733117024665 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.518453493 30 ctime=1787067792.118682641 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-statefile.rst0000666000175000017500000000327115132733117024336 0ustar00rgerrger.. _param-imfile-statefile: .. _imfile.parameter.input.statefile: .. _imfile.parameter.statefile: stateFile ========= .. index:: single: imfile; stateFile single: stateFile .. summary-start Deprecated; sets a fixed state file name for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: stateFile :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the name of this file's state file. This parameter should usually **not** be used. When wildcards are present in the monitored file name, all matching files share the same state file, which typically causes confusion and is unlikely to work properly. Upon startup, rsyslog tries to detect such cases and emits warning messages, but complex wildcard patterns may go unnoticed. For details, see :ref:`State-Files` in the module documentation. Input usage ----------- .. _param-imfile-input-statefile: .. _imfile.parameter.input.statefile-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" stateFile="/path/to/state") Notes ----- - Deprecated; rely on automatically generated state file names instead. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilestatefile: - ``$InputFileStateFile`` — maps to stateFile (status: legacy) .. index:: single: imfile; $InputFileStateFile single: $InputFileStateFile See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-template.rst0000644000000000000000000000013215132411300026404 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.067445085 30 ctime=1787067793.097700885 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-template.rst0000666000175000017500000000157015132411300026055 0ustar00rgerrger.. _param-omelasticsearch-template: .. _omelasticsearch.parameter.module.template: template ======== .. index:: single: omelasticsearch; template single: template .. summary-start Template used to render the JSON document sent to Elasticsearch. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: template :Scope: action :Type: word :Default: action=StdJSONFmt :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Defines the rsyslog template that generates the JSON payload. The default `StdJSONFmt` includes common fields. Action usage ------------ .. _param-omelasticsearch-action-template: .. _omelasticsearch.parameter.action.template: .. code-block:: rsyslog action(type="omelasticsearch" template="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-persiststateaftersubmission.rst0000644000000000000000000000013215132733117030575 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.503453213 30 ctime=1787067792.093682175 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-persiststateaftersubmission.rst0000666000175000017500000000252115132733117030243 0ustar00rgerrger.. _param-imfile-persiststateaftersubmission: .. _imfile.parameter.input.persiststateaftersubmission: .. _imfile.parameter.persiststateaftersubmission: persistStateAfterSubmission =========================== .. index:: single: imfile; persistStateAfterSubmission single: persistStateAfterSubmission .. summary-start Persists state file information after each batch submission for robustness. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: persistStateAfterSubmission :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: 8.2006.0 Description ----------- When switched ``on``, imfile persists state file information after a batch of messages has been submitted. This enhances robustness against unclean shutdowns, but may cause frequent state file writes and degrade performance, depending on overall rsyslog configuration. Input usage ----------- .. _param-imfile-input-persiststateaftersubmission: .. _imfile.parameter.input.persiststateaftersubmission-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" persistStateAfterSubmission="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-address.rst0000644000000000000000000000013215132733117024203 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.132483581 30 ctime=1787067792.557690822 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-address.rst0000666000175000017500000000220415132733117023647 0ustar00rgerrger.. _param-imudp-address: .. _imudp.parameter.input.address: Address ======= .. index:: single: imudp; Address single: Address .. summary-start Local address that UDP server binds to; ``*`` uses all interfaces. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Address :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Local IP address (or name) the UDP server should bind to. Use ``*`` to bind to all of the machine's addresses. Input usage ----------- .. _param-imudp-input-address: .. _imudp.parameter.input.address-usage: .. code-block:: rsyslog input(type="imudp" Address="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.udpserveraddress: - $UDPServerAddress — maps to Address (status: legacy) .. index:: single: imudp; $UDPServerAddress single: $UDPServerAddress See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-skipverifyhost.rst0000644000000000000000000000013215132411300027662 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.169446987 30 ctime=1787067793.095700848 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-skipverifyhost.rst0000666000175000017500000000161215132411300027330 0ustar00rgerrger.. _param-omelasticsearch-skipverifyhost: .. _omelasticsearch.parameter.module.skipverifyhost: skipverifyhost ============== .. index:: single: omelasticsearch; skipverifyhost single: skipverifyhost .. summary-start Disable TLS host name verification (insecure, for testing). .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: skipverifyhost :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Sets the curl `CURLOPT_SSL_VERIFYHOST` option to `0`. Use only for debugging. Action usage ------------ .. _param-omelasticsearch-action-skipverifyhost: .. _omelasticsearch.parameter.action.skipverifyhost: .. code-block:: rsyslog action(type="omelasticsearch" skipverifyhost="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-filtercode.rst0000644000000000000000000000013215145046112025372 xustar0030 mtime=1771326538.943012721 30 atime=1787067672.122446111 30 ctime=1787067792.746694344 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-filtercode.rst0000664000175000017500000000170415145046112025040 0ustar00rgerrger.. _param-mmdarwin-filtercode: .. _mmdarwin.parameter.input.filtercode: filtercode ========== .. index:: single: mmdarwin; filtercode single: filtercode .. summary-start Sets the legacy Darwin filter code expected by older Darwin filters. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: filtercode :Scope: input :Type: word :Default: input=0x00000000 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Each Darwin module has a unique filter code. For example, the code of the hostlookup filter is ``"0x66726570"``. This code was mandatory but is now obsolete. It can be omitted or left at its default value. Input usage ----------- .. _param-mmdarwin-input-filtercode-usage: .. _mmdarwin.parameter.input.filtercode-usage: .. code-block:: rsyslog action(type="mmdarwin" filterCode="0x72657075") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-dcr_id.rst0000644000000000000000000000013215171370365025027 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.491471632 30 ctime=1787067792.948698108 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-dcr_id.rst0000664000175000017500000000174515171370365024502 0ustar00rgerrger.. _param-omazuredce-dcr_id: .. _omazuredce.parameter.action.dcr_id: .. meta:: :description: Reference for the omazuredce dcr_id parameter. :keywords: rsyslog, omazuredce, dcr_id, azure, logs ingestion dcr_id ====== .. index:: single: omazuredce; dcr_id single: dcr_id .. summary-start Specifies the Azure Data Collection Rule immutable ID used in the ingestion URL. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: dcr_id :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``dcr_id`` identifies the Data Collection Rule that receives the uploaded log records. The value is inserted into the request path under ``dataCollectionRules/``. Action usage ------------ .. _omazuredce.parameter.action.dcr_id-usage: .. code-block:: rsyslog action(type="omazuredce" dcr_id="" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-ratelimit-interval.rst0000644000000000000000000000013215132411300030405 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.209447732 30 ctime=1787067793.072700419 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-ratelimit-interval.rst0000666000175000017500000000176615132411300030065 0ustar00rgerrger.. _param-omelasticsearch-ratelimit-interval: .. _omelasticsearch.parameter.module.ratelimit-interval: .. _omelasticsearch.parameter.module.ratelimit.interval: ratelimit.interval ================== .. index:: single: omelasticsearch; ratelimit.interval single: ratelimit.interval .. summary-start Seconds over which retry rate limiting is calculated. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: ratelimit.interval :Scope: action :Type: integer :Default: action=600 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Defines the interval for rate limiting when `retryfailures` is enabled. Set to `0` to disable. Action usage ------------ .. _param-omelasticsearch-action-ratelimit-interval: .. _omelasticsearch.parameter.action.ratelimit-interval: .. code-block:: rsyslog action(type="omelasticsearch" ratelimit.interval="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-dhbits.rst0000644000000000000000000000013215132733117025005 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.911479462 30 ctime=1787067792.430688455 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-dhbits.rst0000666000175000017500000000245015132733117024454 0ustar00rgerrger.. _param-imrelp-tls-dhbits: .. _imrelp.parameter.input.tls-dhbits: tls.dhBits ========== .. index:: single: imrelp; tls.dhBits single: tls.dhBits .. summary-start Specifies the Diffie-Hellman key size, overriding the librelp default when set. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.dhBits :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: Not documented Description ----------- This setting controls how many bits are used for Diffie-Hellman key generation. If not set, the librelp default is used. For security reasons, at least 1024 bits should be used. Please note that the number of bits must be supported by GnuTLS. If an invalid number is given, rsyslog will report an error when the listener is started. We do this to be transparent to changes/upgrades in GnuTLS (to check at config processing time, we would need to hardcode the supported bits and keep them in sync with GnuTLS - this is even impossible when custom GnuTLS changes are made...). Input usage ----------- .. _param-imrelp-input-tls-dhbits-usage: .. _imrelp.parameter.input.tls-dhbits-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.dhBits="2048") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhdfs-omhdfsfilename.rst0000644000000000000000000000013215132733117025701 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.935461267 30 ctime=1787067793.221703196 rsyslog-8.2608.0/doc/source/reference/parameters/omhdfs-omhdfsfilename.rst0000666000175000017500000000220715132733117025350 0ustar00rgerrger.. _param-omhdfs-omhdfsfilename: .. _omhdfs.parameter.module.omhdfsfilename: omhdfsFileName ============== .. index:: single: omhdfs; omhdfsFileName single: omhdfsFileName .. summary-start Sets the HDFS path of the file that omhdfs writes log messages to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhdfs`. :Name: omhdfsFileName :Scope: module :Type: word :Required?: yes :Introduced: Not documented Description ----------- The name of the file to which the output data shall be written. Module usage ------------ .. _omhdfs.parameter.module.omhdfsfilename-usage: .. code-block:: none $ModLoad omhdfs $omhdfsFileName /var/log/hdfs/system.log # write all messages to the specified HDFS file *.* :omhdfs: Legacy names (for reference) ---------------------------- Historic names/directives for compatibility. Do not use in new configs. .. _omhdfs.parameter.legacy.omhdfsfilename: - ``$OMHDFSFileName`` — maps to ``omhdfsFileName`` (status: legacy) .. index:: single: omhdfs; $OMHDFSFileName single: $OMHDFSFileName See also -------- See also :doc:`../../configuration/modules/omhdfs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-parsehostname.rst0000644000000000000000000000013215132733117026153 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.044481941 30 ctime=1787067792.615691903 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-parsehostname.rst0000666000175000017500000000155515132733117025627 0ustar00rgerrger.. _param-imuxsock-parsehostname: .. _imuxsock.parameter.input.parsehostname: ParseHostname ============= .. index:: single: imuxsock; ParseHostname single: ParseHostname .. summary-start Expects hostnames in messages when the special parser is disabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: ParseHostname :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.9.0 Description ----------- Equivalent to the ``SysSock.ParseHostname`` module parameter, but applies to the input that is being defined. .. versionadded:: 8.9.0 Input usage ----------- .. _param-imuxsock-input-parsehostname: .. _imuxsock.parameter.input.parsehostname-usage: .. code-block:: rsyslog input(type="imuxsock" parseHostname="on") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-rotation-sizelimitcommandpassfile0000644000000000000000000000013215145046112031034 xustar0030 mtime=1771326538.945012754 30 atime=1787067672.511453362 30 ctime=1787067793.197702748 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-rotation-sizelimitcommandpassfilename.rst0000664000175000017500000000243015145046112032147 0ustar00rgerrger.. _param-omfile-rotation-sizelimitcommandpassfilename: .. _omfile.parameter.module.rotation-sizelimitcommandpassfilename: rotation.sizeLimitCommandPassFileName ===================================== .. index:: single: omfile; rotation.sizeLimitCommandPassFileName single: rotation.sizeLimitCommandPassFileName .. summary-start Controls whether the current file name is passed as an argument to `rotation.sizeLimitCommand`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: rotation.sizeLimitCommandPassFileName :Scope: action :Type: boolean :Default: action=on :Required?: no :Introduced: 8.x (2026-01-28) Description ----------- When enabled, the file name that exceeded `rotation.sizeLimit` is appended as the last argument to `rotation.sizeLimitCommand`. Any arguments specified as part of `rotation.sizeLimitCommand` are retained and passed first. Set to ``off`` to preserve scripts that expect no additional arguments. Action usage ------------ .. _param-omfile-action-rotation-sizelimitcommandpassfilename: .. _omfile.parameter.action.rotation-sizelimitcommandpassfilename: .. code-block:: rsyslog action(type="omfile" rotation.sizeLimitCommandPassFileName="on") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdblookup-reloadonhup.rst0000644000000000000000000000013115132733117026130 xustar0030 mtime=1768666703.913620329 29 atime=1787067672.19644749 30 ctime=1787067792.767694735 rsyslog-8.2608.0/doc/source/reference/parameters/mmdblookup-reloadonhup.rst0000666000175000017500000000221215132733117025574 0ustar00rgerrger.. _param-mmdblookup-reloadonhup: .. _mmdblookup.parameter.input.reloadonhup: reloadonhup =========== .. index:: single: mmdblookup; reloadonhup single: reloadonhup .. summary-start Controls whether mmdblookup reopens the MaxMind database after a HUP signal. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdblookup`. :Name: reloadonhup :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: 8.24.0 Description ----------- When this setting is ``on``, the action closes and reopens the configured MaxMind DB file whenever rsyslog receives a HUP signal. This lets updated GeoIP data become effective without restarting the daemon. Set it to ``off`` if you prefer to keep the currently loaded database until the action is restarted manually. Input usage ----------- .. _mmdblookup.parameter.input.reloadonhup-usage: .. code-block:: rsyslog action(type="mmdblookup" key="!clientip" mmdbFile="/etc/rsyslog.d/GeoLite2-City.mmdb" fields=["!continent!code", "!location"] reloadOnHup="off") See also -------- See also :doc:`../../configuration/modules/mmdblookup`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-timeout.rst0000644000000000000000000000012715132733117025617 xustar0029 mtime=1768666703.91562036 29 atime=1787067673.66947495 29 ctime=1787067792.99869904 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-timeout.rst0000666000175000017500000000146015132733117025262 0ustar00rgerrger.. _param-omclickhouse-timeout: .. _omclickhouse.parameter.input.timeout: timeout ======= .. index:: single: omclickhouse; timeout single: timeout .. summary-start Configures the send timeout, in milliseconds, for ClickHouse HTTP requests. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: timeout :Scope: input :Type: int (milliseconds) :Default: 0 :Required?: no :Introduced: not specified Description ----------- This parameter sets the timeout for sending data to ClickHouse. Value is given in milliseconds. Input usage ----------- .. _omclickhouse.parameter.input.timeout-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" timeout="4500") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssservermaxsessions.rst0000644000000000000000000000013115171370365030660 xustar0030 mtime=1776677109.116908069 29 atime=1787067672.60145504 30 ctime=1787067792.142683088 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssservermaxsessions.rst0000664000175000017500000000224415171370365030327 0ustar00rgerrger.. _param-imgssapi-inputgssservermaxsessions: .. _imgssapi.parameter.input.inputgssservermaxsessions: InputGSSServerMaxSessions ========================= .. index:: single: imgssapi; InputGSSServerMaxSessions single: InputGSSServerMaxSessions .. summary-start Sets the maximum number of concurrent sessions supported by the server. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerMaxSessions :Scope: input :Type: integer :Default: 200 :Required?: no :Introduced: 3.11.5 Description ----------- Sets the maximum number of concurrent sessions supported by the listener. Input usage ----------- .. _imgssapi.parameter.input.inputgssservermaxsessions-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssServerMaxSessions 200 Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssservermaxsessions: - $inputGssServerMaxSessions — maps to InputGSSServerMaxSessions (status: legacy) .. index:: single: imgssapi; $inputGssServerMaxSessions single: $inputGssServerMaxSessions See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dynafile.rst0000644000000000000000000000013115241075234024505 xustar0030 mtime=1787067036.581577845 29 atime=1787067036.72658056 30 ctime=1787067793.163702115 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dynafile.rst0000664000175000017500000001041615241075234024154 0ustar00rgerrger.. _param-omfile-dynafile: .. _omfile.parameter.module.dynafile: dynaFile ======== .. index:: single: omfile; dynaFile single: dynaFile .. summary-start For each message, the file name is generated based on the given template. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dynaFile :Scope: action :Type: string :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- For each message, the file name is generated based on the given template. Then, this file is opened. As with the *file* property, data is appended if the file already exists. If the file does not exist, a new file is created. The template given in "templateName" is just a regular :doc:`rsyslog template <../../configuration/templates>`, so you have full control over how to format the file name. To avoid path traversal attacks, *you must make sure that the template properly escapes every message-derived path component*. In string templates, use the *secpath-replace* property replacer option. In list templates, use ``securePath="replace"`` on the corresponding ``property()`` statements. Apply this to all fields that can come from the message or sender, such as ``HOSTNAME``, ``programname``, ``APP-NAME``, or parsed variables. Keep fixed directory separators in constant text. By default, omfile also performs lexical containment checks for dynafile paths. The rendered path must remain below the fixed leading directory prefix that was configured in the dynafile template. This blocks remote path traversal through components such as ``..`` or unexpected leading slashes in message-derived fields, but it is not a filesystem sandbox. It does not protect against symlinks, bind mounts, time-of-check/time-of-use races, or malicious local filesystem state. For untrusted inputs, ``secpath-replace`` or ``securePath="replace"`` remains the strongest recommended pattern. Backward-compatibility change ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Opaque legacy templates (subtree and plugin/string-generator templates) do not provide a fixed prefix that omfile can inspect. They remain supported, but their fallback guard rejects output paths that are absolute or lexically escape through ``..``. This deliberately changes the historical behavior of affected legacy configurations. To preserve such a configuration temporarily, set :ref:`param-omfile-dynafile-dangerouspermitpathescape` to ``on`` on the affected action (or module). That opt-in disables the guard for that action; use it only with trusted path data. .. code-block:: rsyslog template(name="DynFile" type="string" string="/var/log/hosts/%HOSTNAME:::secpath-replace%/%programname:::secpath-replace%.log") template(name="DynFileList" type="list") { constant(value="/var/log/hosts/") property(name="hostname" securePath="replace") constant(value="/") property(name="programname" securePath="replace") constant(value=".log") } When ``global(compatibility.defaults.secure="strict")`` is active, dynafile templates default fields without explicit secure path handling to ``secpath-replace``. The ``warn`` setting keeps the historical default and emits a warning for dynafile templates that need an explicit ``securepath`` or ``secpath-*`` option. The ``backward-compatible`` setting keeps the historical default silently. If the same template is used both for ``dynaFile`` and for non-dynafile output, rsyslog emits a warning. In strict mode the secure dynafile default still applies to that shared template. Use separate templates when non-dynafile output must preserve literal slashes. Either file or dynaFile can be used, but not both. If both are given, dynaFile will be used. A cache of recent files is kept. Note that this cache can consume quite some memory (especially if large buffer sizes are used). Files are kept open as long as they stay inside the cache. Files are removed from the cache when a HUP signal is sent, the *closeTimeout* occurs, or the cache runs out of space, in which case the least recently used entry is evicted. Action usage ------------ .. _param-omfile-action-dynafile: .. _omfile.parameter.action.dynafile: .. code-block:: rsyslog action(type="omfile" dynaFile="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-path.rst0000644000000000000000000000013215132733117023670 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.612473887 30 ctime=1787067792.370687337 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-path.rst0000666000175000017500000000136215132733117023340 0ustar00rgerrger.. _param-imptcp-path: .. _imptcp.parameter.input.path: Path ==== .. index:: single: imptcp; Path single: Path .. summary-start Specifies a Unix-domain socket path for the listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Path :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- A path on the filesystem for a unix domain socket. It is an error to specify both ``path`` and ``port``. Input usage ----------- .. _param-imptcp-input-path: .. _imptcp.parameter.input.path-usage: .. code-block:: rsyslog input(type="imptcp" path="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-detect-yearaftertimestamp.rst0000644000000000000000000000013115132411300030223 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.323449858 29 ctime=1787067793.59971024 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-detect-yearaftertimestamp.rst0000666000175000017500000000240415132411300027672 0ustar00rgerrger.. _param-pmrfc3164-detect-yearaftertimestamp: .. _pmrfc3164.parameter.module.detect-yearaftertimestamp: .. _pmrfc3164.parameter.module.detect.YearAfterTimestamp: detect.YearAfterTimestamp ========================= .. index:: single: pmrfc3164; detect.YearAfterTimestamp single: detect.YearAfterTimestamp .. summary-start Treat a year following the timestamp as part of the timestamp instead of the hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: detect.YearAfterTimestamp :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Some devices append the year directly after the timestamp, which would otherwise be parsed as the hostname. When enabled, years between 2000 and 2099 are treated as part of the timestamp. Module usage ------------ .. _param-pmrfc3164-module-detect-yearaftertimestamp: .. _pmrfc3164.parameter.module.detect-yearaftertimestamp-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" detect.YearAfterTimestamp="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-partitions-number.rst0000644000000000000000000000013215132411300026516 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.097464287 30 ctime=1787067793.353705655 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-partitions-number.rst0000666000175000017500000000162615132411300026171 0ustar00rgerrger.. _param-omkafka-partitions-number: .. _omkafka.parameter.module.partitions-number: Partitions.number ================= .. index:: single: omkafka; Partitions.number single: Partitions.number .. summary-start Number of partitions to load-balance across. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Partitions.number :Scope: action :Type: integer :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, specifies how many partitions exist and activates load-balancing among them. The number must match the topic's partition count. Action usage ------------ .. _param-omkafka-action-partitions-number: .. _omkafka.parameter.action.partitions-number: .. code-block:: rsyslog action(type="omkafka" Partitions.number="3") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-output.rst0000644000000000000000000000013115132733117026236 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.570454462 29 ctime=1787067792.81569563 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-output.rst0000666000175000017500000000243015132733117025704 0ustar00rgerrger.. _param-mmjsontransform-output: .. _mmjsontransform.parameter.input.output: output ====== .. index:: single: mmjsontransform; output single: output .. summary-start Sets the destination property that receives the rewritten JSON tree. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: output :Scope: input :Type: string :Default: none :Required?: yes :Introduced: 8.2410.0 Description ----------- Defines where the transformed JSON object is stored on the message. The property must use a JSON-capable prefix (``$!``, ``$.`` or ``$/``). When the configuration uses a leading ``$`` symbol, it is stripped automatically before validation. The module rejects other prefixes during configuration. At runtime ``mmjsontransform`` verifies that the destination property does not already exist. Attempting to overwrite an existing value raises an error and the action aborts without modifying the message. Input usage ----------- .. _param-mmjsontransform-output-usage: .. _mmjsontransform.parameter.input.output-usage: .. code-block:: rsyslog action(type="mmjsontransform" input="$!raw" output="$!normalized") See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-ignorenonvalidstatefile.rst0000644000000000000000000000013215132411300030342 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.893460484 30 ctime=1787067792.181683815 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-ignorenonvalidstatefile.rst0000666000175000017500000000243515132411300030014 0ustar00rgerrger.. _param-imjournal-ignorenonvalidstatefile: .. _imjournal.parameter.module.ignorenonvalidstatefile: .. meta:: :tag: module:imjournal :tag: parameter:IgnoreNonValidStatefile IgnoreNonValidStatefile ======================= .. index:: single: imjournal; IgnoreNonValidStatefile single: IgnoreNonValidStatefile .. summary-start Ignores corrupt state files and restarts reading from the beginning. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: IgnoreNonValidStatefile :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When a corrupted state file is encountered, the module discards it and continues reading from the start of the journal (or from the end if ``IgnorePreviousMessages`` is enabled). A new valid state file is written after the next state persistence or shutdown. Module usage ------------ .. _param-imjournal-module-ignorenonvalidstatefile: .. _imjournal.parameter.module.ignorenonvalidstatefile-usage: .. code-block:: rsyslog module(load="imjournal" IgnoreNonValidStatefile="...") Notes ----- - Historic documentation called this a ``binary`` option; it is boolean. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-template.rst0000644000000000000000000000013215132733117025034 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.709457054 30 ctime=1787067793.382706196 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-template.rst0000666000175000017500000000250015132733117024477 0ustar00rgerrger.. _param-omlibdbi-template: .. _omlibdbi.parameter.module.template: .. _omlibdbi.parameter.input.template: Template ======== .. index:: single: omlibdbi; Template single: Template .. summary-start Defines the template used to render records, either globally for the module or for a specific action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: Template :Scope: module, input :Type: word :Default: module=StdDBFmt; input=inherits module :Required?: no :Introduced: Not documented Description ----------- Set the default template that omlibdbi uses when writing to the database, then optionally override it per action. If no template is provided at the action or module level, omlibdbi uses the built-in ``StdDBFmt`` template. Module usage ------------ .. _param-omlibdbi-module-template-usage: .. _omlibdbi.parameter.module.template-usage: .. code-block:: rsyslog module(load="omlibdbi" template="dbTemplate") Input usage ----------- .. _param-omlibdbi-input-template-usage: .. _omlibdbi.parameter.input.template-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog" template="structuredDb") See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-mode.rst0000644000000000000000000000013215145046112024525 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.821440499 30 ctime=1787067792.715693766 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-mode.rst0000664000175000017500000000500415145046112024170 0ustar00rgerrger.. _param-mmanon-ipv4-mode: .. _mmanon.parameter.input.ipv4-mode: ipv4.mode ========= .. index:: single: mmanon; ipv4.mode single: ipv4.mode .. summary-start Selects the IPv4 anonymization mode used by the mmanon action. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.mode :Scope: input :Type: string :Default: input=zero :Required?: no :Introduced: 7.3.7 Description ----------- The available modes are ``simple``, ``random``, ``random-consistent``, ``random-consistent-unique``, and ``zero``. In simple mode, only octets as a whole can be anonymized and the length of the message is never changed. This means that when the last three octets of the address 10.1.12.123 are anonymized, the result will be 10.x.xx.xxx. The replacement character is configurable via :ref:`ipv4.replaceChar `. This means that the length of the original octets is still visible and may be used to draw some privacy-evasive conclusions. This mode is slightly faster than the other modes, and this may matter in high throughput environments. The modes ``random`` and ``random-consistent`` are very similar, in that they both anonymize IP addresses by randomizing the last bits (any number) of a given address. However, while ``random`` mode assigns a new random IP address for every address in a message, ``random-consistent`` will assign the same randomized address to every instance of the same original address. ``random-consistent-unique`` builds on that behavior and guarantees that no two distinct original addresses share the same anonymized result. It may take longer to generate addresses because a replacement is retried until an unused randomized value is found; this effect grows as more unique IPs are processed. The default ``zero`` mode will do full anonymization of any number of bits. It will also normalize the address, so that no information about the original IP address is available. For example, if 24 bits are anonymized, 10.1.12.123 would be anonymized to 10.0.0.0. Input usage ----------- .. _mmanon.parameter.input.ipv4-mode-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="random-consistent") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmanon.parameter.legacy.mode: - mode — maps to ipv4.mode (status: legacy) .. index:: single: mmanon; mode single: mode See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-main.rst0000644000000000000000000000013215132411300024347 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.931461192 30 ctime=1787067792.186683908 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-main.rst0000666000175000017500000000202715132411300024016 0ustar00rgerrger.. _param-imjournal-main: .. _imjournal.parameter.input.main: .. meta:: :tag: module:imjournal :tag: parameter:Main Main ==== .. index:: single: imjournal; Main single: Main .. summary-start Runs the input's ruleset on the main thread and stops reading if outputs block. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: Main :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2312.0 Description ----------- When enabled, the input module executes its bound ruleset in the main thread and pauses ingestion if the output side cannot accept data. Only the first input with ``Main="on"`` is treated as such; others run in background threads. Input usage ----------- .. _param-imjournal-input-main: .. _imjournal.parameter.input.main-usage: .. code-block:: rsyslog input(type="imjournal" Main="...") Notes ----- - Earlier documentation misclassified this option; it is boolean. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-compression-maxexpansionratio.rst0000644000000000000000000000013215216464435030673 xustar0030 mtime=1782212893.985265521 30 atime=1787067674.068482388 30 ctime=1787067792.461689033 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-maxexpansionratio.rst0000664000175000017500000000350015216464435030335 0ustar00rgerrger.. _param-imtcp-compression-maxexpansionratio: .. _imtcp.parameter.input.compression-maxexpansionratio: .. meta:: :description: Reference for the imtcp compression.maxExpansionRatio input parameter. :keywords: rsyslog, imtcp, compression.maxExpansionRatio, stream compression, decompression, security compression.maxExpansionRatio ============================= .. index:: single: imtcp; compression.maxExpansionRatio single: compression.maxExpansionRatio .. summary-start Limits the cumulative decompressed-to-compressed byte ratio accepted for a stream. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: compression.maxExpansionRatio :Scope: input/module :Type: integer :Default: input=1024 :Required?: no :Introduced: 8.2606.0 Description ----------- ``compression.maxExpansionRatio`` limits how much decompressed output ``imtcp`` accepts relative to compressed bytes received across the compressed stream when ``compression.mode="stream:always"`` is enabled. The default allows up to 1024 decompressed bytes per compressed byte. If the ratio is exceeded, ``imtcp`` logs the compressed stream as invalid and closes the session. This bounds decompression amplification from malformed or unexpectedly dense compressed streams. Set the value to ``0`` to disable this ratio limit for tightly controlled deployments. Input usage ----------- .. _param-imtcp-input-compression-maxexpansionratio: .. _imtcp.parameter.input.compression-maxexpansionratio-usage: .. code-block:: rsyslog input( type="imtcp" port="514" compression.mode="stream:always" compression.maxExpansionRatio="2048" ) See also -------- See also :ref:`param-imtcp-compression-mode`, :ref:`param-imtcp-compression-maxdecompressedbytesperreceive`, and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-dstmetadatapath.rst0000644000000000000000000000013115132733117027310 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.671456345 29 ctime=1787067792.83769604 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-dstmetadatapath.rst0000666000175000017500000000170115132733117026756 0ustar00rgerrger.. _param-mmkubernetes-dstmetadatapath: .. _mmkubernetes.parameter.action.dstmetadatapath: dstmetadatapath =============== .. index:: single: mmkubernetes; dstmetadatapath single: dstmetadatapath .. summary-start Defines where the ``kubernetes`` and ``docker`` properties are written. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: dstmetadatapath :Scope: action :Type: word :Default: $! :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This is the where the `kubernetes` and `docker` properties will be written. By default, the module will add `$!kubernetes` and `$!docker`. Action usage ------------ .. _param-mmkubernetes-action-dstmetadatapath: .. _mmkubernetes.parameter.action.dstmetadatapath-usage: .. code-block:: rsyslog action(type="mmkubernetes" dstMetadataPath="$!") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-failedmsgfile.rst0000644000000000000000000000013115132411300025626 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.001462497 29 ctime=1787067793.34270545 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-failedmsgfile.rst0000666000175000017500000000157415132411300025304 0ustar00rgerrger.. _param-omkafka-failedmsgfile: .. _omkafka.parameter.module.failedmsgfile: failedMsgFile ============= .. index:: single: omkafka; failedMsgFile single: failedMsgFile .. summary-start File that stores messages saved by `KeepFailedMessages`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: failedMsgFile :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: 8.28.0 Description ----------- .. versionadded:: 8.28.0 Filename where the failed messages should be stored. Must be set when ``KeepFailedMessages`` is enabled. Action usage ------------ .. _param-omkafka-action-failedmsgfile: .. _omkafka.parameter.action.failedmsgfile: .. code-block:: rsyslog action(type="omkafka" failedMsgFile="/var/spool/rsyslog/failed.kafkamsgs") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-ruleset.rst0000644000000000000000000000013215132733117024417 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.949442886 30 ctime=1787067792.026680927 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-ruleset.rst0000666000175000017500000000140415132733117024064 0ustar00rgerrger.. _param-imdtls-ruleset: .. _imdtls.parameter.input.ruleset: Ruleset ======= .. index:: single: imdtls; ruleset single: ruleset .. summary-start Binds received DTLS messages to the specified processing ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: ruleset :Scope: input :Type: word :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Determines the ruleset to which the imdtls input will be bound. This can be overridden at the instance level. Input usage ----------- .. _imdtls.parameter.input.ruleset-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" ruleset="secure-logs") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-template.rst0000644000000000000000000000013215132733117024531 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.020462851 30 ctime=1787067793.407706662 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-template.rst0000666000175000017500000000204115132733117024174 0ustar00rgerrger.. _param-ommail-template: .. _ommail.parameter.input.template: template ======== .. index:: single: ommail; template single: template .. summary-start Selects the template used for the mail body when body text is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: template :Scope: input :Type: word :Default: input=RSYSLOG_FileFormat :Required?: no :Introduced: 8.5.0 Description ----------- Specifies the name of the template for the mail body. This parameter is only effective if :ref:`param-ommail-body-enable` is "on" (which is the default). Input usage ------------ .. _ommail.parameter.input.template-usage: .. code-block:: rsyslog module(load="ommail") template(name="mailBody" type="string" string="Message: %msg%") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" template="mailBody" ) See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-errorfile.rst0000644000000000000000000000013215132411300025025 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.956461658 30 ctime=1787067793.340705413 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-errorfile.rst0000666000175000017500000000156515132411300024502 0ustar00rgerrger.. _param-omkafka-errorfile: .. _omkafka.parameter.module.errorfile: errorFile ========= .. index:: single: omkafka; errorFile single: errorFile .. summary-start Write failed messages to this JSON file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: errorFile :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, messages that could not be sent are written to the specified file. Each entry is JSON and contains the full message plus the Kafka error number and reason. Action usage ------------ .. _param-omkafka-action-errorfile: .. _omkafka.parameter.action.errorfile: .. code-block:: rsyslog action(type="omkafka" errorFile="/var/log/omkafka-error.json") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-windowsize.rst0000644000000000000000000000013215145046112025134 xustar0030 mtime=1771326538.956012933 30 atime=1787067672.946461472 30 ctime=1787067793.528708917 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-windowsize.rst0000664000175000017500000000265615145046112024611 0ustar00rgerrger.. _param-omrelp-windowsize: .. _omrelp.parameter.input.windowsize: WindowSize ========== .. index:: single: omrelp; WindowSize single: WindowSize .. summary-start Overrides the RELP client window size used for message transmission. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: WindowSize :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- This is an **expert parameter**. It permits to override the RELP window size being used by the client. Changing the window size has both an effect on performance as well as potential message duplication in failure case. A larger window size means more performance, but also potentially more duplicated messages - and vice versa. The default 0 means that librelp's default window size is being used, which is considered a compromise between goals reached. For your information: at the time of this writing, the librelp default window size is 128 messages, but this may change at any time. Note that there is no equivalent server parameter, as the client proposes and manages the window size in RELP protocol. Input usage ----------- .. _param-omrelp-input-windowsize: .. _omrelp.parameter.input.windowsize-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" windowSize="256") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-parent.rst0000644000000000000000000000013215132411300026062 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.084445402 30 ctime=1787067793.063700251 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-parent.rst0000666000175000017500000000146415132411300025535 0ustar00rgerrger.. _param-omelasticsearch-parent: .. _omelasticsearch.parameter.module.parent: parent ====== .. index:: single: omelasticsearch; parent single: parent .. summary-start Parent document ID assigned to indexed events. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: parent :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Adds a parent ID to each record. The mapping must define a corresponding parent field. Action usage ------------ .. _param-omelasticsearch-action-parent: .. _omelasticsearch.parameter.action.parent: .. code-block:: rsyslog action(type="omelasticsearch" parent="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmtaghostname-tag.rst0000644000000000000000000000013115132733117025056 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.267467456 30 ctime=1787067792.911697419 rsyslog-8.2608.0/doc/source/reference/parameters/mmtaghostname-tag.rst0000666000175000017500000000205015132733117024522 0ustar00rgerrger.. _param-mmtaghostname-tag: .. _mmtaghostname.parameter.input.tag: tag === .. index:: single: mmtaghostname; tag single: tag .. summary-start Assigns a tag to messages. This is useful for inputs like ``imudp`` or ``imtcp`` that do not provide a tag. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmtaghostname`. :Name: tag :Scope: input :Type: string :Default: none :Required?: no :Introduced: at least 7.0, possibly earlier Description ----------- The tag to be assigned to messages processed by this module. This is often used to route messages to different rulesets or output actions based on the tag. If you would like to see the colon after the tag, you need to include it when you assign a tag value, like so: ``tag="myTagValue:"``. If this parameter is not set, message tags are not modified. Input usage ----------- .. _mmtaghostname.parameter.input.tag-usage: .. code-block:: rsyslog action(type="mmtaghostname" tag="front") See also -------- * :doc:`../../configuration/modules/mmtaghostname` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssservertokeniotimeout.rs0000644000000000000000000000013215171370365031200 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.605455115 30 ctime=1787067792.150683237 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssservertokeniotimeout.rst0000664000175000017500000000300015171370365031021 0ustar00rgerrger.. _param-imgssapi-inputgssservertokeniotimeout: .. _imgssapi.parameter.input.inputgssservertokeniotimeout: InputGSSServerTokenIOTimeout ============================ .. index:: single: imgssapi; InputGSSServerTokenIOTimeout single: InputGSSServerTokenIOTimeout .. summary-start Sets the deadline in seconds for reading a full GSSAPI token on an imgssapi session. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerTokenIOTimeout :Scope: input :Type: integer :Default: 10 :Required?: no :Introduced: 8.2604.0 Description ----------- Controls how long imgssapi waits to receive an entire GSSAPI token, including the 4-byte token length and the token payload. The timeout applies to GSSAPI handshake tokens as well as protected message frames. Set this value higher on slow or high-latency links. Set it to ``0`` to disable the deadline entirely. Negative values are rejected as configuration errors. Input usage ----------- .. _imgssapi.parameter.input.inputgssservertokeniotimeout-usage: .. code-block:: rsyslog module(load="imgssapi") $InputGSSServerTokenIOTimeout 30 Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssservertokeniotimeout: - $InputGSSServerTokenIOTimeout — maps to InputGSSServerTokenIOTimeout (status: legacy) .. index:: single: imgssapi; $InputGSSServerTokenIOTimeout single: $InputGSSServerTokenIOTimeout See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-escapelf.rst0000644000000000000000000000013215132411300025002 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.170447006 30 ctime=1787067791.973679939 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-escapelf.rst0000666000175000017500000000171715132411300024456 0ustar00rgerrger.. _param-imdocker-escapelf: .. _imdocker.parameter.module.escapelf: escapeLF ======== .. index:: single: imdocker; escapeLF single: escapeLF .. summary-start Escapes line feeds as ``#012`` in multi-line messages; default ``on``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: escapeLF :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.41.0 Description ----------- If enabled, line feed characters embedded in messages are escaped to the sequence ``#012``. This avoids issues with tools that do not expect embedded LF characters. Module usage ------------ .. _param-imdocker-module-escapelf: .. _imdocker.parameter.module.escapelf-usage: .. code-block:: rsyslog module(load="imdocker" escapeLF="...") Notes ----- - The original documentation described this as a binary option; it is a boolean parameter. See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-frametimeout.rst0000644000000000000000000000013215241075234025565 xustar0030 mtime=1787067036.579577808 30 atime=1787067036.676579624 30 ctime=1787067791.322667808 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-frametimeout.rst0000664000175000017500000000305115241075234025230 0ustar00rgerrger.. _param-imbeats-frametimeout: .. _imbeats.parameter.input.frametimeout: frameTimeout ============ .. meta:: :description: Absolute deadline for completing an in-progress imbeats Lumberjack frame read. :keywords: rsyslog, imbeats, frameTimeout, frame deadline, Lumberjack .. index:: single: imbeats; frameTimeout single: frameTimeout .. summary-start Set an absolute deadline for completing an in-progress Lumberjack frame read. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: frameTimeout :Scope: input :Type: nonnegative integer :Default: input=30 :Required?: no :Introduced: 8.2608.0 Description ----------- Set the maximum number of seconds allowed to complete an in-progress Lumberjack frame read. The deadline is absolute: receiving additional bytes does not extend it. This prevents a client from retaining frame state indefinitely by sending a slow trickle of data. When the deadline expires, ``imbeats`` closes the session and does not acknowledge the incomplete batch. The value ``0`` disables the frame timeout. The independent :ref:`param-imbeats-idletimeout` may still close a session that makes no byte progress. Input usage ----------- .. _param-imbeats-input-frametimeout: .. _imbeats.parameter.input.frametimeout-usage: RainerScript: .. code-block:: rsyslog input(type="imbeats" port="5044" frameTimeout="30") YAML: .. code-block:: yaml inputs: - type: imbeats port: 5044 frameTimeout: 30 See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-uniqueretrycount.rst0000644000000000000000000000013215145046112027250 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.882441636 30 ctime=1787067792.733694102 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-uniqueretrycount.rst0000664000175000017500000000204615145046112026716 0ustar00rgerrger.. _param-mmanon-ipv6-uniqueretrycount: .. _mmanon.parameter.input.ipv6-uniqueretrycount: ipv6.uniqueRetryCount ===================== .. index:: single: mmanon; ipv6.uniqueRetryCount single: ipv6.uniqueRetryCount .. summary-start Sets the maximum retry count for IPv6 random-consistent-unique anonymization. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.uniqueRetryCount :Scope: input :Type: integer :Default: input=1000 :Required?: no :Introduced: 8.2410.0 Description ----------- Defines how many randomized replacements are attempted before giving up when ``ipv6.limitUniqueMaxRetries`` is enabled. The retry limit only applies to ``random-consistent-unique`` mode. Input usage ----------- .. _mmanon.parameter.input.ipv6-uniqueretrycount-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.anonMode="random-consistent-unique" ipv6.limitUniqueMaxRetries="on" ipv6.uniqueRetryCount="500") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-fileowner.rst0000644000000000000000000000013115132733117024725 xustar0030 mtime=1768666703.906620223 29 atime=1787067673.62547413 30 ctime=1787067792.334686666 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-fileowner.rst0000666000175000017500000000161315132733117024375 0ustar00rgerrger.. _param-imptcp-fileowner: .. _imptcp.parameter.input.fileowner: FileOwner ========= .. index:: single: imptcp; FileOwner single: FileOwner .. summary-start Sets the owner of the Unix-domain socket by user name. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FileOwner :Scope: input :Type: UID :Default: input=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the file owner for the domain socket. The parameter is a user name, for which the userid is obtained by rsyslogd during startup processing. Interim changes to the user mapping are *not* detected. Input usage ----------- .. _param-imptcp-input-fileowner: .. _imptcp.parameter.input.fileowner-usage: .. code-block:: rsyslog input(type="imptcp" fileOwner="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-apikey_file.rst0000644000000000000000000000013215132733117025340 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.772439586 30 ctime=1787067792.679693095 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-apikey_file.rst0000666000175000017500000000165015132733117025010 0ustar00rgerrger.. _param-mmaitag-apikey_file: .. _mmaitag.parameter.action.apikey_file: apiKeyFile ========== .. index:: single: mmaitag; apiKeyFile single: apiKeyFile .. summary-start Specifies a file containing the API key for the provider. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: apiKeyFile :Scope: action :Type: string :Default: none :Required?: no (either :ref:`param-mmaitag-apikey` or ``apiKeyFile`` must be set) :Introduced: 9.0.0 Description ----------- File containing the API key for the provider. If :ref:`param-mmaitag-apikey` is not set, the module reads the first line of this file and uses it as the API key. Action usage ------------- .. _param-mmaitag-action-apikey_file: .. _mmaitag.parameter.action.apikey_file-usage: .. code-block:: rsyslog action(type="mmaitag" apiKeyFile="/path/to/keyfile") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-statefile-directory.rst0000644000000000000000000000013215132733117026667 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.362450585 30 ctime=1787067792.115682585 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-statefile-directory.rst0000666000175000017500000000243415132733117026340 0ustar00rgerrger.. _param-imfile-statefile-directory: .. _imfile.parameter.module.statefile-directory: .. _imfile.parameter.statefile-directory: statefile.directory =================== .. index:: single: imfile; statefile.directory single: statefile.directory .. summary-start Sets a dedicated directory for imfile state files. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: statefile.directory :Scope: module :Type: string :Default: module=global(workDirectory) value :Required?: no :Introduced: 8.1905.0 Description ----------- Permits specification of a dedicated directory for the storage of imfile state files. An absolute path name should be specified (e.g., ``/var/rsyslog/imfilestate``). If not specified the global ``workDirectory`` setting is used. **Important: The directory must exist before rsyslog is started.** rsyslog needs write permissions to work correctly. This may also require SELinux definitions or similar permissions in other security systems. Module usage ------------ .. _param-imfile-module-statefile-directory: .. _imfile.parameter.module.statefile-directory-usage: .. code-block:: rsyslog module(load="imfile" statefile.directory="/var/rsyslog/imfilestate") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmutf8fix-mode.rst0000644000000000000000000000013115132733117024312 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.300468071 30 ctime=1787067792.913697456 rsyslog-8.2608.0/doc/source/reference/parameters/mmutf8fix-mode.rst0000666000175000017500000000332115132733117023760 0ustar00rgerrger.. _param-mmutf8fix-mode: .. _mmutf8fix.parameter.input.mode: mode ==== .. index:: single: mmutf8fix; mode single: mode .. summary-start Selects how invalid byte sequences are detected and replaced. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmutf8fix`. :Name: mode :Scope: input :Type: string :Default: "utf-8" :Required?: no :Introduced: 7.5.4 Description ----------- Sets the basic detection mode for invalid byte sequences. ``"utf-8"`` (default) Checks for proper UTF-8 encoding. Bytes that form invalid UTF-8 sequences are replaced with the character defined by :ref:`param-mmutf8fix-replacementchar`. This applies to various invalid conditions, including: * Invalid start bytes or stray continuation bytes. * A multi-byte sequence that is incomplete. * A complete sequence that is invalid (e.g., overlong encoding, a disallowed codepoint like a UTF-16 surrogate, or a value > U+10FFFF). Control characters are not replaced because they are valid UTF-8. This mode is most useful with non-US-ASCII character sets, which validly include multibyte sequences. ``"controlcharacters"`` Replaces all bytes that do not represent a printable US-ASCII character (codes 32 to 126) with the character defined by :ref:`param-mmutf8fix-replacementchar`. This invalidates valid UTF-8 multi-byte sequences and should be used only when characters outside the US-ASCII range are not expected. Input usage ----------- .. _mmutf8fix.parameter.input.mode-usage: .. code-block:: rsyslog module(load="mmutf8fix") action(type="mmutf8fix" mode="controlcharacters") See also -------- See also :doc:`../../configuration/modules/mmutf8fix`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-ratelimit-name.rst0000644000000000000000000000013215171370365027523 xustar0030 mtime=1776677109.119908115 30 atime=1787067672.220447938 30 ctime=1787067793.075700475 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-ratelimit-name.rst0000664000175000017500000000140215171370365027164 0ustar00rgerrger.. index:: ! omelasticsearch; RateLimit.Name .. _param-omelasticsearch-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple actions to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-action limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpheaders.rst0000644000000000000000000000013015132733117025264 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.750457818 29 ctime=1787067793.26270396 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpheaders.rst0000666000175000017500000000217615132733117024742 0ustar00rgerrger.. _param-omhttp-httpheaders: .. _omhttp.parameter.input.httpheaders: httpheaders =========== .. index:: single: omhttp; httpheaders single: httpheaders .. summary-start Configures an array of additional HTTP headers that omhttp sends with each request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpheaders :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: Not specified Description ----------- An array of strings that defines a list of one or more HTTP headers to send with each message. Keep in mind that some HTTP headers are added using other parameters. ``Content-Type`` can be configured using :ref:`param-omhttp-httpcontenttype`, and ``Content-Encoding: gzip`` is added when using the :ref:`param-omhttp-compress` parameter. Input usage ----------- .. _omhttp.parameter.input.httpheaders-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpHeaders=[ "X-Insert-Key: key", "X-Event-Source: logs" ] ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-kubernetesurl.rst0000644000000000000000000000013215241075234027027 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.000680442 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-kubernetesurl.rst0000664000175000017500000000165215241075234026477 0ustar00rgerrger.. _param-imkubernetes-kubernetesurl: .. _imkubernetes.parameter.module.kubernetesurl: KubernetesUrl ============= .. index:: single: imkubernetes; KubernetesUrl single: KubernetesUrl .. summary-start Base URL of the Kubernetes API server; default ``https://kubernetes.default.svc.cluster.local:443``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: KubernetesUrl :Scope: module :Type: word :Default: ``https://kubernetes.default.svc.cluster.local:443`` :Required?: no :Introduced: 8.2604.0 Description ----------- Sets the API endpoint used when enrichment is enabled. The module queries pod metadata using ``/api/v1/namespaces//pods/`` below this base URL. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" KubernetesUrl="https://localhost:8443") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-srcmetadatapath.rst0000644000000000000000000000013215132733117027306 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.715457165 30 ctime=1787067792.851696301 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-srcmetadatapath.rst0000666000175000017500000000170615132733117026760 0ustar00rgerrger.. _param-mmkubernetes-srcmetadatapath: .. _mmkubernetes.parameter.action.srcmetadatapath: srcmetadatapath =============== .. index:: single: mmkubernetes; srcmetadatapath single: srcmetadatapath .. summary-start Specifies the message property containing the original filename. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: srcmetadatapath :Scope: action :Type: word :Default: $!metadata!filename :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When reading json-file logs, with `imfile` and `addmetadata="on"`, this is the property where the filename is stored. Action usage ------------ .. _param-mmkubernetes-action-srcmetadatapath: .. _mmkubernetes.parameter.action.srcmetadatapath-usage: .. code-block:: rsyslog action(type="mmkubernetes" srcMetadataPath="$!metadata!filename") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-annotate.rst0000644000000000000000000000013215132733117026607 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.186484588 30 ctime=1787067792.633692238 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-annotate.rst0000666000175000017500000000242015132733117026253 0ustar00rgerrger.. _param-imuxsock-syssock-annotate: .. _imuxsock.parameter.module.syssock-annotate: SysSock.Annotate ================ .. index:: single: imuxsock; SysSock.Annotate single: SysSock.Annotate .. summary-start Enables annotation or trusted properties on the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.Annotate :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Turn on annotation/trusted properties for the system log socket. See the :ref:`imuxsock-trusted-properties-label` section for more info. Module usage ------------ .. _param-imuxsock-module-syssock-annotate: .. _imuxsock.parameter.module.syssock-annotate-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.annotate="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogsockannotate: - $SystemLogSocketAnnotate — maps to SysSock.Annotate (status: legacy) .. index:: single: imuxsock; $SystemLogSocketAnnotate single: $SystemLogSocketAnnotate See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-tls-myprivkey.rst0000644000000000000000000000013215132733117025612 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.313468313 30 ctime=1787067793.315704947 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-tls-myprivkey.rst0000666000175000017500000000156315132733117025265 0ustar00rgerrger.. _param-omhttp-tls-myprivkey: .. _omhttp.parameter.input.tls-myprivkey: tls.myprivkey ============= .. index:: single: omhttp; tls.myprivkey single: tls.myprivkey .. summary-start Provides the private key file that pairs with :ref:`param-omhttp-tls-mycert`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: tls.myprivkey :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- This parameter sets the path to the SSL private key. Expects ``.pem`` format. Input usage ----------- .. _omhttp.parameter.input.tls-myprivkey-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" tlsMyPrivKey="/etc/rsyslog/certs/omhttp-client.key" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-localclientip.rst0000644000000000000000000000013215145046112025554 xustar0030 mtime=1771326538.952012868 30 atime=1787067673.258467288 30 ctime=1787067793.490708209 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-localclientip.rst0000664000175000017500000000156115145046112025223 0ustar00rgerrger.. _param-omrelp-localclientip: .. _omrelp.parameter.input.localclientip: LocalClientIp ============= .. index:: single: omrelp; LocalClientIp single: LocalClientIp .. summary-start Sets the local client IP address used when connecting to the remote log server. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: LocalClientIp :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Omrelp uses ip_address as local client address while connecting to remote logserver. Input usage ----------- .. _param-omrelp-input-localclientip: .. _omrelp.parameter.input.localclientip-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" localClientIp="192.0.2.10") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-healthcheckapikeyfile.rst0000644000000000000000000000013215171370365027260 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.728457408 30 ctime=1787067792.159683405 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-healthcheckapikeyfile.rst0000664000175000017500000000237515171370365026733 0ustar00rgerrger.. meta:: :description: Protect the imhttp health check endpoint with API key authentication. :keywords: rsyslog, imhttp, healthcheck, api key authentication .. _param-imhttp-healthcheckapikeyfile: .. _imhttp.parameter.module.healthcheckapikeyfile: .. _imhttp-healthcheckapikeyfile: healthCheckApiKeyFile ===================== .. index:: single: imhttp; healthCheckApiKeyFile single: healthCheckApiKeyFile .. summary-start Protects the imhttp health check endpoint with API key authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: healthCheckApiKeyFile :Scope: module :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- If set, the health check endpoint accepts matching API key tokens from a file. Accepted request headers are ``Authorization: ApiKey`` and ``X-API-Key``. Leading whitespace after the header scheme is ignored. Blank lines and lines starting with ``#`` are ignored. Module usage ------------ .. _imhttp.parameter.module.healthcheckapikeyfile-usage: .. code-block:: rsyslog module( load="imhttp" healthCheckApiKeyFile="/etc/rsyslog/api-keys.txt" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmrfc5424addhmac-hashfunction.rst0000644000000000000000000000013215132733117027056 xustar0030 mtime=1768666703.914620344 30 atime=1787067673.017462795 30 ctime=1787067792.897697158 rsyslog-8.2608.0/doc/source/reference/parameters/mmrfc5424addhmac-hashfunction.rst0000666000175000017500000000164615132733117026533 0ustar00rgerrger.. _param-mmrfc5424addhmac-hashfunction: .. _mmrfc5424addhmac.parameter.action.hashFunction: hashFunction ============ .. index:: single: mmrfc5424addhmac; hashFunction single: hashFunction .. summary-start Specifies the OpenSSL hash algorithm used for the HMAC. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmrfc5424addhmac`. :Name: hashFunction :Scope: action :Type: string :Default: none :Required?: yes :Introduced: 7.5.6 Description ----------- An OpenSSL hash function name for the function to be used. This is passed on to OpenSSL, so see the OpenSSL list of supported function names. Action usage ------------ .. _param-mmrfc5424addhmac-action-hashFunction: .. _mmrfc5424addhmac.parameter.action.hashFunction-usage: .. code-block:: rsyslog action(type="mmrfc5424addhmac" hashFunction="sha256") See also -------- See also :doc:`../../configuration/modules/mmrfc5424addhmac`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-dynbulkid.rst0000644000000000000000000000013215132411300026556 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.185447285 30 ctime=1787067793.036699748 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-dynbulkid.rst0000666000175000017500000000164115132411300026226 0ustar00rgerrger.. _param-omelasticsearch-dynbulkid: .. _omelasticsearch.parameter.module.dynbulkid: dynbulkid ========= .. index:: single: omelasticsearch; dynbulkid single: dynbulkid .. summary-start Treat `bulkid` as a template that generates per-record IDs. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: dynbulkid :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Enables interpreting `bulkid` as a template, producing a unique identifier for each record. Action usage ------------ .. _param-omelasticsearch-action-dynbulkid: .. _omelasticsearch.parameter.action.dynbulkid: .. code-block:: rsyslog action(type="omelasticsearch" dynbulkid="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-retryfailures.rst0000644000000000000000000000013115132411300027470 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.199447546 29 ctime=1787067793.07970055 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-retryfailures.rst0000666000175000017500000000173615132411300027146 0ustar00rgerrger.. _param-omelasticsearch-retryfailures: .. _omelasticsearch.parameter.module.retryfailures: retryfailures ============= .. index:: single: omelasticsearch; retryfailures single: retryfailures .. summary-start Resubmit failed bulk items back into rsyslog for retry. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: retryfailures :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled, bulk responses are scanned for errors and failed entries are resubmitted with metadata under `$.omes`. Action usage ------------ .. _param-omelasticsearch-action-retryfailures: .. _omelasticsearch.parameter.action.retryfailures: .. code-block:: rsyslog action(type="omelasticsearch" retryfailures="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-tls-cacert.rst0000644000000000000000000000013215132733117026202 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.720457259 30 ctime=1787067792.855696375 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-tls-cacert.rst0000666000175000017500000000214515132733117025652 0ustar00rgerrger.. _param-mmkubernetes-tls-cacert: .. _mmkubernetes.parameter.action.tls-cacert: tls.cacert ========== .. index:: single: mmkubernetes; tls.cacert single: tls.cacert .. summary-start Specifies the CA certificate used to verify the Kubernetes API server. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: tls.cacert :Scope: action :Type: word :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Full path and file name of file containing the CA cert of the Kubernetes API server cert issuer. Example: `/etc/rsyslog.d/mmk8s-ca.crt`. This parameter is not mandatory if using an `http` scheme instead of `https` in :ref:`param-mmkubernetes-kubernetesurl`, or if :ref:`param-mmkubernetes-allowunsignedcerts` is set to `"on"`. Action usage ------------ .. _param-mmkubernetes-action-tls-cacert: .. _mmkubernetes.parameter.action.tls-cacert-usage: .. code-block:: rsyslog action(type="mmkubernetes" tls.caCert="/etc/rsyslog.d/mmk8s-ca.crt") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-batch-maxsize.rst0000644000000000000000000000013115132733117025511 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.186465946 30 ctime=1787067793.235703456 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-batch-maxsize.rst0000666000175000017500000000150015132733117025154 0ustar00rgerrger.. _param-omhttp-batch-maxsize: .. _omhttp.parameter.input.batch-maxsize: batch.maxsize ============= .. index:: single: omhttp; batch.maxsize single: batch.maxsize .. summary-start Limits how many messages omhttp includes in a batch. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: batch.maxsize :Scope: input :Type: Size :Default: input=100 :Required?: no :Introduced: Not specified Description ----------- This parameter specifies the maximum number of messages that will be sent in each batch. Input usage ----------- .. _omhttp.parameter.input.batch-maxsize-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" batch="on" batchMaxSize="200" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ratelimit-interval.rst0000644000000000000000000000013215132733117027116 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.106483097 30 ctime=1787067792.622692033 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ratelimit-interval.rst0000666000175000017500000000274415132733117026573 0ustar00rgerrger.. _param-imuxsock-ratelimit-interval: .. _imuxsock.parameter.input.ratelimit-interval: RateLimit.Interval ================== .. index:: single: imuxsock; RateLimit.Interval single: RateLimit.Interval .. summary-start Sets the rate-limiting interval in seconds for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: RateLimit.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies the rate-limiting interval in seconds. Default value is 0, which turns off rate limiting. Set it to a number of seconds (5 recommended) to activate rate-limiting. The default of 0 has been chosen as people experienced problems with this feature activated by default. Now it needs an explicit opt-in by setting this parameter. Input usage ----------- .. _param-imuxsock-input-ratelimit-interval: .. _imuxsock.parameter.input.ratelimit-interval-usage: .. code-block:: rsyslog input(type="imuxsock" rateLimit.interval="5") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.imuxsockratelimitinterval: - $IMUXSockRateLimitInterval — maps to RateLimit.Interval (status: legacy) .. index:: single: imuxsock; $IMUXSockRateLimitInterval single: $IMUXSockRateLimitInterval See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-namespace.rst0000644000000000000000000000013215241075234025374 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.676579624 30 ctime=1787067792.188683946 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-namespace.rst0000664000175000017500000000252015241075234025037 0ustar00rgerrger.. _param-imjournal-namespace: .. _imjournal.parameter.module.namespace: .. meta:: :tag: module:imjournal :tag: parameter:Namespace Namespace ========= .. index:: single: imjournal; Namespace single: Namespace .. summary-start Reads entries from a specific systemd journal namespace. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: Namespace :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=unset :Required?: no :Introduced: 8.2608.0 Description ----------- When set, ``imjournal`` opens the named systemd journal namespace instead of the default system journal namespace. This is useful with services that use systemd's ``LogNamespace=`` setting and should be processed by a dedicated ``imjournal`` configuration. ``Namespace`` uses the systemd ``sd_journal_open_namespace()`` API. If rsyslog is built against a libsystemd version that does not provide that API, the configuration fails with an explicit error. This option is mutually exclusive with :ref:`param-imjournal-remote`. Module usage ------------ .. _param-imjournal-module-namespace: .. _imjournal.parameter.module.namespace-usage: .. code-block:: rsyslog module(load="imjournal" Namespace="my-service") See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsendertrack-interval.rst0000644000000000000000000000013115132733117026124 xustar0030 mtime=1768666703.923620481 29 atime=1787067672.99946246 30 ctime=1787067793.532708991 rsyslog-8.2608.0/doc/source/reference/parameters/omsendertrack-interval.rst0000666000175000017500000000243315132733117025575 0ustar00rgerrger.. _param-omsendertrack-interval: .. _omsendertrack.parameter.input.interval: interval ======== .. index:: single: omsendertrack; interval single: interval .. summary-start Sets how many seconds elapse between each write of sender statistics to the state file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsendertrack`. :Name: interval :Scope: input :Type: integer :Default: input=60 :Required?: no :Introduced: 8.2506.0 (Proof-of-Concept) Description ----------- This parameter defines the **interval in seconds** after which the module writes the current sender statistics to the configured :ref:`statefile `. A smaller ``interval`` value results in more frequent updates to the state file, reducing potential data loss in case of an unexpected system crash, but it also increases disk I/O. A larger ``interval`` reduces I/O but means less up-to-date statistics on disk. Input usage ----------- .. _omsendertrack.parameter.input.interval-usage: .. code-block:: rsyslog module(load="omsendertrack") action(type="omsendertrack" senderId="%hostname%" interval="60" stateFile="/var/lib/rsyslog/senderstats.json") See also -------- See also :doc:`../../configuration/modules/omsendertrack`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-userawmsg.rst0000644000000000000000000000013115132733117026006 xustar0030 mtime=1768666703.914620344 29 atime=1787067672.85945985 30 ctime=1787067792.884696916 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-userawmsg.rst0000666000175000017500000000231315132733117025454 0ustar00rgerrger.. _param-mmnormalize-userawmsg: .. _mmnormalize.parameter.action.userawmsg: useRawMsg ========= .. index:: single: mmnormalize; useRawMsg single: useRawMsg .. summary-start Uses the raw message instead of just the MSG part during normalization. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: useRawMsg :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 6.1.2, possibly earlier Description ----------- Specifies if the raw message should be used for normalization (``on``) or just the MSG part of the message (``off``). Action usage ------------- .. _param-mmnormalize-action-userawmsg: .. _mmnormalize.parameter.action.userawmsg-usage: .. code-block:: rsyslog action(type="mmnormalize" useRawMsg="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmnormalize.parameter.legacy.mmnormalizeuserawmsg: - $mmnormalizeUseRawMsg — maps to useRawMsg (status: legacy) .. index:: single: mmnormalize; $mmnormalizeUseRawMsg single: $mmnormalizeUseRawMsg See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dynafilecachesize.rst0000644000000000000000000000013215132411300026350 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.486452896 30 ctime=1787067793.165702152 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dynafilecachesize.rst0000666000175000017500000000405115132411300026016 0ustar00rgerrger.. _param-omfile-dynafilecachesize: .. _omfile.parameter.module.dynafilecachesize: dynaFileCacheSize ================= .. index:: single: omfile; dynaFileCacheSize single: dynaFileCacheSize .. summary-start This parameter specifies the maximum size of the cache for dynamically-generated file names (dynafile= parameter). .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dynaFileCacheSize :Scope: action :Type: integer :Default: action=10 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This parameter specifies the maximum size of the cache for dynamically-generated file names (dynafile= parameter). This setting specifies how many open file handles should be cached. If, for example, the file name is generated with the hostname in it and you have 100 different hosts, a cache size of 100 would ensure that files are opened once and then stay open. This can be a great way to increase performance. If the cache size is lower than the number of different files, the least recently used one is discarded (and the file closed). Note that this is a per-action value, so if you have multiple dynafile actions, each of them have their individual caches (which means the numbers sum up). Ideally, the cache size exactly matches the need. You can use :doc:`impstats <../../configuration/modules/impstats>` to tune this value. Note that a too-low cache size can be a very considerable performance bottleneck. Action usage ------------ .. _param-omfile-action-dynafilecachesize: .. _omfile.parameter.action.dynafilecachesize: .. code-block:: rsyslog action(type="omfile" dynaFileCacheSize="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dynafilecachesize: - $DynaFileCacheSize — maps to dynaFileCacheSize (status: legacy) .. index:: single: omfile; $DynaFileCacheSize single: $DynaFileCacheSize See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-ratelimit-name.rst0000644000000000000000000000013215145046112025640 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.737476218 30 ctime=1787067792.378687486 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-ratelimit-name.rst0000664000175000017500000000254215145046112025307 0ustar00rgerrger.. _param-imptcp-ratelimit-name: .. _imptcp.parameter.input.ratelimit-name: RateLimit.Name ============== .. index:: single: imptcp; RateLimit.Name single: RateLimit.Name .. summary-start Specifies the name of the rate limiting policy to use. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: RateLimit.Name :Scope: input :Type: string :Default: null :Required?: no :Introduced: 8.2602.0 Description ----------- Specifies the name of a rate limiting policy (defined via the top-level :ref:`ratelimit` object) to assert. If this parameter is set, the named policy is looked up and used. If the policy is not found, an error is reported. Using a named policy allows sharing rate limits across multiple inputs or managing them centrally. .. warning:: This parameter is mutually exclusive with :ref:`param-imptcp-ratelimit-interval` and :ref:`param-imptcp-ratelimit-burst`. If ``RateLimit.Name`` is specified, those parameters must **not** be used. Specifying both will result in a configuration error. Input usage ----------- .. _param-imptcp-input-ratelimit-name: .. _imptcp.parameter.input.ratelimit-name-usage: .. code-block:: rsyslog ratelimit(name="myLimit" interval="60" burst="100") input(type="imptcp" RateLimit.Name="myLimit") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-keepalive-interval.rst0000644000000000000000000000013015132733117026341 xustar0030 mtime=1768666703.908620253 28 atime=1787067674.0154814 30 ctime=1787067792.477689331 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-keepalive-interval.rst0000666000175000017500000000216615132733117026016 0ustar00rgerrger.. _param-imtcp-keepalive-interval: .. _imtcp.parameter.module.keepalive-interval: .. _imtcp.parameter.input.keepalive-interval: KeepAlive.Interval ================== .. index:: single: imtcp; KeepAlive.Interval single: KeepAlive.Interval .. summary-start Defines the interval for keep-alive packets. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: KeepAlive.Interval :Scope: module, input :Type: integer :Default: module=0, input=module parameter :Required?: no :Introduced: 8.2106.0 Description ----------- The interval for keep alive packets. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-keepalive-interval: .. _imtcp.parameter.module.keepalive-interval-usage: .. code-block:: rsyslog module(load="imtcp" keepAlive.interval="...") Input usage ----------- .. _param-imtcp-input-keepalive-interval: .. _imtcp.parameter.input.keepalive-interval-usage: .. code-block:: rsyslog input(type="imtcp" port="514" keepAlive.interval="...") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-flushinterval.rst0000644000000000000000000000013115216464435025607 xustar0029 mtime=1782212893.98826557 30 atime=1787067672.526453642 30 ctime=1787067793.183702488 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-flushinterval.rst0000664000175000017500000000330415216464435025254 0ustar00rgerrger.. _param-omfile-flushinterval: .. _omfile.parameter.module.flushinterval: flushInterval ============= .. index:: single: omfile; flushInterval single: flushInterval .. summary-start Defines, in seconds, the interval after which unwritten data is flushed. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: flushInterval :Scope: action :Type: integer :Default: action=1 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines, in seconds, the interval after which unwritten data is flushed. This parameter is applied when :ref:`param-omfile-asyncwriting` is enabled for the action. Use ``flushInterval`` together with ``asyncWriting="on"`` when :ref:`param-omfile-flushontxend` is disabled, for example to keep gzip compression effective while still bounding how long buffered data may remain unflushed. Action usage ------------ .. _param-omfile-action-flushinterval: .. _omfile.parameter.action.flushinterval: .. code-block:: rsyslog action(type="omfile" file="/var/log/app.log" asyncWriting="on" flushOnTXEnd="off" flushInterval=1) YAML usage ---------- .. code-block:: yaml actions: - type: omfile file: /var/log/app.log asyncWriting: "on" flushOnTXEnd: "off" flushInterval: 1 Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.omfileflushinterval: - $OMFileFlushInterval — maps to flushInterval (status: legacy) .. index:: single: omfile; $OMFileFlushInterval single: $OMFileFlushInterval See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-threads.rst0000644000000000000000000000013215171370365024373 xustar0030 mtime=1776677109.117908084 30 atime=1787067673.586473403 30 ctime=1787067792.389687691 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-threads.rst0000664000175000017500000000273615171370365024047 0ustar00rgerrger.. _param-imptcp-threads: .. _imptcp.parameter.module.threads: Threads ======= .. index:: single: imptcp; Threads single: Threads .. summary-start Sets the number of helper threads that pull data off the network. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Threads :Scope: module :Type: integer :Default: module=2 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Number of helper worker threads to process incoming messages. These threads are utilized to pull data off the network. On a busy system, additional helper threads (but not more than there are CPUs/Cores) can help improving performance. The default value is two, which means there is a default thread count of three (the main input thread plus two helpers). The maximum number of worker threads is bound only by system resources (CPU, memory). Module usage ------------ .. _param-imptcp-module-threads: .. _imptcp.parameter.module.threads-usage: .. code-block:: rsyslog module(load="imptcp" threads="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverhelperthreads: - $InputPTCPServerHelperThreads — maps to Threads (status: legacy) .. index:: single: imptcp; $InputPTCPServerHelperThreads single: $InputPTCPServerHelperThreads See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-key.rst0000644000000000000000000000013015145046112024040 xustar0030 mtime=1771326538.943012721 30 atime=1787067672.101445719 28 ctime=1787067792.7496944 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-key.rst0000664000175000017500000000256015145046112023511 0ustar00rgerrger.. _param-mmdarwin-key: .. _mmdarwin.parameter.input.key: key === .. index:: single: mmdarwin; key single: key .. summary-start Stores the Darwin score in the specified JSON field. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: key :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 8.x, possibly earlier Description ----------- The key name to use to store the returned data. For example, given the following log line: .. code-block:: json { "from": "192.168.1.42", "date": "2012-12-21 00:00:00", "status": "200", "data": { "status": true, "message": "Request processed correctly" } } and the ``"certitude"`` key, the enriched log line would be: .. code-block:: json :emphasize-lines: 9 { "from": "192.168.1.42", "date": "2012-12-21 00:00:00", "status": "200", "data": { "status": true, "message": "Request processed correctly" }, "certitude": 0 } where ``"certitude"`` represents the score returned by Darwin. Input usage ----------- .. _param-mmdarwin-input-key-usage: .. _mmdarwin.parameter.input.key-usage: .. code-block:: rsyslog action(type="mmdarwin" key="certitude") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-enable.rst0000644000000000000000000000013115132733117026504 xustar0030 mtime=1768666703.911620299 29 atime=1787067671.89444186 30 ctime=1787067792.698693449 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-enable.rst0000666000175000017500000000172015132733117026153 0ustar00rgerrger.. _param-mmanon-embeddedipv4-enable: .. _mmanon.parameter.input.embeddedipv4-enable: embeddedIpv4.enable =================== .. index:: single: mmanon; embeddedIpv4.enable single: embeddedIpv4.enable .. summary-start Enables or disables anonymization of IPv6 addresses with embedded IPv4 parts. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.enable :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 7.3.7 Description ----------- This parameter controls whether ``mmanon`` will attempt to find and anonymize IPv6 addresses with embedded IPv4 parts. If set to ``off``, all other ``embeddedipv4.*`` parameters for this action are ignored. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-enable-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.enable="off") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-healthchecktimeout.rst0000644000000000000000000000013215132411300030443 xustar0030 mtime=1768559296.208884723 30 atime=1787067671.985443557 30 ctime=1787067793.054700084 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-healthchecktimeout.rst0000666000175000017500000000175115132411300030115 0ustar00rgerrger.. _param-omelasticsearch-healthchecktimeout: .. _omelasticsearch.parameter.module.healthchecktimeout: HealthCheckTimeout ================== .. index:: single: omelasticsearch; HealthCheckTimeout single: HealthCheckTimeout .. summary-start Milliseconds to wait for an HTTP health check before sending events. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: HealthCheckTimeout :Scope: action :Type: integer :Default: action=3500 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Before logging begins, rsyslog issues an HTTP HEAD to `/_cat/health` and waits up to this many milliseconds for `HTTP OK`. Action usage ------------ .. _param-omelasticsearch-action-healthchecktimeout: .. _omelasticsearch.parameter.action.healthchecktimeout: .. code-block:: rsyslog action(type="omelasticsearch" HealthCheckTimeout="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-limituniquemaxretries.rst0000644000000000000000000000013215145046112030254 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.876441524 30 ctime=1787067792.729694027 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-limituniquemaxretries.rst0000664000175000017500000000222115145046112027715 0ustar00rgerrger.. _param-mmanon-ipv6-limituniquemaxretries: .. _mmanon.parameter.input.ipv6-limituniquemaxretries: ipv6.limitUniqueMaxRetries ========================== .. index:: single: mmanon; ipv6.limitUniqueMaxRetries single: ipv6.limitUniqueMaxRetries .. summary-start Controls whether random-consistent-unique anonymization limits retries for IPv6. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.limitUniqueMaxRetries :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2410.0 Description ----------- When enabled, ``random-consistent-unique`` mode will stop retrying after :ref:`ipv6.uniqueRetryCount ` attempts. After the retry limit is reached, the behavior is controlled by :ref:`ipv6.maxRetryHandling `. Input usage ----------- .. _mmanon.parameter.input.ipv6-limituniquemaxretries-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.anonMode="random-consistent-unique" ipv6.limitUniqueMaxRetries="on") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-template.rst0000644000000000000000000000013115132411300024510 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.315449709 29 ctime=1787067793.20370286 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-template.rst0000666000175000017500000000253615132411300024165 0ustar00rgerrger.. _param-omfile-template: .. _omfile.parameter.module.template: Template ======== .. index:: single: omfile; Template single: Template .. summary-start Sets the template to be used for this action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: Template :Scope: module, action :Type: word :Default: module=RSYSLOG_FileFormat; action=inherits module :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the template to be used for this action. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-template: .. _omfile.parameter.module.template-usage: .. code-block:: rsyslog module(load="builtin:omfile" Template="...") Action usage ------------ .. _param-omfile-action-template: .. _omfile.parameter.action.template: .. code-block:: rsyslog action(type="omfile" Template="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.actionfiledefaulttemplate: - $ActionFileDefaultTemplate — maps to Template (status: legacy) .. index:: single: omfile; $ActionFileDefaultTemplate single: $ActionFileDefaultTemplate See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls.rst0000644000000000000000000000013215145046112023534 xustar0030 mtime=1771326538.956012933 30 atime=1787067672.668456289 30 ctime=1787067793.526708879 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls.rst0000664000175000017500000000236215145046112023203 0ustar00rgerrger.. _param-omrelp-tls: .. _omrelp.parameter.input.tls: TLS === .. index:: single: omrelp; TLS single: TLS .. summary-start Enables TLS encryption for the RELP connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- If set to "on", the RELP connection will be encrypted by TLS, so that the data is protected against observers. Please note that both the client and the server must have set TLS to either "on" or "off". Other combinations lead to unpredictable results. *Attention when using GnuTLS 2.10.x or older* Versions older than GnuTLS 2.10.x may cause a crash (Segfault) under certain circumstances. Most likely when an imrelp inputs and an omrelp output is configured. The crash may happen when you are receiving/sending messages at the same time. Upgrade to a newer version like GnuTLS 2.12.21 to solve the problem. Input usage ----------- .. _param-omrelp-input-tls: .. _omrelp.parameter.input.tls-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls="on") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-keepkerneltimestamp.rst0000644000000000000000000000013115132733117026772 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.069463765 29 ctime=1787067792.23668484 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-keepkerneltimestamp.rst0000666000175000017500000000307015132733117026441 0ustar00rgerrger.. _param-imklog-keepkerneltimestamp: .. _imklog.parameter.module.keepkerneltimestamp: KeepKernelTimestamp =================== .. index:: single: imklog; KeepKernelTimestamp single: KeepKernelTimestamp .. summary-start Keeps the kernel-supplied timestamp prefix in each message when kernel timestamps are parsed. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: KeepKernelTimestamp :Scope: module :Type: boolean :Default: off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If enabled, this option keeps the [timestamp] provided by the kernel at the beginning of each message rather than to remove it, when it could be parsed and converted into local time for use as regular message time. Only used when ``ParseKernelTimestamp`` is on. Notes ----- - Legacy documentation referred to the type as "binary"; it behaves as a boolean value. Module usage ------------ .. _param-imklog-module-keepkerneltimestamp: .. _imklog.parameter.module.keepkerneltimestamp-usage: .. code-block:: rsyslog module(load="imklog" parseKernelTimestamp="on" keepKernelTimestamp="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.klogkeepkerneltimestamp: - $klogKeepKernelTimestamp — maps to KeepKernelTimestamp (status: legacy) .. index:: single: imklog; $klogKeepKernelTimestamp single: $klogKeepKernelTimestamp See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-dynparent.rst0000644000000000000000000000013215132411300026575 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.090445514 30 ctime=1787067793.038699785 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-dynparent.rst0000666000175000017500000000162615132411300026250 0ustar00rgerrger.. _param-omelasticsearch-dynparent: .. _omelasticsearch.parameter.module.dynparent: dynParent ========= .. index:: single: omelasticsearch; dynParent single: dynParent .. summary-start Treat `parent` as a template for per-record parent IDs. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: dynParent :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled, `parent` names a template that produces the parent ID for each record. Action usage ------------ .. _param-omelasticsearch-action-dynparent: .. _omelasticsearch.parameter.action.dynparent: .. code-block:: rsyslog action(type="omelasticsearch" dynParent="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-crlfile.rst0000644000000000000000000000013215216464435027220 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.862441264 30 ctime=1787067791.378668851 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-crlfile.rst0000664000175000017500000000204015216464435026660 0ustar00rgerrger.. _param-imbeats-streamdriver-crlfile: .. _imbeats.parameter.input.streamdriver-crlfile: StreamDriver.CRLFile ==================== .. meta:: :description: CRL file for imbeats TLS validation. :keywords: rsyslog, imbeats, streamdriver crlfile .. index:: single: imbeats; StreamDriver.CRLFile single: StreamDriver.CRLFile .. summary-start Specify the certificate revocation list file used by TLS-enabled imbeats listeners. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.CRLFile :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Specify the certificate revocation list file used by TLS-enabled imbeats listeners. Input usage ----------- .. _param-imbeats-input-streamdriver-crlfile: .. _imbeats.parameter.input.streamdriver-crlfile-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.crlFile="/etc/rsyslog/crl.pem") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmrfc5424addhmac-sd-id.rst0000644000000000000000000000013215216464435025374 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.025462945 30 ctime=1787067792.902697251 rsyslog-8.2608.0/doc/source/reference/parameters/mmrfc5424addhmac-sd-id.rst0000664000175000017500000000200215216464435025032 0ustar00rgerrger.. _param-mmrfc5424addhmac-sd-id: .. _mmrfc5424addhmac.parameter.action.sd_id: .. _mmrfc5424addhmac.parameter.action.sdId: sd_id ===== .. index:: single: mmrfc5424addhmac; sd_id single: sd_id .. summary-start Sets the RFC5424 structured data ID added to the message. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmrfc5424addhmac`. :Name: sd_id :Scope: action :Type: string :Default: none :Required?: yes :Introduced: 7.5.6 Description ----------- The RFC5424 structured data ID to be used by this module. This is the SD-ID that will be added. Note that nothing is added if this SD-ID is already present. Action usage ------------ .. _param-mmrfc5424addhmac-action-sd_id: .. _param-mmrfc5424addhmac-action-sdId: .. _mmrfc5424addhmac.parameter.action.sd_id-usage: .. _mmrfc5424addhmac.parameter.action.sdId-usage: .. code-block:: rsyslog action(type="mmrfc5424addhmac" sd_id="exampleSDID@32473") See also -------- See also :doc:`../../configuration/modules/mmrfc5424addhmac`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-maxretryhandling.rst0000644000000000000000000000013215145046112027163 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.886441711 30 ctime=1787067792.731694064 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-maxretryhandling.rst0000664000175000017500000000237715145046112026640 0ustar00rgerrger.. _param-mmanon-ipv6-maxretryhandling: .. _mmanon.parameter.input.ipv6-maxretryhandling: ipv6.maxRetryHandling ===================== .. index:: single: mmanon; ipv6.maxRetryHandling single: ipv6.maxRetryHandling .. summary-start Selects how IPv6 random-consistent-unique handles retry exhaustion. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.maxRetryHandling :Scope: input :Type: string :Default: input=accept-duplicates :Required?: no :Introduced: 8.2410.0 Description ----------- Controls how ``random-consistent-unique`` behaves after the retry limit is reached (see :ref:`ipv6.limitUniqueMaxRetries `). The supported values are: - ``zero``: fall back to zeroing the anonymized bits. - ``accept-duplicates``: keep the last randomized address even if it already exists. A warning is logged whenever the retry limit is hit. Input usage ----------- .. _mmanon.parameter.input.ipv6-maxretryhandling-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.anonMode="random-consistent-unique" ipv6.limitUniqueMaxRetries="on" ipv6.maxRetryHandling="accept-duplicates") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-parsekerneltimestamp.rst0000644000000000000000000000013115132733117027160 xustar0030 mtime=1768666703.905620208 29 atime=1787067673.06546369 30 ctime=1787067792.240684914 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-parsekerneltimestamp.rst0000666000175000017500000000351715132733117026635 0ustar00rgerrger.. _param-imklog-parsekerneltimestamp: .. _imklog.parameter.module.parsekerneltimestamp: ParseKernelTimestamp ==================== .. index:: single: imklog; ParseKernelTimestamp single: ParseKernelTimestamp .. summary-start Parses kernel-provided timestamps and uses them as the message time instead of the receive time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: ParseKernelTimestamp :Scope: module :Type: boolean :Default: off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If enabled and the kernel creates a timestamp for its log messages, this timestamp will be parsed and converted into regular message time instead of using the receive time of the kernel message (as in 5.8.x and before). Default is 'off' to prevent parsing the kernel timestamp, because the clock used by the kernel to create the timestamps is not supposed to be as accurate as the monotonic clock required to convert it. Depending on the hardware and kernel, it can result in message time differences between kernel and system messages which occurred at the same time. Notes ----- - Legacy documentation referred to the type as "binary"; it behaves as a boolean value. Module usage ------------ .. _param-imklog-module-parsekerneltimestamp: .. _imklog.parameter.module.parsekerneltimestamp-usage: .. code-block:: rsyslog module(load="imklog" parseKernelTimestamp="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.klogparsekerneltimestamp: - $klogParseKernelTimestamp — maps to ParseKernelTimestamp (status: legacy) .. index:: single: imklog; $klogParseKernelTimestamp single: $klogParseKernelTimestamp See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-usehttps.rst0000644000000000000000000000013115145046112026460 xustar0030 mtime=1771326538.944012737 29 atime=1787067672.04944475 30 ctime=1787067793.118701276 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-usehttps.rst0000664000175000017500000000172715145046112026134 0ustar00rgerrger.. _param-omelasticsearch-usehttps: .. _omelasticsearch.parameter.module.usehttps: usehttps ======== .. index:: single: omelasticsearch; usehttps single: usehttps .. summary-start Default scheme for servers missing one. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: usehttps :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If enabled, entries in `server` without an explicit scheme use HTTPS; otherwise HTTP is assumed. Servers that already specify ``http`` or ``https`` keep their declared scheme. Action usage ------------ .. _param-omelasticsearch-action-usehttps: .. _omelasticsearch.parameter.action.usehttps: .. code-block:: rsyslog action(type="omelasticsearch" usehttps="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-confirmtimeout.rst0000644000000000000000000000013215132733117026007 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.827459254 30 ctime=1787067793.457707593 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-confirmtimeout.rst0000666000175000017500000000257615132733117025467 0ustar00rgerrger.. _param-omprog-confirmtimeout: .. _omprog.parameter.action.confirmtimeout: confirmTimeout ============== .. index:: single: omprog; confirmTimeout single: confirmTimeout .. summary-start Sets the maximum time in milliseconds to wait for message confirmations. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: confirmTimeout :Scope: action :Type: integer :Default: action=10000 :Required?: no :Introduced: 8.38.0 Description ----------- Specifies how long rsyslog must wait for the external program to confirm each message when :ref:`param-omprog-confirmmessages` is set to "on". If the program does not send a response within this timeout, it will be restarted (see :ref:`param-omprog-signalonclose`, :ref:`param-omprog-closetimeout` and :ref:`param-omprog-killunresponsive` for details on the cleanup sequence). The value must be expressed in milliseconds and must be greater than zero. .. seealso:: `Interface between rsyslog and external output plugins `_ Action usage ------------ .. _param-omprog-action-confirmtimeout: .. _omprog.parameter.action.confirmtimeout-usage: .. code-block:: rsyslog action(type="omprog" confirmMessages="on" confirmTimeout="20000") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-apikey.rst0000644000000000000000000000013115132733117026067 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.107445831 29 ctime=1787067793.02769958 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-apikey.rst0000666000175000017500000000214715132733117025542 0ustar00rgerrger.. _param-omelasticsearch-apikey: .. _omelasticsearch.parameter.module.apikey: apikey ====== .. index:: single: omelasticsearch; apikey single: apikey .. summary-start Supplies the value for the ``Authorization: ApiKey`` HTTP header. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: apikey :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: 8.2406.0 Description ----------- Accepts the API key material expected by Elasticsearch's ``ApiKey`` authentication scheme. The configured value is appended to the ``Authorization: ApiKey`` header without modification, so provide the base64-encoded ``:`` string exactly as documented by Elasticsearch. The API key setting cannot be combined with :ref:`param-omelasticsearch-uid` or :ref:`param-omelasticsearch-pwd`. Action usage ------------ .. _param-omelasticsearch-action-apikey: .. _omelasticsearch.parameter.action.apikey: .. code-block:: rsyslog action(type="omelasticsearch" apikey="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ignoretimestamp.rst0000644000000000000000000000013115132733117030204 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.275486247 29 ctime=1787067792.63969235 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ignoretimestamp.rst0000666000175000017500000000254315132733117027657 0ustar00rgerrger.. _param-imuxsock-syssock-ignoretimestamp: .. _imuxsock.parameter.module.syssock-ignoretimestamp: SysSock.IgnoreTimestamp ======================= .. index:: single: imuxsock; SysSock.IgnoreTimestamp single: SysSock.IgnoreTimestamp .. summary-start Ignores timestamps included in messages from the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.IgnoreTimestamp :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Ignore timestamps included in the messages, applies to messages received via the system log socket. Module usage ------------ .. _param-imuxsock-module-syssock-ignoretimestamp: .. _imuxsock.parameter.module.syssock-ignoretimestamp-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.ignoreTimestamp="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogsocketignoremsgtimestamp: - $SystemLogSocketIgnoreMsgTimestamp — maps to SysSock.IgnoreTimestamp (status: legacy) .. index:: single: imuxsock; $SystemLogSocketIgnoreMsgTimestamp single: $SystemLogSocketIgnoreMsgTimestamp See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-provider.rst0000644000000000000000000000013215132733117024711 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.728438765 30 ctime=1787067792.688693263 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-provider.rst0000666000175000017500000000146315132733117024363 0ustar00rgerrger.. _param-mmaitag-provider: .. _mmaitag.parameter.action.provider: provider ======== .. index:: single: mmaitag; provider single: provider .. summary-start Selects which backend provider processes the classification (``gemini`` or ``gemini_mock``). .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: provider :Scope: action :Type: string :Default: gemini :Required?: no :Introduced: 9.0.0 Description ----------- Specifies which backend to use for classification. Supported values are ``gemini`` and ``gemini_mock``. Action usage ------------- .. _param-mmaitag-action-provider: .. _mmaitag.parameter.action.provider-usage: .. code-block:: rsyslog action(type="mmaitag" provider="gemini_mock") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssserverpermitplaintcp.rs0000644000000000000000000000013215171370365031154 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.596454947 30 ctime=1787067792.145683144 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssserverpermitplaintcp.rst0000664000175000017500000000334615171370365031012 0ustar00rgerrger.. _param-imgssapi-inputgssserverpermitplaintcp: .. _imgssapi.parameter.input.inputgssserverpermitplaintcp: InputGSSServerPermitPlainTcp ============================ .. index:: single: imgssapi; InputGSSServerPermitPlainTcp single: InputGSSServerPermitPlainTcp .. summary-start Allows accepting plain TCP syslog traffic on the GSS-protected port. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerPermitPlainTcp :Scope: input :Type: boolean :Default: 0 :Required?: no :Introduced: 3.11.6 Description ----------- Permits the server to receive plain TCP syslog (without GSS protection) on the same port that the GSS listener uses. .. warning:: This creates an intentional security downgrade path. Use it only on trusted networks. Plain TCP fallback is limited to connections that are identified as regular octet-counted syslog before GSS token processing begins; malformed GSS tokens are no longer reinterpreted as plain TCP traffic. Input usage ----------- .. _imgssapi.parameter.input.inputgssserverpermitplaintcp-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssServerPermitPlainTcp on Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssserverpermitplaintcp: - $InputGSSServerPermitPlainTCP — maps to InputGSSServerPermitPlainTcp (status: legacy) - $inputGssServerPermitPlainTcp — maps to InputGSSServerPermitPlainTcp (status: legacy) .. index:: single: imgssapi; $InputGSSServerPermitPlainTCP single: $InputGSSServerPermitPlainTCP single: imgssapi; $inputGssServerPermitPlainTcp single: $inputGssServerPermitPlainTcp See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxwindowsize.rst0000644000000000000000000000013215216464435026003 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.796440033 30 ctime=1787067791.353668385 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxwindowsize.rst0000664000175000017500000000204515216464435025450 0ustar00rgerrger.. _param-imbeats-maxwindowsize: .. _imbeats.parameter.input.maxwindowsize: maxWindowSize ============= .. meta:: :description: Maximum Lumberjack window size accepted by imbeats. :keywords: rsyslog, imbeats, maxWindowSize, Lumberjack window .. index:: single: imbeats; maxWindowSize single: maxWindowSize .. summary-start Limit how many events imbeats accepts in one Lumberjack batch window. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxWindowSize :Scope: input :Type: positive integer :Default: input=1024 :Required?: no :Introduced: 8.2604.0 Description ----------- Set the maximum Lumberjack v2 window size accepted by this imbeats listener. Connections that announce a larger window are rejected as protocol errors. Input usage ----------- .. _param-imbeats-input-maxwindowsize: .. _imbeats.parameter.input.maxwindowsize-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" maxWindowSize="1024") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-permittedpeer.rst0000644000000000000000000000013215216464435025744 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.819440462 30 ctime=1787067791.360668516 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-permittedpeer.rst0000664000175000017500000000165115216464435025413 0ustar00rgerrger.. _param-imbeats-permittedpeer: .. _imbeats.parameter.input.permittedpeer: PermittedPeer ============= .. meta:: :description: Allowed TLS peer names for imbeats. :keywords: rsyslog, imbeats, permittedpeer .. index:: single: imbeats; PermittedPeer single: PermittedPeer .. summary-start Restrict accepted TLS peers to the configured certificate names. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: PermittedPeer :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Restrict accepted TLS peers to the configured certificate names. Input usage ----------- .. _param-imbeats-input-permittedpeer: .. _imbeats.parameter.input.permittedpeer-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" permittedPeer=["beat.example.net"]) See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmpstrucdata-jsonroot.rst0000644000000000000000000000013215216464435026030 xustar0030 mtime=1782212893.987265553 30 atime=1787067672.948461509 30 ctime=1787067792.889697009 rsyslog-8.2608.0/doc/source/reference/parameters/mmpstrucdata-jsonroot.rst0000664000175000017500000000176315216464435025503 0ustar00rgerrger.. _param-mmpstrucdata-jsonroot: .. _mmpstrucdata.parameter.action.jsonroot: jsonRoot ======== .. index:: single: mmpstrucdata; jsonRoot single: jsonRoot .. summary-start Sets the JSON root container where parsed structured data is stored. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmpstrucdata`. :Name: jsonRoot :Scope: action :Type: string :Default: action="!" :Required?: no :Introduced: 7.5.4 Description ----------- Specifies into which JSON container the module writes its structured-data object. The object member name below this root is controlled by :ref:`param-mmpstrucdata-container`. Action usage ------------ .. _param-mmpstrucdata-action-jsonroot: .. _mmpstrucdata.parameter.action.jsonroot-usage: .. code-block:: rsyslog action(type="mmpstrucdata" jsonRoot="!") YAML usage ---------- .. code-block:: yaml actions: - type: mmpstrucdata jsonRoot: "!" See also -------- See also :doc:`../../configuration/modules/mmpstrucdata`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-template.rst0000644000000000000000000000013215132733117024566 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.241466971 30 ctime=1787067793.308704817 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-template.rst0000666000175000017500000000250215132733117024233 0ustar00rgerrger.. _param-omhttp-template: .. _omhttp.parameter.input.template: template ======== .. index:: single: omhttp; template single: template .. summary-start Selects the rsyslog template used to render each message before omhttp submits it. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: template :Scope: input :Type: word :Default: input=StdJSONFmt :Required?: no :Introduced: Not specified Description ----------- The template to be used for the messages. Note that in batching mode, this describes the format of *each* individual message, *not* the format of the resulting batch. Some batch modes require that a template produces valid JSON. Input usage ----------- .. _omhttp.parameter.input.template-usage: .. code-block:: rsyslog template(name="tpl_omhttp_json" type="list") { constant(value="{") property(name="msg" outname="message" format="jsonfr") constant(value=",") property(name="hostname" outname="host" format="jsonfr") constant(value=",") property(name="timereported" outname="timestamp" format="jsonfr" dateFormat="rfc3339") constant(value="}") } module(load="omhttp") action( type="omhttp" template="tpl_omhttp_json" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-headerless-ruleset.rst0000644000000000000000000000013215132411300026650 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.342450212 30 ctime=1787067793.610710445 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-headerless-ruleset.rst0000666000175000017500000000206015132411300026314 0ustar00rgerrger.. _param-pmrfc3164-headerless-ruleset: .. _pmrfc3164.parameter.module.headerless-ruleset: .. _pmrfc3164.parameter.module.headerless.ruleset: headerless.ruleset ================== .. index:: single: pmrfc3164; headerless.ruleset single: headerless.ruleset .. summary-start Route headerless messages to a specific ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: headerless.ruleset :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none :Required?: no :Introduced: 8.2508.0 Description ----------- If set, detected headerless messages are sent to the given ruleset for further processing, such as writing to a dedicated error log or discarding. Module usage ------------ .. _param-pmrfc3164-module-headerless-ruleset: .. _pmrfc3164.parameter.module.headerless-ruleset-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" headerless.ruleset="errorhandler") See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmcount-value.rst0000644000000000000000000000013215132733117024236 xustar0030 mtime=1768666703.912620314 30 atime=1787067672.052444806 30 ctime=1787067792.740694232 rsyslog-8.2608.0/doc/source/reference/parameters/mmcount-value.rst0000666000175000017500000000251115132733117023703 0ustar00rgerrger.. _param-mmcount-value: .. _mmcount.parameter.input.value: value ===== .. index:: single: mmcount; value single: value .. summary-start Counts only messages where the selected key equals the specified value. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmcount`. :Name: value :Scope: input :Type: word :Default: none (count every observed key value) :Required?: no :Introduced: 7.5.0 Description ----------- Limits counting to a specific property value when combined with :ref:`param-mmcount-key`. After :ref:`param-mmcount-appname` matches and the requested key is present, mmcount compares the property's string representation with ``value``. If they are equal, a dedicated counter is incremented and stored in the message's ``mmcount`` property. Messages that do not match are left unchanged. When ``value`` is not provided, mmcount maintains separate counters for each property value instead. Specifying ``value`` without :ref:`param-mmcount-key` has no practical effect; in that case the module still counts messages per severity. Input usage ----------- .. _param-mmcount-value-usage: .. _mmcount.parameter.input.value-usage: .. code-block:: rsyslog action(type="mmcount" appName="glusterfsd" key="!gf_code" value="9999") See also -------- See also :doc:`../../configuration/modules/mmcount`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-port.rst0000644000000000000000000000013115132733117023541 xustar0030 mtime=1768666703.909620269 29 atime=1787067674.31748703 30 ctime=1787067792.577691195 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-port.rst0000666000175000017500000000257215132733117023216 0ustar00rgerrger.. _param-imudp-port: .. _imudp.parameter.input.port: Port ==== .. index:: single: imudp; Port single: Port .. summary-start Port or array of ports for the UDP listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Port :Scope: input :Type: array[string] :Default: input=514 :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the port the server shall listen to. Either a single port can be specified or an array of ports. If multiple ports are specified, a listener will be automatically started for each port. Thus, no additional inputs need to be configured. Examples: .. code-block:: rsyslog module(load="imudp") # needs to be done just once input(type="imudp" port="514") .. code-block:: rsyslog module(load="imudp") input(type="imudp" port=["514","515","10514"]) Input usage ----------- .. _param-imudp-input-port: .. _imudp.parameter.input.port-usage: .. code-block:: rsyslog input(type="imudp" Port="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.udpserverrun: - $UDPServerRun — maps to Port (status: legacy) .. index:: single: imudp; $UDPServerRun single: $UDPServerRun See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssserverkeepalive.rst0000644000000000000000000000013215132733117030245 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.607455152 30 ctime=1787067792.140683051 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssserverkeepalive.rst0000666000175000017500000000216115132733117027713 0ustar00rgerrger.. _param-imgssapi-inputgssserverkeepalive: .. _imgssapi.parameter.input.inputgssserverkeepalive: InputGSSServerKeepAlive ======================= .. index:: single: imgssapi; InputGSSServerKeepAlive single: InputGSSServerKeepAlive .. summary-start Enables TCP keep-alive handling for GSS-protected connections. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerKeepAlive :Scope: input :Type: boolean :Default: 0 :Required?: no :Introduced: 8.5.0 Description ----------- Enables or disables keep-alive packets at the TCP socket layer. Input usage ----------- .. _imgssapi.parameter.input.inputgssserverkeepalive-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssServerKeepAlive on Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssserverkeepalive: - $inputGssServerKeepAlive — maps to InputGSSServerKeepAlive (status: legacy) .. index:: single: imgssapi; $inputGssServerKeepAlive single: $inputGssServerKeepAlive See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-server.rst0000644000000000000000000000013215145046112024424 xustar0030 mtime=1771326538.949012819 30 atime=1787067672.539453884 30 ctime=1787067793.439707258 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-server.rst0000664000175000017500000000143015145046112024066 0ustar00rgerrger.. _param-ompgsql-server: .. _ompgsql.parameter.input.server: Server ====== .. index:: single: ompgsql; Server single: Server .. summary-start Specifies the hostname or address of the PostgreSQL server when not using a connection string. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: Server :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.32.0 Description ----------- The hostname or address of the PostgreSQL server. Required if ``conninfo`` is not specified. Input usage ----------- .. _ompgsql.parameter.input.server-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" db="syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-socketbacklog.rst0000644000000000000000000000013215132733117025547 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.775476926 30 ctime=1787067792.385687617 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-socketbacklog.rst0000666000175000017500000000343015132733117025215 0ustar00rgerrger.. _param-imptcp-socketbacklog: .. _imptcp.parameter.input.socketbacklog: SocketBacklog ============= .. index:: single: imptcp; SocketBacklog single: SocketBacklog .. summary-start Sets the listen() backlog for pending TCP connections. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: SocketBacklog :Scope: input :Type: integer :Default: input=64 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the backlog parameter passed to the ``listen()`` system call. This parameter defines the maximum length of the queue for pending connections, which includes partially established connections (those in the SYN-ACK handshake phase) and fully established connections waiting to be accepted by the application. For more details, refer to the ``listen(2)`` man page. By default, the value is set to 64 to accommodate modern workloads. It can be adjusted to suit specific requirements, such as: - **High rates of concurrent connection attempts**: Increasing this value helps handle bursts of incoming connections without dropping them. - **Test environments with connection flooding**: Larger values are recommended to prevent SYN queue overflow. - **Servers with low traffic**: Lower values may be used to reduce memory usage. The effective backlog size is influenced by system-wide kernel settings, particularly ``net.core.somaxconn`` and ``net.ipv4.tcp_max_syn_backlog``. The smaller value between this parameter and the kernel limits is used as the actual backlog. Input usage ----------- .. _param-imptcp-input-socketbacklog: .. _imptcp.parameter.input.socketbacklog-usage: .. code-block:: rsyslog input(type="imptcp" socketBacklog="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-skipverifyhost.rst0000644000000000000000000000013215241075234027226 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.008680591 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-skipverifyhost.rst0000664000175000017500000000155015241075234026673 0ustar00rgerrger.. _param-imkubernetes-skipverifyhost: .. _imkubernetes.parameter.module.skipverifyhost: SkipVerifyHost ============== .. index:: single: imkubernetes; SkipVerifyHost single: SkipVerifyHost .. summary-start Disable TLS hostname verification for Kubernetes API requests; default ``off``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: SkipVerifyHost :Scope: module :Type: binary :Default: ``off`` :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled, ``imkubernetes`` does not verify that the Kubernetes API server certificate matches the requested host name. Use only for testing or temporary workarounds. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" SkipVerifyHost="on") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-hostname.rst0000644000000000000000000000013215132733117025120 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.998481083 30 ctime=1787067792.609691791 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-hostname.rst0000666000175000017500000000227015132733117024567 0ustar00rgerrger.. _param-imuxsock-hostname: .. _imuxsock.parameter.input.hostname: HostName ======== .. index:: single: imuxsock; HostName single: HostName .. summary-start Overrides the hostname used inside messages from this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: HostName :Scope: input :Type: string :Default: input=NULL :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Allows overriding the hostname that shall be used inside messages taken from the input that is being defined. Input usage ----------- .. _param-imuxsock-input-hostname: .. _imuxsock.parameter.input.hostname-usage: .. code-block:: rsyslog input(type="imuxsock" hostName="jail1.example.net") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensockethostname: - $InputUnixListenSocketHostName — maps to HostName (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketHostName single: $InputUnixListenSocketHostName See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-serverstreamdriverpermittedpeer.r0000644000000000000000000000013215216464435031062 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.096445626 30 ctime=1787067791.962679734 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-serverstreamdriverpermittedpeer.rst0000664000175000017500000000427615216464435031106 0ustar00rgerrger.. _param-imdiag-serverstreamdriverpermittedpeer: .. _imdiag.parameter.module.serverstreamdriverpermittedpeer: ServerStreamDriverPermittedPeer =============================== .. index:: single: imdiag; ServerStreamDriverPermittedPeer single: ServerStreamDriverPermittedPeer .. summary-start Accepts permitted peer identifiers for compatibility, but the plain TCP driver used by imdiag does not enforce them. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ServerStreamDriverPermittedPeer :Scope: module :Type: array :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines the set of remote peers that may connect when the chosen :doc:`network stream driver <../../concepts/netstrm_drvr>` supports authentication. imdiag always uses the plain TCP (``ptcp``) stream driver, which offers no peer verification. As a result, the configured identities are accepted but ignored. The parameter is kept for forward compatibility with the generic TCP listener framework should imdiag gain authenticated stream support in the future. Configure this parameter before :ref:`ServerRun ` if you need to preserve configuration compatibility. When multiple peers are listed, provide an array of identity strings even though the ``ptcp`` driver ignores them. Module usage ------------ .. _param-imdiag-module-serverstreamdriverpermittedpeer: .. _imdiag.parameter.module.serverstreamdriverpermittedpeer-usage: .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/var/run/rsyslog/imdiag.port" serverStreamDriverPermittedPeer=["diag.example.com","127.0.0.1"] serverRun="19998") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagserverstreamdriverpermittedpeer: - $IMDiagServerStreamDriverPermittedPeer — maps to ServerStreamDriverPermittedPeer (status: legacy) .. index:: single: imdiag; $IMDiagServerStreamDriverPermittedPeer single: $IMDiagServerStreamDriverPermittedPeer See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-keepalive.rst0000644000000000000000000000013215145046112024677 xustar0030 mtime=1771326538.951012852 30 atime=1787067673.133464958 30 ctime=1787067793.488708171 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-keepalive.rst0000664000175000017500000000150115145046112024340 0ustar00rgerrger.. _param-omrelp-keepalive: .. _omrelp.parameter.input.keepalive: KeepAlive ========= .. index:: single: omrelp; KeepAlive single: KeepAlive .. summary-start Enables or disables TCP keep-alive packets for the RELP connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: KeepAlive :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Enable or disable keep-alive packets at the TCP socket layer. By default keep-alive is disabled. Input usage ----------- .. _param-omrelp-input-keepalive: .. _omrelp.parameter.input.keepalive-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" keepAlive="on") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxcompressionratio.rst0000644000000000000000000000013115241075234027171 xustar0030 mtime=1787067036.579577808 30 atime=1787067036.676579624 29 ctime=1787067791.34266818 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxcompressionratio.rst0000664000175000017500000000313715241075234026642 0ustar00rgerrger.. _param-imbeats-maxcompressionratio: .. _imbeats.parameter.input.maxcompressionratio: maxCompressionRatio =================== .. meta:: :description: Maximum decompression ratio accepted for imbeats Lumberjack compressed frames. :keywords: rsyslog, imbeats, maxCompressionRatio, compression ratio, Lumberjack .. index:: single: imbeats; maxCompressionRatio single: maxCompressionRatio .. summary-start Limit how many output bytes a Lumberjack compressed frame may produce per input byte. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxCompressionRatio :Scope: input :Type: positive integer :Default: input=256 :Required?: no :Introduced: 8.2608.0 Description ----------- Set the maximum permitted ratio of decompressed bytes to compressed input bytes. The valid range is ``1`` to ``1000000``. A compressed frame is rejected as soon as its decompressed output would exceed the compressed input size multiplied by this value. This ratio limit is enforced together with :ref:`param-imbeats-maxdecompressedsize` and :ref:`param-imbeats-maxinflightbytes`. A frame must satisfy all applicable limits and is not acknowledged when any limit is exceeded. Input usage ----------- .. _param-imbeats-input-maxcompressionratio: .. _imbeats.parameter.input.maxcompressionratio-usage: RainerScript: .. code-block:: rsyslog input(type="imbeats" port="5044" maxCompressionRatio="256") YAML: .. code-block:: yaml inputs: - type: imbeats port: 5044 maxCompressionRatio: 256 See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-port.rst0000644000000000000000000000013215145046112023716 xustar0030 mtime=1771326538.952012868 30 atime=1787067673.292467922 30 ctime=1787067793.492708246 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-port.rst0000664000175000017500000000137015145046112023363 0ustar00rgerrger.. _param-omrelp-port: .. _omrelp.parameter.input.port: Port ==== .. index:: single: omrelp; Port single: Port .. summary-start Specifies the TCP port number or service name for the RELP connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: Port :Scope: input :Type: string :Default: input=514 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Name or numerical value of TCP port to use when connecting to target. Input usage ----------- .. _param-omrelp-input-port: .. _omrelp.parameter.input.port-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" port="2514") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-policy.rst0000644000000000000000000000013115171370365026202 xustar0030 mtime=1776677109.118908099 29 atime=1787067672.57945463 30 ctime=1787067792.809695518 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-policy.rst0000664000175000017500000000454515171370365025657 0ustar00rgerrger.. _param-mmjsontransform-policy: .. _mmjsontransform-policy: .. _mmjsontransform.parameter.input.policy: policy ====== .. index:: single: mmjsontransform; policy single: policy .. summary-start Loads a YAML policy file that can select the transformation mode and rename or drop keys before processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: policy :Scope: input :Type: string :Default: unset :Required?: no :Introduced: 8.2602.0 Description ----------- When set, ``mmjsontransform`` loads a YAML policy file during startup and re-checks it on ``HUP``. When :ref:`policyWatch ` is enabled, the same file can also be reloaded automatically after watched updates. If reload fails, the previous in-memory policy is kept. The current implementation supports these sections: ``mode`` Selects ``unflatten`` or ``flatten`` from the policy file. When present, this overrides the action parameter on startup and after a successful ``HUP`` reload. ``map.rename`` Mapping of source keys to destination keys. Both keys are dotted JSON paths. ``map.drop`` Sequence of dotted JSON paths that should be removed before transformation. The policy is applied before the selected transformation mode runs. This makes it possible to drop noisy fields, normalize names, and switch between ``flatten`` and ``unflatten`` from one reloadable file. ``input`` and ``output`` remain action parameters because they define which message properties are read and written; the policy file only controls the transformation behavior. If rsyslog is compiled without libyaml support, setting ``policy`` produces a configuration error. Input usage ----------- .. _param-mmjsontransform-policy-usage: .. _mmjsontransform.parameter.input.policy-usage: .. code-block:: rsyslog action(type="mmjsontransform" policy="/etc/rsyslog/mmjsontransform-policy.yaml" policyWatch="on" policyWatchDebounce="500ms" input="$!raw" output="$!normalized") Example policy file ------------------- .. code-block:: yaml version: 1 mode: unflatten map: rename: "usr": "user.name" "ctx.old": "ctx.new" drop: - "debug" See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-ratelimit-burst.rst0000644000000000000000000000013115132733117026062 xustar0030 mtime=1768666703.907620238 29 atime=1787067673.75047646 30 ctime=1787067792.376687449 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-ratelimit-burst.rst0000666000175000017500000000146515132733117025537 0ustar00rgerrger.. _param-imptcp-ratelimit-burst: .. _imptcp.parameter.input.ratelimit-burst: RateLimit.Burst =============== .. index:: single: imptcp; RateLimit.Burst single: RateLimit.Burst .. summary-start Sets the rate-limiting burst size in number of messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: RateLimit.Burst :Scope: input :Type: integer :Default: input=10000 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the rate-limiting burst in number of messages. Input usage ----------- .. _param-imptcp-input-ratelimit-burst: .. _imptcp.parameter.input.ratelimit-burst-usage: .. code-block:: rsyslog input(type="imptcp" rateLimit.burst="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-tlsverifydepth.rst0000644000000000000000000000013215216464435030654 xustar0030 mtime=1782212893.984265505 30 atime=1787067671.766439474 30 ctime=1787067791.393669131 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-tlsverifydepth.rst0000664000175000017500000000212415216464435030317 0ustar00rgerrger.. _param-imbeats-streamdriver-tlsverifydepth: .. _imbeats.parameter.input.streamdriver-tlsverifydepth: StreamDriver.TlsVerifyDepth =========================== .. meta:: :description: Certificate chain depth for imbeats TLS validation. :keywords: rsyslog, imbeats, tls verify depth .. index:: single: imbeats; StreamDriver.TlsVerifyDepth single: StreamDriver.TlsVerifyDepth .. summary-start Set the maximum certificate chain depth accepted during imbeats TLS validation. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.TlsVerifyDepth :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: 8.2604.0 Description ----------- Set the maximum certificate chain depth accepted during imbeats TLS validation. Input usage ----------- .. _param-imbeats-input-streamdriver-tlsverifydepth: .. _imbeats.parameter.input.streamdriver-tlsverifydepth-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.tlsVerifyDepth="5") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-keyfile.rst0000644000000000000000000000013115216464435027227 xustar0030 mtime=1782212893.983265489 29 atime=1787067671.86544132 30 ctime=1787067791.380668888 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-keyfile.rst0000664000175000017500000000200715216464435026673 0ustar00rgerrger.. _param-imbeats-streamdriver-keyfile: .. _imbeats.parameter.input.streamdriver-keyfile: StreamDriver.KeyFile ==================== .. meta:: :description: Private key file for imbeats TLS listeners. :keywords: rsyslog, imbeats, streamdriver keyfile .. index:: single: imbeats; StreamDriver.KeyFile single: StreamDriver.KeyFile .. summary-start Specify the private key file used by TLS-enabled imbeats listeners. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.KeyFile :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Specify the private key file used by TLS-enabled imbeats listeners. Input usage ----------- .. _param-imbeats-input-streamdriver-keyfile: .. _imbeats.parameter.input.streamdriver-keyfile-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.keyFile="/etc/rsyslog/key.pem") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-pollinginterval.rst0000644000000000000000000000013115132733117026115 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.355450454 29 ctime=1787067792.09768225 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-pollinginterval.rst0000666000175000017500000000301215132733117025560 0ustar00rgerrger.. _param-imfile-pollinginterval: .. _imfile.parameter.module.pollinginterval: .. _imfile.parameter.pollinginterval: PollingInterval =============== .. index:: single: imfile; PollingInterval single: PollingInterval .. summary-start Seconds between file scans in polling mode; default ``10``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: PollingInterval :Scope: module :Type: integer :Default: module=10 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Specifies how often files are polled for new data. It has effect only if imfile is running in polling mode. The time specified is in seconds. During each polling interval, all files are processed in a round-robin fashion. A short poll interval provides more rapid message forwarding, but requires more system resources. While it is possible, it is strongly recommended not to set the polling interval to 0 seconds. That will make rsyslogd become a CPU hog, taking up considerable resources. Even if quick response is needed, 1 second should be sufficient. imfile keeps reading files as long as there is any data in them, so a "polling sleep" will only happen when nothing is left to be processed. **We recommend to use inotify mode.** Module usage ------------ .. _param-imfile-module-pollinginterval: .. _imfile.parameter.module.pollinginterval-usage: .. code-block:: rsyslog module(load="imfile" PollingInterval="10") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ratelimit-burst.rst0000644000000000000000000000013215132733117026431 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.090482798 30 ctime=1787067792.619691977 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ratelimit-burst.rst0000666000175000017500000000225115132733117026077 0ustar00rgerrger.. _param-imuxsock-ratelimit-burst: .. _imuxsock.parameter.input.ratelimit-burst: RateLimit.Burst =============== .. index:: single: imuxsock; RateLimit.Burst single: RateLimit.Burst .. summary-start Sets the rate-limiting burst size in messages for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: RateLimit.Burst :Scope: input :Type: integer :Default: input=200 :Required?: no :Introduced: 5.7.1 Description ----------- Specifies the rate-limiting burst in number of messages. The maximum is ``(2^31)-1``. Input usage ----------- .. _param-imuxsock-input-ratelimit-burst: .. _imuxsock.parameter.input.ratelimit-burst-usage: .. code-block:: rsyslog input(type="imuxsock" rateLimit.burst="500") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.imuxsockratelimitburst: - $IMUXSockRateLimitBurst — maps to RateLimit.Burst (status: legacy) .. index:: single: imuxsock; $IMUXSockRateLimitBurst single: $IMUXSockRateLimitBurst See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls.rst0000644000000000000000000000013215132733117023532 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.896479182 30 ctime=1787067792.446688753 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls.rst0000666000175000017500000000237715132733117023211 0ustar00rgerrger.. _param-imrelp-tls: .. _imrelp.parameter.input.tls: tls === .. index:: single: imrelp; tls single: tls (imrelp) .. summary-start Enables TLS encryption for RELP connections handled by this listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not documented Description ----------- If set to "on", the RELP connection will be encrypted by TLS, so that the data is protected against observers. Please note that both the client and the server must have set ``tls`` to either "on" or "off". Other combinations lead to unpredictable results. *Attention when using GnuTLS 2.10.x or older* Versions older than GnuTLS 2.10.x may cause a crash (Segfault) under certain circumstances. Most likely when an imrelp inputs and an omrelp output is configured. The crash may happen when you are receiving/sending messages at the same time. Upgrade to a newer version like GnuTLS 2.12.21 to solve the problem. Input usage ----------- .. _param-imrelp-input-tls-usage: .. _imrelp.parameter.input.tls-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-port.rst0000644000000000000000000000013115132733117023725 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.790439921 29 ctime=1787067793.00569917 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-port.rst0000666000175000017500000000147215132733117023400 0ustar00rgerrger.. _param-omdtls-port: .. _omdtls.parameter.input.port: port ==== .. index:: single: omdtls; port single: port .. summary-start Sets the UDP port on the remote host that receives DTLS messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: port :Scope: input :Type: word :Default: input=443 :Required?: no :Introduced: v8.2402.0 Description ----------- Defines the port number on the target host where log messages will be sent. The standard port for DTLS is 4433. This should be specified explicitly if required, as the module defaults to port 443. Input usage ----------- .. _omdtls.parameter.input.port-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-dynatopic.rst0000644000000000000000000000013215132411300025026 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.908460763 30 ctime=1787067793.338705376 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-dynatopic.rst0000666000175000017500000000163115132411300024475 0ustar00rgerrger.. _param-omkafka-dynatopic: .. _omkafka.parameter.module.dynatopic: DynaTopic ========= .. index:: single: omkafka; DynaTopic single: DynaTopic .. summary-start Treat `topic` as a template for dynamic topic names. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: DynaTopic :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, the topic parameter becomes a template for which topic to produce messages to. The cache is cleared on HUP. Action usage ------------ .. _param-omkafka-action-dynatopic: .. _omkafka.parameter.action.dynatopic: .. code-block:: rsyslog action(type="omkafka" DynaTopic="on" Topic="topic.template") Notes ----- - Originally documented as "binary"; uses boolean values. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-dce_url.rst0000644000000000000000000000013215171370365025220 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.488471576 30 ctime=1787067792.945698052 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-dce_url.rst0000664000175000017500000000214715171370365024670 0ustar00rgerrger.. _param-omazuredce-dce_url: .. _omazuredce.parameter.action.dce_url: .. meta:: :description: Reference for the omazuredce dce_url parameter. :keywords: rsyslog, omazuredce, dce_url, azure, logs ingestion dce_url ======= .. index:: single: omazuredce; dce_url single: dce_url .. summary-start Defines the Azure Data Collection Endpoint base URL used for batch submission. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: dce_url :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``dce_url`` is the base HTTPS endpoint for the Azure Logs Ingestion API. The module appends the DCR and stream path segments to this URL when constructing requests. Both forms with and without a trailing slash are accepted. Action usage ------------ .. _omazuredce.parameter.action.dce_url-usage: .. code-block:: rsyslog action( type="omazuredce" dce_url="https://..ingest.monitor.azure.com" ... ) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-keepalive-time.rst0000644000000000000000000000013215132733117025635 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.730476087 30 ctime=1787067792.350686964 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-keepalive-time.rst0000666000175000017500000000273215132733117025307 0ustar00rgerrger.. _param-imptcp-keepalive-time: .. _imptcp.parameter.input.keepalive-time: KeepAlive.Time ============== .. index:: single: imptcp; KeepAlive.Time single: KeepAlive.Time .. summary-start Sets idle time before the first keepalive probe is sent. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: KeepAlive.Time :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further. The default, 0, means that the operating system defaults are used. This has only effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imptcp-input-keepalive-time: .. _imptcp.parameter.input.keepalive-time-usage: .. code-block:: rsyslog input(type="imptcp" keepAlive.time="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverkeepalive_time: - $InputPTCPServerKeepAlive_time — maps to KeepAlive.Time (status: legacy) .. index:: single: imptcp; $InputPTCPServerKeepAlive_time single: $InputPTCPServerKeepAlive_time See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-tlsrevocationcheck.0000644000000000000000000000013215216464435030741 xustar0030 mtime=1782212893.984265505 30 atime=1787067671.728438765 30 ctime=1787067791.391669093 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-tlsrevocationcheck.rst0000664000175000017500000000220015216464435031130 0ustar00rgerrger.. _param-imbeats-streamdriver-tlsrevocationcheck: .. _imbeats.parameter.input.streamdriver-tlsrevocationcheck: StreamDriver.TlsRevocationCheck =============================== .. meta:: :description: Revocation checking for imbeats TLS peers. :keywords: rsyslog, imbeats, tls revocation check .. index:: single: imbeats; StreamDriver.TlsRevocationCheck single: StreamDriver.TlsRevocationCheck .. summary-start Enable TLS revocation checking for certificates presented to the imbeats listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.TlsRevocationCheck :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2604.0 Description ----------- Enable TLS revocation checking for certificates presented to the imbeats listener. Input usage ----------- .. _param-imbeats-input-streamdriver-tlsrevocationcheck: .. _imbeats.parameter.input.streamdriver-tlsrevocationcheck-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.tlsRevocationCheck="on") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-consumergroup.rst0000644000000000000000000000013215132733117025753 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.974461994 30 ctime=1787067792.220684542 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-consumergroup.rst0000666000175000017500000000157615132733117025432 0ustar00rgerrger.. _param-imkafka-consumergroup: .. _imkafka.parameter.input.consumergroup: consumergroup ============= .. index:: single: imkafka; consumergroup single: consumergroup .. summary-start Sets the Kafka consumer group identifier (group.id) used by imkafka. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: consumergroup :Scope: input :Type: string :Default: input=``none`` :Required?: no :Introduced: 8.27.0 Description ----------- With this parameter the group.id for the consumer is set. All consumers sharing the same group.id belong to the same group. Input usage ----------- .. _imkafka.parameter.input.consumergroup-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="your-topic" consumerGroup="default") See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-statefile.rst0000644000000000000000000000013015132411300025401 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.843459552 28 ctime=1787067792.2076843 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-statefile.rst0000666000175000017500000000231115132411300025046 0ustar00rgerrger.. _param-imjournal-statefile: .. _imjournal.parameter.module.statefile: .. meta:: :tag: module:imjournal :tag: parameter:StateFile StateFile ========= .. index:: single: imjournal; StateFile single: StateFile .. summary-start Specifies path to the state file holding the journal cursor. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: StateFile :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines where the module stores its persistent position in the journal. A relative path is created inside rsyslog's working directory; an absolute path is used as is. Module usage ------------ .. _param-imjournal-module-statefile: .. _imjournal.parameter.module.statefile-usage: .. code-block:: rsyslog module(load="imjournal" StateFile="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournalstatefile: - $imjournalStateFile — maps to StateFile (status: legacy) .. index:: single: imjournal; $imjournalStateFile single: $imjournalStateFile See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omstdout-ensurelfending.rst0000644000000000000000000000013115145046112026321 xustar0030 mtime=1771326538.957012949 29 atime=1787067671.83544076 30 ctime=1787067793.564709587 rsyslog-8.2608.0/doc/source/reference/parameters/omstdout-ensurelfending.rst0000664000175000017500000000245015145046112025767 0ustar00rgerrger.. _param-omstdout-ensurelfending: .. _omstdout.parameter.input.ensurelfending: ensureLFEnding ============== .. index:: single: omstdout; ensureLFEnding single: ensureLFEnding .. summary-start Ensures each message is written with a terminating line feed when sent to stdout. .. summary-end This parameter applies to :doc:`../../configuration/modules/omstdout`. :Name: ensureLFEnding :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 4.1.6 Description ----------- Ensures that each message is written with a terminating line feed. If the message already contains a trailing line feed, none is added. This is needed for the automated tests. Input usage ----------- .. _param-omstdout-input-ensurelfending: .. _omstdout.parameter.input.ensurelfending-usage: .. code-block:: rsyslog action(type="omstdout" ensureLFEnding="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omstdout.parameter.legacy.actionomstdoutensurelfending: - ``$ActionOMStdoutEnsureLFEnding`` — maps to ensureLFEnding (status: legacy) .. index:: single: omstdout; $ActionOMStdoutEnsureLFEnding single: $ActionOMStdoutEnsureLFEnding See also -------- See also :doc:`../../configuration/modules/omstdout`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-cry-provider.rst0000644000000000000000000000013015132411300025321 xustar0030 mtime=1768559296.209884738 28 atime=1787067672.5724545 30 ctime=1787067793.143701742 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-cry-provider.rst0000666000175000017500000000173715132411300025001 0ustar00rgerrger.. _param-omfile-cry-provider: .. _omfile.parameter.module.cry-provider: cry.Provider ============ .. index:: single: omfile; cry.Provider single: cry.Provider .. summary-start Selects a crypto provider for log encryption. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: cry.Provider :Scope: action :Type: word :Default: action=no crypto provider :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Selects a crypto provider for log encryption. By selecting a provider, the encryption feature is turned on. Currently, there are two providers called ":doc:`gcry <../../configuration/cryprov_gcry>`" and ":doc:`ossl <../../configuration/cryprov_ossl>`". Action usage ------------ .. _param-omfile-action-cry-provider: .. _omfile.parameter.action.cry-provider: .. code-block:: rsyslog action(type="omfile" cry.Provider="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-mailto.rst0000644000000000000000000000013115132733117024202 xustar0030 mtime=1768666703.918620405 29 atime=1787067672.80045875 30 ctime=1787067793.391706364 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-mailto.rst0000666000175000017500000000246315132733117023656 0ustar00rgerrger.. _param-ommail-mailto: .. _ommail.parameter.input.mailto: mailTo ====== .. index:: single: ommail; mailTo single: mailTo .. summary-start Provides one or more recipient email addresses for each mail sent by ommail. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: mailTo :Scope: input :Type: array :Default: input=none :Required?: yes :Introduced: 8.5.0 Description ----------- The recipient email address(es). This is an array parameter, so multiple recipients can be provided in a list. For a single recipient, a simple string value is also accepted (for example, ``mailTo="operator@example.net"``). Input usage ------------ .. _ommail.parameter.input.mailto-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo=["operator@example.net", "admin@example.net"] ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailto: - $ActionMailTo — maps to mailTo (status: legacy) .. index:: single: ommail; $ActionMailTo single: $ActionMailTo See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-ignorepreviousmessages.rst0000644000000000000000000000013215132411300030233 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.857459813 30 ctime=1787067792.184683871 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-ignorepreviousmessages.rst0000666000175000017500000000276515132411300027713 0ustar00rgerrger.. _param-imjournal-ignorepreviousmessages: .. _imjournal.parameter.module.ignorepreviousmessages: .. meta:: :tag: module:imjournal :tag: parameter:IgnorePreviousMessages IgnorePreviousMessages ====================== .. index:: single: imjournal; IgnorePreviousMessages single: IgnorePreviousMessages .. summary-start Starts reading only new journal entries when no state file exists. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: IgnorePreviousMessages :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If enabled and no state file is present, messages already stored in the journal are skipped and only new entries are processed, preventing reprocessing of old logs. Module usage ------------ .. _param-imjournal-module-ignorepreviousmessages: .. _imjournal.parameter.module.ignorepreviousmessages-usage: .. code-block:: rsyslog module(load="imjournal" IgnorePreviousMessages="...") Notes ----- - Historic documentation called this a ``binary`` option; it is boolean. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournalignorepreviousmessages: - $ImjournalIgnorePreviousMessages — maps to IgnorePreviousMessages (status: legacy) .. index:: single: imjournal; $ImjournalIgnorePreviousMessages single: $ImjournalIgnorePreviousMessages See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-ciphersuites.rst0000644000000000000000000000013215241075234030115 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.104701015 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-ciphersuites.rst0000664000175000017500000000276615241075234027574 0ustar00rgerrger.. _param-omelasticsearch-tls-ciphersuites: .. _omelasticsearch.parameter.module.tls-ciphersuites: .. _omelasticsearch.parameter.module.tls.ciphersuites: tls.ciphersuites ================ .. index:: single: omelasticsearch; tls.ciphersuites single: tls.ciphersuites .. summary-start TLS 1.3 cipher suite selection for the Elasticsearch connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.ciphersuites :Scope: action :Type: word :Default: none (libcurl/OpenSSL default) :Required?: no :Introduced: 8.2606.0 Description ----------- Passes a colon-separated list of TLS 1.3 cipher suite names to libcurl (``CURLOPT_TLS13_CIPHERS``). The string is validated by OpenSSL at connection time; an invalid name causes the handshake to fail. Requires libcurl 7.61.0 or later. If rsyslog was built against an older libcurl, configuring this parameter has no effect and a warning is logged at configuration load. Action usage ------------ .. _param-omelasticsearch-action-tls-ciphersuites: .. _omelasticsearch.parameter.action.tls-ciphersuites: .. code-block:: rsyslog action(type="omelasticsearch" tls.ciphersuites="TLS_AES_256_GCM_SHA384") YAML usage ---------- .. code-block:: yaml actions: - type: omelasticsearch tls.ciphersuites: "TLS_AES_256_GCM_SHA384" See also -------- See also :doc:`../../configuration/modules/omelasticsearch`, :ref:`param-omelasticsearch-tls-tlsversion`, :ref:`param-omelasticsearch-tls-keyexchangegroups`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-template.rst0000644000000000000000000000013115132411300024646 xustar0030 mtime=1768559296.213884802 30 atime=1787067673.204466281 29 ctime=1787067793.36470586 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-template.rst0000666000175000017500000000137015132411300024316 0ustar00rgerrger.. _param-omkafka-template: .. _omkafka.parameter.module.template: Template ======== .. index:: single: omkafka; Template single: Template .. summary-start Template used to format messages for this action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Template :Scope: action :Type: word :Default: action=inherits module :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Sets the template to be used for this action. Action usage ------------ .. _param-omkafka-action-template: .. _omkafka.parameter.action.template: .. code-block:: rsyslog action(type="omkafka" Template="MyTemplate") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-enterpriseoid.rst0000644000000000000000000000013215132733117025625 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.778439698 30 ctime=1787067793.541709159 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-enterpriseoid.rst0000666000175000017500000000254415132733117025300 0ustar00rgerrger.. _param-omsnmp-enterpriseoid: .. _omsnmp.parameter.module.enterpriseoid: EnterpriseOID ============= .. index:: single: omsnmp; EnterpriseOID single: EnterpriseOID .. summary-start Specifies the enterprise OID used in SNMPv1 traps. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: EnterpriseOID :Scope: module :Type: string :Default: module=1.3.6.1.4.1.3.1.1 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- The default value means "enterprises.cmu.1.1" Customize this value if needed. I recommend to use the default value unless you require to use a different OID. This configuration parameter is used for **SNMPv1** only. It has no effect if **SNMPv2** is used. Module usage ------------ .. _param-omsnmp-module-enterpriseoid: .. _omsnmp.parameter.module.enterpriseoid-usage: .. code-block:: rsyslog action(type="omsnmp" enterpriseOID="1.3.6.1.4.1.3.1.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmpenterpriseoid: - $actionsnmpenterpriseoid — maps to EnterpriseOID (status: legacy) .. index:: single: omsnmp; $actionsnmpenterpriseoid single: $actionsnmpenterpriseoid See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-inputproperty.rst0000644000000000000000000000013215132733117026023 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.746439101 30 ctime=1787067792.684693189 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-inputproperty.rst0000666000175000017500000000152315132733117025472 0ustar00rgerrger.. _param-mmaitag-inputproperty: .. _mmaitag.parameter.action.inputproperty: inputProperty ============= .. index:: single: mmaitag; inputProperty single: inputProperty .. summary-start Selects which message property is classified instead of the raw message. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: inputProperty :Scope: action :Type: string :Default: none (raw message is used) :Required?: no :Introduced: 9.0.0 Description ----------- Specifies which message property to classify. If unset, the module uses the raw message text. Action usage ------------- .. _param-mmaitag-action-inputproperty: .. _mmaitag.parameter.action.inputproperty-usage: .. code-block:: rsyslog action(type="mmaitag" inputProperty="msg") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-permitexpiredcerts.rs0000644000000000000000000000013215132733117031017 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.022481531 30 ctime=1787067792.543690561 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-permitexpiredcerts.rst0000666000175000017500000000327015132733117030653 0ustar00rgerrger.. _param-imtcp-streamdriver-permitexpiredcerts: .. _imtcp.parameter.module.streamdriver-permitexpiredcerts: .. _imtcp.parameter.input.streamdriver-permitexpiredcerts: StreamDriver.PermitExpiredCerts =============================== .. index:: single: imtcp; StreamDriver.PermitExpiredCerts single: StreamDriver.PermitExpiredCerts .. summary-start Controls how expired certificates are handled in TLS mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.PermitExpiredCerts :Scope: module, input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=warn, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Controls how expired certificates will be handled when stream driver is in TLS mode. It can have one of the following values: - on = Expired certificates are allowed - off = Expired certificates are not allowed (Default, changed from warn to off since Version 8.2012.0) - warn = Expired certificates are allowed but warning will be logged The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-permitexpiredcerts: .. _imtcp.parameter.module.streamdriver-permitexpiredcerts-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.permitExpiredCerts="off") Input usage ----------- .. _param-imtcp-input-streamdriver-permitexpiredcerts: .. _imtcp.parameter.input.streamdriver-permitexpiredcerts-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.permitExpiredCerts="off") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-sourceport-start.rst0000644000000000000000000000013215145046112027167 xustar0030 mtime=1771326538.958012966 30 atime=1787067671.957443035 30 ctime=1787067793.575709793 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-sourceport-start.rst0000664000175000017500000000247415145046112026642 0ustar00rgerrger.. _param-omudpspoof-sourceport-start: .. _omudpspoof.parameter.action.sourceport-start: sourcePort.start ================ .. index:: single: omudpspoof; sourcePort.start single: sourcePort.start .. summary-start Sets the starting source port when cycling through spoofed source ports. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: sourcePort.start :Scope: action :Type: integer :Default: 32000 :Required?: no :Introduced: 5.1.3 Description ----------- Specify the start value for circling the source ports. Start must be less than or equal to sourcePort.end. Action usage ------------ .. _param-omudpspoof-action-sourceport-start: .. _omudpspoof.parameter.action.sourceport-start-usage: .. code-block:: rsyslog action(type="omudpspoof" target="192.0.2.1" sourcePort.start="10000" sourcePort.end="19999") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspoofsourceportstart: - $ActionOMUDPSpoofSourcePortStart — maps to sourcePort.start (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofSourcePortStart single: $ActionOMUDPSpoofSourcePortStart See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-name.rst0000644000000000000000000000013215216464435024013 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.804440182 30 ctime=1787067791.356668441 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-name.rst0000664000175000017500000000153415216464435023462 0ustar00rgerrger.. _param-imbeats-name: .. _imbeats.parameter.input.name: name ==== .. meta:: :description: Input name for imbeats messages. :keywords: rsyslog, imbeats, name .. index:: single: imbeats; name single: name .. summary-start Set the ``inputname`` property used for messages received by this imbeats input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: name :Scope: input :Type: string :Default: input=imbeats :Required?: no :Introduced: 8.2604.0 Description ----------- Set the ``inputname`` property used for messages received by this imbeats input. Input usage ----------- .. _param-imbeats-input-name: .. _imbeats.parameter.input.name-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" name="imbeats") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-socket.rst0000644000000000000000000000013215241075234024572 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.725580541 30 ctime=1787067792.630692182 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-socket.rst0000664000175000017500000000246215241075234024242 0ustar00rgerrger.. _param-imuxsock-socket: .. _imuxsock.parameter.input.socket: Socket ====== .. index:: single: imuxsock; Socket single: Socket .. summary-start Adds an additional UNIX socket for this input to listen on. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: Socket :Scope: input :Type: string :Default: input=none :Required?: yes :Introduced: at least 7.0.0, possibly earlier Description ----------- Adds an additional unix socket. Formerly specified with the ``-a`` option. This parameter is required for every ``input(type="imuxsock" ...)`` object, because input objects configure additional sockets only. The system log socket is configured on the module object with ``SysSock.*`` parameters. Input usage ----------- .. _param-imuxsock-input-socket: .. _imuxsock.parameter.input.socket-usage: .. code-block:: rsyslog input(type="imuxsock" socket="/path/to/socket") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.addunixlistensocket: - $AddUnixListenSocket — maps to Socket (status: legacy) .. index:: single: imuxsock; $AddUnixListenSocket single: $AddUnixListenSocket See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-bits.rst0000644000000000000000000000013115132733117026217 xustar0030 mtime=1768666703.911620299 29 atime=1787067671.90944214 30 ctime=1787067792.696693412 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-bits.rst0000666000175000017500000000233415132733117025670 0ustar00rgerrger.. _param-mmanon-embeddedipv4-bits: .. _mmanon.parameter.input.embeddedipv4-bits: embeddedIpv4.bits ================= .. index:: single: mmanon; embeddedIpv4.bits single: embeddedIpv4.bits .. summary-start Sets how many low-order bits of embedded IPv4 addresses within IPv6 are anonymized. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.bits :Scope: input :Type: positive integer :Default: input=96 :Required?: no :Introduced: 7.3.7 Description ----------- This sets the number of bits that should be anonymized (bits are from the right, so lower bits are anonymized first). This setting permits to save network information while still anonymizing user-specific data. The more bits you discard, the better the anonymization obviously is. The default of 96 bits reflects what German data privacy rules consider as being sufficiently anonymized. We assume, this can also be used as a rough but conservative guideline for other countries. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-bits-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.bits="80") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-retryruleset.rst0000644000000000000000000000013215132411300027342 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.202447602 30 ctime=1787067793.081700587 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-retryruleset.rst0000666000175000017500000000161015132411300027006 0ustar00rgerrger.. _param-omelasticsearch-retryruleset: .. _omelasticsearch.parameter.module.retryruleset: retryruleset ============ .. index:: single: omelasticsearch; retryruleset single: retryruleset .. summary-start Ruleset used when processing retried records. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: retryruleset :Scope: action :Type: word :Default: none (unset) :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Names a ruleset to handle records requeued by `retryfailures`. If unset, retries start at the default ruleset. Action usage ------------ .. _param-omelasticsearch-action-retryruleset: .. _omelasticsearch.parameter.action.retryruleset: .. code-block:: rsyslog action(type="omelasticsearch" retryruleset="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omjournal-template.rst0000644000000000000000000000013215132733117025261 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.784458452 30 ctime=1787067793.324705115 rsyslog-8.2608.0/doc/source/reference/parameters/omjournal-template.rst0000666000175000017500000000324315132733117024731 0ustar00rgerrger.. _param-omjournal-template: .. _omjournal.parameter.input.template: template ======== .. index:: single: omjournal; template single: template .. summary-start Selects the template that formats journal entries before they are written. .. summary-end This parameter applies to :doc:`../../configuration/modules/omjournal`. :Name: template :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.17.0 Description ----------- Template to use when submitting messages. By default, rsyslog will use the incoming ``$msg`` property as the ``MESSAGE`` field of the journald entry. It also includes ``SYSLOG_IDENTIFIER`` (from the tag), ``SYSLOG_FACILITY``, and ``PRIORITY`` (derived from facility and severity). You can override the default formatting of the message, and include custom fields with a template. .. warning:: Complex JSON objects or arrays from ``json`` or ``subtree`` templates are **not** supported. The omjournal action currently converts each field via ``json_object_get_string()``, which returns ``NULL`` for nested JSON structures and leads to a crash inside ``build_iovec()``. Emit only values that convert cleanly to strings (plain text, numbers, booleans) until this limitation is fixed. See `rsyslog issue #881 `_ for background on the crash. Journald requires that the template's output contains a field named ``MESSAGE``. Input usage ----------- .. _param-omjournal-input-template: .. _omjournal.parameter.input.template-usage: .. code-block:: shell action(type="omjournal" template="journal") See also -------- See also :doc:`../../configuration/modules/omjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-tls-keyfile.rst0000644000000000000000000000013115145046112026504 xustar0030 mtime=1771326538.940012672 29 atime=1787067673.52947234 30 ctime=1787067792.303686089 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-tls-keyfile.rst0000664000175000017500000000157715145046112026163 0ustar00rgerrger.. _param-impstats-push-tls-keyfile: .. _impstats.parameter.module.push-tls-keyfile: push.tls.keyfile ================ .. index:: single: impstats; push.tls.keyfile single: push.tls.keyfile .. summary-start Specifies the client private key file used for mutual TLS. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.tls.keyfile :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 8.2602.0 Description ----------- Use this together with ``push.tls.certfile`` when the Remote Write endpoint requires client certificate authentication. Module usage ------------ .. _impstats.parameter.module.push-tls-keyfile-usage: .. code-block:: rsyslog module(load="impstats" push.tls.keyfile="/etc/rsyslog/certs/impstats-client.key") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-ratelimit-interval.rst0000644000000000000000000000013015132733117026565 xustar0029 mtime=1768666703.91762039 29 atime=1787067672.96246177 30 ctime=1787067793.280704295 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-ratelimit-interval.rst0000666000175000017500000000242115132733117026234 0ustar00rgerrger.. _param-omhttp-ratelimit-interval: .. _omhttp.parameter.input.ratelimit-interval: ratelimit.interval ================== .. index:: single: omhttp; ratelimit.interval single: ratelimit.interval .. summary-start Controls the duration, in seconds, of the rate-limiting window for the retry ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: ratelimit.interval :Scope: input :Type: integer :Default: input=600 :Required?: no :Introduced: Not specified Description ----------- This parameter sets the rate limiting behavior for the :ref:`param-omhttp-retry-ruleset`. It specifies the interval in seconds onto which rate-limiting is to be applied. If more than :ref:`param-omhttp-ratelimit-burst` messages are read during that interval, further messages up to the end of the interval are discarded. The number of messages discarded is emitted at the end of the interval (if there were any discards). Setting this to value zero turns off ratelimiting. Input usage ----------- .. _omhttp.parameter.input.ratelimit-interval-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" retry="on" rateLimitInterval="300" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-defaulttz.rst0000644000000000000000000000013215132733117024736 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.782477057 30 ctime=1787067792.321686424 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-defaulttz.rst0000666000175000017500000000140415132733117024403 0ustar00rgerrger.. _param-imptcp-defaulttz: .. _imptcp.parameter.input.defaulttz: Defaulttz ========= .. index:: single: imptcp; Defaulttz single: Defaulttz .. summary-start Sets a default time zone string. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Defaulttz :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set default time zone. At most seven chars are set, as we would otherwise overrun our buffer. Input usage ----------- .. _param-imptcp-input-defaulttz: .. _imptcp.parameter.input.defaulttz-usage: .. code-block:: rsyslog input(type="imptcp" defaulttz="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-output.rst0000644000000000000000000000013215132733117024303 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.989462274 30 ctime=1787067793.468707799 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-output.rst0000666000175000017500000000433315132733117023754 0ustar00rgerrger.. _param-omprog-output: .. _omprog.parameter.action.output: output ====== .. index:: single: omprog; output single: output .. summary-start Appends the program's output streams to the specified file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: output :Scope: action :Type: string :Default: action=none :Required?: no :Introduced: v8.1.6 Description ----------- Full path of a file where the output of the external program will be saved. If the file already exists, the output is appended to it. If the file does not exist, it is created with the permissions specified by :ref:`param-omprog-filecreatemode`. If :ref:`param-omprog-confirmmessages` is set to "off" (the default), both the stdout and stderr of the child process are written to the specified file. If :ref:`param-omprog-confirmmessages` is set to "on", only the stderr of the child is written to the specified file (since stdout is used for confirming the messages). Rsyslog will reopen the file whenever it receives a HUP signal. This allows the file to be externally rotated (using a tool like *logrotate*): after each rotation of the file, make sure a HUP signal is sent to rsyslogd. If the omprog action is configured to use multiple worker threads (:doc:`queue.workerThreads <../../rainerscript/queue_parameters>` is set to a value greater than 1), the lines written by the various program instances will not appear intermingled in the output file, as long as the lines do not exceed a certain length and the program writes them to stdout/stderr in line-buffered mode. For details, refer to `Interface between rsyslog and external output plugins `_. If this parameter is not specified, the output of the program will be redirected to ``/dev/null``. .. note:: Before version v8.38.0, this parameter was intended for debugging purposes only. Since v8.38.0, the parameter can be used for production. Action usage ------------ .. _param-omprog-action-output: .. _omprog.parameter.action.output-usage: .. code-block:: rsyslog action(type="omprog" output="/var/log/prog.log") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-snmpv1dynsource.rst0000644000000000000000000000013215132733117026131 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.785439828 30 ctime=1787067793.550709327 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-snmpv1dynsource.rst0000666000175000017500000000235715132733117025606 0ustar00rgerrger.. _param-omsnmp-snmpv1dynsource: .. _omsnmp.parameter.module.snmpv1dynsource: Snmpv1DynSource =============== .. index:: single: omsnmp; Snmpv1DynSource single: Snmpv1DynSource .. summary-start Overrides the SNMPv1 trap source address via template. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Snmpv1DynSource :Scope: module :Type: string :Default: module="" :Required?: no :Introduced: 8.2001 Description ----------- .. versionadded:: 8.2001 If set, the source field of the SNMP trap can be overwritten with a template. valid IPv4 Address. Otherwise setting the source will fail. Below is a sample template called "dynsource" which you can use to set the source to a custom property: .. code-block:: none set $!custom_host = $fromhost; template(name="dynsource" type="list") { property(name="$!custom_host") } This configuration parameter is used for **SNMPv1** only. It has no effect if **SNMPv2** is used. Module usage ------------ .. _param-omsnmp-module-snmpv1dynsource: .. _omsnmp.parameter.module.snmpv1dynsource-usage: .. code-block:: rsyslog action(type="omsnmp" snmpv1DynSource="dynsource") See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-filecreatemode.rst0000644000000000000000000000013215132411300025646 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.327449932 30 ctime=1787067793.172702282 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-filecreatemode.rst0000666000175000017500000000342615132411300025321 0ustar00rgerrger.. _param-omfile-filecreatemode: .. _omfile.parameter.module.filecreatemode: fileCreateMode ============== .. index:: single: omfile; fileCreateMode single: fileCreateMode .. summary-start Specifies the file system permissions for newly created log files. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: fileCreateMode :Scope: module, action :Type: string (octal) :Default: module=0644; action=inherits module :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the file system permissions for log files newly created by ``omfile``. The value must be a 4-digit octal number (e.g., ``0640``). When set at the module level, it defines the default mode for all ``omfile`` actions. When set at the action level, it overrides the module default for that specific action. Please note that the actual permissions depend on rsyslogd's process umask. If in doubt, use ``$umask 0000`` at the beginning of the configuration file to remove any restrictions. Module usage ------------ .. _param-omfile-module-filecreatemode: .. _omfile.parameter.module.filecreatemode-usage: .. code-block:: rsyslog module(load="builtin:omfile" fileCreateMode="0644") Action usage ------------ .. _param-omfile-action-filecreatemode: .. _omfile.parameter.action.filecreatemode: .. code-block:: rsyslog action(type="omfile" fileCreateMode="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.filecreatemode: - $FileCreateMode — maps to fileCreateMode (status: legacy) .. index:: single: omfile; $FileCreateMode single: $FileCreateMode See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-flush_timeout_ms.rst0000644000000000000000000000013215171370365027171 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.510471986 30 ctime=1787067792.952698183 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-flush_timeout_ms.rst0000664000175000017500000000233315171370365026636 0ustar00rgerrger.. _param-omazuredce-flush_timeout_ms: .. _omazuredce.parameter.action.flush_timeout_ms: .. meta:: :description: Reference for the omazuredce flush_timeout_ms parameter. :keywords: rsyslog, omazuredce, flush_timeout_ms, azure, batching flush_timeout_ms ================ .. index:: single: omazuredce; flush_timeout_ms single: flush_timeout_ms .. summary-start Controls how long a partially filled batch may stay idle before it is flushed. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: flush_timeout_ms :Scope: action :Type: non-negative integer :Default: 1000 :Required?: no :Introduced: Not specified Description ----------- When ``flush_timeout_ms`` is greater than ``0``, a worker thread checks for idle batches and flushes them after the configured number of milliseconds. When it is set to ``0``, the timer-based flush is disabled and batches are sent only when they fill up or when the current action queue transaction ends. Action usage ------------ .. _omazuredce.parameter.action.flush_timeout_ms-usage: .. code-block:: rsyslog action(type="omazuredce" flush_timeout_ms="2000" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-createpath.rst0000644000000000000000000000013215216464435025431 xustar0030 mtime=1782212893.986265537 30 atime=1787067673.966480487 30 ctime=1787067792.604691698 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-createpath.rst0000664000175000017500000000403115216464435025073 0ustar00rgerrger.. _param-imuxsock-createpath: .. _imuxsock.parameter.input.createpath: CreatePath ========== .. index:: single: imuxsock; CreatePath single: CreatePath .. summary-start Creates missing directories for the specified socket path. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: CreatePath :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 4.7.0 Description ----------- Create directories in the socket path if they do not already exist. They are created with 0755 permissions with the owner being the process under which rsyslogd runs. The default is not to create directories. Keep in mind, though, that rsyslogd always creates the socket itself if it does not exist (just not the directories by default). This option is primarily considered useful for defining additional sockets that reside on non-permanent file systems. As rsyslogd probably starts up before the daemons that create these sockets, it is a vehicle to enable rsyslogd to listen to those sockets even though their directories do not yet exist. ``CreatePath="on"`` means rsyslog manages creation of the socket path. Do not combine it with ``Unlink="off"``, because that tells rsyslog not to replace or remove the socket path it created. This contradictory configuration is rejected. Use the default ``Unlink="on"`` when rsyslog should manage the socket lifecycle. .. versionadded:: 4.7.0 Input usage ----------- .. _param-imuxsock-input-createpath: .. _imuxsock.parameter.input.createpath-usage: .. code-block:: rsyslog input(type="imuxsock" createPath="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketcreatepath: - $InputUnixListenSocketCreatePath — maps to CreatePath (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketCreatePath single: $InputUnixListenSocketCreatePath See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-socketpath.rst0000644000000000000000000000013115132733117025422 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.109445868 29 ctime=1787067792.75669453 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-socketpath.rst0000666000175000017500000000144515132733117025075 0ustar00rgerrger.. _param-mmdarwin-socketpath: .. _mmdarwin.parameter.input.socketpath: socketpath ========== .. index:: single: mmdarwin; socketpath single: socketpath .. summary-start Specifies the Darwin filter socket path that mmdarwin connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: socketpath :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 8.x, possibly earlier Description ----------- The Darwin filter socket path to use. Input usage ----------- .. _param-mmdarwin-input-socketpath-usage: .. _mmdarwin.parameter.input.socketpath-usage: .. code-block:: rsyslog action(type="mmdarwin" socketPath="/path/to/reputation_1.sock") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfwd-tcp-user-timeout.rst0000644000000000000000000000013115241075234026001 xustar0030 mtime=1787067036.581577845 29 atime=1787067036.67957968 30 ctime=1787067793.127701444 rsyslog-8.2608.0/doc/source/reference/parameters/omfwd-tcp-user-timeout.rst0000664000175000017500000000150415241075234025446 0ustar00rgerrger.. index:: ! omfwd; tcp_user_timeout .. _param-omfwd-tcp-user-timeout: tcp_user_timeout ================ .. summary-start **Default:** 0 **Type:** integer **Description:** Sets the TCP_USER_TIMEOUT socket option, in milliseconds, for TCP-based omfwd connections. A value of ``0`` leaves the operating system default unchanged. This option is independent of TCP keepalive and may not be available on all platforms. .. versionadded:: 8.2608.0 .. summary-end Examples -------- RainerScript: .. code-block:: rsyslog action(type="omfwd" target="central.example.net" port="6514" protocol="tcp" tcp_user_timeout="10000") YAML: .. code-block:: yaml actions: - type: omfwd target: central.example.net port: 6514 protocol: tcp tcp_user_timeout: 10000 rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-committransactionmark.rst0000644000000000000000000000013015132733117027352 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.770458191 28 ctime=1787067793.4527075 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-committransactionmark.rst0000666000175000017500000000210015132733117027013 0ustar00rgerrger.. _param-omprog-committransactionmark: .. _omprog.parameter.action.committransactionmark: commitTransactionMark ====================== .. index:: single: omprog; commitTransactionMark single: commitTransactionMark .. summary-start Defines the marker sent to denote the end of a transaction. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: commitTransactionMark :Scope: action :Type: string :Default: action="COMMIT TRANSACTION" :Required?: no :Introduced: 8.31.0 Description ----------- Allows specifying the mark message that rsyslog will send to the external program to indicate the end of a transaction (batch). This parameter is ignored if :ref:`param-omprog-usetransactions` is disabled. Action usage ------------ .. _param-omprog-action-committransactionmark: .. _omprog.parameter.action.committransactionmark-usage: .. code-block:: rsyslog action(type="omprog" useTransactions="on" commitTransactionMark="COMMIT TRANSACTION") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-ratelimit-name.rst0000644000000000000000000000013215171370365026355 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.853459738 30 ctime=1787067792.202684206 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-ratelimit-name.rst0000664000175000017500000000124315171370365026021 0ustar00rgerrger.. index:: ! imjournal; RateLimit.Name .. _param-imjournal-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, inline rate limit parameters cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-send_partial.rst0000644000000000000000000000013215145046112025717 xustar0030 mtime=1771326538.944012737 30 atime=1787067672.134446334 30 ctime=1787067792.753694474 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-send_partial.rst0000664000175000017500000000301115145046112025356 0ustar00rgerrger.. _param-mmdarwin-send_partial: .. _mmdarwin.parameter.input.send_partial: send_partial ============ .. index:: single: mmdarwin; send_partial single: send_partial .. summary-start Controls whether mmdarwin calls Darwin when some fields are missing from the message. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: send_partial :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Controls whether to send data to Darwin if not all ``"fields"`` could be found in the message. Darwin filters typically require a strict set of parameters and may not process incomplete data, so leaving this setting at ``"off"`` is recommended unless you have verified the filter accepts missing fields. For example, for the following log line: .. code-block:: json { "from": "192.168.1.42", "date": "2012-12-21 00:00:00", "status": "200", "data": { "status": true, "message": "Request processed correctly" } } and the ``"fields"`` array: .. code-block:: none ["!from", "!data!status", "!this!field!is!not!in!message"] the third field won't be found, so the call to Darwin will be dropped. Input usage ----------- .. _param-mmdarwin-input-send_partial-usage: .. _mmdarwin.parameter.input.send_partial-usage: .. code-block:: rsyslog action(type="mmdarwin" sendPartial="on") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-conn-timeout.rst0000644000000000000000000000013215145046112025353 xustar0030 mtime=1771326538.950012835 30 atime=1787067673.113464585 30 ctime=1787067793.479708003 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-conn-timeout.rst0000664000175000017500000000143715145046112025024 0ustar00rgerrger.. _param-omrelp-conn-timeout: .. _omrelp.parameter.input.conn-timeout: Conn.Timeout ============ .. index:: single: omrelp; Conn.Timeout single: Conn.Timeout .. summary-start Controls how long the socket connection attempt is allowed to take. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: Conn.Timeout :Scope: input :Type: integer :Default: input=10 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Timeout for the socket connection. Input usage ----------- .. _param-omrelp-input-conn-timeout: .. _omrelp.parameter.input.conn-timeout-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" connTimeout="10") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-cacert.rst0000644000000000000000000000013115132411300026631 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.132446297 29 ctime=1787067793.10170096 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-cacert.rst0000666000175000017500000000163115132411300026301 0ustar00rgerrger.. _param-omelasticsearch-tls-cacert: .. _omelasticsearch.parameter.module.tls-cacert: .. _omelasticsearch.parameter.module.tls.cacert: tls.cacert ========== .. index:: single: omelasticsearch; tls.cacert single: tls.cacert .. summary-start CA certificate file used to verify the Elasticsearch server. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.cacert :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Path to a PEM file containing the CA certificate that issued the server certificate. Action usage ------------ .. _param-omelasticsearch-action-tls-cacert: .. _omelasticsearch.parameter.action.tls-cacert: .. code-block:: rsyslog action(type="omelasticsearch" tls.cacert="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-maxframesize.rst0000644000000000000000000000013215132733117025247 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.060482239 30 ctime=1787067792.489689555 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-maxframesize.rst0000666000175000017500000000272015132733117024716 0ustar00rgerrger.. _param-imtcp-maxframesize: .. _imtcp.parameter.module.maxframesize: .. _imtcp.parameter.input.maxframesize: MaxFrameSize ============ .. index:: single: imtcp; MaxFrameSize single: MaxFrameSize .. summary-start Sets the maximum frame size in octet-counted mode before switching to octet stuffing. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: MaxFrameSize :Scope: module, input :Type: integer :Default: module=200000, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- When in octet counted mode, the frame size is given at the beginning of the message. With this parameter the max size this frame can have is specified and when the frame gets to large the mode is switched to octet stuffing. The max value this parameter can have was specified because otherwise the integer could become negative and this would result in a Segmentation Fault. (Max Value = 200000000) The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-maxframesize: .. _imtcp.parameter.module.maxframesize-usage: .. code-block:: rsyslog module(load="imtcp" maxFrameSize="...") Input usage ----------- .. _param-imtcp-input-maxframesize: .. _imtcp.parameter.input.maxframesize-usage: .. code-block:: rsyslog input(type="imtcp" port="514" maxFrameSize="...") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-limituniquemaxretries.rst0000644000000000000000000000013215145046112030252 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.832440704 30 ctime=1787067792.711693692 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-limituniquemaxretries.rst0000664000175000017500000000221515145046112027716 0ustar00rgerrger.. _param-mmanon-ipv4-limituniquemaxretries: .. _mmanon.parameter.input.ipv4-limituniquemaxretries: ipv4.limitUniqueMaxRetries ========================== .. index:: single: mmanon; ipv4.limitUniqueMaxRetries single: ipv4.limitUniqueMaxRetries .. summary-start Controls whether random-consistent-unique anonymization limits retries for IPv4. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.limitUniqueMaxRetries :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2410.0 Description ----------- When enabled, ``random-consistent-unique`` mode will stop retrying after :ref:`ipv4.uniqueRetryCount ` attempts. After the retry limit is reached, the behavior is controlled by :ref:`ipv4.maxRetryHandling `. Input usage ----------- .. _mmanon.parameter.input.ipv4-limituniquemaxretries-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="random-consistent-unique" ipv4.limitUniqueMaxRetries="on") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-target.rst0000644000000000000000000000013215145046112025115 xustar0030 mtime=1771326538.959012982 30 atime=1787067671.935442624 30 ctime=1787067793.579709867 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-target.rst0000664000175000017500000000210415145046112024556 0ustar00rgerrger.. _param-omudpspoof-target: .. _omudpspoof.parameter.action.target: target ====== .. index:: single: omudpspoof; target single: target .. summary-start Sets the destination host to which omudpspoof sends messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: target :Scope: action :Type: word :Default: none :Required?: yes :Introduced: 5.1.3 Description ----------- Host that the messages shall be sent to. Action usage ------------ .. _param-omudpspoof-action-target: .. _omudpspoof.parameter.action.target-usage: .. code-block:: rsyslog action(type="omudpspoof" target="192.0.2.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspooftargethost: - $ActionOMUDPSpoofTargetHost — maps to target (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofTargetHost single: $ActionOMUDPSpoofTargetHost See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-body-enable.rst0000644000000000000000000000013115132733117025076 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.743457687 29 ctime=1787067793.38670627 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-body-enable.rst0000666000175000017500000000270115132733117024545 0ustar00rgerrger.. _param-ommail-body-enable: .. _ommail.parameter.input.body-enable: bodyEnable ========== .. index:: single: ommail; bodyEnable single: bodyEnable .. summary-start Toggles inclusion of the mail body in messages sent by ommail. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: bodyEnable :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 8.5.0 Description ----------- Setting this to "off" permits the actual message body to be excluded. This may be useful for pager-like devices or cell phone SMS messages. The default is "on", which is appropriate for almost all cases. This option should only be disabled for specific use cases, as it deviates from standard email behavior. Input usage ------------ .. _ommail.parameter.input.body-enable-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" bodyEnable="off" ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailenablebody: - $ActionMailEnableBody — maps to bodyEnable (status: legacy) .. index:: single: ommail; $ActionMailEnableBody single: $ActionMailEnableBody See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-flowcontrol.rst0000644000000000000000000000013215132733117025124 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.960480375 30 ctime=1787067792.472689238 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-flowcontrol.rst0000666000175000017500000000356415132733117024602 0ustar00rgerrger.. _param-imtcp-flowcontrol: .. _imtcp.parameter.module.flowcontrol: .. _imtcp.parameter.input.flowcontrol: FlowControl =========== .. index:: single: imtcp; FlowControl single: FlowControl .. summary-start Applies light flow control to throttle senders when queues near full. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: FlowControl :Scope: module, input :Type: boolean :Default: module=on, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This setting specifies whether some message flow control shall be exercised on the related TCP input. If set to on, messages are handled as "light delayable", which means the sender is throttled a bit when the queue becomes near-full. This is done in order to preserve some queue space for inputs that can not throttle (like UDP), but it may have some undesired effect in some configurations. Still, we consider this as a useful setting and thus it is the default. To turn the handling off, simply configure that explicitly. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-flowcontrol: .. _imtcp.parameter.module.flowcontrol-usage: .. code-block:: rsyslog module(load="imtcp" flowControl="off") Input usage ----------- .. _param-imtcp-input-flowcontrol: .. _imtcp.parameter.input.flowcontrol-usage: .. code-block:: rsyslog input(type="imtcp" port="514" flowControl="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpflowcontrol: - $InputTCPFlowControl — maps to FlowControl (status: legacy) .. index:: single: imtcp; $InputTCPFlowControl single: $InputTCPFlowControl See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-prioritizesan.rst0000644000000000000000000000013215171370365030170 xustar0030 mtime=1776677109.117908084 30 atime=1787067674.038481829 30 ctime=1787067792.545690598 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-prioritizesan.rst0000664000175000017500000000334215171370365027636 0ustar00rgerrger.. _param-imtcp-streamdriver-prioritizesan: .. _imtcp.parameter.module.streamdriver-prioritizesan: .. _imtcp.parameter.input.streamdriver-prioritizesan: StreamDriver.PrioritizeSAN ========================== .. index:: single: imtcp; StreamDriver.PrioritizeSAN single: StreamDriver.PrioritizeSAN .. summary-start Uses stricter SAN/CN matching for certificate validation. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.PrioritizeSAN :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Whether to use stricter SAN/CN matching. (driver-specific) When set to "on", if any SAN is found in the peer certificate, only the SAN is used for name validation and the CN is ignored (per RFC 6125). If the certificate contains *no* SAN entries at all, validation falls back to checking the CN — certificates are not rejected simply for lacking SANs. This setting only affects name-checking auth modes (``x509/name``). It has no effect when using ``x509/certvalid``, which does not perform name matching. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-prioritizesan: .. _imtcp.parameter.module.streamdriver-prioritizesan-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.prioritizeSAN="on") Input usage ----------- .. _param-imtcp-input-streamdriver-prioritizesan: .. _imtcp.parameter.input.streamdriver-prioritizesan-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.prioritizeSAN="on") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfwd-compression-driver.rst0000644000000000000000000000013215216464435026415 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.669456308 30 ctime=1787067793.123701369 rsyslog-8.2608.0/doc/source/reference/parameters/omfwd-compression-driver.rst0000664000175000017500000000337715216464435026073 0ustar00rgerrger.. _param-omfwd-compression-driver: .. _omfwd.parameter.action.compression-driver: .. meta:: :description: Reference for the omfwd compression.driver action parameter. :keywords: rsyslog, omfwd, compression.driver, stream compression, zlib, zstd compression.driver ================== .. index:: single: omfwd; compression.driver single: compression.driver .. summary-start Selects the compression driver used by ``omfwd`` stream compression. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfwd`. :Name: compression.driver :Scope: action :Type: word :Default: action=zlib :Required?: no :Introduced: 8.2606.0 Description ----------- ``compression.driver`` selects the compression library used when ``compression.mode="stream:always"`` is configured. It does not enable compression by itself; set ``compression.mode`` and a non-zero ``zipLevel`` as needed for the forwarding action. Accepted values are: - ``zlib``: default stream compression driver. - ``zstd``: zstd stream compression driver. This requires rsyslog to be built with libzstd support, and the receiver must also use ``compression.driver="zstd"``. The receiver must use the same driver. For ``imtcp``, configure ``compression.mode="stream:always"`` and the matching ``compression.driver`` on the input. Action usage ------------ .. _param-omfwd-action-compression-driver: .. _omfwd.parameter.action.compression-driver-usage: .. code-block:: rsyslog action( type="omfwd" target="logs.example.com" port="514" protocol="tcp" compression.mode="stream:always" compression.driver="zstd" zipLevel="3" ) See also -------- See also :doc:`../../configuration/modules/omfwd` and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-parsetrusted.rst0000644000000000000000000000013115132733117027522 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.321487105 29 ctime=1787067792.64669248 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-parsetrusted.rst0000666000175000017500000000276515132733117027203 0ustar00rgerrger.. _param-imuxsock-syssock-parsetrusted: .. _imuxsock.parameter.module.syssock-parsetrusted: SysSock.ParseTrusted ==================== .. index:: single: imuxsock; SysSock.ParseTrusted single: SysSock.ParseTrusted .. summary-start Turns trusted properties into JSON fields when annotation is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.ParseTrusted :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 6.5.0 Description ----------- If ``SysSock.Annotation`` is turned on, create JSON/lumberjack properties out of the trusted properties (which can be accessed via |FmtAdvancedName| JSON Variables, e.g. ``$!pid``) instead of adding them to the message. .. versionadded:: 6.5.0 As ``$SystemLogParseTrusted``. .. versionchanged:: 7.2.7 Support for the advanced format was added. Module usage ------------ .. _param-imuxsock-module-syssock-parsetrusted: .. _imuxsock.parameter.module.syssock-parsetrusted-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.parseTrusted="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogparsetrusted: - $SystemLogParseTrusted — maps to SysSock.ParseTrusted (status: legacy) .. index:: single: imuxsock; $SystemLogParseTrusted single: $SystemLogParseTrusted See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-veryrobustzip.rst0000644000000000000000000000013215132411300025645 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.518453493 30 ctime=1787067793.206702916 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-veryrobustzip.rst0000666000175000017500000000367115132411300025322 0ustar00rgerrger.. _param-omfile-veryrobustzip: .. _omfile.parameter.module.veryrobustzip: veryRobustZip ============= .. index:: single: omfile; veryRobustZip single: veryRobustZip .. summary-start If *zipLevel* is greater than 0, then this setting controls if extra headers are written to make the resulting file extra hardened against malfunction. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: veryRobustZip :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 7.3.0 Description ----------- If *zipLevel* is greater than 0, then this setting controls if extra headers are written to make the resulting file extra hardened against malfunction. If set to off, data appended to previously unclean closed files may not be accessible without extra tools (like `gztool `_ with: ``gztool -p``). Note that this risk is usually expected to be bearable, and thus "off" is the default mode. The extra headers considerably degrade compression, files with this option set to "on" may be four to five times as large as files processed in "off" mode. **In order to avoid this degradation in compression** both *flushOnTXEnd* and *asyncWriting* parameters must be set to "off" and also *ioBufferSize* must be raised from default "4k" value to at least "32k". This way a reasonable compression factor is maintained, similar to a non-blocked gzip file: .. code-block:: none veryRobustZip="on" ioBufferSize="64k" flushOnTXEnd="off" asyncWriting="off" Do not forget to add your desired *zipLevel* to this configuration line. Action usage ------------ .. _param-omfile-action-veryrobustzip: .. _omfile.parameter.action.veryrobustzip: .. code-block:: rsyslog action(type="omfile" veryRobustZip="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-sslpartialchain.rst0000644000000000000000000000013215132733117027322 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.717457203 30 ctime=1787067792.853696338 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-sslpartialchain.rst0000666000175000017500000000332315132733117026771 0ustar00rgerrger.. _param-mmkubernetes-sslpartialchain: .. _mmkubernetes.parameter.action.sslpartialchain: sslpartialchain =============== .. index:: single: mmkubernetes; sslpartialchain single: sslpartialchain .. summary-start Enables OpenSSL ``X509_V_FLAG_PARTIAL_CHAIN`` verification. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: sslpartialchain :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This option is only available if rsyslog was built with support for OpenSSL and only if the `X509_V_FLAG_PARTIAL_CHAIN` flag is available. If you attempt to set this parameter on other platforms, you will get an `INFO` level log message. This was done so that you could use the same configuration on different platforms. If `"on"`, this will set the OpenSSL certificate store flag `X509_V_FLAG_PARTIAL_CHAIN`. This will allow you to verify the Kubernetes API server cert with only an intermediate CA cert in your local trust store, rather than having to have the entire intermediate CA + root CA chain in your local trust store. See also `man s_client` - the `-partial_chain` flag. If you get errors like this, you probably need to set `sslpartialchain="on"`: .. code-block:: none rsyslogd: mmkubernetes: failed to connect to [https://...url...] - 60:Peer certificate cannot be authenticated with given CA certificates Action usage ------------ .. _param-mmkubernetes-action-sslpartialchain: .. _mmkubernetes.parameter.action.sslpartialchain-usage: .. code-block:: rsyslog action(type="mmkubernetes" sslPartialChain="on") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-dynatopic-cachesize.rst0000644000000000000000000000013115132411300026761 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.926461099 29 ctime=1787067793.33570532 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-dynatopic-cachesize.rst0000666000175000017500000000155415132411300026435 0ustar00rgerrger.. _param-omkafka-dynatopic-cachesize: .. _omkafka.parameter.module.dynatopic-cachesize: DynaTopic.Cachesize =================== .. index:: single: omkafka; DynaTopic.Cachesize single: DynaTopic.Cachesize .. summary-start Number of dynamic topics kept in cache. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: DynaTopic.Cachesize :Scope: action :Type: integer :Default: action=50 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, defines the number of topics that will be kept in the dynatopic cache. Action usage ------------ .. _param-omkafka-action-dynatopic-cachesize: .. _omkafka.parameter.action.dynatopic-cachesize: .. code-block:: rsyslog action(type="omkafka" DynaTopic.Cachesize="100") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-maxlinesatonce.rst0000644000000000000000000000013215132733117025717 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.425451759 30 ctime=1787067792.079681914 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-maxlinesatonce.rst0000666000175000017500000000326315132733117025371 0ustar00rgerrger.. _param-imfile-maxlinesatonce: .. _imfile.parameter.input.maxlinesatonce: .. _imfile.parameter.maxlinesatonce: MaxLinesAtOnce ============== .. index:: single: imfile; MaxLinesAtOnce single: MaxLinesAtOnce .. summary-start Legacy polling-mode limit on how many lines are read before switching files. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: MaxLinesAtOnce :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This legacy setting is only supported in polling mode. In inotify mode it is fixed at ``0`` and attempts to set a different value are ignored but generate an error message. Future versions may remove this parameter. In polling mode, a value of ``0`` processes each file completely before switching to the next. Any other value limits processing to the specified number of lines before moving to the next file, providing a form of load multiplexing. For polling mode, the default is ``10240``. Input usage ----------- .. _param-imfile-input-maxlinesatonce: .. _imfile.parameter.input.maxlinesatonce-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" MaxLinesAtOnce="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilemaxlinesatonce: - ``$InputFileMaxLinesAtOnce`` — maps to MaxLinesAtOnce (status: legacy) .. index:: single: imfile; $InputFileMaxLinesAtOnce single: $InputFileMaxLinesAtOnce See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-server.rst0000644000000000000000000000013215145046112026110 xustar0030 mtime=1771326538.944012737 30 atime=1787067671.971443296 30 ctime=1787067793.088700717 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-server.rst0000664000175000017500000000207215145046112025555 0ustar00rgerrger.. _param-omelasticsearch-server: .. _omelasticsearch.parameter.module.server: Server ====== .. index:: single: omelasticsearch; Server single: Server .. summary-start List of Elasticsearch servers to send events to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: Server :Scope: action :Type: array[string] :Default: action=localhost :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Defines one or more Elasticsearch servers. Each entry may be a bare hostname or an ``http``/``https`` URL without a trailing slash or path component. If no scheme is given, one is selected based on `usehttps`, otherwise the provided scheme is honored. Missing ports use `serverport`. Requests are load-balanced in round-robin order. Action usage ------------ .. _param-omelasticsearch-action-server: .. _omelasticsearch.parameter.action.server: .. code-block:: rsyslog action(type="omelasticsearch" Server="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-skippipelineifempty.rst0000644000000000000000000000013115132411300030662 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.038444545 29 ctime=1787067793.09370081 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-skippipelineifempty.rst0000666000175000017500000000206415132411300030333 0ustar00rgerrger.. _param-omelasticsearch-skippipelineifempty: .. _omelasticsearch.parameter.module.skippipelineifempty: skipPipelineIfEmpty =================== .. index:: single: omelasticsearch; skipPipelineIfEmpty single: skipPipelineIfEmpty .. summary-start Omit the pipeline parameter when `pipelineName` expands to an empty string. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: skipPipelineIfEmpty :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled and the pipeline name resolves to an empty value, the parameter is not sent to Elasticsearch to avoid errors. Action usage ------------ .. _param-omelasticsearch-action-skippipelineifempty: .. _omelasticsearch.parameter.action.skippipelineifempty: .. code-block:: rsyslog action(type="omelasticsearch" skipPipelineIfEmpty="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-user.rst0000644000000000000000000000013215145046112024074 xustar0030 mtime=1771326538.950012835 30 atime=1787067672.680456513 30 ctime=1787067793.443707333 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-user.rst0000664000175000017500000000137215145046112023543 0ustar00rgerrger.. _param-ompgsql-user: .. _ompgsql.parameter.input.user: User ==== .. index:: single: ompgsql; User single: User .. summary-start Sets the username used to authenticate to the PostgreSQL server. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: User :Scope: input :Type: word :Default: postgres :Required?: no :Introduced: 8.32.0 Description ----------- The username to connect to the PostgreSQL server with. The name ``UID`` is also accepted. Input usage ----------- .. _ompgsql.parameter.input.user-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" user="rsyslog" db="syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-kafkaheader.rst0000644000000000000000000000013215132733117025277 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.017462795 30 ctime=1787067793.344705488 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-kafkaheader.rst0000666000175000017500000000157115132733117024751 0ustar00rgerrger.. _param-omkafka-kafkaheader: .. _omkafka.parameter.module.kafkaheader: KafkaHeader =========== .. index:: single: omkafka; KafkaHeader single: KafkaHeader .. summary-start Defines Kafka message headers to attach to each produced message. Each entry is a `key=value` pair. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: KafkaHeader :Scope: action :Type: array[string] :Default: action=none :Required?: no :Introduced: 8.2405.0 Description ----------- Specifies static headers that are added to every message sent to Kafka. The parameter accepts an array of `key=value` strings. Action usage ------------ .. code-block:: rsyslog action(type="omkafka" topic="mytopic" broker="localhost:9092" kafkaHeader=["foo=bar","answer=42"]) See also -------- * :doc:`../../configuration/modules/omkafka` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-batch-maxseries.rst0000644000000000000000000000013115145046112027333 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.516472098 29 ctime=1787067792.28068566 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-batch-maxseries.rst0000664000175000017500000000160715145046112027004 0ustar00rgerrger.. _param-impstats-push-batch-maxseries: .. _impstats.parameter.module.push-batch-maxseries: push.batch.maxSeries ==================== .. index:: single: impstats; push.batch.maxSeries single: push.batch.maxSeries .. summary-start Limits the number of time series per Remote Write request. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.batch.maxSeries :Scope: module :Type: integer (count) :Default: module=0 :Required?: no :Introduced: 8.2602.0 Description ----------- When set, impstats splits the payload into multiple requests, each containing at most the specified number of series. Module usage ------------ .. _impstats.parameter.module.push-batch-maxseries-usage: .. code-block:: rsyslog module(load="impstats" push.batch.maxSeries="1000") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-dynsearchtype.rst0000644000000000000000000000013215132411300027453 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.020444209 30 ctime=1787067793.045699916 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-dynsearchtype.rst0000666000175000017500000000165315132411300027126 0ustar00rgerrger.. _param-omelasticsearch-dynsearchtype: .. _omelasticsearch.parameter.module.dynsearchtype: dynSearchType ============= .. index:: single: omelasticsearch; dynSearchType single: dynSearchType .. summary-start Treat `searchType` as a template name. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: dynSearchType :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled, `searchType` references a template whose expansion becomes the type. Action usage ------------ .. _param-omelasticsearch-action-dynsearchtype: .. _omelasticsearch.parameter.action.dynsearchtype: .. code-block:: rsyslog action(type="omelasticsearch" dynSearchType="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-cacert.rst0000644000000000000000000000013215145046112024773 xustar0030 mtime=1771326538.954012901 30 atime=1787067672.707457016 30 ctime=1787067793.506708507 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-cacert.rst0000664000175000017500000000246315145046112024444 0ustar00rgerrger.. _param-omrelp-tls-cacert: .. _omrelp.parameter.input.tls-cacert: TLS.CaCert ========== .. index:: single: omrelp; TLS.CaCert single: TLS.CaCert .. summary-start Specifies the CA certificate used to verify peer certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.CaCert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The CA certificate that can verify the machine certs. .. versionadded:: 8.2008.0 With librelp 1.7.0, you can use chained certificates. If using "openssl" as tls.tlslib, we recommend at least OpenSSL Version 1.1 or higher. Chained certificates will also work with OpenSSL Version 1.0.2, but they will be loaded into the main OpenSSL context object making them available to all librelp instances (omrelp/imrelp) within the same process. If this is not desired, you will require to run rsyslog in multiple instances with different omrelp configurations and certificates. Input usage ----------- .. _param-omrelp-input-tls-cacert: .. _omrelp.parameter.input.tls-cacert-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.caCert="/path/to/ca.pem") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-deletestateonfiledelete.rst0000644000000000000000000000013215132733117027570 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.323449858 30 ctime=1787067792.048681337 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-deletestateonfiledelete.rst0000666000175000017500000000335115132733117027240 0ustar00rgerrger.. _param-imfile-deletestateonfiledelete: .. _imfile.parameter.input.deletestateonfiledelete: .. _imfile.parameter.deletestateonfiledelete: deleteStateOnFileDelete ======================= .. index:: single: imfile; deleteStateOnFileDelete single: deleteStateOnFileDelete .. summary-start Removes the state file when the monitored file is deleted. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: deleteStateOnFileDelete :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Controls whether the state file is deleted if its associated main file is removed. This usually prevents problems when a new file with the same name is created. However, if a monitored file is modified with an editor that replaces the file, deleting the state file would cause the whole file to be reprocessed. Disable this setting only when the reason is fully understood. Input usage ----------- .. _param-imfile-input-deletestateonfiledelete: .. _imfile.parameter.input.deletestateonfiledelete-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" deleteStateOnFileDelete="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.removestateondelete: - ``removeStateOnDelete`` — maps to deleteStateOnFileDelete (status: legacy) .. index:: single: imfile; removeStateOnDelete single: removeStateOnDelete See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxinflightbytes.rst0000644000000000000000000000013215241075234026445 xustar0030 mtime=1787067036.579577808 30 atime=1787067036.676579624 30 ctime=1787067791.349668311 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxinflightbytes.rst0000664000175000017500000000321315241075234026110 0ustar00rgerrger.. _param-imbeats-maxinflightbytes: .. _imbeats.parameter.input.maxinflightbytes: maxInFlightBytes ================ .. meta:: :description: Maximum memory charged to in-flight Lumberjack input state for one imbeats instance. :keywords: rsyslog, imbeats, maxInFlightBytes, memory limit, Lumberjack .. index:: single: imbeats; maxInFlightBytes single: maxInFlightBytes .. summary-start Limit the memory charged to incomplete Lumberjack input across an imbeats instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxInFlightBytes :Scope: input :Type: positive integer :Default: input=268435456 :Required?: no :Introduced: 8.2608.0 Description ----------- Set the maximum number of bytes that one ``imbeats`` input instance may charge to incomplete receive buffers, decompression scratch space, retained event copies, and lazily allocated window descriptors. The valid range is ``1`` to ``2000000000`` bytes. Accounting is exact across all sessions of the input instance. A session that would exceed the limit is closed, its charged resources are released, and its incomplete batch is not acknowledged. Increase this value only when legitimate concurrent batches require more aggregate memory. Input usage ----------- .. _param-imbeats-input-maxinflightbytes: .. _imbeats.parameter.input.maxinflightbytes-usage: RainerScript: .. code-block:: rsyslog input(type="imbeats" port="5044" maxInFlightBytes="268435456") YAML: .. code-block:: yaml inputs: - type: imbeats port: 5044 maxInFlightBytes: 268435456 See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-facility.rst0000644000000000000000000000013215132733117024511 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.386451032 30 ctime=1787067792.064681635 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-facility.rst0000666000175000017500000000255315132733117024164 0ustar00rgerrger.. _param-imfile-facility: .. _imfile.parameter.input.facility: .. _imfile.parameter.facility: Facility ======== .. index:: single: imfile; Facility single: Facility .. summary-start Sets the syslog facility for messages read from this file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: Facility :Scope: input :Type: word :Default: local0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The syslog facility to be assigned to messages read from this file. It can be specified in textual form (for example ``local0``) or as a number (for example ``16``). Textual form is recommended. Input usage ----------- .. _param-imfile-input-facility: .. _imfile.parameter.input.facility-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" Facility="local0") Notes ----- - See https://en.wikipedia.org/wiki/Syslog for facility numbers. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilefacility: - ``$InputFileFacility`` — maps to Facility (status: legacy) .. index:: single: imfile; $InputFileFacility single: $InputFileFacility See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-file.rst0000644000000000000000000000013215132733117023624 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.372450771 30 ctime=1787067792.066681672 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-file.rst0000666000175000017500000000240715132733117023275 0ustar00rgerrger.. _param-imfile-file: .. _imfile.parameter.input.file: .. _imfile.parameter.file: File ==== .. index:: single: imfile; File single: File .. summary-start Specifies the absolute file path to monitor; wildcards are allowed. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: File :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- The file being monitored. It must be an absolute path without macros or templates. Wildcards are supported at the file name level. See :ref:`WildCards ` in the module documentation for details. Input usage ----------- .. _param-imfile-input-file: .. _imfile.parameter.input.file-usage: .. code-block:: rsyslog input(type="imfile" File="/path/to/logfile" Tag="example") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilename: - ``$InputFileName`` — maps to File (status: legacy) .. index:: single: imfile; $InputFileName single: $InputFileName See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-preservecase.rst0000644000000000000000000000013215241075234025245 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.725580541 30 ctime=1787067792.579691232 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-preservecase.rst0000664000175000017500000000217215241075234024713 0ustar00rgerrger.. _param-imudp-preservecase: .. _imudp.parameter.module.preservecase: PreserveCase ============ .. index:: single: imudp; PreserveCase single: PreserveCase .. summary-start Controls whether ``fromhost`` preserves original case. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: PreserveCase :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.37.0 Description ----------- This parameter is for controlling the case in ``fromhost``. If ``PreserveCase`` is set to "on", the case in ``fromhost`` is preserved, e.g., ``Host1.Example.Org`` when the message was received from ``Host1.Example.Org``. Default is "off" for backward compatibility. Leave it at the default when existing rules rely on lowercase ``fromhost`` values. Enable it when downstream systems must match the DNS spelling returned by reverse lookup. Module usage ------------ .. _param-imudp-module-preservecase: .. _imudp.parameter.module.preservecase-usage: .. code-block:: rsyslog module(load="imudp" PreserveCase="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonrewrite-output.rst0000644000000000000000000000013215132733117025705 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.468452561 30 ctime=1787067792.802695387 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonrewrite-output.rst0000666000175000017500000000240315132733117025352 0ustar00rgerrger.. _param-mmjsonrewrite-output: .. _mmjsonrewrite.parameter.input.output: output ====== .. index:: single: mmjsonrewrite; output single: output .. summary-start Sets the destination property that receives the rewritten JSON tree. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonrewrite`. :Name: output :Scope: input :Type: string :Default: none :Required?: yes :Introduced: 8.2410.0 Description ----------- Defines where the normalized JSON object is stored on the message. The property must use a JSON-capable prefix (``$!``, ``$.`` or ``$/``). When the configuration includes a leading ``$`` symbol it is removed automatically before validation. Other prefixes are rejected during configuration. At runtime ``mmjsonrewrite`` verifies that the destination property does not already exist. Attempting to overwrite an existing value triggers an error and the action aborts without modifying the message. Output usage ------------ .. _param-mmjsonrewrite-output-usage: .. _mmjsonrewrite.parameter.input.output-usage: .. code-block:: rsyslog action(type="mmjsonrewrite" input="$!raw" output="$!structured") See also -------- See also the :doc:`main mmjsonrewrite module documentation <../../configuration/modules/mmjsonrewrite>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-interface-output.rst0000644000000000000000000000012715216464435027125 xustar0030 mtime=1782212893.986265537 27 atime=1787067672.277449 30 ctime=1787067792.776694903 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-interface-output.rst0000664000175000017500000000311215216464435026562 0ustar00rgerrger.. _param-mmexternal-interface-output: .. _mmexternal.parameter.input.interface-output: interface.output ================ .. index:: single: mmexternal; interface.output single: interface.output .. summary-start Selects whether mmexternal expects a JSON response from the external plugin. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: interface.output :Scope: input :Type: string :Default: json :Required?: no :Introduced: 8.2606.0 Description ----------- This parameter controls what the external program must write to standard output after each received message. It can be set to one of the following values: * ``"json"`` (default): The external program must write one JSON object, followed by a line feed. The object is merged into the rsyslog message. * ``"none"``: The external program is not expected to write a response. ``mmexternal`` sends the message and continues immediately. Use ``"none"`` only for helpers that do not need to modify the rsyslog message, for example side-effect-only enrichment or notification programs. If such a helper writes substantial data to standard output, the helper may eventually block because rsyslog does not read responses in this mode. Input usage ----------- .. _param-mmexternal-input-interface-output: .. _mmexternal.parameter.input.interface-output-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/helper" interface.output="none" ) See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-keepalive.rst0000644000000000000000000000013215132733117024701 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.714475789 30 ctime=1787067792.352687002 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-keepalive.rst0000666000175000017500000000215515132733117024352 0ustar00rgerrger.. _param-imptcp-keepalive: .. _imptcp.parameter.input.keepalive: KeepAlive ========= .. index:: single: imptcp; KeepAlive single: KeepAlive .. summary-start Enables TCP keep-alive packets on the socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: KeepAlive :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Enable or disable keep-alive packets at the tcp socket layer. The default is to disable them. Input usage ----------- .. _param-imptcp-input-keepalive: .. _imptcp.parameter.input.keepalive-usage: .. code-block:: rsyslog input(type="imptcp" keepAlive="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverkeepalive: - $InputPTCPServerKeepAlive — maps to KeepAlive (status: legacy) .. index:: single: imptcp; $InputPTCPServerKeepAlive single: $InputPTCPServerKeepAlive See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-max_batch_size.rst0000644000000000000000000000013215241075234027122 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.970698518 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-max_batch_size.rst0000664000175000017500000000212515241075234026566 0ustar00rgerrger.. _param-omawslogshlc-max_batch_size: .. _omawslogshlc.parameter.action.max_batch_size: .. meta:: :description: Reference for the omawslogshlc max_batch_size parameter. :keywords: rsyslog, omawslogshlc, max_batch_size, aws, cloudwatch, batching max_batch_size ============== .. index:: single: omawslogshlc; max_batch_size single: max_batch_size .. summary-start Specifies the maximum number of events per HTTP request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: max_batch_size :Scope: action :Type: integer :Default: 100 :Required?: no :Introduced: Not specified Description ----------- ``max_batch_size`` controls how many events are accumulated before the batch is flushed to CloudWatch Logs. Valid range is 1 to 10000. AWS recommends 10 to 100 events per request for optimal performance. Action usage ------------ .. _omawslogshlc.parameter.action.max_batch_size-usage: .. code-block:: rsyslog action(type="omawslogshlc" max_batch_size="50" ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-authmode.rst0000644000000000000000000000013215132733117025336 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.924479704 30 ctime=1787067792.424688343 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-authmode.rst0000666000175000017500000000332015132733117025002 0ustar00rgerrger.. _param-imrelp-tls-authmode: .. _imrelp.parameter.input.tls-authmode: tls.authMode ============ .. index:: single: imrelp; tls.authMode single: tls.authMode .. summary-start Selects the mutual authentication strategy for TLS-secured RELP sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.authMode :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- Sets the mode used for mutual authentication. Supported values are ``fingerprint``, ``name``, or ``certvalid``. ``fingerprint`` mode basically is what SSH does. It does not require a full PKI to be present, instead self-signed certs can be used on all peers. Even if a CA certificate is given, the validity of the peer cert is NOT verified against it. Only the certificate fingerprint counts. In ``name`` mode, certificate validation happens. Here, the matching is done against the certificate's subjectAltName and, as a fallback, the subject common name. If the certificate contains multiple names, a match on any one of these names is considered good and permits the peer to talk to rsyslog. ``certvalid`` mode validates the remote peer's certificate chain but does not check the subject name, so any certificate trusted by the configured CAs is accepted. This mode is therefore weaker than ``name`` and typically used only when that reduced verification is acceptable. Input usage ----------- .. _param-imrelp-input-tls-authmode-usage: .. _imrelp.parameter.input.tls-authmode-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.authMode="fingerprint") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-ratelimit-name.rst0000644000000000000000000000013215171370365025670 xustar0030 mtime=1776677109.119908115 30 atime=1787067672.979462087 30 ctime=1787067793.282704332 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-ratelimit-name.rst0000664000175000017500000000136015171370365025334 0ustar00rgerrger.. index:: ! omhttp; RateLimit.Name .. _param-omhttp-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple actions to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-action limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-allowregex.rst0000644000000000000000000000013215132733117026143 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.838459459 30 ctime=1787067792.869696636 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-allowregex.rst0000666000175000017500000000203015132733117025604 0ustar00rgerrger.. _param-mmnormalize-allowregex: .. _mmnormalize.parameter.module.allowregex: allowRegex =========== .. index:: single: mmnormalize; allowRegex single: allowRegex .. summary-start Enables support for liblognorm regex field types despite higher overhead. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: allowRegex :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 6.1.2, possibly earlier Description ----------- Specifies if regex field-type should be allowed. Regex field-type has significantly higher computational overhead compared to other fields, so it should be avoided when another field-type can achieve the desired effect. Needs to be ``on`` for regex field-type to work. Module usage ------------ .. _param-mmnormalize-module-allowregex: .. _mmnormalize.parameter.module.allowregex-usage: .. code-block:: rsyslog module(load="mmnormalize" allowRegex="on") See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssserverservicename.rst0000644000000000000000000000013215132733117030601 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.591454854 30 ctime=1787067792.152683275 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssserverservicename.rst0000666000175000017500000000252215132733117030250 0ustar00rgerrger.. _param-imgssapi-inputgssserverservicename: .. _imgssapi.parameter.input.inputgssserverservicename: InputGSSServerServiceName ========================= .. index:: single: imgssapi; InputGSSServerServiceName single: InputGSSServerServiceName .. summary-start Sets the Kerberos service principal name used by the GSS server. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerServiceName :Scope: input :Type: word :Default: host :Required?: no :Introduced: 3.11.5 Description ----------- Specifies the service name for the GSS server, used to form the Service Principal Name (SPN). This can be a simple name like ``host`` or a compound name such as ``host/rsyslog.example.com``. If not specified, it defaults to ``host``. Input usage ----------- .. _imgssapi.parameter.input.inputgssserverservicename-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssServerServiceName "host/rsyslog.example.com" Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssserverservicename: - $inputGssServerServiceName — maps to InputGSSServerServiceName (status: legacy) .. index:: single: imgssapi; $inputGssServerServiceName single: $inputGssServerServiceName See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-bracketing.rst0000644000000000000000000000013215132733117025415 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.481471445 30 ctime=1787067792.262685324 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-bracketing.rst0000666000175000017500000000571715132733117025075 0ustar00rgerrger.. _param-impstats-bracketing: .. _impstats.parameter.module.bracketing: bracketing ========== .. index:: single: impstats; bracketing single: bracketing .. summary-start Adds BEGIN and END marker messages so post-processing can group statistics blocks. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: bracketing :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.4.1 Description ----------- .. versionadded:: 8.4.1 This is a utility setting for folks who post-process impstats logs and would like to know the begin and end of a block of statistics. When ``bracketing`` is set to ``on``, impstats issues a ``BEGIN`` message before the first counter is issued, then all counter values are issued, and then an ``END`` message follows. As such, if and only if messages are kept in sequence, a block of stats counts can easily be identified by those BEGIN and END messages. **Note well:** in general, sequence of syslog messages is **not** strict and is not ordered in sequence of message generation. There are various occasions that can cause message reordering, some examples are: * using multiple threads * using UDP forwarding * using relay systems, especially with buffering enabled * using disk-assisted queues This is not a problem with rsyslog, but rather the way a concurrent world works. For strict order, a specific order predicate (e.g. a sufficiently fine-grained timestamp) must be used. As such, BEGIN and END records may actually indicate the begin and end of a block of statistics - or they may *not*. Any order is possible in theory. So the bracketing option does not in all cases work as expected. This is the reason why it is turned off by default. *However*, bracketing may still be useful for many use cases. First and foremost, while there are many scenarios in which messages become reordered, in practice it happens relatively seldom. So most of the time the statistics records will come in as expected and actually will be bracketed by the BEGIN and END messages. Consequently, if an application can handle occasional out-of-order delivery (e.g. by graceful degradation), bracketing may actually be a great solution. It is, however, very important to know and handle out of order delivery. For most real-world deployments, a good way to handle it is to ignore unexpected records and use the previous values for ones missing in the current block. To guard against two or more blocks being mixed, it may also be a good idea to never reset a value to a lower bound, except when that lower bound is seen consistently (which happens due to a restart). Note that such lower bound logic requires :ref:`param-impstats-resetcounters` (``resetCounters`` in camelCase examples) to be set to ``off``. Module usage ------------ .. _impstats.parameter.module.bracketing-usage: .. code-block:: rsyslog module(load="impstats" bracketing="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-client_secret.rst0000644000000000000000000000013215171370365026426 xustar0030 mtime=1776677109.118908099 30 atime=1787067673.484471501 30 ctime=1787067792.943698015 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-client_secret.rst0000664000175000017500000000214115171370365026070 0ustar00rgerrger.. _param-omazuredce-client_secret: .. _omazuredce.parameter.action.client_secret: .. meta:: :description: Reference for the omazuredce client_secret parameter. :keywords: rsyslog, omazuredce, client_secret, azure, entra client_secret ============= .. index:: single: omazuredce; client_secret single: client_secret .. summary-start Supplies the client secret paired with ``client_id`` for OAuth token requests. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: client_secret :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``client_secret`` provides the shared secret used by Microsoft Entra client credentials authentication. Treat this value as sensitive and avoid storing real production secrets in example configurations or version control. Action usage ------------ .. _omazuredce.parameter.action.client_secret-usage: .. code-block:: rsyslog action(type="omazuredce" client_secret="" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-bulkmode.rst0000644000000000000000000000013115132733117025726 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.559472899 30 ctime=1787067792.979698686 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-bulkmode.rst0000666000175000017500000000250015132733117025372 0ustar00rgerrger.. _param-omclickhouse-bulkmode: .. _omclickhouse.parameter.input.bulkmode: bulkMode ======== .. index:: single: omclickhouse; bulkMode single: bulkMode single: omclickhouse; bulkmode single: bulkmode .. summary-start Determines whether events are sent individually or batched together in bulk HTTP requests. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: bulkMode :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: not specified Description ----------- The "off" setting means logs are shipped one by one, each in its own HTTP request. The default "on" will send multiple logs in the same request. This is recommended, because it is many times faster than when ``bulkMode`` is turned off. The maximum number of logs sent in a single bulk request depends on your ``maxBytes`` and queue settings - usually limited by the `dequeue batch size `_. More information about queues can be found in the `rsyslog documentation on queues `_. Input usage ----------- .. _omclickhouse.parameter.input.bulkmode-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" bulkMode="off") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-keepfailedmessages.rst0000644000000000000000000000013215132411300026655 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.032463075 30 ctime=1787067793.347705544 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-keepfailedmessages.rst0000666000175000017500000000203615132411300026324 0ustar00rgerrger.. _param-omkafka-keepfailedmessages: .. _omkafka.parameter.module.keepfailedmessages: KeepFailedMessages ================== .. index:: single: omkafka; KeepFailedMessages single: KeepFailedMessages .. summary-start Persist failed messages for resending after restart. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: KeepFailedMessages :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If enabled, failed messages will be saved and loaded on shutdown/startup and resent after startup when Kafka is available. This setting requires ``resubmitOnFailure`` to be enabled. Action usage ------------ .. _param-omkafka-action-keepfailedmessages: .. _omkafka.parameter.action.keepfailedmessages: .. code-block:: rsyslog action(type="omkafka" KeepFailedMessages="on") Notes ----- - Originally documented as "binary"; uses boolean values. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-apiversionstr.rst0000644000000000000000000000013115132411300026127 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.142446483 29 ctime=1787067791.96567979 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-apiversionstr.rst0000666000175000017500000000160515132411300025600 0ustar00rgerrger.. _param-imdocker-apiversionstr: .. _imdocker.parameter.module.apiversionstr: ApiVersionStr ============= .. index:: single: imdocker; ApiVersionStr single: ApiVersionStr .. summary-start Docker API version string like ``v1.27``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: ApiVersionStr :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=v1.27 :Required?: no :Introduced: 8.41.0 Description ----------- Specifies the version of Docker API to use. The value must match the format required by the Docker API, such as ``v1.27``. Module usage ------------ .. _param-imdocker-module-apiversionstr: .. _imdocker.parameter.module.apiversionstr-usage: .. code-block:: rsyslog module(load="imdocker" ApiVersionStr="...") See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-db.rst0000644000000000000000000000013215145046112023522 xustar0030 mtime=1771326538.945012754 30 atime=1787067673.042463262 30 ctime=1787067793.409706699 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-db.rst0000664000175000017500000000144215145046112023167 0ustar00rgerrger.. _param-ommysql-db: .. _ommysql.parameter.input.db: db == .. index:: single: ommysql; db single: db .. summary-start Names the MariaDB/MySQL database that receives the log records. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: db :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 7.x, possibly earlier Description ----------- This is the name of the database on the MariaDB/MySQL server where log records will be inserted. Input usage ----------- .. _ommysql.parameter.input.db-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" db="syslog_db" uid="user" pwd="pwd") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-keepalive-interval.rst0000644000000000000000000000013215132733117026523 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.724475975 30 ctime=1787067792.345686871 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-keepalive-interval.rst0000666000175000017500000000264715132733117026202 0ustar00rgerrger.. _param-imptcp-keepalive-interval: .. _imptcp.parameter.input.keepalive-interval: KeepAlive.Interval ================== .. index:: single: imptcp; KeepAlive.Interval single: KeepAlive.Interval .. summary-start Sets the interval between keepalive probes. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: KeepAlive.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime. The default, 0, means that the operating system defaults are used. This has only effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imptcp-input-keepalive-interval: .. _imptcp.parameter.input.keepalive-interval-usage: .. code-block:: rsyslog input(type="imptcp" keepAlive.interval="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverkeepalive_intvl: - $InputPTCPServerKeepAlive_intvl — maps to KeepAlive.Interval (status: legacy) .. index:: single: imptcp; $InputPTCPServerKeepAlive_intvl single: $InputPTCPServerKeepAlive_intvl See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-defaulttag.rst0000644000000000000000000000013215132411300025543 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.927461118 30 ctime=1787067792.175683703 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-defaulttag.rst0000666000175000017500000000205015132411300025206 0ustar00rgerrger.. _param-imjournal-defaulttag: .. _imjournal.parameter.module.defaulttag: .. meta:: :tag: module:imjournal :tag: parameter:defaultTag defaultTag ========== .. index:: single: imjournal; defaultTag single: defaultTag .. summary-start Provides a default tag when both ``SYSLOG_IDENTIFIER`` and ``_COMM`` are missing. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: defaultTag :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=journal :Required?: no :Introduced: 8.2312.0 Description ----------- Defines the tag value used when neither an identifier string nor process name is available in the journal entry. Module usage ------------ .. _param-imjournal-module-defaulttag: .. _imjournal.parameter.module.defaulttag-usage: .. code-block:: rsyslog module(load="imjournal" defaultTag="...") Notes ----- - Earlier documentation incorrectly described this option as ``binary``. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-unlink.rst0000644000000000000000000000013115216464435024610 xustar0030 mtime=1782212893.986265537 30 atime=1787067673.855478418 29 ctime=1787067792.66869289 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-unlink.rst0000664000175000017500000000253715216464435024264 0ustar00rgerrger.. _param-imuxsock-unlink: .. _imuxsock.parameter.input.unlink: Unlink ====== .. index:: single: imuxsock; Unlink single: Unlink .. summary-start Controls whether the socket is unlinked on open and close. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: Unlink :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 7.3.9 Description ----------- If turned on (default), the socket is unlinked and re-created when opened and also unlinked when finally closed. Set it to off if you handle socket creation yourself. ``Unlink="off"`` is for sockets whose lifecycle is managed outside rsyslog. If rsyslog should create the socket path, leave ``Unlink`` at its default ``on`` value. In particular, ``CreatePath="on"`` cannot be combined with ``Unlink="off"``: rsyslog would be asked to create the socket path but then forbidden from replacing or removing it on restart. .. note:: Note that handling socket creation oneself has the advantage that a limited amount of messages may be queued by the OS if rsyslog is not running. .. versionadded:: 7.3.9 Input usage ----------- .. _param-imuxsock-input-unlink: .. _imuxsock.parameter.input.unlink-usage: .. code-block:: rsyslog input(type="imuxsock" unlink="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-socketbacklog.rst0000644000000000000000000000013215132733117025367 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.183484532 30 ctime=1787067792.521690151 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-socketbacklog.rst0000666000175000017500000000355015132733117025040 0ustar00rgerrger.. _param-imtcp-socketbacklog: .. _imtcp.parameter.input.socketbacklog: SocketBacklog ============= .. index:: single: imtcp; SocketBacklog single: SocketBacklog .. summary-start Sets the backlog length for pending TCP connections. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: SocketBacklog :Scope: input :Type: integer :Default: input=10% of configured connections :Required?: no :Introduced: 8.2502.0 Description ----------- Specifies the backlog parameter passed to the ``listen()`` system call. This parameter defines the maximum length of the queue for pending connections, which includes partially established connections (those in the SYN-ACK handshake phase) and fully established connections waiting to be accepted by the application. **Available starting with the 8.2502.0 series.** For more details, refer to the ``listen(2)`` man page. By default, the value is set to 10% of the configured connections to accommodate modern workloads. It can be adjusted to suit specific requirements, such as: - **High rates of concurrent connection attempts**: Increasing this value helps handle bursts of incoming connections without dropping them. - **Test environments with connection flooding**: Larger values are recommended to prevent SYN queue overflow. - **Servers with low traffic**: Lower values may be used to reduce memory usage. The effective backlog size is influenced by system-wide kernel settings, particularly ``net.core.somaxconn`` and ``net.ipv4.tcp_max_syn_backlog``. The smaller value between this parameter and the kernel limits is used as the actual backlog. Input usage ----------- .. _param-imtcp-input-socketbacklog: .. _imtcp.parameter.input.socketbacklog-usage: .. code-block:: rsyslog input(type="imtcp" socketBacklog="128") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-forcesingleinstance.rst0000644000000000000000000000013015132733117027637 xustar0030 mtime=1768666703.913620329 29 atime=1787067672.29244928 29 ctime=1787067792.77169481 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-forcesingleinstance.rst0000666000175000017500000000344415132733117027314 0ustar00rgerrger.. _param-mmexternal-forcesingleinstance: .. _mmexternal.parameter.input.forcesingleinstance: forceSingleInstance =================== .. index:: single: mmexternal; forceSingleInstance single: forceSingleInstance .. summary-start Enforces that only a single instance of the external message modification plugin runs. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: forceSingleInstance :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: 8.3.0 Description ----------- This is an expert parameter. By default, ``mmexternal`` starts an instance of the external program for each worker thread in the action's queue (the maximum number of worker threads can be specified with the :doc:`queue.workerThreads <../../rainerscript/queue_parameters>` parameter). Moreover, if the action is associated with a :doc:`disk-assisted queue <../../concepts/queues>`, an additional instance may be started to process items from disk. If you want to ensure that only a single instance of the program is ever running, regardless of the number of worker threads or queue type, set this parameter to ``"on"``. This is useful if the external program accesses a shared resource that does not support concurrent access. This parameter is equivalent to the :ref:`param-omprog-forcesingleinstance` parameter. Input usage ----------- .. _param-mmexternal-input-forcesingleinstance: .. _mmexternal.parameter.input.forcesingleinstance-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/mmexternal.py" forceSingleInstance="on" ) Notes ----- - The type was previously documented as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-timeout.rst0000644000000000000000000000013215145046112024420 xustar0030 mtime=1771326538.953012884 30 atime=1787067672.576454574 30 ctime=1787067793.501708413 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-timeout.rst0000664000175000017500000000146515145046112024072 0ustar00rgerrger.. _param-omrelp-timeout: .. _omrelp.parameter.input.timeout: Timeout ======= .. index:: single: omrelp; Timeout single: Timeout .. summary-start Sets the RELP session timeout before a connection is considered dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: Timeout :Scope: input :Type: integer :Default: input=90 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Timeout for relp sessions. If set too low, valid sessions may be considered dead and tried to recover. Input usage ----------- .. _param-omrelp-input-timeout: .. _omrelp.parameter.input.timeout-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" timeout="120") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-hup-signal.rst0000644000000000000000000000013215132733117025012 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.941461379 30 ctime=1787067793.463707705 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-hup-signal.rst0000666000175000017500000000170015132733117024456 0ustar00rgerrger.. _param-omprog-hup-signal: .. _omprog.parameter.action.hup-signal: hup.signal ========== .. index:: single: omprog; hup.signal single: hup.signal .. summary-start Forwards a chosen signal to the program when rsyslog receives HUP. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: hup.signal :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: 8.9.0 Description ----------- Specifies which signal, if any, is to be forwarded to the external program when rsyslog receives a HUP signal. Currently, HUP, USR1, USR2, INT, and TERM are supported. If unset, no signal is sent on HUP. This is the default and what pre 8.9.0 versions did. Action usage ------------ .. _param-omprog-action-hup-signal: .. _omprog.parameter.action.hup-signal-usage: .. code-block:: rsyslog action(type="omprog" hup.signal="HUP") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-log-file.rst0000644000000000000000000000013215216464435025011 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.459471035 30 ctime=1787067792.273685529 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-log-file.rst0000664000175000017500000000257615216464435024467 0ustar00rgerrger.. _param-impstats-log-file: .. _impstats.parameter.module.log-file: log.file ======== .. index:: single: impstats; log.file single: log.file .. summary-start Writes impstats statistics records to the specified local file in addition to other outputs. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: log.file :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If specified, statistics data is written to the specified file. For robustness, this should be a local file. The file format cannot be customized; it consists of a date header, followed by a colon, followed by the actual statistics record, all on one line. Only very limited error handling is done, so if things go wrong stats records will probably be lost. Logging to file can be a useful alternative if for some reasons (e.g. full queues) the regular syslog stream method shall not be used solely. Note that turning on file logging does NOT turn off syslog logging. If that is desired, :ref:`param-impstats-log-syslog` (``log.syslog``) must be explicitly set to ``off``. Module usage ------------ .. _impstats.parameter.module.log-file-usage: .. code-block:: rsyslog module(load="impstats" log.file="/var/log/rsyslog-stats") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmpstrucdata-container.rst0000644000000000000000000000013215216464435026135 xustar0030 mtime=1782212893.986265537 30 atime=1787067672.956461658 30 ctime=1787067792.891697046 rsyslog-8.2608.0/doc/source/reference/parameters/mmpstrucdata-container.rst0000664000175000017500000000236515216464435025607 0ustar00rgerrger.. _param-mmpstrucdata-container: .. _mmpstrucdata.parameter.action.container: container ========= .. index:: single: mmpstrucdata; container single: container .. summary-start Sets the JSON object member name that receives parsed structured data. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmpstrucdata`. :Name: container :Scope: action :Type: string :Default: action="rfc5424-sd" :Required?: no :Introduced: 8.2606.0 Description ----------- Specifies the JSON member name below :ref:`param-mmpstrucdata-jsonroot` where parsed RFC5424 structured data is stored. This parameter changes the member name only; it is not a JSON path. Use ``jsonRoot`` to move the parent location. When an RFC5424 message has no structured data, the module creates this member with a JSON ``null`` value. Action usage ------------ .. _param-mmpstrucdata-action-container: .. _mmpstrucdata.parameter.action.container-usage: .. code-block:: rsyslog action(type="mmpstrucdata" jsonRoot="$!structured-data" container="sd") YAML usage ---------- .. code-block:: yaml actions: - type: mmpstrucdata jsonRoot: "$!structured-data" container: sd See also -------- See also :doc:`../../configuration/modules/mmpstrucdata`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-azure_key.rst0000644000000000000000000000013215216464435027053 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.292467922 30 ctime=1787067792.923697642 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-azure_key.rst0000664000175000017500000000172615216464435026525 0ustar00rgerrger.. _param-omazureeventhubs-azure_key: .. _omazureeventhubs.parameter.input.azure_key: azure_key ========= .. index:: single: omazureeventhubs; azure_key single: azure_key .. summary-start Provides the shared access key value used to sign Event Hubs requests. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: azure_key :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- Specifies the value of the "Event Hubs shared access key". This secret key string authenticates the connection and signs requests to the Event Hubs instance. Supply it unless ``amqp_address`` already embeds the key. Input usage ----------- .. _omazureeventhubs.parameter.input.azure_key-usage: .. code-block:: rsyslog action(type="omazureeventhubs" azure_key_name="MyPolicy" azure_key="MySecretKey" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-timeout-ms.rst0000644000000000000000000000013215145046112026360 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.496471725 30 ctime=1787067792.293685902 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-timeout-ms.rst0000664000175000017500000000147515145046112026033 0ustar00rgerrger.. _param-impstats-push-timeout-ms: .. _impstats.parameter.module.push-timeout-ms: push.timeout.ms =============== .. index:: single: impstats; push.timeout.ms single: push.timeout.ms .. summary-start Sets the HTTP request timeout for Remote Write push (milliseconds). .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.timeout.ms :Scope: module :Type: integer (milliseconds) :Default: module=5000 :Required?: no :Introduced: 8.2602.0 Description ----------- Configures the maximum time allowed for the HTTP request to complete. Module usage ------------ .. _impstats.parameter.module.push-timeout-ms-usage: .. code-block:: rsyslog module(load="impstats" push.timeout.ms="2000") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-listenportfilename-module.rst0000644000000000000000000000013215216464435030070 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.101445719 30 ctime=1787067791.942679361 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-listenportfilename-module.rst0000664000175000017500000000305715216464435027541 0ustar00rgerrger.. _param-imdiag-listenportfilename-module: .. _imdiag.parameter.module.listenportfilename: .. meta:: :description: Reference for the imdiag listenPortFileName module-scope parameter. :keywords: rsyslog, imdiag, listenportfilename, testbench, port file, startup ListenPortFileName (module scope) ================================== .. index:: single: imdiag; ListenPortFileName (module) .. summary-start Path of the file to which imdiag writes its chosen TCP listen port number, set at module load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ListenPortFileName :Scope: module :Type: string (file path) :Default: none :Required?: no (but recommended for testbench use) :Introduced: 8.x Description ----------- When set at module scope, ``ListenPortFileName`` specifies the file that imdiag will create and populate with its chosen listen port number after the TCP listener is ready. The testbench reads this file to discover the port without needing a fixed port number. This parameter is module-scoped. imdiag's diagnostic command listener is configured from ``module(...)`` rather than a dedicated ``input(...)`` object. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/tmp/imdiag.port") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" listenportfilename: "/tmp/imdiag.port" See also -------- See also :doc:`../../configuration/modules/imdiag` and :ref:`param-imdiag-listenportfilename`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-serverrun.rst0000644000000000000000000000013215216464435024734 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.080445328 30 ctime=1787067791.956679622 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-serverrun.rst0000664000175000017500000000414115216464435024400 0ustar00rgerrger.. _param-imdiag-serverrun: .. _imdiag.parameter.module.serverrun: ServerRun ========= .. index:: single: imdiag; ServerRun single: ServerRun .. summary-start Creates the imdiag TCP listener on the specified port (``0`` selects an ephemeral port). .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ServerRun :Scope: module :Type: integer (port) :Default: module=none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- Starts the diagnostic control listener. The value is the TCP port number to bind. Specify ``0`` to request an ephemeral port from the operating system. The chosen port is recorded in the file specified by the mandatory :ref:`ListenPortFileName ` parameter. imdiag always uses the plain TCP (``ptcp``) :doc:`network stream driver <../../concepts/netstrm_drvr>`. As a result, parameters that normally tune stream driver authentication or permitted peers are accepted for compatibility but have no effect in current releases. This includes: * :ref:`param-imdiag-serverstreamdrivermode` * :ref:`param-imdiag-serverstreamdriverauthmode` * :ref:`param-imdiag-serverstreamdriverpermittedpeer` imdiag supports only a single listener. Attempting to configure ``ServerRun`` more than once logs an error and the additional configuration is ignored. Set module-level parameters such as :ref:`MaxSessions ` before invoking ``ServerRun``. Module usage ------------ .. _param-imdiag-module-serverrun: .. _imdiag.parameter.module.serverrun-usage: .. code-block:: rsyslog module(load="imdiag" maxSessions="20" listenPortFileName="/var/run/rsyslog/imdiag.port" serverRun="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagserverrun: - $IMDiagServerRun — maps to ServerRun (status: legacy) .. index:: single: imdiag; $IMDiagServerRun single: $IMDiagServerRun See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-sourcetemplate.rst0000644000000000000000000000013115145046112026662 xustar0030 mtime=1771326538.958012966 30 atime=1787067671.949442886 29 ctime=1787067793.57770983 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-sourcetemplate.rst0000664000175000017500000000363415145046112026335 0ustar00rgerrger.. _param-omudpspoof-sourcetemplate: .. _omudpspoof.parameter.action.sourcetemplate: sourceTemplate ============== .. index:: single: omudpspoof; sourceTemplate single: sourceTemplate .. summary-start Names the template that provides the spoofed source IP address for sent messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: sourceTemplate :Scope: action :Type: word :Default: RSYSLOG_omudpspoofDfltSourceTpl :Required?: no :Introduced: 5.1.3 Description ----------- This is the name of the template that contains a numerical IP address that is to be used as the source system IP address. While it may often be a constant value, it can be generated as usual via the property replacer, as long as it is a valid IPv4 address. If not specified, the built-in default template RSYSLOG_omudpspoofDfltSourceTpl is used. This template is defined as follows: .. code-block:: rsyslog template(name="RSYSLOG_omudpspoofDfltSourceTpl" type="string" string="%fromhost-ip%") So in essence, the default template spoofs the address of the system the message was received from. This is considered the most important use case. Action usage ------------ .. _param-omudpspoof-action-sourcetemplate: .. _omudpspoof.parameter.action.sourcetemplate-usage: .. code-block:: rsyslog template(name="spoofaddr" type="string" string="192.0.2.100") action(type="omudpspoof" target="192.0.2.1" sourceTemplate="spoofaddr") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspoofsourcenametemplate: - $ActionOMUDPSpoofSourceNameTemplate — maps to sourceTemplate (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofSourceNameTemplate single: $ActionOMUDPSpoofSourceNameTemplate See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-tlslib.rst0000644000000000000000000000013215132733117025021 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.856478436 30 ctime=1787067792.444688716 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-tlslib.rst0000666000175000017500000000263015132733117024470 0ustar00rgerrger.. _param-imrelp-tls-tlslib: .. _imrelp.parameter.module.tls-tlslib: tls.tlsLib ========== .. index:: single: imrelp; tls.tlsLib single: tls.tlsLib .. summary-start Selects the TLS backend library that librelp should use for RELP operations. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.tlsLib :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 8.1903.0 Description ----------- Permits to specify the TLS library used by librelp. All RELP protocol operations are actually performed by librelp and not rsyslog itself. The value specified is directly passed down to librelp. Depending on librelp version and build parameters, supported TLS libraries differ (or TLS may not be supported at all). In this case rsyslog emits an error message. Usually, the following options should be available: "openssl", "gnutls". Note that "gnutls" is the current default for historic reasons. We actually recommend to use "openssl". It provides better error messages and accepts a wider range of certificate types. If you have problems with the default setting, we recommend to switch to "openssl". Module usage ------------ .. _param-imrelp-module-tls-tlslib-usage: .. _imrelp.parameter.module.tls-tlslib-usage: .. code-block:: rsyslog module(load="imrelp" tls.tlsLib="openssl") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfifo-tag.rst0000644000000000000000000000013215216464435023473 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.193447434 30 ctime=1787067792.135682958 rsyslog-8.2608.0/doc/source/reference/parameters/imfifo-tag.rst0000664000175000017500000000201615216464435023136 0ustar00rgerrger.. _param-imfifo-tag: .. _imfifo.parameter.input.tag: tag === .. meta:: :description: Syslog tag to apply to messages read from this named pipe (FIFO). :keywords: rsyslog, imfifo, tag .. index:: single: imfifo; tag single: tag .. summary-start Specifies the syslog tag to apply to messages read from this named pipe (FIFO). .. summary-end This parameter applies to :doc:`../../configuration/modules/imfifo`. :Name: tag :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: yes :Introduced: 8.2606.0 Description ----------- The syslog tag to be assigned to all messages read from this named pipe. The tag is typically used to identify the source of the logs in later filtering or formatting steps. Input usage ----------- .. _param-imfifo-input-tag: .. _imfifo.parameter.input.tag-usage: .. code-block:: rsyslog input(type="imfifo" file="/var/log/myfifo" tag="fifo-logs:") See also -------- See also :doc:`../../configuration/modules/imfifo`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-busyretryinterval.rst0000644000000000000000000000013115132733117027755 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.628455544 29 ctime=1787067792.82269576 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-busyretryinterval.rst0000666000175000017500000000262615132733117027432 0ustar00rgerrger.. _param-mmkubernetes-busyretryinterval: .. _mmkubernetes.parameter.action.busyretryinterval: busyretryinterval ================= .. index:: single: mmkubernetes; busyretryinterval single: busyretryinterval .. summary-start Sets the delay before retrying after a ``429 Busy`` response. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: busyretryinterval :Scope: action :Type: integer :Default: 5 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- The number of seconds to wait before retrying operations to the Kubernetes API server after receiving a `429 Busy` response. The default `"5"` means that the module will retry the connection every `5` seconds. Records processed during this time will _not_ have any additional metadata associated with them, so you will need to handle cases where some of your records have all of the metadata and some do not. If you want to have rsyslog suspend the plugin until the Kubernetes API server is available, set `busyretryinterval` to `"0"`. This will cause the plugin to return an error to rsyslog. Action usage ------------ .. _param-mmkubernetes-action-busyretryinterval: .. _mmkubernetes.parameter.action.busyretryinterval-usage: .. code-block:: rsyslog action(type="mmkubernetes" busyRetryInterval="5") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-azure_key_name.rst0000644000000000000000000000013115216464435030052 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.379469544 29 ctime=1787067792.92569768 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-azure_key_name.rst0000664000175000017500000000177415216464435027530 0ustar00rgerrger.. _param-omazureeventhubs-azure_key_name: .. _omazureeventhubs.parameter.input.azure_key_name: azure_key_name ============== .. index:: single: omazureeventhubs; azure_key_name single: azure_key_name .. summary-start Specifies the shared access key name used to authenticate with Event Hubs. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: azure_key_name :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- Specifies the "Event Hubs shared access key name" (the shared access policy name) used to authenticate and authorize connections to the Event Hubs instance. Provide this value unless ``amqp_address`` already supplies the credentials. Input usage ----------- .. _omazureeventhubs.parameter.input.azure_key_name-usage: .. code-block:: rsyslog action(type="omazureeventhubs" azure_key_name="MyPolicy" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omuxsock-abstract.rst0000644000000000000000000000013215132733117025113 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.077445272 30 ctime=1787067793.586709997 rsyslog-8.2608.0/doc/source/reference/parameters/omuxsock-abstract.rst0000666000175000017500000000354315132733117024566 0ustar00rgerrger.. _param-omuxsock-abstract: .. _omuxsock.parameter.module.abstract: abstract ========== .. index:: single: omuxsock; abstract single: abstract .. summary-start This indicates whether the socketName should be used as an abstract socket address or not. .. summary-end This parameter applies to :doc:`../../configuration/modules/omuxsock`. :Name: abstract :Scope: module, action :Type: boolean :Default: module="0", action="0" :Required?: no :Introduced: v8.2512 Description ----------- This indicates whether the socket name is abstract or not. Abstract socket names are generally only supported under Linux, and differ from non-abstract socket names by not requiring a name in the filesystem. The default is False (0). Module usage ------------ .. _param-omuxsock-action-abstract: .. _omuxsock.parameter.action.abstract-usage: If abstract is set at the module level, then it becomes the default abstract setting for the first unnamed action. It only applies to a single unnamed action, so it is primarily just a short-hand notation for when only a single omuxsock action is required. .. code-block:: rsyslog module(load="omuxsock" socketName="/tmp/socksample" abstract="0") Action usage ------------ .. code-block:: rsyslog action(type="omuxsock" socketName="/tmp/example" abstract="0") action(type="omuxsock" socketName="rsyslogd.msg.handler" abstract="1") .. note:: :ref:`param-omuxsock-socketname`, :ref:`param-omuxsock-abstract`, and :ref:`param-omuxsock-sockettype` constitute a logical configuration tuple. They are applied together as a whole tuple from a module level configuration to an action. Therefore, all three parameters must be explicitly specified in the action, or none may be specified in the action. In the latter case, the default is taken from the module. See also -------- See also :doc:`../../configuration/modules/omuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-internalmsgfacility.rst0000644000000000000000000000013215132733117026772 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.049463392 30 ctime=1787067792.234684803 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-internalmsgfacility.rst0000666000175000017500000000314415132733117026442 0ustar00rgerrger.. _param-imklog-internalmsgfacility: .. _imklog.parameter.module.internalmsgfacility: InternalMsgFacility =================== .. index:: single: imklog; InternalMsgFacility single: InternalMsgFacility .. summary-start Sets the facility used for messages that imklog generates internally. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: InternalMsgFacility :Scope: module :Type: facility :Default: Linux: "kern"; other platforms: "syslogd" :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This parameter sets the facility for messages that are generated internally by imklog. imklog generates some messages of itself (e.g. on problems, startup and shutdown) and these do not stem from the kernel. Historically, under Linux, these too have "kern" facility. Thus, on Linux platforms the default is "kern" while on others it is "syslogd". It is recommended to not change this setting unless you have a specific reason to do so. Module usage ------------ .. _param-imklog-module-internalmsgfacility: .. _imklog.parameter.module.internalmsgfacility-usage: .. code-block:: rsyslog module(load="imklog" internalMsgFacility="kern") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.kloginternalmsgfacility: - $KLogInternalMsgFacility — maps to InternalMsgFacility (status: legacy) .. index:: single: imklog; $KLogInternalMsgFacility single: $KLogInternalMsgFacility See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-rotation-sizelimitcommand.rst0000644000000000000000000000013215145046112030114 xustar0030 mtime=1771326538.944012737 30 atime=1787067672.504453232 30 ctime=1787067793.194702692 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-rotation-sizelimitcommand.rst0000664000175000017500000000313315145046112027560 0ustar00rgerrger.. _param-omfile-rotation-sizelimitcommand: .. _omfile.parameter.module.rotation-sizelimitcommand: rotation.sizeLimitCommand ========================= .. index:: single: omfile; rotation.sizeLimitCommand single: rotation.sizeLimitCommand .. summary-start Configures the script invoked when `rotation.sizeLimit` is exceeded. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: rotation.sizeLimitCommand :Scope: action :Type: string :Default: action=(empty) :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This sets the command executed when a file hits the configured size limit. Use together with :ref:`param-omfile-rotation-sizelimit`. By default, the current file name is passed as the last argument. Disable this behavior with :ref:`param-omfile-rotation-sizelimitcommandpassfilename` if your script expects no additional arguments. Action usage ------------ .. _param-omfile-action-rotation-sizelimitcommand: .. _omfile.parameter.action.rotation-sizelimitcommand: .. code-block:: rsyslog action(type="omfile" rotation.sizeLimitCommand="...") Notes ----- - Legacy documentation referred to the type as ``binary``; the value is a command string. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.outchannel: - $outchannel — maps to rotation.sizeLimitCommand (status: legacy) .. index:: single: omfile; $outchannel single: $outchannel See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-table_name.rst0000644000000000000000000000013215171370365025672 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.494471688 30 ctime=1787067792.956698257 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-table_name.rst0000664000175000017500000000200115171370365025327 0ustar00rgerrger.. _param-omazuredce-table_name: .. _omazuredce.parameter.action.table_name: .. meta:: :description: Reference for the omazuredce table_name parameter. :keywords: rsyslog, omazuredce, table_name, azure, stream table_name ========== .. index:: single: omazuredce; table_name single: table_name .. summary-start Sets the stream or table name appended to the Azure ingestion request path. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: table_name :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``table_name`` is appended below ``/streams/`` in the final request URL. The configured value must match a stream accepted by the target Data Collection Rule. Action usage ------------ .. _omazuredce.parameter.action.table_name-usage: .. code-block:: rsyslog action(type="omazuredce" table_name="Custom-MyTable_CL" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-containerrulebase.rst0000644000000000000000000000013215132733117027646 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.643455823 30 ctime=1787067792.828695872 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-containerrulebase.rst0000666000175000017500000000212515132733117027314 0ustar00rgerrger.. _param-mmkubernetes-containerrulebase: .. _mmkubernetes.parameter.action.containerrulebase: containerrulebase ================= .. index:: single: mmkubernetes; containerrulebase single: containerrulebase .. summary-start Specifies the rulebase file used to parse ``CONTAINER_NAME`` values. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: containerrulebase :Scope: action :Type: word :Default: /etc/rsyslog.d/k8s_container_name.rulebase :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When processing journald logs, this is the rulebase used to match the CONTAINER_NAME property value and extract metadata. For the actual rules, see :ref:`param-mmkubernetes-containerrules`. Action usage ------------ .. _param-mmkubernetes-action-containerrulebase: .. _mmkubernetes.parameter.action.containerrulebase-usage: .. code-block:: rsyslog action(type="mmkubernetes" containerRuleBase="/etc/rsyslog.d/k8s_container_name.rulebase") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-supportoctetcountedframing.rst0000644000000000000000000000013215132733117030435 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.694475416 30 ctime=1787067792.387687654 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-supportoctetcountedframing.rst0000666000175000017500000000310415132733117030101 0ustar00rgerrger.. _param-imptcp-supportoctetcountedframing: .. _imptcp.parameter.input.supportoctetcountedframing: SupportOctetCountedFraming ========================== .. index:: single: imptcp; SupportOctetCountedFraming single: SupportOctetCountedFraming .. summary-start Enables legacy octet-counted framing similar to RFC5425. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: SupportOctetCountedFraming :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The legacy octet-counted framing (similar to RFC5425 framing) is activated. This is the default and should be left unchanged until you know very well what you do. It may be useful to turn it off, if you know this framing is not used and some senders emit multi-line messages into the message stream. Input usage ----------- .. _param-imptcp-input-supportoctetcountedframing: .. _imptcp.parameter.input.supportoctetcountedframing-usage: .. code-block:: rsyslog input(type="imptcp" supportOctetCountedFraming="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserversupportoctetcountedframing: - $InputPTCPServerSupportOctetCountedFraming — maps to SupportOctetCountedFraming (status: legacy) .. index:: single: imptcp; $InputPTCPServerSupportOctetCountedFraming single: $InputPTCPServerSupportOctetCountedFraming See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-workerthreads.rst0000644000000000000000000000013215132733117025440 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.091482817 30 ctime=1787067792.555690785 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-workerthreads.rst0000666000175000017500000000424415132733117025112 0ustar00rgerrger.. _param-imtcp-workerthreads: .. _imtcp.parameter.module.workerthreads: WorkerThreads ============= .. index:: single: imtcp; WorkerThreads single: WorkerThreads .. summary-start Sets the default number of worker threads for listeners on epoll-enabled systems. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: WorkerThreads :Scope: module :Type: integer :Default: module=2 :Required?: no :Introduced: 8.2504.0 Description ----------- The ``WorkerThreads`` parameter defines the **default number of worker threads** for all ``imtcp`` listeners. This setting applies only on **epoll-enabled systems**. If ``epoll`` is unavailable, ``imtcp`` will always run in **single-threaded mode**, regardless of this setting. **Default value:** ``2`` **Allowed values:** ``1`` (single-threaded) to any reasonable number (should not exceed CPU cores). **Behavior and Recommendations** - If set to ``1``, ``imtcp`` operates in **single-threaded mode**, using the main event loop for processing. - If set to ``2`` or more, a **worker pool** is created, allowing multiple connections to be processed in parallel. - Setting this too high **can degrade performance** due to excessive thread switching. - A reasonable upper limit is **the number of available CPU cores**. **Scope and Overrides** - This is a **module-level parameter**, meaning it **sets the default** for all ``imtcp`` listeners. - Each listener instance can override this by setting the ``workerthreads`` **listener parameter**. **Example Configuration** The following sets a default of **4** worker threads for all listeners, while overriding it to **8** for a specific listener: .. code-block:: none module(load="imtcp" WorkerThreads="4") # Default for all listeners input(type="imtcp" port="514" workerthreads="8") # Overrides default, using 8 workers If ``WorkerThreads`` is not explicitly set, the default of ``2`` will be used. Module usage ------------ .. _param-imtcp-module-workerthreads: .. _imtcp.parameter.module.workerthreads-usage: .. code-block:: rsyslog module(load="imtcp" workerThreads="4") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-bits.rst0000644000000000000000000000013115132733117024547 xustar0030 mtime=1768666703.912620314 29 atime=1787067671.87244145 30 ctime=1787067792.724693934 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-bits.rst0000666000175000017500000000217715132733117024225 0ustar00rgerrger.. _param-mmanon-ipv6-bits: .. _mmanon.parameter.input.ipv6-bits: ipv6.bits ========= .. index:: single: mmanon; ipv6.bits single: ipv6.bits .. summary-start Sets how many low-order bits of IPv6 addresses are anonymized. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.bits :Scope: input :Type: positive integer :Default: input=96 :Required?: no :Introduced: 7.3.7 Description ----------- This sets the number of bits that should be anonymized (bits are from the right, so lower bits are anonymized first). This setting permits to save network information while still anonymizing user-specific data. The more bits you discard, the better the anonymization obviously is. The default of 96 bits reflects what German data privacy rules consider as being sufficiently anonymized. We assume, this can also be used as a rough but conservative guideline for other countries. Input usage ----------- .. _mmanon.parameter.input.ipv6-bits-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.bits="64") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-allowedsender.rst0000644000000000000000000000013215241075234025404 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.455688921 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-allowedsender.rst0000664000175000017500000000472215241075234025055 0ustar00rgerrger.. _param-imtcp-allowedsender: .. _imtcp.parameter.module.allowedsender: .. _imtcp.parameter.input.allowedsender: AllowedSender ============= .. index:: single: imtcp; AllowedSender single: AllowedSender .. summary-start Restricts TCP syslog senders by source address or hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: AllowedSender :Scope: module, input :Type: array :Default: module=none, input=module parameter :Required?: no :Introduced: 8.2608.0 Description ----------- Sets source-address ACL entries for TCP syslog inputs. Entries use the same address syntax as the legacy :doc:`../../configuration/input_directives/rsconf1_allowedsender` directive, for example ``127.0.0.1/16``, ``192.0.2.0/24``, ``[::1]/128``, ``*.example.net``, or ``somehost.example.com``. A module-level ``AllowedSender`` list is used as the default for imtcp inputs. An input-level ``AllowedSender`` list replaces the module-level list for that input. If neither the module nor the input configures this parameter, all senders are accepted unless legacy ``$AllowedSender`` directives are present. If ``AllowedSender`` is configured, the array must contain at least one entry. An empty input array cannot be used to clear a module-level default. Configure explicit per-input sender lists, or omit the module-level default if some inputs must remain unrestricted. Do not mix legacy ``$AllowedSender`` and modern ``AllowedSender`` in new configurations. ``AllowedSender`` checks the remote socket address or reverse-DNS hostname. It is separate from :ref:`param-imtcp-permittedpeer`, which checks TLS peer identity and only applies to authenticated TLS modes. Firewall rules remain the preferred first line of defense. Module usage ------------ .. _param-imtcp-module-allowedsender: .. _imtcp.parameter.module.allowedsender-usage: .. code-block:: rsyslog module(load="imtcp" allowedSender=["192.0.2.0/24"]) Input usage ----------- .. _param-imtcp-input-allowedsender: .. _imtcp.parameter.input.allowedsender-usage: .. code-block:: rsyslog input(type="imtcp" port="514" allowedSender=["127.0.0.1/16", "[::1]/128"]) YAML usage ---------- .. code-block:: yaml modules: - load: imtcp allowedSender: ["192.0.2.0/24"] inputs: - type: imtcp port: "514" allowedSender: ["127.0.0.1/16"] See also -------- See also :doc:`../../configuration/modules/imtcp` and :doc:`../../configuration/input_directives/rsconf1_allowedsender`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-mode.rst0000644000000000000000000000013215241075234026205 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.725580541 30 ctime=1787067792.538690468 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-mode.rst0000664000175000017500000000376015241075234025657 0ustar00rgerrger.. _param-imtcp-streamdriver-mode: .. _imtcp.parameter.module.streamdriver-mode: .. _imtcp.parameter.input.streamdriver-mode: StreamDriver.Mode ================= .. index:: single: imtcp; StreamDriver.Mode single: StreamDriver.Mode .. summary-start Sets the driver mode for the selected network stream driver. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.Mode :Scope: module, input :Type: integer :Default: module=0, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the driver mode for the currently selected :doc:`network stream driver <../../concepts/netstrm_drvr>`. is driver specific. For the built-in TCP stream drivers, mode ``0`` is plain TCP and mode ``1`` is TLS. Selecting a TLS-capable driver such as ``ossl``, ``gtls``, or ``mbedtls`` does not activate TLS unless the mode is ``1``. In ``global(compatibility.defaults.secure="strict")``, an omitted mode is promoted to ``1`` when the effective stream driver is TLS-capable, while an explicit mode ``0`` is rejected. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-mode: .. _imtcp.parameter.module.streamdriver-mode-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.mode="...") Input usage ----------- .. _param-imtcp-input-streamdriver-mode: .. _imtcp.parameter.input.streamdriver-mode-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.mode="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverstreamdrivermode: - $InputTCPServerStreamDriverMode — maps to StreamDriver.Mode (status: legacy) .. index:: single: imtcp; $InputTCPServerStreamDriverMode single: $InputTCPServerStreamDriverMode See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-label-name.rst0000644000000000000000000000013115145046112026251 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.510471986 29 ctime=1787067792.28768579 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-label-name.rst0000664000175000017500000000154115145046112025717 0ustar00rgerrger.. _param-impstats-push-label-name: .. _impstats.parameter.module.push-label-name: push.label.name =============== .. index:: single: impstats; push.label.name single: push.label.name .. summary-start Controls whether impstats adds the stats object name as a ``name`` label. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.label.name :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2602.0 Description ----------- When enabled, impstats injects the statsobj name as the ``name`` label unless one is already set via ``push.labels``. Module usage ------------ .. _impstats.parameter.module.push-label-name-usage: .. code-block:: rsyslog module(load="impstats" push.label.name="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-keepalive-interval.rst0000644000000000000000000000013115216464435026661 xustar0030 mtime=1782212893.981265456 29 atime=1787067671.71043843 30 ctime=1787067791.331667975 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-keepalive-interval.rst0000664000175000017500000000175315216464435026334 0ustar00rgerrger.. _param-imbeats-keepalive-interval: .. _imbeats.parameter.input.keepalive-interval: KeepAlive.Interval ================== .. meta:: :description: TCP keepalive interval for imbeats sessions. :keywords: rsyslog, imbeats, keepalive interval .. index:: single: imbeats; KeepAlive.Interval single: KeepAlive.Interval .. summary-start Set the interval between TCP keepalive probes for imbeats sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: KeepAlive.Interval :Scope: input :Type: integer :Default: input=system default :Required?: no :Introduced: 8.2604.0 Description ----------- Set the interval between TCP keepalive probes for imbeats sessions. Input usage ----------- .. _param-imbeats-input-keepalive-interval: .. _imbeats.parameter.input.keepalive-interval-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" keepAlive.interval="10") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-tls-mycert.rst0000644000000000000000000000013215132733117025045 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.819440462 30 ctime=1787067793.018699413 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-tls-mycert.rst0000666000175000017500000000155015132733117024514 0ustar00rgerrger.. _param-omdtls-tls-mycert: .. _omdtls.parameter.input.tls-mycert: tls.mycert ========== .. index:: single: omdtls; tls.mycert single: tls.mycert .. summary-start Specifies the certificate file presented by omdtls during the DTLS handshake. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: tls.mycert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- Specifies the certificate file used by omdtls. This certificate is presented to peers during the DTLS handshake. Input usage ----------- .. _omdtls.parameter.input.tls-mycert-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" tls.myCert="/etc/rsyslog/omdtls.crt") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-pwd.rst0000644000000000000000000000013015132733117025376 xustar0030 mtime=1768666703.916620375 28 atime=1787067672.1004457 30 ctime=1787067793.068700344 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-pwd.rst0000666000175000017500000000151415132733117025047 0ustar00rgerrger.. _param-omelasticsearch-pwd: .. _omelasticsearch.parameter.module.pwd: pwd === .. index:: single: omelasticsearch; pwd single: pwd .. summary-start Password for basic HTTP authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: pwd :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Supplies the password when Elasticsearch requires basic authentication. This parameter cannot be combined with :ref:`param-omelasticsearch-apikey`. Action usage ------------ .. _param-omelasticsearch-action-pwd: .. _omelasticsearch.parameter.action.pwd: .. code-block:: rsyslog action(type="omelasticsearch" pwd="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmpstrucdata-sd_name.lowercase.rst0000644000000000000000000000013115216464435027543 xustar0030 mtime=1782212893.987265553 30 atime=1787067672.968461882 29 ctime=1787067792.89569712 rsyslog-8.2608.0/doc/source/reference/parameters/mmpstrucdata-sd_name.lowercase.rst0000664000175000017500000000227315216464435027214 0ustar00rgerrger.. _param-mmpstrucdata-sd_name.lowercase: .. _mmpstrucdata.parameter.action.sd_name.lowercase: sd_name.lowercase ================= .. index:: single: mmpstrucdata; sd_name.lowercase single: sd_name.lowercase .. summary-start Controls whether structured data element names (SDIDs) are lowercased. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmpstrucdata`. :Name: sd_name.lowercase :Scope: action :Type: boolean :Default: action="on" :Required?: no :Introduced: 8.32.0 Description ----------- Specifies if sd names (SDID) shall be lowercased. If set to "on", this is the case; if "off", then not. The default of "on" is used because that was the traditional mode of operations. It is generally advised to change the parameter to "off" if not otherwise required. Action usage ------------ .. _param-mmpstrucdata-action-sd_name.lowercase: .. _mmpstrucdata.parameter.action.sd_name.lowercase-usage: .. code-block:: rsyslog action(type="mmpstrucdata" sd_name.lowercase="off") YAML usage ---------- .. code-block:: yaml actions: - type: mmpstrucdata sd_name.lowercase: off See also -------- See also :doc:`../../configuration/modules/mmpstrucdata`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsendertrack-statefile.rst0000644000000000000000000000013215132733117026261 xustar0030 mtime=1768666703.923620481 30 atime=1787067673.047463355 30 ctime=1787067793.537709084 rsyslog-8.2608.0/doc/source/reference/parameters/omsendertrack-statefile.rst0000666000175000017500000000247715132733117025741 0ustar00rgerrger.. _param-omsendertrack-statefile: .. _omsendertrack.parameter.input.statefile: statefile ========= .. index:: single: omsendertrack; statefile single: statefile .. summary-start Specifies the absolute path to the JSON file where omsendertrack persists sender statistics. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsendertrack`. :Name: statefile :Scope: input :Type: string :Default: input=none :Required?: yes :Introduced: 8.2506.0 (Proof-of-Concept) Description ----------- This mandatory parameter specifies the **absolute path to the JSON file** where sender information is stored. The module updates this file periodically based on the configured :ref:`interval ` and also upon rsyslog shutdown to preserve the latest statistics. **Important:** Ensure that the rsyslog user has appropriate write permissions to the directory where this ``statefile`` is located. Failure to do so will prevent the module from saving its state. Input usage ----------- .. _omsendertrack.parameter.input.statefile-usage: .. code-block:: rsyslog module(load="omsendertrack") action(type="omsendertrack" senderId="%hostname%" stateFile="/var/lib/rsyslog/senderstats.json") See also -------- See also :doc:`../../configuration/modules/omsendertrack`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-maxlisteners.rst0000644000000000000000000000013215132733117025272 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.086482724 30 ctime=1787067792.491689592 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-maxlisteners.rst0000666000175000017500000000274615132733117024751 0ustar00rgerrger.. _param-imtcp-maxlisteners: .. _imtcp.parameter.module.maxlisteners: .. _imtcp.parameter.input.maxlisteners: MaxListeners ============ .. index:: single: imtcp; MaxListeners single: MaxListeners .. summary-start Sets the maximum number of listener ports supported. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: MaxListeners :Scope: module, input :Type: integer :Default: module=20, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the maximum number of listeners (server ports) supported. This must be set before the first $InputTCPServerRun directive. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-maxlisteners: .. _imtcp.parameter.module.maxlisteners-usage: .. code-block:: rsyslog module(load="imtcp" maxListeners="50") Input usage ----------- .. _param-imtcp-input-maxlisteners: .. _imtcp.parameter.input.maxlisteners-usage: .. code-block:: rsyslog input(type="imtcp" port="514" maxListeners="50") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpmaxlisteners: - $InputTCPMaxListeners — maps to MaxListeners (status: legacy) .. index:: single: imtcp; $InputTCPMaxListeners single: $InputTCPMaxListeners See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-needparse.rst0000644000000000000000000000013215132733117024653 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.496453083 30 ctime=1787067792.091682138 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-needparse.rst0000666000175000017500000000204515132733117024322 0ustar00rgerrger.. _param-imfile-needparse: .. _imfile.parameter.input.needparse: .. _imfile.parameter.needparse: needParse ========= .. index:: single: imfile; needParse single: needParse .. summary-start Forces messages to pass through configured parser modules. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: needParse :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: 8.1903.0 Description ----------- By default, read messages are sent to output modules without passing through parsers. Setting ``needParse`` to ``on`` makes rsyslog apply any defined parser modules to these messages. Input usage ----------- .. _param-imfile-input-needparse: .. _imfile.parameter.input.needparse-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" needParse="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-input.rst0000644000000000000000000000013215132733117026036 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.511453362 30 ctime=1787067792.804695425 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-input.rst0000666000175000017500000000244515132733117025511 0ustar00rgerrger.. _param-mmjsontransform-input: .. _mmjsontransform.parameter.input.input: input ===== .. index:: single: mmjsontransform; input single: input .. summary-start Names the JSON property that provides the object to transform. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: input :Scope: input :Type: string :Default: none :Required?: yes :Introduced: 8.2410.0 Description ----------- Specifies which message property contains the JSON object that will be rewritten. The value must be a property reference that begins with ``$`` (for example ``$!raw`` or ``$.normalized``). ``mmjsontransform`` validates the expression during configuration and rejects other prefixes. If the referenced property is missing at runtime, the action simply returns without altering the message. When the property exists but is not a JSON object, the module reports an error and the action fails, leaving the output property untouched. Input usage ----------- .. _param-mmjsontransform-input-usage: .. _mmjsontransform.parameter.input.input-usage: .. code-block:: rsyslog action(type="mmjsontransform" input="$!raw" output="$!normalized") See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-authmode.rst0000644000000000000000000000013215216464435027406 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.839440835 30 ctime=1787067791.369668683 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-authmode.rst0000664000175000017500000000201715216464435027052 0ustar00rgerrger.. _param-imbeats-streamdriver-authmode: .. _imbeats.parameter.input.streamdriver-authmode: StreamDriver.AuthMode ===================== .. meta:: :description: TLS authentication mode for imbeats. :keywords: rsyslog, imbeats, streamdriver authmode .. index:: single: imbeats; StreamDriver.AuthMode single: StreamDriver.AuthMode .. summary-start Set the TLS authentication mode used by the configured imbeats stream driver. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.AuthMode :Scope: input :Type: string :Default: input=anon :Required?: no :Introduced: 8.2604.0 Description ----------- Set the TLS authentication mode used by the configured imbeats stream driver. Input usage ----------- .. _param-imbeats-input-streamdriver-authmode: .. _imbeats.parameter.input.streamdriver-authmode-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.authMode="anon") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-template.rst0000644000000000000000000000013215145046112025442 xustar0030 mtime=1771326538.959012982 30 atime=1787067671.926442457 30 ctime=1787067793.581709904 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-template.rst0000664000175000017500000000330715145046112025111 0ustar00rgerrger.. _param-omudpspoof-template: .. _omudpspoof.parameter.module.template: .. _omudpspoof.parameter.action.template: template ======== .. index:: single: omudpspoof; template single: template .. summary-start Sets the default template used by omudpspoof actions without an explicitly configured template. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: template :Scope: module, action :Type: word :Default: RSYSLOG_TraditionalForwardFormat :Required?: no :Introduced: 5.1.3 Description ----------- This setting specifies the template for formatting output messages. When set at the module level, it becomes the default for all ``omudpspoof`` actions that do not have an explicit template. When set on a specific action, it overrides the module-level default for that action. Module usage ------------ .. _param-omudpspoof-module-template: .. _omudpspoof.parameter.module.template-usage: .. code-block:: rsyslog module(load="omudpspoof" template="RSYSLOG_TraditionalForwardFormat") Action usage ------------ .. _param-omudpspoof-action-template: .. _omudpspoof.parameter.action.template-usage: .. code-block:: rsyslog action(type="omudpspoof" template="RSYSLOG_TraditionalForwardFormat" target="192.0.2.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspoofdefaulttemplate: - $ActionOMUDPSpoofDefaultTemplate — maps to template (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofDefaultTemplate single: $ActionOMUDPSpoofDefaultTemplate See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-confparam.rst0000644000000000000000000000013215132733117025011 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.971461938 30 ctime=1787067792.218684505 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-confparam.rst0000666000175000017500000000241215132733117024456 0ustar00rgerrger.. _param-imkafka-confparam: .. _imkafka.parameter.input.confparam: confparam ========= .. index:: single: imkafka; confparam single: confparam .. summary-start Passes arbitrary librdkafka configuration parameters to the imkafka consumer. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: confparam :Scope: input :Type: array :Default: input=``none`` :Required?: no :Introduced: 8.27.0 Description ----------- Permits to specify Kafka options. Rather than offering a myriad of config settings to match the Kafka parameters, we provide this setting here as a vehicle to set any Kafka parameter. This has the big advantage that Kafka parameters that come up in new releases can immediately be used. Note that we use librdkafka for the Kafka connection, so the parameters are actually those that librdkafka supports. As of our understanding, this is a superset of the native Kafka parameters. Input usage ----------- .. _imkafka.parameter.input.confparam-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="your-topic" confParam=["queued.min.messages=10000", "socket.timeout.ms=60000"]) See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omuxsock-template.rst0000644000000000000000000000013215216464435025132 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.089445495 30 ctime=1787067793.595710165 rsyslog-8.2608.0/doc/source/reference/parameters/omuxsock-template.rst0000664000175000017500000000244715216464435024605 0ustar00rgerrger.. _param-omuxsock-template: .. _omuxsock.parameter.module.template: .. _omuxsock.parameter.action.template: template ======== .. index:: single: omuxsock; template single: template .. summary-start Sets the template for formatting messages sent to Unix sockets. .. summary-end This parameter applies to :doc:`../../configuration/modules/omuxsock`. :Name: template :Scope: module, action :Type: word :Default: RSYSLOG_TraditionalForwardFormat :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Name of the :doc:`template <../../configuration/templates>` to use to format log messages sent to Unix sockets. When set at module scope, it becomes the default for actions without an explicitly configured template. When set on an action, it overrides the module-level default for that action. Module usage ------------ .. _param-omuxsock-module-template: .. _omuxsock.parameter.module.template-usage: .. code-block:: rsyslog module(load="omuxsock" template="RSYSLOG_TraditionalForwardFormat") Action usage ------------ .. _param-omuxsock-action-template: .. _omuxsock.parameter.action.template-usage: .. code-block:: rsyslog action(type="omuxsock" template="RSYSLOG_TraditionalForwardFormat") See also -------- See also :doc:`../../configuration/modules/omuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfifo-facility.rst0000644000000000000000000000013115216464435024523 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.112445924 29 ctime=1787067792.12668279 rsyslog-8.2608.0/doc/source/reference/parameters/imfifo-facility.rst0000664000175000017500000000214515216464435024172 0ustar00rgerrger.. _param-imfifo-facility: .. _imfifo.parameter.input.facility: facility ======== .. meta:: :description: Syslog facility to apply to messages read from this named pipe (FIFO). :keywords: rsyslog, imfifo, facility .. index:: single: imfifo; facility single: facility .. summary-start Specifies the syslog facility to apply to messages read from this named pipe (FIFO). .. summary-end This parameter applies to :doc:`../../configuration/modules/imfifo`. :Name: facility :Scope: input :Type: facility (word/integer) :Default: local0 :Required?: no :Introduced: 8.2606.0 Description ----------- The syslog facility to be assigned to all messages read from this named pipe. It can be specified in textual form (for example ``local0``) or as a number (for example ``16``). Textual form is recommended. Input usage ----------- .. _param-imfifo-input-facility: .. _imfifo.parameter.input.facility-usage: .. code-block:: rsyslog input(type="imfifo" file="/var/log/myfifo" tag="fifo-logs:" facility="local4") See also -------- See also :doc:`../../configuration/modules/imfifo`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-tls-myprivkey.rst0000644000000000000000000000013215132733117027000 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.732457483 30 ctime=1787067792.860696468 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-tls-myprivkey.rst0000666000175000017500000000221315132733117026444 0ustar00rgerrger.. _param-mmkubernetes-tls-myprivkey: .. _mmkubernetes.parameter.action.tls-myprivkey: tls.myprivkey ============= .. index:: single: mmkubernetes; tls.myprivkey single: tls.myprivkey .. summary-start Specifies the unencrypted private key corresponding to ``tls.mycert``. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: tls.myprivkey :Scope: action :Type: word :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This is the full path and file name of the file containing the private key corresponding to the cert :ref:`param-mmkubernetes-tls-mycert` used for doing client cert auth against Kubernetes. This file is in PEM format, and must be unencrypted, so take care to secure it properly. For example: `/etc/rsyslog.d/k8s-client-key.pem` Action usage ------------ .. _param-mmkubernetes-action-tls-myprivkey: .. _mmkubernetes.parameter.action.tls-myprivkey-usage: .. code-block:: rsyslog action(type="mmkubernetes" tls.myPrivKey="/etc/rsyslog.d/k8s-client-key.pem") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-batch-format.rst0000644000000000000000000000013215132733117025322 xustar0030 mtime=1768666703.916620375 30 atime=1787067673.131464921 30 ctime=1787067793.230703363 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-batch-format.rst0000666000175000017500000000600015132733117024764 0ustar00rgerrger.. _param-omhttp-batch-format: .. _omhttp.parameter.input.batch-format: batch.format ============ .. index:: single: omhttp; batch.format single: batch.format .. summary-start Chooses how omhttp combines multiple messages when batching is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: batch.format :Scope: input :Type: word :Default: input=newline :Required?: no :Introduced: Not specified Description ----------- This parameter specifies how to combine multiple messages into a single batch. Valid options are *newline* (default), *jsonarray*, *kafkarest*, and *lokirest*. Each message on the "Inputs" line is the templated log line that is fed into the omhttp action, and the "Output" line describes the resulting payload sent to the configured HTTP server. 1. *newline* - Concatenates each message into a single string joined by newline (``"\\n"``) characters. This mode is default and places no restrictions on the structure of the input messages. .. code-block:: text Inputs: "message 1" "message 2" "message 3" Output: "message 1\nmessage 2\nmessage 3" 2. *jsonarray* - Builds a JSON array containing all messages in the batch. This mode requires that each message is parsable JSON, since the plugin parses each message as JSON while building the array. .. code-block:: text Inputs: {"msg": "message 1"} {"msg": "message 2"} {"msg": "message 3"} Output: [{"msg": "message 1"}, {"msg": "message 2"}, {"msg": "message 3"}] 3. *kafkarest* - Builds a JSON object that conforms to the `Kafka Rest Proxy specification `_. This mode requires that each message is parsable JSON, since the plugin parses each message as JSON while building the batch object. .. code-block:: text Inputs: {"msg": "message 1"} {"msg": "message 2"} {"msg": "message 3"} Output: {"records": [{"value": {"msg": "message 1"}}, {"value": {"msg": "message 2"}}, {"value": {"msg": "message 3"}}]} 4. *lokirest* - Builds a JSON object that conforms to the `Loki Rest specification `_. This mode requires that each message is parsable JSON, since the plugin parses each message as JSON while building the batch object. Additionally, the operator is responsible for providing index keys, and message values. .. code-block:: text Inputs: {"stream": {"tag1":"value1"}, values:[[ "%timestamp%", "message 1" ]]} {"stream": {"tag2":"value2"}, values:[[ "%timestamp%", "message 2" ]]} Output: {"streams": [{"stream": {"tag1":"value1"}, values:[[ "%timestamp%", "message 1" ]]},{"stream": {"tag2":"value2"}, values:[[ "%timestamp%", "message 2" ]]}]} Input usage ----------- .. _omhttp.parameter.input.batch-format-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" batch="on" batchFormat="jsonarray" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-key.rst0000644000000000000000000000013215132411300023624 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.060463597 30 ctime=1787067793.349705581 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-key.rst0000666000175000017500000000143715132411300023277 0ustar00rgerrger.. _param-omkafka-key: .. _omkafka.parameter.module.key: Key === .. index:: single: omkafka; Key single: Key .. summary-start Key used for partitioning messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Key :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Kafka key to be used for all messages. If a key is provided and ``partitions.auto="on"`` is set, then all messages will be assigned to a partition based on the key. Action usage ------------ .. _param-omkafka-action-key: .. _omkafka.parameter.action.key: .. code-block:: rsyslog action(type="omkafka" Key="mykey") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-annotation-match.rst0000644000000000000000000000013215132733117027405 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.617455338 30 ctime=1787067792.820695723 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-annotation-match.rst0000666000175000017500000000231015132733117027047 0ustar00rgerrger.. _param-mmkubernetes-annotation-match: .. _mmkubernetes.parameter.action.annotation-match: annotation_match ================ .. index:: single: mmkubernetes; annotation_match single: annotation_match .. summary-start Selects pod or namespace annotations whose keys match given patterns. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: annotation_match :Scope: action :Type: array :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- By default no pod or namespace annotations will be added to the messages. This parameter is an array of patterns to match the keys of the `annotations` field in the pod and namespace metadata to include in the `$!kubernetes!annotations` (for pod annotations) or the `$!kubernetes!namespace_annotations` (for namespace annotations) message properties. Example: `["k8s.*master","k8s.*node"]` Action usage ------------ .. _param-mmkubernetes-action-annotation-match: .. _mmkubernetes.parameter.action.annotation-match-usage: .. code-block:: rsyslog action(type="mmkubernetes" annotationMatch="...") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-cacheentryttl.rst0000644000000000000000000000013215132733117027012 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.636455693 30 ctime=1787067792.824695797 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-cacheentryttl.rst0000666000175000017500000000246015132733117026462 0ustar00rgerrger.. _param-mmkubernetes-cacheentryttl: .. _mmkubernetes.parameter.action.cacheentryttl: cacheentryttl ============= .. index:: single: mmkubernetes; cacheentryttl single: cacheentryttl .. summary-start Sets the maximum age of entries in the metadata cache. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: cacheentryttl :Scope: action :Type: integer :Default: 3600 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This parameter allows you to set the maximum age (time-to-live, or ttl) of an entry in the metadata cache. The value is in seconds. The default value is `3600` (one hour). When cache expiration is checked, if a cache entry has a ttl less than or equal to the current time, it will be removed from the cache. This option is only used if :ref:`param-mmkubernetes-cacheexpireinterval` is 0 or greater. This value must be 0 or greater, otherwise, if :ref:`param-mmkubernetes-cacheexpireinterval` is 0 or greater, you will get an error. Action usage ------------ .. _param-mmkubernetes-action-cacheentryttl: .. _mmkubernetes.parameter.action.cacheentryttl-usage: .. code-block:: rsyslog action(type="mmkubernetes" cacheEntryTtl="3600") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-replymaxbytes.rst0000644000000000000000000000013215145046112025657 xustar0030 mtime=1771326538.945012754 30 atime=1787067673.054463485 30 ctime=1787067793.239703531 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-replymaxbytes.rst0000664000175000017500000000207015145046112025322 0ustar00rgerrger.. meta:: :description: Configure the maximum HTTP response size stored by omhttp. :keywords: rsyslog, omhttp, replymaxbytes, http, response size .. _param-omhttp-replymaxbytes: .. _omhttp.parameter.input.replymaxbytes: replymaxbytes ============= .. index:: single: omhttp; replymaxbytes single: replymaxbytes .. summary-start Limits how much HTTP response data omhttp stores per request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: replymaxbytes :Scope: input :Type: Size :Default: input=1048576 (1MB) :Required?: no :Introduced: Not specified Description ----------- ``replymaxbytes`` caps the number of bytes retained from an HTTP response. Set this to bound memory usage when servers return large response bodies. Use ``0`` to disable the limit. Input usage ----------- .. _omhttp.parameter.input.replymaxbytes-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" replyMaxBytes="512k" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-serverinputname.rst0000644000000000000000000000013215216464435026130 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.104445775 30 ctime=1787067791.953679566 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-serverinputname.rst0000664000175000017500000000322315216464435025574 0ustar00rgerrger.. _param-imdiag-serverinputname: .. _imdiag.parameter.module.serverinputname: ServerInputName ================ .. index:: single: imdiag; ServerInputName single: ServerInputName .. summary-start Overrides the ``inputname`` property for the diagnostic TCP listener's own log messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ServerInputName :Scope: module :Type: string :Default: module=imdiag :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the ``inputname`` metadata assigned to log messages originating from the imdiag TCP listener itself (for example, connection warnings). This does **not** affect the ``inputname`` of messages injected via the control channel, which always remains ``imdiag``. This parameter must be configured before using :ref:`ServerRun `. This ensures the listener logs use the desired identifier from startup onward. Module usage ------------ .. _param-imdiag-module-serverinputname: .. _imdiag.parameter.module.serverinputname-usage: .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/var/run/rsyslog/imdiag.port" serverInputName="diag-main" serverRun="19998") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagserverinputname: - $IMDiagServerInputName — maps to ServerInputName (status: legacy) .. index:: single: imdiag; $IMDiagServerInputName single: $IMDiagServerInputName See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-filegroup.rst0000644000000000000000000000013215132733117024730 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.634474298 30 ctime=1787067792.330686592 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-filegroup.rst0000666000175000017500000000160715132733117024402 0ustar00rgerrger.. _param-imptcp-filegroup: .. _imptcp.parameter.input.filegroup: FileGroup ========= .. index:: single: imptcp; FileGroup single: FileGroup .. summary-start Sets the group of the Unix-domain socket by group name. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FileGroup :Scope: input :Type: GID :Default: input=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the group for the domain socket. The parameter is a group name, for which the groupid is obtained by rsyslogd during startup processing. Interim changes to the user mapping are not detected. Input usage ----------- .. _param-imptcp-input-filegroup: .. _imptcp.parameter.input.filegroup-usage: .. code-block:: rsyslog input(type="imptcp" fileGroup="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-topic.rst0000644000000000000000000000013115216464435024167 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.005462572 29 ctime=1787067792.22968471 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-topic.rst0000664000175000017500000000217015216464435023634 0ustar00rgerrger.. _param-imkafka-topic: .. _imkafka.parameter.input.topic: topic ===== .. index:: single: imkafka; topic single: topic .. summary-start Identifies one or more Kafka topics from which imkafka consumes messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: topic :Scope: input :Type: array :Required?: yes :Introduced: 8.27.0 Description ----------- Specifies the Kafka topic or topics to consume from. A single topic name may be given as a string. Multiple topics may be given as an array, allowing one ``input()`` to consume from several topics at once. Input usage ----------- .. _imkafka.parameter.input.topic-usage: Single topic: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="mytopic" broker="localhost:9092" consumergroup="default") Multiple topics: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic=["topic1", "topic2", "topic3"] broker="localhost:9092" consumergroup="default") See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-failonchownfailure.rst0000644000000000000000000000013215132733117026613 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.654474671 30 ctime=1787067792.326686517 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-failonchownfailure.rst0000666000175000017500000000166215132733117026266 0ustar00rgerrger.. _param-imptcp-failonchownfailure: .. _imptcp.parameter.input.failonchownfailure: FailOnChOwnFailure ================== .. index:: single: imptcp; FailOnChOwnFailure single: FailOnChOwnFailure .. summary-start Controls startup failure if changing socket owner, group, or mode fails. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FailOnChOwnFailure :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Rsyslog will not start if this is on and changing the file owner, group, or access permissions fails. Disable this to ignore these errors. Input usage ----------- .. _param-imptcp-input-failonchownfailure: .. _imptcp.parameter.input.failonchownfailure-usage: .. code-block:: rsyslog input(type="imptcp" failOnChOwnFailure="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-flowcontrol.rst0000644000000000000000000000013215132733117025300 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.981480766 30 ctime=1787067792.396687822 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-flowcontrol.rst0000666000175000017500000000345715132733117024757 0ustar00rgerrger.. _param-imrelp-flowcontrol: .. _imrelp.parameter.input.flowcontrol: flowControl =========== .. index:: single: imrelp; flowControl single: flowControl .. summary-start Fine-tunes RELP input flow control behavior between no, light, or full throttling. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: flowControl :Scope: input :Type: string :Default: input=light :Required?: no :Introduced: 8.1911.0 Description ----------- This parameter permits the fine-tuning of the flowControl parameter. Possible values are "no", "light", and "full". With "light" being the default and previously only value. Changing the flow control setting may be useful for some rare applications, this is an advanced setting and should only be changed if you know what you are doing. Most importantly, **rsyslog block incoming data and become unresponsive if you change flowcontrol to "full"**. While this may be a desired effect when intentionally trying to make it most unlikely that rsyslog needs to lose/discard messages, usually this is not what you want. General rule of thumb: **if you do not fully understand what this description here talks about, leave the parameter at default value**. This part of the documentation is intentionally brief, as one needs to have deep understanding of rsyslog to evaluate usage of this parameter. If someone has the insight, the meaning of this parameter is crystal-clear. If not, that someone will most likely make the wrong decision when changing this parameter away from the default value. Input usage ----------- .. _param-imrelp-input-flowcontrol-usage: .. _imrelp.parameter.input.flowcontrol-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" flowControl="light") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-port.rst0000644000000000000000000000013115132733117023537 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.140483731 29 ctime=1787067792.50768989 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-port.rst0000666000175000017500000000221415132733117023205 0ustar00rgerrger.. _param-imtcp-port: .. _imtcp.parameter.input.port: Port ==== .. index:: single: imtcp; Port single: Port .. summary-start Starts a TCP server on the specified port. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: Port :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- Starts a TCP server on the selected port. If port zero is selected, the OS automatically assigns a free port. Use ``listenPortFileName`` to learn which port was assigned. Input usage ----------- .. _param-imtcp-input-port: .. _imtcp.parameter.input.port-usage: .. code-block:: rsyslog input(type="imtcp" port="514") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverrun: - $InputTCPServerRun — maps to Port (status: legacy) .. index:: single: imtcp; $InputTCPServerRun single: $InputTCPServerRun See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-transport.rst0000644000000000000000000000013115132733117025004 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.757439306 29 ctime=1787067793.55570942 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-transport.rst0000666000175000017500000000232015132733117024450 0ustar00rgerrger.. _param-omsnmp-transport: .. _omsnmp.parameter.module.transport: Transport ========= .. index:: single: omsnmp; Transport single: Transport .. summary-start Selects the transport protocol for SNMP communication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Transport :Scope: module :Type: string :Default: module=udp :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- Defines the transport type you wish to use. Technically we can support all transport types which are supported by NET-SNMP. To name a few possible values: udp, tcp, udp6, tcp6, icmp, icmp6 ... Module usage ------------ .. _param-omsnmp-module-transport: .. _omsnmp.parameter.module.transport-usage: .. code-block:: rsyslog action(type="omsnmp" transport="udp") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmptransport: - $actionsnmptransport — maps to Transport (status: legacy) .. index:: single: omsnmp; $actionsnmptransport single: $actionsnmptransport See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-authmode.rst0000644000000000000000000000013215145046112025340 xustar0030 mtime=1771326538.953012884 30 atime=1787067672.691456718 30 ctime=1787067793.503708451 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-authmode.rst0000664000175000017500000000277615145046112025020 0ustar00rgerrger.. _param-omrelp-tls-authmode: .. _omrelp.parameter.input.tls-authmode: TLS.AuthMode ============ .. index:: single: omrelp; TLS.AuthMode single: TLS.AuthMode .. summary-start Chooses the mutual authentication mode (fingerprint or name) for TLS. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.AuthMode :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Sets the mode used for mutual authentication. Supported values are either "*fingerprint*" or "*name*". Fingerprint mode basically is what SSH does. It does not require a full PKI to be present, instead self-signed certs can be used on all peers. Even if a CA certificate is given, the validity of the peer cert is NOT verified against it. Only the certificate fingerprint counts. In "name" mode, certificate validation happens. Here, the matching is done against the certificate's subjectAltName and, as a fallback, the subject common name. If the certificate contains multiple names, a match on any one of these names is considered good and permits the peer to talk to rsyslog. The permitted names or fingerprints are configured via `TLS.PermittedPeer`. Input usage ----------- .. _param-omrelp-input-tls-authmode: .. _omrelp.parameter.input.tls-authmode-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.authMode="fingerprint") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omusrmsg-ratelimit-name.rst0000644000000000000000000000013115171370365026230 xustar0030 mtime=1776677109.119908115 30 atime=1787067672.019444191 29 ctime=1787067793.58470996 rsyslog-8.2608.0/doc/source/reference/parameters/omusrmsg-ratelimit-name.rst0000664000175000017500000000136415171370365025701 0ustar00rgerrger.. index:: ! omusrmsg; RateLimit.Name .. _param-omusrmsg-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple actions to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-action limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-timeoutgranularity.rst0000644000000000000000000000013215132733117026655 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.340450174 30 ctime=1787067792.122682716 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-timeoutgranularity.rst0000666000175000017500000000302315132733117026321 0ustar00rgerrger.. _param-imfile-timeoutgranularity: .. _imfile.parameter.module.timeoutgranularity: .. _imfile.parameter.timeoutgranularity: timeoutGranularity ================== .. index:: single: imfile; timeoutGranularity single: timeoutGranularity .. summary-start Interval in seconds for checking multi-line read timeouts. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: timeoutGranularity :Scope: module :Type: integer :Default: module=1 :Required?: no :Introduced: 8.23.0 Description ----------- Sets the interval in which multi-line-read timeouts are checked. The interval is specified in seconds. This establishes a lower limit on the length of the timeout. For example, if ``timeoutGranularity`` is 60 seconds and a ``readTimeout`` value of 10 seconds is used, the timeout is nevertheless only checked every 60 seconds (if there is no other activity in imfile). This means that the ``readTimeout`` is also only checked every 60 seconds, so a timeout can occur only after 60 seconds. Note that ``timeoutGranularity`` has some performance implication. The more frequently timeout processing is triggered, the more processing time is needed. This effect should be negligible, except if a very large number of files is being monitored. Module usage ------------ .. _param-imfile-module-timeoutgranularity: .. _imfile.parameter.module.timeoutgranularity-usage: .. code-block:: rsyslog module(load="imfile" timeoutGranularity="1") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-escapelf.rst0000644000000000000000000000013215241075234025717 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.995680349 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-escapelf.rst0000664000175000017500000000144015241075234025362 0ustar00rgerrger.. _param-imkubernetes-escapelf: .. _imkubernetes.parameter.module.escapelf: EscapeLF ======== .. index:: single: imkubernetes; EscapeLF single: EscapeLF .. summary-start Escapes embedded line feeds in the submitted message payload; default ``on``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: EscapeLF :Scope: module :Type: binary :Default: ``on`` :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled, line-feed characters in the final message payload are escaped before submission so each rsyslog record remains single-line by default. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" EscapeLF="on") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-filecreatemode.rst0000644000000000000000000000013215132733117025713 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.858459831 30 ctime=1787067793.459707631 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-filecreatemode.rst0000666000175000017500000000220115132733117025354 0ustar00rgerrger.. _param-omprog-filecreatemode: .. _omprog.parameter.action.filecreatemode: fileCreateMode ============== .. index:: single: omprog; fileCreateMode single: fileCreateMode .. summary-start Sets permissions for the output file when it is created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: fileCreateMode :Scope: action :Type: string :Default: action=0600 :Required?: no :Introduced: v8.38.0 Description ----------- Permissions the :ref:`param-omprog-output` file will be created with, in case the file does not exist. The value must be a 4-digit octal number, with the initial digit being zero. Please note that the actual permission depends on the rsyslogd process umask. If in doubt, use ``$umask 0000`` right at the beginning of the configuration file to remove any restrictions. Action usage ------------ .. _param-omprog-action-filecreatemode: .. _omprog.parameter.action.filecreatemode-usage: .. code-block:: rsyslog action(type="omprog" output="/var/log/prog.log" fileCreateMode="0640") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-port.rst0000644000000000000000000000013115132733117025110 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.637474354 30 ctime=1787067792.987698835 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-port.rst0000666000175000017500000000131115132733117024553 0ustar00rgerrger.. _param-omclickhouse-port: .. _omclickhouse.parameter.input.port: port ==== .. index:: single: omclickhouse; port single: port .. summary-start Sets the HTTP port used to connect to the ClickHouse server. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: port :Scope: input :Type: integer :Default: 8123 :Required?: no :Introduced: not specified Description ----------- HTTP port to use to connect to ClickHouse. Input usage ----------- .. _omclickhouse.parameter.input.port-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" port="9000") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-usespecialparser.rst0000644000000000000000000000013215132733117030350 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.798477355 30 ctime=1787067792.664692816 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-usespecialparser.rst0000666000175000017500000000264015132733117030020 0ustar00rgerrger.. _param-imuxsock-syssock-usespecialparser: .. _imuxsock.parameter.module.syssock-usespecialparser: SysSock.UseSpecialParser ======================== .. index:: single: imuxsock; SysSock.UseSpecialParser single: SysSock.UseSpecialParser .. summary-start Uses a specialized parser for the typical system log socket format. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.UseSpecialParser :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.9.0 Description ----------- The equivalent of the ``UseSpecialParser`` input parameter, but for the system socket. If turned on (the default) a special parser is used that parses the format that is usually used on the system log socket (the one :manpage:`syslog(3)` creates). If set to "off", the regular parser chain is used, in which case the format on the log socket can be arbitrary. .. note:: When the special parser is used, rsyslog is able to inject a more precise timestamp into the message (it is obtained from the log socket). If the regular parser chain is used, this is not possible. Module usage ------------ .. _param-imuxsock-module-syssock-usespecialparser: .. _imuxsock.parameter.module.syssock-usespecialparser-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.useSpecialParser="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-tls-myprivkey.rst0000644000000000000000000000013115132733117025600 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.823440536 29 ctime=1787067793.02069945 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-tls-myprivkey.rst0000666000175000017500000000173515132733117025255 0ustar00rgerrger.. _param-omdtls-tls-myprivkey: .. _omdtls.parameter.input.tls-myprivkey: tls.myprivkey ============= .. index:: single: omdtls; tls.myprivkey single: tls.myprivkey .. summary-start Provides the private key that matches ``tls.mycert`` for DTLS authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: tls.myprivkey :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- The private key file corresponding to :ref:`tls.mycert `. This key is used for the cryptographic operations in the DTLS handshake. Input usage ----------- .. _omdtls.parameter.input.tls-myprivkey-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" tls.myCert="/etc/rsyslog/omdtls.crt" tls.myPrivKey="/etc/rsyslog/omdtls.key") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-debugfile.rst0000644000000000000000000000013215241075234025720 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.873696711 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-debugfile.rst0000664000175000017500000000314115241075234025363 0ustar00rgerrger.. _param-mmnormalize-debugfile: .. _mmnormalize.parameter.action.debugfile: .. meta:: :description: Select a dedicated file for mmnormalize liblognorm debug tracing. :keywords: rsyslog, mmnormalize, liblognorm, debug, trace file debugFile ========= .. index:: single: mmnormalize; debugFile single: debugFile .. summary-start Writes per-action liblognorm debug records to an append-only dedicated file. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: debugFile :Scope: action :Type: word :Default: none :Required?: no :Introduced: 8.2608.0 Description ----------- Sets an append-only output file for liblognorm debug records generated by this action. It requires :ref:`param-mmnormalize-debug` to be enabled. rsyslog opens the file while loading the configuration and fails configuration processing if the file cannot be opened. The file path is administrator-controlled configuration. Select a path whose directory and permissions are appropriate for the rsyslog service account. Action usage ------------ .. _param-mmnormalize-action-debugfile: .. _mmnormalize.parameter.action.debugfile-usage: .. code-block:: rsyslog action(type="mmnormalize" rulebase="/path/to/rules.rb" debug="on" debugFile="/path/to/mmnormalize-debug.log") YAML usage ---------- .. code-block:: yaml actions: - type: mmnormalize rulebase: /path/to/rules.rb debug: on debugFile: /path/to/mmnormalize-debug.log See also -------- See also :doc:`../../configuration/modules/mmnormalize` and :ref:`param-mmnormalize-debug`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-permit-squarebracketsinhostnam0000644000000000000000000000013215132411300030477 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.297449373 30 ctime=1787067793.619710612 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-permit-squarebracketsinhostname.rst0000666000175000017500000000226415132411300031125 0ustar00rgerrger.. _param-pmrfc3164-permit-squarebracketsinhostname: .. _pmrfc3164.parameter.module.permit-squarebracketsinhostname: .. _pmrfc3164.parameter.module.permit.squareBracketsInHostname: permit.squareBracketsInHostname ================================ .. index:: single: pmrfc3164; permit.squareBracketsInHostname single: permit.squareBracketsInHostname .. summary-start Accept hostnames enclosed in ``[]``. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: permit.squareBracketsInHostname :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This option allows hostnames wrapped in square brackets to be parsed without the brackets. Module usage ------------ .. _param-pmrfc3164-module-permit-squarebracketsinhostname: .. _pmrfc3164.parameter.module.permit-squarebracketsinhostname-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" permit.squareBracketsInHostname="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-dynrestpath.rst0000644000000000000000000000013115132733117025317 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.200466207 30 ctime=1787067793.248703699 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-dynrestpath.rst0000666000175000017500000000215215132733117024766 0ustar00rgerrger.. _param-omhttp-dynrestpath: .. _omhttp.parameter.input.dynrestpath: dynrestpath =========== .. index:: single: omhttp; dynrestpath single: dynrestpath .. summary-start Enables using a template name in :ref:`param-omhttp-restpath` so each message can select a REST path dynamically. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: dynrestpath :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- When this parameter is set to ``on`` you can specify a template name in the :ref:`param-omhttp-restpath` parameter instead of the actual path. This way you can use dynamic REST paths for your messages based on the template you are using. Input usage ----------- .. _omhttp.parameter.input.dynrestpath-usage: .. code-block:: rsyslog template(name="tpl_dynamic_path" type="string" string="tenant/%hostname%/events") module(load="omhttp") action( type="omhttp" dynRestPath="on" restPath="tpl_dynamic_path" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-batch-maxbytes.rst0000644000000000000000000000013215145046112027170 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.513472042 30 ctime=1787067792.278685623 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-batch-maxbytes.rst0000664000175000017500000000164315145046112026640 0ustar00rgerrger.. _param-impstats-push-batch-maxbytes: .. _impstats.parameter.module.push-batch-maxbytes: push.batch.maxBytes =================== .. index:: single: impstats; push.batch.maxBytes single: push.batch.maxBytes .. summary-start Sets an approximate maximum protobuf size per Remote Write request. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.batch.maxBytes :Scope: module :Type: integer (bytes) :Default: module=0 :Required?: no :Introduced: 8.2602.0 Description ----------- When set, impstats estimates the protobuf payload size and splits requests into smaller batches. This is a best-effort limit, not a strict cap. Module usage ------------ .. _impstats.parameter.module.push-batch-maxbytes-usage: .. code-block:: rsyslog module(load="impstats" push.batch.maxBytes="500000") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-facility.rst0000644000000000000000000000013215132733117025110 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.447470812 30 ctime=1787067792.264685362 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-facility.rst0000666000175000017500000000150215132733117024554 0ustar00rgerrger.. _param-impstats-facility: .. _impstats.parameter.module.facility: facility ======== .. index:: single: impstats; facility single: facility .. summary-start Selects the numeric syslog facility value used for generated statistics messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: facility :Scope: module :Type: integer :Default: module=5 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The numerical syslog facility code to be used for generated messages. Default is 5 (syslog). This is useful for filtering messages. Module usage ------------ .. _impstats.parameter.module.facility-usage: .. code-block:: rsyslog module(load="impstats" facility="16") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omjournal-namespace.rst0000644000000000000000000000013215132733117025402 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.758457967 30 ctime=1787067793.322705078 rsyslog-8.2608.0/doc/source/reference/parameters/omjournal-namespace.rst0000666000175000017500000000277115132733117025057 0ustar00rgerrger.. _param-omjournal-namespace: .. _omjournal.parameter.input.namespace: namespace ========= .. index:: single: omjournal; namespace single: namespace .. summary-start Writes journal entries to a specific systemd journal namespace instead of the default target. .. summary-end This parameter applies to :doc:`../../configuration/modules/omjournal`. :Name: namespace :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.2406.0 (requires systemd v256+) Description ----------- Starting from systemd v256, the journal supports namespaces. This allows you to write to a specific namespace in the journal, which can be useful for isolating logs from different applications or components. However, this feature has important limitations: * This parameter is mutually exclusive with the ``template`` parameter. If both are specified for the same action, the action fails with an error. * Namespaces must be created before use. If a namespace does not exist, the action fails and logs an error. Create namespaces by adding directories under ``/var/log/journal/``. For more information, see the `systemd-journald.service(8) `_ man page. Input usage ----------- .. _param-omjournal-input-namespace: .. _omjournal.parameter.input.namespace-usage: .. code-block:: shell action(type="omjournal" namespace="audit-journal-namespace") See also -------- See also :doc:`../../configuration/modules/omjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdblookup-key.rst0000644000000000000000000000013215132733117024401 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.180447192 30 ctime=1787067792.762694642 rsyslog-8.2608.0/doc/source/reference/parameters/mmdblookup-key.rst0000666000175000017500000000166315132733117024055 0ustar00rgerrger.. _param-mmdblookup-key: .. _mmdblookup.parameter.input.key: key === .. index:: single: mmdblookup; key single: key .. summary-start Identifies the message field that supplies the IP address to look up. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdblookup`. :Name: key :Scope: input :Type: string (word) :Default: none :Required?: yes :Introduced: 8.24.0 Description ----------- This parameter specifies the name of the field in the message that contains the IP address to be looked up. This is typically a JSON property obtained from a parsed message or structured log. Input usage ----------- .. _mmdblookup.parameter.input.key-usage: .. code-block:: rsyslog action(type="mmdblookup" key="!clientip" mmdbFile="/etc/rsyslog.d/GeoLite2-City.mmdb" fields=["!continent!code", "!location"]) See also -------- See also :doc:`../../configuration/modules/mmdblookup`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-keepalive-probes.rst0000644000000000000000000000013215132733117026011 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.046481978 30 ctime=1787067792.480689387 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-keepalive-probes.rst0000666000175000017500000000342215132733117025460 0ustar00rgerrger.. _param-imtcp-keepalive-probes: .. _imtcp.parameter.module.keepalive-probes: .. _imtcp.parameter.input.keepalive-probes: KeepAlive.Probes ================ .. index:: single: imtcp; KeepAlive.Probes single: KeepAlive.Probes .. summary-start Defines how many unacknowledged probes are sent before a connection is considered dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: KeepAlive.Probes :Scope: module, input :Type: integer :Default: module=0, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The number of unacknowledged probes to send before considering the connection dead and notifying the application layer. The default, 0, means that the operating system defaults are used. This has only effect if keep-alive is enabled. The functionality may not be available on all platforms. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-keepalive-probes: .. _imtcp.parameter.module.keepalive-probes-usage: .. code-block:: rsyslog module(load="imtcp" keepAlive.probes="...") Input usage ----------- .. _param-imtcp-input-keepalive-probes: .. _imtcp.parameter.input.keepalive-probes-usage: .. code-block:: rsyslog input(type="imtcp" port="514" keepAlive.probes="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverkeepalive_probes: - $InputTCPServerKeepAlive_probes — maps to KeepAlive.Probes (status: legacy) .. index:: single: imtcp; $InputTCPServerKeepAlive_probes single: $InputTCPServerKeepAlive_probes See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmtaghostname-forcelocalhostname.rst0000644000000000000000000000013115132733117030153 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.276467624 30 ctime=1787067792.908697363 rsyslog-8.2608.0/doc/source/reference/parameters/mmtaghostname-forcelocalhostname.rst0000666000175000017500000000255215132733117027626 0ustar00rgerrger.. _param-mmtaghostname-forcelocalhostname: .. _mmtaghostname.parameter.input.forcelocalhostname: forceLocalHostname ================== .. index:: single: mmtaghostname; forceLocalHostname single: forceLocalHostname .. summary-start Forces the message ``HOSTNAME`` to the rsyslog ``localHostName`` value. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmtaghostname`. :Name: forceLocalHostname :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: at least 7.0, possibly earlier Description ----------- When enabled, this parameter forces the message's ``HOSTNAME`` field to the rsyslog value ``localHostName``. This is useful for setting a consistent hostname on messages that may not have one, e.g. those received via ``imudp`` or ``imtcp``. A common use case is with applications in auto-scaling environments (e.g. AWS), where instances may have ephemeral hostnames. Forcing the hostname to the rsyslog host's name can provide more meaningful and consistent hostnames in logs. Input usage ----------- .. _mmtaghostname.parameter.input.forcelocalhostname-usage: .. code-block:: rsyslog action(type="mmtaghostname" forceLocalHostname="on") Notes ----- - Legacy documentation referred to the type as ``Binary``; it is treated as boolean. See also -------- * :doc:`../../configuration/modules/mmtaghostname` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-ratelimit-burst.rst0000644000000000000000000000013215132411300026552 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.850459682 30 ctime=1787067792.193684039 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-ratelimit-burst.rst0000666000175000017500000000243415132411300026223 0ustar00rgerrger.. _param-imjournal-ratelimit-burst: .. _imjournal.parameter.module.ratelimit-burst: .. meta:: :tag: module:imjournal :tag: parameter:Ratelimit.Burst Ratelimit.Burst =============== .. index:: single: imjournal; Ratelimit.Burst single: Ratelimit.Burst .. summary-start Maximum messages accepted within each rate-limit window. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: Ratelimit.Burst :Scope: module :Type: integer :Default: module=20000 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies how many messages are permitted during each ``Ratelimit.Interval`` period. Messages beyond this threshold are discarded until the interval expires. Module usage ------------ .. _param-imjournal-module-ratelimit-burst: .. _imjournal.parameter.module.ratelimit-burst-usage: .. code-block:: rsyslog module(load="imjournal" Ratelimit.Burst="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournalratelimitburst: - $imjournalRatelimitBurst — maps to Ratelimit.Burst (status: legacy) .. index:: single: imjournal; $imjournalRatelimitBurst single: $imjournalRatelimitBurst See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-keyfile.rst0000644000000000000000000000013115132733117026710 xustar0030 mtime=1768666703.909620269 29 atime=1787067673.96448045 30 ctime=1787067792.536690431 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-keyfile.rst0000666000175000017500000000203015132733117026352 0ustar00rgerrger.. _param-imtcp-streamdriver-keyfile: .. _imtcp.parameter.input.streamdriver-keyfile: streamDriver.KeyFile ==================== .. index:: single: imtcp; streamDriver.KeyFile single: streamDriver.KeyFile .. summary-start Overrides ``DefaultNetstreamDriverKeyFile`` for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: streamDriver.KeyFile :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=global parameter :Required?: no :Introduced: 8.2108.0 Description ----------- .. versionadded:: 8.2108.0 This permits to override the ``DefaultNetstreamDriverKeyFile`` global parameter on the ``input()`` level. For further details, see the global parameter. Input usage ----------- .. _param-imtcp-input-streamdriver-keyfile: .. _imtcp.parameter.input.streamdriver-keyfile-usage: .. code-block:: rsyslog input(type="imtcp" streamDriver.keyFile="/etc/ssl/private/key.pem") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-threads.rst0000644000000000000000000000013215132733117024210 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.835478045 30 ctime=1787067792.597691567 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-threads.rst0000666000175000017500000000220015132733117023650 0ustar00rgerrger.. _param-imudp-threads: .. _imudp.parameter.module.threads: Threads ======= .. index:: single: imudp; Threads single: Threads .. summary-start Number of worker threads receiving data; upper limit 32. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Threads :Scope: module :Type: integer :Default: module=1 :Required?: no :Introduced: 7.5.5 Description ----------- Number of worker threads to process incoming messages. These threads are utilized to pull data off the network. On a busy system, additional threads (but not more than there are CPUs/Cores) can help improving performance and avoiding message loss. Note that with too many threads, performance can suffer. There is a hard upper limit on the number of threads that can be defined. Currently, this limit is set to 32. It may increase in the future when massive multicore processors become available. Module usage ------------ .. _param-imudp-module-threads: .. _imudp.parameter.module.threads-usage: .. code-block:: rsyslog module(load="imudp" Threads="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-severity.rst0000644000000000000000000000013215132733117024557 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.390451107 30 ctime=1787067792.108682455 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-severity.rst0000666000175000017500000000255615132733117024235 0ustar00rgerrger.. _param-imfile-severity: .. _imfile.parameter.input.severity: .. _imfile.parameter.severity: Severity ======== .. index:: single: imfile; Severity single: Severity .. summary-start Sets the syslog severity for lines read from the file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: Severity :Scope: input :Type: word :Default: notice :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The syslog severity to be assigned to lines read. It can be specified in textual form (for example ``info`` or ``warning``) or as a number (for example ``6`` for ``info``). Textual form is recommended. Input usage ----------- .. _param-imfile-input-severity: .. _imfile.parameter.input.severity-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" Severity="notice") Notes ----- - See https://en.wikipedia.org/wiki/Syslog for severity numbers. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfileseverity: - ``$InputFileSeverity`` — maps to Severity (status: legacy) .. index:: single: imfile; $InputFileSeverity single: $InputFileSeverity See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-gnutlsprioritystring.rst0000644000000000000000000000013215216464435027440 xustar0030 mtime=1782212893.981265456 30 atime=1787067671.733438859 30 ctime=1787067791.324667845 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-gnutlsprioritystring.rst0000664000175000017500000000201615216464435027103 0ustar00rgerrger.. _param-imbeats-gnutlsprioritystring: .. _imbeats.parameter.input.gnutlsprioritystring: gnutlsPriorityString ==================== .. meta:: :description: GnuTLS priority string for imbeats TLS sessions. :keywords: rsyslog, imbeats, gnutlsprioritystring .. index:: single: imbeats; gnutlsPriorityString single: gnutlsPriorityString .. summary-start Override the GnuTLS priority string used by the selected TLS stream driver. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: gnutlsPriorityString :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Override the GnuTLS priority string used by the selected TLS stream driver. Input usage ----------- .. _param-imbeats-input-gnutlsprioritystring: .. _imbeats.parameter.input.gnutlsprioritystring-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" gnutlsPriorityString="NORMAL") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-address.rst0000644000000000000000000000013215132733117024201 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.149483898 30 ctime=1787067792.450688828 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-address.rst0000666000175000017500000000151015132733117023644 0ustar00rgerrger.. _param-imtcp-address: .. _imtcp.parameter.input.address: Address ======= .. index:: single: imtcp; Address single: Address .. summary-start Local address that the listener binds to; ``*`` uses all interfaces. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: Address :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- On multi-homed machines, specifies to which local address the listener should be bound. Input usage ----------- .. _param-imtcp-input-address: .. _imtcp.parameter.input.address-usage: .. code-block:: rsyslog input(type="imtcp" address="127.0.0.1" port="514") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-trapoid.rst0000644000000000000000000000013115132733117024412 xustar0030 mtime=1768666703.923620481 29 atime=1787067671.76943953 30 ctime=1787067793.557709457 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-trapoid.rst0000666000175000017500000000333115132733117024061 0ustar00rgerrger.. _param-omsnmp-trapoid: .. _omsnmp.parameter.module.trapoid: TrapOID ======= .. index:: single: omsnmp; TrapOID single: TrapOID .. summary-start Defines the notification OID used for SNMPv2 traps. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: TrapOID :Scope: module :Type: string :Default: module=1.3.6.1.4.1.19406.1.2.1 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- The default value means "ADISCON-MONITORWARE-MIB::syslogtrap". This configuration parameter is used for **SNMPv2** only. This is the OID which defines the trap-type, or notification-type rsyslog uses to send the trap. In order to decode this OID, you will need to have the ADISCON-MONITORWARE-MIB and ADISCON-MIB mibs installed on the receiver side. Downloads of these mib files can be found here: `https://www.adiscon.org/download/ADISCON-MIB.txt `_ `https://www.adiscon.org/download/ADISCON-MONITORWARE-MIB.txt `_ Thanks to the net-snmp mailinglist for the help and the recommendations ;). Module usage ------------ .. _param-omsnmp-module-trapoid: .. _omsnmp.parameter.module.trapoid-usage: .. code-block:: rsyslog action(type="omsnmp" trapOID="1.3.6.1.4.1.19406.1.2.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmptrapoid: - $actionsnmptrapoid — maps to TrapOID (status: legacy) .. index:: single: omsnmp; $actionsnmptrapoid single: $actionsnmptrapoid See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-flowcontrol.rst0000644000000000000000000000013215132733117027346 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.243485651 30 ctime=1787067792.635692275 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-flowcontrol.rst0000666000175000017500000000232015132733117027011 0ustar00rgerrger.. _param-imuxsock-syssock-flowcontrol: .. _imuxsock.parameter.module.syssock-flowcontrol: SysSock.FlowControl =================== .. index:: single: imuxsock; SysSock.FlowControl single: SysSock.FlowControl .. summary-start Applies flow control to the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.FlowControl :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies if flow control should be applied to the system log socket. Module usage ------------ .. _param-imuxsock-module-syssock-flowcontrol: .. _imuxsock.parameter.module.syssock-flowcontrol-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.flowControl="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogflowcontrol: - $SystemLogFlowControl — maps to SysSock.FlowControl (status: legacy) .. index:: single: imuxsock; $SystemLogFlowControl single: $SystemLogFlowControl See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-fileownernum.rst0000644000000000000000000000013215132733117025446 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.631474242 30 ctime=1787067792.337686722 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-fileownernum.rst0000666000175000017500000000170315132733117025115 0ustar00rgerrger.. _param-imptcp-fileownernum: .. _imptcp.parameter.input.fileownernum: FileOwnerNum ============ .. index:: single: imptcp; FileOwnerNum single: FileOwnerNum .. summary-start Sets the owner of the Unix-domain socket by numeric UID. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FileOwnerNum :Scope: input :Type: integer :Default: input=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the file owner for the domain socket. The parameter is a numerical ID, which is used regardless of whether the user actually exists. This can be useful if the user mapping is not available to rsyslog during startup. Input usage ----------- .. _param-imptcp-input-fileownernum: .. _imptcp.parameter.input.fileownernum-usage: .. code-block:: rsyslog input(type="imptcp" fileOwnerNum="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-responsetimeout.rst0000644000000000000000000000013215216464435027070 xustar0030 mtime=1782212893.986265537 30 atime=1787067672.290449242 30 ctime=1787067792.780694978 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-responsetimeout.rst0000664000175000017500000000265315216464435026542 0ustar00rgerrger.. _param-mmexternal-responsetimeout: .. _mmexternal.parameter.input.responsetimeout: responseTimeout =============== .. index:: single: mmexternal; responseTimeout single: responseTimeout .. summary-start Bounds how long mmexternal waits for a JSON response from the external plugin. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: responseTimeout :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: 8.2606.0 Description ----------- This parameter sets the maximum time, in milliseconds, that ``mmexternal`` waits for the external program to return a complete JSON response line. The default value ``0`` keeps the historical behavior and waits without a module-level timeout. When the timeout expires, ``mmexternal`` logs a warning, terminates and restarts the external program, and continues processing. The current message is not retried through the timed-out helper. The timeout applies only when :ref:`param-mmexternal-interface-output` is ``"json"``. It has no effect when ``interface.output="none"``. Input usage ----------- .. _param-mmexternal-input-responsetimeout: .. _mmexternal.parameter.input.responsetimeout-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/mmexternal.py" responseTimeout="500" ) See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ratelimit-name.rst0000644000000000000000000000013215171370365026217 xustar0030 mtime=1776677109.117908084 30 atime=1787067674.126483469 30 ctime=1787067792.624692071 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ratelimit-name.rst0000664000175000017500000000140415171370365025662 0ustar00rgerrger.. index:: ! imuxsock; RateLimit.Name .. _param-imuxsock-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use for this socket. This allows multiple sockets to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-socket limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-indextimeout.rst0000644000000000000000000000013115132411300027306 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.061444974 29 ctime=1787067793.05770014 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-indextimeout.rst0000666000175000017500000000153515132411300026761 0ustar00rgerrger.. _param-omelasticsearch-indextimeout: .. _omelasticsearch.parameter.module.indextimeout: indexTimeout ============ .. index:: single: omelasticsearch; indexTimeout single: indexTimeout .. summary-start Milliseconds to wait for an indexing request to complete. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: indexTimeout :Scope: action :Type: integer :Default: action=0 :Required?: no :Introduced: 8.2204.0 Description ----------- Sets the client-side timeout for a log indexing request. `0` means no timeout. Action usage ------------ .. _param-omelasticsearch-action-indextimeout: .. _omelasticsearch.parameter.action.indextimeout: .. code-block:: rsyslog action(type="omelasticsearch" indexTimeout="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfifo-ruleset.rst0000644000000000000000000000013215216464435024403 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.149446614 30 ctime=1787067792.131682883 rsyslog-8.2608.0/doc/source/reference/parameters/imfifo-ruleset.rst0000664000175000017500000000204415216464435024047 0ustar00rgerrger.. _param-imfifo-ruleset: .. _imfifo.parameter.input.ruleset: ruleset ======= .. meta:: :description: Bind the imfifo input instance to a specific ruleset. :keywords: rsyslog, imfifo, ruleset .. index:: single: imfifo; ruleset single: ruleset .. summary-start Binds this imfifo input instance to a specific ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfifo`. :Name: ruleset :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: no :Introduced: 8.2606.0 Description ----------- Binds the input instance to a specific ruleset. If specified, messages read from this FIFO will be processed by the ruleset instead of the default ruleset. Input usage ----------- .. _param-imfifo-input-ruleset: .. _imfifo.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imfifo" file="/var/log/myfifo" tag="fifo-logs:" ruleset="my_custom_ruleset") See also -------- See also :doc:`../../configuration/modules/imfifo`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-discardtruncatedmsg.rst0000644000000000000000000000013215132733117026737 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.372450771 30 ctime=1787067792.055681467 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-discardtruncatedmsg.rst0000666000175000017500000000226615132733117026413 0ustar00rgerrger.. _param-imfile-discardtruncatedmsg: .. _imfile.parameter.input.discardtruncatedmsg: .. _imfile.parameter.discardtruncatedmsg: discardTruncatedMsg =================== .. index:: single: imfile; discardTruncatedMsg single: discardTruncatedMsg .. summary-start Discards the truncated part of an overlong message instead of processing it. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: discardTruncatedMsg :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When messages are too long they are truncated and the remaining part is processed as a new message. If ``discardTruncatedMsg`` is ``on``, the truncated part is discarded instead. Input usage ----------- .. _param-imfile-input-discardtruncatedmsg: .. _imfile.parameter.input.discardtruncatedmsg-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" discardTruncatedMsg="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-userawmsg.rst0000644000000000000000000000013215132733117026013 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.375450827 30 ctime=1787067792.798695313 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-userawmsg.rst0000666000175000017500000000173015132733117025462 0ustar00rgerrger.. _param-mmjsonparse-userawmsg: .. _mmjsonparse.parameter.input.userawmsg: useRawMsg ========= .. index:: single: mmjsonparse; useRawMsg single: useRawMsg single: mmjsonparse; userawmsg single: userawmsg .. summary-start Controls whether parsing operates on the raw message or only the MSG part. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: useRawMsg :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: 6.6.0 Description ----------- Specifies if the raw message should be used for parsing (``on``) or just the MSG part of the message (``off``). Notes ----- - Older documentation referred to this boolean setting as ``binary``. Input usage ----------- .. _mmjsonparse.parameter.input.userawmsg-usage: .. code-block:: rsyslog action(type="mmjsonparse" useRawMsg="on") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-pwd.rst0000644000000000000000000000013115145046112023726 xustar0029 mtime=1771326538.94601277 30 atime=1787067673.118464678 30 ctime=1787067793.416706829 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-pwd.rst0000664000175000017500000000156315145046112023400 0ustar00rgerrger.. _param-ommysql-pwd: .. _ommysql.parameter.input.pwd: PWD === .. index:: single: ommysql; PWD single: PWD .. summary-start Specifies the password for the MariaDB/MySQL user defined in :ref:`param-ommysql-uid`. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: pwd :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 7.x, possibly earlier Description ----------- This is the password for the user account specified in the :ref:`param-ommysql-uid` parameter, used to authenticate with the MariaDB/MySQL server. Input usage ----------- .. _ommysql.parameter.input.pwd-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" db="syslog_db" uid="user" pwd="pwd") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-retry-ruleset.rst0000644000000000000000000000013115132733117025600 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.169465629 30 ctime=1787067793.293704537 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-retry-ruleset.rst0000666000175000017500000000513715132733117025255 0ustar00rgerrger.. _param-omhttp-retry-ruleset: .. _omhttp.parameter.input.retry-ruleset: retry.ruleset ============= .. index:: single: omhttp; retry.ruleset single: retry.ruleset .. summary-start Names the ruleset where omhttp requeues failed messages when :ref:`param-omhttp-retry` is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: retry.ruleset :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- This parameter specifies the ruleset where this plugin should requeue failed messages if :ref:`param-omhttp-retry` is on. This ruleset generally would contain another omhttp action instance. **Important** - Note that the message that is queued on the retry ruleset is the templated output of the initial omhttp action. This means that no further templating should be done to messages inside this ruleset, unless retries should be templated differently than first-tries. An "echo template" does the trick here. .. code-block:: text template(name="tpl_echo" type="string" string="%msg%") This retry ruleset can recursively call itself as its own ``retry.ruleset`` to retry forever, but there is no timeout behavior currently implemented. Alternatively, the omhttp action in the retry ruleset could be configured to support ``action.resumeRetryCount`` as explained above in the :ref:`param-omhttp-retry` section. The benefit of this approach is that retried messages still hit the server in a batch format (though with a single message in it), and the ability to configure rsyslog to give up after some number of resume attempts so as to avoid resource exhaustion. Or, if some data loss or high latency is acceptable, do not configure retries with the retry ruleset itself. A single retry from the original ruleset might catch most failures, and errors from the retry ruleset could still be logged using the :ref:`param-omhttp-errorfile` parameter and sent later on via some other process. Input usage ----------- .. _omhttp.parameter.input.retry-ruleset-usage: .. code-block:: rsyslog module(load="omhttp") # This action enables the retry ruleset. action( type="omhttp" template="tpl_omhttp_json" retry="on" retryRuleSet="rs_omhttp_retry" ) # The "rs_omhttp_retry" ruleset itself could be defined as follows: ruleset(name="rs_omhttp_retry") { action( type="omhttp" template="tpl_echo" batch="on" batchFormat="jsonarray" batchMaxSize="5" ) } See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-device.rst0000644000000000000000000000013215132733117024015 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.235485501 30 ctime=1787067792.566690989 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-device.rst0000666000175000017500000000174515132733117023472 0ustar00rgerrger.. _param-imudp-device: .. _imudp.parameter.input.device: Device ====== .. index:: single: imudp; Device single: Device .. summary-start Binds UDP socket to a specific network device or VRF. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Device :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Bind socket to given device (e.g., ``eth0``). For Linux with VRF support, the ``Device`` option can be used to specify the VRF for the ``Address``. Examples: .. code-block:: rsyslog module(load="imudp") # needs to be done just once input(type="imudp" port="514" device="eth0") Input usage ----------- .. _param-imudp-input-device: .. _imudp.parameter.input.device-usage: .. code-block:: rsyslog input(type="imudp" Device="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-prioritizesan.rst0000644000000000000000000000013115216464435030501 xustar0030 mtime=1782212893.984265505 29 atime=1787067671.89444186 30 ctime=1787067791.389669056 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-prioritizesan.rst0000664000175000017500000000213515216464435030147 0ustar00rgerrger.. _param-imbeats-streamdriver-prioritizesan: .. _imbeats.parameter.input.streamdriver-prioritizesan: StreamDriver.PrioritizeSAN ========================== .. meta:: :description: SAN preference for imbeats TLS name validation. :keywords: rsyslog, imbeats, prioritize SAN .. index:: single: imbeats; StreamDriver.PrioritizeSAN single: StreamDriver.PrioritizeSAN .. summary-start Prefer subject alternative names over common names when validating imbeats TLS peer names. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.PrioritizeSAN :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2604.0 Description ----------- Prefer subject alternative names over common names when validating imbeats TLS peer names. Input usage ----------- .. _param-imbeats-input-streamdriver-prioritizesan: .. _imbeats.parameter.input.streamdriver-prioritizesan-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.prioritizeSAN="on") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-closetimeout.rst0000644000000000000000000000013215132411300025412 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.478452747 30 ctime=1787067793.134701574 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-closetimeout.rst0000666000175000017500000000176215132411300025066 0ustar00rgerrger.. _param-omfile-closetimeout: .. _omfile.parameter.module.closetimeout: closeTimeout ============ .. index:: single: omfile; closeTimeout single: closeTimeout .. summary-start Specifies after how many minutes of inactivity a file is automatically closed. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: closeTimeout :Scope: action :Type: integer :Default: action=File: 0 DynaFile: 10 :Required?: no :Introduced: 8.3.3 Description ----------- Specifies after how many minutes of inactivity a file is automatically closed. Note that this functionality is implemented based on the :doc:`janitor process <../../concepts/janitor>`. See its doc to understand why and how janitor-based times are approximate. Action usage ------------ .. _param-omfile-action-closetimeout: .. _omfile.parameter.action.closetimeout: .. code-block:: rsyslog action(type="omfile" closeTimeout="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-compression.rst0000644000000000000000000000013215132733117026071 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.903479313 30 ctime=1787067792.428688418 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-compression.rst0000666000175000017500000000174115132733117025542 0ustar00rgerrger.. _param-imrelp-tls-compression: .. _imrelp.parameter.input.tls-compression: tls.compression =============== .. index:: single: imrelp; tls.compression single: tls.compression .. summary-start Controls whether TLS sessions compress payload data before transmission. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.compression :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not documented Description ----------- This controls if the TLS stream should be compressed (zipped). While this increases CPU use, the network bandwidth should be reduced. Note that typical text-based log records usually compress rather well. Input usage ----------- .. _param-imrelp-input-tls-compression-usage: .. _imrelp.parameter.input.tls-compression-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.compression="on") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-server.rst0000644000000000000000000000013215132733117024257 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.746439101 30 ctime=1787067793.548709289 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-server.rst0000666000175000017500000000220215132733117023721 0ustar00rgerrger.. _param-omsnmp-server: .. _omsnmp.parameter.module.server: Server ====== .. index:: single: omsnmp; Server single: Server .. summary-start Defines the SNMP target host by hostname or IP address. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Server :Scope: module :Type: string :Default: module=none :Required?: yes :Introduced: at least 7.3.0, possibly earlier Description ----------- This can be a hostname or ip address, and is our snmp target host. This parameter is required, if the snmptarget is not defined, nothing will be send. Module usage ------------ .. _param-omsnmp-module-server: .. _omsnmp.parameter.module.server-usage: .. code-block:: rsyslog action(type="omsnmp" server="192.0.2.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmptarget: - $actionsnmptarget — maps to Server (status: legacy) .. index:: single: omsnmp; $actionsnmptarget single: $actionsnmptarget See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-tls-insecureskipverify.rst0000644000000000000000000000013215145046112031006 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.537472489 30 ctime=1787067792.301686051 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-tls-insecureskipverify.rst0000664000175000017500000000170115145046112030451 0ustar00rgerrger.. _param-impstats-push-tls-insecureskipverify: .. _impstats.parameter.module.push-tls-insecureskipverify: push.tls.insecureSkipVerify =========================== .. index:: single: impstats; push.tls.insecureSkipVerify single: push.tls.insecureSkipVerify .. summary-start Disables TLS certificate verification for Remote Write (testing only). .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.tls.insecureSkipVerify :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2602.0 Description ----------- When enabled, TLS peer and host verification are disabled. This should only be used in testing environments. Module usage ------------ .. _impstats.parameter.module.push-tls-insecureskipverify-usage: .. code-block:: rsyslog module(load="impstats" push.tls.insecureSkipVerify="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-rebindinterval.rst0000644000000000000000000000013215145046112025742 xustar0030 mtime=1771326538.952012868 30 atime=1787067673.313468313 30 ctime=1787067793.494708283 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-rebindinterval.rst0000664000175000017500000000226115145046112025407 0ustar00rgerrger.. _param-omrelp-rebindinterval: .. _omrelp.parameter.input.rebindinterval: RebindInterval ============== .. index:: single: omrelp; RebindInterval single: RebindInterval .. summary-start Forces periodic reconnection after a configured number of transmitted messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: RebindInterval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Permits to specify an interval at which the current connection is broken and re-established. This setting is primarily an aid to load balancers. After the configured number of messages has been transmitted, the current connection is terminated and a new one started. This usually is perceived as a ``new connection`` by load balancers, which in turn forward messages to another physical target system. Input usage ----------- .. _param-omrelp-input-rebindinterval: .. _omrelp.parameter.input.rebindinterval-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" rebindInterval="10000") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-mycert.rst0000644000000000000000000000013115132733117025032 xustar0030 mtime=1768666703.908620253 29 atime=1787067673.93447989 30 ctime=1787067792.433688511 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-mycert.rst0000666000175000017500000000147215132733117024505 0ustar00rgerrger.. _param-imrelp-tls-mycert: .. _imrelp.parameter.input.tls-mycert: tls.myCert ========== .. index:: single: imrelp; tls.myCert single: tls.myCert .. summary-start Points rsyslog to the server certificate presented during TLS handshakes. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.myCert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- The machine certificate that is being used for TLS communication. Input usage ----------- .. _param-imrelp-input-tls-mycert-usage: .. _imrelp.parameter.input.tls-mycert-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.myCert="/etc/rsyslog/server.pem") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-allow_trailing.rst0000644000000000000000000000013215132733117027005 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.372450771 30 ctime=1787067792.787695108 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-allow_trailing.rst0000666000175000017500000000274515132733117026463 0ustar00rgerrger.. _param-mmjsonparse-allow_trailing: .. _mmjsonparse.parameter.allow_trailing: allow_trailing ============== .. index:: single: mmjsonparse; allow_trailing single: allow_trailing single: trailing data .. summary-start Whether to allow non-whitespace data after the JSON object in find-json mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: allow_trailing :Scope: action :Type: boolean :Default: on :Required?: no :Introduced: 8.2506.0 Description ----------- Controls whether trailing non-whitespace characters are permitted after the parsed JSON object in find-json mode. - **on** (default): Allow trailing data after the JSON object. The JSON portion will be parsed and the trailing content ignored. - **off**: Reject messages with trailing non-whitespace content after the JSON object. Such messages will be treated as non-JSON. Whitespace characters (spaces, tabs, newlines) are always allowed after the JSON object regardless of this setting. This parameter is only effective when mode="find-json". Input usage ----------- .. _mmjsonparse.parameter.allow_trailing-usage: .. code-block:: rsyslog # Allow trailing data (default) action(type="mmjsonparse" mode="find-json" allow_trailing="on") # Reject messages with trailing data action(type="mmjsonparse" mode="find-json" allow_trailing="off") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`.rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-fsync.rst0000644000000000000000000000013215132411300024545 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.911460819 30 ctime=1787067792.179683778 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-fsync.rst0000666000175000017500000000212115132411300024207 0ustar00rgerrger.. _param-imjournal-fsync: .. _imjournal.parameter.module.fsync: .. meta:: :tag: module:imjournal :tag: parameter:FSync FSync ===== .. index:: single: imjournal; FSync single: FSync .. summary-start Force ``fsync()`` on the state file to guard against crash corruption. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: FSync :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.1908.0 Description ----------- When enabled, the module synchronizes the state file to persistent storage after each write. This reduces the risk of duplicate messages after abrupt shutdowns at the cost of additional I/O. Module usage ------------ .. _param-imjournal-module-fsync: .. _imjournal.parameter.module.fsync-usage: .. code-block:: rsyslog module(load="imjournal" FSync="...") Notes ----- - Historic documentation called this a ``binary`` option; it is boolean. - May significantly impact performance with low ``PersistStateInterval`` values. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-defaultfacility.rst0000644000000000000000000000013215241075234027306 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.989680237 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-defaultfacility.rst0000664000175000017500000000146015241075234026753 0ustar00rgerrger.. _param-imkubernetes-defaultfacility: .. _imkubernetes.parameter.module.defaultfacility: DefaultFacility =============== .. index:: single: imkubernetes; DefaultFacility single: DefaultFacility .. summary-start Default syslog facility assigned to submitted records; default ``user``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: DefaultFacility :Scope: module :Type: facility :Default: ``user`` :Required?: no :Introduced: 8.2604.0 Description ----------- Sets the facility used for messages created by ``imkubernetes`` before they are placed on the main queue. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" DefaultFacility="local0") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-properterminationfile.rst0000644000000000000000000000013015241066365027316 xustar0030 mtime=1787063541.603533173 28 atime=1787063541.6265336 30 ctime=1787067791.945679417 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-properterminationfile.rst0000664000175000017500000000373515241066365026774 0ustar00rgerrger.. _param-imdiag-properterminationfile: .. _imdiag.parameter.module.properterminationfile: ProperTerminationFile ===================== .. index:: single: imdiag; ProperTerminationFile .. summary-start Configures the testbench-only file that rsyslogd writes as its final normal process-exit action. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ProperTerminationFile :Scope: module :Type: string :Default: unset :Required?: no Description ----------- ``ProperTerminationFile`` is intended for daemonized rsyslog testbench scenarios where the shell cannot use ``wait`` to observe the real daemon process exit status. When set, imdiag passes the path to rsyslog core-owned storage. If rsyslog reaches the final normal ``main`` return path, the core writes the file as the last action before returning to the operating system. The marker file is opened with ``O_NOFOLLOW`` and mode ``0600``. If the file cannot be opened, written, or closed, rsyslog writes a concise diagnostic to stderr and exits with a non-zero status. No rsyslog internal warning or error message is emitted for marker write failures. A valid clean-shutdown file contains line-oriented fields such as ``status=ok`` and ``phase=main-return``. TimeoutGuard writes the same file before aborting with ``status=error``, ``reason=timeoutGuard``, and ``phase=timeoutguard-abort``. Marker content also includes ``queue.overall.size`` so failing tests retain basic queue backlog context. Absence of the file means the daemon did not prove a proper final shutdown and testbench code should treat that as crash or abort evidence. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" properTerminationFile="./rstb.example.proper-termination") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" properterminationfile: "./rstb.example.proper-termination" See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-keepalive-time.rst0000644000000000000000000000013115216464435025773 xustar0030 mtime=1782212893.981265456 30 atime=1787067671.770439548 29 ctime=1787067791.33566805 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-keepalive-time.rst0000664000175000017500000000171615216464435025445 0ustar00rgerrger.. _param-imbeats-keepalive-time: .. _imbeats.parameter.input.keepalive-time: KeepAlive.Time ============== .. meta:: :description: TCP keepalive idle time for imbeats sessions. :keywords: rsyslog, imbeats, keepalive time .. index:: single: imbeats; KeepAlive.Time single: KeepAlive.Time .. summary-start Set the idle time before TCP keepalive probing begins on imbeats sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: KeepAlive.Time :Scope: input :Type: integer :Default: input=system default :Required?: no :Introduced: 8.2604.0 Description ----------- Set the idle time before TCP keepalive probing begins on imbeats sessions. Input usage ----------- .. _param-imbeats-input-keepalive-time: .. _imbeats.parameter.input.keepalive-time-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" keepAlive.time="30") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmsnmptrapd-severitymapping.rst0000644000000000000000000000013015132733117027226 xustar0029 mtime=1768666703.91562036 29 atime=1787067673.22046658 30 ctime=1787067792.904697288 rsyslog-8.2608.0/doc/source/reference/parameters/mmsnmptrapd-severitymapping.rst0000666000175000017500000000371315132733117026702 0ustar00rgerrger.. _param-mmsnmptrapd-severitymapping: .. _mmsnmptrapd.parameter.module.severitymapping: severityMapping =============== .. index:: single: mmsnmptrapd; severityMapping single: severityMapping .. summary-start Defines severity string to numeric code mappings. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmsnmptrapd`. :Name: severityMapping :Scope: module :Type: string :Default: module=none :Required?: no :Introduced: at least 5.8.1, possibly earlier Description ----------- This specifies the severity mapping table. It must be specified as a list. Note that **no whitespace** is supported inside the list, as it will likely lead to parsing errors. The list is constructed of Severity-Name/Severity-Value pairs, delimited by comma. Severity-Name is a case-sensitive string, e.g. ``warning`` and an associated numerical value (e.g. 4). Possible values are in the range 0..7 and are defined in `RFC5424, table 2 `_. The given sample would be specified as ``warning/4``. The mapping is defined when the module is loaded using the ``module()`` statement. This setting applies to all subsequent actions that use this module instance. To use different mappings, load separate instances of the module in different rulesets. Module usage ------------ .. _param-mmsnmptrapd-module-severitymapping: .. _mmsnmptrapd.parameter.module.severitymapping-usage: .. code-block:: rsyslog module(load="mmsnmptrapd" severityMapping="warning/4,error/3") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmsnmptrapd.parameter.legacy.mmsnmptrapdseveritymapping: - $mmsnmptrapdSeverityMapping — maps to severityMapping (status: legacy) .. index:: single: mmsnmptrapd; $mmsnmptrapdSeverityMapping single: $mmsnmptrapdSeverityMapping See also -------- See also :doc:`../../configuration/modules/mmsnmptrapd`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-ratelimit-name.rst0000644000000000000000000000013215145046112025462 xustar0030 mtime=1771326538.941012688 30 atime=1787067674.379488186 30 ctime=1787067792.586691362 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-ratelimit-name.rst0000664000175000017500000000136215145046112025130 0ustar00rgerrger.. index:: ! imudp; RateLimit.Name .. _param-imudp-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple listeners to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-listener limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-policywatchdebounce.rst0000644000000000000000000000013215171370365030737 xustar0030 mtime=1776677109.118908099 30 atime=1787067672.589454817 30 ctime=1787067792.813695592 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-policywatchdebounce.rst0000664000175000017500000000303115171370365030400 0ustar00rgerrger.. meta:: :description: The mmjsontransform policyWatchDebounce parameter sets the quiet period before watched policy reloads. :keywords: rsyslog, mmjsontransform, policyWatchDebounce, debounce, watched reload .. _param-mmjsontransform-policywatchdebounce: .. _mmjsontransform.parameter.input.policywatchdebounce: policyWatchDebounce =================== .. index:: single: mmjsontransform; policyWatchDebounce single: policyWatchDebounce .. summary-start Sets the quiet period used before a watched policy change is reloaded. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: policyWatchDebounce :Scope: input :Type: time interval :Default: 5s :Required?: no :Introduced: 8.2604.0 Description ----------- Defines the debounce interval used by :ref:`policyWatch `. Each new file event resets the timer, so rapid updates are coalesced into one later reload. Supported suffixes are ``ms``, ``s``, ``m``, and ``h``. Bare numbers are interpreted as seconds. Input usage ----------- .. _param-mmjsontransform-policywatchdebounce-usage: .. _mmjsontransform.parameter.input.policywatchdebounce-usage: .. code-block:: rsyslog action(type="mmjsontransform" policy="/etc/rsyslog/mmjsontransform-policy.yaml" policyWatch="on" policyWatchDebounce="500ms" input="$!raw" output="$!normalized") See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-cacheexpireinterval.rst0000644000000000000000000000013215132733117030166 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.641455786 30 ctime=1787067792.826695835 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-cacheexpireinterval.rst0000666000175000017500000000353215132733117027637 0ustar00rgerrger.. _param-mmkubernetes-cacheexpireinterval: .. _mmkubernetes.parameter.action.cacheexpireinterval: cacheexpireinterval =================== .. index:: single: mmkubernetes; cacheexpireinterval single: cacheexpireinterval .. summary-start Controls how often to check for expired metadata cache entries. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: cacheexpireinterval :Scope: action :Type: integer :Default: -1 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This parameter allows you to expire entries from the metadata cache. The values are: - -1 (default) - disables metadata cache expiration - 0 - check cache for expired entries before every cache lookup - 1 or higher - the number is a number of seconds - check the cache for expired entries every this many seconds, when processing an entry The cache is only checked if processing a record from Kubernetes. There isn't some sort of housekeeping thread that continually runs cleaning up the cache. When an record from Kubernetes is processed: If `cacheexpireinterval` is -1, then do not check for cache expiration. If `cacheexpireinterval` is 0, then check for cache expiration. If `cacheexpireinterval` is greater than 0, check for cache expiration if the last time we checked was more than this many seconds ago. When cache expiration is checked, it will delete all cache entries which have a ttl less than or equal to the current time. The cache entry ttl is set using the :ref:`param-mmkubernetes-cacheentryttl`. Action usage ------------ .. _param-mmkubernetes-action-cacheexpireinterval: .. _mmkubernetes.parameter.action.cacheexpireinterval-usage: .. code-block:: rsyslog action(type="mmkubernetes" cacheExpireInterval="-1") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-begintransactionmark.rst0000644000000000000000000000013215132733117027150 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.696456811 30 ctime=1787067793.446707389 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-begintransactionmark.rst0000666000175000017500000000207015132733117026615 0ustar00rgerrger.. _param-omprog-begintransactionmark: .. _omprog.parameter.action.begintransactionmark: beginTransactionMark ===================== .. index:: single: omprog; beginTransactionMark single: beginTransactionMark .. summary-start Defines the marker sent to denote the start of a transaction. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: beginTransactionMark :Scope: action :Type: string :Default: action="BEGIN TRANSACTION" :Required?: no :Introduced: 8.31.0 Description ----------- Allows specifying the mark message that rsyslog will send to the external program to indicate the start of a transaction (batch). This parameter is ignored if :ref:`param-omprog-usetransactions` is disabled. Action usage ------------ .. _param-omprog-action-begintransactionmark: .. _omprog.parameter.action.begintransactionmark-usage: .. code-block:: rsyslog action(type="omprog" useTransactions="on" beginTransactionMark="BEGIN TRANSACTION") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-keepalive-interval.rst0000644000000000000000000000013215132733117026517 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.962480412 30 ctime=1787067792.398687859 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-keepalive-interval.rst0000666000175000017500000000213415132733117026165 0ustar00rgerrger.. _param-imrelp-keepalive-interval: .. _imrelp.parameter.input.keepalive-interval: keepAlive.interval ================== .. index:: single: imrelp; keepAlive.interval single: keepAlive.interval .. summary-start Determines the delay between successive keep-alive probes when enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: keepAlive.interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: Not documented Description ----------- The interval between subsequent keep-alive probes, regardless of what the connection has been exchanged in the meantime. The default, 0, means that the operating system defaults are used. This only has an effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imrelp-input-keepalive-interval-usage: .. _imrelp.parameter.input.keepalive-interval-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" keepAlive="on" keepAlive.interval="30") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-eventproperties.rst0000644000000000000000000000013115132733117030303 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.473471296 30 ctime=1787067792.934697847 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-eventproperties.rst0000666000175000017500000000330415132733117027752 0ustar00rgerrger.. _param-omazureeventhubs-eventproperties: .. _omazureeventhubs.parameter.input.eventproperties: eventproperties =============== .. index:: single: omazureeventhubs; eventproperties single: eventproperties .. summary-start Adds custom key-value properties to each AMQP message emitted by the action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: eventproperties :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- The ``eventProperties`` configuration property is an array property used to add key-value pairs as additional properties to the encoded AMQP message object, providing additional information about the log event. These properties can be used for filtering, routing, and grouping log events in Azure Event Hubs. The ``eventProperties`` property is an array of strings, where each string is a key-value pair with the key and value separated by an equal sign. For example, the following configuration adds two event properties inside an action definition: .. code-block:: rsyslog action( type="omazureeventhubs" # ... other parameters eventProperties=["Table=TestTable", "Format=JSON"] ) In this example, the Table and Format keys are added to the message object as event properties, with the corresponding values of ``TestTable`` and ``JSON``, respectively. Input usage ----------- .. _omazureeventhubs.parameter.input.eventproperties-usage: .. code-block:: rsyslog action(type="omazureeventhubs" eventProperties=["Table=TestTable", "Format=JSON"] ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-listenportfilename.rst0000644000000000000000000000013215132733117026640 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.796477318 30 ctime=1787067792.354687039 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-listenportfilename.rst0000666000175000017500000000172015132733117026306 0ustar00rgerrger.. _param-imptcp-listenportfilename: .. _imptcp.parameter.input.listenportfilename: ListenPortFileName ================== .. index:: single: imptcp; ListenPortFileName single: ListenPortFileName .. summary-start Writes the port number being listened on into the specified file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: ListenPortFileName :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.38.0 Description ----------- With this parameter you can specify the name for a file. In this file the port, imptcp is connected to, will be written. This parameter was introduced because the testbench works with dynamic ports. Input usage ----------- .. _param-imptcp-input-listenportfilename: .. _imptcp.parameter.input.listenportfilename-usage: .. code-block:: rsyslog input(type="imptcp" listenPortFileName="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-errorfile.rst0000644000000000000000000000013115132733117024743 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.278467661 30 ctime=1787067793.251703755 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-errorfile.rst0000666000175000017500000000247415132733117024421 0ustar00rgerrger.. _param-omhttp-errorfile: .. _omhttp.parameter.input.errorfile: errorfile ========= .. index:: single: omhttp; errorfile single: errorfile .. summary-start Specifies a file where omhttp records HTTP requests that return error responses. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: errorfile :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- Here you can set the name of a file where all errors will be written to. Any request that returns a 4XX or 5XX HTTP code is recorded in the error file. Each line is JSON formatted with ``"request"`` and ``"response"`` fields, example pretty-printed below. .. code-block:: text { "request": { "url": "https://example.com:443/path", "postdata": "mypayload" }, "response" : { "status": 400, "message": "error string" } } It is intended that a full replay of failed data is possible by processing this file. Input usage ----------- .. _omhttp.parameter.input.errorfile-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" errorFile="/var/log/rsyslog/omhttp.error" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-de-dot-separator.rst0000644000000000000000000000013215132733117027313 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.664456215 30 ctime=1787067792.833695965 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-de-dot-separator.rst0000666000175000017500000000203415132733117026760 0ustar00rgerrger.. _param-mmkubernetes-de-dot-separator: .. _mmkubernetes.parameter.action.de-dot-separator: de_dot_separator ================ .. index:: single: mmkubernetes; de_dot_separator single: de_dot_separator .. summary-start Defines the string used to replace dots when ``de_dot`` is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: de_dot_separator :Scope: action :Type: word :Default: _ :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When processing labels and annotations, if the :ref:`param-mmkubernetes-de-dot` parameter is set to `"on"`, the key strings will have their `.` characters replaced with the string specified by the string value of this parameter. Action usage ------------ .. _param-mmkubernetes-action-de-dot-separator: .. _mmkubernetes.parameter.action.de-dot-separator-usage: .. code-block:: rsyslog action(type="mmkubernetes" deDotSeparator="_") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-retrievenewlogsfromstart.rst0000644000000000000000000000013215132411300030406 xustar0030 mtime=1768559296.193884485 30 atime=1787067671.772439586 30 ctime=1787067791.982680107 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-retrievenewlogsfromstart.rst0000666000175000017500000000222415132411300030054 0ustar00rgerrger.. _param-imdocker-retrievenewlogsfromstart: .. _imdocker.parameter.module.retrievenewlogsfromstart: RetrieveNewLogsFromStart ======================== .. index:: single: imdocker; RetrieveNewLogsFromStart single: RetrieveNewLogsFromStart .. summary-start Whether to read newly discovered container logs from start; default ``on``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: RetrieveNewLogsFromStart :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.41.0 Description ----------- Specifies whether imdocker processes newly found container logs from the beginning. Containers that exist when imdocker starts are controlled by ``GetContainerLogOptions`` and its ``tail`` option. Module usage ------------ .. _param-imdocker-module-retrievenewlogsfromstart: .. _imdocker.parameter.module.retrievenewlogsfromstart-usage: .. code-block:: rsyslog module(load="imdocker" RetrieveNewLogsFromStart="...") Notes ----- - The original documentation described this as a binary option; it is a boolean parameter. See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv6-anonmode.rst0000644000000000000000000000013215145046112025403 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.864441301 30 ctime=1787067792.722693897 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv6-anonmode.rst0000664000175000017500000000354215145046112025053 0ustar00rgerrger.. _param-mmanon-ipv6-anonmode: .. _mmanon.parameter.input.ipv6-anonmode: ipv6.anonMode ============= .. index:: single: mmanon; ipv6.anonMode single: ipv6.anonMode .. summary-start Defines how IPv6 addresses are anonymized by the mmanon action. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv6.anonMode :Scope: input :Type: string :Default: input=zero :Required?: no :Introduced: 7.3.7 Description ----------- The available modes are ``random``, ``random-consistent``, ``random-consistent-unique``, and ``zero``. The modes ``random`` and ``random-consistent`` are very similar, in that they both anonymize IP addresses by randomizing the last bits (any number) of a given address. However, while ``random`` mode assigns a new random IP address for every address in a message, ``random-consistent`` will assign the same randomized address to every instance of the same original address. ``random-consistent-unique`` builds on that behavior and guarantees that no two distinct original addresses share the same anonymized result. It may take longer to generate addresses because a replacement is retried until an unused randomized value is found; this effect grows as more unique IPs are processed. The default ``zero`` mode will do full anonymization of any number of bits and it will also normalize the address, so that no information about the original IP address is available. Also note that an anonymized IPv6 address will be normalized, meaning there will be no abbreviations, leading zeros will **not** be displayed, and capital letters in the hex numerals will be lowercase. Input usage ----------- .. _mmanon.parameter.input.ipv6-anonmode-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv6.anonMode="random-consistent") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-addtlframedelimiter.rst0000644000000000000000000000013215132733117026556 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.057482183 30 ctime=1787067792.452688865 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-addtlframedelimiter.rst0000666000175000017500000000334115132733117026225 0ustar00rgerrger.. _param-imtcp-addtlframedelimiter: .. _imtcp.parameter.module.addtlframedelimiter: .. _imtcp.parameter.input.addtlframedelimiter: AddtlFrameDelimiter =================== .. index:: single: imtcp; AddtlFrameDelimiter single: AddtlFrameDelimiter .. summary-start Specifies an additional frame delimiter for message reception. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: AddtlFrameDelimiter :Scope: module, input :Type: integer :Default: module=-1, input=module parameter :Required?: no :Introduced: 4.3.1 Description ----------- This directive permits to specify an additional frame delimiter. The value must be the decimal ASCII code of the character to be used as the delimiter. For example, to use ``#`` as the delimiter, specify ``addtlFrameDelimiter="35"``. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-addtlframedelimiter: .. _imtcp.parameter.module.addtlframedelimiter-usage: .. code-block:: rsyslog module(load="imtcp" addtlFrameDelimiter="...") Input usage ----------- .. _param-imtcp-input-addtlframedelimiter: .. _imtcp.parameter.input.addtlframedelimiter-usage: .. code-block:: rsyslog input(type="imtcp" port="514" addtlFrameDelimiter="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserveraddtlframedelimiter: - $InputTCPServerAddtlFrameDelimiter — maps to AddtlFrameDelimiter (status: legacy) .. index:: single: imtcp; $InputTCPServerAddtlFrameDelimiter single: $InputTCPServerAddtlFrameDelimiter See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-name.rst0000644000000000000000000000013215132733117025716 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.290486527 30 ctime=1787067792.642692406 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-name.rst0000666000175000017500000000300115132733117025356 0ustar00rgerrger.. _param-imuxsock-syssock-name: .. _imuxsock.parameter.module.syssock-name: SysSock.Name ============ .. index:: single: imuxsock; SysSock.Name single: SysSock.Name .. summary-start Selects an alternate log socket instead of the default ``/dev/log``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.Name :Scope: module :Type: word :Default: module=/dev/log :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies an alternate log socket to be used instead of the default system log socket, traditionally ``/dev/log``. Unless disabled by the ``SysSock.Unlink`` setting, this socket is created upon rsyslog startup and deleted upon shutdown, according to traditional syslogd behavior. The behavior of this parameter is different for systemd systems. See the :ref:`imuxsock-systemd-details-label` section for details. Module usage ------------ .. _param-imuxsock-module-syssock-name: .. _imuxsock.parameter.module.syssock-name-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.name="/var/run/rsyslog/devlog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogsockname: - $SystemLogSocketName — maps to SysSock.Name (status: legacy) .. index:: single: imuxsock; $SystemLogSocketName single: $SystemLogSocketName See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-model.rst0000644000000000000000000000013215132733117024157 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.739438971 30 ctime=1787067792.686693226 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-model.rst0000666000175000017500000000134215132733117023625 0ustar00rgerrger.. _param-mmaitag-model: .. _mmaitag.parameter.action.model: model ===== .. index:: single: mmaitag; model single: model .. summary-start Specifies the AI model identifier used by the provider. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: model :Scope: action :Type: string :Default: gemini-2.0-flash :Required?: no :Introduced: 9.0.0 Description ----------- AI model identifier to use. The meaning of the value is provider specific. Action usage ------------- .. _param-mmaitag-action-model: .. _mmaitag.parameter.action.model-usage: .. code-block:: rsyslog action(type="mmaitag" model="gemini-1.5-flash") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-inputshutdowntimeout.rst0000644000000000000000000000013215171370365027241 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.043444638 30 ctime=1787067791.938679287 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-inputshutdowntimeout.rst0000664000175000017500000000251515171370365026710 0ustar00rgerrger.. _param-imdiag-inputshutdowntimeout: .. _imdiag.parameter.module.inputshutdowntimeout: .. meta:: :description: Reference for the imdiag inputShutdownTimeout module parameter. :keywords: rsyslog, imdiag, inputshutdowntimeout, testbench, timeout, shutdown InputShutdownTimeout ==================== .. index:: single: imdiag; InputShutdownTimeout .. summary-start Sets the input shutdown timeout at config load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: InputShutdownTimeout :Scope: module :Type: integer (milliseconds) :Default: 60000 :Required?: no :Introduced: 8.x Description ----------- Sets ``globals.inputTimeoutShutdown`` — the time rsyslog allows each input plugin to stop during an orderly shutdown — at config-load time. The testbench uses this to ensure inputs have enough time to shut down cleanly under load, in both RainerScript and YAML-only modes. Override per-test via ``RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT`` before ``generate_conf``. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" inputShutdownTimeout="60000") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" inputshutdowntimeout: "60000" See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgssserverrun.rst0000644000000000000000000000013215132733117027104 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.588454798 30 ctime=1787067792.147683181 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgssserverrun.rst0000666000175000017500000000213715132733117026555 0ustar00rgerrger.. _param-imgssapi-inputgssserverrun: .. _imgssapi.parameter.input.inputgssserverrun: InputGSSServerRun ================= .. index:: single: imgssapi; InputGSSServerRun single: InputGSSServerRun .. summary-start Starts a dedicated GSSAPI syslog listener on the specified port. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSServerRun :Scope: input :Type: word :Default: none :Required?: no :Introduced: 3.11.5 Description ----------- Starts a GSSAPI server on the selected port. This listener runs independently from the TCP server provided by other modules. Input usage ----------- .. _imgssapi.parameter.input.inputgssserverrun-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssServerRun 1514 Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgssserverrun: - $inputGssServerRun — maps to InputGSSServerRun (status: legacy) .. index:: single: imgssapi; $inputGssServerRun single: $inputGssServerRun See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-getcontainerlogoptions.rst0000644000000000000000000000013215132411300030020 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.150446633 30 ctime=1787067791.976679995 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-getcontainerlogoptions.rst0000666000175000017500000000216315132411300027470 0ustar00rgerrger.. _param-imdocker-getcontainerlogoptions: .. _imdocker.parameter.module.getcontainerlogoptions: GetContainerLogOptions ====================== .. index:: single: imdocker; GetContainerLogOptions single: GetContainerLogOptions .. summary-start HTTP query options for ``Get container logs`` requests; default ``timestamps=0&follow=1&stdout=1&stderr=1&tail=1``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: GetContainerLogOptions :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=timestamps=0&follow=1&stdout=1&stderr=1&tail=1 :Required?: no :Introduced: 8.41.0 Description ----------- Specifies the HTTP query component of a ``Get container logs`` API request. See the Docker API for available options. It is not necessary to prepend ``?``. Module usage ------------ .. _param-imdocker-module-getcontainerlogoptions: .. _imdocker.parameter.module.getcontainerlogoptions-usage: .. code-block:: rsyslog module(load="imdocker" GetContainerLogOptions="...") See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-maxinotifywatches.rst0000644000000000000000000000013115145046112026446 xustar0030 mtime=1771326538.939012655 30 atime=1787067672.365450641 29 ctime=1787067792.07568184 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-maxinotifywatches.rst0000664000175000017500000000303615145046112026115 0ustar00rgerrger.. _param-imfile-maxinotifywatches: .. _imfile.parameter.module.maxinotifywatches: .. _imfile.parameter.maxinotifywatches: maxiNotifyWatches ================= .. index:: single: imfile; maxiNotifyWatches single: maxiNotifyWatches .. summary-start Specifies the maximum number of inotify watches that imfile can use. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: maxiNotifyWatches :Scope: module :Type: integer :Default: module=0 :Required?: no :Introduced: 8.2602.0 Description ----------- This sets the maximum number of inotify watches that imfile can consume. This is useful to limit rsyslog's consumption of inotify watches, for example, to prevent it from using up all available watches on a system where other applications also need them. When the limit is reached, imfile keeps processing known files and switches to periodic rescans (see ``inotifyFallbackInterval``) to discover changes and retry arming watches. It is recommended to set this value high enough to cover all monitored files, including those that may be created in the future. The system's limit can be checked via ``/proc/sys/fs/inotify/max_user_watches``. If you do not have sufficient permissions to change the system-wide limit, this parameter provides a way to limit rsyslog's resource consumption. Module usage ------------ .. _imfile.parameter.module.maxinotifywatches-usage: .. code-block:: rsyslog module(load="imfile" maxiNotifyWatches="256000") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-usesystimestamp.rst0000644000000000000000000000013215132733117026561 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.920479629 30 ctime=1787067792.675693021 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-usesystimestamp.rst0000666000175000017500000000313515132733117026231 0ustar00rgerrger.. _param-imuxsock-usesystimestamp: .. _imuxsock.parameter.input.usesystimestamp: UseSysTimeStamp =============== .. index:: single: imuxsock; UseSysTimeStamp single: UseSysTimeStamp .. summary-start Takes message timestamps from the system instead of the message itself. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: UseSysTimeStamp :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 5.9.1 Description ----------- This parameter instructs ``imuxsock`` to obtain message time from the system (via control messages) instead of using time recorded inside the message. This may be most useful in combination with systemd. Due to the usefulness of this functionality, we decided to enable it by default. As such, the behavior is slightly different than previous versions. However, we do not see how this could negatively affect existing environments. .. versionadded:: 5.9.1 Input usage ----------- .. _param-imuxsock-input-usesystimestamp: .. _imuxsock.parameter.input.usesystimestamp-usage: .. code-block:: rsyslog input(type="imuxsock" useSysTimeStamp="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketusesystimestamp: - $InputUnixListenSocketUseSysTimeStamp — maps to UseSysTimeStamp (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketUseSysTimeStamp single: $InputUnixListenSocketUseSysTimeStamp See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-specifictype.rst0000644000000000000000000000013215132733117025440 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.782439772 30 ctime=1787067793.552709364 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-specifictype.rst0000666000175000017500000000225715132733117025114 0ustar00rgerrger.. _param-omsnmp-specifictype: .. _omsnmp.parameter.module.specifictype: SpecificType ============ .. index:: single: omsnmp; SpecificType single: SpecificType .. summary-start Defines the SNMPv1 specific trap number. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: SpecificType :Scope: module :Type: integer :Default: module=0 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- This is the specific trap number. This configuration parameter is used for **SNMPv1** only. It has no effect if **SNMPv2** is used. Module usage ------------ .. _param-omsnmp-module-specifictype: .. _omsnmp.parameter.module.specifictype-usage: .. code-block:: rsyslog action(type="omsnmp" specificType="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmpspecifictype: - $actionsnmpspecifictype — maps to SpecificType (status: legacy) .. index:: single: omsnmp; $actionsnmpspecifictype single: $actionsnmpspecifictype See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-metricsapikeyfile.rst0000644000000000000000000000013115171370365026462 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.737457576 29 ctime=1787067792.16368348 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-metricsapikeyfile.rst0000664000175000017500000000231515171370365026130 0ustar00rgerrger.. meta:: :description: Protect the imhttp metrics endpoint with API key authentication. :keywords: rsyslog, imhttp, metrics, api key authentication .. _param-imhttp-metricsapikeyfile: .. _imhttp.parameter.module.metricsapikeyfile: .. _imhttp-metricsapikeyfile: metricsApiKeyFile ================= .. index:: single: imhttp; metricsApiKeyFile single: metricsApiKeyFile .. summary-start Protects the imhttp Prometheus metrics endpoint with API key authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: metricsApiKeyFile :Scope: module :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- If set, the metrics endpoint accepts matching API key tokens from a file. Accepted request headers are ``Authorization: ApiKey`` and ``X-API-Key``. Leading whitespace after the header scheme is ignored. Blank lines and lines starting with ``#`` are ignored. Module usage ------------ .. _imhttp.parameter.module.metricsapikeyfile-usage: .. code-block:: rsyslog module( load="imhttp" metricsApiKeyFile="/etc/rsyslog/api-keys.txt" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-uid.rst0000644000000000000000000000013215132733117024002 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.727457389 30 ctime=1787067793.384706233 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-uid.rst0000666000175000017500000000227015132733117023451 0ustar00rgerrger.. _param-omlibdbi-uid: .. _omlibdbi.parameter.input.uid: UID === .. index:: single: omlibdbi; UID single: UID .. summary-start Defines the user name that omlibdbi uses when authenticating to the database. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: UID :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Provide the account that has permission to write into the target database. Combine this with ``PWD`` to supply the password. Input usage ----------- .. _param-omlibdbi-input-uid-usage: .. _omlibdbi.parameter.input.uid-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbiusername: - $ActionLibdbiUserName — maps to UID (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiUserName single: $ActionLibdbiUserName See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-interleaved.rst0000644000000000000000000000013115216464435027116 xustar0029 mtime=1782212893.98826557 30 atime=1787067672.128446222 30 ctime=1787067793.059700177 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-interleaved.rst0000664000175000017500000000247115216464435026567 0ustar00rgerrger.. _param-omelasticsearch-interleaved: .. _omelasticsearch.parameter.module.interleaved: interleaved =========== .. index:: single: omelasticsearch; interleaved single: interleaved .. summary-start Interleave request and response data in bulk error-file output. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: interleaved :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled, omelasticsearch stores request and response data together for each item written to the configured :ref:`param-omelasticsearch-errorfile`. This makes it easier to correlate a bulk request item with the Elasticsearch item response that caused the error file entry. The option can be combined with :ref:`param-omelasticsearch-erroronly` to write only failed bulk items while still keeping each failed request next to its response. Action usage ------------ .. _param-omelasticsearch-action-interleaved: .. _omelasticsearch.parameter.action.interleaved: .. code-block:: rsyslog action(type="omelasticsearch" errorFile="..." interleaved="on") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`, :ref:`param-omelasticsearch-errorfile`, and :ref:`param-omelasticsearch-erroronly`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-writeoperation.rst0000644000000000000000000000013215132411300027644 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.188447341 30 ctime=1787067793.120701314 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-writeoperation.rst0000666000175000017500000000171715132411300027320 0ustar00rgerrger.. _param-omelasticsearch-writeoperation: .. _omelasticsearch.parameter.module.writeoperation: writeoperation ============== .. index:: single: omelasticsearch; writeoperation single: writeoperation .. summary-start Bulk action type: `index` (default) or `create` to avoid overwrites. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: writeoperation :Scope: action :Type: word :Default: action=index :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Controls the operation sent in bulk requests. Use `create` to only add documents that do not yet exist. Requires `bulkid` and `dynbulkid`. Action usage ------------ .. _param-omelasticsearch-action-writeoperation: .. _omelasticsearch.parameter.action.writeoperation: .. code-block:: rsyslog action(type="omelasticsearch" writeoperation="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-ratelimit-name.rst0000644000000000000000000000013215171370365025662 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.755457911 30 ctime=1787067792.168683573 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-ratelimit-name.rst0000664000175000017500000000136415171370365025332 0ustar00rgerrger.. index:: ! imhttp; RateLimit.Name .. _param-imhttp-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple listeners to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-listener limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-binary.rst0000644000000000000000000000013215132733117025100 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.263448739 30 ctime=1787067792.769694773 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-binary.rst0000666000175000017500000000166415132733117024555 0ustar00rgerrger.. _param-mmexternal-binary: .. _mmexternal.parameter.input.binary: binary ====== .. index:: single: mmexternal; binary single: binary .. summary-start Specifies the external message modification plugin executable that mmexternal invokes. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: binary :Scope: input :Type: string :Default: none :Required?: yes :Introduced: 8.3.0 Description ----------- The name of the external message modification plugin to be called. This can be a full path name. Command-line arguments for the executable can also be included in the string. Input usage ----------- .. _param-mmexternal-input-binary: .. _mmexternal.parameter.input.binary-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/mmexternal.py" ) See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-listenportfilename.rst0000644000000000000000000000013215216464435026605 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.072445179 30 ctime=1787067791.940679324 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-listenportfilename.rst0000664000175000017500000000327115216464435026254 0ustar00rgerrger.. _param-imdiag-listenportfilename: .. _imdiag.parameter.module.listenportfilename.listener: ListenPortFileName ================== .. index:: single: imdiag; ListenPortFileName single: ListenPortFileName .. summary-start Writes the port chosen for the diagnostic listener to the named file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ListenPortFileName :Scope: module :Type: string (filename) :Default: module=none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- Specifies a file that receives the TCP port number after the listener starts. Use :ref:`ServerRun ` to initialize the listener. The parameter is mandatory and must be provided before the listener is created. The file is overwritten each time the listener starts. When the listener is configured with port ``0`` (ephemeral port selection), this file is the only way to discover the actual port allocated by the operating system. Module usage ------------ .. _param-imdiag-module-listenportfilename-listener: .. _imdiag.parameter.module.listenportfilename.listener-usage: .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/var/run/rsyslog/imdiag.port" serverRun="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiaglistenportfilename: - $IMDiagListenPortFileName — maps to ListenPortFileName (status: legacy) .. index:: single: imdiag; $IMDiagListenPortFileName single: $IMDiagListenPortFileName See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-freshstarttail.rst0000644000000000000000000000013215132733117025744 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.487452915 30 ctime=1787067792.068681709 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-freshstarttail.rst0000666000175000017500000000324315132733117025414 0ustar00rgerrger.. _param-imfile-freshstarttail: .. _imfile.parameter.input.freshstarttail: .. _imfile.parameter.freshstarttail: freshStartTail ============== .. index:: single: imfile; freshStartTail single: freshStartTail .. summary-start On first start, seeks to the end of existing files and processes only new lines. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: freshStartTail :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Causes rsyslog to seek to the end of input files at the initial start and process only new log messages. Useful when deploying rsyslog and only new logs are of interest. This parameter applies only to files that exist when rsyslog performs its initial processing of file monitors. .. warning:: Depending on the number and location of existing files, startup may take time. If another process creates a new file exactly during startup and writes data to it, rsyslog may treat that file as preexisting and skip it. The same risk exists for log data written between the last shutdown and the next start. Some data loss is therefore possible. The rsyslog team advises against activating ``freshStartTail``. Input usage ----------- .. _param-imfile-input-freshstarttail: .. _imfile.parameter.input.freshstarttail-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" freshStartTail="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-defaultseverity.rst0000644000000000000000000000013215132411300026642 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.864459943 30 ctime=1787067792.172683647 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-defaultseverity.rst0000666000175000017500000000242415132411300026312 0ustar00rgerrger.. _param-imjournal-defaultseverity: .. _imjournal.parameter.module.defaultseverity: .. meta:: :tag: module:imjournal :tag: parameter:DefaultSeverity DefaultSeverity =============== .. index:: single: imjournal; DefaultSeverity single: DefaultSeverity .. summary-start Fallback severity used if a journal entry lacks ``SYSLOG_PRIORITY``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: DefaultSeverity :Scope: module :Type: word :Default: module=notice :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the severity assigned to messages that do not provide the ``SYSLOG_PRIORITY`` field. Values may be given as names or numbers. Module usage ------------ .. _param-imjournal-module-defaultseverity: .. _imjournal.parameter.module.defaultseverity-usage: .. code-block:: rsyslog module(load="imjournal" DefaultSeverity="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournaldefaultseverity: - $ImjournalDefaultSeverity — maps to DefaultSeverity (status: legacy) .. index:: single: imjournal; $ImjournalDefaultSeverity single: $ImjournalDefaultSeverity See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-usetransactions.rst0000644000000000000000000000013115241075234026167 xustar0030 mtime=1787067036.581577845 29 atime=1787067036.72658056 30 ctime=1787067793.477707966 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-usetransactions.rst0000664000175000017500000000544715241075234025646 0ustar00rgerrger.. _param-omprog-usetransactions: .. _omprog.parameter.action.usetransactions: useTransactions =============== .. index:: single: omprog; useTransactions single: useTransactions .. summary-start Enables batch processing with begin and commit transaction markers. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: useTransactions :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.31.0 Description ----------- Specifies whether the external program processes the messages in :doc:`batches <../../development/dev_oplugins>` (transactions). When this switch is enabled, the logs sent to the program are grouped in transactions. At the start of a transaction, rsyslog sends a special mark message to the program (see :ref:`param-omprog-begintransactionmark`). At the end of the transaction, rsyslog sends another mark message (see :ref:`param-omprog-committransactionmark`). If :ref:`param-omprog-confirmmessages` is also set to "on", the program must confirm both the mark messages and the logs within the transaction. The mark messages must be confirmed by returning ``OK``, and the individual messages by returning ``DEFER_COMMIT`` (instead of ``OK``). Refer to the link below for details. .. seealso:: `Interface between rsyslog and external output plugins `_ .. warning:: This feature is currently **experimental**. It could change in future releases without keeping backwards compatibility with existing configurations or the specified interface. There is also a `known issue `_ with the use of transactions together with ``confirmMessages=on``. Implementation status --------------------- ``omprog`` currently implements this option through rsyslog's legacy output transaction callbacks. That is intentional for the existing module: the option is action-specific, so one ``omprog`` action can run in transaction mode while another action can keep the normal per-message processing path. The newer output transaction interface expects a module to be transactional as a module capability instead of switching that behavior per action. Moving this option to that interface would therefore need either a compatible core design change, a separate transactional module, or an incompatible change to this parameter. It is not a drop-in implementation detail. Action usage ------------ .. _param-omprog-action-usetransactions: .. _omprog.parameter.action.usetransactions-usage: .. code-block:: rsyslog action(type="omprog" useTransactions="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfifo-severity.rst0000644000000000000000000000013215216464435024572 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.178447155 30 ctime=1787067792.133682921 rsyslog-8.2608.0/doc/source/reference/parameters/imfifo-severity.rst0000664000175000017500000000214215216464435024235 0ustar00rgerrger.. _param-imfifo-severity: .. _imfifo.parameter.input.severity: severity ======== .. meta:: :description: Syslog severity to apply to messages read from this named pipe (FIFO). :keywords: rsyslog, imfifo, severity .. index:: single: imfifo; severity single: severity .. summary-start Specifies the syslog severity to apply to messages read from this named pipe (FIFO). .. summary-end This parameter applies to :doc:`../../configuration/modules/imfifo`. :Name: severity :Scope: input :Type: severity (word/integer) :Default: notice :Required?: no :Introduced: 8.2606.0 Description ----------- The syslog severity to be assigned to all messages read from this named pipe. It can be specified in textual form (for example ``notice``) or as a number (for example ``5``). Textual form is recommended. Input usage ----------- .. _param-imfifo-input-severity: .. _imfifo.parameter.input.severity-usage: .. code-block:: rsyslog input(type="imfifo" file="/var/log/myfifo" tag="fifo-logs:" severity="info") See also -------- See also :doc:`../../configuration/modules/imfifo`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-cacheentryttl.rst0000644000000000000000000000013015241075234027004 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 28 ctime=1787067791.9876802 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-cacheentryttl.rst0000664000175000017500000000147615241075234026462 0ustar00rgerrger.. _param-imkubernetes-cacheentryttl: .. _imkubernetes.parameter.module.cacheentryttl: CacheEntryTtl ============= .. index:: single: imkubernetes; CacheEntryTtl single: CacheEntryTtl .. summary-start Seconds to keep pod metadata in the in-memory cache; default ``300``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: CacheEntryTtl :Scope: module :Type: integer :Default: ``300`` :Required?: no :Introduced: 8.2604.0 Description ----------- When Kubernetes enrichment is enabled, successful pod lookups are cached for this many seconds before the entry expires and must be re-fetched. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" CacheEntryTtl="300") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-statsname.rst0000644000000000000000000000013215132411300025033 xustar0030 mtime=1768559296.213884802 30 atime=1787067673.186465946 30 ctime=1787067793.362705823 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-statsname.rst0000666000175000017500000000151015132411300024476 0ustar00rgerrger.. _param-omkafka-statsname: .. _omkafka.parameter.module.statsname: statsName ========= .. index:: single: omkafka; statsName single: statsName .. summary-start Name of statistics instance for this action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: statsName :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: 8.2108.0 Description ----------- .. versionadded:: 8.2108.0 The name assigned to statistics specific to this action instance. Counters include ``submitted``, ``acked`` and ``failures``. Action usage ------------ .. _param-omkafka-action-statsname: .. _omkafka.parameter.action.statsname: .. code-block:: rsyslog action(type="omkafka" statsName="producer-1") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfifo-file.rst0000644000000000000000000000013215216464435023637 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.134446334 30 ctime=1787067792.129682846 rsyslog-8.2608.0/doc/source/reference/parameters/imfifo-file.rst0000664000175000017500000000223215216464435023302 0ustar00rgerrger.. _param-imfifo-file: .. _imfifo.parameter.input.file: file ==== .. meta:: :description: Path to the named pipe (FIFO) to monitor. :keywords: rsyslog, imfifo, file, pipe .. index:: single: imfifo; file single: file .. summary-start Specifies the absolute filesystem path of the named pipe (FIFO) to read log messages from. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfifo`. :Name: file :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: yes :Introduced: 8.2606.0 Description ----------- The path to the named pipe (FIFO) to be monitored. This must be an absolute path. The FIFO must exist on the filesystem before Rsyslog starts; `imfifo` will not attempt to create it. If the file does not exist or is not a FIFO, an error will be reported at startup and the input instance will not be activated. Input usage ----------- .. _param-imfifo-input-file: .. _imfifo.parameter.input.file-usage: .. code-block:: rsyslog input(type="imfifo" file="/var/log/myfifo" tag="fifo-logs:") See also -------- See also :doc:`../../configuration/modules/imfifo`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-name-appendport.rst0000644000000000000000000000013115132733117025647 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.301486732 29 ctime=1787067792.57369112 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-name-appendport.rst0000666000175000017500000000311715132733117025320 0ustar00rgerrger.. _param-imudp-name-appendport: .. _imudp.parameter.input.name-appendport: Name.appendPort =============== .. index:: single: imudp; Name.appendPort single: Name.appendPort .. summary-start Appends listener port number to ``inputname``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Name.appendPort :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 7.3.9 Description ----------- Appends the port to the ``inputname`` property. Note that when no ``name`` is specified, the default of ``imudp`` is used and the port is appended to that default. So, for example, a listener port of 514 in that case will lead to an ``inputname`` of ``imudp514``. The ability to append a port is most useful when multiple ports are defined for a single input and each of the ``inputname`` values shall be unique. Note that there currently is no differentiation between IPv4/v6 listeners on the same port. Examples: .. code-block:: rsyslog module(load="imudp") input(type="imudp" port=["10514","10515","10516"] name="udp" name.appendPort="on") .. code-block:: rsyslog module(load="imudp") input(type="imudp" port=["10514","10515","10516"] name="" name.appendPort="on") Input usage ----------- .. _param-imudp-input-name-appendport: .. _imudp.parameter.input.name-appendport-usage: .. code-block:: rsyslog input(type="imudp" Name.appendPort="...") Notes ----- - Earlier documentation described the type as ``binary``; this maps to boolean. See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmsnmptrapd-tag.rst0000644000000000000000000000013115132733117024554 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.210466393 30 ctime=1787067792.906697326 rsyslog-8.2608.0/doc/source/reference/parameters/mmsnmptrapd-tag.rst0000666000175000017500000000263515132733117024231 0ustar00rgerrger.. _param-mmsnmptrapd-tag: .. _mmsnmptrapd.parameter.module.tag: tag === .. index:: single: mmsnmptrapd; tag single: tag .. summary-start Specifies the tag prefix that identifies messages for processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmsnmptrapd`. :Name: tag :Scope: module :Type: word (see :doc:`../../rainerscript/constant_strings`) :Default: module=snmptrapd :Required?: no :Introduced: at least 5.8.1, possibly earlier Description ----------- Tells the module which start string inside the tag to look for. The default is ``snmptrapd``. Note that a slash (``/``) is automatically appended to this tag for matching. You should not include a trailing slash unless you specifically need to match a double slash. For example, setting ``tag="tag/"`` results in a check for ``tag//`` at the start of the tag field. Module usage ------------ .. _param-mmsnmptrapd-module-tag: .. _mmsnmptrapd.parameter.module.tag-usage: .. code-block:: rsyslog module(load="mmsnmptrapd" tag="snmptrapd") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmsnmptrapd.parameter.legacy.mmsnmptrapdtag: - $mmsnmptrapdTag — maps to tag (status: legacy) .. index:: single: mmsnmptrapd; $mmsnmptrapdTag single: $mmsnmptrapdTag See also -------- See also :doc:`../../configuration/modules/mmsnmptrapd`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-addceetag.rst0000644000000000000000000000013115132733117024605 xustar0030 mtime=1768666703.903620178 29 atime=1787067672.21144777 30 ctime=1787067792.044681262 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-addceetag.rst0000666000175000017500000000171315132733117024256 0ustar00rgerrger.. _param-imfile-addceetag: .. _imfile.parameter.input.addceetag: .. _imfile.parameter.addceetag: addCeeTag ========= .. index:: single: imfile; addCeeTag single: addCeeTag .. summary-start Adds the ``@cee:`` cookie to the message when enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: addCeeTag :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Turns on or off the addition of the ``@cee:`` cookie to the message object. Input usage ----------- .. _param-imfile-input-addceetag: .. _imfile.parameter.input.addceetag-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" addCeeTag="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dirgroupnum.rst0000644000000000000000000000013215132411300025251 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.371450753 30 ctime=1787067793.150701872 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dirgroupnum.rst0000666000175000017500000000314715132411300024724 0ustar00rgerrger.. _param-omfile-dirgroupnum: .. _omfile.parameter.module.dirgroupnum: dirGroupNum =========== .. index:: single: omfile; dirGroupNum single: dirGroupNum .. summary-start Set the group for directories newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dirGroupNum :Scope: module, action :Type: integer :Default: module=process user's primary group; action=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the group for directories newly created. Please note that this setting does not affect the group of directories already existing. The parameter is a numerical ID, which is used regardless of whether the group actually exists. This can be useful if the group mapping is not available to rsyslog during startup. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-dirgroupnum: .. _omfile.parameter.module.dirgroupnum-usage: .. code-block:: rsyslog module(load="builtin:omfile" dirGroupNum="...") Action usage ------------ .. _param-omfile-action-dirgroupnum: .. _omfile.parameter.action.dirgroupnum: .. code-block:: rsyslog action(type="omfile" dirGroupNum="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dirgroupnum: - $DirGroupNum — maps to dirGroupNum (status: legacy) .. index:: single: omfile; $DirGroupNum single: $DirGroupNum See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdblookup-container.rst0000644000000000000000000000013215132733117025573 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.175447099 30 ctime=1787067792.758694568 rsyslog-8.2608.0/doc/source/reference/parameters/mmdblookup-container.rst0000666000175000017500000000162315132733117025243 0ustar00rgerrger.. _param-mmdblookup-container: .. _mmdblookup.parameter.module.container: container ========= .. index:: single: mmdblookup; container single: container .. summary-start Specifies the container for fields amended by mmdblookup. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdblookup`. :Name: container :Scope: module :Type: string (word) :Default: ``!iplocation`` :Required?: no :Introduced: 8.28.0 Description ----------- .. versionadded:: 8.28.0 This parameter specifies the JSON container (a JSON object) used to store the fields amended by mmdblookup within the rsyslog message. If not specified, it defaults to ``!iplocation``. Module usage ------------ .. _mmdblookup.parameter.module.container-usage: .. code-block:: rsyslog module(load="mmdblookup" container="!geo_ip") See also -------- See also :doc:`../../configuration/modules/mmdblookup`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-ratelimit-name.rst0000644000000000000000000000013215145046112025460 xustar0030 mtime=1771326538.940012672 30 atime=1787067674.190484663 30 ctime=1787067792.516690058 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-ratelimit-name.rst0000664000175000017500000000253015145046112025124 0ustar00rgerrger.. _param-imtcp-ratelimit-name: .. _imtcp.parameter.input.ratelimit-name: RateLimit.Name ============== .. index:: single: imtcp; RateLimit.Name single: RateLimit.Name .. summary-start Specifies the name of the rate limiting policy to use. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: RateLimit.Name :Scope: input :Type: string :Default: null :Required?: no :Introduced: 8.2602.0 Description ----------- Specifies the name of a rate limiting policy (defined via the top-level :ref:`ratelimit` object) to assert. If this parameter is set, the named policy is looked up and used. If the policy is not found, an error is reported. Using a named policy allows sharing rate limits across multiple inputs or managing them centrally. .. warning:: This parameter is mutually exclusive with :ref:`param-imtcp-ratelimit-interval` and :ref:`param-imtcp-ratelimit-burst`. If ``RateLimit.Name`` is specified, those parameters must **not** be used. Specifying both will result in a configuration error. Input usage ----------- .. _param-imtcp-input-ratelimit-name: .. _imtcp.parameter.input.ratelimit-name-usage: .. code-block:: rsyslog ratelimit(name="myLimit" interval="60" burst="100") input(type="imtcp" rateLimit.Name="myLimit") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-consoleloglevel.rst0000644000000000000000000000013215132733117026116 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.062463634 30 ctime=1787067792.232684765 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-consoleloglevel.rst0000666000175000017500000000331115132733117025562 0ustar00rgerrger.. _param-imklog-consoleloglevel: .. _imklog.parameter.module.consoleloglevel: ConsoleLogLevel ================ .. index:: single: imklog; ConsoleLogLevel single: ConsoleLogLevel .. summary-start Filters kernel console messages, printing only those with a severity up to the configured level. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: ConsoleLogLevel :Scope: module :Type: integer :Default: -1 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the console log level. If specified, only messages with up to the specified level are printed to the console. The default is -1, which means that the current settings are not modified. To get this behavior, do not specify ``consoleLogLevel`` in the configuration file. Note that this is a global parameter. Each time it is changed, the previous definition is reset. The active setting will be the last one defined when imklog actually starts processing. To avoid unexpected behavior, it is recommended to specify this directive only once. **Linux only**, ignored on other platforms (but may be specified). Module usage ------------ .. _param-imklog-module-consoleloglevel: .. _imklog.parameter.module.consoleloglevel-usage: .. code-block:: rsyslog module(load="imklog" consoleLogLevel="4") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.klogconsoleloglevel: - $klogConsoleLogLevel — maps to ConsoleLogLevel (status: legacy) .. index:: single: imklog; $klogConsoleLogLevel single: $klogConsoleLogLevel See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-errorfile.rst0000644000000000000000000000013115132733117026115 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.587473422 30 ctime=1787067792.981698723 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-errorfile.rst0000666000175000017500000000341115132733117025563 0ustar00rgerrger.. _param-omclickhouse-errorfile: .. _omclickhouse.parameter.input.errorfile: errorFile ========= .. index:: single: omclickhouse; errorFile single: errorFile single: omclickhouse; errorfile single: errorfile .. summary-start Specifies a file that receives bulk-mode failures along with the ClickHouse error response. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: errorFile :Scope: input :Type: word :Default: none :Required?: no :Introduced: not specified Description ----------- If specified, records failed in bulk mode are written to this file, including their error cause. Rsyslog itself does not process the file any more, but the idea behind that mechanism is that the user can create a script to periodically inspect the error file and react appropriately. As the complete request is included, it is possible to simply resubmit messages from that script. .. note:: When rsyslog has problems connecting to ClickHouse, a general error is assumed. However, if we receive negative responses during batch processing, we assume an error in the data itself (like a mandatory field is not filled in, a format error or something along those lines). Such errors cannot be solved by simply resubmitting the record. As such, they are written to the error file so that the user (script) can examine them and act appropriately. Note that e.g. after search index reconfiguration (e.g. dropping the mandatory attribute) a resubmit may be successful. Input usage ----------- .. _omclickhouse.parameter.input.errorfile-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" errorFile="clickhouse-error.log") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/immark-interval.rst0000644000000000000000000000013115132733117024543 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.299468053 29 ctime=1787067792.25168512 rsyslog-8.2608.0/doc/source/reference/parameters/immark-interval.rst0000666000175000017500000000203415132733117024211 0ustar00rgerrger.. _param-immark-interval: .. _immark.parameter.module.interval: interval ======== .. index:: single: immark; interval single: interval .. summary-start Specifies how often immark injects a mark message, in seconds. .. summary-end This parameter applies to :doc:`../../configuration/modules/immark`. :Name: interval :Scope: module :Type: integer (seconds) :Default: module=1200 (seconds) :Required?: no :Introduced: 3.0.0 Module usage ------------ .. _immark.parameter.module.interval-usage: .. code-block:: rsyslog module(load="immark" interval="1200") Legacy names (for reference) ---------------------------- Historic names/directives for compatibility. Do not use in new configs. .. _immark.parameter.legacy.markmessageperiod: - ``$MarkMessagePeriod`` — maps to interval (status: legacy) .. index:: single: immark; $MarkMessagePeriod single: $MarkMessagePeriod See also -------- .. seealso:: * ``action.writeAllMarkMessages`` in :doc:`../../configuration/actions` * :doc:`../../configuration/modules/immark` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmcount-appname.rst0000644000000000000000000000013215132733117024543 xustar0030 mtime=1768666703.912620314 30 atime=1787067672.044444656 30 ctime=1787067792.735694139 rsyslog-8.2608.0/doc/source/reference/parameters/mmcount-appname.rst0000666000175000017500000000253115132733117024212 0ustar00rgerrger.. _param-mmcount-appname: .. _mmcount.parameter.input.appname: appName ======= .. index:: single: mmcount; appName single: appName .. summary-start Selects the application name whose messages the mmcount action tracks. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmcount`. :Name: appName :Scope: input :Type: word :Default: none :Required?: yes :Introduced: 7.5.0 Description ----------- Specifies the syslog APP-NAME that must match for mmcount to process a message. When the application name of the current message does not match ``appName``, the action immediately returns without altering counters. If no match is found, no ``mmcount`` property is added to the message. For matching messages, mmcount increments counters based on the additional parameters. When :ref:`param-mmcount-key` is omitted, the module counts per-severity totals for the selected application. If :ref:`param-mmcount-key` is provided, counters are updated according to that parameter's logic. The updated total is written into the message's ``mmcount`` JSON property so later actions can react to it. Input usage ----------- .. _param-mmcount-appname-usage: .. _mmcount.parameter.input.appname-usage: .. code-block:: rsyslog action(type="mmcount" appName="gluster") See also -------- See also :doc:`../../configuration/modules/mmcount`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-container.rst0000644000000000000000000000013115216464435027036 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.445470774 29 ctime=1787067792.93269781 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-container.rst0000664000175000017500000000170015216464435026501 0ustar00rgerrger.. _param-omazureeventhubs-container: .. _omazureeventhubs.parameter.input.container: container ========= .. index:: single: omazureeventhubs; container single: container .. summary-start Identifies the Event Hubs instance that receives the formatted log messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: container :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- Specifies the name of the "Event Hubs Instance"—the specific event hub within the namespace—that should receive the forwarded log data. Define it unless ``amqp_address`` already points at the desired event hub. Input usage ----------- .. _omazureeventhubs.parameter.input.container-usage: .. code-block:: rsyslog action(type="omazureeventhubs" container="MyEventHub" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-usesystimestamp.rst0000644000000000000000000000013215132733117030255 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.826477877 30 ctime=1787067792.666692853 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-usesystimestamp.rst0000666000175000017500000000330515132733117027724 0ustar00rgerrger.. _param-imuxsock-syssock-usesystimestamp: .. _imuxsock.parameter.module.syssock-usesystimestamp: SysSock.UseSysTimeStamp ======================= .. index:: single: imuxsock; SysSock.UseSysTimeStamp single: SysSock.UseSysTimeStamp .. summary-start Obtains message time from the system instead of the message content. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.UseSysTimeStamp :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 5.9.1 Description ----------- The same as the input parameter ``UseSysTimeStamp``, but for the system log socket. This parameter instructs ``imuxsock`` to obtain message time from the system (via control messages) instead of using time recorded inside the message. This may be most useful in combination with systemd. Due to the usefulness of this functionality, we decided to enable it by default. As such, the behavior is slightly different than previous versions. However, we do not see how this could negatively affect existing environments. Module usage ------------ .. _param-imuxsock-module-syssock-usesystimestamp: .. _imuxsock.parameter.module.syssock-usesystimestamp-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.useSysTimeStamp="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogusesystimestamp: - $SystemLogUseSysTimeStamp — maps to SysSock.UseSysTimeStamp (status: legacy) .. index:: single: imuxsock; $SystemLogUseSysTimeStamp single: $SystemLogUseSysTimeStamp See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsontransform-policywatch.rst0000644000000000000000000000013215171370365027232 xustar0030 mtime=1776677109.118908099 30 atime=1787067672.582454686 30 ctime=1787067792.811695555 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsontransform-policywatch.rst0000664000175000017500000000347015171370365026702 0ustar00rgerrger.. meta:: :description: The mmjsontransform policyWatch parameter enables automatic reloads for watched policy files. :keywords: rsyslog, mmjsontransform, policyWatch, watched reload, yaml policy .. _param-mmjsontransform-policywatch: .. _mmjsontransform.parameter.input.policywatch: policyWatch =========== .. index:: single: mmjsontransform; policyWatch single: policyWatch .. summary-start Enables automatic reload of the configured policy file when it changes. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsontransform`. :Name: policyWatch :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled together with :ref:`policy `, ``mmjsontransform`` watches the configured YAML policy file and reloads it after the configured debounce interval. This is useful for targeted policy updates that should not wait for a full ``HUP`` cycle. The watcher monitors the file's parent directory and matches the configured basename, so common write-temp-and-rename editor save patterns also trigger a reload. If watch support is unavailable in the current build or runtime environment, rsyslog logs a warning and continues with ``HUP``-only reload behavior. If the updated policy is invalid, the reload is rejected and the previous in-memory policy remains active. Input usage ----------- .. _param-mmjsontransform-policywatch-usage: .. _mmjsontransform.parameter.input.policywatch-usage: .. code-block:: rsyslog action(type="mmjsontransform" policy="/etc/rsyslog/mmjsontransform-policy.yaml" policyWatch="on" input="$!raw" output="$!normalized") See also -------- See also the :doc:`main mmjsontransform module documentation <../../configuration/modules/mmjsontransform>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-cafile.rst0000644000000000000000000000013215132733117026504 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.237485539 30 ctime=1787067792.527690263 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-cafile.rst0000666000175000017500000000201115132733117026144 0ustar00rgerrger.. _param-imtcp-streamdriver-cafile: .. _imtcp.parameter.input.streamdriver-cafile: streamDriver.CAFile =================== .. index:: single: imtcp; streamDriver.CAFile single: streamDriver.CAFile .. summary-start Overrides ``DefaultNetstreamDriverCAFile`` for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: streamDriver.CAFile :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=global parameter :Required?: no :Introduced: 8.2108.0 Description ----------- .. versionadded:: 8.2108.0 This permits to override the ``DefaultNetstreamDriverCAFile`` global parameter on the ``input()`` level. For further details, see the global parameter. Input usage ----------- .. _param-imtcp-input-streamdriver-cafile: .. _imtcp.parameter.input.streamdriver-cafile-usage: .. code-block:: rsyslog input(type="imtcp" streamDriver.caFile="/etc/ssl/certs/ca.pem") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-permittedpeer.rst0000644000000000000000000000013215132733117026401 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.917479573 30 ctime=1787067792.437688586 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-permittedpeer.rst0000666000175000017500000000423215132733117026050 0ustar00rgerrger.. _param-imrelp-tls-permittedpeer: .. _imrelp.parameter.input.tls-permittedpeer: tls.permittedPeer ================= .. index:: single: imrelp; tls.permittedPeer single: tls.permittedPeer .. summary-start Restricts accepted clients to the listed certificate fingerprints or wildcard names. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.permittedPeer :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: Not documented Description ----------- The ``tls.permittedPeer`` setting places access restrictions on this listener. Only peers which have been listed in this parameter may connect. The certificate presented by the remote peer is used for its validation. The *peer* parameter lists permitted certificate fingerprints. Note that it is an array parameter, so either a single or multiple fingerprints can be listed. When a non-permitted peer connects, the refusal is logged together with its fingerprint. So if the administrator knows this was a valid request, he can simply add the fingerprint by copy and paste from the logfile to rsyslog.conf. To specify multiple fingerprints, just enclose them in braces like this: .. code-block:: none tls.permittedPeer=["SHA1:...1", "SHA1:....2"] To specify just a single peer, you can either specify the string directly or enclose it in braces. You may also use wildcards to match a larger number of permitted peers, e.g. ``*.example.com``. When using wildcards to match larger number of permitted peers, please know that the implementation is similar to Syslog RFC5425 which means: This wildcard matches any left-most DNS label in the server name. That is, the subject ``*.example.com`` matches the server names ``a.example.com`` and ``b.example.com``, but does not match ``example.com`` or ``a.b.example.com``. Input usage ----------- .. _param-imrelp-input-tls-permittedpeer-usage: .. _imrelp.parameter.input.tls-permittedpeer-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.permittedPeer=["SHA1:0123456789ABCDEF0123456789ABCDEF01234567"]) See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-keepalive-time.rst0000644000000000000000000000013215132733117025455 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.069482407 30 ctime=1787067792.482689424 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-keepalive-time.rst0000666000175000017500000000344715132733117025133 0ustar00rgerrger.. _param-imtcp-keepalive-time: .. _imtcp.parameter.module.keepalive-time: .. _imtcp.parameter.input.keepalive-time: KeepAlive.Time ============== .. index:: single: imtcp; KeepAlive.Time single: KeepAlive.Time .. summary-start Sets the interval between last data and first keepalive probe. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: KeepAlive.Time :Scope: module, input :Type: integer :Default: module=0, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further. The default, 0, means that the operating system defaults are used. This has only effect if keep-alive is enabled. The functionality may not be available on all platforms. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-keepalive-time: .. _imtcp.parameter.module.keepalive-time-usage: .. code-block:: rsyslog module(load="imtcp" keepAlive.time="...") Input usage ----------- .. _param-imtcp-input-keepalive-time: .. _imtcp.parameter.input.keepalive-time-usage: .. code-block:: rsyslog input(type="imtcp" port="514" keepAlive.time="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverkeepalive_time: - $InputTCPServerKeepAlive_time — maps to KeepAlive.Time (status: legacy) .. index:: single: imtcp; $InputTCPServerKeepAlive_time single: $InputTCPServerKeepAlive_time See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhdfs-omhdfshost.rst0000644000000000000000000000013215132733117025076 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.938461323 30 ctime=1787067793.224703252 rsyslog-8.2608.0/doc/source/reference/parameters/omhdfs-omhdfshost.rst0000666000175000017500000000220015132733117024536 0ustar00rgerrger.. _param-omhdfs-omhdfshost: .. _omhdfs.parameter.module.omhdfshost: omhdfsHost ========== .. index:: single: omhdfs; omhdfsHost single: omhdfsHost .. summary-start Selects the hostname or IP address of the HDFS system omhdfs connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhdfs`. :Name: omhdfsHost :Scope: module :Type: word :Default: default :Required?: no :Introduced: Not documented Description ----------- Name or IP address of the HDFS host to connect to. Module usage ------------ .. _omhdfs.parameter.module.omhdfshost-usage: .. code-block:: none $ModLoad omhdfs $omhdfsHost hdfs01.example.net $omhdfsFileName /var/log/hdfs/system.log # write all messages to the specified HDFS host *.* :omhdfs: Legacy names (for reference) ---------------------------- Historic names/directives for compatibility. Do not use in new configs. .. _omhdfs.parameter.legacy.omhdfshost: - ``$OMHDFSHost`` — maps to ``omhdfsHost`` (status: legacy) .. index:: single: omhdfs; $OMHDFSHost single: $OMHDFSHost See also -------- See also :doc:`../../configuration/modules/omhdfs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-name.rst0000644000000000000000000000013215216464435026520 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.880441599 30 ctime=1787067791.384668963 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-name.rst0000664000175000017500000000176715216464435026177 0ustar00rgerrger.. _param-imbeats-streamdriver-name: .. _imbeats.parameter.input.streamdriver-name: StreamDriver.Name ================= .. meta:: :description: Stream driver backend for imbeats. :keywords: rsyslog, imbeats, streamdriver name .. index:: single: imbeats; StreamDriver.Name single: StreamDriver.Name .. summary-start Select the netstrm backend used by imbeats, for example ``ptcp``, ``gtls``, or ``ossl``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.Name :Scope: input :Type: string :Default: input=ptcp :Required?: no :Introduced: 8.2604.0 Description ----------- Select the netstrm backend used by imbeats, for example ``ptcp``, ``gtls``, or ``ossl``. Input usage ----------- .. _param-imbeats-input-streamdriver-name: .. _imbeats.parameter.input.streamdriver-name-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.name="ossl") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-driverdirectory.rst0000644000000000000000000000013215132733117026441 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.351469022 30 ctime=1787067793.375706065 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-driverdirectory.rst0000666000175000017500000000267215132733117026116 0ustar00rgerrger.. _param-omlibdbi-driverdirectory: .. _omlibdbi.parameter.module.driverdirectory: DriverDirectory =============== .. index:: single: omlibdbi; DriverDirectory single: DriverDirectory .. summary-start Points libdbi to the directory that contains its driver shared objects. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: DriverDirectory :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: Not documented Description ----------- Set this global option only when libdbi cannot find its drivers automatically. It tells libdbi where the driver modules are installed. Most systems ship libdbi-driver packages that register the directory properly. Only installations that place drivers in nonstandard paths need this parameter. Module usage ------------ .. _param-omlibdbi-module-driverdirectory-usage: .. _omlibdbi.parameter.module.driverdirectory-usage: .. code-block:: rsyslog module(load="omlibdbi" driverDirectory="/usr/lib/libdbi") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbidriverdirectory: - $ActionLibdbiDriverDirectory — maps to DriverDirectory (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiDriverDirectory single: $ActionLibdbiDriverDirectory See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dircreatemode.rst0000644000000000000000000000013215132411300025505 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.324449876 30 ctime=1787067793.145701779 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dircreatemode.rst0000666000175000017500000000342415132411300025156 0ustar00rgerrger.. _param-omfile-dircreatemode: .. _omfile.parameter.module.dircreatemode: dirCreateMode ============= .. index:: single: omfile; dirCreateMode single: dirCreateMode .. summary-start Sets the creation mode for directories that are automatically generated. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dirCreateMode :Scope: module, action :Type: string (octal) :Default: module=0700; action=inherits module :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the file system permissions for directories automatically created by ``omfile``. The value must be a 4-digit octal number (e.g., ``0700``). When set at the module level, it defines the default mode for all ``omfile`` actions. When set at the action level, it overrides the module default for that specific action. Please note that the actual permissions depend on rsyslogd's process umask. If in doubt, use ``$umask 0000`` at the beginning of the configuration file to remove any restrictions. Module usage ------------ .. _param-omfile-module-dircreatemode: .. _omfile.parameter.module.dircreatemode-usage: .. code-block:: rsyslog module(load="builtin:omfile" dirCreateMode="0700") Action usage ------------ .. _param-omfile-action-dircreatemode: .. _omfile.parameter.action.dircreatemode: .. code-block:: rsyslog action(type="omfile" dirCreateMode="0755" ...) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dircreatemode: - $DirCreateMode — maps to dirCreateMode (status: legacy) .. index:: single: omfile; $DirCreateMode single: $DirCreateMode See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-uniqueretrycount.rst0000644000000000000000000000013215145046112027246 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.840440853 30 ctime=1787067792.720693859 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-uniqueretrycount.rst0000664000175000017500000000204215145046112026710 0ustar00rgerrger.. _param-mmanon-ipv4-uniqueretrycount: .. _mmanon.parameter.input.ipv4-uniqueretrycount: ipv4.uniqueRetryCount ===================== .. index:: single: mmanon; ipv4.uniqueRetryCount single: ipv4.uniqueRetryCount .. summary-start Sets the maximum retry count for IPv4 random-consistent-unique anonymization. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.uniqueRetryCount :Scope: input :Type: integer :Default: input=1000 :Required?: no :Introduced: 8.2410.0 Description ----------- Defines how many randomized replacements are attempted before giving up when ``ipv4.limitUniqueMaxRetries`` is enabled. The retry limit only applies to ``random-consistent-unique`` mode. Input usage ----------- .. _mmanon.parameter.input.ipv4-uniqueretrycount-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="random-consistent-unique" ipv4.limitUniqueMaxRetries="on" ipv4.uniqueRetryCount="500") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-addmetadata.rst0000644000000000000000000000013215216464435025145 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.273448926 30 ctime=1787067792.046681299 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-addmetadata.rst0000664000175000017500000000310615216464435024611 0ustar00rgerrger.. _param-imfile-addmetadata: .. _imfile.parameter.input.addmetadata: .. _imfile.parameter.addmetadata: addMetadata =========== .. index:: single: imfile; addMetadata single: addMetadata .. summary-start Turns metadata addition on or off; enabled by default when wildcards are used. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: addMetadata :Scope: input :Type: boolean :Default: auto (on with wildcards) :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Used to control whether file metadata is added to the message object. By default it is enabled for ``input()`` statements that contain wildcards and disabled otherwise. This parameter overrides the default behavior. When metadata is enabled, imfile adds these fields below ``$!metadata``: * ``filename``: the monitored file name, or the symlink name when the input matched a symlink. * ``fileoffset``: the byte offset at which the submitted record starts. * ``line_number``: the 1-based line or record number for the monitored file. The value is persisted in the imfile state file and continues across restarts when state is available. Input usage ----------- .. _param-imfile-input-addmetadata: .. _imfile.parameter.input.addmetadata-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" addMetadata="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-turbo.rst0000644000000000000000000000013215241075234025125 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.882696878 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-turbo.rst0000664000175000017500000000365215241075234024577 0ustar00rgerrger.. _param-mmnormalize-turbo: .. _mmnormalize.parameter.action.turbo: .. meta:: :description: Enable TurboVM acceleration for mmnormalize actions. :keywords: rsyslog, mmnormalize, turbo, liblognorm, normalization turbo ===== .. index:: single: mmnormalize; turbo single: turbo .. summary-start Enable TurboVM bytecode acceleration for normalization. Requires liblognorm 2.1.0+ built with ``--enable-turbo``. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: turbo :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: 8.2602.0 Description ----------- When enabled, mmnormalize compiles the rulebase into bytecode at startup and uses the TurboVM engine for SIMD-accelerated normalization. Each rsyslog worker thread gets an independent TurboVM context, ensuring thread-safe operation without mutexes on the hot path. Normalized results are stored as opaque snapshots that support zero-JSON field resolution: template access reads fields directly from the snapshot without building a json-c object tree. If bytecode compilation fails (e.g., unsupported parser types or inline data exceeding 60 bytes), mmnormalize falls back to standard ``ln_normalize()`` automatically. On HUP signal, per-worker TurboVM contexts are rebuilt. **Requirements:** - liblognorm >= 2.1.0 with ``--enable-turbo`` - The ``lognorm-features.h`` header must define ``LOGNORM_TURBO_SUPPORTED`` - rsyslog detects this automatically at ``./configure`` time Action usage ------------ .. _param-mmnormalize-action-turbo: .. _mmnormalize.parameter.action.turbo-usage: .. code-block:: rsyslog action(type="mmnormalize" rulebase="/etc/rsyslog.d/rules.rb" turbo="on") YAML usage ---------- .. code-block:: yaml actions: - type: mmnormalize rulebase: /etc/rsyslog.d/rules.rb turbo: on See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-mtu.rst0000644000000000000000000000013215145046112024434 xustar0030 mtime=1771326538.957012949 30 atime=1787067671.970443277 30 ctime=1787067793.568709662 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-mtu.rst0000664000175000017500000000127315145046112024103 0ustar00rgerrger.. _param-omudpspoof-mtu: .. _omudpspoof.parameter.action.mtu: mtu === .. index:: single: omudpspoof; mtu single: mtu .. summary-start Sets the maximum packet length that omudpspoof sends. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: mtu :Scope: action :Type: integer :Default: 1500 :Required?: no :Introduced: 5.1.3 Description ----------- Maximum packet length to send. Action usage ------------ .. _param-omudpspoof-action-mtu: .. _omudpspoof.parameter.action.mtu-usage: .. code-block:: rsyslog action(type="omudpspoof" target="192.0.2.1" mtu="1400") See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-startmsg-regex.rst0000644000000000000000000000013215132733117025661 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.396451218 30 ctime=1787067792.113682548 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-startmsg-regex.rst0000666000175000017500000000233415132733117025331 0ustar00rgerrger.. _param-imfile-startmsg-regex: .. _imfile.parameter.input.startmsg-regex: .. _imfile.parameter.startmsg-regex: startmsg.regex ============== .. index:: single: imfile; startmsg.regex single: startmsg.regex .. summary-start Regex that marks the beginning of a new message for multiline processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: startmsg.regex :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: no :Introduced: 8.10.0 Description ----------- Permits the processing of multi-line messages. When set, a message is terminated when the next one begins and ``startmsg.regex`` matches the line that identifies the start of a message. It is more flexible than ``readMode`` but has lower performance. ``startmsg.regex``, ``endmsg.regex`` and ``readMode`` cannot all be defined for the same input. Input usage ----------- .. _param-imfile-input-startmsg-regex: .. _imfile.parameter.input.startmsg-regex-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" startmsg.regex="^start") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-keepalive-interval.rst0000644000000000000000000000013215145046112026521 xustar0030 mtime=1771326538.950012835 30 atime=1787067673.157465405 30 ctime=1787067793.481708041 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-keepalive-interval.rst0000664000175000017500000000176215145046112026173 0ustar00rgerrger.. _param-omrelp-keepalive-interval: .. _omrelp.parameter.input.keepalive-interval: KeepAlive.Interval ================== .. index:: single: omrelp; KeepAlive.Interval single: KeepAlive.Interval .. summary-start Configures the time between successive TCP keepalive probes. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: KeepAlive.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The interval between subsequent keepalive probes. The default, 0, uses the operating system defaults. This only has an effect if keep-alive is enabled and may not be available on all platforms. Input usage ----------- .. _param-omrelp-input-keepalive-interval: .. _omrelp.parameter.input.keepalive-interval-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" keepAliveInterval="30") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmcount-key.rst0000644000000000000000000000013215132733117023712 xustar0030 mtime=1768666703.912620314 30 atime=1787067672.046444694 30 ctime=1787067792.737694176 rsyslog-8.2608.0/doc/source/reference/parameters/mmcount-key.rst0000666000175000017500000000246415132733117023366 0ustar00rgerrger.. _param-mmcount-key: .. _mmcount.parameter.input.key: key === .. index:: single: mmcount; key single: key .. summary-start Names the JSON property whose values are counted on matching messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmcount`. :Name: key :Scope: input :Type: word :Default: none (count messages per severity) :Required?: no :Introduced: 7.5.0 Description ----------- Directs mmcount to evaluate a structured property on each message that matches :ref:`param-mmcount-appname`. The value should be the RainerScript variable name used to access the JSON property (e.g., ``!gf_code``). If the named property is absent, mmcount leaves the message unchanged and no counter is modified. When the property exists, its value is converted into a string (JSON ``null`` becomes an empty string) and used to select which counter to increment. Without :ref:`param-mmcount-value`, mmcount creates a distinct counter for every observed value and writes the running total for that value into the message's ``mmcount`` property. Input usage ----------- .. _param-mmcount-key-usage: .. _mmcount.parameter.input.key-usage: .. code-block:: rsyslog action(type="mmcount" appName="glusterd" key="!gf_code") See also -------- See also :doc:`../../configuration/modules/mmcount`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-injectdelaymode.rst0000644000000000000000000000013215132733117026032 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.028444358 30 ctime=1787067791.936679249 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-injectdelaymode.rst0000666000175000017500000000340215132733117025477 0ustar00rgerrger.. _param-imdiag-injectdelaymode: .. _imdiag.parameter.module.injectdelaymode: InjectDelayMode =============== .. index:: single: imdiag; InjectDelayMode single: InjectDelayMode .. summary-start Sets the flow-control classification applied to messages injected by imdiag. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: InjectDelayMode :Scope: module :Type: string (``no``, ``light``, ``full``) :Default: module=no :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The diagnostics interface can inject messages into rsyslog's queues on demand. :ref:`InjectDelayMode ` assigns the flow-control policy used for those messages: ``no`` Injected messages bypass delay throttling. ``light`` Injected messages are marked "light delayable" so that queue congestion slows them while preserving capacity for non-throttleable inputs. ``full`` Injected messages are fully delayable and subject to the strongest throttling when queues fill up. Use this setting to prevent diagnostics traffic from overwhelming production inputs when the main queue is near capacity. Module usage ------------ .. _param-imdiag-module-injectdelaymode: .. _imdiag.parameter.module.injectdelaymode-usage: .. code-block:: rsyslog module(load="imdiag" injectDelayMode="light") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiaginjectdelaymode: - $IMDiagInjectDelayMode — maps to InjectDelayMode (status: legacy) .. index:: single: imdiag; $IMDiagInjectDelayMode single: $IMDiagInjectDelayMode See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-multiline.rst0000644000000000000000000000013215132733117024736 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.766476758 30 ctime=1787067792.361687169 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-multiline.rst0000666000175000017500000000154215132733117024406 0ustar00rgerrger.. _param-imptcp-multiline: .. _imptcp.parameter.input.multiline: MultiLine ========= .. index:: single: imptcp; MultiLine single: MultiLine .. summary-start Detects a new message only when LF is followed by '<' or end of input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: MultiLine :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Experimental parameter which causes rsyslog to recognize a new message only if the line feed is followed by a '<' or if there are no more characters. Input usage ----------- .. _param-imptcp-input-multiline: .. _imptcp.parameter.input.multiline-usage: .. code-block:: rsyslog input(type="imptcp" multiLine="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-uid.rst0000644000000000000000000000013215145046112023716 xustar0030 mtime=1771326538.948012803 30 atime=1787067673.239466934 30 ctime=1787067793.428707053 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-uid.rst0000664000175000017500000000142215145046112023361 0ustar00rgerrger.. _param-ommysql-uid: .. _ommysql.parameter.input.uid: UID === .. index:: single: ommysql; UID single: UID .. summary-start Defines the MariaDB/MySQL user account used for the connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: uid :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 7.x, possibly earlier Description ----------- This is the username used to authenticate with the MariaDB/MySQL server. Input usage ----------- .. _ommysql.parameter.input.uid-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" db="syslog_db" uid="user" pwd="pwd") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-port.rst0000644000000000000000000000013215216464435024057 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.823440536 30 ctime=1787067791.362668553 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-port.rst0000664000175000017500000000150015216464435023517 0ustar00rgerrger.. _param-imbeats-port: .. _imbeats.parameter.input.port: port ==== .. meta:: :description: Listening port for imbeats. :keywords: rsyslog, imbeats, port .. index:: single: imbeats; port single: port .. summary-start Set the TCP port on which the imbeats listener accepts Lumberjack v2 clients. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: port :Scope: input :Type: string :Default: input=none :Required?: yes :Introduced: 8.2604.0 Description ----------- Set the TCP port on which the imbeats listener accepts Lumberjack v2 clients. Input usage ----------- .. _param-imbeats-input-port: .. _imbeats.parameter.input.port-usage: .. code-block:: rsyslog input(type="imbeats" port="5044") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-compression.rst0000644000000000000000000000013215171370365026144 xustar0030 mtime=1776677109.118908099 30 atime=1787067673.517472116 30 ctime=1787067792.950698146 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-compression.rst0000664000175000017500000000321615171370365025612 0ustar00rgerrger.. _param-omazuredce-compression: .. _omazuredce.parameter.action.compression: .. meta:: :description: Reference for the omazuredce compression parameter. :keywords: rsyslog, omazuredce, compression, gzip, azure, logs ingestion compression =========== .. index:: single: omazuredce; compression single: compression .. summary-start Selects whether ``omazuredce`` compresses the HTTP request body and which gzip compression trade-off it uses. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: compression :Scope: action :Type: word :Default: off :Required?: no :Introduced: 8.2604.1 Description ----------- Set ``compression="off"`` to send the JSON batch uncompressed. Set ``compression`` to one of these values to gzip-compress the JSON request body and send it with ``Content-Encoding: gzip``: - ``speed``: use zlib's fastest compression level for lower CPU cost. - ``default``: use zlib's default compression level to balance CPU usage and compression ratio. - ``size``: use zlib's highest compression level to minimize transfer size at the cost of more CPU time. ``omazuredce`` still applies a ``max_batch_bytes`` size check before sending the request, so enabling compression reduces network transfer size without changing the module's batching semantics. Action usage ------------ .. _omazuredce.parameter.action.compression-usage: .. code-block:: rsyslog action(type="omazuredce" compression="default" ...) YAML usage ---------- .. code-block:: yaml actions: - type: omazuredce compression: default See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-flowcontrol.rst0000644000000000000000000000013215132733117025652 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.983480804 30 ctime=1787067792.606691735 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-flowcontrol.rst0000666000175000017500000000224015132733117025316 0ustar00rgerrger.. _param-imuxsock-flowcontrol: .. _imuxsock.parameter.input.flowcontrol: FlowControl =========== .. index:: single: imuxsock; FlowControl single: FlowControl .. summary-start Enables flow control on this input's socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: FlowControl :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies if flow control should be applied to the input being defined. Input usage ----------- .. _param-imuxsock-input-flowcontrol: .. _imuxsock.parameter.input.flowcontrol-usage: .. code-block:: rsyslog input(type="imuxsock" flowControl="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketflowcontrol: - $InputUnixListenSocketFlowControl — maps to FlowControl (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketFlowControl single: $InputUnixListenSocketFlowControl See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-createdirs.rst0000644000000000000000000000013215132411300025023 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.555454183 30 ctime=1787067793.141701705 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-createdirs.rst0000666000175000017500000000215615132411300024475 0ustar00rgerrger.. _param-omfile-createdirs: .. _omfile.parameter.module.createdirs: createDirs ========== .. index:: single: omfile; createDirs single: createDirs .. summary-start Create directories on an as-needed basis. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: createDirs :Scope: action :Type: boolean :Default: action=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Create directories on an as-needed basis Action usage ------------ .. _param-omfile-action-createdirs: .. _omfile.parameter.action.createdirs: .. code-block:: rsyslog action(type="omfile" createDirs="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.createdirs: - $CreateDirs — maps to createDirs (status: legacy) .. index:: single: omfile; $CreateDirs single: $CreateDirs See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-certfile.rst0000644000000000000000000000013215216464435027375 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.852441077 30 ctime=1787067791.373668758 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-certfile.rst0000664000175000017500000000203715216464435027043 0ustar00rgerrger.. _param-imbeats-streamdriver-certfile: .. _imbeats.parameter.input.streamdriver-certfile: StreamDriver.CertFile ===================== .. meta:: :description: Certificate file for imbeats TLS listeners. :keywords: rsyslog, imbeats, streamdriver certfile .. index:: single: imbeats; StreamDriver.CertFile single: StreamDriver.CertFile .. summary-start Specify the local certificate presented by TLS-enabled imbeats listeners. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.CertFile :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Specify the local certificate presented by TLS-enabled imbeats listeners. Input usage ----------- .. _param-imbeats-input-streamdriver-certfile: .. _imbeats.parameter.input.streamdriver-certfile-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.certFile="/etc/rsyslog/cert.pem") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdblookup-mmdbfile.rst0000644000000000000000000000013215132733117025370 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.183447248 30 ctime=1787067792.764694679 rsyslog-8.2608.0/doc/source/reference/parameters/mmdblookup-mmdbfile.rst0000666000175000017500000000163715132733117025045 0ustar00rgerrger.. _param-mmdblookup-mmdbfile: .. _mmdblookup.parameter.input.mmdbfile: mmdbfile ======== .. index:: single: mmdblookup; mmdbfile single: mmdbfile .. summary-start Specifies the path to the MaxMind DB file used for lookups. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdblookup`. :Name: mmdbfile :Scope: input :Type: string (word) :Default: none :Required?: yes :Introduced: 8.24.0 Description ----------- This parameter specifies the full path to the MaxMind DB file (for example, ``/etc/rsyslog.d/GeoLite2-City.mmdb``) to be used for IP lookups. Input usage ----------- .. _mmdblookup.parameter.input.mmdbfile-usage: .. code-block:: rsyslog action(type="mmdblookup" key="!clientip" mmdbFile="/etc/rsyslog.d/GeoLite2-City.mmdb" fields=["!continent!code", "!location"]) See also -------- See also :doc:`../../configuration/modules/mmdblookup`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-myprivkey.rst0000644000000000000000000000013215145046112025571 xustar0030 mtime=1771326538.954012901 30 atime=1787067672.768458154 30 ctime=1787067793.512708618 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-myprivkey.rst0000664000175000017500000000144415145046112025240 0ustar00rgerrger.. _param-omrelp-tls-myprivkey: .. _omrelp.parameter.input.tls-myprivkey: TLS.MyPrivKey ============= .. index:: single: omrelp; TLS.MyPrivKey single: TLS.MyPrivKey .. summary-start Specifies the path to the machine's private key for TLS. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.MyPrivKey :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The machine private key. Input usage ----------- .. _param-omrelp-input-tls-myprivkey: .. _omrelp.parameter.input.tls-myprivkey-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.myPrivKey="/path/to/key.pem") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-tag.rst0000644000000000000000000000013115132733117023631 xustar0030 mtime=1768666703.911620299 29 atime=1787067671.73243884 30 ctime=1787067792.691693319 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-tag.rst0000666000175000017500000000134515132733117023303 0ustar00rgerrger.. _param-mmaitag-tag: .. _mmaitag.parameter.action.tag: tag === .. index:: single: mmaitag; tag single: tag .. summary-start Names the message variable used to store the classification tag. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: tag :Scope: action :Type: string :Default: .aitag :Required?: no :Introduced: 9.0.0 Description ----------- Message variable name for the classification. If the name starts with ``$``, the leading ``$`` is stripped. Action usage ------------- .. _param-mmaitag-action-tag: .. _mmaitag.parameter.action.tag-usage: .. code-block:: rsyslog action(type="mmaitag" tag="$.aitag") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ratelimit-burst.rst0000644000000000000000000000013215132733117030125 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.337487403 30 ctime=1787067792.648692518 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ratelimit-burst.rst0000666000175000017500000000243015132733117027572 0ustar00rgerrger.. _param-imuxsock-syssock-ratelimit-burst: .. _imuxsock.parameter.module.syssock-ratelimit-burst: SysSock.RateLimit.Burst ======================= .. index:: single: imuxsock; SysSock.RateLimit.Burst single: SysSock.RateLimit.Burst .. summary-start Sets the rate-limiting burst size in messages for the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.RateLimit.Burst :Scope: module :Type: integer :Default: module=200 :Required?: no :Introduced: 5.7.1 Description ----------- Specifies the rate-limiting burst in number of messages. The maximum is ``(2^31)-1``. Module usage ------------ .. _param-imuxsock-module-syssock-ratelimit-burst: .. _imuxsock.parameter.module.syssock-ratelimit-burst-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.rateLimit.burst="100") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogratelimitburst: - $SystemLogRateLimitBurst — maps to SysSock.RateLimit.Burst (status: legacy) .. index:: single: imuxsock; $SystemLogRateLimitBurst single: $SystemLogRateLimitBurst See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imgssapi-inputgsslistenportfilename.rst0000644000000000000000000000013215132733117030755 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.612455245 30 ctime=1787067792.137682995 rsyslog-8.2608.0/doc/source/reference/parameters/imgssapi-inputgsslistenportfilename.rst0000666000175000017500000000271215132733117030425 0ustar00rgerrger.. _param-imgssapi-inputgsslistenportfilename: .. _imgssapi.parameter.input.inputgsslistenportfilename: InputGSSListenPortFileName ========================== .. index:: single: imgssapi; InputGSSListenPortFileName single: InputGSSListenPortFileName .. summary-start Writes the listener's bound port number to the specified file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imgssapi`. :Name: InputGSSListenPortFileName :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.38.0 Description ----------- Specifies the path to a file where the listener will write its bound port number upon startup. This is useful for integration with other services or in test environments that use dynamic ports. .. note:: If this parameter is set, a port of ``0`` for ``InputGSSServerRun`` is accepted. Otherwise, a port of ``0`` defaults to ``514``. Input usage ----------- .. _imgssapi.parameter.input.inputgsslistenportfilename-usage: .. code-block:: rsyslog module(load="imgssapi") $inputGssListenPortFileName "/var/run/rsyslog-gss-port" Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imgssapi.parameter.legacy.inputgsslistenportfilename: - $inputGssListenPortFileName — maps to InputGSSListenPortFileName (status: legacy) .. index:: single: imgssapi; $inputGssListenPortFileName single: $inputGssListenPortFileName See also -------- See also :doc:`../../configuration/modules/imgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-unlink.rst0000644000000000000000000000013215132733117026276 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.745476367 30 ctime=1787067792.657692685 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-unlink.rst0000666000175000017500000000205515132733117025746 0ustar00rgerrger.. _param-imuxsock-syssock-unlink: .. _imuxsock.parameter.module.syssock-unlink: SysSock.Unlink ============== .. index:: single: imuxsock; SysSock.Unlink single: SysSock.Unlink .. summary-start Controls whether the system socket is unlinked and recreated on start and stop. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.Unlink :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 7.3.9 Description ----------- If turned on (default), the system socket is unlinked and re-created when opened and also unlinked when finally closed. Note that this setting has no effect when running under systemd control (because systemd handles the socket. See the :ref:`imuxsock-systemd-details-label` section for details. Module usage ------------ .. _param-imuxsock-module-syssock-unlink: .. _imuxsock.parameter.module.syssock-unlink-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.unlink="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-confirmmessages.rst0000644000000000000000000000013215132733117026130 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.801458769 30 ctime=1787067793.455707556 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-confirmmessages.rst0000666000175000017500000000367415132733117025610 0ustar00rgerrger.. _param-omprog-confirmmessages: .. _omprog.parameter.action.confirmmessages: confirmMessages =============== .. index:: single: omprog; confirmMessages single: confirmMessages .. summary-start Waits for the program to acknowledge each message via stdout. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: confirmMessages :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.31.0 Description ----------- Specifies whether the external program provides feedback to rsyslog via stdout. When this switch is set to "on", rsyslog will wait for the program to confirm each received message. This feature facilitates error handling: instead of having to implement a retry logic, the external program can rely on the rsyslog queueing capabilities. To confirm a message, the program must write a line with the word ``OK`` to its standard output. If it writes a line containing anything else, rsyslog considers that the message could not be processed, keeps it in the action queue, and re-sends it to the program later (after the period specified by the :doc:`action.resumeInterval <../../configuration/actions>` parameter). In addition, when a new instance of the program is started, rsyslog will also wait for the program to confirm it is ready to start consuming logs. This prevents rsyslog from starting to send logs to a program that could not complete its initialization properly. .. seealso:: `Interface between rsyslog and external output plugins `_ Action usage ------------ .. _param-omprog-action-confirmmessages: .. _omprog.parameter.action.confirmmessages-usage: .. code-block:: rsyslog action(type="omprog" confirmMessages="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonrewrite-input.rst0000644000000000000000000000013115132733117025503 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.460452412 29 ctime=1787067792.80069535 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonrewrite-input.rst0000666000175000017500000000236715132733117025162 0ustar00rgerrger.. _param-mmjsonrewrite-input: .. _mmjsonrewrite.parameter.input.input: input ===== .. index:: single: mmjsonrewrite; input single: input .. summary-start Names the JSON property that supplies the tree to rewrite. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonrewrite`. :Name: input :Scope: input :Type: string :Default: none :Required?: yes :Introduced: 8.2410.0 Description ----------- Specifies which message property contains the JSON object that will be normalized. The value must be a property reference that begins with ``$`` (for example ``$!raw`` or ``$.structured``). ``mmjsonrewrite`` validates the expression at load time and rejects other prefixes. If the property is absent at runtime, the action returns without altering the message. When the property exists but does not resolve to a JSON object, the module logs an error and the action fails without creating the output tree. Input usage ----------- .. _param-mmjsonrewrite-input-usage: .. _mmjsonrewrite.parameter.input.input-usage: .. code-block:: rsyslog action(type="mmjsonrewrite" input="$!raw" output="$!structured") See also -------- See also the :doc:`main mmjsonrewrite module documentation <../../configuration/modules/mmjsonrewrite>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-address.rst0000644000000000000000000000013215132733117024361 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.803440164 30 ctime=1787067792.017680759 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-address.rst0000666000175000017500000000147015132733117024031 0ustar00rgerrger.. _param-imdtls-address: .. _imdtls.parameter.input.address: Address ======= .. index:: single: imdtls; address single: address .. summary-start Listens for DTLS syslog messages on the specified local IP address. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: address :Scope: input :Type: word :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Specifies the IP address on which the imdtls module will listen for incoming syslog messages. By default the module listens on all available network connections. Input usage ----------- .. _imdtls.parameter.input.address-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" address="192.0.2.1") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-erroronly.rst0000644000000000000000000000013015216464435026646 xustar0029 mtime=1782212893.98826557 30 atime=1787067672.121446092 29 ctime=1787067793.04969999 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-erroronly.rst0000664000175000017500000000242115216464435026313 0ustar00rgerrger.. _param-omelasticsearch-erroronly: .. _omelasticsearch.parameter.module.erroronly: errorOnly ========= .. index:: single: omelasticsearch; errorOnly single: errorOnly .. summary-start Limit bulk error-file output to failed records. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: errorOnly :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When enabled, omelasticsearch writes only records that Elasticsearch reported as failed to the configured :ref:`param-omelasticsearch-errorfile`. This option affects the format of the error file in bulk mode. Without it, the error file includes the full bulk request and response context for a failed bulk operation. With ``errorOnly="on"``, entries that succeeded inside the same bulk response are omitted from the error-file payload. Action usage ------------ .. _param-omelasticsearch-action-erroronly: .. _omelasticsearch.parameter.action.erroronly: .. code-block:: rsyslog action(type="omelasticsearch" errorFile="..." errorOnly="on") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`, :ref:`param-omelasticsearch-errorfile`, and :ref:`param-omelasticsearch-interleaved`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-compress.rst0000644000000000000000000000013015132733117024604 xustar0029 mtime=1768666703.91762039 29 atime=1787067673.22746671 30 ctime=1787067793.246703662 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-compress.rst0000666000175000017500000000173415132733117024261 0ustar00rgerrger.. _param-omhttp-compress: .. _omhttp.parameter.input.compress: compress ======== .. index:: single: omhttp; compress single: compress .. summary-start Enables GZIP compression of each HTTP payload sent by omhttp. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: compress :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- When switched to ``on`` each message will be compressed as GZIP using zlib's deflate compression algorithm. A ``Content-Encoding: gzip`` HTTP header is added to each request when this feature is used. Set the :ref:`param-omhttp-compress-level` for fine-grained control. Input usage ----------- .. _omhttp.parameter.input.compress-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" compress="on" compressLevel="6" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-ratelimit-interval.rst0000644000000000000000000000013215132733117026372 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.364487906 30 ctime=1787067792.584691325 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-ratelimit-interval.rst0000666000175000017500000000161315132733117026041 0ustar00rgerrger.. _param-imudp-ratelimit-interval: .. _imudp.parameter.input.ratelimit-interval: RateLimit.Interval ================== .. index:: single: imudp; RateLimit.Interval single: RateLimit.Interval .. summary-start Rate-limiting interval in seconds; ``0`` disables throttling. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: RateLimit.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: 7.3.1 Description ----------- The rate-limiting interval in seconds. Value 0 turns off rate limiting. Set it to a number of seconds (5 recommended) to activate rate-limiting. Input usage ----------- .. _param-imudp-input-ratelimit-interval: .. _imudp.parameter.input.ratelimit-interval-usage: .. code-block:: rsyslog input(type="imudp" RateLimit.Interval="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-apikeyfile.rst0000644000000000000000000000013215171370365025074 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.799458731 30 ctime=1787067792.154683312 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-apikeyfile.rst0000664000175000017500000000247015171370365024543 0ustar00rgerrger.. meta:: :description: Configure imhttp to protect an input with API key authentication. :keywords: rsyslog, imhttp, apikeyfile, api key authentication, http .. _param-imhttp-apikeyfile: .. _imhttp.parameter.input.apikeyfile: .. _imhttp-apikeyfile: apiKeyFile ========== .. index:: single: imhttp; apiKeyFile single: apiKeyFile .. summary-start Protects an imhttp input with API key authentication using tokens listed in a file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: apiKeyFile :Scope: input :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- If set, imhttp reads one API key token per line from the specified file and accepts matching HTTP ``Authorization: ApiKey`` or ``X-API-Key`` credentials. Leading whitespace after ``ApiKey`` and ``X-API-Key`` is ignored. Blank lines and lines starting with ``#`` are ignored. If both ``basicAuthFile`` and ``apiKeyFile`` are configured for the same input, either authentication method is accepted. Input usage ----------- .. _imhttp.parameter.input.apikeyfile-usage: .. code-block:: rsyslog input( type="imhttp" endpoint="/ingest" apiKeyFile="/etc/rsyslog/api-keys.txt" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-pollinginterval.rst0000644000000000000000000000013215132411300026431 xustar0030 mtime=1768559296.193884485 30 atime=1787067671.727438747 30 ctime=1787067791.980680069 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-pollinginterval.rst0000666000175000017500000000161315132411300026100 0ustar00rgerrger.. _param-imdocker-pollinginterval: .. _imdocker.parameter.module.pollinginterval: PollingInterval =============== .. index:: single: imdocker; PollingInterval single: PollingInterval .. summary-start Seconds between ``List Containers`` polls for new containers; default ``60``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: PollingInterval :Scope: module :Type: integer :Default: module=60 :Required?: no :Introduced: 8.41.0 Description ----------- Specifies the polling interval in seconds. imdocker polls for new containers by calling the ``List containers`` Docker API. Module usage ------------ .. _param-imdocker-module-pollinginterval: .. _imdocker.parameter.module.pollinginterval-usage: .. code-block:: rsyslog module(load="imdocker" PollingInterval="...") See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-prioritystring.rst0000644000000000000000000000013215145046112026642 xustar0030 mtime=1771326538.955012917 30 atime=1787067672.853459738 30 ctime=1787067793.519708749 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-prioritystring.rst0000664000175000017500000000267315145046112026316 0ustar00rgerrger.. _param-omrelp-tls-prioritystring: .. _omrelp.parameter.input.tls-prioritystring: TLS.PriorityString ================== .. index:: single: omrelp; TLS.PriorityString single: TLS.PriorityString .. summary-start Passes a custom GnuTLS priority string to control TLS parameters. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.PriorityString :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- This parameter permits to specify the so-called "priority string" to GnuTLS. This string gives complete control over all crypto parameters, including compression setting. For this reason, when the prioritystring is specified, the "tls.compression" parameter has no effect and is ignored. Full information about how to construct a priority string can be found in the GnuTLS manual. At the time of this writing, this information was contained in `section 6.10 of the GnuTLS manual `__. **Note: this is an expert parameter.** Do not use if you do not exactly know what you are doing. Input usage ----------- .. _param-omrelp-input-tls-prioritystring: .. _omrelp.parameter.input.tls-prioritystring-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.priorityString="NORMAL") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-variable.rst0000644000000000000000000000013215132733117025557 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.873460111 30 ctime=1787067792.886696953 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-variable.rst0000666000175000017500000000205615132733117025230 0ustar00rgerrger.. _param-mmnormalize-variable: .. _mmnormalize.parameter.action.variable: variable ======== .. index:: single: mmnormalize; variable single: variable .. summary-start Normalizes the content of a specified variable instead of the default ``msg`` property. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: variable :Scope: action :Type: word :Default: action=msg :Required?: no :Introduced: 8.5.1 Description ----------- .. versionadded:: 8.5.1 Specifies if a variable instead of property ``msg`` should be used for normalization. A variable can be property, local variable, json-path etc. Please note that :ref:`param-mmnormalize-userawmsg` overrides this parameter, so if it is set, ``variable`` will be ignored and raw message will be used. Action usage ------------- .. _param-mmnormalize-action-variable: .. _mmnormalize.parameter.action.variable-usage: .. code-block:: rsyslog action(type="mmnormalize" variable="$.foo") See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-resetcounters.rst0000644000000000000000000000013215132733117026211 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.452470905 30 ctime=1787067792.308686182 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-resetcounters.rst0000666000175000017500000000301215132733117025653 0ustar00rgerrger.. _param-impstats-resetcounters: .. _impstats.parameter.module.resetcounters: resetcounters ============= .. index:: single: impstats; resetcounters single: resetcounters .. summary-start Controls whether impstats resets counters after emitting them so they show deltas. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: resetcounters :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- When set to ``on``, counters are automatically reset after they are emitted. In that case, they contain only deltas to the last value emitted. When set to ``off``, counters always accumulate their values. Note that in auto-reset mode not all counters can be reset. Some counters (like queue size) are directly obtained from internal objects and cannot be modified. Also, auto-resetting introduces some additional slight inaccuracies due to the multi-threaded nature of rsyslog and the fact that for performance reasons it cannot serialize access to counter variables. As an alternative to auto-reset mode, you can use rsyslog's statistics manipulation scripts to create delta values from the regular statistic logs. This is the suggested method if deltas are not necessarily needed in real-time. Module usage ------------ .. _impstats.parameter.module.resetcounters-usage: .. code-block:: rsyslog module(load="impstats" resetCounters="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-filenamerulebase.rst0000644000000000000000000000013115132733117027443 xustar0030 mtime=1768666703.914620344 29 atime=1787067672.67545642 30 ctime=1787067792.840696096 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-filenamerulebase.rst0000666000175000017500000000205015132733117027107 0ustar00rgerrger.. _param-mmkubernetes-filenamerulebase: .. _mmkubernetes.parameter.action.filenamerulebase: filenamerulebase ================ .. index:: single: mmkubernetes; filenamerulebase single: filenamerulebase .. summary-start Specifies the rulebase file used to match json-file log filenames. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: filenamerulebase :Scope: action :Type: word :Default: /etc/rsyslog.d/k8s_filename.rulebase :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When processing json-file logs, this is the rulebase used to match the filename and extract metadata. For the actual rules, see :ref:`param-mmkubernetes-filenamerules`. Action usage ------------ .. _param-mmkubernetes-action-filenamerulebase: .. _mmkubernetes.parameter.action.filenamerulebase-usage: .. code-block:: rsyslog action(type="mmkubernetes" filenameRuleBase="/etc/rsyslog.d/k8s_filename.rulebase") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-readmode.rst0000644000000000000000000000013215132733117024465 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.404451368 30 ctime=1787067792.099682287 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-readmode.rst0000666000175000017500000000311715132733117024135 0ustar00rgerrger.. _param-imfile-readmode: .. _imfile.parameter.input.readmode: .. _imfile.parameter.readmode: readMode ======== .. index:: single: imfile; readMode single: readMode .. summary-start Selects a built-in method for detecting multi-line messages (0–2). .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: readMode :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Provides support for processing some standard types of multi-line messages. It is less flexible than ``startmsg.regex`` or ``endmsg.regex`` but offers higher performance. ``readMode``, ``startmsg.regex`` and ``endmsg.regex`` cannot all be defined for the same input. The value ranges from 0 to 2: - 0 – line based (**default**; each line is a new message) - 1 – paragraph (blank line separates log messages) - 2 – indented (lines starting with a space or tab belong to the previous message) Input usage ----------- .. _param-imfile-input-readmode: .. _imfile.parameter.input.readmode-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" readMode="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilereadmode: - ``$InputFileReadMode`` — maps to readMode (status: legacy) .. index:: single: imfile; $InputFileReadMode single: $InputFileReadMode See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-workaroundjournalbug.rst0000644000000000000000000000013215132411300027707 xustar0030 mtime=1768559296.196884533 30 atime=1787067672.900460614 30 ctime=1787067792.213684411 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-workaroundjournalbug.rst0000666000175000017500000000224615132411300027361 0ustar00rgerrger.. _param-imjournal-workaroundjournalbug: .. _imjournal.parameter.module.workaroundjournalbug: .. meta:: :tag: module:imjournal :tag: parameter:WorkAroundJournalBug WorkAroundJournalBug ==================== .. index:: single: imjournal; WorkAroundJournalBug single: WorkAroundJournalBug .. summary-start Legacy flag with no current effect; retained for compatibility. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: WorkAroundJournalBug :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.37.0 Description ----------- Originally enabled a workaround for a journald bug. The option has had no effect since version 8.1910.0 and remains only for backward compatibility. Module usage ------------ .. _param-imjournal-module-workaroundjournalbug: .. _imjournal.parameter.module.workaroundjournalbug-usage: .. code-block:: rsyslog module(load="imjournal" WorkAroundJournalBug="...") Notes ----- - Historic documentation called this a ``binary`` option; it is boolean. - Deprecated; enabling or disabling changes nothing. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-defaultactionqueuetimeoutshutdown0000644000000000000000000000013115171370365031161 xustar0030 mtime=1776677109.116908069 29 atime=1787067672.00544393 30 ctime=1787067791.934679212 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-defaultactionqueuetimeoutshutdown.rst0000664000175000017500000000316115171370365031436 0ustar00rgerrger.. _param-imdiag-defaultactionqueuetimeoutshutdown: .. _imdiag.parameter.module.defaultactionqueuetimeoutshutdown: .. meta:: :description: Reference for the imdiag defaultActionQueueTimeoutShutdown module parameter. :keywords: rsyslog, imdiag, defaultactionqueuetimeoutshutdown, testbench, timeout, action queue DefaultActionQueueTimeoutShutdown ================================== .. index:: single: imdiag; DefaultActionQueueTimeoutShutdown .. summary-start Sets the default action queue shutdown timeout at config load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: DefaultActionQueueTimeoutShutdown :Scope: module :Type: integer (milliseconds) :Default: 20000 :Required?: no :Introduced: 8.x Description ----------- Sets ``globals.actq_dflt_toQShutdown`` — the default shutdown timeout for action queues created after this point — at config-load time. This only affects action queues that do not specify their own timeout. The testbench uses this to ensure action queues drain cleanly under test conditions. .. note:: This parameter affects action queues created *after* the module is loaded. Existing queues are unaffected. Override per-test via ``RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN`` before ``generate_conf``. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" defaultActionQueueTimeoutShutdown="20000") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" defaultactionqueuetimeoutshutdown: "20000" See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-parsetrusted.rst0000644000000000000000000000013015132733117026025 xustar0030 mtime=1768666703.910620284 29 atime=1787067674.06748237 29 ctime=1787067792.61769194 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-parsetrusted.rst0000666000175000017500000000222615132733117025477 0ustar00rgerrger.. _param-imuxsock-parsetrusted: .. _imuxsock.parameter.input.parsetrusted: ParseTrusted ============ .. index:: single: imuxsock; ParseTrusted single: ParseTrusted .. summary-start Turns annotation data into JSON fields when annotation is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: ParseTrusted :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Equivalent to the ``SysSock.ParseTrusted`` module parameter, but applies to the input that is being defined. Input usage ----------- .. _param-imuxsock-input-parsetrusted: .. _imuxsock.parameter.input.parsetrusted-usage: .. code-block:: rsyslog input(type="imuxsock" parseTrusted="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.parsetrusted: - $ParseTrusted — maps to ParseTrusted (status: legacy) .. index:: single: imuxsock; $ParseTrusted single: $ParseTrusted See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-labels.rst0000644000000000000000000000013215145046112025517 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.493471669 30 ctime=1787067792.291685865 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-labels.rst0000664000175000017500000000151215145046112025162 0ustar00rgerrger.. _param-impstats-push-labels: .. _impstats.parameter.module.push-labels: push.labels =========== .. index:: single: impstats; push.labels single: push.labels .. summary-start Adds static labels (``key=value``) to every pushed metric. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.labels :Scope: module :Type: array (strings) :Default: module=none :Required?: no :Introduced: 8.2602.0 Description ----------- Defines an array of labels that will be attached to all metrics. Each entry must be a ``key=value`` string. Module usage ------------ .. _impstats.parameter.module.push-labels-usage: .. code-block:: rsyslog module(load="impstats" push.labels=["env=dev", "instance=rsyslog-1"]) See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-ruleset.rst0000644000000000000000000000013215216464435024556 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.827440611 30 ctime=1787067791.365668609 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-ruleset.rst0000664000175000017500000000157015216464435024225 0ustar00rgerrger.. _param-imbeats-ruleset: .. _imbeats.parameter.input.ruleset: ruleset ======== .. meta:: :description: Ruleset binding for imbeats. :keywords: rsyslog, imbeats, ruleset .. index:: single: imbeats; ruleset single: ruleset .. summary-start Bind the imbeats input to a specific ruleset instead of the default ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: ruleset :Scope: input :Type: string :Default: input=default ruleset :Required?: no :Introduced: 8.2604.0 Description ----------- Bind the imbeats input to a specific ruleset instead of the default ruleset. Input usage ----------- .. _param-imbeats-input-ruleset: .. _imbeats.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" ruleset="beats") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-defaulttz.rst0000644000000000000000000000013215132733117024560 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.220485222 30 ctime=1787067792.564690952 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-defaulttz.rst0000666000175000017500000000302415132733117024225 0ustar00rgerrger.. _param-imudp-defaulttz: .. _imudp.parameter.input.defaulttz: DefaultTZ ========= .. index:: single: imudp; DefaultTZ single: DefaultTZ .. summary-start Experimental default timezone applied when none present. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: DefaultTZ :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This is an **experimental** parameter; details may change at any time and it may also be discontinued without any early warning. Permits to set a default timezone for this listener. This is useful when working with legacy syslog (RFC3164 et al) residing in different timezones. If set it will be used as timezone for all messages **that do not contain timezone info**. Currently, the format **must** be ``+/-hh:mm``, e.g. ``-05:00``, ``+01:30``. Other formats, including TZ names (like EST) are NOT yet supported. Note that consequently no daylight saving settings are evaluated when working with timezones. If an invalid format is used, "interesting" things can happen, among them malformed timestamps and ``rsyslogd`` segfaults. This will obviously be changed at the time this feature becomes non-experimental. Input usage ----------- .. _param-imudp-input-defaulttz: .. _imudp.parameter.input.defaulttz-usage: .. code-block:: rsyslog input(type="imudp" DefaultTZ="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-windowtimeout.rst0000644000000000000000000000013215241075234026002 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.676579624 30 ctime=1787067791.398669224 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-windowtimeout.rst0000664000175000017500000000336415241075234025454 0ustar00rgerrger.. _param-imbeats-windowtimeout: .. _imbeats.parameter.input.windowtimeout: windowTimeout ============= .. meta:: :description: Absolute deadline for completing an advertised imbeats Lumberjack window. :keywords: rsyslog, imbeats, windowTimeout, window deadline, Lumberjack .. index:: single: imbeats; windowTimeout single: windowTimeout .. summary-start Set an absolute deadline for completing an advertised Lumberjack event window. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: windowTimeout :Scope: input :Type: nonnegative integer :Default: input=300 :Required?: no :Introduced: 8.2608.0 Description ----------- Set the maximum number of seconds allowed between accepting a Lumberjack ``W`` frame and receiving all events it advertises. The deadline is absolute: receiving complete event frames does not extend it. This prevents a client from retaining an incomplete batch and its session slot indefinitely by periodically sending valid events. When the deadline expires, ``imbeats`` closes the session, releases the incomplete batch, and does not acknowledge it. The deadline ends before a complete, sequence-valid batch enters submission. The value ``0`` disables the window timeout. The independent :ref:`param-imbeats-idletimeout` and :ref:`param-imbeats-frametimeout` settings may still close the session earlier. Input usage ----------- .. _param-imbeats-input-windowtimeout: .. _imbeats.parameter.input.windowtimeout-usage: RainerScript: .. code-block:: rsyslog input(type="imbeats" port="5044" windowTimeout="300") YAML: .. code-block:: yaml inputs: - type: imbeats port: 5044 windowTimeout: 300 See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-tlscfgcmd.rst0000644000000000000000000000013115132733117025475 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.946480114 29 ctime=1787067792.44168866 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-tlscfgcmd.rst0000666000175000017500000000330615132733117025146 0ustar00rgerrger.. _param-imrelp-tls-tlscfgcmd: .. _imrelp.parameter.input.tls-tlscfgcmd: tls.tlsCfgCmd ============= .. index:: single: imrelp; tls.tlsCfgCmd single: tls.tlsCfgCmd .. summary-start Forwards SSL_CONF-style commands to OpenSSL when using the openssl backend. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.tlsCfgCmd :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2001.0 Description ----------- The setting can be used if :ref:`param-imrelp-tls-tlslib` is set to "openssl" to pass configuration commands to the openssl library. OpenSSL Version 1.0.2 or higher is required for this feature. A list of possible commands and their valid values can be found in the `OpenSSL documentation `_. The setting can be single or multiline, each configuration command is separated by linefeed (\n). Command and value are separated by equal sign (=). Here are a few samples: Example 1 --------- This will allow all protocols except for SSLv2 and SSLv3: .. code-block:: none tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3" Example 2 --------- This will allow all protocols except for SSLv2, SSLv3 and TLSv1. It will also set the minimum protocol to TLSv1.2. .. code-block:: none tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1 MinProtocol=TLSv1.2" Input usage ----------- .. _param-imrelp-input-tls-tlscfgcmd-usage: .. _imrelp.parameter.input.tls-tlscfgcmd-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.tlsLib="openssl" tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-azureport.rst0000644000000000000000000000013215216464435027110 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.430470495 30 ctime=1787067792.930697773 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-azureport.rst0000664000175000017500000000227615216464435026563 0ustar00rgerrger.. _param-omazureeventhubs-azureport: .. _omazureeventhubs.parameter.input.azureport: azureport ========= .. index:: single: omazureeventhubs; azureport single: azureport .. summary-start Defines the TCP port used when connecting to the Event Hubs namespace. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: azureport :Scope: input :Type: word :Default: input=5671 :Required?: no :Introduced: v8.2304 Description ----------- Specifies the TCP port number used by the Event Hubs instance for incoming connections. The default port number for Event Hubs is 5671 for connections over the AMQP Secure Sockets Layer (SSL) protocol. This property is usually optional in the configuration file of the rsyslog output plugin, as the default value of 5671 is typically used. When ``amqp_address`` is specified, the module ignores ``azurePort`` and always uses the default. Input usage ----------- .. _omazureeventhubs.parameter.input.azureport-usage: .. code-block:: rsyslog action(type="omazureeventhubs" azureHost="example.servicebus.windows.net" azurePort="5671" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-compression-zstd-workers.rst0000644000000000000000000000013215132411300027713 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.388451069 30 ctime=1787067793.138701649 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-compression-zstd-workers.rst0000666000175000017500000000304615132411300027364 0ustar00rgerrger.. _param-omfile-compression-zstd-workers: .. _omfile.parameter.module.compression-zstd-workers: compression.zstd.workers ======================== .. index:: single: omfile; compression.zstd.workers single: compression.zstd.workers .. summary-start In zstd mode, this enables to configure zstd-internal compression worker threads. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: compression.zstd.workers :Scope: module :Type: positive-integer :Default: module=zlib library default :Required?: no :Introduced: 8.2208.0 Description ----------- In zstd mode, this enables to configure zstd-internal compression worker threads. This setting has nothing to do with rsyslog workers. The zstd library provides an enhanced worker thread pool which permits multithreaed compression of serial data streams. Rsyslog fully supports this mode for optimal performance. Please note that for this parameter to have an effect, the zstd library must be compiled with multithreading support. As of this writing (2022), this is **not** the case for many frequently used distros and distro versions. In this case, you may want to custom install the zstd library with threading enabled. Note that this does not require a rsyslog rebuild. Module usage ------------ .. _param-omfile-module-compression-zstd-workers: .. _omfile.parameter.module.compression-zstd-workers-usage: .. code-block:: rsyslog module(load="builtin:omfile" compression.zstd.workers="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ratelimit-name.rst0000644000000000000000000000013215171370365027713 xustar0030 mtime=1776677109.117908084 30 atime=1787067673.717475845 30 ctime=1787067792.653692611 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ratelimit-name.rst0000664000175000017500000000134315171370365027360 0ustar00rgerrger.. index:: ! imuxsock; SysSock.RateLimit.Name .. _param-imuxsock-syssock-ratelimit-name: SysSock.RateLimit.Name ====================== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use for the system log socket. The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``syssock.ratelimit.interval`` and ``syssock.ratelimit.burst``. If ``syssock.ratelimit.name`` is specified, local limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dynafile-dangerouspermitpathescap0000644000000000000000000000013215241075234030776 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.156701984 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dynafile-dangerouspermitpathescape.rst0000664000175000017500000000612315241075234031420 0ustar00rgerrger.. _param-omfile-dynafile-dangerouspermitpathescape: .. _omfile.parameter.module.dynafile-dangerouspermitpathescape: .. _omfile.parameter.action.dynafile-dangerouspermitpathescape: dynafile.dangerousPermitPathEscape ================================== .. meta:: :description: Permit omfile dynafile paths to escape the configured base path. :keywords: rsyslog, omfile, dynafile, path traversal, security, dangerous .. index:: single: omfile; dynafile.dangerousPermitPathEscape single: dynafile.dangerousPermitPathEscape .. summary-start Dangerous fallback option that permits rendered dynafile paths to escape the fixed path prefix configured in the dynafile template. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dynafile.dangerousPermitPathEscape :Scope: module, action :Type: boolean :Default: module=off; action=inherits module :Required?: no :Introduced: not specified Description ----------- By default, omfile validates rendered :ref:`param-omfile-dynafile` paths against the fixed path prefix configured in the dynafile template. For example, a dynafile template that starts with ``/var/log/`` must render paths below that configured base. Message-derived fields such as ``%HOSTNAME%`` must not use ``..`` components to escape that location. Set this parameter to ``on`` only as a temporary compatibility fallback for a trusted legacy configuration. At the module scope, it sets the default for all ``omfile`` actions; an action-level setting overrides that default. Enabling it allows message-derived dynafile names to escape the configured path prefix. If untrusted data can reach the dynafile template, rsyslog may create or overwrite any file that the rsyslog process user is allowed to write. Only operating-system permissions, mandatory access controls, mount options, and similar external controls remain as protection. This also restores the historical behavior for opaque legacy dynafile templates that render absolute paths or relative paths containing leading ``..`` components. Without this explicit opt-in, those paths are rejected by the default fallback guard. Before enabling this option, reconsider the use case. Prefer changing the dynafile template so that untrusted fields cannot select parent directories or absolute paths. For network-sourced fields, keep this option disabled. Module usage ------------ .. _param-omfile-module-dynafile-dangerouspermitpathescape: .. _omfile.parameter.module.dynafile-dangerouspermitpathescape-usage: .. code-block:: rsyslog module(load="builtin:omfile" dynafile.dangerousPermitPathEscape="on") Use module scope only when every affected action is trusted. Prefer an action-level setting when compatibility is needed for one action only. Action usage ------------ .. _param-omfile-action-dynafile-dangerouspermitpathescape: .. code-block:: rsyslog action(type="omfile" dynafile="legacyDynFile" dynafile.dangerousPermitPathEscape="on") See also -------- See also :doc:`../../configuration/modules/omfile`, :doc:`omfile-dynafile`, and :doc:`omfile-dynafile-restricttemplatetype`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-filegroupnum.rst0000644000000000000000000000013115132411300025411 xustar0030 mtime=1768559296.210884754 29 atime=1787067672.35145038 30 ctime=1787067793.177702376 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-filegroupnum.rst0000666000175000017500000000311615132411300025061 0ustar00rgerrger.. _param-omfile-filegroupnum: .. _omfile.parameter.module.filegroupnum: fileGroupNum ============ .. index:: single: omfile; fileGroupNum single: fileGroupNum .. summary-start Set the group for files newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: fileGroupNum :Scope: module, action :Type: integer :Default: module=process user's primary group; action=system default :Required?: no :Introduced: 7.5.8 Description ----------- Set the group for files newly created. Please note that this setting does not affect the group of files already existing. The parameter is a numerical ID, which is used regardless of whether the group actually exists. This can be useful if the group mapping is not available to rsyslog during startup. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-filegroupnum: .. _omfile.parameter.module.filegroupnum-usage: .. code-block:: rsyslog module(load="builtin:omfile" fileGroupNum="...") Action usage ------------ .. _param-omfile-action-filegroupnum: .. _omfile.parameter.action.filegroupnum: .. code-block:: rsyslog action(type="omfile" fileGroupNum="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.filegroupnum: - $FileGroupNum — maps to fileGroupNum (status: legacy) .. index:: single: omfile; $FileGroupNum single: $FileGroupNum See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-limituniquemaxretrie0000644000000000000000000000013115145046112030731 xustar0030 mtime=1771326538.941012688 29 atime=1787067671.91644227 30 ctime=1787067792.700693487 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-limituniquemaxretries.rst0000664000175000017500000000242415145046112031372 0ustar00rgerrger.. _param-mmanon-embeddedipv4-limituniquemaxretries: .. _mmanon.parameter.input.embeddedipv4-limituniquemaxretries: embeddedIpv4.limitUniqueMaxRetries ================================== .. index:: single: mmanon; embeddedIpv4.limitUniqueMaxRetries single: embeddedIpv4.limitUniqueMaxRetries .. summary-start Controls whether random-consistent-unique anonymization limits retries for embedded IPv4 addresses. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.limitUniqueMaxRetries :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2410.0 Description ----------- When enabled, ``random-consistent-unique`` mode will stop retrying after :ref:`embeddedIpv4.uniqueRetryCount ` attempts. After the retry limit is reached, the behavior is controlled by :ref:`embeddedIpv4.maxRetryHandling `. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-limituniquemaxretries-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.anonMode="random-consistent-unique" embeddedIpv4.limitUniqueMaxRetries="on") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-maxretryhandling.rst0000644000000000000000000000013215145046112027161 xustar0030 mtime=1771326538.942012704 30 atime=1787067671.848441003 30 ctime=1787067792.713693729 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-maxretryhandling.rst0000664000175000017500000000235615145046112026633 0ustar00rgerrger.. _param-mmanon-ipv4-maxretryhandling: .. _mmanon.parameter.input.ipv4-maxretryhandling: ipv4.maxRetryHandling ===================== .. index:: single: mmanon; ipv4.maxRetryHandling single: ipv4.maxRetryHandling .. summary-start Selects how IPv4 random-consistent-unique handles retry exhaustion. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.maxRetryHandling :Scope: input :Type: string :Default: input=accept-duplicates :Required?: no :Introduced: 8.2410.0 Description ----------- Controls how ``random-consistent-unique`` behaves after the retry limit is reached (see :ref:`ipv4.limitUniqueMaxRetries `). The supported values are: - ``zero``: fall back to zeroing the anonymized bits. - ``accept-duplicates``: keep the last randomized address even if it already exists. A warning is logged whenever the retry limit is hit. Input usage ----------- .. _mmanon.parameter.input.ipv4-maxretryhandling-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="random-consistent-unique" ipv4.limitUniqueMaxRetries="on" ipv4.maxRetryHandling="zero") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-ratelimit-interval.rst0000644000000000000000000000013215132733117026370 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.193484719 30 ctime=1787067792.514690021 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-ratelimit-interval.rst0000666000175000017500000000166415132733117026045 0ustar00rgerrger.. _param-imtcp-ratelimit-interval: .. _imtcp.parameter.input.ratelimit-interval: RateLimit.Interval ================== .. index:: single: imtcp; RateLimit.Interval single: RateLimit.Interval .. summary-start Sets the rate-limiting interval in seconds. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: RateLimit.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the rate-limiting interval in seconds. Default value is ``0``, which turns off rate limiting. Set it to a number of seconds (``5`` recommended) to activate rate limiting. Input usage ----------- .. _param-imtcp-input-ratelimit-interval: .. _imtcp.parameter.input.ratelimit-interval-usage: .. code-block:: rsyslog input(type="imtcp" rateLimit.Interval="5") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ruleset.rst0000644000000000000000000000013215132733117024765 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.154483992 30 ctime=1787067792.628692145 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ruleset.rst0000666000175000017500000000142215132733117024432 0ustar00rgerrger.. _param-imuxsock-ruleset: .. _imuxsock.parameter.input.ruleset: Ruleset ======= .. index:: single: imuxsock; Ruleset single: Ruleset .. summary-start Binds a specified ruleset to the input instead of the default ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: Ruleset :Scope: input :Type: string :Default: input=default ruleset :Required?: no :Introduced: 8.17.0 Description ----------- Binds specified ruleset to this input. If not set, the default ruleset is bound. Input usage ----------- .. _param-imuxsock-input-ruleset: .. _imuxsock.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imuxsock" ruleset="myRuleset") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-iobuffersize.rst0000644000000000000000000000013215132411300025372 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.536453829 30 ctime=1787067793.190702618 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-iobuffersize.rst0000666000175000017500000000244215132411300025042 0ustar00rgerrger.. _param-omfile-iobuffersize: .. _omfile.parameter.module.iobuffersize: ioBufferSize ============ .. index:: single: omfile; ioBufferSize single: ioBufferSize .. summary-start Size of the buffer used to writing output data. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: ioBufferSize :Scope: action :Type: size :Default: action=4 KiB :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Size of the buffer used to writing output data. The larger the buffer, the potentially better performance is. The default of 4k is quite conservative, it is useful to go up to 64k, and 128k if you used gzip compression (then, even higher sizes may make sense) Action usage ------------ .. _param-omfile-action-iobuffersize: .. _omfile.parameter.action.iobuffersize: .. code-block:: rsyslog action(type="omfile" ioBufferSize="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.omfileiobuffersize: - $OMFileIOBufferSize — maps to ioBufferSize (status: legacy) .. index:: single: omfile; $OMFileIOBufferSize single: $OMFileIOBufferSize See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-timeout.rst0000644000000000000000000000013215132411300026257 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.054444843 30 ctime=1787067793.099700922 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-timeout.rst0000666000175000017500000000154015132411300025725 0ustar00rgerrger.. _param-omelasticsearch-timeout: .. _omelasticsearch.parameter.module.timeout: timeout ======= .. index:: single: omelasticsearch; timeout single: timeout .. summary-start How long Elasticsearch waits for a primary shard before failing. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: timeout :Scope: action :Type: word :Default: action=1m :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Controls the `timeout` query parameter for index operations. Example values use time units such as `1m`. Action usage ------------ .. _param-omelasticsearch-action-timeout: .. _omelasticsearch.parameter.action.timeout: .. code-block:: rsyslog action(type="omelasticsearch" timeout="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-listenportfilename.rst0000644000000000000000000000013215216464435026647 xustar0030 mtime=1782212893.984265505 30 atime=1787067671.818440443 30 ctime=1787067792.019680796 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-listenportfilename.rst0000664000175000017500000000212715216464435026315 0ustar00rgerrger.. _param-imdtls-listenportfilename: .. _imdtls.parameter.input.listenportfilename: ListenPortFileName ================== .. index:: single: imdtls; listenPortFileName single: listenPortFileName .. summary-start Writes the UDP port selected by the operating system when imdtls binds to port 0. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: listenPortFileName :Scope: input :Type: word :Default: none :Required?: no :Introduced: v8.2606.0 Description ----------- When ``port="0"`` is configured, the operating system selects an available UDP port for the imdtls listener. ``listenPortFileName`` writes that selected port number to the named file after the socket is bound. This is primarily useful for tests and automation that must avoid preselecting a port before the listener starts. Input usage ----------- .. _imdtls.parameter.input.listenportfilename-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" port="0" listenPortFileName="imdtls.port") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-remote.rst0000644000000000000000000000013215132411300024716 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.913460857 30 ctime=1787067792.205684262 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-remote.rst0000666000175000017500000000166515132411300024374 0ustar00rgerrger.. _param-imjournal-remote: .. _imjournal.parameter.module.remote: .. meta:: :tag: module:imjournal :tag: parameter:Remote Remote ====== .. index:: single: imjournal; Remote single: Remote .. summary-start Also read journal files from remote sources. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: Remote :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.1910.0 Description ----------- When enabled, the module processes not only local journal files but also those originating from remote systems stored on the host. Module usage ------------ .. _param-imjournal-module-remote: .. _imjournal.parameter.module.remote-usage: .. code-block:: rsyslog module(load="imjournal" Remote="...") Notes ----- - Historic documentation called this a ``binary`` option; it is boolean. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-processonpoller.rst0000644000000000000000000000013215132733117026165 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.600473664 30 ctime=1787067792.374687412 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-processonpoller.rst0000666000175000017500000000250615132733117025636 0ustar00rgerrger.. _param-imptcp-processonpoller: .. _imptcp.parameter.module.processonpoller: ProcessOnPoller =============== .. index:: single: imptcp; ProcessOnPoller single: ProcessOnPoller .. summary-start Processes messages on the poller thread when feasible to reduce resource use. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: ProcessOnPoller :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Instructs imptcp to process messages on poller thread opportunistically. This leads to lower resource footprint (as poller thread doubles up as message-processing thread too). "On" works best when imptcp is handling low ingestion rates. At high throughput though, it causes polling delay (as poller spends time processing messages, which keeps connections in read-ready state longer than they need to be, filling socket-buffer, hence eventually applying backpressure). It defaults to allowing messages to be processed on poller (for backward compatibility). Module usage ------------ .. _param-imptcp-module-processonpoller: .. _imptcp.parameter.module.processonpoller-usage: .. code-block:: rsyslog module(load="imptcp" processOnPoller="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-de-dot.rst0000644000000000000000000000013215132733117025315 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.657456084 30 ctime=1787067792.835696002 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-de-dot.rst0000666000175000017500000000163415132733117024767 0ustar00rgerrger.. _param-mmkubernetes-de-dot: .. _mmkubernetes.parameter.action.de-dot: de_dot ====== .. index:: single: mmkubernetes; de_dot single: de_dot .. summary-start Replaces dots in annotation and label keys. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: de_dot :Scope: action :Type: boolean :Default: on :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When processing labels and annotations, if this parameter is set to `"on"`, the key strings will have their `.` characters replaced with the string specified by the :ref:`param-mmkubernetes-de-dot-separator` parameter. Action usage ------------ .. _param-mmkubernetes-action-de-dot: .. _mmkubernetes.parameter.action.de-dot-usage: .. code-block:: rsyslog action(type="mmkubernetes" deDot="on") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-mycert.rst0000644000000000000000000000013215145046112025035 xustar0030 mtime=1771326538.954012901 30 atime=1787067672.742457669 30 ctime=1787067793.510708581 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-mycert.rst0000664000175000017500000000141415145046112024501 0ustar00rgerrger.. _param-omrelp-tls-mycert: .. _omrelp.parameter.input.tls-mycert: TLS.MyCert ========== .. index:: single: omrelp; TLS.MyCert single: TLS.MyCert .. summary-start Provides the path to the machine's public certificate. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.MyCert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The machine public certificate. Input usage ----------- .. _param-omrelp-input-tls-mycert: .. _omrelp.parameter.input.tls-mycert-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.myCert="/path/to/cert.pem") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-tlsverifydepth.rst0000644000000000000000000000013215132733117030335 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.082482649 30 ctime=1787067792.547690635 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-tlsverifydepth.rst0000666000175000017500000000322515132733117030005 0ustar00rgerrger.. _param-imtcp-streamdriver-tlsverifydepth: .. _imtcp.parameter.module.streamdriver-tlsverifydepth: .. _imtcp.parameter.input.streamdriver-tlsverifydepth: StreamDriver.TlsVerifyDepth =========================== .. index:: single: imtcp; StreamDriver.TlsVerifyDepth single: StreamDriver.TlsVerifyDepth .. summary-start Specifies the maximum depth allowed for certificate chain verification. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.TlsVerifyDepth :Scope: module, input :Type: integer :Default: module=TLS library default, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the allowed maximum depth for the certificate chain verification. Support added in v8.2001.0, supported by GTLS and OpenSSL driver. If not set, the API default will be used. For OpenSSL, the default is 100 - see the doc for more: https://docs.openssl.org/1.1.1/man3/SSL_CTX_set_verify/ For GnuTLS, the default is 5 - see the doc for more: https://www.gnutls.org/manual/gnutls.html The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-tlsverifydepth: .. _imtcp.parameter.module.streamdriver-tlsverifydepth-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.tlsVerifyDepth="7") Input usage ----------- .. _param-imtcp-input-streamdriver-tlsverifydepth: .. _imtcp.parameter.input.streamdriver-tlsverifydepth-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.tlsVerifyDepth="7") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-version.rst0000644000000000000000000000013215132733117024436 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.760439362 30 ctime=1787067793.561709532 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-version.rst0000666000175000017500000000220115132733117024077 0ustar00rgerrger.. _param-omsnmp-version: .. _omsnmp.parameter.module.version: Version ======= .. index:: single: omsnmp; Version single: Version .. summary-start Chooses whether SNMPv1 or SNMPv2c traps are sent. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Version :Scope: module :Type: integer :Default: module=1 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- There can only be two choices for this parameter for now. 0 means SNMPv1 will be used. 1 means SNMPv2c will be used. Any other value will default to 1. Module usage ------------ .. _param-omsnmp-module-version: .. _omsnmp.parameter.module.version-usage: .. code-block:: rsyslog action(type="omsnmp" version="1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmpversion: - $actionsnmpversion — maps to Version (status: legacy) .. index:: single: omsnmp; $actionsnmpversion single: $actionsnmpversion See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-framing-delimiter-regex.rst0000644000000000000000000000013115132733117027442 xustar0030 mtime=1768666703.906620223 29 atime=1787067673.77247687 30 ctime=1787067792.341686797 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-framing-delimiter-regex.rst0000666000175000017500000000317715132733117027121 0ustar00rgerrger.. _param-imptcp-framing-delimiter-regex: .. _imptcp.parameter.input.framing-delimiter-regex: framing.delimiter.regex ======================= .. index:: single: imptcp; framing.delimiter.regex single: framing.delimiter.regex .. summary-start Uses a regular expression to identify the start of the next message. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: framing.delimiter.regex :Scope: input :Type: string :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Experimental parameter. It is similar to "MultiLine", but provides greater control of when a log message ends. You can specify a regular expression that characterizes the header to expect at the start of the next message. As such, it indicates the end of the current message. For example, one can use this setting to use an RFC3164 header as frame delimiter:: framing.delimiter.regex="^<[0-9]{1,3}>(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)" Note that when oversize messages arrive this mode may have problems finding the proper frame terminator. There are some provisions inside imptcp to make these kinds of problems unlikely, but if the messages are very much over the configured MaxMessageSize, imptcp emits an error messages. Chances are great it will properly recover from such a situation. Input usage ----------- .. _param-imptcp-input-framing-delimiter-regex: .. _imptcp.parameter.input.framing-delimiter-regex-usage: .. code-block:: rsyslog input(type="imptcp" framing.delimiter.regex="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-maxbytes.rst0000644000000000000000000000013115132733117025760 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.631474242 30 ctime=1787067792.985698798 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-maxbytes.rst0000666000175000017500000000203515132733117025427 0ustar00rgerrger.. _param-omclickhouse-maxbytes: .. _omclickhouse.parameter.input.maxbytes: maxBytes ======== .. index:: single: omclickhouse; maxBytes single: maxBytes single: omclickhouse; maxbytes single: maxbytes .. summary-start Limits the maximum size of a bulk HTTP request when ``bulkMode`` is enabled. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: maxBytes :Scope: input :Type: size :Default: 104857600/100mb :Required?: no :Introduced: not specified Description ----------- When shipping logs with ``bulkMode`` **on**, ``maxBytes`` specifies the maximum size of the request body sent to ClickHouse. Logs are batched until either the buffer reaches ``maxBytes`` or the `dequeue batch size `_ is reached. Input usage ----------- .. _omclickhouse.parameter.input.maxbytes-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" maxBytes="64mb") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-tag.rst0000644000000000000000000000013215132733117023460 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.379450902 30 ctime=1787067792.120682678 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-tag.rst0000666000175000017500000000230315132733117023124 0ustar00rgerrger.. _param-imfile-tag: .. _imfile.parameter.input.tag: .. _imfile.parameter.tag: Tag === .. index:: single: imfile; Tag single: Tag .. summary-start Assigns a tag to messages read from the file; include a colon if desired. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: Tag :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- The tag to be assigned to messages read from this file. If a colon should follow the tag, include it in the value, for example ``Tag="myTag:"``. Input usage ----------- .. _param-imfile-input-tag: .. _imfile.parameter.input.tag-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="app:") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfiletag: - ``$InputFileTag`` — maps to Tag (status: legacy) .. index:: single: imfile; $InputFileTag single: $InputFileTag See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-user.rst0000644000000000000000000000013215132733117025103 xustar0030 mtime=1768666703.916620375 30 atime=1787067673.682475192 30 ctime=1787067793.003699133 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-user.rst0000666000175000017500000000137015132733117024552 0ustar00rgerrger.. _param-omclickhouse-user: .. _omclickhouse.parameter.input.user: user ==== .. index:: single: omclickhouse; user single: user .. summary-start Sets the username for HTTP basic authentication against ClickHouse. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: user :Scope: input :Type: word :Default: none :Required?: no :Introduced: not specified Description ----------- If you have basic HTTP authentication deployed you can specify your user-name here. Input usage ----------- .. _omclickhouse.parameter.input.user-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" user="ingest") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-networknamespace.rst0000644000000000000000000000013215216464435026441 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.812440332 30 ctime=1787067791.358668478 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-networknamespace.rst0000664000175000017500000000173715216464435026115 0ustar00rgerrger.. _param-imbeats-networknamespace: .. _imbeats.parameter.input.networknamespace: NetworkNamespace ================ .. meta:: :description: Network namespace for imbeats listener sockets. :keywords: rsyslog, imbeats, network namespace .. index:: single: imbeats; NetworkNamespace single: NetworkNamespace .. summary-start Open imbeats listener sockets inside the specified Linux network namespace. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: NetworkNamespace :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Open imbeats listener sockets inside the specified Linux network namespace. Input usage ----------- .. _param-imbeats-input-networknamespace: .. _imbeats.parameter.input.networknamespace-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" networkNamespace="ns1") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmutf8fix-replacementchar.rst0000644000000000000000000000013215241075234026524 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.725580541 30 ctime=1787067792.915697493 rsyslog-8.2608.0/doc/source/reference/parameters/mmutf8fix-replacementchar.rst0000664000175000017500000000242315241075234026171 0ustar00rgerrger.. _param-mmutf8fix-replacementchar: .. _mmutf8fix.parameter.input.replacementchar: replacementChar =============== .. index:: single: mmutf8fix; replacementChar single: replacementChar .. summary-start Defines the printable character used to substitute invalid sequences. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmutf8fix`. :Name: replacementChar :Scope: input :Type: string :Default: " " :Required?: no :Introduced: 7.5.4 Description ----------- This is the character that invalid sequences are replaced by. It is strongly recommended to use a printable US-ASCII character. Note that only the first byte of the provided string is used without validation. Use :ref:`param-mmutf8fix-replacementsequence` instead when the replacement marker needs more than one byte. The two parameters are mutually exclusive. Input usage ----------- .. _mmutf8fix.parameter.input.replacementchar-usage: .. code-block:: rsyslog module(load="mmutf8fix") action(type="mmutf8fix" replacementChar="#") YAML usage ---------- .. code-block:: yaml modules: - load: "mmutf8fix" rulesets: - name: main script: | action(type="mmutf8fix" replacementChar="#") See also -------- See also :doc:`../../configuration/modules/mmutf8fix`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-max_batch_bytes.rst0000644000000000000000000000013115171370365026736 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.502471837 29 ctime=1787067792.95469822 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-max_batch_bytes.rst0000664000175000017500000000235315171370365026406 0ustar00rgerrger.. _param-omazuredce-max_batch_bytes: .. _omazuredce.parameter.action.max_batch_bytes: .. meta:: :description: Reference for the omazuredce max_batch_bytes parameter. :keywords: rsyslog, omazuredce, max_batch_bytes, azure, batching max_batch_bytes =============== .. index:: single: omazuredce; max_batch_bytes single: max_batch_bytes .. summary-start Limits the estimated total size of one Azure ingestion request, including the payload and HTTP overhead. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: max_batch_bytes :Scope: action :Type: integer :Default: 1048576 :Required?: no :Introduced: Not specified Description ----------- ``max_batch_bytes`` defines the upper bound for a batch. Before appending a new record, the module estimates the final HTTP request size and flushes the current batch if needed. Valid values are in the range ``1`` to ``1048576``. Records that still do not fit into an otherwise empty batch are logged and dropped. Action usage ------------ .. _omazuredce.parameter.action.max_batch_bytes-usage: .. code-block:: rsyslog action(type="omazuredce" max_batch_bytes="524288" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-addlf.rst0000644000000000000000000000013215132733117023765 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.318449765 30 ctime=1787067793.129701481 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-addlf.rst0000666000175000017500000000477115132733117023444 0ustar00rgerrger.. _param-omfile-addlf: .. _omfile.parameter.module.addlf: addLF ===== .. index:: single: omfile; addLF single: addLF .. summary-start Appends an LF if a rendered message does not already end with one, ensuring full-line records. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: addLF :Scope: module, action :Type: boolean :Default: module=on; action=inherits module :Required?: no :Introduced: 8.2510.0 Description ----------- When enabled, the omfile action checks whether a rendered message already ends with an LF (line feed). If not, omfile appends one before writing, so that every record is a complete line regardless of the template used. In text-based logging, a line feed (LF) marks the end of a record. Without it, the record may appear as an incomplete line when viewed with standard tools such as ``cat`` or ``tail -f``. The extra byte is added transparently even when compression or cryptographic providers are active. If set at the module level, the value becomes the default for all omfile actions that do not explicitly define ``addLF``. Notes on default behavior ------------------------- Since **8.2510.0**, the default has been changed to ``on``. In earlier releases, messages without a trailing LF were written as incomplete lines. With the new default, rsyslog ensures that all records end with a line feed. This change aligns with common user expectations—especially when writing JSON logs, where line-separated records are the norm. If incomplete lines are desired, you can disable the feature either globally at the module level or for individual actions. Module usage ------------ .. _param-omfile-module-addlf: .. _omfile.parameter.module.addlf-usage: To override the default globally and allow incomplete lines, disable ``addLF`` at the module level: .. code-block:: rsyslog module(load="builtin:omfile" addLF="off") Action usage ------------ .. _param-omfile-action-addlf: .. _omfile.parameter.action.addlf: By default, actions inherit the module setting. No explicit parameter is needed: .. code-block:: rsyslog action(type="omfile" file="/var/log/messages") In rare cases, you may want to allow incomplete lines only for one action. You can disable ``addLF`` explicitly at the action level: .. code-block:: rsyslog action(type="omfile" file="/var/log/raw.log" addLF="off") See also -------- - :doc:`../../configuration/modules/omfile` .. meta:: :keywords: rsyslog, omfile, addLF, line termination, json logging, full line records rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-defaultseverity.rst0000644000000000000000000000013215132411300026437 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.165446912 30 ctime=1787067791.969679865 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-defaultseverity.rst0000666000175000017500000000210215132411300026100 0ustar00rgerrger.. _param-imdocker-defaultseverity: .. _imdocker.parameter.module.defaultseverity: DefaultSeverity =============== .. index:: single: imdocker; DefaultSeverity single: DefaultSeverity .. summary-start Syslog severity assigned to received messages; default ``info``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: DefaultSeverity :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=info :Required?: no :Introduced: 8.41.0 Description ----------- The syslog severity to be assigned to log messages. Textual names such as ``info`` are suggested, though numeric values are also accepted. Module usage ------------ .. _param-imdocker-module-defaultseverity: .. _imdocker.parameter.module.defaultseverity-usage: .. code-block:: rsyslog module(load="imdocker" DefaultSeverity="...") Notes ----- - Numeric severity values are accepted but textual names are recommended. - See https://en.wikipedia.org/wiki/Syslog. See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omgssapi-gsstokeniotimeout.rst0000644000000000000000000000013215171370365027063 xustar0030 mtime=1776677109.119908115 30 atime=1787067672.892460465 30 ctime=1787067793.217703121 rsyslog-8.2608.0/doc/source/reference/parameters/omgssapi-gsstokeniotimeout.rst0000664000175000017500000000310115171370365026522 0ustar00rgerrger.. _param-omgssapi-gsstokeniotimeout: .. _omgssapi.parameter.module.gsstokeniotimeout: GssTokenIOTimeout ================= .. index:: single: omgssapi; GssTokenIOTimeout single: GssTokenIOTimeout .. summary-start Sets the deadline in seconds for reading a full GSSAPI handshake token while omgssapi establishes a session. .. summary-end This parameter applies to :doc:`../../configuration/modules/omgssapi`. :Name: GssTokenIOTimeout :Scope: module :Type: integer :Default: 10 :Required?: no :Introduced: 8.2604.0 Description ----------- Controls how long omgssapi waits for each full GSSAPI handshake token while it initializes a secured forwarding session. The timeout covers both the 4-byte token length and the token payload. Increase this value if the receiver is reachable only over slow or high-latency links. Set it to ``0`` to disable the deadline entirely. Negative values are rejected as configuration errors. Module usage ------------ .. _param-omgssapi-module-gsstokeniotimeout: .. _omgssapi.parameter.module.gsstokeniotimeout-usage: .. code-block:: rsyslog module(load="omgssapi" gssTokenIOTimeout="30") action(type="omgssapi" target="receiver.mydomain.com") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omgssapi.parameter.legacy.gsstokeniotimeout: - $GssTokenIOTimeout — maps to GssTokenIOTimeout (status: legacy) .. index:: single: omgssapi; $GssTokenIOTimeout single: $GssTokenIOTimeout See also -------- See also :doc:`../../configuration/modules/omgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-tls-cacert.rst0000644000000000000000000000013215132733117025003 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.812440332 30 ctime=1787067793.016699376 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-tls-cacert.rst0000666000175000017500000000172715132733117024460 0ustar00rgerrger.. _param-omdtls-tls-cacert: .. _omdtls.parameter.input.tls-cacert: tls.cacert ========== .. index:: single: omdtls; tls.cacert single: tls.cacert .. summary-start Defines the CA certificate used to verify client certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: tls.cacert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- The CA certificate that is being used to verify the client certificates. This parameter is required when :ref:`tls.authmode ` is set to ``fingerprint``, ``name``, or ``certvalid``. Input usage ----------- .. _omdtls.parameter.input.tls-cacert-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" tls.authMode="certvalid" tls.caCert="/etc/rsyslog/ca.pem") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-errorfile.rst0000644000000000000000000000013215132411300026562 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.113445943 30 ctime=1787067793.047699953 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-errorfile.rst0000666000175000017500000000155115132411300026232 0ustar00rgerrger.. _param-omelasticsearch-errorfile: .. _omelasticsearch.parameter.module.errorfile: errorFile ========= .. index:: single: omelasticsearch; errorFile single: errorFile .. summary-start File that receives records rejected during bulk mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: errorFile :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Failed bulk records are appended to this file with error details for later inspection or resubmission. Action usage ------------ .. _param-omelasticsearch-action-errorfile: .. _omelasticsearch.parameter.action.errorfile: .. code-block:: rsyslog action(type="omelasticsearch" errorFile="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxframesize.rst0000644000000000000000000000013115216464435025565 xustar0030 mtime=1782212893.982265473 29 atime=1787067671.79143994 30 ctime=1787067791.346668255 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxframesize.rst0000664000175000017500000000212315216464435025230 0ustar00rgerrger.. _param-imbeats-maxframesize: .. _imbeats.parameter.input.maxframesize: maxFrameSize ============ .. meta:: :description: Maximum Lumberjack frame payload size accepted by imbeats. :keywords: rsyslog, imbeats, maxFrameSize, Lumberjack frame .. index:: single: imbeats; maxFrameSize single: maxFrameSize .. summary-start Limit the JSON or compressed frame payload size imbeats accepts from one Lumberjack frame. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxFrameSize :Scope: input :Type: positive integer :Default: input=10485760 :Required?: no :Introduced: 8.2604.0 Description ----------- Set the maximum byte size accepted for an individual Lumberjack JSON frame or compressed frame payload. Frames larger than this value are rejected before payload allocation. Input usage ----------- .. _param-imbeats-input-maxframesize: .. _imbeats.parameter.input.maxframesize-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" maxFrameSize="10485760") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-usespecialparser.rst0000644000000000000000000000013215132733117026654 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.902479294 30 ctime=1787067792.673692984 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-usespecialparser.rst0000666000175000017500000000167515132733117026333 0ustar00rgerrger.. _param-imuxsock-usespecialparser: .. _imuxsock.parameter.input.usespecialparser: UseSpecialParser ================ .. index:: single: imuxsock; UseSpecialParser single: UseSpecialParser .. summary-start Selects the special parser tailored for default UNIX socket format. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: UseSpecialParser :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 8.9.0 Description ----------- Equivalent to the ``SysSock.UseSpecialParser`` module parameter, but applies to the input that is being defined. .. versionadded:: 8.9.0 The setting was previously hard-coded "on" Input usage ----------- .. _param-imuxsock-input-usespecialparser: .. _imuxsock.parameter.input.usespecialparser-usage: .. code-block:: rsyslog input(type="imuxsock" useSpecialParser="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-rulebase.rst0000644000000000000000000000013215132733117025574 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.846459608 30 ctime=1787067792.880696841 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-rulebase.rst0000666000175000017500000000270715132733117025250 0ustar00rgerrger.. _param-mmnormalize-rulebase: .. _mmnormalize.parameter.action.rulebase: ruleBase ======== .. index:: single: mmnormalize; ruleBase single: ruleBase .. summary-start Sets the rulebase file used for normalization. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: ruleBase :Scope: action :Type: word :Default: none :Required?: yes :Introduced: at least 6.1.2, possibly earlier Description ----------- Specifies which rulebase file is to use. If there are multiple mmnormalize instances, each one can use a different file. However, a single instance can use only a single file. This parameter or :ref:`param-mmnormalize-rule` MUST be given, because normalization can only happen based on a rulebase. It is recommended that an be found in the `liblognorm manual `_. Action usage ------------- .. _param-mmnormalize-action-rulebase: .. _mmnormalize.parameter.action.rulebase-usage: .. code-block:: rsyslog action(type="mmnormalize" ruleBase="/path/to/rulebase.rb") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmnormalize.parameter.legacy.mmnormalizerulebase: - $mmnormalizeRuleBase — maps to ruleBase (status: legacy) .. index:: single: mmnormalize; $mmnormalizeRuleBase single: $mmnormalizeRuleBase See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-bearer_token.rst0000644000000000000000000000013215241075234026602 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.963698388 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-bearer_token.rst0000664000175000017500000000207315241075234026250 0ustar00rgerrger.. _param-omawslogshlc-bearer_token: .. _omawslogshlc.parameter.action.bearer_token: .. meta:: :description: Reference for the omawslogshlc bearer_token parameter. :keywords: rsyslog, omawslogshlc, bearer_token, aws, cloudwatch, hlc bearer_token ============ .. index:: single: omawslogshlc; bearer_token single: bearer_token .. summary-start Specifies the bearer token for HLC endpoint authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: bearer_token :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``bearer_token`` is sent in the ``Authorization: Bearer `` header with each request. Tokens start with ``ACWL`` and are generated via the CloudWatch Logs bearer token authentication setup. Action usage ------------ .. _omawslogshlc.parameter.action.bearer_token-usage: .. code-block:: rsyslog action(type="omawslogshlc" bearer_token="ACWL..." ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-address.rst0000644000000000000000000000013215132733117024361 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.682475192 30 ctime=1787067792.315686312 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-address.rst0000666000175000017500000000212415132733117024026 0ustar00rgerrger.. _param-imptcp-address: .. _imptcp.parameter.input.address: Address ======= .. index:: single: imptcp; Address single: Address .. summary-start Specifies the local address to bind the listener to. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Address :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- On multi-homed machines, specifies to which local address the listener should be bound. Input usage ----------- .. _param-imptcp-input-address: .. _imptcp.parameter.input.address-usage: .. code-block:: rsyslog input(type="imptcp" address="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverlistenip: - $InputPTCPServerListenIP — maps to Address (status: legacy) .. index:: single: imptcp; $InputPTCPServerListenIP single: $InputPTCPServerListenIP See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-token.rst0000644000000000000000000000013215132733117025261 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.740457632 30 ctime=1787067792.862696506 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-token.rst0000666000175000017500000000163715132733117024736 0ustar00rgerrger.. _param-mmkubernetes-token: .. _mmkubernetes.parameter.action.token: token ===== .. index:: single: mmkubernetes; token single: token .. summary-start Specifies the authentication token string. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: token :Scope: action :Type: word :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- The token to use to authenticate to the Kubernetes API server. One of `token` or :ref:`param-mmkubernetes-tokenfile` is required if Kubernetes is configured with access control. Example: `UxMU46ptoEWOSqLNa1bFmH` Action usage ------------ .. _param-mmkubernetes-action-token: .. _mmkubernetes.parameter.action.token-usage: .. code-block:: rsyslog action(type="mmkubernetes" token="UxMU46ptoEWOSqLNa1bFmH") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-container.rst0000644000000000000000000000013215132733117025760 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.378450883 30 ctime=1787067792.789695145 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-container.rst0000666000175000017500000000225115132733117025426 0ustar00rgerrger.. _param-mmjsonparse-container: .. _mmjsonparse.parameter.input.container: container ========= .. index:: single: mmjsonparse; container single: container single: JSON container .. summary-start Sets the JSON container path where parsed properties are stored. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: container :Scope: input :Type: string :Default: $! :Required?: no :Introduced: 6.6.0 Description ----------- Specifies the JSON container (path) under which parsed elements should be placed. By default (``$!``), all parsed properties are merged into the root of the message properties. You can specify a different container: * To place data in a subtree of message properties, for example ``container="$!json"``. * To use a local variable, for example ``container="$.parses"``. * To use a global variable, for example ``container="$/parses"``. Input usage ----------- .. _mmjsonparse.parameter.input.container-usage: .. code-block:: rsyslog action(type="mmjsonparse" container="$.parses") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-reloadonhup.rst0000644000000000000000000000013015132733117025271 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.034463112 29 ctime=1787067793.28470437 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-reloadonhup.rst0000666000175000017500000000171515132733117024745 0ustar00rgerrger.. _param-omhttp-reloadonhup: .. _omhttp.parameter.input.reloadonhup: reloadonhup =========== .. index:: single: omhttp; reloadonhup single: reloadonhup .. summary-start Reinitializes libcurl handles on ``HUP`` signals so certificates can be refreshed without restarting rsyslog. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: reloadonhup :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- If this parameter is ``on``, the plugin will close and reopen any libcurl handles on a HUP signal. This option is primarily intended to enable reloading short-lived certificates without restarting rsyslog. Input usage ----------- .. _omhttp.parameter.input.reloadonhup-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" reloadOnHup="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-detect-headerless.rst0000644000000000000000000000013215132411300026435 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.326449914 30 ctime=1787067793.597710203 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-detect-headerless.rst0000666000175000017500000000250315132411300026103 0ustar00rgerrger.. _param-pmrfc3164-detect-headerless: .. _pmrfc3164.parameter.module.detect-headerless: .. _pmrfc3164.parameter.module.detect.headerless: detect.headerless ================= .. index:: single: pmrfc3164; detect.headerless single: detect.headerless .. summary-start Enable detection of messages lacking standard syslog headers. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: detect.headerless :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2508.0 Description ----------- When enabled, rsyslog applies extra heuristics to classify messages without a syslog header. A message is considered headerless only if: - It has no PRI header (facility/severity). - It does not start with an accepted timestamp. - It does not begin with whitespace followed by ``{`` or ``[``. Messages starting with ``{`` or ``[`` are treated as structured data (e.g., JSON) instead. Module usage ------------ .. _param-pmrfc3164-module-detect-headerless: .. _pmrfc3164.parameter.module.detect-headerless-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" detect.headerless="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-ratelimit-interval.rst0000644000000000000000000000013215132733117026550 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.742476311 30 ctime=1787067792.380687523 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-ratelimit-interval.rst0000666000175000017500000000161015132733117026214 0ustar00rgerrger.. _param-imptcp-ratelimit-interval: .. _imptcp.parameter.input.ratelimit-interval: RateLimit.Interval ================== .. index:: single: imptcp; RateLimit.Interval single: RateLimit.Interval .. summary-start Specifies the rate-limiting interval in seconds. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: RateLimit.Interval :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the rate-limiting interval in seconds. Set it to a number of seconds (5 recommended) to activate rate-limiting. Input usage ----------- .. _param-imptcp-input-ratelimit-interval: .. _imptcp.parameter.input.ratelimit-interval-usage: .. code-block:: rsyslog input(type="imptcp" rateLimit.interval="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-starvationprotection-maxreads.rs0000644000000000000000000000013215216464435031012 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.831440686 30 ctime=1787067791.367668646 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-starvationprotection-maxreads.rst0000664000175000017500000000303015216464435030636 0ustar00rgerrger.. _param-imbeats-starvationprotection-maxreads: .. _imbeats.parameter.input.starvationprotection-maxreads: starvationProtection.maxReads ============================= .. meta:: :description: Maximum consecutive reads per imbeats session before another session can run. :keywords: rsyslog, imbeats, starvationProtection.maxReads, Beats sessions, fairness .. index:: single: imbeats; starvationProtection.maxReads single: starvationProtection.maxReads .. summary-start Limit consecutive reads from one imbeats session before other sessions can run. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: starvationProtection.maxReads :Scope: input :Type: non-negative integer :Default: input=500 :Required?: no :Introduced: 8.2606.0 Description ----------- Set the maximum number of consecutive socket reads a worker performs for one ``imbeats`` session before yielding so other ready sessions can be processed. This prevents one busy Beats sender from monopolizing the listener. Use ``0`` to disable this fairness limit. Positive values cap the number of consecutive reads per turn; smaller values favor fairness across sessions, while larger values favor throughput for busy senders. Input usage ----------- .. _param-imbeats-input-starvationprotection-maxreads: .. _imbeats.parameter.input.starvationprotection-maxreads-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" starvationProtection.maxReads="300") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-sourceport-end.rst0000644000000000000000000000013215145046112026600 xustar0030 mtime=1771326538.958012966 30 atime=1787067671.964443165 30 ctime=1787067793.572709737 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-sourceport-end.rst0000664000175000017500000000243415145046112026247 0ustar00rgerrger.. _param-omudpspoof-sourceport-end: .. _omudpspoof.parameter.action.sourceport-end: sourcePort.end ============== .. index:: single: omudpspoof; sourcePort.end single: sourcePort.end .. summary-start Sets the ending source port when cycling through spoofed source ports. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: sourcePort.end :Scope: action :Type: integer :Default: 42000 :Required?: no :Introduced: 5.1.3 Description ----------- Specify the end value for circling the source ports. End must be equal to or more than sourcePort.start. Action usage ------------ .. _param-omudpspoof-action-sourceport-end: .. _omudpspoof.parameter.action.sourceport-end-usage: .. code-block:: rsyslog action(type="omudpspoof" target="192.0.2.1" sourcePort.start="10000" sourcePort.end="19999") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspoofsourceportend: - $ActionOMUDPSpoofSourcePortEnd — maps to sourcePort.end (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofSourcePortEnd single: $ActionOMUDPSpoofSourcePortEnd See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-rcvbufsize.rst0000644000000000000000000000013215132733117024740 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.393488447 30 ctime=1787067792.588691399 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-rcvbufsize.rst0000666000175000017500000000314415132733117024410 0ustar00rgerrger.. _param-imudp-rcvbufsize: .. _imudp.parameter.input.rcvbufsize: RcvBufSize ========== .. index:: single: imudp; RcvBufSize single: RcvBufSize .. summary-start Requests specific socket receive buffer size; disables auto-tuning. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: RcvBufSize :Scope: input :Type: size :Default: input=0 :Required?: no :Introduced: 7.3.9 Description ----------- This requests a socket receive buffer of specific size from the operating system. It is an expert parameter, which should only be changed for a good reason. Note that setting this parameter disables Linux auto-tuning, which usually works pretty well. The default value is 0, which means "keep the OS buffer size unchanged". This is a size value. So in addition to pure integer values, sizes like ``256k``, ``1m`` and the like can be specified. Note that setting very large sizes may require root or other special privileges. Also note that the OS may slightly adjust the value or shrink it to a system-set max value if the user is not sufficiently privileged. Technically, this parameter will result in a ``setsockopt()`` call with ``SO_RCVBUF`` (and ``SO_RCVBUFFORCE`` if it is available). (Maximum Value: 1G) Examples: .. code-block:: rsyslog module(load="imudp") # needs to be done just once input(type="imudp" port="514" rcvbufSize="1m") Input usage ----------- .. _param-imudp-input-rcvbufsize: .. _imudp.parameter.input.rcvbufsize-usage: .. code-block:: rsyslog input(type="imudp" RcvBufSize="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-statsfile.rst0000644000000000000000000000013215132411300025032 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.169465629 30 ctime=1787067793.360705786 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-statsfile.rst0000666000175000017500000000155715132411300024510 0ustar00rgerrger.. _param-omkafka-statsfile: .. _omkafka.parameter.module.statsfile: statsFile ========= .. index:: single: omkafka; statsFile single: statsFile .. summary-start Write librdkafka statistics JSON to this file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: statsFile :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, the JSON statistics from librdkafka are written to the specified file. Updates occur based on the ``statistics.interval.ms`` `confParam` value. Action usage ------------ .. _param-omkafka-action-statsfile: .. _omkafka.parameter.action.statsfile: .. code-block:: rsyslog action(type="omkafka" statsFile="/var/log/omkafka-stats.json") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-pwd.rst0000644000000000000000000000013115132733117024716 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.644474484 30 ctime=1787067792.990698891 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-pwd.rst0000666000175000017500000000133115132733117024363 0ustar00rgerrger.. _param-omclickhouse-pwd: .. _omclickhouse.parameter.input.pwd: pwd === .. index:: single: omclickhouse; pwd single: pwd .. summary-start Provides the password for HTTP basic authentication when required by ClickHouse. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: pwd :Scope: input :Type: word :Default: none :Required?: no :Introduced: not specified Description ----------- Password for basic authentication. Input usage ----------- .. _omclickhouse.parameter.input.pwd-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" user="ingest" pwd="s3cr3t") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-port.rst0000644000000000000000000000013215132733117023720 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.929442513 30 ctime=1787067792.024680889 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-port.rst0000666000175000017500000000140415132733117023365 0ustar00rgerrger.. _param-imdtls-port: .. _imdtls.parameter.input.port: Port ==== .. index:: single: imdtls; port single: port .. summary-start Binds the imdtls listener to the specified UDP port for DTLS traffic. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: port :Scope: input :Type: word :Default: 4433 :Required?: yes :Introduced: v8.2402.0 Description ----------- Specifies the UDP port to which the imdtls module will bind and listen for incoming connections. The default port number for DTLS is 4433. Input usage ----------- .. _imdtls.parameter.input.port-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" port="4433") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-pass.rst0000644000000000000000000000013215145046112024064 xustar0030 mtime=1771326538.949012819 30 atime=1787067673.378469525 30 ctime=1787067793.435707183 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-pass.rst0000664000175000017500000000136415145046112023534 0ustar00rgerrger.. _param-ompgsql-pass: .. _ompgsql.parameter.input.pass: Pass ==== .. index:: single: ompgsql; Pass single: Pass .. summary-start Provides the password used for PostgreSQL authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: Pass :Scope: input :Type: word :Default: postgres :Required?: no :Introduced: 8.32.0 Description ----------- The password to connect to the PostgreSQL server with. The name ``PWD`` is also accepted. Input usage ----------- .. _ompgsql.parameter.input.pass-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" pass="test1234" db="syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-ratelimitinterval.rst0000644000000000000000000000013215132733117026461 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.084464045 30 ctime=1787067792.247685045 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-ratelimitinterval.rst0000666000175000017500000000160215132733117026126 0ustar00rgerrger.. _param-imklog-ratelimitinterval: .. _imklog.parameter.module.ratelimitinterval: RatelimitInterval ================= .. index:: single: imklog; RatelimitInterval single: RatelimitInterval .. summary-start Sets the interval window for the imklog rate limiter in seconds. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: RatelimitInterval :Scope: module :Type: integer :Default: 0 :Required?: no :Introduced: 8.35.0 Description ----------- The rate-limiting interval in seconds. Value 0 turns off rate limiting. Set it to a number of seconds (5 recommended) to activate rate-limiting. Module usage ------------ .. _param-imklog-module-ratelimitinterval: .. _imklog.parameter.module.ratelimitinterval-usage: .. code-block:: rsyslog module(load="imklog" ratelimitInterval="5") See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-asyncrepl.rst0000644000000000000000000000013215132411300026571 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.042444619 30 ctime=1787067793.029699618 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-asyncrepl.rst0000666000175000017500000000167115132411300026244 0ustar00rgerrger.. _param-omelasticsearch-asyncrepl: .. _omelasticsearch.parameter.module.asyncrepl: asyncrepl ========= .. index:: single: omelasticsearch; asyncrepl single: asyncrepl .. summary-start Deprecated option formerly enabling asynchronous replication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: asyncrepl :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Kept for compatibility; Elasticsearch removed support for asynchronous replication so this setting has no effect. Action usage ------------ .. _param-omelasticsearch-action-asyncrepl: .. _omelasticsearch.parameter.action.asyncrepl: .. code-block:: rsyslog action(type="omelasticsearch" asyncrepl="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ignoretimestamp.rst0000644000000000000000000000013215132733117026511 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.028481643 30 ctime=1787067792.613691865 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ignoretimestamp.rst0000666000175000017500000000237215132733117026163 0ustar00rgerrger.. _param-imuxsock-ignoretimestamp: .. _imuxsock.parameter.input.ignoretimestamp: IgnoreTimestamp =============== .. index:: single: imuxsock; IgnoreTimestamp single: IgnoreTimestamp .. summary-start Ignores timestamps included in messages from this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: IgnoreTimestamp :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Ignore timestamps included in messages received from the input being defined. Input usage ----------- .. _param-imuxsock-input-ignoretimestamp: .. _imuxsock.parameter.input.ignoretimestamp-usage: .. code-block:: rsyslog input(type="imuxsock" ignoreTimestamp="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketignoremsgtimestamp: - $InputUnixListenSocketIgnoreMsgTimestamp — maps to IgnoreTimestamp (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketIgnoreMsgTimestamp single: $InputUnixListenSocketIgnoreMsgTimestamp See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-template.rst0000644000000000000000000000013215171370365025416 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.177465778 30 ctime=1787067792.959698313 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-template.rst0000664000175000017500000000265015171370365025065 0ustar00rgerrger.. _param-omazuredce-template: .. _omazuredce.parameter.action.template: .. meta:: :description: Reference for the omazuredce template parameter. :keywords: rsyslog, omazuredce, template, azure template ======== .. index:: single: omazuredce; template single: template .. summary-start Selects the rsyslog template used to render each message before it is added to the Azure ingestion batch. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: template :Scope: action :Type: word :Default: action=StdJSONFmt :Required?: no :Introduced: Not specified Description ----------- The selected template must render exactly one valid JSON object per message. ``omazuredce`` parses the rendered text and merges it into the batch payload. If this parameter is omitted, the module uses the built-in ``StdJSONFmt`` template, which already renders one JSON object per message. Action usage ------------ .. _omazuredce.parameter.action.template-usage: .. code-block:: rsyslog template(name="tplAzureDce" type="list" option.jsonf="on") { property(outname="TimeGenerated" name="timereported" dateFormat="rfc3339" format="jsonf") property(outname="Host" name="hostname" format="jsonf") property(outname="Message" name="msg" format="jsonf") } action(type="omazuredce" template="tplAzureDce" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-severity.rst0000644000000000000000000000013215132733117025156 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.449470849 30 ctime=1787067792.312686256 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-severity.rst0000666000175000017500000000146715132733117024634 0ustar00rgerrger.. _param-impstats-severity: .. _impstats.parameter.module.severity: severity ======== .. index:: single: impstats; severity single: severity .. summary-start Sets the syslog severity value that impstats assigns to emitted messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: severity :Scope: module :Type: integer :Default: module=6 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The numerical syslog severity code to be used for generated messages. Default is 6 (info). This is useful for filtering messages. Module usage ------------ .. _impstats.parameter.module.severity-usage: .. code-block:: rsyslog module(load="impstats" severity="7") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-force-tagendingbycolon.rst0000644000000000000000000000013215132411300027472 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.316449727 30 ctime=1787067793.602710295 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-force-tagendingbycolon.rst0000666000175000017500000000216215132411300027141 0ustar00rgerrger.. _param-pmrfc3164-force-tagendingbycolon: .. _pmrfc3164.parameter.module.force-tagendingbycolon: .. _pmrfc3164.parameter.module.force.tagEndingByColon: force.tagEndingByColon ====================== .. index:: single: pmrfc3164; force.tagEndingByColon single: force.tagEndingByColon .. summary-start Require tags to end with a colon or set the tag to ``-``. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: force.tagEndingByColon :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2508.0 Description ----------- When enabled, tags must end with a colon to be valid. Otherwise the tag is replaced with ``-`` without modifying the message. Module usage ------------ .. _param-pmrfc3164-module-force-tagendingbycolon: .. _pmrfc3164.parameter.module.force-tagendingbycolon-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" force.tagEndingByColon="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-tls-certfile.rst0000644000000000000000000000013215145046112026652 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.524472247 30 ctime=1787067792.298685995 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-tls-certfile.rst0000664000175000017500000000160715145046112026322 0ustar00rgerrger.. _param-impstats-push-tls-certfile: .. _impstats.parameter.module.push-tls-certfile: push.tls.certfile ================= .. index:: single: impstats; push.tls.certfile single: push.tls.certfile .. summary-start Specifies the client certificate file used for mutual TLS. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.tls.certfile :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 8.2602.0 Description ----------- Use this together with ``push.tls.keyfile`` when the Remote Write endpoint requires client certificate authentication. Module usage ------------ .. _impstats.parameter.module.push-tls-certfile-usage: .. code-block:: rsyslog module(load="impstats" push.tls.certfile="/etc/rsyslog/certs/impstats-client.crt") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmpstrucdata-maxstructureddatasize.rst0000644000000000000000000000013115216464435030611 xustar0030 mtime=1782212893.987265553 29 atime=1787067672.96246177 30 ctime=1787067792.893697083 rsyslog-8.2608.0/doc/source/reference/parameters/mmpstrucdata-maxstructureddatasize.rst0000664000175000017500000000232515216464435030260 0ustar00rgerrger.. _param-mmpstrucdata-maxstructureddatasize: .. _mmpstrucdata.parameter.action.maxstructureddatasize: maxStructuredDataSize ===================== .. index:: single: mmpstrucdata; maxStructuredDataSize single: maxStructuredDataSize .. summary-start Sets the largest RFC5424 structured-data field, in bytes, that ``mmpstrucdata`` parses. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmpstrucdata`. :Name: maxStructuredDataSize :Scope: action :Type: size :Default: action=global(maxMessageSize) :Required?: no :Introduced: 8.2606.0 Description ----------- ``mmpstrucdata`` skips parsing when a message's RFC5424 structured-data field is larger than this value and logs an error. The default follows ``global(maxMessageSize)`` so normal input-side message-size policy also bounds structured-data parsing unless this action parameter is set explicitly. The value must be greater than zero. Action usage ------------ .. code-block:: rsyslog action(type="mmpstrucdata" maxStructuredDataSize="64k") YAML usage ---------- .. code-block:: yaml actions: - type: mmpstrucdata maxStructuredDataSize: 64k See also -------- See also :doc:`../../configuration/modules/mmpstrucdata`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-tokenfile.rst0000644000000000000000000000013215132733117026121 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.747457762 30 ctime=1787067792.864696543 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-tokenfile.rst0000666000175000017500000000176115132733117025574 0ustar00rgerrger.. _param-mmkubernetes-tokenfile: .. _mmkubernetes.parameter.action.tokenfile: tokenfile ========= .. index:: single: mmkubernetes; tokenfile single: tokenfile .. summary-start Reads the authentication token from the specified file. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: tokenfile :Scope: action :Type: word :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- The file containing the token to use to authenticate to the Kubernetes API server. One of `tokenfile` or :ref:`param-mmkubernetes-token` is required if Kubernetes is configured with access control. Example: `/etc/rsyslog.d/mmk8s.token` Action usage ------------ .. _param-mmkubernetes-action-tokenfile: .. _mmkubernetes.parameter.action.tokenfile-usage: .. code-block:: rsyslog action(type="mmkubernetes" tokenFile="/etc/rsyslog.d/mmk8s.token") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-template.rst0000644000000000000000000000013115216464435025746 xustar0029 mtime=1782212893.98826557 30 atime=1787067673.661474801 30 ctime=1787067792.996699003 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-template.rst0000664000175000017500000000377115216464435025423 0ustar00rgerrger.. _param-omclickhouse-template: .. _omclickhouse.parameter.input.template: template ======== .. index:: single: omclickhouse; template single: template .. summary-start Selects the message template that renders the INSERT statement sent to ClickHouse. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: template :Scope: input :Type: word :Default: `` StdClickHouseFmt`` :Required?: no :Introduced: not specified Description ----------- This is the message format that will be sent to ClickHouse. The resulting string needs to be a valid INSERT Query, otherwise ClickHouse will return an error. Custom INSERT templates must enable the template-level SQL escaping option, for example ``option.stdsql="on"`` in RainerScript. ``stdSQL`` is not an ``omclickhouse`` action parameter. Defaults to: .. note:: The leading space in `` StdClickHouseFmt`` is intentional. Rsyslog registers its built-in templates with a leading space in the internal configuration state, and the module looks up the default by that exact name. When overriding the parameter yourself, use the natural form ``StdClickHouseFmt`` (without the space) as shown below. .. code-block:: none "\"INSERT INTO rsyslog.SystemEvents (severity, facility, " "timestamp, hostname, tag, message) VALUES (" "%syslogseverity%, %syslogfacility%, " "'%timereported:::date-unixtimestamp%', '%hostname%', " "'%syslogtag%', '%msg%')\"" Input usage ----------- .. _omclickhouse.parameter.input.template-usage: .. code-block:: rsyslog module(load="omclickhouse") template(name="CustomClickHouseFmt" type="string" option.stdsql="on" string="INSERT INTO rsyslog.SystemEvents (severity, facility, timestamp, hostname, tag, message) VALUES (%syslogseverity%, %syslogfacility%, '%timereported:::date-unixtimestamp%', '%hostname%', '%syslogtag%', '%msg%')") action(type="omclickhouse" template="CustomClickHouseFmt") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-healthchecktimedelay.rst0000644000000000000000000000013215171370365027121 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.145465182 30 ctime=1787067793.255703829 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-healthchecktimedelay.rst0000664000175000017500000000176415171370365026575 0ustar00rgerrger.. _param-omhttp-healthchecktimedelay: .. _omhttp.parameter.input.healthchecktimedelay: healthchecktimedelay ==================== .. index:: single: omhttp; healthchecktimedelay single: healthchecktimedelay .. summary-start Sets the number of seconds omhttp waits before doing another health check to the API. This parameter is used only if "checkpath" is set up. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: healthchecktimedelay :Scope: input :Type: integer :Default: input=-1 :Required?: no :Introduced: v8.2602.0 Description ----------- Sets the number of seconds omhttp waits before doing another health check to the API. This parameter is used only if "checkpath" is set up. Input usage ----------- .. _omhttp.parameter.input.healthchecktimedelay-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" healthchecktimedelay="60" ) See also -------- See also :doc:`../../configuration/modules/omhttp`.rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-ipfreebind.rst0000644000000000000000000000013215132733117024665 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.252485819 30 ctime=1787067792.568691027 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-ipfreebind.rst0000666000175000017500000000245315132733117024337 0ustar00rgerrger.. _param-imudp-ipfreebind: .. _imudp.parameter.input.ipfreebind: IpFreeBind ========== .. index:: single: imudp; IpFreeBind single: IpFreeBind .. summary-start Controls Linux ``IP_FREEBIND`` socket option for nonlocal binds. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: IpFreeBind :Scope: input :Type: integer :Default: input=2 :Required?: no :Introduced: 8.18.0 Description ----------- Manages the ``IP_FREEBIND`` option on the UDP socket, which allows binding it to an IP address that is nonlocal or not (yet) associated to any network interface. The parameter accepts the following values: - 0 - does not enable the ``IP_FREEBIND`` option on the UDP socket. If the ``bind()`` call fails because of ``EADDRNOTAVAIL`` error, socket initialization fails. - 1 - silently enables the ``IP_FREEBIND`` socket option if it is required to successfully bind the socket to a nonlocal address. - 2 - enables the ``IP_FREEBIND`` socket option and warns when it is used to successfully bind the socket to a nonlocal address. Input usage ----------- .. _param-imudp-input-ipfreebind: .. _imudp.parameter.input.ipfreebind-usage: .. code-block:: rsyslog input(type="imudp" IpFreeBind="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-timerequery.rst0000644000000000000000000000013215132733117025131 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.924479704 30 ctime=1787067792.599691605 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-timerequery.rst0000666000175000017500000000373715132733117024611 0ustar00rgerrger.. _param-imudp-timerequery: .. _imudp.parameter.module.timerequery: TimeRequery =========== .. index:: single: imudp; TimeRequery single: TimeRequery .. summary-start Frequency of system time queries; lower values yield more precise timestamps. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: TimeRequery :Scope: module :Type: integer :Default: module=2 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This is a performance optimization. Getting the system time is very costly. With this setting, imudp can be instructed to obtain the precise time only once every n-times. This logic is only activated if messages come in at a very fast rate, so doing less frequent time calls should usually be acceptable. The default value is two, because we have seen that even without optimization the kernel often returns twice the identical time. You can set this value as high as you like, but do so at your own risk. The higher the value, the less precise the timestamp. .. note:: The time requery is based on executed system calls, not messages received. When batch sizes are used, multiple messages are obtained with one system call and all receive the same timestamp. At very high traffic the requery logic means time is queried only for every second batch by default. Do not set ``TimeRequery`` above 10 when input batches are used. Module usage ------------ .. _param-imudp-module-timerequery: .. _imudp.parameter.module.timerequery-usage: .. code-block:: rsyslog module(load="imudp" TimeRequery="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.udpservertimerequery: - $UDPServerTimeRequery — maps to TimeRequery (status: legacy) .. index:: single: imudp; $UDPServerTimeRequery single: $UDPServerTimeRequery See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omuxsock-sockettype.rst0000644000000000000000000000013215132733117025502 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.069445123 30 ctime=1787067793.593710128 rsyslog-8.2608.0/doc/source/reference/parameters/omuxsock-sockettype.rst0000666000175000017500000000356615132733117025162 0ustar00rgerrger.. _param-omuxsock-sockettype: .. _omuxsock.parameter.module.sockettype: socketType ========== .. index:: single: omuxsock; socketType single: socketType .. summary-start This is the type of the socket (DGRAM, STREAM, SEQPACKET). .. summary-end This parameter applies to :doc:`../../configuration/modules/omuxsock`. :Name: socketType :Scope: module, action :Type: string :Default: module=DGRAM, action=DGRAM :Required?: no :Introduced: v8.2512 Description ----------- This indicates the type of socket. It can take on the value DGRAM to indicate a datagram socket type (the default) or STREAM to indicate a streaming socket type. When supported by the underlying operating system, it can also have the value SEQPACKET to indicate a sequenced packet socket type. Module usage ------------ .. _omuxsock.parameter.module.sockettype-usage: A socketType set at the module level becomes the default socketType for the first unnamed action. It only applies to a single unnamed action, so it is primarily just a short-hand notation for when only a single omuxsock action is required. .. code-block:: rsyslog module(load="omuxsock" socketType="DGRAM") Action usage ------------ .. _omuxsock.parameter.action.sockettype-usage: .. code-block:: rsyslog action(type="omuxsock" socketType="DGRAM") action(type="omuxsock" socketType="STREAM") action(type="omuxsock" socketType="SEQPACKET") .. note:: :ref:`param-omuxsock-socketname`, :ref:`param-omuxsock-abstract`, and :ref:`param-omuxsock-sockettype` constitute a logical configuration tuple. They are applied together as a whole tuple from a module level configuration to an action. Therefore, all three parameters must be explicitly specified in the action, or none may be specified in the action. In the latter case, the default is taken from the module. See also -------- See also :doc:`../../configuration/modules/omuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-container.rst0000644000000000000000000000013115145046112025233 xustar0030 mtime=1771326538.942012704 29 atime=1787067672.09344557 30 ctime=1787067792.742694269 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-container.rst0000664000175000017500000000255215145046112024704 0ustar00rgerrger.. _param-mmdarwin-container: .. _mmdarwin.parameter.module.container: container ========= .. index:: single: mmdarwin; container single: container .. summary-start Defines the JSON container path that holds mmdarwin's generated data. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: container :Scope: module :Type: word :Default: module="!mmdarwin" :Required?: no :Introduced: 8.2008.0 Description ----------- Set the JSON container path that mmdarwin uses when it writes Darwin metadata and response values back to the message. The container string must begin with ``"!"`` or ``"."`` so the path resolves to either the structured data in the message or a local variable tree. If no value is configured, mmdarwin stores data under ``"!mmdarwin"``. The module prefixes this container to the target specified by :ref:`param-mmdarwin-key` and to the generated ``"darwin_id"`` field that tracks the request UUID. As a result, selecting a custom container lets you control where the Darwin score and identifier are recorded. Module usage ------------ .. _param-mmdarwin-module-container-usage: .. _mmdarwin.parameter.module.container-usage: .. code-block:: rsyslog module(load="mmdarwin" container="!darwin") action(type="mmdarwin" key="certitude") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omstdout-template.rst0000644000000000000000000000013215145046112025125 xustar0030 mtime=1771326538.957012949 30 atime=1787067671.827440611 30 ctime=1787067793.566709625 rsyslog-8.2608.0/doc/source/reference/parameters/omstdout-template.rst0000664000175000017500000000147015145046112024573 0ustar00rgerrger.. _param-omstdout-template: .. _omstdout.parameter.input.template: template ======== .. index:: single: omstdout; template single: template .. summary-start Selects the rsyslog template used to format messages written to stdout. .. summary-end This parameter applies to :doc:`../../configuration/modules/omstdout`. :Name: template :Scope: input :Type: word :Default: input=RSYSLOG_FileFormat :Required?: no :Introduced: 4.1.6 Description ----------- Set the template that will be used for the output. If none is specified the module uses the default template. Input usage ----------- .. _param-omstdout-input-template: .. _omstdout.parameter.input.template-usage: .. code-block:: rsyslog action(type="omstdout" template="outfmt") See also -------- See also :doc:`../../configuration/modules/omstdout`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-template.rst0000644000000000000000000000013215145046112024731 xustar0030 mtime=1771326538.949012819 30 atime=1787067672.577454593 30 ctime=1787067793.441707295 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-template.rst0000664000175000017500000000157315145046112024403 0ustar00rgerrger.. _param-ompgsql-template: .. _ompgsql.parameter.input.template: Template ======== .. index:: single: ompgsql; Template single: Template .. summary-start Selects the template used for the SQL ``INSERT`` statement sent to PostgreSQL. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: Template :Scope: input :Type: word :Default: StdPgSQLFmt :Required?: no :Introduced: 8.32.0 Description ----------- The template name to use to ``INSERT`` rows into the database with. Valid SQL syntax is required, as the module does not perform any insertion statement checking. Input usage ----------- .. _ompgsql.parameter.input.template-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" db="syslog" template="sql-syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-db.rst0000644000000000000000000000013215132733117023606 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.314468332 30 ctime=1787067793.371705991 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-db.rst0000666000175000017500000000227115132733117023256 0ustar00rgerrger.. _param-omlibdbi-db: .. _omlibdbi.parameter.input.db: DB == .. index:: single: omlibdbi; DB single: DB .. summary-start Names the database schema that omlibdbi writes to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: DB :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Set this to the database instance that should receive the syslog events. It must exist on the selected server and accept the credentials supplied via ``UID`` and ``PWD``. Input usage ----------- .. _param-omlibdbi-input-db-usage: .. _omlibdbi.parameter.input.db-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbidbname: - $ActionLibdbiDBName — maps to DB (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiDBName single: $ActionLibdbiDBName See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-community.rst0000644000000000000000000000013215132733117024775 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.763439418 30 ctime=1787067793.539709122 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-community.rst0000666000175000017500000000204115132733117024440 0ustar00rgerrger.. _param-omsnmp-community: .. _omsnmp.parameter.module.community: Community ========= .. index:: single: omsnmp; Community single: Community .. summary-start Sets the SNMP community string. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: Community :Scope: module :Type: string :Default: module=public :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- This sets the used SNMP Community. Module usage ------------ .. _param-omsnmp-module-community: .. _omsnmp.parameter.module.community-usage: .. code-block:: rsyslog action(type="omsnmp" community="public") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmpcommunity: - $actionsnmpcommunity — maps to Community (status: legacy) .. index:: single: omsnmp; $actionsnmpcommunity single: $actionsnmpcommunity See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-basicauthfile.rst0000644000000000000000000000013215171370365025555 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.796458675 30 ctime=1787067792.156683349 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-basicauthfile.rst0000664000175000017500000000253715171370365025230 0ustar00rgerrger.. meta:: :description: Configure imhttp to protect an input with HTTP Basic Authentication. :keywords: rsyslog, imhttp, basicauthfile, http basic authentication .. _param-imhttp-basicauthfile: .. _imhttp.parameter.input.basicauthfile: .. _imhttp-basicauthfile: basicAuthFile ============= .. index:: single: imhttp; basicAuthFile single: basicAuthFile .. summary-start Protects an imhttp input with HTTP Basic Authentication using an htpasswd file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: basicAuthFile :Scope: input :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- imhttp accepts ``Authorization: Basic`` credentials for the input when this parameter is set. The htpasswd file is read line-by-line and blank lines or ``#`` comments are ignored. For safety, the Basic-auth header is capped at 2048 Base64 characters. That is already larger than practical Basic-auth credentials, but small enough to keep the parser on a fixed stack buffer and reject oversized headers outright. Input usage ----------- .. _imhttp.parameter.input.basicauthfile-usage: .. code-block:: rsyslog input( type="imhttp" endpoint="/ingest" basicAuthFile="/etc/rsyslog/htpasswd" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-tenant_id.rst0000644000000000000000000000013115171370365025547 xustar0030 mtime=1776677109.119908115 30 atime=1787067673.258467288 29 ctime=1787067792.96169835 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-tenant_id.rst0000664000175000017500000000170415171370365025216 0ustar00rgerrger.. _param-omazuredce-tenant_id: .. _omazuredce.parameter.action.tenant_id: .. meta:: :description: Reference for the omazuredce tenant_id parameter. :keywords: rsyslog, omazuredce, tenant_id, azure, entra tenant_id ========= .. index:: single: omazuredce; tenant_id single: tenant_id .. summary-start Sets the Microsoft Entra tenant used when requesting OAuth access tokens. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: tenant_id :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``tenant_id`` identifies the Microsoft Entra tenant that issues the token for the configured application credentials. Action usage ------------ .. _omazuredce.parameter.action.tenant_id-usage: .. code-block:: rsyslog action(type="omazuredce" tenant_id="" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-mainmsgqueuetimeoutenqueue.rst0000644000000000000000000000013215171370365030376 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.039444563 30 ctime=1787067791.947679455 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-mainmsgqueuetimeoutenqueue.rst0000664000175000017500000000301615171370365030042 0ustar00rgerrger.. _param-imdiag-mainmsgqueuetimeoutenqueue: .. _imdiag.parameter.module.mainmsgqueuetimeoutenqueue: .. meta:: :description: Reference for the imdiag mainMsgQueueTimeoutEnqueue module parameter. :keywords: rsyslog, imdiag, mainmsgqueuetimeoutenqueue, testbench, timeout, queue MainMsgQueueTimeoutEnqueue =========================== .. index:: single: imdiag; MainMsgQueueTimeoutEnqueue .. summary-start Sets the main message queue enqueue timeout at config load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: MainMsgQueueTimeoutEnqueue :Scope: module :Type: integer (milliseconds) :Default: 30000 :Required?: no :Introduced: 8.x Description ----------- Sets ``globals.mainQ.iMainMsgQtoEnq`` — the time a producer will wait when the main message queue is full before dropping the message — at config-load time. The testbench uses this to establish a safe default without relying on legacy ``$MainMsgQueueTimeoutEnqueue`` directives, which are not available in YAML-only mode. Override per-test via ``RSTB_MAIN_Q_TO_ENQUEUE`` before ``generate_conf``, or via a ``$MainMsgQueueTimeoutEnqueue`` directive in the RainerScript test fragment. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" mainMsgQueueTimeoutEnqueue="30000") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" mainmsgqueuetimeoutenqueue: "30000" See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-resubmitonfailure.rst0000644000000000000000000000013115132411300026572 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.133464958 29 ctime=1787067793.35770573 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-resubmitonfailure.rst0000666000175000017500000000200515132411300026236 0ustar00rgerrger.. _param-omkafka-resubmitonfailure: .. _omkafka.parameter.module.resubmitonfailure: resubmitOnFailure ================= .. index:: single: omkafka; resubmitOnFailure single: resubmitOnFailure .. summary-start Retry failed messages when Kafka becomes available. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: resubmitOnFailure :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.28.0 Description ----------- .. versionadded:: 8.28.0 If enabled, failed messages will be resubmitted automatically when Kafka can send messages again. Messages rejected because they exceed the maximum size are dropped. Action usage ------------ .. _param-omkafka-action-resubmitonfailure: .. _omkafka.parameter.action.resubmitonfailure: .. code-block:: rsyslog action(type="omkafka" resubmitOnFailure="on") Notes ----- - Originally documented as "binary"; uses boolean values. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/immark-ruleset.rst0000644000000000000000000000013215132733117024403 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.306468183 30 ctime=1787067792.256685213 rsyslog-8.2608.0/doc/source/reference/parameters/immark-ruleset.rst0000666000175000017500000000224415132733117024053 0ustar00rgerrger.. _param-immark-ruleset: .. _immark.parameter.module.ruleset: ruleset ======= .. index:: single: immark; ruleset single: ruleset .. summary-start Routes mark messages to the named ruleset instead of the default. .. summary-end This parameter applies to :doc:`../../configuration/modules/immark`. :Name: ruleset :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none :Required?: no :Introduced: 8.2012.0 Description ----------- Set this parameter to bind mark messages emitted by immark to a specific ruleset. The module looks up the ruleset during configuration; if it is not found, immark logs a warning and continues with the default ruleset. If a ruleset is configured while :ref:`param-immark-use-syslogcall` remains ``on``, immark issues a warning and forces this parameter to ``off`` so the ruleset can take effect. Module usage ------------ .. _immark.parameter.module.ruleset-usage: .. code-block:: rsyslog module(load="immark" use.syslogCall="off" ruleset="markRouting") See also -------- .. seealso:: * :ref:`param-immark-use-syslogcall` * :doc:`../../configuration/modules/immark` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-killunresponsive.rst0000644000000000000000000000013215132733117026357 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.958461695 30 ctime=1787067793.466707761 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-killunresponsive.rst0000666000175000017500000000431415132733117026027 0ustar00rgerrger.. _param-omprog-killunresponsive: .. _omprog.parameter.action.killunresponsive: killUnresponsive ================ .. index:: single: omprog; killUnresponsive single: killUnresponsive .. summary-start Kills the program if it remains after the close timeout expires. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: killUnresponsive :Scope: action :Type: boolean :Default: action=the value of 'signalOnClose' :Required?: no :Introduced: 8.35.0 Description ----------- Specifies whether a KILL signal must be sent to the external program in case it does not terminate within the timeout indicated by :ref:`param-omprog-closetimeout` (when either the worker thread has been unscheduled, a restart of the program is being forced, or rsyslog is about to shutdown). If :ref:`param-omprog-signalonclose` is set to "on", the default value of ``killUnresponsive`` is also "on". In this case, the cleanup sequence of the child process is as follows: (1) a TERM signal is sent to the child, (2) the pipe with the child process is closed (the child will receive EOF on stdin), (3) rsyslog waits for the child process to terminate during :ref:`param-omprog-closetimeout`, (4) if the child has not terminated within the timeout, a KILL signal is sent to it. If :ref:`param-omprog-signalonclose` is set to "off", the default value of ``killUnresponsive`` is also "off". In this case, the child cleanup sequence is as follows: (1) the pipe with the child process is closed (the child will receive EOF on stdin), (2) rsyslog waits for the child process to terminate during :ref:`param-omprog-closetimeout`, (3) if the child has not terminated within the timeout, rsyslog ignores it. This parameter can be set to a different value than :ref:`param-omprog-signalonclose`, obtaining the corresponding variations of cleanup sequences described above. Action usage ------------ .. _param-omprog-action-killunresponsive: .. _omprog.parameter.action.killunresponsive-usage: .. code-block:: rsyslog action(type="omprog" killUnresponsive="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-healthchecktimeout.rst0000644000000000000000000000013115132733117026624 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.138465051 30 ctime=1787067793.253703792 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-healthchecktimeout.rst0000666000175000017500000000155615132733117026302 0ustar00rgerrger.. _param-omhttp-healthchecktimeout: .. _omhttp.parameter.input.healthchecktimeout: healthchecktimeout ================== .. index:: single: omhttp; healthchecktimeout single: healthchecktimeout .. summary-start Sets the number of milliseconds omhttp waits before a health check request times out. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: healthchecktimeout :Scope: input :Type: integer :Default: input=3500 :Required?: no :Introduced: Not specified Description ----------- The time after which the health check will time out in milliseconds. Input usage ----------- .. _omhttp.parameter.input.healthchecktimeout-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" healthCheckTimeout="5000" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-myprivkey.rst0000644000000000000000000000013215132411300027430 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.147446577 30 ctime=1787067793.110701127 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-myprivkey.rst0000666000175000017500000000167615132411300027110 0ustar00rgerrger.. _param-omelasticsearch-tls-myprivkey: .. _omelasticsearch.parameter.module.tls-myprivkey: .. _omelasticsearch.parameter.module.tls.myprivkey: tls.myprivkey ============= .. index:: single: omelasticsearch; tls.myprivkey single: tls.myprivkey .. summary-start Unencrypted private key for `tls.mycert`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.myprivkey :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- PEM file containing the private key corresponding to the client certificate. The key must not be encrypted. Action usage ------------ .. _param-omelasticsearch-action-tls-myprivkey: .. _omelasticsearch.parameter.action.tls-myprivkey: .. code-block:: rsyslog action(type="omelasticsearch" tls.myprivkey="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-schedulingpolicy.rst0000644000000000000000000000013215132733117026123 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.775476926 30 ctime=1787067792.593691493 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-schedulingpolicy.rst0000666000175000017500000000253415132733117025575 0ustar00rgerrger.. _param-imudp-schedulingpolicy: .. _imudp.parameter.module.schedulingpolicy: SchedulingPolicy ================ .. index:: single: imudp; SchedulingPolicy single: SchedulingPolicy .. summary-start Selects OS scheduler policy like ``fifo`` for real-time handling. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: SchedulingPolicy :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Can be used to set the scheduler priority, if the necessary functionality is provided by the platform. Most useful to select ``fifo`` for real-time processing under Linux (and thus reduce chance of packet loss). Other options are ``rr`` and ``other``. Module usage ------------ .. _param-imudp-module-schedulingpolicy: .. _imudp.parameter.module.schedulingpolicy-usage: .. code-block:: rsyslog module(load="imudp" SchedulingPolicy="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.imudpschedulingpolicy: - $IMUDPSchedulingPolicy — maps to SchedulingPolicy (status: legacy) .. index:: single: imudp; $IMUDPSchedulingPolicy single: $IMUDPSchedulingPolicy See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-ziplevel.rst0000644000000000000000000000013215132411300024530 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.493453027 30 ctime=1787067793.208702953 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-ziplevel.rst0000666000175000017500000000222515132411300024177 0ustar00rgerrger.. _param-omfile-ziplevel: .. _omfile.parameter.module.ziplevel: zipLevel ======== .. index:: single: omfile; zipLevel single: zipLevel .. summary-start If greater than 0, turns on gzip compression of the output file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: zipLevel :Scope: action :Type: integer :Default: action=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If greater than 0, turns on gzip compression of the output file. The higher the number, the better the compression, but also the more CPU is required for zipping. Action usage ------------ .. _param-omfile-action-ziplevel: .. _omfile.parameter.action.ziplevel: .. code-block:: rsyslog action(type="omfile" zipLevel="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.omfileziplevel: - $OMFileZipLevel — maps to zipLevel (status: legacy) .. index:: single: omfile; $OMFileZipLevel single: $OMFileZipLevel See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-tls-mycert.rst0000644000000000000000000000013215132733117026244 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.726457371 30 ctime=1787067792.857696412 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-tls-mycert.rst0000666000175000017500000000175215132733117025717 0ustar00rgerrger.. _param-mmkubernetes-tls-mycert: .. _mmkubernetes.parameter.action.tls-mycert: tls.mycert ========== .. index:: single: mmkubernetes; tls.mycert single: tls.mycert .. summary-start Specifies the client certificate for authenticating to Kubernetes. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: tls.mycert :Scope: action :Type: word :Default: none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This is the full path and file name of the file containing the client cert for doing client cert auth against Kubernetes. This file is in PEM format. For example: `/etc/rsyslog.d/k8s-client-cert.pem` Action usage ------------ .. _param-mmkubernetes-action-tls-mycert: .. _mmkubernetes.parameter.action.tls-mycert-usage: .. code-block:: rsyslog action(type="mmkubernetes" tls.myCert="/etc/rsyslog.d/k8s-client-cert.pem") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-server.rst0000644000000000000000000000013215132733117024527 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.692456737 30 ctime=1787067793.380706159 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-server.rst0000666000175000017500000000236615132733117024204 0ustar00rgerrger.. _param-omlibdbi-server: .. _omlibdbi.parameter.input.server: Server ====== .. index:: single: omlibdbi; Server single: Server .. summary-start Specifies the hostname or address of the database server to connect to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: Server :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Use this to point omlibdbi at the host that runs the selected database engine. Combine it with the driver, credentials, and database name to form the full connection information. Input usage ----------- .. _param-omlibdbi-input-server-usage: .. _omlibdbi.parameter.input.server-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbihost: - $ActionLibdbiHost — maps to Server (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiHost single: $ActionLibdbiHost See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-permittedpeer.rst0000644000000000000000000000013215132733117025425 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.112483209 30 ctime=1787067792.505689853 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-permittedpeer.rst0000666000175000017500000000372115132733117025076 0ustar00rgerrger.. _param-imtcp-permittedpeer: .. _imtcp.parameter.module.permittedpeer: .. _imtcp.parameter.input.permittedpeer: PermittedPeer ============= .. index:: single: imtcp; PermittedPeer single: PermittedPeer .. summary-start Restricts connections to listed peer identities. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: PermittedPeer :Scope: module, input :Type: array :Default: module=none, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets permitted peer IDs. Only these peers are able to connect to the listener. semantics depend on the currently selected AuthMode and :doc:`network stream driver <../../concepts/netstrm_drvr>`. PermittedPeer may not be set in anonymous modes. PermittedPeer may be set either to a single peer or an array of peers either of type IP or name, depending on the tls certificate. Single peer: PermittedPeer="127.0.0.1" Array of peers: PermittedPeer=["test1.example.net","10.1.2.3","test2.example.net","..."] The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-permittedpeer: .. _imtcp.parameter.module.permittedpeer-usage: .. code-block:: rsyslog module(load="imtcp" permittedPeer="127.0.0.1") Input usage ----------- .. _param-imtcp-input-permittedpeer: .. _imtcp.parameter.input.permittedpeer-usage: .. code-block:: rsyslog input(type="imtcp" port="514" permittedPeer="127.0.0.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverstreamdriverpermittedpeer: - $InputTCPServerStreamDriverPermittedPeer — maps to PermittedPeer (status: legacy) .. index:: single: imtcp; $InputTCPServerStreamDriverPermittedPeer single: $InputTCPServerStreamDriverPermittedPeer See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-reopenontruncate.rst0000644000000000000000000000013115132733117026277 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.462452449 29 ctime=1787067792.10468238 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-reopenontruncate.rst0000666000175000017500000000235015132733117025746 0ustar00rgerrger.. _param-imfile-reopenontruncate: .. _imfile.parameter.input.reopenontruncate: .. _imfile.parameter.reopenontruncate: reopenOnTruncate ================ .. index:: single: imfile; reopenOnTruncate single: reopenOnTruncate .. summary-start Experimental: reopen the input file if it was truncated without changing its inode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: reopenOnTruncate :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When activated, tells rsyslog to reopen the input file if it was truncated (the inode is unchanged but the file size on disk is smaller than the current offset in memory). This feature is experimental. Input usage ----------- .. _param-imfile-input-reopenontruncate: .. _imfile.parameter.input.reopenontruncate-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" reopenOnTruncate="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. - This parameter is **experimental** and may change. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-ratelimit-burst.rst0000644000000000000000000000013215132411300027720 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.213447807 30 ctime=1787067793.070700382 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-ratelimit-burst.rst0000666000175000017500000000172315132411300027371 0ustar00rgerrger.. _param-omelasticsearch-ratelimit-burst: .. _omelasticsearch.parameter.module.ratelimit-burst: .. _omelasticsearch.parameter.module.ratelimit.burst: ratelimit.burst =============== .. index:: single: omelasticsearch; ratelimit.burst single: ratelimit.burst .. summary-start Maximum messages allowed in a rate-limit interval. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: ratelimit.burst :Scope: action :Type: integer :Default: action=20000 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Specifies the burst size permitted within `ratelimit.interval` when retry limiting is active. Action usage ------------ .. _param-omelasticsearch-action-ratelimit-burst: .. _omelasticsearch.parameter.action.ratelimit-burst: .. code-block:: rsyslog action(type="omelasticsearch" ratelimit.burst="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-socket.rst0000644000000000000000000000013115145046112024424 xustar0030 mtime=1771326538.947012786 30 atime=1787067673.182465871 29 ctime=1787067793.42370696 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-socket.rst0000664000175000017500000000212315145046112024067 0ustar00rgerrger.. _param-ommysql-socket: .. _ommysql.parameter.input.socket: Socket ====== .. index:: single: ommysql; Socket single: Socket .. summary-start Sets the Unix socket path to use when connecting to the MariaDB/MySQL server. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: socket :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: at least 7.x, possibly earlier Description ----------- This is the unix socket path of the MariaDB/MySQL server. When the server address is set localhost, the MariaDB/MySQL client library connects using the default unix socket specified at build time. If you run MariaDB/MySQL server and run the unix socket path differently than the default, you can set the socket path with this option. Input usage ----------- .. _ommysql.parameter.input.socket-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="localhost" socket="/var/run/mysqld/mysqld.sock" db="syslog_db" uid="user" pwd="pwd") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-listenportfilename.rst0000644000000000000000000000013215216464435026471 xustar0030 mtime=1782212893.985265521 30 atime=1787067674.269486135 30 ctime=1787067792.571691083 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-listenportfilename.rst0000664000175000017500000000357615216464435026150 0ustar00rgerrger.. _param-imudp-listenportfilename: .. _imudp.parameter.input.listenportfilename: ListenPortFileName ================== .. index:: single: imudp; ListenPortFileName single: ListenPortFileName .. summary-start Writes the UDP listener's bound port number into the given file. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: ListenPortFileName :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: 8.2606.0 Description ----------- Specifies a file name into which the port number this input listens on is written after the UDP socket is bound. It is primarily useful with ``port="0"``, where the operating system assigns an available port and rsyslog writes the assigned port to the file. This parameter can be used only when the ``port`` array contains one value and that value binds exactly one UDP socket. Wildcard addresses can resolve to multiple sockets, for example separate IPv4 and IPv6 sockets, and are rejected with ``listenPortFileName`` because one file would be ambiguous. Set ``address`` to a single local address, or configure separate ``imudp`` inputs with separate ``listenPortFileName`` values. When used with a nonzero single port, rsyslog writes the actual bound port number to the file after the bind succeeds. The file is created with owner-only permissions when it does not already exist, and rsyslog refuses symlinks, FIFOs, and other special files. Configure this path in a trusted directory such as ``/run/rsyslog`` rather than a directory writable by unprivileged users. Input usage ----------- .. _param-imudp-input-listenportfilename: .. _imudp.parameter.input.listenportfilename-usage: .. code-block:: rsyslog input(type="imudp" port="0" listenPortFileName="/run/rsyslog/imudp.port") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dirowner.rst0000644000000000000000000000013115132411300024526 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.357450492 29 ctime=1787067793.15270191 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dirowner.rst0000666000175000017500000000301715132411300024176 0ustar00rgerrger.. _param-omfile-dirowner: .. _omfile.parameter.module.dirowner: dirOwner ======== .. index:: single: omfile; dirOwner single: dirOwner .. summary-start Set the file owner for directories newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dirOwner :Scope: module, action :Type: uid :Default: module=process user; action=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the file owner for directories newly created. Please note that this setting does not affect the owner of directories already existing. The parameter is a user name, for which the userid is obtained by rsyslogd during startup processing. Interim changes to the user mapping are not detected. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-dirowner: .. _omfile.parameter.module.dirowner-usage: .. code-block:: rsyslog module(load="builtin:omfile" dirOwner="...") Action usage ------------ .. _param-omfile-action-dirowner: .. _omfile.parameter.action.dirowner: .. code-block:: rsyslog action(type="omfile" dirOwner="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dirowner: - $DirOwner — maps to dirOwner (status: legacy) .. index:: single: omfile; $DirOwner single: $DirOwner See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-template.rst0000644000000000000000000000013215145046112024545 xustar0030 mtime=1771326538.953012884 30 atime=1787067672.523453586 30 ctime=1787067793.499708376 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-template.rst0000664000175000017500000000144015145046112024210 0ustar00rgerrger.. _param-omrelp-template: .. _omrelp.parameter.input.template: Template ======== .. index:: single: omrelp; Template single: Template .. summary-start Selects the output template used to format RELP messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: Template :Scope: input :Type: string :Default: input=RSYSLOG_ForwardFormat :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Defines the template to be used for the output. Input usage ----------- .. _param-omrelp-input-template: .. _omrelp.parameter.input.template-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" template="RSYSLOG_ForwardFormat") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-logpath.rst0000644000000000000000000000013215132733117024360 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.077463914 30 ctime=1787067792.238684877 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-logpath.rst0000666000175000017500000000223715132733117024032 0ustar00rgerrger.. _param-imklog-logpath: .. _imklog.parameter.module.logpath: LogPath ======= .. index:: single: imklog; LogPath single: LogPath .. summary-start Specifies the kernel log device or file that imklog reads. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: LogPath :Scope: module :Type: word :Default: Linux: "/proc/kmsg"; other platforms: "/dev/klog" :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines the path to the kernel log device or file that imklog reads from. If this parameter is not set, it defaults to "/proc/kmsg" on Linux and "/dev/klog" on other platforms. Module usage ------------ .. _param-imklog-module-logpath: .. _imklog.parameter.module.logpath-usage: .. code-block:: rsyslog module(load="imklog" logPath="/dev/klog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.klogpath: - $klogpath — maps to LogPath (status: legacy) .. index:: single: imklog; $klogpath single: $klogpath See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-pwd.rst0000644000000000000000000000013215132733117024013 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.544453978 30 ctime=1787067793.377706103 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-pwd.rst0000666000175000017500000000225115132733117023461 0ustar00rgerrger.. _param-omlibdbi-pwd: .. _omlibdbi.parameter.input.pwd: PWD === .. index:: single: omlibdbi; PWD single: PWD .. summary-start Sets the password for the database user defined via ``UID``. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: PWD :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Supply the password that matches the user provided through the ``UID`` parameter so omlibdbi can authenticate to the database. Input usage ----------- .. _param-omlibdbi-input-pwd-usage: .. _omlibdbi.parameter.input.pwd-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbipassword: - $ActionLibdbiPassword — maps to PWD (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiPassword single: $ActionLibdbiPassword See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-serverport.rst0000644000000000000000000000013215132411300027004 xustar0030 mtime=1768559296.208884723 30 atime=1787067671.978443426 30 ctime=1787067793.090700754 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-serverport.rst0000666000175000017500000000152015132411300026450 0ustar00rgerrger.. _param-omelasticsearch-serverport: .. _omelasticsearch.parameter.module.serverport: Serverport ========== .. index:: single: omelasticsearch; Serverport single: Serverport .. summary-start Default port used when server URLs omit a port. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: Serverport :Scope: action :Type: integer :Default: action=9200 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Port applied to entries in `server` that lack an explicit port number. Action usage ------------ .. _param-omelasticsearch-action-serverport: .. _omelasticsearch.parameter.action.serverport: .. code-block:: rsyslog action(type="omelasticsearch" Serverport="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-timeout.rst0000644000000000000000000000013115132733117024421 xustar0030 mtime=1768666703.903620178 29 atime=1787067671.96844324 30 ctime=1787067792.028680964 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-timeout.rst0000666000175000017500000000170215132733117024070 0ustar00rgerrger.. _param-imdtls-timeout: .. _imdtls.parameter.input.timeout: Timeout ======= .. index:: single: imdtls; timeout single: timeout .. summary-start Closes idle DTLS sessions after the configured inactivity period. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: timeout :Scope: input :Type: word :Default: 1800 :Required?: no :Introduced: v8.2402.0 Description ----------- Specifies the DTLS session timeout. As DTLS runs on the connectionless UDP protocol, there are no automatic detections of a session timeout. The input closes the DTLS session if no data is received from the client for the configured timeout period. The default is 1800 seconds, which is equal to 30 minutes. Input usage ----------- .. _imdtls.parameter.input.timeout-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" timeout="900") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omlibdbi-driver.rst0000644000000000000000000000013215132733117024514 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.333468686 30 ctime=1787067793.373706028 rsyslog-8.2608.0/doc/source/reference/parameters/omlibdbi-driver.rst0000666000175000017500000000275315132733117024171 0ustar00rgerrger.. _param-omlibdbi-driver: .. _omlibdbi.parameter.input.driver: Driver ====== .. index:: single: omlibdbi; Driver single: Driver .. summary-start Selects the libdbi driver backend to use for this action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omlibdbi`. :Name: Driver :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Set this to the driver name that matches your database backend, as documented by libdbi-drivers. Common values include: - ``mysql`` (:doc:`../../configuration/modules/ommysql` is recommended instead) - ``firebird`` (Firebird and InterBase) - ``ingres`` - ``msql`` - ``Oracle`` - ``sqlite`` - ``sqlite3`` - ``freetds`` (Microsoft SQL and Sybase) - ``pgsql`` (:doc:`../../configuration/modules/ompgsql` is recommended instead) Input usage ----------- .. _param-omlibdbi-input-driver-usage: .. _omlibdbi.parameter.input.driver-usage: .. code-block:: rsyslog action(type="omlibdbi" driver="mysql" server="db.example.net" uid="dbwriter" pwd="sup3rSecret" db="syslog") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omlibdbi.parameter.legacy.actionlibdbidriver: - $ActionLibdbiDriver — maps to Driver (status: legacy) .. index:: single: omlibdbi; $ActionLibdbiDriver single: $ActionLibdbiDriver See also -------- See also :doc:`../../configuration/modules/omlibdbi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-proxyhost.rst0000644000000000000000000000013115132733117025031 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.855459775 30 ctime=1787067793.271704127 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-proxyhost.rst0000666000175000017500000000162515132733117024504 0ustar00rgerrger.. _param-omhttp-proxyhost: .. _omhttp.parameter.input.proxyhost: proxyhost ========= .. index:: single: omhttp; proxyhost single: proxyhost .. summary-start Sets the hostname of the HTTP proxy that omhttp should use. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: proxyhost :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- Configures the libcurl ``CURLOPT_PROXY`` option for HTTP requests issued by omhttp. For more details see the `libcurl documentation for CURLOPT_PROXY `_. Input usage ----------- .. _omhttp.parameter.input.proxyhost-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" proxyHost="proxy.internal.example" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-pwd.rst0000644000000000000000000000013115132733117023544 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.902460651 30 ctime=1787067793.276704221 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-pwd.rst0000666000175000017500000000130115132733117023206 0ustar00rgerrger.. _param-omhttp-pwd: .. _omhttp.parameter.input.pwd: pwd === .. index:: single: omhttp; pwd single: pwd .. summary-start Provides the password for HTTP basic authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: pwd :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The password for the user for basic auth. Input usage ----------- .. _omhttp.parameter.input.pwd-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" uid="api-user" pwd="s3cr3t!" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsendertrack-senderid.rst0000644000000000000000000000013215132733117026076 xustar0030 mtime=1768666703.923620481 30 atime=1787067673.026462963 30 ctime=1787067793.535709047 rsyslog-8.2608.0/doc/source/reference/parameters/omsendertrack-senderid.rst0000666000175000017500000000311415132733117025543 0ustar00rgerrger.. _param-omsendertrack-senderid: .. _omsendertrack.parameter.input.senderid: senderid ======== .. index:: single: omsendertrack; senderid single: senderid .. summary-start Sets the template used to derive the unique sender identifier that omsendertrack tracks. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsendertrack`. :Name: senderid :Scope: input :Type: string :Default: input=RSYSLOG_FileFormat :Required?: no :Introduced: 8.2506.0 (Proof-of-Concept) Description ----------- This parameter defines the **template used to determine the sender's unique identifier**. The value produced by this template becomes the key for tracking individual senders within the module's internal statistics. For instance: * A simple template like ``"%hostname%"`` tracks each unique host that submits messages to rsyslog. * Using ``"%fromhost-ip%"`` tracks senders based on their IP address. * A more granular template such as ``"%hostname%-%app-name%"`` differentiates between applications on the same host. **Note:** The processing of this template for every incoming message can impact overall throughput, especially if complex templates are used. Choose your template wisely based on your tracking needs and performance considerations. Input usage ----------- .. _omsendertrack.parameter.input.senderid-usage: .. code-block:: rsyslog module(load="omsendertrack") action(type="omsendertrack" senderId="%hostname%" stateFile="/var/lib/rsyslog/senderstats.json") See also -------- See also :doc:`../../configuration/modules/omsendertrack`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-statsname.rst0000644000000000000000000000013115132733117027044 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.494471688 30 ctime=1787067792.936697884 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-statsname.rst0000666000175000017500000000204115132733117026510 0ustar00rgerrger.. _param-omazureeventhubs-statsname: .. _omazureeventhubs.parameter.input.statsname: statsname ========= .. index:: single: omazureeventhubs; statsname single: statsname .. summary-start Names the statistics counters that track this action instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: statsname :Scope: input :Type: word :Default: input=omazureeventhubs :Required?: no :Introduced: v8.2304 Description ----------- The name assigned to statistics specific to this action instance. The supported set of statistics tracked for this action instance are ``submitted``, ``accepted``, ``failures``, and ``othererrors``. Note that in global module statistics, the counter corresponding to ``othererrors`` is named ``failures_other``. Input usage ----------- .. _omazureeventhubs.parameter.input.statsname-usage: .. code-block:: rsyslog action(type="omazureeventhubs" statsName="custom-azure" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-mode.rst0000644000000000000000000000013215216464435026524 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.873441469 30 ctime=1787067791.382668926 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-mode.rst0000664000175000017500000000172315216464435026173 0ustar00rgerrger.. _param-imbeats-streamdriver-mode: .. _imbeats.parameter.input.streamdriver-mode: StreamDriver.Mode ================= .. meta:: :description: Stream driver mode for imbeats. :keywords: rsyslog, imbeats, streamdriver mode .. index:: single: imbeats; StreamDriver.Mode single: StreamDriver.Mode .. summary-start Select whether imbeats uses plain TCP or a TLS-enabled stream driver mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.Mode :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: 8.2604.0 Description ----------- Select whether imbeats uses plain TCP or a TLS-enabled stream driver mode. Input usage ----------- .. _param-imbeats-input-streamdriver-mode: .. _imbeats.parameter.input.streamdriver-mode-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.mode="1") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-compression.rst0000644000000000000000000000013215145046112026073 xustar0030 mtime=1771326538.954012901 30 atime=1787067672.724457333 30 ctime=1787067793.508708544 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-compression.rst0000664000175000017500000000172315145046112025542 0ustar00rgerrger.. _param-omrelp-tls-compression: .. _omrelp.parameter.input.tls-compression: TLS.Compression =============== .. index:: single: omrelp; TLS.Compression single: TLS.Compression .. summary-start Controls whether the TLS stream is compressed. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.Compression :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The controls if the TLS stream should be compressed (zipped). While this increases CPU use, the network bandwidth should be reduced. Note that typical text-based log records usually compress rather well. Input usage ----------- .. _param-omrelp-input-tls-compression: .. _omrelp.parameter.input.tls-compression-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.compression="on") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-networknamespace.rst0000644000000000000000000000013015132733117026120 xustar0030 mtime=1768666703.908620253 28 atime=1787067674.1334836 30 ctime=1787067792.498689722 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-networknamespace.rst0000666000175000017500000000273315132733117025575 0ustar00rgerrger.. _param-imtcp-networknamespace: .. _imtcp.parameter.input.networknamespace: NetworkNamespace ================ .. index:: single: imtcp; NetworkNamespace single: NetworkNamespace .. summary-start Sets the value for the ``networknamespace`` property. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: NetworkNamespace :Scope: module, input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: v8.2512 Description ----------- Sets the network namespace for the listener. - If not set, the listener operates in the default (startup) network namespace. - The specified namespace must exist before rsyslogd starts (e.g., created via ``ip netns add ``). - This feature requires rsyslog to be built with ``setns()`` support. An error will be logged if a namespace is configured but support is missing. - The underlying operating system must also support network namespaces. Input usage ----------- .. _param-imtcp-input-networknamespace: .. _imtcp.parameter.input.networknamespace-usage: .. code-block:: rsyslog input(type="imtcp" port="514" NetworkNamespace="routing") input(type="imtcp" port="514" NetworkNamespace="management") .. code-block:: rsyslog module(load="imtcp" NetworkNamespace="routing") input(type="imtcp" port="514") input(type="imtcp" port="514" NetworkNamespace="management") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-permittedpeer.rst0000644000000000000000000000013215132733117026405 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.072445179 30 ctime=1787067792.040681188 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-permittedpeer.rst0000666000175000017500000000364615132733117026064 0ustar00rgerrger.. _param-imdtls-tls-permittedpeer: .. _imdtls.parameter.input.tls-permittedpeer: tls.permittedPeer ================= .. index:: single: imdtls; tls.permittedPeer single: tls.permittedPeer .. summary-start Restricts DTLS clients to the listed certificate fingerprints or names. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.permittedPeer :Scope: input :Type: array :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- ``tls.permittedPeer`` places access restrictions on this listener. Only peers whose certificate fingerprint or name is listed in this array parameter may connect. The certificate presented by the remote peer is used for its validation. When a non-permitted peer connects, the refusal is logged together with its fingerprint. If the administrator knows this was a valid request, they can simply add the fingerprint by copy and paste from the logfile to ``rsyslog.conf``. To specify multiple fingerprints, enclose them in braces like this: .. code-block:: none tls.permittedPeer=["SHA1:...1", "SHA1:....2"] To specify just a single peer, you can either specify the string directly or enclose it in braces. You may also use wildcards to match a larger number of permitted peers, e.g. ``*.example.com``. When using wildcards to match a larger number of permitted peers, the implementation is similar to Syslog RFC5425. This wildcard matches any left-most DNS label in the server name. That is, the subject ``*.example.com`` matches the server names ``a.example.com`` and ``b.example.com``, but does not match ``example.com`` or ``a.b.example.com``. Input usage ----------- .. _imdtls.parameter.input.tls-permittedpeer-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.permittedPeer=["SHA1:11223344556677889900AABBCCDDEEFF00112233"]) See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-name.rst0000644000000000000000000000013215132733117023476 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.285486434 30 ctime=1787067792.575691157 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-name.rst0000666000175000017500000000311615132733117023145 0ustar00rgerrger.. _param-imudp-name: .. _imudp.parameter.input.name: Name ==== .. index:: single: imudp; Name single: Name .. summary-start Value assigned to ``inputname`` property for this listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: Name :Scope: input :Type: word :Default: input=imudp :Required?: no :Introduced: 8.3.3 Description ----------- Specifies the value of the ``inputname`` property. In older versions, this was always ``imudp`` for all listeners, which still is the default. Starting with 7.3.9 it can be set to different values for each listener. Note that when a single input statement defines multiple listener ports, the ``inputname`` will be the same for all of them. If you want to differentiate in that case, use ``name.appendPort`` to make them unique. Note that the ``name`` parameter can be an empty string. In that case, the corresponding ``inputname`` property will obviously also be the empty string. This is primarily meant to be used together with ``name.appendPort`` to set the ``inputname`` equal to the port. Examples: .. code-block:: rsyslog module(load="imudp") input(type="imudp" port=["10514","10515","10516"] name="udp" name.appendPort="on") .. code-block:: rsyslog module(load="imudp") input(type="imudp" port=["10514","10515","10516"] name="" name.appendPort="on") Input usage ----------- .. _param-imudp-input-name: .. _imudp.parameter.input.name-usage: .. code-block:: rsyslog input(type="imudp" Name="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-use.rst0000644000000000000000000000013215132733117025572 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.760476647 30 ctime=1787067792.659692723 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-use.rst0000666000175000017500000000360415132733117025243 0ustar00rgerrger.. _param-imuxsock-syssock-use: .. _imuxsock.parameter.module.syssock-use: SysSock.Use =========== .. index:: single: imuxsock; SysSock.Use single: SysSock.Use .. summary-start Enables listening on the system log socket or the path set by SysSock.Name. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.Use :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Listen on the default local log socket (``/dev/log``) or, if provided, use the log socket value assigned to the ``SysSock.Name`` parameter instead of the default. This is most useful if you run multiple instances of rsyslogd where only one shall handle the system log socket. Unless disabled by the ``SysSock.Unlink`` setting, this socket is created upon rsyslog startup and deleted upon shutdown, according to traditional syslogd behavior. The behavior of this parameter is different for systemd systems. For those systems, ``SysSock.Use`` still needs to be enabled, but the value of ``SysSock.Name`` is ignored and the socket provided by systemd is used instead. If this parameter is *not* enabled, then imuxsock will only be of use if a custom input is configured. See the :ref:`imuxsock-systemd-details-label` section for details. Module usage ------------ .. _param-imuxsock-module-syssock-use: .. _imuxsock.parameter.module.syssock-use-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.use="off") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.omitlocallogging: - $OmitLocalLogging — maps to SysSock.Use (status: legacy) .. index:: single: imuxsock; $OmitLocalLogging single: $OmitLocalLogging See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxdecompressedsize.rst0000644000000000000000000000013215216464435027151 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.788439884 30 ctime=1787067791.344668218 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxdecompressedsize.rst0000664000175000017500000000224415216464435026617 0ustar00rgerrger.. _param-imbeats-maxdecompressedsize: .. _imbeats.parameter.input.maxdecompressedsize: maxDecompressedSize =================== .. meta:: :description: Maximum decompressed Lumberjack payload size accepted by imbeats. :keywords: rsyslog, imbeats, maxDecompressedSize, Lumberjack compression .. index:: single: imbeats; maxDecompressedSize single: maxDecompressedSize .. summary-start Limit how large a compressed Lumberjack frame may become after decompression. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxDecompressedSize :Scope: input :Type: positive integer :Default: input=67108864 :Required?: no :Introduced: 8.2604.0 Description ----------- Set the maximum byte size accepted after decompressing a Lumberjack compressed frame. Frames that expand beyond this value are rejected before unbounded memory growth can occur. Input usage ----------- .. _param-imbeats-input-maxdecompressedsize: .. _imbeats.parameter.input.maxdecompressedsize-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" maxDecompressedSize="67108864") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-notifyonconnectionclose.rst0000644000000000000000000000013115132733117027526 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.076482537 29 ctime=1787067792.50068976 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-notifyonconnectionclose.rst0000666000175000017500000000323615132733117027201 0ustar00rgerrger.. _param-imtcp-notifyonconnectionclose: .. _imtcp.parameter.module.notifyonconnectionclose: .. _imtcp.parameter.input.notifyonconnectionclose: NotifyOnConnectionClose ======================= .. index:: single: imtcp; NotifyOnConnectionClose single: NotifyOnConnectionClose .. summary-start Emits a message when a remote peer closes a connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: NotifyOnConnectionClose :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Instructs imtcp to emit a message if the remote peer closes a connection. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-notifyonconnectionclose: .. _imtcp.parameter.module.notifyonconnectionclose-usage: .. code-block:: rsyslog module(load="imtcp" notifyOnConnectionClose="on") Input usage ----------- .. _param-imtcp-input-notifyonconnectionclose: .. _imtcp.parameter.input.notifyonconnectionclose-usage: .. code-block:: rsyslog input(type="imtcp" port="514" notifyOnConnectionClose="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpservernotifyonconnectionclose: - $InputTCPServerNotifyOnConnectionClose — maps to NotifyOnConnectionClose (status: legacy) .. index:: single: imtcp; $InputTCPServerNotifyOnConnectionClose single: $InputTCPServerNotifyOnConnectionClose See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfwd-ratelimit-name.rst0000644000000000000000000000013215171370365025471 xustar0030 mtime=1776677109.119908115 30 atime=1787067672.688456662 30 ctime=1787067793.125701407 rsyslog-8.2608.0/doc/source/reference/parameters/omfwd-ratelimit-name.rst0000664000175000017500000000135615171370365025142 0ustar00rgerrger.. index:: ! omfwd; RateLimit.Name .. _param-omfwd-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. This allows multiple actions to share the same rate limiting configuration (and state). The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-action limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-followsymlinks.rst0000644000000000000000000000013215241075234026007 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.187702562 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-followsymlinks.rst0000664000175000017500000000331515241075234025455 0ustar00rgerrger.. _param-omfile-followsymlinks: .. _omfile.parameter.module.followsymlinks: followSymlinks ============== .. index:: single: omfile; followSymlinks single: followSymlinks .. summary-start Controls whether omfile follows a symbolic link in the final output path component. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: followSymlinks :Scope: module, action :Type: boolean :Default: depends on ``global(compatibility.defaults.secure=...)`` :Required?: no :Introduced: 8.2608.0 Description ----------- When set to ``on``, omfile keeps the historic behavior and follows a symbolic link if the final component of the configured output path is a symlink. When set to ``off``, omfile opens the final path component with ``O_NOFOLLOW`` where the platform supports it, so a symlinked output file is rejected instead of being followed. If the parameter is not configured explicitly, the default follows ``global(compatibility.defaults.secure=...)``: - ``strict``: do not follow the final output path component. - ``warn``: follow the symlink and emit a warning when the final output path component is a symlink. - ``backward-compatible``: follow the symlink without a warning. This setting only applies to the final path component. Symlinks in parent directories are not rejected by this parameter. Action usage ------------ .. _param-omfile-action-followsymlinks: .. _omfile.parameter.action.followsymlinks: .. code-block:: rsyslog action(type="omfile" file="/var/log/app.log" followSymlinks="off") Module usage ------------ .. code-block:: rsyslog module(load="builtin:omfile" followSymlinks="off") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-bulkmode.rst0000644000000000000000000000013215132411300026373 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.074445216 30 ctime=1787067793.034699711 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-bulkmode.rst0000666000175000017500000000163615132411300026047 0ustar00rgerrger.. _param-omelasticsearch-bulkmode: .. _omelasticsearch.parameter.module.bulkmode: bulkmode ======== .. index:: single: omelasticsearch; bulkmode single: bulkmode .. summary-start Use the Elasticsearch Bulk API to send batched events. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: bulkmode :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If enabled, events are buffered and sent in bulk requests. Without it, each event is sent individually. Action usage ------------ .. _param-omelasticsearch-action-bulkmode: .. _omelasticsearch.parameter.action.bulkmode: .. code-block:: rsyslog action(type="omelasticsearch" bulkmode="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-schedulingpriority.rst0000644000000000000000000000013115132733117026504 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.812477616 29 ctime=1787067792.59569153 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-schedulingpriority.rst0000666000175000017500000000222715132733117026156 0ustar00rgerrger.. _param-imudp-schedulingpriority: .. _imudp.parameter.module.schedulingpriority: SchedulingPriority ================== .. index:: single: imudp; SchedulingPriority single: SchedulingPriority .. summary-start Scheduler priority value when ``SchedulingPolicy`` is used. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: SchedulingPriority :Scope: module :Type: integer :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Scheduling priority to use. Module usage ------------ .. _param-imudp-module-schedulingpriority: .. _imudp.parameter.module.schedulingpriority-usage: .. code-block:: rsyslog module(load="imudp" SchedulingPriority="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imudp.parameter.legacy.imudpschedulingpriority: - $IMUDPSchedulingPriority — maps to SchedulingPriority (status: legacy) .. index:: single: imudp; $IMUDPSchedulingPriority single: $IMUDPSchedulingPriority See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-mysqlconfig-file.rst0000644000000000000000000000013115145046112026404 xustar0029 mtime=1771326538.94601277 30 atime=1787067673.062463634 30 ctime=1787067793.412706755 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-mysqlconfig-file.rst0000664000175000017500000000300215145046112026044 0ustar00rgerrger.. _param-ommysql-mysqlconfig-file: .. _ommysql.parameter.input.mysqlconfig-file: MySQLConfig.File ================ .. index:: single: ommysql; MySQLConfig.File single: MySQLConfig.File .. summary-start Selects an optional MariaDB/MySQL client configuration file (my.cnf) for the connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: mysqlconfig.file :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: at least 7.x, possibly earlier Description ----------- Permits the selection of an optional MariaDB/MySQL Client Library configuration file (my.cnf) for extended configuration functionality. The use of this configuration parameter is necessary only if you have a non-standard environment or if fine-grained control over the database connection is desired. Input usage ----------- .. _ommysql.parameter.input.mysqlconfig-file-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" mysqlConfig.file="/etc/mysql/my.cnf" db="syslog_db" uid="user" pwd="pwd") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommysql.parameter.legacy.ommysqlconfigfile: - $OmMySQLConfigFile — maps to MySQLConfig.File (status: legacy) .. index:: single: ommysql; $OmMySQLConfigFile single: $OmMySQLConfigFile See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-tls-cafile.rst0000644000000000000000000000013215145046112026300 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.521472191 30 ctime=1787067792.295685939 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-tls-cafile.rst0000664000175000017500000000162615145046112025751 0ustar00rgerrger.. _param-impstats-push-tls-cafile: .. _impstats.parameter.module.push-tls-cafile: push.tls.cafile =============== .. index:: single: impstats; push.tls.cafile single: push.tls.cafile .. summary-start Specifies the CA bundle used to verify the Remote Write TLS certificate. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.tls.cafile :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 8.2602.0 Description ----------- If set, the CA file is used to verify the server certificate when using an ``https://`` push URL. The file must be readable by the rsyslog process. Module usage ------------ .. _impstats.parameter.module.push-tls-cafile-usage: .. code-block:: rsyslog module(load="impstats" push.tls.cafile="/etc/ssl/certs/ca-bundle.crt") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-dynakey.rst0000644000000000000000000000013115132411300024477 xustar0030 mtime=1768559296.212884786 29 atime=1787067672.87446013 30 ctime=1787067793.333705283 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-dynakey.rst0000666000175000017500000000151315132411300024146 0ustar00rgerrger.. _param-omkafka-dynakey: .. _omkafka.parameter.module.dynakey: DynaKey ======= .. index:: single: omkafka; DynaKey single: DynaKey .. summary-start Treat `key` as a template for dynamic partition keys. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: DynaKey :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.1903 Description ----------- If set, the key parameter becomes a template for the key to base the partitioning on. Action usage ------------ .. _param-omkafka-action-dynakey: .. _omkafka.parameter.action.dynakey: .. code-block:: rsyslog action(type="omkafka" DynaKey="on" Key="keytemplate") Notes ----- - Originally documented as "binary"; uses boolean values. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-name.rst0000644000000000000000000000013215132733117023650 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.873478753 30 ctime=1787067792.411688101 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-name.rst0000666000175000017500000000135115132733117023316 0ustar00rgerrger.. _param-imrelp-name: .. _imrelp.parameter.input.name: name ==== .. index:: single: imrelp; name single: name .. summary-start Sets a human-readable name for the RELP listener instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: name :Scope: input :Type: string :Default: input=imrelp :Required?: no :Introduced: Not documented Description ----------- Assigns a name to the listener. If not specified, the default "imrelp" is used. Input usage ----------- .. _param-imrelp-input-name-usage: .. _imrelp.parameter.input.name-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" name="relpServer") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-supportoctetcountedframing.rst0000644000000000000000000000013215132733117030255 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.099482966 30 ctime=1787067792.552690729 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-supportoctetcountedframing.rst0000666000175000017500000000320115132733117027717 0ustar00rgerrger.. _param-imtcp-supportoctetcountedframing: .. _imtcp.parameter.input.supportoctetcountedframing: SupportOctetCountedFraming ========================== .. index:: single: imtcp; SupportOctetCountedFraming single: SupportOctetCountedFraming .. summary-start Enables legacy octet-counted framing compatibility. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: SupportOctetCountedFraming :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If set to ``on``, the legacy octet-counted framing (similar to RFC5425 framing) is activated. This should be left unchanged until you know very well what you do. It may be useful to turn it off if this framing is not used and some senders emit multi-line messages into the message stream. Input usage ----------- .. _param-imtcp-input-supportoctetcountedframing: .. _imtcp.parameter.input.supportoctetcountedframing-usage: .. code-block:: rsyslog input(type="imtcp" supportOctetCountedFraming="off") Notes ----- - Earlier documentation described the type as "binary"; this maps to boolean. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserversupportoctetcountedframing: - $InputTCPServerSupportOctetCountedFraming — maps to SupportOctetCountedFraming (status: legacy) .. index:: single: imtcp; $InputTCPServerSupportOctetCountedFraming single: $InputTCPServerSupportOctetCountedFraming See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-healthchecktimeout.rst0000644000000000000000000000012715132733117030003 xustar0029 mtime=1768666703.91562036 29 atime=1787067673.61047385 29 ctime=1787067792.98369876 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-healthchecktimeout.rst0000666000175000017500000000175315132733117027453 0ustar00rgerrger.. _param-omclickhouse-healthchecktimeout: .. _omclickhouse.parameter.input.healthchecktimeout: healthCheckTimeout ================== .. index:: single: omclickhouse; healthCheckTimeout single: healthCheckTimeout single: omclickhouse; healthchecktimeout single: healthchecktimeout .. summary-start Sets the timeout, in milliseconds, for verifying ClickHouse availability. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: healthCheckTimeout :Scope: input :Type: int (milliseconds) :Default: 3500 :Required?: no :Introduced: not specified Description ----------- This parameter sets the timeout for checking the availability of ClickHouse. Value is given in milliseconds. Input usage ----------- .. _omclickhouse.parameter.input.healthchecktimeout-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" healthCheckTimeout="5000") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-ruleset.rst0000644000000000000000000000013215132733117024526 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.989462274 30 ctime=1787067792.225684635 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-ruleset.rst0000666000175000017500000000230215132733117024171 0ustar00rgerrger.. _param-imkafka-ruleset: .. _imkafka.parameter.module.ruleset: .. _imkafka.parameter.input.ruleset: ruleset ======= .. index:: single: imkafka; ruleset single: ruleset .. summary-start Assigns the rsyslog ruleset that processes messages received via imkafka. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: ruleset :Scope: module, input :Type: string :Default: module=``none``; input=``none`` :Required?: no :Introduced: 8.27.0 Description ----------- Binds the input to a specific ruleset for processing. If not specified, messages are passed to the default ruleset. When set at the module level, the value becomes the default ruleset for inputs that do not override it. Module usage ------------ .. _imkafka.parameter.module.ruleset-usage: .. code-block:: rsyslog module(load="imkafka" ruleset="kafkaRules") # This input will use 'kafkaRules' ruleset input(type="imkafka" topic="my-topic") Input usage ----------- .. _imkafka.parameter.input.ruleset-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="static" ruleset="kafkaRules") See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-headerless-errorfile.rst0000644000000000000000000000013115132411300027155 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.347450305 29 ctime=1787067793.60671037 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-headerless-errorfile.rst0000666000175000017500000000213515132411300026625 0ustar00rgerrger.. _param-pmrfc3164-headerless-errorfile: .. _pmrfc3164.parameter.module.headerless-errorfile: .. _pmrfc3164.parameter.module.headerless.errorfile: headerless.errorfile ==================== .. index:: single: pmrfc3164; headerless.errorfile single: headerless.errorfile .. summary-start Append raw headerless input to a file before other processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: headerless.errorfile :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none :Required?: no :Introduced: 8.2508.0 Description ----------- If specified, raw headerless input is appended to this file before further processing. The file is created if it does not already exist. Module usage ------------ .. _param-pmrfc3164-module-headerless-errorfile: .. _pmrfc3164.parameter.module.headerless-errorfile-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" headerless.errorfile="/var/log/rsyslog-headerless.log") See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-pipelinename.rst0000644000000000000000000000013215132411300027237 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.028444358 30 ctime=1787067793.066700307 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-pipelinename.rst0000666000175000017500000000161315132411300026706 0ustar00rgerrger.. _param-omelasticsearch-pipelinename: .. _omelasticsearch.parameter.module.pipelinename: pipelineName ============ .. index:: single: omelasticsearch; pipelineName single: pipelineName .. summary-start Ingest pipeline to run before indexing. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: pipelineName :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Adds an ingest pipeline name to the request so events are pre-processed before indexing. By default no pipeline is used. Action usage ------------ .. _param-omelasticsearch-action-pipelinename: .. _omelasticsearch.parameter.action.pipelinename: .. code-block:: rsyslog action(type="omelasticsearch" pipelineName="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-keepalive-probes.rst0000644000000000000000000000013215145046112026167 xustar0030 mtime=1771326538.951012852 30 atime=1787067673.173465704 30 ctime=1787067793.483708078 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-keepalive-probes.rst0000664000175000017500000000201115145046112025625 0ustar00rgerrger.. _param-omrelp-keepalive-probes: .. _omrelp.parameter.input.keepalive-probes: KeepAlive.Probes ================ .. index:: single: omrelp; KeepAlive.Probes single: KeepAlive.Probes .. summary-start Sets how many keepalive probes are sent before a connection is deemed dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: KeepAlive.Probes :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The number of keepalive probes to send before considering the connection dead. The default, 0, uses the operating system defaults. This only has an effect if keep-alive is enabled and may not be available on all platforms. Input usage ----------- .. _param-omrelp-input-keepalive-probes: .. _omrelp.parameter.input.keepalive-probes-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" keepAliveProbes="5") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-bits.rst0000644000000000000000000000013215132733117024546 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.824440555 30 ctime=1787067792.707693617 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-bits.rst0000666000175000017500000000302115132733117024210 0ustar00rgerrger.. _param-mmanon-ipv4-bits: .. _mmanon.parameter.input.ipv4-bits: ipv4.bits ========= .. index:: single: mmanon; ipv4.bits single: ipv4.bits .. summary-start Sets how many low-order bits of IPv4 addresses are anonymized. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.bits :Scope: input :Type: positive integer :Default: input=16 :Required?: no :Introduced: 7.3.7 Description ----------- This sets the number of bits that should be anonymized (bits are from the right, so lower bits are anonymized first). This setting permits to save network information while still anonymizing user-specific data. The more bits you discard, the better the anonymization obviously is. The default of 16 bits reflects what German data privacy rules consider as being sufficiently anonymized. We assume, this can also be used as a rough but conservative guideline for other countries. Note: when in :ref:`simple mode `, only bits on a byte boundary can be specified. As such, any value other than 8, 16, 24 or 32 is invalid. If an invalid value is given, it is rounded to the next byte boundary (so we favor stronger anonymization in that case). For example, a bit value of 12 will become 16 in simple mode (an error message is also emitted). Input usage ----------- .. _mmanon.parameter.input.ipv4-bits-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="simple" ipv4.bits="24") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-dockerapiunixsockaddr.rst0000644000000000000000000000013215132411300027600 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.134446334 30 ctime=1787067791.971679902 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-dockerapiunixsockaddr.rst0000666000175000017500000000167715132411300027261 0ustar00rgerrger.. _param-imdocker-dockerapiunixsockaddr: .. _imdocker.parameter.module.dockerapiunixsockaddr: DockerApiUnixSockAddr ===================== .. index:: single: imdocker; DockerApiUnixSockAddr single: DockerApiUnixSockAddr .. summary-start Unix socket path for Docker API connections; default ``/var/run/docker.sock``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: DockerApiUnixSockAddr :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=/var/run/docker.sock :Required?: no :Introduced: 8.41.0 Description ----------- Specifies the Docker unix socket address to use. Module usage ------------ .. _param-imdocker-module-dockerapiunixsockaddr: .. _imdocker.parameter.module.dockerapiunixsockaddr-usage: .. code-block:: rsyslog module(load="imdocker" DockerApiUnixSockAddr="...") See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-listcontainersoptions.rst0000644000000000000000000000013215132411300027675 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.147446577 30 ctime=1787067791.978680032 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-listcontainersoptions.rst0000666000175000017500000000202515132411300027342 0ustar00rgerrger.. _param-imdocker-listcontainersoptions: .. _imdocker.parameter.module.listcontainersoptions: ListContainersOptions ===================== .. index:: single: imdocker; ListContainersOptions single: ListContainersOptions .. summary-start HTTP query options appended to ``List Containers`` requests; omit leading ``?``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: ListContainersOptions :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module= :Required?: no :Introduced: 8.41.0 Description ----------- Specifies the HTTP query component of a ``List Containers`` API request. See the Docker API for available options. It is not necessary to prepend ``?``. Module usage ------------ .. _param-imdocker-module-listcontainersoptions: .. _imdocker.parameter.module.listcontainersoptions-usage: .. code-block:: rsyslog module(load="imdocker" ListContainersOptions="...") See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdocker-defaultfacility.rst0000644000000000000000000000013215132411300026371 xustar0030 mtime=1768559296.193884485 30 atime=1787067672.158446782 30 ctime=1787067791.967679827 rsyslog-8.2608.0/doc/source/reference/parameters/imdocker-defaultfacility.rst0000666000175000017500000000210215132411300026032 0ustar00rgerrger.. _param-imdocker-defaultfacility: .. _imdocker.parameter.module.defaultfacility: DefaultFacility =============== .. index:: single: imdocker; DefaultFacility single: DefaultFacility .. summary-start Syslog facility assigned to received messages; default ``user``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdocker`. :Name: DefaultFacility :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=user :Required?: no :Introduced: 8.41.0 Description ----------- The syslog facility to be assigned to log messages. Textual names such as ``user`` are suggested, though numeric values are also accepted. Module usage ------------ .. _param-imdocker-module-defaultfacility: .. _imdocker.parameter.module.defaultfacility-usage: .. code-block:: rsyslog module(load="imdocker" DefaultFacility="...") Notes ----- - Numeric facility values are accepted but textual names are recommended. - See https://en.wikipedia.org/wiki/Syslog. See also -------- See also :doc:`../../configuration/modules/imdocker`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-sync.rst0000644000000000000000000000013215132733117023667 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.562454313 30 ctime=1787067793.201702823 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-sync.rst0000666000175000017500000000313115132733117023333 0ustar00rgerrger.. _param-omfile-sync: .. _omfile.parameter.module.sync: sync ==== .. index:: single: omfile; sync single: sync .. summary-start Enables file syncing capability of omfile. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: sync :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Enables file syncing capability of omfile. When enabled, rsyslog does a sync to the data file as well as the directory it resides after processing each batch. There currently is no way to sync only after each n-th batch. Enabling sync causes a severe performance hit. Actually, it slows omfile so much down, that the probability of losing messages **increases**. In short, you should enable syncing only if you know exactly what you do, and fully understand how the rest of the engine works, and have tuned the rest of the engine to lossless operations. Action usage ------------ .. _param-omfile-action-sync: .. _omfile.parameter.action.sync: .. code-block:: rsyslog action(type="omfile" sync="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.actionfileenablesync: - $ActionFileEnableSync — maps to sync (status: legacy) .. index:: single: omfile; $ActionFileEnableSync single: $ActionFileEnableSync See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-filegroup.rst0000644000000000000000000000013115132411300024671 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.344450249 29 ctime=1787067793.17470232 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-filegroup.rst0000666000175000017500000000302715132411300024342 0ustar00rgerrger.. _param-omfile-filegroup: .. _omfile.parameter.module.filegroup: fileGroup ========= .. index:: single: omfile; fileGroup single: fileGroup .. summary-start Set the group for files newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: fileGroup :Scope: module, action :Type: gid :Default: module=process user's primary group; action=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the group for files newly created. Please note that this setting does not affect the group of files already existing. The parameter is a group name, for which the groupid is obtained by rsyslogd during startup processing. Interim changes to the user mapping are not detected. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-filegroup: .. _omfile.parameter.module.filegroup-usage: .. code-block:: rsyslog module(load="builtin:omfile" fileGroup="...") Action usage ------------ .. _param-omfile-action-filegroup: .. _omfile.parameter.action.filegroup: .. code-block:: rsyslog action(type="omfile" fileGroup="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.filegroup: - $FileGroup — maps to fileGroup (status: legacy) .. index:: single: omfile; $FileGroup single: $FileGroup See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-keepalive-probes.rst0000644000000000000000000000013215132733117026165 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.958480338 30 ctime=1787067792.401687915 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-keepalive-probes.rst0000666000175000017500000000211415132733117025631 0ustar00rgerrger.. _param-imrelp-keepalive-probes: .. _imrelp.parameter.input.keepalive-probes: keepAlive.probes ================ .. index:: single: imrelp; keepAlive.probes single: keepAlive.probes .. summary-start Defines how many keep-alive retries occur before the connection is declared dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: keepAlive.probes :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: Not documented Description ----------- The number of keep-alive probes to send before considering the connection dead and notifying the application layer. The default, 0, means that the operating system defaults are used. This only has an effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imrelp-input-keepalive-probes-usage: .. _imrelp.parameter.input.keepalive-probes-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" keepAlive="on" keepAlive.probes="5") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-cacert.rst0000644000000000000000000000013215132733117024771 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.931479834 30 ctime=1787067792.426688381 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-cacert.rst0000666000175000017500000000163115132733117024440 0ustar00rgerrger.. _param-imrelp-tls-cacert: .. _imrelp.parameter.input.tls-cacert: tls.caCert ========== .. index:: single: imrelp; tls.caCert single: tls.caCert .. summary-start Specifies the CA certificate file used to validate client certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.caCert :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- The CA certificate that is being used to verify the client certificates. Has to be configured if :ref:`param-imrelp-tls-authmode` is set to ``name`` or ``certvalid``. Input usage ----------- .. _param-imrelp-input-tls-cacert-usage: .. _imrelp.parameter.input.tls-cacert-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.caCert="/etc/rsyslog/ca.pem") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-mycert.rst0000644000000000000000000000013215132733117025037 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.016444135 30 ctime=1787067792.035681095 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-mycert.rst0000666000175000017500000000155715132733117024515 0ustar00rgerrger.. _param-imdtls-tls-mycert: .. _imdtls.parameter.input.tls-mycert: tls.myCert ========== .. index:: single: imdtls; tls.myCert single: tls.myCert .. summary-start Identifies the certificate file the imdtls listener presents to peers. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.myCert :Scope: input :Type: string :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Specifies the certificate file used by imdtls. This certificate is presented to peers during the DTLS handshake. Input usage ----------- .. _imdtls.parameter.input.tls-mycert-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.myCert="/etc/rsyslog/server.pem" tls.myPrivKey="/etc/rsyslog/server.key") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-aborttimeout.rst0000644000000000000000000000013215132733117025410 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.943442774 30 ctime=1787067791.929679119 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-aborttimeout.rst0000666000175000017500000000342215132733117025057 0ustar00rgerrger.. _param-imdiag-aborttimeout: .. _imdiag.parameter.module.aborttimeout: AbortTimeout ============ .. index:: single: imdiag; AbortTimeout single: AbortTimeout .. summary-start Starts a watchdog thread that aborts rsyslog if it runs longer than the configured time limit. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: AbortTimeout :Scope: module :Type: integer (seconds) :Default: module=none (disabled) :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- When set, ``AbortTimeout`` installs a guard thread that tracks the runtime of the rsyslog instance. The timer starts as soon as this configuration parameter is loaded and applies for the entire process runtime. If rsyslog remains active for longer than the configured number of seconds after the guard starts, the thread writes a status message to ``stderr`` and terminates the daemon with ``abort()``. The guard is intended for automated test environments to detect deadlocks or hangs. The guard can only be configured once during the lifetime of the process. A second attempt to configure the watchdog is ignored and logs an error. Values less than or equal to zero are rejected. Module usage ------------ .. _param-imdiag-module-aborttimeout: .. _imdiag.parameter.module.aborttimeout-usage: .. code-block:: rsyslog module(load="imdiag" abortTimeout="600") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagaborttimeout: - $IMDiagAbortTimeout — maps to AbortTimeout (status: legacy) .. index:: single: imdiag; $IMDiagAbortTimeout single: $IMDiagAbortTimeout See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-headerless-tag.rst0000644000000000000000000000013215132411300025740 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.339450156 30 ctime=1787067793.613710501 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-headerless-tag.rst0000666000175000017500000000165015132411300025410 0ustar00rgerrger.. _param-pmrfc3164-headerless-tag: .. _pmrfc3164.parameter.module.headerless-tag: .. _pmrfc3164.parameter.module.headerless.tag: headerless.tag ============== .. index:: single: pmrfc3164; headerless.tag single: headerless.tag .. summary-start Set the tag used for headerless messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: headerless.tag :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=headerless :Required?: no :Introduced: 8.2508.0 Description ----------- Specifies the tag to assign to detected headerless messages. Module usage ------------ .. _param-pmrfc3164-module-headerless-tag: .. _pmrfc3164.parameter.module.headerless-tag-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" headerless.tag="missing") See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-closetimeout.rst0000644000000000000000000000013215132733117025457 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.750457818 30 ctime=1787067793.450707463 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-closetimeout.rst0000666000175000017500000000224515132733117025130 0ustar00rgerrger.. _param-omprog-closetimeout: .. _omprog.parameter.action.closetimeout: closeTimeout ============ .. index:: single: omprog; closeTimeout single: closeTimeout .. summary-start Waits the specified milliseconds for the program to exit after stdin closes. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: closeTimeout :Scope: action :Type: integer :Default: action=5000 :Required?: no :Introduced: 8.35.0 Description ----------- Specifies how long rsyslog must wait for the external program to terminate (when either the worker thread has been unscheduled, a restart of the program is being forced, or rsyslog is about to shutdown) after closing the pipe, that is, after sending EOF to the stdin of the child process. The value must be expressed in milliseconds and must be greater than or equal to zero. See the :ref:`param-omprog-killunresponsive` parameter for more details. Action usage ------------ .. _param-omprog-action-closetimeout: .. _omprog.parameter.action.closetimeout-usage: .. code-block:: rsyslog action(type="omprog" closeTimeout="10000") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-partitions-usefixed.rst0000644000000000000000000000013215132411300027042 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.113464585 30 ctime=1787067793.355705693 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-partitions-usefixed.rst0000666000175000017500000000163015132411300026510 0ustar00rgerrger.. _param-omkafka-partitions-usefixed: .. _omkafka.parameter.module.partitions-usefixed: Partitions.useFixed =================== .. index:: single: omkafka; Partitions.useFixed single: Partitions.useFixed .. summary-start Send all messages to a specific partition. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Partitions.useFixed :Scope: action :Type: integer :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If set, specifies the partition to which data is produced. All data goes to this partition; no other partition is used. Action usage ------------ .. _param-omkafka-action-partitions-usefixed: .. _omkafka.parameter.action.partitions-usefixed: .. code-block:: rsyslog action(type="omkafka" Partitions.useFixed="1") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-confparam.rst0000644000000000000000000000013215132411300025002 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.858459831 30 ctime=1787067793.331705245 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-confparam.rst0000666000175000017500000000166615132411300024461 0ustar00rgerrger.. _param-omkafka-confparam: .. _omkafka.parameter.module.confparam: ConfParam ========= .. index:: single: omkafka; ConfParam single: ConfParam .. summary-start Arbitrary librdkafka producer options `name=value`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: ConfParam :Scope: action :Type: array[string] :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Permits specifying Kafka options using ``name=value`` strings. Parameters are passed directly to librdkafka and support all its producer settings. Action usage ------------ .. _param-omkafka-action-confparam: .. _omkafka.parameter.action.confparam: .. code-block:: rsyslog action(type="omkafka" confParam=["compression.codec=snappy"]) Notes ----- - Multiple values may be set using array syntax. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-tokenreloadinterval.rst0000644000000000000000000000013115241075234030214 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 29 ctime=1787067792.86669658 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-tokenreloadinterval.rst0000664000175000017500000000355115241075234027665 0ustar00rgerrger.. _param-mmkubernetes-tokenreloadinterval: .. _mmkubernetes.parameter.action.tokenreloadinterval: tokenreloadinterval =================== .. index:: single: mmkubernetes; tokenreloadinterval single: tokenreloadinterval .. summary-start How often to proactively re-read the bearer token from ``tokenfile``. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: tokenreloadinterval :Scope: action :Type: integer :Default: 3600 :Required?: no :Introduced: 8.2608.0 Description ----------- How often, in seconds, to proactively re-read the bearer token from :ref:`param-mmkubernetes-tokenfile`. The default is ``3600`` (one hour). The token read from ``tokenfile`` is cached in the HTTP ``Authorization`` header when the worker starts. Kubernetes projected ServiceAccount tokens are short-lived and rotated on disk by the kubelet (well before they expire), so a long-running worker would otherwise keep sending the original token until it becomes invalid, at which point metadata lookups fail with HTTP 401 until the process is restarted. Re-reading the token periodically keeps the worker well inside the token validity window. Set this to ``0`` to disable the proactive reload. Regardless of this setting, mmkubernetes also reloads the token from ``tokenfile`` and retries the request once when a lookup returns HTTP 401, so a rotated token is picked up automatically without a restart. This value must be 0 or greater. This option has no effect when the inline :ref:`param-mmkubernetes-token` parameter is used instead of ``tokenfile``. Action usage ------------ .. _param-mmkubernetes-action-tokenreloadinterval: .. _mmkubernetes.parameter.action.tokenreloadinterval-usage: .. code-block:: rsyslog action(type="mmkubernetes" tokenReloadInterval="3600") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-debug.rst0000644000000000000000000000013215241075234025060 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.871696673 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-debug.rst0000664000175000017500000000250515241075234024526 0ustar00rgerrger.. _param-mmnormalize-debug: .. _mmnormalize.parameter.action.debug: .. meta:: :description: Enable per-action liblognorm debug tracing for mmnormalize. :keywords: rsyslog, mmnormalize, liblognorm, debug, tracing debug ===== .. index:: single: mmnormalize; debug single: debug .. summary-start Enables per-action liblognorm debug tracing to rsyslog diagnostics or a configured debug file. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: debug :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: 8.2608.0 Description ----------- Enables verbose liblognorm debug records for this action. Without :ref:`param-mmnormalize-debugfile`, rsyslog emits the records through its internal diagnostic stream. Use ``debugFile`` when trace records should be kept separately from rsyslog diagnostics. Action usage ------------ .. _param-mmnormalize-action-debug: .. _mmnormalize.parameter.action.debug-usage: .. code-block:: rsyslog action(type="mmnormalize" rulebase="/path/to/rules.rb" debug="on") YAML usage ---------- .. code-block:: yaml actions: - type: mmnormalize rulebase: /path/to/rules.rb debug: on See also -------- See also :doc:`../../configuration/modules/mmnormalize` and :ref:`param-mmnormalize-debugfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-topic.rst0000644000000000000000000000013215132411300024152 xustar0030 mtime=1768559296.213884802 30 atime=1787067673.269467493 30 ctime=1787067793.366705898 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-topic.rst0000666000175000017500000000125515132411300023623 0ustar00rgerrger.. _param-omkafka-topic: .. _omkafka.parameter.module.topic: Topic ===== .. index:: single: omkafka; Topic single: Topic .. summary-start Kafka topic to produce to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Topic :Scope: action :Type: string :Default: action=none :Required?: yes :Introduced: at least 8.x, possibly earlier Description ----------- Specifies the topic to produce to. Action usage ------------ .. _param-omkafka-action-topic: .. _omkafka.parameter.action.topic: .. code-block:: rsyslog action(type="omkafka" Topic="mytopic") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-containerrules.rst0000644000000000000000000000013215132733117027176 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.650455954 30 ctime=1787067792.831695928 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-containerrules.rst0000666000175000017500000000307715132733117026653 0ustar00rgerrger.. _param-mmkubernetes-containerrules: .. _mmkubernetes.parameter.action.containerrules: containerrules ============== .. index:: single: mmkubernetes; containerrules single: containerrules .. summary-start Defines lognorm rules to parse ``CONTAINER_NAME`` values for metadata. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: containerrules :Scope: action :Type: word :Default: SEE BELOW :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- .. note:: This directive is not supported with liblognorm 2.0.2 and earlier. For journald logs, there must be a message property `CONTAINER_NAME` which has a value matching these rules specified by this parameter. The default value is:: rule=:%k8s_prefix:char-to:_%_%container_name:char-to:.%.%container_hash:char-to:\ _%_%pod_name:char-to:_%_%namespace_name:char-to:_%_%not_used_1:char-to:_%_%not_u\ sed_2:rest% rule=:%k8s_prefix:char-to:_%_%container_name:char-to:_%_%pod_name:char-to:_%_%na\ mespace_name:char-to:_%_%not_used_1:char-to:_%_%not_used_2:rest% .. note:: In the above rules, the slashes ``\`` ending each line indicate line wrapping - they are not part of the rule. There are two rules because the `container_hash` is optional. Action usage ------------ .. _param-mmkubernetes-action-containerrules: .. _mmkubernetes.parameter.action.containerrules-usage: .. code-block:: rsyslog action(type="mmkubernetes" containerRules="...") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-headerless-drop.rst0000644000000000000000000000013215132411300026131 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.350450361 30 ctime=1787067793.604710333 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-headerless-drop.rst0000666000175000017500000000205215132411300025576 0ustar00rgerrger.. _param-pmrfc3164-headerless-drop: .. _pmrfc3164.parameter.module.headerless-drop: .. _pmrfc3164.parameter.module.headerless.drop: headerless.drop =============== .. index:: single: pmrfc3164; headerless.drop single: headerless.drop .. summary-start Discard headerless messages after optional logging. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: headerless.drop :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2508.0 Description ----------- When enabled, headerless messages are discarded after optional logging to ``headerless.errorfile`` and are not processed by later rules. Module usage ------------ .. _param-pmrfc3164-module-headerless-drop: .. _pmrfc3164.parameter.module.headerless-drop-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" headerless.drop="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/immark-use-syslogcall.rst0000644000000000000000000000013215132733117025666 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.316468369 30 ctime=1787067792.260685287 rsyslog-8.2608.0/doc/source/reference/parameters/immark-use-syslogcall.rst0000666000175000017500000000251415132733117025336 0ustar00rgerrger.. _param-immark-use-syslogcall: .. _immark.parameter.module.use-syslogcall: use.syslogCall =============== .. index:: single: immark; use.syslogCall single: use.syslogCall .. summary-start Chooses whether immark logs via syslog(3) or its internal pipeline. .. summary-end This parameter applies to :doc:`../../configuration/modules/immark`. :Name: use.syslogCall :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.2012.0 Description ----------- Controls how immark emits its periodic mark messages: * ``on`` (default) — immark calls the system ``syslog(3)`` interface. Messages bypass rsyslog's internal queueing and are handled like any other syslog API submission. * ``off`` — immark constructs the message internally and submits it to rsyslog's main queue. This enables features such as binding a custom :ref:`param-immark-ruleset` or applying mark-specific templates. If a ruleset is configured while ``use.syslogCall`` remains ``on``, immark issues a warning and forces this parameter to ``off`` so the ruleset can take effect. Module usage ------------ .. _immark.parameter.module.use-syslogcall-usage: .. code-block:: rsyslog module(load="immark" use.syslogCall="off") See also -------- .. seealso:: * :ref:`param-immark-ruleset` * :doc:`../../configuration/modules/immark` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpretrycodes.rst0000644000000000000000000000013015241075234026034 xustar0030 mtime=1787067036.581577845 29 atime=1787067036.72658056 29 ctime=1787067793.26970409 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpretrycodes.rst0000664000175000017500000000230015241075234025475 0ustar00rgerrger.. _param-omhttp-httpretrycodes: .. _omhttp.parameter.input.httpretrycodes: httpretrycodes ============== .. index:: single: omhttp; httpretrycodes single: httpretrycodes .. summary-start Lists HTTP status codes that omhttp treats as retriable errors. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpretrycodes :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: Not specified Description ----------- An array of strings that defines one or more HTTP status codes that are retriable by the omhttp plugin in addition to its built-in retry behavior. By default, transport failures, HTTP 429, and HTTP 5xx responses are retried; ordinary HTTP 3xx and 4xx responses are treated as permanent data failures. Use this parameter when a deployment wants a specific response, such as a temporary HTTP 403 from an authorization workflow, to follow the retry path. Input usage ----------- .. _omhttp.parameter.input.httpretrycodes-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpRetryCodes=["500", "502", "503"] ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-anonmode.rst0000644000000000000000000000013215145046112027053 xustar0030 mtime=1771326538.941012688 30 atime=1787067671.901441991 30 ctime=1787067792.693693356 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-anonmode.rst0000664000175000017500000000364315145046112026525 0ustar00rgerrger.. _param-mmanon-embeddedipv4-anonmode: .. _mmanon.parameter.input.embeddedipv4-anonmode: embeddedIpv4.anonMode ===================== .. index:: single: mmanon; embeddedIpv4.anonMode single: embeddedIpv4.anonMode .. summary-start Defines how IPv6 addresses with embedded IPv4 parts are anonymized. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.anonMode :Scope: input :Type: string :Default: input=zero :Required?: no :Introduced: 7.3.7 Description ----------- The available modes are ``random``, ``random-consistent``, ``random-consistent-unique``, and ``zero``. The modes ``random`` and ``random-consistent`` are very similar, in that they both anonymize IP addresses by randomizing the last bits (any number) of a given address. However, while ``random`` mode assigns a new random IP address for every address in a message, ``random-consistent`` will assign the same randomized address to every instance of the same original address. ``random-consistent-unique`` builds on that behavior and guarantees that no two distinct original addresses share the same anonymized result. It may take longer to generate addresses because a replacement is retried until an unused randomized value is found; this effect grows as more unique IPs are processed. The default ``zero`` mode will do full anonymization of any number of bits and it will also normalize the address, so that no information about the original IP address is available. Also note that an anonymized IPv6 address will be normalized, meaning there will be no abbreviations, leading zeros will **not** be displayed, and capital letters in the hex numerals will be lowercase. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-anonmode-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.anonMode="random") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-usepid.rst0000644000000000000000000000013215132411300024714 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.886460353 30 ctime=1787067792.209684337 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-usepid.rst0000666000175000017500000000217715132411300024371 0ustar00rgerrger.. _param-imjournal-usepid: .. _imjournal.parameter.module.usepid: .. meta:: :tag: module:imjournal :tag: parameter:UsePid UsePid ====== .. index:: single: imjournal; UsePid single: UsePid .. summary-start Selects which journal PID field to use: ``syslog``, ``system``, or ``both``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: UsePid :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=both :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Determines the journal field that supplies the process identifier. ``syslog`` Use ``SYSLOG_PID``. ``system`` Use ``_PID``. ``both`` Try ``SYSLOG_PID`` first and fall back to ``_PID``. If neither is available, the message is parsed without a PID. Module usage ------------ .. _param-imjournal-module-usepid: .. _imjournal.parameter.module.usepid-usage: .. code-block:: rsyslog module(load="imjournal" UsePid="...") Notes ----- - Case-insensitive values are accepted. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-starvationprotection-maxreads.rst0000644000000000000000000000013215132733117030657 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.094482873 30 ctime=1787067792.523690188 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-starvationprotection-maxreads.rst0000666000175000017500000000507115132733117030330 0ustar00rgerrger.. _param-imtcp-starvationprotection-maxreads: .. _imtcp.parameter.module.starvationprotection-maxreads: StarvationProtection.MaxReads ============================= .. index:: single: imtcp; StarvationProtection.MaxReads single: StarvationProtection.MaxReads .. summary-start Limits consecutive reads per connection before switching to another session. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StarvationProtection.MaxReads :Scope: module :Type: integer :Default: module=500 :Required?: no :Introduced: 8.2504.0 Description ----------- The ``StarvationProtection.MaxReads`` parameter defines the **maximum number of consecutive requests** a worker can process for a single connection before switching to another session. This mechanism prevents any single sender from **monopolizing imtcp's processing capacity**. **Default value:** ``500`` **Allowed values:** - ``0`` → Disables starvation protection (a single sender may dominate worker time). - Any positive integer → Specifies the maximum number of consecutive reads before switching. **Behavior and Use Cases** - When a connection continuously sends data, a worker will process it **up to MaxReads times** before returning it to the processing queue. - This ensures that **other active connections** get a chance to be processed. - Particularly useful in **high-volume environments** where a few senders might otherwise consume all resources. - In **single-threaded mode**, this still provides fairness but cannot fully prevent resource exhaustion. **Scope and Overrides** - This is a **module-level parameter**, meaning it **sets the default** for all ``imtcp`` listeners. - Each listener instance can override this by setting the ``starvationProtection.maxReads`` **listener parameter**. **Example Configuration** The following sets a **default of 300** reads per session before switching to another connection, while overriding it to **1000** for a specific listener: .. code-block:: none module(load="imtcp" StarvationProtection.MaxReads="300") # Default for all listeners input(type="imtcp" port="514" starvationProtection.MaxReads="1000") # Overrides default If ``StarvationProtection.MaxReads`` is not explicitly set, the default of ``500`` will be used. Module usage ------------ .. _param-imtcp-module-starvationprotection-maxreads: .. _imtcp.parameter.module.starvationprotection-maxreads-usage: .. code-block:: rsyslog module(load="imtcp" starvationProtection.maxReads="300") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-esversion-major.rst0000644000000000000000000000013215132733117027731 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.991443668 30 ctime=1787067793.052700046 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-esversion-major.rst0000666000175000017500000000313715132733117027403 0ustar00rgerrger.. _param-omelasticsearch-esversion-major: .. _omelasticsearch.parameter.module.esversion-major: .. _omelasticsearch.parameter.module.esVersion.major: esVersion.major =============== .. index:: single: omelasticsearch; esVersion.major single: esVersion.major .. summary-start Deprecated manual override for the detected Elasticsearch/OpenSearch major version. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: esVersion.major :Scope: action :Type: integer :Default: action=0 (overridden when detection succeeds) :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- .. warning:: This parameter is deprecated as of rsyslog 8.2510.0. The module performs a best-effort probe at startup to discover the target platform (Elasticsearch or OpenSearch) and its version, and ``esVersion.major`` is automatically updated with the detected major version when the probe succeeds. .. versionchanged:: 8.2510.0 Automatically overridden when startup platform detection succeeds. This setting is only consulted when detection fails or when no servers are reachable during startup. Administrators may keep it configured as a fallback for air-gapped or permission-restricted environments, but future releases may remove the option entirely. Action usage ------------ .. _param-omelasticsearch-action-esversion-major: .. _omelasticsearch.parameter.action.esversion-major: .. code-block:: rsyslog action(type="omelasticsearch" esVersion.major="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-dynpipelinename.rst0000644000000000000000000000013215132411300027752 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.035444489 30 ctime=1787067793.040699823 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-dynpipelinename.rst0000666000175000017500000000172015132411300027420 0ustar00rgerrger.. _param-omelasticsearch-dynpipelinename: .. _omelasticsearch.parameter.module.dynpipelinename: dynPipelineName =============== .. index:: single: omelasticsearch; dynPipelineName single: dynPipelineName .. summary-start Treat `pipelineName` as a template name. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: dynPipelineName :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If enabled, the value of `pipelineName` is taken as a template whose result selects the pipeline. Action usage ------------ .. _param-omelasticsearch-action-dynpipelinename: .. _omelasticsearch.parameter.action.dynpipelinename: .. code-block:: rsyslog action(type="omelasticsearch" dynPipelineName="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-db.rst0000644000000000000000000000013215145046112023503 xustar0030 mtime=1771326538.948012803 30 atime=1787067673.353469059 30 ctime=1787067793.432707128 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-db.rst0000664000175000017500000000140515145046112023147 0ustar00rgerrger.. _param-ompgsql-db: .. _ompgsql.parameter.input.db: db == .. index:: single: ompgsql; db single: db .. summary-start Names the PostgreSQL database into which rows are inserted when not specified in a connection string. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: db :Scope: input :Type: word :Default: none :Required?: no :Introduced: 8.32.0 Description ----------- The multi-tenant database name to ``INSERT`` rows into. Required if ``conninfo`` is not specified. Input usage ----------- .. _ompgsql.parameter.input.db-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" db="syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-restpathtimeout.rst0000644000000000000000000000013115132733117026213 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.098464305 30 ctime=1787067793.289704463 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-restpathtimeout.rst0000666000175000017500000000150415132733117025662 0ustar00rgerrger.. _param-omhttp-restpathtimeout: .. _omhttp.parameter.input.restpathtimeout: restpathtimeout =============== .. index:: single: omhttp; restpathtimeout single: restpathtimeout .. summary-start Specifies how long omhttp waits for a dynamic REST path template to resolve. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: restpathtimeout :Scope: input :Type: integer :Default: input=none :Required?: no :Introduced: Not specified Description ----------- Timeout value for the configured :ref:`param-omhttp-restpath`. Input usage ----------- .. _omhttp.parameter.input.restpathtimeout-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" restPathTimeout="2000" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-tlsrevocationcheck.rs0000644000000000000000000000013215216464435030776 xustar0030 mtime=1782212893.985265521 30 atime=1787067674.054482127 30 ctime=1787067792.550690691 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-tlsrevocationcheck.rst0000664000175000017500000001260215216464435030627 0ustar00rgerrger.. _param-imtcp-streamdriver-tlsrevocationcheck: .. _imtcp.parameter.module.streamdriver-tlsrevocationcheck: .. _imtcp.parameter.input.streamdriver-tlsrevocationcheck: StreamDriver.TlsRevocationCheck ================================ .. index:: single: imtcp; StreamDriver.TlsRevocationCheck single: StreamDriver.TlsRevocationCheck .. summary-start Controls whether TLS certificate revocation checking via OCSP is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.TlsRevocationCheck :Scope: module, input :Type: binary :Default: module=off, input=module parameter :Required?: no :Introduced: 8.2602.0 .. warning:: **EXPERIMENTAL FEATURE** This feature is experimental and new in 8.2602.0. It is intended to be production-ready, but it has limited real-world practice and may expose operational edge cases. Review the details below and test in your environment before enabling it broadly. * **Bounded I/O**: OCSP uses non-blocking connect with socket timeouts for send/receive, but each responder can still add latency (up to ``OCSP_TIMEOUT`` seconds). * **DoS Attack Vector**: Malicious certificates can contain multiple OCSP responder URLs pointing to slow or unresponsive servers, causing cumulative latency and potential denial of service. * **Thread Blocking**: Timeouts limit the duration, but under load, slow responders can still reduce throughput. * **Cache behavior**: OCSP responses are cached with expiry based on ``nextUpdate`` when available (or a default TTL). This reduces repeated network I/O but still depends on network availability for cache misses. Description ----------- Controls whether TLS certificate revocation checking is performed during the TLS handshake. When enabled, rsyslog will query OCSP (Online Certificate Status Protocol) responders to verify that certificates have not been revoked. The revocation check is performed by the ``ossl`` network stream driver (``StreamDriver.Name="ossl"``) when rsyslog is compiled against OpenSSL or wolfSSL. The feature is not available when using the GnuTLS driver. OCSP stapling is not used on either backend. rsyslog always queries the OCSP responder URL embedded in the certificate's Authority Information Access extension, regardless of whether the peer offered a stapled response. This applies to both the OpenSSL and wolfSSL builds. **wolfSSL notes:** * wolfSSL must be built with ``--enable-crl`` and ``--enable-ocsp``. * OCSP responder I/O is performed by wolfSSL's built-in HTTP client; the bounded-I/O, cache and DoS notes above describe the OpenSSL path — wolfSSL keeps its own internal OCSP response cache inside the ``WOLFSSL_CERT_MANAGER`` that is not visible to rsyslog. **Important considerations:** * **Disabled by default**: Certificate revocation checking is disabled by default for backward compatibility and to avoid potential performance impacts. * **Bounded I/O**: OCSP checks use non-blocking connect and socket timeouts during the TLS handshake. Each responder can still add latency (up to ``OCSP_TIMEOUT`` seconds) which may impact throughput and cause connection delays. * **Network requirements**: OCSP checks require outbound network connectivity to OCSP responder servers specified in the certificate's Authority Information Access extension. * **Certificate requirements**: Certificates must contain OCSP responder URLs. Certificates with only CRL (Certificate Revocation List) distribution points are not supported and will fail revocation checks. * **Caching**: OCSP responses are cached with an expiry based on the response ``nextUpdate`` value when available, or a default TTL. This reduces repeat lookups but does not eliminate network dependency for cache misses. When enabled (``"on"``), the TLS handshake will fail if: - The certificate is revoked - The OCSP responder is unreachable - The OCSP response is invalid - The certificate contains no OCSP responder information but has CRL information The same-named input parameter can override the module setting. **Security note**: OCSP checking provides additional security by verifying that certificates have not been revoked, but introduces operational complexity and potential availability risks due to external dependencies. Module usage ------------ .. _param-imtcp-module-streamdriver-tlsrevocationcheck: .. _imtcp.parameter.module.streamdriver-tlsrevocationcheck-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.name="ossl" streamDriver.mode="1" streamDriver.authMode="x509/certvalid" streamDriver.tlsRevocationCheck="on") Input usage ----------- .. _param-imtcp-input-streamdriver-tlsrevocationcheck: .. _imtcp.parameter.input.streamdriver-tlsrevocationcheck-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.name="ossl" streamDriver.mode="1" streamDriver.authMode="x509/certvalid" streamDriver.tlsRevocationCheck="on") Example: Disabled (default) ---------------------------- .. code-block:: rsyslog # Explicitly disable revocation checking (same as default) module(load="imtcp" streamDriver.name="ossl" streamDriver.mode="1" streamDriver.authMode="x509/certvalid" streamDriver.tlsRevocationCheck="off") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ignoreownmessages.rst0000644000000000000000000000013215132733117030535 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.259485949 30 ctime=1787067792.637692313 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ignoreownmessages.rst0000666000175000017500000000226415132733117030207 0ustar00rgerrger.. _param-imuxsock-syssock-ignoreownmessages: .. _imuxsock.parameter.module.syssock-ignoreownmessages: SysSock.IgnoreOwnMessages ========================= .. index:: single: imuxsock; SysSock.IgnoreOwnMessages single: SysSock.IgnoreOwnMessages .. summary-start Ignores messages that originate from the same rsyslogd instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.IgnoreOwnMessages :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 7.3.7 Description ----------- Ignores messages that originated from the same instance of rsyslogd. There usually is no reason to receive messages from ourselves. This setting is vital when writing messages to the systemd journal. .. seealso:: See :doc:`omjournal <../../configuration/modules/omjournal>` module documentation for a more in-depth description. Module usage ------------ .. _param-imuxsock-module-syssock-ignoreownmessages: .. _imuxsock.parameter.module.syssock-ignoreownmessages-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.ignoreOwnMessages="off") See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-allowedsender.rst0000644000000000000000000000013215241075234025406 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.559690859 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-allowedsender.rst0000664000175000017500000000464615241075234025064 0ustar00rgerrger.. _param-imudp-allowedsender: .. _imudp.parameter.module.allowedsender: .. _imudp.parameter.input.allowedsender: AllowedSender ============= .. index:: single: imudp; AllowedSender single: AllowedSender .. summary-start Restricts UDP syslog senders by source address or hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: AllowedSender :Scope: module, input :Type: array :Default: module=none, input=module parameter :Required?: no :Introduced: 8.2608.0 Description ----------- Sets source-address ACL entries for UDP syslog inputs. Entries use the same address syntax as the legacy :doc:`../../configuration/input_directives/rsconf1_allowedsender` directive, for example ``127.0.0.1/16``, ``192.0.2.0/24``, ``[::1]/128``, ``*.example.net``, or ``somehost.example.com``. A module-level ``AllowedSender`` list is used as the default for imudp inputs. An input-level ``AllowedSender`` list replaces the module-level list for that input. If neither the module nor the input configures this parameter, all senders are accepted unless legacy ``$AllowedSender`` directives are present. If ``AllowedSender`` is configured, the array must contain at least one entry. An empty input array cannot be used to clear a module-level default. Configure explicit per-input sender lists, or omit the module-level default if some inputs must remain unrestricted. Do not mix legacy ``$AllowedSender`` and modern ``AllowedSender`` in new configurations. ``AllowedSender`` checks the remote socket address or reverse-DNS hostname. By UDP design, source addresses can be spoofed. Use firewall ingress and egress filtering, and prefer TCP or TLS transports when sender authenticity matters. Module usage ------------ .. _param-imudp-module-allowedsender: .. _imudp.parameter.module.allowedsender-usage: .. code-block:: rsyslog module(load="imudp" allowedSender=["192.0.2.0/24"]) Input usage ----------- .. _param-imudp-input-allowedsender: .. _imudp.parameter.input.allowedsender-usage: .. code-block:: rsyslog input(type="imudp" port="514" allowedSender=["127.0.0.1/16"]) YAML usage ---------- .. code-block:: yaml modules: - load: imudp allowedSender: ["192.0.2.0/24"] inputs: - type: imudp port: "514" allowedSender: ["127.0.0.1/16"] See also -------- See also :doc:`../../configuration/modules/imudp` and :doc:`../../configuration/input_directives/rsconf1_allowedsender`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-failonchownfailure.rst0000644000000000000000000000013215132411300026555 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.548454052 30 ctime=1787067793.168702208 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-failonchownfailure.rst0000666000175000017500000000323015132411300026221 0ustar00rgerrger.. _param-omfile-failonchownfailure: .. _omfile.parameter.module.failonchownfailure: failOnChOwnFailure ================== .. index:: single: omfile; failOnChOwnFailure single: failOnChOwnFailure .. summary-start This option modifies behaviour of file creation. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: failOnChOwnFailure :Scope: action :Type: boolean :Default: action=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This option modifies behaviour of file creation. If different owners or groups are specified for new files or directories and rsyslogd fails to set these new owners or groups, it will log an error and NOT write to the file in question if that option is set to "on". If it is set to "off", the error will be ignored and processing continues. Keep in mind, that the files in this case may be (in)accessible by people who should not have permission. The default is "on". Action usage ------------ .. _param-omfile-action-failonchownfailure: .. _omfile.parameter.action.failonchownfailure: .. code-block:: rsyslog action(type="omfile" failOnChOwnFailure="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.failonchownfailure: - $FailOnCHOwnFailure — maps to failOnChOwnFailure (status: legacy) .. index:: single: omfile; $FailOnCHOwnFailure single: $FailOnCHOwnFailure See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-target.rst0000644000000000000000000000013215132733117024230 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.783439791 30 ctime=1787067793.010699264 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-target.rst0000666000175000017500000000145615132733117023704 0ustar00rgerrger.. _param-omdtls-target: .. _omdtls.parameter.input.target: target ====== .. index:: single: omdtls; target single: target .. summary-start Specifies the destination host name or IP address for omdtls. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: target :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: v8.2402.0 Description ----------- Specifies the target hostname or IP address to send log messages to. This parameter must be set; otherwise the action has no destination and messages cannot be delivered. Input usage ----------- .. _omdtls.parameter.input.target-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpignorablecodes.rst0000644000000000000000000000013115241075234026632 xustar0030 mtime=1787067036.581577845 29 atime=1787067036.72658056 30 ctime=1787067793.266704034 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpignorablecodes.rst0000664000175000017500000000245215241075234026302 0ustar00rgerrger.. _param-omhttp-httpignorablecodes: .. _omhttp.parameter.input.httpignorablecodes: httpignorablecodes ================== .. index:: single: omhttp; httpignorablecodes single: httpignorablecodes .. summary-start Lists HTTP status codes that omhttp never retries. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpignorablecodes :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: Not specified Description ----------- An array of strings that defines one or more HTTP status codes that omhttp treats as successfully handled after the HTTP response is received. Use this only when dropping the affected message is acceptable for the target system. For example, a Splunk HEC deployment may choose to ignore a known permanent HTTP 400 response after capturing the failed request in :ref:`param-omhttp-errorfile`. Codes listed here override the normal failure result. They do not make the remote service accept the data, and they do not replay the message later. Input usage ----------- .. _omhttp.parameter.input.httpignorablecodes-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpIgnorableCodes=["400", "404"] ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-azurehost.rst0000644000000000000000000000013215216464435027101 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.403469991 30 ctime=1787067792.927697717 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-azurehost.rst0000664000175000017500000000220315216464435026542 0ustar00rgerrger.. _param-omazureeventhubs-azurehost: .. _omazureeventhubs.parameter.input.azurehost: azurehost ========= .. index:: single: omazureeventhubs; azurehost single: azurehost .. summary-start Sets the fully qualified Event Hubs namespace host the action connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: azurehost :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- Specifies the fully qualified domain name (FQDN) of the Event Hubs instance that the rsyslog output plugin should connect to. The format of the hostname should be ``.servicebus.windows.net``, where ```` is the name of the Event Hubs namespace that was created in Microsoft Azure. This setting is required unless ``amqp_address`` supplies the complete connection string. Input usage ----------- .. _omazureeventhubs.parameter.input.azurehost-usage: .. code-block:: rsyslog action(type="omazureeventhubs" azureHost="example.servicebus.windows.net" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-rule.rst0000644000000000000000000000013215132733117024741 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.853459738 30 ctime=1787067792.878696804 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-rule.rst0000666000175000017500000000164215132733117024412 0ustar00rgerrger.. _param-mmnormalize-rule: .. _mmnormalize.parameter.action.rule: rule ==== .. index:: single: mmnormalize; rule single: rule .. summary-start Builds the rulebase from an array of strings. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: rule :Scope: action :Type: array :Default: none :Required?: yes :Introduced: 8.26.0 Description ----------- .. versionadded:: 8.26.0 Contains an array of strings which will be put together as the rulebase. This parameter or :ref:`param-mmnormalize-rulebase` MUST be given, because normalization can only happen based on a rulebase. Action usage ------------- .. _param-mmnormalize-action-rule: .. _mmnormalize.parameter.action.rule-usage: .. code-block:: rsyslog action(type="mmnormalize" rule=["rule=:%host:word% %ip:ipv4% user was logged out"]) See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-amqp_address.rst0000644000000000000000000000013215216464435027520 xustar0030 mtime=1782212893.987265553 30 atime=1787067673.276467624 30 ctime=1787067792.920697586 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-amqp_address.rst0000664000175000017500000000252115216464435027164 0ustar00rgerrger.. _param-omazureeventhubs-amqp_address: .. _omazureeventhubs.parameter.input.amqp_address: amqp_address ============ .. index:: single: omazureeventhubs; amqp_address single: amqp_address .. summary-start Provides a full AMQPS connection string that overrides individual Azure settings. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: amqp_address :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2304 Description ----------- Specifies the "Event Hubs connection string", a full AMQPS URL used to connect to the target Event Hubs instance. When this parameter is set, the host, key name, and key are parsed from the URL, overriding ``azureHost``, ``azure_key_name``, and ``azure_key``. The port is not parsed from the URL; it always defaults to ``5671`` and any configured ``azurePort`` value is ignored. A sample Event Hubs connection string URL is: .. code-block:: none amqps://:@.servicebus.windows.net/ Input usage ----------- .. _omazureeventhubs.parameter.input.amqp_address-usage: .. code-block:: rsyslog action(type="omazureeventhubs" amqp_address="amqps://user:key@namespace.servicebus.windows.net/hub" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-defaultfacility.rst0000644000000000000000000000013115132411300026573 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.870460055 29 ctime=1787067792.17068361 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-defaultfacility.rst0000666000175000017500000000242315132411300026243 0ustar00rgerrger.. _param-imjournal-defaultfacility: .. _imjournal.parameter.module.defaultfacility: .. meta:: :tag: module:imjournal :tag: parameter:DefaultFacility DefaultFacility =============== .. index:: single: imjournal; DefaultFacility single: DefaultFacility .. summary-start Fallback facility used if a journal entry lacks ``SYSLOG_FACILITY``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: DefaultFacility :Scope: module :Type: word :Default: module=LOG_USER :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the facility assigned to messages missing the ``SYSLOG_FACILITY`` field. Values may be given as facility names or numbers. Module usage ------------ .. _param-imjournal-module-defaultfacility: .. _imjournal.parameter.module.defaultfacility-usage: .. code-block:: rsyslog module(load="imjournal" DefaultFacility="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournaldefaultfacility: - $ImjournalDefaultFacility — maps to DefaultFacility (status: legacy) .. index:: single: imjournal; $ImjournalDefaultFacility single: $ImjournalDefaultFacility See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-server.rst0000644000000000000000000000013215145046112024443 xustar0030 mtime=1771326538.947012786 30 atime=1787067673.134464977 30 ctime=1787067793.419706885 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-server.rst0000664000175000017500000000143715145046112024114 0ustar00rgerrger.. _param-ommysql-server: .. _ommysql.parameter.input.server: Server ====== .. index:: single: ommysql; Server single: Server .. summary-start Sets the MariaDB/MySQL server address the action connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: server :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: at least 7.x, possibly earlier Description ----------- This is the hostname or IP address of the MariaDB/MySQL server. Input usage ----------- .. _ommysql.parameter.input.server-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" db="syslog_db" uid="user" pwd="pwd") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-batch-maxbytes.rst0000644000000000000000000000013115132733117025665 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.160465461 30 ctime=1787067793.233703419 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-batch-maxbytes.rst0000666000175000017500000000166015132733117025337 0ustar00rgerrger.. _param-omhttp-batch-maxbytes: .. _omhttp.parameter.input.batch-maxbytes: batch.maxbytes ============== .. index:: single: omhttp; batch.maxbytes single: batch.maxbytes .. summary-start Limits the serialized size of each batched HTTP payload. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: batch.maxbytes :Scope: input :Type: Size :Default: input=10485760 (10MB) :Required?: no :Introduced: Not specified Description ----------- ``batch.maxbytes`` and ``maxbytes`` do the same thing, ``maxbytes`` is included for backwards compatibility. This parameter specifies the maximum size in bytes for each batch. Input usage ----------- .. _omhttp.parameter.input.batch-maxbytes-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" batch="on" batchMaxBytes="5m" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-topicconfparam.rst0000644000000000000000000000013215132411300026041 xustar0030 mtime=1768559296.213884802 30 atime=1787067673.297468015 30 ctime=1787067793.369705954 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-topicconfparam.rst0000666000175000017500000000160515132411300025511 0ustar00rgerrger.. _param-omkafka-topicconfparam: .. _omkafka.parameter.module.topicconfparam: TopicConfParam ============== .. index:: single: omkafka; TopicConfParam single: TopicConfParam .. summary-start Arbitrary librdkafka topic options `name=value`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: TopicConfParam :Scope: action :Type: array[string] :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- In essence the same as ``ConfParam``, but for Kafka topic options. Action usage ------------ .. _param-omkafka-action-topicconfparam: .. _omkafka.parameter.action.topicconfparam: .. code-block:: rsyslog action(type="omkafka" topicConfParam=["acks=all"]) Notes ----- - Multiple values may be set using array syntax. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-traptype.rst0000644000000000000000000000013215132733117024621 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.792439959 30 ctime=1787067793.559709494 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-traptype.rst0000666000175000017500000000271515132733117024274 0ustar00rgerrger.. _param-omsnmp-traptype: .. _omsnmp.parameter.module.traptype: TrapType ======== .. index:: single: omsnmp; TrapType single: TrapType .. summary-start Selects the SNMPv1 generic trap type. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: TrapType :Scope: module :Type: integer :Default: module=6 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- There are only 7 Possible trap types defined which can be used here. These trap types are: .. code-block:: none 0 = SNMP_TRAP_COLDSTART 1 = SNMP_TRAP_WARMSTART 2 = SNMP_TRAP_LINKDOWN 3 = SNMP_TRAP_LINKUP 4 = SNMP_TRAP_AUTHFAIL 5 = SNMP_TRAP_EGPNEIGHBORLOSS 6 = SNMP_TRAP_ENTERPRISESPECIFIC .. note:: Any other value will default to 6 automatically. This configuration parameter is used for **SNMPv1** only. It has no effect if **SNMPv2** is used. Module usage ------------ .. _param-omsnmp-module-traptype: .. _omsnmp.parameter.module.traptype-usage: .. code-block:: rsyslog action(type="omsnmp" trapType="6") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmptraptype: - $actionsnmptraptype — maps to TrapType (status: legacy) .. index:: single: omsnmp; $actionsnmptraptype single: $actionsnmptraptype See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-permit-atsignsinhostname.rst0000644000000000000000000000013215132411300030104 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.313449671 30 ctime=1787067793.615710538 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-permit-atsignsinhostname.rst0000666000175000017500000000221615132411300027553 0ustar00rgerrger.. _param-pmrfc3164-permit-atsignsinhostname: .. _pmrfc3164.parameter.module.permit-atsignsinhostname: .. _pmrfc3164.parameter.module.permit.AtSignsInHostname: permit.AtSignsInHostname ========================= .. index:: single: pmrfc3164; permit.AtSignsInHostname single: permit.AtSignsInHostname .. summary-start Allow ``@`` in hostnames, typically from syslog-ng relays. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: permit.AtSignsInHostname :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2508.0 Description ----------- This option allows hostnames to include at-sign characters, which is useful when syslog-ng relays prefix source names with ``@``. Module usage ------------ .. _param-pmrfc3164-module-permit-atsignsinhostname: .. _pmrfc3164.parameter.module.permit-atsignsinhostname-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" permit.AtSignsInHostname="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-broker.rst0000644000000000000000000000013215132411300024320 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.808458899 30 ctime=1787067793.326705152 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-broker.rst0000666000175000017500000000134615132411300023772 0ustar00rgerrger.. _param-omkafka-broker: .. _omkafka.parameter.module.broker: Broker ====== .. index:: single: omkafka; Broker single: Broker .. summary-start List of Kafka brokers in `host:port` form. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Broker :Scope: action :Type: array[string] :Default: action=localhost:9092 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Specifies the broker(s) to use. Action usage ------------ .. _param-omkafka-action-broker: .. _omkafka.parameter.action.broker: .. code-block:: rsyslog action(type="omkafka" Broker=["host1:9092","host2:9092"]) See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-address.rst0000644000000000000000000000013215132733117024355 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.866478623 30 ctime=1787067792.394687784 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-address.rst0000666000175000017500000000145515132733117024030 0ustar00rgerrger.. _param-imrelp-address: .. _imrelp.parameter.input.address: address ======= .. index:: single: imrelp; address single: address .. summary-start Forces the RELP listener to bind to the specified local IP address or hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: address :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.37.0 Description ----------- Bind the RELP server to that address. If not specified, the server will be bound to the wildcard address. Input usage ----------- .. _param-imrelp-input-address-usage: .. _imrelp.parameter.input.address-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" address="203.0.113.5") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-uniqueretrycount.rst0000644000000000000000000000013215145046112030720 xustar0030 mtime=1771326538.941012688 30 atime=1787067671.926442457 30 ctime=1787067792.704693561 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-uniqueretrycount.rst0000664000175000017500000000222015145046112030360 0ustar00rgerrger.. _param-mmanon-embeddedipv4-uniqueretrycount: .. _mmanon.parameter.input.embeddedipv4-uniqueretrycount: embeddedIpv4.uniqueRetryCount ============================= .. index:: single: mmanon; embeddedIpv4.uniqueRetryCount single: embeddedIpv4.uniqueRetryCount .. summary-start Sets the maximum retry count for embedded IPv4 random-consistent-unique anonymization. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.uniqueRetryCount :Scope: input :Type: integer :Default: input=1000 :Required?: no :Introduced: 8.2410.0 Description ----------- Defines how many randomized replacements are attempted before giving up when ``embeddedIpv4.limitUniqueMaxRetries`` is enabled. The retry limit only applies for ``random-consistent-unique`` mode. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-uniqueretrycount-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.anonMode="random-consistent-unique" embeddedIpv4.limitUniqueMaxRetries="on" embeddedIpv4.uniqueRetryCount="500") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-bulkid.rst0000644000000000000000000000013215132411300026043 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.177447136 30 ctime=1787067793.032699674 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-bulkid.rst0000666000175000017500000000150315132411300025510 0ustar00rgerrger.. _param-omelasticsearch-bulkid: .. _omelasticsearch.parameter.module.bulkid: bulkid ====== .. index:: single: omelasticsearch; bulkid single: bulkid .. summary-start Unique identifier assigned to each record. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: bulkid :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Specifies a static value or template used as the document `_id`. Required with `writeoperation="create"`. Action usage ------------ .. _param-omelasticsearch-action-bulkid: .. _omelasticsearch.parameter.action.bulkid: .. code-block:: rsyslog action(type="omelasticsearch" bulkid="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-mode.rst0000644000000000000000000000013215132733117023631 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.324449876 30 ctime=1787067792.086682045 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-mode.rst0000666000175000017500000000311015132733117023272 0ustar00rgerrger.. _param-imfile-mode: .. _imfile.parameter.module.mode: .. _imfile.parameter.mode: Mode ==== .. index:: single: imfile; Mode single: Mode .. summary-start Selects `inotify`, `polling`, or `fen` mode for file monitoring. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: Mode :Scope: module :Type: word :Default: module=inotify :Required?: no :Introduced: 8.1.5 Description ----------- This specifies if imfile shall run in inotify ("inotify") or polling ("polling") mode. Traditionally, imfile used polling mode, which is much more resource-intense (and slower) than inotify mode. It is suggested that users turn on "polling" mode only if they experience strange problems in inotify mode. In theory, there should never be a reason to enable "polling" mode and later versions will most probably remove it. If a legacy "$ModLoad" statement is used, the default is *polling*. This default was kept to prevent problems with old configurations. It might change in the future. On Solaris, the FEN API is used instead of INOTIFY. You can set the mode to fen or inotify (which is automatically mapped to fen on Solaris OS). Please note that the FEN is limited compared to INOTIFY. Deep wildcard matches may not work because of the API limits for now. Module usage ------------ .. _param-imfile-module-mode: .. _imfile.parameter.module.mode-usage: .. code-block:: rsyslog module(load="imfile" Mode="inotify") Notes ----- - Solaris uses the FEN API; deep wildcard matches may fail. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmutf8fix-replacementsequence.rst0000644000000000000000000000013215241075234027417 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.918697549 rsyslog-8.2608.0/doc/source/reference/parameters/mmutf8fix-replacementsequence.rst0000664000175000017500000000413715241075234027070 0ustar00rgerrger.. _param-mmutf8fix-replacementsequence: .. _mmutf8fix.parameter.input.replacementsequence: replacementSequence =================== .. index:: single: mmutf8fix; replacementSequence single: replacementSequence .. summary-start Defines a byte sequence used to substitute invalid input bytes. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmutf8fix`. :Name: replacementSequence :Scope: input :Type: string :Default: not set :Required?: no :Introduced: 8.2606.0 Description ----------- This parameter configures a replacement byte sequence for each invalid input byte detected by mmutf8fix. It is useful when a single printable US-ASCII character is not enough, for example when operators want to use the UTF-8 encoding of ``U+FFFD`` as the invalid-character marker. ``replacementSequence`` and :ref:`param-mmutf8fix-replacementchar` are mutually exclusive. Use ``replacementChar`` when a single-byte replacement is sufficient. Use ``replacementSequence`` only when a multi-byte marker is needed; it is an explicit opt-in to the rebuild path because the output field can become longer than the original input. Each invalid input byte is replaced independently. For example, if an invalid two-byte sequence is detected and ``replacementSequence`` is set to the UTF-8 bytes for ``U+FFFD``, the output contains two replacement markers. Use byte escapes in object-parameter strings. For example, write the UTF-8 bytes for ``U+FFFD`` as ``\xef\xbf\xbd``. The equivalent octal spelling is ``\357\277\275``. Hexadecimal escapes use exactly two digits, and octal escapes use exactly three digits. Input usage ----------- .. _mmutf8fix.parameter.input.replacementsequence-usage: .. code-block:: rsyslog module(load="mmutf8fix") # U+FFFD encoded as UTF-8 bytes. action(type="mmutf8fix" replacementSequence="\xef\xbf\xbd") YAML usage ---------- .. code-block:: yaml modules: - load: "mmutf8fix" rulesets: - name: main script: | action(type="mmutf8fix" replacementSequence="\xef\xbf\xbd") See also -------- See also :doc:`../../configuration/modules/mmutf8fix`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-label-instance.rst0000644000000000000000000000013215145046112027136 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.498471762 30 ctime=1787067792.282685697 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-label-instance.rst0000664000175000017500000000161115145046112026601 0ustar00rgerrger.. _param-impstats-push-label-instance: .. _impstats.parameter.module.push-label-instance: push.label.instance =================== .. index:: single: impstats; push.label.instance single: push.label.instance .. summary-start Controls whether impstats adds ``instance=`` to pushed metrics. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.label.instance :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.2602.0 Description ----------- When enabled, impstats injects the local hostname as the ``instance`` label unless one is already set via ``push.labels``. Module usage ------------ .. _impstats.parameter.module.push-label-instance-usage: .. code-block:: rsyslog module(load="impstats" push.label.instance="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-usepidfromsystem.rst0000644000000000000000000000013215132411300027045 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.879460223 30 ctime=1787067792.211684374 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-usepidfromsystem.rst0000666000175000017500000000223115132411300026511 0ustar00rgerrger.. _param-imjournal-usepidfromsystem: .. _imjournal.parameter.module.usepidfromsystem: .. meta:: :tag: module:imjournal :tag: parameter:UsePidFromSystem UsePidFromSystem ================ .. index:: single: imjournal; UsePidFromSystem single: UsePidFromSystem .. summary-start Use ``_PID`` instead of ``SYSLOG_PID`` as the process identifier. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: UsePidFromSystem :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Retrieves the trusted ``_PID`` field from the journal instead of ``SYSLOG_PID``. This option overrides ``UsePid`` and is deprecated; use ``UsePid="system"`` for equivalent behavior. Module usage ------------ .. _param-imjournal-module-usepidfromsystem: .. _imjournal.parameter.module.usepidfromsystem-usage: .. code-block:: rsyslog module(load="imjournal" UsePidFromSystem="...") Notes ----- - Legacy documentation referred to this as a ``binary`` option. - Deprecated; prefer ``UsePid``. See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-restpath.rst0000644000000000000000000000013115132733117024604 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.083464026 30 ctime=1787067793.287704425 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-restpath.rst0000666000175000017500000000154515132733117024260 0ustar00rgerrger.. _param-omhttp-restpath: .. _omhttp.parameter.input.restpath: restpath ======== .. index:: single: omhttp; restpath single: restpath .. summary-start Sets the REST path portion of the request URL used by omhttp. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: restpath :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The REST path you want to use. Do not include the leading slash character. If the full path looks like ``localhost:5000/my/path``, ``restpath`` should be ``my/path``. Input usage ----------- .. _omhttp.parameter.input.restpath-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" restPath="logs/v1/events" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-maxsessions.rst0000644000000000000000000000013215241075234025130 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.725580541 30 ctime=1787067792.494689648 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-maxsessions.rst0000664000175000017500000000365715241075234024607 0ustar00rgerrger.. _param-imtcp-maxsessions: .. _imtcp.parameter.module.maxsessions: .. _imtcp.parameter.input.maxsessions: MaxSessions =========== .. index:: single: imtcp; MaxSessions single: MaxSessions .. summary-start Sets the maximum number of sessions supported. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: MaxSessions :Scope: module, input :Type: integer :Default: module=200, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the maximum number of sessions supported. This must be set before the first $InputTCPServerRun directive. The same-named input parameter can override this module setting. Each session owns its framing, transport, TLS, and optional decompressor state. Consequently, unusually large values multiply the memory retained by idle or incomplete connections. A zlib ``stream:always`` session has a bounded history window of at most 32 KiB plus decoder bookkeeping; completed zlib streams release that decoder state immediately, but incomplete streams retain it until the connection closes. Size ``MaxSessions`` for the listener's expected concurrency and available memory. Module usage ------------ .. _param-imtcp-module-maxsessions: .. _imtcp.parameter.module.maxsessions-usage: .. code-block:: rsyslog module(load="imtcp" maxSessions="500") Input usage ----------- .. _param-imtcp-input-maxsessions: .. _imtcp.parameter.input.maxsessions-usage: .. code-block:: rsyslog input(type="imtcp" port="514" maxSessions="500") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpmaxsessions: - $InputTCPMaxSessions — maps to MaxSessions (status: legacy) .. index:: single: imtcp; $InputTCPMaxSessions single: $InputTCPMaxSessions See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-sig-provider.rst0000644000000000000000000000013215132411300025310 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.569454444 30 ctime=1787067793.199702786 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-sig-provider.rst0000666000175000017500000000214215132411300024755 0ustar00rgerrger.. _param-omfile-sig-provider: .. _omfile.parameter.module.sig-provider: sig.Provider ============ .. index:: single: omfile; sig.Provider single: sig.Provider .. summary-start Selects a signature provider for log signing. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: sig.Provider :Scope: action :Type: word :Default: action=no signature provider :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Selects a signature provider for log signing. By selecting a provider, the signature feature is turned on. Currently there is one signature provider available: ":doc:`ksi_ls12 <../../configuration/modules/sigprov_ksi12>`". Previous signature providers ":doc:`gt <../../configuration/modules/sigprov_gt>`" and ":doc:`ksi <../../configuration/modules/sigprov_ksi>`" are deprecated. Action usage ------------ .. _param-omfile-action-sig-provider: .. _omfile.parameter.action.sig-provider: .. code-block:: rsyslog action(type="omfile" sig.Provider="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-workerthreads.rst0000644000000000000000000000013115216464435025756 xustar0030 mtime=1782212893.984265505 29 atime=1787067671.80644022 30 ctime=1787067791.395669168 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-workerthreads.rst0000664000175000017500000000255315216464435025430 0ustar00rgerrger.. _param-imbeats-workerthreads: .. _imbeats.parameter.input.workerthreads: workerThreads ============= .. meta:: :description: Number of worker threads used by an imbeats listener. :keywords: rsyslog, imbeats, workerThreads, Beats sessions, multiplexing .. index:: single: imbeats; workerThreads single: workerThreads .. summary-start Set how many worker threads an imbeats listener uses to process client sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: workerThreads :Scope: input :Type: positive integer :Default: input=2 :Required?: no :Introduced: 8.2606.0 Description ----------- Set the number of worker threads used by this ``imbeats`` listener. A value of ``1`` keeps processing single-threaded. Higher values allow multiple client sessions to be processed in parallel when the platform and stream layer support session multiplexing. Increasing this value can improve throughput for many active senders, but each worker consumes system resources. Avoid setting it higher than the expected active sender count or available CPU capacity. Input usage ----------- .. _param-imbeats-input-workerthreads: .. _imbeats.parameter.input.workerthreads-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" workerThreads="4") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmfields-separator.rst0000644000000000000000000000013215132733117025240 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.318449765 30 ctime=1787067792.785695071 rsyslog-8.2608.0/doc/source/reference/parameters/mmfields-separator.rst0000666000175000017500000000257115132733117024713 0ustar00rgerrger.. _param-mmfields-separator: .. _mmfields.parameter.input.separator: separator ========= .. index:: single: mmfields; separator single: separator .. summary-start Sets the character that separates fields when mmfields extracts them. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmfields`. :Name: separator :Scope: input :Type: char :Default: ``,`` :Required?: no :Introduced: 7.5.1 Description ----------- This parameter specifies the character used to separate fields. The module currently accepts only a single character. Multi-character separators are not supported by ``mmfields`` but can be implemented via the RainerScript method. CEF does not require multi-character separators, so this limitation is usually acceptable. If you need multi-character separators in ``mmfields``, please request this feature on the rsyslog mailing list and describe the use case; support can be added when there is a documented requirement. The fields are named f\ *nbr*, where *nbr* is the field number starting with one and being incremented for each field. Input usage ----------- .. _param-mmfields-input-separator-usage: .. _mmfields.parameter.input.separator-usage: .. code-block:: rsyslog module(load="mmfields") action(type="mmfields" separator=",") See also -------- This parameter is part of the :doc:`../../configuration/modules/mmfields` module. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-keepalive.rst0000644000000000000000000000013215216464435025040 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.750439176 30 ctime=1787067791.329667938 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-keepalive.rst0000664000175000017500000000160015216464435024501 0ustar00rgerrger.. _param-imbeats-keepalive: .. _imbeats.parameter.input.keepalive: KeepAlive ========= .. meta:: :description: Enable TCP keepalive for imbeats client sessions. :keywords: rsyslog, imbeats, keepalive .. index:: single: imbeats; KeepAlive single: KeepAlive .. summary-start Enable socket-level TCP keepalive on accepted imbeats connections. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: KeepAlive :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2604.0 Description ----------- Enable socket-level TCP keepalive on accepted imbeats connections. Input usage ----------- .. _param-imbeats-input-keepalive: .. _imbeats.parameter.input.keepalive-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" keepAlive="on") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-mycert.rst0000644000000000000000000000013115132411300026673 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.139446427 29 ctime=1787067793.10870109 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-mycert.rst0000666000175000017500000000160015132411300026337 0ustar00rgerrger.. _param-omelasticsearch-tls-mycert: .. _omelasticsearch.parameter.module.tls-mycert: .. _omelasticsearch.parameter.module.tls.mycert: tls.mycert ========== .. index:: single: omelasticsearch; tls.mycert single: tls.mycert .. summary-start Client certificate for mutual TLS authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.mycert :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- PEM file containing the client certificate presented to Elasticsearch. Action usage ------------ .. _param-omelasticsearch-action-tls-mycert: .. _omelasticsearch.parameter.action.tls-mycert: .. code-block:: rsyslog action(type="omelasticsearch" tls.mycert="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-authmode.rst0000644000000000000000000000013115132733117025341 xustar0030 mtime=1768666703.903620178 30 atime=1787067671.984443538 29 ctime=1787067792.03168102 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-authmode.rst0000666000175000017500000000223215132733117025007 0ustar00rgerrger.. _param-imdtls-tls-authmode: .. _imdtls.parameter.input.tls-authmode: tls.authMode ============ .. index:: single: imdtls; tls.authMode single: tls.authMode .. summary-start Defines the mutual authentication method used for DTLS clients. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.authMode :Scope: input :Type: string :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Sets the mode used for mutual authentication. Supported values are: * **fingerprint**: Authentication based on certificate fingerprint. * **name**: Authentication based on the ``subjectAltName`` and, as a fallback, the ``subject common name``. * **certvalid**: Requires a valid certificate for authentication. If any other value is provided, or if the parameter is omitted, anonymous authentication (**certanon**) is used, which does not require a client certificate. Input usage ----------- .. _imdtls.parameter.input.tls-authmode-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.authMode="certvalid") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-allowunsignedcerts.rst0000644000000000000000000000013015216464435030046 xustar0029 mtime=1782212893.98826557 30 atime=1787067673.533472415 29 ctime=1787067792.97669863 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-allowunsignedcerts.rst0000664000175000017500000000176415216464435027524 0ustar00rgerrger.. _param-omclickhouse-allowunsignedcerts: .. _omclickhouse.parameter.input.allowunsignedcerts: allowUnsignedCerts ================== .. index:: single: omclickhouse; allowUnsignedCerts single: allowUnsignedCerts single: omclickhouse; allowunsignedcerts single: allowunsignedcerts .. summary-start Allows connections to servers that present unsigned TLS certificates. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: allowUnsignedCerts :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: not specified Description ----------- If set to ``"on"``, the module accepts servers with unsigned certificates. By default (``"off"``), TLS peer certificates are verified. Input usage ----------- .. _omclickhouse.parameter.input.allowunsignedcerts-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" allowUnsignedCerts="off") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-skipverifyhost.rst0000644000000000000000000000013115132733117027215 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.658474745 30 ctime=1787067792.994698966 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-skipverifyhost.rst0000666000175000017500000000203515132733117026664 0ustar00rgerrger.. _param-omclickhouse-skipverifyhost: .. _omclickhouse.parameter.input.skipverifyhost: skipVerifyHost ============== .. index:: single: omclickhouse; skipVerifyHost single: skipVerifyHost single: omclickhouse; skipverifyhost single: skipverifyhost .. summary-start Controls whether the module disables host name verification for HTTPS connections. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: skipVerifyHost :Scope: input :Type: boolean :Default: off :Required?: no :Introduced: not specified Description ----------- If ``"on"``, this will set the curl ``CURLOPT_SSL_VERIFYHOST`` option to ``0``. .. warning:: You are strongly discouraged to set this to ``"on"``. It is primarily useful only for debugging or testing. Input usage ----------- .. _omclickhouse.parameter.input.skipverifyhost-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" skipVerifyHost="on") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-maxdatasize.rst0000644000000000000000000000013215132733117025242 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.889479051 30 ctime=1787067792.408688045 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-maxdatasize.rst0000666000175000017500000000207315132733117024712 0ustar00rgerrger.. _param-imrelp-maxdatasize: .. _imrelp.parameter.input.maxdatasize: maxDataSize =========== .. index:: single: imrelp; maxDataSize single: maxDataSize .. summary-start Sets the max message size the RELP listener accepts before oversize handling. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: maxDataSize :Scope: input :Type: size_nbr :Default: input=:doc:`global(maxMessageSize) <../../rainerscript/global>` :Required?: no :Introduced: Not documented Description ----------- Sets the max message size (in bytes) that can be received. Messages that are too long are handled as specified in parameter :ref:`param-imrelp-oversizemode`. Note that maxDataSize cannot be smaller than the global parameter :doc:`global(maxMessageSize) <../../rainerscript/global>`. Input usage ----------- .. _param-imrelp-input-maxdatasize-usage: .. _imrelp.parameter.input.maxdatasize-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" maxDataSize="10k") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-subject-text.rst0000644000000000000000000000013215132733117025337 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.001462497 30 ctime=1787067793.404706606 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-subject-text.rst0000666000175000017500000000230015132733117025000 0ustar00rgerrger.. _param-ommail-subject-text: .. _ommail.parameter.input.subject-text: subjectText =========== .. index:: single: ommail; subjectText single: subjectText .. summary-start Sets a fixed subject line instead of generating one from a template. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: subjectText :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.5.0 Description ----------- Use this parameter to set a **constant** subject text. Choose :ref:`param-ommail-subject-template` when the subject should be generated from a template. The ``subjectTemplate`` and ``subjectText`` parameters cannot both be configured within a single action. If neither is specified, a default, non-configurable subject line will be generated. Input usage ------------ .. _ommail.parameter.input.subject-text-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" subjectText="rsyslog detected disk problem" ) See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpcontenttype.rst0000644000000000000000000000013115132733117026226 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.611455227 30 ctime=1787067793.257703866 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpcontenttype.rst0000666000175000017500000000217515132733117025702 0ustar00rgerrger.. _param-omhttp-httpcontenttype: .. _omhttp.parameter.input.httpcontenttype: httpcontenttype =============== .. index:: single: omhttp; httpcontenttype single: httpcontenttype .. summary-start Overrides the HTTP ``Content-Type`` header that omhttp sends with each request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpcontenttype :Scope: input :Type: word :Default: input=application/json; charset=utf-8 :Required?: no :Introduced: Not specified Description ----------- The HTTP ``Content-Type`` header sent with each request. This parameter will override other defaults. If a batching mode is specified, the correct content type is automatically configured. The ``Content-Type`` header can also be configured using the :ref:`param-omhttp-httpheaders` parameter; configure it in only one place. Input usage ----------- .. _omhttp.parameter.input.httpcontenttype-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpContentType="application/cloudevents+json" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-skipverifyhost.rst0000644000000000000000000000013215132733117026044 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.221466598 30 ctime=1787067793.303704724 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-skipverifyhost.rst0000666000175000017500000000176015132733117025516 0ustar00rgerrger.. _param-omhttp-skipverifyhost: .. _omhttp.parameter.input.skipverifyhost: skipverifyhost ============== .. index:: single: omhttp; skipverifyhost single: skipverifyhost .. summary-start Controls whether omhttp verifies the HTTPS server hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: skipverifyhost :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- If ``"on"``, this will set the curl `CURLOPT_SSL_VERIFYHOST `_ option to ``0``. You are strongly discouraged to set this to ``"on"``. It is primarily useful only for debugging or testing. Input usage ----------- .. _omhttp.parameter.input.skipverifyhost-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" skipVerifyHost="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-rebindinterval.rst0000644000000000000000000000013215132411300027601 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.231448143 30 ctime=1787067793.077700512 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-rebindinterval.rst0000666000175000017500000000166315132411300027255 0ustar00rgerrger.. _param-omelasticsearch-rebindinterval: .. _omelasticsearch.parameter.module.rebindinterval: rebindinterval ============== .. index:: single: omelasticsearch; rebindinterval single: rebindinterval .. summary-start Operations after which to reconnect; `-1` disables periodic reconnect. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: rebindinterval :Scope: action :Type: integer :Default: action=-1 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- After this many operations the module drops and re-establishes the connection. Useful behind load balancers. Action usage ------------ .. _param-omelasticsearch-action-rebindinterval: .. _omelasticsearch.parameter.action.rebindinterval: .. code-block:: rsyslog action(type="omelasticsearch" rebindinterval="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-port.rst0000644000000000000000000000013215216464435023711 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.850459682 30 ctime=1787067793.395706438 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-port.rst0000664000175000017500000000245415216464435023362 0ustar00rgerrger.. _param-ommail-port: .. _ommail.parameter.input.port: port ==== .. index:: single: ommail; port single: port .. summary-start Sets the SMTP port number or service name that ommail uses in SMTP mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: port :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: 8.5.0 Description ----------- Port number or name of the SMTP port to be used by ``mode="smtp"``. While the module may fall back to port 25 in some legacy scenarios, this parameter is required for modern SMTP-mode configurations. It is not used by ``mode="sendmail"``. Input usage ------------ .. _ommail.parameter.input.port-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailsmtpport: - $ActionMailSMTPPort — maps to port (status: legacy) .. index:: single: ommail; $ActionMailSMTPPort single: $ActionMailSMTPPort See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-token.rst0000644000000000000000000000013215241075234025255 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.013680685 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-token.rst0000664000175000017500000000140215241075234024716 0ustar00rgerrger.. _param-imkubernetes-token: .. _imkubernetes.parameter.module.token: Token ===== .. index:: single: imkubernetes; Token single: Token .. summary-start Literal bearer token used for Kubernetes API authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: Token :Scope: module :Type: string :Default: none :Required?: no :Introduced: 8.2604.0 Description ----------- If set, this token is used directly in the ``Authorization: Bearer`` header. It takes precedence over :ref:`TokenFile `. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" Token="eyJhbGciOi...") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-compress-level.rst0000644000000000000000000000013115132733117025712 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.292467922 30 ctime=1787067793.244703624 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-compress-level.rst0000666000175000017500000000220115132733117025354 0ustar00rgerrger.. _param-omhttp-compress-level: .. _omhttp.parameter.input.compress-level: compress.level ============== .. index:: single: omhttp; compress.level single: compress.level .. summary-start Sets the zlib compression level used when :ref:`param-omhttp-compress` is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: compress.level :Scope: input :Type: integer :Default: input=-1 :Required?: no :Introduced: Not specified Description ----------- Specify the zlib compression level if :ref:`param-omhttp-compress` is enabled. Check the `zlib manual `_ for further documentation. ``-1`` is the default value that strikes a balance between best speed and best compression. ``0`` disables compression. ``1`` results in the fastest compression. ``9`` results in the best compression. Input usage ----------- .. _omhttp.parameter.input.compress-level-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" compress="on" compressLevel="9" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ompgsql-port.rst0000644000000000000000000000013115145046112024101 xustar0030 mtime=1771326538.949012819 29 atime=1787067673.40447001 30 ctime=1787067793.437707221 rsyslog-8.2608.0/doc/source/reference/parameters/ompgsql-port.rst0000664000175000017500000000132715145046112023551 0ustar00rgerrger.. _param-ompgsql-port: .. _ompgsql.parameter.input.port: Port ==== .. index:: single: ompgsql; Port single: Port .. summary-start Sets the TCP port of the PostgreSQL server. .. summary-end This parameter applies to :doc:`../../configuration/modules/ompgsql`. :Name: Port :Scope: input :Type: integer :Default: 5432 :Required?: no :Introduced: 8.32.0 Description ----------- The IP port of the PostgreSQL server. The name ``serverport`` is also accepted. Input usage ----------- .. _ompgsql.parameter.input.port-usage: .. code-block:: rsyslog module(load="ompgsql") action(type="ompgsql" server="localhost" port="5432" db="syslog") See also -------- See also :doc:`../../configuration/modules/ompgsql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-deletestateonfilemove.rst0000644000000000000000000000013015132733117027272 xustar0030 mtime=1768666703.903620178 28 atime=1787067672.3364501 30 ctime=1787067792.050681374 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-deletestateonfilemove.rst0000666000175000017500000000317415132733117026747 0ustar00rgerrger.. _param-imfile-deletestateonfilemove: .. _imfile.parameter.input.deletestateonfilemove: .. _imfile.parameter.deletestateonfilemove: deleteStateOnFileMove ===================== .. index:: single: imfile; deleteStateOnFileMove single: deleteStateOnFileMove .. summary-start Removes the state file when a monitored file is moved or renamed. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: deleteStateOnFileMove :Scope: module, input :Type: boolean :Default: module=off; input=inherits module :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- When set to ``on`` at module scope, the state file for a monitored file is removed when that file is moved or rotated away. By default the state file is kept. The input parameter controls whether the state file is deleted when its associated file is moved or renamed. It inherits the module setting unless explicitly configured. Enabling it prevents orphaned state files. Module usage ------------ .. _param-imfile-module-deletestateonfilemove: .. _imfile.parameter.module.deletestateonfilemove-usage: .. code-block:: rsyslog module(load="imfile" deleteStateOnFileMove="on") Input usage ----------- .. _param-imfile-input-deletestateonfilemove: .. _imfile.parameter.input.deletestateonfilemove-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" deleteStateOnFileMove="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-discardtruncatedmsg.rst0000644000000000000000000000013215132733117026606 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.940480002 30 ctime=1787067792.470689201 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-discardtruncatedmsg.rst0000666000175000017500000000255515132733117026263 0ustar00rgerrger.. _param-imtcp-discardtruncatedmsg: .. _imtcp.parameter.module.discardtruncatedmsg: .. _imtcp.parameter.input.discardtruncatedmsg: DiscardTruncatedMsg =================== .. index:: single: imtcp; DiscardTruncatedMsg single: DiscardTruncatedMsg .. summary-start Discards data beyond the truncation point in octet-stuffing mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: DiscardTruncatedMsg :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Normally when a message is truncated in octet stuffing mode the part that is cut off is processed as the next message. When this parameter is activated, the part that is cut off after a truncation is discarded and not processed. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-discardtruncatedmsg: .. _imtcp.parameter.module.discardtruncatedmsg-usage: .. code-block:: rsyslog module(load="imtcp" discardTruncatedMsg="on") Input usage ----------- .. _param-imtcp-input-discardtruncatedmsg: .. _imtcp.parameter.input.discardtruncatedmsg-usage: .. code-block:: rsyslog input(type="imtcp" port="514" discardTruncatedMsg="on") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-mode.rst0000644000000000000000000000013215132733117024722 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.356450473 30 ctime=1787067792.795695257 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-mode.rst0000666000175000017500000000245615132733117024377 0ustar00rgerrger.. _param-mmjsonparse-mode: .. _mmjsonparse.parameter.mode: mode ==== .. index:: single: mmjsonparse; mode single: mode single: parsing mode .. summary-start Specifies the parsing mode for JSON content detection. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: mode :Scope: action :Type: string :Default: cookie :Required?: no :Introduced: 8.2506.0 Description ----------- Sets the parsing mode to determine how JSON content is detected and processed. - **cookie** (default): Legacy CEE cookie mode. Expects messages to begin with the configured cookie (default "@cee:") followed by JSON content. This preserves backward compatibility with existing configurations. - **find-json**: Scans the message to locate the first valid top-level JSON object "{...}" regardless of its position. The module uses a tokenizer-aware scanner that respects quotes and escapes to find complete JSON objects. Input usage ----------- .. _mmjsonparse.parameter.mode-usage: .. code-block:: rsyslog # Legacy CEE cookie mode (default) action(type="mmjsonparse" mode="cookie") # Find-JSON scanning mode action(type="mmjsonparse" mode="find-json") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`.rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dirownernum.rst0000644000000000000000000000013215132411300025247 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.362450585 30 ctime=1787067793.154701947 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dirownernum.rst0000666000175000017500000000310615132411300024715 0ustar00rgerrger.. _param-omfile-dirownernum: .. _omfile.parameter.module.dirownernum: dirOwnerNum =========== .. index:: single: omfile; dirOwnerNum single: dirOwnerNum .. summary-start Set the file owner for directories newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dirOwnerNum :Scope: module, action :Type: integer :Default: module=process user; action=system default :Required?: no :Introduced: 7.5.8 Description ----------- Set the file owner for directories newly created. Please note that this setting does not affect the owner of directories already existing. The parameter is a numerical ID, which is used regardless of whether the user actually exists. This can be useful if the user mapping is not available to rsyslog during startup. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-dirownernum: .. _omfile.parameter.module.dirownernum-usage: .. code-block:: rsyslog module(load="builtin:omfile" dirOwnerNum="...") Action usage ------------ .. _param-omfile-action-dirownernum: .. _omfile.parameter.action.dirownernum: .. code-block:: rsyslog action(type="omfile" dirOwnerNum="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dirownernum: - $DirOwnerNum — maps to dirOwnerNum (status: legacy) .. index:: single: omfile; $DirOwnerNum single: $DirOwnerNum See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-ratelimit-burst.rst0000644000000000000000000000013215132733117025705 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.348487608 30 ctime=1787067792.582691288 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-ratelimit-burst.rst0000666000175000017500000000141715132733117025356 0ustar00rgerrger.. _param-imudp-ratelimit-burst: .. _imudp.parameter.input.ratelimit-burst: RateLimit.Burst =============== .. index:: single: imudp; RateLimit.Burst single: RateLimit.Burst .. summary-start Maximum messages permitted per rate-limiting burst. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: RateLimit.Burst :Scope: input :Type: integer :Default: input=10000 :Required?: no :Introduced: 7.3.1 Description ----------- Specifies the rate-limiting burst in number of messages. Input usage ----------- .. _param-imudp-input-ratelimit-burst: .. _imudp.parameter.input.ratelimit-burst-usage: .. code-block:: rsyslog input(type="imudp" RateLimit.Burst="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-cafile.rst0000644000000000000000000000013215216464435027023 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.845440947 30 ctime=1787067791.371668721 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-cafile.rst0000664000175000017500000000174715216464435026500 0ustar00rgerrger.. _param-imbeats-streamdriver-cafile: .. _imbeats.parameter.input.streamdriver-cafile: StreamDriver.CAFile =================== .. meta:: :description: CA file for imbeats TLS validation. :keywords: rsyslog, imbeats, streamdriver cafile .. index:: single: imbeats; StreamDriver.CAFile single: StreamDriver.CAFile .. summary-start Specify the CA bundle used to validate TLS peers for imbeats. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.CAFile :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Specify the CA bundle used to validate TLS peers for imbeats. Input usage ----------- .. _param-imbeats-input-streamdriver-cafile: .. _imbeats.parameter.input.streamdriver-cafile-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.caFile="/etc/rsyslog/ca.pem") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-log_stream.rst0000644000000000000000000000013215241075234026276 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.968698481 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-log_stream.rst0000664000175000017500000000200615241075234025740 0ustar00rgerrger.. _param-omawslogshlc-log_stream: .. _omawslogshlc.parameter.action.log_stream: .. meta:: :description: Reference for the omawslogshlc log_stream parameter. :keywords: rsyslog, omawslogshlc, log_stream, aws, cloudwatch log_stream ========== .. index:: single: omawslogshlc; log_stream single: log_stream .. summary-start Specifies the CloudWatch Logs log stream name within the log group. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: log_stream :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``log_stream`` identifies the target log stream within the configured log group. The value is URL-encoded automatically when constructing the HLC endpoint URL. Action usage ------------ .. _omawslogshlc.parameter.action.log_stream-usage: .. code-block:: rsyslog action(type="omawslogshlc" log_stream="server-01" ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-reportfailures.rst0000644000000000000000000000013215132733117026011 xustar0030 mtime=1768666703.920620435 30 atime=1787067673.012462702 30 ctime=1787067793.470707836 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-reportfailures.rst0000666000175000017500000000303315132733117025456 0ustar00rgerrger.. _param-omprog-reportfailures: .. _omprog.parameter.action.reportfailures: reportFailures ============== .. index:: single: omprog; reportFailures single: reportFailures .. summary-start Logs a warning when the program signals an error while confirming messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: reportFailures :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.38.0 Description ----------- Specifies whether rsyslog must internally log a warning message whenever the program returns an error when confirming a message. The logged message will include the error line returned by the program. This parameter is ignored when :ref:`param-omprog-confirmmessages` is set to "off". Enabling this flag can be useful to log the problems detected by the program. However, the information that can be logged is limited to a short error line, and the logs will be tagged as originated by the 'syslog' facility (like the rest of rsyslog logs). To avoid these shortcomings, consider the use of the :ref:`param-omprog-output` parameter to capture the stderr of the program. Action usage ------------ .. _param-omprog-action-reportfailures: .. _omprog.parameter.action.reportfailures-usage: .. code-block:: rsyslog action(type="omprog" confirmMessages="on" reportFailures="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-authmode.rst0000644000000000000000000000013215132733117027067 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.099482966 30 ctime=1787067792.525690225 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-authmode.rst0000666000175000017500000000334115132733117026536 0ustar00rgerrger.. _param-imtcp-streamdriver-authmode: .. _imtcp.parameter.module.streamdriver-authmode: .. _imtcp.parameter.input.streamdriver-authmode: StreamDriver.AuthMode ===================== .. index:: single: imtcp; StreamDriver.AuthMode single: StreamDriver.AuthMode .. summary-start Sets stream driver authentication mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.AuthMode :Scope: module, input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets stream driver authentication mode. Possible values and meaning depend on the :doc:`network stream driver <../../concepts/netstrm_drvr>`. used. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-authmode: .. _imtcp.parameter.module.streamdriver-authmode-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.authMode="...") Input usage ----------- .. _param-imtcp-input-streamdriver-authmode: .. _imtcp.parameter.input.streamdriver-authmode-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.authMode="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverstreamdriverauthmode: - $InputTCPServerStreamDriverAuthMode — maps to StreamDriver.AuthMode (status: legacy) .. index:: single: imtcp; $InputTCPServerStreamDriverAuthMode single: $InputTCPServerStreamDriverAuthMode See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-retry.rst0000644000000000000000000000013115132733117024117 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.118464678 30 ctime=1787067793.296704593 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-retry.rst0000666000175000017500000000443215132733117023571 0ustar00rgerrger.. _param-omhttp-retry: .. _omhttp.parameter.input.retry: retry ===== .. index:: single: omhttp; retry single: retry .. summary-start Enables omhttp's internal retry logic that requeues failed requests for another attempt. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: retry :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- This parameter specifies whether failed requests should be retried using the custom retry logic implemented in this plugin. Requests returning 5XX HTTP status codes are considered retriable. If retry is enabled, set :ref:`param-omhttp-retry-ruleset` as well. Note that retries are generally handled in rsyslog by setting ``action.resumeRetryCount="-1"`` (or some other integer), and the plugin lets rsyslog know it should start retrying by suspending itself. This is still the recommended approach in the two cases enumerated below when using this plugin. In both of these cases, the output plugin transaction interface is not used. That is, from rsyslog core's point of view, each message is contained in its own transaction. 1. Batching is off (``batch="off"``) 2. Batching is on and the maximum batch size is 1 (``batch="on" batchMaxSize="1"``) This custom retry behavior is the result of a bug in rsyslog's handling of transaction commits. See `this issue `_ for full details. Essentially, if rsyslog hands omhttp 4 messages, and omhttp batches them up but the request fails, rsyslog will only retry the LAST message that it handed the plugin, instead of all 4, even if the plugin returns the correct "defer commit" statuses for messages 1, 2, and 3. This means that omhttp cannot rely on ``action.resumeRetryCount`` for any transaction that processes more than a single message, and explains why the 2 above cases do work correctly. It looks promising that issue will be resolved at some point, so this behavior can be revisited at that time. Input usage ----------- .. _omhttp.parameter.input.retry-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" retry="on" retryRuleSet="rs_omhttp_retry" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-port.rst0000644000000000000000000000013215132733117023714 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.860478511 30 ctime=1787067792.415688176 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-port.rst0000666000175000017500000000177315132733117023372 0ustar00rgerrger.. _param-imrelp-port: .. _imrelp.parameter.input.port: port ==== .. index:: single: imrelp; port single: port .. summary-start Starts a RELP server instance that listens on the specified TCP port. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: port :Scope: input :Type: string :Default: input=none :Required?: yes :Introduced: Not documented Description ----------- Starts a RELP server on the selected port. Input usage ----------- .. _param-imrelp-input-port-usage: .. _imrelp.parameter.input.port-usage: .. code-block:: rsyslog input(type="imrelp" port="2514") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imrelp.parameter.legacy.inputrelpserverrun: - $InputRELPServerRun — maps to port (status: legacy) .. index:: single: imrelp; $InputRELPServerRun single: $InputRELPServerRun See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-closetimeout.rst0000644000000000000000000000013215132411300025550 xustar0030 mtime=1768559296.212884786 30 atime=1787067672.841459514 30 ctime=1787067793.329705208 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-closetimeout.rst0000666000175000017500000000162315132411300025220 0ustar00rgerrger.. _param-omkafka-closetimeout: .. _omkafka.parameter.module.closetimeout: closeTimeout ============ .. index:: single: omkafka; closeTimeout single: closeTimeout .. summary-start Milliseconds to wait for pending messages on shutdown. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: closeTimeout :Scope: action :Type: integer :Default: action=2000 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Sets the time to wait in ms for draining messages submitted to the Kafka handle before closing it. The maximum across all actions is used as librdkafka's unload timeout. Action usage ------------ .. _param-omkafka-action-closetimeout: .. _omkafka.parameter.action.closetimeout: .. code-block:: rsyslog action(type="omkafka" closeTimeout="2000") See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-maxsessions.rst0000644000000000000000000000013215132733117025246 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.065445048 30 ctime=1787067791.951679529 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-maxsessions.rst0000666000175000017500000000252615132733117024721 0ustar00rgerrger.. _param-imdiag-maxsessions: .. _imdiag.parameter.module.maxsessions: MaxSessions =========== .. index:: single: imdiag; MaxSessions single: MaxSessions .. summary-start Limits the number of concurrent diagnostic control connections accepted. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: MaxSessions :Scope: module :Type: integer :Default: module=20 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines how many client sessions the diagnostic listener accepts at once. By default the listener allows 20 concurrent sessions. The limit must be set before :ref:`ServerRun ` creates the TCP listener. Additional connection attempts beyond the configured number are rejected. Module usage ------------ .. _param-imdiag-module-maxsessions: .. _imdiag.parameter.module.maxsessions-usage: .. code-block:: rsyslog module(load="imdiag" maxSessions="10") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagmaxsessions: - $IMDiagMaxSessions — maps to MaxSessions (status: legacy) .. index:: single: imdiag; $IMDiagMaxSessions single: $IMDiagMaxSessions See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-ratelimit-name.rst0000644000000000000000000000013215171370365025645 xustar0030 mtime=1776677109.117908084 30 atime=1787067673.990480934 30 ctime=1787067792.417688213 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-ratelimit-name.rst0000664000175000017500000000165515171370365025320 0ustar00rgerrger.. index:: ! imrelp; RateLimit.Name .. _param-imrelp-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. All listeners (even across different modules) that reference the same name share the same rate limiting configuration and per-source tracking state. Each listener still maintains its own basic message counters so that independent input streams are rate-limited individually. The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimit.interval`` and ``ratelimit.burst``. If ``ratelimit.name`` is specified, local per-listener limits cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2604.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-readtimeout.rst0000644000000000000000000000013215132733117025227 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.328449951 30 ctime=1787067792.102682343 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-readtimeout.rst0000666000175000017500000000321115132733117024672 0ustar00rgerrger.. _param-imfile-readtimeout: .. _imfile.parameter.input.readtimeout: .. _imfile.parameter.readtimeout: readTimeout =========== .. index:: single: imfile; readTimeout single: readTimeout .. summary-start Sets the multi-line read timeout in seconds; module value provides the default. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: readTimeout :Scope: module, input :Type: integer :Default: module=0; input=inherits module :Required?: no :Introduced: 8.23.0 Description ----------- The module parameter defines the default value for input ``readTimeout`` settings. The value is the number of seconds before partially read messages are timed out. At input scope, this can be used with ``startmsg.regex`` (but not ``readMode``). If specified, partial multi-line reads are timed out after the specified interval. The current message fragment is processed and the next fragment arriving is treated as a completely new message. This is useful when a file is infrequently written and a late next message would otherwise delay processing for a long time. Module usage ------------ .. _param-imfile-module-readtimeout: .. _imfile.parameter.module.readtimeout-usage: .. code-block:: rsyslog module(load="imfile" readTimeout="0") Input usage ----------- .. _param-imfile-input-readtimeout: .. _imfile.parameter.input.readtimeout-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" readTimeout="0") Notes ----- - Use only with ``startmsg.regex``; ignored with ``readMode``. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-tls-authmode.rst0000644000000000000000000000013215132733117025350 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.804440182 30 ctime=1787067793.014699338 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-tls-authmode.rst0000666000175000017500000000230715132733117025020 0ustar00rgerrger.. _param-omdtls-tls-authmode: .. _omdtls.parameter.input.tls-authmode: tls.authmode ============ .. index:: single: omdtls; tls.authmode single: tls.authmode .. summary-start Sets the DTLS peer authentication method used by the action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: tls.authmode :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- Sets the mode of authentication to be used. Supported values are ``fingerprint``, ``name``, or ``certvalid``. * ``fingerprint``: Authentication based on certificate fingerprint. * ``name``: Authentication based on the ``subjectAltName`` and, as a fallback, the subject common name. * ``certvalid``: Requires a valid certificate for authentication. If this parameter is not set, or if an unsupported value is provided, the action falls back to anonymous authentication (no client certificate required). Input usage ----------- .. _omdtls.parameter.input.tls-authmode-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" tls.authMode="certvalid") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-keyexchangegroups.rs0000644000000000000000000000013215241075234030755 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.106701052 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-keyexchangegroups.rst0000664000175000017500000000436015241075234030610 0ustar00rgerrger.. _param-omelasticsearch-tls-keyexchangegroups: .. _omelasticsearch.parameter.module.tls-keyexchangegroups: .. _omelasticsearch.parameter.module.tls.keyexchangegroups: tls.keyexchangegroups ===================== .. index:: single: omelasticsearch; tls.keyexchangegroups single: tls.keyexchangegroups .. summary-start Key exchange group preference list, enabling post-quantum hybrid KEMs. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.keyexchangegroups :Scope: action :Type: word :Default: none (libcurl/OpenSSL default) :Required?: no :Introduced: 8.2606.0 Description ----------- Passes a colon-separated list of named key-exchange groups to libcurl (``CURLOPT_SSL_EC_CURVES``). Groups are advertised in order of preference in the TLS ClientHello. This is the primary knob for post-quantum cryptography (PQC) readiness. Setting it to ``X25519MLKEM768:X25519`` requests the hybrid ML-KEM / X25519 group first, falling back to classical X25519 if the server does not support it. For a hard PQC-only policy, omit the ``:X25519`` suffix — connections to non-PQC servers will then fail. PQC key exchange requires: * libcurl 7.73.0 or later (``CURLOPT_SSL_EC_CURVES`` support) * OpenSSL 3.x with the `OQS provider `_ installed If rsyslog was built against libcurl older than 7.73, configuring this parameter has no effect and a warning is logged at configuration load. Action usage ------------ .. _param-omelasticsearch-action-tls-keyexchangegroups: .. _omelasticsearch.parameter.action.tls-keyexchangegroups: .. code-block:: rsyslog action(type="omelasticsearch" usehttps="on" tls.cacert="/etc/pki/tls/certs/ca-bundle.crt" tls.tlsversion="TLSv1.3" tls.keyexchangegroups="X25519MLKEM768:X25519") YAML usage ---------- .. code-block:: yaml actions: - type: omelasticsearch usehttps: "on" tls.cacert: "/etc/pki/tls/certs/ca-bundle.crt" tls.tlsversion: "TLSv1.3" tls.keyexchangegroups: "X25519MLKEM768:X25519" See also -------- See also :doc:`../../configuration/modules/omelasticsearch`, :ref:`param-omelasticsearch-tls-tlsversion`, :ref:`param-omelasticsearch-tls-ciphersuites`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-preservecase.rst0000644000000000000000000000013215241075234025243 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.725580541 30 ctime=1787067792.509689927 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-preservecase.rst0000664000175000017500000000242715241075234024714 0ustar00rgerrger.. _param-imtcp-preservecase: .. _imtcp.parameter.module.preservecase: .. _imtcp.parameter.input.preservecase: PreserveCase ============ .. index:: single: imtcp; PreserveCase single: PreserveCase .. summary-start Controls whether the case of fromhost is preserved. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: PreserveCase :Scope: module, input :Type: boolean :Default: module=on, input=module parameter :Required?: no :Introduced: 8.37.0 Description ----------- This parameter controls the case in ``fromhost``. If ``PreserveCase`` is set to "off", rsyslog normalizes the resolved host name to lowercase, e.g., ``host1.example.org`` when the message was received from ``Host1.Example.Org``. The default is "on" for backward compatibility. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-preservecase: .. _imtcp.parameter.module.preservecase-usage: .. code-block:: rsyslog module(load="imtcp" preserveCase="off") Input usage ----------- .. _param-imtcp-input-preservecase: .. _imtcp.parameter.input.preservecase-usage: .. code-block:: rsyslog input(type="imtcp" port="514" preserveCase="off") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/immark-use-markflag.rst0000644000000000000000000000013115132733117025275 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.309468239 29 ctime=1787067792.25868525 rsyslog-8.2608.0/doc/source/reference/parameters/immark-use-markflag.rst0000666000175000017500000000214115132733117024742 0ustar00rgerrger.. _param-immark-use-markflag: .. _immark.parameter.module.use-markflag: use.markFlag ============= .. index:: single: immark; use.markFlag single: use.markFlag .. summary-start Controls whether emitted mark messages carry the ``MARK`` flag bit. .. summary-end This parameter applies to :doc:`../../configuration/modules/immark`. :Name: use.markFlag :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: 8.2012.0 Description ----------- When enabled, immark tags generated messages with the ``MARK`` flag. This allows actions to filter or suppress them via settings such as the ``action.writeAllMarkMessages`` parameter in :doc:`../../configuration/actions`. Disable the flag when mark messages should be treated exactly like ordinary log entries. Module usage ------------ .. _immark.parameter.module.use-markflag-usage: .. code-block:: rsyslog module(load="immark" use.markFlag="off") See also -------- .. seealso:: * :ref:`param-immark-interval` * :doc:`../../configuration/modules/immark` * ``action.writeAllMarkMessages`` in :doc:`../../configuration/actions` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-ratelimit-burst.rst0000644000000000000000000000013215132733117025703 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.196484775 30 ctime=1787067792.512689983 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-ratelimit-burst.rst0000666000175000017500000000152515132733117025354 0ustar00rgerrger.. _param-imtcp-ratelimit-burst: .. _imtcp.parameter.input.ratelimit-burst: RateLimit.Burst =============== .. index:: single: imtcp; RateLimit.Burst single: RateLimit.Burst .. summary-start Defines the maximum number of messages allowed per rate-limit interval. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: RateLimit.Burst :Scope: input :Type: integer :Default: input=10000 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies the rate-limiting burst in number of messages. Default is ``10,000``. Input usage ----------- .. _param-imtcp-input-ratelimit-burst: .. _imtcp.parameter.input.ratelimit-burst-usage: .. code-block:: rsyslog input(type="imtcp" rateLimit.Burst="20000") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-template.rst0000644000000000000000000000013215132733117024555 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.774439623 30 ctime=1787067793.012699301 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-template.rst0000666000175000017500000000256715132733117024235 0ustar00rgerrger.. _param-omdtls-template: .. _omdtls.parameter.module.template: .. _omdtls.parameter.input.template: template ======== .. index:: single: omdtls; template single: template .. summary-start Selects the template used to format messages sent through omdtls actions. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: template :Scope: module, input :Type: word :Default: module=none, input=RSYSLOG_FileFormat :Required?: no :Introduced: v8.2402.0 Description ----------- Selects the template that formats messages for omdtls actions. If an action does not specify this parameter, it uses ``RSYSLOG_FileFormat``. The module parameter is defined for compatibility but is currently ignored. The module has always defaulted actions to ``RSYSLOG_FileFormat`` (see ``plugins/omdtls/omdtls.c``), even though earlier documentation mentioned ``RSYSLOG_TraditionalForwardFormat``. Update existing configurations only if you require a different template. Module usage ------------ .. _omdtls.parameter.module.template-usage: .. code-block:: rsyslog module(load="omdtls" template="ForwardingTemplate") Input usage ----------- .. _omdtls.parameter.input.template-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" template="ForwardingTemplate") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-tls-cacert.rst0000644000000000000000000000013215132733117025014 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.299468053 30 ctime=1787067793.310704854 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-tls-cacert.rst0000666000175000017500000000152115132733117024461 0ustar00rgerrger.. _param-omhttp-tls-cacert: .. _omhttp.parameter.input.tls-cacert: tls.cacert ========== .. index:: single: omhttp; tls.cacert single: tls.cacert .. summary-start Points omhttp to the CA bundle used to verify HTTPS servers. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: tls.cacert :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- This parameter sets the path to the Certificate Authority (CA) bundle. Expects ``.pem`` format. Input usage ----------- .. _omhttp.parameter.input.tls-cacert-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" tlsCaCert="/etc/ssl/certs/ca-bundle.pem" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmdarwin-response.rst0000644000000000000000000000013215145046112025110 xustar0030 mtime=1771326538.944012737 30 atime=1787067672.114445962 30 ctime=1787067792.751694437 rsyslog-8.2608.0/doc/source/reference/parameters/mmdarwin-response.rst0000664000175000017500000000314415145046112024556 0ustar00rgerrger.. _param-mmdarwin-response: .. _mmdarwin.parameter.input.response: response ======== .. index:: single: mmdarwin; response single: response .. summary-start Controls whether Darwin returns a score, forwards data, or does both. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmdarwin`. :Name: response :Scope: input :Type: word :Default: input="no" :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Tells the Darwin filter what to do next: * ``"no"``: no response will be sent, nothing will be sent to next filter. * ``"back"``: a score for the input will be returned by the filter, nothing will be forwarded to the next filter. * ``"darwin"``: the data provided will be forwarded to the next filter (in the format specified in the filter's configuration), no response will be given to mmdarwin. * ``"both"``: the filter will respond to mmdarwin with the input's score AND forward the data (in the format specified in the filter's configuration) to the next filter. .. note:: Please be mindful when setting this parameter, as the called filter will only forward data to the next configured filter if you ask the filter to do so with ``"darwin"`` or ``"both"``. If a next filter is configured but you ask for a ``"back"`` response, the next filter **WILL NOT** receive anything! Input usage ----------- .. _param-mmdarwin-input-response-usage: .. _mmdarwin.parameter.input.response-usage: .. code-block:: rsyslog action(type="mmdarwin" response="both") See also -------- See also :doc:`../../configuration/modules/mmdarwin`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhdfs-omhdfsport.rst0000644000000000000000000000013215145046112025101 xustar0030 mtime=1771326538.945012754 30 atime=1787067672.941461379 30 ctime=1787067793.226703289 rsyslog-8.2608.0/doc/source/reference/parameters/omhdfs-omhdfsport.rst0000664000175000017500000000221615145046112024546 0ustar00rgerrger.. _param-omhdfs-omhdfsport: .. _omhdfs.parameter.module.omhdfsport: omhdfsPort ========== .. index:: single: omhdfs; omhdfsPort single: omhdfsPort .. summary-start Specifies the TCP port number used to reach the configured HDFS host. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhdfs`. :Name: omhdfsPort :Scope: module :Type: integer :Default: 0 :Required?: no :Introduced: Not documented Description ----------- Port on which to connect to the HDFS host. Module usage ------------ .. _omhdfs.parameter.module.omhdfsport-usage: .. code-block:: text $ModLoad omhdfs $omhdfsHost hdfs01.example.net $omhdfsPort 8020 $omhdfsFileName /var/log/hdfs/system.log # write all messages to the specified HDFS host and port *.* :omhdfs: Legacy names (for reference) ---------------------------- Historic names/directives for compatibility. Do not use in new configs. .. _omhdfs.parameter.legacy.omhdfsport: - ``$OMHDFSPort`` — maps to ``omhdfsPort`` (status: legacy) .. index:: single: omhdfs; $OMHDFSPort single: $OMHDFSPort See also -------- See also :doc:`../../configuration/modules/omhdfs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-inotifyfallbackinterval.rst0000644000000000000000000000013215145046112027607 xustar0030 mtime=1771326538.939012655 30 atime=1787067672.368450697 30 ctime=1787067792.077681877 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-inotifyfallbackinterval.rst0000664000175000017500000000222515145046112027254 0ustar00rgerrger.. _param-imfile-inotifyfallbackinterval: .. _imfile.parameter.module.inotifyfallbackinterval: .. _imfile.parameter.inotifyfallbackinterval: inotifyFallbackInterval ======================= .. index:: single: imfile; inotifyFallbackInterval single: inotifyFallbackInterval .. summary-start Sets the interval in seconds for fallback rescans when imfile cannot add inotify watches. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: inotifyFallbackInterval :Scope: module :Type: integer :Default: module=60 :Required?: no :Introduced: 8.2602.0 Description ----------- When imfile runs in inotify mode and cannot allocate new watches (for example, because the module limit or the system limit was reached), it switches to periodic rescans to discover changes and retry arming watches. This parameter controls the rescan interval in seconds. Set it to ``0`` to disable fallback rescans. Module usage ------------ .. _imfile.parameter.module.inotifyfallbackinterval-usage: .. code-block:: rsyslog module(load="imfile" inotifyFallbackInterval="60") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-persiststateinterval.rst0000644000000000000000000000013115132411300027721 xustar0030 mtime=1768559296.195884517 29 atime=1787067672.83745944 30 ctime=1787067792.190683983 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-persiststateinterval.rst0000666000175000017500000000263015132411300027371 0ustar00rgerrger.. _param-imjournal-persiststateinterval: .. _imjournal.parameter.module.persiststateinterval: .. meta:: :tag: module:imjournal :tag: parameter:PersistStateInterval PersistStateInterval ==================== .. index:: single: imjournal; PersistStateInterval single: PersistStateInterval .. summary-start Saves the journal cursor after every N messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: PersistStateInterval :Scope: module :Type: integer :Default: module=10 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines how often the module writes its position in the journal to the state file. The cursor is saved after each ``PersistStateInterval`` messages so rsyslog resumes from the last processed entry on restart. Module usage ------------ .. _param-imjournal-module-persiststateinterval: .. _imjournal.parameter.module.persiststateinterval-usage: .. code-block:: rsyslog module(load="imjournal" PersistStateInterval="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournalpersiststateinterval: - $imjournalPersistStateInterval — maps to PersistStateInterval (status: legacy) .. index:: single: imjournal; $imjournalPersistStateInterval single: $imjournalPersistStateInterval See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-checkextendedkeypurpo0000644000000000000000000000013215132733117031047 xustar0030 mtime=1768666703.909620269 30 atime=1787067673.929479797 30 ctime=1787067792.531690337 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-checkextendedkeypurpose.rst0000666000175000017500000000301715132733117031655 0ustar00rgerrger.. _param-imtcp-streamdriver-checkextendedkeypurpose: .. _imtcp.parameter.module.streamdriver-checkextendedkeypurpose: .. _imtcp.parameter.input.streamdriver-checkextendedkeypurpose: streamDriver.checkExtendedKeyPurpose ==================================== .. index:: single: imtcp; StreamDriver.checkExtendedKeyPurpose single: StreamDriver.checkExtendedKeyPurpose .. summary-start Checks certificate extended key purpose for compatibility with rsyslog operation. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: StreamDriver.checkExtendedKeyPurpose :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Whether to check also purpose value in extended fields part of certificate for compatibility with rsyslog operation. (driver-specific) The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-streamdriver-checkextendedkeypurpose: .. _imtcp.parameter.module.streamdriver-checkextendedkeypurpose-usage: .. code-block:: rsyslog module(load="imtcp" streamDriver.checkExtendedKeyPurpose="on") Input usage ----------- .. _param-imtcp-input-streamdriver-checkextendedkeypurpose: .. _imtcp.parameter.input.streamdriver-checkextendedkeypurpose-usage: .. code-block:: rsyslog input(type="imtcp" port="514" streamDriver.checkExtendedKeyPurpose="on") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-permit-slashesinhostname.rst0000644000000000000000000000013215132411300030076 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.306449541 30 ctime=1787067793.617710575 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-permit-slashesinhostname.rst0000666000175000017500000000210515132411300027542 0ustar00rgerrger.. _param-pmrfc3164-permit-slashesinhostname: .. _pmrfc3164.parameter.module.permit-slashesinhostname: .. _pmrfc3164.parameter.module.permit.slashesInHostname: permit.slashesInHostname ======================== .. index:: single: pmrfc3164; permit.slashesInHostname single: permit.slashesInHostname .. summary-start Allow ``/`` in hostnames, useful for syslog-ng relay chains. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: permit.slashesInHostname :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.20.0 Description ----------- This option allows hostnames to include slash characters. Module usage ------------ .. _param-pmrfc3164-module-permit-slashesinhostname: .. _pmrfc3164.parameter.module.permit-slashesinhostname-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" permit.slashesInHostname="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-keepalive-probes.rst0000644000000000000000000000013215216464435026330 xustar0030 mtime=1782212893.981265456 30 atime=1787067671.763439418 30 ctime=1787067791.333668012 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-keepalive-probes.rst0000664000175000017500000000175515216464435026004 0ustar00rgerrger.. _param-imbeats-keepalive-probes: .. _imbeats.parameter.input.keepalive-probes: KeepAlive.Probes ================ .. meta:: :description: TCP keepalive probe count for imbeats sessions. :keywords: rsyslog, imbeats, keepalive probes .. index:: single: imbeats; KeepAlive.Probes single: KeepAlive.Probes .. summary-start Set how many TCP keepalive probes are sent before the peer is considered dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: KeepAlive.Probes :Scope: input :Type: integer :Default: input=system default :Required?: no :Introduced: 8.2604.0 Description ----------- Set how many TCP keepalive probes are sent before the peer is considered dead. Input usage ----------- .. _param-imbeats-input-keepalive-probes: .. _imbeats.parameter.input.keepalive-probes-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" keepAlive.probes="5") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-template.rst0000644000000000000000000000013115132733117024555 xustar0030 mtime=1768666703.920620435 30 atime=1787067673.051463429 29 ctime=1787067793.47470791 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-template.rst0000666000175000017500000000153315132733117024226 0ustar00rgerrger.. _param-omprog-template: .. _omprog.parameter.action.template: template ======== .. index:: single: omprog; template single: template .. summary-start Sets the template for formatting messages sent to the program. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: template :Scope: action :Type: word :Default: action=RSYSLOG_FileFormat :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Name of the :doc:`template <../../configuration/templates>` to use to format the log messages passed to the external program. Action usage ------------ .. _param-omprog-action-template: .. _omprog.parameter.action.template-usage: .. code-block:: rsyslog action(type="omprog" template="RSYSLOG_FileFormat") See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-persiststateinterval.rst0000644000000000000000000000013215132733117027204 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.393451163 30 ctime=1787067792.095682213 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-persiststateinterval.rst0000666000175000017500000000350315132733117026653 0ustar00rgerrger.. _param-imfile-persiststateinterval: .. _imfile.parameter.input.persiststateinterval: .. _imfile.parameter.persiststateinterval: PersistStateInterval ==================== .. index:: single: imfile; PersistStateInterval single: PersistStateInterval .. summary-start Controls how often the state file is written based on processed line count. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: PersistStateInterval :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Specifies how often the state file is written when processing the input file. A value of ``0`` means the state file is written when the monitored file is closed, typically at rsyslog shutdown. Any other value ``n`` causes the state file to be written after at least every ``n`` processed lines. This setting can guard against message duplication due to fatal errors but may reduce performance if set to a low value. Rsyslog may write state files more frequently if needed. **Note: If this parameter is not set, state files are not created.** Input usage ----------- .. _param-imfile-input-persiststateinterval: .. _imfile.parameter.input.persiststateinterval-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" PersistStateInterval="0") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilepersiststateinterval: - ``$InputFilePersistStateInterval`` — maps to PersistStateInterval (status: legacy) .. index:: single: imfile; $InputFilePersistStateInterval single: $InputFilePersistStateInterval See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-output.rst0000644000000000000000000000013115132733117025153 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.284449131 29 ctime=1787067792.77869494 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-output.rst0000666000175000017500000000271115132733117024623 0ustar00rgerrger.. _param-mmexternal-output: .. _mmexternal.parameter.input.output: output ====== .. index:: single: mmexternal; output single: output .. summary-start Writes the external plugin's standard output and standard error to a helper log file for debugging. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: output :Scope: input :Type: string :Default: none :Required?: no :Introduced: 8.3.0 Description ----------- This is a debug aid. If set, this is a filename where the combined standard output and standard error stream from the plugin is logged before rsyslog parses it as a JSON response. Note that the output is also being processed as usual by rsyslog. Setting this parameter thus gives insight into the internal processing that happens between plugin and rsyslog core. .. warning:: The external program's standard error stream is captured together with standard output. Any data written to stderr is intermingled with the JSON response from stdout and will likely cause parsing failures. Ensure the external program does not write to stderr. Input usage ----------- .. _param-mmexternal-input-output: .. _mmexternal.parameter.input.output-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/mmexternal.py" output="/var/log/mmexternal-debug.log" ) See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-gnutlsprioritystring.rst0000644000000000000000000000013215171370365027126 xustar0030 mtime=1776677109.117908084 30 atime=1787067673.977480692 30 ctime=1787067792.475689294 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-gnutlsprioritystring.rst0000664000175000017500000001104415171370365026572 0ustar00rgerrger.. _param-imtcp-gnutlsprioritystring: .. _imtcp.parameter.module.gnutlsprioritystring: .. _imtcp.parameter.input.gnutlsprioritystring: gnutlsPriorityString ==================== .. index:: single: imtcp; gnutlsPriorityString single: gnutlsPriorityString .. summary-start Provides driver-specific TLS configuration via a priority string. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: gnutlsPriorityString :Scope: module, input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module=none, input=module parameter :Required?: no :Introduced: 8.29.0 Description ----------- The "gnutls priority string" parameter in rsyslog offers enhanced customization for secure communications, allowing detailed configuration of TLS driver properties. This includes specifying handshake algorithms and other settings for GnuTLS, as well as implementing OpenSSL configuration commands. Initially developed for GnuTLS, the "gnutls priority string" has evolved since version v8.1905.0 to also support OpenSSL, broadening its application and utility in network security configurations. This update signifies a key advancement in rsyslog's capabilities, making the "gnutls priority string" an essential feature for advanced TLS configuration. .. versionadded:: 8.29.0 **Configuring Driver-Specific Properties** This configuration string is used to set properties specific to different drivers. Originally designed for the GnuTLS driver, it has been extended to support OpenSSL configuration commands from version v8.1905.0 onwards. **GNUTLS Configuration** In GNUTLS, this setting determines the handshake algorithms and options for the TLS session. It's designed to allow user overrides of the library's default settings. If you leave this parameter unset (NULL), the system will revert to the default settings. For more detailed information on priority strings in GNUTLS, you can refer to the GnuTLS Priority Strings Documentation available at [GnuTLS Website](https://gnutls.org/manual/html_node/Priority-Strings.html). **OpenSSL Configuration** This feature is compatible with OpenSSL Version 1.0.2 and above. It enables the passing of configuration commands to the OpenSSL library. You can find a comprehensive list of commands and their acceptable values in the `OpenSSL Documentation `_. **Native post-quantum usage** Native post-quantum TLS is supported only on distro and library combinations that already ship it in their regular OpenSSL or GnuTLS packages. Rsyslog does not currently add provider-specific compatibility for older distro versions. At the time this support was added, the intended native baselines were Fedora 43 or newer and Debian 13 or newer for OpenSSL 3.5-based hybrid groups, with GnuTLS hybrid support available on supported native GnuTLS builds. **General Configuration Guidelines** The configuration can be formatted as a single line or across multiple lines. Each command within the configuration is separated by a linefeed (``\n``). To differentiate between a command and its corresponding value, use an equal sign (``=``). Below are some examples to guide you in formatting these commands. Example 1 --------- This will allow all protocols except for SSLv2 and SSLv3: .. code-block:: none gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3" Example 2 --------- This will allow all protocols except for SSLv2, SSLv3 and TLSv1. It will also set the minimum protocol to TLSv1.2 .. code-block:: none gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1 MinProtocol=TLSv1.2" Example 3 --------- Native OpenSSL hybrid post-quantum TLS on supported distro versions: .. code-block:: none gnutlsPriorityString="MinProtocol=TLSv1.3 MaxProtocol=TLSv1.3 Groups=X25519MLKEM768" Example 4 --------- Native GnuTLS hybrid post-quantum TLS on supported distro versions: .. code-block:: none gnutlsPriorityString="NORMAL:-GROUP-ALL:+GROUP-X25519-MLKEM768:+GROUP-X25519" The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-gnutlsprioritystring: .. _imtcp.parameter.module.gnutlsprioritystring-usage: .. code-block:: rsyslog module(load="imtcp" gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3") Input usage ----------- .. _param-imtcp-input-gnutlsprioritystring: .. _imtcp.parameter.input.gnutlsprioritystring-usage: .. code-block:: rsyslog input(type="imtcp" port="514" gnutlsPriorityString="Protocol=ALL,-SSLv2,-SSLv3") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-rotation-sizelimit.rst0000644000000000000000000000013215132411300026544 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.496453083 30 ctime=1787067793.192702655 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-rotation-sizelimit.rst0000666000175000017500000000335315132411300026216 0ustar00rgerrger.. _param-omfile-rotation-sizelimit: .. _omfile.parameter.module.rotation-sizelimit: rotation.sizeLimit ================== .. index:: single: omfile; rotation.sizeLimit single: rotation.sizeLimit .. summary-start This permits to set a size limit on the output file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: rotation.sizeLimit :Scope: action :Type: size :Default: action=0 (disabled) :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This permits to set a size limit on the output file. When the limit is reached, rotation of the file is tried. The rotation script needs to be configured via `rotation.sizeLimitCommand`. Please note that the size limit is not exact. Some excess bytes are permitted to prevent messages from being split across two files. Also, a full batch of messages is not terminated in between. As such, in practice, the size of the output file can grow some KiB larger than configured. Also avoid to configure a too-low limit, especially for busy files. Calling the rotation script is relatively performance intense. As such, it could negatively affect overall rsyslog performance. Action usage ------------ .. _param-omfile-action-rotation-sizelimit: .. _omfile.parameter.action.rotation-sizelimit: .. code-block:: rsyslog action(type="omfile" rotation.sizeLimit="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.outchannel: - $outchannel — maps to rotation.sizeLimit (status: legacy) .. index:: single: omfile; $outchannel single: $outchannel See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-escapelf-replacement.rst0000644000000000000000000000013115132733117026763 xustar0030 mtime=1768666703.903620178 29 atime=1787067672.41745161 30 ctime=1787067792.059681542 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-escapelf-replacement.rst0000666000175000017500000000245015132733117026433 0ustar00rgerrger.. _param-imfile-escapelf-replacement: .. _imfile.parameter.input.escapelf-replacement: .. _imfile.parameter.escapelf-replacement: escapeLF.replacement ==================== .. index:: single: imfile; escapeLF.replacement single: escapeLF.replacement .. summary-start Overrides the default LF escape sequence when ``escapeLF`` is ``on``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: escapeLF.replacement :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: depending on use :Required?: no :Introduced: 8.2001.0 Description ----------- Works together with ``escapeLF``. It is honored only if ``escapeLF="on"``. It permits replacing the default escape sequence, which historically may be ``#012`` or ``\n``. If not configured, that default remains. Examples: .. code-block:: rsyslog escapeLF.replacement=" " escapeLF.replacement="[LF]" escapeLF.replacement="" Input usage ----------- .. _param-imfile-input-escapelf-replacement: .. _imfile.parameter.input.escapelf-replacement-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" escapeLF="on" escapeLF.replacement="[LF]") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-subject-template.rst0000644000000000000000000000013215132733117026166 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.904460689 30 ctime=1787067793.402706569 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-subject-template.rst0000666000175000017500000000322115132733117025632 0ustar00rgerrger.. _param-ommail-subject-template: .. _ommail.parameter.input.subject-template: subjectTemplate ================ .. index:: single: ommail; subjectTemplate single: subjectTemplate .. summary-start Selects the template used to generate the mail subject line. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: subjectTemplate :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: 8.5.0 Description ----------- The name of the template to be used as the mail subject. Use this parameter when message content should appear in the subject. If you just need a constant subject line, use :ref:`param-ommail-subject-text` instead. The ``subjectTemplate`` and ``subjectText`` parameters cannot both be configured within a single action. If neither is specified, a default, non-configurable subject line will be generated. Input usage ------------ .. _ommail.parameter.input.subject-template-usage: .. code-block:: rsyslog module(load="ommail") template(name="mailSubject" type="string" string="Alert: %msg%") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" subjectTemplate="mailSubject" ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailsubject: - $ActionMailSubject — maps to subjectTemplate (status: legacy) .. index:: single: ommail; $ActionMailSubject single: $ActionMailSubject See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-compression-maxdecompressedbytespe0000644000000000000000000000031115216464435031071 xustar00111 path=rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-maxdecompressedbytesperreceive.rst 30 mtime=1782212893.985265521 30 atime=1787067674.070482425 30 ctime=1787067792.459688995 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-maxdecompressedbytesperreceive.rs0000664000175000017500000000363615216464435032716 0ustar00rgerrger.. _param-imtcp-compression-maxdecompressedbytesperreceive: .. _imtcp.parameter.input.compression-maxdecompressedbytesperreceive: .. meta:: :description: Reference for the imtcp compression.maxDecompressedBytesPerReceive input parameter. :keywords: rsyslog, imtcp, compression.maxDecompressedBytesPerReceive, stream compression, decompression, security compression.maxDecompressedBytesPerReceive ========================================== .. index:: single: imtcp; compression.maxDecompressedBytesPerReceive single: compression.maxDecompressedBytesPerReceive .. summary-start Limits decompressed bytes accepted from one compressed TCP receive operation. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: compression.maxDecompressedBytesPerReceive :Scope: input/module :Type: integer :Default: input=67108864 :Required?: no :Introduced: 8.2606.0 Description ----------- ``compression.maxDecompressedBytesPerReceive`` limits how many decompressed bytes ``imtcp`` accepts from one compressed TCP receive operation when ``compression.mode="stream:always"`` is enabled. The default is 64 MiB. If the limit is exceeded, ``imtcp`` logs the compressed stream as invalid and closes the session. Already accepted data from earlier receive operations is not affected. Set the value to ``0`` to disable this limit for tightly controlled deployments that need a larger decompression burst. Input usage ----------- .. _param-imtcp-input-compression-maxdecompressedbytesperreceive: .. _imtcp.parameter.input.compression-maxdecompressedbytesperreceive-usage: .. code-block:: rsyslog input( type="imtcp" port="514" compression.mode="stream:always" compression.maxDecompressedBytesPerReceive="134217728" ) See also -------- See also :ref:`param-imtcp-compression-mode`, :ref:`param-imtcp-compression-maxexpansionratio`, and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-escapelf.rst0000644000000000000000000000013115132733117024466 xustar0030 mtime=1768666703.903620178 29 atime=1787067672.41045148 30 ctime=1787067792.062681598 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-escapelf.rst0000666000175000017500000000232215132733117024134 0ustar00rgerrger.. _param-imfile-escapelf: .. _imfile.parameter.input.escapelf: .. _imfile.parameter.escapelf: escapeLF ======== .. index:: single: imfile; escapeLF single: escapeLF .. summary-start Escapes embedded LF characters in multi-line messages as ``#012`` when enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: escapeLF :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Only meaningful when multi-line messages are processed. LF characters inside messages cause issues with many tools. If set to ``on``, LF characters are escaped to the sequence ``#012``. By default escaping is enabled. If turned off, test carefully. When using plain TCP syslog with embedded LFs, enable octet-counted framing. Input usage ----------- .. _param-imfile-input-escapelf: .. _imfile.parameter.input.escapelf-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" escapeLF="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-ratelimit-burst.rst0000644000000000000000000000013115132733117026101 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.932461211 30 ctime=1787067793.278704258 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-ratelimit-burst.rst0000666000175000017500000000205015132733117025545 0ustar00rgerrger.. _param-omhttp-ratelimit-burst: .. _omhttp.parameter.input.ratelimit-burst: ratelimit.burst =============== .. index:: single: omhttp; ratelimit.burst single: ratelimit.burst .. summary-start Sets how many messages the retry ruleset may emit within each rate-limiting window. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: ratelimit.burst :Scope: input :Type: integer :Default: input=20000 :Required?: no :Introduced: Not specified Description ----------- This parameter sets the rate limiting behavior for the :ref:`param-omhttp-retry-ruleset`. It specifies the maximum number of messages that can be emitted within the :ref:`param-omhttp-ratelimit-interval` interval. For further information, see the description there. Input usage ----------- .. _omhttp.parameter.input.ratelimit-burst-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" retry="on" rateLimitBurst="1000" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-ruleset.rst0000644000000000000000000000013215216464435024776 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.474471315 30 ctime=1787067792.310686219 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-ruleset.rst0000664000175000017500000000173115216464435024444 0ustar00rgerrger.. _param-impstats-ruleset: .. _impstats.parameter.module.ruleset: ruleset ======= .. index:: single: impstats; ruleset single: ruleset .. summary-start Binds impstats-generated messages to the specified ruleset for further processing. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: ruleset :Scope: module :Type: string :Default: module=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Binds the listener to a specific :doc:`ruleset <../../concepts/multi_ruleset>`. **Note** that setting ``ruleset`` and setting :ref:`param-impstats-log-syslog` (``log.syslog``) to ``off`` are mutually exclusive because syslog stream processing must be enabled to use a ruleset. Module usage ------------ .. _impstats.parameter.module.ruleset-usage: .. code-block:: rsyslog module(load="impstats" ruleset="impstatsRules") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-ignoreolderthan.rst0000644000000000000000000000013215132733117026071 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.511453362 30 ctime=1787067792.070681747 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-ignoreolderthan.rst0000666000175000017500000000206715132733117025544 0ustar00rgerrger.. _param-imfile-ignoreolderthan: .. _imfile.parameter.input.ignoreolderthan: .. _imfile.parameter.ignoreolderthan: ignoreOlderThan =============== .. index:: single: imfile; ignoreOlderThan single: ignoreOlderThan .. summary-start Ignores newly discovered files older than the specified number of seconds. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: ignoreOlderThan :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: 8.2108.0 Description ----------- Instructs imfile to ignore a discovered file that has not been modified in the given number of seconds. Once the file is discovered, it is no longer ignored and new data will be read. The default ``0`` disables this option. Input usage ----------- .. _param-imfile-input-ignoreolderthan: .. _imfile.parameter.input.ignoreolderthan-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" ignoreOlderThan="0") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-ruleset.rst0000644000000000000000000000013215132733117024413 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.854478399 30 ctime=1787067792.422688306 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-ruleset.rst0000666000175000017500000000217315132733117024064 0ustar00rgerrger.. _param-imrelp-ruleset: .. _imrelp.parameter.module.ruleset: ruleset ======= .. index:: single: imrelp; ruleset single: ruleset .. summary-start Assigns a ruleset to all RELP listeners created by the module instance. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: ruleset :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 7.5.0 Description ----------- Binds the specified ruleset to **all** RELP listeners. This can be overridden at the instance level. Module usage ------------ .. _param-imrelp-module-ruleset-usage: .. _imrelp.parameter.module.ruleset-usage: .. code-block:: rsyslog module(load="imrelp" ruleset="relpRuleset") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imrelp.parameter.legacy.inputrelpserverbindruleset: - $InputRELPServerBindRuleset — maps to ruleset (status: legacy) .. index:: single: imrelp; $InputRELPServerBindRuleset single: $InputRELPServerBindRuleset See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-keepalive-probes.rst0000644000000000000000000000013215132733117026171 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.717475845 30 ctime=1787067792.348686927 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-keepalive-probes.rst0000666000175000017500000000271015132733117025637 0ustar00rgerrger.. _param-imptcp-keepalive-probes: .. _imptcp.parameter.input.keepalive-probes: KeepAlive.Probes ================ .. index:: single: imptcp; KeepAlive.Probes single: KeepAlive.Probes .. summary-start Sets the number of unacknowledged keepalive probes before the connection is considered dead. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: KeepAlive.Probes :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- The number of unacknowledged probes to send before considering the connection dead and notifying the application layer. The default, 0, means that the operating system defaults are used. This has only effect if keep-alive is enabled. The functionality may not be available on all platforms. Input usage ----------- .. _param-imptcp-input-keepalive-probes: .. _imptcp.parameter.input.keepalive-probes-usage: .. code-block:: rsyslog input(type="imptcp" keepAlive.probes="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverkeepalive_probes: - $InputPTCPServerKeepAlive_probes — maps to KeepAlive.Probes (status: legacy) .. index:: single: imptcp; $InputPTCPServerKeepAlive_probes single: $InputPTCPServerKeepAlive_probes See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-enable.rst0000644000000000000000000000013215132733117025033 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.818440443 30 ctime=1787067792.709693654 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-enable.rst0000666000175000017500000000153715132733117024507 0ustar00rgerrger.. _param-mmanon-ipv4-enable: .. _mmanon.parameter.input.ipv4-enable: ipv4.enable =========== .. index:: single: mmanon; ipv4.enable single: ipv4.enable .. summary-start Enables or disables IPv4 address anonymization for the mmanon action. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.enable :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: 7.3.7 Description ----------- This parameter controls whether ``mmanon`` will attempt to find and anonymize IPv4 addresses. If set to ``off``, all other ``ipv4.*`` parameters for this action are ignored. Input usage ----------- .. _mmanon.parameter.input.ipv4-enable-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.enable="off") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-forcesingleinstance.rst0000644000000000000000000000013215132733117026770 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.876460167 30 ctime=1787067793.461707668 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-forcesingleinstance.rst0000666000175000017500000000326315132733117026442 0ustar00rgerrger.. _param-omprog-forcesingleinstance: .. _omprog.parameter.action.forcesingleinstance: forceSingleInstance =================== .. index:: single: omprog; forceSingleInstance single: forceSingleInstance .. summary-start Runs only one instance of the program regardless of worker threads. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: forceSingleInstance :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: v8.1.6 Description ----------- By default, the omprog action will start an instance (process) of the external program per worker thread (the maximum number of worker threads can be specified with the :doc:`queue.workerThreads <../../rainerscript/queue_parameters>` parameter). Moreover, if the action is associated to a :doc:`disk-assisted queue <../../concepts/queues>`, an additional instance will be started when the queue is persisted, to process the items stored on disk. If you want to force a single instance of the program to be executed, regardless of the number of worker threads or the queue type, set this flag to "on". This is useful when the external program uses or accesses some kind of shared resource that does not allow concurrent access from multiple processes. .. note:: Before version v8.38.0, this parameter had no effect. Action usage ------------ .. _param-omprog-action-forcesingleinstance: .. _omprog.parameter.action.forcesingleinstance-usage: .. code-block:: rsyslog action(type="omprog" forceSingleInstance="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-ratelimit-severity.rst0000644000000000000000000000013215132733117027144 xustar0030 mtime=1768666703.910620284 30 atime=1787067674.139483712 30 ctime=1787067792.626692108 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-ratelimit-severity.rst0000666000175000017500000000244615132733117026620 0ustar00rgerrger.. _param-imuxsock-ratelimit-severity: .. _imuxsock.parameter.input.ratelimit-severity: RateLimit.Severity ================== .. index:: single: imuxsock; RateLimit.Severity single: RateLimit.Severity .. summary-start Defines the severity level at or below which messages are rate-limited. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: RateLimit.Severity :Scope: input :Type: integer :Default: input=1 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies the severity of messages that shall be rate-limited. .. seealso:: https://en.wikipedia.org/wiki/Syslog#Severity_level Input usage ----------- .. _param-imuxsock-input-ratelimit-severity: .. _imuxsock.parameter.input.ratelimit-severity-usage: .. code-block:: rsyslog input(type="imuxsock" rateLimit.severity="5") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.imuxsockratelimitseverity: - $IMUXSockRateLimitSeverity — maps to RateLimit.Severity (status: legacy) .. index:: single: imuxsock; $IMUXSockRateLimitSeverity single: $IMUXSockRateLimitSeverity See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-allowunsignedcerts.rst0000644000000000000000000000013215132411300030505 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.166446931 30 ctime=1787067793.025699543 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-allowunsignedcerts.rst0000666000175000017500000000170315132411300030154 0ustar00rgerrger.. _param-omelasticsearch-allowunsignedcerts: .. _omelasticsearch.parameter.module.allowunsignedcerts: allowunsignedcerts ================== .. index:: single: omelasticsearch; allowunsignedcerts single: allowunsignedcerts .. summary-start Disable TLS peer verification (insecure, for testing only). .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: allowunsignedcerts :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Sets the curl `CURLOPT_SSL_VERIFYPEER` option to `0`. Strongly discouraged outside of testing. Action usage ------------ .. _param-omelasticsearch-action-allowunsignedcerts: .. _omelasticsearch.parameter.action.allowunsignedcerts: .. code-block:: rsyslog action(type="omelasticsearch" allowunsignedcerts="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-ruleset.rst0000644000000000000000000000013115132733117024416 xustar0030 mtime=1768666703.907620238 29 atime=1787067673.66947495 30 ctime=1787067792.383687579 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-ruleset.rst0000666000175000017500000000211715132733117024066 0ustar00rgerrger.. _param-imptcp-ruleset: .. _imptcp.parameter.input.ruleset: Ruleset ======= .. index:: single: imptcp; Ruleset single: Ruleset .. summary-start Binds the specified ruleset to this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Ruleset :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Binds specified ruleset to this input. If not set, the default ruleset is bound. Input usage ----------- .. _param-imptcp-input-ruleset: .. _imptcp.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imptcp" ruleset="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverbindruleset: - $InputPTCPServerBindRuleset — maps to Ruleset (status: legacy) .. index:: single: imptcp; $InputPTCPServerBindRuleset single: $InputPTCPServerBindRuleset See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-mainmsgqueuetimeoutshutdown.rst0000644000000000000000000000013215171370365030602 xustar0030 mtime=1776677109.116908069 30 atime=1787067672.032444433 30 ctime=1787067791.949679492 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-mainmsgqueuetimeoutshutdown.rst0000664000175000017500000000330315171370365030245 0ustar00rgerrger.. _param-imdiag-mainmsgqueuetimeoutshutdown: .. _imdiag.parameter.module.mainmsgqueuetimeoutshutdown: .. meta:: :description: Reference for the imdiag mainMsgQueueTimeoutShutdown module parameter. :keywords: rsyslog, imdiag, mainmsgqueuetimeoutshutdown, testbench, timeout, queue MainMsgQueueTimeoutShutdown ============================ .. index:: single: imdiag; MainMsgQueueTimeoutShutdown .. summary-start Sets the main message queue shutdown timeout at config load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: MainMsgQueueTimeoutShutdown :Scope: module :Type: integer (milliseconds) :Default: 10000 :Required?: no :Introduced: 8.x Description ----------- Sets ``globals.mainQ.iMainMsgQtoQShutdown`` — the time rsyslog waits for the main message queue to drain during an orderly shutdown — at config-load time. The testbench uses this to establish a safe default without relying on legacy ``$MainMsgQueueTimeoutShutdown`` directives, which are not available in YAML-only mode. The value can be overridden per-test by setting the ``RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT`` environment variable before calling ``generate_conf``, or by writing a ``$MainMsgQueueTimeoutShutdown`` directive in the test's RainerScript configuration fragment (legacy directives apply after module params and therefore take precedence). Module usage ------------ .. code-block:: rsyslog module(load="imdiag" mainMsgQueueTimeoutShutdown="10000") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" mainmsgqueuetimeoutshutdown: "10000" See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imjournal-ratelimit-interval.rst0000644000000000000000000000013215132411300027237 xustar0030 mtime=1768559296.195884517 30 atime=1787067672.848459645 30 ctime=1787067792.200684169 rsyslog-8.2608.0/doc/source/reference/parameters/imjournal-ratelimit-interval.rst0000666000175000017500000000300615132411300026704 0ustar00rgerrger.. _param-imjournal-ratelimit-interval: .. _imjournal.parameter.module.ratelimit-interval: .. meta:: :tag: module:imjournal :tag: parameter:Ratelimit.Interval Ratelimit.Interval ================== .. index:: single: imjournal; Ratelimit.Interval single: Ratelimit.Interval .. summary-start Time window in seconds for rate limiting; 0 disables the limit. .. summary-end This parameter applies to :doc:`../../configuration/modules/imjournal`. :Name: Ratelimit.Interval :Scope: module :Type: integer :Default: module=600 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Defines the interval over which message rate limiting is applied. If more than ``Ratelimit.Burst`` messages arrive during this interval, additional messages are silently discarded and a discard notice is emitted at the end of the interval. Module usage ------------ .. _param-imjournal-module-ratelimit-interval: .. _imjournal.parameter.module.ratelimit-interval-usage: .. code-block:: rsyslog module(load="imjournal" Ratelimit.Interval="...") Notes ----- - Setting the value to ``0`` disables rate limiting and is generally not recommended. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _imjournal.parameter.legacy.imjournalratelimitinterval: - $imjournalRatelimitInterval — maps to Ratelimit.Interval (status: legacy) .. index:: single: imjournal; $imjournalRatelimitInterval single: $imjournalRatelimitInterval See also -------- See also :doc:`../../configuration/modules/imjournal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omuxsock-socketname.rst0000644000000000000000000000013215132733117025441 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.066445067 30 ctime=1787067793.590710072 rsyslog-8.2608.0/doc/source/reference/parameters/omuxsock-socketname.rst0000666000175000017500000000317515132733117025115 0ustar00rgerrger.. _param-omuxsock-socketname: .. _omuxsock.parameter.module.socketname: socketName ========== .. index:: single: omuxsock; socketName single: socketName .. summary-start This is the name of the socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/omuxsock`. :Name: socketName :Scope: module, action :Type: string :Default: action=none :Required?: yes :Introduced: v8.2512 Description ----------- This is the name of the socket. There is no default. Every socket **must** be named. Module usage ------------ .. _param-omuxsock-module-socketname: .. _omuxsock.parameter.module.socketname-usage: A socketName set at the module level becomes the default socketName for the first unnamed action. It only applies to a single unnamed action, so it is primarily just a short-hand notation for when only a single omuxsock action is required. .. code-block:: rsyslog module(load="omuxsock" socketName="/tmp/socksample") Action usage ------------ .. _param-omuxsock-action-socketname: .. _omuxsock.parameter.action.socketname-usage: .. code-block:: rsyslog action(type="omuxsock" socketName="/tmp/socksample") .. note:: :ref:`param-omuxsock-socketname`, :ref:`param-omuxsock-abstract`, and :ref:`param-omuxsock-sockettype` constitute a logical configuration tuple. They are applied together as a whole tuple from a module level configuration to an action. Therefore, all three parameters must be explicitly specified in the action, or none may be specified in the action. In the latter case, the default is taken from the module. See also -------- See also :doc:`../../configuration/modules/omuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-oversizemode.rst0000644000000000000000000000013215132733117025443 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.974480636 30 ctime=1787067792.413688138 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-oversizemode.rst0000666000175000017500000000236215132733117025114 0ustar00rgerrger.. _param-imrelp-oversizemode: .. _imrelp.parameter.input.oversizemode: oversizeMode ============ .. index:: single: imrelp; oversizeMode single: oversizeMode .. summary-start Determines how messages larger than MaxDataSize are handled by the listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: oversizeMode :Scope: input :Type: string :Default: input=truncate :Required?: no :Introduced: 8.35.0 Description ----------- This parameter specifies how messages that are too long will be handled. For this parameter the length of the parameter :ref:`param-imrelp-maxdatasize` is used. - truncate: Messages will be truncated to the maximum message size. - abort: This is the behaviour until version 8.35.0. Upon receiving a message that is too long imrelp will abort. - accept: Messages will be accepted even if they are too long and an error message will be output. Using this option does have associated risks. Input usage ----------- .. _param-imrelp-input-oversizemode-usage: .. _imrelp.parameter.input.oversizemode-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" maxDataSize="10k" oversizeMode="truncate") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omgssapi-gssforwardservicename.rst0000644000000000000000000000013215132733117027665 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.877460186 30 ctime=1787067793.212703028 rsyslog-8.2608.0/doc/source/reference/parameters/omgssapi-gssforwardservicename.rst0000666000175000017500000000316315132733117027336 0ustar00rgerrger.. _param-omgssapi-gssforwardservicename: .. _omgssapi.parameter.module.gssforwardservicename: GssForwardServiceName ===================== .. index:: single: omgssapi; GssForwardServiceName single: GssForwardServiceName .. summary-start Sets the Kerberos service principal base name used when omgssapi establishes a GSSAPI-secured forwarding session. .. summary-end This parameter applies to :doc:`../../configuration/modules/omgssapi`. :Name: GssForwardServiceName :Scope: module :Type: string :Default: host :Required?: no :Introduced: 1.21.2 Description ----------- Specifies the service name used by the client when forwarding GSS-API wrapped messages. If unset, the module uses ``host`` as the base name. The actual service principal is constructed by appending ``@`` and the hostname that follows the ``:omgssapi:`` selector in legacy configurations. In legacy syntax this is configured with ``$GssForwardServiceName rsyslog``. Module usage ------------ .. _param-omgssapi-module-gssforwardservicename: .. _omgssapi.parameter.module.gssforwardservicename-usage: .. code-block:: rsyslog module(load="omgssapi" gssForwardServiceName="rsyslog") action(type="omgssapi" target="receiver.mydomain.com") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omgssapi.parameter.legacy.gssforwardservicename: - $GssForwardServiceName — maps to GssForwardServiceName (status: legacy) .. index:: single: omgssapi; $GssForwardServiceName single: $GssForwardServiceName See also -------- See also :doc:`../../configuration/modules/omgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-mode.rst0000644000000000000000000000013215216464435023651 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.827459254 30 ctime=1787067793.393706401 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-mode.rst0000664000175000017500000000166015216464435023320 0ustar00rgerrger.. _param-ommail-mode: .. _ommail.parameter.input.mode: mode ==== .. index:: single: ommail; mode single: mode .. summary-start Selects whether ommail sends mail directly via SMTP or through a sendmail-compatible local submission program. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: mode :Scope: input :Type: word :Default: input=smtp :Required?: no :Introduced: 8.2606.0 Description ----------- Use ``smtp`` to let ommail talk directly to an SMTP server. Use ``sendmail`` to invoke a sendmail-compatible binary and write the mail message to its standard input. Input usage ----------- .. _ommail.parameter.input.mode-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" mode="sendmail" mailFrom="rsyslog@example.net" mailTo="operator@example.net" ) See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-sendmail-binary.rst0000644000000000000000000000013215216464435026003 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.870460055 30 ctime=1787067793.398706494 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-sendmail-binary.rst0000664000175000017500000000227615216464435025456 0ustar00rgerrger.. _param-ommail-sendmail-binary: .. _ommail.parameter.input.sendmail-binary: sendmail.binary =============== .. index:: single: ommail; sendmail.binary single: sendmail.binary .. summary-start Specifies the sendmail-compatible binary used when ommail runs in sendmail mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: sendmail.binary :Scope: input :Type: string :Default: input=/usr/sbin/sendmail :Required?: no :Introduced: 8.2606.0 Description ----------- Configures the binary executed for ``mode="sendmail"``. The default ``/usr/sbin/sendmail`` follows the standard local mail submission interface. Ommail verifies that the configured binary is executable before attempting delivery. Ommail invokes the binary without a shell and passes recipients as separate arguments. Input usage ----------- .. _ommail.parameter.input.sendmail-binary-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" mode="sendmail" sendmail.binary="/usr/sbin/sendmail" mailFrom="rsyslog@example.net" mailTo="operator@example.net" ) See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-log-file-overwrite.rst0000644000000000000000000000013215216464435027035 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.468471203 30 ctime=1787067792.271685492 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-log-file-overwrite.rst0000664000175000017500000000264615216464435026511 0ustar00rgerrger.. _param-impstats-log-file-overwrite: .. _impstats.parameter.module.log-file-overwrite: log.file.overwrite ================== .. index:: single: impstats; log.file.overwrite single: log.file.overwrite .. summary-start If set to "on", the statistics log file specified by :ref:`param-impstats-log-file` is overwritten with each emission instead of being appended to. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: log.file.overwrite :Scope: module :Type: binary :Default: off :Required?: no :Introduced: 8.2602.0 Description ----------- When this parameter is set to ``on``, rsyslog will overwrite the file specified in ``log.file`` every time it emits statistics. This is useful for external monitoring tools (like Prometheus sidecars or node exporter) that expect to read a single, consistent set of metrics from a file. To ensure that reader processes always see a complete and consistent set of statistics, rsyslog writes the data to a temporary file first and then atomically renames it to the final destination. Note that this parameter only has an effect if ``log.file`` is also specified. Module usage ------------ .. _impstats.parameter.module.log-file-overwrite-usage: .. code-block:: rsyslog module(load="impstats" log.file="/var/log/rsyslog-stats" log.file.overwrite="on") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omgssapi-actiongssforwarddefaulttemplate0000644000000000000000000000013215132733117031133 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.886460353 30 ctime=1787067793.210702991 rsyslog-8.2608.0/doc/source/reference/parameters/omgssapi-actiongssforwarddefaulttemplate.rst0000666000175000017500000000353215132733117031413 0ustar00rgerrger.. _param-omgssapi-actiongssforwarddefaulttemplate: .. _omgssapi.parameter.module.actiongssforwarddefaulttemplate: ActionGSSForwardDefaultTemplate =============================== .. index:: single: omgssapi; ActionGSSForwardDefaultTemplate single: ActionGSSForwardDefaultTemplate .. summary-start Sets the default output template omgssapi applies when a forwarding action omits an explicit template. .. summary-end This parameter applies to :doc:`../../configuration/modules/omgssapi`. :Name: ActionGSSForwardDefaultTemplate :Scope: module :Type: string :Default: RSYSLOG_TraditionalForwardFormat :Required?: no :Introduced: 3.12.4 Description ----------- Sets a new default template for the GSS-API forwarding action. When no template is specified in the forwarding rule, omgssapi falls back to this value. By default the module uses the built-in ``RSYSLOG_TraditionalForwardFormat`` template, matching the legacy syslog forward format. Legacy syntax configures this with directives such as ``$ActionGSSForwardDefaultTemplate RSYSLOG_ForwardFormat``. Module usage ------------ .. _param-omgssapi-module-actiongssforwarddefaulttemplate: .. _omgssapi.parameter.module.actiongssforwarddefaulttemplate-usage: .. code-block:: rsyslog module( load="omgssapi" actionGssForwardDefaultTemplate="RSYSLOG_ForwardFormat" ) action(type="omgssapi" target="receiver.mydomain.com") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omgssapi.parameter.legacy.actiongssforwarddefaulttemplate: - $ActionGSSForwardDefaultTemplate — maps to ActionGSSForwardDefaultTemplate (status: legacy) .. index:: single: omgssapi; $ActionGSSForwardDefaultTemplate single: $ActionGSSForwardDefaultTemplate See also -------- See also :doc:`../../configuration/modules/omgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-keepalive-time.rst0000644000000000000000000000013215145046112025633 xustar0030 mtime=1771326538.951012852 30 atime=1787067673.229466748 30 ctime=1787067793.486708134 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-keepalive-time.rst0000664000175000017500000000173215145046112025302 0ustar00rgerrger.. _param-omrelp-keepalive-time: .. _omrelp.parameter.input.keepalive-time: KeepAlive.Time ============== .. index:: single: omrelp; KeepAlive.Time single: KeepAlive.Time .. summary-start Specifies the idle time before the first TCP keepalive probe is sent. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: KeepAlive.Time :Scope: input :Type: integer :Default: input=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- The idle time before the first keepalive probe is sent. The default, 0, uses the operating system defaults. This only has an effect if keep-alive is enabled and may not be available on all platforms. Input usage ----------- .. _param-omrelp-input-keepalive-time: .. _omrelp.parameter.input.keepalive-time-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" keepAliveTime="300") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-usepidfromsystem.rst0000644000000000000000000000013215132733117030420 xustar0030 mtime=1768666703.911620299 30 atime=1787067673.776476945 30 ctime=1787067792.662692779 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-usepidfromsystem.rst0000666000175000017500000000266715132733117030101 0ustar00rgerrger.. _param-imuxsock-syssock-usepidfromsystem: .. _imuxsock.parameter.module.syssock-usepidfromsystem: SysSock.UsePIDFromSystem ======================== .. index:: single: imuxsock; SysSock.UsePIDFromSystem single: SysSock.UsePIDFromSystem .. summary-start Obtains the logged PID from the log socket itself. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.UsePIDFromSystem :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 5.7.0 Description ----------- Specifies if the pid being logged shall be obtained from the log socket itself. If so, the TAG part of the message is rewritten. It is recommended to turn this option on, but the default is "off" to keep compatible with earlier versions of rsyslog. Module usage ------------ .. _param-imuxsock-module-syssock-usepidfromsystem: .. _imuxsock.parameter.module.syssock-usepidfromsystem-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.usePIDFromSystem="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogusepidfromsystem: - $SystemLogUsePIDFromSystem — maps to SysSock.UsePIDFromSystem (status: legacy) .. index:: single: imuxsock; $SystemLogUsePIDFromSystem single: $SystemLogUsePIDFromSystem See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmnormalize-path.rst0000644000000000000000000000013215132733117024726 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.865459962 30 ctime=1787067792.876696766 rsyslog-8.2608.0/doc/source/reference/parameters/mmnormalize-path.rst0000666000175000017500000000170515132733117024377 0ustar00rgerrger.. _param-mmnormalize-path: .. _mmnormalize.parameter.action.path: path ==== .. index:: single: mmnormalize; path single: path .. summary-start Sets the JSON path where parsed elements are stored. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmnormalize`. :Name: path :Scope: action :Type: word :Default: action=$! :Required?: no :Introduced: at least 6.1.2, possibly earlier Description ----------- Specifies the JSON path under which parsed elements should be placed. By default, all parsed properties are merged into root of message properties. You can place them under a subtree, instead. You can place them in local variables, also, by setting ``path="$."``. Action usage ------------- .. _param-mmnormalize-action-path: .. _mmnormalize.parameter.action.path-usage: .. code-block:: rsyslog action(type="mmnormalize" path="$!subtree") See also -------- See also :doc:`../../configuration/modules/mmnormalize`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-tls-mycert.rst0000644000000000000000000000013115132733117025055 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.306468183 29 ctime=1787067793.31370491 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-tls-mycert.rst0000666000175000017500000000153415132733117024527 0ustar00rgerrger.. _param-omhttp-tls-mycert: .. _omhttp.parameter.input.tls-mycert: tls.mycert ========== .. index:: single: omhttp; tls.mycert single: tls.mycert .. summary-start Supplies the client certificate file used for HTTPS mutual authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: tls.mycert :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- This parameter sets the path to the SSL client certificate. Expects ``.pem`` format. Input usage ----------- .. _omhttp.parameter.input.tls-mycert-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" tlsMyCert="/etc/rsyslog/certs/omhttp-client.pem" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-proxyport.rst0000644000000000000000000000013115132733117025040 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.880460242 30 ctime=1787067793.273704165 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-proxyport.rst0000666000175000017500000000161215132733117024507 0ustar00rgerrger.. _param-omhttp-proxyport: .. _omhttp.parameter.input.proxyport: proxyport ========= .. index:: single: omhttp; proxyport single: proxyport .. summary-start Sets the port number of the HTTP proxy used by omhttp. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: proxyport :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- Configures the libcurl ``CURLOPT_PROXYPORT`` option for HTTP requests issued by omhttp. For more details see the `libcurl documentation for CURLOPT_PROXYPORT `_. Input usage ----------- .. _omhttp.parameter.input.proxyport-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" proxyPort="8080" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-cacert.rst0000644000000000000000000000013215132733117024775 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.000443836 30 ctime=1787067792.033681057 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-cacert.rst0000666000175000017500000000163715132733117024452 0ustar00rgerrger.. _param-imdtls-tls-cacert: .. _imdtls.parameter.input.tls-cacert: tls.caCert ========== .. index:: single: imdtls; tls.caCert single: tls.caCert .. summary-start Specifies the CA certificate file used to verify DTLS client certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.caCert :Scope: input :Type: string :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- The CA certificate that is being used to verify the client certificates. This file must be configured if ``tls.authMode`` is set to ``fingerprint``, ``name`` or ``certvalid``. Input usage ----------- .. _imdtls.parameter.input.tls-cacert-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.caCert="/etc/rsyslog/ca.pem" tls.authMode="certvalid") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-allowunsignedcerts.rst0000644000000000000000000000013215241075234030051 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.984680144 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-allowunsignedcerts.rst0000664000175000017500000000155215241075234027520 0ustar00rgerrger.. _param-imkubernetes-allowunsignedcerts: .. _imkubernetes.parameter.module.allowunsignedcerts: AllowUnsignedCerts ================== .. index:: single: imkubernetes; AllowUnsignedCerts single: AllowUnsignedCerts .. summary-start Disable TLS peer verification for Kubernetes API requests; default ``off``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: AllowUnsignedCerts :Scope: module :Type: binary :Default: ``off`` :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled, ``imkubernetes`` skips certificate trust validation for Kubernetes API TLS connections. Use only in controlled test environments. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" AllowUnsignedCerts="on") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-allowunsignedcerts.rst0000644000000000000000000000013215132733117026667 xustar0030 mtime=1768666703.916620375 30 atime=1787067673.070463783 30 ctime=1787067793.228703326 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-allowunsignedcerts.rst0000666000175000017500000000204615132733117026337 0ustar00rgerrger.. _param-omhttp-allowunsignedcerts: .. _omhttp.parameter.input.allowunsignedcerts: allowunsignedcerts ================== .. index:: single: omhttp; allowunsignedcerts single: allowunsignedcerts .. summary-start Controls whether omhttp skips server certificate validation when using HTTPS. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: allowunsignedcerts :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- If ``"on"``, this will set the curl `CURLOPT_SSL_VERIFYPEER `_ option to ``0``. You are strongly discouraged to set this to ``"on"``. It is primarily useful only for debugging or testing. Input usage ----------- .. _omhttp.parameter.input.allowunsignedcerts-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" useHttps="on" allowUnsignedCerts="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-maxbytesperminute.rst0000644000000000000000000000013115132733117026471 xustar0030 mtime=1768666703.904620193 29 atime=1787067672.47645271 30 ctime=1787067792.073681803 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-maxbytesperminute.rst0000666000175000017500000000223515132733117026142 0ustar00rgerrger.. _param-imfile-maxbytesperminute: .. _imfile.parameter.input.maxbytesperminute: .. _imfile.parameter.maxbytesperminute: MaxBytesPerMinute ================= .. index:: single: imfile; MaxBytesPerMinute single: MaxBytesPerMinute .. summary-start Drops messages when the total bytes per minute exceed the specified limit. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: MaxBytesPerMinute :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Instructs rsyslog to enqueue only up to the specified number of bytes as messages per minute. Once the limit is reached, subsequent messages are discarded. Messages are not truncated; an entire message is dropped if it would exceed the limit. The default ``0`` disables this check. Input usage ----------- .. _param-imfile-input-maxbytesperminute: .. _imfile.parameter.input.maxbytesperminute-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" MaxBytesPerMinute="0") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-compression-driver.rst0000644000000000000000000000013215216464435026415 xustar0030 mtime=1782212893.985265521 30 atime=1787067674.065482332 30 ctime=1787067792.457688958 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-driver.rst0000664000175000017500000000316115216464435026062 0ustar00rgerrger.. _param-imtcp-compression-driver: .. _imtcp.parameter.input.compression-driver: .. meta:: :description: Reference for the imtcp compression.driver input parameter. :keywords: rsyslog, imtcp, compression.driver, stream compression, zlib, zstd compression.driver ================== .. index:: single: imtcp; compression.driver single: compression.driver .. summary-start Selects the decompression driver for ``imtcp`` stream-compressed TCP input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: compression.driver :Scope: input/module :Type: word :Default: input=zlib :Required?: no :Introduced: 8.2606.0 Description ----------- ``compression.driver`` selects the decompression library used when ``compression.mode="stream:always"`` is configured. Accepted values are: - ``zlib``: default stream decompression driver. - ``zstd``: zstd stream decompression driver. This requires rsyslog to be built with libzstd support, and the ``omfwd`` sender must also use ``compression.driver="zstd"``. The driver setting must match the sender. A zstd-compressed stream cannot be received with ``compression.driver="zlib"``, and a zlib-compressed stream cannot be received with ``compression.driver="zstd"``. Input usage ----------- .. _param-imtcp-input-compression-driver: .. _imtcp.parameter.input.compression-driver-usage: .. code-block:: rsyslog input( type="imtcp" port="514" compression.mode="stream:always" compression.driver="zstd" ) See also -------- See also :ref:`param-imtcp-compression-mode` and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-dynsearchindex.rst0000644000000000000000000000013115132411300027600 xustar0030 mtime=1768559296.208884723 29 atime=1787067672.00544393 30 ctime=1787067793.043699878 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-dynsearchindex.rst0000666000175000017500000000176015132411300027253 0ustar00rgerrger.. _param-omelasticsearch-dynsearchindex: .. _omelasticsearch.parameter.module.dynsearchindex: dynSearchIndex ============== .. index:: single: omelasticsearch; dynSearchIndex single: dynSearchIndex .. summary-start Treat `searchIndex` as a template name instead of a literal. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: dynSearchIndex :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If enabled, the value of `searchIndex` is interpreted as the name of a template whose expansion becomes the index name. Action usage ------------ .. _param-omelasticsearch-action-dynsearchindex: .. _omelasticsearch.parameter.action.dynsearchindex: .. code-block:: rsyslog action(type="omelasticsearch" dynSearchIndex="...") Notes ----- - Previously documented as a "binary" option. See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-ratelimitburst.rst0000644000000000000000000000013215132733117025774 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.092464194 30 ctime=1787067792.245685008 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-ratelimitburst.rst0000666000175000017500000000153315132733117025444 0ustar00rgerrger.. _param-imklog-ratelimitburst: .. _imklog.parameter.module.ratelimitburst: RatelimitBurst ============== .. index:: single: imklog; RatelimitBurst single: RatelimitBurst .. summary-start Specifies how many messages imklog can emit within the configured rate-limiting interval. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: RatelimitBurst :Scope: module :Type: integer :Default: 10000 :Required?: no :Introduced: 8.35.0 Description ----------- Specifies the rate-limiting burst in number of messages. Set it high to preserve all boot-up messages. Module usage ------------ .. _param-imklog-module-ratelimitburst: .. _imklog.parameter.module.ratelimitburst-usage: .. code-block:: rsyslog module(load="imklog" ratelimitBurst="20000") See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-certfile.rst0000644000000000000000000000013015132733117027054 xustar0030 mtime=1768666703.909620269 30 atime=1787067673.779477001 28 ctime=1787067792.5296903 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-certfile.rst0000666000175000017500000000256615132733117026535 0ustar00rgerrger.. _param-imtcp-streamdriver-certfile: .. _imtcp.parameter.input.streamdriver-certfile: streamDriver.CertFile ===================== .. index:: single: imtcp; streamDriver.CertFile single: streamDriver.CertFile .. summary-start Overrides ``DefaultNetstreamDriverCertFile`` for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: streamDriver.CertFile :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=global parameter :Required?: no :Introduced: 8.2108.0 Description ----------- .. versionadded:: 8.2108.0 This permits to override the ``DefaultNetstreamDriverCertFile`` global parameter on the ``input()`` level. For further details, see the global parameter. .. note:: The GnuTLS driver sends all certificates contained in the file specified via ``StreamDriver.CertFile`` to connecting clients. To expose intermediate certificates, the file must contain the server certificate first, followed by the intermediate certificates. This capability was added in rsyslog version 8.36.0. Input usage ----------- .. _param-imtcp-input-streamdriver-certfile: .. _imtcp.parameter.input.streamdriver-certfile-usage: .. code-block:: rsyslog input(type="imtcp" streamDriver.certFile="/etc/ssl/certs/cert.pem") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-statsname.rst0000644000000000000000000000013215132733117024741 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.839440835 30 ctime=1787067793.007699208 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-statsname.rst0000666000175000017500000000242015132733117024405 0ustar00rgerrger.. _param-omdtls-statsname: .. _omdtls.parameter.input.statsname: statsname ========= .. index:: single: omdtls; statsname single: statsname .. summary-start Enables a dedicated per-action statistics counter identified by the provided name. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: statsname :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- This parameter assigns a unique name to a dedicated statistics counter for the ``omdtls`` action instance. When set, rsyslog tracks separate "submitted" and "failures" counters for this action that can be retrieved via the :doc:`impstats <../../configuration/modules/impstats>` module by referencing the specified name. This makes it easier to monitor the performance and health of individual DTLS forwarding actions. If left unset, the action contributes only to the global ``omdtls`` statistics origin. Input usage ----------- .. _omdtls.parameter.input.statsname-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" statsName="dtls_to_server1") See also -------- See also :doc:`../../configuration/modules/omdtls`, :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-notifyonconnectionopen.rst0000644000000000000000000000013015132733117027361 xustar0030 mtime=1768666703.908620253 28 atime=1787067674.0744825 30 ctime=1787067792.503689815 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-notifyonconnectionopen.rst0000666000175000017500000000160715132733117027035 0ustar00rgerrger.. _param-imtcp-notifyonconnectionopen: .. _imtcp.parameter.module.notifyonconnectionopen: NotifyOnConnectionOpen ====================== .. index:: single: imtcp; NotifyOnConnectionOpen single: NotifyOnConnectionOpen .. summary-start Emits a message when a remote peer opens a connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: NotifyOnConnectionOpen :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Instructs imtcp to emit a message if the remote peer opens a connection. Module usage ------------ .. _param-imtcp-module-notifyonconnectionopen: .. _imtcp.parameter.module.notifyonconnectionopen-usage: .. code-block:: rsyslog module(load="imtcp" notifyOnConnectionOpen="on") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsendertrack-cmdfile.rst0000644000000000000000000000013215132733117025704 xustar0030 mtime=1768666703.923620481 30 atime=1787067672.971461938 30 ctime=1787067793.530708954 rsyslog-8.2608.0/doc/source/reference/parameters/omsendertrack-cmdfile.rst0000666000175000017500000000261215132733117025353 0ustar00rgerrger.. _param-omsendertrack-cmdfile: .. _omsendertrack.parameter.input.cmdfile: cmdfile ======= .. index:: single: omsendertrack; cmdfile single: cmdfile .. summary-start Defines the absolute path to the command file that omsendertrack reads when rsyslog receives a HUP signal. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsendertrack`. :Name: cmdfile :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2506.0 (Proof-of-Concept) Description ----------- This optional parameter allows you to specify the **absolute path to a command file**. This file *is designed to be processed when rsyslog receives a HUP signal* (for example via ``systemctl reload rsyslog``). **Note:** Command file support is currently **not implemented** in this proof-of-concept version of the module. When implemented, this feature is intended to allow dynamic control over the module's behavior, such as resetting statistics for specific senders, without requiring an rsyslog restart. Input usage ----------- .. _omsendertrack.parameter.input.cmdfile-usage: .. code-block:: rsyslog module(load="omsendertrack") action(type="omsendertrack" senderId="%hostname%" stateFile="/var/lib/rsyslog/senderstats.json" cmdFile="/var/lib/rsyslog/sendercommands.txt") See also -------- See also :doc:`../../configuration/modules/omsendertrack`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-batch.rst0000644000000000000000000000013115132733117024033 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.090464156 30 ctime=1787067793.237703494 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-batch.rst0000666000175000017500000000513115132733117023502 0ustar00rgerrger.. _param-omhttp-batch: .. _omhttp.parameter.input.batch: batch ===== .. index:: single: omhttp; batch single: batch .. summary-start Enables batching so omhttp queues messages and submits them in a single HTTP request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: batch :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not specified Description ----------- Batch and ``bulkmode`` do the same thing, ``bulkmode`` is included for backwards compatibility. See the :ref:`param-omhttp-batch-format` section for a detailed breakdown of how batching is implemented. This parameter activates batching mode, which queues messages and sends them as a single request. There are several related parameters that specify the format and size of the batch: they are :ref:`param-omhttp-batch-format`, :ref:`param-omhttp-batch-maxbytes`, and :ref:`param-omhttp-batch-maxsize`. Note that rsyslog core is the ultimate authority on when a batch must be submitted, due to the way that batching is implemented. This plugin implements the `output plugin transaction interface `_. There may be multiple batches in a single transaction, but a batch will never span multiple transactions. This means that if :ref:`param-omhttp-batch-maxsize` or :ref:`param-omhttp-batch-maxbytes` is set very large, you may never actually see batches hit this size. Additionally, the number of messages per transaction is determined by the size of the main, action, and ruleset queues as well. The plugin flushes a batch early if either the configured :ref:`param-omhttp-batch-maxsize` is reached or if adding the next message would exceed :ref:`param-omhttp-batch-maxbytes` once serialized (format overhead included). When :ref:`param-omhttp-dynrestpath` is enabled, a change of the effective REST path also forces a flush so that each batch targets a single path. Additionally, due to some open issues with rsyslog and the transaction interface, batching requires some nuanced :ref:`param-omhttp-retry` configuration. By default, omhttp signals transport/server failures to rsyslog core (suspend/resume), which performs retries. The :ref:`param-omhttp-retry-ruleset` mechanism remains available for advanced per-message retry handling in batch mode. Input usage ----------- .. _omhttp.parameter.input.batch-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" batch="on" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-tlscfgcmd.rst0000644000000000000000000000013215145046112025500 xustar0030 mtime=1771326538.955012917 30 atime=1787067672.878460204 30 ctime=1787067793.521708786 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-tlscfgcmd.rst0000664000175000017500000000322715145046112025150 0ustar00rgerrger.. _param-omrelp-tls-tlscfgcmd: .. _omrelp.parameter.input.tls-tlscfgcmd: tls.tlscfgcmd ============= .. index:: single: omrelp; tls.tlscfgcmd single: tls.tlscfgcmd .. summary-start Passes OpenSSL configuration commands to librelp when using the OpenSSL TLS backend. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: tls.tlscfgcmd :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2001.0 Description ----------- .. versionadded:: 8.2001.0 The setting can be used if tls.tlslib is set to "openssl" to pass configuration commands to the openssl library. OpenSSL Version 1.0.2 or higher is required for this feature. A list of possible commands and their valid values can be found in the documentation: https://docs.openssl.org/1.0.2/man3/SSL_CONF_cmd/ The setting can be single or multiline, each configuration command is separated by linefeed (\n). Command and value are separated by equal sign (=). Here are a few samples: Example 1 --------- This will allow all protocols except for SSLv2 and SSLv3: .. code-block:: rsyslog tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3" Example 2 --------- This will allow all protocols except for SSLv2, SSLv3 and TLSv1. It will also set the minimum protocol to TLSv1.2 .. code-block:: rsyslog tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1 MinProtocol=TLSv1.2" Input usage ----------- .. _param-omrelp-input-tls-tlscfgcmd: .. _omrelp.parameter.input.tls-tlscfgcmd-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.tlscfgcmd="Protocol=ALL,-SSLv3") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-flushontxend.rst0000644000000000000000000000013215216464435025443 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.533453773 30 ctime=1787067793.185702525 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-flushontxend.rst0000664000175000017500000000435715216464435025120 0ustar00rgerrger.. _param-omfile-flushontxend: .. _omfile.parameter.module.flushontxend: flushOnTXEnd ============ .. index:: single: omfile; flushOnTXEnd single: flushOnTXEnd .. summary-start Omfile has the capability to write output using a buffered writer. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: flushOnTXEnd :Scope: action :Type: boolean :Default: action=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Omfile has the capability to write output using a buffered writer. Disk writes are only done when the buffer is full. So if an error happens during that write, data is potentially lost. Bear in mind that the buffer may become full only after several hours or a rsyslog shutdown (however a buffer flush can still be forced by sending rsyslogd a HUP signal). In cases where this is unacceptable, set FlushOnTXEnd to "on". Then, data is written at the end of each transaction (for pre-v5 this means after each log message) and the usual error recovery thus can handle write errors without data loss. Note that this option severely reduces the effect of zip compression and should be switched to "off" for that use case. If ``flushOnTXEnd`` is disabled, use :ref:`param-omfile-flushinterval` to configure timed flushing of buffered data. Also note that the default -on- is primarily an aid to preserve the traditional syslogd behaviour. If you are using dynamic file names (dynafiles), flushes can actually happen more frequently. In this case, a flush can also happen when the file name changes within a transaction. Action usage ------------ .. _param-omfile-action-flushontxend: .. _omfile.parameter.action.flushontxend: .. code-block:: rsyslog action(type="omfile" flushOnTXEnd="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.omfileflushontxend: - $OMFileFlushOnTXEnd — maps to flushOnTXEnd (status: legacy) .. index:: single: omfile; $OMFileFlushOnTXEnd single: $OMFileFlushOnTXEnd See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-searchindex.rst0000644000000000000000000000013215132411300027066 xustar0030 mtime=1768559296.208884723 30 atime=1787067671.998443799 30 ctime=1787067793.083700624 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-searchindex.rst0000666000175000017500000000153415132411300026537 0ustar00rgerrger.. _param-omelasticsearch-searchindex: .. _omelasticsearch.parameter.module.searchindex: searchIndex =========== .. index:: single: omelasticsearch; searchIndex single: searchIndex .. summary-start Elasticsearch index where events are written. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: searchIndex :Scope: action :Type: word :Default: action=system :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Name of the target Elasticsearch index. When unset it defaults to `system`. Action usage ------------ .. _param-omelasticsearch-action-searchindex: .. _omelasticsearch.parameter.action.searchindex: .. code-block:: rsyslog action(type="omelasticsearch" searchIndex="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-ruleset.rst0000644000000000000000000000013215241075234025620 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.006680554 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-ruleset.rst0000664000175000017500000000164615241075234025273 0ustar00rgerrger.. _param-imkubernetes-ruleset: .. _imkubernetes.parameter.input.ruleset: Ruleset ======== .. index:: single: imkubernetes; Ruleset single: Ruleset .. summary-start Ruleset that receives records submitted by ``imkubernetes``; default is the default ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: Ruleset :Scope: module, input :Type: string :Default: default ruleset :Required?: no :Introduced: 8.2606.0 Description ----------- Bind ``imkubernetes`` records to the named ruleset. This is especially useful with YAML configuration, where the input object can name the ruleset that owns the output actions. Input usage ----------- .. code-block:: rsyslog module(load="imkubernetes" Ruleset="kubernetes") .. code-block:: rsyslog input(type="imkubernetes" Ruleset="kubernetes") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ratelimit-interval.rst0000644000000000000000000000013215132733117030612 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.570473104 30 ctime=1787067792.650692555 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ratelimit-interval.rst0000666000175000017500000000312315132733117030257 0ustar00rgerrger.. _param-imuxsock-syssock-ratelimit-interval: .. _imuxsock.parameter.module.syssock-ratelimit-interval: SysSock.RateLimit.Interval ========================== .. index:: single: imuxsock; SysSock.RateLimit.Interval single: SysSock.RateLimit.Interval .. summary-start Sets the rate-limiting interval in seconds for the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.RateLimit.Interval :Scope: module :Type: integer :Default: module=0 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies the rate-limiting interval in seconds. Default value is 0, which turns off rate limiting. Set it to a number of seconds (5 recommended) to activate rate-limiting. The default of 0 has been chosen as people experienced problems with this feature activated by default. Now it needs an explicit opt-in by setting this parameter. Module usage ------------ .. _param-imuxsock-module-syssock-ratelimit-interval: .. _imuxsock.parameter.module.syssock-ratelimit-interval-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.rateLimit.interval="5") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogratelimitinterval: - $SystemLogRateLimitInterval — maps to SysSock.RateLimit.Interval (status: legacy) .. index:: single: imuxsock; $SystemLogRateLimitInterval single: $SystemLogRateLimitInterval See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-keepalive.rst0000644000000000000000000000013215132733117024675 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.951480207 30 ctime=1787067792.406688008 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-keepalive.rst0000666000175000017500000000144015132733117024342 0ustar00rgerrger.. _param-imrelp-keepalive: .. _imrelp.parameter.input.keepalive: keepAlive ========= .. index:: single: imrelp; keepAlive single: keepAlive .. summary-start Toggles TCP keep-alive probes for RELP listener sockets. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: keepAlive :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: Not documented Description ----------- Enable or disable keep-alive packets at the TCP socket layer. By default keep-alive is disabled. Input usage ----------- .. _param-imrelp-input-keepalive-usage: .. _imrelp.parameter.input.keepalive-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" keepAlive="on") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-name.rst0000644000000000000000000000013115132733117023473 xustar0030 mtime=1768666703.908620253 29 atime=1787067674.15548401 30 ctime=1787067792.496689685 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-name.rst0000666000175000017500000000232615132733117023145 0ustar00rgerrger.. _param-imtcp-name: .. _imtcp.parameter.input.name: Name ==== .. index:: single: imtcp; Name single: Name .. summary-start Sets the value for the ``inputname`` property. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: Name :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=imtcp :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets a name for the ``inputname`` property. If no name is set, ``imtcp`` is used by default. Setting a name is not strictly necessary but can be useful to filter based on which input received the message. Input usage ----------- .. _param-imtcp-input-name: .. _imtcp.parameter.input.name-usage: .. code-block:: rsyslog input(type="imtcp" name="tcp1" port="514") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverinputname: - $InputTCPServerInputName — maps to Name (status: legacy) .. index:: single: imtcp; $InputTCPServerInputName single: $InputTCPServerInputName See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-endmsg-regex.rst0000644000000000000000000000013215132733117025272 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.388451069 30 ctime=1787067792.057681505 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-endmsg-regex.rst0000666000175000017500000000264615132733117024750 0ustar00rgerrger.. _param-imfile-endmsg-regex: .. _imfile.parameter.input.endmsg-regex: .. _imfile.parameter.endmsg-regex: endmsg.regex ============ .. index:: single: imfile; endmsg.regex single: endmsg.regex .. summary-start Regex that identifies the end of a multi-line message. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: endmsg.regex :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: no :Introduced: 8.38.0 Description ----------- Allows processing of multi-line messages. A message is terminated when ``endmsg.regex`` matches the line that marks the end of the message. It is more flexible than ``readMode`` but has lower performance. ``endmsg.regex``, ``startmsg.regex`` and ``readMode`` cannot all be defined for the same input. Examples: .. code-block:: none date stdout P start of message date stdout P middle of message date stdout F end of message Here ``endmsg.regex="^[^ ]+ stdout F "`` matches the line with ``F`` and assembles the message ``start of message middle of message end of message``. Input usage ----------- .. _param-imfile-input-endmsg-regex: .. _imfile.parameter.input.endmsg-regex-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" endmsg.regex="pattern") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-mailfrom.rst0000644000000000000000000000013215132733117024524 xustar0030 mtime=1768666703.918620405 30 atime=1787067672.776458303 30 ctime=1787067793.389706326 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-mailfrom.rst0000666000175000017500000000231615132733117024174 0ustar00rgerrger.. _param-ommail-mailfrom: .. _ommail.parameter.input.mailfrom: mailFrom ======== .. index:: single: ommail; mailFrom single: mailFrom .. summary-start Defines the sender email address placed in outgoing messages from ommail. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: mailFrom :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: 8.5.0 Description ----------- This mandatory parameter defines the email address used as the sender. It will appear in the ``From:`` header of the email. Input usage ------------ .. _ommail.parameter.input.mailfrom-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailfrom: - $ActionMailFrom — maps to mailFrom (status: legacy) .. index:: single: ommail; $ActionMailFrom single: $ActionMailFrom See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-serverstreamdrivermode.rst0000644000000000000000000000013215216464435027504 xustar0030 mtime=1782212893.984265505 30 atime=1787067672.083445383 30 ctime=1787067791.960679697 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-serverstreamdrivermode.rst0000664000175000017500000000330015216464435027144 0ustar00rgerrger.. _param-imdiag-serverstreamdrivermode: .. _imdiag.parameter.module.serverstreamdrivermode: ServerStreamDriverMode ====================== .. index:: single: imdiag; ServerStreamDriverMode single: ServerStreamDriverMode .. summary-start Accepts a numeric stream driver mode value, but imdiag forces the plain TCP driver so the setting is ignored. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: ServerStreamDriverMode :Scope: module :Type: integer :Default: module=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Provides the mode number consumed by the selected :doc:`network stream driver <../../concepts/netstrm_drvr>`. imdiag always uses the plain TCP (``ptcp``) stream driver, which does not act on the provided mode value. The parameter remains available for configuration compatibility and possible future extensions, but it does not alter behavior in current releases. Module usage ------------ .. _param-imdiag-module-serverstreamdrivermode: .. _imdiag.parameter.module.serverstreamdrivermode-usage: .. code-block:: rsyslog module(load="imdiag" listenPortFileName="/var/run/rsyslog/imdiag.port" serverStreamDriverMode="1" serverRun="19998") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imdiag.parameter.legacy.imdiagserverstreamdrivermode: - $IMDiagServerStreamDriverMode — maps to ServerStreamDriverMode (status: legacy) .. index:: single: imdiag; $IMDiagServerStreamDriverMode single: $IMDiagServerStreamDriverMode See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-label-job.rst0000644000000000000000000000013215145046112026104 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.502471837 30 ctime=1787067792.284685734 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-label-job.rst0000664000175000017500000000156415145046112025556 0ustar00rgerrger.. _param-impstats-push-label-job: .. _impstats.parameter.module.push-label-job: push.label.job ============== .. index:: single: impstats; push.label.job single: push.label.job .. summary-start Adds a ``job=`` label to pushed metrics. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.label.job :Scope: module :Type: word :Default: module=rsyslog :Required?: no :Introduced: 8.2602.0 Description ----------- Sets the ``job`` label used by Prometheus conventions. Set to an empty string to disable. If a ``job`` label already exists in ``push.labels``, it is not overridden. Module usage ------------ .. _impstats.parameter.module.push-label-job-usage: .. code-block:: rsyslog module(load="impstats" push.label.job="rsyslog") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-syssock-ratelimit-severity.rst0000644000000000000000000000013215132733117030640 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.730476087 30 ctime=1787067792.655692648 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-syssock-ratelimit-severity.rst0000666000175000017500000000262515132733117030313 0ustar00rgerrger.. _param-imuxsock-syssock-ratelimit-severity: .. _imuxsock.parameter.module.syssock-ratelimit-severity: SysSock.RateLimit.Severity ========================== .. index:: single: imuxsock; SysSock.RateLimit.Severity single: SysSock.RateLimit.Severity .. summary-start Specifies which message severity levels are rate-limited on the system log socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: SysSock.RateLimit.Severity :Scope: module :Type: integer :Default: module=1 :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Specifies the severity of messages that shall be rate-limited. .. seealso:: https://en.wikipedia.org/wiki/Syslog#Severity_level Module usage ------------ .. _param-imuxsock-module-syssock-ratelimit-severity: .. _imuxsock.parameter.module.syssock-ratelimit-severity-usage: .. code-block:: rsyslog module(load="imuxsock" sysSock.rateLimit.severity="5") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.systemlogratelimitseverity: - $SystemLogRateLimitSeverity — maps to SysSock.RateLimit.Severity (status: legacy) .. index:: single: imuxsock; $SystemLogRateLimitSeverity single: $SystemLogRateLimitSeverity See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omdtls-tls-tlscfgcmd.rst0000644000000000000000000000013215132733117025510 xustar0030 mtime=1768666703.916620375 30 atime=1787067671.831440686 30 ctime=1787067793.023699506 rsyslog-8.2608.0/doc/source/reference/parameters/omdtls-tls-tlscfgcmd.rst0000666000175000017500000000331015132733117025153 0ustar00rgerrger.. _param-omdtls-tls-tlscfgcmd: .. _omdtls.parameter.input.tls-tlscfgcmd: tls.tlscfgcmd ============= .. index:: single: omdtls; tls.tlscfgcmd single: tls.tlscfgcmd .. summary-start Passes additional OpenSSL configuration commands to fine-tune DTLS behavior. .. summary-end This parameter applies to :doc:`../../configuration/modules/omdtls`. :Name: tls.tlscfgcmd :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: v8.2402.0 Description ----------- Used to pass additional OpenSSL configuration commands. This can be used to fine-tune the OpenSSL settings by passing configuration commands to the OpenSSL library. OpenSSL Version 1.0.2 or higher is required for this feature. A list of possible commands and their valid values can be found in the `SSL_CONF_cmd documentation `_. The setting can be single or multiline, each configuration command is separated by linefeed (``\n``). Command and value are separated by an equal sign (``=``). Here are a few samples: Example 1 ~~~~~~~~~ This will allow all protocols except for SSLv2 and SSLv3: .. code-block:: none tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3" Example 2 ~~~~~~~~~ This will allow all protocols except for SSLv2, SSLv3 and TLSv1. It will also set the minimum protocol to TLSv1.2 .. code-block:: none tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1\nMinProtocol=TLSv1.2" Input usage ----------- .. _omdtls.parameter.input.tls-tlscfgcmd-usage: .. code-block:: rsyslog action(type="omdtls" target="192.0.2.1" port="4433" tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3") See also -------- See also :doc:`../../configuration/modules/omdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-logfileglob.rst0000644000000000000000000000013215241075234026422 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.002680479 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-logfileglob.rst0000664000175000017500000000160015241075234026063 0ustar00rgerrger.. _param-imkubernetes-logfileglob: .. _imkubernetes.parameter.module.logfileglob: LogFileGlob =========== .. index:: single: imkubernetes; LogFileGlob single: LogFileGlob .. summary-start Glob that selects Kubernetes log files to tail; default ``/var/log/pods/*/*/*.log``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: LogFileGlob :Scope: module :Type: path :Default: ``/var/log/pods/*/*/*.log`` :Required?: no :Introduced: 8.2604.0 Description ----------- Use this to point ``imkubernetes`` at the node-local container log files you want to follow. Common values are ``/var/log/pods/*/*/*.log`` and ``/var/log/containers/*.log``. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" LogFileGlob="/var/log/pods/*/*/*.log") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpheaderkey.rst0000644000000000000000000000013115132733117025613 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.716457184 30 ctime=1787067793.260703922 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpheaderkey.rst0000666000175000017500000000206015132733117025260 0ustar00rgerrger.. _param-omhttp-httpheaderkey: .. _omhttp.parameter.input.httpheaderkey: httpheaderkey ============= .. index:: single: omhttp; httpheaderkey single: httpheaderkey .. summary-start Defines the single custom HTTP header name to send with each omhttp request. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpheaderkey :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The header key. Currently only a single additional header/key pair is configurable with this parameter. To specify multiple headers use the :ref:`param-omhttp-httpheaders` parameter. This parameter, along with :ref:`param-omhttp-httpheadervalue`, may be deprecated in the future. Input usage ----------- .. _omhttp.parameter.input.httpheaderkey-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpHeaderKey="X-Event-Source" httpHeaderValue="logs" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-signalonclose.rst0000644000000000000000000000012715132733117025607 xustar0030 mtime=1768666703.920620435 27 atime=1787067673.028463 30 ctime=1787067793.472707873 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-signalonclose.rst0000666000175000017500000000267415132733117025262 0ustar00rgerrger.. _param-omprog-signalonclose: .. _omprog.parameter.action.signalonclose: signalOnClose ============= .. index:: single: omprog; signalOnClose single: signalOnClose .. summary-start Sends a TERM signal to the program before closing its stdin. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: signalOnClose :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: 8.23.0 Description ----------- Specifies whether a TERM signal must be sent to the external program before closing it (when either the worker thread has been unscheduled, a restart of the program is being forced, or rsyslog is about to shutdown). If this switch is set to "on", rsyslog will send a TERM signal to the child process before closing the pipe. That is, the process will first receive a TERM signal, and then an EOF on stdin. No signal is issued if this switch is set to "off" (default). The child process can still detect it must terminate because reading from stdin will return EOF. See the :ref:`param-omprog-killunresponsive` parameter for more details. Action usage ------------ .. _param-omprog-action-signalonclose: .. _omprog.parameter.action.signalonclose-usage: .. code-block:: rsyslog action(type="omprog" signalOnClose="on") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-tls-tlsversion.rst0000644000000000000000000000013215241075234027616 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067793.113701183 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-tls-tlsversion.rst0000664000175000017500000000305115241075234027261 0ustar00rgerrger.. _param-omelasticsearch-tls-tlsversion: .. _omelasticsearch.parameter.module.tls-tlsversion: .. _omelasticsearch.parameter.module.tls.tlsversion: tls.tlsversion ============== .. index:: single: omelasticsearch; tls.tlsversion single: tls.tlsversion .. summary-start Minimum TLS protocol version for the Elasticsearch connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: tls.tlsversion :Scope: action :Type: word :Default: none (libcurl default) :Required?: no :Introduced: 8.2606.0 Description ----------- Sets the minimum (floor) TLS version accepted for the connection to Elasticsearch. Accepted values are ``TLSv1.2`` and ``TLSv1.3``. An unknown value is rejected at configuration load time and prevents rsyslog from starting. When omitted, libcurl negotiates the highest version supported by both sides, typically TLS 1.3 on modern systems. .. note:: Setting this to ``TLSv1.2`` downgrades the effective floor and should be avoided unless the server does not support TLS 1.3. Action usage ------------ .. _param-omelasticsearch-action-tls-tlsversion: .. _omelasticsearch.parameter.action.tls-tlsversion: .. code-block:: rsyslog action(type="omelasticsearch" tls.tlsversion="TLSv1.3") YAML usage ---------- .. code-block:: yaml actions: - type: omelasticsearch tls.tlsversion: "TLSv1.3" See also -------- See also :doc:`../../configuration/modules/omelasticsearch`, :ref:`param-omelasticsearch-tls-ciphersuites`, :ref:`param-omelasticsearch-tls-keyexchangegroups`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imsolaris-imsolarislogsocketname.rst0000644000000000000000000000013215132733117030220 xustar0030 mtime=1768666703.908620253 30 atime=1787067674.027481624 30 ctime=1787067792.448688791 rsyslog-8.2608.0/doc/source/reference/parameters/imsolaris-imsolarislogsocketname.rst0000666000175000017500000000245515132733117027674 0ustar00rgerrger.. _param-imsolaris-imsolarislogsocketname: .. _imsolaris.parameter.module.imsolarislogsocketname: IMSolarisLogSocketName ====================== .. index:: single: imsolaris; IMSolarisLogSocketName single: IMSolarisLogSocketName .. summary-start Specifies the Solaris log stream device imsolaris reads, defaulting to ``/dev/log``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imsolaris`. .. note:: This is a legacy global directive. The imsolaris module does not support the modern ``module()``/``input()`` syntax. :Name: IMSolarisLogSocketName :Scope: module :Type: string (path) :Default: /dev/log :Required?: no :Introduced: Not documented Description ----------- This directive specifies the path to the Solaris log socket (stream) for reading local application and kernel messages. If omitted, it defaults to ``/dev/log``. Since directive names are case-insensitive, the canonical form ``$IMSolarisLogSocketName`` is recommended for readability. Module usage ------------ .. _param-imsolaris-module-imsolarislogsocketname-usage: .. _imsolaris.parameter.module.imsolarislogsocketname-usage: .. code-block:: rsyslog $ModLoad imsolaris $IMSolarisLogSocketName "/var/run/rsyslog/solaris.log" See also -------- See also :doc:`../../configuration/modules/imsolaris`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-fileowner.rst0000644000000000000000000000013215132411300024670 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.334450063 30 ctime=1787067793.179702413 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-fileowner.rst0000666000175000017500000000302115132411300024332 0ustar00rgerrger.. _param-omfile-fileowner: .. _omfile.parameter.module.fileowner: fileOwner ========= .. index:: single: omfile; fileOwner single: fileOwner .. summary-start Set the file owner for files newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: fileOwner :Scope: module, action :Type: uid :Default: module=process user; action=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the file owner for files newly created. Please note that this setting does not affect the owner of files already existing. The parameter is a user name, for which the userid is obtained by rsyslogd during startup processing. Interim changes to the user mapping are *not* detected. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-fileowner: .. _omfile.parameter.module.fileowner-usage: .. code-block:: rsyslog module(load="builtin:omfile" fileOwner="...") Action usage ------------ .. _param-omfile-action-fileowner: .. _omfile.parameter.action.fileowner: .. code-block:: rsyslog action(type="omfile" fileOwner="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.fileowner: - $FileOwner — maps to fileOwner (status: legacy) .. index:: single: omfile; $FileOwner single: $FileOwner See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-fileownernum.rst0000644000000000000000000000013115132411300025407 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.340450174 29 ctime=1787067793.18170245 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-fileownernum.rst0000666000175000017500000000310615132411300025056 0ustar00rgerrger.. _param-omfile-fileownernum: .. _omfile.parameter.module.fileownernum: fileOwnerNum ============ .. index:: single: omfile; fileOwnerNum single: fileOwnerNum .. summary-start Set the file owner for files newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: fileOwnerNum :Scope: module, action :Type: integer :Default: module=process user; action=system default :Required?: no :Introduced: 7.5.8 Description ----------- Set the file owner for files newly created. Please note that this setting does not affect the owner of files already existing. The parameter is a numerical ID, which is used regardless of whether the user actually exists. This can be useful if the user mapping is not available to rsyslog during startup. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-fileownernum: .. _omfile.parameter.module.fileownernum-usage: .. code-block:: rsyslog module(load="builtin:omfile" fileOwnerNum="...") Action usage ------------ .. _param-omfile-action-fileownernum: .. _omfile.parameter.action.fileownernum: .. code-block:: rsyslog action(type="omfile" fileOwnerNum="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.fileownernum: - $FileOwnerNum — maps to fileOwnerNum (status: legacy) .. index:: single: omfile; $FileOwnerNum single: $FileOwnerNum See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imuxsock-annotate.rst0000644000000000000000000000013215132733117025113 xustar0030 mtime=1768666703.910620284 30 atime=1787067673.943480058 30 ctime=1787067792.602691661 rsyslog-8.2608.0/doc/source/reference/parameters/imuxsock-annotate.rst0000666000175000017500000000231315132733117024560 0ustar00rgerrger.. _param-imuxsock-annotate: .. _imuxsock.parameter.input.annotate: Annotate ======== .. index:: single: imuxsock; Annotate single: Annotate .. summary-start Enables annotation and trusted properties for this input. .. summary-end This parameter applies to :doc:`../../configuration/modules/imuxsock`. :Name: Annotate :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Turn on annotation/trusted properties for the input that is being defined. See the :ref:`imuxsock-trusted-properties-label` section for more info. Input usage ----------- .. _param-imuxsock-input-annotate: .. _imuxsock.parameter.input.annotate-usage: .. code-block:: rsyslog input(type="imuxsock" annotate="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imuxsock.parameter.legacy.inputunixlistensocketannotate: - $InputUnixListenSocketAnnotate — maps to Annotate (status: legacy) .. index:: single: imuxsock; $InputUnixListenSocketAnnotate single: $InputUnixListenSocketAnnotate See also -------- See also :doc:`../../configuration/modules/imuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-delay-message.rst0000644000000000000000000000013115241075234025424 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.676579624 29 ctime=1787067792.05368143 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-delay-message.rst0000664000175000017500000000472515241075234025101 0ustar00rgerrger.. _param-imfile-delay-message: .. _imfile.parameter.input.delay-message: .. _imfile.parameter.delay-message: delay.message ============= .. index:: single: imfile; delay.message single: delay.message .. meta:: :description: imfile delay.message parameter reference - adds per-message delay for bandwidth rate-limiting :keywords: imfile, delay.message, rate-limiting, bandwidth, input plugin .. summary-start Adds a delay after each line read from the file, useful for rate-limiting log sources in multi-tenant environments. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: delay.message :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: 8.38.0 (via PR #2999) Description ----------- Instructs rsyslog to pause after reading each line from the monitored file. The default ``0`` disables this delay. This parameter is useful in multi-tenant environments where multiple applications write to separate log files that are all being collected by a single rsyslog instance. By adding a small per-message delay, no single log source can dominate the available bandwidth for transporting logs off the host. Unlike :doc:`imfile-maxbytesperminute` and :doc:`imfile-maxlinesperminute`, which drop messages when rate limits are exceeded, ``delay.message`` slows down processing without message loss. This makes it suitable for scenarios where all messages must be preserved but bandwidth sharing is required. The value is converted into whole seconds and remaining microseconds before rsyslog sleeps. For example, ``delay.message="1000"`` adds a 1 millisecond delay, while ``delay.message="1500000"`` adds a 1.5 second delay. Input usage ----------- .. _param-imfile-input-delay-message: .. _imfile.parameter.input.delay-message-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/containers/app1.log" Tag="app1" delay.message="1000") The above example configures a delay value of 1000 microseconds. Notes ----- - The delay is applied per-message, after each line is read from the file. - Value is specified in microseconds (1 second = 1,000,000 microseconds). - For bandwidth throttling without message loss, prefer this over rate-limiting parameters that discard messages. - In high-throughput scenarios, even small delays can significantly reduce throughput. Test carefully to balance bandwidth sharing against processing lag. See also -------- :doc:`../../configuration/modules/imfile` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-streamdriver-crlfile.rst0000644000000000000000000000013215216464435026710 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.948480151 30 ctime=1787067792.534690393 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-streamdriver-crlfile.rst0000664000175000017500000000261715216464435026362 0ustar00rgerrger.. _param-imtcp-streamdriver-crlfile: .. _imtcp.parameter.input.streamdriver-crlfile: streamDriver.CRLFile ==================== .. index:: single: imtcp; streamDriver.CRLFile single: streamDriver.CRLFile .. summary-start Overrides the CRL file set via the global configuration. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: streamDriver.CRLFile :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=global parameter :Required?: no :Introduced: 8.2308.0 Description ----------- .. versionadded:: 8.2308.0 This permits to override the CRL (Certificate revocation list) file set via ``global()`` config object at the per-action basis. This parameter is ignored if the netstream driver and/or its mode does not need or support certificates. CRL checking is available with the ``ossl`` network stream driver when rsyslog is compiled against either OpenSSL or wolfSSL. On wolfSSL builds, wolfSSL must be compiled with ``--enable-crl``; both PEM and DER CRL files are accepted. The GnuTLS driver also supports CRL files (see its own documentation). Input usage ----------- .. _param-imtcp-input-streamdriver-crlfile: .. _imtcp.parameter.input.streamdriver-crlfile-usage: .. code-block:: rsyslog input(type="imtcp" streamDriver.crlFile="/etc/ssl/crl.pem") See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dirgroup.rst0000644000000000000000000000013215132411300024531 xustar0030 mtime=1768559296.209884738 30 atime=1787067672.365450641 30 ctime=1787067793.147701817 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dirgroup.rst0000666000175000017500000000303215132411300024175 0ustar00rgerrger.. _param-omfile-dirgroup: .. _omfile.parameter.module.dirgroup: dirGroup ======== .. index:: single: omfile; dirGroup single: dirGroup .. summary-start Set the group for directories newly created. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dirGroup :Scope: module, action :Type: gid :Default: module=process user's primary group; action=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the group for directories newly created. Please note that this setting does not affect the group of directories already existing. The parameter is a group name, for which the groupid is obtained by rsyslogd on during startup processing. Interim changes to the user mapping are not detected. When set on the module, the value becomes the default for actions. Module usage ------------ .. _param-omfile-module-dirgroup: .. _omfile.parameter.module.dirgroup-usage: .. code-block:: rsyslog module(load="builtin:omfile" dirGroup="...") Action usage ------------ .. _param-omfile-action-dirgroup: .. _omfile.parameter.action.dirgroup: .. code-block:: rsyslog action(type="omfile" dirGroup="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.dirgroup: - $DirGroup — maps to dirGroup (status: legacy) .. index:: single: omfile; $DirGroup single: $DirGroup See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-pollinginterval.rst0000644000000000000000000000013215241075234027346 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.004680517 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-pollinginterval.rst0000664000175000017500000000144015241075234027011 0ustar00rgerrger.. _param-imkubernetes-pollinginterval: .. _imkubernetes.parameter.module.pollinginterval: PollingInterval =============== .. index:: single: imkubernetes; PollingInterval single: PollingInterval .. summary-start Seconds between filesystem scans for matching log files; default ``1``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: PollingInterval :Scope: module :Type: integer :Default: ``1`` :Required?: no :Introduced: 8.2604.0 Description ----------- Controls how often ``imkubernetes`` refreshes the configured glob and tails newly discovered files. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" PollingInterval="1") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omclickhouse-usehttps.rst0000644000000000000000000000013115132733117026003 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.676475081 30 ctime=1787067793.001699096 rsyslog-8.2608.0/doc/source/reference/parameters/omclickhouse-usehttps.rst0000666000175000017500000000156315132733117025457 0ustar00rgerrger.. _param-omclickhouse-usehttps: .. _omclickhouse.parameter.input.usehttps: useHttps ======== .. index:: single: omclickhouse; useHttps single: useHttps single: omclickhouse; usehttps single: usehttps .. summary-start Controls whether HTTPS is used by default when no scheme is specified for the ClickHouse server. .. summary-end This parameter applies to :doc:`/configuration/modules/omclickhouse`. :Name: useHttps :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: not specified Description ----------- Default scheme to use when sending events to ClickHouse if none is specified on a server. Input usage ----------- .. _omclickhouse.parameter.input.usehttps-usage: .. code-block:: rsyslog module(load="omclickhouse") action(type="omclickhouse" useHttps="off") See also -------- See also :doc:`/configuration/modules/omclickhouse`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omprog-binary.rst0000644000000000000000000000013215132733117024227 xustar0030 mtime=1768666703.920620435 30 atime=1787067672.716457184 30 ctime=1787067793.448707426 rsyslog-8.2608.0/doc/source/reference/parameters/omprog-binary.rst0000666000175000017500000000257615132733117023707 0ustar00rgerrger.. _param-omprog-binary: .. _omprog.parameter.action.binary: binary ====== .. index:: single: omprog; binary single: binary .. summary-start Specifies the command line of the external program to execute. .. summary-end This parameter applies to :doc:`../../configuration/modules/omprog`. :Name: binary :Scope: action :Type: string :Default: none :Required?: yes :Introduced: at least 5.x, possibly earlier Description ----------- Full path and command line parameters of the external program to execute. Arbitrary external programs should be placed under the /usr/libexec/rsyslog directory. That is, the binaries put in this namespaced directory are meant for the consumption of rsyslog, and are not intended to be executed by users. In legacy config, it is **not possible** to specify command line parameters. Action usage ------------ .. _param-omprog-action-binary: .. _omprog.parameter.action.binary-usage: .. code-block:: rsyslog action(type="omprog" binary="/usr/libexec/rsyslog/log.sh") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omprog.parameter.legacy.actionomprogbinary: - $ActionOMProgBinary — maps to binary (status: legacy) .. index:: single: omprog; $ActionOMProgBinary single: $ActionOMProgBinary See also -------- See also :doc:`../../configuration/modules/omprog`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmfields-jsonroot.rst0000644000000000000000000000013215132733117025115 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.324449876 30 ctime=1787067792.782695015 rsyslog-8.2608.0/doc/source/reference/parameters/mmfields-jsonroot.rst0000666000175000017500000000156015132733117024565 0ustar00rgerrger.. _param-mmfields-jsonroot: .. _mmfields.parameter.input.jsonroot: jsonroot ======== .. index:: single: mmfields; jsonroot single: jsonroot .. summary-start Sets the JSON path that receives the extracted fields. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmfields`. :Name: jsonroot :Scope: input :Type: string :Default: ``!`` :Required?: no :Introduced: 7.5.1 Description ----------- This parameter specifies into which JSON path the extracted fields shall be written. The default is to use the JSON root object itself. Input usage ----------- .. _param-mmfields-input-jsonroot-usage: .. _mmfields.parameter.input.jsonroot-usage: .. code-block:: rsyslog module(load="mmfields") action(type="mmfields" jsonRoot="!mmfields") See also -------- This parameter is part of the :doc:`../../configuration/modules/mmfields` module. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-notifyonconnectionclose.rst0000644000000000000000000000013215132733117027707 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.703475584 30 ctime=1787067792.365687244 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-notifyonconnectionclose.rst0000666000175000017500000000247015132733117027360 0ustar00rgerrger.. _param-imptcp-notifyonconnectionclose: .. _imptcp.parameter.input.notifyonconnectionclose: NotifyOnConnectionClose ======================= .. index:: single: imptcp; NotifyOnConnectionClose single: NotifyOnConnectionClose .. summary-start Emits a message when a remote peer closes the connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: NotifyOnConnectionClose :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Instructs imptcp to emit a message if a remote peer closes the connection. Input usage ----------- .. _param-imptcp-input-notifyonconnectionclose: .. _imptcp.parameter.input.notifyonconnectionclose-usage: .. code-block:: rsyslog input(type="imptcp" notifyOnConnectionClose="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpservernotifyonconnectionclose: - $InputPTCPServerNotifyOnConnectionClose — maps to NotifyOnConnectionClose (status: legacy) .. index:: single: imptcp; $InputPTCPServerNotifyOnConnectionClose single: $InputPTCPServerNotifyOnConnectionClose See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-serverport.rst0000644000000000000000000000013115132733117025165 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.135464995 30 ctime=1787067793.301704686 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-serverport.rst0000666000175000017500000000140215132733117024631 0ustar00rgerrger.. _param-omhttp-serverport: .. _omhttp.parameter.input.serverport: serverport ========== .. index:: single: omhttp; serverport single: serverport .. summary-start Specifies the TCP port that omhttp uses when connecting to the configured HTTP server. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: serverport :Scope: input :Type: integer :Default: input=443 :Required?: no :Introduced: Not specified Description ----------- The port you want to connect to. Input usage ----------- .. _omhttp.parameter.input.serverport-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" serverPort="8443" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-searchtype.rst0000644000000000000000000000013115132411300026737 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.013444079 29 ctime=1787067793.08670068 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-searchtype.rst0000666000175000017500000000160615132411300026411 0ustar00rgerrger.. _param-omelasticsearch-searchtype: .. _omelasticsearch.parameter.module.searchtype: searchType ========== .. index:: single: omelasticsearch; searchType single: searchType .. summary-start Elasticsearch type to use; empty string omits the type. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: searchType :Scope: action :Type: word :Default: action=events :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Specifies the document type. Set to an empty string to omit the type which is required for Elasticsearch 7 and later. Action usage ------------ .. _param-omelasticsearch-action-searchtype: .. _omelasticsearch.parameter.action.searchtype: .. code-block:: rsyslog action(type="omelasticsearch" searchType="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-template.rst0000644000000000000000000000013215145046112024750 xustar0030 mtime=1771326538.947012786 30 atime=1787067673.210466393 30 ctime=1787067793.426707016 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-template.rst0000664000175000017500000000465715145046112024430 0ustar00rgerrger.. _param-ommysql-template: .. _ommysql.parameter.input.template: Template ======== .. index:: single: ommysql; Template single: Template .. summary-start Specifies the template used to format log records for insertion into the MariaDB/MySQL database. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: template :Scope: input :Type: word :Default: input=StdDBFmt :Required?: no :Introduced: at least 7.x, possibly earlier Description ----------- Rsyslog contains a canned default template to write to the MariaDB/MySQL database. It works on the MonitorWare schema. This template is: .. code-block:: rsyslog template(name="tpl" type="string" string="insert into SystemEvents (Message, Facility, " & "FromHost, Priority, DeviceReportedTime, ReceivedAt, " & "InfoUnitID, SysLogTag) values ('%msg%', " & "%syslogfacility%, '%HOSTNAME%', %syslogpriority%, " & "'%timereported:::date-mysql%', " & "'%timegenerated:::date-mysql%', %iut%, " & "'%syslogtag%')" option.sql="on") As you can see, the template is an actual SQL statement. Note the ``option.sql="on"`` parameter: it tells the template processor that the template is used for SQL processing, thus quote characters are quoted to prevent security issues. You can not assign a template without ``option.sql="on"`` to a MariaDB/MySQL output action. If you would like to change fields contents or add or delete your own fields, you can simply do so by modifying the schema (if required) and creating your own custom template. Input usage ----------- .. _ommysql.parameter.input.template-usage: .. code-block:: rsyslog module(load="ommysql") template(name="tpl" type="string" string="insert into SystemEvents (Message, Facility, " & "FromHost, Priority, DeviceReportedTime, ReceivedAt, " & "InfoUnitID, SysLogTag) values ('%msg%', " & "%syslogfacility%, '%HOSTNAME%', %syslogpriority%, " & "'%timereported:::date-mysql%', " & "'%timegenerated:::date-mysql%', %iut%, " & "'%syslogtag%')" option.sql="on") action(type="ommysql" server="mysqlserver.example.com" db="syslog_db" uid="user" pwd="pwd" template="tpl") See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-permittedpeer.rst0000644000000000000000000000013215145046112026403 xustar0030 mtime=1771326538.955012917 30 atime=1787067672.820459123 30 ctime=1787067793.515708674 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-permittedpeer.rst0000664000175000017500000000524715145046112026057 0ustar00rgerrger.. _param-omrelp-tls-permittedpeer: .. _omrelp.parameter.input.tls-permittedpeer: TLS.PermittedPeer ================= .. index:: single: omrelp; TLS.PermittedPeer single: TLS.PermittedPeer .. summary-start Restricts which peers may connect based on expected names or fingerprints. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: TLS.PermittedPeer :Scope: input :Type: array :Default: input=none :Required?: no :Introduced: at least 7.0.0, possibly earlier Description ----------- Note: this parameter is mandatory depending on the value of `TLS.AuthMode` but the code does currently not check this. Peer Places access restrictions on this forwarder. Only peers which have been listed in this parameter may be connected to. This guards against rogue servers and man-in-the-middle attacks. The validation bases on the certificate the remote peer presents. This contains either remote system names or fingerprints, depending on the value of parameter `TLS.AuthMode`. One or more values may be entered. When a non-permitted peer is connected to, the refusal is logged together with the given remote peer identify. This is especially useful in *fingerprint* authentication mode: if the administrator knows this was a valid request, he can simply add the fingerprint by copy and paste from the logfile to rsyslog.conf. It must be noted, though, that this situation should usually not happen after initial client setup and administrators should be alert in this case. Note that usually a single remote peer should be all that is ever needed. Support for multiple peers is primarily included in support of load balancing scenarios. If the connection goes to a specific server, only one specific certificate is ever expected (just like when connecting to a specific ssh server). To specify multiple fingerprints, just enclose them in braces like this: .. code-block:: rsyslog tls.permittedPeer=["SHA1:...1", "SHA1:....2"] To specify just a single peer, you can either specify the string directly or enclose it in braces. Note that in *name* authentication mode wildcards are supported. This can be done as follows: .. code-block:: rsyslog tls.permittedPeer="*.example.com" Of course, there can also be multiple names used, some with and some without wildcards: .. code-block:: rsyslog tls.permittedPeer=["*.example.com", "srv1.example.net", "srv2.example.net"] Input usage ----------- .. _param-omrelp-input-tls-permittedpeer: .. _omrelp.parameter.input.tls-permittedpeer-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv" tls.permittedPeer="*.example.com") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-region.rst0000644000000000000000000000013215241075234025425 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.972698556 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-region.rst0000664000175000017500000000173215241075234025074 0ustar00rgerrger.. _param-omawslogshlc-region: .. _omawslogshlc.parameter.action.region: .. meta:: :description: Reference for the omawslogshlc region parameter. :keywords: rsyslog, omawslogshlc, region, aws, cloudwatch region ====== .. index:: single: omawslogshlc; region single: region .. summary-start Specifies the AWS region for the CloudWatch Logs HLC endpoint. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: region :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``region`` is used to construct the HLC endpoint URL: ``https://logs..amazonaws.com/services/collector/event``. For example, ``us-west-2`` or ``eu-west-1``. Action usage ------------ .. _omawslogshlc.parameter.action.region-usage: .. code-block:: rsyslog action(type="omawslogshlc" region="us-west-2" ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-permitexpiredcerts.0000644000000000000000000000013215216464435030771 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.886441711 30 ctime=1787067791.387669019 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-permitexpiredcerts.rst0000664000175000017500000000217115216464435031167 0ustar00rgerrger.. _param-imbeats-streamdriver-permitexpiredcerts: .. _imbeats.parameter.input.streamdriver-permitexpiredcerts: StreamDriver.PermitExpiredCerts =============================== .. meta:: :description: Expired certificate policy for imbeats TLS peers. :keywords: rsyslog, imbeats, permitexpiredcerts .. index:: single: imbeats; StreamDriver.PermitExpiredCerts single: StreamDriver.PermitExpiredCerts .. summary-start Control how the imbeats TLS stream driver handles expired peer certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.PermitExpiredCerts :Scope: input :Type: string :Default: input=off :Required?: no :Introduced: 8.2604.0 Description ----------- Control how the imbeats TLS stream driver handles expired peer certificates. Input usage ----------- .. _param-imbeats-input-streamdriver-permitexpiredcerts: .. _imbeats.parameter.input.streamdriver-permitexpiredcerts-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.permitExpiredCerts="off") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-address.rst0000644000000000000000000000013115216464435024517 xustar0030 mtime=1782212893.981265456 30 atime=1787067671.719438598 29 ctime=1787067791.32066777 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-address.rst0000664000175000017500000000161515216464435024167 0ustar00rgerrger.. _param-imbeats-address: .. _imbeats.parameter.input.address: address ======== .. meta:: :description: Bind address for the imbeats listener. :keywords: rsyslog, imbeats, address .. index:: single: imbeats; address single: address .. summary-start Bind the imbeats listener to a specific local address instead of all interfaces. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: address :Scope: input :Type: string :Default: input=all interfaces :Required?: no :Introduced: 8.2604.0 Description ----------- Bind the imbeats listener to a specific local address instead of all interfaces. Input usage ----------- .. _param-imbeats-input-address: .. _imbeats.parameter.input.address-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" address="127.0.0.1") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-freshstarttail.rst0000644000000000000000000000013215241075234027174 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.998680405 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-freshstarttail.rst0000664000175000017500000000156215241075234026644 0ustar00rgerrger.. _param-imkubernetes-freshstarttail: .. _imkubernetes.parameter.module.freshstarttail: FreshStartTail ============== .. index:: single: imkubernetes; FreshStartTail single: FreshStartTail .. summary-start Start newly discovered files at end-of-file instead of replaying existing content; default ``off``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: FreshStartTail :Scope: module :Type: binary :Default: ``off`` :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled, ``imkubernetes`` seeks to the current end of a file the first time it sees that file. Use this when you only want records appended after startup. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" FreshStartTail="on") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-maxsessions.rst0000644000000000000000000000013215132733117025310 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.593473533 30 ctime=1787067792.359687132 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-maxsessions.rst0000666000175000017500000000230015132733117024751 0ustar00rgerrger.. _param-imptcp-maxsessions: .. _imptcp.parameter.module.maxsessions: .. _imptcp.parameter.input.maxsessions: MaxSessions =========== .. index:: single: imptcp; MaxSessions single: MaxSessions .. summary-start Limits the number of open sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: MaxSessions :Scope: module, input :Type: integer :Default: module=0; input=0 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Maximum number of open sessions allowed. When used as a module parameter this value becomes the default inherited by each ``input()`` instance but is not a global maximum. When set inside an input, it applies to that listener. A setting of zero or less than zero means no limit. Module usage ------------ .. _param-imptcp-module-maxsessions: .. _imptcp.parameter.module.maxsessions-usage: .. code-block:: rsyslog module(load="imptcp" maxSessions="...") Input usage ----------- .. _param-imptcp-input-maxsessions: .. _imptcp.parameter.input.maxsessions-usage: .. code-block:: rsyslog input(type="imptcp" maxSessions="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazureeventhubs-template.rst0000644000000000000000000000013015132733117026657 xustar0029 mtime=1768666703.91562036 30 atime=1787067673.510471986 29 ctime=1787067792.93969794 rsyslog-8.2608.0/doc/source/reference/parameters/omazureeventhubs-template.rst0000666000175000017500000000357615132733117026342 0ustar00rgerrger.. _param-omazureeventhubs-template: .. _omazureeventhubs.parameter.input.template: template ======== .. index:: single: omazureeventhubs; template single: template .. summary-start Selects the rsyslog template that formats messages sent to Event Hubs. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazureeventhubs`. :Name: template :Scope: input :Type: word :Default: input=RSYSLOG_FileFormat :Required?: no :Introduced: v8.2304 Description ----------- Specifies the template used to format and structure the log messages that will be sent from rsyslog to Microsoft Azure Event Hubs. The message template can include rsyslog variables, such as the timestamp, hostname, or process name, and it can use rsyslog macros, such as ``$rawmsg`` or ``$json``, to control the formatting of log data. For a message template sample with valid JSON output see the sample below: .. code-block:: rsyslog template(name="generic" type="list" option.jsonf="on") { property(outname="timestamp" name="timereported" dateFormat="rfc3339" format="jsonf") constant(value='"source": "EventHubMessage", ') # Note trailing comma and space for JSON concatenation property(outname="host" name="hostname" format="jsonf") property(outname="severity" name="syslogseverity" caseConversion="upper" format="jsonf" datatype="number") property(outname="facility" name="syslogfacility" format="jsonf" datatype="number") property(outname="appname" name="syslogtag" format="jsonf") property(outname="message" name="msg" format="jsonf" ) property(outname="etlsource" name="$myhostname" format="jsonf") } Input usage ----------- .. _omazureeventhubs.parameter.input.template-usage: .. code-block:: rsyslog action(type="omazureeventhubs" template="generic" ...) See also -------- See also :doc:`../../configuration/modules/omazureeventhubs`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-file.rst0000644000000000000000000000013215132411300023615 xustar0030 mtime=1768559296.210884754 30 atime=1787067672.471452617 30 ctime=1787067793.170702245 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-file.rst0000666000175000017500000000223015132411300023260 0ustar00rgerrger.. _param-omfile-file: .. _omfile.parameter.module.file: File ==== .. index:: single: omfile; File single: File .. summary-start This creates a static file output, always writing into the same file. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: File :Scope: action :Type: string :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This creates a static file output, always writing into the same file. If the file already exists, new data is appended to it. Existing data is not truncated. If the file does not already exist, it is created. Files are kept open as long as rsyslogd is active. This conflicts with external log file rotation. In order to close a file after rotation, send rsyslogd a HUP signal after the file has been rotated away. Either file or dynaFile can be used, but not both. If both are given, dynaFile will be used. Action usage ------------ .. _param-omfile-action-file: .. _omfile.parameter.action.file: .. code-block:: rsyslog action(type="omfile" File="...") See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-unlink.rst0000644000000000000000000000013215132733117024234 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.658474745 30 ctime=1787067792.391687728 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-unlink.rst0000666000175000017500000000144615132733117023707 0ustar00rgerrger.. _param-imptcp-unlink: .. _imptcp.parameter.input.unlink: Unlink ====== .. index:: single: imptcp; Unlink single: Unlink .. summary-start Unlinks a Unix-domain socket before listening and after closing. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Unlink :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If a unix domain socket is being used this controls whether or not the socket is unlinked before listening and after closing. Input usage ----------- .. _param-imptcp-input-unlink: .. _imptcp.parameter.input.unlink-usage: .. code-block:: rsyslog input(type="imptcp" unlink="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omuxsock-networknamespace.rst0000644000000000000000000000013215132733117026656 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.080445328 30 ctime=1787067793.588710035 rsyslog-8.2608.0/doc/source/reference/parameters/omuxsock-networknamespace.rst0000666000175000017500000000443115132733117026326 0ustar00rgerrger.. _param-omuxsock-networknamespace: .. _omuxsock.parameter.module.networknamespace: networkNamespace ================ .. index:: single: omuxsock; networkNamespace single: networkNamespace .. summary-start This is the name of the network namespace. .. summary-end This parameter applies to :doc:`../../configuration/modules/omuxsock`. :Name: networkNamespace :Scope: module, action :Type: string :Default: module=none, action=none :Required?: no :Introduced: v8.2512 Description ----------- Sets a name for the ``networknamespace`` property. If no network namespace is set, the local (startup) network namespace is used by default. The namespace must be created (and interfaces appropriately configured) prior to starting rsyslogd. rsyslogd must be explicitly built with namespace support, otherwise an error will occur when the namespace is subsequently used against an input stream. The underlying operating system must also support the setns() system call, otherwise the input instance will be unable to bind within the given namespace. .. note:: The network namespace should exist as a named file under /var/run/netns/. In particular, the namespace must be created prior to starting rsyslogd. Rsyslogd must be explicitly built with namespace support, otherwise an error will occur when the namespace is subsequently used by an output action. The underlying operating system must also support the setns() system call, otherwise the output action will be unable to operate within the given namespace. Module usage ------------ .. _omuxsock.parameter.networknamespace-usage: If networkNamespace is set at the module level, then it becomes the default networkNamespace setting for all omuxsock actions. .. code-block:: rsyslog module(load="omuxsock" networkNamespace="management") Action usage ------------ .. _omuxsock.parameter.action.networknamespace: An empty string (``""``) can be used at the action level to override a module level ``networkNamespace`` setting and explicitly use the startup network namespace for that action. .. code-block:: rsyslog action(type="omuxsock" socketName="/tmp/example" networkNamespace="routing") action(type="omuxsock" socketName="rsyslogd.msg.handler" networkNamespace="") See also -------- See also :doc:`../../configuration/modules/omuxsock`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-maxbytes.rst0000644000000000000000000000013215132411300026425 xustar0030 mtime=1768559296.208884723 30 atime=1787067672.077445272 30 ctime=1787067793.061700214 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-maxbytes.rst0000666000175000017500000000154715132411300026102 0ustar00rgerrger.. _param-omelasticsearch-maxbytes: .. _omelasticsearch.parameter.module.maxbytes: maxbytes ======== .. index:: single: omelasticsearch; maxbytes single: maxbytes .. summary-start Maximum size of a bulk request body when bulkmode is enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: maxbytes :Scope: action :Type: word :Default: action=100m :Required?: no :Introduced: 8.23.0 Description ----------- Events are batched until this size or the dequeue batch size is reached. Set to match Elasticsearch `http.max_content_length`. Action usage ------------ .. _param-omelasticsearch-action-maxbytes: .. _omelasticsearch.parameter.action.maxbytes: .. code-block:: rsyslog action(type="omelasticsearch" maxbytes="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-ipv4-replacechar.rst0000644000000000000000000000013215132733117026056 xustar0030 mtime=1768666703.912620314 30 atime=1787067671.826440592 30 ctime=1787067792.718693822 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-ipv4-replacechar.rst0000666000175000017500000000233115132733117025523 0ustar00rgerrger.. _param-mmanon-ipv4-replacechar: .. _mmanon.parameter.input.ipv4-replacechar: ipv4.replaceChar ================ .. index:: single: mmanon; ipv4.replaceChar single: ipv4.replaceChar .. summary-start Sets the character used to overwrite anonymized IPv4 octets in simple mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: ipv4.replaceChar :Scope: input :Type: character :Default: input=x :Required?: no :Introduced: 7.3.7 Description ----------- In simple mode, this sets the character that the to-be-anonymized part of the IP address is to be overwritten with. In any other mode the parameter is ignored if set. Input usage ----------- .. _mmanon.parameter.input.ipv4-replacechar-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" ipv4.mode="simple" ipv4.replaceChar="*") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _mmanon.parameter.legacy.replacementchar: - replacementchar — maps to ipv4.replacechar (status: legacy) .. index:: single: mmanon; replacementchar single: replacementchar See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-metricsbasicauthfile.rst0000644000000000000000000000013115171370365027143 xustar0030 mtime=1776677109.117908084 29 atime=1787067672.73445752 30 ctime=1787067792.166683535 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-metricsbasicauthfile.rst0000664000175000017500000000215315171370365026611 0ustar00rgerrger.. meta:: :description: Protect the imhttp metrics endpoint with HTTP Basic Authentication. :keywords: rsyslog, imhttp, metrics, basicauthfile, http basic authentication .. _param-imhttp-metricsbasicauthfile: .. _imhttp.parameter.module.metricsbasicauthfile: .. _imhttp-metricsbasicauthfile: metricsBasicAuthFile ==================== .. index:: single: imhttp; metricsBasicAuthFile single: metricsBasicAuthFile .. summary-start Protects the imhttp Prometheus metrics endpoint with HTTP Basic Authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: metricsBasicAuthFile :Scope: module :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- If set, the metrics endpoint requires HTTP Basic Authentication and expects credentials from an htpasswd file. Module usage ------------ .. _imhttp.parameter.module.metricsbasicauthfile-usage: .. code-block:: rsyslog module( load="imhttp" metricsBasicAuthFile="/etc/rsyslog/htpasswd" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-sortfiles.rst0000644000000000000000000000013215132733117024717 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.348450324 30 ctime=1787067792.110682492 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-sortfiles.rst0000666000175000017500000000206215132733117024365 0ustar00rgerrger.. _param-imfile-sortfiles: .. _imfile.parameter.module.sortfiles: .. _imfile.parameter.sortfiles: sortFiles ========= .. index:: single: imfile; sortFiles single: sortFiles .. summary-start Processes files in sorted order when enabled. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: sortFiles :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.32.0 Description ----------- If this parameter is set to ``on``, the files will be processed in sorted order. Due to the inherent asynchronicity of the operations involved in tracking files, it is not possible to guarantee this sorted order, as it also depends on operation mode and OS timing. Module usage ------------ .. _param-imfile-module-sortfiles: .. _imfile.parameter.module.sortfiles-usage: .. code-block:: rsyslog module(load="imfile" sortFiles="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-allowunsignedcerts.rst0000644000000000000000000000013215132733117030055 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.620455395 30 ctime=1787067792.817695667 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-allowunsignedcerts.rst0000666000175000017500000000176115132733117027530 0ustar00rgerrger.. _param-mmkubernetes-allowunsignedcerts: .. _mmkubernetes.parameter.action.allowunsignedcerts: allowunsignedcerts ================== .. index:: single: mmkubernetes; allowunsignedcerts single: allowunsignedcerts .. summary-start Disables TLS peer certificate verification. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: allowunsignedcerts :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If `"on"`, this will set the curl `CURLOPT_SSL_VERIFYPEER` option to `0`. You are strongly discouraged to set this to `"on"`. It is primarily useful only for debugging or testing. Action usage ------------ .. _param-mmkubernetes-action-allowunsignedcerts: .. _mmkubernetes.parameter.action.allowunsignedcerts-usage: .. code-block:: rsyslog action(type="mmkubernetes" allowUnsignedCerts="on") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-ratelimit-name.rst0000644000000000000000000000013215171370365025637 xustar0030 mtime=1776677109.117908084 30 atime=1787067673.101464361 30 ctime=1787067792.249685082 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-ratelimit-name.rst0000664000175000017500000000123315171370365025302 0ustar00rgerrger.. index:: ! imklog; RateLimit.Name .. _param-imklog-ratelimit-name: RateLimit.Name ============== .. summary-start **Default:** none **Type:** string **Description:** Sets the name of the rate limit to use. The name refers to a :doc:`global rate limit object <../../rainerscript/configuration_objects/ratelimit>` defined in the configuration. **Note:** This parameter is mutually exclusive with ``ratelimitinterval`` and ``ratelimitburst``. If ``ratelimit.name`` is specified, inline rate limit parameters cannot be defined and any attempt to do so will result in an error (and the named rate limit will be used). .. versionadded:: 8.2602.0 .. summary-end rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxsessions.rst0000644000000000000000000000013215241075234025440 xustar0030 mtime=1787067036.579577808 30 atime=1787067036.724580522 30 ctime=1787067791.351668348 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxsessions.rst0000664000175000017500000000265415241075234025113 0ustar00rgerrger.. _param-imbeats-maxsessions: .. _imbeats.parameter.input.maxsessions: maxSessions =========== .. meta:: :description: Maximum simultaneous client sessions accepted by an imbeats input. :keywords: rsyslog, imbeats, maxSessions, Beats sessions, Lumberjack .. index:: single: imbeats; maxSessions single: maxSessions .. summary-start Limit how many simultaneous Beats client sessions an imbeats listener accepts. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxSessions :Scope: input :Type: positive integer :Default: input=1000 :Required?: no :Introduced: 8.2606.0 Description ----------- Set the maximum number of simultaneous client sessions accepted by this ``imbeats`` listener. When the limit is reached, additional connection attempts are rejected while existing sessions continue to run. Use this limit to bound file descriptors, per-session memory, and sender fan-in for a listener. Size it for the number of Beats or Elastic Agent senders that may be connected at the same time, including reconnect overlap during restarts. Values larger than ``UINT_MAX`` are accepted with a warning and capped at ``UINT_MAX``. Input usage ----------- .. _param-imbeats-input-maxsessions: .. _imbeats.parameter.input.maxsessions-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" maxSessions="500") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omazuredce-client_id.rst0000644000000000000000000000013215171370365025535 xustar0030 mtime=1776677109.118908099 30 atime=1787067673.481471445 30 ctime=1787067792.941697978 rsyslog-8.2608.0/doc/source/reference/parameters/omazuredce-client_id.rst0000664000175000017500000000200115171370365025172 0ustar00rgerrger.. _param-omazuredce-client_id: .. _omazuredce.parameter.action.client_id: .. meta:: :description: Reference for the omazuredce client_id parameter. :keywords: rsyslog, omazuredce, client_id, azure, entra client_id ========= .. index:: single: omazuredce; client_id single: client_id .. summary-start Specifies the Microsoft Entra application client ID used for OAuth token requests. .. summary-end This parameter applies to :doc:`../../configuration/modules/omazuredce`. :Name: client_id :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``client_id`` identifies the Azure application that requests access tokens for the Logs Ingestion API. It is used together with ``client_secret`` and ``tenant_id``. Action usage ------------ .. _omazuredce.parameter.action.client_id-usage: .. code-block:: rsyslog action(type="omazuredce" client_id="" ...) See also -------- See also :doc:`../../configuration/modules/omazuredce`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdtls-tls-tlscfgcmd.rst0000644000000000000000000000013215132733117025502 xustar0030 mtime=1768666703.903620178 30 atime=1787067672.089445495 30 ctime=1787067792.042681225 rsyslog-8.2608.0/doc/source/reference/parameters/imdtls-tls-tlscfgcmd.rst0000666000175000017500000000315215132733117025151 0ustar00rgerrger.. _param-imdtls-tls-tlscfgcmd: .. _imdtls.parameter.input.tls-tlscfgcmd: tls.tlsCfgCmd ============= .. index:: single: imdtls; tls.tlsCfgCmd single: tls.tlsCfgCmd .. summary-start Passes additional OpenSSL configuration commands to fine-tune DTLS handling. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdtls`. :Name: tls.tlsCfgCmd :Scope: input :Type: string :Default: none :Required?: no :Introduced: v8.2402.0 Description ----------- Used to pass additional OpenSSL configuration commands. This can be used to fine-tune the OpenSSL settings by passing configuration commands to the OpenSSL library. OpenSSL version 1.0.2 or higher is required for this feature. A list of possible commands and their valid values can be found in the `documentation `_. The setting can be single or multiline, each configuration command is separated by linefeed (``\n``). Command and value are separated by equal sign (``=``). Examples ~~~~~~~~ This will allow all protocols except for SSLv2 and SSLv3: .. code-block:: none tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3" This will allow all protocols except for SSLv2, SSLv3 and TLSv1 and will also set the minimum protocol to TLSv1.2: .. code-block:: none tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1\nMinProtocol=TLSv1.2" Input usage ----------- .. _imdtls.parameter.input.tls-tlscfgcmd-usage: .. code-block:: rsyslog module(load="imdtls") input(type="imdtls" tls.tlsCfgCmd="Protocol=ALL,-SSLv2,-SSLv3") See also -------- See also :doc:`../../configuration/modules/imdtls`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-skipverifyhost.rst0000644000000000000000000000013215132733117027232 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.712457109 30 ctime=1787067792.849696263 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-skipverifyhost.rst0000666000175000017500000000172715132733117026707 0ustar00rgerrger.. _param-mmkubernetes-skipverifyhost: .. _mmkubernetes.parameter.action.skipverifyhost: skipverifyhost ============== .. index:: single: mmkubernetes; skipverifyhost single: skipverifyhost .. summary-start Skips verification of the Kubernetes API server hostname. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: skipverifyhost :Scope: action :Type: boolean :Default: off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- If `"on"`, this will set the curl `CURLOPT_SSL_VERIFYHOST` option to `0`. You are strongly discouraged to set this to `"on"`. It is primarily useful only for debugging or testing. Action usage ------------ .. _param-mmkubernetes-action-skipverifyhost: .. _mmkubernetes.parameter.action.skipverifyhost-usage: .. code-block:: rsyslog action(type="mmkubernetes" skipVerifyHost="on") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imudp-batchsize.rst0000644000000000000000000000013215132733117024532 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.165484197 30 ctime=1787067792.562690915 rsyslog-8.2608.0/doc/source/reference/parameters/imudp-batchsize.rst0000666000175000017500000000266115132733117024205 0ustar00rgerrger.. _param-imudp-batchsize: .. _imudp.parameter.module.batchsize: BatchSize ========= .. index:: single: imudp; BatchSize single: BatchSize .. summary-start Maximum messages retrieved per ``recvmmsg()`` call when available. .. summary-end This parameter applies to :doc:`../../configuration/modules/imudp`. :Name: BatchSize :Scope: module :Type: integer :Default: module=32 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This parameter is only meaningful if the system supports ``recvmmsg()`` (newer Linux systems do this). The parameter is silently ignored if the system does not support it. If supported, it sets the maximum number of UDP messages that can be obtained with a single OS call. For systems with high UDP traffic, a relatively high batch size can reduce system overhead and improve performance. However, this parameter should not be overdone. For each buffer, max message size bytes are statically required. Also, a too-high number leads to reduced efficiency, as some structures need to be completely initialized before the OS call is done. We would suggest to not set it above a value of 128, except if experimental results show that this is useful. Module usage ------------ .. _param-imudp-module-batchsize: .. _imudp.parameter.module.batchsize-usage: .. code-block:: rsyslog module(load="imudp" BatchSize="...") See also -------- See also :doc:`../../configuration/modules/imudp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-server.rst0000644000000000000000000000013115132733117024260 xustar0029 mtime=1768666703.91762039 30 atime=1787067673.131464921 30 ctime=1787067793.298704631 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-server.rst0000666000175000017500000000155115132733117023731 0ustar00rgerrger.. _param-omhttp-server: .. _omhttp.parameter.input.server: server ====== .. index:: single: omhttp; server single: server .. summary-start Defines the list of HTTP server hostnames or IP addresses that omhttp connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: server :Scope: input :Type: array :Default: input=localhost :Required?: no :Introduced: Not specified Description ----------- The server address you want to connect to. Specify one or more entries to enable client-side load-balancing behavior provided by libcurl. Input usage ----------- .. _omhttp.parameter.input.server-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" server=["api1.example.net", "api2.example.net"] ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-interval.rst0000644000000000000000000000013215132733117025130 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.444470756 30 ctime=1787067792.269685455 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-interval.rst0000666000175000017500000000212315132733117024574 0ustar00rgerrger.. _param-impstats-interval: .. _impstats.parameter.module.interval: interval ======== .. index:: single: impstats; interval single: interval .. summary-start Configures how often, in seconds, impstats emits statistics messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: interval :Scope: module :Type: integer (seconds) :Default: module=300 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Sets the interval, in **seconds**, at which messages are generated. Please note that the actual interval may be a bit longer. We do not try to be precise and so the interval is actually a sleep period which is entered after generating all messages. So the actual interval is what is configured here plus the actual time required to generate messages. In general, the difference should not really matter. Module usage ------------ .. _impstats.parameter.module.interval-usage: .. code-block:: rsyslog module(load="impstats" interval="600") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/im3195-input3195listenport.rst0000644000000000000000000000013115132733117026173 xustar0030 mtime=1768666703.903620178 29 atime=1787067672.32944997 30 ctime=1787067791.927679082 rsyslog-8.2608.0/doc/source/reference/parameters/im3195-input3195listenport.rst0000666000175000017500000000211515132733117025641 0ustar00rgerrger.. _param-im3195-input3195listenport: .. _im3195.parameter.module.input3195listenport: Input3195ListenPort ------------------- .. index:: single: im3195; Input3195ListenPort single: im3195; $Input3195ListenPort .. summary-start The TCP port on which im3195 listens for RFC 3195 messages. The default is 601. .. summary-end This parameter applies to :doc:`../../configuration/modules/im3195`. .. note:: This is a legacy global directive. The im3195 module does not support the modern ``input()`` syntax. :Name: Input3195ListenPort :Scope: module :Type: integer :Default: 601 :Required?: no :Introduced: Not documented Description ~~~~~~~~~~~ The default port is 601, the IANA-assigned port for the BEEP protocol on which RFC 3195 is based. Since directive names are case-insensitive, the PascalCase form ``$Input3195ListenPort`` is recommended for readability. Module usage ~~~~~~~~~~~~ .. _im3195.parameter.module.input3195listenport-usage: .. code-block:: rsyslog $ModLoad im3195 $Input3195ListenPort 1601 See also ~~~~~~~~ :doc:`../../configuration/modules/im3195` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omsnmp-messageoid.rst0000644000000000000000000000013215132733117025071 xustar0030 mtime=1768666703.923620481 30 atime=1787067671.775439642 30 ctime=1787067793.543709196 rsyslog-8.2608.0/doc/source/reference/parameters/omsnmp-messageoid.rst0000666000175000017500000000301515132733117024536 0ustar00rgerrger.. _param-omsnmp-messageoid: .. _omsnmp.parameter.module.messageoid: MessageOID ========== .. index:: single: omsnmp; MessageOID single: MessageOID .. summary-start Specifies the OID for the message variable carrying the syslog text. .. summary-end This parameter applies to :doc:`../../configuration/modules/omsnmp`. :Name: MessageOID :Scope: module :Type: string :Default: module=1.3.6.1.4.1.19406.1.2.1 :Required?: no :Introduced: at least 7.3.0, possibly earlier Description ----------- This OID will be used as a variable, type "OCTET STRING". This variable will contain up to 255 characters of the original syslog message including syslog header. It is recommend to use the default OID. In order to decode this OID, you will need to have the ADISCON-MONITORWARE-MIB and ADISCON-MIB mibs installed on the receiver side. To download these custom mibs, see the description of :ref:`param-omsnmp-trapoid`. Module usage ------------ .. _param-omsnmp-module-messageoid: .. _omsnmp.parameter.module.messageoid-usage: .. code-block:: rsyslog action(type="omsnmp" messageOID="1.3.6.1.4.1.19406.1.2.1") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omsnmp.parameter.legacy.actionsnmpsyslogmessageoid: - $actionsnmpsyslogmessageoid — maps to MessageOID (status: legacy) .. index:: single: omsnmp; $actionsnmpsyslogmessageoid single: $actionsnmpsyslogmessageoid See also -------- See also :doc:`../../configuration/modules/omsnmp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-includenamespacemetadata.rs0000644000000000000000000000013215241075234030756 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.846696207 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-includenamespacemetadata.rst0000664000175000017500000000305215241075234030606 0ustar00rgerrger.. meta:: :description: Control whether mmkubernetes queries and adds Kubernetes namespace metadata. :keywords: rsyslog, mmkubernetes, namespace, metadata, Kubernetes .. _param-mmkubernetes-includenamespacemetadata: .. _mmkubernetes.parameter.action.includenamespacemetadata: includeNamespaceMetadata ======================== .. index:: single: mmkubernetes; includeNamespaceMetadata single: includeNamespaceMetadata .. summary-start Controls whether mmkubernetes queries and adds namespace metadata. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: includeNamespaceMetadata :Scope: module, action :Type: boolean :Default: on :Required?: no :Introduced: 8.2608.0 Description ----------- When set to ``off``, mmkubernetes does not query the Kubernetes namespace API and does not add ``namespace_id``, ``namespace_labels``, ``namespace_annotations``, or the namespace ``creation_timestamp``. The ``namespace_name`` parsed from the input metadata is still added because it is needed to identify and query the pod. Disabling namespace metadata can reduce Kubernetes API traffic and avoids collecting namespace labels and annotations when they are not needed. Pod metadata collection is unchanged. Action usage ------------ .. code-block:: rsyslog action(type="mmkubernetes" includeNamespaceMetadata="off") YAML usage ---------- .. code-block:: yaml actions: - type: mmkubernetes includeNamespaceMetadata: off See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-filegroupnum.rst0000644000000000000000000000013215132733117025450 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.641474428 30 ctime=1787067792.332686629 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-filegroupnum.rst0000666000175000017500000000170015132733117025114 0ustar00rgerrger.. _param-imptcp-filegroupnum: .. _imptcp.parameter.input.filegroupnum: FileGroupNum ============ .. index:: single: imptcp; FileGroupNum single: FileGroupNum .. summary-start Sets the group of the Unix-domain socket by numeric GID. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FileGroupNum :Scope: input :Type: integer :Default: input=system default :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the group for the domain socket. The parameter is a numerical ID, which is used regardless of whether the group actually exists. This can be useful if the group mapping is not available to rsyslog during startup. Input usage ----------- .. _param-imptcp-input-filegroupnum: .. _imptcp.parameter.input.filegroupnum-usage: .. code-block:: rsyslog input(type="imptcp" fileGroupNum="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-compression-mode.rst0000644000000000000000000000013215216464435026226 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.757476591 30 ctime=1787067792.319686387 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-compression-mode.rst0000664000175000017500000000752515216464435025703 0ustar00rgerrger.. _param-imptcp-compression-mode: .. _imptcp.parameter.input.compression-mode: Compression.mode ================ .. index:: single: imptcp; Compression.mode single: Compression.mode .. summary-start Selects decompression mode matching compression used by omfwd. Supports auto-detection so a single listener accepts both compressed and plain peers. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Compression.mode :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This is the counterpart to the compression modes set in :doc:`omfwd <../../configuration/modules/omfwd>`. ``imptcp`` accepts the following values: - ``none`` - do not attempt stream decompression. - ``stream:always`` - treat the full TCP byte stream as a zlib-compressed stream generated by :doc:`omfwd <../../configuration/modules/omfwd>` with ``compression.mode="stream:always"``. - ``stream:auto`` - sniff the first two bytes of each session, lock-in the verdict for the remainder of the connection. Lets a single listener accept compressed and plain peers simultaneously (staged client roll-out). This receive path is a fixed-policy implementation: - it uses streaming zlib decompression during normal receives, - it performs a final decompression drain when the TCP session closes, - it is compatible with sender-side ``compression.stream.flushOnTXEnd="on"`` and ``"off"``, - it logs malformed or truncated compressed streams and closes the session. ``imptcp`` does not support the sender-side ``single`` compression mode here. Accepted values --------------- ``none`` No stream decompression. Per-message single-message compression (the legacy ``z``-prefixed payload) is still decoded by the parser stage. ``stream:always`` Every accepted session is treated as a zlib stream (RFC 1950). Plain peers connecting to the listener will be rejected after the first failed ``inflate()`` call. ``stream:auto`` *(since v8.2606.0)* The first two bytes of each session are inspected to decide whether the peer is sending a zlib stream or plain syslog. Once the decision is made it is locked-in for the lifetime of the session, so the hot path stays branch-free after the initial probe. This is intended for staged client roll-outs where a single listener must accept both compressed and uncompressed peers while the fleet of senders (typically :doc:`omfwd <../../configuration/modules/omfwd>`) is migrated one peer at a time. **Detection rules.** A session is treated as compressed if and only if the first byte is ``0x78`` (zlib CMF for deflate, 32 KiB window - what ``omfwd`` emits via ``deflateInit()``), the two-byte FCHECK value is valid, and the FDICT bit is clear. Any other byte sequence selects the plain path; a plain syslog frame always starts with an ASCII digit (octet-counted framing) or ``<`` (non-transparent framing), so the test is conclusive for any rsyslog-to-rsyslog deployment and for every standard 3rd-party syslog sender we know of. **Caveats.** * Custom senders that emit raw deflate (RFC 1951, no zlib wrapper) are not detected. Use ``stream:always`` for those. * Senders that intentionally build a zlib stream with a non-default window size (CMF != ``0x78``) are not detected as compressed. This is a deliberate tightening of the probe to avoid false positives against octet-counted plain framing. * Detection is per session, never per message; flipping a peer between modes requires a new TCP connection. Input usage ----------- .. _param-imptcp-input-compression-mode: .. _imptcp.parameter.input.compression-mode-usage: .. code-block:: rsyslog input(type="imptcp" compression.mode="stream:auto") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-disablelfdelimiter.rst0000644000000000000000000000013215132733117026400 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.901479275 30 ctime=1787067792.468689163 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-disablelfdelimiter.rst0000666000175000017500000000406515132733117026053 0ustar00rgerrger.. _param-imtcp-disablelfdelimiter: .. _imtcp.parameter.module.disablelfdelimiter: .. _imtcp.parameter.input.disablelfdelimiter: DisableLFDelimiter ================== .. index:: single: imtcp; DisableLFDelimiter single: DisableLFDelimiter .. summary-start Disables LF as a frame delimiter to allow a custom delimiter. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: DisableLFDelimiter :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Industry-standard plain text tcp syslog uses the LF to delimit syslog frames. However, some users brought up the case that it may be useful to define a different delimiter and totally disable LF as a delimiter (the use case named were multi-line messages). This mode is non-standard and will probably come with a lot of problems. However, as there is need for it and it is relatively easy to support, we do so. Be sure to turn this setting to "on" only if you exactly know what you are doing. You may run into all sorts of troubles, so be prepared to wrangle with that! The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-disablelfdelimiter: .. _imtcp.parameter.module.disablelfdelimiter-usage: .. code-block:: rsyslog module(load="imtcp" disableLFDelimiter="on") Input usage ----------- .. _param-imtcp-input-disablelfdelimiter: .. _imtcp.parameter.input.disablelfdelimiter-usage: .. code-block:: rsyslog input(type="imtcp" port="514" disableLFDelimiter="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverdisablelfdelimiter: - $InputTCPServerDisableLFDelimiter — maps to DisableLFDelimiter (status: legacy) .. index:: single: imtcp; $InputTCPServerDisableLFDelimiter single: $InputTCPServerDisableLFDelimiter See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommail-server.rst0000644000000000000000000000013215216464435024233 xustar0030 mtime=1782212893.989265586 30 atime=1787067672.886460353 30 ctime=1787067793.400706531 rsyslog-8.2608.0/doc/source/reference/parameters/ommail-server.rst0000664000175000017500000000254715216464435023707 0ustar00rgerrger.. _param-ommail-server: .. _ommail.parameter.input.server: server ====== .. index:: single: ommail; server single: server .. summary-start Specifies the hostname or IP address of the SMTP server used by ommail SMTP-mode actions. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommail`. :Name: server :Scope: input :Type: word :Default: input=none :Required?: yes :Introduced: 8.5.0 Description ----------- Name or IP address of the SMTP server to be used by ``mode="smtp"``. While a default of 127.0.0.1 (the local machine) exists for legacy configurations, this parameter is required for modern SMTP-mode configurations. It is not used by ``mode="sendmail"``. Input usage ------------ .. _ommail.parameter.input.server-usage: .. code-block:: rsyslog module(load="ommail") action( type="ommail" server="mail.example.net" port="25" mailFrom="rsyslog@example.net" mailTo="operator@example.net" ) Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommail.parameter.legacy.actionmailsmtpserver: - $ActionMailSMTPServer — maps to server (status: legacy) .. index:: single: ommail; $ActionMailSMTPServer single: $ActionMailSMTPServer See also -------- See also :doc:`../../configuration/modules/ommail`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-filecreatemode.rst0000644000000000000000000000013115132733117025703 xustar0030 mtime=1768666703.906620223 29 atime=1787067673.64747454 30 ctime=1787067792.328686554 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-filecreatemode.rst0000666000175000017500000000206715132733117025357 0ustar00rgerrger.. _param-imptcp-filecreatemode: .. _imptcp.parameter.input.filecreatemode: FileCreateMode ============== .. index:: single: imptcp; FileCreateMode single: FileCreateMode .. summary-start Sets access permissions for the Unix-domain socket. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: FileCreateMode :Scope: input :Type: octalNumber :Default: input=0644 :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Set the access permissions for the domain socket. The value given must always be a 4-digit octal number, with the initial digit being zero. Please note that the actual permission depend on rsyslogd's process umask. If in doubt, use "``$umask 0000``" right at the beginning of the configuration file to remove any restrictions. Input usage ----------- .. _param-imptcp-input-filecreatemode: .. _imptcp.parameter.input.filecreatemode-usage: .. code-block:: rsyslog input(type="imptcp" fileCreateMode="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/immark-markmessagetext.rst0000644000000000000000000000013215132733117026124 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.304468146 30 ctime=1787067792.254685175 rsyslog-8.2608.0/doc/source/reference/parameters/immark-markmessagetext.rst0000666000175000017500000000210115132733117025564 0ustar00rgerrger.. _param-immark-markmessagetext: .. _immark.parameter.module.markmessagetext: markMessageText ================ .. index:: single: immark; markMessageText single: markMessageText .. summary-start Overrides the text that immark injects for each mark message. .. summary-end This parameter applies to :doc:`../../configuration/modules/immark`. :Name: markMessageText :Scope: module :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: module="-- MARK --" :Required?: no :Introduced: 8.2012.0 Description ----------- Provide a custom string that immark uses when it emits the periodic mark message. If unset, immark falls back to the historical ``-- MARK --`` text. The string may include whitespace and other characters supported by :doc:`../../rainerscript/constant_strings`. Module usage ------------ .. _immark.parameter.module.markmessagetext-usage: .. code-block:: rsyslog module(load="immark" markMessageText="-- CUSTOM MARK --") See also -------- .. seealso:: * :ref:`param-immark-interval` * :doc:`../../configuration/modules/immark` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-filenamerules.rst0000644000000000000000000000013215132733117026774 xustar0030 mtime=1768666703.914620344 30 atime=1787067672.689456681 30 ctime=1787067792.842696133 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-filenamerules.rst0000666000175000017500000000237615132733117026452 0ustar00rgerrger.. _param-mmkubernetes-filenamerules: .. _mmkubernetes.parameter.action.filenamerules: filenamerules ============= .. index:: single: mmkubernetes; filenamerules single: filenamerules .. summary-start Defines lognorm rules to parse json-file log filenames for metadata. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: filenamerules :Scope: action :Type: word :Default: SEE BELOW :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- .. note:: This directive is not supported with liblognorm 2.0.2 and earlier. When processing json-file logs, these are the lognorm rules to use to match the filename and extract metadata. The default value is:: rule=:/var/log/containers/%pod_name:char-to:_%_%namespace_name:char-to:_%_%contai\ ner_name_and_id:char-to:.%.log .. note:: In the above rules, the slashes ``\`` ending each line indicate line wrapping - they are not part of the rule. Action usage ------------ .. _param-mmkubernetes-action-filenamerules: .. _mmkubernetes.parameter.action.filenamerules-usage: .. code-block:: rsyslog action(type="mmkubernetes" filenameRules="...") See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-flowcontrol.rst0000644000000000000000000000013215132733117025304 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.763476702 30 ctime=1787067792.339686759 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-flowcontrol.rst0000666000175000017500000000153715132733117024760 0ustar00rgerrger.. _param-imptcp-flowcontrol: .. _imptcp.parameter.input.flowcontrol: flowControl =========== .. index:: single: imptcp; flowControl single: flowControl .. summary-start Throttles the sender when the receiver queue is nearly full. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: flowControl :Scope: input :Type: boolean :Default: input=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Flow control is used to throttle the sender if the receiver queue is near-full preserving some space for input that can not be throttled. Input usage ----------- .. _param-imptcp-input-flowcontrol: .. _imptcp.parameter.input.flowcontrol-usage: .. code-block:: rsyslog input(type="imptcp" flowControl="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-log-syslog.rst0000644000000000000000000000013215216464435025412 xustar0030 mtime=1782212893.985265521 30 atime=1787067673.456470979 30 ctime=1787067792.276685585 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-log-syslog.rst0000664000175000017500000000227015216464435025057 0ustar00rgerrger.. _param-impstats-log-syslog: .. _impstats.parameter.module.log-syslog: log.syslog ========== .. index:: single: impstats; log.syslog single: log.syslog .. summary-start Enables or disables sending statistics to the regular syslog stream. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: log.syslog :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- This is a boolean setting specifying if data should be sent to the usual syslog stream. This is useful if custom formatting or more elaborate processing is desired. However, output is placed under the same restrictions as regular syslog data, especially in regard to the queue position (stats data may sit for an extended period of time in queues if they are full). If set to ``off``, the :ref:`param-impstats-ruleset` parameter cannot be used, as syslog stream processing is required for rulesets. Module usage ------------ .. _impstats.parameter.module.log-syslog-usage: .. code-block:: rsyslog module(load="impstats" log.syslog="off") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-notifyonconnectionopen.rst0000644000000000000000000000013215132733117027543 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.710475714 30 ctime=1787067792.367687281 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-notifyonconnectionopen.rst0000666000175000017500000000167315132733117027220 0ustar00rgerrger.. _param-imptcp-notifyonconnectionopen: .. _imptcp.parameter.input.notifyonconnectionopen: NotifyOnConnectionOpen ====================== .. index:: single: imptcp; NotifyOnConnectionOpen single: NotifyOnConnectionOpen .. summary-start Emits a message when a remote peer opens a connection. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: NotifyOnConnectionOpen :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Instructs imptcp to emit a message if a remote peer opens a connection. Hostname of the remote peer is given in the message. Input usage ----------- .. _param-imptcp-input-notifyonconnectionopen: .. _imptcp.parameter.input.notifyonconnectionopen-usage: .. code-block:: rsyslog input(type="imptcp" notifyOnConnectionOpen="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omkafka-partitions-auto.rst0000644000000000000000000000013215132411300026176 xustar0030 mtime=1768559296.212884786 30 atime=1787067673.078463933 30 ctime=1787067793.351705618 rsyslog-8.2608.0/doc/source/reference/parameters/omkafka-partitions-auto.rst0000666000175000017500000000176115132411300025651 0ustar00rgerrger.. _param-omkafka-partitions-auto: .. _omkafka.parameter.module.partitions-auto: Partitions.Auto =============== .. index:: single: omkafka; Partitions.Auto single: Partitions.Auto .. summary-start Use librdkafka's automatic partitioning. .. summary-end This parameter applies to :doc:`../../configuration/modules/omkafka`. :Name: Partitions.Auto :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Librdkafka provides an automatic partitioning function that distributes messages into all partitions configured for a topic. Action usage ------------ .. _param-omkafka-action-partitions-auto: .. _omkafka.parameter.action.partitions-auto: .. code-block:: rsyslog action(type="omkafka" Partitions.Auto="on") Notes ----- - Originally documented as "binary"; uses boolean values. - Overrides other partitioning settings when enabled. See also -------- See also :doc:`../../configuration/modules/omkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omudpspoof-port.rst0000644000000000000000000000013215145046112024613 xustar0030 mtime=1771326538.957012949 30 atime=1787067671.943442774 30 ctime=1787067793.570709699 rsyslog-8.2608.0/doc/source/reference/parameters/omudpspoof-port.rst0000664000175000017500000000211715145046112024260 0ustar00rgerrger.. _param-omudpspoof-port: .. _omudpspoof.parameter.action.port: port ==== .. index:: single: omudpspoof; port single: port .. summary-start Specifies the destination port used when sending messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/omudpspoof`. :Name: port :Scope: action :Type: word :Default: 514 :Required?: no :Introduced: 5.1.3 Description ----------- Remote port that the messages shall be sent to. Default is 514. Action usage ------------ .. _param-omudpspoof-action-port: .. _omudpspoof.parameter.action.port-usage: .. code-block:: rsyslog action(type="omudpspoof" target="192.0.2.1" port="10514") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omudpspoof.parameter.legacy.actionomudpspooftargetport: - $ActionOMUDPSpoofTargetPort — maps to port (status: legacy) .. index:: single: omudpspoof; $ActionOMUDPSpoofTargetPort single: $ActionOMUDPSpoofTargetPort See also -------- See also :doc:`../../configuration/modules/omudpspoof`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-msgdiscardingerror.rst0000644000000000000000000000013215132733117026575 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.493453027 30 ctime=1787067792.088682082 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-msgdiscardingerror.rst0000666000175000017500000000217015132733117026243 0ustar00rgerrger.. _param-imfile-msgdiscardingerror: .. _imfile.parameter.input.msgdiscardingerror: .. _imfile.parameter.msgdiscardingerror: msgDiscardingError ================== .. index:: single: imfile; msgDiscardingError single: msgDiscardingError .. summary-start Controls whether an error is logged when a message is truncated. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: msgDiscardingError :Scope: input :Type: boolean :Default: on :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- By default an error message is emitted when a message is truncated. If ``msgDiscardingError`` is ``off``, no error is shown upon truncation. Input usage ----------- .. _param-imfile-input-msgdiscardingerror: .. _imfile.parameter.input.msgdiscardingerror-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" msgDiscardingError="on") Notes ----- - Legacy documentation used the term ``binary`` for the type. It is treated as boolean. See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-discardtruncatedmsg.rst0000644000000000000000000000013215132733117026766 xustar0030 mtime=1768666703.906620223 30 atime=1787067673.618473999 30 ctime=1787067792.323686461 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-discardtruncatedmsg.rst0000666000175000017500000000201015132733117026425 0ustar00rgerrger.. _param-imptcp-discardtruncatedmsg: .. _imptcp.parameter.input.discardtruncatedmsg: DiscardTruncatedMsg =================== .. index:: single: imptcp; DiscardTruncatedMsg single: DiscardTruncatedMsg .. summary-start Discards the remaining part of a message after truncation. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: DiscardTruncatedMsg :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- When a message is split because it is too long the second part is normally processed as the next message. This can cause problems. When this parameter is turned on the part of the message after the truncation will be discarded. Input usage ----------- .. _param-imptcp-input-discardtruncatedmsg: .. _imptcp.parameter.input.discardtruncatedmsg-usage: .. code-block:: rsyslog input(type="imptcp" discardTruncatedMsg="...") See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-tokenfile.rst0000644000000000000000000000013215241075234026115 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.015680722 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-tokenfile.rst0000664000175000017500000000171215241075234025562 0ustar00rgerrger.. _param-imkubernetes-tokenfile: .. _imkubernetes.parameter.module.tokenfile: TokenFile ========= .. index:: single: imkubernetes; TokenFile single: TokenFile .. summary-start Path to a file containing the Kubernetes API bearer token; default ``/var/run/secrets/kubernetes.io/serviceaccount/token``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: TokenFile :Scope: module :Type: path :Default: ``/var/run/secrets/kubernetes.io/serviceaccount/token`` :Required?: no :Introduced: 8.2604.0 Description ----------- If :ref:`Token ` is not set, ``imkubernetes`` reads the first line from this file and uses it as the bearer token for Kubernetes API requests. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" TokenFile="/var/run/secrets/kubernetes.io/serviceaccount/token") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-broker.rst0000644000000000000000000000013215132733117024327 xustar0030 mtime=1768666703.905620208 30 atime=1787067672.967461863 30 ctime=1787067792.216684467 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-broker.rst0000666000175000017500000000154015132733117023775 0ustar00rgerrger.. _param-imkafka-broker: .. _imkafka.parameter.input.broker: broker ====== .. index:: single: imkafka; broker single: broker .. summary-start Selects the Kafka broker(s) imkafka connects to when consuming messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: broker :Scope: input :Type: array :Default: input=``localhost:9092`` :Required?: no :Introduced: 8.27.0 Description ----------- Specifies the broker or brokers to use. Provide a single Kafka address or a list of bootstrap servers for a cluster. Input usage ----------- .. _imkafka.parameter.input.broker-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="your-topic" broker=["localhost:9092", "localhost:9093"]) See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-ruleset.rst0000644000000000000000000000013215132733117024237 xustar0030 mtime=1768666703.909620269 30 atime=1787067674.168484252 30 ctime=1787067792.518690095 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-ruleset.rst0000666000175000017500000000217615132733117023713 0ustar00rgerrger.. _param-imtcp-ruleset: .. _imtcp.parameter.input.ruleset: Ruleset ======= .. index:: single: imtcp; Ruleset single: Ruleset .. summary-start Binds the listener to a specific ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: Ruleset :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Binds the listener to a specific :doc:`ruleset <../../concepts/multi_ruleset>`. Input usage ----------- .. _param-imtcp-input-ruleset: .. _imtcp.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imtcp" port="514" ruleset="remote") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverbindruleset: - $InputTCPServerBindRuleset — maps to Ruleset (status: legacy) .. index:: single: imtcp; $InputTCPServerBindRuleset single: $InputTCPServerBindRuleset See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-prioritystring.rst0000644000000000000000000000013215132733117026640 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.943480058 30 ctime=1787067792.439688623 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-prioritystring.rst0000666000175000017500000000272515132733117026314 0ustar00rgerrger.. _param-imrelp-tls-prioritystring: .. _imrelp.parameter.input.tls-prioritystring: tls.priorityString ================== .. index:: single: imrelp; tls.priorityString single: tls.priorityString .. summary-start Passes a custom GnuTLS priority string to fine-tune cryptographic parameters. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.priorityString :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- This parameter allows passing the so-called "priority string" to GnuTLS. This string gives complete control over all crypto parameters, including compression settings. For this reason, when ``tls.priorityString`` is specified, the :ref:`param-imrelp-tls-compression` parameter has no effect and is ignored. Full information about how to construct a priority string can be found in the GnuTLS manual. At the time of writing, this information was contained in `section 6.10 of the GnuTLS manual `_. **Note: this is an expert parameter.** Do not use if you do not exactly know what you are doing. Input usage ----------- .. _param-imrelp-input-tls-prioritystring-usage: .. _imrelp.parameter.input.tls-prioritystring-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.priorityString="NONE:+COMP-DEFLATE") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-ruleset-input.rst0000644000000000000000000000013115132733117025547 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.881478902 29 ctime=1787067792.41968825 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-ruleset-input.rst0000666000175000017500000000151215132733117025215 0ustar00rgerrger.. _param-imrelp-ruleset-input: .. _imrelp.parameter.input.ruleset: ruleset ======= .. index:: single: imrelp; ruleset (input) single: ruleset (imrelp input) .. summary-start Overrides the module-wide ruleset binding for this specific RELP listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: ruleset :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- Binds the specified ruleset to this listener. This overrides the module-level ruleset parameter. Input usage ----------- .. _param-imrelp-input-ruleset-usage: .. _imrelp.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" ruleset="relpListenerRules") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omelasticsearch-uid.rst0000644000000000000000000000013115132733117025366 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.097445645 29 ctime=1787067793.11570122 rsyslog-8.2608.0/doc/source/reference/parameters/omelasticsearch-uid.rst0000666000175000017500000000151615132733117025040 0ustar00rgerrger.. _param-omelasticsearch-uid: .. _omelasticsearch.parameter.module.uid: uid === .. index:: single: omelasticsearch; uid single: uid .. summary-start User name for basic HTTP authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/omelasticsearch`. :Name: uid :Scope: action :Type: word :Default: action=none :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Supplies the user name when Elasticsearch requires basic authentication. This parameter cannot be combined with :ref:`param-omelasticsearch-apikey`. Action usage ------------ .. _param-omelasticsearch-action-uid: .. _omelasticsearch.parameter.action.uid: .. code-block:: rsyslog action(type="omelasticsearch" uid="...") See also -------- See also :doc:`../../configuration/modules/omelasticsearch`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-max_scan_bytes.rst0000644000000000000000000000013115132733117026774 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.366450659 29 ctime=1787067792.79369522 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-max_scan_bytes.rst0000666000175000017500000000263715132733117026453 0ustar00rgerrger.. _param-mmjsonparse-max_scan_bytes: .. _mmjsonparse.parameter.max_scan_bytes: max_scan_bytes ============== .. index:: single: mmjsonparse; max_scan_bytes single: max_scan_bytes single: scan limit .. summary-start Maximum number of bytes to scan when searching for JSON content in find-json mode. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: max_scan_bytes :Scope: action :Type: positive integer :Default: 65536 :Required?: no :Introduced: 8.2506.0 Description ----------- Sets the maximum number of bytes to scan when searching for JSON objects in find-json mode. This prevents performance issues with very large messages by limiting the amount of data that will be examined. When the scan limit is reached without finding a complete JSON object, the message is treated as non-JSON and processed through the fallback path (creating a simple JSON object with the original message as the "msg" field). This parameter is only effective when mode="find-json". Input usage ----------- .. _mmjsonparse.parameter.max_scan_bytes-usage: .. code-block:: rsyslog # Scan up to 32KB for JSON content action(type="mmjsonparse" mode="find-json" max_scan_bytes="32768") # Use default 64KB scan limit action(type="mmjsonparse" mode="find-json") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`.rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-compression-maxtotalzstdwindowbyte0000644000000000000000000000013115241075234031155 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 29 ctime=1787067792.46368907 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-maxtotalzstdwindowbytes.rst0000664000175000017500000000604215241075234031616 0ustar00rgerrger.. _param-imtcp-compression-maxtotalzstdwindowbytes: .. _imtcp.parameter.input.compression-maxtotalzstdwindowbytes: .. meta:: :description: Reference for the imtcp compression.maxTotalZstdWindowBytes parameter. :keywords: rsyslog, imtcp, compression.maxTotalZstdWindowBytes, zstd, decoder window, memory limit compression.maxTotalZstdWindowBytes =================================== .. index:: single: imtcp; compression.maxTotalZstdWindowBytes single: compression.maxTotalZstdWindowBytes .. summary-start Limits aggregate advertised zstd decoder-window bytes across active sessions for one ``imtcp`` listener. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: compression.maxTotalZstdWindowBytes :Scope: input/module :Type: integer :Default: 0 :Required?: no :Introduced: 8.2608.0 Description ----------- ``compression.maxTotalZstdWindowBytes`` limits the sum of advertised zstd decoder-window sizes retained by active compressed sessions on one ``imtcp`` listener. It applies only when ``compression.mode="stream:always"`` and ``compression.driver="zstd"`` are active. A frame whose reservation would exceed the limit is rejected and its session is closed without affecting already admitted sessions. The default ``0`` leaves aggregate decoder-window memory unlimited for compatibility. This setting is independent of :ref:`param-imtcp-compression-maxdecompressedbytesperreceive`, which limits decompressed output from one TCP receive operation. The secure-default policy controls omitted values: - ``compatibility.defaults.secure="backward-compatible"`` accepts the unlimited default silently. - ``compatibility.defaults.secure="warn"`` accepts it and emits a startup warning. Explicitly setting ``0`` acknowledges unlimited operation and suppresses that warning. - ``compatibility.defaults.secure="strict"`` requires an explicitly configured positive value and rejects omitted or explicit-zero values. The accounting uses the window size declared by each zstd frame. It bounds the dominant retained decoder-window allocation, but does not attempt to account for every byte of decoder bookkeeping or unrelated per-connection memory. RainerScript usage ------------------ .. code-block:: rsyslog input( type="imtcp" address="127.0.0.1" port="514" compression.mode="stream:always" compression.driver="zstd" compression.maxTotalZstdWindowBytes="536870912" ) YAML usage ---------- .. code-block:: yaml inputs: - type: imtcp address: "127.0.0.1" port: "514" compression.mode: "stream:always" compression.driver: "zstd" compression.maxTotalZstdWindowBytes: "536870912" The same parameter may be placed on ``module(load="imtcp" ...)`` or its YAML module entry to provide an explicitly configured default inherited by inputs. See also -------- See also :ref:`param-imtcp-compression-mode`, :ref:`param-imtcp-compression-driver`, :ref:`param-imtcp-compression-maxdecompressedbytesperreceive`, and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imrelp-tls-myprivkey.rst0000644000000000000000000000013215132733117025567 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.937479946 30 ctime=1787067792.435688548 rsyslog-8.2608.0/doc/source/reference/parameters/imrelp-tls-myprivkey.rst0000666000175000017500000000153715132733117025243 0ustar00rgerrger.. _param-imrelp-tls-myprivkey: .. _imrelp.parameter.input.tls-myprivkey: tls.myPrivKey ============= .. index:: single: imrelp; tls.myPrivKey single: tls.myPrivKey .. summary-start References the private key file that matches the configured tls.myCert. .. summary-end This parameter applies to :doc:`../../configuration/modules/imrelp`. :Name: tls.myPrivKey :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: Not documented Description ----------- The machine private key for the configured :ref:`param-imrelp-tls-mycert`. Input usage ----------- .. _param-imrelp-input-tls-myprivkey-usage: .. _imrelp.parameter.input.tls-myprivkey-usage: .. code-block:: rsyslog input(type="imrelp" port="2514" tls="on" tls.myPrivKey="/etc/rsyslog/server.key") See also -------- See also :doc:`../../configuration/modules/imrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-dynafile-donotsuspend.rst0000644000000000000000000000013015132411300027212 xustar0030 mtime=1768559296.209884738 29 atime=1787067672.37345079 29 ctime=1787067793.15970204 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-dynafile-donotsuspend.rst0000666000175000017500000000213715132411300026665 0ustar00rgerrger.. _param-omfile-dynafile-donotsuspend: .. _omfile.parameter.module.dynafile-donotsuspend: dynafile.donotsuspend ===================== .. index:: single: omfile; dynafile.donotsuspend single: dynafile.donotsuspend .. summary-start This permits SUSPENDing dynafile actions. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: dynafile.donotsuspend :Scope: module :Type: boolean :Default: module=on :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- This permits SUSPENDing dynafile actions. Traditionally, SUSPEND mode was never entered for dynafiles as it would have blocked overall processing flow. Default is not to suspend (and thus block). Module usage ------------ .. _param-omfile-module-dynafile-donotsuspend: .. _omfile.parameter.module.dynafile-donotsuspend-usage: .. code-block:: rsyslog module(load="builtin:omfile" dynafile.donotsuspend="...") Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-defaultseverity.rst0000644000000000000000000000013215241075234027354 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.991680275 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-defaultseverity.rst0000664000175000017500000000162115241075234027020 0ustar00rgerrger.. _param-imkubernetes-defaultseverity: .. _imkubernetes.parameter.module.defaultseverity: DefaultSeverity =============== .. index:: single: imkubernetes; DefaultSeverity single: DefaultSeverity .. summary-start Default severity assigned to submitted records that are not mapped to ``stderr``; default ``info``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: DefaultSeverity :Scope: module :Type: severity :Default: ``info`` :Required?: no :Introduced: 8.2604.0 Description ----------- ``imkubernetes`` uses ``err`` for parsed ``stderr`` records. For other records, including ``stdout`` and raw fallback lines, this setting controls the emitted syslog severity. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" DefaultSeverity="notice") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omgssapi-gssmode.rst0000644000000000000000000000013215132733117024723 xustar0030 mtime=1768666703.916620375 30 atime=1787067672.885460335 30 ctime=1787067793.215703084 rsyslog-8.2608.0/doc/source/reference/parameters/omgssapi-gssmode.rst0000666000175000017500000000264715132733117024402 0ustar00rgerrger.. _param-omgssapi-gssmode: .. _omgssapi.parameter.module.gssmode: GssMode ======= .. index:: single: omgssapi; GssMode single: GssMode .. summary-start Chooses whether omgssapi requests integrity-only or encrypted message protection for GSSAPI sessions. .. summary-end This parameter applies to :doc:`../../configuration/modules/omgssapi`. :Name: GssMode :Scope: module :Type: string :Default: encryption :Required?: no :Introduced: 1.21.2 Description ----------- Specifies the GSS-API protection level used by the client. The available modes are: - ``integrity`` — only authenticates clients and verifies message integrity. - ``encryption`` — provides the same guarantees as ``integrity`` and encrypts messages when both peers support it. Legacy configurations set this directive with statements such as ``$GssMode encryption``. Module usage ------------ .. _param-omgssapi-module-gssmode: .. _omgssapi.parameter.module.gssmode-usage: .. code-block:: rsyslog module(load="omgssapi" gssMode="encryption") action(type="omgssapi" target="receiver.mydomain.com") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omgssapi.parameter.legacy.gssmode: - $GssMode — maps to GssMode (status: legacy) .. index:: single: omgssapi; $GssMode single: $GssMode See also -------- See also :doc:`../../configuration/modules/omgssapi`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-expert-initialprompt.rst0000644000000000000000000000013215132733117027257 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.742439027 30 ctime=1787067792.682693151 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-expert-initialprompt.rst0000666000175000017500000000211715132733117026726 0ustar00rgerrger.. _param-mmaitag-expert-initialprompt: .. _mmaitag.parameter.action.expert-initialprompt: expert.initialPrompt ===================== .. index:: single: mmaitag; expert.initialPrompt single: expert.initialPrompt .. summary-start Provides a custom prompt text used by the AI provider before classifying messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: expert.initialPrompt :Scope: action :Type: string :Default: Task: Classify the log message that follows. Output: Exactly one label from this list: NOISE, REGULAR, IMPORTANT, CRITICAL. Restrictions: No other text, explanations, formatting, or newline characters. :Required?: no :Introduced: 9.0.0 Description ----------- Optional custom prompt text. If unset, the default value is used. Action usage ------------- .. _param-mmaitag-action-expert-initialprompt: .. _mmaitag.parameter.action.expert-initialprompt-usage: .. code-block:: rsyslog action(type="mmaitag" expert.initialPrompt="Classify precisely") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imhttp-healthcheckbasicauthfile.rst0000644000000000000000000000013215171370365027741 xustar0030 mtime=1776677109.117908084 30 atime=1787067672.724457333 30 ctime=1787067792.161683442 rsyslog-8.2608.0/doc/source/reference/parameters/imhttp-healthcheckbasicauthfile.rst0000664000175000017500000000223315171370365027405 0ustar00rgerrger.. meta:: :description: Protect the imhttp health check endpoint with HTTP Basic Authentication. :keywords: rsyslog, imhttp, healthcheck, basicauthfile, http basic authentication .. _param-imhttp-healthcheckbasicauthfile: .. _imhttp.parameter.module.healthcheckbasicauthfile: .. _imhttp-healthcheckbasicauthfile: healthCheckBasicAuthFile ======================== .. index:: single: imhttp; healthCheckBasicAuthFile single: healthCheckBasicAuthFile .. summary-start Protects the imhttp health check endpoint with HTTP Basic Authentication. .. summary-end This parameter applies to :doc:`../../configuration/modules/imhttp`. :Name: healthCheckBasicAuthFile :Scope: module :Type: string :Default: none :Required?: no :Introduced: Not specified Description ----------- If set, the health check endpoint requires HTTP Basic Authentication and expects credentials from an htpasswd file. Module usage ------------ .. _imhttp.parameter.module.healthcheckbasicauthfile-usage: .. code-block:: rsyslog module( load="imhttp" healthCheckBasicAuthFile="/etc/rsyslog/htpasswd" ) See also -------- See also :doc:`../../configuration/modules/imhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-log_group.rst0000644000000000000000000000013215241075234026137 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.965698425 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-log_group.rst0000664000175000017500000000175715241075234025615 0ustar00rgerrger.. _param-omawslogshlc-log_group: .. _omawslogshlc.parameter.action.log_group: .. meta:: :description: Reference for the omawslogshlc log_group parameter. :keywords: rsyslog, omawslogshlc, log_group, aws, cloudwatch log_group ========= .. index:: single: omawslogshlc; log_group single: log_group .. summary-start Specifies the CloudWatch Logs log group name to send events to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: log_group :Scope: action :Type: string :Default: none :Required?: yes :Introduced: Not specified Description ----------- ``log_group`` identifies the target CloudWatch Logs log group. The value is URL-encoded automatically when constructing the HLC endpoint URL. Action usage ------------ .. _omawslogshlc.parameter.action.log_group-usage: .. code-block:: rsyslog action(type="omawslogshlc" log_group="my-application-logs" ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-keepalive.rst0000644000000000000000000000013215132733117024521 xustar0030 mtime=1768666703.908620253 30 atime=1787067673.998481083 30 ctime=1787067792.484689461 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-keepalive.rst0000666000175000017500000000263715132733117024177 0ustar00rgerrger.. _param-imtcp-keepalive: .. _imtcp.parameter.module.keepalive: .. _imtcp.parameter.input.keepalive: KeepAlive ========= .. index:: single: imtcp; KeepAlive single: KeepAlive .. summary-start Enables TCP keep-alive packets on connections. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: KeepAlive :Scope: module, input :Type: boolean :Default: module=off, input=module parameter :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Enable or disable keep-alive packets at the tcp socket layer. The default is to disable them. The same-named input parameter can override this module setting. Module usage ------------ .. _param-imtcp-module-keepalive: .. _imtcp.parameter.module.keepalive-usage: .. code-block:: rsyslog module(load="imtcp" keepAlive="on") Input usage ----------- .. _param-imtcp-input-keepalive: .. _imtcp.parameter.input.keepalive-usage: .. code-block:: rsyslog input(type="imtcp" port="514" keepAlive="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imtcp.parameter.legacy.inputtcpserverkeepalive: - $InputTCPServerKeepAlive — maps to KeepAlive (status: legacy) .. index:: single: imtcp; $InputTCPServerKeepAlive single: $InputTCPServerKeepAlive See also -------- See also :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imptcp-port.rst0000644000000000000000000000013215132733117023720 xustar0030 mtime=1768666703.907620238 30 atime=1787067673.604473738 30 ctime=1787067792.372687374 rsyslog-8.2608.0/doc/source/reference/parameters/imptcp-port.rst0000666000175000017500000000201515132733117023364 0ustar00rgerrger.. _param-imptcp-port: .. _imptcp.parameter.input.port: Port ==== .. index:: single: imptcp; Port single: Port .. summary-start Selects the TCP port on which to listen. .. summary-end This parameter applies to :doc:`../../configuration/modules/imptcp`. :Name: Port :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Select a port to listen on. It is an error to specify both ``path`` and ``port``. Input usage ----------- .. _param-imptcp-input-port: .. _imptcp.parameter.input.port-usage: .. code-block:: rsyslog input(type="imptcp" port="...") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imptcp.parameter.legacy.inputptcpserverrun: - $InputPTCPServerRun — maps to Port (status: legacy) .. index:: single: imptcp; $InputPTCPServerRun single: $InputPTCPServerRun See also -------- See also :doc:`../../configuration/modules/imptcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-httpheadervalue.rst0000644000000000000000000000013115132733117026137 xustar0029 mtime=1768666703.91762039 30 atime=1787067672.777458321 30 ctime=1787067793.264703997 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-httpheadervalue.rst0000666000175000017500000000156615132733117025616 0ustar00rgerrger.. _param-omhttp-httpheadervalue: .. _omhttp.parameter.input.httpheadervalue: httpheadervalue =============== .. index:: single: omhttp; httpheadervalue single: httpheadervalue .. summary-start Provides the value for the single custom HTTP header defined by :ref:`param-omhttp-httpheaderkey`. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: httpheadervalue :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The header value for :ref:`param-omhttp-httpheaderkey`. Input usage ----------- .. _omhttp.parameter.input.httpheadervalue-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" httpHeaderKey="X-Insert-Key" httpHeaderValue="apikey" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmkubernetes-kubernetesurl.rst0000644000000000000000000000013115241075234027032 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.725580541 29 ctime=1787067792.84469617 rsyslog-8.2608.0/doc/source/reference/parameters/mmkubernetes-kubernetesurl.rst0000664000175000017500000000313415241075234026500 0ustar00rgerrger.. _param-mmkubernetes-kubernetesurl: .. _mmkubernetes.parameter.action.kubernetesurl: KubernetesURL ============= .. index:: single: mmkubernetes; KubernetesURL single: KubernetesURL .. summary-start Specifies the URL of the Kubernetes API server. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmkubernetes`. :Name: KubernetesURL :Scope: action :Type: array[string] :Default: https://kubernetes.default.svc.cluster.local:443 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- The URL of the Kubernetes API server. Example: `https://localhost:8443`. You can specify multiple API server URLs with standard rsyslog array syntax. mmkubernetes uses the first URL as the primary server, cache identity, statistic name, and ``master_url`` metadata value. If a transport connection to that URL fails, mmkubernetes tries the next configured URL for the same metadata lookup. Kubernetes API responses such as ``404 Not Found`` or ``429 Busy`` are handled with the normal module semantics and do not by themselves advance to the next URL. Existing single-URL configurations remain valid because a scalar value is treated as a one-element array. Action usage ------------ .. _param-mmkubernetes-action-kubernetesurl: .. _mmkubernetes.parameter.action.kubernetesurl-usage: .. code-block:: rsyslog action(type="mmkubernetes" kubernetesUrl="https://localhost:8443") action(type="mmkubernetes" kubernetesUrl=["https://k8s-a.example:6443", "https://k8s-b.example:6443"]) See also -------- See also :doc:`../../configuration/modules/mmkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/pmrfc3164-remove-msgfirstspace.rst0000644000000000000000000000013115132411300027214 xustar0030 mtime=1768559296.219884897 30 atime=1787067672.320449802 29 ctime=1787067793.62171065 rsyslog-8.2608.0/doc/source/reference/parameters/pmrfc3164-remove-msgfirstspace.rst0000666000175000017500000000220415132411300026661 0ustar00rgerrger.. _param-pmrfc3164-remove-msgfirstspace: .. _pmrfc3164.parameter.module.remove-msgfirstspace: .. _pmrfc3164.parameter.module.remove.msgFirstSpace: remove.msgFirstSpace ==================== .. index:: single: pmrfc3164; remove.msgFirstSpace single: remove.msgFirstSpace .. summary-start Remove the first space after the tag to improve RFC3164/RFC5424 interoperability. .. summary-end This parameter applies to :doc:`../../configuration/modules/pmrfc3164`. :Name: remove.msgFirstSpace :Scope: module :Type: boolean :Default: module=off :Required?: no :Introduced: 8.2508.0 Description ----------- RFC3164 places a space after the tag. When enabled, this option removes that first space so RFC3164 and RFC5424 messages can mix more easily. Module usage ------------ .. _param-pmrfc3164-module-remove-msgfirstspace: .. _pmrfc3164.parameter.module.remove-msgfirstspace-usage: .. code-block:: rsyslog parser(name="custom.rfc3164" type="pmrfc3164" remove.msgFirstSpace="on") Notes ----- - Legacy docs referred to this as a ``binary`` option, which maps to a boolean. See also -------- See also :doc:`../../configuration/modules/pmrfc3164`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imdiag-defaultactionqueuetimeoutenqueue.0000644000000000000000000000013215171370365031034 xustar0030 mtime=1776677109.116908069 30 atime=1787067671.972443314 30 ctime=1787067791.931679156 rsyslog-8.2608.0/doc/source/reference/parameters/imdiag-defaultactionqueuetimeoutenqueue.rst0000664000175000017500000000315115171370365031231 0ustar00rgerrger.. _param-imdiag-defaultactionqueuetimeoutenqueue: .. _imdiag.parameter.module.defaultactionqueuetimeoutenqueue: .. meta:: :description: Reference for the imdiag defaultActionQueueTimeoutEnqueue module parameter. :keywords: rsyslog, imdiag, defaultactionqueuetimeoutenqueue, testbench, timeout, action queue DefaultActionQueueTimeoutEnqueue ================================= .. index:: single: imdiag; DefaultActionQueueTimeoutEnqueue .. summary-start Sets the default action queue enqueue timeout at config load time. .. summary-end This parameter applies to :doc:`../../configuration/modules/imdiag`. :Name: DefaultActionQueueTimeoutEnqueue :Scope: module :Type: integer (milliseconds) :Default: 30000 :Required?: no :Introduced: 8.x Description ----------- Sets ``globals.actq_dflt_toEnq`` — the default enqueue timeout for action queues created after this point — at config-load time. This only affects action queues that do not specify their own timeout. When an action queue is full, a producer waits up to this duration before dropping the message. .. note:: This parameter affects action queues created *after* the module is loaded. Existing queues are unaffected. Override per-test via ``RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE`` before ``generate_conf``. Module usage ------------ .. code-block:: rsyslog module(load="imdiag" defaultActionQueueTimeoutEnqueue="30000") YAML usage ---------- .. code-block:: yaml testbench_modules: - load: "../plugins/imdiag/.libs/imdiag" defaultactionqueuetimeoutenqueue: "30000" See also -------- See also :doc:`../../configuration/modules/imdiag`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-maxsubmitatonce.rst0000644000000000000000000000013115132733117026107 xustar0030 mtime=1768666703.904620193 29 atime=1787067672.43245189 30 ctime=1787067792.084682008 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-maxsubmitatonce.rst0000666000175000017500000000206415132733117025560 0ustar00rgerrger.. _param-imfile-maxsubmitatonce: .. _imfile.parameter.input.maxsubmitatonce: .. _imfile.parameter.maxsubmitatonce: MaxSubmitAtOnce =============== .. index:: single: imfile; MaxSubmitAtOnce single: MaxSubmitAtOnce .. summary-start Sets the maximum batch size that imfile submits at once. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: MaxSubmitAtOnce :Scope: input :Type: integer :Default: 1024 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- An expert option that defines the maximum number of messages a single input batch may contain. The default of ``1024`` suits most applications. Modify only if familiar with rsyslog's batch processing semantics. Input usage ----------- .. _param-imfile-input-maxsubmitatonce: .. _imfile.parameter.input.maxsubmitatonce-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" MaxSubmitAtOnce="1024") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-push-url.rst0000644000000000000000000000013215145046112025057 xustar0030 mtime=1771326538.940012672 30 atime=1787067673.487471557 30 ctime=1787067792.305686126 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-push-url.rst0000664000175000017500000000150315145046112024522 0ustar00rgerrger.. _param-impstats-push-url: .. _impstats.parameter.module.push-url: push.url ======== .. index:: single: impstats; push.url single: push.url .. summary-start Specifies the Prometheus Remote Write endpoint URL to enable impstats push. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: push.url :Scope: module :Type: word :Default: module=none :Required?: no :Introduced: 8.2602.0 Description ----------- When set, impstats sends its statistics to the specified Remote Write endpoint. Use an ``https://`` URL to enable TLS. Module usage ------------ .. _impstats.parameter.module.push-url-usage: .. code-block:: rsyslog module(load="impstats" push.url="http://localhost:8428/api/v1/write") See also -------- See also :doc:`../../configuration/modules/impstats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmaitag-apikey.rst0000644000000000000000000000013215132733117024341 xustar0030 mtime=1768666703.911620299 30 atime=1787067671.757439306 30 ctime=1787067792.677693058 rsyslog-8.2608.0/doc/source/reference/parameters/mmaitag-apikey.rst0000666000175000017500000000145615132733117024015 0ustar00rgerrger.. _param-mmaitag-apikey: .. _mmaitag.parameter.action.apikey: apiKey ====== .. index:: single: mmaitag; apiKey single: apiKey .. summary-start Sets the API key used to authenticate with the provider. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmaitag`. :Name: apiKey :Scope: action :Type: string :Default: none :Required?: no (either ``apiKey`` or :ref:`param-mmaitag-apikey_file` must be set) :Introduced: 9.0.0 Description ----------- API key for the provider. This parameter takes precedence over :ref:`param-mmaitag-apikey_file`. Action usage ------------- .. _param-mmaitag-action-apikey: .. _mmaitag.parameter.action.apikey-usage: .. code-block:: rsyslog action(type="mmaitag" apiKey="ABC") See also -------- * :doc:`../../configuration/modules/mmaitag` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmjsonparse-cookie.rst0000644000000000000000000000013215132733117025247 xustar0030 mtime=1768666703.913620329 30 atime=1787067672.359450529 30 ctime=1787067792.791695182 rsyslog-8.2608.0/doc/source/reference/parameters/mmjsonparse-cookie.rst0000666000175000017500000000224315132733117024716 0ustar00rgerrger.. _param-mmjsonparse-cookie: .. _mmjsonparse.parameter.input.cookie: cookie ====== .. index:: single: mmjsonparse; cookie single: cookie single: CEE cookie .. summary-start Defines the cookie string that must appear before the JSON content of a message. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmjsonparse`. :Name: cookie :Scope: input :Type: string :Default: @cee: :Required?: no :Introduced: 6.6.0 Description ----------- Permits setting the cookie that must be present in front of the JSON part of the message. Most importantly, this can be set to the empty string ("") to not require any cookie. In this case, leading spaces are permitted in front of the JSON. No characters, including whitespace, are permitted after the JSON object. If trailing characters must be handled, a tool like the :doc:`mmnormalize module <../../configuration/modules/mmnormalize>` can be used. Input usage ----------- .. _mmjsonparse.parameter.input.cookie-usage: .. code-block:: rsyslog action(type="mmjsonparse" cookie="") See also -------- See also the :doc:`main mmjsonparse module documentation <../../configuration/modules/mmjsonparse>`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-maxbatchbytes.rst0000644000000000000000000000013215216464435025731 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.783439791 30 ctime=1787067791.340668143 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-maxbatchbytes.rst0000664000175000017500000000216315216464435025377 0ustar00rgerrger.. _param-imbeats-maxbatchbytes: .. _imbeats.parameter.input.maxbatchbytes: maxBatchBytes ============= .. meta:: :description: Maximum cumulative Lumberjack batch payload size accepted by imbeats. :keywords: rsyslog, imbeats, maxBatchBytes, Lumberjack batch, size limit .. index:: single: imbeats; maxBatchBytes single: maxBatchBytes .. summary-start Limit the cumulative JSON payload bytes accepted in one Lumberjack batch. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: maxBatchBytes :Scope: input :Type: positive integer :Default: input=67108864 :Required?: no :Introduced: 8.2604.0 Description ----------- Set the maximum cumulative byte size of JSON event payloads accepted in one Lumberjack batch window. Batches that exceed this limit are rejected before all payloads are retained in memory. Input usage ----------- .. _param-imbeats-input-maxbatchbytes: .. _imbeats.parameter.input.maxbatchbytes-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" maxBatchBytes="67108864") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imklog-permitnonkernelfacility.rst0000644000000000000000000000013115132733117027662 xustar0030 mtime=1768666703.905620208 30 atime=1787067673.057463541 29 ctime=1787067792.24368497 rsyslog-8.2608.0/doc/source/reference/parameters/imklog-permitnonkernelfacility.rst0000666000175000017500000000307215132733117027333 0ustar00rgerrger.. _param-imklog-permitnonkernelfacility: .. _imklog.parameter.module.permitnonkernelfacility: PermitNonKernelFacility ======================= .. index:: single: imklog; PermitNonKernelFacility single: PermitNonKernelFacility .. summary-start Controls whether imklog submits kernel log messages that use non-kernel facilities. .. summary-end This parameter applies to :doc:`../../configuration/modules/imklog`. :Name: PermitNonKernelFacility :Scope: module :Type: boolean :Default: off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- At least under BSD the kernel log may contain entries with non-kernel facilities. This setting controls how those are handled. The default is "off", in which case these messages are ignored. Switch it to on to submit non-kernel messages to rsyslog processing. Notes ----- - Legacy documentation referred to the type as "binary"; it behaves as a boolean value. Module usage ------------ .. _param-imklog-module-permitnonkernelfacility: .. _imklog.parameter.module.permitnonkernelfacility-usage: .. code-block:: rsyslog module(load="imklog" permitNonKernelFacility="on") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imklog.parameter.legacy.klogpermitnonkernelfacility: - $KLogPermitNonKernelFacility — maps to PermitNonKernelFacility (status: legacy) .. index:: single: imklog; $KLogPermitNonKernelFacility single: $KLogPermitNonKernelFacility See also -------- :doc:`../../configuration/modules/imklog` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-tls-tlslib.rst0000644000000000000000000000013215145046112025023 xustar0030 mtime=1771326538.956012933 30 atime=1787067672.919460968 30 ctime=1787067793.524708842 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-tls-tlslib.rst0000664000175000017500000000263015145046112024470 0ustar00rgerrger.. _param-omrelp-tls-tlslib: .. _omrelp.parameter.module.tls-tlslib: tls.tlslib ========== .. index:: single: omrelp; tls.tlslib single: tls.tlslib .. summary-start Specifies which TLS library librelp uses for RELP operations. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: tls.tlslib :Scope: module :Type: string :Default: module=none :Required?: no :Introduced: 8.1903.0 Description ----------- .. versionadded:: 8.1903.0 Permits to specify the TLS library used by librelp. All RELP protocol operations are actually performed by librelp and not rsyslog itself. This value is directly passed down to librelp. Depending on librelp version and build parameters, supported TLS libraries differ (or TLS may not be supported at all). In this case rsyslog emits an error message. Usually, the following options should be available: "openssl", "gnutls". Note that "gnutls" is the current default for historic reasons. We actually recommend to use "openssl". It provides better error messages and accepts a wider range of certificate types. If you have problems with the default setting, we recommend to switch to "openssl". Module usage ------------ .. _param-omrelp-module-tls-tlslib: .. _omrelp.parameter.module.tls-tlslib-usage: .. code-block:: rsyslog module(load="omrelp" tls.tlslib="openssl") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-streamdriver-checkextendedkeypur0000644000000000000000000000013215216464435031027 xustar0030 mtime=1782212893.983265489 30 atime=1787067671.859441208 30 ctime=1787067791.376668814 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-streamdriver-checkextendedkeypurpose.rst0000664000175000017500000000225315216464435032173 0ustar00rgerrger.. _param-imbeats-streamdriver-checkextendedkeypurpose: .. _imbeats.parameter.input.streamdriver-checkextendedkeypurpose: StreamDriver.CheckExtendedKeyPurpose ==================================== .. meta:: :description: Extended key usage enforcement for imbeats TLS peers. :keywords: rsyslog, imbeats, extended key usage .. index:: single: imbeats; StreamDriver.CheckExtendedKeyPurpose single: StreamDriver.CheckExtendedKeyPurpose .. summary-start Enable extended key usage checks when validating imbeats TLS certificates. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: StreamDriver.CheckExtendedKeyPurpose :Scope: input :Type: boolean :Default: input=off :Required?: no :Introduced: 8.2604.0 Description ----------- Enable extended key usage checks when validating imbeats TLS certificates. Input usage ----------- .. _param-imbeats-input-streamdriver-checkextendedkeypurpose: .. _imbeats.parameter.input.streamdriver-checkextendedkeypurpose-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" streamDriver.checkExtendedKeyPurpose="on") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-maxlinesperminute.rst0000644000000000000000000000013015132733117026454 xustar0030 mtime=1768666703.904620193 29 atime=1787067672.46945258 29 ctime=1787067792.08268197 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-maxlinesperminute.rst0000666000175000017500000000210615132733117026123 0ustar00rgerrger.. _param-imfile-maxlinesperminute: .. _imfile.parameter.input.maxlinesperminute: .. _imfile.parameter.maxlinesperminute: MaxLinesPerMinute ================= .. index:: single: imfile; MaxLinesPerMinute single: MaxLinesPerMinute .. summary-start Limits how many lines per minute are enqueued as messages; excess lines are discarded. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: MaxLinesPerMinute :Scope: input :Type: integer :Default: 0 :Required?: no :Introduced: at least 8.x, possibly earlier Description ----------- Instructs rsyslog to enqueue up to the specified maximum number of lines as messages per minute. Lines above this value are discarded. The default ``0`` means no lines are discarded. Input usage ----------- .. _param-imfile-input-maxlinesperminute: .. _imfile.parameter.input.maxlinesperminute-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" MaxLinesPerMinute="0") See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-statsname.rst0000644000000000000000000000013215132733117024752 xustar0030 mtime=1768666703.918620405 30 atime=1787067673.238466915 30 ctime=1787067793.306704779 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-statsname.rst0000666000175000017500000000174215132733117024424 0ustar00rgerrger.. _param-omhttp-statsname: .. _omhttp.parameter.input.statsname: statsname ========= .. index:: single: omhttp; statsname single: statsname .. summary-start Assigns a dedicated statistics counter origin name for this omhttp action. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: statsname :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The name assigned to statistics specific to this action instance. The supported set of statistics tracked for this action instance are **submitted**, **acked**, **failures**. See the `Statistic Counter` section of :doc:`../../configuration/modules/omhttp` for more details. Input usage ----------- .. _omhttp.parameter.input.statsname-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" statsName="omhttp_api" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/ommysql-mysqlconfig-section.rst0000644000000000000000000000013115145046112027131 xustar0029 mtime=1771326538.94601277 30 atime=1787067673.094464231 30 ctime=1787067793.414706792 rsyslog-8.2608.0/doc/source/reference/parameters/ommysql-mysqlconfig-section.rst0000664000175000017500000000334615145046112026604 0ustar00rgerrger.. _param-ommysql-mysqlconfig-section: .. _ommysql.parameter.input.mysqlconfig-section: MySQLConfig.Section =================== .. index:: single: ommysql; MySQLConfig.Section single: MySQLConfig.Section .. summary-start Chooses the section within the client configuration file specified by :ref:`param-ommysql-mysqlconfig-file`. .. summary-end This parameter applies to :doc:`../../configuration/modules/ommysql`. :Name: mysqlconfig.section :Scope: input :Type: word :Default: input=client :Required?: no :Introduced: at least 7.x, possibly earlier Description ----------- Permits the selection of the section within the client configuration file specified by the :ref:`param-ommysql-mysqlconfig-file` parameter. This parameter is only effective if :ref:`param-ommysql-mysqlconfig-file` is also used. It is typically used when a database administrator provides a single configuration file with multiple profiles. If omitted, the MariaDB/MySQL Client Library default of "client" will be used. Input usage ----------- .. _ommysql.parameter.input.mysqlconfig-section-usage: .. code-block:: rsyslog module(load="ommysql") action(type="ommysql" server="mysqlserver.example.com" mysqlConfig.file="/etc/mysql/my.cnf" mysqlConfig.section="custom-client" db="syslog_db" uid="user" pwd="pwd") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _ommysql.parameter.legacy.ommysqlconfigsection: - $OmMySQLConfigSection — maps to MySQLConfig.Section (status: legacy) .. index:: single: ommysql; $OmMySQLConfigSection single: $OmMySQLConfigSection See also -------- See also :doc:`../../configuration/modules/ommysql`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkafka-split-json-records.rst0000644000000000000000000000013215145046112026600 xustar0030 mtime=1771326538.939012655 30 atime=1787067672.996462404 30 ctime=1787067792.227684672 rsyslog-8.2608.0/doc/source/reference/parameters/imkafka-split-json-records.rst0000664000175000017500000000500015145046112026237 0ustar00rgerrger.. _param-imkafka-split-json-records: .. _imkafka.parameter.input.split.json.records: split.json.records ================== .. index:: single: imkafka; split.json.records single: split.json.records .. summary-start Controls whether imkafka splits JSON batches into individual messages. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkafka`. :Name: split.json.records :Scope: input :Type: boolean :Default: input=``off`` :Required?: no :Introduced: 8.2502.0 Description ----------- When enabled, imkafka will detect JSON messages with the format ``{"records":[...]}`` and split the array into individual syslog messages. Each record within the array becomes a separate message, allowing for message-level filtering and processing. This is particularly useful when consuming messages from Azure Event Hub or other systems that batch multiple log records into a single Kafka message. **Behavior:** - If splitting is enabled and the message contains a ``"records"`` array, each element is submitted as a separate message. - If the ``"records"`` field is not found or the JSON is malformed, the entire message is forwarded unchanged. - When a record contains a ``"time"`` field (ISO 8601 timestamp), it is used as the message timestamp. - Empty arrays ``{"records":[]}`` are forwarded as a single message without splitting. **Error Handling:** - Malformed JSON: A warning is logged and the message is forwarded as received. - Missing ``"records"`` field: The message is processed as a normal single event. Input usage ----------- .. _imkafka.parameter.input.split.json.records-usage: .. code-block:: rsyslog module(load="imkafka") input(type="imkafka" topic="your-topic" broker="localhost:9092" consumergroup="default" split.json.records="on") Example ------- **Input (Single Kafka Message):** .. code-block:: json { "records": [ { "time": "2025-02-20T03:19:34.655Z", "operationName": "CreatePathDir", "statusCode": 409 }, { "time": "2025-02-20T03:19:34.693Z", "operationName": "CreatePathDir", "statusCode": 409 } ] } **Output (Two Separate Syslog Messages):** .. code-block:: json {"time":"2025-02-20T03:19:34.655Z","operationName":"CreatePathDir","statusCode":409} .. code-block:: json {"time":"2025-02-20T03:19:34.693Z","operationName":"CreatePathDir","statusCode":409} See also -------- See also :doc:`../../configuration/modules/imkafka`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omhttp-checkpath.rst0000644000000000000000000000012715132733117024711 xustar0029 mtime=1768666703.91762039 28 atime=1787067673.2054663 30 ctime=1787067793.242703587 rsyslog-8.2608.0/doc/source/reference/parameters/omhttp-checkpath.rst0000666000175000017500000000302115132733117024347 0ustar00rgerrger.. _param-omhttp-checkpath: .. _omhttp.parameter.input.checkpath: checkpath ========= .. index:: single: omhttp; checkpath single: checkpath .. summary-start Defines the health-check endpoint that omhttp polls to decide when to resume after suspension. .. summary-end This parameter applies to :doc:`../../configuration/modules/omhttp`. :Name: checkpath :Scope: input :Type: word :Default: input=none :Required?: no :Introduced: Not specified Description ----------- The health check path you want to use. Do not include the leading slash character. If the full path looks like ``localhost:5000/my/path``, ``checkpath`` should be ``my/path``. When this parameter is set, omhttp utilizes this path to determine if it is safe to resume (from suspend mode) and communicates this status back to rsyslog core. This parameter defaults to ``none``, which implies that health checks are not needed, and it is always safe to resume from suspend mode. **Important** - Note that it is highly recommended to set a valid health check path, as this allows omhttp to better determine whether it is safe to retry. See the `rsyslog action queue documentation for more info `_ regarding general rsyslog suspend and resume behavior. Input usage ----------- .. _omhttp.parameter.input.checkpath-usage: .. code-block:: rsyslog module(load="omhttp") action( type="omhttp" checkPath="health" ) See also -------- See also :doc:`../../configuration/modules/omhttp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/impstats-format.rst0000644000000000000000000000013215241075234024574 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.724580522 30 ctime=1787067792.266685399 rsyslog-8.2608.0/doc/source/reference/parameters/impstats-format.rst0000664000175000017500000000323215241075234024240 0ustar00rgerrger.. _param-impstats-format: .. _impstats.parameter.module.format: format ====== .. index:: single: impstats; format single: format .. summary-start Specifies which output format impstats uses for emitted statistics records. .. summary-end This parameter applies to :doc:`../../configuration/modules/impstats`. :Name: format :Scope: module :Type: word :Default: module=legacy :Required?: no :Introduced: 8.16.0 Description ----------- .. versionadded:: 8.16.0 Specifies the format of emitted stats messages. The default of ``legacy`` is compatible with pre v6-rsyslog. The other options provide support for structured formats (note that ``cee`` is actually "project lumberjack" logging). The ``json-elasticsearch`` format supports the broken ElasticSearch JSON implementation. ES 2.0 no longer supports valid JSON and disallows dots inside names. The ``json-elasticsearch`` format option replaces those dots by the bang ("!") character. So ``discarded.full`` becomes ``discarded!full``. Options: * ``json`` * ``json-elasticsearch`` * ``cee`` * ``legacy`` * ``prometheus`` * ``zabbix`` For ``prometheus``, metric names in the legacy Prometheus character set are emitted unchanged. Other rsyslog-assigned names use a reversible ``U__``-prefixed values escape so punctuation cannot produce invalid or colliding metric identifiers. .. note:: The ``prometheus`` option is available in builds that include the 2025-07-15 enhancement noted in the ``ChangeLog``. Module usage ------------ .. _impstats.parameter.module.format-usage: .. code-block:: rsyslog module(load="impstats" format="json") See also -------- See also :doc:`../../configuration/modules/impstats`.rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imfile-ruleset.rst0000644000000000000000000000013215132733117024370 xustar0030 mtime=1768666703.904620193 30 atime=1787067672.449452207 30 ctime=1787067792.106682418 rsyslog-8.2608.0/doc/source/reference/parameters/imfile-ruleset.rst0000666000175000017500000000232115132733117024034 0ustar00rgerrger.. _param-imfile-ruleset: .. _imfile.parameter.input.ruleset: .. _imfile.parameter.ruleset: Ruleset ======= .. index:: single: imfile; Ruleset single: Ruleset .. summary-start Binds the input instance to a specific ruleset. .. summary-end This parameter applies to :doc:`../../configuration/modules/imfile`. :Name: Ruleset :Scope: input :Type: string (see :doc:`../../rainerscript/constant_strings`) :Default: none :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- Binds the listener to a specific :doc:`ruleset <../../concepts/multi_ruleset>`. Input usage ----------- .. _param-imfile-input-ruleset: .. _imfile.parameter.input.ruleset-usage: .. code-block:: rsyslog input(type="imfile" File="/var/log/example.log" Tag="example" Ruleset="myrules") Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _imfile.parameter.legacy.inputfilebindruleset: - ``$InputFileBindRuleset`` — maps to Ruleset (status: legacy) .. index:: single: imfile; $InputFileBindRuleset single: $InputFileBindRuleset See also -------- See also :doc:`../../configuration/modules/imfile`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-tls-cacert.rst0000644000000000000000000000013215241075234026176 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067792.011680647 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-tls-cacert.rst0000664000175000017500000000163615241075234025650 0ustar00rgerrger.. _param-imkubernetes-tls-cacert: .. _imkubernetes.parameter.module.tls-cacert: tls.caCert ========== .. index:: single: imkubernetes; tls.caCert single: tls.caCert .. summary-start CA certificate bundle used to verify the Kubernetes API TLS certificate; default ``/var/run/secrets/kubernetes.io/serviceaccount/ca.crt``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: tls.caCert :Scope: module :Type: path :Default: ``/var/run/secrets/kubernetes.io/serviceaccount/ca.crt`` :Required?: no :Introduced: 8.2604.0 Description ----------- Points libcurl at the CA certificate bundle that should be trusted for the Kubernetes API endpoint. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" tls.caCert="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmanon-embeddedipv4-maxretryhandling.rst0000644000000000000000000000013215145046112030633 xustar0030 mtime=1771326538.941012688 30 atime=1787067671.977443407 30 ctime=1787067792.702693524 rsyslog-8.2608.0/doc/source/reference/parameters/mmanon-embeddedipv4-maxretryhandling.rst0000664000175000017500000000257215145046112030305 0ustar00rgerrger.. _param-mmanon-embeddedipv4-maxretryhandling: .. _mmanon.parameter.input.embeddedipv4-maxretryhandling: embeddedIpv4.maxRetryHandling ============================= .. index:: single: mmanon; embeddedIpv4.maxRetryHandling single: embeddedIpv4.maxRetryHandling .. summary-start Selects how embedded IPv4 random-consistent-unique handles retry exhaustion. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmanon`. :Name: embeddedIpv4.maxRetryHandling :Scope: input :Type: string :Default: input=accept-duplicates :Required?: no :Introduced: 8.2410.0 Description ----------- Controls how ``random-consistent-unique`` behaves after the retry limit is reached (see :ref:`embeddedIpv4.limitUniqueMaxRetries `). The supported values are: - ``zero``: fall back to zeroing the anonymized bits. - ``accept-duplicates``: keep the last randomized address even if it already exists. A warning is logged whenever the retry limit is hit. Input usage ----------- .. _mmanon.parameter.input.embeddedipv4-maxretryhandling-usage: .. code-block:: rsyslog module(load="mmanon") action(type="mmanon" embeddedIpv4.anonMode="random-consistent-unique" embeddedIpv4.limitUniqueMaxRetries="on" embeddedIpv4.maxRetryHandling="accept-duplicates") See also -------- :doc:`../../configuration/modules/mmanon` rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omrelp-target.rst0000644000000000000000000000013215145046112024220 xustar0030 mtime=1771326538.953012884 30 atime=1787067673.333468686 30 ctime=1787067793.497708339 rsyslog-8.2608.0/doc/source/reference/parameters/omrelp-target.rst0000664000175000017500000000130215145046112023660 0ustar00rgerrger.. _param-omrelp-target: .. _omrelp.parameter.input.target: Target ====== .. index:: single: omrelp; Target single: Target .. summary-start Defines the remote server omrelp connects to. .. summary-end This parameter applies to :doc:`../../configuration/modules/omrelp`. :Name: Target :Scope: input :Type: string :Default: input=none :Required?: yes :Introduced: at least 7.0.0, possibly earlier Description ----------- The target server to connect to. Input usage ----------- .. _param-omrelp-input-target: .. _omrelp.parameter.input.target-usage: .. code-block:: rsyslog action(type="omrelp" target="centralserv") See also -------- See also :doc:`../../configuration/modules/omrelp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imkubernetes-enrichkubernetes.rst0000644000000000000000000000013215241075234027475 xustar0030 mtime=1787067036.580577826 30 atime=1787067036.677579642 30 ctime=1787067791.993680312 rsyslog-8.2608.0/doc/source/reference/parameters/imkubernetes-enrichkubernetes.rst0000664000175000017500000000160515241075234027143 0ustar00rgerrger.. _param-imkubernetes-enrichkubernetes: .. _imkubernetes.parameter.module.enrichkubernetes: EnrichKubernetes ================ .. index:: single: imkubernetes; EnrichKubernetes single: EnrichKubernetes .. summary-start Enable Kubernetes API lookups for pod metadata enrichment; default ``on``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imkubernetes`. :Name: EnrichKubernetes :Scope: module :Type: binary :Default: ``on`` :Required?: no :Introduced: 8.2604.0 Description ----------- When enabled, ``imkubernetes`` fetches pod metadata from the Kubernetes API and adds it under ``$!kubernetes``. Turn this off to operate purely from the file path and log record contents. Module usage ------------ .. code-block:: rsyslog module(load="imkubernetes" EnrichKubernetes="off") See also -------- See also :doc:`../../configuration/modules/imkubernetes`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omawslogshlc-template.rst0000644000000000000000000000013215241075234025755 xustar0030 mtime=1787067036.581577845 30 atime=1787067036.678579661 30 ctime=1787067792.974698593 rsyslog-8.2608.0/doc/source/reference/parameters/omawslogshlc-template.rst0000664000175000017500000000210415241075234025416 0ustar00rgerrger.. _param-omawslogshlc-template: .. _omawslogshlc.parameter.action.template: .. meta:: :description: Reference for the omawslogshlc template parameter. :keywords: rsyslog, omawslogshlc, template, aws, cloudwatch template ======== .. index:: single: omawslogshlc; template single: template .. summary-start Specifies the rsyslog template used to render the message content. .. summary-end This parameter applies to :doc:`../../configuration/modules/omawslogshlc`. :Name: template :Scope: action :Type: word :Default: RSYSLOG_TraditionalFileFormat :Required?: no :Introduced: Not specified Description ----------- ``template`` controls how each syslog message is rendered before being placed into the HLC JSON event's ``event`` field. The default ``RSYSLOG_TraditionalFileFormat`` produces the traditional syslog one-line format. Action usage ------------ .. _omawslogshlc.parameter.action.template-usage: .. code-block:: rsyslog action(type="omawslogshlc" template="MyCustomTemplate" ...) See also -------- See also :doc:`../../configuration/modules/omawslogshlc`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/mmexternal-interface-input.rst0000644000000000000000000000013115132733117026710 xustar0030 mtime=1768666703.913620329 29 atime=1787067672.27044887 30 ctime=1787067792.773694847 rsyslog-8.2608.0/doc/source/reference/parameters/mmexternal-interface-input.rst0000666000175000017500000000327015132733117026361 0ustar00rgerrger.. _param-mmexternal-interface-input: .. _mmexternal.parameter.input.interface-input: interface.input =============== .. index:: single: mmexternal; interface.input single: interface.input .. summary-start Selects which message representation mmexternal passes to the external plugin. .. summary-end This parameter applies to :doc:`../../configuration/modules/mmexternal`. :Name: interface.input :Scope: input :Type: string :Default: msg :Required?: no :Introduced: 8.3.0 Description ----------- This parameter controls what part of the message is passed to the external program's standard input. It can be set to one of the following values: * ``"msg"`` (default): Passes the MSG part of the syslog message. * ``"rawmsg"``: Passes the complete, original syslog message as received by rsyslog, including headers. * ``"fulljson"``: Passes the complete rsyslog message object (with all properties) as a JSON object string. This corresponds to the ``jsonmesg`` dynamic message property. This setting **must** match the external plugin's expectations. Check the external plugin documentation for what needs to be used. .. note:: When processing multi-line messages, you **must** use ``"fulljson"``. This ensures that embedded line breaks are encoded properly and do not cause parsing errors in the external plugin interface. Input usage ----------- .. _param-mmexternal-input-interface-input: .. _mmexternal.parameter.input.interface-input-usage: .. code-block:: rsyslog module(load="mmexternal") action( type="mmexternal" binary="/path/to/mmexternal.py" interfaceInput="fulljson" ) See also -------- See also :doc:`../../configuration/modules/mmexternal`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imtcp-compression-mode.rst0000644000000000000000000000013215216464435026046 xustar0030 mtime=1782212893.985265521 30 atime=1787067674.063482295 30 ctime=1787067792.466689126 rsyslog-8.2608.0/doc/source/reference/parameters/imtcp-compression-mode.rst0000664000175000017500000000470515216464435025520 0ustar00rgerrger.. _param-imtcp-compression-mode: .. _imtcp.parameter.input.compression-mode: .. meta:: :description: Reference for the imtcp compression.mode input parameter. :keywords: rsyslog, imtcp, compression.mode, stream compression, decompression, zlib, zstd compression.mode ================ .. index:: single: imtcp; compression.mode single: compression.mode .. summary-start Enables stream decompression for TCP streams sent by omfwd with ``compression.mode="stream:always"``. .. summary-end This parameter applies to :doc:`../../configuration/modules/imtcp`. :Name: compression.mode :Scope: input/module :Type: word :Default: input=none :Required?: no :Introduced: 8.2606.0 Description ----------- ``compression.mode`` selects whether ``imtcp`` decompresses the received TCP stream before parsing syslog frames. Accepted values are: - ``none``: do not attempt stream decompression. - ``stream:always``: treat the full TCP byte stream as compressed data from :doc:`omfwd <../../configuration/modules/omfwd>` configured with ``compression.mode="stream:always"``. The sender and receiver must use the same ``compression.driver``. The default driver is ``zlib``. For ``zstd``, both sides must be built with libzstd support and configured with ``compression.driver="zstd"``. This is rsyslog stream compression, not TLS-native compression. It is intended for trusted company VPNs and internal WAN/LAN links where the endpoints are controlled together. Compression can create side channels through compressed sizes and timing, so do not enable it for sensitive traffic unless that risk is acceptable. Use TLS separately when confidentiality or peer authentication is required. ``imtcp`` supports ``stream:always`` decompression only. It does not receive ``omfwd`` sender-side ``single`` compression mode. Decompressed output is bounded by :ref:`param-imtcp-compression-maxexpansionratio` and :ref:`param-imtcp-compression-maxdecompressedbytesperreceive`. If either guard is exceeded, ``imtcp`` logs the stream as invalid and closes the session. Input usage ----------- .. _param-imtcp-input-compression-mode: .. _imtcp.parameter.input.compression-mode-usage: .. code-block:: rsyslog input(type="imtcp" port="514" compression.mode="stream:always") See also -------- See also :ref:`param-imtcp-compression-driver`, :ref:`param-imtcp-compression-maxexpansionratio`, :ref:`param-imtcp-compression-maxdecompressedbytesperreceive`, and :doc:`../../configuration/modules/imtcp`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/imbeats-listenportfilename.rst0000644000000000000000000000013215216464435026777 xustar0030 mtime=1782212893.982265473 30 atime=1787067671.778439698 30 ctime=1787067791.337668087 rsyslog-8.2608.0/doc/source/reference/parameters/imbeats-listenportfilename.rst0000664000175000017500000000232715216464435026447 0ustar00rgerrger.. _param-imbeats-listenportfilename: .. _imbeats.parameter.input.listenportfilename: listenPortFileName ================== .. meta:: :description: Port file for imbeats listeners. :keywords: rsyslog, imbeats, listenPortFileName .. index:: single: imbeats; listenPortFileName single: listenPortFileName .. summary-start Write the actual bound port to a file after an imbeats listener starts. .. summary-end This parameter applies to :doc:`../../configuration/modules/imbeats`. :Name: listenPortFileName :Scope: input :Type: string :Default: input=none :Required?: no :Introduced: 8.2604.0 Description ----------- Write the actual bound port to a file after an imbeats listener starts. Production configurations normally use a fixed Beats listener port such as ``5044``. Dynamic port allocation with ``port="0"`` is intended for testbench and automation scenarios that need to discover an ephemeral listener port. Input usage ----------- .. _param-imbeats-input-listenportfilename: .. _imbeats.parameter.input.listenportfilename-usage: .. code-block:: rsyslog input(type="imbeats" port="5044" listenPortFileName="/run/rsyslog/imbeats.port") See also -------- See also :doc:`../../configuration/modules/imbeats`. rsyslog-8.2608.0/doc/source/reference/parameters/PaxHeaders/omfile-asyncwriting.rst0000644000000000000000000000013115216464435025442 xustar0029 mtime=1782212893.98826557 30 atime=1787067672.530453717 30 ctime=1787067793.132701537 rsyslog-8.2608.0/doc/source/reference/parameters/omfile-asyncwriting.rst0000664000175000017500000000334315216464435025112 0ustar00rgerrger.. _param-omfile-asyncwriting: .. _omfile.parameter.module.asyncwriting: asyncWriting ============ .. index:: single: omfile; asyncWriting single: asyncWriting .. summary-start If turned on, the files will be written in asynchronous mode via a separate thread. .. summary-end This parameter applies to :doc:`../../configuration/modules/omfile`. :Name: asyncWriting :Scope: action :Type: boolean :Default: action=off :Required?: no :Introduced: at least 5.x, possibly earlier Description ----------- If turned on, the files will be written in asynchronous mode via a separate thread. In that case, double buffers will be used so that one buffer can be filled while the other buffer is being written. The :ref:`param-omfile-flushinterval` setting is applied when ``asyncWriting`` is enabled for the action. Set ``asyncWriting="on"`` when using ``flushInterval`` to bound how long buffered data may remain unflushed. Action usage ------------ .. _param-omfile-action-asyncwriting: .. _omfile.parameter.action.asyncwriting: .. code-block:: rsyslog action(type="omfile" file="/var/log/app.log" asyncWriting="on") YAML usage ---------- .. code-block:: yaml actions: - type: omfile file: /var/log/app.log asyncWriting: "on" Notes ----- - Legacy documentation referred to the type as ``binary``; this maps to ``boolean``. Legacy names (for reference) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historic names/directives for compatibility. Do not use in new configs. .. _omfile.parameter.legacy.omfileasyncwriting: - $OMFileASyncWriting — maps to asyncWriting (status: legacy) .. index:: single: omfile; $OMFileASyncWriting single: $OMFileASyncWriting See also -------- See also :doc:`../../configuration/modules/omfile`. rsyslog-8.2608.0/doc/source/reference/PaxHeaders/templates0000644000000000000000000000013215241076621020467 xustar0030 mtime=1787067793.744712942 30 atime=1787067808.811993704 30 ctime=1787067793.744712942 rsyslog-8.2608.0/doc/source/reference/templates/0000775000175000017500000000000015241076621020210 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-reserved-names.rst0000644000000000000000000000013215216464435026220 xustar0030 mtime=1782212893.989265586 30 atime=1787067671.788439884 30 ctime=1787067793.731712699 rsyslog-8.2608.0/doc/source/reference/templates/templates-reserved-names.rst0000664000175000017500000001502715216464435025671 0ustar00rgerrger.. _ref-templates-reserved-names: Reserved template names ======================= .. summary-start Names beginning with ``RSYSLOG_`` are reserved. The following templates are predefined and may be used without explicit definition. .. summary-end Template names starting with ``RSYSLOG_`` are reserved for rsyslog. Do not create custom templates with this prefix to avoid conflicts. The following predefined templates are available: **RSYSLOG_TraditionalFileFormat** – "old style" default log file format with low-precision timestamps. .. code-block:: none template(name="RSYSLOG_TraditionalFileFormat" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n") **RSYSLOG_FileFormat** – modern logfile format similar to TraditionalFileFormat with high-precision timestamps and timezone information. .. code-block:: none template(name="RSYSLOG_FileFormat" type="list") { property(name="timereported" dateFormat="rfc3339") constant(value=" ") property(name="hostname") constant(value=" ") property(name="syslogtag") property(name="msg" spIfNo1stSp="on") property(name="msg" dropLastLf="on") constant(value="\n") } **RSYSLOG_TraditionalForwardFormat** – traditional forwarding format with low-precision timestamps. Useful when sending to older syslogd instances. .. code-block:: none template(name="RSYSLOG_TraditionalForwardFormat" type="string" string="<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%") **RSYSLOG_SysklogdFileFormat** – sysklogd compatible log file format. Use with options ``$SpaceLFOnReceive on``, ``$EscapeControlCharactersOnReceive off`` and ``$DropTrailingLFOnReception off`` for full compatibility. .. code-block:: none template(name="RSYSLOG_SysklogdFileFormat" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg%\n") **RSYSLOG_ForwardFormat** – high-precision forwarding format similar to the traditional one but with high-precision timestamps and timezone information. .. code-block:: none template(name="RSYSLOG_ForwardFormat" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%") **RSYSLOG_SyslogProtocol23Format** – format from IETF draft *ietf-syslog-protocol-23*, close to `RFC5424 `_. .. code-block:: none template(name="RSYSLOG_SyslogProtocol23Format" type="string" string="<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n") **RSYSLOG_SyslogRFC5424Format** – RFC 5424 syslog format without a trailing line feed. Use this when the transport or framing layer provides message separation. .. code-block:: none template(name="RSYSLOG_SyslogRFC5424Format" type="string" string="<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%") **RSYSLOG_DebugFormat** – used for troubleshooting property problems. Write to a log file only; do **not** use for production or forwarding. .. code-block:: none template(name="RSYSLOG_DebugFormat" type="list") { constant(value="Debug line with all properties:\nFROMHOST: '") property(name="fromhost") constant(value="', fromhost-ip: '") property(name="fromhost-ip") constant(value="', HOSTNAME: '") property(name="hostname") constant(value="', PRI: '") property(name="pri") constant(value=",\nsyslogtag '") property(name="syslogtag") constant(value="', programname: '") property(name="programname") constant(value="', APP-NAME: '") property(name="app-name") constant(value="', PROCID: '") property(name="procid") constant(value="', MSGID: '") property(name="msgid") constant(value="',\nTIMESTAMP: '") property(name="timereported") constant(value="', STRUCTURED-DATA: '") property(name="structured-data") constant(value="',\nmsg: '") property(name="msg") constant(value="'\nescaped msg: '") property(name="msg" controlCharacters="drop") constant(value="'\ninputname: ") property(name="inputname") constant(value=" rawmsg: '") property(name="rawmsg") constant(value="'\n$!:") property(name="$!") constant(value="\n$.:") property(name="$.") constant(value="\n$/:") property(name="$/") constant(value="\n\n") } **RSYSLOG_WallFmt** – information about host and time followed by the syslogtag and message. .. code-block:: none template(name="RSYSLOG_WallFmt" type="string" string="\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n%syslogtag%%msg%\n\r") **RSYSLOG_StdUsrMsgFmt** – syslogtag followed by the message. .. code-block:: none template(name="RSYSLOG_StdUsrMsgFmt" type="string" string=" %syslogtag%%msg%\n\r") **RSYSLOG_StdDBFmt** – insert command for table ``SystemEvents`` in MariaDB/MySQL. .. code-block:: none template(name="RSYSLOG_StdDBFmt" type="list") { constant(value="insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag)") constant(value=" values ('") property(name="msg") constant(value="', ") property(name="syslogfacility") constant(value=", '") property(name="hostname") constant(value="', ") property(name="syslogpriority") constant(value=", '") property(name="timereported" dateFormat="date-mysql") constant(value="', '") property(name="timegenerated" dateFormat="date-mysql") constant(value="', ") property(name="iut") constant(value=", '") property(name="syslogtag") constant(value="')") } **RSYSLOG_StdPgSQLFmt** – insert command for table ``SystemEvents`` in PostgreSQL. .. code-block:: none template(name="RSYSLOG_StdPgSQLFmt" type="string" string="insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')") **RSYSLOG_spoofadr** – message containing only the sender's IP address. .. code-block:: none template(name="RSYSLOG_spoofadr" type="string" string="%fromhost-ip%") rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-legacy.rst0000644000000000000000000000013215132733117024535 xustar0030 mtime=1768666703.926620526 30 atime=1787067671.793439977 30 ctime=1787067793.727712625 rsyslog-8.2608.0/doc/source/reference/templates/templates-legacy.rst0000666000175000017500000000172415132733117024207 0ustar00rgerrger.. _ref-templates-legacy: Legacy ``$template`` statement ============================== .. summary-start Historic syntax supporting only string templates. Kept for compatibility with older configurations. .. summary-end Legacy format provides limited functionality but is still frequently encountered. Only string templates are supported with the syntax: .. code-block:: none $template myname, Here *myname* is the template name (similar to ``name="myname"`` in the modern format) and ```` is the same as the ``string`` parameter in modern templates. Example modern template: .. code-block:: none template(name="tpl3" type="string" string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" ) Equivalent legacy statement: .. code-block:: none $template tpl3,"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-statement-constant.rst0000644000000000000000000000013115241075234027123 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.733712737 rsyslog-8.2608.0/doc/source/reference/templates/templates-statement-constant.rst0000664000175000017500000000451015241075234026570 0ustar00rgerrger.. _ref-templates-statement-constant: Constant statement ================== .. summary-start Outputs literal text. Supports escape sequences and optional JSON field formatting when an outname and format are specified. .. summary-end This statement specifies constant text. It is primarily intended for text-based output so constant fragments, such as newlines, can be included. Example from the testbench: :: template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n") } The following common escape sequences are recognized inside the constant text: - ``\\`` – single backslash - ``\n`` – LF - ``\ooo`` – three octal digits representing a character (``\101`` is ``"A"``). Exactly three digits must be given. - ``\xhh`` – two hexadecimal digits representing a character (``\x41`` is ``"A"``). Exactly two digits must be given. For the complete list, see :doc:`/rainerscript/constant_strings`. The ``value`` parameter is parsed by the generic configuration parser and then interpreted again as template constant text. To output literal text that looks like a byte escape, escape the backslash for both layers. For example, ``constant(value="\\\\x41")`` emits literal ``\x41``. If an unsupported character follows a backslash, behavior is unpredictable. When creating structured outputs, constant text without an ``outname`` parameter is ignored. To include constant data in the name/value tree, provide ``outname`` as shown: .. code-block:: none template(name="outfmt" type="list") { property(name="$!usr!msgnum") constant(value="\n" outname="IWantThisInMyDB") } To generate a constant JSON field the ``format`` parameter can be used: .. code-block:: none template(name="outfmt" type="list" option.jsonf="on") { property(outname="message" name="msg" format="jsonf") constant(outname="@version" value="1" format="jsonf") } Here the constant statement generates ``"@version":"1"``. Both ``value`` and ``format`` must be specified. When you want dotted ``outname`` values to be emitted as nested objects, enable ``option.jsonftree="on"`` on the template instead of ``option.jsonf``. Parameters ---------- - ``value`` – constant value to emit - ``outname`` – output field name for structured outputs - ``format`` – empty or ``jsonf`` rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-examples.rst0000644000000000000000000000013115241075234025106 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.725712588 rsyslog-8.2608.0/doc/source/reference/templates/templates-examples.rst0000664000175000017500000001217315241075234024557 0ustar00rgerrger.. _ref-templates-examples: Template examples ================= .. summary-start Practical templates for files, forwarding, databases, JSON output, and dynamic file names. .. summary-end Standard template for writing to files -------------------------------------------------- .. code-block:: none template(name="FileFormat" type="list") { property(name="timestamp" dateFormat="rfc3339") constant(value=" ") property(name="hostname") constant(value=" ") property(name="syslogtag") property(name="msg" spIfNo1stSp="on") property(name="msg" dropLastLf="on") constant(value="\n") } Equivalent string template: .. code-block:: none template(name="FileFormat" type="string" string="%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n") Standard template for forwarding to a remote host (RFC3164) -------------------------------------------------------------- .. code-block:: none template(name="ForwardFormat" type="list") { constant(value="<") property(name="pri") constant(value=">") property(name="timestamp" dateFormat="rfc3339") constant(value=" ") property(name="hostname") constant(value=" ") property(name="syslogtag" position.from="1" position.to="32") property(name="msg" spIfNo1stSp="on") property(name="msg") } Equivalent string template: .. code-block:: none template(name="ForwardFormat" type="string" string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%") Standard template for writing to the MariaDB/MySQL database -------------------------------------------------------------------------- .. code-block:: none template(name="StdSQLformat" type="list" option.sql="on") { constant(value="insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag)") constant(value=" values ('") property(name="msg") constant(value="', ") property(name="syslogfacility") constant(value=", '") property(name="hostname") constant(value="', ") property(name="syslogpriority") constant(value=", '") property(name="timereported" dateFormat="mysql") constant(value="', '") property(name="timegenerated" dateFormat="mysql") constant(value="', ") property(name="iut") constant(value=", '") property(name="syslogtag") constant(value="')") } Equivalent string template: .. code-block:: none template(name="StdSQLformat" type="string" option.sql="on" string="insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')") Generating JSON --------------- Useful for RESTful APIs such as ElasticSearch. .. code-block:: none template(name="outfmt" type="list" option.jsonf="on") { property(outname="@timestamp" name="timereported" dateFormat="rfc3339" format="jsonf") property(outname="host" name="hostname" format="jsonf") property(outname="severity" name="syslogseverity" caseConversion="upper" format="jsonf" dataType="number") property(outname="facility" name="syslogfacility" format="jsonf" dataType="number") property(outname="syslog-tag" name="syslogtag" format="jsonf") property(outname="source" name="app-name" format="jsonf" onEmpty="null") property(outname="message" name="msg" format="jsonf") } Produces output similar to: .. code-block:: none {"@timestamp":"2018-03-01T01:00:00+00:00", "host":"192.0.2.8", "severity":7, "facility":20, "syslog-tag":"tag", "source":"tag", "message":" msgnum:00000000:"} Pretty-printed: .. code-block:: none { "@timestamp": "2018-03-01T01:00:00+00:00", "host": "192.0.2.8", "severity": 7, "facility": 20, "syslog-tag": "tag", "source": "tag", "message": " msgnum:00000000:" } If ``onEmpty="null"`` is used and ``source`` is empty: .. code-block:: none {"@timestamp":"2018-03-01T01:00:00+00:00", "host":"192.0.2.8", "severity":7, "facility":20, "syslog-tag":"tag", "source":null, "message":" msgnum:00000000:"} .. note:: The output is not pretty-printed in actual use to avoid waste of resources. Creating dynamic file names for ``omfile`` --------------------------------------------------------- Templates can generate dynamic file names. For example, to split syslog messages by host name: .. code-block:: none template(name="DynFile" type="string" string="/var/log/system-%HOSTNAME:::secpath-replace%.log") If a template is used with ``omfile`` ``dynaFile``, treat every message-derived path component as untrusted. Use ``secpath-replace`` in string templates, or ``securePath="replace"`` in list template property statements, for fields such as ``HOSTNAME``, ``programname``, ``APP-NAME``, and variables extracted from the message. rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-type-list.rst0000644000000000000000000000013115132733117025222 xustar0030 mtime=1768666703.926620526 30 atime=1787067671.755439269 29 ctime=1787067793.73871283 rsyslog-8.2608.0/doc/source/reference/templates/templates-type-list.rst0000666000175000017500000002057415132733117024701 0ustar00rgerrger.. _ref-templates-type-list: .. _templates.parameter.type-list: List template type ================== .. index:: single: template; type=list single: templates; list type .. meta:: :keywords: rsyslog, template type, list, constant statement, property statement, JSON, schema mapping, data pipeline, ECS, LEEF .. summary-start List templates build output from a sequence of constant and property statements. They are ideal for schema mapping when fields must be added one by one. .. summary-end :Name: ``type="list"`` :Scope: template :Type: list :Introduced: 5.9.6 Description -------------------------------------------------------------------------------- The *list template type* generates output from a sequence of **constant** and **property** statements enclosed in curly braces. Use it when you need to build structured output **field by field** or perform explicit schema mapping. - **Property statement** — emit values from rsyslog properties or variables into the output (see :ref:`ref-templates-statement-property`). - **Constant statement** — set fixed values or inject literal text into the output (see :ref:`ref-templates-statement-constant`). List templates work well for: - **Schema mapping**: assign each output field one by one. - **Structure-aware outputs** such as :ref:`ref-ommongodb` or :ref:`ref-omelasticsearch`. - **Text outputs** such as :ref:`ref-omfile` where you need constant text (e.g., line breaks). Compared to :ref:`ref-templates-type-subtree`, list templates are more verbose but provide maximum control. Prefer list templates when you **don’t yet have** a complete schema tree (e.g., while building an ECS mapping from scratch). Generic data pipeline -------------------------------------------------------------------------------- List templates are a key **data pipeline** step for mapping: .. mermaid:: flowchart TD A["Input
(imudp, imtcp, imkafka)"] B["Parser
(mmjsonparse, mmaudit)"] C["Template
list (mapping)"] D["Action
(omfile, omelasticsearch)"] A --> B --> C --> D Example: simple ECS mapping (jsonftree) -------------------------------------------------------------------------------- A minimal list template that emits selected ECS fields in JSON format. Use ``option.jsonftree="on"`` so dotted ``outname`` values become nested objects instead of flat strings: .. code-block:: none template(name="ecs_min" type="list" option.jsonftree="on") { property(outname="@timestamp" name="timereported" format="jsonf" dateFormat="rfc3339") property(outname="event.original" name="msg" format="jsonf") property(outname="host.hostname" name="hostname" format="jsonf") property(outname="log.level" name="syslogseverity-text" format="jsonf") } This produces valid JSON without hand-crafted quoting or braces. Example: fixing a field with a constant (jsonftree) -------------------------------------------------------------------------------- Sometimes you need to set a **fixed JSON field** (e.g., a version marker or a tag). Use a **constant** statement with `outname` and `format="jsonf"` so the encoder handles quoting consistently: .. code-block:: none template(name="ecs_fix" type="list" option.jsonftree="on") { property(outname="@timestamp" name="timereported" format="jsonf" dateFormat="rfc3339") property(outname="event.original" name="msg" format="jsonf") /* fixed field via constant, encoded as JSON */ constant(outname="@version" value="1" format="jsonf") } Example: Palo Alto firewall (LEEF → ECS) -------------------------------------------------------------------------------- A practical case is mapping Palo Alto firewall logs into ECS fields. The typical workflow looks like this: .. mermaid:: flowchart TD A["Input
(imtcp)"] B["Parser
(mmleefparse)"] C["Template
list (LEEF→ECS mapping)"] D["Action
(omelasticsearch)"] A --> B --> C --> D The list template performs field-by-field mapping using ``jsonftree`` to keep dotted field names properly nested: .. code-block:: none template(name="outfmt" type="list" option.jsonftree="on") { property(outname="@timestamp" name="timereported" format="jsonf" dateFormat="rfc3339") property(outname="event.created" name="$!leef!fields!ReceiveTime" format="jsonf") property(outname="observer.serial_number" name="$!leef!fields!SerialNumber" format="jsonf") property(outname="event.category" name="$!leef!fields!Type" format="jsonf") property(outname="event.action" name="$!leef!fields!Subtype" format="jsonf") property(outname="client.ip" name="$!leef!fields!src" format="jsonf") property(outname="source.ip" name="$!leef!fields!src" format="jsonf") property(outname="server.ip" name="$!leef!fields!dst" format="jsonf") property(outname="destination.ip" name="$!leef!fields!dst" format="jsonf") property(outname="client.user.name" name="$!leef!fields!usrName" format="jsonf") property(outname="source.user.name" name="$!leef!fields!usrName" format="jsonf") property(outname="server.user.name" name="$!leef!fields!DestinationUser" format="jsonf") property(outname="destination.user.name" name="$!leef!fields!DestinationUser" format="jsonf") property(outname="network.application" name="$!leef!fields!Application" format="jsonf") property(outname="client.port" name="$!leef!fields!srcPort" format="jsonf" dataType="number") property(outname="source.port" name="$!leef!fields!srcPort" format="jsonf" dataType="number") property(outname="destination.port" name="$!leef!fields!dstPort" format="jsonf" dataType="number") property(outname="server.port" name="$!leef!fields!dstPort" format="jsonf" dataType="number") property(outname="labels" name="$!leef!fields!Flags" format="jsonf") property(outname="network.transport" name="$!leef!fields!proto" format="jsonf") property(outname="event.outcome" name="$!leef!fields!action" format="jsonf") property(outname="network.bytes" name="$!leef!fields!totalBytes" format="jsonf" dataType="number") property(outname="client.bytes" name="$!leef!fields!srcBytes" format="jsonf" dataType="number") property(outname="source.bytes" name="$!leef!fields!srcBytes" format="jsonf" dataType="number") property(outname="server.bytes" name="$!leef!fields!dstBytes" format="jsonf" dataType="number") property(outname="destination.bytes" name="$!leef!fields!dstBytes" format="jsonf" dataType="number") property(outname="network.packets" name="$!leef!fields!totalPackets" format="jsonf" dataType="number") property(outname="event.start" name="$!leef!fields!StartTime" format="jsonf") property(outname="event.duration" name="$!leef!fields!ElapsedTime" format="jsonf" dataType="number") property(outname="client.packets" name="$!leef!fields!srcPackets" format="jsonf" dataType="number") property(outname="source.packets" name="$!leef!fields!srcPackets" format="jsonf" dataType="number") property(outname="server.packets" name="$!leef!fields!dstPackets" format="jsonf" dataType="number") property(outname="destination.packets" name="$!leef!fields!dstPackets" format="jsonf" dataType="number") property(outname="observer.hostname" name="$!leef!fields!DeviceName" format="jsonf") } Notes -------------------------------------------------------------------------------- - Prefer `property(... format="jsonf")` for dynamic fields; use **`constant(outname=…, format="jsonf")`** for small fixed values. - Best used when mapping output **field by field**. - For complete schema trees, prefer :ref:`ref-templates-type-subtree`. See also -------------------------------------------------------------------------------- - :ref:`ref-templates-type-subtree` - :ref:`ref-templates-statement-constant` - :ref:`ref-templates-statement-property` - :ref:`ref-mmleefparse` - :ref:`ref-ommongodb` - :ref:`ref-omelasticsearch` - :ref:`ref-omfile` - :ref:`ref-templates` rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-type-string.rst0000644000000000000000000000013115241075234025555 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.742712905 rsyslog-8.2608.0/doc/source/reference/templates/templates-type-string.rst0000664000175000017500000000265515241075234025232 0ustar00rgerrger.. _ref-templates-type-string: String template type ==================== .. summary-start Uses a single template string mixing constants and replacement variables. Best suited for textual output with simple manipulation needs. .. summary-end String templates closely resemble the legacy ``$template`` statement. They have a mandatory parameter ``string`` which holds the template string to be applied. The string mixes constant text and replacement variables processed by the :doc:`property replacer <../../configuration/property_replacer>`. Example: .. code-block:: none template(name="tpl3" type="string" string="%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n" ) The text between percent signs is interpreted by the property replacer, which reads message properties and applies options for formatting and processing. When a string template is used as an ``omfile`` ``dynaFile`` name, escape each message-derived path component with ``secpath-replace``. This is needed for fields such as ``HOSTNAME``, ``programname``, ``APP-NAME``, or variables populated from message content: .. code-block:: none template(name="DynFile" type="string" string="/var/log/hosts/%HOSTNAME:::secpath-replace%/%programname:::secpath-replace%.log") The escaping must be applied to the properties that form path components, not to the whole path including fixed separators. rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-options.rst0000644000000000000000000000013215132733117024764 xustar0030 mtime=1768666703.926620526 30 atime=1787067671.784439809 30 ctime=1787067793.729712662 rsyslog-8.2608.0/doc/source/reference/templates/templates-options.rst0000666000175000017500000000375015132733117024437 0ustar00rgerrger.. _ref-templates-options: Template options ================ .. summary-start Global modifiers applied to a template. Include SQL and JSON helpers and case sensitivity control. .. summary-end Template options influence the whole template and are specified as parameters of the ``template()`` object. They are distinct from property options which apply only to individual properties. Available options (case-insensitive): ``option.sql`` Format string for MariaDB/MySQL. Replaces single quotes (``'``) and backslashes (``\\``) by escaped counterparts (``\\'`` and ``\\\\``). MySQL must run with ``NO_BACKSLASH_ESCAPES`` turned off. ``option.stdsql`` Format string for standards-compliant SQL servers. Replaces single quotes by doubled quotes (``''``). Use this with MySQL when ``NO_BACKSLASH_ESCAPES`` is enabled. ``option.json`` Escape data suitable for JSON. ``option.jsonf`` Render the template as a JSON object, adding braces and commas between elements. ``option.jsonftree`` Render as JSON like ``option.jsonf`` but also interpret dotted ``outname`` segments (for example ``event.dataset.name``) as nested objects. When this option is not set, dotted names remain flat strings in the output to preserve legacy behaviour. ``option.caseSensitive`` Treat property names as case sensitive. Normally names are converted to lowercase at definition time. Enable this if JSON (``$!*``), local (``!.``), or global (``$!``) properties contain uppercase letters. Options ``option.sql``, ``option.stdsql``, ``option.json``, ``option.jsonf``, and ``option.jsonftree`` are mutually exclusive. Either ``option.sql`` or ``option.stdsql`` must be specified when writing into a database to guard against SQL injection. The database writer checks for the presence of one of these options and refuses to run otherwise. These options can also be useful when generating files intended for later import into a database. Do not enable them without need as they introduce extra processing overhead. rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-type-plugin.rst0000644000000000000000000000013215132733117025546 xustar0030 mtime=1768666703.926620526 30 atime=1787067671.768439511 30 ctime=1787067793.740712867 rsyslog-8.2608.0/doc/source/reference/templates/templates-type-plugin.rst0000666000175000017500000000125715132733117025221 0ustar00rgerrger.. _ref-templates-type-plugin: Plugin template type ==================== .. summary-start Delegates string generation to a plugin for maximum performance. Configuration selects the plugin by name. .. summary-end In plugin templates, the output string is generated by a plugin (also called a *string generator*). The format is fixed as coded in the plugin, which offers high performance at the cost of flexibility. The template parameter ``plugin`` specifies the generator name, and the plugin must be loaded before use. Configuration example: .. code-block:: none template(name="tpl4" type="plugin" plugin="mystrgen") Refer to the plugin's documentation for further details. rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-statement-property.rst0000644000000000000000000000013115241075234027156 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.736712793 rsyslog-8.2608.0/doc/source/reference/templates/templates-statement-property.rst0000664000175000017500000001270115241075234026624 0ustar00rgerrger.. _ref-templates-statement-property: Property statement ================== .. summary-start Extracts and optionally transforms message properties. Supports substring, case, regex, JSON formatting, and more. .. summary-end The property statement inserts property values. It can access any property and offers numerous options to select portions of a property or modify its text. Parameters ---------- - ``name`` – property to access - ``outname`` – output field name for structured outputs - ``dateFormat`` – date format for date-related properties. See :doc:`property replacer <../../configuration/property_replacer>` for available formats. The property replacer documentation currently lists options for string templates. The names here omit the ``date-`` prefix (e.g. ``year`` rather than ``date-year``). To build custom formats, combine multiple property statements: .. code-block:: none property(name="timereported" dateFormat="year") constant(value="-") property(name="timereported" dateFormat="month") constant(value="-") property(name="timereported" dateFormat="day") - ``date.inUTC`` – show date in UTC. Available since 8.18.0. - ``caseConversion`` – convert text case; ``lower`` or ``upper`` - ``controlCharacters`` – handle control characters: ``escape``, ``escape-octal``, ``space``, or ``drop``. ``escape`` keeps the legacy decimal ``#010`` style, while ``escape-octal`` uses the octal ``#012`` style used by receive-time control-character escaping. RainerScript example: .. code-block:: none template(name="octal-control" type="list") { property(name="msg" controlCharacters="escape-octal") constant(value="\n") } YAML example: .. code-block:: yaml templates: - name: octal-control type: list elements: - property: name: msg controlCharacters: escape-octal - constant: value: "\n" - ``securePath`` – escape a property for use as one path component in an ``omfile`` dynafile template; ``drop`` removes path separators and ``replace`` changes them to ``_``. Use ``replace`` for message-derived fields such as host names, application names, program names, or parsed variables. - ``format`` – field format. Supported values: - ``csv`` – generate CSV data - ``json`` – JSON-encode content without field header - ``jsonf`` – complete JSON field - ``jsonr`` – avoid double escaping while keeping JSON safe - ``jsonfr`` – combination of ``jsonf`` and ``jsonr`` - ``position.to`` – end position. Since 8.2302.0, negative values strip characters from the end. For example, ``position.from="2" position.to="-1"`` removes the first and last character. This is handy when removing surrounding characters such as brackets: .. code-block:: none property(name="msg" position.from="2" position.to="-1") With an input of ``[abc]`` the result is ``abc``. This is especially useful when parsing ``STRUCTURED-DATA`` fields. - ``position.relativeToEnd`` – interpret positions relative to end of string (since 7.3.10) - ``fixedWidth`` – pad string with spaces up to ``position.to`` when shorter; ``on`` or ``off`` (default) (since 8.13.0) - ``compressSpace`` – compress multiple spaces to one, applied after substring extraction (since 8.18.0) - ``field.number`` – select this field match - ``field.delimiter`` – decimal value of delimiter character - ``regex.expression`` – regular expression - ``regex.type`` – ``ERE`` or ``BRE`` - ``regex.noMatchMode`` – action when there is no match - ``regex.match`` – match to use - ``regex.subMatch`` – submatch to use - ``dropLastLf`` – drop trailing LF - ``mandatory`` – if ``on``, always emit field for structured outputs even when empty - ``spIfNo1stSp`` – expert option for RFC3164 processing - ``dataType`` – for ``jsonf`` format only; sets JSON data type. Rsyslog properties are strings, but some consuming systems require numbers or booleans. ``dataType`` controls how the ``jsonf`` field is emitted. Supported values: - ``number`` – emit numeric value, using 0 if empty - ``string`` – emit as string (default) - ``auto`` – use number if integer, otherwise string - ``bool`` – emit ``true`` unless value is empty or ``0`` ``dataType`` does not create JSON arrays or objects from strings. If the incoming message text contains JSON such as ``["a","b"]``, parse it first with :ref:`mmjsonparse `. If an already extracted property contains JSON text, parse that string with :doc:`parse_json() <../../rainerscript/functions/rs-parse_json>`. Then render the parsed property with ``format="jsonf"``. Rsyslog intentionally does not provide ``dataType="array"`` for templates. - ``onEmpty`` – for ``jsonf`` format only; handling of empty values: ``keep``, ``skip``, or ``null`` Dynafile path components ------------------------ When a list template is used as an ``omfile`` ``dynaFile`` name, apply ``securePath="replace"`` to every property that can be influenced by the message or sender. Fixed directory separators belong in ``constant()`` statements; do not apply ``securePath`` to the complete path. .. code-block:: none template(name="DynFile" type="list") { constant(value="/var/log/hosts/") property(name="hostname" securePath="replace") constant(value="/") property(name="programname" securePath="replace") constant(value=".log") } rsyslog-8.2608.0/doc/source/reference/templates/PaxHeaders/templates-type-subtree.rst0000644000000000000000000000013215132733117025721 xustar0030 mtime=1768666703.926620526 30 atime=1787067671.761439381 30 ctime=1787067793.744712942 rsyslog-8.2608.0/doc/source/reference/templates/templates-type-subtree.rst0000666000175000017500000000544015132733117025372 0ustar00rgerrger.. _ref-templates-type-subtree: .. _templates.parameter.type-subtree: Subtree template type ===================== .. index:: single: template; type=subtree single: templates; subtree type .. summary-start Builds output from a full JSON subtree (CEE). Best used when the schema has already been remapped and an appropriate variable tree exists. .. summary-end :Name: ``type="subtree"`` :Scope: template :Type: subtree :Introduced: 7.1.4 Description ----------- The *subtree template type* generates output from a complete (CEE/JSON) subtree. This is useful when working with **data pipelines** where schema mapping is done beforehand and a full variable tree (e.g. ``$!ecs``) is available. This method is required when an entire subtree must be placed at the root of the generated object. With other template types, only sub-containers can be produced. Constant text cannot be inserted inside subtree templates. Subtree templates are often used with structured outputs such as :ref:`ommongodb `, :ref:`omelasticsearch `, or with text-based outputs like :ref:`omfile `. They are particularly effective after message transformation with parsing modules such as :ref:`mmjsonparse `, :ref:`mmaudit `, or :ref:`mmleefparse `. Example: ECS mapping -------------------- A typical workflow is to normalize message content into an ECS-compatible subtree and then export it with a subtree template: .. code-block:: none set $!ecs!event!original = $msg; set $!ecs!host!hostname = $hostname; set $!ecs!log!level = $syslogseverity-text; set $!ecs!observer!type = "rsyslog"; template(name="ecs_tpl" type="subtree" subtree="$!ecs") Here the message is mapped into ECS fields under ``$!ecs``. The complete ECS subtree is then emitted as JSON by the template. Data pipeline usage ------------------- Subtree templates are a natural part of rsyslog data pipelines: .. mermaid:: flowchart TD A["Input
(imudp, imtcp, imkafka)"] B["Parser
(mmjsonparse, mmaudit, ...)"] C["Schema Tree
($!ecs)"] D["Template
type=subtree"] E["Action
(omfile, omkafka, ...)"] A --> B --> C --> D --> E Alternative mapping approach ---------------------------- If you do **not** yet have a remapped schema tree, consider using a :ref:`list template ` instead. List templates allow mapping fields one-by-one into structured output before exporting. Notes ----- * Use subtree templates when a full schema tree is already present. * Use list templates when building or remapping the schema incrementally. See also -------- * :ref:`ref-templates-type-list` * :ref:`ref-templates` * :ref:`ref-ommongodb` * :ref:`ref-omelasticsearch` * :ref:`ref-omfile` * :ref:`ref-omkafka` rsyslog-8.2608.0/doc/source/reference/PaxHeaders/properties0000644000000000000000000000013215241076621020665 xustar0030 mtime=1787067793.722712532 30 atime=1787067808.811993704 30 ctime=1787067793.722712532 rsyslog-8.2608.0/doc/source/reference/properties/0000775000175000017500000000000015241076621020406 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogpriority.rst0000644000000000000000000000013215132733117026237 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.751457836 30 ctime=1787067793.678711712 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogpriority.rst0000666000175000017500000000164515132733117025713 0ustar00rgerrger.. _prop-message-syslogpriority: .. _properties.message.syslogpriority: syslogpriority ============== .. index:: single: properties; syslogpriority single: syslogpriority .. summary-start Provides the same numeric value as :ref:`prop-message-syslogseverity` for historical reasons. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogpriority :Category: Message Properties :Type: integer Description ----------- An alias for :ref:`prop-message-syslogseverity` - included for historical reasons (be careful: it still is the severity, not PRI!). The alias mirrors the same derived value even for inputs without a syslog header. Usage ----- .. _properties.message.syslogpriority-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogpriority") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogseverity-text.rst0000644000000000000000000000013215132733117027212 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.744457706 30 ctime=1787067793.680711749 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogseverity-text.rst0000666000175000017500000000331315132733117026660 0ustar00rgerrger.. _prop-message-syslogseverity-text: .. _properties.message.syslogseverity-text: .. _properties.alias.syslogpriority-text: syslogseverity-text =================== .. index:: single: properties; syslogseverity-text single: syslogseverity-text .. summary-start Returns the textual syslog severity defined in RFC 5424 Table 2. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogseverity-text :Category: Message Properties :Type: string :Aliases: syslogpriority-text Description ----------- Returns the textual name of the syslog severity defined in RFC 3164 and RFC 5424 (Table 2, ``emerg`` through ``debug``). These strings describe how urgent the sending application considered the event. They map directly to the numeric values reported by :ref:`prop-message-syslogseverity`. When rsyslog processes a message that lacked a syslog header, this property reports the configured or inferred severity label instead of a name supplied by the sender. Usage ----- .. _properties.message.syslogseverity-text-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogseverity-text") } Notes ~~~~~ - Canonical severities: ``emerg``, ``alert``, ``crit``, ``err``, ``warning``, ``notice``, ``info``, ``debug``. - Filter by name with comparisons such as ``if $syslogseverity-text == 'warning'``. Keep in mind that emitters may use small spelling variations like ``warn``. - Severity remains independent from the facility; both combine into ``PRI`` (``PRI = facility * 8 + severity``). Aliases ~~~~~~~ - syslogpriority-text — alias for syslogseverity-text See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-iut.rst0000644000000000000000000000013215132733117023716 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.721457277 30 ctime=1787067793.642711041 rsyslog-8.2608.0/doc/source/reference/properties/message-iut.rst0000666000175000017500000000136515132733117023371 0ustar00rgerrger.. _prop-message-iut: .. _properties.message.iut: iut === .. index:: single: properties; iut single: iut .. summary-start Holds the monitorware InfoUnitType value when present. .. summary-end This property belongs to the **Message Properties** group. :Name: iut :Category: Message Properties :Type: string Description ----------- The monitorware InfoUnitType - used when talking to a `MonitorWare `_ backend (also for `Adiscon LogAnalyzer `_). Usage ----- .. _properties.message.iut-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="iut") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-uuid.rst0000644000000000000000000000013215132733117024063 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.636455693 30 ctime=1787067793.695712029 rsyslog-8.2608.0/doc/source/reference/properties/message-uuid.rst0000666000175000017500000000271615132733117023537 0ustar00rgerrger.. _prop-message-uuid: .. _properties.message.uuid: uuid ==== .. index:: single: properties; uuid single: uuid .. summary-start Exposes a per-message UUID generated on first access when enabled. .. summary-end This property belongs to the **Message Properties** group. :Name: uuid :Category: Message Properties :Type: string Description ----------- .. note:: Only available if rsyslog is built with ``--enable-uuid``. A UUID for the message. It is not present by default, but will be created on first read of the uuid property. Thereafter, in the local rsyslog instance, it will always be the same value. This is also true if rsyslog is restarted and messages stayed in an on-disk queue. Note well: the UUID is **not** automatically transmitted to remote syslog servers when forwarding. If that is needed, a special template needs to be created that contains the uuid. Likewise, the receiver must parse that UUID from that template. The uuid property is most useful if you would like to track a single message across multiple local destination. An example is messages being written to a database as well as to local files. Usage ----- .. _properties.message.uuid-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="uuid") } Notes ~~~~~ The UUID is generated lazily on first access and remains local unless explicitly forwarded. See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-month.rst0000644000000000000000000000013215132733117025076 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.812458974 30 ctime=1787067793.711712327 rsyslog-8.2608.0/doc/source/reference/properties/system-time-month.rst0000666000175000017500000000123115132733117024541 0ustar00rgerrger.. _prop-system-time-month: .. _properties.system-time.month: $month ====== .. index:: single: properties; $month single: $month .. summary-start Provides the current month as a two-digit number. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $month :Category: Time-Related System Properties :Type: integer Description ----------- The current month (2-digit). Usage ----- .. _properties.system-time.month-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$month") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-procid.rst0000644000000000000000000000013215132733117024375 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.806458862 30 ctime=1787067793.655711283 rsyslog-8.2608.0/doc/source/reference/properties/message-procid.rst0000666000175000017500000000203115132733117024037 0ustar00rgerrger.. _prop-message-procid: .. _properties.message.procid: procid ====== .. index:: single: properties; procid single: procid .. summary-start Carries the PROCID header field defined in RFC 5424 Section 6.2.6. .. summary-end This property belongs to the **Message Properties** group. :Name: procid :Category: Message Properties :Type: string Description ----------- Carries the ``PROCID`` header field defined in RFC 5424 Section 6.2.6. The field has no fixed syntax; senders often use it for a process name, PID, transaction identifier, or other origin-specific token, and RFC 5424 allows the NILVALUE (``-``) when no value applies. When rsyslog ingests messages without a syslog header, this property holds the configured or inferred value for the source instead of a transmitted header field. Usage ----- .. _properties.message.procid-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="procid") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-jsonmesg.rst0000644000000000000000000000013215132733117024742 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.738457594 30 ctime=1787067793.644711078 rsyslog-8.2608.0/doc/source/reference/properties/message-jsonmesg.rst0000666000175000017500000000274115132733117024414 0ustar00rgerrger.. _prop-message-jsonmesg: .. _properties.message.jsonmesg: jsonmesg ======== .. index:: single: properties; jsonmesg single: jsonmesg .. summary-start Provides the entire message object as a JSON representation. .. summary-end This property belongs to the **Message Properties** group. :Name: jsonmesg :Category: Message Properties :Type: JSON :Introduced: 8.3.0 Description ----------- The whole message object as JSON representation. Note that the JSON string will *not* include an LF and it will contain *all other message properties* specified here as respective JSON containers. It also includes all message variables in the "$!" subtree (this may be null if none are present). This property is primarily meant as an interface to other systems and tools that want access to the full property set (namely external plugins). Note that it contains the same data items potentially multiple times. For example, parts of the syslog tag will by contained in the rawmsg, syslogtag, and programname properties. As such, this property has some additional overhead. Thus, it is suggested to be used only when there is actual need for it. Usage ----- .. _properties.message.jsonmesg-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="jsonmesg") } Notes ~~~~~ Use this property when consumers require the complete structured message in a single JSON object. See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-inputname.rst0000644000000000000000000000013215132733117025115 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.709457054 30 ctime=1787067793.639710985 rsyslog-8.2608.0/doc/source/reference/properties/message-inputname.rst0000666000175000017500000000257115132733117024570 0ustar00rgerrger.. _prop-message-inputname: .. _properties.message.inputname: inputname ========= .. index:: single: properties; inputname single: inputname .. summary-start Identifies the rsyslog input module instance that produced the message. .. summary-end This property belongs to the **Message Properties** group. :Name: inputname :Category: Message Properties :Type: string Description ----------- The name of the input module that generated the message (e.g. "imuxsock", "imudp"). Note that not all modules necessarily provide this property. If not provided, it is an empty string. Also note that the input module may provide any value of its liking. Most importantly, it is **not** necessarily the module input name. Internal sources can also provide inputnames. Currently, "rsyslogd" is defined as inputname for messages internally generated by rsyslogd, for example startup and shutdown and error messages. This property is considered useful when trying to filter messages based on where they originated - e.g. locally generated messages ("rsyslogd", "imuxsock", "imklog") should go to a different place than messages generated somewhere else. Usage ----- .. _properties.message.inputname-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="inputname") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-fromhost-ip.rst0000644000000000000000000000013215132733117025364 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.652455991 30 ctime=1787067793.630710817 rsyslog-8.2608.0/doc/source/reference/properties/message-fromhost-ip.rst0000666000175000017500000000145415132733117025036 0ustar00rgerrger.. _prop-message-fromhost-ip: .. _properties.message.fromhost-ip: fromhost-ip =========== .. index:: single: properties; fromhost-ip single: fromhost-ip .. summary-start Provides the message source as an IP address just like :ref:`prop-message-fromhost`. .. summary-end This property belongs to the **Message Properties** group. :Name: fromhost-ip :Category: Message Properties :Type: string Description ----------- The same as :ref:`prop-message-fromhost`, but always as an IP address. Local inputs (like imklog) use 127.0.0.1 in this property. Usage ----- .. _properties.message.fromhost-ip-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="fromhost-ip") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-timereceived.rst0000644000000000000000000000013115241075234025561 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.67957968 30 ctime=1787067793.689711917 rsyslog-8.2608.0/doc/source/reference/properties/message-timereceived.rst0000664000175000017500000000217615241075234025234 0ustar00rgerrger.. _prop-message-timereceived: .. _properties.message.timereceived: timereceived ============ .. index:: single: properties; timereceived single: timereceived .. summary-start Alias for ``timegenerated`` that records when rsyslog received the message. .. summary-end This property belongs to the **Message Properties** group. :Name: timereceived :Category: Message Properties :Type: timestamp Description ----------- ``timereceived`` is an alias for :ref:`prop-message-timegenerated`. It returns the same timestamp: the point in time when the operating system hands the message to rsyslog's reception buffer, before queueing or ruleset processing. The alias exists because the older ``timegenerated`` name can be confused with the sender-side timestamp. The sender-side timestamp remains :ref:`prop-message-timereported`. Usage ----- .. _properties.message.timereceived-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="timereceived") } See also -------- See :doc:`message-timegenerated` for the detailed behavior and :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-qhour.rst0000644000000000000000000000013215132733117025107 xustar0030 mtime=1768666703.926620526 30 atime=1787067672.863459924 30 ctime=1787067793.718712457 rsyslog-8.2608.0/doc/source/reference/properties/system-time-qhour.rst0000666000175000017500000000143415132733117024557 0ustar00rgerrger.. _prop-system-time-qhour: .. _properties.system-time.qhour: $qhour ====== .. index:: single: properties; $qhour single: $qhour .. summary-start Indicates the current quarter-hour within the hour. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $qhour :Category: Time-Related System Properties :Type: integer Description ----------- The current quarter hour we are in. Much like :ref:`prop-system-time-hhour`, but values range from 0 to 3 (for the four quarter hours that are in each hour). Usage ----- .. _properties.system-time.qhour-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$qhour") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-bom.rst0000644000000000000000000000013215132733117023572 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.662456177 30 ctime=1787067793.698712085 rsyslog-8.2608.0/doc/source/reference/properties/system-bom.rst0000666000175000017500000000134715132733117023245 0ustar00rgerrger.. _prop-system-bom: .. _properties.system.bom: $bom ==== .. index:: single: properties; $bom single: $bom .. summary-start Emits the UTF-8 byte-order mark for use in templates when required. .. summary-end This property belongs to the **System Properties** group. :Name: $bom :Category: System Properties :Type: string Description ----------- The UTF-8 encoded Unicode byte-order mask (BOM). This may be useful in templates for RFC5424 support, when the character set is known to be Unicode. Usage ----- .. _properties.system.bom-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$bom") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogfacility.rst0000644000000000000000000000013215132733117026162 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.727457389 30 ctime=1787067793.673711619 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogfacility.rst0000666000175000017500000000335715132733117025640 0ustar00rgerrger.. _prop-message-syslogfacility: .. _properties.message.syslogfacility: syslogfacility ============== .. index:: single: properties; syslogfacility single: syslogfacility .. summary-start Contains the numeric syslog facility extracted from the message. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogfacility :Category: Message Properties :Type: integer Description ----------- Reports the numeric syslog facility defined in RFC 3164 and RFC 5424 (Table 1 of RFC 5424). The field is a 5-bit code describing the general origin of the message (for example 3 for ``daemon`` or 20 for ``local4``). Facility values combine with severity to form the PRI value (``PRI = facility * 8 + severity``), but otherwise remain independent. For inputs received without a syslog header, rsyslog supplies this value from configuration or other metadata. Usage ----- .. _properties.message.syslogfacility-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogfacility") } Notes ~~~~~ - Common facility codes: - **0** ``kern`` - **1** ``user`` - **2** ``mail`` - **3** ``daemon`` - **4** ``auth`` - **5** ``syslog`` - **6** ``lpr`` - **7** ``news`` - **8** ``uucp`` - **9** ``cron`` - **10** ``authpriv`` - **11** ``ftp`` - **12-15** reserved/OS-specific - **16-23** ``local0``..``local7`` - Applications assign facilities themselves, so naming can diverge by platform. The ``local0``..``local7`` range is intentionally left for site-defined uses. - Filter or route by facility, for example ``if $syslogfacility == 3`` or with legacy selectors such as ``mail.*``. See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-pri.rst0000644000000000000000000000013215132733117023707 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.707457016 30 ctime=1787067793.653711246 rsyslog-8.2608.0/doc/source/reference/properties/message-pri.rst0000666000175000017500000000214115132733117023353 0ustar00rgerrger.. _prop-message-pri: .. _properties.message.pri: pri === .. index:: single: properties; pri single: pri .. summary-start Provides the undecoded PRI header value defined by RFC 5424 Section 6.2.1. .. summary-end This property belongs to the **Message Properties** group. :Name: pri :Category: Message Properties :Type: string Description ----------- Contains the raw ``PRI`` header value from RFC 5424 Section 6.2.1, which is written as ```` in front of the syslog message. The integer inside the angle brackets encodes facility and severity per ``PRIVAL = facility * 8 + severity``. Facilities 0 through 23 and severities 0 through 7 follow the tables in RFC 5424 (Tables 1 and 2). When rsyslog reads data without a syslog header, the ``PRI`` value is derived from input metadata or configuration so downstream templates can still compute facility and severity. Usage ----- .. _properties.message.pri-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="pri") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-now-unixtimestamp.rst0000644000000000000000000000013215132733117027461 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.860459869 30 ctime=1787067793.713712364 rsyslog-8.2608.0/doc/source/reference/properties/system-time-now-unixtimestamp.rst0000666000175000017500000000332215132733117027127 0ustar00rgerrger.. _prop-system-time-now-unixtimestamp: .. _properties.system-time.now-unixtimestamp: $now-unixtimestamp ================== .. index:: single: properties; $now-unixtimestamp single: $now-unixtimestamp .. summary-start Exposes the current time as a monotonically increasing Unix timestamp. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $now-unixtimestamp :Category: Time-Related System Properties :Type: integer Description ----------- The current time as a unix timestamp (seconds since epoch). This actually is a monotonically increasing counter and as such can also be used for any other use cases that require such counters. Usage ----- .. _properties.system-time.now-unixtimestamp-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$now-unixtimestamp") } Additional example: .. code-block:: none # Get Unix timestamp of current message set $.tnow = $$now-unixtimestamp # Rate limit info to 5 every 60 seconds if ($!severity == 6 and $!facility == 17) then { if (($.tnow - $/trate) > 60) then { # 5 seconds window expired, allow more messages set $/trate = $.tnow; set $/ratecount = 0; } if ($/ratecount > 5) then { # discard message stop } else { set $/ratecount = $/ratecount + 1; } } Notes ~~~~~ .. note:: By definition, there is no "UTC equivalent" of the ``$now-unixtimestamp`` property. - Properties that include hyphens require the double dollar form (``$$``) when used in expressions so the parser does not treat the hyphen as subtraction. See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-hhour.rst0000644000000000000000000000013215132733117025076 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.729457427 30 ctime=1787067793.704712196 rsyslog-8.2608.0/doc/source/reference/properties/system-time-hhour.rst0000666000175000017500000000140615132733117024545 0ustar00rgerrger.. _prop-system-time-hhour: .. _properties.system-time.hhour: $hhour ====== .. index:: single: properties; $hhour single: $hhour .. summary-start Indicates whether the current minute is in the first or second half of the hour. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $hhour :Category: Time-Related System Properties :Type: integer Description ----------- The current half hour we are in. From minute 0 to 29, this is always 0 while from 30 to 59 it is always 1. Usage ----- .. _properties.system-time.hhour-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$hhour") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-protocol-version.rst0000644000000000000000000000013215132733117026441 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.789458545 30 ctime=1787067793.660711377 rsyslog-8.2608.0/doc/source/reference/properties/message-protocol-version.rst0000666000175000017500000000211515132733117026106 0ustar00rgerrger.. _prop-message-protocol-version: .. _properties.message.protocol-version: protocol-version ================ .. index:: single: properties; protocol-version single: protocol-version .. summary-start Carries the VERSION header field defined by RFC 5424 Section 6.2.2. .. summary-end This property belongs to the **Message Properties** group. :Name: protocol-version :Category: Message Properties :Type: string Description ----------- Contains the RFC 5424 Section 6.2.2 ``VERSION`` header field that signals which syslog message format the sender used. RFC 5424 assigns ``1`` to the standard defined in the specification and reserves future numbers for later revisions. When rsyslog consumes data without a native syslog header, this property reflects the configured or inferred version value for that input, commonly ``1``. Usage ----- .. _properties.message.protocol-version-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="protocol-version") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-minute.rst0000644000000000000000000000013215132733117025252 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.773458247 30 ctime=1787067793.709712289 rsyslog-8.2608.0/doc/source/reference/properties/system-time-minute.rst0000666000175000017500000000124315132733117024720 0ustar00rgerrger.. _prop-system-time-minute: .. _properties.system-time.minute: $minute ======= .. index:: single: properties; $minute single: $minute .. summary-start Returns the current minute as a two-digit number. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $minute :Category: Time-Related System Properties :Type: integer Description ----------- The current minute (2-digit). Usage ----- .. _properties.system-time.minute-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$minute") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-source.rst0000644000000000000000000000013015132733117024413 xustar0030 mtime=1768666703.925620511 28 atime=1787067672.6314556 30 ctime=1787067793.666711488 rsyslog-8.2608.0/doc/source/reference/properties/message-source.rst0000666000175000017500000000122215132733117024060 0ustar00rgerrger.. _prop-message-source: .. _properties.message.source: source ====== .. index:: single: properties; source single: source .. summary-start Provides the same hostname value as :ref:`prop-message-hostname`. .. summary-end This property belongs to the **Message Properties** group. :Name: source :Category: Message Properties :Type: string Description ----------- Alias for :ref:`prop-message-hostname`. Usage ----- .. _properties.message.source-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="source") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-structured-data.rst0000644000000000000000000000013215132733117026230 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.796458675 30 ctime=1787067793.669711544 rsyslog-8.2608.0/doc/source/reference/properties/message-structured-data.rst0000666000175000017500000000213715132733117025701 0ustar00rgerrger.. _prop-message-structured-data: .. _properties.message.structured-data: structured-data =============== .. index:: single: properties; structured-data single: structured-data .. summary-start Provides the STRUCTURED-DATA field defined in RFC 5424 Section 6.3. .. summary-end This property belongs to the **Message Properties** group. :Name: structured-data :Category: Message Properties :Type: string Description ----------- Contains the ``STRUCTURED-DATA`` portion of a syslog message as defined in RFC 5424 Section 6.3. The field holds zero or more SD-ELEMENT blocks with ASCII SD-IDs and UTF-8 parameter values. When no structured data is present, RFC 5424 requires the NILVALUE (``-``). For events ingested without a syslog header, rsyslog populates this property with structured data derived from configuration or input metadata, if any. Usage ----- .. _properties.message.structured-data-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="structured-data") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-myhostname.rst0000644000000000000000000000013215132733117025201 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.684456588 30 ctime=1787067793.700712122 rsyslog-8.2608.0/doc/source/reference/properties/system-myhostname.rst0000666000175000017500000000134015132733117024645 0ustar00rgerrger.. _prop-system-myhostname: .. _properties.system.myhostname: $myhostname =========== .. index:: single: properties; $myhostname single: $myhostname .. summary-start Returns the local host name as rsyslog knows it. .. summary-end This property belongs to the **System Properties** group. :Name: $myhostname :Category: System Properties :Type: string Description ----------- The name of the current host as it knows itself (probably useful for filtering in a generic way). Usage ----- .. _properties.system.myhostname-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$myhostname") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-hour.rst0000644000000000000000000000013215132733117024726 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.745457725 30 ctime=1787067793.707712252 rsyslog-8.2608.0/doc/source/reference/properties/system-time-hour.rst0000666000175000017500000000124415132733117024375 0ustar00rgerrger.. _prop-system-time-hour: .. _properties.system-time.hour: $hour ===== .. index:: single: properties; $hour single: $hour .. summary-start Returns the current hour in 24-hour format. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $hour :Category: Time-Related System Properties :Type: integer Description ----------- The current hour in military (24 hour) time (2-digit). Usage ----- .. _properties.system-time.hour-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$hour") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-rawmsg-after-pri.rst0000644000000000000000000000013215132733117026304 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.620455395 30 ctime=1787067793.662711414 rsyslog-8.2608.0/doc/source/reference/properties/message-rawmsg-after-pri.rst0000666000175000017500000000256715132733117025764 0ustar00rgerrger.. _prop-message-rawmsg-after-pri: .. _properties.message.rawmsg-after-pri: rawmsg-after-pri ================ .. index:: single: properties; rawmsg-after-pri single: rawmsg-after-pri .. summary-start Contains the raw message content with the syslog PRI removed when present. .. summary-end This property belongs to the **Message Properties** group. :Name: rawmsg-after-pri :Category: Message Properties :Type: string Description ----------- Almost the same as :ref:`prop-message-rawmsg`, but the syslog PRI is removed. If no PRI was present, ``rawmsg-after-pri`` is identical to :ref:`prop-message-rawmsg`. Note that the syslog PRI is a header field that contains information on syslog facility and severity. It is enclosed in greater-than and less-than characters, e.g. ``<191>``. This field is often not written to log files, but usually needs to be present for the receiver to properly classify the message. There are some rare cases where one wants the raw message, but not the PRI. You can use this property to obtain that. In general, you should know that you need this format, otherwise stay away from the property. Usage ----- .. _properties.message.rawmsg-after-pri-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="rawmsg-after-pri") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogpriority-text.rst0000644000000000000000000000013215132733117027221 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.759457986 30 ctime=1787067793.675711656 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogpriority-text.rst0000666000175000017500000000162115132733117026667 0ustar00rgerrger.. _prop-message-syslogpriority-text: .. _properties.message.syslogpriority-text: syslogpriority-text =================== .. index:: single: properties; syslogpriority-text single: syslogpriority-text .. summary-start Returns the same textual severity string as :ref:`prop-message-syslogseverity-text`. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogpriority-text :Category: Message Properties :Type: string Description ----------- An alias for :ref:`prop-message-syslogseverity-text`. The rendered string matches the derived severity name even when no syslog header was present on receipt. Usage ----- .. _properties.message.syslogpriority-text-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogpriority-text") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogtag.rst0000644000000000000000000000013215132733117025131 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.443452095 30 ctime=1787067793.684711824 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogtag.rst0000666000175000017500000000123115132733117024574 0ustar00rgerrger.. _prop-message-syslogtag: .. _properties.message.syslogtag: syslogtag ========= .. index:: single: properties; syslogtag single: syslogtag .. summary-start Returns the TAG field extracted from the syslog message header. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogtag :Category: Message Properties :Type: string Description ----------- TAG from the message. Usage ----- .. _properties.message.syslogtag-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogtag") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-rawmsg.rst0000644000000000000000000000013215132733117024415 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.613455264 30 ctime=1787067793.664711451 rsyslog-8.2608.0/doc/source/reference/properties/message-rawmsg.rst0000666000175000017500000000153215132733117024064 0ustar00rgerrger.. _prop-message-rawmsg: .. _properties.message.rawmsg: rawmsg ====== .. index:: single: properties; rawmsg single: rawmsg .. summary-start Provides the received message exactly as rsyslog stored it. .. summary-end This property belongs to the **Message Properties** group. :Name: rawmsg :Category: Message Properties :Type: string Description ----------- The message "as is". Should be useful for debugging and also if a message should be forwarded totally unaltered. Please notice *EscapecontrolCharactersOnReceive* is enabled by default, so it may be different from what was received in the socket. Usage ----- .. _properties.message.rawmsg-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="rawmsg") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-hostname.rst0000644000000000000000000000013215132733117024733 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.628455544 30 ctime=1787067793.637710948 rsyslog-8.2608.0/doc/source/reference/properties/message-hostname.rst0000666000175000017500000000136115132733117024402 0ustar00rgerrger.. _prop-message-hostname: .. _properties.message.hostname: .. _properties.alias.source: hostname ======== .. index:: single: properties; hostname single: hostname .. summary-start Captures the hostname transmitted within the syslog message. .. summary-end This property belongs to the **Message Properties** group. :Name: hostname :Category: Message Properties :Type: string :Aliases: source Description ----------- Hostname from the message. Usage ----- .. _properties.message.hostname-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="hostname") } Aliases ~~~~~~~ - source — alias for hostname See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-timegenerated.rst0000644000000000000000000000013115132733117025731 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.491452989 29 ctime=1787067793.68771188 rsyslog-8.2608.0/doc/source/reference/properties/message-timegenerated.rst0000666000175000017500000000254615132733117025407 0ustar00rgerrger.. _prop-message-timegenerated: .. _properties.message.timegenerated: timegenerated ============= .. index:: single: properties; timegenerated single: timegenerated .. summary-start Records when rsyslog received the message with high resolution. .. summary-end This property belongs to the **Message Properties** group. :Name: timegenerated :Category: Message Properties :Type: timestamp Description ----------- Timestamp captured when the operating system hands the message to rsyslog's reception buffer. The value reflects the precise moment rsyslog accepted the event, before any queueing or ruleset processing begins. If several messages are delivered in the same receive buffer (for example when TCP transports multiple entries together), they all carry the same ``timegenerated`` stamp because rsyslog accepted them at the same instant. The timestamp remains stable even if the message spends time in an in-memory or disk queue. As a result, ``timegenerated`` is usually newer than ``timereported`` (which comes from the sender) but still older than ``$now``, which is evaluated later during processing. Usage ----- .. _properties.message.timegenerated-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="timegenerated") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-programname.rst0000644000000000000000000000013215132733117025425 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.700456886 30 ctime=1787067793.657711321 rsyslog-8.2608.0/doc/source/reference/properties/message-programname.rst0000666000175000017500000000303515132733117025074 0ustar00rgerrger.. _prop-message-programname: .. _properties.message.programname: programname =========== .. index:: single: properties; programname single: programname .. summary-start Extracts the static program name portion from the syslog tag. .. summary-end This property belongs to the **Message Properties** group. :Name: programname :Category: Message Properties :Type: string Description ----------- The "static" part of the tag, as defined by BSD syslogd. For example, when TAG is "named[12345]", programname is "named". Precisely, the programname is terminated by either (whichever occurs first): - end of tag - nonprintable character - ':' - '[' - '/' The above definition has been taken from the FreeBSD syslogd sources. Please note that some applications include slashes in the static part of the tag, e.g. "app/foo[1234]". In this case, programname is "app". If they store an absolute path name like in "/app/foo[1234]", programname will become empty (""). If you need to actually store slashes as part of the programname, you can use the global option: .. code-block:: rsyslog global(parser.permitSlashInProgramName="on") to permit this. Then, a syslogtag of "/app/foo[1234]" will result in programname being "/app/foo". Note: this option is available starting at rsyslogd version 8.25.0. Usage ----- .. _properties.message.programname-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="programname") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-now.rst0000644000000000000000000000013115132733117024553 xustar0030 mtime=1768666703.926620526 30 atime=1787067672.824459197 29 ctime=1787067793.71671242 rsyslog-8.2608.0/doc/source/reference/properties/system-time-now.rst0000666000175000017500000000211315132733117024217 0ustar00rgerrger.. _prop-system-time-now: .. _properties.system-time.now: $now ==== .. index:: single: properties; $now single: $now .. summary-start Yields the current local date stamp when the message is processed. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $now :Category: Time-Related System Properties :Type: timestamp Description ----------- Reports the local system date stamp (``YYYY-MM-DD``) at the moment rsyslog processes the message. The value is independent of the event payload and changes whenever the ruleset advances to the next message. ``$now`` is always a little newer than ``timegenerated`` because rsyslog only evaluates it during processing, after the event has left the input queue. When queues back up, the gap between the two can grow from fractions of a second to minutes or hours. Usage ----- .. _properties.system-time.now-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$now") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogseverity.rst0000644000000000000000000000013215132733117026230 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.738457594 30 ctime=1787067793.682711787 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogseverity.rst0000666000175000017500000000353015132733117025677 0ustar00rgerrger.. _prop-message-syslogseverity: .. _properties.message.syslogseverity: .. _properties.alias.syslogpriority: syslogseverity ============== .. index:: single: properties; syslogseverity single: syslogseverity .. summary-start Provides the numeric syslog severity extracted from the message. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogseverity :Category: Message Properties :Type: integer :Aliases: syslogpriority Description ----------- Reports the numeric syslog severity defined in RFC 3164 and RFC 5424 (Table 2 of RFC 5424). The field is a 3-bit integer from 0 (``emerg``) to 7 (``debug``); smaller numbers indicate higher urgency. The sending application chooses this value, so real-world usage can vary and mappings are sometimes fuzzy. Severity combines with the facility code to form the PRI value (``PRI = facility * 8 + severity``). When rsyslog accepts messages without a syslog header, the severity comes from configured defaults or input metadata rather than a value that was transmitted on the wire. Usage ----- .. _properties.message.syslogseverity-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogseverity") } Notes ~~~~~ - Canonical severities: - **0** ``emerg`` - **1** ``alert`` - **2** ``crit`` - **3** ``err`` - **4** ``warning`` - **5** ``notice`` - **6** ``info`` - **7** ``debug`` - Filter by number or name; for example ``if $syslogseverity <= 3 then ...`` routes urgent messages (``emerg`` through ``err``). - The textual property :ref:`prop-message-syslogseverity-text` exposes the same information as words. Legacy selector syntax such as ``*.err`` works as well. Aliases ~~~~~~~ - syslogpriority — alias for syslogseverity See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-msgid.rst0000644000000000000000000000013215132733117024220 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.768458154 30 ctime=1787067793.649711171 rsyslog-8.2608.0/doc/source/reference/properties/message-msgid.rst0000666000175000017500000000177215132733117023675 0ustar00rgerrger.. _prop-message-msgid: .. _properties.message.msgid: msgid ===== .. index:: single: properties; msgid single: msgid .. summary-start Carries the MSGID header field defined in RFC 5424 Section 6.2.7. .. summary-end This property belongs to the **Message Properties** group. :Name: msgid :Category: Message Properties :Type: string Description ----------- Carries the ``MSGID`` header field defined in RFC 5424 Section 6.2.7. The value identifies the semantic type of the event (for example an SMTP transaction label) and RFC 5424 allows the NILVALUE (``-``) when the sender cannot provide one. When rsyslog processes messages that lacked a syslog header at ingestion, the property contains the configured or inferred MSGID value rather than an on-the-wire header. Usage ----- .. _properties.message.msgid-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="msgid") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-pri-text.rst0000644000000000000000000000013215132733117024671 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.714457147 30 ctime=1787067793.651711209 rsyslog-8.2608.0/doc/source/reference/properties/message-pri-text.rst0000666000175000017500000000176615132733117024351 0ustar00rgerrger.. _prop-message-pri-text: .. _properties.message.pri-text: pri-text ======== .. index:: single: properties; pri-text single: pri-text .. summary-start Formats the RFC 5424 PRI header as facility.severity with the numeric PRI appended. .. summary-end This property belongs to the **Message Properties** group. :Name: pri-text :Category: Message Properties :Type: string Description ----------- Formats the RFC 5424 Section 6.2.1 ``PRI`` value as ``facility.severity`` and appends the numeric ```` (for example ``local0.err<133>``). Facility and severity names follow Tables 1 and 2 from RFC 5424. For inputs that lack a syslog header, rsyslog derives the facility and severity from configuration or other metadata before rendering this property. Usage ----- .. _properties.message.pri-text-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="pri-text") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-msg.rst0000644000000000000000000000013115241075234023702 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.646711115 rsyslog-8.2608.0/doc/source/reference/properties/message-msg.rst0000664000175000017500000000133215241075234023346 0ustar00rgerrger.. _prop-message-msg: .. _properties.message.msg: msg === .. index:: single: properties; msg single: msg .. summary-start Returns the MSG part of the processed syslog message. .. summary-end This property belongs to the **Message Properties** group. :Name: msg :Category: Message Properties :Type: string Description ----------- The MSG part of the message (aka "the message"). Usage ----- .. _properties.message.msg-usage: .. rsyslog-doc-sample: validate-config .. code-block:: rsyslog template(name="example" type="list") { property(name="msg") } action(type="omfile" file="/dev/null" template="example") See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-fromhost.rst0000644000000000000000000000013115241075234024755 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.72658056 30 ctime=1787067793.635710911 rsyslog-8.2608.0/doc/source/reference/properties/message-fromhost.rst0000664000175000017500000000305015241075234024420 0ustar00rgerrger.. _prop-message-fromhost: .. _properties.message.fromhost: fromhost ======== .. index:: single: properties; fromhost single: fromhost .. summary-start Reports the hostname of the system from which the message was received. .. summary-end This property belongs to the **Message Properties** group. :Name: fromhost :Category: Message Properties :Type: string Description ----------- Hostname of the system the message was received from (in a relay chain, this is the system immediately in front of us and not necessarily the original sender). This is a DNS-resolved name, except if that is not possible or DNS resolution has been disabled. Reverse lookup results are cached; see :ref:`reverse_dns_cache` for controlling cache timeout. Forward lookups for outbound connections are not cached by rsyslog and are resolved via the system resolver whenever a connection is made. Case handling is input-specific. Some network inputs normalize the resolved name to lowercase for backward compatibility, while others preserve the DNS result by default. For inputs that support it, use the module or input ``PreserveCase`` parameter to choose the behavior: :ref:`imudp PreserveCase ` defaults to lowercase output and :ref:`imtcp PreserveCase ` defaults to preserving case. Usage ----- .. _properties.message.fromhost-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="fromhost") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-year.rst0000644000000000000000000000013215132733117024711 xustar0030 mtime=1768666703.926620526 30 atime=1787067672.832459347 30 ctime=1787067793.722712532 rsyslog-8.2608.0/doc/source/reference/properties/system-time-year.rst0000666000175000017500000000121615132733117024357 0ustar00rgerrger.. _prop-system-time-year: .. _properties.system-time.year: $year ===== .. index:: single: properties; $year single: $year .. summary-start Returns the current year as a four-digit number. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $year :Category: Time-Related System Properties :Type: integer Description ----------- The current year (4-digit). Usage ----- .. _properties.system-time.year-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$year") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-syslogfacility-text.rst0000644000000000000000000000013215132733117027144 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.731457464 30 ctime=1787067793.671711581 rsyslog-8.2608.0/doc/source/reference/properties/message-syslogfacility-text.rst0000666000175000017500000000302415132733117026611 0ustar00rgerrger.. _prop-message-syslogfacility-text: .. _properties.message.syslogfacility-text: syslogfacility-text =================== .. index:: single: properties; syslogfacility-text single: syslogfacility-text .. summary-start Returns the textual syslog facility defined in RFC 5424 Table 1. .. summary-end This property belongs to the **Message Properties** group. :Name: syslogfacility-text :Category: Message Properties :Type: string Description ----------- Returns the human-readable name of the syslog facility (such as ``daemon`` or ``local4``). The names follow the RFC 3164 and RFC 5424 mappings and correspond directly to the numeric property :ref:`prop-message-syslogfacility`. When the input does not supply a syslog header, rsyslog emits the configured or inferred facility name for the message instead. Usage ----- .. _properties.message.syslogfacility-text-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="syslogfacility-text") } Notes ~~~~~ - Expect the canonical names ``kern``, ``user``, ``mail``, ``daemon``, ``auth``, ``syslog``, ``lpr``, ``news``, ``uucp``, ``cron``, ``authpriv``, ``ftp``, system-reserved slots, and ``local0``..``local7``. - Some systems expose small spelling differences; compare strings carefully if you expect portable configurations. - Facility selection is independent from severity, but both values combine into ``PRI`` (``PRI = facility * 8 + severity``). See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-day.rst0000644000000000000000000000013215132733117024526 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.705456979 30 ctime=1787067793.702712159 rsyslog-8.2608.0/doc/source/reference/properties/system-time-day.rst0000666000175000017500000000123415132733117024174 0ustar00rgerrger.. _prop-system-time-day: .. _properties.system-time.day: $day ==== .. index:: single: properties; $day single: $day .. summary-start Returns the current day of the month as a two-digit number. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $day :Category: Time-Related System Properties :Type: integer Description ----------- The current day of the month (2-digit). Usage ----- .. _properties.system-time.day-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$day") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-fromhost-port.rst0000644000000000000000000000013215132733117025740 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.671456345 30 ctime=1787067793.633710873 rsyslog-8.2608.0/doc/source/reference/properties/message-fromhost-port.rst0000666000175000017500000000150415132733117025406 0ustar00rgerrger.. _prop-message-fromhost-port: .. _properties.message.fromhost-port: fromhost-port ============= .. index:: single: properties; fromhost-port single: fromhost-port .. summary-start Reports the numeric source port of the sender in line with :ref:`prop-message-fromhost`. .. summary-end This property belongs to the **Message Properties** group. :Name: fromhost-port :Category: Message Properties :Type: string Description ----------- The same as :ref:`prop-message-fromhost`, but contains the numeric source port of the sender. Local inputs provide an empty string. Usage ----- .. _properties.message.fromhost-port-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="fromhost-port") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-timereported.rst0000644000000000000000000000013215132733117025620 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.536453829 30 ctime=1787067793.691711954 rsyslog-8.2608.0/doc/source/reference/properties/message-timereported.rst0000666000175000017500000000241315132733117025266 0ustar00rgerrger.. _prop-message-timereported: .. _properties.message.timereported: .. _properties.alias.timestamp: timereported ============ .. index:: single: properties; timereported single: timereported .. summary-start Captures the timestamp present in the original message header. .. summary-end This property belongs to the **Message Properties** group. :Name: timereported :Category: Message Properties :Type: timestamp :Aliases: timestamp Description ----------- Timestamp copied from the sender supplied header. It represents when the originating application believes the event occurred, so accuracy depends on the remote clock, time zone configuration, and transport delays. Older transports frequently provide only second-level resolution. Messages that spent time on relays or queues can arrive with a ``timereported`` value that is minutes or hours behind ``timegenerated`` or ``$now``. Treat the field as a hint rather than an absolute truth when correlating events. Usage ----- .. _properties.message.timereported-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="timereported") } Aliases ~~~~~~~ - timestamp — alias for timereported See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-timestamp.rst0000644000000000000000000000013215132733117025120 xustar0030 mtime=1768666703.925620511 30 atime=1787067672.609455189 30 ctime=1787067793.693711991 rsyslog-8.2608.0/doc/source/reference/properties/message-timestamp.rst0000666000175000017500000000130715132733117024567 0ustar00rgerrger.. _prop-message-timestamp: .. _properties.message.timestamp: timestamp ========= .. index:: single: properties; timestamp single: timestamp .. summary-start Provides the same value as :ref:`prop-message-timereported` from the message header. .. summary-end This property belongs to the **Message Properties** group. :Name: timestamp :Category: Message Properties :Type: timestamp Description ----------- Alias for :ref:`prop-message-timereported`. Usage ----- .. _properties.message.timestamp-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="timestamp") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/system-time-wday.rst0000644000000000000000000000013215132733117024715 xustar0030 mtime=1768666703.926620526 30 atime=1787067672.843459552 30 ctime=1787067793.720712495 rsyslog-8.2608.0/doc/source/reference/properties/system-time-wday.rst0000666000175000017500000000131415132733117024362 0ustar00rgerrger.. _prop-system-time-wday: .. _properties.system-time.wday: $wday ===== .. index:: single: properties; $wday single: $wday .. summary-start Returns the current weekday number as defined by ``gmtime()``. .. summary-end This property belongs to the **Time-Related System Properties** group. :Name: $wday :Category: Time-Related System Properties :Type: integer Description ----------- The current week day as defined by ``gmtime()``. 0=Sunday, ..., 6=Saturday. Usage ----- .. _properties.system-time.wday-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="$wday") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/properties/PaxHeaders/message-app-name.rst0000644000000000000000000000013115132733117024612 xustar0030 mtime=1768666703.924620496 30 atime=1787067672.548454052 29 ctime=1787067793.62871078 rsyslog-8.2608.0/doc/source/reference/properties/message-app-name.rst0000666000175000017500000000210615132733117024260 0ustar00rgerrger.. _prop-message-app-name: .. _properties.message.app-name: app-name ======== .. index:: single: properties; app-name single: app-name .. summary-start Carries the APP-NAME header field defined in RFC 5424 Section 6.2.5. .. summary-end This property belongs to the **Message Properties** group. :Name: app-name :Category: Message Properties :Type: string Description ----------- Carries the ``APP-NAME`` header field defined in RFC 5424 Section 6.2.5, which identifies the originator application with up to 48 printable characters. RFC 5424 permits the NILVALUE (``-``) when an application cannot supply a value. When rsyslog receives events without a native syslog header (for example from imfile inputs or JSON payloads), this property reflects a configured default or an inferred placeholder instead of a transmitted header value. Usage ----- .. _properties.message.app-name-usage: .. code-block:: rsyslog template(name="example" type="list") { property(name="app-name") } See also -------- See :doc:`../../configuration/properties` for the category overview. rsyslog-8.2608.0/doc/source/reference/PaxHeaders/tools0000644000000000000000000000013215241076621017631 xustar0030 mtime=1787067793.626710743 30 atime=1787067808.812993723 30 ctime=1787067793.626710743 rsyslog-8.2608.0/doc/source/reference/tools/0000775000175000017500000000000015241076621017352 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/reference/tools/PaxHeaders/rsyslog-segqueue.rst0000644000000000000000000000013115241075234023761 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.67957968 30 ctime=1787067793.626710743 rsyslog-8.2608.0/doc/source/reference/tools/rsyslog-segqueue.rst0000664000175000017500000000745615241075234023442 0ustar00rgerrger.. _rsyslog-segqueue: ================= rsyslog-segqueue ================= .. meta:: :description: Inspect, export, and safely repair experimental segmentedDisk queue stores. :keywords: rsyslog, segmentedDisk, queue, repair, recovery, JSON Lines .. summary-start ``rsyslog-segqueue`` is an offline maintenance utility for version 2 ``segmentedDisk`` stores. It provides fast status, complete integrity checks, lossless JSONL export, conservative state reconstruction, and salvage repair. .. summary-end Use this tool on the dedicated ``/.segq/`` directory. It does not support classic ``.qi`` queues or the rejected experimental version 1 format. Safety model ============ Status, check, and export are read-only. Stop rsyslog before applying any repair: the utility can detect files that change during preparation, but the daemon and utility do not share a lock protocol. Repair runs in plan-only mode unless both ``--apply`` and ``--offline`` are present. A state-slot repair retains a timestamped copy of the old state file. Rebuild and salvage create and validate a sibling store, rename the original to a timestamped backup, and atomically install the replacement. No backup is removed automatically. When state cannot prove which records were committed, rebuild and salvage make every recovered record pending. This can produce duplicates, but avoids silently discarding recoverable log records. Commands ======== ``status QUEUE-DIR [--json]`` Read state slots and segment metadata without scanning record payloads. ``check QUEUE-DIR [--json]`` Validate the state file, topology, segment headers and footers, record framing and checksums, and every persisted TLV message. ``export QUEUE-DIR [--output FILE|-] [--scope live|all] [--salvage]`` Write one JSON object per record. ``live`` is the default scope and begins at the durable commit frontier. ``all`` includes already committed physical data. Corruption is fatal unless ``--salvage`` is selected. ``repair QUEUE-DIR --mode state-slot|rebuild|salvage`` Produce a no-write plan. Add ``--apply --offline`` to apply it. ``state-slot`` restores redundant state, ``rebuild`` requires clean segment data, and ``salvage`` copies every independently verified record into a normalized store. ``tui [QUEUE-DIR]`` Open a guided, dependency-free terminal menu over the same operations. JSONL schema ============ Each line contains a ``queue`` object with the source segment, byte offsets, and local record sequence, plus a ``message`` object containing every persisted message property. ``msg`` and ``rawmsg_after_pri`` are derived from the stored offsets. Embedded message JSON and local variables remain nested JSON values. An unparsed message may carry rsyslog's unsigned ``0xffffffff`` offset sentinel; in that case ``msg`` contains the complete raw message and ``msg_offset_unset`` is true. Text fields are JSON strings when they contain valid UTF-8. Otherwise the field is an object such as ``{"encoding":"base64","data":"..."}``, preserving the original bytes without replacement characters. Exit codes ========== ``0`` Success with no integrity errors. ``1`` Invalid invocation, filesystem failure, or internal processing error. ``2`` Integrity errors were found, or salvage export completed with omissions. Examples ======== .. code-block:: bash rsyslog-segqueue status /var/spool/rsyslog/mainq.segq rsyslog-segqueue check --json /var/spool/rsyslog/mainq.segq rsyslog-segqueue export /var/spool/rsyslog/mainq.segq --output backlog.jsonl rsyslog-segqueue repair /var/spool/rsyslog/mainq.segq --mode salvage rsyslog-segqueue repair /var/spool/rsyslog/mainq.segq \ --mode salvage --apply --offline See also ======== See :doc:`../../concepts/queues` for segmented queue behavior and durability semantics. rsyslog-8.2608.0/doc/source/reference/tools/PaxHeaders/index.rst0000644000000000000000000000013115241075234021545 xustar0030 mtime=1787067036.582577864 29 atime=1787067036.67957968 30 ctime=1787067793.624710705 rsyslog-8.2608.0/doc/source/reference/tools/index.rst0000664000175000017500000000055115241075234021213 0ustar00rgerrger.. _reference-tools: ==================== Command-line tools ==================== .. meta:: :description: Command-line utilities supplied with rsyslog. :keywords: rsyslog, command line, tools, maintenance .. summary-start Operator-facing command-line utilities supplied with rsyslog. .. summary-end .. toctree:: :maxdepth: 1 rsyslog-segqueue rsyslog-8.2608.0/doc/source/PaxHeaders/conf_helpers.py0000644000000000000000000000013215216464435017637 xustar0030 mtime=1782212893.972265311 30 atime=1782715518.807789163 30 ctime=1787067791.067663056 rsyslog-8.2608.0/doc/source/conf_helpers.py0000664000175000017500000001335715216464435017314 0ustar00rgerrger# Helper functions for main conf.py Sphinx build configuration import datetime import re import shutil import subprocess # Resolve git executable to avoid relying on PATH (Bandit B607) # # Note: Building docs from a release/dist tarball should NOT require git. # If git is unavailable or the working directory is not a git repository, # we degrade gracefully and return placeholder values so Sphinx can build. GIT_EXE = shutil.which("git") def _run_git(args): """Run a git command and return decoded stdout, or None on failure. We explicitly handle environments where git is missing or the current directory is not a git repository (e.g., dist tarball builds). """ if GIT_EXE is None: return None try: output_bytes = subprocess.check_output([GIT_EXE] + args) return output_bytes.decode("utf-8").strip() except (subprocess.CalledProcessError, FileNotFoundError): return None def get_current_branch(): """Return the current branch we are on or the branch that the detached head is pointed to""" current_branch = _run_git(['rev-parse', '--abbrev-ref', 'HEAD']) if not current_branch: return 'unknown' if current_branch == 'HEAD': # This means we are operating in a detached head state, will need to # parse out the branch that the commit is from. # Decode "bytes" type to UTF-8 string to avoid Python 3 error: # "TypeError: a bytes-like object is required, not 'str'"" # https://docs.python.org/3/library/stdtypes.html#bytes.decode branches_output = _run_git(['branch']) if not branches_output: return 'unknown' branches = branches_output.split('\n') for branch in branches: # Git marks the current branch, or in this case the branch # we are currently detached from with an asterisk if '*' in branch: # Split on the remote/branch separator, grab the # last entry in the list and then strip off the trailing # parenthesis. detached_from_branch = branch.split('/')[-1].replace(')', '') return detached_from_branch return 'unknown' else: # The assumption is that we are on a branch at this point. Return that. return current_branch def get_current_stable_version(): """Return the current X.Y stable version number from the latest git tag""" def get_latest_tag(): """Helper function: Return the latest git tag""" git_tag_output = _run_git(['tag', '--list', 'v*']) if not git_tag_output: return None git_tag_list = [] for tag in git_tag_output.splitlines(): match = re.fullmatch(r'v(\d+)\.(\d+)\.(\d+)', tag.strip()) if match: git_tag_list.append(tuple(int(part) for part in match.groups())) if not git_tag_list: return None git_tag_list.sort() # The latest tag is the last in the list git_tag_latest = "{}.{}.{}".format(*git_tag_list[-1]) return git_tag_latest latest_tag = get_latest_tag() if not latest_tag: # Fallback for non-git environments (e.g., release tarball builds) return '0.0' # Return 'X.Y' from 'X.Y.Z' return '.'.join(latest_tag.split('.')[:2]) def get_next_stable_version(): """Return the next stable version""" current_version = get_current_stable_version() # Break apart 'x.y' value, increment y and then concatenate into 'x.y' again try: next_version = "{}.{}".format( int(current_version.split('.')[0]), int(current_version.split('.')[1]) + 1 ) except (IndexError, ValueError): # Conservative fallback if parsing fails next_version = '0.1' return next_version def get_current_commit_hash(): """Return commit hash string""" commit_hash = _run_git(['log', '--pretty=format:%h', 'HEAD', '-n1']) return commit_hash if commit_hash else 'nogit' def get_release_string(release_type, release_string_detail, version): """Return a release string representing the type of build. Verbose for dev builds and with sparse version info for release builds""" if release_type == "dev": # Used in dev builds DATE = datetime.date.today() TODAY = DATE.strftime('%Y%m%d') # The detailed release string is too long for the rsyslog.com 'better' # theme and perhaps too long for other themes as well, so we set the # level to 'simple' by default (to be explicit) and # allow overriding by command-line if desired. if release_string_detail == "simple": # 'rsyslog' prefix is already set via 'project' variable in conf.py # HASH # 'docs' string suffix is already ... release_string = "{}".format(get_current_commit_hash()) elif release_string_detail == "detailed": # The verbose variation of the release string. This was previously # the default when using the 'classic' theme, but proves to be # too long when viewed using alternate themes. If requested # via command-line override this format is used. release_string = "{}-{}-{}-{}".format( get_next_stable_version(), get_current_branch(), TODAY, get_current_commit_hash() ) else: # This means that someone set a value that we do not # have a format defined for. Return an error string instead # to help make it clear what happened. release_string = "invalid value for release_string_detail" else: release_string = "{}".format(version) return release_string rsyslog-8.2608.0/doc/source/PaxHeaders/community.rst0000644000000000000000000000013215132411300017350 xustar0030 mtime=1768559296.171884137 30 atime=1787067671.933442587 30 ctime=1787067791.026662292 rsyslog-8.2608.0/doc/source/community.rst0000666000175000017500000000373215132411300017023 0ustar00rgerrgerCommunity Resources =================== The rsyslog project is supported by a vibrant community and official resources that help users learn, troubleshoot, and stay up to date. Primary Resources ----------------- - `AI "rsyslog assistant" experiment `_ An AI-powered assistant designed to help with configuration questions, troubleshooting, and learning rsyslog concepts. - `GitHub Discussions `_ A community forum for questions, ideas, and feedback. - `rsyslog mailing list `_ A long-standing mailing list where the community exchanges knowledge and support. - `Rainer Gerhards' blog `_ Insights and updates from the maintainer of rsyslog. Filter for *syslog* and *rsyslog* tags for relevant content. Self-Help --------- For general support and troubleshooting, start with these resources: - `AI "rsyslog assistant" `_ - `GitHub Discussions `_ - `rsyslog mailing list `_ - `GitHub issue tracker `_ Professional Support -------------------- For guaranteed response times, private consultations, or expert help, consider `Adiscon’s professional services `_. Adiscon is the main sponsor of rsyslog, and using its services helps fund the continued development of the project. Legacy Resources ---------------- The following resources may still be helpful but are no longer actively updated. New users are encouraged to start with the **AI assistant** and **GitHub Discussions** listed above for the most current information. - `rsyslog video tutorials `_ These tutorials are slightly dated but still provide useful background on common rsyslog concepts and configurations. rsyslog-8.2608.0/doc/source/PaxHeaders/direct_queue_rsyslog2.png0000644000000000000000000000013115132411300021621 xustar0029 mtime=1768559296.18788439 30 atime=1782715518.820789384 30 ctime=1787067791.660674106 rsyslog-8.2608.0/doc/source/direct_queue_rsyslog2.png0000666000175000017500000003007615132411300021276 0ustar00rgerrger‰PNG  IHDR¬‘ŒÃåsBITÛáOà pHYsêe¤ IDATxœí�y|MÇÿÿŸ7»ÄNľ´µ+JJQŠ.TQÔR>­òAµ¥Õ�6EjK• ÔRµt±´µ´”úص>%Uj_b�$„”D‰¬w~œþò��äÞÜsï™›Ìó‘‡ÇuîÜ÷¼ÎÌœó:3gΓ; …Bd}°ößÿÐIóU²‹B¾JvQÈ׉d?ú裧OŸæÜNž<Ù¶m[ÝU* Ã1™LÖþ[€ŸÈðsk;£l{ä[¹r凶7ŸgžyÆIwOÉ. ù*Ùþ¹BQ0Lê_¡P(Ùq±w'99‰Ie?¶’Iæw|w�{F ± 3æ}ì3Z…B¡È ;à Nô¦wš4¢‘ Õ±-8)¤,fq=êmg{1Š-§€d’¹ŠU�òh:éFkQ(ya—¡¤œ˜Â”�lˆÇxì$']ìß5)”Ä¿˜Ås™CŒç9_�êF‹²3æïøn SÂkC›0Z‘B¡È 7}Ã�ää¦l`CÖØQAÊ ÀMnÎcÞB&’¨mÉH§s3æu¬›Ìä0´-“™l¬$…B‘/ºõ²,Ð\Á—GxDu,!û=˜+\™Íì¬H%Õ„I L˜¼ñ¾Â•ò”7P¤U˜1o`Ãd&Ÿå¬ .fÌ&L-iù-Má8"û߃[rÛhUbÁÚ£U‚yTœÆpžóñÑ6˜1çøª4¥½ðÊj"Ù›‹ã?. �ÏY<Â#ç9ÿ`I6¢Qg:W¤b*T Â³<+�Ý ABÉÉÂ»ØÆR»'3ù4§5KÈJ2œáõ©�ÑG…ý"8�`{GpDÃSXÏ5®U¡J t0†xâ?ã³9̉'^»ÂÍúêQ­A�ÿË,Û-h§øìàL3È0cÞÊÖ8âr”dŽÿºãþO´¥m/ð‚#îígfrè×®qíׯÿ߇»wIJ"9™ôn) ÔrÜÚL2í.ɘ0eýåøoÞÛ-ßh¿Ä*‚Š`a„ºÔuËó>‚nCIÚƒ .¨p™ËÎ;‘Æ≟Íì9ÌI&YÛâ‚K-jàÀmnGy–³ÿã»ÙK,P�jÃö:¯ç} `5áá9Âñãœ8Áñã\½Jö¦b2áïOõêx{ÿß_ñâx{óÜs—Ÿ¬<ƒ_óuÙCN`Â~Tä±QÏT(œ�g%Å?Ÿù!„įm™Ç¼·y[Ç,Š7¹9�éKX’5¹ó~x™—³§¹Ìå�ìœÆ´(¢L˜úÓÿ3>³é>DRûöñßÿ²};.ü³ÑË‹æÍiܘÆ�ñ÷§Jüü¨PS>§Ñpƒ ^Éʬ]¨D¥+\É]T(’"ì@¼ˆŸ*¦–¥T•’E²=r) \—‹Á.ÂA3Ñì¡i̼[ìî%z!ðÞÓÄ´‘b]6iiâÛoEÏžÂÅE€Ñ°¡ 6ˆ „ÙlË.„‹ð‹» wæ‰y¶DS(À.Æ ¡ÙCQF� lä¤8ÙCô@°]lÏ#Y¨}\<ŽÀWø†ŠP‹BŸ=+ÆŽeË %KŠ—_Ë–‰èh}tg#BDŒ£<„GeQY]((’c÷µ’’Hú–oG0B àÚÈìdgÞϘ1/eé&¤’ºŒe˜kÒsç7ŽmÛZµbøpú÷§xq½UßGQ3™ù��d¤]3R(¶ Ñ+„„Ö�î¹øLejΉ­áá²v-&¯¾ÊĉԪåHyÉ${ãíÈ …U(c(œÄÛ—¾»Ù=€«XõOw-3“™3 "#ƒþý™1ƒ5 ªP(äCç%1’P†2;ÙÙ�~kXS“šÓ˜FX}ûrâíÚBË–FkT(’"ÙÓ³úѵk×Ö­[3f̨Zµêßÿ½oß¾ÚµkoÛ¶-99¹AƒÁÁÁÀ€Ì›7¯mÛ¶IIIû÷ïïÔ©Shhh||üóÏ?¿råJà­·Þ –/_>hРŒŒŒÐÐÐaÆ�={6..nôèÑ¿üò 0mÚ´%K–ëׯŸ#„8yòäùóç…aaaBDFFîÚµ+!!!>>~ëÖ­—/_ÖGbF†4(º¥îºù™«ÄŠX}Â*ŒãÌ™3ÀÌ™3…åË—þùç…½{÷öññBÌŸ?8vìØÉ“'ýüüV®\)„ BLžýôÓ×^{M±sçÎáÇGDDDEE�?þ÷ßBÌœ9ó§Ÿ~BlÞ¼Yûá©S§Ö®]›��`ØnÛõ9…ÁddˆAƒˆÁƒ7f®GðŠxÅhM [ÑÏž=+„X±b…vNY³fÍĉ…Û·oâ£tÒæçºÔý…_¼ðZÄ¢?ù¨Mí&4iHçyº! Ÿà  ÍZÑ (KÙºÔõÄÓ|Üq7c¾Ç=í”EÔE.—¹¼›Ýd\çújVG‘Jê"íg?ð_-g9°•­òaiŽÛù={˜2…¶mYµ —ªØïéL¿ÆµùÌwœ…Bá„¶¡¤“œœËܬXÂ’‘ŒÜÅ®f4 !d ã±xâKQÊ®îqÏ„É ¯;ÜI'½<åos;–ØÚÔvЫunÜ Y3228z”ªU³“IfSš^ãÚ%.Îѳ"I9–W(l¤�ÃMn®fõ8Æ}ÌÇóñÎøâ{‘‹­i튫ÑêKÇŽüö[·Ò­Ûƒ_nfó‹¼øþó Ÿ8^š¢ÜàFa—¸¤ýE•@BII$%“\ŒbfÌ·¸••þÁ·M”§|Qî‚ór‚W¹zžóYn¸Ýå®ýrÏø L°_| qzcˆ#Îß×xí+¾ºÄ¥â/A‰¢»Ïš5 Èøñ|úinIšÓü—®q-ï—¾* äö±Oû»Îõ¬í&Lõ©_œâY¨à‰g"‰}¿¦öW‚KXbàî8a„ýÆoÚ_YÛ«Rµ>õÝq÷ÀÃ~¹÷£ßØ/¾…8·1¬d囼yžóIdÚ­ÈPîÝã‘GÈÈ ,Œ¹žôײv³øßüÛ‘êùr•«_ðÅ*VE ¸àÒšÖmi[—ºu¨S›ÚU©ª‹ìÄ9έbÕjV‡¸âÚ‚OñÔc<Ö”¦ i˜÷»0 N¹«dLfrAu©Û….fÌþøW¥jþ¿,ÜÌ�KD+Väá @ozW¤¢2yˆõ¬_ÈÂßøM Òpƒ:Ðá)žRo»³7é¤É—ËYþ¾øŽg|g:·§½6�½ˆbèSä[ñ-‚…b¡ÑBd":ZøøˆfÍDff¾iE ‚ýB=k0fa^+ÖÖµ”%‡‹áˆ?ŒUT¸#îhoÓ^4ùŽxçOñ§Ñ¢dÁ™Œ!CdLÓ?›…y®˜k6½r²°ñþûÄîÝ–¤�Ñ®Âu¨joQŠ<Ø/ö7͵7î­+2D†ÑŠŠ "#D„Å<"Ù$6­H:rÞc8uêÔêÕ«Mù½ç=‹Ò¥K¿ÿþûVõQ‚ƒƒïÞµâ¶þàÁƒyäà&7Ѩ m6±)�ô{÷îݽ{wÞ1³ï`ݺu_}õUËõ$''kKh刓cÇŽõõµbzèºuëN�:eyú¶-Z<óÚkT«Æ‘#–¤¿zõj{ÚÇTˆyoö{.™yM¢ÕvÐÍÍM[\Ör–,YróæÍqò {÷îÍš5³<þ‘#G´m-¤råÊÆ ³<=0}útañ8“É4tèP???K§‘ö>ïÏg¾{ºû“¡O¶ mç‘æ‘'·_5lذG�ênß¾½téRËÓãÆ�óô´büdíÚµÚ*~Ò¡CmÍc 9þü�?þøÐ¯ZP>>>#GæórÀøÿ:Ïù¦4�ÈÄèEÑÉIV¬cúÒK/Õ©SÇòôüý÷ß-O_³fÍÞ½{[ž>%%eáÂ…y$x° ^{íµÒ¥Kç7‡Q¬_¿ÞrM@µjÕ¬õ¢Š+Z•ÅæÍ›cEì›âÍL‘yE\É·£0eÊ«âkëaYέ[·òz?—.]²*‹~ýúYM·nIJeÆÿí·ßxt¶(¾———Uú…�5²j–/_nU|myZËiÞ¼¹µ»àêjÝDçƒZö’¸ÔR´DPáj*[ðàÁVé?wîœUú�øøx«²èÔ©“Uñƒƒƒ­Š¿aëâûûûç-Y$�ã\„‹�ðY)VjµuO-G[~Êr¦N�jUü®]»ZÿöíÛVÅ.^¼˜oØœ=†””mý^ qqq©P¡‚U²nÞ¼™÷âÀ9$•)Sf¦×Ì�ùøþhIþ/HLLLLL|h¨‡âååU¶lÙ|“ea6›¯_¿žºlTªTÉÍÍŠûü·oß¶d5ö¬½óëÝÛõÒ%¢¢ð¶hžnjjêÑÛGª ¼;pzìtò+(“ÉT­Z5K"gqýúõ´4+ö.W®\‰<ï™ç 11Ñr‡BxzzZx9ŸÅåË—*·ô~~~^^ùÜ+ÞÉÎôÈ$s:Ó‡Þ'Þr=>>>V]T¥¥¥Yu9Ô®]ÛÅÅŠÇ0£¢¢rk¨-¨òåË—)SÆòø‰‰‰V­>íææ–Ûåüu®w¡ËiNw¡Ë—|Y�Úó… 222,Ï¢jÕª>>>–§¿uëVLLL rT‰%ªW¯nyüÌÌLí À’s�F½zõ´—ä�ìÓUà /A‰2”ÙÅ®.t1ZŽ”?NÓ¦ŒËœ9Vý®­¢ˆŠ"ÊA�dy¶°¥}ÊRv;ÛÒÐh9Eˆœxžç¯sý3>{õJ’ü‘úŒ íi_›Ú™d*WÈ•U«F�²öwÝéMôiNë/Iñ[ÙÚ‡>¨ð¿)Wp$¿òk[ÚÞáÎf6+W°yŸcÈ$Ó×Íl>ÃwÜ�–#1[¶P¿>ÖÜÓhMkà‡aÝý…µüʯ=éY™Ê{Ù[›ÚFË)B„ú,Ï–¢ÔÏüÜ‚FËqäí1ô¢×$&5¡É+¼b´‰¹x‘sçxþùü´%-M˜qHwQŠìDÙ›Þå(÷'*Wp$—¸ÔƒžxîcŸr«�´Ç�HbQEwÉ#ËÙ²à… ðÓÒ”®O}e v%�ôþô¿Ã�]쪈uóñ¶p›ÛÏó|<ñÛÙ^ŸúFËq2dì1\áŠ;îG8ò5_­Ez¶l¡tiÚ¶-د[Ñê§’±b·Â* <À� ‚:ÐÁh-E‹þô?Ïùå,ױ䓓 Áš§°œéŒA zÓ»2•3Ȱë*†…�´4öï§KÜ x¦­2ÈÐV‰QèÎŽÌfvg:ȇFk)Z|Í×»Øõ&ob�Ža½½‰Œ¤zu¦O'!AÇÀÒ!�1˜0…2•©Ej-Ãräii<ùd�ho¬S£Iö@ Æ0Æ ¯å,W‚I4Ñc[‹ZÁëü?ÿ!9™�>*äö W{�#.˜àö´W³Ê,âða€¿«Ö„&žx*c°?ðÃAŽc\Ö³T Ç0ŠQw¸³ŒeÅ)®{ðÊ•1àÎ�ìaÚ´Bhr=à6žñ³™}˜Ã�ó¸ÑZœ�!CX³†øx x~(­iCÌeò”¯¢À¤�ò(�¦�ržó>Xñ ¬ÂFpàIžư/ùÒNYDGS³&©©&BPº4ï¾Ë[oQ²¤�òt4ù÷ßò×ÿ‚~hZ7š]ÓÃZ}óèÁ×seoØh €àÍ Ì.n�/·%ìá!o�ï²à¥ßôJ¨�wJ«6ÚÁ©++²ë²“o½ÑpÁþۆˣJZ:ª:ûY×Äf¿6}ù‚ÇMû©ŠŒ$û:…ÏòÇß¶�µk ¦}Äú>Ì}�Cr3�‡. ™Ûªš¹%.ÁÝ•aߺ ɪËÃfߘéÙ’.l¹vÔuWWÛU¸ÑpÙ7Þž¹Èåvù˜YCþN“HU¡�Òì`|«¾ß�¼wÞÿž=U=t±7³™ŒŒ‡åtäßcHN&=ýþߨ¡FM ~Þ¾ý2.KûÆÞyÞ|õáàAøüsF�¶%Ìÿø_;Ú-e鼡—´"ÎA0� ö¸ù©Èƒgyv/{/pÁûåró&5j�šŠÿôJ–dìXÞy‡|W³vòï1Ø0|mÅ)™DÒ-·[Þj.’…hkZ¿Füð®aÅ–мYÄ"W\G0Âh!E‹«\ÝÁŽ! ±«+³f‘’òÏç%;–±c �%hH1+)•ÔÁ ¾ÎuõÞf+¨YÓÆ0U¨b¤ŒA/’I^Ǻçx®5ŒÖR´XÅ*3æ¡ µk.7o²h€�“&qõ*\Ø\I–Ä8À�U¬êD§ZÔ2Z‹ópå ..X³tûCñij<壈ÒE”b+[SIí‡u¯ZRØÎ7|S“šíhg×\fÍÂÃñãyç¬y+£“!…1t¤c<ñj Uë¸r…Ê•±æEŒ¹á‡Ÿê1èŶ¸âÚ�nF )Z„zžó™hÂ~·õ¸w�²e¹z•R¥ì—‰?”EÔ4¦%’XŒbFkq*ÂÃmGÒPÆ fÌÛØÖ†6e±â�€ ÛÙÈF` íšK±b|ðAáwd0†ÿò߉L<Å)£…8™™DDP£†.Áüð‹%ö÷òOªÈ“?øãoþ~�‚,v«°…=ì©A µŠª^o ¯óúŸü©Öž´Ž„22°òmÛ¹¡ÝóW�ÛÙË^@�#9˜Xb�r´�ŒRx0ØÒI&¸µ<Ña¬¼‘”ºM%V3VõâG¼ñVoît0{ÙkÆü4O-¤ð`°1ìdg �ëYo¬ ç#9t651Évþâ¯&4qÅÕh!E‹=ì1aRÆ #ÏJz†g~áµdžÕhÆP\ŸÅ#U�Ans;œpuƒÁñáHmjW¢’ÑB ÷r°#+ ÏXyBס$m MqºD+²áМæF )Z˜1Ÿæ´¾Ó#�A zÒ³½ Ôà¬èÚcð H!%ß”Š<8ÉI )M�R´'ü.wÑÈh!… #‡’2É !Ä—Âûø ýеǠŒA"ˆj¢ÏÃ% Ñfº«ƒ¾i I$ý‹(À‰Ñõæ³'ž&L©¤ê­ÈADIJ–¦Ð­›#7ZGMƒ¾i ³˜Lð5®9Ý]#³ÙœiOúöí[¬XžÏ�ë:”dÂ䉧å=†›7o†„„è’µóòÔSO½ðÂ}÷™#‰´÷ºžŠ‰$¨MmäµcÇŽyóæÕ©SÇÃÃC< à¡Û-ùÖÞ?Ï‘à½÷ÞëÕ+×a|7mogÍš¥o &$$+VìçŸöñÉõ½†MiÚƒ©¨oÖy „hÞ¼yZZZ¹råò8/gddäý­½u>óÌ3ùƒ®CI€UưsçNÝŒÓqæÌ™ÆAD þþmINN~ç�w|}}[´ha�ÓŠ#^®\¹%K–<þøã?ýôS¾;Gœ7ÞŽyê÷ßß¶m›íqLÙÈñß±1Anߦ¦æ5Bàܹsçܹs¶ïmvnݺ•‡1ô¡Oúè›o¾;v¬D‰©©©®÷ãááájÜÜܬJ¿xñâŸ~úiÔ¨Q÷éÎÈÀ-[÷îÁ¡$³—‚O%ðÂËrc¸{÷.°}ûöæÍ‹è œ—^zéäɓٷ¤�r‹[Õ¨f”¤´´´/¿´×[ŽL½zõÒÒÒ,¼‹%¶ eòM¶dÉ’°°°¹sçÚ¬ŽãÇ�W­ZÕ–·íì�зoß¾}ûêwÚ´i'Ny¾®#˜Îô¼C]¹r¥X±b•*é0ܤUIŸ>}V®\i{4;ñÒK/ !rÃúõüõï¾KÅŠpÿPRJ _|ÁåË|öY�3µÊ\\\€’%K–+W®À9:59¶Ä+å°¢@ž|òI—ýû÷ë"IkÛ/¾øâˆ#l¿œ4öç®®®µk[:4K¬%XvìØ±wï^]ŒÁ××·L™ü­È©±×=­Öó6†Rþæï|C5kÖ¬S§N6lÐKXÞª çá {÷&0�Ï?gäHÆ�ÿg(ÉÕ•Ï?gÆ nÜàøq[2õÂËò›Ï–TnáæÁ:J$(A ˃$%%¹ØÐÉ{PP£F�gŸ}V¯˜NAqvÔ +ö½ùœ÷¹ã íšûCqVcpwç£�xí5æÌáóÏ©W Q#nÝèÕ‹FŸÇ½téÒ{÷î½ýöÛygjU�AÃut—»Xi úRd+%–XõìˆîØë·|›é®¼ÍÛñ—�䆳0x0µj¤¥qêÀíÛÚ˜81·h_}õÕ’%KòÍTƒU(c�„ 2H°äƒÂ* 3†k\›Ïü£µ“€Üpbcps#(è¾-B`2Ñ£Mm½bòÄ3‰$ËRôÎAÙQÆ qÄ „zHVw 3†6´‰#ÎÞo\z'6`ÀêÖÍ9û(÷î‚å4§¹å‹ ÍsPv¬#ÍV‹£Ï“% hVжÀ—ê1èŽaÆp“›ûØO¼�ä†sƒ«+AA˜ÍYIyî9·umZ3æ�ìÜÍîh¢-THÑ;eçÁ:Ò–ÚÎ$Ó EE´Rb‰Eƒ0Ìrð%^:Ìa; È ç6 _?ê×ÿ§Ó “&ÙžãOütšÓ÷¸L°… )zç ìø¬gýqr]•¯hžƒ²cI�!…”¼;^ºK¢èUŠºÇ`':”ô Ÿxãý#?v¥kg:¿È‹Ã>“™é¤ûá÷/äLga’<–(Ô¤²¥Çp˜Ã7¸±™Í¡„>Ã3šÇ”¡Ì f\åêd&Ïc^ )zç ì˜L&á*ö²W›Í¸ãîŽ{–1¬eí£õµ�Ž™ÃRè1æ9†Où´%L˜L˜êQÏ‘×Vò<›®še V‘½Ž±È÷ì6à†Û†«ªã�ÿ‡|DDP2É¡„Þàà°9,…cŒ¡2•?æc�к ޼¶’ÿà±ÐL˜lœ®š-”æ7ù¢Œ!{Õ§þû¼ŸÕcІF+RÑXU…›wy·6µ³/墕¿Ãæ°z {òy cã±bsðµ•ü�…CI:ºªÇ`%9êèC>¬IMí<%ùÞvvŒªBŒ'ž X�})ò›Ã¢° ÃŒÁ÷,x…W¼Àªü�…=}¯Œ”1XEŽ:*F±…,ÔÎSÕ©Þ™Î2¨*Ü<˳/òbÖ`C¾sXVa˜1OóôlfÛI@nÈðXh ªÇ` Öѳ<Û›ÞÀ¼áb·ÃÊZU…›¹ÌõÀCóÏa)ôi ñê%ù ‡’T�Á@ZGó˜ç‹ï¿ø—!’p†¶­/5©ù!jw<‡¥Ðc°18ù5”$?­£ªTÝÁǯ$Ÿ…üm[wÞçýÔ<‡¥Ð£ŒA:ÔP’üäVGŽUmväoÛºã…×|æ{ãmÈüàBŒ2é0d(I‹¦ŒÁBälErª²7Ýé¾�…Ž”.Ü(c�5”$?r¶"9U9€¡ 5ZBaCƒt(c�9[‘œªΈ2éP÷äGÎ�¿mÈÕ«WOŸ>m´ §Aƒt¨éªò£K ÌŸ?Á‚:)ghÛ2vìØ¶mÛ­ÂipcèÝ»÷Ô©yg}Á�ÿàQCIò£K ¬X±båÊ•:)ghÛ gÁ€e·­e÷îݶÉBþƒGß¡¤[·n™Íæ *ä�LƒUÈYò·m…³àÆ /ò<%yâiI´=zÄÅÅ�=›Ï[é•1X…œ% ÛV8 N0”¤/òùäÛãhÈðä«Ð—Çx¬ÕôÍ7†˜ T°$¥29K@þ¶­pœÀôEþƒ'_…‰$žáÌüaI´>ø`̘1ù&K#-ޏŠT´P!RV®Ã�³äoÛ gA½�A:òUØ„&&LÇ8fI´_ý5...ßd§9-öB¤­\‡!g Èß¶΂ê1HG¾ KQªµö±OÇL×±èAKK[¹CÎ�¿m+œe Òa‰Â>ô #ìW~Õ+Óø¡>õ›ÐÄ’ÄÒV®Ã�³äoÛ gAƒtX¢p c<ð!D—á—K\²|ò«´•ë0ä,ùÛ¶ÂYPÆ –(ôÃï^Ù–?±u"oI£]Žroò¦å ‘²r†œ% ÛV8 ʤÃB…AyãÝ›Þó·-ÙMbR8á!„”§¼å ‘²r†œ% ÛV8 ʤÃB…5¨±ŠUQDõ¥¯…KY<ÈbÏc^g:f°U ‘²r†œ% ÛV8 ʤÃr…=é9� ûØ÷ÏÝæ¶µ…2šÑ�i¼†5Ù_ð`‰B¤¬\‡!g Èß¶΂2é°JáT¦¾Ïû;ÙÙœæ>ÙÄ;��ïñ^+Zía�åƒHY ‘²r†V²!ÛV8 ʤÃ*…®¸ÎdæüG\ Zô§ÿaç‘ÞŒy)K«S} kF1êW~õÅ· ‘²r†œ% ÛV8 êÉgé(€Â>ôiD£ILZǺïù¾ ]šÒ´ÍZÐ"Å?%¥rÊ.v�áÌV¶îeo:é i8�y�èd‹NɋѮÈÙ¼åoÛ g¡(ƒÑò¡`‡w}êÏ÷‘D~ʧßñÝvüóÅ÷Ïð à�wOzö¤gÖÛ~ ¬)+×aÈYÊzQ�ABUÙ±E¡?þ X°€‘DåèQŽ®X²"õvê'�ŸøâÛ�Ô-må: 9K@þ¶m C‡íÔɦ.r‘Â^ÆP¶lÙQ£F5mÚÔöP+Vôõµz<7Þxã�çŸ^¯hö@—ÃÛü{Ðcû7Ûãââ†ÕCÚ?”,YrÁ‚�?þ¸Ž1�‹Æ��5ª\¹r¶Ùµk—¾ý×1cÆ$&&ê°0Ñ£‡Eë€)4Ô%†tìÛ·ïÒ¥K¯¿þº.ÑâââΞ=«K4…Â1ü÷¿ÿ-]ºtëÖ­�r“'Ož2eJDD„¿¿¿ÑZ싽z ŠÓ¡C‡:èíÕW_½wïž^Ñ ÇЭ[7£%iT�A¡P(,"&&&&&¦~ýúîîîFk±/Ê …BqözÀM¡P(NŠ2…B¡P܇2…B¡P܇2…B¡P܇1Æ0mÚ´òå˧¥¥å–`Μ9Ú‡—_~¹`Y„„„øøøì· …BQ”1Æ~üñÇlÞ¼9·YưnݺÄ���Ý¿©R¥ ¨Obìê©{öìiÓ¦Mûöí›7oþóÏ?\e‘Ä®Usâĉ€€€§žzªeË–»ví*¸J…„ÃÙ¿ÿo¼qáÂ…^xAÖ¾}û€€€:DGG !,XàááѾ}û &øùù !Nž<Ù¦M›6mÚœ>}Z‹S¥J•Ñ£G?öØcsçÎ͑Ÿqã<¨ý¶�Ѽyó·Þzkݺu¹%°e¯SSSµÑÑÑ5jÔ(pœ¢‰]«ææÍ›‰‰‰BˆˆˆˆÚµk8N!`êÔ©åÊ•Ëj«¢}èÓ§OâÏ�;·nݺ>>>ÔW(0À^ýõÐÐP!DçÎ�£££;tè°sçNí«ÌÌLíCÖ!¤}hÛ¶í¯¿þ*„øý÷ßÛµk§}UºtéË—/ÇÇÇשS'{üK—.õïß_Øvʉyòd ))©}ûö�<òÈÞ½{Ÿ~úiÀl6k哃ڵkÿïÿkÛ¶í�jÕª¥mÌmµçÔÔTOOO téÒñññöÚ“B‡ªF1|øðêÕ«¿÷Þ{vÛÙINNÞ¶m[TT³jÕªsçÎe½eá¡… \¼xñ©§ž._¾¬môöö®Y³&�žžîéN‡ÑΤ°”N�::t(ë¿]ºtY½zu»ví:vì¨õ£…£F�êÒ¥Kpp°vÉsìØ±'žxBëJŸ|contains|startswith|endswith|re_match|re_extract)\s*"[^"]*"\s+', bygroups(Name.Tag, Operator.Word, String.Double), 'legacy_action'), # RainerScript Keywords (r'\b(%s)\b' % '|'.join(keywords), Keyword.Reserved), (r'\b(%s)\b' % '|'.join(objects), Keyword.Declaration), (r'\b(on|off|yes|no|true|false)\b', Keyword.Constant), # Operators (r'(&&|\|\||and|or|not)\b', Operator.Word), (r'(=|==|!=|<>|<=|>=|<|>|:=|contains_i|startswith_i|contains|startswith|endswith)', Operator), # Variables and Properties (r'\$[a-zA-Z0-9_.-]+', Name.Variable), (r'\$\![\w\.-]+', Name.Variable.Instance), (r'\$\.[\w\.-]+', Name.Variable.Global), # Built-in functions (r'\b(%s)\b' % '|'.join(builtins), Name.Builtin), # Strings (r'"', String.Double, 'double_string'), (r"'", String.Single, 'single_string'), (r'`', String.Backtick, 'backtick_string'), # Numbers (r'\b(0x[0-9a-fA-F]+)\b', Number.Hex), (r'\b\d+\b', Number.Integer), # Punctuation (r'[{}(),;\\\[\].&]', Punctuation), # Identifiers (r'[a-zA-Z_][a-zA-Z0-9_-]*', Name), # <<<--- THIS IS THE CHANGE: Added '-' to allowed identifier characters # Legacy Directives (r'^\$\w+', Keyword.Pseudo), ], 'comment': [ (r'[^*/]+', Comment.Multiline), (r'/\*', Comment.Multiline, '#push'), (r'\*/', Comment.Multiline, '#pop'), (r'[*/]', Comment.Multiline), ], 'double_string': [ (r'\\"', String.Escape), (r'[^"]+', String.Double), (r'"', String.Double, '#pop'), ], 'single_string': [ (r"\\'", String.Escape), (r"[^']+", String.Single), (r"'", String.Single, '#pop'), ], 'backtick_string': [ (r"\\`", String.Escape), (r"[^`]+", String.Backtick), (r"`", String.Backtick, '#pop'), ], 'legacy_action': [ (r'~', Operator, '#pop'), (r'-?/[^;\s]+', Name.Constant, '#pop'), (r'\S+', Name.Constant), (r'.*?\n', Text, '#pop'), ], } # --- Sphinx Extension setup function --- def setup(app): app.add_lexer('rainerscript', RainerScriptLexer) app.add_lexer('rsyslog', RainerScriptLexer) return { 'version': '0.1', 'parallel_read_safe': True, 'parallel_write_safe': True, } rsyslog-8.2608.0/doc/source/PaxHeaders/whitepapers0000644000000000000000000000013215241076621017066 xustar0030 mtime=1787067793.887715607 30 atime=1787067808.812993723 30 ctime=1787067793.887715607 rsyslog-8.2608.0/doc/source/whitepapers/0000775000175000017500000000000015241076621016607 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/syslog_protocol.rst0000644000000000000000000000013115132733117023134 xustar0030 mtime=1768666703.927620541 29 atime=1787067672.83745944 30 ctime=1787067793.887715607 rsyslog-8.2608.0/doc/source/whitepapers/syslog_protocol.rst0000666000175000017500000003132415132733117022606 0ustar00rgerrgersyslog-protocol support in rsyslog ================================== `rsyslog `_ **provides a trial implementation of the proposed** `syslog-protocol `_ **standard.** The intention of this implementation is to find out what inside syslog-protocol is causing problems during implementation. As syslog-protocol is a standard under development, its support in rsyslog is highly volatile. It may change from release to release. So while it provides some advantages in the real world, users are cautioned against using it right now. If you do, be prepared that you will probably need to update all of your rsyslogds with each new release. If you try it anyhow, please provide feedback as that would be most beneficial for us. Currently supported message format ---------------------------------- Due to recent discussion on syslog-protocol, we do not follow any specific revision of the draft but rather the candidate ideas. The format supported currently is: **``VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG``** Field syntax and semantics are as defined in IETF I-D syslog-protocol-15. Capabilities Implemented ------------------------ - receiving message in the supported format (see above) - sending messages in the supported format - relaying messages - receiving messages in either legacy or -protocol format and transforming them into the other one - virtual availability of TAG, PROCID, APP-NAME, MSGID, SD-ID no matter if the message was received via legacy format, API or syslog-protocol format (non-present fields are being emulated with great success) - maximum message size is set via preprocessor #define - syslog-protocol messages can be transmitted both over UDP and plain TCP with some restrictions on compliance in the case of TCP Findings -------- This lists what has been found during implementation: - The same receiver must be able to support both legacy and syslog-protocol syslog messages. Anything else would be a big inconvenience to users and would make deployment much harder. The detection must be done automatically (see below on how easy that is). - **NUL characters inside MSG** cause the message to be truncated at that point. This is probably a major point for many C-based implementations. No measures have yet been taken against this. Modifying the code to "cleanly" support NUL characters is non-trivial, even though rsyslogd already has some byte-counted string library (but this is new and not yet available everywhere). - **character encoding in MSG**: it is problematic to do the right UTF-8 encoding. The reason is that we pick up the MSG from the local domain socket (which got it from the syslog(3) API). The text obtained does not include any encoding information, but it does include non US-ASCII characters. It may also include any other encoding. Other than by guessing based on the provided text, I have no way to find out what it is. In order to make the syslogd do anything useful, I have now simply taken the message as is and stuffed it into the MSG part. Please note that I think this will be a route that other implementers would take, too. - A minimal parser is easy to implement. It took me roughly 2 hours to add it to rsyslogd. This includes the time for restructuring the code to be able to parse both legacy syslog as well as syslog-protocol. The parser has some restrictions, though - STRUCTURED-DATA field is extracted, but not validated. Structured data "[test ]]" is not caught as an error. Nor are any other errors caught. For my needs with this syslogd, that level of structured data processing is probably sufficient. I do not want to parse/validate it in all cases. This is also a performance issue. I think other implementers could have the same view. As such, we should not make validation a requirement. - MSG is not further processed (e.g. Unicode not being validated) - the other header fields are also extracted, but no validation is performed right now. At least some validation should be easy to add (not done this because it is a proof-of-concept and scheduled to change). - Universal access to all syslog fields (missing ones being emulated) was also quite easy. It took me around another 2 hours to integrate emulation of non-present fields into the code base. - The version at the start of the message makes it easy to detect if we have legacy syslog or syslog-protocol. Do NOT move it to somewhere inside the middle of the message, that would complicate things. It might not be totally fail-safe to just rely on "1 " as the "cookie" for a syslog-protocol. Eventually, it would be good to add some more uniqueness, e.g. "@#1 ". - I have no (easy) way to detect truncation if that happens on the UDP stack. All I see is that I receive e.g. a 4K message. If the message was e.g. 6K, I received two chunks. The first chunk (4K) is correctly detected as a syslog-protocol message, the second (2K) as legacy syslog. I do not see what we could do against this. This questions the usefulness of the TRUNCATE bit. Eventually, I could look at the UDP headers and see that it is a fragment. I have looked at a network sniffer log of the conversation. This looks like two totally-independent messages were sent by the sender stack. - The maximum message size is currently being configured via a preprocessor #define. It can easily be set to 2K or 4K, but more than 4K is not possible because of UDP stack limitations. Eventually, this can be worked around, but I have not done this yet. - rsyslogd can accept syslog-protocol formatted messages but is able to relay them in legacy format. I find this a must in real-life deployments. For this, I needed to do some field mapping so that APP-NAME/PROCID are mapped into a TAG. - rsyslogd can also accept legacy syslog message and relay them in syslog-protocol format. For this, I needed to apply some sub-parsing of the TAG, which on most occasions provides correct results. There might be some misinterpretations but I consider these to be mostly non-intrusive. - Messages received from the syslog API (the normal case under \*nix) also do not have APP-NAME and PROCID and I must parse them out of TAG as described directly above. As such, this algorithm is absolutely vital to make things work on \*nix. - I have an issue with messages received via the syslog(3) API (or, to be more precise, via the local domain socket this API writes to): These messages contain a timestamp, but that timestamp does neither have the year nor the high-resolution time. The year is no real issue, I just take the year of the reception of that message. There is a very small window of exposure for messages read from the log immediately after midnight Jan 1st. The message in the domain socket might have been written immediately before midnight in the old year. I think this is acceptable. However, I can not assign a high-precision timestamp, at least it is somewhat off if I take the timestamp from message reception on the local socket. An alternative might be to ignore the timestamp present and instead use that one when the message is pulled from the local socket (I am talking about IPC, not the network - just a reminder...). This is doable, but eventually not advisable. It looks like this needs to be resolved via a configuration option. - rsyslogd already advertised its origin information on application startup (in a syslog-protocol-14 compatible format). It is fairly easy to include that with any message if desired (not currently done). - A big problem I noticed are malformed messages. In -syslog-protocol, we recommend/require to discard malformed messages. However, in practice users would like to see everything that the syslogd receives, even if it is in error. For the first version, I have not included any error handling at all. However, I think I would deliberately ignore any "discard" requirement. My current point of view is that in my code I would eventually flag a message as being invalid and allow the user to filter on this invalidness. So these invalid messages could be redirected into special bins. - The error logging recommendations (those I insisted on;)) are not really practical. My application has its own error logging philosophy and I will not change this to follow a draft. - Relevance of support for leap seconds and senders without knowledge of time is questionable. I have not made any specific provisions in the code nor would I know how to handle that differently. I could, however, pull the local reception timestamp in this case, so it might be useful to have this feature. I do not think any more about this for the initial proof-of-concept. Note it as a potential problem area, especially when logging to databases. - The HOSTNAME field for internally generated messages currently contains the hostname part only, not the FQDN. This can be changed inside the code base, but it requires some thinking so that thinks are kept compatible with legacy syslog. I have not done this for the proof-of-concept, but I think it is not really bad. Maybe an hour or half a day of thinking. - It is possible that I did not receive a TAG with legacy syslog or via the syslog API. In this case, I can not generate the APP-NAME. For consistency, I have used "-" in such cases (just like in PROCID, MSGID and STRUCTURED-DATA). - As an architectural side-effect, syslog-protocol formatted messages can also be transmitted over non-standard syslog/raw tcp. This implementation uses the industry-standard LF termination of tcp syslog records. As such, syslog-protocol messages containing an LF will be broken invalidly. There is nothing that can be done against this without specifying a TCP transport. This issue might be more important than one thinks on first thought. The reason is the wide deployment of syslog/tcp via industry standard. **Some notes on syslog-transport-udp-06** - I did not make any low-level modifications to the UDP code and think I am still basically covered with this I-D. - I deliberately violate section 3.3 insofar as that I do not necessarily accept messages destined to port 514. This feature is user-required and a must. The same applies to the destination port. I am not sure if the "MUST" in section 3.3 was meant that this MUST be an option, but not necessarily be active. The wording should be clarified. - section 3.6: I do not check checksums. See the issue with discarding messages above. The same solution will probably be applied in my code.   Conclusions/Suggestions ----------------------- These are my personal conclusions and suggestions. Obviously, they must be discussed ;) - NUL should be disallowed in MSG - As it is not possible to definitely know the character encoding of the application-provided message, MSG should **not** be specified to use UTF-8 exclusively. Instead, it is suggested that any encoding may be used but UTF-8 is preferred. To detect UTF-8, the MSG should start with the UTF-8 byte order mask of "EF BB BF" if it is UTF-8 encoded (see section 155.9 of `https://www.unicode.org/versions/Unicode4.0.0/ch15.pdf `_) - Requirements to drop messages should be reconsidered. I guess I would not be the only implementer ignoring them. - Logging requirements should be reconsidered and probably be removed. - It would be advisable to specify "-" for APP-NAME is the name is not known to the sender. - The implications of the current syslog/tcp industry standard on syslog-protocol should be further evaluated and be fully understood .. _concept-model-whitepapers-syslog_protocol: Conceptual model ---------------- - syslog-protocol introduces a structured header (PRI, VERSION, TIMESTAMP, HOSTNAME, APP-NAME, PROCID, MSGID, SD, MSG) to standardize message framing. - rsyslog auto-detects legacy vs. protocol messages, mapping missing fields (e.g., TAG to APP-NAME/PROCID) to maintain compatibility during transition. - Parsing focuses on minimal validation for performance; structured data may be accepted without strict checks to avoid drop-induced data loss. - Message transport (UDP/TCP) imposes limits: UDP fragmentation and LF-delimited TCP can truncate or split protocol frames. - Encoding and NUL handling are implementation challenges; messages are often forwarded as-is because source encoding is unknown. - Rules for discarding malformed messages are relaxed in practice; marking and routing invalid messages preserves observability.   rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue_rsyslog.png0000644000000000000000000000013215132411300024073 xustar0030 mtime=1768559296.227885023 30 atime=1787067730.724538459 30 ctime=1787067793.869715271 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue_rsyslog.png0000666000175000017500000002434115132411300023545 0ustar00rgerrger‰PNG  IHDR¬‘ŒÃåsBITÛáOà pHYsêe¤ IDATxœí�ytÅÚ‡Ÿ„l„û ‘EÙ¾Hà‚ ¢‚"•íƒ^P<^‘EE#² "²) *"—‚¢—v D ’��uêû£½¹aI2Cfº«gê99œ¡§ç­_×[Ý¿®îêj7!@ +„(ø`ë¿wýC“–«d»B¹J¶+”k"Ù�5:zô(·áݾ}{»«T(†ãææfë¿wñ~nëÊf”íˆrkÖ¬yÇ–ãáïïÿè£�štó”lW(WɾëŸ+w‡›:ÁWè‰ËW|Õ�~¾ø­E¡PÜw£(\ –µ¬mLãïøN¹‚B!3F P8?,ëX7�i'8áŽû6­H¡P‡2…±`ù†o¦2õ8ǵ%ÏðL#«J¡P�ºÇ p±� S™z”£î¸[°n¸EݘÆF«“�ˆ‚·üÝqyéWV\3BOz†VLkT=…�ˆoùvÓsØw@s µÞäMŒÞ+䌠wž&Ä 7íß[þ¬_¨-oHÃâ RÆ °Ž¼<Ž#&† HM%#ƒë×ÉÈ lY>ú¨ðŠ—¹¼‰MG9J!KÐH&y{JÙ¦ïb¡;Pz æ�`:ÁNÁ^{s‰¨KIŠ"¸~�ˆ¶oçÔ)NŸæüù;¯Ö°!'Nܾ8–Øwyw«òÈÓ–¸áæƒÏ9ÎU£šãT+ŠÒ£ŒAQ!øê+"#Ù³‡Ã‡ÑÚF­Z4lHp0 L�:T¨@¹røùáï_|¼3œy�÷>ã³{x…Wf1ËÑÛ¡P(Jƒ2'NðÙg¬ZõwÏ 8˜Î�ÿþ«U«”±Ïqî=Þ[ÉÊ\rµNCuªÛA³B¡p Ê\!ظ‘U«øö[€à`FŽdà@í^Tqïóþr–‡6‡9v�¯P(ì…2æûï™2…¨(4ˆ!ChÕÊÑe&�0�y“˜@€£ËR(w‡2—ä×_4ˆØXÊ—güxÆ�§B£5) YPÆàbdg3u*³fáãÃK/1q"•+­I¡PÈ…zŽÁ•8x�!CˆŽ¦kW–/§n]£) Q³«º ‹Ѫ±±ÌŸÏÎ�Ê EQ8­1„††¶iÓxï½÷/_¾¼gÏž   mÛ¶eff6nÜ8<<xî¹ç |øá‡íÛ·ÏÈÈØ»wo·nÝ"##SSS{÷î½bÅ `ܸq“&M–-[öüóÏçååEFF>üøñã)))aaaßÿ=0}úôÅ‹ëׯŸ:u*pðàÁéÓ§'&&¦¤¤Ìš5ë·ß~Ó‚|÷ÝwÀ®]»>ÿüsàäÉ“kÖ¬¹zõjjjêúõëcbbìY ¯¾JXÍšqö,cÇâ¦Þâ¢P@nn®"///999338wîÜùóç�˜˜˜¨¨(mIDD„ö­Q8­14oÞ¼E‹@�57nìåååããS§N___!„¿¿¿——`±Xrss�ŒŒŒË—/ׯ_�‰‰ÉÌÌÌÍÍ�ŠŠJLL"##ýõWàÀ�_ý5púôéeË–%%%¥¥¥-Z´H;â/]ºtݺuÀæÍ›ß{ï=à�?þ˜ËìÙôêÅÞ½TSO››ŒŒŒï¾ûîìÙ³ÀÁƒãââ€+W®\»v °X,%ü^a ‡š2eʹsç’““_~ùåmÛ¶&LÐN+ç̙ӯ_?`Ó¦M:t8vìXlll³fÍ´³ÉæÍ›:4h�öÍ9sæxyy9räСCU«VÕVkܸñ+¯¼Œ;ö±ÇÖ®]z¾¨¹ôA(î–üü|‹Åb±X222²³³…©©©×®]B¤¤¤$$$!ÒÒÒbbbnܸ‘��}ôèÑK—. !¢££O�:%„8yòä¾}û„ ;wîLKKKMMݺuë™3gì#1'G´o/@ .rsíSa(ÇŽf̘!„¨ZµjïÞ½…ýû÷÷÷÷BÌŸ?8tèPtttíÚµW¬X!„ ™4i’bêÔ©{÷î5R½ÙÐ:ô?üðùsç€iÓ¦ !êÖ­Û³gO!ĨQ£…k×® >xðàÙ³g[µjµjÕ*!Ä“O>9eÊ!Ä|ðâ‹/ !vìØ1räÈøøøÄÄĉ'þòË/Bˆ3f|ûí·BˆÍ›7k?6œœLÓ¦X,=J•*z”¨0”<ò y—‹Â‰qc¸ÈÅ5¬™À„·xë-Þ:ƱbˆiC›2”1Z�¾<õß|Ö-ôéc´…ø‹¿Nr2–Xí/‘Ä4Ò2ÈÈ #“̲”µ`I&¹`ýÛ_ûU•ª‰$¸ æå0‡ãˆ;Å©‚?<®sÝq%Ndâë¼î¸øVbzcH!%€€yq%+c‰-G9?ü|ñ5Z—A|þ9C†0bK–-Eq÷œæôöh¸P°Ü ·†4,G¹‚¿jTóÆ;�ô;¾kZûóÃo1‹ Üsq’“?ñ“öO|Áò@ÒÐO/¼Wú<ÇsŽ‹o%æ6†¬x‰—NqJ HhK[£Jj*õëS±"ÑÑ”+g´…ÍÄ÷ Ÿ¬fu €;îmhÓžöÁ7 AA�ª‹Eâ'V³z kÎq(C™V´êHÇxà!jBWšYΔ›šGÞT¦NcZ0Á=èaÁR‡:�ØÿÝ2&#<œ”V®T®`.b=ë²ð'~ˆ&4yžç;Ó¹#}ð1Z�““Kî§|ºŒe80‘‰ÝéÞ‰NÚpv×Ä”=†Õ¬Ìà…,ãµHÃùóÓ¢?ÿl´…µÄW|5‰Ig8Sžò8ŒaÚÐ8…£I%u æ2÷*WkPc 1¨W•)0S�!ŸüÌhF³A J&y4£�V$Ó¦qã3f­Ca-?óó˼|€,gù ¼àr% "Ÿüy̛” 2îçþ¬èK_£EÉÅ­=†#GެY³ÆÍêÙ7+V¬øÚk¯ÙTdxxøõë6ÜÖñÄ 4°~ýýû÷ÿòË/Ö¯_¿~ýþýû[¿~VVÖÂ… ‹YáöŠzñÅ+V¬XBÜ[¦ÈX¿~½õš€{î¹ÇÖY8ªW¯nS›7o¾*®¾$^ÊùgÅY‹°ÿí·ß¶)¾6–õ$''—ôfbccm*bÀ€6ÅßÓ²¥qø°•ñúé'›âûøøØ¤_Ñ´iS›ŠX¶l™Mñµéi­§E‹¶nB™2¶�¿ï߿ߚ°±"¶µh� Z\5jÚðàÁ6é?qâ„Mú�ÔÔT›ŠèÖ­›MñÃÃÃmŠÿÍ7ߨ¿N�:ÅDË™Äwáî/üWˆÚBmÞSëѦŸ²žwÞyǦø¡¡¡6Å¿råŠMñ�˜˜˜ÃÞÚcÈÊÊÒæïµww÷j6Îä|ñâÅâ'¾ER¥J•føÌx‹·~å×Ö´.1~zzzzzúCݟʶ¼ÞÒb±\¸p¡äõ Q£F ®Ú]¹rÅšÙØµ­sËÎlÓÆ-(ˆß~³2~vvváÓyJª(77·{î¹ÇÊà.\Èɱáaï*UªøùùY¿~zzºõ-„ðöö¶òt¾€3gÎÜ1TQë×®]Ûǧ„{Å;ØÑ—¾ùä¿Ë»C“‡¦^Kµ^�¿¿¿M'U9996�ÎAAAî¶<*Ÿ˜˜XTC½cEU­ZµR¥JÖÇOOO·iöi�¢Nç/p¡=Žr´=>åÓ{ø»=Ÿ>}://Ïú"ýýý­_?99ùÒ¥KŬpKEùùùÕµå%ZùùùÚ€5Ç:�ûî»O{é@1È~óùçüð«D¥�ììA£åHÉêÕ ÌÒ¥ f´Eq|ÇwOñTe*og{š-Ç…8ÌáÞô¾À…yÌ{‰—Œ–c¤6�¨G½k\K&ÙO£åÈJ‡DGsþ¼¥*3[ÙÚŸþÕ¨¶›ÝA-Ç…ø‘ã1�ø’/{ÓÛh9æ@ÞQIùä—¡Ìf6ã˜r…"‰�åçŸ S® 3?òãã<^“šÊt&’È^ôª@…-lQCQ­G^cx’'äÁ·yûA4Z‹ÄhÃ�žyÆhŠ"I ¡?ý«Påw~¯Žm#/¥!–ؾôõÆ{{ÒÐh9fBRcH'=‘D×�òÈz¾ÿž€BBŒÖ¡¸3¹ädà5®íd§r=¹Â•ÞôN%u;Û•+ØŠŒ“õŸå¬'žQD}ÆgFk‘›´4öî¥Glò¤Ð“ILÚǾiLëLg£µ¸xŠSËXfÇšÏÌdölly ˬHg ÑŸþ5©™GžCg1tvì '‡Þê~š¤üÁ³˜Õ�îoð†ÑZ\‹Ïøl';_â¥çyÞŽa}}IH n]Þ}—´4;–G%íf÷QŽªQe%3bË—sé¶<‡¡Ð�hG»C:Á‰‚Qó H"©1�8ÌárØyPFR÷ÞKV+ò꫌Kùòö-A äê1¤�Nx':)W°Šßçþû•+ÈÉ×|½Ÿý˜ \AgÆ0æ×–²Ôî®Ô¬É¨Q×®ñæ›Ô­ËôéNØ{�«Ç0‘‰³˜õ´¤¥ÑZ¤'+‹òå0€U«Œ–¢¸•,²Ñ(‹¬Sœòdže¥dûÚÑn8Ã?åS‘”Dýúdg¸¹!+òÊ+Œç<½‡’�aÕ*øûó×µãBK™Ü“Þhÿ°¢D9ZÀ],4JÀ½W~ŸöýÃ_´šóŸFãUµÈ¦*!tiô¸M|RgÛHyTI+ÀŽªŽÏ MoþãCOŸöºXÇqª(<Ï…óÙCÉ£Y¶mcíZ”Àô7Yÿó‡ý KirÇ 4‹šU³¨•GX˶øé�ÍaK¹PϲLªêÊŒEîWª^š9ärŽDªœ^@Vóý©G|9úÆ©:7©êŽ“½Y,äåÝù+ÓQr�!3“ÜÜ›「¦»¥Õö �7hiÎçŽ.ËðækF�âÓOII¡B‡•¡¸ö³?„�×y=œp£µ¸½èµ›Ý§9]‡:Ž+åâEêÕ#;!þî+”/Ïøñüë_”8›µY(¹Çà«ËCfå(ŸAF²G²¯‘o%Ç�S·®r YÄ¢2”Å(£…¸qÄE1„!u`æL²²þþìçÇøñŒï<– !Ũ¤l²3øÔ{›m 1‘:ŽÝwA&™ëX÷þQ�zFkq-V³Ú‚e(CZÊÅ‹,ZàïÏ”)ÄÅñÖ[Îæ Hb ûØ·šÕ?aÛÛc\!¸p�@å£Ò±•­ÙdÀ¶W-)JÏç|^ŸúèàÐRfÎÄËë–`ˋ̈́nºÐ%•T5…ª \¾Lv66¾yF¡ßñ]Êô¤§ÑB\‹H"Oqj2“ÝpÜm=nÜ reââœÿ ®ñ=†D§3=�ô²”5Z‹yHLT�A6,X¶±­-m+£ž:Ô• l1È¡¥”-Ë¿ÿíü®€ Æðþ3™ÉG8b´S¡½ïPƒdüʯ—¹Ü‡>F q9~à‡zÔS³¨Ú ã�aÃ~çw5÷¤mho¯ZÕhŠ›ØÍn@]GÒ™«\=ÈÁnt3Zˆó`°1ä’Nø½Üë�·±JL†6\®¤WÏ+t&Š(_|Õûœuf7»-XºÒÕh!΃Áưƒ“˜´žõÆÊ0š1x+7•‹(¢äÁ2”1Zˆkñ?¸á¦ŒÁŽ<*éQÝÊVõ.V›Q=ù¸Â•8âã1£…¸QDTƒF q î1ìgWºV£š±2̇2ùˆ" hA £…¸,G9ª.ßÙ#�A çñ'yÒ@ fE›óWƒLD <ÄCF q-Îqî:×›ÒÔh!N…‘—’òÉŸÍìœôÙA‡’—¨W=KE<ñ@}ê-ĵÐFº«ƒ}1òÈ’AÆ?ù§�LLÙ²™™êõmòO|yÊWÄéæÍ‘­£¦ŒÁ¾i 3™NøyΛÅbÉw$Ï<óLÙ²Å>®Íy›™ù¿%99xz:ršïÿqñâÅÙ³gëP�ÌtìØ±OŸ›dK ÁÑóz*n'� ˆ ÊŠˆˆøðÃ4hàåå%îpÇåÖ|ëèŸß²Â«¯¾úä“E^Æ÷жvæÌ™ö­Á´´´²eËnÙ²Åß¿È÷>ȃ}é[�êö-º„-Z´ÈÉÉ©R¥J1Çå¼¼¼â¿u´ÎG}ôVc8tˆûïÿßM…råà¿Æ`±°d »wóÕWަ±cÇ»7ÓqìØ±[Œ!žxÇ×effþë_ÿ hÕª•#+zþ¼J•*‹/nÙ²å·ß~[↧�⋯>BýòË/Û¶m+}·BÜòßÛ)å E}›­Ý§,àÚµk'Nœ(ýÖ&------99¹cxš§Ÿæiû–["‡òóóËÎÎ.s3^^^eƒ‡‡‡MëüñÇß~ûí˜1cnÒ]«AA„†2z4­[ÿÝcÈÈ 2’°0`½~Ï‚\¿~ؾ}{‹.:ç‰'žˆŽŽ.¼$‹¬d’ïá£$åää|ú©£Þr¬3÷Ýw_NNŽ•g`W¹Z‰J%®¶xñâ“'OÎ�;·ÔêøóÏ?Ksà.½Gã<óÌ3Ï<óŒ}ãNŸ>}òäÉ¢Ø×Ãu¡K!ïònñ¡Îž=[¶lÙ5ìp¹IKÉSO=µbÅŠÒGsO<ñ„âVc¨V�×_gÜ8V¬ eKZ¶˜>�ˆ„ F úöÕM¡»»;P¾|ù*UªèV¨Txyyݲä*W¢ 6TH»víÜÝÝ÷îÝkIZÛîׯߨQ£J:iìÏË”)dí¥¡«\µfKDDÄîÝ»íb •*•lE¦ÆQ÷´¬o Yd]ær‰¡š7oÞ­[·o¾ùÆ^ŠWe8E*=š¥K9|˜¨(¢¢¶oÿû«‘#ñÔoÒrk’ëÜÜž£tÒ?ü¬’‘‘¡Y¬½$õêÕëÕ«—½bš‚R ì¨9+Ž}Ž¡øcÇ~ö/a‰CÜŽ‰�ÁÃ�>ºÃíå2e1¢¨hK–,™7ož]*c¸CŽ®s�Á¾¸lR¬¼”¤° GC‰Íô,g_æåp�€¢0±1:0hÐ-kÓ·o1óo¯\¹rñâÅvèºÇ ”1HByi¤)c°;†ÃyÎÏgþA:H@Q˜Û€>ÀÏïý!=Za¸æ1¨0Ê$!…�PÉÚÃŒ¡-mSHqô—nÇôÆP³&o½…¶‚»;AAtï®›6 ×<æöe�”£œAŠ\4))¤ªÇ`w 3†‹\ÜÞTR$ (Lo Àر4j`±0z´>µÆ5�A…¹=GÚTÛ,)rѤ\å*Ê€aưŸýOðÄüá Eá ÆàéÉÂ…ÞÞ ª‹¨›pÍcPanÏ‘/¾@&™EüÂá¸fR4cP—’ìŽaÃUCÙÄ&ýŸucºtaÀ|| ™+É5�A…¹=Ge)‹2ݹÁ ½‚ç¬f ¨Ðžöú߬scæÏ'!Áñrî€kƒ £z ’ Í„‘E–ÑBœ Ã.%}Íו©I¤ƒ…óCµj?ÿ¬;®y *Œ2IÐ:jZ¿AaG 3†¦4}•WkQËAŠÂyŒÁ8\óT˜¢ŒÁÀ#”k&E3Õc°;†]JjIË–Üt»‘�=èáèË…¦8ìʯ×;Fõ$ÁT�Áè×cˆ'~Ó’HÒþETco`p’“¡„~Â':ÜD2ÅaW~…¸Þ1¨0êæ³$¨ƒƒÐÏîážxâïáž'y2‚O<ýðË'ÿu^oJÓ"þ�ÿs�˜[„I¾ó˜B!®w *Œ5=†,²Žs\OI¸^RÔ=¡ë=†÷yßß�l %´;ÝûÑo$#g0#—ÜÚÔîCŸ"‚ÙY˜ä;�)âzǠ¸¹¹‰2b7»W‚'žžxÃZÖ6¢QUªê) ×KŠõ—’ºuë6xð`Ç+rt½ÇP�jÓ™>ŽqÀe.Ob’?µ;ŠQº¼gÔ‡]ùâzǠ¸¹¹‰\±� #9œáCZ�ê¾øÞàÆ)N�aÌ.v d`ñ¯gX²d‰›]ŸZ—¿åØ�;^J:ÏùÚÔ¾eͰ°0ýd™½G%�ftSšºÿ·\í„Ë�á /*ÔÙ³g?ûì3; “|ç1…B”11�é×¹þ:¯×¦öSùßðÍU®Æ›K.DPº¢JçBuÆ�QŒêA� lÈ#ÏowܳÈJ'ý5^kF37ÜÐÀh™¦Ç€áªè0ˆA«Y­ýW F£ßÄÑòï<öU8cÆ {…*@CAŽžåÙ¥,-|³Ac$# .“ê¯Ê¹™Å¬F4ÚÁŽšÔÅ(|Nr²! µ�úŒaqzŒyÀí>ðÃÏ 77Üîã>=Ï­äßyL¡e ÿÝüE,òij° xà1„!ƪrbêPç Þ’HšÆ´L2#‰ü‹¿Ýư8=ÆCMj¾Å[¡uô<·’ç1…B”1üwóÒð5^+è1h—F«SÝXUÎÍ+¼D�{¡Ã—Vÿº�aqz ›c,cà�²”ÕùÜJþ�Ç QÆPhóßà�úÔ׎SQâmg}T91Þx/`Á-o¿(~ ‹Â& 3O<°àYžÕy.uùwS(DC¡Í/KÙ…,ÔŽSu©Û½ß©wGUÎM/zõ£_Áņǰ(lÂ0cºÒu³$ (äßyL¡e 7o~/zõ§?0‚îÛ­lUåÜÌe®^š7è<†Åé1Ò0âÕKòï<¦Pˆ2†Û6ÿC> àŸüÓI˜¡åØ—úÔƒ7´» :�aqz 6ý‘ç1…B¤L®nÜ1G�F¡ÿLòÈßrìÎk¼V�z€ÎcXœe Òa …H™\Ý(*Gú¿ª¶0ò·»ãƒÏ|æûâkÈø`'Fƒt˜B!R&W7äÌ‘œªÍc<¶�…ú_”vn”1H‡)"eruCÎÉ©J†2Ôh Ά2é0…B¤L®nÈ™#9U)̈2é0…B¤L®nÈYò·‰‹‹;zô¨Ñ*Lƒ2é0…B¤L®nØ¥æÏŸ¿`Á;)3´?~|ûöí�VaL` ýû÷ç�wJGCþ�Ç QÆPêX¾|ùŠ+ì¤ÌÐrfÁ€i·me×®]¥R€ü;�}&''[,–jÕªÙ+ Êd­ùÛ¶Â,˜Àì‹ü;�}öíÛ7%%åøq{¾•^Úäꆜ5 ÛV˜\J²/òï<¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\Ý�³äo9 ³ ŒAF$W(mruCÎ0EÛV˜e Òa …H™\Ý�³äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAM¢'¦Pˆ”ÉÕ »Ô@·nÝÜÝíyf&Ë1�¯¾úÊb±­Â4˜À&MšT¿~ýÒÇXkâuxIDATÑpss“¼}È¿{+c°K Ìž=ÛNrþFþ–c žžžFK0&0†‰'–>Hòï<¦Pˆ2ùj@þ–£0 &0û"ÿÎc_…›6m²{IÚäꆜ5 ÛV˜e Òa_…U«VµW¨¤M®nÈYò·m…YP£’¤Ã ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\Ý�³äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\ݰK üõ×_ýõ—��ZŽ�Lš4éÿø‡Ñ*Lƒ &ÑÛ¶m[•*UZ·n]úP˜aç1…B”1”ºzöìéîî~àÀ;‰2Á»F äøñãû÷ï7Z…i0A�áÙgŸ}ÿý÷KGÇ]ù¢ŒA¾�¿å(Ì‚ ŒÁ¾È¿óØWá¿ÿýï±cÇÚ+š†´ÉÕ 9k@þ¶­0 &¸”d_äßyì«ðÇLII±W4 i“«rÖ€üm[aT�A:L¡)“«rÖ€ü-Ga”1H‡)"eruCÎ�¿å(Ì‚2é0…B¤L®nÈYò·…YPÆ ¦Pˆ”ÉÕ 9k@þ–£0 ʤà ‘2¹º!g ÈßrfAƒt˜B!R&W7ä¬ù[ŽÂ,(c�S(DÊäꆜ5 ËQ˜e Òa …H™\ÝÐj@6äo9 ³ ŒA:L¡)“«rÖ€ü-Ga”1H‡ü 5L!ÒAÈÙ¼ÍÒròãŠÆ`´„�÷–6¹º!g ÈßrfAÍ•$¦Pˆ”ÉÕ 9k@þ–c C‡íÖ­›Ñ*Lƒ£Œ¡råÊcÆŒy衇Jªzõê¥�£1bĈ޽{Û+š#�÷._¾ü‚ Z¶li´ÃhÖ¬Ù˜1cªT©Rš ;wî´oÿuìØ±ééév èLôíÛ×h fBöc� ²gÏžØØØaÆÙ%ZHHHJJÊñãÇíM¡Ð‡ÿüç?+VlÓ¦�ÑBnbêÔ©o¿ýv|||�:uŒÖâXÕcPÜ5�;wîܹ³½¢½ð 7nܰW4…Bzöìi´—Fõ …Â*.]ºtéÒ¥† zzz­Å±(cP( ÅM8j¸ªB¡P(LŠ2…B¡PÜ„2…B¡PÜ„2…B¡PÜ„1Æ0}úôªU«æääµÂœ9s´O?ýôÝ1{ölÿ»û­B¡P¸2ÆÃÆ�Ÿ{î¹Í›7µB�1¬[·î.â_½zuïÞ½*T¸K}ãPOýá‡Ú¶mÛ©S§-ZlÙ²åîUº$MÍáÇCBB:vìØºuë�;wÞ½J…„îìÝ»wĈ§OŸîÓ§�âäÉ“�:u éܹsRR’bÁ‚^^^�:uzýõ×k×®-„ˆŽŽnÛ¶mÛ¶mCBBŽ=ªÅ©U«VXXØ<0wîÜ[Š˜0aÂþýûµß:-Z´7nܺuëŠZ¡4[���­}HJJªW¯Þ]ÇqMšš‹/¦§§ !âãヂ‚î:ŽðÎ;ïT©R¥ ­ÞÎìÙ³µO=õÔ]ÄŸ;wnpp°¿¿ÿ]ês 0†aÆEFF !ºwïž””Ô¹sç;vh_åççk v!íCûöíüñG!Ä/¿üÒ¡Cí«Š+ž9s&55µAƒ…ãÇÆÆ8P”n?”÷Üs'NœÎh ŽöT!DDDD›6mªW¯åø rtH�ªoß¾kÖ¬qðÖÈ‹nì|G›ÐÛV­Z5mÚ4íóõë×[¶lÙ¹sç]»viKŠÚ…Úµk·wï^qó.T°Î-ÆðÈ#�hÆãííÝ¿‡nŽžèà©—+W®råÊC† ™6mÚäÉ“½½½¿øâ‹5jýúõ íÒ¥‹¶æÂ… G�åîî,Y²¤ø""##µ���ëׯwÔ–èΆ FŽ9uêT ##£S§N÷ßÿîÝ»»ví X,­~n!((èçŸnß¾ý¾}ûî½÷^maQ³=ggg{{{+VLMMuÔ–8:¤F1räȺuë¾úê«ÛÙÉÌÌܶm[bb"péÒ¥Õ«WŸ8q¢à- w¬d &&¦cÇŽ@HHÈ™3g´…¾¾¾õë×rssõ�n:Œv&…µtëÖí·ß~+øo�=Ö¬YÓ¡C‡���.]ºhýh!Ę1czôè®�ò:tè‘GѺÒÑÑÑÚ:Eu¶>þøãN�:µoß¾uëÖÛ·o×a£œR³qãFí I§N�ºvíªÃFIˆ× pñƒšDO¡P˜ƒîÝ»‡‡‡·nÝZûohhè�!C/^œŸŸ_øzCXXXLLL—.]>úè£ÄÄÄ?ÿü³ðõ†&Mš���ZÏ£^½zçÎ�+\Ê—_~¹téR­37|øð�ê¼™2 ŒA¡P(7¡¦ÄP( ÅM(cP( ÅM(cP( ÅM(cP( ÅM(cP( ÅM(cP( ÅMü?�Ùå^yV4IEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/queue_analogy_tv.png0000644000000000000000000000013215132411300023202 xustar0030 mtime=1768559296.227885023 30 atime=1787067730.719538366 30 ctime=1787067793.878715439 rsyslog-8.2608.0/doc/source/whitepapers/queue_analogy_tv.png0000666000175000017500000004445215132411300022661 0ustar00rgerrger‰PNG  IHDRë8ô;LwsBITÛáOà pHYsÐй‹çŸ IDATxœíÝw\S×ßðOKöRQdƒ7ÕZ«­J­uÕ]·uàh뮥\m©¨ÕÚV­£¿ÖV[[«m]åqTqáAPA�d„™�óüq1 ! ; |ß/ÿ8Üœ{ï ćs﹇Ç!ºC$Â’%HLĹsÚn !ºŽG NtKa!‘›‹‡áâ¢íÖ¢Ó ´ÝBÊ25EPÃÏ?k»)„è:Jp¢{F�@ NÈKÑ( Ñ=4�BHÕPœèH!¤j(Á‰N¢�Bª€FQˆN¢�Bª€úàD'Ñ@ !U@ Nt ¤ò24ŠBt ¤ò2Ô'ºŠRyJp¢Ã†h …� Ñ( ÑaÝ»#2< ¤¢õÁ‰ @)„T„œè°ž=K ”à„hB£(D‡=x4�BˆFÔ':ÌÝ ¤¢%8Ñm4�BHÅ(Á‰nëÑ£´p´ÚBt%8Ñm\ÜÛ¹¹01ÑvkÑ-t%“è¶¼8ÑmqqÊøp÷®öšBˆÎ¡'ºMíæ�;Zj!ºˆœè6µ ˜ 7WKM!DçP‚ݦ–àr9®^ÕRSÑ9”àD‡åä &F}#ÝVHÈ ”àD‡EF¢¤D}#%8!/P‚¦1¬/_ÝKJp¢Ó4Τ‹ßàM!DQ‚]ÅX…ÏB¡�BP‚݇ÌLÍ/ÑS®@ NtW%1M}pBP‚ÝUILß½Kóz%8Ñ]•$xI Íë!”àDG©Îåáñ4T �B(Á‰ŽR�Ë£q�cJpBA‚ @ÛM õ@5 ÍÍ5T y=„èo‚3°£8êWà·kµÝRToDQMp ‹ÒÍë!D¼4»süFlqgÁ�ð›ábˆµÝ(R§Ôæò¨&x‡Ê2 ¤�&OŸ\™ÝŸ�¸ûÅ]ó‰æþ_ùçý�÷9>×vÓH�R�Ëck[fÜ×WY¦y=¤ÉÓ�WËn§±N;Cvf8e|mø5Ï�GÝðÆF5š¹…êTœúà¤ÉÓõטÝ�ÎÆlc àͱoR7¼±Q�fµo×/>´4¯‡4yº›à•g·¢ZˆauÃÕ/,,sÏIf&,-KË4¯‡4y<¦{·d1°_ñë'9ŸÜÝ}8ÍpZå´j*¦ª·ª!²!'–ŸX¾ey(B¸©¤îåäÀƦÌÂÍš¡àÅ=£|~™—Ö­ÃÊ• Ú3ÓZ‚ëHv+„P7\ï¨Íå±±ÁÙ³èØ –y”Uj*Þ{¢¤††�ÉJ·ÿ÷%8©={û‚àà[ ÞÏ?÷Ìj°cmÇÁµ5Þ]9 ×?jsyâã1gärlÙ‚›7•ÕF�Â÷ßÃÐ àƒ”Ûi^i’jžàrÈu0»Bè¦ý¢6—ÇÆ;v 2={¢¸Xù’L†I“‹/¿Ä€Êít1“4I5Ea`31óÏœ?Ÿí~¦ c&•ކ¢‹—D$j»9äe4ÎåéÜ/ÂË ¥[ÄØ±¥en^�\¼˜×Sùí+„TGPÐÐú>ůåjÒ_„EßF}ûlÖ³VSZéT¿[ÕZ¬='=‡,<ŽyLÝp=PÑ\¯Ì})ª×zh^iòª�àÛ±=ü`8l7,°] ›Ù-”W‡¯.X_SæšÕèi8ÕšË£Šæõ�¦­z ¾ÛƒÃÃ�‡£6>ؘ‡¼zjY (²;ocžu�õ¶uÛà C6C3m7�TªZsyTѼÒ´U#Áñ½óÝ�GqÔ|йx�x'v¾|Ïú§šÝöAö_¬û"Ù5y*¦j»]¤jªø8”òÊÏë!¤)©j‚«Æ÷,̰\°\ºáå³;É5iQ¿[‹®]»V½ÔÖå©:Z¯‡4mUJðòñ `9–k·NÙ­³RRRz÷î}êÔ©*ծʺ<¡õzHÓöò×ßmuÃ)»u\PPPaaáÀ�«”ãªsyŒ�!•VãL±±xüXù%Íë!MÌK¼’ø†6ºá”Ýz�Çã}òÉ'.]ºôòW�Ýâbtìˆ1cý’s$%aêTtèP¦&õÁISY‚Wßœë†Svë—   Î�;så—ä¸ÚeLcc> ?¿ s<= ÂÛ{÷‚ÏÇŒ´^©Äÿý·aÆÜFúÁ¨0Á«ßh�n8e·>RtÃ*ÌqÕ_» 8¸LŽçç++|ý5Üݱu+d2LœˆØXìÞMózH%zôèñ믿º¸¸¬[·.;;[ÛÍ©k¬œóìü86Žw�ÇûoÛU¾‚šPŠm°M°•0ÉK+W˶F�+ÀV`%ìÚÁ¾ÈgùUß=�åá8L™Ü¾}›1&“É¢¢¢îܹ£(ß½{—1&•JÕÊÑÑÑŒ±ââbE¹¨¨(***&&FQ¾wïc¬°°P­Ë+((P”óóó£¢¢âââåû÷ï3ÆòòòÔÊñññŒ1‰D¢(çææFEE%$$(Ê<`Œåä䨕>|ÈËÎÎV”³²²¢¢¢=z¤('&&2Æž?®VNJJbŒeff*Êb±8**êñãÇŠò“'Ocjå§OŸ2ÆD"‘¢œžž•œœ,—Ëýüü4~êzõêõÏ?ÿ0ÆXv6ãóÀÆç³œœÒ^r2 f¦¦¥/©þãñØÛo³»w•?é™3•¯®[W�OiþüóOîƒgmmòüùs�ÕnÞdnnY¼Pþ£Wçÿçê×ïéÁƒ5yk|:›Ž?�§ðfÞ…¬°*G1—˜c¶°-5i‚&µÌnNËÃQ …Œ1îׯ¥¥%c,33€­­-cL$ppp`Œ={ö @‹-cOŸ>ЪU+ÆXRRÆØÃ‡¸»»3Æîß¿ÀËË‹1vïÞ=íÚµcŒÝ½{€¯¯/cìÖ­[:uêÄ»~ý:€.]º0Æ"##tïÞ�1ößÿq¹Æ;þ<€ÀÀ@ÆØ¿ÿþ  _¿~Œ±3gÎ0`cìŸþ0hÐ ÆØ‰' <˜1öÇ bŒýöÛo†Î;r䀑#G2Æ~úé'cÆŒaŒýðÃÆ�Ï;pà€I“&1ÆöíÛ`Ê”)Œ±o¿ýÀôéÓc_ý5€Ù³g3ƾúê+sçÎeŒ…‡‡fŒ………X´hclòäÉ•ô:vìxë믕g??õ!—ãÊ:ìòeõj{ö(+ RÝÏ i z¨ÜãdiiùñÇ‹Åbµ:ú˜àFQ,`�KÀAÄ}'LNÁ”|ä—¯¦ªGÃëxÌ„/®'ÈçóýýýU˾¾¾ ýýý;tèÀÈÈHcÙØØØßß¿]»vjeÿ¶mÛ055õ÷÷÷ññÑXööö`ff¦VöòòR”===…B�essswwwµ²………¢liiéïïïææ¦(»ººª•­­­ýýý]\\å6mÚ¨•mllüýý���ØÚÚª•[µjÀÎÎNQ¶··W+;99¨dðÑÅÅeîܹ>))ÊMåïoÙ[·¢kWå–íÛËÜ>X~Gš×C4 Q”³³³×®]ëêêºråÊŒŒ í5ª.”õ#ì>AÖÁ1Ó�OaøÔð=ö^Ë«äWAí»áuÒïV•Çòð'šE6«ÍAH�eeeY[[—ÿȹ¸¸ìÞ½»¨¨ˆ1ÆVvHöíÓ| ^½”u®\ÑPA.g66Ê:qqõø®ˆÞêÕ«WùO£P(\ºtizz:k4}pŽ|R¬S~\ú£Ï|ÙAÙ¾5û,“-+é�צN×*¥­[·>þ\u —Ýqqq3fÌ066®Õ\U5š×#—ËKJJ0ÆŠŠŠŠŠŠ¸�yyyyyy\9++‹|“Éd"‘H,�J¥)))éé銋‹“’’RRR%$$ýå—_._¾ ))éÿûߥK—<|øpÿþý.\¿gÏn€.66öë¯¿Žˆˆ½}ûösçθ}ûvXXØÙ³gܸqcóæÍÜÀ]dddhhèéÓ§ü÷ߟ~ú)w-úüùó«V­âôÎ�;·téÒ¿ÿþÀ©S§/^ü×_8qâÄüùó¹òï¿ÿþþûïså£G�NŸ>ýäÉ“~úé§É“'s僎7Ž+ïÝ»wÔ¨Q\y÷îÝo¿ý6WÞ±cÇСC¹ã|ùå—ƒ âÊ[¶léß¿?׆õë×rm éÑ£Ç?ÿüóé§Ÿ–ÿH$’M›6¹ºº~ôÑGb±ÖW«­ò¡ÎõÁG²‘Ü—%¬äGö£O¦ÏKûã5è†×y¿[õÁµH­^¦ß­pïž²7bkËärÍÇziœ1¶f�¢NÆ{ï™››s-RSSMMMÛ´iÃ{úô)ŸÏwvvfe/lpÙZõ QQQ¨Ý…�W_}•UçÂÆ[o½ÅöÂÆ¶mÛ éÂÆgŸ}à£�>bŒmÚ´ À²eËcëׯ°råJÆØš5k¬^½š1ÆÝ�´fÍÆØªU«¬_¿ž1¶lÙ27ndŒ}ôÑG¶lÙÂ[¼x1€°°0ÆØ‚ „‡‡3ÆæÎ� `ÇŽŒ±Ù³gصkclÆŒ¾ýö[ÆØÔ©SìÝ»—16iÒ$û÷ïgŒ�?À¡C‡222x/‡íêêºmÛŸz×ù 0ƒ1£¬Gý¼ôç�ç!±»c÷í;8íà§ ;°CõÁ­ËËW´X±ñÁÆ÷Ýß@Pùa×bí&ɦ¼=yH‡ý4ûå®Ëgc6uº EÜÅÅeÅŠ“'O66.÷bµxm›W ¿v-77×ÔÔ”ûª°°�ë_óx¼’’®ßÍãñø|>ŸÏÀçóMMM¹ú|>ßÜÜ\(044´±±±´´äÊŽŽŽ¶¶¶Œ��[µjåèèÀÄÄÄÅÅ…ô755õôôlݺ533³víÚq„BaÇŽ=<<XXXtíÚ•»øaiiÙ³gOµµu`` waÆÎήÿþ;vààà0hÐ Í›7:th×®]´lÙrøðáݺuкuëQ£FõìÙ“ûn�7Ž.pss›�+·mÛöý÷ßçÊ:tæÊ;v\¼xqŸ>}tîÜyéÒ¥ÜöîÝ»¯ZµŠ+÷êÕëÓO?åŽÿÊ+¯„††rçíß¿ÿ–-[¸«…477çʃ¶··ïÞ½;€·Þz«uëÖFŒáå厗wß}×ÏÏ�›=0a„nݺqïwÊ”)����:u0sæÌ�r±æÎ�ûÖ[oq¨.\8zôhî{øÑGMš4‰»È´råÊY³fq�>ýôÓàà`ww÷ÐÐP¦é‰‡‡ÇÇ<~üø;wøaaúv»aùPW냫zi¼*Ýðzíw«¢>¸¶ppÍýnUªw®YSaµªôÁ³³·¬Èù|Ijj~~>cL.—I¥R®–¼¢n>iìÒÒÒÌÌÔ× pssÛ³g�âãѨÆÁ5âúãÑÖÑ��W>NãÝMıcÇ6mÚ¤ﮈê€õ®]ؽEE59ßÍ›˜>½t¹5€WR"ˆŽnÖ¬�glllhXú·f%D“Æí³Ï>ËW™æââòÍ7ßÄÆÆN™2EññÐG5Ye­’_€§hRv7)“&MzIv£ìº<RR0kÜÝñå—e&aVîÒ% ‚.]ðóÏàó•Ûé)DEFFÆÎ�¥‰äìì¼k×®¸¸¸éÓ§i·aµWóµê5æ¸E²EA8)»á”ÝD3Õuy|}qø0:uBr2-‚‹ BCQùèÓ§ñê«èÝ'N@ À‡â³Ï”¯R‚Ÿþ¹D"iÕªÕŽ;îß¿?kÖ¬—t/ôGmÿ|(�ónÑ]L‡ø²x„ûˆIDážBºVI4P Ù^½0jFŽÄ‰ Å¥KX¹›7cÞ<,XPf/ÆpìBC ÖÖFp0ll‹E‹J«qózhÌ„b±ø×_ Ÿ1c†âúvUÔ~!ùP7@ê9þu,†ãïð¿ñ ö3µ“ÝrÈ·ad yNRå×åáñ0d† Á¿ÿbýzœ>�õëñå—°´TÖœ0 àèˆÅ‹ñþûÊE5¹õz¸G�sëõxy5Ð{!:,++ëîÝ»z=Ø]‰š�¢h:–ÁŒ‰±ŽùqÙ�<9B|°áƒ§®Ox̤%‡pÈ[ì½lÝ2܆k[×;5©ªÊçòôë‡S§på Þz ùùP�yŸ�gglÛ†G�°dI™5‘i½¢‰»»{c�oÔm‚sxà�Á�S,Æbc4Üx—Ý>bŸ ¡v&¸ÍrÛ·jß-á­k©*Õuylm5w–»uñc¸u vvÊ�«V!!óæ¡™¦>�ÚRiìɯ¦”üˆCÄ! _'@·Yn«íW�ÇxÃÆò›ªÏåñõ…—� B%÷¨&8õÁIõ=zdùÎ;ƒU·””ÔüjŠ¡!“É4ïn`ÀT?õ%%¼éÓktŠ5L‡Pvë%Õx­ñãPÊëÖ ¥7†sëõ¨³R©ŽQPÕ‘‰ ØíÛ‰'Þ«Ùß{ïõ�?Žôöî +ë”PXºì¿ÿ:%'·?t¨LFÕìÎF=Ž9Ên=¦¶²Z]±°@ûö¸sx±^OÿþuvpÒØñx01)³¥_?Þ¯¿ÚÉk|̜㘘›#/ϬmÛÒ½ÅÇÛ b¨v®š©ûqð >Þ=Ãmߪ}qöq“1™â[¨ÎåáóÑ­[]œRHÝéÖ ‚ââZådBbcËl‰�µéÝ»V Sг¼£~wc :—§mÛ:èèÑ»w—–)ÁI혙ÁÛ[~î\«V­$+$%™3¦y¤»U+ cÈÍ5nÞü*©Ô :Ú†+dd˜øúÖM õ&ø(»Õ`}ø;wbúôŽª‘HJ‡P84¯‡ÔÚ„ ¿üÒöúuͯFFº¸ä–ÿˆ%&šûú–…¼óçÛ•Ÿþ9iS}DmèAüQv76ª7¢äçcÎ|ñ֮Ř15OÛÂBì܉�‘ž®ÜHózH­-^l°xq…£(¦¦lË– åÊçÌyýçŸMÜÝÔQTW@§ÇÁi¼»R›Ë³};ÚµCBÆŽE×®øûïj°¸»vÁË#=½{—X§�R§¤R´i#oݺ„ûW\¬¹ÏÁëÓ§´Ž³³<:º¾ÚSa>ÁdÚ Jêw7ZjsyæÌÁìÙØ¿!!¸qo¼�W_ņ –3.O&ÃÁƒX³�@—.X»o¾‰µkKŸšàòeLž\?ï„4EŒáÙ3Þ®]ç[ 5Ü©²nÝÅ�ä¡¡½Š‹ëkRº†@4‚zãÊÂ+Ž —º.�‹¹/]p§Qv7råçòðù˜2cÇ⫯Šsçг'†ÇúõðñÑ|¹‡#$qqСÖ¬ÁÛo—ÂÐí(¤>Éå¼S§œ«^?+«³‹Ç4-;t§W¬þoïx ›©6K=ª�ãüX¾ü†ž?§y=¤®””`Æjï5}:š7¯‡Ö@Ó*k §Ø©žù=±X›x›Ml“„IªºöÏ=B2K®Je“d=2<°X ·t·}lŸ”I«x.¢O|}•kL�>­¹Î³glî\flÌÖ¬kÙR¹K»v¥¶g“Vð!Q=Ë™3õ÷nѮʜS³¯b‚Sv7-ÙÙŒÏ/ V>ŸåäTV9!��§XýRùÏɉíØÁ*Y~“•]�sݺº}„莗'8§º9þÒ§ìnŠN�R«Ÿ_•v¹y“Y[+÷Z°€åWa]ì={”» RËV“¦F nedÁ ¯¿þúæÍ›U«­X±bøðájû^¿~=00ÐÌÌL(úúú;vLã)âããAí›ZÕçT=Ç+IpÊî¦kÍe°ÎšUÕ½ª²V½š{÷”»ØÚ2Z¢žTŸZÈ~ÿý÷�:uR|)—Ë]\\Ž9¢º‹T*mÞ¼ù×_]\\,“É®\¹òÿ÷U9x�U/Á9UÉq� NÙÝÔ ¬ Ö}ûªºW \.g66ʽââjÜdÒd©…lnn®™™Ytt4÷å… ¬¬¬ UwIJJ244”Édj‡ÊËË›9s¦­­­••ÕÔ©S \]]üää*]/Ô¨&3z`À¥f—NÍ9Õóãž™ÿd.]±Ô9Áy36sKkDssÈKÖå©[<”_Ò=…¤Ö„Bá°aÃ:Ä}yèСQ£F™”}À “““““Ó»ï¾ûûï¿§¥¥)¶Ï›7/???11ñÉ“'b±8$$äŸþ‰D"‘´lYÕö4¨qös*ê�+úàÔï&¥TG66|8»v­J;V·ž“Ã6nd�r¯Ù³kÙvÒ•èøóÏ?]]]cR©ÔÎÎ.""¢ü^‰‰‰³gÏöððàñx½{÷Ž��ÏÏÏ766‰D\…ÈÈHwwwmŽ¢”§šã–ñ–›Ø&.Á¿b_µÉhCÙMclï^e¤rw¤ðxlð`véÒKv¬z‚gf²��2ã'Ü¿Žëð}�&¢|ÈJ¥R‡‹/?~¼M›6òJ¯¯¤¥¥�?¾OŸ>‰‰‰,_°°°°³³Ó­ç¨æ8îá ì&Jªwø-[Æ–.eææ¥_¾ö;{¶Â«’àéélùrfaQZ­_?öûïÊ;_zç"!åh ÙùóçÏ™3gìØ±Ë—/énݺecc#‘HLLLòËÞC•�� s Î9ÅNõ,ì‰`)ÚˆÛPv“RåçòˆÅlõjåÍ‚½{³“'5ìXy‚§¤°Å‹•c&o¼ÁΟ×pFš×CªIc‚_¹rÅÖÖVõ’¦*‘H´~ýúG�1Ʋ²²fÏžýúë¯3Æ&Nœ8kÖ¬¬¬,ÆXrrò™3gÄb±��AZZZ-Y÷ ÎéÈ:z2Ï$–TOÇ'z¦’¹<ÙÙlýzfo_új×®ì·ßÊÜÿWQ‚'%±9s˜©ié€Ì°a,2²ÌIi^©…Š:¼¼¼üýý5î’““3vìX''§fÍšY[[�1âéÓ§Œ±¼¼¼yóæ988…B//¯mÛ¶1ÆæÍ›gaaaiiY›{Qê+ÁåLÎ+a%õt|¢g^:—G"aŸÎZ´PÖùé'VR˜¦��gÓ¦•N»70`£G³[·4“æõ�Æ®¾žÎ€�n?œ4œ—.m,`ñb<|ˆíÛáìŒÛ·1f Ú·ÇþýP}øZb"&NDÛ¶øî;Èå˜8ÑÑøé'øùi8¦ê‰¸õzi\4?›��:6dNœ(-ïÛ÷’gvcÿ~l܈ÀÔ……¥/@.‡±1&OƲeps«ì8ŒÁÎNù8ò¸8Z¯‡42ÔG&õ¯ºsyŒ�1}:bc±?Ú¶UÆ7##Ì›‡„ìÞý’øÀã•Y)‚æõ�F‡œÔ?µuyªØ64Äĉ¸{ÞÞÊ�¿ý†mÛкuUO­6�BHãB Nê_ùuyªÎÀ¶¶Ê/mlªwjZ¯‡4j”à¤þ©F§©)¤Ò†;µP¨ü…q÷.rsîÔ„Ô?JpRÿTüÈxzbûvÔïI¯\ÁÛo£W/å-(%%¸zµ~OJHâ'õ,'11¥e´k‡¤$ÌŸlØ€ììº?ãéÓxí5ôè�cÇЬ:tP¾D)¤q¡'õ,2%%¥åp÷.~û°nÑ IDAT Ý»#=+V M¬X�ôô:8‘\^zä×_ÇÙ³°²ÂÊ•HLÄâÅÊ:”à¤q¡'õLm.�‡aÃpù2ΜÁ€ÈÎÆ† puEp0?®á)d28__ ŽÈH4oŽ�‘”„uë`oOózH#F Nê™ê�(ªaÚ¿?N�Bd$†Ga!¶mƒ‡¦LAll5^P€¯¾‚§'&MBL \\°c>ÄÒ¥°°(­ãí­¼ƒE,F||-ß!ºƒœÔ§—Îå ÀÑ£¸s“&�1ìÛ‡öí1r$®_É‘sr°iÜÜ0w.Ñ®öïG|<æÌA³fejÒ¼ÒxQ‚“úTŹ<íÚáûïKó×ÄGŽ kW „ˆ •E"|ü1Ú´Á²eHMUþ˜8†¬ØGózH#E NêSµæòpc �•Ž�üóúõCïÞxþ\Y', ..X·YYeÆa *ý$Ó¼ÒHQ‚“ú¤—U\򯄱ÌuÈK—pïžòÕDAA™k¡UÑ­›2âi^iDj˜àB¡P( �'|aàÀ�[¶lQ­¶råÊwÞyGmß7n¼òÊ+�ÀÜÜÜÏÏï÷ßOHH …Õj·ËÇ›7o^³·@ÂK*[++Œ�4tÛ[·ÆøñèÖ­G³°@ûö¥eš×C‘&¸D"‘H$·nÝ’&L˜ðÃ?(ê0Æ~øá‡ &¨î(“Ɇ 2a„¬¬¬¬¬¬o¿ýÖÚںƭwssKMM­ñî¤~©Îåáó«‘¹b1/†�þ÷? 7ÿ=~ŒÑ£Ñ£Î�«Fch …4JµYBm¢ÜÜ\Õåã.\¸`eeUXX¨ºKRR’¡¡¡L&SÝèêê @ ‚äädÕê–322†*¼¼¼vîÜ)Ô�‘‘1bÄ [[Û… J¥´>§V©®ËchÈÂÃYQÑKvÉËc¡¡ÌÒR}±ùŠþ½ù¦æÕyÔ\»ÆÚ·§õzHãS—ãàB¡pذa‡â¾Õ^ P–Õî69yþþ˜<IIšÛ�1c€èhåFš×C�ÚÄù•@ÿüóOWWWƘT*µ³³‹ˆˆ(¿WbbâìÙ³=<Ÿ¯XûùäÉ“ÞÞÞµyw¤¶Vv{-b~~Ê50�/SóèQæã£¡‹íêÊd={*·9ÂÆŒa<žzM¶x1ËÈP39™ÍšÅŒŒÀÌÌØ²eÌÚZY?.®�¿„Ô‡:Np©TêààpñâÅãÇ�·iÓF®ºâx9iiiãÇ�ïÓ§OUüÑ£G¦¦¦Š:÷îÝSKðò¬¬¬jóîH­ÈåÌÆF™˜±±¬¤„íßÏ\]K·² Øùóe2Vü³³c_~Y:êR~¥ã«WÙk¯iØËÊŠ…†²”¶l33+½™5‹qk�¿ù¦²æ¾}ÚüæRGêønBCCÃ1cÆ:tèСCãÆ�ãUzÿ¯ƒƒÃ’%KbbbÔª1Ƥ¿x摽½½T*U|™Tî¯f;;»ââbÕ ŽŽŽuò¦HM”ŸËc`€‰‹­[áà€óçѧqéR™¬Z…°`Œ�5¼kWœ>�¿þB§Ne¶geaÅ ´j…�QP€Ñ£�]»À ÍѼÒèÔýýà&Løé§ŸŽ;¦v '###44411@vvöÎ�;»tébmm]PP _'''�@ðÛo¿…‡‡sAPPÐ’%K D"ѺuëÔŽ, ‡ ¢¨2vìØ:w¤ª*šËclŒwÞÁ AæàbÖ,ÄÇcíZåSM*1h®_ÇÁƒpu-³�gwqÁرef�Òí(¤Ñ©ûïÖ­›­­­··w»víÊ¿jbbr÷îÝ>}ú˜™™¹ººŠD¢½{÷ÚØØÌ™3ÇÓÓÓÊÊ*%%…Ï燇‡O›6ÍËË«W¯^Š}wïÞ-‰ìííÇ�_þàß}÷]NNŽ£££��O@@ÀŠ+êüÝ‘ªÒ8—çùs,] //8 ~=ÓÀãÇcíZ´hQ�³`Ü8¬_õ—=ÂðáèÝ.”n¡y=¤ñÑö0i¤|}•ƒÎ§O³‚¶eK™‘qÅ¿îÝÙ›o2>ŸÌÜœ}ú)ËÉ)s¨òãà §O³€€Ò—<=Ù;ï0�@Ã)Þz‹q7¹ª¶êÌ™†ûnR?hV=©jsyâãáí��>RŽŒs|}qü8._ƉˆŠBPrsñÉ'ððÀ¶m(.®ìׯcà@ €«Wáä„Ý»ƒ#G�™3Õo:üýwøùaútøù)7Ò@ i´ý+„4FªsyLM5tŠ��ÙÞ½¬ìÄ.Æ»p�*o%ù�©¿dhˆiÓ°z5*ž¾[ÆñãX¾wïjx).®ÂG–¢hœÔ5µuyðxèß±±Ø´©Jñ ”¹yÜÈH¹}À€2·xWÅСˆŠÂ¦M(ÿüK 'zŽœÔµÇ�Õ¯X2†³gñÆ8p2Y5elŒà`té¢Ü²~}µ{Í11˜2+WB"Qé¥k¹¢Û(ÁI]kÓ—/#(H}ˆùÞ=Lš//ìÚ…¢¢j°òõw*qãFŽ„¯¯†ß­[#<›6ÕðÈ„èJpRºwÇï¿#* ï¾ >¿ÌK�áý÷áæ†/¾@^^}5à Œ®]qäˆúÔ!OO|û-0¾úšÈ„èJpRoüüð¿ÿ!&S§–Ë�’‚>P®xY‡þù}û"0'Oª?BÖ×?ü€{÷0mZ…O\!D¯P‚“zæå…ï¾CBæÍSïófdàã�áâ‚+ðâ©85$—ã·ß€Aƒ4Ü>Ø­Ží[;VýoBô%8iÎÎØ¶ �aɘ›—y);6ÀÕ âéÓjY&áCðóÃðá¸vMýÕ~ýpê®\Á[oѭߤñ¡' ÈÑ›6!) !!°±)óR~>¶n…»;fÌ@BB•ŽV\Œo¾��&L(³C†àâEœ;WÕõì ÑC”à¤ÁY[ã“O�”„-[мy™—Š‹ñí·ðñÁøñšçàpq?s&<(ó’�F�Â�8~*¶$¤Q¢9™D« ±g6oÖ°Ð%�‡aðb.T®qæ ®\AXD"õúFF7Ë–ÁǧޛMˆn ':@*Å¡Cظqq^µ²RÞ¯bn®á¹Þ¦¦˜2K–ÀÅ¥^›Iˆ®¡':C.Ç/¿`ÃDEUu¡³fც·.!�%8Ñ1ŒáÏ?ú’‡–X[cþ|ÃÖ¶¡ZFˆÎ¡'ºêÜ9¬_�3gÔ·;:bÑ"¼ÿ~•ÖÒ$¤Q£'ºíʬ_�ãÇÁZ·ÆGaútš O‡œèƒÔTüø#æÏ§•„¨¢'„}E3z!D_Q‚Bˆ¾¢'„}E N!úŠœÔJBB�Ç …fff]»v½yófµö …>l®ö|« …B¡P(¸3rjÚpBJpR[�@"‘H$’¡C‡Îš5«º»»¹¹¥¦¦V¥&w–[·n)Î()¿xqí×í ©W”à¤nŒ1â�ʳ^ÃÃÃ���AïÞ½¹�b±8((H(z{{Ÿ>}/z⊽ÄbñÈ‘#---íìì-Z$«tm{�•¿ùæ›qãÆ�J¥�`Íš5îß¿ïää ??Ö¬YvvvÖÖÖÓ¦M+,,äîääTƒß@„h%8©2™ìðáÃ�:uRlñööŽŠŠÊÊÊòòòZ´h·qæÌ™ÖÖÖ"‘èÂ… (œiÓ¦™™™¥¦¦ÆÄÄ\ºtiÆ •œTcåÀÀÀóçϸqㆣ£ã… œ?>00À¼yóòóóŸ}úœ?þüùó}ûöõóó»yó&×OOO/..öðð°²²²²²0`@vv6333KKË:ùnÒ�(ÁIÝ077ß²eKXX—‰YYY³gÏÞ·o_vvvDDc €½½½T*M±,}R¹uyìì슋‹U+(â¾¼J*FDDܼy³K—.���‡‹Å¾¾¾vvv&&&Ïž=ËÊÊÊÊÊÊÎΕ_ë‡ýA NêLÇŽ;vìÈuË‹‹KJJlllŠ‹‹·nÝÊUAAAK–,)((‰DëÖ­S;‚P(2dˆ¢BHHÈØ±c+:]%•þùg##£W^ye×®]½zõ200£G�^´h÷k&%%åìÙ³õò½ ¤AP‚“º4wîÜ;vÈår‡¥K—véÒÅÇÇÇ××WQa÷îÝ"‘ÈÞÞ>00püøñå�ðÝwßåää8::úøø¬X±¢’ÓUTÙßߟ1Ö§OR©”+صk—‘‘‘———¹¹ù«¯¾Sgož�GÏ&$„}E}pBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœBô%8!„è+Cm7€�—))Az:22 A$*-äçÃÑöö°·‡�]iA Ðv[ iP”àD'=x€Ó§�ˆ¤¤Tu/¡Ý»£o_ €=ÀãÕg Ñ>cLÛm ä…çÏñã�Ø»W¯*7òùppPv´¹‚™ÒÒÊôÊE"äå)÷jÞ&`Ê´k×ðïƒ�†A NtC^BC†‚°¶Æo o_ôí oïªö¦³²pî""ð÷߈�-ÝøúëØ¾^^õÕrB´‡œh›\Žýû±reéhÉk¯aÆ ¼ý6LLjuØ«W±w/~øÙÙ04ÄìÙ �­m�4™Á fÁÚnƒvÌÆì¶h«íV4y/báB\»½z!, ݺÕåñÅb„„`×.Èd°±Á'Ÿàý÷adT—§ Zuò$nÝÒv#´ÁÛÇ`MôßIv’-JNfcÆ0�ÌÙ™ýð“Ëëë\ÑÑlРҟ¼³3;w®¾NDÜôéÚŽ-ý1‚1Æ ðÀ G¸¶£4œ�؃m·¢iûë/LœˆŒ X²~3³z<]»vøë/üù'>øqqèß~ˆÐPÒ½X�ÄàÁèØQÛ�h(÷ïãÈÅW Ì@Û¿GÔ`6˜úàZ#•²+˜�ØàÁL"iг—”°-[ŸÏÖ»7{ò¤AÏNê×ÿö[m·£=ªìƒÓœLÒ€RR0`BCa`€�qüxCÏÁ10À‡âüy8;ãâEøû㯿´„Ô)JpÒPNŸ†¿?""à䄳g±t©ÖfÜôì‰70d220dV®„L¦�–R;”à¤þ•” $ƒ!=ƒáæMj¹I¶¶øãlÜ„†bÀ€jÌü$DgP‚“ú÷Ö[øôSðxX»'NÀÞ^Û ðxXºgÏ¢eKDDÀÇh»M„T%8©.€‰ <=a c¹–-á๹HHÐvk©ûïD%>òóñ;EEÚnÐ GŽ KDEÑC ‰ž¢'õ�»bSS|õz÷ÖþxEq1,À¨QÈÎÆ¨QèÕKËí!¤F(ÁICyï=ü÷<=qý:ºtQ�“ÐЈðpcûv>LS{ˆž¢' ¨S'\»VÚó9k×¢¤¤¡ÛðóÏðóCd$ÜÜpáæÎmèRw(ÁIò°ÀáÃØ¾&&X½nnøßÿÐ0ÈŒ‰Áo`ôhäæbøp\¿Ž®]⼄ÔJp¢ sçâÒ%´iƒÇ�1núôAdd=žN,ÆüùèØÿ �Û¶áèQXYÕã i”àDK:wÆÃ‡Ø»-ZàÒ%ôè�É“‘œ\Çg‘J//lßóæ!) óæÕñYÑJp¢=xï=Ü¿�+`b‚ýûѦ ¦NÅ�upð¬,„…¡}{,X€ÌL „[·°m-ò@Jp¢mB!֯ǽ{5 r9öîE—.èÔ Ÿ|‚³gQ\\�C1†»w±cÆ�ƒ­-/F|<¼½qü8þú‹Ì$�ÝDEtƒ‹ Ft4¾ûàÖ­Ò•Wx¾ªGppÀ A4£FÁظ>ÛJˆöQ‚ÝÃã!(AA ‘àÉ“2m®�ŸGÇ2½r“¶[OHá'ºM(DÛ¶hKkR¢]É$„}E NÑ9r¹\ÛMДà¤&ÒÓÓ/^üôéSm7„4NsæÌ ËÏÏ×vCt]µÿüó¼¼¼Ú0""bذaÓ§OOKKËÉÉ ;}út]µ¶ÎU=Íj>ŠÂçóÇŒ‹}êððp''§Y³f‰Åâ‘#GZZZÚÙÙ-Z´H&“‹ÅAAAB¡ÐÛÛ[ñ½S팫–³³³'Mšdmmmee5qâDnc~~þ¬Y³ìì쬭­§M›VXX¨vÞ¿RÎÎÎï½÷€ÂÂÂððpww÷E‹¥¦¦j»]¤‘øä“Ox<€´´´?üÐÍÍmË–-5Îñ%K–lÞ¼yôèÑÆÆÆ}úôùþûï”+EªØÙÙµiÓæ¿ÿþSd×®]ÎÎÎfffÍ›7 Ó_\aëÖ­®®®W¯^ýüóÏœ��/_¾ÌU.e(—¢U|_5Op™Löã�?úøø(Ú””””””´sçÎiÓ¦™™™¥¦¦ÆÄÄ\ºtiÆ fΜimm-‰.\¸ðÒ¿_fΜ)•J?~œ‘‘1÷ÅœçÍ›—ŸŸŸ˜˜øäɱX¢vÞ¿R3Ë—/722âÊ_~ù¥»»û|�––¦Ý†‘FÀßßÿí·ßV|™žž¾dÉWW×Í›7K$’j*77÷êÕ«#GŽ,ÿ’ư*((ÈÎÎNKK›2eÊÒ¥K¹šb±xþüù¿þúk~~~llì€*:]AAANNNjjêôéÓßyç�¼¼¼ÔÔÔ3f,[¶Œ« 1ÊPÃ4c0`¬ÊâããXZZZZZöîÝûÎ�;ÜF�—••ÅËÍÍåóùiii\ý“'Oz{{K$>ŸŸššªØ(¸¹‚jY"‘**sòóó���E"÷edd¤»»»êy«n0 †Ÿ3NMM-**bŒeee‰D¢ââbÆXNNNff¦T*åZ’��-“ɸH$’’’ÆXaaaAAW......–ËåŒ1™LÆUn:¦OŸ^þ3efföá‡*>ÌÆ†ìùs­¶´Ro¾Éö×_Ún)#**Šë†«±··ß¸qcnn.clút°o¿­ì8‰‰‰&&&å·k +.UòòòcwïÞµ¶¶æ^ÍÉÉ155=xð D"á¶hŒ/ÕÝ£££UeccÃ*ˆ2V6E+wô(؈Œ1VÃq𬬬¬¬¬ .tèÐAñŸÖÒÒ@FF†‘‘‘·þ7àââ’––&‰ŒŒŒ+9¾H$244TT椧§{xxXYYYYY 0 ;;[õ¼Õµiü¦æÍ›Ÿ;wÀèÑ£ííí#"" >ÜÆÆæüùó† biiyñâE …ÜßA¯¾új³fÍ®^½  wïÞÆÆÆ×¯_Э[7CCÛ7oèÔ©�Çã®ôvìØÑÐÐðÞ½{üüüLLLîß¿À×××ÌÌìáÇ\ÙÜÜ<)) @‡¬¬¬’““´oßÞÖÖ–�hß¾½ƒƒƒH$âÊ-Z´xþü9WnÕªUNN€víÚµiÓ†ûc³]»vnnnÜßhíÚµóôô”J¥\ÙÇLJ»a«]»víÛ· —Ë}}}ýýýÈd²N�:uëÖ @QQQ—.]úôé    àÕW_ ‘Hzôè§è†+äççöÙgnnnK—.åZ«VìÝ;hР7nX²dÉ믿`ñâÅýû÷¿}û6€ààà~ýúݽ{Àœ9s^y啘˜3gÎìÓ§7¨8uêÔ^½zq?âI“&õèÑ#!!Àرc»uëÆý¸G�ÕµkWîÇ=|øðÎ�;?yòÀСC;vìÈýèßxã ___îGÿÚk¯µoß>==À+¯¼Ò¶m[±X  W¯^ÞÞÞÜÇ ÀÓÓ“ûtêÔÉÝÝ�û´oßÞÕÕµ  €———³³37ÌêêêÚªU«’’­ZµjÙ²%ÆX‹-œœœH¥R‡V­Z(,,´³³kݺ5€¼¼<ggg999VVVmÚ´ðüùs îwFF†P(tuu�ššjffæææ 99ÙÔÔÔÃÃÀãÇ����===<|ø�Ïç{yy¸ÿ>�Çóññ騱£Æ®®H$Z¶l™‹‹Ë† ¤Ò—÷ÇmllŠ‹‹sssÕ¶k +ffffffLLLCÒæææG�ýþûï�œœúöí{åÊ•ŠN§ØÝØØXõPEEE¨8ÊP£4«û9™vvvÅÅÅéééÜ÷%))ÉÑÑÑÞÞ^*•ªnä*s½`�Ç}:ØÛÛËd2EeÅaMLLž={Ö¬Y3ÅFî?Fۘ͘·hÑÂÄÄ€•••ƒƒƒ±±1 [[[.•„B¡••W633377çóùLMMÍÌ̸²±±±‰‰‰��CCCCCC®Ì{@IIIÉ‹åĤR©â3Áõåcòòò¸ßírss³³³¹rvvvff&W‹Åܯnééé\ùÙ³gÏŸ?çÊÉÉÉ999\9)))??Ÿ+?|ø°èÅ"ññññÜÅ \èຠ†††ärù­[·LMM¹ò�7™LvíÚ5 ®|åÊkkk�Ã&yyyÛ¶m344\ÿ²ŸÅ¿ÿþ»zõꨨ(CCþ}ûnÙ²…ûÞÀn$$üsýú‡~àÆ�gΜÉÌÌpóæÍÿý—Kɨ¨¨óçÏsÿånݺuéÒ%.1oݺÉeÄíÛ·¯_¿Î¥ç�;w¢¢¢¸»)¢££ïܹÃ%ittô½{÷¸rLLÌýû÷¹ŸNll샸OH\\\bb"W¾ÿþÓ§O¹_À Ïž=ã~‚]>ÌÌÌäʉ‰‰ÙÙÙ\ùñãÇŠ�ÖÓ§O¹äädîoMÏž=SÜ‚�ššÊ}¶y<žH$2~ñx±X¬øß÷üùsÅG(;;[ÑSÎÍÍåê3Æòòò¸� €‚‚Åǯ¨¨ˆ{SŒ1©Tª8Ž\.çÚ ú‡U¼~S³fÍ,-- Ô;å™››üòË/S¦LQÝ®1¬*9Λo¾ùæ›oJ¥Ò­[·Ž?þìÙ³åãë¥4FY-T%Ó§ZµIDATEñ‡CEƒ‚‚&OžœŸŸŸžžÞ£G���ÆØÛo¿­ØØ§O®¾L&³´´­—ŸDEÞ|“×·o?uê”X,fŒ)œ1vóæÍsçÎq¿#£¢¢"""¸ß¯\šs¿/¹4çþ®¿}ûöåË—¹Ð¼sçNdd¤âïèk×®q¿S£££oܸÁ…é½{÷¢¢¢ c±±±·oßær!..îîÝ»ÜàÞýû÷cbb¸ÀMHHˆ‹‹ãÊ<à~³?bî#‘˜˜øèÑ#®üøñ㤤$îGÿäÉÅÇ#99999™û<{öìÙ³g\9---==�+‹D"®£ —ËÅb1÷M�ËåÏŸ?ç¾ r¹<;;›{ãr¹\"‘poV.—çççsoP.—roJ.—s�gŒÉd2Å ®Uª*EqrrÚ¾};÷«Ê( cìßÿµ³³;|øpQQQIIÉùóç'NœÈ4…•ƱÆXJJʉ'¸ÿ°»wïöððÐ_í®Z.e¬‚hÕHu¥^<==}øðáæææ666óçÏç>‚éééƒÞÞÞ;wîTÔÿþûï­­­���·nÝªØøüùó±cÇr£í“&Mâ6æååÍ›7ÏÁÁA(zyymÛ¶M_¼±***âþ|Veaa±råJî¿}©J< à›o¾QÝ2gΜ÷ß¿¢O^^ÞÌ™3mmm­¬¬¦N�ÊeDµ*k@ãà:é�wÞQûtµlÙ2<<\õçXÅgŒ]¼xqÀ€–––� k×®dšÂª¢ÏÒ“'OzõêennnffÖ¥K—‹/2MñU•/e¬Á¼ ¯+»víRýßeiiùñÇs}Ø2*Npîp®7§áééYѧÊ”)&LÈÍÍÍÍÍ6lØÒ¥KYÅÿU4VÖ€\÷ܺuKµÞ²eË­[·–ÿ\õo4TœžMHj¨¨¨(44”+[YY-X°`Á‚ÖÖÖÕ:Hff¦‰‰ 7°® ¸Z[^AAÁ¡C‡’““¹{oW®\9vìØ�7Ö¾2Ñ5kÖ¬aŒhÑ¢ÅÒ¥KgΜYGÇ� %8©¡={ö<~üØÚÚzáÂ…ÁÁÁV5Zú�»I ''G5ÄÓÓÓ+úM ¸ŽÏ}É3®x‡jU&:åÎ�;¿þúkóæÍ—,Y2{ölÊîŠP‚“š(**Úµkך5k‚ƒƒkv7'ÇÂÂ" àðáê÷•ÿôÓOýû÷×xŸRE×ñ«U™è¾Ý»woÙ²eöìÙÜ­x¤"ôlBRb±øêÕ«üqm⛳iÓ¦eË–=z´¤¤¤  `ëÖ­?üðòeËœœœÁo¿ýVTTÎU£G�^´hw?_JJÊÙ³gT«2Ñ}[·n]¼x1Å÷KQ‚“šhÙ²e]�HôíÛ÷èÑ£[·nå·qãÆÿý×ÃÃÏ燇‡O›6ÍËË«W¯^Šú»ví222òòò277õÕW¹ 5ÕªLt7©‚TÝ‹Bê[•gÕß¹sÇÚÚzÿþý Ш2è^½ÕÄïE¡_tD‡tèÐáäÉ“OŸ>UÌß#„T‚®dÝÒ½{÷îÝ»k»„èêƒBˆ¾¢'„}E N!úŠœBô%8!„è+JpBÑW”à„¢¯(Á !D_Q‚Bˆ¾¢'„}E N!úŠœ4”?Dq±¶¡ÉÉ“¸xQÛ� ¤&(ÁIýûì3˜˜à»ïл7=ÒvkTcÑ" ‚œ  •‹¢(ÁIý›2—.ÁÝ×®¡sgüú«¶HJÂ+¯àË/ad„ðpüñÌ͵Ý&Bª‡œ4ˆÎ�qý:FŒ@VFŒÀ¢EZQùãtîŒ+WàêŠ 0¾6CHMQ‚“†bi‰_~ÁÖ­02—_â•W�”¤…fH¥X²Æ!3Æáúuh¡„ÔCrÈ=á©í–4œ¤h» MXp0zöĘ1¸r�;#43f ÁEŒ�Å„ ¸~FFظ‹�Çk S“ú´y3öï×v#JF†²\ºFO´ÓÒàæMŒ�?ÿÄìÙøê+„…¡ÿú=ir2V¬À�` ­[ãèQtíZ¿g$ èþ}Ü¿¯íFhï{ í6hGs47ƒ™¶[Ñ´=Š%Kðà¼ý6¶l�‡GÝŸ¥ ŸŽ�‘—SS,^ŒåË!Öý‰ˆ6$$ 5UÛ�Ð;;øø€ÇÓvKHVT„/¿Dh(rr`d„… ñÑG°·¯›ƒ3†_~Ap0RSÁãaäHlÞ —º98!:€œè€´4¬\‰½{!—ÃÈAA˜9Ö|�úöm8€ï¿‡H]º , ��uØdBt%8ÑOŸâã�±?är06FŸ>èÛ^^pr‚�ìíak«ë¹¹‰�‘‘))8{ý…¬¬ÒWmm±d >úˆ®X’F‰œè±{÷âÈ\¾¬áU¯4Ê…B¤¤ %¥4îÕ´h�áÃñÞ{t§ iÜ(Á‰®ÊËéS8s))Ê^¶X µO¬¹9ìíKc½yst놾}áí­¥FÒ (Á‰^a¬4Ê%´l‰–-î^rBtÏÿª«S�ÿ#VæIEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/syslog_parsing.rst0000644000000000000000000000013215171370365022744 xustar0030 mtime=1776677109.301910921 30 atime=1787067672.752457855 30 ctime=1787067793.885715569 rsyslog-8.2608.0/doc/source/whitepapers/syslog_parsing.rst0000664000175000017500000003434715171370365022423 0ustar00rgerrgersyslog parsing in rsyslog ========================= *Written by* `Rainer Gerhards `_, `Großrinderfeld `_ *(2008-09-23)* **We regularly receive messages asking why** `rsyslog `_ **parses this or that message incorrectly.** Of course, it turns out that rsyslog does the right thing, but the message sender does not. And also of course, this is not even of the slightest help to the end user experiencing the problem ;). So I thought I write this paper. It describes the problem source and shows potential solutions (aha!). Syslog Standardization ---------------------- The syslog protocol has not been standardized until relatively recently. The first document "smelling" a bit like a standard is :rfc:`3164`, which dates back to August 2001. The problem is that this document is no real standard. It has assigned "informational" status by the `IETF `_ which means it provides some hopefully useful information but does not demand anything. It is impossible to "comply" to an informational document. This, of course, doesn't stop marketing guys from telling they comply to RFC3164 and it also does not stop some techs to tell you "this and that does not comply to RFC3164, so it is 's fault". Then, there is :rfc:`3195`, which is a real standard. In it's section 3 it makes (a somewhat questionable) reference to (informational) RFC 3164 which may be interpreted in a way that RFC3195 standardizes the format laid out in RFC 3164 by virtue of referencing them. So RFC3195 seems to extend its standardization domain to the concepts laid out in RFC 3164 (which is why I tend to find that reference questionable). In that sense, RFC3195 standardizes the format informationally described in RFC3164, Section 4. But it demands it only for the scope of RFC3195, which is syslog over BEEP - and NOT syslog over UDP. So one may argue whether or not the RFC3164 format could be considered a standard for any non-BEEP (including UDP) syslog, too. In the strict view I tend to have, it does not. Referring to the RFC3195 context usually does not help, because there are virtually no RFC3195 implementations available (at this time, I would consider this RFC a failure). Now let's for a short moment assume that RFC3195 would somehow be able to demand RFC3164 format for non-BEEP syslog. So we could use RFC3164 format as a standard. But does that really help? Let's cite RFC 3164, right at the beginning of section 4 (actually, this is the first sentence): :: The payload of any IP packet that has a UDP destination port of 514 MUST be treated as a syslog message. Think a bit about it: this means that whatever is send to port 514 must be considered a valid syslog message. No format at all is demanded. So if "this is junk" is sent to UDP port 514 - voila, we have a valid message (interestingly, it is no longer a syslog message if it is sent to port 515 ;)). You may now argue that I am overdoing. So let's cite RFC 3164, Section 5.4, Example 2: Example 2 Use the BFG! While this is a valid message, it has extraordinarily little useful information. As you can see, RFC3164 explicitly states that no format at all is required. Now a side-note is due: all of this does not mean that the RFC3164 authors did not know what they were doing. No, right the contrary is true: RFC3164 mission is to describe what has been seen in practice as syslog messages and the conclusion is quite right that there is no common understanding on the message format. This is also the reason why RFC3164 is an informational document: it provides useful information, but does not precisely specify anything. After all of this bashing, I now have to admit that RFC3164 has some format recommendations laid out in section 4. The format described has quite some value in it and implementers recently try to follow it. This format is usually meant when someone tells you that a software is "RFC3164 compliant" or expects "RFC3164 compliant messages". I also have to admit that rsyslog also uses this format and, in the sense outlined here, expects messages received to be "RFC3164 compliant" (knowingly that such a beast does not exist - I am simply lying here ;)). Please note that there is some relief of the situation in reach. There is a new normative syslog RFC series upcoming, and it specifies a standard message format. At the time of this writing, the main documents are sitting in the RFC editor queue waiting for a transport mapping to be completed. I personally expect them to be assigned RFC numbers in 2009. Update: the numbers are now assigned and the base RFC is :rfc:`5424`. Practical Format Requirements ----------------------------- From a practical point of view, the message format expected (and generated by default in legacy mode) is: :: TIMESTAMP SP HOST SP TAG MSG(Freetext) SP is the ASCII "space" character and the definition of the rest of the fields can be taken from RFC3164. Please note that there also is a lot of confusion on what syntax and semantics the TAG actually has. This format is called "legacy syslog" because it is not well specified (as you know by now) and has been "inherited from the real world". Rsyslog offers two parsers: one for the upcoming RFC series and one for legacy format. We concentrate on the later. That parser applies some logic to detect missing hostnames, is able to handle various ways the TIMESTAMP is typically malformed. In short it applies a lot of guesswork in trying to figure out what a message really means. I am sure the guessing algorithm can be improved, and I am always trying that when I see new malformed messages (and there is an ample set of them...). However, this finds its limits where it is not possible to differentiate between two entities which could be either. For example, look at this message: :: <144>Tue Sep 23 11:40:01 taghost sample message Does it contain a hostname? Maybe. The value "taghost" is a valid hostname. Of course, it is also a valid tag. If it is a hostname, the tag's value is "sample" and the msg value is "message". Or is the hostname missing, the tag is "taghost" and msg is "sample message"? As a human, I tend to say the later interpretation is correct. But that's hard to tell the message parser (and, no, I do not intend to apply artificial intelligence just to guess what the hostname value is...). One approach is to configure the parser so that it never expects hostnames. This becomes problematic if you receive messages from multiple devices. Over time, I may implement parser conditionals, but this is not yet available and I am not really sure if it is needed complexity... Things like this, happen. Even more scary formats happen in practice. Even from mainstream vendors. For example, I was just asked about this message (which, btw, finally made me write this article here): :: "<130> [ERROR] iapp_socket_task.c 399: iappSocketTask: iappRecvPkt returned error" If you compare it with the format RFC3164 "suggests", you'll quickly notice that the message is "a bit" malformed. Actually, even my human intelligence is not sufficient to guess if there is a TAG or not (is "[ERROR]" a tag or part of the message). I may not be the smartest guy, but don't expect me to program a parser that is smarter than me. To the best of my knowledge, these vendor's device's syslog format can be configured, so it would probably be a good idea to include a (sufficiently well-formed) timestamp, the sending hostname and (maybe?) a tag to make this message well parsable. I will also once again take this sample and see if we can apply some guesswork. For example, "[" can not be part of a well-formed TIMESTAMP, so logic can conclude there is not TIMESTAMP. Also, "[" can not be used inside a valid hostname, so logic can conclude that the message contains no hostname. Even if I implement this logic (which I will probably do), this is a partial solution: it is impossible to guess if there is a tag or not (honestly!). And, even worse, it is a solution only for those set of messages that can be handled by the logic described. Now consider this hypothetical message: :: "<130> [ERROR] host.example.net 2008-09-23 11-40-22 PST iapp_socket_task.c 399: iappSocketTask: iappRecvPkt returned error" Obviously, it requires additional guesswork. If we iterate over all the cases, we can very quickly see that it is impossible to guess everything correct. In the example above we can not even surely tell if PST should be a timezone or some other message property. A potential solution is to generate a parser-table based parser, but this requires considerable effort and also has quite some runtime overhead. I try to avoid this for now (but I may do it, especially if someone sponsors this work ;)). Side-note: if you want to be a bit scared about potential formats, you may want to have a look at my paper "`On the Nature of Syslog Data `_\ ". Work-Around ----------- **The number one work-around is to configure your devices so that they emit (sufficiently) well-formed messages.** You should by now know what these look like. If that cure is not available, there are some things you can do in rsyslog to handle the situation. First of all, be sure to read about :doc:`rsyslog.conf format <../configuration/basic_structure>` and the :doc:`property replacer <../configuration/property_replacer>` specifically. You need to understand that everything is configured in rsyslog. And that the message is parsed into properties. There are also properties available which do not stem back directly to parsing. Most importantly, %fromhost% property holds the name of the system rsyslog received the message from. In non-relay cases, this can be used instead of hostname. In relay cases, there is no cure other than to either fix the original sender or at least one of the relays in front of the rsyslog instance in question. Similarly, you can use %timegenerated% instead of %timereported%. Timegenerated is the time the message hit rsyslog for the first time. For non-relayed, locally connected peers, Timegenerated should be a very close approximation of the actual time a message was formed at the sender (depending, of course, on potential internal queueing inside the sender). Also, you may use the %rawmsg% property together with the several extraction modes the property replacer supports. Rawmsg contains the message as it is received from the remote peer. In a sense, you can implement a post-parser with this method. To use these properties, you need to define your own templates and assign them. Details can be found in the above-quoted documentation. Just let's do a quick example. Let's say you have the horrible message shown above and can not fix the sending device for some good reason. In rsyslog.conf, you used to say: :: *.* /var/log/somefile Of course, things do not work out well with that ill-formed message. So you decide to dump the rawmsg to the file and pull the remote host and time of message generation from rsyslog's internal properties (which, btw, is clever, because otherwise there is no indication of these two properties...). So you need to define a template for that and make sure the template is used with your file logging action. This is how it may look: :: $template, MalformedMsgFormater,"%timegenerated% %fromhost% %rawmsg:::drop-last-lf%\n" *.* /var/log/somefile;MalformedMsgFormatter This will make your log much nicer, but not look perfect. Experiment a bit with the available properties and replacer extraction options to fine-tune it to your needs. The Ultimate Solution... ------------------------ Is available with rsyslog 5.3.4 and above. Here, we can define so-called custom parsers. These are plugin modules, written in C and adapted to a specific message format need. The big plus of custom parsers is that they offer excellent performance and unlimited possibilities - far better than any work-around could do. Custom parsers can be :doc:`bound to specific rule sets ` (and thus listening) ports with relative ease. The only con is that they must be written. However, if you are lucky, a parser for your device may already exist. If not, you can opt to write it yourself, what is not too hard if you know some C. Alternatively, Adiscon can program one for you as part of the `rsyslog professional services offering `_. In any case, you should seriously consider custom parsers as an alternative if you can not reconfigure your device to send decent message format. Wrap-Up ------- Syslog message format is not sufficiently standardized. There exists a weak "standard" format, which is used by a good number of implementations. However, there exist many others, including mainstream vendor implementations, which have a (sometimes horribly) different format. Rsyslog tries to deal with anomalies but can not guess right in all instances. If possible, the sender should be configured to submit well-formed messages. If that is not possible, you can work around these issues with rsyslog's property replacer and template system. Or you can use a suitable message parser or write one for your needs. I hope this is a useful guide. You may also have a look at the :doc:`rsyslog troubleshooting guide ` for further help and places where to ask questions. .. _concept-model-whitepapers-syslog_parsing: Conceptual model ---------------- - Legacy syslog message format is underspecified; parsers must tolerate malformed inputs and often rely on heuristics. - RFC3164 provides only informational guidance, so vendors emit divergent formats that can blur hostname, tag, and message boundaries. - Parser ambiguity arises when tokens can represent multiple fields; without clear delimiters, deterministic recovery is impossible. - rsyslog exposes internal properties (e.g., fromhost, timegenerated, rawmsg) to rebuild structured output when parsing fails. - Custom C parsers can be bound per ruleset to normalize proprietary formats efficiently, avoiding heavy regex-based workarounds. - The safest path is to configure senders to emit well-formed messages, reducing guesswork and preserving semantic fidelity. rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue_rsyslog2.png0000644000000000000000000000013215132411300024155 xustar0030 mtime=1768559296.227885023 30 atime=1787067730.726538496 30 ctime=1787067793.871715309 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue_rsyslog2.png0000666000175000017500000003007615132411300023631 0ustar00rgerrger‰PNG  IHDR¬‘ŒÃåsBITÛáOà pHYsêe¤ IDATxœí�y|MÇÿÿŸ7»ÄNľ´µ+JJQŠ.TQÔR>­òAµ¥Õ�6EjK• ÔRµt±´µ´”úص>%Uj_b�$„”D‰¬w~œþò��äÞÜsï™›Ìó‘‡ÇuîÜ÷¼ÎÌœó:3gΓ; …Bd}°ößÿÐIóU²‹B¾JvQÈ׉d?ú裧OŸæÜNž<Ù¶m[ÝU* Ã1™LÖþ[€ŸÈðsk;£l{ä[¹r凶7ŸgžyÆIwOÉ. ù*Ùþ¹BQ0Lê_¡P(Ùq±w'99‰Ie?¶’Iæw|w�{F ± 3æ}ì3Z…B¡È ;à Nô¦wš4¢‘ Õ±-8)¤,fq=êmg{1Š-§€d’¹ŠU�òh:éFkQ(ya—¡¤œ˜Â”�lˆÇxì$']ìß5)”Ä¿˜Ås™CŒç9_�êF‹²3æïøn SÂkC›0Z‘B¡È 7}Ã�ää¦l`CÖØQAÊ ÀMnÎcÞB&’¨mÉH§s3æu¬›Ìä0´-“™l¬$…B‘/ºõ²,Ð\Á—GxDu,!û=˜+\™Íì¬H%Õ„I L˜¼ñ¾Â•ò”7P¤U˜1o`Ãd&Ÿå¬ .fÌ&L-iù-Má8"û߃[rÛhUbÁÚ£U‚yTœÆpžóñÑ6˜1çøª4¥½ðÊj"Ù›‹ã?. �ÏY<Â#ç9ÿ`I6¢Qg:W¤b*T Â³<+�Ý ABÉÉÂ»ØÆR»'3ù4§5KÈJ2œáõ©�ÑG…ý"8�`{GpDÃSXÏ5®U¡J t0†xâ?ã³9̉'^»ÂÍúêQ­A�ÿË,Û-h§øìàL3È0cÞÊÖ8âr”dŽÿºãþO´¥m/ð‚#îígfrè×®qíׯÿ߇»wIJ"9™ôn) ÔrÜÚL2í.ɘ0eýåøoÞÛ-ßh¿Ä*‚Š`a„ºÔuËó>‚nCIÚƒ .¨p™ËÎ;‘Æ≟Íì9ÌI&YÛâ‚K-jàÀmnGy–³ÿã»ÙK,P�jÃö:¯ç} `5áá9Âñãœ8Áñã\½Jö¦b2áïOõêx{ÿß_ñâx{óÜs—Ÿ¬<ƒ_óuÙCN`Â~Tä±QÏT(œ�g%Å?Ÿù!„įm™Ç¼·y[Ç,Š7¹9�éKX’5¹ó~x™—³§¹Ìå�ìœÆ´(¢L˜úÓÿ3>³é>DRûöñßÿ²};.ü³ÑË‹æÍiܘÆ�ñ÷§Jüü¨PS>§Ñpƒ ^Éʬ]¨D¥+\É]T(’"ì@¼ˆŸ*¦–¥T•’E²=r) \—‹Á.ÂA3Ñì¡i̼[ìî%z!ðÞÓÄ´‘b]6iiâÛoEÏžÂÅE€Ñ°¡ 6ˆ „ÙlË.„‹ð‹» wæ‰y¶DS(À.Æ ¡ÙCQF� lä¤8ÙCô@°]lÏ#Y¨}\<ŽÀWø†ŠP‹BŸ=+ÆŽeË %KŠ—_Ë–‰èh}tg#BDŒ£<„GeQY]((’c÷µ’’Hú–oG0B àÚÈìdgÞϘ1/eé&¤’ºŒe˜kÒsç7ŽmÛZµbøpú÷§xq½UßGQ3™ù��d¤]3R(¶ Ñ+„„Ö�î¹øLejΉ­áá²v-&¯¾ÊĉԪåHyÉ${ãíÈ …U(c(œÄÛ—¾»Ù=€«XõOw-3“™3 "#ƒþý™1ƒ5 ªP(äCç%1’P†2;ÙÙ�~kXS“šÓ˜FX}ûrâíÚBË–FkT(’"ÙÓ³úѵk×Ö­[3f̨Zµêßÿ½oß¾ÚµkoÛ¶-99¹AƒÁÁÁÀ€Ì›7¯mÛ¶IIIû÷ïïÔ©Shhh||üóÏ?¿råJà­·Þ –/_>hРŒŒŒÐÐÐaÆ�={6..nôèÑ¿üò 0mÚ´%K–ëׯŸ#„8yòäùóç…aaaBDFFîÚµ+!!!>>~ëÖ­—/_ÖGbF†4(º¥îºù™«ÄŠX}Â*ŒãÌ™3ÀÌ™3…åË—þùç…½{÷öññBÌŸ?8vìØÉ“'ýüüV®\)„ BLžýôÓ×^{M±sçÎáÇGDDDEE�?þ÷ßBÌœ9ó§Ÿ~BlÞ¼Yûá©S§Ö®]›��`ØnÛõ9…ÁddˆAƒˆÁƒ7f®GðŠxÅhM [ÑÏž=+„X±b…vNY³fÍĉ…Û·oâ£tÒæçºÔý…_¼ðZÄ¢?ù¨Mí&4iHçyº! Ÿà  ÍZÑ (KÙºÔõÄÓ|Üq7c¾Ç=í”EÔE.—¹¼›Ýd\çújVG‘Jê"íg?ð_-g9°•­òaiŽÛù={˜2…¶mYµ —ªØïéL¿ÆµùÌwœ…Bá„¶¡¤“œœËܬXÂ’‘ŒÜÅ®f4 !d ã±xâKQÊ®îqÏ„É ¯;ÜI'½<åos;–ØÚÔvЫunÜ Y3228z”ªU³“IfSš^ãÚ%.Îѳ"I9–W(l¤�ÃMn®fõ8Æ}ÌÇóñÎøâ{‘‹­i튫ÑêKÇŽüö[·Ò­Ûƒ_nfó‹¼øþó Ÿ8^š¢ÜàFa—¸¤ýE•@BII$%“\ŒbfÌ·¸••þÁ·M”§|Qî‚ór‚W¹zžóYn¸Ýå®ýrÏø L°_| qzcˆ#Îß×xí+¾ºÄ¥â/A‰¢»Ïš5 Èøñ|úinIšÓü—®q-ï—¾* äö±Oû»Îõ¬í&Lõ©_œâY¨à‰g"‰}¿¦öW‚KXbàî8a„ýÆoÚ_YÛ«Rµ>õÝq÷ÀÃ~¹÷£ßØ/¾…8·1¬d囼yžóIdÚ­ÈPîÝã‘GÈÈ ,Œ¹žôײv³øßüÛ‘êùr•«_ðÅ*VE ¸àÒšÖmi[—ºu¨S›ÚU©ª‹ìÄ9έbÕjV‡¸âÚ‚OñÔc<Ö”¦ i˜÷»0 N¹«dLfrAu©Û….fÌþøW¥jþ¿,ÜÌ�KD+Väá @ozW¤¢2yˆõ¬_ÈÂßøM Òpƒ:Ðá)žRo»³7é¤É—ËYþ¾øŽg|g:·§½6�½ˆbèSä[ñ-‚…b¡ÑBd":ZøøˆfÍDff¾iE ‚ýB=k0fa^+ÖÖµ”%‡‹áˆ?ŒUT¸#îhoÓ^4ùŽxçOñ§Ñ¢dÁ™Œ!CdLÓ?›…y®˜k6½r²°ñþûÄîÝ–¤�Ñ®Âu¨joQŠ<Ø/ö7͵7î­+2D†ÑŠŠ "#D„Å<"Ù$6­H:rÞc8uêÔêÕ«Mù½ç=‹Ò¥K¿ÿþûVõQ‚ƒƒïÞµâ¶þàÁƒyäà&7Ѩ m6±)�ô{÷îݽ{wÞ1³ï`ݺu_}õUËõ$''kKh刓cÇŽõõµbzèºuëN�:eyú¶-Z<óÚkT«Æ‘#–¤¿zõj{ÚÇTˆyoö{.™yM¢ÕvÐÍÍM[\Ör–,YróæÍqò {÷îÍš5³<þ‘#G´m-¤råÊÆ ³<=0}útañ8“É4tèP???K§‘ö>ïÏg¾{ºû“¡O¶ mç‘æ‘'·_5lذG�ênß¾½téRËÓãÆ�óô´büdíÚµÚ*~Ò¡CmÍc 9þü�?þøÐ¯ZP>>>#GæórÀøÿ:Ïù¦4�ÈÄèEÑÉIV¬cúÒK/Õ©SÇòôüý÷ß-O_³fÍÞ½{[ž>%%eáÂ…y$x° ^{íµÒ¥Kç7‡Q¬_¿ÞrM@µjÕ¬õ¢Š+Z•ÅæÍ›cEì›âÍL‘yE\É·£0eÊ«âkëaYέ[·òz?—.]²*‹~ýúYM·nIJeÆÿí·ßxt¶(¾———Uú…�5²j–/_nU|myZËiÞ¼¹µ»àêjÝDçƒZö’¸ÔR´DPáj*[ðàÁVé?wîœUú�øøx«²èÔ©“Uñƒƒƒ­Š¿aëâûûûç-Y$�ã\„‹�ðY)VjµuO-G[~Êr¦N�jUü®]»ZÿöíÛVÅ.^¼˜oØœ=†””mý^ qqq©P¡‚U²nÞ¼™÷âÀ9$•)Sf¦×Ì�ùøþhIþ/HLLLLL|h¨‡âååU¶lÙ|“ea6›¯_¿žºlTªTÉÍÍŠûü·oß¶d5ö¬½óëÝÛõÒ%¢¢ð¶hžnjjêÑÛGª ¼;pzìtò+(“ÉT­Z5K"gqýúõ´4+ö.W®\‰<ï™ç 11Ñr‡BxzzZx9ŸÅåË—*·ô~~~^^ùÜ+ÞÉÎôÈ$s:Ó‡Þ'Þr=>>>V]T¥¥¥Yu9Ô®]ÛÅÅŠÇ0£¢¢rk¨-¨òåË—)SÆòø‰‰‰V­>íææ–Ûåüu®w¡ËiNw¡Ë—|Y�Úó… 222,Ï¢jÕª>>>–§¿uëVLLL rT‰%ªW¯nyüÌÌLí À’s�F½zõ´—ä�ìÓUà /A‰2”ÙÅ®.t1ZŽ”?NÓ¦ŒËœ9Vý®­¢ˆŠ"ÊA�dy¶°¥}ÊRv;ÛÒÐh9Eˆœxžç¯sý3>{õJ’ü‘úŒ íi_›Ú™d*WÈ•U«F�²öwÝéMôiNë/Iñ[ÙÚ‡>¨ð¿)Wp$¿òk[ÚÞáÎf6+W°yŸcÈ$Ó×Íl>ÃwÜ�–#1[¶P¿>ÖÜÓhMkà‡aÝý…µüʯ=éY™Ê{Ù[›ÚFË)B„ú,Ï–¢ÔÏüÜ‚FËqäí1ô¢×$&5¡É+¼b´‰¹x‘sçxþùü´%-M˜qHwQŠìDÙ›Þå(÷'*Wp$—¸ÔƒžxîcŸr«�´Ç�HbQEwÉ#ËÙ²à… ðÓÒ”®O}e v%�ôþô¿Ã�]쪈uóñ¶p›ÛÏó|<ñÛÙ^ŸúFËq2dì1\áŠ;îG8ò5_­Ez¶l¡tiÚ¶-د[Ñê§’±b·Â* <À� ‚:ÐÁh-E‹þô?Ïùå,ױ䓓 Áš§°œéŒA zÓ»2•3Ȱë*†…�´4öï§KÜ x¦­2ÈÐV‰QèÎŽÌfvg:ȇFk)Z|Í×»Øõ&ob�Ža½½‰Œ¤zu¦O'!AÇÀÒ!�1˜0…2•©Ej-Ãräii<ùd�ho¬S£Iö@ Æ0Æ ¯å,W‚I4Ñc[‹ZÁëü?ÿ!9™�>*äö W{�#.˜àö´W³Ê,âða€¿«Ö„&žx*c°?ðÃAŽc\Ö³T Ç0ŠQw¸³ŒeÅ)®{ðÊ•1àÎ�ìaÚ´Bhr=à6žñ³™}˜Ã�ó¸ÑZœ�!CX³†øx x~(­iCÌeò”¯¢À¤�ò(�¦�ržó>Xñ ¬ÂFpàIžư/ùÒNYDGS³&©©&BPº4ï¾Ë[oQ²¤�òt4ù÷ßò×ÿ‚~hZ7š]ÓÃZ}óèÁ×seoØh €àÍ Ì.n�/·%ìá!o�ï²à¥ßôJ¨�wJ«6ÚÁ©++²ë²“o½ÑpÁþۆˣJZ:ª:ûY×Äf¿6}ù‚ÇMû©ŠŒ$û:…ÏòÇß¶�µk ¦}Äú>Ì}�Cr3�‡. ™Ûªš¹%.ÁÝ•aߺ ɪËÃfߘéÙ’.l¹vÔuWWÛU¸ÑpÙ7Þž¹Èåvù˜YCþN“HU¡�Òì`|«¾ß�¼wÞÿž=U=t±7³™ŒŒ‡åtäßcHN&=ýþߨ¡FM ~Þ¾ý2.KûÆÞyÞ|õáàAøüsF�¶%Ìÿø_;Ú-e鼡—´"ÎA0� ö¸ù©Èƒgyv/{/pÁûåró&5j�šŠÿôJ–dìXÞy‡|W³vòï1Ø0|mÅ)™DÒ-·[Þj.’…hkZ¿Füð®aÅ–мYÄ"W\G0Âh!E‹«\ÝÁŽ! ±«+³f‘’òÏç%;–±c �%hH1+)•ÔÁ ¾ÎuõÞf+¨YÓÆ0U¨b¤ŒA/’I^Ǻçx®5ŒÖR´XÅ*3æ¡ µk.7o²h€�“&qõ*\Ø\I–Ä8À�U¬êD§ZÔ2Z‹ópå ..X³tûCñij<壈ÒE”b+[SIí‡u¯ZRØÎ7|S“šíhg×\fÍÂÃñãyç¬y+£“!…1t¤c<ñj Uë¸r…Ê•±æEŒ¹á‡Ÿê1èŶ¸âÚ�nF )Z„zžó™hÂ~·õ¸w�²e¹z•R¥ì—‰?”EÔ4¦%’XŒbFkq*ÂÃmGÒPÆ fÌÛØÖ†6e±â�€ ÛÙÈF` íšK±b|ðAáwd0†ÿò߉L<Å)£…8™™DDP£†.Áüð‹%ö÷òOªÈ“?øãoþ~�‚,v«°…=ì©A µŠª^o ¯óúŸü©Öž´Ž„22°òmÛ¹¡ÝóW�ÛÙË^@�#9˜Xb�r´�ŒRx0ØÒI&¸µ<Ña¬¼‘”ºM%V3VõâG¼ñVoît0{ÙkÆü4O-¤ð`°1ìdg �ëYo¬ ç#9t651Évþâ¯&4qÅÕh!E‹=ì1aRÆ #ÏJz†g~áµdžÕhÆP\ŸÅ#U�Ans;œpuƒÁñáHmjW¢’ÑB ÷r°#+ ÏXyBס$m MqºD+²áМæF )Z˜1Ÿæ´¾Ó#�A zÒ³½ Ôà¬èÚcð H!%ß”Š<8ÉI )M�R´'ü.wÑÈh!… #‡’2É !Ä—Âûø ýеǠŒA"ˆj¢ÏÃ% Ñfº«ƒ¾i I$ý‹(À‰Ñõæ³'ž&L©¤ê­ÈADIJ–¦Ð­›#7ZGMƒ¾i ³˜Lð5®9Ý]#³ÙœiOúöí[¬XžÏ�ë:”dÂ䉧å=†›7o†„„è’µóòÔSO½ðÂ}÷™#‰´÷ºžŠ‰$¨MmäµcÇŽyóæÕ©SÇÃÃC< à¡Û-ùÖÞ?Ï‘à½÷ÞëÕ+×a|7mogÍš¥o &$$+VìçŸöñÉõ½†MiÚƒ©¨oÖy „hÞ¼yZZZ¹råò8/gddäý­½u>óÌ3ùƒ®CI€UưsçNÝŒÓqæÌ™ÆAD þþmINN~ç�w|}}[´ha�ÓŠ#^®\¹%K–<þøã?ýôS¾;Gœ7ÞŽyê÷ßß¶m›íqLÙÈñß±1Anߦ¦æ5Bàܹsçܹs¶ïmvnݺ•‡1ô¡Oúè›o¾;v¬D‰©©©®÷ãááájÜÜܬJ¿xñâŸ~úiÔ¨Q÷éÎÈÀ-[÷îÁ¡$³—‚O%ðÂËrc¸{÷.°}ûöæÍ‹è œ—^zéäɓٷ¤�r‹[Õ¨f”¤´´´/¿´×[ŽL½zõÒÒÒ,¼‹%¶ eòM¶dÉ’°°°¹sçÚ¬ŽãÇ�W­ZÕ–·íì�зoß¾}ûêwÚ´i'Ny¾®#˜Îô¼C]¹r¥X±b•*é0ܤUIŸ>}V®\i{4;ñÒK/ !rÃúõüõï¾KÅŠpÿPRJ _|ÁåË|öY�3µÊ\\\€’%K–+W®À9:59¶Ä+å°¢@ž|òI—ýû÷ë"IkÛ/¾øâˆ#l¿œ4öç®®®µk[:4K¬%XvìØ±wï^]ŒÁ××·L™ü­È©±×=­Öó6†Rþæï|C5kÖ¬S§N6lÐKXÞª çá {÷&0�Ï?gäHÆ�ÿg(ÉÕ•Ï?gÆ nÜàøq[2õÂËò›Ï–TnáæÁ:J$(A ˃$%%¹ØÐÉ{PP£F�gŸ}V¯˜NAqvÔ +ö½ùœ÷¹ã íšûCqVcpwç£�xí5æÌáóÏ©W Q#nÝèÕ‹FŸÇ½téÒ{÷î½ýöÛygjU�AÃut—»Xi úRd+%–XõìˆîØë·|›é®¼ÍÛñ—�䆳0x0µj¤¥qêÀíÛÚ˜81·h_}õÕ’%KòÍTƒU(c�„ 2H°äƒÂ* 3†k\›Ïü£µ“€Üpbcps#(è¾-B`2Ñ£Mm½bòÄ3‰$ËRôÎAÙQÆ qÄ „zHVw 3†6´‰#ÎÞo\z'6`ÀêÖÍ9û(÷î‚å4§¹å‹ ÍsPv¬#ÍV‹£Ï“% hVжÀ—ê1èŽaÆp“›ûØO¼�ä†sƒ«+AA˜ÍYIyî9·umZ3æ�ìÜÍîh¢-THÑ;eçÁ:Ò–ÚÎ$Ó EE´Rb‰Eƒ0Ìrð%^:Ìa; È ç6 _?ê×ÿ§Ó “&ÙžãOütšÓ÷¸L°… )zç ìø¬gýqr]•¯hžƒ²cI�!…”¼;^ºK¢èUŠºÇ`':”ô Ÿxãý#?v¥kg:¿È‹Ã>“™é¤ûá÷/äLga’<–(Ô¤²¥Çp˜Ã7¸±™Í¡„>Ã3šÇ”¡Ì f\åêd&Ïc^ )zç ì˜L&á*ö²W›Í¸ãîŽ{–1¬eí£õµ�Ž™ÃRè1æ9†Où´%L˜L˜êQÏ‘×Vò<›®še V‘½Ž±È÷ì6à†Û†«ªã�ÿ‡|DDP2É¡„Þàà°9,…cŒ¡2•?æc�к ޼¶’ÿà±ÐL˜lœ®š-”æ7ù¢Œ!{Õ§þû¼ŸÕcІF+RÑXU…›wy·6µ³/墕¿Ãæ°z {òy cã±bsðµ•ü�…CI:ºªÇ`%9êèC>¬IMí<%ùÞvvŒªBŒ'ž X�})ò›Ã¢° ÃŒÁ÷,x…W¼Àªü�…=}¯Œ”1XEŽ:*F±…,ÔÎSÕ©Þ™Î2¨*Ü<˳/òbÖ`C¾sXVa˜1OóôlfÛI@nÈðXh ªÇ` Öѳ<Û›ÞÀ¼áb·ÃÊZU…›¹ÌõÀCóÏa)ôi ñê%ù ‡’T�Á@ZGó˜ç‹ï¿ø—!’p†¶­/5©ù!jw<‡¥Ðc°18ù5”$?­£ªTÝÁǯ$Ÿ…üm[wÞçýÔ<‡¥Ð£ŒA:ÔP’üäVGŽUmväoÛºã…×|æ{ãmÈüàBŒ2é0d(I‹¦ŒÁBälErª²7Ýé¾�…Ž”.Ü(c�5”$?r¶"9U9€¡ 5ZBaCƒt(c�9[‘œªΈ2éP÷äGÎ�¿mÈÕ«WOŸ>m´ §Aƒt¨éªò£K ÌŸ?Á‚:)ghÛ2vìØ¶mÛ­ÂipcèÝ»÷Ô©yg}Á�ÿàQCIò£K ¬X±båÊ•:)ghÛ gÁ€e·­e÷îݶÉBþƒGß¡¤[·n™Íæ *ä�LƒUÈYò·m…³àÆ /ò<%yâiI´=zÄÅÅ�=›Ï[é•1X…œ% ÛV8 N0”¤/òùäÛãhÈðä«Ð—Çx¬ÕôÍ7†˜ T°$¥29K@þ¶­pœÀôEþƒ'_…‰$žáÌüaI´>ø`̘1ù&K#-ޏŠT´P!RV®Ã�³äoÛ gA½�A:òUØ„&&LÇ8fI´_ý5...ßd§9-öB¤­\‡!g Èß¶΂ê1HG¾ KQªµö±OÇL×±èAKK[¹CÎ�¿m+œe Òa‰Â>ô #ìW~Õ+Óø¡>õ›ÐÄ’ÄÒV®Ã�³äoÛ gAƒtX¢p c<ð!D—á—K\²|ò«´•ë0ä,ùÛ¶ÂYPÆ –(ôÃï^Ù–?±u"oI£]Žroò¦å ‘²r†œ% ÛV8 ʤÃB…AyãÝ›Þó·-ÙMbR8á!„”§¼å ‘²r†œ% ÛV8 ʤÃB…5¨±ŠUQDõ¥¯…KY<ÈbÏc^g:f°U ‘²r†œ% ÛV8 ʤÃr…=é9� ûØ÷ÏÝæ¶µ…2šÑ�i¼†5Ù_ð`‰B¤¬\‡!g Èß¶΂2é°JáT¦¾Ïû;ÙÙœæ>ÙÄ;��ïñ^+Zía�åƒHY ‘²r†V²!ÛV8 ʤÃ*…®¸ÎdæüG\ Zô§ÿaç‘ÞŒy)K«S} kF1êW~õÅ· ‘²r†œ% ÛV8 êÉgé(€Â>ôiD£ILZǺïù¾ ]šÒ´ÍZÐ"Å?%¥rÊ.v�áÌV¶îeo:é i8�y�èd‹NɋѮÈÙ¼åoÛ g¡(ƒÑò¡`‡w}êÏ÷‘D~ʧßñÝvüóÅ÷Ïð à�wOzö¤gÖÛ~ ¬)+×aÈYÊzQ�ABUÙ±E¡?þ X°€‘DåèQŽ®X²"õvê'�ŸøâÛ�Ô-må: 9K@þ¶m C‡íÔɦ.r‘Â^ÆP¶lÙQ£F5mÚÔöP+Vôõµz<7Þxã�çŸ^¯hö@—ÃÛü{Ðcû7Ûãââ†ÕCÚ?”,YrÁ‚�?þ¸Ž1�‹Æ��5ª\¹r¶Ùµk—¾ý×1cÆ$&&ê°0Ñ£‡Eë€)4Ô%†tìÛ·ïÒ¥K¯¿þº.ÑâââΞ=«K4…Â1ü÷¿ÿ-]ºtëÖ­�r“'Ož2eJDD„¿¿¿ÑZ싽z ŠÓ¡C‡:èíÕW_½wïž^Ñ ÇЭ[7£%iT�A¡P(,"&&&&&¦~ýúîîîFk±/Ê …BqözÀM¡P(NŠ2…B¡P܇2…B¡P܇2…B¡P܇1Æ0mÚ´òå˧¥¥å–`Μ9Ú‡—_~¹`Y„„„øøøì· …BQ”1Æ~üñÇlÞ¼9·YưnݺÄ���Ý¿©R¥ ¨Obìê©{öìiÓ¦Mûöí›7oþóÏ?\e‘Ä®Usâĉ€€€§žzªeË–»ví*¸J…„ÃÙ¿ÿo¼qáÂ…^xAÖ¾}û€€€:DGG !,XàááѾ}û &øùù !Nž<Ù¦M›6mÚœ>}Z‹S¥J•Ñ£G?öØcsçÎ͑Ÿqã<¨ý¶�Ѽyó·Þzkݺu¹%°e¯SSSµÑÑÑ5jÔ(pœ¢‰]«ææÍ›‰‰‰BˆˆˆˆÚµk8N!`êÔ©åÊ•Ëj«¢}èÓ§OâÏ�;·nݺ>>>ÔW(0À^ýõÐÐP!DçÎ�£££;tè°sçNí«ÌÌLíCÖ!¤}hÛ¶í¯¿þ*„øý÷ßÛµk§}UºtéË—/ÇÇÇשS'{üK—.õïß_Øvʉyòd ))©}ûö�<òÈÞ½{Ÿ~úiÀl6k哃ڵkÿïÿkÛ¶í�jÕª¥mÌmµçÔÔTOOO téÒñññöÚ“B‡ªF1|øðêÕ«¿÷Þ{vÛÙINNÞ¶m[TT³jÕªsçÎe½eá¡… \¼xñ©§ž._¾¬môöö®Y³&�žžîéN‡ÑΤ°”N�::t(ë¿]ºtY½zu»ví:vì¨õ£…£F�êÒ¥Kpp°vÉsìØ±'žxBëJŸéûN¾ë–nWܬdý:â¼/ï—H‰~ꃆ5ΰ7AûMðÏ”Ji¥TÊ«éþV™”}*Ÿþ.¿§%=õAGœ¨D?‘ODÄï_§Ó_ jæ¿Ä?ãGöí¯ÈM˜ù3ù»ZäÉWòU‡tL3 ûË7"#‡åðOòÓ¤LN=¤.É¥*© w1Xi†÷Tõ¯„² LÊþón÷Ù,ßypX·I›´õ…|ñ‹üöR‚dO°|äÁ!9Ô.íiI÷JïgòYØŒmÁò Ëð!9ô‡üñ³üö.cg°|OäIT¢³dVØ‹†ÍÁ`{žéÀz € € € € € € € € €ÿx¿[·n?~Üð+çÏŸßØØhþ�ššš?~l8¼k×®U«Vwuu]¸pÁp¸¢¢¢¾¾ÞpxllìàÁƒ†Ã"ràÀ�‚‚Ãácǎݽ{×pxÛ¶mëׯ7¾råÊéÓ§ ‡KJJöìÙc8,"9 Çb±¥K—Ÿ9sæòåˆÃUUUµµµ†ÃCCCG�5ž={vKK‹á°ˆ´´´ŒŽŽ×ÕÕ­]»Öp8‘Hœ;wÎpxåÊ• †Ãããã9ýðîß¿¿¨¨ÈpøÄ‰†Ã[¶l©©©1ßäÁºwï^[[›áW.Y²$§Û�Ç>|h8¼yófó`õõõ™¯][[k¬d2i~Í"ÒÜÜl¬ÎÎÎÞÞ^ÃáåË—›ëöíÛæk¯Y³&§µ··›¿þ´®®ÎúÈÎlñ<,À*££RV&OŸŠˆËÞ½ÒÐ ……a¯ް«,^,ß|#Ž#"26&±˜”•Ùs´•ÛÖ³g²}{þ–€ÉII$$“yqÑu%›µäh+òÿ#/ñ<¹?O›F6+"â8â�øS)¹_ž<Ñ,þ†Øæ‡äûï_œw)(�¯¿–o¿•>u­ ,À*©”|ø¡$“""Ѩ=©òåö_B3Ü�?J2iaª|aöH¥¤¼\¾üÒÂTù8ÂìñçŸ20 ï½öyÃ5xâ(5555555þ~âh<?uê”뺎㸮;u&ØÓ™…oyOÇã"˜éìì¼víÚÔ]ç{ùâ4ŸÊǤÒoö?ãëû;X“““ãããžçe³ÙW�Nó©\O³þ{^@äMúø&]±bE2™<{ölØw@vìØñÔ3M¼�›ãêêêÆÆÆi6ó™îžçÞÁ<]¡•{F£Ñþþþááá°¯¡¸¸xëÖ­íííSï%/_|½O…;É·Û¸qcssó4€0_K8•Õwx—íܹ³¿¿?ì-ræºn$Âk`ßQÄAJ¥REEEGŽ {؉`!Hžç¥R©t:ö"°Á Á Á Á Á Á Á Á Á Á Á Á Á ï+„ Í›7¯»»{Ù²ea/;,)‰lذ!ì-`-þK@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚@ ‚… MLLÄb±D"ö"°ÁB�ÒétkkëÕ«WÃ^v"XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÔ XÒœ9sêëëËËËÃ^vŠ„½¬RXX�ÇÃÞÖâ € € € € € € € € € € € € € AÊd27nÜ {؉`!Hããã'Ož {؉`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`Pƒ`PÃñ`, some of the concepts are hard to grasp even for experienced people. I think this is because rsyslog uses a very high layer of abstraction which includes things that look quite unnatural, like queues that do **not** actually queue... With this document, I take a different approach: I will not describe every specific detail of queue operation but hope to be able to provide the core idea of how queues are used in rsyslog by using an analogy. I will compare the rsyslog data flow with real-life traffic flowing at an intersection. But first let's set the stage for the rsyslog part. The graphic below describes the data flow inside rsyslog: .. figure:: dataflow.png :align: center :alt: rsyslog data flow rsyslog data flow Note that there is a `video tutorial `_ available on the data flow. It is not perfect, but may aid in understanding this picture. For our needs, the important fact to know is that messages enter rsyslog on "the left side" (for example, via UDP), are preprocessed, put into the so-called main queue, taken off that queue, filtered and are placed into one or several action queues (depending on filter results). They leave rsyslog on "the right side" where output modules (like the file or database writer) consume them. So there are always **two** stages where a message (conceptually) is queued - first in the main queue and later on in *n* action specific queues (with *n* being the number of actions that the message in question needs to be processed by, what is being decided by the "Filter Engine"). As such, a message will be in at least two queues during its lifetime (with the exception of messages being discarded by the queue itself, but for the purpose of this document, we will ignore that possibility). Also, it is vitally important to understand that **each** action has a queue sitting in front of it. If you have dug into the details of rsyslog configuration, you have probably seen that a queue mode can be set for each action. And the default queue mode is the so-called "direct mode", in which "the queue does not actually enqueue data". That sounds silly, but is not. It is an important abstraction that helps keep the code clean. To understand this, we first need to look at who is the active component. In our data flow, the active part always sits to the left of the object. For example, the "Preprocessor" is being called by the inputs and calls itself into the main message queue. That is, the queue receiver is called, it is passive. One might think that the "Parser & Filter Engine" is an active component that actively pulls messages from the queue. This is wrong! Actually, it is the queue that has a pool of worker threads, and these workers pull data from the queue and then call the passively waiting Parser and Filter Engine with those messages. So the main message queue is the active part, the Parser and Filter Engine is passive. Let's now try an analogy for this part: Think about a TV show. The show is produced in some TV studio, from there sent (actively) to a radio tower. The radio tower passively receives from the studio and then actively sends out a signal, which is passively received by your TV set. In our simplified view, we have the following picture: .. figure:: queue_analogy_tv.png :align: center :alt: rsyslog queues and TV analogy rsyslog queues and TV analogy The lower part of the picture lists the equivalent rsyslog entities, in an abstracted way. Every queue has a producer (in the above sample the input) and a consumer (in the above sample the Parser and Filter Engine). Their active and passive functions are equivalent to the TV entities that are listed on top of the rsyslog entity. For example, a rsyslog consumer can never actively initiate reception of a message in the same way a TV set cannot actively "initiate" a TV show - both can only "handle" (display or process) what is sent to them. Now let's look at the action queues: here, the active part, the producer, is the Parser and Filter Engine. The passive part is the Action Processor. The latter does any processing that is necessary to call the output plugin, in particular it processes the template to create the plugin calling parameters (either a string or vector of arguments). From the action queue's point of view, Action Processor and Output form a single entity. Again, the TV set analogy holds. The Output **does not** actively ask the queue for data, but rather passively waits until the queue itself pushes some data to it. Armed with this knowledge, we can now look at the way action queue modes work. My analogy here is a junction, as shown below (note that the colors in the pictures below are **not** related to the colors in the pictures above!): .. figure:: direct_queue0.png :align: center :alt: This is a very simple real-life traffic case: one road joins another. We look at traffic on the straight road, here shown by blue and green arrows. Traffic in the opposing direction is shown in blue. Traffic flows without any delays as long as nobody takes turns. To be more precise, if the opposing traffic takes a (right) turn, traffic still continues to flow without delay. However, if a car in the red traffic flow intends to do a (left, then) turn, the situation changes: .. figure:: direct_queue1.png :align: center :alt: The turning car is represented by the green arrow. It cannot turn unless there is a gap in the "blue traffic stream". And as this car blocks the roadway, the remaining traffic (now shown in red, which should indicate the block condition), must wait until the "green" car has made its turn. So a queue will build up on that lane, waiting for the turn to be completed. Note that in the examples below I do not care that much about the properties of the opposing traffic. That is, because its structure is not really important for what I intend to show. Think about the blue arrow as being a traffic stream that most of the time blocks left-turners, but from time to time has a gap that is sufficiently large for a left-turn to complete. Our road network designers know that this may be unfortunate, and for more important roads and junctions, they came up with the concept of turning lanes: .. figure:: direct_queue2.png :align: center :alt: Now, the car taking the turn can wait in a special area, the turning lane. As such, the "straight" traffic is no longer blocked and can flow in parallel to the turning lane (indicated by a now-green-again arrow). However, the turning lane offers only finite space. So if too many cars intend to take a left turn, and there is no gap in the "blue" traffic, we end up with this well-known situation: .. figure:: direct_queue3.png :align: center :alt: The turning lane is now filled up, resulting in a tailback of cars intending to left turn on the main driving lane. The end result is that "straight" traffic is again being blocked, just as in our initial problem case without the turning lane. In essence, the turning lane has provided some relief, but only for a limited amount of cars. Street system designers now try to weight cost vs. benefit and create (costly) turning lanes that are sufficiently large to prevent traffic jams in most, but not all cases. **Now let's dig a bit into the mathematical properties of turning lanes.** We assume that cars all have the same length. So, units of cars, the length is always one (which is nice, as we don't need to care about that factor any longer ;)). A turning lane has finite capacity of *n* cars. As long as the number of cars wanting to take a turn is less than or equal to *n*, "straight traffic" is not blocked (or the other way round, traffic is blocked if at least *n + 1* cars want to take a turn!). We can now find an optimal value for *n*: it is a function of the probability that a car wants to turn and the cost of the turning lane (as well as the probability there is a gap in the "blue" traffic, but we ignore this in our simple sample). If we start from some finite upper bound of *n*, we can decrease *n* to a point where it reaches zero. But let's first look at *n = 1*, in which case exactly one car can wait on the turning lane. More than one car, and the rest of the traffic is blocked. Our everyday logic indicates that this is actually the lowest boundary for *n*. In an abstract view, however, *n* can be zero and that works nicely. There still can be *n* cars at any given time on the turning lane, it just happens that this means there can be no car at all on it. And, as usual, if we have at least *n + 1* cars wanting to turn, the main traffic flow is blocked. True, but *n + 1 = 0 + 1 = 1* so as soon as there is any car wanting to take a turn, the main traffic flow is blocked (remember, in all cases, I assume no sufficiently large gaps in the opposing traffic). This is the situation our everyday perception calls "road without turning lane". In my math model, it is a "road with turning lane of size 0". The subtle difference is important: my math model guarantees that, in an abstract sense, there always is a turning lane, it may just be too short. But it exists, even though we don't see it. And now I can claim that even in my small home village, all roads have turning lanes, which is rather impressive, isn't it? ;) **And now we finally have arrived at rsyslog's queues!** Rsyslog action queues exists for all actions just like all roads in my village have turning lanes! And as in this real-life sample, it may be hard to see the action queues for that reason. In rsyslog, the "direct" queue mode is the equivalent to the 0-sized turning lane. And actions queues are the equivalent to turning lanes in general, with our real-life *n* being the maximum queue size. The main traffic line (which sometimes is blocked) is the equivalent to the main message queue. And the periods without gaps in the opposing traffic are equivalent to execution time of an action. In a rough sketch, the rsyslog main and action queues look like in the following picture. .. figure:: direct_queue_rsyslog.png :align: center :alt: We need to read this picture from right to left (otherwise I would need to redo all the graphics ;)). In action 3, you see a 0-sized turning lane, aka an action queue in "direct" mode. All other queues are run in non-direct modes, but with different sizes greater than 0. Let us first use our car analogy: Assume we are in a car on the main lane that wants to take turn into the "action 4" road. We pass action 1, where a number of cars wait in the turning lane and we pass action 2, which has a slightly smaller, but still not filled up turning lane. So we pass that without delay, too. Then we come to "action 3", which has no turning lane. Unfortunately, the car in front of us wants to turn left into that road, so it blocks the main lane. So, this time we need to wait. An observer standing on the sidewalk may see that while we need to wait, there are still some cars in the "action 4" turning lane. As such, even though no new cars can arrive on the main lane, cars still turn into the "action 4" lane. In other words, an observer standing in "action 4" road is unable to see that traffic on the main lane is blocked. Now on to rsyslog: Other than in the real-world traffic example, messages in rsyslog can - at more or less the same time - "take turns" into several roads at once. This is done by duplicating the message if the road has a non-zero-sized "turning lane" - or in rsyslog terms a queue that is running in any non-direct mode. If so, a deep copy of the message object is made, that placed into the action queue and then the initial message proceeds on the "main lane". The action queue then pushes the duplicates through action processing. This is also the reason why a discard action inside a non-direct queue does not seem to have an effect. Actually, it discards the copy that was just created, but the original message object continues to flow. In action 1, we have some entries in the action queue, as we have in action 2 (where the queue is slightly shorter). As we have seen, new messages pass action one and two almost instantaneously. However, when a messages reaches action 3, its flow is blocked. Now, message processing must wait for the action to complete. Processing flow in a direct mode queue is something like a U-turn: .. figure:: direct_queue_directq.png :align: center :alt: message processing in an rsyslog action queue in direct mode message processing in an rsyslog action queue in direct mode The message starts to execute the action and once this is done, processing flow continues. In a real-life analogy, this may be the route of a delivery man who needs to drop a parcel in a side street before he continues driving on the main route. As a side-note, think of what happens with the rest of the delivery route, at least for today, if the delivery truck has a serious accident in the side street. The rest of the parcels won't be delivered today, will they? This is exactly how the discard action works. It drops the message object inside the action and thus the message will no longer be available for further delivery - but as I said, only if the discard is done in a direct mode queue (I am stressing this example because it often causes a lot of confusion). Back to the overall scenario. We have seen that messages need to wait for action 3 to complete. Does this necessarily mean that at the same time no messages can be processed in action 4? Well, it depends. As in the real-life scenario, action 4 will continue to receive traffic as long as its action queue ("turn lane") is not drained. In our drawing, it is not. So action 4 will be executed while messages still wait for action 3 to be completed. Now look at the overall picture from a slightly different angle: .. figure:: direct_queue_rsyslog2.png :align: center :alt: message processing in an rsyslog action queue in direct mode message processing in an rsyslog action queue in direct mode The number of all connected green and red arrows is four - one each for action 1, 2 and 4 (this one is dotted as action 4 was a special case) and one for the "main lane" as well as action 3 (this one contains the sole red arrow). **This number is the lower bound for the number of threads in rsyslog's output system ("right-hand part" of the main message queue)!** Each of the connected arrows is a continuous thread and each "turn lane" is a place where processing is forked onto a new thread. Also, note that in action 3 the processing is carried out on the main thread, but not in the non-direct queue modes. I have said this is "the lower bound for the number of threads...". This is with good reason: the main queue may have more than one worker thread (individual action queues currently do not support this, but could do in the future - there are good reasons for that, too but exploring why would finally take us away from what we intend to see). Note that you configure an upper bound for the number of main message queue worker threads. The actual number varies depending on a lot of operational variables, most importantly the number of messages inside the queue. The number *t\_m* of actually running threads is within the integer-interval [0,confLimit] (with confLimit being the operator configured limit, which defaults to 5). Output plugins may have more than one thread created by themselves. It is quite unusual for an output plugin to create such threads and so I assume we do not have any of these. Then, the overall number of threads in rsyslog's filtering and output system is *t\_total = t\_m + number of actions in non-direct modes*. Add the number of inputs configured to that and you have the total number of threads running in rsyslog at a given time (assuming again that inputs utilize only one thread per plugin, a not-so-safe assumption). A quick side-note: I gave the lower bound for *t\_m* as zero, which is somewhat in contrast to what I wrote at the beginning of the last paragraph. Zero is actually correct, because rsyslog stops all worker threads when there is no work to do. This is also true for the action queues. So the ultimate lower bound for a rsyslog output system without any work to carry out actually is zero. But this bound will never be reached when there is continuous flow of activity. And, if you are curious: if the number of workers is zero, the worker wakeup process is actually handled within the threading context of the "left-hand-side" (or producer) of the queue. After being started, the worker begins to play the active queue component again. All of this, of course, can be overridden with configuration directives. When looking at the threading model, one can simply add n lanes to the main lane but otherwise retain the traffic analogy. This is a very good description of the actual process (think what this means to the "turning lanes"; hint: there still is only one per action!). **Let's try to do a warp-up:** I have hopefully been able to show that in rsyslog, an action queue "sits in front of" each output plugin. Messages are received and flow, from input to output, over various stages and two level of queues to the outputs. Actions queues are always present, but may not easily be visible when in direct mode (where no actual queuing takes place). The "road junction with turning lane" analogy well describes the way - and intent - of the various queue levels in rsyslog. On the output side, the queue is the active component, **not** the consumer. As such, the consumer cannot ask the queue for anything (like n number of messages) but rather is activated by the queue itself. As such, a queue somewhat resembles a "living thing" whereas the outputs are just tools that this "living thing" uses. **Note that I left out a couple of subtleties**, especially when it comes to error handling and terminating a queue (you hopefully have now at least a rough idea why I say "terminating **a queue**" and not "terminating an action" - *who is the "living thing"?*). An action returns a status to the queue, but it is the queue that ultimately decides which messages can finally be considered processed and which not. Please note that the queue may even cancel an output right in the middle of its action. This happens, if configured, if an output needs more than a configured maximum processing time and is a guard condition to prevent slow outputs from deferring a rsyslog restart for too long. Especially in this case re-queuing and cleanup is not trivial. Also, note that I did not discuss disk-assisted queue modes. The basic rules apply, but there are some additional constraints, especially in regard to the threading model. Transitioning between actual disk-assisted mode and pure-in-memory-mode (which is done automatically when needed) is also far from trivial and a real joy for an implementer to work on ;). If you have not done so before, it may be worth reading :doc:`Understanding rsyslog Queues <../concepts/queues>`, which most importantly lists all the knobs you can turn to tweak queue operation. .. _concept-model-whitepapers-queues_analogy: Conceptual model ---------------- - rsyslog message flow mirrors traffic: the main queue drives processing and pushes work to passive consumers. - Every action conceptually has a queue; "direct" mode is equivalent to a zero-capacity turning lane that still gates flow. - Non-direct queues duplicate messages for parallel delivery, isolating slow actions from the main path. - Queue workers are the active agents pulling from queues and invoking parsers or actions; consumers never request data. - Queue capacity and worker counts bound concurrency: more lanes/queues increase parallelism, while zero-capacity queues serialize. - Shutdown, error handling, and timeouts are governed by the queue, which decides completion and can cancel long-running actions. rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/reliable_logging.rst0000644000000000000000000000013215145046112023155 xustar0030 mtime=1771326538.960012998 30 atime=1787067672.735457538 30 ctime=1787067793.882715513 rsyslog-8.2608.0/doc/source/whitepapers/reliable_logging.rst0000664000175000017500000001201115145046112022614 0ustar00rgerrgerHow reliable should reliable logging be? ======================================== With any logging, you need to decide what you want to do if the log cannot be written * do you want the application to stop because it can't write a log message or * do you want the application to continue, but not write the log message Note that this decision is still there even if you are not logging remotely, your local disk partition where you are writing logs can fill up, become read-only, or have other problems. The RFC for syslog (dating back a couple of decades, well before rsyslog started) specify that the application writing the log message should block and wait for the log message to be processed. Rsyslog (like every other modern syslog daemon) fudges this a bit and buffers the log data in RAM rather than following the original behavior of writing the data to disk and doing a fsync before acknowledging the log message. If you have a problem with your output from rsyslog, your application will keep running until rsyslog fills its queues, and then it will stop. When you configure rsyslog to send the logs to another machine (either to rsyslog on another machine or to some sort of database), you introduce a significant new set of failure modes for the output from rsyslog. You can configure the size of the rsyslog memory queues (I had one machine dedicated to running rsyslog where I created queues large enough to use >100G of ram for logs) You can configure rsyslog to spill from its memory queues to disk queues (disk assisted queue mode) when it fills its memory queues. You can create a separate set of queues for the action that has a high probability of failing (sending to a remote machine via TCP in this case), but this doesn't buy you more time, it just means that other logs can continue to be written when the remote system is down. You can configure rsyslog to have high/low watermark levels, when the queue fills past the high watermark, rsyslog will start discarding logs below a specified severity, and stop doing so when it drops below the low watermark level For rsyslog -> \*syslog, you can use UDP for your transport so that the logs will get dropped at the network layer if the remote system is unresponsive. You have lots of options. If you are really concerned with reliability, I should point out that using TCP does not eliminate the possibility of losing logs when a remote system goes down. When you send a message via TCP, the sender considers it sent when it's handed to the OS to send it. The OS has a window of how much data it allows to be outstanding (sent without acknowledgement from the remote system), and when the TCP connection fails (due to a firewall or a remote machine going down), the sending OS has no way to tell the application what data what data is outstanding, so the outstanding data will be lost. This is a smaller window of loss than UDP, which will happily keep sending your data forever, but it's still a potential for loss. Rsyslog offers the RELP (Reliable Event Logging Protocol), which addresses this problem by using application level acknowledgements so no messages can get lost due to network issues. That just leaves memory buffering (both in rsyslog and in the OS after rsyslog tells the OS to write the logs) as potential data loss points. Those failures will only trigger if the system crashes or rsyslog is shutdown (and yes, there are ways to address these as well) The reason why nothing today operates without the possibility of losing log messages is that making the logs completely reliable absolutely kills performance. With buffering, rsyslog can handle 400,000 logs/sec on a low-mid range machine. With utterly reliable logs and spinning disks, this rate drops to <100 logs/sec. With a $5K PCI SSD card, you can get up to ~4,000 logs/sec (in both cases, at the cost of not being able to use the disk for anything else on the system (so if you do use the disk for anything else, performance drops from there, and pretty rapidly). This is why traditional syslog had a reputation for being very slow. See Also -------- * https://rainer.gerhards.net/2008/04/on-unreliability-of-plain-tcp-syslog.html .. _concept-model-whitepapers-reliable_logging: Conceptual model ---------------- - Reliability is a policy choice: block the application when logging stalls or drop messages to keep workloads running. - rsyslog decouples applications via in-memory queues, only halting writers when queues saturate. - Disk-assisted queues extend buffer capacity and persistence but introduce latency and eventual disk exhaustion risks. - Per-action queues isolate unreliable destinations so other actions can continue during outages. - High/low watermarks and severity-based discard policies bound backlog growth under sustained failures. - Transport choice defines delivery guarantees: UDP sacrifices reliability; TCP reduces loss window but can drop in-flight data; RELP adds application-level acknowledgements. - Absolute durability is limited by OS and disk flush semantics; stronger guarantees trade away throughput by orders of magnitude. rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue_directq.png0000644000000000000000000000013215132411300024024 xustar0030 mtime=1768559296.226885008 30 atime=1787067730.725538478 30 ctime=1787067793.867715234 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue_directq.png0000666000175000017500000002353315132411300023500 0ustar00rgerrger‰PNG  IHDRVÒž›®sBITÛáOà pHYsÐй‹çŸ IDATxœí�wxTUÞÇ?“N ´�@ ½@D ½¨HQÄ.ëbE—¢²Ë몈(¬ˆ€K}A¥IO�wEŠt $ôHH!“óþqycL=3¹3wrs>Ož<3wNùÍ�9ßùžsÏ=Ç"„pww·ÁÍÍ­èÁRŽÛ‘Ũã.’ Uæ8 à!„Bäåå‰BQH­\?ÔŽ;öíÛð°X,Zûׄ@‡«wÁ�T¨Î9®~«ôâÙgŸ½-ù‡,‹»»»q!)R¸š*•~ÜCÒŽ·oß^;Ÿ!„±Ÿ¨Bá6³9„�V´2:—ÃÍÀº7°á @QØÌæbžåÙæ47:WÄ£ì$`¦0å×ö³ß�eò¿Eitåb3›'3y;Û�Å,vGõs‹ÁÙ.`îæîxâw²óoüÍÍP¢(–D{Ñk KŒÄ~´_þ{¸GkÿMi:”¡Fåª;`àÖ‹õ�EgÚ_sÑÜ*¬N«]Q&VaýV|ÛItB"B®‹ëFGd›Ä¦.¢Kþ×Lû[,—ëâ (Ôøµ¿/Å—N¨Z!CŽÈY(¶-ò?�b†ÑAÙL±�ASÑ4Wä�ëâØ+ZŸ'; oNóýìW½Ã¹ÉÍyÌ{�÷Nr2ÿ`8áG9ê�·��&'‡C‡øí7$-�Œ ÒÓIO×\ªÁàÕžšç/J_ú6¥©“ã5„;¹ó!²5—£$ ¤Æ¯Ñ—¾MhâˆzÅ2˜Á]èRðÈU®~ÌÇ3™y‘‹…/`Á£<êÄèŠã÷ßIHà§Ÿ8|˜cÇ8{¶”´)õ ;å´È\—ŒXÌb[s9äŠÀW|5Œa‚Åe kÖ°ÆU+Š¥! ó%à g>àƒñ¯Ü(6e4Ñi¤èÜ!9™„IH %åO/yzÒ´)�IH��øûã燿?þþYÁ—‡²àk¾Î£˜¹ƒð@g:;é-Š}fÇQ.à ßâ­’>•y0šhGÔ«(–îtoCà"ˆÈ £Ì,, iXŸúèОöèÐ�†p¯Î¥K,]ÊÂ…üüóˆ�'.Ž&MˆŒ$4´ÌbJúÊ…vŒc^xé¸IpèHÃq`¨ê&Ü �Є‹ðl‘íЪ%qI\š &TUŠŽœ!¨%jEŠÈj¢ZÑ—<…gÑ™X–%²tˆ#'G¬\)î»OxyÝ®!8XÜ¿˜5K8 Jžo[:Å~åf‹Ù:lRœqE ØOå_â_N¨ZQ)"e¬ë!< µsásVœB䉼d‘¼N¬{K¼5P ¬%jå§ £Ä¨�b£�—u³²ÄŒ¢víÛåyxˆþýÅÿþ¯ÈÖíW¡ÐW.L„©Ÿœ’pÞ¼€BŸŠ2®Àqdˆb–‚*ðªxµØÄ‡ÅáYbV´ˆÎOßB´øN|gC}99bÎz»ª–-Å{ï‰óçõy3E(ø•SF $œ'?e\„]bWOÑ3_Eà5q­”ô©"uª˜Ú@4ÐÒw]¶‹íeWóå—¢~ýÛ•´k'Ö¬Ñí ”Šö•k ¨Ÿœbq¶hhŸJ„ˆPŸŠë°Elé(:j­úïâïe¦Ï9³Ä¬üÂ01,]¤Ÿô·ßDLÌ¿üË—ÛÝÕ·›‘r@pr¥c$@#U¤ @Qˆ<‘·B¬h.š×µnŠ›2YÒEúT1µª¨Š BDì»þ\bž˜=[øû ~~â½÷œßø¥£Ö PÆŠõßü»&5ûÒW2K2ÉCú_þë�÷û¼ÿ4O¤¦2f ë×<ü03gä°¨v¢$@¡9ä¼ÄK3™ <Â# zÖÒ3žk× aölî»ÏèÅã>yòd£cp 6oÞwäÈ‘~ýúmÚ´©ÿþÇ����߸qã°aÃRRRzôè±qãÆÇ{ìܹs1117n|öÙg/_¾Ü©S§�7¾üòËiiiíÚµÛ´iÓ¤I“222Ú´i³yóæéÓ§ggg7oÞéÓ§Ï÷ß¼÷Þ{±±±k×®Þzë­»îºK{üÚk¯µjÕJKó /ÜqÇÚcq?÷¯_:ªJ&³ž²NØÚ�ï¿WæßÅQ.à6aaaO<ñÄ AƒüüüÂÂÂFŽÙ¿ÿ€€€zõê=øàƒ}úô ª[·î€âããkÔ¨Q«V­øøø{ï½7$$¤F�ݺu‹‹‹«]»vPPPttt�=êÖ­[µjÕ¨¨¨ØØØÐÐÐ*Uª´lÙ2666,,ÌÃãQ£Fݺu B„‡‡ÇÆÆ6hÐàÖ­[µk×îÞ½{Æ 322‚ƒƒ»wïqõêÕªU«öèÑãŽ;î8þ¼··w\\\ddä©S§,KÏž=###�;–››Û«W¯ÈÈÈýû÷gfföíÛ722r×®]ׯ_0`@ddä¶mÛ®\¹2xðà;î¸Ã!'Ñjå™g"^›Ûn�ÛÿsßÞ Õj±ö ‡CêRè„ Pè„<ôK—âëË’%úö£ß-n­de?úœ¢DTG@¡'²t)ÞÞ$$0pà½Ü;�é1šÑ©¤œ¢D” PèÁìÙ<ý4žž¬Yý÷jÇb W±ª+]·°E­Þ隨±€2È&;�„ìhC›+\‰#î^¸À…Ö´nLãILÊ&»;Ý7°á ž¸ÈÅÎtÞĦ—xé×ÚÓ>�„·y;ƒŒV´Úƶ™ÌÌ&» M’HZÀ‚\r#ˆØÅ®å,ˆPB÷±o#-XjQëG’HrÇ=˜àßùý<ð à g’IöÀÃ_£Oß~ËèÑóç3xpþa –žô\Â’ýì÷À£Ý ‹PQ2ª#ð'´[ͯpå~î×n°¿ÉÍžô|žç –$’2ȸÀO<Ïqî&7µ%·Nsz [Žp8Á‰¬ØË^à0‡?çó$’€Ýì~Ÿ÷I´”7°ØÄ¦çy~5«�•¬ÉȬ–°d–± øŒÏºÒU[æ>hMë/øÂˆ3T„={2«•wÞá‘G ½X�êÚJÄçï§P+û¸"Æì#à‚Ä$’xžóÕ¨–Hâ®\ãZA÷roÙdð_¹áÖ….Õ©¾�}7¸Q�z@ú$’BГžßòma@q X ­’Ö�n3˜Ñ–¶@g:Of²¶šM:Œg¼¶†JÚŒb”–¦Í1HËÛ�†±ÄjeÖ¡N[ÚjuLf&#F�›Ëðá¼öZ±Ibˆy˜‡±h"ÿÍ¿� ¢l œœì |">©%j�'…w‰»$‰$!Äâ‡â€Zy¶ ž{N€hÕJd•¶ˆÈIq²Š¨b–ÿŠÿ:-4…$•±#�EÖ|ækF}';Ïs~9Ë�YÌÊ$³�€bZÐB�`•ÆÆ�Ìš…·7‹á]ÚrÃa„ý…¿Ä_ù«Ó¢SHR¯¼À 3™9†1s™û ¿\åjWº:dU<sõ*­Zqú4Ó§óòËe&O'ýî¸À…MlŠ#Î *$©,. ƒŒiLÅ(à5^ëLçû¹hMëntSíßfþòNŸ¦kW&L�Iî�ÿxƳ˜åàȶa~ ,¹¨­œ›BŠ6€§°Ÿ½{i×ww~ý• $3]äba·¸õ¿5@6—ÂјÜìc_{Úÿ‡ÿÔ¤æ|°�}ªýëÀ믓—Ç /È· &5‡1ÌŠõ>qXd ›1¹ ˜ÈÄiLëOÿ•¬4:³�˜H÷îT«ÆñãÛ”u7»ÛÑ.˜àR\e^S¥Çœ. ™ä±ŒˆÉL~‰—¾æk£#2 Bðꫯ¼bkû¢ˆêLç+\YÅ*ýcSØE1.@±oß¾üÇùÿežz{{·mÛÖ¾P®_¿¾gÏùº > ɯ7—ÜB®rõS>ËØ2ëMNNÖÞo±U”^u‹-Z´haßûMJJúõ×_åßlÁãñññáááöÕ»lÙ²óçÏÛwžŸ­[·ÊÃS¯¿þНm?ãï¼óŽÕjýÏ]ÿYÛkm‹C-†|=D²j__߉'Ú÷fÏ�;÷î»ïÊŸØ‚O›4iòÜsÏÙWoRRÒgŸ}VfÅFÒ·oßáÇÛWïÂ… W­ZU¨ð¸¸¸gžy¦ÄwOk.`Û~(ª¢S�%À�ºÔíNwuW¿ÃY» O½Ê‹ ¢õÎsþW~Õ«LÓ³p!‰‰ú[Q%à×:Ðá §3ÝèXÌÎÍ›$$àîN¯^:–Ú….À�ü¨c™æ&6–øxºucóf=‹­�ðß5¤áJV nõw8›7“•EÇŽÔ¨¡c©Úúˆû±ö^e#<œÇㇸçºtaÃ}Š­�°šÕ׸¦V¤uZ/ ¯ìFã’´¢Jläõ×o/ѶcññDGSþ "+¤Ìeîæ(tDó�½{ë[jKZ¢$ÀFê×g̘?žþø#}úp×]¬^�ÝSü*ØìÀŸøi9Ë_çõŒŽ¥rpý:ÕªQ¥ iixè¹ä¼@”FÚ%.U§ºŽ%››Ó§‰Œ$+«ðñ¨(þö7 Àbcϸ‚í#ð¯mfsªLb’ѱTx„¸ý——÷ÇãBOݶíñ"·yë´4�ÒS–òR )- š¶Üç¿cÙ¡ýw¦ÅêTf¹R:¹:»SÖ®MrráOs÷n ¢m[Þ|“ÁƒmY ÈÍ%1Ñø3Ҳƌ3Ý&Z¿}ñ­,õE)oJþÂî÷aî®;ŸÖs(ðÿùW žØñ̬ÃÌŽu@é•‘½{yõU7FþVY HOÏß-Ò ,‚ÐTRZÂwoˆ °Xpsûãþ_ѧ�nî!›_ý£B|KLYf!%½tV„¥@hÇÓá¿èV¦£SºB`/¿ÌÁƒÅ|¬­[3y2ƒÙÖ�•OOzö4òŒnûåªí½ê“¨Ýc\êóp…êlMi-ws�¶F}eK.9æS÷1¸÷Ñ3Ÿ?ªáfeË–bÚË–LšÄý÷ÛÖø5d%ÀÏ�õëm.]G¦sj%¹÷r=ÈÈ0*7orä^^6ØJ[ЦuŸå¬# 7+S§þéi³fLšÄ�!6*{*ÌEÁWx%�ôŒ0:�ÊıcX­4i‚——#ŠW`+[·²uëíÇMš°x1û÷3t¨ý퟊"‹Xt� ¾øzSÚÞu �9} ~}¯IÀÎ8¨|ó¡Y€F�øâ dÄîÛª¯sý)žÊ ãjàˆ�iE ¤¦ÔsÔæ+5¨á‰çe.ßâ–'žªÅ4lßNr2óçóðÃzNѨ�EÖCp‚�ñ˜ZaÊÜ@ ¸®îV³z>ó³ÉÖÖ™Q8w€ºÔE]0W—€Á Î&[»·\álΟ(Çö0e¢® Ž«K@(¡˜`t•mk¹rlæS&J Ç¥ÇV³º+]¿á£©¬dgc±Ü^¤Â1h5` ®.ÛØv„#FR)¹u «//{æ�KL0p�kŽ«BQ:.ݘÉÌÞônC£©”h«Røø8´|€l²Z‹¢\Z¼ðÈ@££¨¬8E¼ðBI€¡¸nGà~'|*SËNªpÙÙàp ÐnúP` ®+{Ù{ŠSç8gt •Í8r,%.€ëvžçùÞè¼j­ÂÕP`8®+Ùd7¢‘ÑQTbüü22Z‰’ÃqQ È$3€€–´ÜÍn‹Ä~A§OŸ¾~ýzݺu�žk’››k-  Q#9aÕfݼYø¸Õª×æ¢Ø+7oÞ\±b…^1TB:uê©=¾-_|ñ…sê êß¿™É’IÎ%÷·dÚ?ðæ›oΟ?áÂ…#GŽ,wŒÅ°aÆŸ~ú)((ÈÝݽÌffyrK×®]ûìÙâ¦â Qøú±°mß|ÃûïÛy‹à…—K96åJNN~ä‘GôŠ¡2oÞ¼?I€âÑG�´€£››ÛöíÛ£££KOÖŒfyä¥�"Y¬ÕjÜõûu*ĸqã’‹.ÝîJxxx¸KP³fÍâó_ºÄøñ NïÞ·ä==ñò";›Ü\<<8{–—_fñb¾úª¤nÞ¼ùûï¿ûúúFDDH†mÁâ…W6Ù¹äzH{Òõë×Mš4éÔ©“dEAòÛ?ù.`Ô¨QN¨øûï¿?þ¼Ö\K'‹,|“,ÙÑàïï 0 ^½z2-ÍA”ÔÎÝäÖ‘øâ‹/Æ�÷ÔSOÍž=»ðk5kÒ±#ýûÎOðøãÔª…¯/99¤¥±p!S¦pý:uê0°Ä™»w‰éÚµëÖüî$ðÆ;›ìl²å% J•*@\\ÜÇ,_‘¢X<‹Å2þ|'TÖ½{÷óçÏËla6�éS˜ò!>Çs2%;ZªW¯L˜0!ÆAë68«Õš•••››[üËO?ͼyüò '2e ÷Ýw{yª»ïæèÑÛiÆŒÁ³Ä¾, `ëuù³ƒüð“Ì¢UaqäÌåʃSçhŸ™L¯5�t�Ðf�Êàh °ïËíj”¿‡}t{D '‡/¿äÒ%à�öïáÁر¥`ßY²cDPI€Ž8U4¿*óy—wóÈ{ˆ‡$KV Oi-§kWF”¼L{¿~¥¯&¬$ "â¢.à,g-X|‘½S]I€ RñÿÏÿPµjñ/=õTéYí;KÚ€’£pQp'wºáv™Ë’%k 9*fæ�)êÖeRq»6GFrÏ=¥gµï,õ£_aòC¿( Ðux„üÆ!ÊÈSvËyþyš7/|pܸ2×¯ŽŠŠ:sæÌêի價Á�,8Å©,�Ï¥$@G p2�Jª@øã/Yò’%KNŸ>Ý­[·rÅW2æ�Ùø==ùè£?ññaôh‰|žuêÔ –é>¹ÂàÞÉ$S2—’qÑŽ@:é6•\­Zµºuëú8ìÎVsH€†TËéуüãé�!T¯®{$™d~ÀÚãÓœžM‘Ù % $@G\±#�IfUªÊ['` °-þþóö�B”=hs™{žóùOÿÁ?$¥_I€Ž¸¢ È!'€ùËNÀ`õëóÆmÛRÖ„n;È!ç]Þ-xä"?äC™¼JtÄ]@ �i¤]à‚S‚’ÂL`CËyñE7v�XÈÂTR ü'ÿ¼ÊÕ2ó* ÐWtV¬é¤k£D.‚9$Àæø½¼Fn ¯>öÕ5¬Ñ7’\r§3½èñk\{�÷ÊÌ®$@G\ÑœætUª¶£�S‚’ aS˹QÛïŠåª•²ï첉/ùò8Ç‹}éC>,Ó* ÐWt~øùã@€S‚’Â`Gü¹äòÿøô"�¼¿ó÷’^M'½XƒP%:âŠ. :Õopcû ÏCjU G` а©åh¿ÿúJÀ7|sˆCÚãf4‹&ÁˆB´ƒ³™}šÓ¥” $@GŒw³:]&™…ÖþŽïžæi‡†W æ�»]€;ºM»ˆiL"ˆXÈÂýìoHC`Npâ>¨G½L2ßæíÒ Q Æ»+Ö~ôûŒÏ jAMjÖ¡Ž6]ìÇúÐgƒzÑ˙ѤÒ~Ûtï|Ï÷¸0‡9G82’‘î¸kú’K®/¾ãœãs˜“@ N”Tˆ’1~‚pÃ6–±¡„>Ïó‡9 Ô¤f]ê^áÊD&¶¢Õ÷|Jh?ú93Ú‚˜ÃhÛÈ%÷w~Ç8On/=¢®i à�÷8ÆâP)÷* Ч® \ÒpàC<ô)ŸncÛG|4‹YÝè6�éÞxw¤c~Ÿp,cõí‘Ú„9$À†0 Ð­ðBÜpkJÓ’ Q #NmT% Z°|ÄGíiŸK®@$’˜HbÁžxŽaŒÓâ,Š9$@æ–£ûX@Qò;òY”èˆñÃ�mhó%ÎBÈ@m#z£0‡¸‚ (J±. t”èˆñÃ�ùLejþe¡B”¢ÎÁ`ޏ(XåŒÅU\P�jÿàE�7¡Iwº;6²²0“¸ZG Ðp  JtÄ…\0ŠQ�(¼9Ä“<)¹§�ã0‡¨Ž€¢(.ä –YÌ*ø›ã‹ï£8i§£R0‡h>;°ª#`,®å€v´Ë‹ÕcXAe–ìèÆi pôìÀ'N¸¹¹Én[úÿ(`,®å4ÞæíêÜ^¦êIž”)¹jÕªîîîYYY匰$Ì!v`kG@aëYR.ÀX\ÎÕ©®M#oOût�)YÛZW­ ,ƒã:åÙG@¹£0~‚p±ŒaL{ÚË_ T‹ˆËà莀}gI¹c1`v ÌWÄ ·9ÌiIKÉ’­V«ÅbQ[‰È`ÇEA'¸%FaÀ=2.�_5H‘——çááÀ÷b °#~Õ0=®8h+ŽÞM ³H€8Á¨Ž€±¸âp ­8z sI€ãf*P1� p¨hTt pôì@å*"ÊHQ9]€@ä‘'?)@ VD” �Â`kü¶Þ#¤:å¤0‡hÈ·[§ªŽ@ED¹)Ì!¶Æoë=BÊTD” �Â`+Îé(`,.:AØ&”Ø„«uÔp ±àTGÀ(TG@Qå¤0‡h¸š PcQÃ�R˜CÔEAEQÔp æ�[Q. 2à» •%6!ßrl pww¯]»vµjÕlŠG ‹Kì&TNÜÜÜêÔ©S£F }‹-ˆ9$ÀÑ�ªU«ž={ÖÖ¨TGÀXÌàš5kvæÌ}Ë,„9$@ÃqÃ�ö¡:Æb†±'` pôEAûP.ÀXÌpEÀ ˜ClÅ [ ¡\€Ñ( …™$ÀÕ:j8ÐXÌ05È ˜C\³# ¹›:JtÁ „�@Å�¼(¶ºGw” 0å¤0‡ØwQP š5(…9$@ÃqSƒìC ‹”ÂL �r•å¤0‡8zv }(`,ÊHa¦o›º(¨(ˆrRTN fV” � ájUGÀX” � . *Š¢\€æ�[Q+jj�f’Wë¨á@cQ„¥¨¸‘Ä5;Zyä dÃS #ÊHa ÐpµÙ�ØÞP #j8P sH€\À/¿ü²gÏG/"¬$@GÌ0xñâÅ={ö8tí0sH@é¬gýqŽ—’1Ãp 0‡ØA,±íiŽs_ð…#ÊŸÁŒ›ÜÀ€Ò#*„’1ƒ pf’[[ŽvƒÀë¼~–³úFò¿}ȇZá6eT #ÊHa °/þ! éKßK\Å(ù=¿Ê$‹¬x ƒŒQŒê@›ò* Ðå¤0‡hØÚr,Xæ1¯µ6°á9žÓ+Œ±ŒÝǾ¦4ýˆ�lÍ«$@G” �Â`wüµ¨µ�…,óqþMÄvcÅú8�/b‘>_óµ?þ¶– $@G” �ÂPâ‰_Æ2O<§1m clÚ ¼ V¬Cò9Ÿû㿊U-iiG!JtD¹)Ì$v·œ! YÁ |æ1¯%-·³ÝÖV²2‚ˆoø¦:Õ7±éî±/%:¢\€æ�€òÇß�~;ÙÙ”¦G9CÌP†î`GÙõ"6±éÈÀSœjLã�ììHG»ÃP #ÊHa¦o[9ßË�ܹ�}S˜â…×W|Õ….5©9‘‰kY[èžÂ“œ\Ū)L©Nõ{¹w‹ ü˜�s¸1�˃’1à ÂN@¹€‚xáõ7þö�}ʧŸñÙYÎNcšöR �á–MvAE¨Oý'yr cB)JtÄ ¨ˆ É ¡WË %t*S'3ùk¾þ™Ÿæçù1�´üu¨ÓšÖÑDw¥k,±tk±JtÄ w :sH€#âwÃm(Có×L'ÝŠÕŠÕ÷@u¯NCI€Ž( …9$À Øq‘ߔ舔ÂL`‚–£$@GÔEA)Ì!=þ|”èˆrR˜C4LÐr”èˆrR˜C*züù( Ðå¤0‡8�ï¾ûnþüùW¯^uh-JtÄ W–.]š••õàƒúùùé[r>f’‡¶œI“&íÛ·¯C‡AA²›Ø�’1ü€W^y%%%%>>^I@é8!~çœ(%:b†„Õ>6áЖ£$ Âa†á@%’( (І•¸J*æqj7!ITG@Qå¤0‡¨Ž€¢(æq•�Š.Ê( ¢\€ÊH¢$ Â¡\€æ� å1‰ °X,J\%Ž ï„yyy½€Y$@uE©ð.À9c�æ� ÕP¤ÂOV �rŠ¢TøŽ€’[Q.@QÕ� \€¢(ÊHa pJ*ÊHa& PEA” � :Š¢TøUƒ”ØŠC[Έ#¢££ëׯï¸*P +N•ÀÍÍM߆äçç÷Æo8nÉ0 sH€â3fŒ£«@I€®8[,K^^žB¯Ï/ à­·ÞÒ¥¨Rˆˆˆxã�75jäèŠJïÞ½ƒƒƒÛµkgt åeüøñiiiŽÖýJ‚ÅÉ¿l^^^·nݲZ­ŽžÒ«P(dp¶ ˜8qbE·Ó …™p¶ P(.Åÿã;Î#âÓIEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/dataflow.png0000644000000000000000000000013215132411300021434 xustar0030 mtime=1768559296.226885008 30 atime=1787067730.718538347 30 ctime=1787067793.856715029 rsyslog-8.2608.0/doc/source/whitepapers/dataflow.png0000666000175000017500000006003115132411300021102 0ustar00rgerrger‰PNG  IHDR1–ÍÌsBITÛáOà pHYsÐй‹çŸ IDATxœìÝy~üÝB&“mll444TUUÇŽ+)))..>dÈ�––:�N§Óëêêrss‹‹‹ß½{—žžŽ~ÈÈÈlذaõêÕ’’’¸~ ˆ'ÀÄAüêóçÏK–,yøð!@\\ÜÛÛÛÆÆfòäÉì·ÐØØxøðáèèè/_¾† vüøqKKKNE ñ ˜ ˆ/�;wnÕªU555²²²îîî"""}níîÝ»¡¡¡hŽYµjUtt´˜˜vÁB|&â3t:}ýúõIII€ $&&6¬ÿÍ"²ÿþÍ›7·´´P(”Ó§O«««÷¿YˆÁÄAüäéÓ§öööoß¾Û»wïÊ•+±m¿  `Ù²e………‘‘‘^^^Û. Þñ�cÇŽ¹¹¹!¢©©yúôiNôÒÜÜìëë� ÈìÙ³/]º$$$Ä‰Ž žñ‡˜˜˜M›6!âáá±oß>AAAŽv—••µ`Á‚êêê3f¤§§“Éd¬Znkkc0XµÆQƒô„ � ˆçýùçŸ"‘xàÀ®uZTT4jÔ(€®®î�?°jVOOï¯=v}ÿþ«OÍ_à¤Gâi‚øúúFGG ;vÌÑÑ‘k]«ªªfeeÍš5+;;ÛØØøÖ­[222X5.,,L$±j s---È M�‰‚xƒÁXµjUbb¢°°ð™3g,XÀå³²²LMM_¾|9}úôÛ·o�3“–ïÝ»§««‹ISœ ++[QQ�w¸áÝŒ Aƒ\{{»ƒƒCbb¢¸¸ø¥K—¸ŸPrrr÷ïß×ÒÒzóæ�‘‘ÑÛ·oq â&˜ ˆµ¶¶ZZZž9sFRRòæÍ›fff83|øð;wî}úôÉÀÀ ¸¸Ç` .€‰‚xQiiéíÛ·îîîx‡$%%wíÚ%((XUUuêÔ)¼Ã�8 &âi»wï Ä; ððáCssóööv¿Ül õL Ä»F�-((¸cÇŽuëÖáøu|ûöíÙ³g×ÖÖ¢ú`�î&â]iii¢¢¢û÷ï_±bEGG÷c¸xñâܹsÝÝÝmmm¹Ä}01@O³´´¼víÚ�!CŽ?ngg×ÖÖÆÍÞOž>>·nÝJNN–••ŪýÎÎÎ�;wnÙ²¥½½]KKëÔ©S'NĪñÁÌÇÇ'!!ï(Ø¢¨¨øáØ ˆŸˆˆˆÄÆÆÎž=ÛÅÅåÖ­[jjj)))æææýoùóç϶¶¶ÙÙÙD"Ñ××7""‚w–a°µµ9yòd�¯ÆÇǯY³àââ‚.lÇ›Èdr–_å4ƒñãÇô1L ÄæÌ™óòåK—ëׯ[XX˜››÷mdéÇ»víJNNnii‘““;qâÄÌ™31�¹ÏêëëëëëüøÑÜÜ,**Ú}fbàå¬ˆŽŽÆ|Å= •••)**¢�áÅgâK222W¯^ݲe‹°°pVVÖœ9s(JHHȳgÏØ¬]YYyèÐ!SSÓqãÆ%$$´¶¶®X±âõë×<•iii666óæÍ»rå  ¤¤ÄÐÐÐÈÈÈÁÁpòäÉÒÒRccãÇS©ÔÂÂB}}}}}}ƒ¢¢"´ …âáᡦ¦‡ç'áðŒ‚ø�@ óöö>|øðž={JJJ""""""ÄÄÄ444TUUÇŽ+))I&“‡ ÒÜÜL§Óétz]]]^^^QQѧOŸÐ"$$äàààçç7a¼?S.\¸�œœÜÞÞ¾nÝ:[[ÛuëÖíÙ³G[[� îèè¸sçÎ{÷îâââ¼¼¼bbb´µµŸ>}êåå…Ö›ª­­ 6l˜ŽŽÎúõëñý8|&âod2yÓ¦MëÖ­ËÌÌLOOOOOÿôéÓ£G�=zôë7Š‹‹›™™Y[[[YY 6Œ;ÑöVUUUnnîÒ¥K¯^½ª¯¯///×ÖÖô8ÛîË—/è«Ó¦Mûúõ+ºqèСòòòó`L 4 Μ9sæÌ™qqqUUUEEEÅÅÅ555���õõõ¢¢¢d2™L&KHH¨©©Q(eeeÞŸ³vþüùmÛ¶999.^¼(//ÿìÙ³©S§2 47t:5jTNNzÆ€®K àý�Ék`b€ �fĈ4�F£áΜ9“ššŠ>655]»vmll¬››‰DRTT.**rqqQVVÞ³g�NǶ#IIÉ{÷î]ºt)$$„¹¯±---544ÐÇÍÍÍ{÷îUVV dV£ë-ƒáëë«§§g``àëëû³ÏÏ~›½ÚAØX»v-:Áõùógooï1cÆc~-//ßÐРP(+V¬°´´ì±J§ô¤�‰N§ïرCIIiëÖ­õõõ½m0&&†H$>~üøáDZ±±=îA¿akkëèèø³W™ß ... CTTtË–-,kjj¶mÛ6vìXOOÏ>`ÕWAAÁˆ#Ðö}}}¯_¿ŽVIzôèQLLŒ——&½ØÛÛOŸ>ÝÄÄÄÔÔÔÜÜÜÒÒrÞ¼y ,X´h‘��ݲe˯\¹"%%Åòƺºº°°0%%¥¨¨¨¦¦&ö{LMMefÿ³gÏ¢�©T*ú@CC£kÝ@…Bqvv¦P(èØZ×=Á‹ öâ“#ñžââbôoþ·{ÖÕÕ™™™Í˜1£©©©Ç&Mš„UTÛ¶mÌ�;—F£éêꢥú”””F�5lØ02™,((ø‹o"‘hoo¯«« xüøqßb=z4�F›>}znn.‚ ***èö‰'2÷¡P(1114Í××·o½üñÇLJHÉÈȸ¹¹:ôÛ~©Tj×§èæQ]]ùïÏTVV¶¬¬ìãÇ�&&&Ý÷DØþ@o½UTTDÎ|† þ†V¥nnn¾r劭­mII‰››�@PPPHIIa0.[¶,...55]€@ $&&R(…B122zôè‘»»;;ÅGkkk»NHfA �žîJpvvÞ²e‹­­m?>îÿ]c`>eÖÅc©’äååÕÿó†ÔÔT‘În:::˜�étº··wccc÷·�5ÊÇÇgåÊ•ÞÞÞlö(&&V__/!!hllì¾°O÷ÿ[2™¬  ¨©©ùõžìƒ‰‚ø÷«R«««oÛ¶MøDDD˜�ïß¿oiiɲ?�@X°`Á¶mÛTTT°ÿüÿÉ*I“'O9rä¯÷ ëžÆŽëçççââ",,Ü«—,Y¹}ûv@TT”��º�H$¢%Ó«««Á¿ôétzyy9`èСÝ÷}Ê01@Ã¥*µ”””‘‘Q�/EEE±l¡Ñh‘‘‘èð&˜…�XžR©ÔîU’8­ºº:&&¦ë– &øûû;88üzTígÖ¯_ïçç§§§G$õôôÂÂÂÐíººº:::è·?³n ½½½””TPPгgÏöíÛ×}O–�Ù &âcbĈàààU«V õ¹)~©®®lnnŽãZ@,ck˜€‰‚ $$$ûøø 2ïX¸A– L a`Ë–-Ýçy `ágWà€2"A¾ø(+àUX‰�À3‚xË|½²²²•+W677#’��pùòåÔÔTiii“ÐÐÐ;v0Ÿ.\¸°Ç©|ºººß¾}C/Æ@?ñ+ƒáçç÷àÁ"‘¨¯¯¿sçÎsW Ë|½µk×FEEihh|üøÑÝݽ´´4==-8vìóé¬Y³ºOåC +©ªªâü©xL į˜•8ÁÁÁqqq6lÀ;(Œ±Ì×{õêó3¶µµ%%%EGG777;::ZXXt}ÚãT>)))˜Øñ«ÔÔÔŒŒ ô±¿¿ÿ¬Y³Ð/M*•ŠÞ¨¡¡qñâÅ®c/héÍßîÀ;XæëQ(”½{÷N˜0ÐÞÞÞÑÑahhØÔÔ¤¥¥eaa¡¥¥Å|ÚãT¾þL=T`b€ ~ÕÜÜŒV[�ÉäWLc{¹uëVowÀË|½ýû÷{zzÒét‰D£ÑrssZ[[W­ZX¼x1óéÌ™397•oÀƒ‰‚ø;•8YÆ^z»î(J×ùzŠŠŠ×®]ûÙΗ/_îúôSù _ƒ‰‚øK%Nt{×úšêêê]Ç^ØÜâ„ÏŸ?¿xñï(~Šy%ÀÄAü ­Ä©¯¯_WW§©©yüøqt{×úš,c/è k¿Ýâ„ðððððp¼£` L į˜•8sss===kkkÑÇXêkv{ùí¶äååÑ…6yßèÑ£L 4hiieggãôS������xGÑ m: AÔO¹¹¹xÇ𪪪bbbxGA4x L�:ïþ#//OSSï( ‚¯ÿ»Æ0mÚ4|ã¼zõª©© ï( ‚;‘HÌÉÉÁ; ¥¥•——‡wAƒ¼ø AýL AÐÀy á€ÇË òê 01@ï*//÷îݸqãðZ[[¯^½ŠUkîîîX5a&âEŠŠŠ3f̸{÷®¶¶öÕ«Wõôôð�§¡¡aÞ¼y�=>|ø’%KúÓ”šš�@À*0ŽÄ;|D"±³³ïHþï®$8�‚PmmmçÏŸ'“É/^œ9s&^‘üøñÃÂÂ"''G^^þöíÛ'NÄ+ˆ;àÅgâQBBBgΜY±b�N·²²ºté.aTTTçääŒ7.33f…Á&â]$éÈ‘#ëׯoiiY´hÑéÓ§¹ÀÇ��ŒŒ ¨TjffæØ±c¹„ ˜ ˆwµ¶¶ÆÄÄ„���öövGGÇÇs­÷ׯ_½{÷nÚ´i÷îÝ“••åZ×¾`b€ ^ÔÙÙ™œœ~üPQQøøø:tˆ@ ÄÇÇëéé½yó†C½·´´lذÁÀÀàßÿ�5kÖÍ›7Ñe¥¡Á&â!™™™úúúóçÏõês#óz¯»»û£G�”••Ÿ={¦¥¥uìØ1ÌxõꕎŽNll¬  à®]»nÞ¼),,Œy/�ƒ‰‚x‹/,--i4ÚãÇ�»n'‰ãÇ�g>ÕÕÕÍËËstt¤Óé®®®‹/®©©Á$Aâãã§M›öòåˉ'>~üØÇLJH„_ƒü©CÎ>|ø`oo?eÊ”×^VPPíºEBBâĉ§OŸ–””<þ¼ššÚÁƒÛÚÚúÃýû÷���===›››ÝÝÝsss§L™ÒŸ!¾áæû÷ïk×®UUU=}ú4ƒÁèqôCwK—.}ñâ…žžÞ—/_Ö¬Yƒ^ .**êUÍÍÍqqqcÆŒ166ÎÌÌ”––¾xñâáÇÅÅÅ{ýa –Ä€ |466üº>Ä/&”)(( 2dÈâÅ‹ÕÕÕ)Š‚‚‚¤¤$™LE¤®®ŽN§×ÖÖæåå¿}ûöÂ… ‚†îåååéé9tèPì?*Äo`I Âßׯ_KJJ^¿~}ðàÁ‚‚‚®/%$$xxxü¶…¿þúëÆ�çÏŸ¯¯¯ïþ*‰Dêño\@@`æÌ™666...ð0ú?ðW‚ð''''''G§Ó „…… ³ì3›%(-Z´hÑ¢ÄÄÄ7n¼}û¶¸¸¸¨¨¨¢¢¢¶¶–N§755„¡C‡Š‹‹KJJª©©©ªªR©Ô¹sçÂ|u×‹ß —¤¤¤>ô¿fÍš>¼‚�ŠŠ 777@TTÔÛ·o÷ïß�nÿÙ5† –í Þ_±¯¿+}Ë €øøø¾½‚ A\\\ªªªÌÍÍ×­[L&“RRRüñGÿÛ‡Yê•^üºP©T…BñððPSS‹‹‹C·S(ggg …rçÎæn ÀÉ“'KKK���¹Yã‚øK\\Ü�7FŒ‘””D ddd6nÜØG‚ ì‰D„ “&MBDVVöÓ§O���T*Ý.++[VVöñãGæn‚¨««w}ão¡÷M?xð€��!hÀxùò¥ˆˆ�@¸tésc]]ÝðáÃ�œœð‹ ¼z}ÝièСòòò‰„n!“É –˜‚ôªe:�Ø·oŸ��Ao£‚ >ÕÒÒbooßÒÒ²jÕª¹sç2·KHH¶´´à4hõzä±û=×t:½¼¼¼¼¼½šH$Òéô/_¾TWW£;°™!ÐLsþüùÌÌÌÞFA|Êßß¿  @EE%::šå%OOO\¢‚9 .IIIIÍž=;((àáá¡««Êœ)cbbbiiyêÔ©_·ƒÎûg0®®®MMMý ‚xÜÍ›7ãââ„„„N�:%&&Æòª���®®..�AƒܨTjaaaÿCA'¸Mœ8ñõë×7nܳgOÿÛ„ žUUU¥®®þíÛ·¨¨(___¼Ã� ÿ�çnbÛ²e‹  `llì£G�ðŽ‚8ÈÍÍíÛ·o3fÌðööÆ;ú &§ L'Nô÷÷g0+V¬€WÞ �êСC—.]’––>~ü8œdñ^ü� ¦R©¯_¿ Ã;Â^IIɦM›‡=z4Þá@+^L BBBIIIÑÑÑ999x‡AXjkk³··ojjrqqY´hÞá@Px11¦N�êããÓÙÙ¹bÅŠÖÖV¼Ã� Ì„„„äåå�7.66ïX ¨g<šaaaªªª¯^½Úºu+Þ±@6þùçŸÝ»w ¤¤¤ 2ïp ¨g¼›DDDŽ;F"‘¢¢¢òòòð‚ú«¦¦ÆÉɉÁ`„††êèèàýï&€®®î† :::\\\ú¹¤-áÎÃã¼¼ÜÐÐ000ïX èWx:1ÂÃÃ'L˜ðòåËíÛ·ã õ]rròùóç%%%Ož<ɬ3A¼‰×ƒ¨¨èÑ£G‰DâŽ;^¼x�w8Ôïß¿_¿~=àÀ�cÇŽÅ;ú ^O CCõk×¶µµ­X±¢££ïp ¨w:::–-[foo�w8ô{|�Û·oWVVÎËËÛ¹s'Þ±@P‡ggg+((À¥ !~Á‰A\\üÈ‘#!<<üÕ«Wx‡Aìzøðá¶mÛH$ÒÉ“'%%%ñ‚ØÂ‰`ll¼jÕªÖÖÖ+Vô§,qM}}½££cgg§¿¿¿‘‘Þá@»ø&1vîÜ9vìØœœœîKš@òôô,--ÕÖÖ†U¿ þÂO‰aÈ�!‡&aaa%%%x‡A¿ræÌ™””2™œ’’"((ˆw8Ô ü”¦¦¦nnn---®®® ïp ¨g?~\³f &&füøñx‡A½Ãg‰°k×.yyùG�Ádoêìì\¾|ymm­���««+Þá@P¯ñ_b�””ݲe ‘H<~üø°aøÙu}}ý_ý•ŸŸ_\\üæÍ›ººº®)aÈ�!’’’ŠŠŠªªªZZZS§N�2e 7à¾ËËËCØðãÇ999À¾}ûØÙ‚¸ ¡¡½¢àããõNëêê"""TUU{üƒ•’’êñ¥¡C‡zzzææær-Tˆ_–/_ιoù>غu«‚‚;{^ºtÉÚÚšL&¿|ùRQQ‘Ó�AÐo¹»»9rDCC#;;[XX˜ÓÝDFFž;w-#""âàà ªªªªªJ¥R%%%%$$˜;Óéôººº×¯_¦¤¤Ðétô¥Ù³gÐh4N ñ ‚ xÇÐw§N�š1cFFF�@À;þF§Ó¿ÿ^YYùýû÷†††Q£FÉÈÈŒ9røðáðÿ–.\°±±}öì…Báh_mmmÁÁÁÑÑÑ ƒD"mÚ´ÉÒÒÒÈȨWê¹¹¹—.]ŠŠŠjii,]ºôàÁƒpz6xŸ²ôË¿ÿþ+##8xð ޱ𙖖–›7oúúú)**þâ …@ üñÇêêê666III•••xÇ΋¾|ù‚^Q8pà§û*))ÑÒÒB4îîîUUUýi­¡¡ÁÛÛ[@@0vìØ`'Ä¿ø;1 ò÷߆ òñãG¼cáOž ÌÿÊÊÊäååRRRgΜÁ¼}¦û÷ï�3 ))ùìÙ3Îuñ²�pÆ8{öì’%K$%% »nÿþ=<<üÀ�úúú?»«�ܺu«¼¼üúõëæææ6{îܹ 6|ûöMHHhóæÍAAA"""ýo6##ÃÝݽ¬¬ŒD"­Y³&""‚s_ß’’’èMúÝGÀxJYY™§§§††ÆóçÏ1löÅ‹³gÏþþýûÔ©S¯\¹‚^Wã:�nggwíÚ5QQÑ¿þúkΜ9íâA$1.\˜––fiiyåÊ•®ÛKKK÷ìÙƒ È�8€V°áM–––×®]Ã01|üøÑÝÝýöíÛ€éÓ§'$$`››››ÃÃÃwïÞÝÞÞ.++{ðàAkkk ÛgBC}}=¶ƒ'˜{ùò¥ºº:¶‰!;;{Μ9555sæÌáZjd0ëÖ­‹��JII±µµÅ°ñªª*+++ ä ^˜¾Ž O IDATœÏX°óíÛ7iiiÀñãÇ»n·±±155E‡’¸pÇH ‡fX %]»v ½õPZZúÈ‘#œ»(ZPP```€þ:­^½º­­ ó.Ðs‘úúzÌ[ƺ,9†CId2`kkÛÚÚŠU³lò÷÷�H¤£G�bØì—/_ðù²ë=### ?8Àû3üñGll¬££ãÆ�MMMeee÷îÝûûï¿'L˜0a¼äªÝ»wûûûwvvZ[[£ÅŸ9וJÍÊÊŠŒŒ =xð`IIÉùóç¹\ b@ºté’��]KK‹‹‹Kbb".ò³Ø±c‡„„D`` ››[CCƒ——†��9òêÕ«6ˆ­üü|www¼£ÀÞ™ csçÎX[[#ÒÑÑ¡®®}ª££óáÃ==½Ë—/s­ë&55ÕÁÁ¡½½=$$$&&ߙ瞞žIII¡¡¡~~~8FqÍ@K rrr{öì¬[·.((ˆ¹½¡¡¿ ¸$77wÚ´i�?VTT|ôèÑüù󹃬¬ì½{÷æÏŸ‰ ”»¸)&&†Á`Œ9rõêÕxÇ666èm GŽÁ;ˆTbhmm-,,9r$…B©®®®®®f¾4àí[· >þL£ÑrrrÔÔÔðŠDDDääÉ“;wîXXXÀÜÐ[è)Bee¥‘‘QYY¾ÁÔÖÖΞ=»  ß0 nâûÄPWW·dÉMMÍaƉˆˆ¨©©YYY±ìÆ,$9P=z´µµUPPpóæÍÇÇ;àââ2yòdÀÍ›7ÛÛÛñ‡Ï (Êû÷ï�ŒŒp\ἪªjÆŒ>D§×¡%• �¤dLLŒ¦¦fmmí/vðg ¨öööyóæíÝ»ß0^¾|©­­�ŸŸ˲öÇÞ½{MLLг@lg̱‰ÙµŠŠ Ëô h`ãûÄøã�?Ž;öäÉæÝôÝ øÄ€ÊÙÚÚ2ŒM›6­X±¢µµ—H.^¼h``PVV¦§§‡ùB}#&&võêUKKËÊÊÊ3fº ÞèÑ£óóó±³g��� .�H¤Ý»w£Ñ¢LýŸ²Û‡y £G�¦Ñhýì�}XÍc˜>}: ++ }ÚÑÑáêêŠþ߆„„pº&ö¡C‡ÐÊÞ³fÍ¢ÓéèÆªª*ÀÈ‘#ûß>œÇÀûaݺu\ûêÿ™ÔÔÔÊÊÊþ·#&&ö矺ººnÞ¼ùܹs‚ðWÁ…ººzNN΢E‹²²²tttüýý8ºÒdFFÆêÕ«ß½{'))yæÌ ÎõÅ&IIÉ{÷î•——ÛÙÙÍœ9³Ç} ›Kž±¿''�H¤#GŽLœ8Ñßß?<<üöíÛ§N�RRR¼£êêjww÷´´4@@@wjªC<ŠH$â�ŸA¦L™°8cè*33m5HÎP6l@/ÿN˜0áîÝ»ØEúÿ}ÿþÝÞÞýïUWW¯¨¨èú*Žg “&MBP©Ô#GŽOš4 =P@DUUÕÅÅÅÜÜ|ûöí“'O666þóÏ?KKKMMM Xöd§S�10eee¡ç‚'Ožìg/,îܹƒN\:tèÙ³gY^…g ƒÊ¿ùÌÈÈèéÓ§ÇŽóòò$“Ÿ™H$ÒÞ½{mmm=<< gΜ¹|ùòÝ»wcu3+‚ G�õóóûñㇸ¸xXXØÆ�yívÆ‚‚‚#F,[¶ÌÕÕõÇ�fffh¡Ðšš___UUÕñãǧ§§S(AæÎ�¥¡¡�V¥½uëV×=ñþ(`hh˜ŸŸ¿jÕª³gÏ:::¦¦¦žhii655iiiQ(”½{÷¢…x™“òxs�ÝÉÉÉÒÒÒÇÇçøñã;wîŒ��555µ¶¶ž7o;7õ544\¿~===ýÊ•+õõõ™‹/¢Ë>ó ´´4›æææ+W®ØÚÚ–””¸¹¹…”””“'O–––/[¶,...55uåÊ•��˜˜H¡P ÅÈÈèÑ£GîîîëׯÇåSÌŸ?ÇŽ¸tͦéÓ§£Gƒ%1ôS�W2ñ½ Ù[JJJ7nܸråÊþýûoݺE$ÍÍÍeddFŽÙõ_2™üõë×ÊÊÊïß¿£ÿ~ûöíúõëÌkørrr^^^è’+𿺄›`b`K]]�±±1‚ h")))ô6•W¯^mذݧ­­-666--M[[;** ÏpÙ&((È s ¬ Ãî éÇzæÌ™ÔÔTô±©©éÚµkcccÝÜÜH$’¢¢â‰'&&&–––è-±±±îîî�H$Â:á}[º^É]ÎFY.W b»ü!Aè B(eeåëׯX*G1Kû ³j?~ÌÒsH0??Ÿs¡01ôËþýûùèr%A;`b` ËHæSEEÅ^]¼…xDjjjTT”  à‘#Gp\Ôh Ad°�㣃xGÁ|s `�ÿMtÂÅÞ½{?~üðáC´ÂÔW®\ ¨¨¨À;î¹{÷îúõë¿ÿŽw ؃‰�w}ÿþ}ÕªUèdÚ�‡@ „††.Z´èÍ›7Üゥ©éÁƒèœjîôøöí[îô… KKËk×®)**®Y³æÃ‡x‡Ã fffÿüóϸqãBCCÑy‚L ¼KFFfذa¦¦¦h� ¼#˜··÷… ¨Tª§§'7»þý÷_!!!t-×:Û°a�F»yó&×:å&"‘¸mÛ¶–––ƒNœ8ÑÞÞþåË—êK^^ÞØØXSSóÎ�;ê‚aóæÍt:=<<\YYyÏž=---8ƃ!>N ;??¿‘#GfddÌ™3GMMíèÑ£æ7@¡P,--ÛÛÛãããÇ�÷çŸrgin�°°°yóæUVV£h9-<<<++ËÜÜ|Ú´iiiiÜé”›¬¬¬Ð Z§OŸÖÐа²²zðàæ¡w ^ºt)$$„¹—ÿÏ%K– £‘ÿþû¯··÷„ Ž;ÖÙÙÉýH°ÅljáóçÏöööÿüóÏÎaaaèãW¯^¹¹¹�;6<<|À,§åããƒ> Óé[¶l?~üÁƒ™uŠ8äË—/JJJ^^^Ð××_¼x1wf{M™2ÅÆÆðìÙ³… Nž<ùÔ©S\èškºÖBäêÕ«FFFFFFW¯^Åüï´k%‚+VXZZêëëëëëaÛ]�½½½™OËËË]]]ÕÔÔ.\¸Ð·ÏË`0|}}õôô |}}–íâããÙo³W;£ø81ÈËË+))͘1CMMíàÁƒÜ9ØdÁ…ƒ”•+Wv­¯òýû÷ÐÐP…Õ«Wã2:�-�†V/@UTT¬Y³†J¥öùö÷÷700ˆŽŽ^·nÝéÓ§kjj8Ô‹­[·2'Á¼zõÊÁÁAEE%11±­­­o ÚÚÚ:::þìUæ7‚‹‹KßÚï-###´HpW<°²²ÒÐÐ8}ú4†‰�¥Áõë×Ñ*I�=Љ‰ÁdFƒÁ(**z÷îݧOŸ***jjjY\\]]Y ÛØØèêêöa¤+&&†H$¢wF ÇÆÆö¸§ü\v›N§�=ý’’’^^^¯_¿îqOOOOÐ�²ÛªªªNNNªªªÌu"Ñõ[F�­§§§§§§¯¯ÿêÕ«¾5Îô³²Û/^üÙnÞ¼y÷ïßG~YvGhÙmOOOŸ���íÛ·ïÝ»7!!!99ùìÙ³—.]º}ûvDDD�ŸNOO�Ywºe·qÁNÙíåË—wÿ°£G�މ‰illD÷ùmÙm7‹Q£E7‡¾páB+++333ccc}}ý©S§Nžt�ΪSWWÿÙ‘��>|ø¨Q£~±$†©©éÓ§OѲÛÎÎοíwÚ´iuuuèㆆô1óG©®®~âÄ 111�vèÐ!¤Û·S×=aÙù×Ðìß¾}û¿ï—^ÿ·q@ßÖc8}út×�@˜={öåË—;;;»îÖÏÄ ++[VVöñãGtËüQTT4cÆŒ'Ož ’““3kÖ¬¾5΄&ô˜ËØØxÚ´i eìØ±#FŒøõX‡²²²��àÕÄП�kk뢢"þJ jjj—.]ºpá¹sçNŸ>}âĉcÇŽ>|8>>>66600ðguÜF޹}ûöÚÚZ6Crrò¡C‡bbbЕ銋‹ ííí‘ÿ~#Lš4©   ûAŒªªêÊ•+©Tjllì¯ûb&†>ÿ(¢¢¢>>>è4 þ$–„Ç|ÚõïÑÔÔ´Ïí#ÿK T*u„ ²²²Ã† 2dˆ��P¯>µ””zàÏNb R©]Ÿ22X¾î»þ°|;±ì‰ôæø€™z1Á­ÏK#1Wâ„%K–ÄÇÇ3/p!róæÍ›7o*))­^½zÅŠÒÒÒýï…L&£—˜˜ch¹¤îuû_.©k€ß"‘HÎÎÎ[·nõõõýíÎ ÃÏÏïÁƒD"Q__çÎ�Ü[�‰‰ikkkþŸ–––æ.jjjÐã¾ß›››‹ï�'}ÐÖÖ6oÞ¼>¼±²²200055•ÍbæÜ/FM .\¸ ôsÂÂÂAAA‡fy£€€€‹‹KhhèèÑ£™O1‡y•¤!C†dfföøR[[[[[[kkkCCƒ��A�jüøñ¾¾¾Ë—/?{ö,›=Љ‰Õ××£GB���è¡UWÝÿRº;ýlOöõ"1ôyÁ<Ž&�;mÚ4–áþ>øúú†……-[¶ =]è:�^^^`ž3¢}Ýë8zyyõsp3((ÈÀÀ@\\\LL ý·ººZ[[»û­æææQQQìOÜe_‚ƒƒãââ˜9ÊÃÃãY¶¶¶Ïž=ë¾}êÔ©>>>666AAAœ c$iÞ¼y‚‚‚=iooOLLìñ»¶¶vDD„©©)�Fûm/¸£& ,øuT))),o±µµ GKŠaâg•¨Tj÷*I‚&B2™|üøñîYaÊ”)~~~666½­ò½dÉ’ÈÈÈíÛ·¢¢¢Ð‘‘H¤ÓéuuuÕÕÕà¿_ú,ßN,{‚>eˆ^$*•ZXXØ}!$ …¢­­�““³oß¾™3g¢»444òóó».®„.«ô[���õõõ555µµµµµµ,ºoonnþYSMMMGŽÉÏÏGÇ©ú ­SýìÙ³}ûöuÝΉ:ކ††æææ]·ìÝ»—%+¨««ïÚµ«·‹«¤¦¦2ËôûûûÏš5 M ]d/^ì¾ÂÄowè³'Ožüý÷ß]·sss___“þ´Œ#!!¡ôôôŸ½Ò=+¨©©mݺÕÚÚšýª¼YŒ:66¶ëâêfffÛ·o×ÒÒ¶ÞQ__ϲ(›‰‰‰¿¿¿™™Yß\¿~½ŸŸŸžž‘HÔÓÓcÞ”èáá¡«««££ƒ~û3«ÉÚÛÛ³|;±ìɲs/Baó:P%++ûéÓ§ÆÆFæXV#\èw7™Lîí¥ˆˆº qwcÇŽý믿�~_cÀ|EÙõxñ¹¦¦¦ëռѣG'%%±\AAØ»øÌ2|©©©‰>èú#³´´|þü9‚ eeeÌQÚßîð3¿]ó¹ëBBBNNN/_¾ì¾[ß®1 —(ÑË�Ìá]ô³phõïß^|®««“’’êú+:~üøS§N±ü@Ù¹Æ`hhøùógôñ»wïÌÍÍ_½z¥§§ghhèèèˆn÷ôôœ3gNJJ z�AWW½²¸¸Ý¡û_ëϰ³æs}}=óËHWW÷îÝ»=îÖ‡5Ÿ¹�Í5Ÿ™)ˆDâüùó³³³{Ü�ý‹Ï}€á·S_®1 ºŸ{b;Â…V*•”””’’:t¨””Ô/ ÿÒét4¤®ÄÄÄüýý}||~–3øÅáÇћµ‡ âçç·qãF11±¾5ÅÎð%Ë ½Ý¡W._¾ŒàJHH¬\¹ÒËË‹y�&XŠ¥wõÛáM­ÛzàÀ�ÚÚZôñ˜1cBBBœ��™ë)ö £NHH¨©©™4iRDDD¯Î~øTeeåÞ½{ííí7oÞŒ®Ñ20ôú7²ûÛ®ÌÌL##£^…Óu>0�@X¼xñ®]»ºg‹>Ãk}Çööö}ûö ¸»»‡……ÉÈÈô§5–áKt²øï�L]]½ë lîÐ���£F�òòòZ¹r%§×Žfކºoš™™±ŒŒ1×mE¿j1ÔÔÔ�‘‘ ôððƶ µ¶¶¦¥¥%'';88 ’å3cbb\]]½½½1üªéN|;aPvÛ®Þ%uvv&$$0ŸjhhÄÆÆ˜(Ïž=;eÊ”ÈÈHLFÐáK}}ýºº:MMMôôü÷GÖã ¿Ý¡=zäããcooϹÂÅèº{€µk×vÝÞõv�2×mÅ<ôšóöíÛׯ_/..Žyûø¢Óéè oxÂ=¿ž´Á¿z‘мÔýÜ“H$¢«ë¡<==YîbžÏrÂåË—?~ü>|xxx¸»»û@:Z111qppÀª5‰´{÷n@nn®§§gmmí°aÃ@·Y÷&~»C •úßÎ/tJúYë>2Æ\·[‚�H¤�?Ô¯ôw‰/`5N8P”`,Ô³ÿ~�Õ«Wÿù矿˜ȧ˜w�`KKK+;;›-ó æð&Ë⬀í7{‹@ °œ¸@ì())qssCײNII)++ë:ôwùòåÔÔTiii“ÐÐÐ;v0Ÿ.\¸½ ’@ $&&R(çÆ  ^ãï€ââb�ðüùó~Þ4ɺ˜ õ sx“gÅkº"—±ÌÚ[»vmס¿ÒÒÒôôt …‚fúcÇŽ1ŸÎš5«û„>Î�0ü}Æ ..Žþ¼±R†®‡,ÌÇ胮Û,#c8èô ^Ó¹ŒeÖËÐ_RRRtttss³£££……E×§=NèãÐ8áÀÃ߉a̘1œh¤@¼�§+rˬ=–¡¿ŽŽCCæ¦&--- ---æÓ'ô ¤ �Å߉�CàA Äûš››™ë’’Éäç”°Óܺu«·;à.66ÖÍÍ�D")**ž8q‚eè/77·¡¡¡µµuÕªU€Å‹3ŸÎœ9óªƒL =€)ïãµéŠB¡PºÎÚSTTüÅMq—/_îúôú _ƒ‰¡ð â}<5]``bè¬4ƒ£�œ***–-[öÏ?ÿà„'–BñÒÒÒååå¡®®î×{v/£AƒÄ€M ÷îÝ[ºtiEEÞ�pÕ¹sçlmmydæD^^.ÚÌ¡$@׺¿¨€€33³)S¦t?c`ïØ�­˜ Fdddhh(Ë:É›ƒƒÃ_ý•––6{öìsçÎIKKãOLLŒ��ƒÁ011éÛ e}†.ÅÄR(ÞÔÔ´¸¸øÓ§OK–,aÙ‡eÏ_ߦ AØ@+ÇX]]mee4¨²ÀÂÂ"33SVVöÎ�;:::ÅÅÅxEÒÚÚêêêºqãFƒñçŸÞ¹s‡§ª~>zôˆF£™››3Wë… ˆÅ€:cÈÎζ³³ûôéÞ�àCGGçéÓ§óçÏö왞žÞ©S§,--¹Ã÷ïßmll>|(..~âÄ ¼ÃÈÈèþýûxGA<�‡åúA�˜˜�6h³jÔ¨Q™™™K—.­««³¶¶Þµk7{ÏÏÏ×ÖÖ~øð¡‚‚ÂÇy0+@ÄŽ�pÆPWWçêêú÷ßÐ:E�@ Î;IDEEO�:E¥RCBB6oÞœ““süøq111N÷»{÷îÀÀÀöövCCÿÿþ{äÈ‘œîqÀKLL400`¹W /©©©Ø6øåË!!!lÛÄs�¿ÁI€ /¬!S__ß·72$55•H$vË633»}û¶””Tmm-Fò �H¥RÑ+Ò÷ïß�ŽŽvppàÐWLIIÉêÕ«Ñ©®®®ñññ¼üÏ|}}Ÿ=MSS311±±±‘£qv5˜‚ ¥¥¥èÒCãÇ�/**¶ñî¾~ýŠ–ž•––ÎÎÎætwh#}‚¬^½zøðá]·£OÿüóÏØØXœBû½/_¾p¡CCCCCÃÄÄÄ»wïfdddggþüùëׯ?~üøñãGIII÷·HKKËÈÈŒ?ÞÊÊÊÒÒRNNŽ qBLcÇŽÍÉÉ¡Ñh………šššÛ·o߸q#‡î1;þ¼‡‡GMMͨQ£}jooÿöí[11±½{÷®\¹“f!~…÷Xf^½zE$EDD¾~ýŠw,Æ0¹‰™k0¿ÆÀ¢¢¢ÂÜÜíkþüùÅÅÅýiíóçÏNNNhÆÕÔÔìgkÐÀ0pÎìííOŸ>½nݺ¸¸8¼c�0†^vÆ;Šž577«¨¨tttûsÚÛÛoܸqíڵÇ£ë®Y³fïÞ½pÖ:ÌPÒ›7o(Š€€À»wïÐ{û ˆkЃccc.×ÿöíÛž={:ÔÐÐ ‰***ªªªT*URR’L&‹‹‹ ÕÖÖ666ÖÕÕ½~ýº¨¨¨¨¨èÊ•+hiz!!!{{{??¿‰'r-rˆÇ �ÄàäätâĉU«V¼Áâk|ŸÊÊÊ&L˜€ Èëׯ•””ð¼jkkÕÔÔ>þ½iÓ&¼Ã� ¾ãûãš;v´··;88À¬áKJJêðáÃ!88¸Ç äÄ/øûŒ¡¼¼|ܸq���ÅÅÅãÇ�Ç;îîîGŽÑÕÕ}ðàî ì@Pßð÷ÃÎ�;ÛÚÚ–.] ³Ä#¢££ÇŒ“��½{÷n¼c� >âã3†/_¾Œ7®½½½°°PEEïp èÿddd˜™™ åææNš4 ïp ¨×øøŒa×®]---¶¶¶0+@CCà 6´··;;;·¶¶â±…ÏÎjjjëêêž�û�AP?={öLOOA�ÌÌLxÊ ñ2�@HKKÃ;àííýþýûŸ½_]]M£Ñ`V€øÔÔ©Sýýý#""\\\ž?.&&†wDÔ3€H$²¿†8çhiiåååõxÆÐØØ¨¨¨XUU•‘‘1sæL\ƒ þkkkÓÖÖ~ñâņ öîÝ‹w8Ô3þ¸+)!!¡ªªÊÀÀfˆ¯ %'' ÆÅÅeffâõŒCss3ºæIHHÞ±@Pihh3Œ+V466âõ€ÃáÇ+**tttfÏž�w,„�€€€)S¦¼ÿÞÏÏïX ¨¼žZZZÐ{ûàé4` &'' ÇÇÇß½{ïp ˆ¯'†£G�~ýúUKKkΜ9xÇA˜QSS CÄÕÕµ¡¡ïp è?x:1´µµíܹB ðÜ” ê___mmí²²2Ÿî¯^¼x‘û!AЧCRRRyy¹ººú¼yóðŽ‚0& �œœ,""’˜˜xëÖ­®/UVVzxx0 ¼bƒ9ÞM ííí‘‘‘ž.@—ªªjxx8‚ nnnuuuÌí¡¡¡•••ß¾}Ã16h0ãÝÄpâĉ²²2*•ÊkÕœ C7nÔ××///߸q#º¥°°ðÈ‘#€ÒÒR\Cƒ/M ;vì‰<$õ‰DJJJKJJºzõ*ÀÛÛ­D„ýÎ=uêÔû÷ïUTTlmmñŽ‚8k„ Û¶m¬\¹òܹsÌë 01@xÀ;€tvv¢ ]ÁÓh0X¿~}ZZZffæÊ•+™û–>þüúõ놆:�N§ÓÛÚÚ¤¤¤Èd²„„„’’’¢¢"¼bý/&†³gϾyófüøñK—.Å;âƒñåË—Ò.šššB×KÐl&Až>}šžžž���™™ÙÑÑñ‹�‰D¢‘‘ÑäÉ“­­­i4š€/~@¸ã¹_ ƒ $‘Hx‡AØc0Û·o�ŒŒüu­¤ß&†úúú˜˜˜C‡}ýú•¹QFFfòäÉäÿª­­¥Óé ÅÅÅååå÷ïß¿ÿþ¾}û–/_¾}ûvl>4�‰D„L™2€ÎhSRRjooÇ;"â ¯_¿º¸¸üb°”D"µ¶¶öøÞ¶¶¶ˆˆæ¡rrr^^^¿ý«éèèÈÊÊ VSScöâììüùóg|Dˆ_ñ\b7n 11ïp ˆòòòŒ��–Þ¾}Ûý-Ož}¢Ñh謯¯ïÏF™ú€Á`ìÛ·˜RUU}þü9V-C|ª‰ý~WUU]¹r%•J���E·«ªª:99©ªªfdd ]Ò€ºº:‚ 'Nœ£Ñh]Å{¤¬¬ �‘‘iiiéóç� ¾VUUµvíZæÍBþþþèö+W®HHH —Ð?4Ì „„„8ÑÄ/z±æ3•J-,,”““{òäɰaÃttt ÐßÔÇ�ggç»w444òóó™oümû&Lxûö­ŸŸZ" ‚­ââbŸk×®ÙÙÙ¥¦¦ÆÆÆnܸAkkë#GŽ >œCý¶´´lÞ¼yÿþý‚¬^½zÿþýšH´k×.N4‹¹¡C‡º¹¹áNzuÆ@¡PЧè ‚ ãÇ�Ghhh ]Î&OžÜõ�¿…%=yò„½”AÜÍ›7W¬X±uëV�@ˆ‰‰áN¿×¯_888pâæ@>ª;nÜ8Ì?>_èõ<†îÓ&étzyy9`èС"‘H§Óëêꪫ«ÑtÄŠ=è…5‚LMMoß¾* pôèÑåË—s§_ssó[·nÍ›7/%%…N§§¦¦ cÞ �@ؼy3æÍb¥¶¶öСCxG� &¸III={ölß¾}]]]4OLLL,--—-[fooßÿî h0`0«W¯>|ø°°°ðéÓ§.\ÈÍÞi4ZFF†……ÅÅ‹çÎ�›––&..ŽmD"‘—�?|ø0˜ý¾+‰Í‘¢ßB‡’0¹‚øZ[[Û²eËbbb7nÜÀ+Œ‚‚YYY€��AMM VÍ¢CI$ «9áýû÷`%ÁuÄ[ZZZ-ZtúôiIIÉ›7oΞ=¯H¨TjffæØ±c>|8cÆŒªª*¼"�¸ìÿµwïAM\]Àï AñAkÆJÀ)"O‰Z@¡ˆ� â«€óçÏ/_¾¼»»{ÇŽ\.Wõ Ab@MmÚ´)--MSSóðáÃDI • �˜˜¸víÚÞÞÞƒÆÆÆÂn ïµÛÁ @ d2™«V­âr¹ÍÍÍéééD± å‘H$û÷ï?zô(†a'NœØ¹s§R‡{OÔ×ן;wŽê(䉵æëë{ýúuŸK—.UTTddd�ê®±±1((èÞ½{ #99yãÆ�Jè}SWWwèÐ!ª£�—��$ÔÝ‚ JJJ***£££wîÜ©ðº§/^Ü´iŸÏ744LKK[°`�bûfff*+x5}êæævúôib[0''''''ggçêêj¢6›6kÖ¬“'ORùMh¦’PƒM%ɸ|ùòŒ3Èÿ®®®±±±·nÝjjjì#/_¾,**:uê”——¹{(‹Å:uêÔÐ;HS>•äããÓÖÖöâÅ‹•+Wâ8Îápˆ½úúúˆd�gKKKâ– Žã¥¥¥‡8Ïb±E"‘•••<#¾çSIpóZZ¶l™ŸŸßõë×/\¸�‘‘Q\\\\\L¼Åd2'MšÄd2uuuµ´´ÚÛÛ…B!ŸÏooo'?Žaؼyó¼½½###544(úrimm-++[½z5B¨ªªª³³³©©ÉÞÞ!4àøææfâÝ9sæ�·R'L˜`dd„Ró/«& 1@W†y{{{{{§¤¤\»víþýûååå555/^¼ …ýÛkkkÛØØÌ™3ÇÆÆfÅŠ ß{GI.]º½nÝ:„PbbâÕ«W�ŒŒ>|hgg'‘HˆÜ€K­þ344,--µ··ÿí·ß ‰“°Fï�@b€öÆŽëïïïïïO >Ÿ/‰„BaOO�¾¾¾®®î¸qã&NœHmœÃ“™™™••E¼^¸páÖ­[y<^pp°†††©©iZZ’Ú&!ÄãñBBB0 c0)))T†N[š!‰DbeeEu$¨¾¾žê ôôôôôô¨ŽBaÈ)2„�™™Ù�7B¿üò‹t›øøxâQïïÁƒ2��ÛÆüñÇÊ uÔøßCUUµq½äççÏœ9ÓÌÌŒê@OSÝRÂôéÓ©ðÎpßæñgÏžmnnîååuàÀ�Y³fQŽ"i²ÙlªcÐ^vvvEEExxø‡~Hu,*Âb±BBBx<^vvö²eËFSz€nðõõ½té’‰‰IhhhMM�RÇ222rss³±±),,Tê@oõÁH$’üÑÚÚzÅŠ•••#éP"‘ìÚµËÑÑÑÙÙy×®]Äš�þÈ•Þòx§ÆH ÐÔÔŒ‰‰ù矒““---—.]z÷î]%�5~üø»wïæææîß¿Ÿ<9Øo¨R±X,r¹¸BÒ—Ëe0<¸ÿ¾––�ǰ$=,]ºÔÍÍ !„ãx^^ž»»»��]fffoo¯2†322!6›½qãFooï‹a(qÑ@Ž0=deeíÝ»—x½gÏž .¯ÉG­­­¥K€ „ØlöúõëÙl6qý$ݽY/Dþ0`@aŽ?nooO.7+++ سgODDDppð¸qã8Vee¥��BˆÏçïÚµËÂÂÂÃÃËåKÛ"""nß¾=Â!úúú"##ßÚlæÌ™åååÒgˆô@Þ{�D±XLþ+1™Ìîîîþm‚‚‚bbbÈ ²ööö¯¿þðõë×{xx ÝXN� «+Vhkk¶5XBB–-[B6lPYÍQ;;»Õ«WgddHŸlllŒŒŒ<|øpHHȶmÛ¦N�:ÂQ:::ÜÜÜp�‹‹Céëë[XX ~Å0x<Þ•+Wìíí�;6¼�$Illì°ã$ÒCnnnrr²œÑÑÑéìì$rƒH$ÒÖÖ–i€÷Ûá•Édš˜˜ „ø|þÐ-å‰Z"*Q·µµ‰Åbé© ™•p?zôhWWWWW—H$ê’"}(‰üxGGÇwß}—””4ÂHˆ{ ä!YþH¦FDDDDDÄHÒÐÐ rÏÐ233KKKûŸ×ÑÑ Û½{·üsJŸþù·ß~{ôèQ„бcÇV­ZEœg0B¡°££ãõë×èÍ}¡PØÔÔ„š0aBÿ–hx‚ª2~€ÉY]õìÙ³III\.÷âÅ‹8Ž×ÔÔ8;;»¸¸â8ž––¦££3þü¤¤$KKËÊÊJGGGGGG''§ªª*¢ ‹ÐÐP+++�7ôXDuÕ‘ïÓ0eÊ”ÄÄD¢Hø»nÔ#�¬¥*sXYYéàà@<ÒSSS3ìþñw©®ú×_‘¥jI:::;vìxþü9ÑFþꪽ½½‘‘‘NNN‘‘‘dùØøøxKKË�7ÕaÃÃý¼¼ÒÓÓq·°° ²°°(((èßR¦ñÐÈêª�P/r&UV¢&ÃäÉ“÷îÝÍårOŸ>�žžž��}óæÍâââ²²²ššš†††ÖÖÖƒöO ºººøpwpS1ù¹ùÝ€)� Ô²Û2ir$ ì64FI%j ÃŽ92t›îîîÄÄDé36l8|ø0‹Å’gz©««#ïñ�GS¦L¡6ª‘ƒÄý¨m%êôôô/^�‡^^^111êP£SI¢££{{{©M d}@‚Äý¨g%jÇÉgxfÏž}üøñ (i,uPWWwùòå;vŒŽ«i� õ¬D}ãÆ�êêjccãèè耀€'µF“úúú††}}}ªQ‰úÉÊÊ*(( ^ïÙ³‡Ãá‰ÁÊÊŠxÕÚÚúêÕ«ÒÓñÄ*³·6P72ë3âããÃÃÃ…B¡††ÆüùóËÊÊAww÷¦M›B+W®$=<bé$èGžªý2ÓñïÚ(\UUUHHÕQ ¥¡¡�x‰ú‘©ÚïïïOœ—®ÅÿÉ'ŸHOÇËÙ(Oss3]&µ 1@?Û¶m‹ŠŠrrrêèè°±±ùᇈóaaasçÎ�0a‚Ìtü¡C‡äi”ÁÒÒòÌ™3TG!/ccc Áöo…sss+**ºwïž««ë[—••…‡‡ççç�|�!¼~ýzòäÉ/_¾yo8Ž3 �ÞÞÞ‘÷¦$õõõfffæææOž<¡: À4fkkû믿RmFç¢Ã‰À 1x$o€Äà �¼€7À:$I`` ÕQ J(R• 1 ŽÔjU°2*){D+¼[ �P/DÍÔÍ›7ß¾}ÛÈȈêp�@ @ÿlä0 ËÌÌTHWÊÆd2©�P+ õÒÚÚúé§Ÿþþûï&&&æææÓÖÖæååURR2uêÔÛ·oÏœ9“Â`€ÊÀÍgÔ‹��Á�;w\\\æÍ›GáÞ2---îîî%%%fffÅÅÅ�Þ�P;ãÇ�¿yóæ¢E‹ž?îææVZZªúçÍ›WQQaiiY\\S`ç€và/èaîܹåååëÖ­‰D!!!§µµuäÝvuuíܹÓÓÓ³¥¥ÅÃÃãÑ£G�$hCOOïìÙ³™™™úúú………¦¦¦Û·oojj^o|>ÿÈ‘#Ó¦M‹‹‹3fLLLÌ­[· 3 #˜J€~ø|~TTTJJ ŽãcÆŒqww÷õõ]²d‰±±ñ[?ÛÖÖ–ŸŸŸ““sóæM‘H„244ÌÉɱµµU~à€ 1@W555ÑÑÑ.\ +îikkÏ™3gÖ¬YzzzL&“ÉdŽ;¶½½]( ‚ÚÚÚêêêgÏž‘=p8œ}ûöÍŸ?Ÿ¢oÔ$è­½½=///''çÎ�;mmmomÏd2���}}}ýüü¦L™¢‚í@b`ôhii©®®~üøqgg§P( …===úúúL&sܸq¦¦¦l6ÛØØÃ0ª#jí?w´w‚ÝZNIEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/preserve_in_nat.rst0000644000000000000000000000013215132411300023042 xustar0030 mtime=1768559296.227885023 30 atime=1787067672.659456121 30 ctime=1787067793.876715402 rsyslog-8.2608.0/doc/source/whitepapers/preserve_in_nat.rst0000666000175000017500000000442415132411300022514 0ustar00rgerrgerPreserving syslog sender over NAT ================================= Question: I have a number of syslog clients behind a NAT device. The receiver receives syslog messages that travelled over the NAT device. This leads the receiver to believe that all messages originated from the same IP address. With stock syslogd, I can not differentiate between the senders. Is there any way to record the correct sender of the message with rsyslog? Answer: OK, I’ve now had some real lab time. The good news in short: if you use rsyslog both on the senders as well as on the receiver, you do NOT have any problems with NAT. To double-check (and out of curiosity), I also tried with stock syslogd. I used the ones that came with RedHat and FreeBSD. Neither of them reports the sending machine correctly, they all report the NAT address. Obviously, this is what made this thread appear, but it is a good verification for the correctness of my lab. Next, I tried rsyslogd on the sender and stock syslogd on the receiver (just RedHat this time). The machine was still incorrectly displayed as the NAT address. However, now the real machine name immediately followed the NAT address, so you could differentiate the different machines – but in a inconsistent way. Finally, I tried to run the stock syslogds against rsyslogd. Again, the host was not properly displayed. Actually, this time the host was not displayed at all (with the default rsyslogd template). Instead, the tag showed up in the host field. So this configuration is basically unusable. The root cause of the NAT issue with stock syslogd obviously is that it does NOT include the HOST header that should be sent as of RFC 3164. This requires the receiver to take the host from the socket, which – in a NATed environment – can only hold the mangled NAT address. Rsyslog instead includes the HOST header, so the actual host name can be taken from that (this is the way rsyslog works with the default templates). I barely remember seeing this in code when I initially forked rsyslog from sysklogd. I have not verified it once again. I have also not tested with syslog-ng, simply because that is not my prime focus and a lab would have required too much time. To make a long story short: If you use rsyslog on both the senders and receivers, NAT is no issue for you.rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue1.png0000644000000000000000000000013215132411300022372 xustar0030 mtime=1768559296.226885008 30 atime=1787067730.721538403 30 ctime=1787067793.860715103 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue1.png0000666000175000017500000000564315132411300022050 0ustar00rgerrger‰PNG  IHDR�ŒݾhÏsBITÛáOà pHYsêe¤ FIDATxœíÝLUõÇñ×¹ ¨ê ;Šh®™8q¶}ñGΡýnõ5\Φø‡ŽYYmèr+K0WÙ–Nfšß-Kú1ûåWÔ…n-$LóËïÔT² Lhö%Þ{¾\§VzÏïåœsïó1Ƹ»Ÿ{yöäsν\T^^.p�¾}ûš7?xðà%K–8=!\Ñ£G�›]e˜¦Ù•£@§ùœì"X<ƒ`ð ‚À3Ï Xp+ÓÔ¶m:~Üé9à"ñNü�iª¸XË—Ë0TQáô4p‚7 ´e‹ tô¨$mÛ&Ãpz&¸O…;úê+èøq†LScǪ¢‚`ázì°à4¿__|¡eËTY©¸8I þ]²D.È0nðæó]ù1†œP਎öûŸñ�Ñ�¨®îO×wXv„Ι‡®uí`]|mjª23C}à º†)s¿ö—ªô�ý¤Ÿ*UP`¥V.Ñ'³4ËéY‹:`ª¦Vª²JUÝÔÍéY‹8i »~Õ¯e*›§yÔ N!X°k‹¶˜®éN‚ØÅ!!욢)uª«T¥Óƒ v±Ã‚- j(W9Û+—;yR—/;=D$,زC;üò?©'�¡ôé£{îÑêÕºxÑéQ"ƒ`Á–ïõ}²’Ãów%1))ÊÎV^ž†�Îlq ¶ŒÔÈT¥îÔN§�…†¥¥éÂIêß_/¿¬ùóÕ³§Óc… ;,Xû]¿ŸÐ‰‰šèô °–’¢çŸ—aHÒÙ³ÊËSZZôì¶:¶ÃºxQO=¹aàRg2·U¼ö¯q¯”ö;œåô,°ÖÖ¦ÒRùýW.ú| ¢d·Õ±——1MÕÖFh¸×™Gÿ+éü®FÇOé¨H’a(¸ ^lnVm­ÎŸ÷v°8‡ks5·D%õªwzØòÆzõÕ+†´`�^zI¼ÿÊû Ö²”uQ÷iŸÓƒÀZs³RSÕÔ$I=zDOª‚xÅQX«Vu¦2�ž¶¬Y£¦¦(LU�ÂÂe]®UíP uzXknÖ¿ÿ­E‹T]­wÞ‰¶Z‰,�Öé˺œ¦4§�µÓ§u옒’œž#b,T«Z;,OHOwz‚ã�ªT%‰Ü€`ÁBµª}ò ѧ¬T«z &Èî×"‡`ÁB�jØ^Á%,œ×ùd%;= ,XjUkwuwz @"X°Ô¦6‚—¸ö<¬¢¢¢�?þØçó†áóù®~Þ÷î¿Ã.žÓ¾p‘‹µ©Í=gÜ‹‹‹üñÇ«_º ë/†¸*+=úéœþ6vÞµ`µµµµ´´˜¦nö>ÄU}¾æ¤[éã­dtøðáMMM›7o=ž«vX³fͺ|1MÜ׿8+++???Ääׂ•›››››ù¯Õ5¦i†½ƒºÃ¨œ³¶¶öèÑ£–ß&W�ÃJLL|úé§×¯_õ�y�ë/vî*gWÆø§óûý–û'5çjVœ!–Í›7ÏN°\µÃ’äóùâãù•²E,`¡Cç°š››{÷î]XXÑ‘³B1evh‡ešfssskkkD§BÌ"X¥]í¦LW"–,„Ò¦6IîyZbÁ‚5S¼ð?\�`!”^êeÈ8¯óNH ¡ùäë¥^-jqz@"X°”¤$‚— X°@°à ܃`ÁÁ‚{,XHR�Â%,$*ñúV«Z�阃ó –,üÕ �جÍ~ùƒ¯š2?Õ§#4"E)ŽˆØE°ðW#4b­Ö¦*µ@uª 눎LÖäÙš=AœÂë áÖhÍ�Y¦e¯ëõáÞ¬æ eAçY=↉‰‰eeeÆ ëªI[ØaáÒ•þ‚^�dÊüE¿0e2Fjä}º/Ä ããã'OžŸÏ0ŒðÞíÕ;7 ÃçãmŒ"X<ãÿs¡@a µIIEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue3.png0000644000000000000000000000013115132411300022373 xustar0030 mtime=1768559296.226885008 29 atime=1787067730.72353844 30 ctime=1787067793.865715197 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue3.png0000666000175000017500000001051615132411300022045 0ustar00rgerrger‰PNG  IHDR�ŒݾhÏsBITÛáOà pHYsêe¤ñIDATxœíÝyPÔ÷ýÇñ×.‡Ë!�2Þàxk…Nò£VÑÓ4Óf¢ÅÆ!‘ƒ±Î”Ick­`’ÆcLƒc­T!Æ`B6âA¸"¢L8"Zð ¸ »ŸßëxUÝ/†å»_öõ†�åÃò†…§ßï×Ýï"??DDNã‘G÷á¼zõj¹'$"ºA£ÑÜïC*!DoŽBDJeµâÓO1>îGSËõ…‰H1¬VìÝ‹I“��-c­¸Ëøµ‰ÈÙY­Ø¿qq¨®†Z�ä‡Á"¢{ééX³P© 2cÇÊ;�aÑ�„@FââðÝwpsƒÅj5**0aÂ�BÀj½ã�n½{ÏËÝÜì‘Á"¢Ûœù@YYYzz:€âââC‡ÈÍÍ-,, ÕjKJJ¤¥¥UUUؽ{÷ùóçlÛ¶íêÕ«>üðC½^à�wÞ±Z­V¯^-„ðòòŠ��BÆÄÄ!‚ƒƒ£¢¢„ãÇ��ˆˆB„……=ýôÓBˆéÓ§Ï™3GñÄOؾÇgžyfòäÉBˆçž{nôèÑBˆ—_~yÈ�!BˆåË—!Þxã OOO!D\\€ÎÎÎ 6xxx´µµ%$$xyy]¹r%))ÉVÆ´´´ÀÀÀªª*­V;hРÒÒÒÜÜÜ   ãÇ�Ÿ8qbäÈ‘¹¹¹åååcÇŽÍÎή««›8qbFFÆ]7A¡(ô~£Ä¨sâ\/Üâ=‚Á"çe±XÌf³¢³³Ó`0!:::Z[[­V«ÉdÒét‹Å`0\¾|¹««Ë`0444˜Íf½^öìY“ɤ×ëkjj ƒ^¯¯¨¨hoo7 §OŸ¾víšÑhçb®TîpWC}׋ ªÞ¹PA_+Ñ—pÉÞ^ðÒ@ã ï¡„ a„ Ñ­�œç_wnaQo¸„KIHJCÚ·ø€;ܧcúLÌ�ñã0n ¦xÁKîI,r ,ÉHÞ‰�(ó1ÿøE8§aš<䞎”‡Á"‡0¸Û7`ÃE\‹±‘ˆ|Ï�…ÌOa@JÇcXÔÃÄflŽG|ÚÇã{°gæÈ=õ õ¤jT¿‚WŠP4ÓßÆÛ¿Â¯äžˆúÞÓ�zÌ6l CX5ªwa×7ø†µ¢Ç-,ê&˜¢õ>û-~û/ük(†Ê=õMwt¯ªªÚ±c‡ÄÏôóó³�ôC¢µk×¶··K\=Áö”�hµÚ£G�J\%q±N§{÷Ýw%.°nݺ~’Ï›��pöìY‰‹Ÿ}öÙ™3gJ\|òäɽ{÷J\)qq||üûï¿/qñ‚ öìÙ#qq]]ÝäÉ“%.ÐÔÔäë+õþÄóæÍûæ›o$.Þ¸qãk¯½&qqrr²ôßÝ)S¦?~\âb>>>wüϲ/L…&1Bx.õtÛçv×âcÇŽIÿû\¶lYRR’ÄÅ111›6m’¸¸¨¨hîܹ{{{ët:‰‹„††ÖÖÖJ\¼{÷‰‹?øàƒ5kÖH\ŒÃ³1[îq¨ïã1,zHX"Y‚’4¤±VÔ;,zHÃßàÀ‡øp>æË= ¹ îÒÃ(@ÁlÌ^„E)H‘{r! u›†0„™a.CYô—{r!¼ã(uÛ¬9ƒ3ÿÆ¿Y+gS[‹®.¹‡p$‹ºç,ÎnÁ–—ñò€†da6#'–§Ë‡Z «µ�lmuB ±ÑA“�³ky:½Ë«½ßÞù;àä¬VP©`Û±½ÛÖ†ÆFèõÊ�a‘T¿Æ¯«PuçÔ<’àÜÞyÿøÇ�·U*ôë‡åËñƤ°§y¾>4‡$iBÓù+þÊZ9¹¶6Üðy/È8ƒE Ý—í»ܨ¡^ŒÅ~ð“q‹,º/T[±Õ¶Kh…512ÏÃ`¹<‹$¡¯á5�ãñP„Ê; ƒE Ùñ6Þˆ�òn·a°ˆ÷Ã";°[‡ßÉ=ƒE Ið{ü^KH Â`ƒEŠÁ`ƒEŠÁ`ƒEŠÁ`ƒEŠÁ`ƒE=Éd2ÅÆÆæää8âÊ,b°¨'utt|ôÑG§N�rĕۂE®ŒÁ"Åà1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1X¤ 1XÔ“<==£¢¢BBBqå ñYs¨'yyy%%%9èÊ,â)ƒE )ƒE )ƒE )ƒE )ƒE )ƒE )ƒE )ƒE )‰J¥b°\ƒEJÂ`¹8‹”„Árq ) ƒåâ,RËÅ1XÔ“,Ë÷ßõêU]?ƒåâ,êIׯ_ ݹs§ƒ®ŸÁrq ) ƒåâ,RËÅ1X¤$ –‹c°HI,Ç`‘’0X.ŽÁ"%a°\ƒEJÂ`¹8‹”„Árq ) ƒåâ,RËÅ1X¤$ –‹c°HI,Ç`‘’0X.ŽÁ"%a°\o~×USSÓÒÒ2uêÔž½Z‹Å¢V«mÏpÓ㺺ºÜÜÜtåäü,"RŒÿìM#H²ŽùÃIEND®B`‚rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/index.rst0000644000000000000000000000013215132411300020766 xustar0030 mtime=1768559296.227885023 30 atime=1787067672.642455805 30 ctime=1787067793.874715364 rsyslog-8.2608.0/doc/source/whitepapers/index.rst0000666000175000017500000000067715132411300020446 0ustar00rgerrgerRsyslog Whitepapers =================== These are a collection of white papers written by Rainer Gerhards. They detail logging comparisons and realities based on his experience. They also cover observations regarding the development of rsyslog and the community around syslog messaging White Papers ------------ .. toctree:: :maxdepth: 1 syslog_parsing syslog_protocol queues_analogy preserve_in_nat reliable_logging.rst rsyslog-8.2608.0/doc/source/whitepapers/PaxHeaders/direct_queue2.png0000644000000000000000000000013215132411300022373 xustar0030 mtime=1768559296.226885008 30 atime=1787067730.722538422 30 ctime=1787067793.862715141 rsyslog-8.2608.0/doc/source/whitepapers/direct_queue2.png0000666000175000017500000001002515132411300022037 0ustar00rgerrger‰PNG  IHDR�Œ ²ªsBITÛáOà pHYsêe¤¸IDATxœíÝkPTçÇñß.  F4Ž—u¼ÄK½A§/Œ¦ŽRcêdÚL´h:$’kD­/˜Œ¶ŽQPƒ1Æk޵2ÑD#NhÑõ A¼Æ¢D„•;˲°ûôÅfŒRd†åìáù}&Ã,ðìî_�ož=.g‘””""—Ñ·o_Ñ÷¡C‡®]»Víñˆˆ~âééÙêÇuBˆNÅÅÝÆmw¸�Â(µ!¢§èÕÀ…$#yæ,À‚‘©ö,DÔ’»Ú¸„¤„ ä,ΈAŒ:µ'"¢–d$˜‚”P„žÁtb&¤#�µ"rAòî­R‘‚�38ã7Àl�*Uö?uiûÝö®çÝÉ3Þs\Ý£1Ï&ãÞ*y+±òN=ùAt:è^À ªÍ:óîˆ\Ç` ¾�ûm,�qo5Ã�‹Ü;¸ã7+¬ö�»ÁmtGw-vXÿ¿áj{AÇ^ÝÅïÎÅÇãÝie¼è�6ɸ·²³ÂzGBzwôÐÛ`ð >Ù„Mj�FD­�·VvöfmÀ†\äè…^…(|/ª=µ$ûó­Üàö.ÞÍBÖaƒ1u¨Û‰�jED­�}oõ$+¬GqôK|i€�Û+"WÃZµ$ âá R{"z kEDÚ ûq+R˾}û>ûì3ÑÑÑaaaŽ;öé§Ÿˆ‹‹Û´i€sçÎÙ/$%%………Y­ÖÔÔÔ­[·666Þ¸qcÇŽõõõ™™™áááÕÕÕwîÜÙ»woEEEaaáþýûËËËKJJ¢¢¢JKKËËË¿þúë’’’ªªªo¿ý¶¸¸¸®®î»ï¾+**jhh8qâĽ{÷šššNŸ>]XXh³Ùâãã \¸pÁ~!%%¥°°Àõë×ínݺuïÞ=¹¹¹ÅÅÅ JJJÜ¿¿´´@YYYYY€ŠŠŠG�¨­­­ªª`2™êêêX,³Ù Àjµ677àâ™Z=� ‘³L™2EñÁŒ?^ñÑG 2D±råJooo!ÄêÕ«=<<„!!!,Ë矠ªª*<<Àƒ"##äåå}óÍ7ÒÓÓccc¤¦¦ž={@bbâ¥K— †´´4111YYY..®³¿Æ�µ"×eµZ-‹¢©©Éd2 !«««m6›Ùl6�V«Õd2•––677›L¦¢¢"‹ÅR__÷î]³Ù\__Ÿ““c2™êëëoݺU[[k2™nܸQUUÕÐÐpíÚ5£Ñh6›“““KKK-KRRRqqqsssBBB~~¾âÌ™3999BˆS§NݺuKa0®_¿.„8yòdjjªâĉ/^BÄÅÅ�?Þ~áäÉ“ö Ç�·¯9|ø°ýZ‘‘‘öÛ‰ˆˆBœ>}zÛ¶mBˆ³gÏnܸQ¿víZ›Íöý÷߯^½Úl6'%%×ÖÖ^¹reåÊ•�=ºzõjPPPIIIZZÚâÅ‹óóóÓÓÓßÿýììììì쀀€ü1//oþüù©©©EEEsçνpáB§;�[‘6ð¸ikEDÚÀZ‘6ÈxrXr�óø?/xe!Kí¡T°ûyrm%X+êTF/ââ\HBÒMÜ||ºž0 ³ѨîxªàIÇâ¿ Rgx€QˆŠAÌñ_îpŸ†iÓ1},ÆŽÁ˜É˜ì/µg$WÇZ‘Ya�Fô¸ˆ‹b.æþ¿ž�S1ÕjOGÃZ‘S4 aömÅÖ”ŒÆè¼‹wÛ>ë6QÛxÜŠ:˜€Ø�Ý!©AÍ«xõùÁOí¡¨+`­¨#e#ûC|˜Œäi˜¶ ›~‡ß©=u|¾u˜½Øë ßldÿ ÿºŒËLu,î­¨˜aDà1ûþðüc0«=uAOeÏÊÊÚ¿¿ÂköîÝÛ~…BCCkkk.^²dɸqã.6 ñññ ûøø*\l4íç`RhóæÍÝ»wW¸8""âîÝ» ¿ýöÛÓ§OW¸ø‡~8räˆÂŃþøã�.ðÿ‹Í=Ìÿþðß÷‡ßŸ7ã7~óä§‚ƒƒ‡ ¢ð–�=zõêU…‹_{íµyóæ)\œŸŸÿÕW_)\ìáá±eË…‹lÙ²Å~¶%.\èëë«pqBBÂÉ“'.3fÌÒ¥K.®««k×ïúõë½½½.ŽŒŒÌÌÌT¸xΜ9³gÏV¸ø©Z�>}ZùwÀ Aƒ”ÿ°1bÄÇ.Ž��}ã�7. ùâ‹/.ž7oÞ¡C‡.ÎËË›4i’ÂÅÊÊÊzõê¥pñìÙ³/_¾¬pñ¶mÛ–/_®pqtt´òoÜÉ“'§¤¤(\  gÏžOý;r/˜/™ÅpÑí£nnߺµX|åÊå?œË–-‹ŠŠR¸8((hÇŽ '''Ïš5Káâ=z�F…‹øøøäææ*\|ðàA…‹·oß¾nÝ:…‹gÍš§p±Ñh6l˜ÂÅrss_~ùe…‹ýýý ƒÂÅëÖ­[³f�ÂÅ|=¿zÔÏÄ̸qçfb¦ÚãPÇãVôœ¬° i1ˆaª¨°VôœþŽ¿ÿÿÙ‰�s1WíYH |$HÏã".ÎÄÌ?ãχqXíYH¬µ› &_øZ`IGú xAíqH|v(µÛ:¬»ƒ;ÿÄ?™*W“›‹æfµ‡pÖŠÚç.î†#|͆ҧÉP§éÓ¿úvíBCƒÚ£8kEí³›õÐoÀµ¡Vôï�yóŒ#º`³xÜŠÚ!ùc1ö/øËìQ{j]y9†‡É`Í,] ¯.q®Cî­¨¶`‹ú5Púäcê|ýû㯅NF#‚ƒ1|xÙgµooÕЀùó�7 ¹4«gýùè—%ÏõÙ¡ô÷cH `ýé”÷Ðëa³u…}Vûž*Š‹�4 ¹ºÊ7c›½j»yŸß.Îf�ö­ˆýÝš£¾^õâq+Rê÷ø}² P ç׆O>ùé²N‡îݱbV­ÂÀ�ªŽõ‹ñ7oH‘2”�Çù¿áoL•‹«©Áã3’xzv‘NÙ±V¤ˆlþPz¶RKx8ª«»Z§ìøH� D †2”qoåÊjj0q",èj�²ãÞŠ‰G¼ü˜*WT„ÌL(>#¤Æ°VäX²JPÂW…p}&¨=�3ñ•äØ\ÀSX+r,žðƒ1jBRc­È±t¤�Çx7´|‘¢ÎÄZ‘cȘˆ‰jOA²c­È#Œñ�µ"Õ±Vä@! ŒÄHµ!Ù±Vä@%*¼ˆÕ„d÷óó­¢¢¢¢££õz½N§Óëõ�/tì[׿ÁNžSg?‘ «@\¦V±±±iii�ÿêìž|·�O9c¥FïNí/ãsú¹V‹¥®®Na³Ùžõ¶�Oµ÷­Í~ ~IIC_yå•êêêãÇ�·=ž½V}Ñ·Sþ28qâDdd¤ÚShžË¶ØÏÏ/$$äYcÿ\«%K–,Y²¤Sþ®~"„èð:é»äœÅÅÅ¿L®óH033óöíÛIIIS§N}üÍ#žðä»Ï÷)uWJ~wV«µíMŒš¿yó8¨*Î ³Å‹+©U*º¡[/¨ÿ»gµµµ—.]ª¬¬twçoŒÉˆ¥ *P¡|cUSSãíí½{÷ngLb?à"xÖY±Vä@*”´BÔÔÔ466:cÖJr¬9P‰JW8hÖJz¬9ЮG‚NÅZI޵"ªQí oµ§X+é±Vä€<šÐ¤ök%=ÖŠð‚—fµ§X+é±Vä€'<à¯JÎZI޵"¼àÅZ‘+`­È>$ÁZ‘|$H.‚µ"¸·"ÁZ‘-öV�hÌD¦*“°V’c­¨¥ldÇq+¬öwe‡qxÆõGUc­$ÇZQKã0.Ã0,¡÷qßþH0é30ã=¼7 ÓX+RÏD­G¸/|7`ÃFl�Ñ hð��€° ËÚ¸bÏž=GŽtÊKN°V’ãÞŠZ1Vb%‘‹\! tÐ�Çøßâ·m\ÑÝÝ}ÆŒC‡uÆT¬•äX+j](Bû£¿zû– €€X�*ŽÄZI޵¢ÖõFïíØnÃÏçÉïá=Gb­$ÇZÑ3Ù�©»Á €ú…XؽUœ‡µ’kEϤƒnöØ Ú` B�Êó°Vrc­¨->ðYŽå^Å«>ðQwÖJr¬9° ›`€ºÇ×íX+ÉñùVä@ôÙƒ=ÄÕ„µ’kEŽý R{€µ’ ’f°V’c­H3X+ɱV¤¬•äX+Ò ÖJr¬ik%9ÖŠ:’ÙlNHHpÆ�³V’c­¨#566îÚµëÚµkθq{­HZ¬i÷V’c­H3X+ɱV¤¬•äX+Ò ÖJr¬ik%9ÖŠ4ƒµ’kEšÁZI޵"Í`­$ÇZ‘f°V’c­H3X+ɱV¤¬•äX+Ò ÖJr¬ik%9ÖŠ:R·nÝ'NœèŒg­$Ç×¼¡Žäååå¤g­$ǽik%9ÖŠ4ƒµ’kEšÁZI޵"Í`­$ÇZ‘f°V’c­H3X+ɱV¤¬•äX+Ò ÖJr¬i‰N§c­¤ÅZ‘–°V2c­HKX+™±V¤%¬•ÌX+ÒÖJf¬u$«ÕzóæÍòòr'Ý>k%3ÖŠ:R]]���Ï�œtû¬•ÌX+ÒÖJf¬i k%3ÖŠ´„µ’kEZÂZÉŒµ"-a­dÆZ‘–°V2c­HKX+™±V¤%¬•ÌX+ÒÖJf¬i k%3ÖŠ´„µ’kEZÂZÉŒµ"-a­dÆZ‘–°V2ã×^^999•••S¦L騛µZ­z½Þþú4®¹¹ÙÍÍÍI7N.޵""møbòR5k,™IEND®B`‚rsyslog-8.2608.0/doc/source/PaxHeaders/configuration0000644000000000000000000000013215241076617017407 xustar0030 mtime=1787067791.537671814 30 atime=1787067808.812993723 30 ctime=1787067791.537671814 rsyslog-8.2608.0/doc/source/configuration/0000775000175000017500000000000015241076617017130 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/PaxHeaders/parser.rst0000644000000000000000000000013215132411300021467 xustar0030 mtime=1768559296.183884327 30 atime=1787067672.553454145 30 ctime=1787067791.510671311 rsyslog-8.2608.0/doc/source/configuration/parser.rst0000666000175000017500000000547415132411300021147 0ustar00rgerrgerParser ====== .. index:: ! parser .. _cfgobj_input: The ``parser`` object, as its name suggests, describes message parsers. Message parsers have a standard parser name, which can be used by simply loading the parser module. Only when specific parameters need to be set the parser object is needed. In that case, it is used to define a new parser name (aka "parser definition") which configures this name to use the parser module with set parameters. This is important as the ruleset() object does not support to set parser parameters. Instead, if parameters are needed, a proper parser name must be defined using the parser() object. A parser name defined via the parser() object can be used wherever a parser name can occur. Note that not all message parser modules are supported in the parser() object. The reason is that many do not have any user-selectable parameters and as such, there is no point in issuing a parser() object for them. The parser object has different parameters: - those that apply to all parser and are generally available for all of them. These are documented below. - parser-specific parameters. These are specific to a certain parser module. They are documented by the :doc:`parser module ` in question. General Parser Parameters ------------------------- Note: parameter names are case-insensitive. .. function:: name *Mandatory* This names the parser. Names starting with "rsyslog." are reserved for rsyslog use and must not be used. It is suggested to replace "rsyslog." with "custom." and keep the rest of the name descriptive. However, this is not enforced and just good practice. .. function:: type *Mandatory* The ```` is a string identifying the parser module as given it each module's documentation. Do not mistake the parser module name with its default parser name. For example, the :doc:`Cisco IOS message parser module ` parser module name is "pmciscoios", whereas it's default parser name is "rsyslog.pmciscoios". Samples ------- The following example creates a custom parser definition and uses it within a ruleset: :: module(load="pmciscoios") parser(name="custom.pmciscoios.with_origin" type="pmciscoios") ruleset(name="myRuleset" parser="custom.pmciscoios.with_origin") { ... do something here ... } The following example uses multiple parsers within a ruleset without a parser object (the order is important): :: module(load="pmaixforwardedfrom") module(load="pmlastmsg") ruleset(name="myRuleset" parser=["rsyslog.lastline","rsyslog.aixforwardedfrom","rsyslog.rfc5424","rsyslog.rfc3164"]) { ... do something here ... } A more elaborate example can also be found in the :doc:`Cisco IOS message parser module ` documentation. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/filters.rst0000644000000000000000000000013215132411300021643 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.140446446 30 ctime=1787067791.120664043 rsyslog-8.2608.0/doc/source/configuration/filters.rst0000666000175000017500000003371315132411300021320 0ustar00rgerrgerFilter Conditions ================= Rsyslog offers four different types "filter conditions": - "traditional" severity and facility based selectors - property-based filters - expression-based filters - BSD-style blocks (not upward compatible) Selectors --------- **Selectors are the traditional way of filtering syslog messages.** They have been kept in rsyslog with their original syntax, because it is well-known, highly effective and also needed for compatibility with stock syslogd configuration files. If you just need to filter based on priority and facility, you should do this with selector lines. They are **not** second-class citizens in rsyslog and offer the simplest syntax for this job. In versions of rsyslog prior to v7 there were significant performance gains by using selector lines instead of the |FmtAdvancedName| format. There is no longer any difference in performance between the two formats. The selector field itself again consists of two parts, a facility and a priority, separated by a period (".''). Both parts are case insensitive and can also be specified as decimal numbers, but don't do that, you have been warned. Both facilities and priorities are described in syslog(3). The names mentioned below correspond to the similar LOG\_-values in /usr/include/syslog.h. The facility is one of the following keywords: auth, authpriv, cron, daemon, kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and local0 through local7. The keyword security should not be used anymore and mark is only for internal use and therefore should not be used in applications. Anyway, you may want to specify and redirect these messages here. The facility specifies the subsystem that produced the message, i.e. all mail programs log with the mail facility (LOG\_MAIL) if they log using syslog. The priority is one of the following keywords, in ascending order: debug, info, notice, warning, warn (same as warning), err, error (same as err), crit, alert, emerg, panic (same as emerg). The keywords error, warn and panic are deprecated and should not be used anymore. The priority defines the severity of the message. The behavior of the original BSD syslogd is that all messages of the specified priority and higher are logged according to the given action. Rsyslogd behaves the same, but has some extensions. In addition to the above mentioned names the rsyslogd(8) understands the following extensions: An asterisk ("\*'') stands for all facilities or all priorities, depending on where it is used (before or after the period). The keyword none stands for no priority of the given facility. You can specify multiple facilities with the same priority pattern in one statement using the comma (",'') operator. You may specify as much facilities as you want. Remember that only the facility part from such a statement is taken, a priority part would be skipped. Multiple selectors may be specified for a single action using the semicolon (";'') separator. Remember that each selector in the selector field is capable to overwrite the preceding ones. Using this behavior you can exclude some priorities from the pattern. Rsyslogd has a syntax extension to the original BSD source, that makes the use of selectors use more intuitively. You may precede every priority with an equals sign ("='') to specify only this single priority and not any of the above. You may also (both is valid, too) precede the priority with an exclamation mark ("!'') to ignore all that priorities, either exact this one or this and any higher priority. If you use both extensions then the exclamation mark must occur before the equals sign, just use it intuitively. However, please note that there are some restrictions over the traditional BSD syslog behaviour. These restrictions stem back to sysklogd, exist probably since at least the 1990's and as such have always been in rsyslog. Namely, in BSD syslogd you can craft a selector like this: \*.debug;local6.err The intent is to log all facilities at debug or higher, except for local6, which should only log at err or higher. Unfortunately, local6.err will permit error severity and higher, but will *not* exclude lower severity messages from facility local6. As an alternative, you can explicitly exclude all severities that you do not want to match. For the above case, this selector is equivalent to the BSD syslog selector: \*.debug;local6.!=info;local6.!=notice;local6.!=warn An easier approach is probably to do if ... then based matching in script. Property-Based Filters ---------------------- Property-based filters are unique to rsyslogd. They allow to filter on any property, like HOSTNAME, syslogtag and msg. A list of all currently-supported properties can be found in the :doc:`rsyslog properties documentation `. With this filter, each property can be checked against a specified value, using a specified compare operation. A property-based filter must start with a colon **in column 1**. This tells rsyslogd that it is the new filter type. The colon must be followed by the property name, a comma, the name of the compare operation to carry out, another comma and then the value to compare against. This value must be quoted. There can be spaces and tabs between the commas. Property names and compare operations are case-sensitive, so "msg" works, while "MSG" is an invalid property name. In brief, the syntax is as follows: ``:property, [!]compare-operation, "value"`` Compare-Operations ~~~~~~~~~~~~~~~~~~ The following **compare-operations** are currently supported: **contains** Checks if the string provided in value is contained in the property. There must be an exact match, wildcards are not supported. **isequal** Compares the "value" string provided and the property contents. These two values must be exactly equal to match. The difference to contains is that contains searches for the value anywhere inside the property value, whereas all characters must be identical for isequal. As such, isequal is most useful for fields like syslogtag or FROMHOST, where you probably know the exact contents. **startswith** Checks if the value is found exactly at the beginning of the property value. For example, if you search for "val" with ``:msg, startswith, "val"`` it will be a match if msg contains "values are in this message" but it won't match if the msg contains "There are values in this message" (in the later case, *"contains"* would match). Please note that "startswith" is by far faster than regular expressions. So even once they are implemented, it can make very much sense (performance-wise) to use "startswith". **endswith** Checks if the value appears exactly at the end of the property value. For example, ``:programname, endswith, "_foo"`` matches if the program name ends with ``_foo``. **regex** Compares the property against the provided POSIX BRE regular expression. **ereregex** Compares the property against the provided POSIX ERE regular expression. You can use the bang-character (!) immediately in front of a compare-operation, the outcome of this operation is negated. For example, if msg contains "This is an informative message", the following sample would not match: ``:msg, contains, "error"`` but this one matches: ``:msg, !contains, "error"`` Using negation can be useful if you would like to do some generic processing but exclude some specific events. You can use the discard action in conjunction with that. A sample would be: :: *.* /var/log/allmsgs-including-informational.log :msg, contains, "informational"  ~ *.* /var/log/allmsgs-but-informational.log Do not overlook the tilde in line 2! In this sample, all messages are written to the file allmsgs-including-informational.log. Then, all messages containing the string "informational" are discarded. That means the config file lines below the "discard line" (number 2 in our sample) will not be applied to this message. Then, all remaining lines will also be written to the file allmsgs-but-informational.log. Value Part ~~~~~~~~~~ **Value** is a quoted string. It supports some escape sequences: \\" - the quote character (e.g. "String with \\"Quotes\\"") \\\\ - the backslash character (e.g. "C:\\\\tmp") Escape sequences always start with a backslash. Additional escape sequences might be added in the future. Backslash characters **must** be escaped. Any other sequence then those outlined above is invalid and may lead to unpredictable results. Probably, "msg" is the most prominent use case of property based filters. It is the actual message text. If you would like to filter based on some message content (e.g. the presence of a specific code), this can be done easily by: ``:msg, contains, "ID-4711"`` This filter will match when the message contains the string "ID-4711". Please note that the comparison is case-sensitive, so it would not match if "id-4711" would be contained in the message. ``:msg, regex, "fatal .* error"`` This filter uses a POSIX regular expression. It matches when the string contains the words "fatal" and "error" with anything in between (e.g. "fatal net error" and "fatal lib error" but not "fatal error" as two spaces are required by the regular expression!). Getting property-based filters right can sometimes be challenging. In order to help you do it with as minimal effort as possible, rsyslogd spits out debug information for all property-based filters during their evaluation. To enable this, run rsyslogd in foreground and specify the "-d" option. Boolean operations inside property based filters (like 'message contains "ID17" or message contains "ID18"') are currently not supported (except for "not" as outlined above). Please note that while it is possible to query facility and severity via property-based filters, it is far more advisable to use classic selectors (see above) for those cases. Expression-Based Filters ------------------------ Expression based filters allow filtering on arbitrary complex expressions, which can include boolean, arithmetic and string operations. Expression filters will evolve into a full configuration scripting language. Unfortunately, their syntax will slightly change during that process. So if you use them now, you need to be prepared to change your configuration files some time later. However, we try to implement the scripting facility as soon as possible (also in respect to stage work needed). So the window of exposure is probably not too long. Expression based filters are indicated by the keyword "if" in column 1 of a new line. They have this format: :: if expr then action-part-of-selector-line "if" and "then" are fixed keywords that must be present. "expr" is a (potentially quite complex) expression. So the :doc:`expression documentation <../rainerscript/expressions>` for details. "action-part-of-selector-line" is an action, just as you know it (e.g. "/var/log/logfile" to write to that file). BSD-style Blocks ---------------- **Note:** rsyslog v7+ no longer supports BSD-style blocks for technical reasons. So it is strongly recommended **not** to use them. Rsyslogd supports BSD-style blocks inside rsyslog.conf. Each block of lines is separated from the previous block by a program or hostname specification. A block will only log messages corresponding to the most recent program and hostname specifications given. Thus, a block which selects ‘ppp’ as the program, directly followed by a block that selects messages from the hostname ‘dialhost’, then the second block will only log messages from the ppp program on dialhost. A program specification is a line beginning with ‘!prog’ and the following blocks will be associated with calls to syslog from that specific program. A program specification for ‘foo’ will also match any message logged by the kernel with the prefix ‘foo: ’. Alternatively, a program specification ‘-foo’ causes the following blocks to be applied to messages from any program but the one specified. A hostname specification of the form ‘+hostname’ and the following blocks will be applied to messages received from the specified hostname. Alternatively, a hostname specification ‘-hostname’ causes the following blocks to be applied to messages from any host but the one specified. If the hostname is given as ‘@’, the local hostname will be used. (NOT YET IMPLEMENTED) A program or hostname specification may be reset by giving the program or hostname as ‘\*’. Please note that the "#!prog", "#+hostname" and "#-hostname" syntax available in BSD syslogd is not supported by rsyslogd. By default, no hostname or program is set. Examples -------- :: *.* /var/log/file1 # the traditional way if $msg contains 'error' then /var/log/errlog # the expression-based way Right now, you need to specify numerical values if you would like to check for facilities and severity. These can be found in :rfc:`5424`. If you don't like that, you can of course also use the textual property - just be sure to use the right one. As expression support is enhanced, this will change. For example, if you would like to filter on message that have facility local0, start with "DEVNAME" and have either "error1" or "error0" in their message content, you could use the following filter: :: if $syslogfacility-text == 'local0' and $msg startswith 'DEVNAME' and ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog Please note that the above must all be on one line! And if you would like to store all messages except those that contain "error1" or "error0", you just need to add a "not": :: if $syslogfacility-text == 'local0' and $msg startswith 'DEVNAME' and not ($msg contains 'error1' or $msg contains 'error0') then /var/log/somelog If you would like to do case-insensitive comparisons, use "contains\_i" instead of "contains" and "startswith\_i" instead of "startswith". Note that regular expressions are currently NOT supported in expression-based filters. These will be added later when function support is added to the expression engine (the reason is that regular expressions will be a separate loadable module, which requires some more prerequisites before it can be implemented). rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/cryprov_ossl.rst0000644000000000000000000000013215132733117022754 xustar0030 mtime=1768666703.892620011 30 atime=1787067672.080445328 30 ctime=1787067791.111663875 rsyslog-8.2608.0/doc/source/configuration/cryprov_ossl.rst0000666000175000017500000000553615132733117022433 0ustar00rgerrgerlibossl Log Crypto Provider (ossl) ==================================== **Crypto Provider Name:**    ossl **Author:** Attila Lakatos **Supported Since:** since 8.2408.0 **Description**: Provides encryption support to rsyslog. **Configuration Parameters**: Crypto providers are loaded by omfile, when the provider is selected in its "cry.providerName" parameter. Parameters for the provider are given in the omfile action instance line. This provider creates an encryption information file with the same base name but the extension ".encinfo" for each log file (both for fixed-name files as well as dynafiles). Both files together form a set. So you need to archive both in order to prove integrity. The main differences between the ossl and gcry crypto providers are: In ossl, algorithms are not hardcoded. There are concerns about potential side-channel vulnerabilities with ossl, such as the Minerva Attack and the Raccoon Attack, due to their bad handling of well-known side-channel attacks. As a result of the Marvin incident, they have downgraded their threat model. Note for distro maintainers: the libossl crypto provider will be available only if rsyslog is compiled with --enable-openssl option. - **cry.algo** The algorithm and mode to be used for encryption. The default is "AES-128-CBC". The actual availability of algorithms depends on which ones are compiled into openssl. The cipher implementation is retrieved using the EVP_CIPHER_fetch() function. See "ALGORITHM FETCHING" in crypto(7) for further information. Algorithms are not hardcoded, we provide everything that can be fetched using the aforementioned function. Note: Always check carefully when you change the algorithm if it's available. - **cry.key** TESTING AID, NOT FOR PRODUCTION USE. This uses the KEY specified inside rsyslog.conf. This is the actual key, and as such this mode is highly insecure. However, it can be useful for initial testing steps. This option may be removed in the future. - **cry.keyfile** Reads the key from the specified file. The file must contain the key, only, no headers or other meta information. Keyfiles can be generated via the rscrytool utility. **Caveats/Known Bugs:** - currently none known **Samples:** This encrypts a log file. Default parameters are used, the key is provided via a keyfile. :: action(type="omfile" file="/var/log/somelog" cry.provider="ossl" cry.keyfile="/secured/path/to/keyfile") In addition to previous example, this changes the default algorithm: :: action(type="omfile" file="/var/log/somelog" cry.provider="ossl" cry.keyfile="/secured/path/to/keyfile" cry.algo="AES-256-CBC") Note that the keyfile can be generated via the rscrytool utility (see its documentation for how to actually do that). rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/percentile_stats.rst0000644000000000000000000000013215132411300023543 xustar0030 mtime=1768559296.183884327 30 atime=1787067672.573454518 30 ctime=1787067791.512671348 rsyslog-8.2608.0/doc/source/configuration/percentile_stats.rst0000666000175000017500000001412615132411300023215 0ustar00rgerrgerPercentile Stats ================ The Percentile Stats component allows user to configure statistical namespaces (called stats-buckets), which can then be used to record statistical values for publishing periodic percentiles and summaries. Percentile Stats Configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Percentile-stats configuration involves a **two part setup**. First, define a ``percentile-stats`` bucket and its attributes. Then, add statistics and observation values to the namespace, by making ``percentile_observation`` calls. percentile_stats(name="", percentiles=[...], windowsize=""...) (object) ----------------------------------------------------------------------------------------------------------- **Defines** the statistics bucket(identified by the bucket-name) and allows user to set some properties that control behavior of the bucket. .. code-block:: percentile_stats(name="bucket_name" percentiles=["95"] windowsize=1000) Parameters: **name** : Bucket name of a set of statistics to sample. **percentiles** : A list of strings, with percentile statistic value between 1, 100 inclusive, user would like to publish to impstats. This list of percentiles would apply for all statistics tracked under this bucket. **windowSize** : A max *sliding* window (FIFO) size - rounded *up* to the nearest power of 2, that is larger than the given window size. Specifies the maximum number of observations stored over an impstats reporting interval. This attribute would apply to all statistics tracked under this bucket. **delimiter** : A single character delimiter used in the published fully qualified statname. This delimiter would apply to all statistics tracked under this bucket. A definition setting all the parameters looks like: .. code-block:: percentile_stats(name="host_statistics" percentiles=["50", "95", "99"] windowsize="1000" delimiter="|") percentile_observe("", "", ) (function) ---------------------------------------------------------------- **Adds** a statistical sample to the statistic set identified by the , and . If the number of values exceed the defined **windowSize**, the earliest recorded value is dropped and the new value is recorded. .. note:: Sums and counts only include values found in the sliding window. Min and Max summary values will include all values seen over an observation interval. See :ref:`Reporting` below for more info on published summary statistics. Parameters: **bucket name** : Name of the statistic bucket **stat name** : Name of the statistic to record (this name will be combined with a percentile and reported by impstats to identify the percentile) **value** : Value to record A ``percentile_observe`` call looks like: .. code-block:: set $.ret = percentile_observe("host_statistics", "msg_per_host", $.mycount); if ($.ret != 0) then { .... } ``$.ret`` captures the error-code. It has value ``0`` when operation is successful and non-zero when it fails. It uses Rsyslog error-codes. .. _Reporting: Reporting ^^^^^^^^^ The following example metrics would be reported by **impstats** Legacy format: .. code-block:: ... global: origin=percentile host_statistics.new_metric_add=1 host_statistics.ops_overflow=0 ... host_statistics: origin=percentile.bucket msg_per_host|p95=1950 msg_per_host|p50=1500 msg_per_host|p99=1990 msg_per_host|window_min=1001 msg_per_host|window_max=2000 msg_per_host|window_sum=1500500 msg_per_host|window_count=1000 ... Json(variants with the same structure are used in other Json based formats such as ``cee`` and ``json-elasticsearch``) format: .. code-block:: ... { "name": "global", "origin": "percentile", "values": { "host_statistics.new_metric_add": 1, "host_statistics.ops_overflow": 0 } } ... { "name": "host_statistics", "origin": "percentile.bucket", "values": { "msg_per_host|p95": 1950, "msg_per_host|p50": 1500, "msg_per_host|p99": 1990, "msg_per_host|window_min": 1001, "msg_per_host|window_max": 2000, "msg_per_host|window_sum": 1500500, "msg_per_host|window_count": 1000 } } ... In this case counters are encapsulated inside an object hanging off top-level-key ``values``. Fields ------ **global: origin=percentile.bucket**: **new_metric_add**: Number of "new" metrics added (new counters created). **ops_overflow**: Number of operations ignored because number-of-counters-tracked has hit configured max-cardinality. **host_statistic: origin=percentile.bucket**: **msg_per_host|**: percentile value, identified by , where pXX is one of the requested ``percentiles`` requested. **msg_per_host|window_min**: minimum recorded value in the statistical population window. Identified by ``window_min`` **msg_per_host|window_max**: maximum recorded value in the statistical population window. Identified by ``window_max`` **msg_per_host|window_sum**: sum of recorded values in the statistical population window. Identified by ``delimiter>window_sum`` **msg_per_host|window_count**: count of recorded values in the statistical population window. Identified by ``window_count`` Implementation Details ---------------------- Percentile stats module uses a sliding window, sized according to the **windowSize** configuration parameter. The percentile values are calculated, once every **impstats** interval. Percentiles are calculated according to the standard “nearest-rankâ€� method: n = CEILING((P/100) x N) where: * n - index to percentile value * P - percentile [1, 100] * N - number of values recorded .. note:: In order to sort the values, a standard implementation of quicksort is used, which performs pretty well on average. However quicksort quickly degrades when there are many repeated elements, thus it is best to avoid repeated values if possible. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/config_param_types.rst0000644000000000000000000000013215132411300024044 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.007443967 30 ctime=1787067791.105663764 rsyslog-8.2608.0/doc/source/configuration/config_param_types.rst0000666000175000017500000000336615132411300023522 0ustar00rgerrgerConfiguration Parameter Types ============================= Configuration parameter values have different data types. Unfortunately, the type currently must be guessed from the description (consider contributing to the doc to help improve it). In general, the following types are used: - **numbers** The traditional integer format. Numbers may include '.' and ',' for readability. So you can for example specify either "1000" or "1,000" with the same result. Please note that rsyslogd simply *ignores* the punctuation. From it's point of view, "1,,0.0.,.,0" also has the value 1000. - **sizes** Used for things like file size, main message queue sizes and the like. These are integers, but support modifier after the number part. For example, 1k means 1024. Supported are k(ilo), m(ega), g(iga), t(era), p(eta) and e(xa). Lower case letters refer to the traditional binary definition (e.g. 1m equals 1,048,576) whereas upper case letters refer to their new 1000-based definition (e.g 1M equals 1,000,000). - **complete line** A string consisting of multiple characters. This is relatively seldom used and sometimes looks confusing (rsyslog v7+ has a much better approach at these types of values). - **single word** This is used when only a single word can be provided. A "single word" is a string without spaces in it. **No** quoting is necessary nor permitted (the quotes would become part of the word). - **character** A single (printable) character. Must **not** be quoted. - **boolean** The traditional boolean type, specified as "on" (1) or "off" (0). Note that some other value types are occasionally used. However, the majority of types is one of those listed above. The list is updated as need arises and time permits. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/ruleset0000644000000000000000000000013215241076617021072 xustar0030 mtime=1787067791.528671646 30 atime=1787067808.812993723 30 ctime=1787067791.528671646 rsyslog-8.2608.0/doc/source/configuration/ruleset/0000775000175000017500000000000015241076617020613 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/ruleset/PaxHeaders/rsconf1_rulesetparser.rst0000644000000000000000000000013215171370365026233 xustar0030 mtime=1776677109.112908007 30 atime=1787067672.958461695 30 ctime=1787067791.528671646 rsyslog-8.2608.0/doc/source/configuration/ruleset/rsconf1_rulesetparser.rst0000664000175000017500000001210715171370365025700 0ustar00rgerrger$RulesetParser -------------- **Type:** ruleset-specific configuration directive **Parameter Values:** string **Available since:** 5.3.4+ **Default:** rsyslog.rfc5424 followed by rsyslog.rfc3164 **Description:** This directive permits to specify which `message parsers <../../concepts/messageparser.html>`_ should be used for the ruleset in question. It no ruleset is explicitly specified, the default ruleset is used. Message parsers are contained in (loadable) parser modules with the most common cases (RFC3164 and RFC5424) being built into rsyslogd. When this directive is specified the first time for a ruleset, it will not only add the parser to the ruleset's parser chain, it will also wipe out the default parser chain. So if you need to have them in addition to the custom parser, you need to specify those as well. Order of directives is important. Parsers are tried one after another, in the order they are specified inside the config. As soon as a parser is able to parse the message, it will do so and no other parsers will be executed. If no matching parser can be found, the message will be discarded and a warning message be issued (but only for the first 1,000 instances of this problem, to prevent message generation loops). Note that the rfc3164 parser will **always** be able to parse a message - it may just not be the format that you like. This has two important implications: 1) always place that parser at the END of the parser list, or the other parsers after it will never be tried and 2) if you would like to make sure no message is lost, placing the rfc3164 parser at the end of the parser list ensures that. Multiple parser modules are very useful if you have various devices that emit messages that are malformed in various ways. The route to take then is - make sure you find a custom parser for that device; if there is no one, you may consider writing one yourself (it is not that hard) or getting one written as part of `Adiscon's professional services for rsyslog `_. - load your custom parsers via $ModLoad - create a ruleset for each malformed format; assign the custom parser to it - create a specific listening port for all devices that emit the same malformed format - bind the listener to the ruleset with the required parser Note that it may be cumbersome to add all rules to all rulesets. To avoid this, you can either use $Include or :doc:`omruleset ` (what probably provides the best solution). More information about rulesets in general can be found in :doc:`multi-ruleset support in rsyslog <../../concepts/multi_ruleset>`. **Caveats:** currently none known **Example:** This example assumes there are two devices emitting malformed messages via UDP. We have two custom parsers for them, named "device1.parser" and "device2.parser". In addition to that, we have a number of other devices sending well-formed messages, also via UDP. The solution is to listen for data from the two devices on two special ports (10514 and 10515 in this example), create a ruleset for each and assign the custom parsers to them. The rest of the messages are received via port 514 using the regular parsers. Processing shall be equal for all messages. So we simply forward the malformed messages to the regular queue once they are parsed (keep in mind that a message is never again parsed once any parser properly processed it). :: $ModLoad imudp $ModLoad pmdevice1 # load parser "device1.parser" for device 1 $ModLoad pmdevice2 # load parser "device2.parser" for device 2 # define ruleset for the first device sending malformed data $Ruleset maldev1 $RulesetCreateMainQueue on # create ruleset-specific queue $RulesetParser "device1.parser" # note: this deactivates the default parsers # forward all messages to default ruleset: $ActionOmrulesetRulesetName RSYSLOG\_DefaultRuleset \*.\* :omruleset: # define ruleset for the second device sending malformed data $Ruleset maldev2 $RulesetCreateMainQueue on # create ruleset-specific queue $RulesetParser "device2.parser" # note: this deactivates the default parsers # forward all messages to default ruleset: $ActionOmrulesetRulesetName RSYSLOG\_DefaultRuleset \*.\* :omruleset: # switch back to default ruleset $Ruleset RSYSLOG\_DefaultRuleset \*.\* /path/to/file auth.info @authlogger.example.net # whatever else you usually do... # now define the inputs and bind them to the rulesets # first the default listener (utilizing the default ruleset) $UDPServerRun 514 # now the one with the parser for device type 1: $InputUDPServerBindRuleset maldev1 $UDPServerRun 10514 # and finally the one for device type 2: $InputUDPServerBindRuleset maldev2 $UDPServerRun 10515 For an example of how multiple parser can be chained (and an actual use case), please see the example section on the :doc:`pmlastmsg ` parser module. Note the positions of the directives. With the current config language, **sequence of statements is very important**. This is ugly, but unfortunately the way it currently works. rsyslog-8.2608.0/doc/source/configuration/ruleset/PaxHeaders/rsconf1_rulesetcreatemainqueue.rst0000644000000000000000000000013215171370365030114 xustar0030 mtime=1776677109.112908007 30 atime=1787067672.944461435 30 ctime=1787067791.526671609 rsyslog-8.2608.0/doc/source/configuration/ruleset/rsconf1_rulesetcreatemainqueue.rst0000664000175000017500000000631615171370365027566 0ustar00rgerrger:doc:`rsyslog.conf configuration directive ` $RulesetCreateMainQueue ----------------------- **Type:** ruleset-specific configuration directive **Parameter Values:** boolean (on/off, yes/no) **Available since:** 5.3.5+ **Default:** off **Description:** Rulesets may use their own "main" message queue for message submission. Specifying this directive, **inside a ruleset definition**, turns this on. This is both a performance enhancement and also permits different rulesets (and thus different inputs within the same rsyslogd instance) to use different types of main message queues. The ruleset queue is created with the parameters that are specified for the main message queue at the time the directive is given. If different queue configurations are desired, different main message queue directives must be used **in front of** the $RulesetCreateMainQueue directive. Note that this directive may only be given once per ruleset. If multiple statements are specified, only the first is used and for the others error messages are emitted. Note that the final set of ruleset configuration directives specifies the parameters for the default main message queue. To learn more about this feature, please be sure to read about :doc:`multi-ruleset support in rsyslog `. **Caveats:** The configuration statement "$RulesetCreateMainQueue off" has no effect at all. The capability to specify this is an artifact of the legacy configuration language. **Example:** This example sets up a tcp server with three listeners. Each of these three listener is bound to a specific ruleset. As a performance optimization, the rulesets all receive their own private queue. The result is that received messages can be independently processed. With only a single main message queue, we would have some lock contention between the messages. This does not happen here. Note that in this example, we use different processing. Of course, all messages could also have been processed in the same way ($IncludeConfig may be useful in that case!). :: $ModLoad imtcp # at first, this is a copy of the unmodified rsyslog.conf #define rulesets first $RuleSet remote10514 $RulesetCreateMainQueue on # create ruleset-specific queue *.* /var/log/remote10514 $RuleSet remote10515 $RulesetCreateMainQueue on # create ruleset-specific queue *.* /var/log/remote10515 $RuleSet remote10516 $RulesetCreateMainQueue on # create ruleset-specific queue mail.* /var/log/mail10516 & ~ # note that the discard-action will prevent this message from # being written to the remote10516 file - as usual... *.* /var/log/remote10516 # and now define listeners bound to the relevant ruleset $InputTCPServerBindRuleset remote10514 $InputTCPServerRun 10514 $InputTCPServerBindRuleset remote10515 $InputTCPServerRun 10515 $InputTCPServerBindRuleset remote10516 $InputTCPServerRun 10516 Note the positions of the directives. With the legacy language, position is very important. It is highly suggested to use the *ruleset()* object in RainerScript config language if you intend to use ruleset queues. The configuration is much more straightforward in that language and less error-prone. rsyslog-8.2608.0/doc/source/configuration/ruleset/PaxHeaders/index.rst0000644000000000000000000000013215132411300022765 xustar0030 mtime=1768559296.183884327 30 atime=1787067672.929461155 30 ctime=1787067791.524671572 rsyslog-8.2608.0/doc/source/configuration/ruleset/index.rst0000666000175000017500000000161015132411300022431 0ustar00rgerrgerRuleset-Specific Legacy Configuration Statements ================================================ These statements can be used to set ruleset parameters. To set these parameters, first use *$Ruleset*, **then** use the other configuration directives. Please keep in mind that each ruleset has a *main* queue. To specify parameter for these ruleset (main) queues, use the main queue configuration directives. .. toctree:: :glob: *rule* - **$Ruleset** *name* - starts a new ruleset or switches back to one already defined. All following actions belong to that new rule set. the *name* does not yet exist, it is created. To switch back to rsyslog's default ruleset, specify "RSYSLOG\_DefaultRuleset") as the name. All following actions belong to that new rule set. It is advised to also read our paper on :doc:`using multiple rule sets in rsyslog <../../concepts/multi_ruleset>`. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/input_directives0000644000000000000000000000013215241076617022767 xustar0030 mtime=1787067791.180665161 30 atime=1787067808.812993723 30 ctime=1787067791.180665161 rsyslog-8.2608.0/doc/source/configuration/input_directives/0000775000175000017500000000000015241076617022510 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_dropmsgswithmaliciousd0000644000000000000000000000031515132733117031223 xustar00115 path=rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_dropmsgswithmaliciousdnsptrrecords.rst 30 mtime=1768666703.892620011 30 atime=1787067671.979443445 30 ctime=1787067791.172665012 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_dropmsgswithmaliciousdnsptrrecord0000666000175000017500000000146715132733117033164 0ustar00rgerrger$DropMsgsWithMaliciousDnsPTRRecords ----------------------------------- **Type:** global configuration parameter **Default:** off **Description:** Rsyslog contains code to detect malicious DNS PTR records (reverse name resolution). An attacker might use specially-crafted DNS entries to make you think that a message might have originated on another IP address. Rsyslog can detect those cases. It will log an error message in any case. If this option here is set to "on", the malicious message will be completely dropped from your logs. If the option is set to "off", the message will be logged, but the original IP will be used instead of the DNS name. Reverse lookup results are cached; see :ref:`reverse_dns_cache` for controlling cache timeout and refresh. **Sample:** ``$DropMsgsWithMaliciousDnsPTRRecords on`` rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_markmessageperiod.rst0000644000000000000000000000013215132411300030710 xustar0030 mtime=1768559296.176884216 30 atime=1787067672.095445607 30 ctime=1787067791.180665161 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_markmessageperiod.rst0000666000175000017500000000125715132411300030363 0ustar00rgerrger$MarkMessagePeriod ------------------ **Type:** specific to immark input module **Default:** 1200 (20 minutes) **Description:** This specifies when mark messages are to be written to output modules. The time specified is in seconds. Specifying 0 is possible and disables mark messages. In that case, however, it is more efficient to NOT load the immark input module. So far, there is only one mark message process and any subsequent $MarkMessagePeriod overwrites the previous. **This parameter is only available after the immark input module has been loaded.** **Sample:** ``$MarkMessagePeriod  600 # mark messages appear every 10 Minutes`` **Available since:** rsyslog 3.0.0 rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_controlcharacterescape0000644000000000000000000000013215132411300031115 xustar0030 mtime=1768559296.175884201 30 atime=1787067671.966443203 30 ctime=1787067791.169664956 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_controlcharacterescapeprefix.rst0000666000175000017500000000137115132411300032612 0ustar00rgerrger$ControlCharacterEscapePrefix ----------------------------- **Type:** global configuration parameter **Default:** \\ **Description:** This option specifies the prefix character to be used for control character escaping (see option $EscapeControlCharactersOnReceive). By default, it is '\\', which is backwards-compatible with sysklogd. Change it to '#' in order to be compliant to the value that is somewhat suggested by Internet-Draft syslog-protocol. **IMPORTANT**: do not use the ' character. This is reserved and will most probably be used in the future as a character delimiter. For the same reason, the syntax of this parameter will probably change in future releases. **Sample:** ``$EscapeControlCharactersOnReceive #  # as of syslog-protocol`` rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_droptrailinglfonrecept0000644000000000000000000000013215216464435031203 xustar0030 mtime=1782212893.972265311 30 atime=1787067672.042444619 30 ctime=1787067791.174665049 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_droptrailinglfonreception.rst0000664000175000017500000000164515216464435032172 0ustar00rgerrger$DropTrailingLFOnReception -------------------------- **Type:** global configuration parameter **Default:** on **Description:** This is a legacy directive. For new configurations, prefer the modern ``global(parser.dropTrailingLFOnReception="...")`` form. To remove a trailing carriage return (CR) after LF handling, use ``global(parser.dropTrailingCROnReception="on")`` or the legacy ``$DropTrailingCROnReception on`` directive. Syslog messages frequently have the line feed character (LF) as the last character of the message. In almost all cases, this LF should not really become part of the message. However, recent IETF syslog standardization recommends against modifying syslog messages (e.g. to keep digital signatures valid). This option allows to specify if trailing LFs should be dropped or not. The default is to drop them, which is consistent with what sysklogd does. **Sample:** ``$DropTrailingLFOnReception on`` rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_escapecontrolcharacter0000644000000000000000000000031315171370365031140 xustar00113 path=rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_escapecontrolcharactersonreceive.rst 30 mtime=1776677109.108907945 30 atime=1787067672.070445141 30 ctime=1787067791.178665124 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_escapecontrolcharactersonreceive.0000664000175000017500000000243215171370365032745 0ustar00rgerrger$EscapeControlCharactersOnReceive --------------------------------- **Type:** global configuration parameter **Default:** on **Description:** This parameter instructs rsyslogd to replace control characters during reception of the message. The intent is to provide a way to stop non-printable messages from entering the syslog system as whole. If this option is turned on, all control-characters are converted to a 3-digit octal number and be prefixed with the $ControlCharacterEscapePrefix character (being '\\' by default). For example, if the BEL character (ctrl-g) is included in the message, it would be converted to "\\007". To be compatible to sysklogd, this option must be turned on. **Warning:** - turning on this option most probably destroys non-western character sets (like Japanese, Chinese and Korean) - turning on this option destroys digital signatures if such exists inside the message - if turned on, the drop-cc, space-cc and escape-cc :doc:`property replacer ` options do not work as expected because control characters are already removed upon message reception. If you intend to use these property replacer options, you must turn off $EscapeControlCharactersOnReceive. **Sample:** ``$EscapeControlCharactersOnReceive on`` rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_allowedsender.rst0000644000000000000000000000013215241075234030053 xustar0030 mtime=1787067036.575577733 30 atime=1787067036.719580429 30 ctime=1787067791.167664919 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_allowedsender.rst0000664000175000017500000000731615241075234027526 0ustar00rgerrger$AllowedSender -------------- **Type:** legacy global input configuration directive **Default:** all allowed **Description:** *Note:* this legacy directive is supported for backward compatibility. New configurations should use the modern :ref:`imtcp AllowedSender ` and :ref:`imudp AllowedSender ` module or input parameters. The rsyslog team recommends proper firewalling as the first line of defense. Allowed sender lists can be used to specify which remote systems are allowed to send syslog messages to rsyslogd. With them, further hurdles can be placed between an attacker and rsyslogd. If a message from a system not in the allowed sender list is received, that message is discarded. A diagnostic message is logged, so that the fact is recorded (this message can be turned off with the "-w" rsyslogd command line option). Allowed sender lists can be defined for UDP and TCP senders separately. There can be as many allowed senders as needed. The syntax to specify them is: :: $AllowedSender , ip[/bits], ip[/bits] "$AllowedSender" is the parameter - it must be written exactly as shown and the $ must start at the first column of the line. "" is either "UDP" or "TCP" (or "GSS", if this is enabled during compilation). It must immediately be followed by the comma, else you will receive an error message. "ip[/bits]" is a machine or network ip address as in "192.0.2.0/24" or "127.0.0.1". If the "/bits" part is omitted, a single host is assumed (32 bits or mask 255.255.255.255). "/0" is not allowed, because that would match any sending system. If you intend to do that, just remove all $AllowedSender parameters. If more than 32 bits are requested with IPv4, they are adjusted to 32. For IPv6, the limit is 128 for obvious reasons. Hostnames, with and without wildcards, may also be provided. If so, the result of revers DNS resolution is used for filtering. Multiple allowed senders can be specified in a comma-delimited list. Also, multiple $AllowedSender lines can be given. They are all combined into one UDP and one TCP list. Performance-wise, it is good to specify those allowed senders with high traffic volume before those with lower volume. As soon as a match is found, no further evaluation is necessary and so you can save CPU cycles. Modern ``AllowedSender`` parameters support the same address syntax as this legacy directive. A module-level list is used as the default for inputs of the same module, and an input-level list overrides that module default. Do not mix legacy ``$AllowedSender`` and modern ``AllowedSender`` in new configurations. Rsyslogd handles allowed sender detection very early in the code, nearly as the first action after receiving a message. This keeps the access to potential vulnerable code in rsyslog at a minimum. However, it is still a good idea to impose allowed sender limitations via firewalling. **WARNING:** by UDP design, rsyslogd can not identify a spoofed sender address in UDP syslog packets. As such, a malicious person could spoof the address of an allowed sender, send such packets to rsyslogd and rsyslogd would accept them as being from the faked sender. To prevent this, use syslog via TCP exclusively. If you need to use UDP-based syslog, make sure that you do proper egress and ingress filtering at the firewall and router level. Rsyslog also detects some kind of malicious reverse DNS entries. In any case, using DNS names adds an extra layer of vulnerability. Reverse lookup results are cached; see :ref:`reverse_dns_cache` for ways to refresh cached names. We recommend to stick with hard-coded IP addresses wherever possible. **Sample:** :: $AllowedSender UDP, 127.0.0.1, 192.0.2.0/24, [::1]/128, *.example.net, somehost.example.com rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/rsconf1_escape8bitcharsonrecei0000644000000000000000000000013215171370365031036 xustar0030 mtime=1776677109.108907945 30 atime=1787067672.057444899 30 ctime=1787067791.176665087 rsyslog-8.2608.0/doc/source/configuration/input_directives/rsconf1_escape8bitcharsonreceive.rst0000664000175000017500000000271715171370365031653 0ustar00rgerrger$Escape8BitCharactersOnReceive ------------------------------ **Type:** global configuration parameter **Default:** off **Available Since:** 5.5.2 **Description:** This parameter instructs rsyslogd to replace non US-ASCII characters (those that have the 8th bit set) during reception of the message. This may be useful for some systems. Please note that this escaping breaks Unicode and many other encodings. Most importantly, it can be assumed that Asian and European characters will be rendered hardly readable by this settings. However, it may still be useful when the logs themselves are primarily in English and only occasionally contain local script. If this option is turned on, all control-characters are converted to a 3-digit octal number and be prefixed with the $ControlCharacterEscapePrefix character (being '#' by default). **Warning:** - turning on this option most probably destroys non-western character sets (like Japanese, Chinese and Korean) as well as European character sets. - turning on this option destroys digital signatures if such exists inside the message - if turned on, the drop-cc, space-cc and escape-cc :doc:`property replacer ` options do not work as expected because control characters are already removed upon message reception. If you intend to use these property replacer options, you must turn off $Escape8BitCharactersOnReceive. **Sample:** ``$Escape8BitCharactersOnReceive on`` rsyslog-8.2608.0/doc/source/configuration/input_directives/PaxHeaders/index.rst0000644000000000000000000000013215132411300024662 xustar0030 mtime=1768559296.175884201 30 atime=1787067671.937442662 30 ctime=1787067791.165664882 rsyslog-8.2608.0/doc/source/configuration/input_directives/index.rst0000666000175000017500000000137015132411300024331 0ustar00rgerrgerLegacy Directives affecting Input Modules ========================================= Legacy Directives affecting multiple Input Modules -------------------------------------------------- While these directives only affect input modules, they are global in the sense that they cannot be overwritten for specific input instances. So they apply globally for all inputs that support these directives. .. toctree:: :glob: rsconf1_allowedsender rsconf1_dropmsgswithmaliciousdnsptrrecords rsconf1_controlcharacterescapeprefix rsconf1_droptrailinglfonreception rsconf1_escape8bitcharsonreceive rsconf1_escapecontrolcharactersonreceive immark-specific Directives -------------------------- .. toctree:: :glob: rsconf1_markmessageperiod rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/droppriv.rst0000644000000000000000000000013215132411300022040 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.094445589 30 ctime=1787067791.114663931 rsyslog-8.2608.0/doc/source/configuration/droppriv.rst0000666000175000017500000000247115132411300021512 0ustar00rgerrgerDropping privileges in rsyslog ============================== **Available since**: 4.1.1 **Description**: Rsyslogd provides the ability to drop privileges by impersonating as another user and/or group after startup. Please note that due to POSIX standards, rsyslogd always needs to start up as root if there is a listener who must bind to a network port below 1024. For example, the UDP listener usually needs to listen to 514 and therefore rsyslogd needs to start up as root. If you do not need this functionality, you can start rsyslog directly as an ordinary user. That is probably the safest way of operations. However, if a startup as root is required, you can use the $PrivDropToGroup and $PrivDropToUser config directives to specify a group and/or user that rsyslogd should drop to after initialization. Once this happens, the daemon runs without high privileges (depending, of course, on the permissions of the user account you specified). A special note for Docker and other container system users: user and group names are usually not fully mirrored into containers. As such, we strongly advise to use numerical IDs instead of user or group names when configuring privilege drop. Privilege drop is configured via the :doc:`global configuration object<../rainerscript/global>` under the "`privilege.`" set of parameters. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/properties.rst0000644000000000000000000000013215241075234022404 xustar0030 mtime=1787067036.578577789 30 atime=1787067036.722580485 30 ctime=1787067791.515671404 rsyslog-8.2608.0/doc/source/configuration/properties.rst0000664000175000017500000003334515241075234022060 0ustar00rgerrgerrsyslog Properties ================== Data items in rsyslog are called "properties". They can have different origin. The most important ones are those that stem from received messages. But there are also others. Whenever you want to access data items, you need to access the respective property. Properties are used in - :doc:`templates ` - conditional statements The property name is case-insensitive (prior to 3.17.0, they were case-sensitive). Note: many users refer to "rsyslog properties" as "rsyslog variables". You can treat them as synonymous. Read how `rsyslog lead author Rainer Gerhards explains the naming difference `_. Message Properties ------------------ These are extracted by rsyslog parsers from the original message. All message properties start with a letter. The following message properties exist: .. note:: Property names are case-insensitive. Use the spelling from headings in prose and examples. .. list-table:: :widths: 30 70 :header-rows: 1 * - Property - Summary * - :ref:`prop-message-msg` - .. include:: ../reference/properties/message-msg.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-rawmsg` - .. include:: ../reference/properties/message-rawmsg.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-rawmsg-after-pri` - .. include:: ../reference/properties/message-rawmsg-after-pri.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-hostname` - .. include:: ../reference/properties/message-hostname.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-source` - .. include:: ../reference/properties/message-source.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-fromhost` - .. include:: ../reference/properties/message-fromhost.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-fromhost-ip` - .. include:: ../reference/properties/message-fromhost-ip.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-fromhost-port` - .. include:: ../reference/properties/message-fromhost-port.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogtag` - .. include:: ../reference/properties/message-syslogtag.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-programname` - .. include:: ../reference/properties/message-programname.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-pri` - .. include:: ../reference/properties/message-pri.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-pri-text` - .. include:: ../reference/properties/message-pri-text.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-iut` - .. include:: ../reference/properties/message-iut.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogfacility` - .. include:: ../reference/properties/message-syslogfacility.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogfacility-text` - .. include:: ../reference/properties/message-syslogfacility-text.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogseverity` - .. include:: ../reference/properties/message-syslogseverity.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogseverity-text` - .. include:: ../reference/properties/message-syslogseverity-text.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogpriority` - .. include:: ../reference/properties/message-syslogpriority.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-syslogpriority-text` - .. include:: ../reference/properties/message-syslogpriority-text.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-timegenerated` - .. include:: ../reference/properties/message-timegenerated.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-timereceived` - .. include:: ../reference/properties/message-timereceived.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-timereported` - .. include:: ../reference/properties/message-timereported.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-timestamp` - .. include:: ../reference/properties/message-timestamp.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-protocol-version` - .. include:: ../reference/properties/message-protocol-version.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-structured-data` - .. include:: ../reference/properties/message-structured-data.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-app-name` - .. include:: ../reference/properties/message-app-name.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-procid` - .. include:: ../reference/properties/message-procid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-msgid` - .. include:: ../reference/properties/message-msgid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-inputname` - .. include:: ../reference/properties/message-inputname.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-uuid` - .. include:: ../reference/properties/message-uuid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-message-jsonmesg` - .. include:: ../reference/properties/message-jsonmesg.rst :start-after: .. summary-start :end-before: .. summary-end System Properties ----------------- These properties are provided by the rsyslog core engine. They are **not** related to the message. All system properties start with a dollar-sign. Special care needs to be taken in regard to time-related system variables: * ``timereported`` contains the timestamp that is contained within the message header. Ideally, it resembles the time when the message was created at the original sender. Depending on how long the message was in the relay chain, this can be quite old. * ``timegenerated`` contains the timestamp when the message was received by the local system. ``timereceived`` is an alias with the same value and clearer naming. Here "received" actually means the point in time when the message was handed over from the OS to rsyslog's reception buffers, but before any actual processing takes place. This also means a message is "received" before it is placed into any queue. Note that depending on the input, some minimal processing like extraction of the actual message content from the receive buffer can happen. If multiple messages are received via the same receive buffer (a common scenario for example with TCP-based syslog), they bear the same ``timegenerated`` / ``timereceived`` stamp because they actually were received at the same time. * ``$now`` is **not** from the message. It is the system time when the message is being **processed**. There is always a small difference between ``timegenerated`` and ``$now`` because processing always happens after reception. If the message is sitting inside a queue on the local system, the time difference between the two can be some seconds (e.g. due to a message burst and in-memory queueing) up to several hours in extreme cases where a message is sitting inside a disk queue (e.g. due to a database outage). The ``timereported`` property is usually older than ``timegenerated``, but may be totally different due to differences in time and time zone configuration between systems. The following system properties exist: .. list-table:: :widths: 30 70 :header-rows: 1 * - Property - Summary * - :ref:`prop-system-bom` - .. include:: ../reference/properties/system-bom.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-myhostname` - .. include:: ../reference/properties/system-myhostname.rst :start-after: .. summary-start :end-before: .. summary-end Time-Related System Properties .............................. All of these system properties exist in a local time variant (e.g. \$now) and a variant that emits UTC (e.g. \$now-utc). The UTC variant is always available by appending "-utc". Note that within a single template, only the localtime or UTC variant should be used. While it is possible to mix both variants within a single template, it is **not** guaranteed that they will provide exactly the same time. The technical reason is that rsyslog needs to re-query system time when the variant is changed. Because of this, we strongly recommend not mixing both variants in the same template. Note that use in different templates will generate a consistent timestamp within each template. However, as $now always provides local system time at time of using it, time may advance and consequently different templates may have different time stamp. To avoid this, use *timegenerated* instead. .. list-table:: :widths: 30 70 :header-rows: 1 * - Property - Summary * - :ref:`prop-system-time-now` - .. include:: ../reference/properties/system-time-now.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-year` - .. include:: ../reference/properties/system-time-year.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-month` - .. include:: ../reference/properties/system-time-month.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-day` - .. include:: ../reference/properties/system-time-day.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-wday` - .. include:: ../reference/properties/system-time-wday.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-hour` - .. include:: ../reference/properties/system-time-hour.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-hhour` - .. include:: ../reference/properties/system-time-hhour.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-qhour` - .. include:: ../reference/properties/system-time-qhour.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-minute` - .. include:: ../reference/properties/system-time-minute.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`prop-system-time-now-unixtimestamp` - .. include:: ../reference/properties/system-time-now-unixtimestamp.rst :start-after: .. summary-start :end-before: .. summary-end .. toctree:: :hidden: ../reference/properties/message-msg ../reference/properties/message-rawmsg ../reference/properties/message-rawmsg-after-pri ../reference/properties/message-hostname ../reference/properties/message-source ../reference/properties/message-fromhost ../reference/properties/message-fromhost-ip ../reference/properties/message-fromhost-port ../reference/properties/message-syslogtag ../reference/properties/message-programname ../reference/properties/message-pri ../reference/properties/message-pri-text ../reference/properties/message-iut ../reference/properties/message-syslogfacility ../reference/properties/message-syslogfacility-text ../reference/properties/message-syslogseverity ../reference/properties/message-syslogseverity-text ../reference/properties/message-syslogpriority ../reference/properties/message-syslogpriority-text ../reference/properties/message-timegenerated ../reference/properties/message-timereceived ../reference/properties/message-timereported ../reference/properties/message-timestamp ../reference/properties/message-protocol-version ../reference/properties/message-structured-data ../reference/properties/message-app-name ../reference/properties/message-procid ../reference/properties/message-msgid ../reference/properties/message-inputname ../reference/properties/message-uuid ../reference/properties/message-jsonmesg ../reference/properties/system-bom ../reference/properties/system-myhostname ../reference/properties/system-time-now ../reference/properties/system-time-year ../reference/properties/system-time-month ../reference/properties/system-time-day ../reference/properties/system-time-wday ../reference/properties/system-time-hour ../reference/properties/system-time-hhour ../reference/properties/system-time-qhour ../reference/properties/system-time-minute ../reference/properties/system-time-now-unixtimestamp rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/basic_structure.rst0000644000000000000000000000013215216464435023420 xustar0030 mtime=1782212893.972265311 30 atime=1787067671.930442531 30 ctime=1787067791.100663671 rsyslog-8.2608.0/doc/source/configuration/basic_structure.rst0000664000175000017500000001675015216464435023075 0ustar00rgerrgerBasic Structure =============== .. meta:: :description: Introduction to rsyslog configuration structure, formats, rulesets, actions, and common RainerScript syntax. :keywords: rsyslog, configuration, RainerScript, ruleset, action, input, semicolon .. summary-start This page introduces the core concepts and structure of rsyslog configuration. Rsyslog is best thought of as a **highly extensible logging and event processing framework**. While the general message flow is fixed, almost every aspect of its processing pipeline can be customized by configuring rsyslog objects. .. summary-end Message Flow Overview --------------------- At a high level, rsyslog processes messages in three main stages: 1. **Inputs**: Messages are received from input modules (e.g., `imuxsock` for system logs or `imtcp` for TCP-based logging). 2. **Rulesets**: Each message is passed through one or more rulesets. A ruleset contains a sequence of rules, each with a filter and associated actions. 3. **Actions (Outputs)**: When a rule matches, its actions are executed. Actions determine what to do with the message: write to a file, forward to a remote server, insert into a database, or other processing. .. mermaid:: flowchart LR A[Input Modules] --> B[Rulesets] B --> C[Rules: Filter and Action List] C --> D[Actions and Outputs] D --> E[File, DB, Remote,
Custom Destinations] Processing Principles --------------------- Key rules to understand the rsyslog processing model: - **Rulesets as Entry Points**: Inputs submit messages to a ruleset. If no ruleset is explicitly bound, the default ruleset (`RSYSLOG_DefaultRuleset`) is used. Additional, custom rulesets can be defined. - **Rules within Rulesets**: A ruleset contains zero or more rules (though zero rules makes no sense). Rules are evaluated **in order, top to bottom**, within the ruleset. - **Filter and Action Lists**: A rule consists of a **filter** (evaluated as true/false) and an **action list**. When a filter matches, the action list is executed. If a filter does not match, rsyslog continues with the next rule. - **Full Evaluation**: All rules are evaluated unless message processing is explicitly stopped by a ``stop`` command. ``stop`` immediately halts processing for that message. - **Action Lists**: An action list can contain one or multiple actions. Actions are executed sequentially. Actions have no filters inside the same list (filters apply only at the rule level). .. mermaid:: flowchart TD Start([Message Entered]) --> CheckFilter1{Filter 1 Match?} CheckFilter1 -- Yes --> Action1[Execute Action 1] CheckFilter1 -- No --> CheckFilter2{Filter 2 Match?} CheckFilter2 -- Yes --> Action2[Execute Action 2] CheckFilter2 -- No --> End([Processing Ends]) Action1 --> CheckFilter2 Action2 --> End Configuration File ------------------ By default, rsyslog loads its configuration from ``/etc/rsyslog.conf``. This file may include other configuration snippets (commonly under ``/etc/rsyslog.d/``). To specify a different configuration file, use: .. code-block:: bash rsyslogd -f /path/to/your-config.conf Supported Configuration Formats ------------------------------- Rsyslog currently supports four configuration syntaxes: 1. **RainerScript (modern style)** - **fully supported and actively maintained** This is the current, fully supported configuration format. It is clean, structured, and a strong fit when you author rsyslog logic directly. 2. **YAML** - **fully supported for YAML-centric workflows** Use this when rsyslog is part of a broader YAML-based deployment or automation environment. YAML and RainerScript express the same underlying rsyslog concepts and share the same core semantics. 3. **sysklogd style (legacy)** - **deprecated for new configs** This format is widely known and still functional, but **hard to grasp for new users**. It remains an option for experienced admins who know it well or need to maintain older configurations. Example: .. code-block:: none mail.info /var/log/mail.log mail.err @server.example.net 4. **Legacy rsyslog style (dollar-prefix)** - **deprecated** This format, with directives starting with `$` (e.g., `$ActionFileDefaultTemplate`), is fully supported for backward compatibility but **not recommended for any new configuration**. Why Use RainerScript Directly? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RainerScript is easier to read and maintain, avoids side effects with include files, and supports modern features such as structured filters, templates, and complex control flow. For direct rsyslog authoring, RainerScript remains the clearest default. If your environment is already YAML-centric, YAML is also a first-class fit. Legacy formats exist only for compatibility with older setups and distributions. Example RainerScript rule: .. code-block:: rsyslog if $syslogfacility-text == 'mail' and $syslogseverity-text == 'err' then { action(type="omfile" file="/var/log/mail-errors.log") } Configuration objects such as ``action()``, ``module()``, and ``input()`` end at the closing parenthesis. Do not add a semicolon after them: .. code-block:: rsyslog action(type="omfile" file="/var/log/messages") # correct action(type="omfile" file="/var/log/messages"); # invalid Comments -------- Rsyslog supports: - **# Comments** — start with `#` and extend to the end of the line. - **C-style Comments** — start with `/*` and end with `*/`. These can span multiple lines but cannot be nested. Processing Order ---------------- - Directives are processed **in order from top to bottom** of the configuration. - Once a message is stopped via ``stop`` subsequent statements will not be evaluated for that message. Flow Control ~~~~~~~~~~~~ - Control structures (if/else, etc.) are available in RainerScript. - Filters (e.g., `prifilt()`) provide conditional matching for messages. See :doc:`../rainerscript/control_structures` and :doc:`filters` for details. Data Manipulation ~~~~~~~~~~~~~~~~~ Data can be modified using the `set`, `unset`, and `reset` statements. For details, refer to :doc:`../rainerscript/variable_property_types`. Inputs ------ - Each input requires a dedicated input module. - Inputs are defined using the `input()` object after loading the module. Example: .. code-block:: rsyslog module(load="imtcp") # Load TCP input module input(type="imtcp" port="514") # Listen on TCP port 514 See :doc:`modules/index` for the full list of input modules. Outputs (Actions) ----------------- - Actions are responsible for output, such as writing to files, databases, or forwarding to other systems. - Actions are configured with the `action()` object. Example: .. code-block:: rsyslog action(type="omfile" file="/var/log/messages") # Write to local file Rulesets and Rules ------------------ - A **ruleset** acts like a "program" for message processing. - A ruleset can be bound to specific inputs or used as the default. Example: .. code-block:: rsyslog ruleset(name="fileLogging") { if prifilt("*.info") then { action(type="omfile" file="/var/log/info.log") } } .. mermaid:: graph TD Input1[Input: imtcp] --> Ruleset1 Input2[Input: imudp] --> Ruleset2 Ruleset1 --> Action1[omfile] Ruleset2 --> Action2[omfwd] Ruleset2 --> Action3[omelasticsearch] For details, see :doc:`../concepts/multi_ruleset`. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/timezone.rst0000644000000000000000000000013215132411300022025 xustar0030 mtime=1768559296.184884343 30 atime=1787067671.821440499 30 ctime=1787067791.535671777 rsyslog-8.2608.0/doc/source/configuration/timezone.rst0000666000175000017500000000426015132411300021475 0ustar00rgerrgertimezone ======== .. index:: ! timezone .. _cfgobj_input: The ``timezone`` object, as its name suggests, describes timezones. Currently, they are used by message parser modules to interpret timestamps that contain timezone information via a timezone string (but not an offset, e.g. "CET" but not "-01:00"). The object describes a UTC offset for a given timezone ID. Each timestamp object adds the zone definition to a global table with timezone information. Duplicate IDs are forbidden, but the same offset may be used with multiple IDs. As with other configuration objects, parameters for this object are case-insensitive. Parameters ---------- .. function:: id *Mandatory* This identifies the timezone. Note that this id must match the zone name as reported within the timestamps. Different devices and vendors use different, often non-standard, names and so it is important to use the actual ids that messages contain. For multiple devices, this may mean that you may need to include multiple definitions, each one with a different id, for the same time zone. For example, it is seen that some devices report "CEST" for central European daylight savings time while others report "METDST" for it. .. function:: offset <[+/-]>: *Mandatory* This defines the timezone offset over UTC. It must always be 6 characters and start with a "+" (east of UTC) or "-" (west uf UTC) followed by a two-digit hour offset, a colon and a two-digit minute offset. Hour offsets can be in the range from zero to twelve, minute offsets in the range from zero to 59. Any other format is invalid. Sample ------ The following sample defines UTC time. From rsyslog PoV, it doesn't matter if a plus or minus offset prefix is used. For consistency, plus is suggested. :: timezone(id="UTC" offset="+00:00") The next sample defines some common timezones: :: timezone(id="CET" offset="+01:00") timezone(id="CEST" offset="+02:00") timezone(id="METDST" offset="+02:00") # duplicate to support different formats timezone(id="EST" offset="-05:00") timezone(id="EDT" offset="-04:00") timezone(id="PST" offset="-08:00") timezone(id="PDT" offset="-07:00") rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/output_channels.rst0000644000000000000000000000013115171370365023427 xustar0030 mtime=1776677109.111907992 29 atime=1787067672.52845368 30 ctime=1787067791.508671274 rsyslog-8.2608.0/doc/source/configuration/output_channels.rst0000664000175000017500000000644215171370365023102 0ustar00rgerrgerOutput Channels --------------- Output Channels are a new concept first introduced in rsyslog 0.9.0. **As of this writing, it is most likely that they will be replaced by something different in the future.** So if you use them, be prepared to change you configuration file syntax when you upgrade to a later release. The idea behind output channel definitions is that it shall provide an umbrella for any type of output that the user might want. In essence, this is the "file" part of selector lines (and this is why we are not sure output channel syntax will stay after the next review). There is a difference, though: selector channels both have filter conditions (currently facility and severity) as well as the output destination. they can only be used to write to files - not pipes, ttys or whatever Output channels define the output definition, only. As of this build, else. If we stick with output channels, this will change over time. In concept, an output channel includes everything needed to know about an output actions. In practice, the current implementation only carries a filename, a maximum file size and a command to be issued when this file size is reached. More things might be present in future version, which might also change the syntax of the directive. Output channels are defined via an $outchannel directive. It's syntax is as follows: $outchannel name,file-name,max-size,action-on-max-size name is the name of the output channel (not the file), file-name is the file name to be written to, max-size the maximum allowed size and action-on-max-size a command to be issued when the max size is reached. This command always has exactly one parameter. The binary is that part of action-on-max-size before the first space, its parameter is everything behind that space. Please note that max-size is queried BEFORE writing the log message to the file. So be sure to set this limit reasonably low so that any message might fit. For the current release, setting it 1k lower than you expected is helpful. The max-size must always be specified in bytes - there are no special symbols (like 1k, 1m,...) at this point of development. Keep in mind that $outchannel just defines a channel with "name". It does not activate it. To do so, you must use a selector line (see below). That selector line includes the channel name plus a $ sign in front of it. A sample might be: \*.\* :omfile:$mychannel In its current form, output channels primarily provide the ability to size-limit an output file. To do so, specify a maximum size. When this size is reached, rsyslogd will execute the action-on-max-size command and then reopen the file and retry. The command should be something like a :doc:`log rotation script ` or a similar thing. If there is no action-on-max-size command or the command did not resolve the situation, the file is closed and never reopened by rsyslogd (except, of course, by huping it). This logic was integrated when we first experienced severe issues with files larger 2gb, which could lead to rsyslogd dumping core. In such cases, it is more appropriate to stop writing to a single file. Meanwhile, rsyslogd has been fixed to support files larger 2gb, but obviously only on file systems and operating system versions that do so. So it can still make sense to enforce a 2gb file size limit. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/index_directives.rst0000644000000000000000000000013215132411300023523 xustar0030 mtime=1768559296.175884201 30 atime=1787067671.897441916 30 ctime=1787067791.160664789 rsyslog-8.2608.0/doc/source/configuration/index_directives.rst0000666000175000017500000000143715132411300023176 0ustar00rgerrgerLegacy Configuration Directives =============================== All legacy configuration directives need to be specified on a line by their own and must start with a dollar-sign. Note that legacy configuration directives that set object options (e.g. for inputs or actions) only affect those objects that are defined via legacy constructs. Objects defined via new-style RainerScript objects (e.g. action(), input()) are **not** affected by legacy directives. The reason is that otherwise we would again have the ability to mess up a configuration file with hard to understand constructs. This is avoided by not permitting to mix and match the way object values are set. .. toctree:: :maxdepth: 2 config_param_types global/index input_directives/index action/index ruleset/index rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/ipv6.rst0000644000000000000000000000013215132411300021057 xustar0030 mtime=1768559296.176884216 30 atime=1787067672.118446036 30 ctime=1787067791.182665199 rsyslog-8.2608.0/doc/source/configuration/ipv6.rst0000666000175000017500000000522415132411300020530 0ustar00rgerrgerNotes on IPv6 Handling in Rsyslog ================================= **Rsyslog fully\* supports sending and receiving syslog messages via both IPv4 and IPv6.** IPv6 is natively supported for both UDP and TCP. However, there are some options that control handling of IPv6 operations. I thought it is a good idea to elaborate a little about them, so that you can probably find your way somewhat easier. First of all, you can restrict rsyslog to using IPv4 or IPv6 addresses only by specifying the -4 or -6 command line option (now guess which one does what...). If you do not provide any command line option, rsyslog uses IPv4 and IPv6 addresses concurrently. In practice, that means the listener binds to both addresses (provided they are configured). When sending syslog messages, rsyslog uses IPv4 addresses when the receiver can be reached via IPv4 and IPv6 addresses if it can be reached via IPv6. If it can be reached on either IPv4 and v6, rsyslog leaves the choice to the socket layer. The important point to know is that it uses whatever connectivity is available to reach the destination. **There is one subtle difference between UDP and TCP.** With the new IPv4/v6 ignorant code, rsyslog has potentially different ways to reach destinations. The socket layer returns all of these paths in a sorted array. For TCP, rsyslog loops through this array until a successful TCP connect can be made. If that happens, the other addresses are ignored and messages are sent via the successfully-connected socket. For UDP, there is no such definite success indicator. Sure, the socket layer may detect some errors, but it may not notice other errors (due to the unreliable nature of UDP). By default, the UDP sender also tries one entry after the other in the sorted array of destination addresses. When a send fails, the next address is tried. When the send function finally succeeds, rsyslogd assumes the UDP packet has reached its final destination. However, if rsyslogd is started with the "-A" (capital A!) was given on the command line, rsyslogd will continue to send messages until the end of the destination address array is reached. This may result in duplicate messages, but it also provides some additional reliability in case a message could not be received. You need to be sure about the implications before applying this option. In general, it is NOT recommended to use the -A option. **\***\ rsyslog does not support RFC 3195 over IPv6. The reason is that the RFC 3195 library, `liblogging `_, supports IPv4, only. Currently, there are no plans to update either rsyslog to another RFC 3195 stack or update liblogging. There is simply no demand for 3195 solutions. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/dyn_stats.rst0000644000000000000000000000013115145046112022213 xustar0029 mtime=1771326538.91601228 30 atime=1787067672.107445831 30 ctime=1787067791.116663969 rsyslog-8.2608.0/doc/source/configuration/dyn_stats.rst0000664000175000017500000001416015145046112021662 0ustar00rgerrgerDynamic Stats ============= Rsyslog produces runtime-stats to allow user to study service health, performance, bottlenecks etc. Runtime-stats counters that Rsyslog components publish are statically defined. **Dynamic Stats** (called dyn-stats henceforth) component allows user to configure stats-namespaces (called stats-buckets) and increment counters within these buckets using RainerScript function call. The metric-name in this case can be a message-property or a sub-string extracted from message etc. Dyn-stats configuration ^^^^^^^^^^^^^^^^^^^^^^^ Dyn-stats configuration involves a **two part setup**. dyn_stats(name=""...) (object) -------------------------------------- **Defines** the bucket(identified by the bucket-name) and allows user to set some properties that control behavior of the bucket. :: dyn_stats(name="msg_per_host") Parameters: **name** : Name of the bucket. **resettable** : Whether or not counters should be reset every time they are reported. This works independent of ``resetCounters`` config parameter in :doc:`modules/impstats`. **maxCardinality** : Maximum number of unique counter-names to track. **unusedMetricLife** : Interval between full purges (in seconds). This prevents unused counters from occupying resources forever. **persistStateInterval** : Number of bucket updates before persisting state to disk. When set to 0 (default), count-based persistence is disabled. When set to a positive value, the bucket state will be written to disk after this many counter updates. **persistStateTimeInterval** : Time interval in seconds before persisting bucket state to disk. When set to 0 (default), time-based persistence is disabled. When set to a positive value, the bucket state will be written to disk at least once per interval when counters change. If a bucket remains idle (no counter updates), no periodic write is performed because the persisted state is already current. **statefile.directory** : Directory where state files should be stored. If not specified, the global ``workDirectory`` is used. State files are named ``dynstats-state:``. A definition setting all the parameters looks like: :: dyn_stats(name="msg_per_host" resettable="on" maxCardinality="3000" unusedMetricLife="600") To enable persistence: :: dyn_stats(name="msg_per_host" persistStateInterval="100" statefile.directory="/var/lib/rsyslog/dynstats") dyn_inc("", ) (function) -------------------------------------- **Increments** counter identified by value of variable in bucket identified by name. Parameters: **name** : Name of the bucket **expr** : Name of counter (this name will be reported by impstats to identify the counter) A ``dyn_inc`` call looks like: :: set $.inc = dyn_inc("msg_per_host", $hostname); if ($.inc != 0) then { .... } ``$.inc`` captures the error-code. It has value ``0`` when increment operation is successful and non-zero when it fails. It uses Rsyslog error-codes. State Persistence ^^^^^^^^^^^^^^^^^ When ``persistStateInterval`` or ``persistStateTimeInterval`` is configured for a bucket, dynstats will save the current counter values to disk when counters are updated. This allows counters to survive rsyslog restarts. If there are no counter updates, no write is triggered because the on-disk state remains current. **State File Format**: State files are written in JSON format with the following structure: :: { "name": "bucket_name", "values": { "metric1": 42, "metric2": 17 } } **Startup Behavior**: When rsyslog starts, it automatically loads state files for buckets with persistence enabled. If a state file exists, counter values are restored; otherwise, counters start at zero. **File Write Worker**: A background thread handles state file writes to avoid blocking message processing. The worker is automatically started when the first bucket with persistence is created. **Persistence Stats**: Three additional counters are reported for each bucket with persistence enabled: - ``_flushed_bytes``: Total bytes written to state files - ``_flushed_counts``: Number of successful state file writes - ``_flush_errors``: Number of failed state file write attempts Reporting ^^^^^^^^^ Legacy format: :: ... global: origin=dynstats msg_per_host.ops_overflow=1 msg_per_host.new_metric_add=3 msg_per_host.no_metric=0 msg_per_host.metrics_purged=0 msg_per_host.ops_ignored=0 ... msg_per_host: origin=dynstats.bucket foo=2 bar=1 baz=1 ... Json(variants with the same structure are used in other Json based formats such as ``cee`` and ``json-elasticsearch``) format: :: ... { "name": "global", "origin": "dynstats", "values": { "msg_per_host.ops_overflow": 1, "msg_per_host.new_metric_add": 3, "msg_per_host.no_metric": 0, "msg_per_host.metrics_purged": 0, "msg_per_host.ops_ignored": 0 } } ... { "name": "msg_per_host", "origin": "dynstats.bucket", "values": { "foo": 2, "bar": 1, "baz": 1 } } ... In this case counters are encapsulated inside an object hanging off top-level-key ``values``. Fields ------ **global: origin=dynstats**: **ops_overflow**: Number of operations ignored because number-of-counters-tracked has hit configured max-cardinality. **new_metric_add**: Number of "new" metrics added (new counters created). **no_metric**: Counter-name given was invalid (length = 0). **metrics_purged**: Number of counters discarded at discard-cycle (controlled by **unusedMetricLife**). **ops_ignored**: Number of operations ignored due to potential performance overhead. Dyn-stats subsystem ignores operations to avoid performance-penalty if it can't get access to counter without delay(lock acquiring latency). **purge_triggered**: Indicates that a discard was performed (1 implies a discard-cycle run). **msg_per_host: origin=dynstats.bucket**: ****: Value of counter identified by . rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/rsyslog-example.conf0000644000000000000000000000013215132733117023460 xustar0030 mtime=1768666703.898620102 30 atime=1787067686.625716472 30 ctime=1787067791.519671479 rsyslog-8.2608.0/doc/source/configuration/rsyslog-example.conf0000666000175000017500000001402715132733117023132 0ustar00rgerrger# A commented quick reference and sample configuration # WARNING: This is not a manual, the full manual of rsyslog configuration is in # rsyslog.conf (5) manpage # # "$" starts lines that contain new directives. The full list of directives # can be found in /usr/share/doc/rsyslog-1.19.6/doc/rsyslog_conf.html or online # at http://www.rsyslog.com/doc if you do not have (or find) a local copy. # # Set syslogd options # Some global directives # ---------------------- # $AllowedSender - specifies which remote systems are allowed to send syslog messages to rsyslogd # -------------- $AllowedSender UDP, 127.0.0.1, 192.0.2.0/24, [::1]/128, *.example.net, somehost.example.com # $UMASK - specifies the rsyslogd processes' umask # ------ $umask 0000 # $FileGroup - Set the group for dynaFiles newly created # ---------- $FileGroup loggroup # $FileOwner - Set the file owner for dynaFiles newly created. # ---------- $FileOwner loguser # $IncludeConfig - include other files into the main configuration file # -------------- $IncludeConfig /etc/some-included-file.conf # one file $IncludeConfig /etc/rsyslog.d/ # whole directory (must contain the final slash) # $ModLoad - Dynamically loads a plug-in and activates it # -------- $ModLoad ommysql # load MySQL functionality $ModLoad /rsyslog/modules/somemodule.so # load a module via absolute path # Templates # --------- # Templates allow to specify any format a user might want. # They MUST be defined BEFORE they are used. # A template consists of a template directive, a name, the actual template text # and optional options. A sample is: # $template MyTemplateName,"\7Text %property% some more text\n", # where: # * $template - tells rsyslog that this line contains a template. # * MyTemplateName - template name. All other config lines refer to this name. # * "\7Text %property% some more text\n" - templage text # The backslash is an escape character, i.e. \7 rings the bell, \n is a new line. # To escape: # % = \% # \ = \\ # Template options are case-insensitive. Currently defined are: # sql format the string suitable for an SQL statement. This will replace single # quotes ("'") by two single quotes ("''") to prevent the SQL injection # (NO_BACKSLASH_ESCAPES turned off) # stdsql - format the string suitable for an SQL statement that is to # be sent to a standards-compliant sql server. # (NO_BACKSLASH_ESCAPES turned on) # Properties inside templates # --------------------------- # Properties can be modified by the property replacer. They are accessed # inside the template by putting them between percent signs. The full syntax is as follows: # %propname:fromChar:toChar:options% # FromChar and toChar are used to build substrings. # If you need to obtain the first 2 characters of the # message text, you can use this syntax: "%msg:1:2%". # If you do not wish to specify from and to, but you want to # specify options, you still need to include the colons. # For example, to convert the full message text to lower case only, use # "%msg:::lowercase%". # The full list of property options can be found in rsyslog.conf(5) manpage # Samples of template definitions # ------------------------------- # A template that resambles traditional syslogd file output: $template TraditionalFormat,"%timegenerated% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n" # A more verbose template: $template precise,"%syslogpriority%,%syslogfacility%,%timegenerated::fulltime%,%HOSTNAME%,%syslogtag%,%msg%\n" # A template that resembles RFC 3164 on-the-wire format: # (yes, there is NO space between syslogtag and msg! that's important!) $template RFC3164fmt,"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%msg%" # a template resembling traditional wallmessage format: $template wallmsg,"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r" # The template below emulates winsyslog format, but we need to check the time # stamps used. It is also a good sampleof the property replacer in action. $template WinSyslogFmt,"%HOSTNAME%,%timegenerated:1:10:date-rfc3339%,%timegenerated:12:19:date-rfc3339%,%timegenerated:1:10:date-rfc3339%,%timegenerated:12:19:date-rfc3339%,%syslogfacility%,%syslogpriority%,%syslogtag%%msg%\n" # A template used for database writing (notice it *is* an actual # sql-statement): $template dbFormat,"insert into SystemEvents (Message, Facility,FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%',%syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')",sql # Samples of rules # ---------------- # Regular file # ------------ *.* /var/log/traditionalfile.log;TraditionalFormat # log to a file in the traditional format # Forwarding to remote machine # ---------------------------- *.* @172.19.2.16 # udp (standard for syslog) *.* @@172.19.2.17 # tcp # Database action # --------------- # (you must have rsyslog-mysql package installed) # !!! Don't forget to set permission of rsyslog.conf to 600 !!! *.* >hostname,dbname,userid,password # (default Monitorware schema, can be created by /usr/share/doc/rsyslog-mysql-1.19.6/createDB.sql) # And this one uses the template defined above: *.* >hostname,dbname,userid,password;dbFormat # Program to execute # ------------------ *.* ^alsaunmute # set default volume to soundcard # Filter using regex # ------------------ # if the user logges word rulez or rulezz or rulezzz or..., then we will shut down his pc # (note, that + have to be double backslashed...) :msg, regex, "rulez\\+" ^poweroff # A more complex example # ---------------------- $template bla_logged,"%timegenerated% the BLA was logged" :msg, contains, "bla" ^logger;bla_logged # Pipes # ----- # first we need to create pipe by # mkfifo /a_big_pipe *.* |/a_big_pipe # Discarding # ---------- *.* ~ # discards everything rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/global0000644000000000000000000000013215241076617020647 xustar0030 mtime=1787067791.123664099 30 atime=1787067808.812993723 30 ctime=1787067791.123664099 rsyslog-8.2608.0/doc/source/configuration/global/0000775000175000017500000000000015241076617020370 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/global/PaxHeaders/options0000644000000000000000000000013215241076617022342 xustar0030 mtime=1787067791.156664714 30 atime=1787067808.812993723 30 ctime=1787067791.156664714 rsyslog-8.2608.0/doc/source/configuration/global/options/0000775000175000017500000000000015241076617022063 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsyslog_confgraph_complex.png0000644000000000000000000000013215132411300030362 xustar0030 mtime=1768559296.174884185 30 atime=1787067730.695537918 30 ctime=1787067791.154664677 rsyslog-8.2608.0/doc/source/configuration/global/options/rsyslog_confgraph_complex.png0000666000175000017500000042754415132411300030050 0ustar00rgerrger‰PNG  IHDRP—ómûbKGDÿÿÿ ½§“ pHYsHHFÉk> vpAgP XU°€IDATxÚìýw\÷þÿ?v—¥#UŠ(6°cÁ†½w±aÁ‚%±ÆÞMLb4‰-cbŒG�Æbï½WPQ¬  "* ½·Ý¹þø�ó½rò9ç$ꪼîÿxËì2ïç¼goáÉÌìŒJù'„BQb¨ @!„ož‘¡!Ä3¿g~Ïü`¿Ñ~£ýF�j�j�j ª‘ª‘ª‘€‚ÂÛ|œÒ[lA™­ÌVfƒEŠEŠE t×u\×qPubÕ‰U'‚ê¹ê¹ê¹¡Ã ñÿQÉ)!Ä›–=9{röd8ÔýP÷CÝá°ýaûÃöàvÀí€Û¨u¥Ö•ZW@å®rW¹™d’ièÔÿ‡F4¢èëëCL‡˜1 bJÄ”ˆ)Ðâ‹_´ø|³}³}³Áî˜Ý1»c†-J:)Bˆ×Ng¢3Ñ™ÀÕaW‡]Aß}ô=hÖjÖjÖ Aƒ ^#¼Fx�ÍÍÍC§þ\pÁîëîëîë °]`»Àv�0#aF è;¯ï¼¾ó µ}kûÖö`²Éd“É&C‡%�!Ä«W—ºÔ…˜f1ÍbšA`ëÀÖ�­á�É“&ÐóÇž?öü:÷ïÜ¿s0ûÐìC³!eqÊâ”Åp1ùbòÅdȘ•1+c¨WªWªWòÖ P:(”`z×ô®é]hfÖ̬™”©]¦v™ÚPÔ½¨{Qw¸Pp¡àBlÓnÓnÓ‚Ý&»Mv›`È€!† €_ÕøªÆW úLõ™ê3Co•xßIB¼2YͲše5ƒ}“÷MÞ7N,>±øÄb¨;§îœºsÀïŠß¿+à²Üe¹Ër(š^4½h:œß~ÿùý°½þöúÛëƒæ�æ�æ¸å¸å¸å¼üoå²rY¹lè­ü#UUUxžö<íy¤ú§ú§úC‡= ³®³®³Ìš/4_iåÒÊ¥•ƒ=c÷ŒÝ3Ο)>S Þ›¼7yo‚þ¾ý}ûûBéoJSúCo�x_IBüeEnEnEn21dbÈDØÚck�­=À"À"À";vì unÔ¹Q稂TAª ¸×è^£{� Ð%Ð%Ð’þ‘ô�¤@ß«}¯ö½ ­ú·êߪ?˜¤˜¤˜¤z+ÿ{Å{Š÷ï�ÐJ¡•B+ÁÖÎ[;oí êáêáêá0H=H=H ^ã¼Æy�µ³ÚYí �¶<Úòh > |øž9=szæ½§÷žÞ{:´Éh“Ñ&ÌUæ*s•¡·R¼/¤!þkÊfe³²¢—F/�^ åÊ”ƒ§6OmžÚ@oÓÞ¦½M¡½¦½¦½L×™®3]ÉaÉaÉa°Ój§ÕN+¸”{)÷R.´œÔrRËIàëçëçëvãìÆÙ�ƒÜ/r¿Èý”yPæAÈ3Ê3Ê3Õ(Õ(Õ(CÏÂïæc—²KÙÆ?ÿhü#Tʪ”U) l.Û\¶¹ 9Ãs†ç ‡Ce•=T�?tþÐy¨Y®f¹šå``ß�}ö…r½Ëõ.׊sŠsŠsà’ú’ú’¶®Þºzëj°p·p·pÿŠþý+‚ç Ïž3@}\}\}Üг ÞUR„ÿQzÿôþéýaOõ=Õ÷T‡ÓV§­N[AãøÆñ�ã¡ß'ý>é÷ 898989@¡}¡}¡=œúâÔ§¾€�ÝwvßÙ\×»®w]C̆˜ 1ƒ*ÙU²«dƒrU¹ª\…°åaËÖÖá[†o)­SZ§´ë@ë@ë@P"”%Âг¨P¡ÕBÕBÕBÈZ�µ:k5×7®o\–Xj`)hººéꦫA»V»V»b�b�b� hTШ Qp÷—»¿ÜýºÌè2£Ë èþA÷º–Û,·YnƒÌ#™G2�À>Í>Í> œ¨|¢ò‰ÊàuÖë¬×YÐd@“MÀ¥†K —†žñ®‘ „øƒÂ…= {ÀE“‹&M`{æöÌí™`jj ƒž z2è ÔxPãA�ÀÎpÂï‡ß¿�½{ö‚ŒmÛ2¶Aûþöýí¡ydóÈæ‘ =¬=¬= qÇ}÷1l­¼µòÖÊpÇìŽÙ3èäÜɹ“3ttêèÔÑ JÍ,5³ÔLP)‹”E†ž^€‘È;“w&ï \ìp±ÃŰ»öîÚ»kƒë×®#`pÚà´ÁiP¥s•ÎU:ƒî¶î¶î6ÜH¼‘x#¶tÙÒeK(6.6.6¿»~wýîB£'�ž4zFmŒÚµ�Ǿ�}ûBе kA×à¡î¡î¡zÔìQ³GMèЧCŸ}ÀbŒÅ‹1†ž$ñ¶“ „@Ñ):EQË¢–E-ƒ€À€À€@xÞýy÷çݡƒú‚¶ß´ý¦í7`¼Éx“ñ&Hì“Ø'±l7Þn¼Ý®Ö¿Zÿj}hÿCûÚÿ½2zeôÊë ë ë Èi’Ó$§ n{¸íá¶ppæÁ™gBõÀê�ÕaðóÁÏ?‡r_•ûªÜW†ž•¿.¹Mr›ä6°Ã{‡÷o111‡–m[¶mÙúô èv?Ùýd÷äõÏëŸ×Ž… 9ûÌö™í3÷8÷8÷8œ;8wp.T¨R¡J…* ;®;®;WG]uula [£›F7�nÂà&ƒ› nõÆÖ,hºhºhºzVÄÛF €%XÊÜ”¹)sa×Ï»~Þõ3\8zá腣ТA‹-€ïVß­¾[Á¾¯}_û¾�““'¾>ñõ‰¯ao�½uöÖ� ]*t©Ð6l •ÊT*S© èÑ£®/½¾ôúRèÐ%  ¨\T.*|lð±ÁÇ þ¶úÛêoÍ!Í!Í!CÏÊ«£ªª ÷ï;Þw„€Þ½z˵/Ö¾X ýû;öw„Ö¶þ°õ‡  ÐhàyìóØç±°íãmoûÂú†õ ë tttÐ3¹grÏd(5ºÔèR£!35353Ž4>ÒøHc8\|¸øp1xÖð¬áYÞxkà-p�u�u�5ô¬ˆ·…!J�ŸŸ8Wç\�su`çí�·wÞ§>N}œúÀàCƒ >ÕÎU;Wí(éJº’7»Ýìv³v ìØòªæUÍ« Æ ‡ÆF���vœvœvµvר]cw (W»\írµaÈÕ!W‡\÷Ûî·Ýoƒþ{ý÷úï!¬eX˰–°:`uÀêðJðJðJ€ ùò'äËXÆ2CφxÓ4_ü“¡ƒ!^¿“åO–?Y*׬\³rMÔgPŸA} h\Ѹ¢q°¿óþÎû;ÃjV³°�g;ÏvLº1鯤ÐB×B×BFéFéFéâââ ßýîèwG!±|bùÄò0:`tÀèè9µçÔžSÁº·uoëÞ†Þú·�™ÖLk¦¯k^×¼®�gˆgˆg_ ¾|v{ïöÞí ZµV­UC¥ó•ÎW:Õ÷TßS}4ñlâÙÄb2b2b2 °|`ùÀò�á”á”áîÝ/º_„ŠC+­84·4·4· *-*-* ZÎj9«å,P›«ÍÕæ†ž ñ¦ÉÓ…(A4Õ5Õ5ÕÁx¡ñBã…À&0.^¼xñâEØztëÑ­GaÚøiã§�‡†ÕVoX4&� <ªø¨â£Š49hrÐdxìöØí±ô íÚ3Úïh¿£ý0555ôÖ¾CV±ŠUà�À§e?-ûiY¸ôüÒóKÏa[Ýmu·Õ…ó{Îï9¿�4bШ•V+­VŒë<®ó¸ÎÐÚ¥µKkX~où½å÷@ÓAÓAÓ†2”¡€ö¦ö¦ö&m5Új´ÃÆð¯S ¢d‘ DI’DI ü ü üðrqVLVLV Ôq«ãVÇ ¼ã¼ã¼ã À¬À¬À ¶ßz|ëq86áØ„c Á„L€…çž[xœf9ÍršÌb³ ½‘ï¾ßÎå·¦5­�zëë­¯·ö=Ø÷`ßø¦÷7½¿é mÚ6´…á©ÃS‡§BÍû5ï׼͌š53‚”A)ƒRýnÅ1ÄJœ§Ä/xÁ Co­0µ¡! ï·Çîªïªïªï¾\~gÖ�YwfÁÞ�{îÓwMß5}L¨1¡Æ„à´Ëi—Ó.C§ÿY�´i=üCýCýCáónŸwû¼œÙxfã™�ª U…þþÁÎ8ã ªMªM*yÊ øR„ªà»‚ï ¾ÇŽ@�au†Õêöêöêö¯~¼a/Â^„Atqtqt1(þŠ¿âoèYx{¨¨¨€{k÷Öî­¡^ûzí뵇Â*…U «:�x×HBü¹V´¢ÿz¾= ¯ñ;CÁŸü)l´yÐæAPÔ·¨oQ_COèëêëêëB¾{¾{¾;/op`(7¸Á Pò•|%ßг#ÞUR„†WH!…Ðv[Ûmm·ÁDωž=Áè�Ñ£ ë«ë«ë :�‹ÎŠÚµ)jú²ú²ú²ÀyÎst_é¾Ò}ÅaÅaÅaPä\ä\ä ÅÅÅÅÅÅ/‡Ó�×�×�ÝGº�tÞxã ú†ú†ú† ›¥›¥ûݵ —\zpélûzÛ×Û¾]œ.NÜæ6·A×C×C× ,<ú•ú•ú•†žT!þor Âàô+ô+ô+àtÆéŒÓpÚî´Ýi;Wi\¥q•`õðÕÃW�<€‘…‘…‘ÄV‹­[ &L ˜î¸sà\Kº–t- ll°±ÁFˆÛ·)nøîöÝí»ŠÔEê"5üôóO?ÿô3Ì<2óÈÌ#�1.c\Æ8X7jݨu£`ôíÑ·G߆ )R6¤@êG©¥~îÏÝŸ»?ënÖݬ»Áž�ö|´ç#0›f6Íl”ïT¾SùNÐ;§wNy…x›È!„Á©g«g«gƒÛI·“n'án™»eî–�Rß—ú¾Ô÷�R1¥bJE°µµµµµ???ˆ<y:ò4Üȼ‘y#¬o[ß¶¾ ™¥3Kg–†!‡<òÜκ�u; ÿ¸÷�{ÿ¸.�]:»t†Ç<þàñ�}=ûzöupoáÞ½DO�ž=´ÿÐþCû(ëVÖ­¬Ô©]§v�ÚÐlJ³)ͦÀ¾zûêí«ñ·ãoÇ߆aµ‡ÕV<}<}<}€{Üãž¡gWˆO €â­¡IÔ$jA½L½L½ Ô±êXu,¨²TYª,0úÊè+£¯ÀRo©·Ôƒq3ãfÆÍ wYî²Üe ŽPG¨#Àh…Ñ £`êjêjê fffð¤Ã“O:@q|q|q<¨SÕ©êTP%©’TI >¤>¤>ª`U°*Ô¥Õ¥Õ¥AÝOÝOÝŒ-0Zð2o=Ïzžõ­Ú´jÓª ü°í‡m?lëëë˜å?Ë–?$x&x&xzR…ø÷¤!ÞÙÛ²·eoƒ‚ô‚ô‚tHë–Ö-­ä·Ëo—ßr»ävÉíE�Š:u‚‚Ç CîªÜU¹«@Y¦,S–A~ùüòùå!¾l|Ùø²ömØ·aßBƒ”) RÀÒÌÒÌÒ ´Í´Í´ÍàYýgõŸÕ‡ · · 7(šV4­hä×ɯ“_LT&*Äí‹Û·RN¦œL9 'žœxrâ YYYA{Óö¦íMÁøcã��?†â§ÅO‹ŸzV…ø÷ä"@!„Á´-h[ÐÒ§N; ÍmšÛ4·�È#Œüjͨ5£Ö °,oYÞ²<ÄùÆùÆùB� u6ÔÙV&V&V&�‘‘ ªU‚ ŽŒ;2îÈ8°«jWÕ®*t«Ú­j·ª`ínínícŠÇ�)†èºÑu£ë‚&H¤ ‚6 Û,l³”1Êe tÏêžÕ= v5ÝÕtWS¸¼òòÊË+Áv¾í|Ûùp±èbÑÅ"Py©¼T^0½ÙôfÓ›A™‚2e =»Bü{R„grÚä´ÉièF7ºݶtÛÒmËË×{Ñ‹^¿ÿ�–´¤%|>úóÑŸ�~¹xÛ�m7¶Ý€ §*œªp †Ž:nè8ÐZk­µÖ·G·ÝztûÝW\q…nm»µíÖö�ï¯Mmjÿ›ü¿Ý.sÌ1ç__Kâm&§„î·sâ¯ù@;æ\Ý\Ý\x¶éÙ¦g› ëJÖ•¬+ðäô“ÓON:Ýkàƒ>r«_ñ÷È!ÄŸRg¨3Ô�z2õdêIH¼˜x1ñâËkäÞ¿}[`ÄÚkG¬…ÁUW\l;Ûv¶í ô¦7ïÑãˆ3g,ÎX �n=ºõè4 oÞ0ÜЩĻFŽ!PN+§•Ó@#Ñèåòê‹«/®¾<{6öl s§Î�:w*J:”t( ò~Èû!<ì+óÛ_ÂöííÛÛ·7770�0�0�0tº¿¯h|Ñø¢ñpÑõ¢ëEWøÄùçOœÁ®µ]k»ÖPײ®e]Ë—ïW7Q7Q7%T Uä±ÌâOHB`tÎèœÑ9¸oußê¾<òlȳ!`Óܦ¹Ms˜•0+aVøÿâÿ‹ÿ/pÀâ€Å‹—O¥»}÷öÝÛwA¿H¿H¿ÈÐ[óîS6(” ðèÞ£{�îÁ"Õ"Õ"l8ºá膣Ð% K@—€—Ë]r]r]r!uNêœÔ9pÇåŽË0±1±1±ùýŠßîS9âÍ’ D ¢_¢_¢_úúú/—7û¼ÙçÍ>ÏIž“<'Á§‹?]üébØn·Ýn»ä7Ìo˜ßZ¶*lUKÛ.m»´-xnõÜê¹–]]vuÙUø!⇈" alÂØ„±†ÞÚwOzZzZzl²Ùd³É¾þ"ø‹`°Í´Í´Í„ESM]4|’}’}’AÝJÝJÝ Ž 8³ÊÎ*;«,X&Y&Y&�OªOªOêËõ+U”*JP¦(S”)@6Ùdz«…¡¨”2t!Äë·Îb�Å: 8Þáx‡ã`Ⴥ>�£G=Ž‚îÝ7ºo ¬_X¿°~°¥ý–ö[Úƒî¡î¡î! j;¨í ¶Ð0½azÃtммм€èMÑ›¢7AБ #AGàQ³GÍ5ƒž7{ÞìyÚOi?¥ý°ð´ð´�ãüKa\a\a\jq©Å¥°í̶3Û΀mÛ&¶M`PÄ ˆAP3§fNÍ „B "6"6"mmm!-#-#-úŸí¶ÿYh>¨ù æƒÀ¸¯q_ã¾ðÜë¹×s/XÑxEã�Á¦”M)›RðqÃ�~ÜT}U}UoÁSÅ›%@ˆ$õJê•Ô+°µxkñÖb¸Üër¯Ë½ 5­i ôZÞky¯å`7Ôn¨ÝPÈ«–W-¯™wdÞ‘y°¿Ïþ>ûû€‡‘‡‘‡ é6¤Û�nP¾zùê嫃n‚n‚n\i|¥ñ•ư¥ü–ò[ʃö²ö²ö2 >dø�áPwXÝau‡�¦£¦£¦£¡gå jG;ÚAT¥¨JQ• À<À<ÀâæÄ͉›}�ö=Ú÷(´mÚ¶iÛ¦`RÕ¤ªIUHê’Ô%© lwÜî¸Ý®L¹2åÊh»»íî¶»¡wtïèÞÑ`hh9ù9ù9ùp$äHÈ‘8Øë`¯ƒ½ ZnµÜj¹àç箎®Ž®Ž†ža(R„(�ôAú }Ü+u¯Ô½Rp*àTÀ)Hš24e(ôwéïÒßZílµ³ÕNЎ׎׎‡ç}ž÷yÞ¶žÛznë9¸©½©½©…Ï:<ëð z÷4îi VŠ•b¥@fÿÌþ™ýápåÕW†#;�ì<²jש]§vðã7Æo ¸vpíàÚáïo×Û*µjjÕÔª°K½K½K çÇž{~,4_Ù|eó•àââNNN�_%¿J~8ñʼn/N|{Gíµw¸ítÛ鶆,²pÈB¨S9¦r è;ë;ë;Ãõ�×7^ßÓ¦Lîr—»0hì ±ƒÆBýŠõ+Ö¯FµŒjÕ2ô¬C“ „  IA“‚&pnƹçfÀÎ;;ììŽ+W8®€Á&ƒM›@µnÕºUë,g9Ëá–Å-‹[˜˜˜¹r7än¿ñ~ãýƃ÷ïÞ@{L{L{ žV{Zíi5Z´6h-Ükt¯Ñ½FÐíÃnvûºôíÒ·K_°ìmÙÛòþÚ^~~~~~>œßq~Çù°kÍ®5»Ö@饔ƒsçÎ…j«u¬Ö˜Ç<æÁ­ž·zÞê �«W®‚\u®:W ~Q~Q~Qàíëíëí ÚMÚMÚMð´áÓ†OBÐÞ ½A{á^Á½‚{Ðmx·á݆C—y]æu™–í,ÛY¶3ô¬ˆ·�!ĤÖI­“ZvUÚUiW%8owÞî¼4?Úühó£Ð×¶¯m_[°¿k×þ.ä×ͯ›_N|zâӟž&{šìiåï–¿[þ. 5dÔ�QP9¡rBåÐ{é½ô^p½úõê׫C@ã€Æ�AùPùPùÏÓ|<ãÏ ½u¤4R)�@ó¡æC͇Ðq]Çu×A½õõÖ×[êPu¨:¦?L˜�Á�Á�Á÷CÜq?@ï*½«ô®mú´éÓ¦˜Í5›k6×Ð[%ÞwR„¯]VpVpV0ìß·ßþ}p<÷xîñ\¨S­Nµ:ÕÀ¯¾_}¿úPÆ»ŒwoC§}uRƒRƒRƒ`Ï{~ØóœÕœÕœÕ@“êMª7©ýõ?Ôÿ8Ä9Ä9¼Åßrï')Bˆ7çŸÏ±ý$úI4 <x ¢2¢2¢2 í…¶Ú^€·jܪq ˜Ît¦9ä�ó7Æ- €P·W·W·šÑŒf Ÿ£Ÿ£ŸØ`ƒÍßXuªS”^J/¥<«û¬î³ºpÌì˜Ù13°oc߯¾ ‰?$ª_®~¹úeP}«úVõ­¡wŠ(©¤! F7V7V7BcBcBc`‡²CÙ¡@þÃü‡ùA® W…ÅSü×ÇQmVmVm†§fOÍžšAÑ‚¢E À½·{o÷Þ Ÿ¯Ÿ¯ÿß.PUPUPUÝÝÝ0jjÔÔ¨)tŸÚ}j÷©Ðʾ•}+{0™l2Ùd²¡g]ˆÿ�!Ä[C÷L÷L÷ t: �PDE€ ª¿¾^µƒÚAí>ØðÁ† uTê¨ÔQ0Ûj¶Õl+(r.r.rþÁõèѦ˜b šAšAšA ™®™®™Î¿ž ÄÛÄÈЄâ7šršršr Aƒæ5¬ßÈËÈËÈ Œ† 1ªÇªÇªÇ`Œ1Ưr Ãæðš4!þ"µ¡!Ä£  Ç;…¤!„%’!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!D‰¡š©š©š ”¢¥ �FÃ’ „xïê u…:H\Ÿ¸>q=¼°xañÂÒï¥ßK¿YyYyYy�²1ecÊFH“8&q äµËk—×ÎÐé…x3TÊ?:ˆB¼*wMïšÞ5¿î~ÝýºCF¥ŒJ• §QN£œF OÓ§éÓÀj–Õ,«Y`ee+mWÚ®´…FŒ:z+„x½ä#.„x︪\U®*(g^μœ9„þMø7|_dµ}kûÖö…Z�k5®Õø†oøæUˆw‹œB¼wlólóló “k'×N®`ôØè±Ñã?û¾íû¶ï N*'•“ÊÐé…x3ä€â½Õ–¶´\º4tiÏxƳ߽nkk ²:duÈu5u5u5C§âÍ�#Bˆ÷–Ç_x|�5�5�5|½öîÚ»kúºúºzC§âÍ’ „xo™™˜™˜™@ë.Ö]¬A½Z½Z½T¦*S•)´ú±Õ�­~çÎ5œk:­o–!Ä{¯‰{÷&îà1Éc’Ç$°ÚhµÑj#t=ÓõL×3†N'„aÈ5Bˆ7¦0®0®0n=½õôÖSH³N³N³Uš*M•¨Pñ /ÂSõUõUõ…Âã…Ç �C©U¥V•ZŵŠkׂ¸Œ¸Œ¸ 8UæT™Se@¿S¿S¿ó5løINrLZ›´6i š7hÞ 9˜«ÍÕæòg˜0)Bˆ7&ø@ð�à°tçÒ�KwBÍ{5ïÕ¼ššš@"‰$¾Ââ'~µ§ÚSí îÝ/º_„ì¢ì¢ì"¸5áÖ„[@ÿ‹þý/¼ü^à«b‹-¶ Ú¨Ú¨Úaéaéaé0ìÖ°[ÃnÁ ‰ƒ&šø&÷€/É�€„¯]ÖŠ¬Y+`Nòœä9ÉÐIÕIÕI>·|nùܽJ¯Ò«€\rÉ}õã«n«n«nCš>MŸ¦‡LÿLÿL(ï^Þ½¼;({”=Êž×°áZ´hAõ™ê3ÕgÚ<´yhsøéÀO~:_�úzÔ×£À5Þ5Þ5þuï!þ_R„¯Ý¶úÛêo«¡ñ¡ñ¡ñðåÚ/×~¹Ì|Ì|Ì| �îÍÑÏÔÏÔÏ„¥ÉK“—&ƒiGÓŽ¦aJÄ”ˆ)À—|É—†N)J 9û$„xm⿈ÿ"þ 8b}Äúˆ5 ðà=À»äýâÿ�úõ7êo`€f€f€nøÝð»áwÝïºßu7t:QÒHB¼6»ï:¼ë0xÄzÄzÄ‚×~¯ý^û �Êð*®¯¸¾âzhÕ¡U‡V ¨{P÷ îP¸±pcáFC§%…!Ä+1&bLĸ}=úz4ø­ñ[ã·4:�N£3tº·G�9=æô˜‰J¢’¨@0Á:”(1¤!^™â-Å[Š·ÀÖò[Ëo-ÍM››67…Êm+·­ÜÖÐéÞ>íÚ;´‡Þ {7ìÝvì(ØQ™Ó3§gN7t:ñ¾“ „xeBrBrBr ^¯�×B� =.ô¸`èTo¿¶ËÚ.k» Lê™Ô3©ÇN;u씡S‰÷�!Äß–µ0kaÖBØæ¸Íq›#ôXßc}�õàXѱ¢cEC§{û™ùšùšù³fÌàÈ¥#—Ž\‚„2 eÊ:�x_IBümǦ›~l:Í5šk4Újw¨Ý!C§z÷4´mhÛÐ*i*i*i`ÇÒKw,Ô¨åÿÖâU“�”â/Kx‘ð"áiq¤Å‘0à耣Ž‚…»…»…|­í¦.§.§.~^~^~^úIè'¡ŸÀ½û÷îß»oètâ}#@ñ¿{Ä#ÁžN{:íéå生S~4®Ý¸vãÚ†÷îsuu…æ™Í3›gÂÖè­Ñ[£¡¸iqÓ⦆N'ÞR„ÿ³ÈŸ"Šü .Ç\޹¿øÅÀ/@�ªNU§:Ý{À , ÷²ÞËz/ƒØò±åcËÃå)—§\žbèpâ}!@ñ_+._\¾¸üË¿H½ïzßõ¾ ·=n{Ü6tº÷Oé‘¥G– >w|îøÜ�ƒw Þ1rkçÖΕ#-âo’ „ø¯]=põÀÕðÄø‰ñcèãÛÇ·�¯¡S½ÿ:tëЭC7PÍTÍTÍ„£7ŽÞ8zÃЩĻN €â?Êy�ó çl»}ìö±Ð=¢{D÷p q q 1tºW§(ª(ª( 2¿Ìü2óKPZ)­”V†NÐÿJÿ+ý¯À�¢EŠ É+É+ÉËÐéÄ»J €â?:yñäÅ“Aï¬wÖ;C§…�vZhèT¯Þ�~wúÝé_ø|áó…¤·Jo•þ€ß4œÕpVÃYP~PùAåÁî‘»GîièTâ]%@ñ§^¤¾H}‘ çœp>ô›Ûon¿¹`ÑÝ¢»EwC§{õܸ/p_cö�Ù7fXeYeYe:ÕKÚNÚNÚN0°ÖÀZkAHnHnH.D}õMÔ7†N'Þ5F† „x{íé»§ïž¾PƸŒqchr¾Éù&ç�úÔ§þëW—®Kץá‡:Z>hù %TN­œZ9¢NF�Œ: n*7•› LãMãMãáÑ7�¾yô t\ÐqAÇà9ßs¾ç|x¸àႇ àä‘“GN}”>Jå”oP¾tÊî”Ý)ï{¼ïñ>8yòäÉ“'¡‡S§Np¾êùªç«‚2X¬ k¬±âcâcâc ¿_¿þ~àÒÑ¥£KÇ׿_ªzWõ®ê �¯4¾Òø lËÞ–½-涘Ûbn P_P_PË-˜Å G„ððÙÃgŸÁÅЋ¡CÁ¯À¯À¯Œ¦M5šúúÇרhl46�~$ýHú‰ ‰ ‰ƒÆWh\ŠW¯.^ G¶Ùrd xû{û{ûCQó¢æEÍaCƆŒ /×—u"ëDÖ ¨v Ú�j Qq£âFŰfÑšEkÁc£ÇF�� ô†ÒJo€ƒ.]º@ö¦ìMÙ›àÁƒ<€‡þýúC‹ -.´¸·gÞžy{&ì»»ïî¾»opu¥+]¡÷„ÞzO€Ç¾�}ûBhHhHè{tM†x½¤!þEo£·ÑÛÀ¶Äm‰Û¡á ?høT^ýyõço>�i5Ój¦ÕÀt¿é~Óýàbëbëb îöîöîö ›¤›¤›Îõœë9×ƒŠ³+ή8^Œx1âÅ(ÞS¼§xTJ«”V) >søÌá3(Ø\°¹`3dÎÉœ“9²‡gÏ3-fZÌ###0l4Øh0˜L4™h2Ì{š÷4ï Î'œO8ŸçcÎÇœ�AÒá¤ÃI‡ßüü¸”v)íRº:uuêêAÓƒ¦M‡\×\×\×7ŸG¼[¤!þåÚ¶kÛ®mƒ‡ÕVXúzöõìë RH¡)((@4ÑDÿn¹ *Àlþ¸\µTµTµ 6l,Ø+-WZ®´„í·:Ü žn|ºñéF(jTÔ¨¨¨>U}ªúУGÿorSL1K,±¿[þÏöЂ´0ÀüüS§Å�wZ ÅÅÅp2ðdàÉ@Ãåï)BòÏåŸË?ÛömÛ·mtV:+�pé2ÒÅ€W™ëÓôiú4Ð5Ö5Ö5ý3ý3ý3ÐÇéãôq k¢k¢kŠ•b¥Xýnù�ºu?BÎÚœµ9ká|íóµÏ×ï™Þ3½gB—Ó]Nw9 f­ÍZ›µ†âàâàâ`ЫÿVÿ-èÓõéút(ÖkŠ5 ?¯?¯?:{�½Îþwù¬ôVz+Ðyè‚Ù}f÷™Ý†,²xÈbh}²õÉÖ' l3˜EcŠÆ�jPƒ ¾®¾®¾ú|}¾>ŸzW_S_S_}–>KŸ bƒÀ(Ù(Ù(¨Le*Ca�Â:…u@µLµLµ TZ•V¥uOuOuOPf(3” ¯«¯«¯ 8á„I$‘ º©º©º š'š'š' ;§;§;Le*SÁ¨•Q+£V ²TYª, 7}‡#G†%O–/óy™ÏË@åž•{VîiÀý*Þ*R„(Á6žÚxjã)xð݃ï|óÍ[4o˜Ô2©eRËÐéÄ_N8áðýåï/²_d¿È~³Sf§ÌNÍ7šo4r߀ONQEoŒÞ½Î8àütwÐÝAwåÿ{£&5© ¾¾¾ðpÉÃ%—@Øa„}`èpâm!@ˆè\ÿsýÏõ‡ *@õîÕ»WïìWÒ¹ötíéÚ* ©4¤ÒØÛdo“½M �J¼-¤Qyžó<çy’û$÷Iî   †N%^µÌ&™M2›@l™Ø2±eÀ[ñV¼å„¯ø')B”@^6^6^6PÕ¹ªsUgرvÇÚkAùXùXùØÐéÄ«rD}D}D ó,æỸöMÛ7mßÔЩÄÛBž D ¤nªnªn æ ˜3`|¾ùóÍŸo†ð‚ð‚ð¨E-äR€wW|™ø2ñeà襣—Ž^‚�L>2ùÈÌʘ•1+cètâm!G„(Á*.®¸¸âbhMkZ[£¶Fm�‚¢ÉE“‹& Ð<æ1ŠcŠcŠc H)RŠзззå‘òHyúŠúŠúŠ ôWú+ý�ø€@§Óét:P|_ÅÈ"‹ß=ÍOwCwCwŠë×-® t§;Ý�ºÔ¥.è u…ºBPî(w”; ¤)iJè’uɺdP®*W•«¿Ë{‚œ€âüâüâ|(Ž(Ž(Žnr“›˜¿žô¤'ì꾫û®îà±Ðc¡ÇB¨]?º~ôß_½x¿h¾ø'CBNùg埕ûÝÿëþ_Áæ[›om¾… ,*X¼þñõëôëôëàXü±øcñ°'aOžˆ54j(ü:ñ׉¿NãAƃŒÁÉïN~wò;8Þõx×ã]¡žªžªž Ö®/\_§ZŸj}ª54ÖlX³apÏúžõ=kؼoó¾Íû $3$3$žL|2ñÉDpNtNtN„Åî‹Ý»ÃócÏ�=?å*”«P®|­úZõµ Æ%ŒKµ‡×^{8œ{rîɹ'°«Ç®»z@ð÷Áß¹Cs‡æ…J[*m©´TMUMUoàÐ{D�ˆ=`Ç£�v<‚�¦~4õ£©`_þ†}�×?¾x·È!ö-í[Ú·„ž'zžèyví0ÚaÙ£²Ge�zýãßó¾ç}ÏÖkÖkÖk û³îϺ?ÿfþÍü›AâñÄã‰Ç!õTê©ÔS`û¥í—¶_Bx¿ð~áýÀòSËO-?»™v3ífB¸Y¸Y¸äŽÈ‘;~´þÑúGkp›ë6×m. »:ìê°«°çÙžg{žAܽ¸{q÷@ÕNÕNÕyxäá°s·s·sÅ]qWÜ!ºOtŸè>�8!qBâø©×O½~êí~n÷s»Ÿ¡ýÎö;Ûï„TþGåT†¤˜¤˜¤˜×?…ممÙÔ5¨kPWhîÑÜ£¹¸;»;»;¿þñÅ»I €â_Úµ5jk&ÓL¦™Lƒ#wŽÜ9òn%ûÀã�Ç0*kTÖ¨,¸ÏvŸí>L²M²M²AóLóLó Ô�Ô�Ô�@ÓJÓJÓ T«U«U«�RHÍÍÍPG©£ÔQ�?1bþDˆØ±/b$,MXš°®}{íÛkßBÖY_d}i™i™i™`ÔΨ�Q;P�P�P�x™Oc­±ÖXƒæœæœæ¼øâÅ/¾€Çæ�Í›Ãá‡> ‘Ý#»Gv‡Ô¥©KS—BN™œ29oàœû•ÙWf_™ ñÃã‡Ç‡^ù½ò{å¿þqÅ»M.Bü‹Y®Y®Y. x2àÉ€'°fÞšykæAsçæÎÍ�Á%Á%Á%áÕ�«úDõ‰êPÊ)å”rÀe.s™—OýûÃüs¹^xý›å®¸â ô =À¨³Qg£Î`3ÄfˆÍpÕ¸j\5°`Ò‚I &A�–5ZÖh §5§5§5`dmdmdý»õjÑ¢¬°Â TTT@ûLûLû lîÚܵ¹ ŽŽްlÁ²Ë@™Ae•ôúöWööìíÙÛaGÁŽ‚ÐsQÏE=Aé¨ÒQ¥£^߸âý G„Pߨ¾Q}#¨4­Ò´JÓ`×®]»víz}ãyTõ¨êQŠ»w-î a…a…a…�ªMÕ¦j¡hTѨ¢QÀö°,V[¬¶X Yg²Îd��¤¯“¾Núò&æMÌ›…³ gÎíTíTíT¨ST§¨NäææBy¥¼R^�š¹5skæ‚e+ËV–­ÀÒßÒßÒ^l}±õÅVȶ˶˶ƒüGù�òA^¿¼~yý t¯Ò½J÷‚Šùó+惮‡®‡®TÞTySåMPcT�Q5F�é*ÓU¦«^ß¼;xìృ Ù®Ù®Ù¦v˜ÚaêëO¼_ä"@!ĨK©K©K�k× ® È1È1ȪW® -Z:´|uã9ôrèåÐ àúæë›¯o~ù8Û�”�”�ð:àuÀë´ØÞb{‹í�1(cPÆ H0N0N0ÅB±P,ÀêœÕ9«sPG©£ÔQÀ«‰W¯&9,rXä0¸ïrßå¾ËËŸw)v)v)×T×T×Tˆû>îû¸ï!½gzÏôž@ºÐ*:Tt¨ œ87p†jí«µ¯ÖÂòÂòÂòà±Õc«ÇVPh]h]h .V.V.V ñÖxk¼_Ý|%^I¼’x~òýÉ÷'_útèÓ¡O¡â¢Š‹*.zÃñÎ’‡ !þ£µ³ÖÎZ; â·Åo‹ßŸ%|–ðYh 4š‚×8°3Î8ÃàòƒË.>Ù>Ù>ÙàîînèY1€¬`¬îµº×ê^�¼1ycòF˜»h‹@S¤)Ò:¤xWÈ)!ÄÔ«C¯½:@¬M¬M¬ \¶½l{Ùöõ�û¤å“–OZBVBVBV¼¨÷¢Þ‹z 7Ó›éÍ =+o^äØÈ±‘c!$"$"$ü¢ü¢ü¢ä¿øk¤!þ#ÇŽ;@÷;Ýït¿[c·Æn�…ìMÙ›²7½Æq×9®s\?Õú©ÖOµ`ðÕÁW_Õ:Õ:Õ:CÏÊ›£KÔ%êaÛØmc·�…&�štjÒ ª¸Vq­âjètâ]%§„ÿµì Ù²/À'µ?©ýImh�Ý:»u6ôqíãÚG~½6!Æ!Æ!ư>|}øúpXÔkQ¯E½À1Ü1ܱ$ž ¯„Bü×,[X¶°l~'üNø�€CŸúôЧ�Ø/±_b?C§{ÿäæææææÂ¶ÆÛok ÝÚtkÓ­�ü⯆!Äÿ¬ñ×�¿nü5¸Å¸Å¸ÅÀÞø½ñ{ã �êýsâ鉧'ž‚n…n…ntØÜas‡Í†N%ÞR„ÿ3Í Í Í ð‹ô‹ô‹„à Á‚'ÀƒVZ=heètᄂI’Àþãû�ï?ýK÷/Ý¿4Xµ±jcÕÆÐéÄûB €â/«_5¾j<4þ¼ñç�?‡ Û Û [(X<°x ¡Ó½»ö}³ï›}߀k€k€kx¯ò^åýo($J&)Bˆ¿­O~Ÿü>ùð¸Áã�Àµö×Ú_koèTïžGíµ{Ô.ú]ô»è~_ú}é÷%h¿Ñ~£ýÆÐéÄûF €âos~æüÌùt íÚ-¶ÏÝ>wû\Èž;Ê„È_"‰ü"ÊD”‰(EÖEÖEÖ/.cþÆü�¹>r}äz¸�w;ïvÄëãõñzPr•\%÷ÏÇÍõÎõÎõ†¨Q;¢v@⇉&~9s&æLÛ{¶÷lïAóÇÍ7 Fß}gôX.´\h¹´çµçµç¡èdÑÉ¢“àààë=Ö{¬÷€ûû{PÒ•t%ú%ôKè·ëÜ®s»D'F'F'‚îKÝ—º/!öYì³ØgÙ ²AdxRæI™'e Þ*Þ*Þ XÊR–zo‰×ÍÈЄâMь֌֌†ufëÌÖ™½,GvÙq$lŠÞ½)†Z µj�,:Yt²€��7vÞØò¯ç_Ï¿ÎcœÇ8��kß^ûöÚ·0tÇÐCw@�‹u.Ö¹øÇq³ïdßɾ¹¹¹€1ÆCÂü„ù ó¡8ª8ª8 fŽ™9fæøáÑ�~x妗›^n:I$‘PT©¨RQ%¸q9âr–),SX’¿Kþ.ù;È8˜q0ã ¬;¸î຃P«C­µ:ÀÍR7KÝ,}–÷YÞg9¤þšúk꯰|éò¥Ë— ƒF V'¬NX�€�×^x 4hÐz§‰×F €¢ÄPõVõVõ�«ÎUç ¥}Jû”ö�.Å]Š»Ã…M6]Ø7_Ü|qóT?TýPõCpäÊ‘+G®ÀÊ++¯¬¼uuuðäö“ÛOnÃŽQ;Fíu¨C�3®cŽcŽcT¸\ár…Ë`>Î|œù8¨W¿^ýzõ!¥FJ�” 5Ök�A¿H¿H¿pÄG  hÖ_Ziý%”=[ölÙ³`V`V`Vµ>«õY­Ïà»§ß=ýî)P‹ZÔ‚áû‡ï¾–™,3Yf‡*ªp¨ô?ÓÿLÿ3`œkœkœ =Œzõ0ëkÖ׬¯�z¨z¨z¨¡÷–xÝ䀢äУGd‘E@/_V¿P¿P¿}}}}}}Èþ<ûóìÏ¡ ¤ ¤ ̃̓̓_¾ß^m¯¶WC"‰$þ7ãGM4(m•¶JÛóúorÿÙŸÞ*T¨€§<å)(þŠ¿âÿòåDûDûD{ˆ58j0l¨º¡ê†ªðb‹ /&€K�K�K0‹YÌ#Œ0Lõ¦zS=XN°œ`9T¥T¥T¥ ½³Äë&@QrhÑ¢ÊQŽrÀv°ãw¯»ãŽ;PƒÔ‹\‹\‹\ÐŽÐŽÐŽ€ü&ùMò›¼|{z—ô.é]ÀAå rPýãW¤"AuBuBuâwË ( ˜Ît¦ƒj„j„j/‹Ê$&1 Æ0†;ÙÉNP†(C”!/WcçoçoçUW\e0ø÷?î>]øtáS˜â5ÅkŠè§é§é§�jªjªj*à�†Þ9âM“ „(1”�ÊFe#p—»Ü…¤ ¤ ¤ Hœ>8}0$vJì”Ø ’>Jú(é#°ÿÚþkû¯¡íçm?oû9ì²oȾ!°÷—½¿ìýbÆ>Œ}}êô©Ó§ÎŸ�›5.k\Ö8x>äù�çCàéæ§›Ÿn†¤åIË“–Ãã”Ç)�S c]ƺŒuð°æÃškÂÃ*«<¬þþþðä“'Ÿ<ùœÎ:�u: 7«Ý¬v³„……AûYígµŸ9Ýrºåtƒ]UwUÝU‚›7 nI{’ö$í�8ã8ã8cH›’6%m ÄæÆæÆæþws(Þ*åŸ D!^·�‹6.Ú¸®$]Iº’ãW�_=~5¸9¹9¹9Áƒ´iÒ@3P3P3jzÖô¬é E¾E¾E¾µ.j]Ô:(ø¨à£‚�À)Õ)Õ)*̯0¿Â|PmQmQmùã¸Ù‹³g/†ðkáׯñ¯¯#z8{8{8C¶]¶]¶ÄŒ�3œ>púÀé0�6�6�†§�žvzÚ Êx•ñ*ã6ŸÚ|jó)D4‰hÑ ê媗«^†§öOíŸÚÃóºÏë>¯ æ£ÍG›�†r?—û¹ÜÏ�žžžžž±»cwÇî÷_ÝuÿÊ|Sæ›2ßz/‰7E €¢ÄذzÃê «!uYê²Ôe0#zFôŒhC§Â0䀢ä(¢ˆ"@AAþì%œ!„¢’ „B”@R„BˆH €BQIB!J )B!D $@Qr´ -L01t! K €â½£©© Ù+³Wf¯„ÜÄÜÄÜD(˜]0»`6|UðUÁWPð¤àIÁÈÊËÊËʃ¢iEÓŠ¦:½o†<XñÞyxãá�‡7`æ�™Cf]Œ.F±mcÛÆ¶…¢�E‹ÂeÍeÍe ¨�«�«�ÃÌF3ÍlÍiNsCo„¯™!Ä{ÇZ±V¬H^�¼:y5„ìÙ²ã�ï»W|¯ø^1¸åþ•ûWà\ŹŠsÀ?ü ½B¼^r @ñÞqssƒNQ�¢:Eg9ËÙ? m m -T0©`RA® %„!Ä{«Ý¶vÛÚmÇ\Ç\Çó¸[ãŸ�6þº´èÒ¢K 0Zn´Üh¹¡S ñfÈ)!Ä{«NÝ:uëÔ…Úŵ‹kÃINròw¯W�«W=¤5Hk�fè´B¼Yr@ñ޲ʳʳʃ®C»í:ô�¯7ù¤É'M>� öì+Ø:­o–B¼÷Zjq¨Å!(»¹ìæ²›!uqêâÔÅàcâcâcªbU±ªØÐ)…x³¤!^»¤RI¥’JÁóÎÏ;?ï Üä&7l°y�ï`; ¨TQ©¢RàòƒË.?€º¬º¬º,¨Ôê¸ýøöãÛ�A  P¼Æh¯k¯k¯ƒå$ËI–“@­ŒVF¿Æ…RêuŽ:,_X¾°|êêêppÅÁW8ÀPâ”8%îõÅQ­V­V­†œ97rn@ŽkŽkŽ+Ly8åᔇÐ4¤iHÓ  MhòçE@¥ü“¡ƒ!Þ·¯Þ¾zû*|ÛÿÛþßö‡vOÚ=i÷|.ú\ô¹F£ŒF�e·²[Ùýúó¨ÜTn*7xÞôyÓçM!Õ.Õ.Õj�®5ºÖhÐ×Ó×Ó×^ãÿ U5T5T5@ÿµþký×p)øRð¥`¸p)àŒl7²ÝÈvÐfG›mvüýñ„ø¿HBü}ç8Ç9¸v÷ÚÝkwáûŠßWü¾"ôÜÜssÏÍЧEŸ}Z€ê#ÕGª� ˜ó)Oy <ä!�¶´¥­ó¨P¡‚óåÏ—?_Ö–Z[jm)ð7õ7õ7…NW;]ítÕ€ùÄ{M €âo îÜ7¸/ühú£é�¦àgægæg>Û}¶ûl2È ÃÐ)ß~—c/Ç^Ž…nÿpû‡Û0Àq€ãGðiãÓÆ§ ¨²TYª,C§ï ¹@ñ—�‰?&~ø9àçš24eh tÜÙqgÇ�À:Ö±ÎÐ)ßÞe½Ëz—­…ÖBk+.¯¸¼â2~QøEáÐǺ�ukPg¨3ÔR¨Äß$G„ÿ5ÅD1QLàXè±Ðc¡˜˜˜®ûp݇ë õúÖë[¯7tÊ÷Ç�‡wÞyË;,ï°¼t¸×á^‡{àçàçàçšlM¶&ÛÐ)Å»J €â?RF(#”°Ÿýìv$íHÚ‘ã“Æ'�O‚&¡MB›„:åû+²Md›È6°$cIÆ’ h~´ùÑæGÁ–ÿ,ÿY ýEû‹öC§ï¹ âO)s•¹Ê\ØytçÑ�Ga·õnëÝÖ0µÞÔzSëA“ÝMv7yWñ—tUÏT=Sõ |2ç“9ŸÌ��U!«BVÁÏ·¾ýóm(˜X0±`¢¡SŠw�BüAñòâåÅË!(*(*( ÎdŸÉ>“ SO=<õ0x¦y¦yʽó æIä“È'‘°$rIä’H¨ª®ª®ª†ÑcG�=ÌbÍbÍb �R¼í¤!þ¥èQÑ£¢G°)gSΦÞ¼'xÌšï{ø±ò�•¬ á«ÂW…¯‚¹óçΟ;ÿ¯ÿâ/W<®x<Ýýt÷ÓÝpcÍ�57Ö@ø’ð%áK b]ĺˆupwÔÝQwGÁ‹/^¼xaèÙxV±ŠU�®Mצk!<,<,< Ò'¥OJŸô×Wë¬rV9«àã~÷û¸ä̘?–¦-M[šisÓæ¦Í5ôÆ‹·�!J \Ç\Ç\Gø¾ô÷¥¿/ Ñ�£G?†¹“çNž;ܼݼݼÿúúõçõçõçáªùUó«æ0:xtðè`U…ªBUðhÊ£)�¦À‰èÑ'¢á”ë)×S®†ž•7`›ØiÓ.¦]„Ù�³gÂÙÃgŸ=ü÷WoŸoŸoŸ³gÍž5{hnhnhnÀ o,¼ÉÍ’›%Ë)ñOR„(A²Ü²Ü²ÜàÛ*ßVù¶ $5Ij’Ô>ùùÈÏGB™Æe—iü÷Ç177‡*õ«Ô¯RljÛÔ¶© �ëw®ß¹>øäøäøä€_Ž_Ž_T¶¬lYÙòåÏ+ã”qÊ8(Î(Î(Î}/}/}/ �<ò@IQR”P|ŨG=ê�>Z­�}¨>T ú}Œ>”�Ê@e ¼#¡:PV(+” _¦_¦_Æ¿nÑ«D+ÑJ4GGG‚~Œ~Œ~ÌïrNR&)“@9¡œPN€rE¹¢\¥¦RS© P@°žõ¬Ý*Ý*Ý*(w³ÜÍr7Ár…å ËP<¤xHñ�W·ŸKå”Ê)•ÓÇN;},Ø.µ]j»¾Îû:ïëÏ|ÅÝ‹»w‡Äs‰çÏÁ”ƒSN9Q_E}õ˜¿0aþJ�,=²ôHpâ2Äe”ëV®[¹n0¶ÁØc€³£³£³#üªÿUÿ«œs�s�sáÖœ[snÍ›"›"›"hü}ãï÷•ûÊ}Öu\×q]Gè–Þ-½[: 1xÄàà¼ÁyƒóÐ7Ó7Ó¿ÆCóæÌ7˜o€ k&¬™°ª¬¬²²ÊJø2åË”/S zwôîh¹ŸC‰#@ˆ÷QCÒ~Iþ%ù—dx|éñ¥Ç—`ZËi-§µëÅÖ‹­¿�s™Ë\(uºÔéR§¡©OSŸ¦>ÐxQãE��ŧŸZ|úòí7moÚÞ´…JC* ©4LÏšž5= Õ/T¿Pý$I8’pÒ¾Iû&í0¹drÉä”ý®ìwe¿ƒšík¶¯ÙjN¬9±æDð®ç]Ï»\˜taÒ…IðÐë¡×C/ÈHÉHÉH�S™§2OeÂcïÇÞ�½¡®¦®¦®4Ã4Ã4ÃÀNg§³ÓÁeíeíe-<;ÿìü³ó�ýUöWÙ_�ú;õwêïÀl¶Ùl³ÙP±cÅŽ;BÍñ5Ç×Ï:=ëô¬hii�‡ƒ‡ƒ‡˜55kjÖ4 5 5 �ÛÜæöëß&[M¶šl…Ñv£íFÛ�®¢®¢®",½`ô‚Ñ/¿ "J)B¼�B %Ú›µ7kofÍ*šU„£ŽN8:t5t5t5^ å´rZ9 &çLΙœssshP®A¹å �_¿6~/߯٥٥ÙzK½¥þw×èƒôAú `³˜ª�ª�ª�/·S9¬VþÍEt­Û´nÓº Ü©}§ö�Úììì c§Œ�2v \hv¡Ù…fðÐæ¡ÍC¨~¥ú•êWàòÎË;/ï„o3ø›Á`ô£ýÌ1ÇÀ /¼+¬°%X V‚A S”°ßèK_ú‚ª�ª�ªàŽ;‚Xb‰%à„Noàs±›Ý솋K/.½¸²wdïÈÞ~‡üùmUmUmÕ7�C¼ä!Þcõ¶×Û^o;̰�a;Ö&-MZšù=ò{ä÷€!K†,²ŒfÍ6šýêÇÏ Ë Ë ƒU�ª@™+3Wf®§ÙN³�fƒÝ5»kv×^¾ß;Ð;Ð;¢,£,£,!9 9 9®ï¼¾óúN¨T®R¹JåÀ6Ö6Ö6 ®\+¸¹þ¹þ¹þ¿ÖÚZkk­�£ÆQãd‘EtîÖ¹[çn°±ÛÆn»�Å]‹»wÁt·énÓÝ�¨JT%ª sjæÔÌ©à9Às€çxPöAÙe!Ü#Ü#Ürä,ÈYE­ŠZµ‚5úÔè£ÜG¹�rÓV¦­L[:¥ø«tÞ:o�7ì|ºóéΧphÌ¡1‡ÆÀ´ÃÓO; u¯Ô½R÷Š¡S C“k„(�*<ªð¨Â#˜ûáÜç~÷?½ÿéýOaUýUõWÕ‡¼áyÃó†:¥ø_·/n_ÜŸ> |G;ít´ÌIž“<'Y~ñ‹ÿ—B�èŸèŸè‹#G.ŽǾŽ}ûÂDÕDÕDXδœi9ÓÐ)ÅŸ)ì[Ø·°/üÒè—F¿4‚ÐÌÐÌÐL˜1rÆÈ#¡j…ªªV0tJñ¶‘ „ø—äŒäŒä Xú`郥Àâ‹O,>�Én“Ý&»�Íz›õ6ë �Rü&¿S~§üN°®ñºÆëCDZDZDÌt˜é0Ó*Í«4¯Òí<|SüMñ7Å úQõ£êG˜n3Ýfº Øýl÷³ÝφNYråÆäÆäÆÀ�ç<ÿãyx¶èÙ¢g‹`vöììÙÙàúÌõ™ë3C§o;)Bˆ?•96slæXø.÷»Üïr!;";";f|<ãャ¯£¯£¯¡S–Ù�Ù�Ù�°rÖÊY+gAJLJLJ ÌL�™:3\œ\œ\ÞÄýÄ{A €â?ÊNÎNÎN†UšUšUHXš°4a)Ì\2sÉÌ%àªwÕ»ê �òý•q1ãbÆEø6üÛðoáàFÁ�‚0�éLJ¯)½¦ôC§ïù€â?²t°t°t€É¡“C'‡Bùúåë—¯_g~�ùu&<­ð´ÂÓ †NùþI=Ÿz>õ<,*»¨ì¢² ·ÕÛêmaŽóç9Îò‹_ü=r@ñ?+h_о =lðÜà¹ÁnÞ¼yóæM˜í:Ûu¶+T ¨P)ÀÐ)ß]Iw’î$Ý�%éKÒ—¤ƒÍ¯6¿Úü “GN9y$”j\ªq©WðØfQ²IBüe… €%@ Pàb…‹.V€™a3Ãf†AõáÕ‡Wnè”ïŽç#Ÿ�|>–œ^rzÉipqwqwq‡ ê ê j°8jqÔ⨡SŠ÷…!ÄßV|ªøTñ)ØvnÛ¹mçàø•ãWŽ_�^3¼fx�ç"ÏEž‹ �òíõÛUü‹ª.ªº¨*xœö8íqÆùŒóç¦�L;™v2tJñ¾‘ „xeô�õ�õ�aw·ÝÝvwƒýßîÿvÿ·0¥þ”úSêƒ×N¯�^; �òíñhÍ£5�ÖÀ’fKš-iu‚ë× †‘åF–YLºšt5éjè”â}%@ñÊ)M”&J8èrÐå  lÌߘ¿1êÇÔ�©VŸX}bõ (­•ÖJë7(—\rA¬V¾øâ ú(}”>Š7ö8^ÕϪŸU?CNÙœ²9eáöšÛkn¯�ö~íýÚûÁPŸ¡>C}@[E[E[å Ì‹(Ѥ!^¥…ÒBi!î!î!îóòÆBhРyý9ÔžjOµ'\¾|9rŸä>É}íRÛ¥¶K]K]K]Ë70!e)KYÐ7Ñ7Ñ7�ò!åCʇ@Ûkm¯µ½F­ŒZÉC˜Ä"@Qbl,ÚX´±Rz§ôNé 3Î88ã ¡S ar!D‰¡¬VV+«�p 7t! K €BQIB!J )B!D $@!„(�¤!„%�!„¢’ „B”@R„BˆH €BQIB!J )B!D $@!„(�¤!„%�!„xCô}õ}õ}áæ²›Ën.ƒK+/­¼´tYº,]0–±Œ‚ &”J¥(ÁJ° Üâ· ½â}!@!Þ��Ü�Ü�\صx×â]‹!ºvtíèÚpóÓ›ŸÞü–|°äƒ%@Zë´Öi­!øjðÕà«0©Â¤ “*Àã!�‡<bè­ï )Bˆ’Cƒ  B…êÍ¡ö…ÚjƒéBÓ…¦ aàÔ�SNç;Îwœï@�žuzÖé æµÌk™×‚Ê÷*ß«|Â3Â3Â3 Ó6Ó6ÓSSS!¬IX“°&†žTñ®22t!„xSÔ3Ô3Ô3àVï[½oõ† iÒ.¤;ÙÉNÈ�Ë�Ë�ƒf­šµjÖ ,ÛX¶±léÆéÆéÆpËö–í-[ȋɋɋ×®\@Íû5ï×¼ê(u”:ê�㦤¦¤¦¤BÄâˆÅ‹A=Q=Q=Ø>°}` &eLʘ”UgUgUgÈwÉwÉw­³ÖYë šGšGšG�ë–ë–ëÿ8ñ�ÿ8ÏÛ>oû¼-L91åÄ”à‘à‘à‘÷ŠîÝ+‚§ÇŸzl>°ùÀ樿³þÎú;!rjäÔÈ©�x<ñxâq°ùÞæ{›ïÁä¡ÉC“‡àéêéêé ÄO¼¡÷šx]䀢ÄÐh 4°ãÆŽ;nÀ¾ü}ùûòÁ|´ùhóÑðk̯1¿ÆÀÁõ×\ù;ówæï„•+#VFÀ#»Gv�ìÀtŒéÓ1°6hmÐÚ 8wëÜ­sÿǹyíííÐj µ…`ÜÀ¸�q0ícÚÇ´äyåyåyÁ×s¿žûõ\ˆ1�1�1M5M5M5à Oxš¾š¾š¾ð|ÁóÏ€ÞIï¤wó æÌ/Àõ%×—\_«¬n°ºhr5¹š\خڮڮ‚ÓO><â–Å-‹[s3æfÌÍ€ˆ9s"æÀï~õð+ÐM×M×M7ôÞ¯›!DÉQ‰JTqÄì~°ûÁÔWê+P±uÅÖ[Ãá‡> Ïæ?›ÿl>\±¿bÅ:.ãbhýkë_[ÿ •kU®U¹¼zðêÁ«>l©Ã¥—: N¡N¡N¡àö¥Û—n_Bʼn'VœÎë�×;¯“Ú&µMjÖXc ä“O>0•©L‹‹‹°o?Þ~<¸e»e»eC¹å”[§Êž*{ª,GGGBó:Íë4¯NþNþNþp6ôlèÙP(=ªô¨Ò£ÀúºõuëëÐåA—]€Ï8Ÿq>ã@“¬IÖ$zg‰×M €¢äУGd‘EpˆCúÝë™d’ xà�ä·ÏoŸßt³t³t³@k£µÑÚ¼|»Å0‹aà 볬ϲ>û/Æÿç_òJO¥§Òó/äÿíÚ…tÒI $ðwñã3ã3ãáq…ÇW€§vœÚq hE+ZAãq�Ç5ô¡}@5Z5Z5Ô+Ô+Ô+ÀÈÁÈÁÈXÄ"zg‰×M®B”¿]h‚ &@YÊRöw¯›bŠ)ЈF4kkk0»mvÛì6¤?Nœþœp xîûÜ÷¹/¸9¸9¸9üã›a†P�zÔûÝòߊ‰ .¸¥)Mi@‡ÿ:bñ¯?çs>‡¢šE5‹j¾\M™ü2ùeò!ß4ß4ßü¯ú_õ¿ ê`u°:øåûB¯†^ ½ú»<æ˜cnè�#Þ4)BˆCi®4Wšƒ©ÞToª‡äíÉÛ“·C¢*Q•¨‚ó^Ì{1ÌrÌrÌrÀz¾õ|ëùЯ _A¿ØóÉžOö|öÉöÉöÉPQQÃO ?1üÄŸ�›œœ Ï[=oõ¼hëkëkëÃSç§ÎO�áI§'�žt‚|×|×|W¿~?ü>dÌ̘™1 îÜ-¸ QÞQÞQÞP%³Jf•LØûpïýáH�#5ŽÔ€®Í»6ïÚÖ\[smÍ5ø±Ö�µ~¬åΖ;[î,xÅyÅyÅÁ“ÙOf?™ y³òfåÍ‚G6�lÙ€=öØz'‰7F¥ü“¡ƒ!Äë¶Ñr£åFKˆÚµ7j/L­4µÒÔJ`¥¶R[©!%%%%%ÔwÕwÕwÁé§_œ~ÅWñU|!isÒæ¤ÍPäUäUäÖݬ»Yw›t›t›t`Cø7ßÓ/ˆ,ˆ,ˆ„¤II“’&ñ¯Sö-í[Ú·„‚eË –AÆŒŒ3Àâ°Åa‹Ã`dndndßf|›ñ-Xݱºcű͋͋!qGâŽÄ`æiæiæ N7œn8Ý€ô-é[Ò·@ú­ô[é·Àx¤ñHã‘`Óʦ•M+ÈÛ“·'od É’5ìžÙ=³{¥ÂJ…• 3ô^oŠ!D‰±aÕ†UVAêòÔå©ËaÆã�g<6t*! C.B”¿�SBHB!J")B!D $@!„(�¤!„%�!„¢’ „B”@R„ïŸ/ø‚/@y¦¤û°égÓϦP›ÚÔ6ôFˆ·•!ô§?ýáÚ—×¾¼ö%l>¾ùøæã «« ýªö«Ú¯*4ˆlÙ ̵æZs­¡C—\IIIp7ànÀÝØ1wÇÜs!5=5=56Øh`#h™ß2¿e>h"5‘šHC§o)B”`¹º\]®¶>ßú|ës8÷�sÿ8÷ð)çSΧtvïìÞÙ,ÛZ¶µlkè´âÏŒ)S0ÎežË<— [7lݰuxîõÜë¹F”Q~Dy°ijÓÔ¦©¡ÓŠ·…!J Ì[™·2oÁªŽ«:®ê óæ'̇‰™3'f‚Ç,�Y³ �RüUñcãÇÆ�…Ÿ–ÿ´ü§å�÷uÞ×y_ÃŒ¼y3òÀy…ó ç†N) Mž D ’W>¯|^yXU¸ªpU!ä¯Ë_—¿æo˜¿aþ†ÿâ9ä€r^9¯œœp ˆ!†˜W°�B � l`p�{ÜÜpà ”o•o•o�½ìeïÿ±ž (~æg~æ_w |]2~Ìø1ãG8×ì\³sÍ z^ô¼èy¿{ÃyÎsøˆ�ø”qÊ8e°‚¬tèнºKŸ¥‡éÕ¦W›^ l¯Ú^µ½ú_¬ÇlàfÊÍ”›)0Ùw²ïd_x°ãÁŽ;þ~ÌüÞù½ó{Ãwß~÷íwß•òWÊ_)‰&„{ì]°[¶ lõçëÉËÍËÍË…Ê e…WG]uuÔ«ŸÖâKÅ—Š/Á¯Û~Ýöë¶—WíÇLŽ™3¶tÚÒiK'Øo´ßh¿d–É,“YV»®v]í Ë�—;/w½£ÞQïøêóY”¶(mQÆ 7xÜ`pZè´Ði!üìý³÷ÏÞ óÑùè|^ý¸âÝ @ˆàþÊû+﯄0ÿ0ÿ0øhÞGó>šÖU¬«XWùVTDEà¶Øm±Ûbˆø5â׈_!mTÚ¨´Wð V3P3P3jÖ(¬Q¥ƒJ•§%NKœ–@Áˆ‚# òzäõÈëP¬/ÖëárÒå¤ËI�åŸåŸåÚµj?„ujÔ©QJ?-ý´ôÓW?¯ÙU³«fW…³gÏž={Z o5¼ÕphYز°e!T¨W¡^…zP®a¹†åB©OK}ZêS°L±L±L�›ov¼Ùô[õ[õ[_}¾ßï3Þg¼FÞygäHÚœ´9i3\ît¹ÓåN¯o\ñv“ D pdù‘åG–Cƒ6 Ú4h厖;Zîè__ŸQ£>F}@ç¡óÐy@x™ð2áeàäù“çOž‡° aÂ6@Ö¦¬MY›àÔ¾SûNíƒðRá¥ÂKAöÅì‹Ùá䘓cNŽ�ð&áM›@á£ÂG…�À8Æ8Æ8òoçßοý»quF:#¨W«W«WÃå–—[^n __ÿúú××á\™seΕ�”­)[S¶‚I˜I˜Iä×ʯ•_ ¢’¢’¢’à°Ýa»Ãv:4thèP8Üæp›Ãm º}tûèöÿyûõóôóôó Ê-Ê-Ê bbbàö¸Ûãn�ƒÑ/¢_Dƒ¦¹¦¹¦9¿üyíJíJíJPPPÕÕÕÈÙ™³3g'\H¿�~!ަM=š у¢EúûŸ›96slæ@§�tZ‡Zjy¨%œ-8[pö5}øÄ[K €ï±Ô›©7SoÂýv÷ÛÝoMG7Ýtô+Xq.¹ä?ð?€q¸q¸q8h“´IÚ$Xc½Æz�5œÛynç¹�°/l_ؾ0Øž½={{6˜|lò±ÉǰÇh�Ñ#ØÞt{ÓíMÁ¸ºquãê°cÔŽQ;FÁ6ý6ý6ýïÆýç¹r•›ÊMåy½ózçõ†„�„�„0_a¾Â|˜39fr ¶·ÙÞf{ØYgý�õ!Î&Î&Ξ_x~áy(=ó)”êXªc©Ž ¬UÖ*kA{A{A{œœœA™¤LR&�¶¿¶¿¶?8¬uXë°H �„ß�›J*© Þ Þ ÞÎ�:Û�¶m7BÍ5oÔ¼6>6>6>`Àþ€ýP}§úNõØ/±_b¿̽ͽͽ¡Ú¢j‹ª-‚v9írÚå@LXLXLäŒË—3²ªfUͪ IÛ“¶'m‡•_T~Qtãuãuã¡ü½ò÷Êß›Ã6‡mCM�š5=À¶—m/Û^àô©Ó§NŸ‚ê”ê”êÔ§Q5]5]5²¼³¼³¼áØÞc{�í¯ ^¼&@³�f!ÍBàYì³Øg±iiiÿ÷wŸÍ-›[6·Àô±écÓÇ�Ô4©i’|=°Ä‘gñS¶)Û”m úEõ‹ê`Cò VüÛÍï�r”£€^xãÏx(5¾ÔøRã!ëqÖã¬Ç`ÚÏ´Ÿi?à1�yü 7Ð#Œ@ÙªlU¶þný5©IÍó~ 4 œTN*'�cãPžò”%P T?üðƒm¶Ûl·Ù­C·Ý:�¿ÆÆ´ÓnL;piäÒÈ¥(Ί³â J=¥žRïÈ_Žr”]˜.Li‡Ò¥‚à˜à˜àˆý8öãØ�¡n«º­ê¶—-.[\¶½éMï¿>m¿�rPuTuTuýAýAýÁW¸_Ä;A €ï1{c{c{cPn+·•Û�v4íhÚQ°ZgµÎjÝ+ Ÿ|ò� T ÂËÅ7=ÜôpTëY­gµž�Õ<«yVsÈWò•üßßuä·"Q–²”ýÝrSL1Ѐÿfy jPÈ@B±}±}±=èÝônz·ß½ß ,xy�|=zô¼¼EîU®r•—§š¨š¨šð¯;#ú‡û‡û‡Ã€Š*¨t¡ ]À¼‚yó �á—á—áÇ¿¾Þ‡;î¸ÿn|*Tÿf;~[þÏq�7o6Þ e‹Ê•-‚fšuhÖ:Ìï0¿ÃüßýÜ&0áïï¶ ¯ ¯ /È«˜W1¯"8¶qlãØæ|Ä;E €ï±Òö¥íKÛCÅ[Tl—+]®t¹Ò¿¾Vÿ—i‡k‡k‡ƒ»µ»µ»5\\|qñÅÅpgÄ�wF@‘o‘o‘/ôû¼ßçý>‡Û+n¯¸½‚6mÚ ‡¶Úrh ¤,LY˜²Œs�s�s!¦8¦8¦ž'>O|žœä$'!"5"5"’ÔIê$5¨[¨[¨[€þ¬þ¬þ,ØŽµk;öå×ñº¶éÚ¦kHÜž¸=q;¨»©»©»ÁÕ®W»^í M š4…§ƒŸ~:žœrþÉyȯ’_%¿ <Ÿ÷|Þóyàhåhåh&˜`ò»íWâ”8%¿êþ*È-Ÿ[>·<ÜýÇÝÜý¸Íq›ã6?.~\ é�Ò;¥w‚[Kn-¹µbnÅÜŠ¹éáéáéá�v-íZÚ5ÔuP×A]áø‘ãGŽ�„* Uª@ÙÑeG— �&4šÐhX˜Z˜Z˜þõý©ŠTEªÀz…õ ëàlælælfèO«xÓäN€B”7Rn¤ÜH�MúMúMz˜;mî´¹Ó ôæÒ›Koþ +lK[ÚBê©ÔS©§ §nNÝœº Û©Û©Û ¶ lØ.ëÍÖ›­7CÑ÷Eß} ³f'Ìõ]õ]õ]`0ƒ êºêºêº`ÕÕª«UWH[œ¶8m1EQPÊ£”G)È Ê Ê â_‡úKw)Ý¥tHßœ¾9}3ävËíöÿcï>㢸úþ�fwéM¥ƒ‚ˆ *XP,(Vì½÷D�51‰Fb,1jŒ±w�½ÄØ{ÃÞ°‚ A�"Ò{]Ø6ÿwüß¹r_IŒÙ¨ó~¢/v÷Ì÷œÝSÎ)íU~ªòS•Ÿ èvÑí¢Û n7ˆ@±@±@±Êë•×+¯616161 j®j®j… /^Û^¶½l{�y#óFæÿiu½YÌbä?ΜÿrÝrÝrÝÀ¬–Y-³Z`•n•n•¹B®�+€ª�ª�ªTšSiN¥9 LQ¦(S@¥R©T*°mcÛÆ¶ YYYBÆ�Œ7@å£òQù€i’i’iX?³~fý äáòpyøŸØ_?+••ÊJeðí¬og}; Z5kÕ¬U3èØ­c·ŽÝô}”JþiR ‘¼t}t}t}`Ó O6<�üYù³ògÁ”Ð)¡SBÁd­ÉZ“µúN)y]tN:'�l¾µùÖæ[�1,cXÆ0ø¢Ã¾è†s çÎyõíHÞ,ÒSÉ;@vDvDv†}7ì»aßAa»Âv…íàûÜïs¿ÏeUeUeÕWߎäßEýHýHývÛí¶Ûm}ú<ô�&|0რÒÿ»N: ‘¼ƒ2ëeÖˬ˯,¿²ü µ0jaÔ&ö˜Øcbp\â¸Äq‰¾SJþªü%ùKò—À¶Ûnl»1ícÚÇ´‡ A3‚f€{‰{‰{‰¾SJôM*$’wX~ïüÞù½aóªÍ«6¯‚èÈèÈèHþlø³áÏÀ_ç¯ó×�ᧆŸ~ªï´’ߣ� � �P±FÃ6ÇmŽÛ¡J@•€*ðá­o}x V8¬pX¡ï´’ ©�H$h«k«k«Ã¥”K)—R`cöާmNÛœ¶Á ¥ƒ–Z µ…ÚBmä“ä“äÃãh’¿F÷ƒîÝ�Ø ±Ab8°ôÀÒK!29292z¬é±¦Çèù^Ï÷z¾FO�ž=ÕwjÉ¿�TH$’ßÈ2È2È2€cŽÇ�9Â�¾7úÞè Õƒ«W†.^]¼ºxA=ÿzþõüÁxšñ4ãi¯¾]ÉöË<QžQžQžü øAðˆ9$rÔÿ¡þõ€þ7ûßìª:Tu¨ê‚—à%xé;½äßJ*$Éï;ÃÎ@JAJAJ\ØqaÇ…pÓø¦ñMc0~füÌø4Ó|Ló1Ðäh“£MŽ‚s¡s¡s!………ê»oMGMGMGH]˜º0u!<þ B\C\C\!oqÞâ¼Åà«öUûª¡ÓÌN3;Í„{kì­±„ÍÂfáoX+@òn� ‰DòÇ}Á|E{Šöí�°Ü°Ü°\¸6áÚ„k ¹mrÛä¶P© RA¥¨Y/²^$Ô¿RÿJý+P]Y]Y] fçÌΙ�…•ÂJaEÅŒ€o9� t”hK´%ZxaûÂö…-„«ÃÕájx4ìѰGÃ Ó Ó ÓìzÛõ¶ë -†¶Úb(4§9Í�*æUÌ«˜qħï^IÞTR ‘H^™¶½¶½¶=dÍËš—5"kEÖŠ¬÷¿¾ÿõý¯áùÎç;Ÿï��ÎGç–ý-û[öO;O;O;psssss§Ï�>wúì­í­í­ÁRc©±Ô€l¸l¸l8¿Nýû¯qŒcqŽ8Gœřřř�1-cZÆ4H”þ(ý$öMì›Øâ¢â¢â¢ «RV¥¬J k¨k¨kÕÚVk[­-ÔŸUVýYPÿ^ý{õï�}sûæöÍÁ`ªÁTƒ©úî¬äm#‰äµ+kXÖ°¬!ü`ôƒÑFpjý©õ§ÖCàØÀ±�c!'5'5'ò¶åmËÛb˜&†�Å·ßZ| U|ªøTñË`Ë`Ë`°ö¶ö¶ö[o[o[ïŠ)mM6˜l0ÙË –,E?E?E?V «…Õ ß,ß,ß Ìf6³AW_W_WtëuëuëA;O;O;ÔuÕuÕu¡LY¦,SB¡_¡_¡ä®È]‘»2÷eîËÜ 6l€Ü©¹Ss§BáâÂÅ…‹A(‚Õz«õVëÁÑÞÑÞÑ<7ynòÜ®Ç\�¹ƒê;ªï¨¾,÷Yî³Üǯ‹I$ÿéP“H$¯]t@t@tÜï¿ÿýþ0Ãü ó7@Ó°¦aMÃ@}Z}Z}ÊÇ—�/™Á™Á™Á�b”b”bT±@®e®e®eÅ= U#ªFT…âjÅÕŠ«�vŸvŸvˆ/Äâ ;‰�ÄNÀr–³ØÈF6‚ØWì+öaˆ0Dæ0‡A¨.Tªßò-ß‚b©b©b)èÎêÎêÎBè†Ð ¡ _P¿ ~AàèèÖqÖqÖqà¼Ùy³ófphíÐÚ¡5dü‘ñG`8ÕpªáT@Däå_·zÒ“žúÞ;’w•t@"‘¼6Iý“ú'õ‡yÙó²çeC·€nÝ ï ¾ƒú¼ñÆû¯·¯MÓ¦iÓ@m¤6R�ÆUãªq­XŒHÛ@Û@Û bù_]Œ.Fâ2q™¸ äååA¨,T*ƒ\!WÈ �)d YÅ©÷ŸíãëC_úú41ibÒÄúíî·»ßn}�²Dò×H€D"ùÛN(œP8¾nòu“¯›@õ‹Õ/V¿ZNh9¡%(&*&*&ê;åŸw§Ý�vwÚÁ§8ýÃiXä¶Èm‘إ٥٥é;�DòçHkH$’¿�V­UkÕ°uæÖ™[g‚Aƒ&M`t³ÑÍF7{s¿øÑx_ã}�÷AµøjñÕâá¨ßQ¿£~úN%‘ü5R ‘Hþ6§—�^vzD¼ñ^Ä{ðц�6|´L?6ýØôc}§{ur[¹­Ü¶Øj`+yò0ä!$¶Jl•ØJßé$’?Gº ‘H^Ù#ûGö�ìaiý¥õ—Ö‡O¯zýÓëà§ôSú)õ�îï'v»‰Ý`yŸå}–÷ªQ�j0ÕyªóTg¼oáîm�Hþ Ò‰Dò—e»d»d»Àúo×»þ[èÒ;¤wø-ð[à·@ßé^á”pJ8ý�ú;õw‚p�p�px²éɦ'›ô�N"ùc¤@"‘üiº.º.º.°m×¶]Ûv�s?ç~Îý W�^uzÕ>ã3>ÓwÊׯz×ê]«w…–ñ-ã[ÆÃ�¸qâ@×Q×Q×Qßé$’ÿ›TH$’?í¢ ‹.,‚˜b>ˆùÆŽ aaaúN÷Ïë5¿×ü^ó!ùAòƒäú,ôYè3}§’HþoR ‘Hþ°ô¾é}ÓûÂÞa{‡íÃZ k1¬8„9„9¼ƒ_ü¿°¿fÍþtÜqpÇÁ°¿ÕþVû[A™¬LV&ý/+ù—’M‰Dò_‰wÄ;âØýÞî÷v¿Ë<–y,ƒ–n-ÝZºé;Ý¿G§�N!�B Ø´Ø´ØB¾ ù2äK}§’Hþ3©�H$ÿÕÃ+¯<¼)))0<{xöðlPÌUÌUÌÕwº�Jw+Ý­tzuèÕ¡W8zíèµ£× hGÑŽ¢úN'‘üÿ¤@"‘ü.õ}õ}õ}Ø_yåý•¡ýŽö;Úï€jë ¯6\ßéþ½ÚÎn;»íl�¥ÉÒdipåÄ•WNè;•Dòÿ“ ‰Dò»î¯¼¿òþJÈžœ=9{2tžÞyzçéúNõïgnn=½W€IDAT½}zûôö�S½Nõ:Õ ( @ßá$’ŸI€D"ù õfõfõf8Þåx—ã] µGk�Ö`Óצ¯M_}§{s´xÚâi‹§`>Î|œù88·æÜšskô�J"ùR ‘H~#ºGt�èðbÏ‹=/ö@à¤ÀI�“ô�êÍcôØè±ÑcèÔ'¨OÇÇÇ@Îòœå9Ëõ�Nò®“ ‰DòÁ«ƒW¯??????pë0ÖaìßÐpI$)¤�òÇ?ölð³ÁÏÕFW]i%‘%‘%‘/½¡ˆ"Š@ÌsÄ u¨ä‘Gž¾G·iܦq°}jûÔö)œI>“|&Yß©þ€rÊ)žð„'@e”ý÷�•½_ö~Ùûp+öVì­Xxñ8âqÄKoH&™dà(G9 â�â�â�À1Žq P¡B¥ïοý¤@"‘üêùÎç;Ÿï„¨&QM¢š@× ]7tÝð74ìˆ#Žð“åO–?Y‘¢#EGŠþ@÷çîÏÝaKŸ-}¶ô�èuÑë¢×AüÊø•ñ+añ²ÅË/ƒDm¢6Q ±Q±Q±Qäää!½Bz…ôÒ÷¨‚Q{£öFí¡ÿ�þ7ú߀K/=¼ôÒ¦=L{¨ït¿/ý›ôoÒ¿�…XxRìSìSìÿûçŽÎ::ëè,¸øüâó‹Ï!>*>*> Î=wôÜQØâ¼Åy‹3ûûûÃÁSO<³²feÍÊ‚¢‚¢‚"éf‰×N*$ɯBlClClÁµŸk?×~P½EõÕ[ü �d$#¡zIõ’ê%àâãâãâóß?ö8úqôãhHOOOOO‡áý‡÷Þ\šº4ui µ§ÖžZ{*XÔ¶¨mQjÌ©1§ÆH6J6J6‚Ÿ¾øôŧ tT:*áΔ;SîLÍ<Í<ͼ~|ú4ôièÕüªùUóƒÓ§Nüó9þ(“““¨k_×¾®=˜7nú<ý¡Û«Û«Û »\ìr± ÔÙZgk�­Ð#¸Gp�`p r r ‚šv5íjÚ�¹�¹�¹8&:&:&Bظ°qaã@½Z½Z½bÅŠ=qKâ–Ä-Ñ÷h¼}ú ‘HôOYYYYYnu¹ÕåV¸vàÚ�k!Û;Û;Û»þîz°Xo±Þb=”û•û•û�GW�®]ÁÑÞÑÞÑn׿]ÿv}0›c6ÇlhGhGhG€³»³»³;60l`Ø´×µ×µ×A´-D Š„"á¥3eëËÖ—­‡È'‘O"ŸÀóGÏ=OÒŸ¤?I‡ªêªêªj0-3-3-åUåUåU°ö´ö´öùUùUùUg‰³ÄYpLvLvL‡—^vxµ jÔ |/û^ö½ iKÓ–¦-…èëÑ×£¯ƒ¡ƒ¡ƒ¡4šÛhn£¹�o‘o‘oQª(U” l/Û^¶½ +�•Æ <šy4óh�?xüÁãÀk�ׯ=`sÝæºÍõŠ~ÉïÈïÈï@ߤ¾I}“`åâ•‹W.†Îý:÷ëÜœ9r>ô×÷£n¡n¡n!„½{ör.ä\ȹ&ãMÆ›Œ¡«ÐUè ~Ûý¶ûm‡ìÙ-²[ÀÓ£O�>= ¶ŸØ~bû h7i7i7�Co‡Þ½Á4Í4Í4 ÊŽ—/;|Çw|÷Ò†ÛІ6�x$ñHâˆ;w$î<ûdì“±ÐØ¦±Mc’„$! „-Âa è~Ôý¨û >6øØàc�}*ûTö)dÎ<œy–w_Þ}yw¨q¯Æ½÷`”Ã(‡Q`½Ñz£õFxØæa›‡m wNîœÜ9PuxÕáU‡ƒ§è)zŠVVVô¦7½AÞRÞRÞâââA£‹ÑÅ@æ¥ÌK™— Qt£èFÑ Ÿ(Ÿ(Ÿ¨ï•¯Ÿt@"‘ðhÓ£M�6�ÖEë¢ußTßTßT(ý±ôÇÒaáü…ó·¤ÑI£“FCn|n|n<,깨碞�‘‘G><òá‘a퉵'Öž€øöñíãÛCúÚôµékáÎì;³ï̆UŠUŠU Ðøh|4ÿáL€ì„ì„ì(ÊeŠ2�m‘m‘mƒíÛ ¶ƒì¾ì¾ì>¬^¹zåê•pÃ÷†ï ß—øù²ÌCæ!󀜌œŒœ (˜[0·`.˜$™$™$AÊ•”+)W`Y�e=–õ€Â‹… /Â�¦7šÞh ›ý6ûmöƒâ�Å‹Âì.³»Ìî×b®Å\‹�§wžÞyzR>Jù(å#ØÕ~Wû]íá™Ç3�g¿?ÞõÞ¯÷~½÷Á³‘g#ÏFptæÑ™GgÙd“ý×÷£l†l†lÜè}£÷�Þ°ÁiƒÓ'0p1p1p�S·OÝ>uv·ÞÝzwk(T2¨d|©úRõ¥ B"B"B" úTô©èS tV:+�aÅÝwWÜ…;†w ïþ‡ Ûb‹-("Š�Õ“Õ“ÕKKK0úÐèC£!>4>4>¾éõM¯ozAñûÅï¿Bª�*¤™d’ Âmá¶pA±A±A±MMMáÄû'Þ?ñ>~pøÁá ‹ÓÅéâ`Í©5§Öœ‚'=ùèÉG V/X½`5Ä��;w¾âž’PÿPÿP8˜{0÷`.¨ž«ž«žëû_ã?G: ‘H™23d&4 lØ0Ì¿7ÿÞü{Ðiƒ´A`>Å|ŠùðêäÕÉ«ÔßTSýMppÔÁQGÁ³KÏ.=»¶!¶!¶!`.7—›Ëa¨0T*€à"¸.�œœ Âcá±ð°Ã»ßæ1ðÙï³ßg?œîºÿéþ�|+ùVò-hkÞÖ¼­9ºººÃ¦:›êlªýÝû»÷wóÏÌ?3ÿ Z|×â»ßAÃ9 ç4œâq‡¸–.-\Zf'ÍNš�üýñ. —…ËÐwpßÁ}Â; î,¸]kw­Ýµ6¸áƫ̰lÓÔ¦©MS¨Ò¯J¿*ý Eÿý[ô‡ÂF…� ÁöšÛkn¯ ]>èòA—À¼­y[ó¶Ð²VËZ-kA½%õ–Ô[ººº`þÌü™ù3ˆÄÿaƒ8ÀpŽuŽuŽ…*�ªtªÒ ¼¾ñúÆë°¿nÝþ:8ìpØá°d¶2[™-0�éLçׂM)ŽGB展ÇV •ÛUnW¹ÔÚQkG­`Óæ‡M8±üÄòËÁ_ë¯õ×Bë•­W¶^ û½÷{ï÷†EŠ�ÃF‡�ÁÞÛÞÛÞŽ8~àx«ˆUÄ* ë¡ë¡ë]’º$uI///}ÿküçHg$’wXÖá¬ÃY‡!Ê>Ê>ÊZ´mѶEÛ—Þ`€@0Á‡8Ä!�-‘-‘-y€<@¥—J/•^!LÂ@æ"s‘¹T|ñÿêw¸ó'jР±ƒØAìd�A ü‰v´hÑ‚¸^\/®šÓœæPâZâZâ é­Ó[§·†Ã>‡}û@|@|@|´ÜØrcË� ÿJþ•ü+ …B¡dé²tY:È2…LòMòMòM`9Ùr²åd�gÊ3å™ÿ=V-ÏZžµ<¡Þƒzê=€£ Ž68Úˆ!†˜Wر?�KYÊÒŠ·1ncÜ”ÔÔÃ@—¥ËÒe�`/Ø ö {!{!{²²² »$»$»¤‘FÚØî/ÇË/w÷O'‰åñQ9rä@8ᄇ9ÌኗóòòòòòàÑüGó͇ý-÷·ÜßªŽ«:®ê8¨y¼æñšÇA7H7H7¨b?ýÒ/ƒO >5øŒ¦M7š^Qàþr¯Ê»B*$’wX„C„C„˜×5¯k^j̨1£ÆŒ—ÞðËãX}èCö û„}PÜ ¸AqP¯T¯T¯û‰öí'‚¸X\,.¡¹Ð\hþ6(C† hK[ÚÆcüüåý=éIOÀSL:tüútMhB“—>÷Ë™o¼ñjS›Ú ™£™£™â|q¾8ª,ª²¨Ê"¨z©ê¥ª—`€ÏŸ>0ùÔäS“OÁ´zÓêM«F#ŒF� ¢ðø_¿¢«ÜTn*7ˆ<y8ò0-6(lPØvîݹwç^¨íWÛ¯¶Ô«W¯^½z°¾ßú~ëûÁÁ ƒAƒàɆ'žl€Än‰Ý»�òŠòŠò ĚŚŚUäÍ Î Î †EÇ_t"GEŽŠõÇ÷C�Oj|Rãh´¤Ñ’FKàèÄ£�N1SÌÿÀ™„ÿM8 @âáÄɇa×Õ]Ww]…>øðÁ‡0üÆðÃo@ÚÙ´³igA§ŒSÆAlÕØª±U�Où”O!6)6)6 •…ÊB%Äõ‰ë×Êæ•Í+ûOQ$ìHØ‘° >*ø¨à#ˆ>}>úQlÔ>¨}�(?qüÄñ¢˜\-¹Zr5Q,É.É.ÉEõ5õ5õ5QLª”T)©’(&&$&$&ˆbù˜ò1åcDQ]_]_]__ä¾È}‘+ŠÏ|žù<óÅ¢oо)úæ·ÛÕtÑtÑtÅ_\|qQã{Æ÷Œï)Šùòä?Å   Q|6ôÙÐgCEñŇ/>|ñ¡(æuÎëœ×YŸ•=+{V&Š)7Sn¦ÜEålålålQ|ø<ðy (&~™øeâ—¢¨Ù¤Ù¤Ù$ŠÅ“‹'OÅgžuxÖAŸW^ýyuQÌ_‘¿"…(|PðAÁ¢———!Š™]3»fvÅÿ¹¤ йF®‘‹bê™Ô3©gDQ9]9]9ýÏï—Äî‰Ý»‹âû3ߟùþLQŒ¬Y#²ÆŸog—÷.ï]Þ¢8àà€ƒŠb|ÿøþñýE1­FZ�´¢¨ ׆kÃE± }Aû‚ö¢&Š™‰™‰™‰¢(Öë‹õE±Ð¥Ð¥ÐEã ã ã E1eBÊ„” ¢¨ Ôj»Ý¢IE“Š&‰b|·ønñÝD19;9;9[KÕ¥êRµ(¦OOŸž>]ãíãíãíE1{vöììÙ¢˜žž.Šñ£ãGÇ�Åü#ùGò�ˆbþ½ü{ù÷D1æÓ˜Oc>Åœ¤œ¤œ$QÔÍÐÍÐÍÅôVé­Ò[‰büþøýñûE1Õ=Õ=Õ]KÅR±TÅ”í)ÛS¶‹â³¼gyÏòD±Ô«Ô«Ô«"o¡m¡m¡­(f|™ñeÆ—¢¨Û®Û®Ûþºÿõý{H€Dò ) ) )Å�eË>–‰¢²®²®²îoß—Ô>©}R{Ql‘Ü"¹E²(÷ îÜSßéß~ëCׇ®Åy·æÝšwK5Æc�ñÿüÚqkÇ­'Š}Ÿö}Ú÷©(æÊ?”Hß½’üÛH—$’wУ:�ê<ªµKj—Ô.ãããˆß¾¯ìnÙݲ»0xÍà5ƒ×€Ñh£ÑF£Aw[w[w[ß½x{õìÒ³KÏ.=þzüuxœ÷8ïñ˜ÒX¨T‚ëû®ï»¾�’:%uJ‚¢»Ew‹îê»W’á—J@ßA$Éë÷˵Û/²¾Èú" m´iÐ&ð/÷/÷/×w:Éÿ¶åΖ;[îÀóÄç‰Ïá«V_µúª(Ž G}§“¼é¤3É;$åqÊã”Ç ¼¦¼¦¼ž2O™§þÈMÌMÌM„¸Uq«âV�*[•­z… pÞV=:÷èÜ£3üϽðàûß?ø^ß©$o ©�HÞ!á«ÂW…¯‡µkÖ‚Í›;6æ¹üW”Ý%»KvØôÓ¦Ÿ6ýû|÷ùîó…¬mYÛ²¶ý÷Ï]-ºZtM<4ñÐDØ¿zÿêý«A×F×F×F_£úúØåÙåÙåA»Äv‰íáp³ÃÍ7ÍQÍQÍQ}§“¼é¤@"y‡DŸ‰>}¼Â½Â½Â�zÔ£Þ?·ý‡‘#FB\Õ¸ªqUáƒÃþà0ØÖ°­a[ã¿Þ"Ñ"Ñ"òîçÝÏ»GGqth{j{j{êkT_¿Î �:'@–{–{–;Ü�¹s÷U& ú«†0„!ð¢Á‹/@Á½‚{÷ô=:’¿J*$’w@A½‚zõ ùËä/“¿ssónûºÎºÎºÎW=®z\uȘ“1'c”,=Xzäµäµäµ ýdúÉô“ðDóDóD1{böÄì�²Ùe³Ëfïó>ïƒÅ‹;w@vKvKv „mÂ6a}[ômÑ·}-úZô5ˆ‘ÇÈcäPÚ¿´iÿŠz;4ßt|Óñbbòò¢A?OMûËT³ekËÖ–­…ës®Ï¹>¬»Yw³î#Œh0¢Ôµ¨kQ×’,’,’,àtãÓ�O7†f̘Aß}oô½çzœëq®üÏ„5úÞk¿U9¤rHåèêÐÕ¡«ó?æÌ”®JW¥ë«·ÿßT_^}yõåË!·ÞÑzGëФZ“jMª�¬³¬³¬3´nÜ"Æ=÷xÜcðºäuÉë”y—y—yƒI_“¾&}Áõ�ë!×C JV%«’¡àË‚/ ¾„ý;öïØ¿cccá½[ïÝzï=ÄbÒ„4! ¾(ø¢à ¸6äÚ�kC`ƒnƒnƒ®F^�¼ Ú³Ú³Ú³/µóóâââ`nnnnnã§�Ÿ>~:œ¬y²æÉš0¥ï”¾SúBĦˆM› ä@É�’�r(åPÊ!8zêè©£§àÌ…3Î\‡R‡R‡R�{È=ä¹—¯]`ïÀÞ�½¡ì~Ùý²û2+dVȬ׿]ÁH0Œ€U¬b°�}ìžò”§ 7•›ÊMÁ¤‘I#“F`ô™ÑgFŸ�ü‚ü‚üPB %/7øóÚ ƒÄ P�T�T�„”“)'SNÂÅŽ;^ì{ý÷úïõ‡JG+­tŒÂŒÂŒÂô½Þ|Ò%‰ä-¦Û¥Û¥ÛIý’ú%õƒ®�»6îÚ˜_¯µþã(P€pA¸ \E¨"T 747474pÄìˆÙ3Øn·Ýn»˜÷4ïiÞ‚7 nôR;?¯'l6 Ag«³ÕÙBÀå€Ë—¡k“®Mº6�/ÏyþËó°UÜ*na²ÁdƒÉ`·Ón§ÝNè6¸Ûànƒ¡Æ75¾©ñ ˆ^¢—è¹—¯�E„E„EôpîáÜÃŽçÏ?ž- Z´(ÓÏM?7ýüul ,@l(6‚ØDl"6á×ņèF7º�à/ø þT¬jXJ)¥ «¢«¢«òR{†bÂ(a”0 Æ c…1Ø4·inÓÚÚ·µok-,[X¶°„QÇGu Ò Ò Òõ½Þ|R ‘¼Å²§gOÏž¹¹¹à1Ìc˜Ç°>‡vžvžv$oMÞš¼2?Îü8ócH2K2K2‹­[-¶VÌ0xÏýžû=wH]�º uAÅ"1é©é©é©�¢JQ¥¨ g|Îøœñ�èšèšè ß;øÞÁ÷ ©wSï¦Þ`<Úx´ñhðøÂã �/ ÚgÕ>«ö4+lVجŽß=~÷ø]hr¨É¡&‡ÀÁÝÁÝÁjzÕôªéòKòKòKúÞ‹¿¯õÈÖ#[�„3–g,ÏX•ãWŽ_9]?ïúy××Pæææ€Y™Y™Yümð·P/½^z½t(t,t,t„¤[I·’nU,ÆXíDµÕN@^Q^Q^„4 iÒR R R  P, E�»È]ä.ÐIÖIÖI*_¨|¡2hii�Í{6ïÙ¼µšÔjR« a„‘¾wÂLš P"y‹…Í ›6vœÜqrÇIX¼mñ¶ÅÛÀÔÇÔÇÔçŸË¡Z«Z«Z �C‡>…ü¸ü¸ü8ð:ïuÞë<Øô²éeÓ ÂÛ†· o šÝšÝšÝ`4Ùh²Ñd(Qþ¢ü¸wuïêÞR¤ HæææàuÁë‚×Ho—Þ.½Ü,¸YpŒ§O1žÞVÞVÞV`¶Öl­ÙZÈwÏwÏw‡È!‘C"‡€PY¨,T»©vSí¦‚Ûf·Ín›A>F>F>Fß{ñ¿;w>î|ö9ìsØÛ/¶_l–‰–‰–‰ßvÄ�Å�Å�áÉ´'ÓžLƒ´–i-ÓZB•mU¶UٹŹŹÅP͸šq5c¨e]˺–5”e”e”eÀÃúë?¬²(Y”, ä“å“å“¡üaùÃò‡Ð`Iƒ% –½éMox\ü¸øq1¨OªOªO‚u±u±u1¸+Üî 0\b¸Äp‰¾GÿÍ%É[ìðõÃ×_‡ÈN‘�";Á—Æ_i B®�+äê;�äïR:¨tPé ˜á7Ão†´=Øö`ÛƒÐûvïÛ½¥5$¿Cº P"y‹%|�ðuÂ×woK_üo'Ó}¦ûL÷Amm-œñ9ãsÆò†å ËÓÃ%É›A*$’·�*^¯Š‡ M†&CUÛTmSµ�¾SI^7ÿ•þ+ýW‚ÅgŸY|çÇŸ~¼¾SIþ­¤@"y •••AAÍ‚š5Á>Õ>Õ>Uß©$¯›aºaºa:ô½Ù÷fß›pîĹçN@NNNNN޾ÓIþm¤@"y e̘=t�F§‡F�½z»’7ƒß¿!~CÀ6Ý6Ý6Τ�I;“¦ïT’©�HÞB   `9×r®å\¨Ü¬r³ÊÍô�JòO105050…¾}úÀÅŒ‹3 㓌O2>Ñw:É¿…TH$o¡” )R6€C{‡öíAˆ¢…h}§’üÓ j0¨Á pövövö†SCO =5Tß©$ÿR ‘¼…2b2b2bÀ®¿]»þ¯ÞžäÍd`e`e`ýû÷ïß¿?\ï½ÿõþ�2)eRÊ$}§“è›TH$oM¶&[“ ™O3Ÿf>­˜�Mònó™ç3ÏgÔð«áWÃN|}âë_W¼žR˜R˜RW¿¹úÍÕo@ÛSÛSÛSß©%¯›4°Dò)¹Ur«äÞ,¼Yx´Z­¾SIôMÞNÞNÞú9÷sîç ‹Æ-·hˆ)bŠ˜»/ì¾°û”Ý-»[v.̽0÷Â\¨D%*é;¼äµ‘ ‰ä-RÒ¿¤IÐåêru¹`þØü±ùc}§’蛺±º±ºqÅZ OO?=ýô4ìß¼óþÍPn^n^nn§ÜN¹�‚”)#RF@¥ÈJ‘•"õ�^òºH—$’·HQxQxQ8~‚ŸàævævævúN%Ñ—¢ïо+úf¹Îr�å C†„ ƒ»SïN½;Ê”(?PñþüjùÕò«A¢u¢u¢µ¾ÓK^7é €Dòɉ͉͉“N&�L:�™ƒ™ƒ™ƒ¾SIôÅ8È8È8\º>t}b7±›Ø xÈCþöýyóæ „DãDãDc}§—¼nÒ‰ä-’ö4íiÚS¨<¤ò�ÊCÀÈÔÈÔÈTß©$úb 4P(aBà„À �°vÊÚ)k§€ÛçnŸ»ý§å‚£‰&CCC@·M·M·Mß½�¼.Ò‰ä-’S�S�SUVYXe!p„#Ñw*‰¾É“åÉòdÔtPÓAM¡Ò�J7*Ý€iÉÓ’§%Cx�ð:áu€¯øŠ¯ ¡GB�„PRZRZR £,FYŒÒw/$7é €Dò)xTð¨àTž]yvåÙúN#ù×¹Ãî@§ÌN™�2aÓÁM7„€7nT¼-æFÌ�˜Pܯ¸_q?}‡–¼.Ò‰äm F�ò=ò=ò= n׺]ëvÒI']ßá$ÿ:N8áMÔMÔMÔ°1zcôÆh4,hܪ~«ú­ê�}=ûzöup<áxÂñ”Þ.½]z”Ó”Ó”Ó@}]}]}tž:O�'¨WªWªWFaU ªTá™ðLx��L¾6ùÚäk0v1v1v™�ÌGæB²�,$™ÈD}ÒÛO*$’·€6U›ªM…ÂÎ…� ;Cå�+\ùc}§’è�^xAI‡’% ß+ß+ß ò ò ò+îI]–º,uÔºXëb­‹u%êJÔ˜›07an8¦8¦8¦€ÚEí¢vmmmmmmŠŃ ¶[Š-Al$6ÖXc ÂûÂûÂû 8 ΂3 ……ÂB�••…‘ÂHaÆŸnü9X„X„X„€•ÖJk¥…J5+Õ¬Tª®z¸êapzâôÄé X5±jbÕ*=¬ô°ÒC0O7O7Ožð„'úô7‡ þLßA$É_W´¯h_Ñ>ºt%è |fõ™ÕgVPkQ­Eµé;�äuÑÞÖÞÖÞ†âóÅç‹ÏCƒ„  Ú9Ú9Ún'ÜN¸ )•S*§TÕIÕIÕI�×�×�׋Ç�-ƒ]¨]¨](ØxÙxÙx�EC‹† A¢Q„€c%ÇJŽ•À¢¹Es‹æ`öÜì¹Ùs0jjÔÔ¨)Èd²0Tª U@5ªQ ÔÓÔÓÔÓ@û�ö;íwPþ~ùûåïCɃ’% 8±8±8J®•\+¹ï¼Wðä�É“7rÇåŽË™f™f™fP`Z`Z` ºÕºÕºÕ P)T 8Îpœá8Üänr79x�÷ï5Ü]Ý]Ý]Á<Ä<Ä<f 3…™¾÷Ú¿‡TH$o�t÷t÷tw˜¹kæ®™»`ᜅsÎûóöçíÏë;�äUiŸjŸjŸBRpRpR0<ÿhü£ñ>.|\ø8H¿—~/ýÈ’eɲdpâ<Äy¸yºyºyB­/k}YëK°)²)²)‹“'-N‚¹Ò\i®E?E?E?ÀC õÝÛÿÐW­«ÖŠ÷ï-Þ Å-‹[·„ìžÙ=³{BLPLPL9õÉ©OàAñƒâÅ`gg-7¶ÜØr#4ÍmšÛ4l l l @^]^]^¨Nuªë»7ÿÆ{Œ÷ïO<ñ¤âÏ®­º¶êÚ r/ç^ν a7Ân„Ý€kæ×̯™ÃñÇ޶޶޶УA�=€ûF÷�îAÞDÞDÞDß½ûûHg$’7HÁ–‚-[àƒÍlþ`3\»síε; ë­ë­ë JC¥¡Ò,’,’,’€Câ,hµ Õ‚VðAì±Äê»’E/Š^Á�<à‘Û#·GnPw`Ý�uB· nAÝ‚ æÐšCkÃ]†» wé;õÛKU¨*TBâƒÄ‰àLÀ™€3ð`ôƒÑFƒ×÷^ß{}cÆ Œ� j4¨Ñ@ß©_�TH$o 9ò9ò9r˜_w~ÝùuA|,>ÿâ?N]œº8u�#qGâŽÄA“˜&1Mbô�þÝS–R–R–§N%œJ€–',OXB�yuæÕ™ý ûö7·Jn•Ü*�°^X/¬×wêwXšÐ’’“’“’áˆçÏ#žpßò¾å}Kèt¿ÓýN÷¡Wí^µ{Õ³ fÌ.è;ôŸ'ÉèÖù[ço�‡n‰Ý»%BÞ¸¼qyã~û¾îNÝ�º;Á¾žûzîë ¦ëM×›J_,ÿ˜Ì~™ý2ûÁ÷¿ŸøýDȘ’1%c Œöí9ÚMj4©Ñ$�µ•µ•µÕwZÉïLjcÄ1aaa›¼6ymòÓ»¦wMïÂ$&1 ¨º¥ê–ª[ô�ö�“f”HÞ@µÜj¹Õrƒ¦›^lzñ·¯+–*–*–BLJv|(}ñÿÓž‡={ .x¸à!˜M1›b6¾]ýíêoWƒß!¿C~‡¤/þ7…°YØ,lŸ•>+}VÂü„ù ó êðªÃ«‡oL¿1ýÆâêÅÕ‹«§ï´œTH$o *5«Ô¬RÚMo7½Ýt�M“M“M«xÝa³Ãf‡ÍÐnp»Áíë;í»#Ó&Ó&ÓVŬŠY>W|®ø\�OÆ~2ö“±P¹]åv•Ûé;å›§(´(´(â­â­â­@i«´UÚê/�Õ"«EV‹`‚áà †ÐÊ·•o+_X6pÙÀe!¹crÇäŽúµÿN*$’7X{ÿöþíýÁé¶Óm§Û?˜0;`6T_P}AõúNùöÓÞÑÞÑÞ�]vtÙѪ׬^³zMx_ù¾ò}%}bô‰Ñ' �Ÿ´?i‚kó¯Í¿6¶¬Ú²jË*(­SZ§´Î«çÌóËóËóƒ=½÷ôÞÓ²f5Ìjñ3ãgÆÏ„ï‡?üû᥉ÒDi~¿�ܹ7roÀß=¾{|!{eöÊì•ÿ¸–Ü-¹[r¶oÚ¾iû&غ;tw(D>Š|ùï>¼ûðnˆß¿1~#¤‡¦‡¦‡Âæ™›gnž !º]ˆîïÏõ E E E tvÐÙAgÁÏÂÏÂ϶šn5Ýj e§ÊN•�z}ÛUR ‘¼Áj÷­Ý·v_ð}äûÈ÷~kø­á·Ð>¼}xûp0kfÖ̬™¾S¾ýîÄ߉¿YYY0òۑߎü < < <ÿx;ò¡ò¡ò¡ ýRû¥öKØ“µ'kO”L(™P2áÕsª»¨»¨»@zŸô>é}@]S]S]l²ýÉö'<*xDEDEDE€ÖNk§µƒ„‚„‚„KÄ±Ô Õ Õ !}Dúˆô >¯>¯~ N%”'”'”ÃÍS7OÝ<Ã<ü1¸ tè6ÒìÒìÒì@ù©òSå§`íiíií a3Ãf†Í„ot¼ñü&.ß+ß+ß ƒG 1x¨‡ª‡ª‡Âõˆë×#^ÿöÿ*©�HÞ`&óMæ›Ì‡¦QM£šF�MW›®6]¡‘w#ïFÞúN÷öÓi‚4ApnܹqçÆAë¸Öq­ãÀê¨ÕQ«£½]ËË–—-/ƒÆCã¡ñ€¤â¤â¤bˆy/潘÷ ÿ£ü�ò?‚’g%ÏJžAÌõ˜ë1ס¨rQå¢Ê«øÅ¬ˆY³ŠêÕ-ª ¦ï™¾gút¯Ü½r÷Ê`QdQdQæ×̯™_ã{Æ÷Œï2dÈà‹ /.¼€•WW^]yž‡>} ƳŒgÏ‚îuÿ¨ûG`ºÝt»évx‘ö"íEÄËãåñrxð<ày<ÝûtïÓ½PÖ¾¬}YûÿÞ1QL!qGâŽÄ�ò(åQÊ#(Š-Š-ŠÃM†› 7Aç{�ïu¾ùùù``e`e`f§ÌN™�ÁSð^*À”}”}”} ®E\‹¸«ŒUÆ*A9J9Jù7,wlVŬŠYè0¬Ã°Ãà‚ .,ÕAÕAÕÁ×z(þ%R ‘¼Án½wë½[ïÁ¡ƒ‡:YYYðCì±?ÄB¾s¾s¾³¾S¾½òGæ�Ì )ÝSº§t‡º=êö¨ÛãÕÛz =…ž�ÆöˆíÛÎ9�s:çóGÏ=4DÙFÙFÙÂÔ½S÷NÝ W¼¯x_ñ†‚»w îÂùù9\ùþÊ÷W¾‡‚¢‚¢‚"˜l4Ùh²\™zeê•© s‘¹È\€zÔ£èšëšëšCh�С= Ü4Ü4ܽ½½!óÓÌO3?…Éq“ã&ÇÁõÃ×_? û¿Üÿåþ/aföÌì™Ù K:/鼤3ì­½·öÞÚÿ½ÿª0U˜* R›¥6KmÊe�bZÇ´Ži yòõ7êoÔêyÔó¨çNININIо^ûzíë�‹§‹§‹'ØlµÙj³Ê{•÷*ïõÛq”u“u“uƒgÕŸUV.¾pøÂaz~èù¡ç¡ÇÚk{¬…Sѧ¢OECvnvnvî«ï?s�¹Î\¦ûM÷›î‡Œ3>Ìøð:(ÿ©�HþÍ $ §N)œ�¿~üõã¯aKÏ-=·ô„{Æ÷Œïƒ0[˜-¼4g¹I¢I¢I"˜~gú�éwúîÄÛK~@~@~tÃtÃtÃ@÷©îSݧGÃÈ‘ƒxH<$qÄŒ-6Z Öµ­k[׆ÔüÔüÔ|À[l©˜óög‚¹`.˜vØa÷Rûf˜aö~þ¿©P¡Þã=Þ ( ÿC;Z´h�;ÜáÎKÝ9#?#?ÚvÚvÚvPüAñÅÀÂì…Ù ³!(-(-( æ¹Ìs™çEK‹–-ÁEp\€÷yŸ÷�‡<äáKù 0Àp §ßÆò„æã—ÚïD':�ð‘ð‘ð°‘�läׂS˜+Ìæ£Íh3Ä 1H!…@ƒ �…ÎBg ƒ„AÀ|ÁÀAòò5oSL1aª0U˜ &¶&¶&¶0¼Êð*뀺“º“º(Ú(Ú(Ú€Å`‹Áƒ©(hB %ð ¯—ÚuÇwv »„]ÀG|ÄG@ jP0Çs033‡ .@÷Ðî¡ÝC¡êüªó«ÎúÑ�~`ØÖ°­aÛ—úùe-ÍZšµÊ\Ë\Ë\¡ê”ªSªN6°� ¯õ�üS¤@"ù'e‘EäûåûåûAø©ðSá§àVÜ­¸[qWWW†w ïÞ�:fuÌê˜Á˜ªcªŽ© î;Üw¸ï€J�•+Vü†c·Ün¹Ýr¨ìPÙ¡²Œž5zÖèY`ll¬ïN¿½,'XN°œ³=f{̆ûŽ÷ï;‚—ÖKë¥ýëí·7noÜŒîÝ7ºwÞix§!yyy�y{óöæí!pfàÌÀ™Ù.²]d;u u u÷±îcÝÇBQFQFQäÔÉ©“S’/$_H¾yÃò†å ƒ$Ç$Ç$GH´N´N´†¼°¼°¼0Hþ.ù»äïÀ©®S]§º�R+¥VJ-¸`tÁ肸«ÜUî*È=�{:÷4ÄŒ? &L,˜¹Gs�æ­x\0½<½<½r{äöÈí¥ËK——.×£®G]�¾Ôñ"ˆ1WÌsáyæóÌç™�{8÷pîax¾íù¶çÛ€e,cdœÌ8™q4W4W4W %(%(%²/g_ξ̯SúZo±Þb½¤5Hk�'Fœqbøºøºøº€Ã ‡3Àý®û]÷»¯~&àÎÖ;[ïl—z.õ\ê�ƒ™ƒ™ƒ™¾�Öß’¦–H^‡‘Œd$Ü(¸Qp¢;GwŽî !'BN„œ€è�þŒ6 ¾};úv„Æ¡�C‡BMûšö5íÁä®É]“»ÿ}s¡kBׄ®�]·wÝÞu_]|uñU0I1I1y…ßd$ÌS³§fOÍà»”ïR¾K� A‚€ËX—±.cÿ|{åõËë—ׇ'»Ÿì~²”�”�”�@wLwLw > > �P-¡ZB5(î^ܽ¸;ø6òmäÛ,Ì-Ì-þéqí·Úoµß“€'O u@ê€Ôà‘ç‘ç‘–û-÷[î‡H×H×HWP„*B¡à²ße¿Ë~HÔ&jµ Ÿ!Ÿ!Ÿ F5Õ`(++Ó:Oê<©òRy©¼¼¼¼ zÝêu«×ÙVÙVÙÖ?¿ßÒóÒóÒó`‰Ã‡%0¼öðÚÃkƒïC߇¾õ}”þ–TH$¯â Oxª¶ª¶ª¶÷4îiÜS¸ºøêâ«‹áaÌØ‡1 |%|%| "D4ˆÿ*þUü«€çHÏ‘ž#Áx�ñã5À 1èÏÇ:.tì\µsÕÎU°Äu‰ëW0É2É2ÉÒ÷ ½;vÖÚYkg-ˆ‹‹ƒ™Wg^�y*u¯Ô½Rw}§“¼.ÅÏ‹Ÿ?‡åõ–×[^ì§ÙO³Ÿ㯌¿2þ ç…óÂk˜'áUI—$’?AÜ-îwCòµäkÉ×àŽÓ§;NpËé–Ó-'(ìWد°x™x™x™À˜ucÖ�Y^½z ‹»w-^þ�>ƒ 2ôÝ+Éße@ÝuÔ…´¡iCӆ²´eiËÒ`ʇS>œò!X'Y'Y'é;¥äïR0´`hÁPX·pÝÂu Ak¡µÐZÀÐAC Â,a–0Kß)Ÿô€DòŸSL1úúúà ù ù 9Ìš4?æ›;lî0þ<ü9tºØéb§‹°°Å [@ÐÉ “A'Á¯º_u¿êÿá‹ÿïöóMc¿þ) è{ß=&‡M›†½>ôúÐ ¬,­,­,aîÁ¹ç„'ÓŸL2ÄŸÄŸÄŸô�Vò§-a K .7.7.¾¶ÿÚþk{кiÝ´n0yâ䉓'‚eMËš–5õö¿“.H$€v«v«v+$''ÕW^\ywºßé~§;áB¸Í7;Üì0´ÞÝzwëÝPµ jAÕ��‘�‘�Ñ_þÐ�¡C7®ջVïZ ‹Ó§-N“\“\“¿á¹fÉ_S>¥|Jù”Š g‚KƒKƒK¡Kv—ì.ÙÐò‡eK°œi9Ór¦¾ÓJ~OéÞÒ½¥{á´æ´æ´Ž Ç„c´.h]к†.ºdè0M4M4MÔwÚ?Nº y'ççç½¼{y÷òàòùËç/Ÿ‡$¯$¯$/p3s3s3ƒ÷V½·ê½Uà]Ï»žw=°xdñÈâP›Úü�Íþ)ò~ò~ò~ /——ËËAì(v߀ÕÈÞvF+�V­„¡%CK†–€O3Ÿf>Í`Wý]õwÕ‡;oì¼±zG÷Žî -¾hñE‹/Àì˜Ù1³cúNÿîR–+Ë•åpG{G{G G<�xñ!@à“ÞŸôþ¤74ŽmÛ8„D!QHÔwê?O: y«‰#ÄâHLL„ku®Õ¹V®¥^K½– b ±…Ø …®…®…ªW ® ‚›à&¸é»ÿÝÃF=l;·ìܲs |SðMÁ7`ÚÚ´µik}§“üoÊpe¸2®ö¼ÚójO8±íĶÛ@0 CŒ Œ Œ„fîÍÜ›¹ƒýrûåöË+¦¶•ü=Ä¥âRq)dÿ�ýCöVVVg?9ûÉÙO ¬yYó²æÐùãÎwþgÎ œæC͇šÕwúW'’·Š&D¢ �¸}qûâöA°A°A°< ~ü(œÆ:�u =;zvô¿ý~ôûLš4ô¡}ôÝ‹?ï¡ýCû‡ö°µíÖ¶[Û¢ۋn/ºýæ�’|çä‘G”6-mZÚn¶½Ùöf[8ßô|ÓóM!+>+>+¼&zMôš-ÂZ„µïÝÞ»½wƒÅp‹áÃAÖKÖKÖëÕ㼭įůů¡hfÑÌ¢™mmm 7ÜpcDŒŠ1 ¬[5¶j �K—.©øÅÀÂÊÂÊŠ_çx[H€ä�VšUšUš¡×B¯…^ƒóÎ_8RW§®N] õ×o\¿1tl×±]ÇvPó`̓5‚Á ƒ/ô�þïóÐì¡ÙC3ر1bc,½¶ôÚÒk`ö¾Ùûfïë;�äÏ*¿R~¥ü $.K\–¸ BœBœBœ üiøÓð§P~§üNùp=âzÄõÔQoD½PóyÍç5ŸƒËr—å.ËÁdŠÉ“)€X¼jª±ŸoÚ-·.·.·†dËdËdKˆk×(®V>VBüÙø³ñgÁÀÞÀÞÀê¨{ îhÐ8 1¸7qoâÞŒãŒãŒãôÝ©×O*$o”_V_»ñù�Ïo|gãÏÆŸ��F£Ñh uTë¨ÖQÐêX«c­Ž�ãMÇ›Ž7Š·ùŽ—‡æÍšÃ&å&å&%,Ùµd×’]`6Ôl¨Ù[pªRò?ÊN–�,; ñ³ãgÇφÈÊ‘•#+Cd‡È‘ £ZFµŒj ''µj9Ô×Ö®­][ƒ{ˆ{ˆ{ØùÚùÚù‚eˆeˆe˜]6»lvL L L @î)÷”{¾zÞ¿J7O7O7”¾J_¥/w,îXÜŠ-(ZYƒ³g †x³x³x3x¾ûùîç»!í»´ïÒ¾õõõ°[h·Ðn!ÔîS»Oí>à½Á{ƒ÷¨ùSÍŸjþ¦¦¦úÞ«ú#’§ `äœÈ9‘s.´½ÐöB[¸tùÒåK—Á8Ö8Ö8ºt)èR-´<Ðò˜Ï3Ÿg>OßáÿyRðnÓŽÒŽÒŽ‚bM±¦X‰7$n€ø±ñcãÇBBqBqB1¼Xÿbý‹õPZPZPZbM±¦XäkåkåkÁj±Õb«ÅP¹såΕ;ƒU«V ÀÌÛÌÛÌÌvší4Û &·Ln™ÜC�¡ÆP²ë²ë²ë`0Ë`–Á,�ÇÉãäq ê ê êšMŒ&TkTkTk@iª4UšBé´Òi¥Ó D[¢-ÑB�G�G�ä�Ï;Ÿw ´Ú-h/k/k/W¹ÊU0™`2Ád8…9…9…�[°[°[0Ôì[³o;PýVõ[Õo�e?Ë~–ý@þBþBþ�ñû»¼Å¿IÞ(%”P/¾øb œË?—.n,»±ìÆ2°›b7Ån ¼÷Ù{Ÿ½÷44hhÐÐL½M½M½o¼ñÖw'ôG,‹ÅbKÅR±8ÊQŽê;•äŸ"ß&ß&ßVXaÔ§>õ�ú?Õÿ©þOÀMnrʋˋˋ¡xTñ¨âQPÔº¨uQk(”Ê å�Q'£NFȨŸQ?£>*÷}îƒ������¾ÓÿûG…£ÂQÔ‚ZPókA%‘à�?þ`„F€Ñ£;FwÀk¬ÿ¯ÏMe*Sÿ�×ÓH# È$“LÀgœaÑÕEW]×f®Í\›Á�à!ÁC^^”*Ž8þÌ5öŸWýc8îïÁ|{H€äŸñóÝõ)Y)Y)YpìÖ±[ÇnÁ�Jw*Ý©µ'ÕžT{|üEðÁàYìYìY ²²²úÿ律©˜©˜ +…•ŠŠeTÇ2–¿°�Dò‡8âˆãK®`+ÀØÙØÙعb"$zЃú+ùߤ@òZ¥ú§ú§úÃÉè“Ñ'£áæ‡7?¼ù!xzzÂôƒÓN?žåžåžå ÷‘ûÈ¥ßðÿ¼}ìc�N:éÀZÖ²Vß¡$ï*Ãñ†ã ǃR§Ô)u¯Þžäõ� ÉßcÓ˜iiipzØéa§‡AÈŠ�!+À½£{G÷޵ïÖ¾[û.È�åÆrc}‡ ¤’J*¨W¨W¨W€ØFl#¶Ñw(É»ÊÄËÄËÄ òîäÝÉ»£ï4’ß#’¿æ—¸¹µrkåÖ‚“‡N:y.�¸tâÒ pmîÚܵ9L¾7ùÞä{àÓÞ§½O{�í•í•íÕwø·Pe”�v§v§v'ЉNtf0ƒú'y×Xܶ¸mqR¦¤LI™¢ï4’ß#’?¥8¢8¢8.TºPéB%8p*àTØæÚæÚæÂ§?=øéAðžî=Ý{:Ô4¨iP8ÂŽè;ýÛOð<O µ¨¥ï4’w•¹Ü\n.åYåYåYÐÐÐÙYÙYÙY}§“üB*$ÿ§òíåÛË·Ã-Ý-Ý-xhà¡� [ [ [#"GDŽˆ„f×›]ov ;v4”¡ù版ˆ/ý)‘è‘yºyºy:(/*/*/‚æ´æ´æ4bˆ¡¾ÃI~%’ÿ�h&š‰f•••»“v'íN‚Œ°Œ°Œ0è5²×È^#¡½{ÿöþ`jbjbjt¤#Ò¿þü2Õë/wc ú%yWçç為™º™ºhghghgÛØÆ6}§“üB*$¤þ”úSêOpðãƒüîͽ7÷Þ\° ° °…Ï ?+ü¬¬eÖ2kÒc=ÿ2ò™ò™ò™ < �A,ËÄ2}§’¼« 40hºÛºÛºÛ i¤i¤i¤ïT’ÿM*ÞQ¥ãJÇ•ŽƒsCÎ 97Žõ?ÖÿXð¸îqÝã:|¥ùJó•ܹ/r_ÄŸD¢W²š²š²š MÐ&h|ðT¨Pé;�ä]cð™ÁgŸ�î¹î¹î9hnininé;•ä“ €w„ØDl"6�G)�R¥À®â]ŻС¬~Yý²ú0ÎiœÓ8'hr¤É‘&G@ž.O—§ë;µä�ª Õ„j@;ÚÑÄ=âq�¾SIÞU†] »vZЂ =¬=¬= |ÄG|¤ït’_Èô@òze©²TY*X×v]Ûumae핵WÖßk¾×|¯Á· ß&|›Ík5¯Õ¼–ôÅÿ¦’»ËÝåî .Š Al+¶Ûê;•ä]¥(V+ŠA×B×B×´*­J+�‰úבμeÔÛÔÛÔÛàºêºêº ö$ìIؓՖV[Zm)Ì�›77ÜÝÝ�e,c™¾SK^•pD8"m=m=m=*»”¿”è�b•b•bˆ·Ä[â-Ð\×\×\×w*Éÿ&oºŸ'€yqòÅÉ'aÇ¥—v\‚øVñ­â[Á�Cn ¹múµéצÔ0¨aP¨A jè;¼äï"/�È @/Œƃ¨¢ô¯[¢' #…‘ÂDÑF´��ÎGç”RJ©¾ÓI~!ýñ†R7V7V7† Á‚/þFûík>¶>¶>¶°°ÓÂN ;�}ª}ª}*P…*TÑwjÉë"L& “Aã¦qÓ¸2dÈøíò¨’¿&’H"AtÝD7DADÀ 3ÌôîßGá¯ðWøƒ8H$M²&Y“¬ïTÿbPP1�‡�/ä ù€+®¸¾¾ÍJ÷¼)®r•«�Z%µJjX¼cñŽÅ;àˆ÷ï#Þ0fܘqcÆÁä�“wNÞ öeöeöeH_üïY�¬@V2™ƒÌÄiâ4qš¾S½ùÄâ q\zýéõ§°¢óŠÎ+:Ó3OÎ<9S±öRñáâÃŇA9C9C9âÓãÓãÓ!«0«0«Pß½øç8àÚ�µk?Öwªß§j¡j¡jÏ­ž[=·‚ÔC©‡R{ØÃßp3mɘ’1%c %$%$%tótótó*^8îḇã`•Ë*—U.pÛê¶Õm«×ßo©ø—Ӟממ‡óUÏW=_fžyxæa0ŒcÌZ0kÁ,hy¾åù–çA¾E¾E¾Eß©%ÿ4ù ù ù LÁ444ô�꟣٨٨Ùb�$ý}í¦nNÝœº~üàÇ~üêß«¯þ=�GÈ#ä°"kEÖŠ,M M Me±²XY ‹Ú/j¿¨=lk½­õ¶Ö/å\¬Y¬Y â2q™øß{£h¬h¬h еее tV:+�õ�ê÷©ÜTn*7Ø:b눭#`aû…í¶q¢8QœøêíßßpÃý °üÈò#Ë�@éÒÒ¥¥K¡xHñ�â!°Åw‹ï_p‹u‹u‹››67mn¾þ~KÀ¿Tî¹Üs¹ç`ÍÍ57×Ü„½óöÎÛ;Þ¯ñ~�÷kÀ”€)SÀöcÛ�mÿÅ•µäŸ!dBˆ‡ÄCâ!ÐZh-´¯‹¾¢¯è t£ݨ¸4Кִ²È" XÊR–[ØÂË…äArÄ®bW±+ˆ;Ä⎗>÷ó*>á>>æc>~i»½éMïÿ¼�B A<%žO�8Gœ#Ί)¦˜Ë\æR±¼q $T|¼À§À§À¶ÚnµÝj ™ù™ù™ù/µM4ÑÀ—|É—ÀINr˜À&ƒÌàß׬#YG²Ž@òÆä�ÉÁûï¼?�Ù³=fÔSLYMn5¹ÕäTY[em•µ`W`W`WªpU¸* ;v,ì[Ÿm}¶õd�Í›5ö¥ ýÜ_ñ xP<â"q‘¸ˆ_ïñùuQ§�ld#C 1Àp†3\ßGßo)T •B†‹ .e]e]eÝ¿qa„âdq²8¹âO 'H$‘D`"™œãç@üLüLü ıD,©hÎüGóÍ—h—h—h(³(³(³ÑD4M€›Üä&ÇÑÏíDAT,¾¥D‰ò·q}ý|ý|ýàs«Ï­>·³‹fÍ.Báܹ…s!Ö1Ö1Ö<'zNôœ5»ÖìZ³ë?°Ÿ^ÿ&$„ø¹ø¹ø9<²~dýÈ6>Øø`ã°ûÊî+»¯`þ²ùËæ/''' ‡rô�Zòo¡°TX*,Aå¥òRyÁ⹋ç.ž 111à|Þù¼óy(]Yº²t% m0´ÁÐðXóXóXçÖŸ[n=ÔÛ_o½ý`|Êø”ñ)èÙ%²K$œ?|þðùÃ�r#åFÊ P?V?V?††‰ &Bã³�Ï6> k�­=¶ö”*K•¥Jpöröröe�2HC͆š 5»»»íÚ-´„ 9rtWtWtWÀÏÚÏÚÏjd×È®‘ ßµú®Õw­ fÝšukÖÝÝÝ(1*1*1‚]Mv5ÙÕtgugugAQ¨(TÂýÈû‘÷#a‚÷ï Þ`gegeg;Gî¹s$´Ö´Ö´Ö@SšÒô¥ñ,;Pv ìÜ^}{õíÕ�P?¡~B}8}"úD4´Ñ¶Ñ¶ÑÂþo÷»ÿ[ð|æùÌó `<ðÀtOuOuO!¸,¸,¸ 6´ßÐ~C{������€þ7úßèž.xºàé¸iqÓâ¦EÅ:MO6=Ùô$¸p=àzÖE®‹\ µ¢kE׊]¨.T íÆ·ßn<WWWƒO7Ÿn>Ý }¿öýÚ÷ÓÃñè¥ðRx�Áƒ%K ô‡ÒJxõvµ×´×´×àbÝ‹u/Ö…˜Ø˜Ø˜XÐÓÓh³ýÍö7awûÝíw·‡¤o“¾Mú¼“½“½“áa¯‡½ö‚¾ñ}ãûÆC£Ñ�F7 Ô¡u€œà\)»Rv¥ öÞÝ{wï]î7Üo¸ÔŸ[ný¹°«Î®:»ê€G”G”Gt2édÒɤ"¯øX|,>†‡=zÀ±-ǶÛúðЇ‡à‘æ‘æ‘G'ŽN]QŸV]it¥Ñà´Õi«ÓÖ×·Ÿ¤3z¦j«j«j {Oí=µ÷,k´¬Ñ²FÐvwÛÝmwÃŒof|3ãpÚæ´ÍIšC[ò{F1ŠQ`nenen¹.¹.¹.PæSæSæC[m9´%dª2U™*Ø›½7{o6ØØØÀµ×V\[Î}�û:÷�R�R�R¸réÊ¥+— 8"8"8ú'öOìŸí¶Øn ¬ÿtý§ë?…4¿4¿4?(½Vz­ô”÷/ï_Þ†Œ2fÈHÛ”¶)mìÕíÕíÕAŽyŽyŽ9¬>µúÔêSÐdz“éM¦C@Ç€ŽaݲuËÖ-ã×3ñ#âGÄ�€œs9çrÎA“ M&4™žÏ=Ÿ{>‡J#*�¨4º„w ïÍ5oÔ¼DäDäDä€.@  aŠ0E˜S ¦L…µjÔªñVM4`<Àx4¨Û nƒºà˜í˜í˜ Äb< = = ¡Ð±Ð±Ð"="="=^jà/xŠjŠjŠjàVÓ­¦[M¨´µÒÖJ[¡ÓG�>êô(W)W)WÁšëk®¯¹þ{ý÷úï…æ½š÷jÞ ÖM\7qÝD�ûÈ}ä>»0vaìBÈ÷È÷È÷€F¥�J•‚áxÃñ†ãÁæ‰Í›'`þØü±ùcýŽò=ò=ò=`nnʡʡʡ¯ÞnxëðÖá­a÷ÒÝKw/…n3»Íì6z�ì=²÷HØscÏ�=7 <*<*< D;ÑN´ƒçKŸ/}¾ºî뺯ë>0»fvÍììÙ²gËž—Ïtý|æ@è&tº�—»—»—;$&'&'&Cɺ’u%ëÀÀ×À×À4Aš Mx–y–yþ‡©·ÁGð�ªšªšª¸{ôîÑ»GA¹V¹V¹Z6´lh öþöþöþN»�v;í~ýûI*ô$#:#:#–”-)[R7Žß8~ã8|øEà�0`Ñ€E�Ñ£=FÒŒn’ÿB¾C¾C¾ä)òy ȳåÙòl0¼kx×ð.XDYDYDA­ãµŽ×:‘}#ûFöyGyGyG0?c~Æü xyyAýÚõkׯ �>„*ŽU«8‚}eûÊö•Á³À³À³t™ºL]&¿øü"T›VmZµi`kkkkkûûãjǪ̂™Q3PÜWÜWÜÓOL?1ý¤âuÅrÅrÅr�­”­”­|éƒ4høõRˆÁ"ƒE‹@¥ˆRD�Ù³ f ûtöéìÓðldzÏv@†o†o†/¤þ�úCê�n–n–n¥{J÷”Fs�æ‚ëc×Ç®�¡arÃä†ÉPÕ£ªGU~{øíá·¡éܦs›ÎÕ÷Q † ¥Z©Vª_½½'gŸœ}rOOOÁ%Õ%Õ%ªÇV�­ VÍ­š[5‡u„:B F+ŒV­ƒï ¾3øÌ›56k ö�í;Ûw†‚Ž ^^ÄL�50†1ŒÇ8Ç8Ç8èØ!°C \޽{9’Ì’Ì’ÌÀ*À*À*܌܌܌~?·ÁçŸ|òEòEòE ;,;,; FFF X¬X¬X ¦íLÛ™¶Ê)§üõï©ø‡=r}äúÈæ„Í › �B£ÐÀ¼çóžÏ{>‚�à#Pq­I"ùdr™\&äÈ‘ƒÚMí¦vÁOðü*Þ§¤¤2s™¹Ìœ_OUÿzîñ9Ïy^ñ~!GÈr@œ+Îç¾´Á<࿞*e?ûÙOÅsÞ`Pñv]]]�9ÊeŽ Æ‰qb‡„CÂ!�M–M–M»Oí>µû¾îõu¯¯{�3Î8º*º*º*À)Nqê¥&˜`¯ÿaÿr×¾¼ª¼ª¼*tìÞ±{Çîpkõ­Õ·VCÈœ�9!sÀ¯¯__¿¾b€×߬²øËÏ+Q‰J/ï�Ÿô +@‹mÅ< xâ‰'pžóœÙMÙMÙMüÁo:Þt¼ _¯ýzí×kÁ±¾c}Çú ö{Š=�`‚ ~i{¿¬ù/cxÅðŠáPå¨rTÃ%Ká¾p_¸ç8Ç©8^¾Eœ%Îg�*„ ¡@ %”ðÛÇ5(P]èB——7ðóþ� ‚ˆŠÇñÚ´7ho±«bWÅ®‚ã-�·<Þ|úô=$“ÌyÌñ—ÆcLÅs¿G¿7ÿ©xÍ4�5�5�áø�ãCŽ�e¥ËJ—•B‡>útèSã¦ÆM�ëöÖí­Ûë;­äM%L¦ Ó@HR…ÔŠÇË¿/ÿ¾ü{ÈŸŸ??><-|Zø´=iô¤ÑÐ\Ò\Ò\uœ:Nå-Ë[–·¬h×w¿ï~ßý�šš iSÓ¦¦M…¨…Q £‚¼º¼º¼:xxx€vŽvŽv”RþIù'�ß)¿S~'xzüéñ§ÇÁ_|»Fv�ìAõ°êaÕÃÀ,Û,Û,72nd -:µèÔ¢SÅõlõlõl(S”)Ê^ºsI>K>K> ”�Ê@e dŒÏŸ1´Úmø÷?îÊÍÊÍÊÍ ³[f·ÌnP5 j@Õ€ÿ>®åVåVåV š š šeš2M™¦âuÕPÕPÕP(__¾¾|=ˆ¡b¨ ª«ª«ª«P¾µ|kùV~½¶\]] éõÒë¥×ƒJ³*ͪ4 \» v ���ÐhT£Q�F�ÿuÿëþ×Áà ƒ/ ¾ÕNÕNÕN(ËÄ2±"GYRYRYlÿxûÇÛ?†[é·Òoý ¦ô6ênÔݨ;”'”'”'¼z{urêäÔÉõ9õ9õ9Hü<ñóÄÏ!þTü©øSPغ°uakðñ÷ñ÷ñ‡²Œ²Œ² PY¨,T N'ˆ@=Z=Z=Ô=Ô=Ô=@×U×U×Tö*{•=”ï,ßY¾TóTóTóÀ'À'À'¬s­s­s!jEÔŠ¨P£¨FQ�¢?pe–g–g‚º¥º¥º%”=*{TöÊ–,?êTuª:”­”­”­þ¹ý#Ÿû³n“ˆ’ˆ’زj˪-«àêÌ«3¯Î„O">‰ø$Ú·nߺ}k�/–/–/ÖwZÉ›N£Óè4:¸xìⱋǠئئØÒz¥õJëª*ª*ª*`Ó̦™M3è¿·ÿÞþ{!>->-> ² ² ²  Æ®»jìª8E^-¨ZPµ ²„,! nO¿=ýötH,H,H,€=z@Ó¦ Lár�Ë=.÷€ÇÓO<T6*• ؅؅؅@¿õýÖ÷[Ö3¬gXÏ€j[ªm©¶n»Ýv»í±Ç~û1(((]éJWˆ½{-öXåXåXå€ÏG>ù|fß™}göä ¹B®Ï<ðlxL÷˜î1lfÛ̶™ Ùk³×f¯_C_C_CðÜê¹Õóÿ¸¹J³W³W³×â^ È/É/É/çSΧœO�ì¾ì¾ì>D­‹Zµ®âR�åTË©–S!) ) )Œ��¡^ïz½ëõ†òŽåË;³Üg¹Ïr¡¡sCç†ÎP›ÚÔn)o)o)!Î-Î-Πʋʋʋ@¼/ÞïClnlnl.Tº[én¥»P×½®{]w`! Y!!!!!!`ýÜú¹õspëîÖÝ­»þŽËÐèÐèÐhP„*B¡à;Ìw˜ï°¿ÞžÝ»v#Àò¶åmËÛp+þVü­xˆ™3#f´QµQµQA“†M6iÔÔÔ ,–KÀc�Ç �Aû0öaìCN §…ÓPíLµ3ÕÎ@üœø9ñs@|$>�W W W Tq¨âPÅJÊKÊKÊ¡ª®ª®ªšŽm:¶éØßϫ֪µj-<Úøhã£��õ ëAÖ°_l¿Ø~1,:Xt2r2r2rÀ6Æ6Æ6Ü» v C…¡Âð5î Qò·J–>,}˜(Îr�å:ËU§)¦)¦)D1iaÒ¤…úN'y[•þXúcé�¢8)uRê¤TQì?¯ÿ¼þóDñËõ_®ÿrýKo<'žω¢¨Õ¢Zÿç±;QŸ‰ÏÄg¢ø?ϧ‹¢¨µ¢ö¥Ï%ˆ b‚(ê”:¥N)Šbg±³Øù·9æ,›³lÎ2QœÝuv×Ù]_zá‚xA¼ðt`¤8R)ŠºKºKºK¢(¶[Š-EQü^ü^ü^Åóâyñ¼(Š[Å­âVQŸŠOŧ/}>ULSEQ·N·N·Nó{æ÷Ìï)Š9ßå|—ó�(îè¿£ÿŽþ¢˜µ,kYÖ²?0 ™b¦˜)Šâ8qœ8Nÿç’…(þÏãf/�Ó:q�¸NÅ`1X Eq€8@ Šâfq³¸ù¥Ü¿¼þKÎR]©®TÅ‹âEñâKÛ"‡ˆ¢î²î²î²(þÏ¢N/mç’xI¼$Šâ&q“¸é¥\ÿRë²Öe­ËÅõ ëÖ'ü� çˆ9bŽ(ж¢­h+Šbu±ºX]¬8®“Åd1YÅÅâbq±(бb¬ûÒ¸-—ˆKDQLÅDQüŸK\¢(Îç‹ó+6SàPàPà ŠE׋®]Å“Lþ1Y[$¶Hlñrf‹Ùb¶(Š£ÄQâ(QcÄ1FÿçR…øëþ£Ä(1JÅ)âqÊK¹^3á—¿¼Æã�+'®œ¸r"Ôú¾Ö÷µ¾‡± Æ.»,šY4³h¦ï”’·•ÆKã¥ñ‚W~¸òÕî¥î¥î¥°äÓ%Ÿ.ù¬+YW²®ô÷o¿´yióÒæðY¿Ïú}ÖÔÕÕaiêÒÔ¥©P¥s•ÎU:ÿa�=ö°|ÙòeË—AùöòíåÛÁÿÿü€65ÛÔlSóÈ!`ã��6U†*C•“&Mš4i’¾Sýq[?ÜúáÖ!ùjòÕä««¨v?×ý\÷s †Cô�ò¯“ €WtëÀ­·À¦I›&mšÊ:”u(ƒþ»úïê¿ zô4è©ï”’·�x\<.‡eÊ>”A»¹íæ¶› ~þ~þ~þàø“ãOŽ?�Q¶Q¶Qöß¿}õQõQõQHù,å³”Ï@w@w@wœ—:/u^ F{�öíýçÆ#y_ò¾ä} z¤z¤z®m\Û¸¶EGEGEÇWn^òmóÛæ·Í â â âarîäÜɹúNõÇe8e8e8AA³‚fÍÀÕßÕßÕŒ‚Œ‚ŒþÆ'õE*þ$]ª.U— Á;ƒwï„ýyûóöçÁ°ãÃŽ;�~ø“„IÂTéJÞp}éK_˜ü|òóÉÏ¡ß÷ý¾ï÷=4 hÐôÕ›—HþŠ]»"vE@zrzrz2|Þåó.Ÿwyõv%i&À?H3T3T3ö¥îKÝ— çýÎû�÷ƒI�'užÔ/n¼¸±t3ŸD_ZÒ’– ˆWÄ+âA]K]K]ëÕ›•H^…ÁrƒåËAc¢1јðÛÇî$z%=ø_¨òTyª<ض|ÛòmËáºÑu£ëF0k÷¬Ý³vCãö�Û7–ß“è[sšÓqŠ8Eh>Ó|¦ùLß¡$ï:Å"Å"Å"ÐÖÖÖwýS�Q�Q��Gmx´ntºÑéF'PG©£ÔQ½]1RŒ#!eRʤ”IpqèÅ¡‡Bæ€Ì™~ÿsRð;”˔˔Ë`ãÌ�37΄ðKá—Â/Á¬u³ÖÍZ©©©úN)‘üì—ÀZa­°õgêÏÔop ^¡^¡^« V¬æ×õÒ%oƒÍ› 6ƒúõê¿a-€7�<@ €è:Ñu¢ëÀ7Ý¿éþMw(Ñ•èJt¯ÐðÏ˾k{i{i{Áâ‹O,>÷Ýï»ßwÿý�IÀÿRêQêQêß¹|çò� Ä÷�ïßfÎ œÕ<ªyTóxõíH$¯ƒÂEá¢pÍ6Í6Í›¸vD!„ÀÅ�7^Ü»fïš½k6”~PúAéPÒ§¤OI(¯Q^£¼”®+]WºJ_”¾(}%MKš–4�ŸÎOçªÆªÆªÆPbRbRbºÑºÑºÑ›S/S/S/ƒ‚ü‚ü‚|P.T.T.³é’Þ+355…²Ø²Ø²X(®W\¯¸*:Tt´Ú m”U*«TV Jw”î(Ýb (‚rµrµr5”n-ÝZºðÁÍD3Ñ Š2Š2Š2 ð‹Â/ ¿ÍÍÍP+Ô µŠeŲb%%%@aRaRah§k§k§ÿ6¯*S•©Ê„‚'O ž@Y½²zeõ€Ílf3”Û”Û”Û@qJqJq ”l.Ù\² C C C@k¯µ×Úÿ¶Ýò�åË7B¹¶\[®…*¦UL«˜‚l‘l‘lP�jT«xYµ²jeÕ  ¬ ¬ T·T·T·~Û®®µ®µ®5�/_<,FYŒ²ÆcŒÇ�.r‘‹¿¿¤{~V*+••Ê`Ýüuó×͇ܒܒܘi2Ód¦ ØÚÛÚÛÚ¿úv$’×IñXñXñÔÕÕõ�æÏ+Ú\´¹h3ìY°gÁž�×9¯s^gp?æ~Ìýœ~þùùç`8Ìp˜á0pŠuŠuŠƒÓ§ Nõ1ׯ\³—Ì^2{ ”Ô+©WR–å-Ë[–sWÏ]=wuÅâ>[3·fnͱ¦XS¬ …í Û¶ƒÁ™ƒ3gBí/jQû }�ʛ˸̸̸ ®_¾ k¾\óåš/A8#œÎ@�„ = òRä¥ÈKpîÇs?žû–*—*—*!x{ðöàíp±ëÅ®»ÂÊ¢•E+‹à’Å%‹KpÏþžý={0³7³7³‡æC›m>Ìæ™Í3›_ŸøúÄ×' CË-;´„üÜüÜü\pÒ8iœ4ðþñ÷�¿rçäÎÉ�;vìØ±cȼeÞ2o(ú¢è‹¢/`„ÿÿþ~7ünø]Ø×g_Ÿ}} ß¤~“úM‚;�wïB��uÖ£ÊG•�*‡ÄQ‰£GÁnÃ݆» Áº—u/ë^�\š\š\ º…º…º… //Ñ÷¢ïE߃6lØ€Ée“Ë&—AW_W_WÆN;iì$0{nöÜì9ìž´{ÒîI�^7½nz]°¹osßæ>d—e—e—�ÐJh%ü3 ¾ógJG•Ž*ßýý×ß ùyùyùy0­Ù´fÓš�mÛ¶=ô�R"ùcäéòty:h¾Ð|¡y¿¸,¶[l·Ø® ® ® ÐàLƒ3 Î@—¡]†v fáfáfáP¶°laÙBè¥ÿ•þW mö Û6„œ;9wrî€ò¡ò¡ò!Ô «V+ rkçÖέ å¥å¥å¥pÆåŒËH8�p áLž3yÎä9`qÚâ´ÅiøIñ“â'é×£WfXÓ°¦aMÈMËMËMƒÞ ¼xè’Q%£J ZZµ´jiP½kõ®Õ»Â‹e/–½XŠDE¢"Üû¸÷qï)gSΦœ•N¥Sé`o�½=ööÛ5¶kl×À>˜ðÁ¨¥©¥©¥�ª%UKª–@qIqIq ´ÛÔnS»Mð~»÷۽ߎE‹8±§bOÅž‚Ÿžøôħ�Ñ8£qFc˜ÒkJ¯)½@öPöPöm=´õÐVpã8Æq øøøB§ÜN¹�r¡ãÔŽS;N…ã#Ž�8> ³ ³ ³`‹Ù³-f`°Ú`µÁj˜ØgbŸ‰} k·®ÝºvÙ²d?Tœºß:j먭£ÀîžÝ=»{ðé„O'|:¢ò¢ò¢òàú{×ß»þ„Î �:N+N+N+àƒ ø`Œ 42¨bÙkq˜8Lü?f^|g €²€²€²øa÷»Ø =3zfô„©6Sm¦Ú@•ÚUjW©­ï”ÉŸc`e`e`ê/Ô_¨ßÀà a†0„}Â>aßK?o+´ÚB%ËJ–•,Áé¬ÓY§³`Öþ¬ýY –XbAø^ø^ø˜Ît¦ƒ&„ a ‹•ÅÊb!Î3Î3ÎRV¦¬LY GÝŽºuƒ”å)ËS–CqŸâ>Å}ô= o>í†[ ·‚B©P*”°êÇU?®ú6uÝÔuSW(P: t΂³à B±P,#ÁV+„‹òÈmå¶r[è4¬Ó°NÃàX±„c °Èe‘Ë"È”3(gAB�B¡ŠP+ÁJ°F #…‘�}9ûröeˆk×8®1¤K9–r Ž <�2:et‚bm±¶X L`@¨*Tª‚ì‘ì‘ì˜6l>T'U'U'AÝ_Ý_ÝbÖĬ‰Y^ݽº{½<%ó/‹Zbˆ!hkhkhkÀÓNO;=íñÆñÆñÆpl䱑ÇFBÉä’É%“+–Ž·ˆ·ˆ·€Jç*�«tl"l"l"€‰Ld"Ð�ntT¨Pýþþyç U *P›7%nJ„”ð”ð”pøÜþsûÏíÁzºõtë鯼‰D/äåòry9hvivivé;Í+0Çs~ûØØ/Ëì¦�BÊK?ÿeµ_Veûåõ_V[k@T¼ndidid ‰‰‰Ð¸Zãj�«Á'Û>ÙöÉ6˜<#xFðÌ*ù}7¹ÉMð_å¿Ê,ÈZ�µ ‡‡?ìýaï{A˜)ÌfOx ˆ"ЍØè@‡ŠÕ{ïソ÷~øáô§8 º‘º‘º‘ðíøoÇ;Ôaê0uÝ„nB7z ½„^ ½«½«½ ÚõÚõÚõ`tÏèžÑ=0r7r7rÇcŽÇ�Aã��76ÞAãƒÆ�‡)_MùjÊW ‹×Åëâ�Á f0àˆ#ŽüºŒ°°_Ø/ì¯è·b�b�b ¨}Õ¾jß—ÆE‡ЛÞô®è¿é2Óe¦Ë FíµkÔ†¦«›®nº—,.Y\=?êùQÏ�@øHøHø4-4-4-€žô¤'«NÖj µ�6´¡Íïïžw¦ÐžÒžÒž‚]ówÍß5bZÆ´Œi Ÿ›}nö¹ØÙÛÙÛI×ø%o8sssP�T�T�Ôwš¿Î¼�y;óv�p%áJÂxfýÌú™5–––@þÒü¥ùKA}V}V}  4¦Q¦Q¦QÝ#ºGtH“§ÉÓäPæQæQæQqÓX³ðfáÍ¡|iùÒò¥�ý(ûQö#P|¯ø^ñ=˜Í0›a6Cߣðæ“Ëä2¹ ÊN–�,; f7Ìn˜ÝÏ®ž]=»‚±¹±¹±9˜u7ënÖ´-´-´-àé¹§çžžƒì�Ù³BÙó²çeÏ¡xgñÎâ�°ÞþyûçA¹u¹u¹5x}çõ�×w`QÉ¢’E%` jGµ£Ú’…d!Y€«^W½®z�Óh§ÑN£Á}‹û÷-ÐlH³!͆@‘Q‘Q‘äzçþ?öî3.Šsÿûøg KïÒTŠX°#Fƒ{ï=ökb/±%±ÄKìF�=±E,X£ÆŠ‚Tªˆ´¥Ãî^÷ƒCîsþ9'‰e�™÷“äå3ß¹fa;s•ê™ÕÁ Ð Ð LË™–3-ê½ê½ê½PðEÁ_@n@n@n¨W©W©WAþ©üSù§ ärÉå’ËÐ( Q@£€²ccïÅÞ‹½iîiîiîPx¾ð|áy(ñ+ñ+ñƒ——HP$(Px´ðháQ0Œ3Œ3ŒÕ^Õ^Õ^¨y¼æñšÇ¡È¿È¿È.n»¸íâ6H8–p,áäßÌ¿™ríríríþËõyïWôÇ82ôÈÐ#CáböÅì‹Ù03jfÔÌ(pä2Èe�¾CJ$¯Ç­�·vÞÚ Zc­±Öü>ôûÐïÃWßïÛæXѱ¢cŲ?�ùwòïäßë¬?°þ?rüÈñ#¨t¥Ò•JWÀ2Ð2Ð2\æ¹Ìs™Ï;>ïø¼#ÈkÊkÊk‚“¥“¥“%x¬òXå± êµ¬×²^K°¶²¶²¶‚˜ó1çcÎCŽOŽOŽXl¶Øl±,{[ö¶ì­ïÖøûʸ”q)ã:t̆˜ 1å]Ë»–w…n³ºÍê6 œ69mrÚVQVQVQ�®MצkÁèK£/�¾×X×X×XðZäµÈkˆZ¢–¨1³cfÇÌÕ÷ªïUßC_u_u_5÷5îkÜv?Øý`÷p¸ãpÇᤤ¤B‡= ü�òwÊßwCwCwC0ÿÖü[óoá‘í#ÛG¶�{"÷Dî 0�4�4�„<§<§<'°Þe½ËzT¬[±nźPèYèYè 666à½Î{�÷:ø`ÉK>XŇŠ‚¤ÝI»“vƒj j j ¸7roäÞ< = = ¡Aå•T.{Dý$ïIÞ“<( * * ‚r.å\ʹ€{5÷jîÕÀµ·ko×Þe«.\8\ \ \ ÊúV¸-u[ê¶d­e­e­s�ÞüzCúuúÀé§1¨dPÉ !î=½÷ôÞS}§’HÞŒÍY›³6g ±ºduÉê}§‘üÓÝ1»cvÇLˆ1ÆcŒÇ ‘¿+Wþ®7ÜT×T×TW!šWm^µyU!¢vFíŒÚ©ïÖx÷¼·�Â… {£öFí�‚ÑõG×]ªºUu«ê¦ïtÉ›aàmàmà š)š)š÷`±Éß›ÜQî(w„-{ B#4Bóæ�w#îFÜ 0ªnTݨ:Ä,‹Y³ xÈCê»UÞï]�°3agÂNøfú7Ó¿™= ÉûB»K»K» bRcRcR¡ÀºÀºÀ^tyÑåEx1鍓à¶ÏmŸÛ>`]ǺŽu°TX*,à¡ñÐxh@v[v[&�Özkd/'Ðw�ÿåâõ‹×/^‡]�wuÞÕ6\ØpaCp9ìrØå°¾ÓI$oWÜ�¸!qC ÷ÀÞ{„yŠ Éû¢xañÂâ…0ÅŠÿøÞú{ëï­ùµÓŸZ£Ö¨5`ñÂâ…Å �)ÿRþ% 04>ßôù¦Ï7éû,þyÞù;é½Ó{§÷†Ý‹v/Ú½zMî5¹×dp™î2Ýåo¼Ú™Dò*»8vqì^ /…—›†7 oúŸÛ½\SÅþKû/í¿„ê?Wÿ¹úÏúN/yß~fø™ágP3©fRÍ$øÆüóoÌAg¥³ÒY•mWH!…€é Ó¦7À¹ÿr©O€Þ¼³�uÏtÏtÏ`Oñžâ=ÅPÞ·¼oy_h6¡Ù„fô�N"Ñ/ÓΦ�M;CËî-»·ìF³�fÍþýí[_o}½õu°km×Ú®õ?ŽDòg4Êi”Ó(<£<£<£~»*Ϫ<«ò üúûõ÷ëÿÇ÷/y½ÞÙàú¡ë‡®‚ˆM›"6Áàùƒçž*c•±ÊXßé$’wC¯&^M¼ ü�ò7ÊßøÏ×-²-²-²¡…e Ë– ?(?(—žýKÞ/ / / ð{â÷ÄïÉïo×rRËI-'�ý9ûsöçô�úŸë�+òÖç­Ï[{•{•{•Ðåj—«]®‚ÛL·™nÒòœÉÿÇm±Ûb·Å���ÿŸ¯×ø©ÆO5~‚ÚvµíjÛýùýK$†²¼²¼²Ï}POQOQO¡ïpÉ[vƒÜ€Ò€Ò€Ò(xPð àw)îRÜJJJ ¤SI§’N Ù£Ù£Ù¥.¥.¥.àìì ÚkÚkÚkPâZâZâ "D>ˆö°‡= ðWø+üÁ šA5ƒj Z­Z­Z ªUŽ*Œºu5ê Æ:c�±”^J/¥P›ÚÔÖw#IÞ6ííí(U8ªp-.Z\´J®”\)¹%ÝKº—t‡RãRãRc-EKÑÜ"Ü"Ü"Àº¶umëÚ`?Ý~ºýtxhôÐè¡èt º„²5[”½”½”½@µFµFµTÇTÇTÇÀpšá4Ãi`l`l`l†+ W®.q‰Kún�¿/½qÇ}÷1ÜŒ»w3æ.œ»pîBP4R4R4Òw:‰äՈꢺ¨źb]±rúäôÉé‰!‰!‰!�Ü6¹mr[H K K ƒôaéÃÒ‡Af~f~f>‚˜'æ‰y€:ÀSL�êT§:ÈêÈêÈê€Á×_| ö‹ìÙ/‚}>û|öù€¸%n‰[@8á„S¶hP6Ùd5©IMà)Oy ²Ú²Ú²Ú`~Þü¼ùy°imÓÚ¦5Ø÷µïkßœœœÀ5Ü5Ü5\“\“\“ÀôŽéÓ;```ð›ýKÞ ýèG?(X2°d \/¸^p½l‰Äá‰Ã‡CêÊÔ•©+!mvÚì´Ù�Ù*³Uf+P‡©ÃÔa 3Ôê �>ô¡O<ñüú~Ä_|¡0¡0¡0ªR•ªÀµ”k)×R ¬NX�°:ÀArÈ#�<às>çs 2•© d ;ì°###°q·q·q‡r�Ëu.×{9örì.w]îºÜ7™›ÌMVC¬†X £UF«ŒV�|£|£|£¾/»Cïm¾aø†á vW»«ÝaZä´Èi‘¿™ÒT"y—QDäeæeæeÂcícíc-<ªþ¨ú£ê���icÒÆ¤��ü‡ùó‚aeÃʆ•Áv¡íBÛ…àpÔá¨ÃQ°k`×À®888€Í|›ù6óÁ¨“Q'£N º§º§ºª`U°*”S•S•SA9W9W9 'N(œEW‹®]…r Ë5,×´‘ÚHm$ˆ‹â¢¸ÚXm¬6JÓJÓJÓ ä“’OJ>�’j%ÕJªAáˆÂ…# ½$½$½žõ}Ö÷Y_xîñÜã¹6}lúXHï‘Þ#½˜˜˜�I?“~&ýÀ®Ð®Ð®¼R¼R¼RÀ;Ù;Ù;<x4ðh–�-[>pÀAßWïíÑ[ð"óEæ‹L˜^<½xz1L œ81jÜ«q¯Æ=}7ËûKý¹úsõç�‘Ÿ‘Ÿ‘Î �:/CCC}§{w 7á&Ü }Wú®ô]ðð»‡ß=ü®_¼~ñúExüôñÓÇOA6C6C6œ›87qn•ÛTnS¹MÙ7—/\¾pùì?·ÿÜþs0P¨ þŽË£žãç ¨oQߢ¾�šœšœš Éw’ï$ß�'yOòžäAÌ¥˜K1—àùÞç{ŸïU7U7U7¨Ü½r÷ÊÝÁÿ¾ÿ}ÿûàêê V¶V¶V¶ü:µ±äwL0ä^ͽš{+++àÆÝwoÜ…ûù÷óïçC~J~J~ ذ`;¼¶xmñÚ•2+eVÊ—ñ.ã]ƃÓ§#NGÀÔÏÔÏÔØÌf6ëû$ÿ<ÍÍÍxQú¢ôE)¤ÌN™�2–$,IXÑÍ¢›E7ƒ¤EI‹’A©g©g©'”/-_Z¾üÎû�÷;Õ'WŸ\}28Lq˜â0——ï᣽§Ö�Zwjœ+ôûÐï!lYز°e i i i•å•å•åP÷“ºŸÔýª6¨Ú j°ò³ò³òå.å.å.þ±}9DUQUT…Â>…} û@b½Äz‰õàÖŠ[+n­€ÛgnŸ¹}2b3b3b¡ÂÔ S+L…f÷šÝkvjo«½­ö60mjÚÔ´©¾ÏæÕ½õ@[W[W[Ì[0oÁ<¨9¿æüšó¡û­î·ºßÒwsè�æKÍ—š/!ùVò­ä[àrßå¾Ë}PÞWÞWÞõý_S]S]SÁ†ÝvoØ _|üÅÇ_| Ê8eœ2ö}¼ïã}C‡vtØ®³\g¹Î‚áAÆA“NM:5é#ŒF�0‚„ 7n€K'—N.�@9J9J9Jß­ø×å-Ê[”·®˜_1¿b§'Ÿž|z2,/X^°êÞ©{§îh¼¸ñâÆ‹Á}¥ûJ÷•`¼Âx…ñ }§ÿú”Oùr›ä6Ém�î=º÷è\8uáÔ…Sp¯å½–÷Z‚Ë— . ýÚökÛ¯…:ñuâëăjªjªjª¾OâÍÑk�µÆ5?j~Ô|8¹íä¶“Ûà‘É#“G&PiM¥5•Ö@ó-Í·4ßUݪºUu«@«@«@ Íh¦ï³øû)µ.µ.µ†Ä–‰-[ÂÃ+†W áZ»kí®µÙ Ù Ù h±¾Åúë¡IA“‚&`3Ñf¢ÍD}§ÿóÞzðòâ¬#³ŽÌ:3ëά;³.x”z”z”–mWª(U”* quâêÄÕ@A�®µ®µ®5˜/4_h¾ì­í­í­!­BZ…´ Pú´ôiéSP ¦FL�˜`ö™ÙgfŸ�ë×®;þs»¢ÇE�‹ÃÜÊs+Ï­ v[í¶Úm…Z½jõªÕ Â,Ã,Ã,aܘqcÆ��ë®o¸¾öºîuÝë �®tºÒé Ø}c÷�Ý7PkZ­iµ¦ÁwAß}ž <x.€äÉÉ““'C¹Är‰å¡{•îUºW�Ù[go�½œ|�|�|¡5¨„-[¶Æ?düpŸà>Á}lHÜ�¸!ðÃ?Èû  |dùÈò‘ðaƒ|Ø>Ö|¬ùXÍ�›77CCCȨšQ5£*„U«Vb®Å\‹¹1ŸÇ|ó9GGGÖá[†oÚvÚvÚv°áîÂH›‘6#mÀ|~ÓŽ…õ ëÖ‡ä>É}’û@f�Ì:™uàA¯½ôåYåYåY˜á:Ãu†+´Ý~tûÑ0hï ½ƒöòkï[±El[ übøÅð‹6'lN؈]»,vØ.³]f» ¾úíÐo‡‚¢®¢®¢.äÈrd92ðâ1ÄcÔ/W¿\ýr0.l\ظ0\¸&p ˜>2}dúš?lþ°ùCXÑaE‡ ßž~{úí�Àn�Ý_C�òaʇ)¶çÛžo{��;=v‚®©]S»¦B‹�-6¶Ø&…&…&…oû·Còò΀#Ž8ý3úgôÏ€¶uÚÖi[~ þ1øÇ`Xî¾Ü}¹;|àþ�ûî0`Ø€a†�ù6ómæ£Î…Ï ž<‡c×�]?vNN<9ñäDðwöwöw†ÅsÏY<[:¶tl DEÔ+Vò'™œ79oršÓœæ@#ÑH4píɵ'מÀþVû[ío+_¬|±2Œ0a8Â<z>ô|T¤"õ}ÿñ–mˆÙ³!FˆµK×.]»ôo?váØ…c ±&xMðšà²Ÿ1vÆØc…Xyyåå•—…ݺ?t¿mú´éÓ¦�©#RG¤ŽB-SËÔ2!o\¼qñF!Ä,ˆYS¶Ÿøñ#âGÑÁ¡ƒC!b^ļˆy!ÄÇ]>îòq!Ö»¯w_ï^¶ý´±ÓÆN+ĪäUÉ«’…ˆ"BÑéD§�N‘––&ĵA×]T¶ßäëÉד¯ Ñnv»Ùíf 4?h~Ð|! ­ ­ ­…8Þéx§ã�„èúi×O»~*DáG…~$Dœkœkœ«í·_Ü~±wÞxw w†Þzg¨{òöäíÉB¥�ÒFý~;ž :t*Hˆn�»5îÖXˆüýùûó÷—½>|èð¡Ã‡ ±iƦ›füæßM†› 7â[×o]¿u"xIð’à%Bt¯Ù½f÷šB«‹ÕÅj!n˜ß0¿a.D—¡]†v*Dfvfvf¶—Ž_:~é¸�útêÓ©�)þ)þ)þB´>ÕúTëSBœÖ�Ö�Ö ¡nªnªn*Dþøüñùã…ˆv�v�v"»]v»ìv¯ð†.†‹áBÜȾ‘}#[ˆa®Ã\‡¹ ±Â|…ù s!ÒRÓRÓR…i"M¤½�ßÉ+¹+BÄ®Ž]»Zˆ™>3}fú1É}’û$w!þõ Zß!ÿ·´/Ó¾LûRˆ9½çôžÓ[ˆñÕÇW_]ˆ;ï ¼3PíIíIíI}§”üQYNYNYNBlŽÚµ9Jˆ�ü?òÿÈ_ˆ3çÏœ?s^ˆ ãÕwÊÿôöîÌe.s!Á.Á.ÁŒŒþÈ¢>/LJîg?û�V´¢X?²~dýžñü‹ç_ÛÙÎvPíRíRí³ŸÍ~6ûÌtf:3$·Jn•Ü ¼M½M½M/¼ðKKKÐ*µJ­²µÙÚl-È�!Ä~±_ì/‹cµÌj™Õ2Hßœ¾9}3äDäDäD@RpRpR0¼uðÖÁ[�?"Dþ(7§Üœrs@¶L¶L¶ ä#ä#ä#Àä²Ée“Ë`”i”i”Y6ŒFDŠH º]º]º]PÉ©’S%'¨º¡ê†ª èVЭ [P¹_å~•ûAåÈÊ‘•#AÞ@Þ@þßfÖúå„Ä`1X æ×ñÞ¿2à 3À<þ@á8FŒc@î"w‘»@VaVaV!$VH¬�XŒ<0òÀHÈÙ•³+gØõ²ëe× XÇ:Ö�âKÅ—Š/Átœé8Óq`kk[¶ï5Þk¼_Ãá¡GC�†…íý¶÷ÛÞúŒì3²ÏHh�Õ:«u(Ž Ç×ðþ–¼¿Œ/÷ðõðõð…¹6smæÚÀž�{îK —.5„‰ê‰ê‰j¨fXͰš¡¾C—Iü"ñ‹Ä/`Y«e­–µ‚Š™3+f”îSºOé–=-{Zö|õãHÞ.«««¾aø†á šc5Çjް¥Ê–*[ª@·9æ|ÝÖt[Óm È'È'Èß�UmßÚTÀÙå³Ëg—‡Ï_<ñ<¯x^ñ¼ò~ð—_øŸ@=J=J= ¬7Xo°Þœà'øufÁ—·®_²žh=Ñz"äW˯–_­ìߋ֭+Z4¢�Àt¥éJÓ• >Ÿ‰Ï@¶_¶_ö› wCî†Ü `-¬…µ#w#w#wpœï8ßq>tÚÙig§�0~ÖøYãgÁÆ{lìVu¬êXÕ†2”¡@ ZÐâ7çùòÚGøkıH!…hÛ¬m³¶Í 4"4"4„?Õ2«eVËüí(�ý(ûQö#¿>ëþÕ/½‚eßȾ‘}ó›¯E-j+YÉJ~í%/¼…·ðQCÔ5ÊfŒsjáÔ©tëÖ9 &ÚM´›hëG¯½~4X·8nqÄV±UlšÒ”¦¿‰9KÌ³Ê ±ÒV¥­J[ýù÷[øóðçáÏá»3ß�ùî ŒV�V�VA»Þíz·ë ЕЕЕÿ¥¹¢E´ˆ†ÂÝ…» wCQ—¢.E]€�lä5L$¢ûD÷‰î(Š)Š)Š1JŒ£ ¤aIÃ’†�;ÿvþmеӵӵû/û®®EQEQEQ žŠ§âéÏñ‡5  |Iø’ð%°·poáÞBÈ<‘y"ó'''�î´î´î4”ƕƕÆAþ‚üù @³_³_³ÿÕcü»—S…Ý?tÿÐýЪY«f­šÁºªëª®« ‰×¯'^íñ'e=Ëz–õ Vy­òZå¾½}{ûö†q�ûhÜGüƒ_WWWWWò‹ó‹ó‹¡$³$³ä�üþÿA/G”Ô-©[RÄD1QL„Bu¡ºP …� 6 0à¿ ÖTÑTÑT�’ê%ÕKªW¸Âù{ÿ'‡‡‡ÂÙîg»ŸíÇçŸ|>”¨KÔ%j(ö*ö*ö±T,K¡xJñ”â)PàVàV຺º¯/ÏË>d �6<Úð(L}0õÁÔpúðéçÃù3çÏœ‡F³¼½ ;;;;›_;ÍY…X…Xý�Î+b’˜$&A\j\j\*¯ ^¼2Úe´Ëh-í[Ú·´/›É*ëRÖ¥¬K�V”V”VT¶Ÿö�Û7nßÒ|Ò|Ò|àLè™Ð3¡p$ôHè‘P¨ß²~Ëú-¡Ri¥ÒJ¥ Qj”%Ä}÷QÜGp:ïtÞé<Èj›Õ6«-´ÜÛro˽àìì Þ—½/{_† þAýƒúí鷦ߚ©mRÛ¤¶�ô¾é}ÓûBv³ìfÙÍ é|Òù¤óeù¬|­|­|!»OvŸì>p6õlêÙT(t.t.t†ºßÕý®îw`‘d‘d‘nSܦ¸M£vFíŒþË„h&š‰f�41ibÒDx±èÅ¢‹ ñEâ‹Ä�^-½Zz5ȘŸ1?c>$?J~”ü’û&÷Mî[ÖY2Ù/Ù/ÙT-U-U-!«vVí¬ÚpzËé-§·€›‘›‘›x¬ñX㱂<ƒ<ƒ<á–ú–ú–ž9|øÀ¼‰ó&Λé¡é¡é¡pûèí£·�Âð¥Ã—_ ÷.Ý»tᅩ?¾ßá~‡û`Þ¤y“æM‚ÌÄÌÄÌÄWÏ÷ï¢ûD÷‰î{›ím¶·ì3Øg°’Ö$­IZŸy}æõ™ÄZÆZÆZÂÓVO[=mçœÿq>œÝqvÇÙ¯?×Kò>ò>ò>Ð-²[d·Hðëî×ݯ;ì²Ýe»ËŠ ‹ ‹õѧ㗂ÿÀŠ+¬—±.c]ÆÂ`»Ávƒí@å«òUùþñÝe�Î�=æLœ3qÎDØ‘»#wÇk\,-H¤RÃÚfk›­mùC󇿅#�Ž4:ÒÆM7mÜ4Ⱦ’}%û¿| />^|¼ÖnY»eíÐÔÔÔÔÔ|ýÍ{vÛÙmg·Áe×Ë®—]A¾L¾L¾ n6¿ÙüfsX¸eá–…[ kZÖ´¬iðóÏ?ÿüóÏ0lÀ°Ã”ÍŸð¦Tm^µyÕæ0ÆxŒñc8zñèÅ£á©ùSó§æoî¸Ô[{ ž§ž§žªïUß«¾Ã†= {ü�´Æk %-i &æ&æ&æ0Ñ|¢ùDsðêëÕ׫/(�)�)�Á¬àYÁ³‚Á(Ò(Ò(²l7õ[×o]¿5X·µnkÝ’‡'OµzÔêQ«T›Wm^µy`4Üh¸Ñp¹"Wäòko$SSS˜”1)cRxòä=dŸÈ>‘}3ªÏ¨>£:ܯ¿þýú ë¯ë¯ë¢›è&º�j»j»j;ÌVÍVÍV�ãeÇËŽ—AWCWCWj©q¤ÆX([([(mKmKmK ˜bŠÁ°ža=Ãz¨Tª¡á' ?iøÉÿn>Í*Í*Í*¨=²öÈÚ#Á¹šs5çj`xÜð¸áqÐÕÔÕÔÕ„±qcãÆÆ�qœqœqhNhNhNÀØÇc�} ¦L˜oGoGoGXðdÁ“O@ç§óÓù�ƒÒAé „�g4žÑî—»_î~9ÐÝÑÝÑÝñ¡øP|†¹†¹†¹0g朙sf‚s˜s˜s/á%¼ÀBg¡³ÐÁÐ>Cû í†W^a8P� Tøßçûcê�©?¦‚{#÷Fî� Ð7Ð7ðOü�}É Û Û œ®;]wº!“B&…LÝ÷ºïuß¿úïƒë<×y®ó wýÞõ{׫VV­¬ZA•§UžVy ™¶™¶™¶P0¤`HÁHl—Ø.±DýAô87pnà\pµuµuµ…Þ^½½z{�ùróåæË�ù�_=çK1þ1þ1þ�±*cUÆ*è0§Ãœs€³œå,ô:Üëp¯Ãàt×é®Ó]0¯f^ͼ”š•š•šAæžÌ=™{^_žß#O–'Ë“¡×Ù^g{�…Eb‘X$àêý«÷¯Þ‡¦u›ÖmZ÷Íçx)jpÔà¨Áð0ñaâÃD˜uiÖ¥Y—@UEUEUåÏïÏf„Í›`¨4T*áùØçcŸ�¥ìè+ªëPס®x{z{z{‚YM³šf5Á³ŽgÏ:°óã�ïü´K´K´Kàæ…›n^ƒŸ ~2ø j�¨u¢Ö ¨R7¤nT6«lVÙ �ö´§ýëkßÇn»q Ì/™_2¿í[µoÕ¾¼Hz‘ô" L˜40i–“-'[N†*±Ub«ÄBÚ–´-i[ (º(º(š_ïp½)u;×í\·3ÜKº—t/ 7:Üèp#˜”2)eR ÈœeÎ2ç7wüßóÖ €‚ùó æƒ²²²²²2<6xlðø¿üÀ.v± 455Ás”ç(ÏQp-àZÀµÿÜÜ÷¨ïQߣ¿>1ø²Ÿe?Ë~.ûøëÁ¿5õË£í<í<í<(?»üìò³!`VÀ¬€Y¿×!Ê!Ê!ê¿Ì$ùË~ÛІ6ÿÇËF-ŒZµ€Æ4¦1 ‰×Äkâ!bhÄЈ¡PúséÏ¥?ƒUºUºU:ThZ¡i…¦”Í™ý; jÔ2¨uoÔ½Q÷Æo^˜ÉLfþ&ÿ¿çîD':�;î¸Ld"¿çú2ç¯6°� e½·_þ÷÷ÚÁ 'œšÐ„&À#ñT¨PþøãÏ—U>«|Vy¸t#èFŒí7¶ßØ~ ·—ÛËíÿÄŽþ�¼³¼³¼3¤ÏJŸ•> NL91åÄÈËËËË˃:ª:ª:*0ò5ò5ò…ó¾ç}ÏûB»vì ÿ«ü¯ò¿‚ ¾|/øBÇÕWw\ Õ ªT‡[Q·¢nE�㇎:~ �…d+d+d+ ¿~ÿüþ°áð†ÃClilil)X(, 0;kvÖì,Üš{kî­¹`•a•a•áׯ…_ƒÒ’Ò’Ò0¿e~ËüVÙ0ÔŽöí;Úƒ½»½»½ûïŸ^H^H^„{†{†{£ó�Î?:÷]Üwqxß÷¾ï}î<¾óøÎc0Þn¼Ýx;T «V5 dÍdÍdÍ@ÖFÖFÖ°Å[ˆô�ô�ô‡ˆ*U"ª€ò åÊ/ Y�f=šõÇ«ŽW¯þõëfÖÒ¬¥YKh\¡q…Æ ¤RH¥�JÐøÓÆŸ6þäíåíå¯ñƒè÷„L ™2j^ªy©æ%°7´7´}~m·õ}ê ÝÜ»¹ws‡'¾O|ŸøÂÓÊO+?­ ^Î^Î^Î ûJö•ì+�Ÿ”Ÿ”Ÿ„¤¥IK“–ÂÒ K',�Ï<žy<“Ù&³MfóÙÏf?› I½’z%õ³D³D³D^¼>x=8w8îp &L.˜ ÊéÊéÊéÐñnÇ»ï‚a[ö†mÿô“Û'·OnQùQùQù`ÜÁ¸ƒq/^>¼<(ý”~J?¸p+àV¸}êö©Û§ ›#›#›²ë²ë²ë ‹“ÅÉâ@‹` ¯]¼vñ<ÝñtÇÓ`Óɦ“M'h1¾ÅøãÁd€É“ý²fffÀÂ¥ —.\ É^É^É^àšïšïšÿæß�ÿî­=(6,6,6åååPÎTÎTÎüýíÓ;¦wLïå¾+÷]¹ïʾçç翹œé é é `÷�Ýwvß�ÆCã¡ñõõõŽ·ÕZ Ü…»p‡ÐâÐâÐb6(l4qjâÔÄ •••_ý8ï‹Ô ©R+€ÖJk¥µ‚òËo,ÿžÕ¿ì«`æeæeæ5ª×¨^£:؅څڅ²šËj.« é Ó¦7„ïµßk¿×BB�„: uÀr†å ËpðöÁÛoC°„a ÃÀüˆùó#°×j¯Õ^«²©Jåqò8y°–µ¬ã>Æ}ŒûS™ÊT°mgÛζT\UqUÅUeì{ëí­··¤N?œ~îL½3õÎT¸ñã�oü¾Ç|�ùƒ«?_ýùêÏpèÆ¡‡nüïó7íiÚÓ´'8Ç;Ç;ǃM›þ6ý¡rÏÊ=+÷„rË=,÷N(O(O(á¶ÿmÿÛÿGå&·‘ÛÈm álÂÙ„³ðuÎ×9_ç@ÅÛoW¼ Y¡Y¡Y¡°®ûºî뺃¶²¶²ö5¼¿k/¯½¼örH©–R-¥<Ïžÿü-ü¡-¨\P¹ 2Äu�ë×|?õýÔ÷Ó×·YMYMYM(·­Ü¶rÛ ®¬®¬® ²²²`uÉê’Õ%�Ý<»yvsØ�º;uw*”4/i^Ò´»´»´»à» ßUø®”¶)mSÚJ®–\-¹ ;»ïì¾³;äÏÈŸ‘?d!²Yˆqbœ#-FZŒ„¢ÁEƒ‹CE³ŠfÍÀu�ë×5Pt¿è~Ñ}Ø‘º#uG*�L2Ép|Éñ%Ç—@æÎÌ�™;ÁÇßÇßÇvíܵs×NoÞ:¼õÿ>›i6Ól¦�­ÖVk«-›�¬ÂŽ ;*ì#c#c#cعcçŽ�; íQÚ£´G ß*ß*ßZ¶Ÿ—wŒB:†t éß÷ý¾ï÷}¡ö‚Ú j/€Ð¸Ð¸Ð88bÄþÈ+|‘xÉq‰ãÇ%`»Èv‘í"¸wøÞá{‡_ë[ïOyk€ÖNk§µ¥�Ò@ ò¶ò¶òÿRáÙ±;bw¾¬úeÕ/«ÂTÏ©žS=Áò¼åyËóü¸–ÝgvŸÙ}‹k-®µ¸LI˜’0%,--Þboq…�Â@SÚOi?¥=Œ?~üøñàxÉñ’ã{8'õ«Jߘ¾1}#˜Æ›Æ›Æƒ‰»‰»‰û«ï÷å-î—•¿n¸�ƒ<ñÄbbbÀHf$3’�L.“Ëä`Ù˲—e/PuVuVuY®,W– j µ…Tþ*•?pŠSœ2É$8ÎqŽƒÊIå¤róJæ•Ì+��ÒFi£» vì&€¥°– nÜ2¸2™�¬l)ÓOM?5ý*\¨p¡ÂpKqKqK�äÛÉ·“o—Í…~/ã^ƽ ¸«»«»«ƒGµÕzT d² YØö²íeÛ ÌW˜¯0_._»|íò5X\²¸dq Œ…±0 {${${ôŸÍ¨U„*Báþ¤û“îO‚gâ™x&À±Ø±Ø±lkÙÖ²­·ÜZpk¹¹½†ëgZ×´®i]P,Q,Q,�»»»WßïÿRr¨äPÉ!(j]Ôº¨5XtµèjÑõ5à—éVÝ­º[u÷ZîµÜkAÏžµú×ê_«?¨U�ª@xñÙ‹Ï^|¹›r7ån‚HûHûH{¸»íî¶»Û i{Òö¤í`Üĸ‰q°¬gYϲ”Ë.—].l½m½m½Á²ƒeË`�g�g�÷›ÎÜ9ä�SÖŒ²Á²Á²ÁpiÄ¥—F€Aƒ ÀvŸí>Û}`tÍèšÑ5¸Yp³àfÁ«_6y y y °x`ñÀâd6ÏlžÙüÍ¿Ï[{ðò߯½¨ÿW¯Ð—½åß¶Œ`ī捻°¤°¤4­5­5­Á$Á$Á$xžü‰½þ(ù¯LMMËzý–î-Ý[º”(_íMþËè qFœg€ñŒg<(3•™ÊL�-ÿZþ5h:h:h:€,\. Ù:Ù:Ù:~5ñÊäÈ‘å(G¹?°ý/}G¸Ë]îRöÌÅC AV_V_Vr,s,s,áPíCµÕ†Â�… ‚ãxÇñŽãaBð„à Á” ýåέiÍø¦ö’l¼l¼l<”4(iPÒr:ætÌé7�ß<~ó8hzizizAÿaý‡õªªª¯ÞlZs­¹Ö´½µ½µ½ÁÐÕÐÕЕ7>U®¢�¢�¢(‚AŠ (ù¸äã’�ùÏÑ?U.¹äþæ}ù ÕmÕmÕm·Åmq´3µ3µ3�v´£e ]ã×þâ±ËcŒ)ë«õ{^Ž«~Á ^±Äò›a¿Øc�}Ù#»Çv�íÛÁ¾ƒûî;b›Ø&¶�Ÿ±Ÿ±Ÿ1¸uê:H#�´²Oÿ,YYY(ü¡ð‡ÂàyÁó‚çpõÜÕsWÏAÅ›oV¼ îGÜ�¸ºÐ….½¹D±(ÅPÜ¡¸Cq0 1 1 áOÿ>½.o¯x.{.{¥~¥~¥~ »§»§» ¼ÁN˜o]Öò¬åYËañþâýÅð¯ n`ŒÇ�1`�ÿåçsãsãsã!r^ä¼Èy`ÑÍ¢›E7¨Þµz×ê¯óÄ{ÆQã¨qÔ@IQIQId,ËX–± \wºîtÝù ;þåƒ÷×?´¿tNx\ø¸ðq!×)®S\ª-¬¶°ÚB8¼åð–Ã[ È£È£È„¹0æ œ…³p¡j¡æ×W´-EK‡ÅaqÄ'âñ ˆKâ’¸â”8%N�ì¼ì¼ì<¼(xQðtž:O�'ˆ©bª˜ Â^Ø û²áN/ÿ Šeb™XƯ`ÄP1T mž6O›å:”ëP®ÌN��:;•_ïÈÊÊ–5ƒh#Úˆ6e£Å^ÎÃ@2Än±[ìÝeÝeÝeÉ"Y$ƒˆñ"tN:'�TjT©Q¥FPº­t[é6èÒ­K·.Ý@Y ,P}éKßW¿lEEE�îŸîŸî½*zUôzóïÇßóÖ UmUmUmÐÆiã´q } } }nnnúk€×-4?4?4âuñºxŒté<Ò +V4üSA*§(§(§À±ùÇæ›%á%á%á°ŠU¬Ò÷ɽÜ>wúÜéspûÈí#·�àÆÐCo W\q}…ýV¸^áz…ëàâëâëâ » wî*„LU¦*S½ì{Ù÷²‡zÕû¨ÞGX?°~`}8p&àLd÷Íî›Ý,W[®¶\ éÑéÑéцM ›6…‡Ë.¸´Úm•7*oTbbb Æ±ÇjƒÝ#v�Ø=ö�Û?nÿ8p©ìRÙ¥2­4Zi´Â&„M›Ï}Ÿû>÷e¾2_™É#’G$�€\Ó\Ó\S �tÒ!W“«ÉÕ€ùóæþóü‹lŠlŠlʆ-½5 j@Ô0¾k|×ø.ˆF¢‘h‰Y‰Y‰YpkÈ­!·†_ð_@bnbnb.N œ8 Z}Öê³VŸÁ&—M.›\À}©ûR÷¥P#»Fv�l¨Õ½V÷ZÝAVOVOö ñ…øB|\\pqÔû¹ÞÏõ~“Z&µLj½ù÷£²·²·²74Ûhl£±pÅëŠ×/ܸ'p¨ú«ú«úÿõý×I¯“^'nÙÞ²½e [ý·úoõ‡´®i]Ӻ¨®£ºŽê •ÆV[i,T¯T½RõJ°oð¾ÁûƒyŒyŒy X=±zbõžœxrâÉ xxöáÙ‡gÁ0Ü0Ü0ÂcÂcÂcàÙžg{ží£<£<£<ˆ_¿"~|¨ùPó¡B†‡ ¶¶¶�ò]Êw)ß�á|Ãù†óá” S.Lá×ÎÄ/†¾úb(Ä.�]»d‰²DY"dTɨ’Q´´´@q[q[qû?ÏÿYè³Ðg¡�›—›—›º*º*º*ðäÚ“kO®AìúØõ±ëÁx·ñnãÝp/ô^è½P°±±“Y&³LfAL˘–1-¡£OGŸŽ>ðbý‹õ/ÖÃê뫯¯¾å{–ïY¾'øòä?*t¨Ð¡B‡¿~Ý„Ƈ�33³7ÿ~ü]okÊÁð»áwÃï 1~ÄøãG‘;+wVî,}O„øú}uù«Ë_]bì¼±óÆÎ¢àQÁ£‚GBˆþ¢¿è/DáñÂã…Ç…Èž3˜ôÁ¤Êþ½ô|éùÒóB¨k¨k¨k‘W/¯^^=!t:�CÙvÚ0m˜6LˆÜª¹Us« ‘7 o@Þ!tStStSôÝJoNÔ¬¨YQ³„ï6Þm¼› ½z'ôþëûӭЭЭ¢àXÁ±‚cBäÜ̹™sSˆÜ‘¹#sG ¡½ª½ª½Z¶}é¦ÒM¥›„ȹ”s)ç’ù5òkä×"73737Sˆ¢EE‹Š Q4¬hXÑ0!ÔWÔWÔW„È�Í�Í�¢HV$+’ ¡ÎRg©³„(¸Up«à–Z/­—ÖKõõõ!rÏæžÍ=û›ícÔ1ê!òÖå­Ë['Dî”Ü)¹S„ÈÛ“·'o�¥;Jw”î({ä]λœwYm¶6[›ý_΀n€n€ùæùæùæB¨×©×©× Qܰ¸aqC!JìKìKì…ÈuËuËu+Ûï¿&Ø"wTî¨ÜQBä×ϯŸ__]{]{]{!41šMŒ9wsîæÜBÝPÝPÝPˆ¢Œ¢Œ¢ !þ5#æ_¿n×÷\ßs}�Ä1A‘ŸŸÿ–ߌBˆ¼ayÃò† 1cÜŒq3Æ qjÅ©§V¼ú~5©šTMªy1y1y1Bä É’3Dˆü”ü”ü!D;ÑNüf í¢öEí‹Ú ‘“™“™“)DþôüéùӅȳʳʳ¢Ä¸Ä¸ÄXˆ‚îÝ º ¡>§>§>'DáÌ™…3…øWo}!Ô±êXu¬ÅTü‘¥—~\ú±ÙÁÙÁÙÁe?_У GA!Ô�Õ�Õ�…ȋʋʋB�­ÎVg Q^^.DÉý’û%÷…È5Ë5Ë5¢PU¨*T !ºŠ®¢ë9ÿÖšÖšÖBävÊí”ÛIˆÜɹ“s' QêQêQê!Da\a\aœêÃêÃêÃB +V0LˆÂÕ…« W ¡ŽPG¨#„(œW8¯pžb»Ø.¶ Qü øAñ!²ó²ó²ó„Èý(÷£Ü�„(V:¬tØ_¿^s2ædÌâÓíŸnÿt»¡³Bg…¾Ÿo­ˆ&šh„U8ªpT¡Ó2¦eLÓ÷é¿>i¶i¶i¶B ¹7äÞ�{Bü«�ާ/Ÿ¾|ú²ÆÆÆB¬µrÔÊQB¬¶jتaBL2yÈä!B\éx¥ã•ŽeûûµÈ™”3)Gˆ‚ ±ºùêæ«› ±8pqàâ@!oZ¼iñ&!âìãìãì…Ðøj|5¾BìÙºgëž­B,öZìµØKˆù‡æšHˆÓÕOW?]]qPõÝjoÀ1D âÛ-ßnùv‹Ó¢§EO‹"c@Æ€Œú'yÓb£c£c£…]ytåÑ•…8åü•óWô�Jˆˆví"Ú 1lÁ°Ãîîî£ïT’7­ \A¹‚rB|!ûBö…LˆÝVt[ÑMˆ’oK¾-ùVßéÞb�:$uHê!†UVeX!’ÔIê$µ¾Oÿõ[eºÊt•©jL¨1¡†º(]”.JˆÒy¥óJç V¶ýâé‹§/ž.Äô^Ó{MïUöï/ €O|>ñùÄGˆ§§'!>ðÁ€ñSÂO ?%‘ôCÒI?¡¶P[¨-„ˆÜ¹!rƒÝ ºt7"¥0¥0¥PˆÐ�¡C ÑË«—W//!Ô=Ô=Ô=ôÝZoN¡A¡A¡�_•ÿªüWå…˜VeZ•iU„HŠLŠLz…o–’wÌqq\â^À½€{BŒh=¢õˆÖBìÞ¼;XÑEt]ôRQ*JE©§ãNÇ�ŽbÐ…A]âç.?wùù]È'y­²¿Îþ:ûk!- Z$Ĭ泚Ïj.DV\V\Vœ¾Ó•ykí’­’­’ÁÈÖÈÖÈÒÓÓÞÇEX^ö®ýe”ƒ¬š¬š¬”jKµ¥ZÈLÉLÉL�ïC¾ù>î}¸÷á^(^_¼¾xýîî_8ÀFa£°Q@Ã1 Ç4_îürç—;aÿäý“÷OÍ"Í"Í"H»‘v#í$^H¼�xBN„œ9·�nÝ6‚By¡¼Pš4?h~Ðwc½9F%F%F%0Öf¬ÍXpvqvqv�µÔ^PÂv‡íÛ b­X+Öê;­äÏÒ<Õ<Õ<…“óOÎ?9,X�Ë—.ƒ>gûœís8ÂŽè;-¿Giýeë/[ “& L‚oF3ú›Ñ°/|_ø¾pø×-w}‡•üi;ØÁxèõÐë¡ÌýxîÇs?Ý:Ý:Ý:˜:5tj(XU²ªdUéUöú¼µN€FÁFÁFÁà`à`à`ñAñAñA¿v:}ü2,F6\6\6œ_{¹žH:‘t" ‚F�  s.Ϲ<ç2ÜYygå�•�ÿSþOù?ÝèF7À#Œ@ì{Å^0J2J2J‚iݦu›Ö ž4~ÒøIcX0dÁ�CÀ`‰Áƒ%PGWGWGVÑVÑVÑPí†[ 70»gvÏìt+ìVØ­,?°üÀò}7Ö›gaacŒy0æœr:åtÊ Öú¯õ_ëþ]ý»úw…nÚnÚnZpT8*ß§a)ï‹_¦j�¯_7¾.ìMØ›°7‚‚‚`Læ˜Ì1™Ð ²AdƒH�%ÿJþ•¾Cÿ¶²•­e£íSíSíSaóÍÍ77ß„ˆ&M"šÀ€v ؾC}‡útèÐé;¼äßeOÏžž=އ= g‡žzv(´8Úâh‹£ÐKÙKÙK ÆZc­±VßiÿÓÛ[øå”?Pþ$œJ8•p ½�|Ý^{QQQ�ì´ì´ì´²‰@ò&çMΛ ÿêlS6Á„â™â™â$$$CQ\Q\QäžÎ=�{òä5ÈkO—>]út)œ9pæÀ™ÐêT«S­N�§‰§‰§ (z*z*zB¥é•¦WšNQNQNQ� HP$(À·À·À·,®X\±¸òhy´>øø Ü5¹kr×âžÄ=‰{Å{‹÷ï…Š… +‚ß¿3~g ¶Sm§ÚN`]ɺ’õ;ÔYê]“×"¯E^ ¸;é“àºúºúºbT1ª(Ž)Ž)ŽAÅJ+U¬¾æ¾æ¾æàyÕóªçU°Yk³Öf-X|eñ•ÅW _-_-_­ï³z�.r‘‹P´£hGÑȪ—U/«¤Z¤Z¤Z@dxdxd8D_Œ¾}Ò»¤wIïR6scÝ)u§Ô�~ƒüù ···�…ÊBe¡ú>¹×ç­/íܲsËÎ-�’’“÷MÞ7yŸ¾›C"ùc^αžÕ4«iVS87ôÜÐsCae½•õVÖ׎®];‚}¤}¤}$´5hkÐ\]]]]]ÁÕÊÕÊÕ œk;×v® ®«]W»®»-v[ì¶€ê–ê–ê(›+›+›ƒb–b–b(F(F(Fw¸Ã�×p"¿L±*¢E´ˆÝ0Ý0Ý0Ð4Ö4Ö4MŠ&E“E]‹ºu…gGžyv’Ï%ŸK>)Q)Q)Q�Ø1±cbGH]™º2ueÙÜû– K…¥¼;zwôîÕ½ª{U÷Ÿ(Ÿ(Ÿ(°øÔâS‹OAî+÷•û¾úéüS‰(%¢ Ï$Ï$Ïä×Õµ‰4‰4‰4�‡AƒAæðÌá™ÃAž*O•§‚ýXû±öcÁí¼Ûy·óà4ßi¾Ó|péçÒÏ¥8×s®ç\Œ2>J;¥�Ò”ϔϔÏ@¢Q„€lšlšleëy¿ªÉLf2èÎèÎè΀f·f·f7h²4Y𬲵>2/f^̼I�“'=†”Î)�S:CòÕä«ÉW!áQ£„GPpºàtÁi0Üf¸ÍpTÔUÔUÔAµgÕžU{¾|ø>{/{/{/PF)£”Qú¾ªožÞ €;#3¶¶ÚÚjk+XâºÄu‰+˜60m`Ú@ßÍ"‘ü1ÖÖÖ°)|Sø¦p¨ä\ɹ’3 \>pùÀå ]¯]¯]©­R[¥¶‚h]´.Zəəəð|ÛómÏ·�zŒzŒz h?Ö~¬ýŒ<Œ<Œ<ÀÄÀÄÀÄŒ4:†} ûösss0«lVÙ¬2ùùù‚ÂEá¢pÃ}†û ÷�n•n•n”X–X–X‚ÆNc§±ƒâÖÅ­‹[ÿfJ+ûFY²®d]É:(\8¸ppYçÔ’ %J&€Aƒ>}ÀÊÇÊÇÊì¯Ø_±¿î'ÝOºŸ¯Æ^�½ƒÝ@»�vÁv·ínÛÝ Z¡Z¡Z¡ï«õÏ¥1Õ˜jL!smæÚ̵ðâð‹Ã/Cì´Øi±ÓàI«'­ž´‚´eiËÒ–Af‡Ì™ ¤sIç’Î`ð�Á7߀ÉI““&'Á¸Ä¸Ä¸ 7n0ܦN¦N¦N`žjžjž F±F±F±`0Ò`¤ÁHPE¨"T HS¤)Ò ¸mqÛâ¶e‹@[[[@þóüçùÏ!÷aîÃ܇PdXdXdE_}QôÎ)œS8 s s sA–)Ë”e‚Ù:³ufëÀ~¤ýHû‘àlàlàlÞxã 8pà<lÛ>¶} f×Í®›]ç×á{ÿTz+Š,‹,‹,aFÇgt„þû?ìÿüÂüÂüÂôÝ,Éÿ­dVɬ’YÔ5¨kPW8,‹ÃºÎï:¿ë|èÕ)ªS$$$üïý‰ùb¾˜ÿšÚ2µ™ÚL-äTÉ©’SrLrLrL ïEÞ‹¼Pж mA[È]—».wä�É;“wŠÌŠÌŠÌ@g¯³×ÙC±w±w±7Ⱦ–}-ûT ªU(Rþ¤ü ŒÎ�1:æÎæÎæÎ`¶Ûl·Ùn0Ùa²Ãd˜™™�å Ë–7ÀÒÆÒÆÒloÚÞ´½ &-MZš´6±‰Mú¾*’׿ 9E?ýXô#d,ÊX”±rå Ê9n9n9n ^¬^¬^ ŽŽŽ�W’W’Wy#óFæ�„«…W ¯‚ö¡ö¡ö!D÷�îÝböÅì‹Ù­´>Ðú¨t*�J†™†™†™`šgšgšæýÌû™÷Óê¦ÕM«ƒé.Ó]¦»Àršå4ËieØ­G[�¶ –�-[>ù ù ù }7âß‡Þ €—¶šm5ÛjÅ�Š?‚��>vúØIßÍ"‘üÿ2§gNÏœ›¯m¾¶ùÄ;Ä;Ä;ÀØø±ñcã¡VX­°ZïBáúË*qÔ¦6µ�&4¡ e«üý²°Dò6]´¼hyÑÎŒ?3þÌxX´ hA(#”Ê}§ûçzk3þžTlP:?t~è Ù‡²eÒw*‰ä_î÷¼ßó~Oø,골Ϣ 8¬8¬8 4^ÐxAãwèƒÿ¥—ãà‹)¦8ÃÎ }ðKôë—å~™Â¦ ïP½Þ¼+xWããÆÇ��Ãí;·ïÜ~�›$’¿@ë®u׺ÃIï“Þ'½aIÌ’˜%1Ðàhƒ£ ŽÂŒ~3úÍèNãœÆ9�ÓwZ‰äo¢”RJ�<òÈÓwÉKz/TÇUÇUÇáà nøpœ¯q¾Æù i¦i¦i¦ït’ µ½Ú^mk£×F¯�†ïݾwûÞ Æ&�M›ýÕýÕýÕ`¸Åp‹á}§•H$’W§÷ॆ .l¸2Š ›}6(¡„}§“¼/^ŽO?ûüíó·aþ£ù�æ?‚jŽÕ«9ÂÜNs;Íí®>®>®>úN+‘H$oÎ;S¼¸5pkàVˆéÓ9¦3$}šôiÒ§úN%ù»+Ø[°·`/li¹¥å––°+{Wö®l¦¦¦†!û†ì²LBLBLBô�V"‘HÞ¼w®pïçÞϽx^ð¼ày‚·o ÞªïT’¿«DÏDÏDOX˜¿0a><²{d÷Èæ­˜·bÞ hêÜÔ¹©3ÈUr•üuÌ`&‘H$ï\Ànv³ÚŸi¦ý¸VñZÅk!éIÒ“¤'ú'yçýÒÛøFíµoÔ†ùæw˜ßœ¼œ¼œ¼`þÄùçO„JA•‚*é;¬D"‘è�Rß~�ÏTŸ©>SÁûCï½?„ã1ÇcŽÇÀ˜ c*Œ© ït’wMÉ ’A%ƒàhç£��v†cãŽ�;6úú÷õïëmk·­Ý¶6(J¥ŠR}§•H$ý{÷îüB¦”)eJèâ×ů‹„>žÜ}r÷É]}§“¼+2K2K2K`eÎÊœ•9pþÅùç_Àt£éFÓ� CõÕ;T—>ø%‰äß½³w^òÌòÌòÌ_µ¯ÚW Ç–[vlL,?±üÄòÀb³Xß)%oÍT¦2¢�£�£�aÝ…uÖ]€rŸ—û¼Üç°Ðj¡ÕB+p¨éPÓ¡¦¾ÃJ$É»ë�½ð’ÌIæ$s‚.á]»„Ã�ÅwßY ‘ޑޑŽúN'y[t×u×u×á¬ËY—³.°è“EŸ,úê=¬÷°ÞC˜qwÆÝw¥~‰D"ù£Þùà%wwwhѸEã�aoøÞð½áPœ\œ\œ¬ït’7¥À§À§À¶5ÙÖd[Øc³Çf� Œœ?rþÈù0°ÅÀ[€áxÃñ†ãõ�V"‘Hþ>ÞùGÿ®Cz‡ôépµùÕæW›Ã…µÖ^X m–´YÒf‰¾ÓI^—de²2Y ëo®¿¹þ&:::¼¦óšÎk £+FWŒÖwJ‰D"ùûúÛÜxÉ2Ï2Ï2zžìy²çI8Üýp÷ÃÝáÅ®»^ìÒw:É« O O Oƒ¹‘s#çFB9ûröåìaþ—ó¿œÿ¥ôÁ/‘H$¯Ëß®x©¡CC‡†àzÔõ¨ëQØŸ»?w.°�mlÓw:ÉUš\š\š ?DÿýC4¬Þ¾zûêíÐ9²sdçH˜à1Ác‚X®µ\k¹Vßi%‰äýñ·- Ö¬5X ƒüÓàŸà–Ë-—[.p½ñõÆ×ë;�äÉÊÉÊÉÊ�ÕíV·[ÝÎ,<³ðÌBø¤î'u?© �{uîÕ¹(‹”EÊ"}§•H$’÷Ïß¶xÉí’Û%·KÐùçÎ?wþv}»ëÛ]ßBN…œ 9ô�Nòïâ¢â¢â¢`~üüøùñ öP{¨=`Q›Emµ�Ú­j·ªÝJß)%‰äý÷·/^jÝ­u·ÖÝÀf�Í:›u°ßf¿Í~cÄ1Fßéþ¹Äz±^¬‡K-.µ¸ÔF/Œ^ ¾¾¾0Ë~–ý,{pè0Ða ¾ÓJ$’7¢)Mi ²%²%²%€è;”D&~¡ï ¯KÜå¸Ëq—aᣅ�>‚1SÇL3¼hð¢Á }§ûç(:Rt¤èÚ}h÷¡Ýpzïé½§÷ ”A)ƒR ™M3›f6 °TX*,õ�V"‘¼¥Á¥Á¥Á�Q-£ZF5�?‘?‘?�Ë·/ß¾|.6½ØôbS˜¢›¢›¢ÅÅÅ0[h¶Ðl!XD[D[DÎ8ã¬ï³yÿ½wÀK'U'U'UptÀÑG”ÝbvèåÐË¡—¾Ó½¿2ÎfœÍ8 ߸}ãö�¤vIí’Ú&¤NH�� >Ù>Ù>ÙúN)‘HÞ„´Ùi³ÓfÃxÿñþãý!®J\•¸*PP¯ ^A=Èù"狜/À%Û%Û%tëuëuëajÈÔ�©!ЧJŸ*}ªèû,þ9Þ›Gÿ®Õ�­~lõ#xÔõ¨ëQ¶¯Þ¾zûjÐLÑLÑLÑwº÷OôêèÕÑ«a^§y�æu æÎœ(}ðK$ÿå²Êe•Ëc c c ¸å}Ëû–7R|¤øH†{ ÷îÕwZ‰D¢ukÕ­U·Tö­ì[Ù÷?_WnRnRn‚æÍ#šG€y¢y¢y¢¾Sÿó¼÷ÀK~Ÿû}î÷9tèÕ¡W‡^°¡â†Š*Búžô=é{ô�îÝ—î‘î‘îKK—–.-…Û[no¹½>ûÙØÏÆBÓòMË7-²ÏdŸÉ>ÓwZ‰D¢OnÕܪ¹UƒÆ3Ïh<ã?_·7±7±7�À�'Oè;í?×?¦ ˆ ‚ [t·ènÑP~Xùaå‡Á¦]›vmÚÅ�Š?ÒwÈwϽ½÷öÞÛ sMæšÌ5U¶*[• j-¨µ xUòªäU 0ÄC}§•H$ïùSùSùShÕµU×V]Á²£eGËŽe¯øôç>…Šöí+Úë;í?×{; àÉ�eÈ2d0÷ë¹_Ïý–4,iXý‹û÷/ÙlÙlÙl}§|ût§t§t§àÜgç>;÷ì<¼óðÎÃÐ>±}bûDè1¶ÇØcA¡ŠPEè;­D"y—¥ßN¿�~ÚýÔî§v?A„g„g„'lœ·qÞÆy0,lXذ0}§üçúÛ­øºØ [a+`üüñóÇχÅO?Yüœ9r>Íg7ŸÝüTì)ØS°vOß=}÷t¸|5øj0Œ0vÀØÐÈ©‘S#' ‚"ô�V"ùg*\^¸¼p9dµËj—ÕDÑF´¬±ÆZßé~£ÝèÚGÚGÚGPç§:?Õù R?Hý õ¨8±âÄŠ!¥0¥0¥„¿ðþ€ 2}‡4hÐÏyÎs0J5J5J•�ÊF2�L'{ú�ýcïü»ŸFý4ê§Q°­â¶ŠÛ*´ÚÓjO« ÕZWk]­µ¾Ó½9©•R+¥V‚o ¿1üÆòŒóŒóŒaüˆñ#Æ�€Jc*�©$ͤ(‘¼‚ƒƒa›Ë6—m.`¥±ÒXi@4ÍD3}§û�_>Èå#å#å#!qâþÄý�Ô;©wRoðké×Ò¯%ÈËËù䓯ïпQ—ºÔ…’>%}Jú€}Š}Š} Ì_7Ýüu`5Èj�Õ }‡|uRðoöUÝWu_UÍ Í Í„ùËæ/›¿ œ>rúÈé#}§{ H î~p÷ƒ»À:Ÿu>ë|Àk„ׯ0²ÁÈ#€eË –ôV"‘üÖæ”Í)›S ý|úùôó0áᄇBiõÒê¥Õõ�î?ÉÎÉÎÉÎAîéÜÓ¹§Aí©öT{‚Ó*§UN«@öHöHöСãúF-«#«#«)ûRö¥ìƒÅ�7ZÜVXy`å°ßj¿Õ~«¾S¾ºì#€ßÓ}T÷QÝGAÊÉ”“)'a•r•r•æÌ ˜—,.Y\ÒwÊ?O©‰ÔDBp·ànÁÝ`諒—ö^‚.¹]r»äBçÐΡ�CAUAUAUAßi%ÉÿEÖGÖGÖLƘŒ1æ_˜aþ…¾Sý}éKßÿò„¢u¨£ï�¿¯p_á¾Â} ˆTD*"�V´â=Z¬ìŸ3 àRMTMTM„Ñ¡£CG‡‚¡·¡·¡7¬ËZ—µ. ŠjÕ(ª¡ï”\^h^h^(l:¹é䦓pÈï�ß!?˜Øhb£‰� ‡cÇŽeç-‘H$’©ø¦Å¦Å¦Å0éÇI?Núžïy¾çùؾ}ûöíÛAÛPÛPÛð?N³_³_³tßé¾Ó}§¿üÉñÉñÉñ°°ÉÂ& ›À“ÛOn?¹ ó;Ïï<¿3ÔO­ŸZ?d2™ƒþrJ$‰D?¤à°]h»Ðv!LÖNÖNÖBÄöˆíÛa¿|¿|¿„³pÎ�:+uVê,˜g:Ïtž)DUˆªUáõåÈËÌËÌ˄؎±c;òëòšÿ.\®WÀ¼ó^Ì{.U]ªºT…¹s æ€[o·Þn½õݪ‰D"Ñ7©øƒÜë¸×q¯“U“U“Up^}^}^ ;Âv„íƒY³ fÀ’3KÎ,9ûŠ÷ï+qDG^áÀg9ËYر'bO 4,<xºªºªºªp$äHÈ‘X½sõÎÕ;¡Ã½÷:܃qÝÇu×,¾³øÎB�w$$‰Dòn‘:þIUVWY]e5ôë߯¿þ0bÀˆ#@‚U‚U‚èŽèŽèŽÀÑíG·ÝE}õQT¡ e•Ë;?Üùáΰjܪq«ÆA4ÑD ’$/H†ºñuãëÆÃƒrÊ=(“£&GMŽ‚:]ët­Ó†è»Õ$‰Dò®‘ €?)µVj­ÔZ°O»O»O ɺd]²tttʶ‹þ1úÇèáPÌ¡˜C10»ÕìV³[ýfØËÿ�»9wsîfX¾~ùúåë!Ú Ú Ú ìõC¡‡B…‹¹/澘 [3·fnÍ„ *L¨0Aß­$‘H$’w�ôàÒ”Ó”Ó”ƒ­.[]¶ºÀžÏ÷|¾çs(½_z¿ôþn/E „ý“÷OÞ?â«ÅW‹¯ö¿�#6‰Mbì•í•í•Áᇇ~øäy¬y¬y F>ù`$ܯx¿âýŠún%‰D"‘ü]HÀ¤<¥<¥<ý¦õ›Öo,˜²`Ê‚)Pëv­Ûµnƒ²Ÿ²Ÿ²à„Ne?]7ºnt]øÁùçœÿ÷q"®G\�¸«ìWÙ¯²‡ßßßßß>¥CJ‡”°Äm‰Û7HZœ´8i±¾[K"‘¼Ë´•´•´•à6·¹ l-ØZ°µ^x¿ð~á ‰mÛ$¶�£ŽG�:B‘c‘c‘£¾Sÿqâ¬8+ÎBìϱ?Çþ [“·&oM†Ø5±kb×è;Ý»C*þ(?üð�&M<šÀ´øiñÓâáÈ´#ÓŽLƒ¯ž|õä«'àŸæŸæŸ……… Ù­Ù­Ù J”(…'ñOâŸÄÿçîsäÈ9_5ýªéWM!ºKt—è.¿ÙÀwÜÁæšÍ5›kÐHÛHÛH SÛLm3µ Ìm6·ÙÜf`ó±ÍÇ6ë»±$É»LÑUÑUÑÌ›6 ße}—õ]¤L˜:ò£ó£ó£á±ö±ö±4Ã5Ã5Ãõ�ú�“%Êe‰`ooG§�~t:Üw¿ï~ß]ßéÞR€¿H¦•ieZ¨@*“MZ4iô ìØ3‚rƒrƒraWæ®Ì]™p·ÜÝrwËÁžÇ{ïy 'œ8p"ÈzÊzÊzÂÁàƒÁƒáÇøãŒÇ*ŽU«€ÏŸ->[ e£–�Z6‚¶°ýƒíà›ê›ê› å”[Pn�¾[C"‘ü¨W«W«WCFqFqF1¨}Ô>j�eɲdY „ƒp—d—d—dèÚ²kË®-A©ŠTE‚ÎFg£³�”€”€”(ú²èË¢/Á¦­M[›¶`³Éf“Í&~]D'3(3(3²ÏeŸË>º5º5º5à0×a®Ã\0bþÄü <�zõ< Ô7Õ7Õ7Á`´ÁhƒÑàìâìâì­ Z´†ìÙ=²{€±£±£±#ˆÚ¢¶¨ ö­ì[Ù·‚¢Ò¢Ò¢Rx6âÙˆg#@÷µîkÝ×@<ñăü”ü”ü�Aú¾ú'¯Ë\æ2\pÁ¥¥¥„®Ãºë: Ž8q:âí7Úo´‡íÛ¶oÛ¾ dgdgdgÀÆÍÆÍÆ æl�³uÎVh6¸Ùàfƒ¡ê ªƒª³êfÕͪƒì¨ì¨ì¨¾OV"‘ü�¤6MmšÚÖ²þ“õŸ€óç ÎÀÐÀÐÀЊ½‹½‹½|ð�‡!C†À¬€Y³`m¥µ•ÖV‚§Ëž.{º N>9ùääðî3Üg8X˜X˜X˜@Ï>ž}<áA¥•T‚}“öMÚ7 ¼"¼"¼" åVÊ­”[PÙ¢²Ee èNwº»÷íÞ·{˜_7¿n~î4¿ÓüNsÈÈȆJ¢’¨$`Ú·Ó¾�ö-tJì”Ø) à à áKR—¤.I°Ûd·Én�ÙÉìdvP¾¤|IùPWWÙzÙzÙz}_�w‡T¼)¿,'i�=ö@ç�t߸~ãú�+Ä/�_¿8Æ1Ž�£«£«£+Œrå:ʬ¿³þÎú;`Ó˜¦ï“‘H$gǯ¿rü d]̺˜u´YÐfAÈÚ™µ3k'쫳¯Î¾: ³�YÈ,À£šG5�j "D„ˆ]w]w]w¸¾ùúæë›!{öþìýйSçN�;�Q=£zFõ@+‹•ÅÂÎØ�±;c¡ü€òÊ€ÁîƒÝ»ÃóóÏÏ??C3†f -Ë×9»svçlð8çqÎãl Ú´%.X_°¾` �W4^Ñxˆú¢¾¨�~lôc£¡ê�ªwªÞ�Ëc.�¹<nn¼¹ñæFØ:ëü­óÁ¬§YO³žð½ï÷¾ßû‚N¡Sèú¾ï©À[¢ì¦ì¦ì&L&˜üÃôL{˜ö0íÊpe¸2\ßi%ÉûäéÇO?~ú18¤9¤9¤�â”â”âˆÕbµXýüÀËÕù<ðÀt‘ºH]$t{ÔíQ·G {¬{¬{ ãÖŒ[3n =zôJ»–v-í ‰‰‰àúƒë®?”íÖ~¨ýPû¡PeR•IU&ANßœ¾9}áZܵ¸kq°åô–Ó[NÃÏ?{üìºiºiºi f‰Yb(((€iwÓî¦ÝÁl€Ù³�¶3mgÚN0ogÞμ˜'˜'˜'Ÿó9Ÿë»õß]Rð–”ëV®[¹nЫ_¯~½ú�gÏžÀû’÷%ïK8.p\à80/1/1/ÑwZ‰Dò>1ílÚÙ´3äËòeù²ß¼ @�d#d#d#@ÖUÖUÖÈ%—\`"™ô¤'=Ái¡ÓB§…ðMÖ7YßdAmm-|sè›Cß‚´‚´‚´°j5Ôj(dÅeÅeÅý~®óKÏ/=¿´¬ïSÏôžé=Ó¡þÝúwëß®r•«€9æ˜øâËoFG™ššB±g±g±'h‡i‡i‡†b4§9Í�)Laо¯Æ»C*Þ2]]]ø´ç§=?í k»¯í¾¶;Ä-�[·2údôÉè£ï”‰ä}Ø+°W`/x^ëy­çµ È È È"U‘ªHäÝÌ»™wž{=÷zî S¦$Lµ¿Ú_í)ÚmŠŽ/:¾èø"8õìÔ³SÏ pzáôÂéPÅ¿Š0w7w7w‡®Çºëz Â’Â’Â’àT‹S-Nµ€›#nޏ9^ô}Ñ÷E_0ýÐôCÓ¡ôQé£ÒGðàÒƒK.AÆÍŒ›7!7?7?7ž< xêGêGêG�\>¹|rù²óó›â7Åo ëŒuÆ:8xèࡃ‡ |Iø’ð% .R©‹ ccÆÆŒ�ú¾ï©À[R2¤dHÉHˆIˆIˆ�^›zmêµ ~Óð›†ßÀO«~ZõÓ*8zðèÁ£aæïЉä½àWÓ¯¦_M0b2Äd¤vJí”Ú L›.6] óÒç¥ÏK‡òOË?-ÿD�(0wÀÜs€Ë*—U.« ÒµJ×*]ƒÇ9�sç€ÌWæ+ó…ù…ó ç‚u¢u¢u"^ ¼x\|]|]|!ezÊô”éPšSšSš¥GJ�”�ƪƪÆ*0.5.5.…Ò“¥'KOB`ÏÀž�=¡ñµÆ×_‹‹‹øÌé3§ÏœÀõ�ë×À.p*l®°¹Âf˜õÁ¬f}±þ±þ±þ 3Õ™êLaꆩ¦n§H§H§HЭҭҭùdùdùd}_=’·"1'1'1Gˆ¡ ý`èB¤I’:¤ìõÈÐÈÐÈP!®¸vàZ!âââô�Z"‘¼K6lØ Äʽ+÷®Ü«ï4ï¿dïdïdo!>êöQ·�º ‘¶1mcÚF}§z}¤GoIL¯˜^1½ÀJi¥´R‚�…�…�EÙëÕÛVo[½-Ôɨ“Q'öwÜßqGІiôaúN/‘H$’÷�T¼%?üp0TJ©”R)«««³A@Ï[=oõ¼Ñ·£oG߆ÛA·ƒné;½D"‘HÞ7Rð†­/Z_´ýôè§G?�ïPß¡¾C{—c.Ç\ŽAëÂÖ…­ aàþÀý�P¬,VK=6$‰DòšHÀ–Ù7³of_P—ªKÕ¥à¾Ñ}£ûè…Ú¾iû¦í›BATATA„œ9rBßg#‘H$’÷…ô�ò ‹Û·9n3˜�1c6k8Öp¬ñ¿Îb½Åz‹õн {A÷8píÀµ× �mÛ¶`�a�a-Íe-‘H$’¿Hºð†EÞ�¼y<Ò<Ò<ÒÀp¼áxÃñüç?”}(ûP¶m;Úv„c-޵8ÖBßg%‘H$’¿;©xC´>Z­ĉ8' Úºj몭ûóû146464†¾ô¥/²3dgÈNxòõ“¯Ÿ|­ï³”H$Éß•T¼!©±©±©±�Ý"»Ev ¨ò´ÊÓ*Oÿúþ|‹}‹}‹¡æƒšj>€ƒŠƒŠƒ ŸˆOÄ'ú>[‰D"‘üÝH}Þ�„ 3f€iÓ¦Àú[ëo­¿ýëû“id™zm赡ט;sî̹3!"$"$"jS›Úú>i‰Dòfý²HObbbbb"Ü^{{ííµ IÕ¤jRõîÿM ˆ’ – E–|¼|<”¬×~¤ý¸Å3ž²W<Îk&3�È mpÚà´ÁP¬.V«�RHÑwº×G*Þ�û÷îß»<*{Tö¨ Æ9Æ9Æ9¯¾ßòcÊ�)?ƒƒƒ`ŸÓ>§}NPµ¨jQÕ"042424Ò÷ÙK$’7¡¢SE§ŠNp¹Åå—[ÀÕÕ0“™ÌÔwºÿ$ÎÉÜeîà0&=1=›¥¤@d�Ê]*w±M>A>Pþkùôw†^xAéîÒÝ¥»ÁÛÍÛÍÛ ŒÜŒÜŒÜôîõ‘½œPßAÞ­F«Ñ¬Ÿfý4ë'háÒÂ¥… ´öníÝÚûõ'K—¥ËÒÁÌë3¯Ï¼]Óº¦uMƒÖ]ZwiÝEß­ ‘HÞ$'âDÜË©ÜSL1ÕwªÿC‘ÜIî²U×ò¯åƒlÝ•W^€.k‚çO @ñBñø×Thï-Z´ «'«'«²ƒ²ƒ²ƒ@cÓXßá^éÀk–3/g^Î<ȼ˜y1ó"xUôªèUØÅ.v½¾ãXË­åÖrèÞ¶{ÛîmáÙ²dP?³~fýL°j=Ôzè«G"‘¼{d2™È�½kwÏÿokþµkj]­uä–Xb ¿üß»çÙ/�(ÞSR'À×,&8&8&Œ�Œ�Œ�ÀÕÅÕÅÕåÍ/à|Àù€ó`bbA©A©Aïâ³@‰Dò¦ˆUÄÙÙКÖúÎ$‘î¼f·>Üúp+¸á† ª©ª©ªùæŽgTר®Q]è÷E¿/ú}«3Vg¬Î€&FMŒš�[‘[‘[‘¾[E"‘H$ïéÀk¢©¯©¯©Ñ3£gFÏßM¾›|7½½ã× ªT+ª-©¶¤Ú8u0ê`ˆf¢™h¦ïÖ‘H$É»F*^“¬¯²¾Êú ^¬|±òÅJ¨4ªÒ¨J£Þb€«\å*ôÌè™Ñ3¢ªEU‹ªw»Þíz·«¾[G"‘ü³e$f$<Ì{˜ vˆúÎ$‘ €×$).).) ‚þչũԩԩôíç¨àTÁ©‚4—7—7—ÃÞV{[ímEQEQEQún%‰DòÏt?å~ Àþ°ýaÚ"­ôhRï¤à5‰Œ�Œ�Œ·Qn£ÜF�y=ózæõô—§ãŽŽ;:î€LËLËLK¸¼éò¦Ëoñ‘„D"‘”ñ¾ã} sÃÎ ÁŠ`}g’HÀ«zÈC£•�V>Z >—}.û\Öw(°îmÝÛº7t¿ÐýB÷ pxßá}‡÷AÎМ¡9Òð@‰DòV9Œt P[U[ ;";¢ïL©xEõ2êeÔƒÔìÔìÔl¨Þ¸zãêïÐDÍŒ›733S3S3S8|"ø„TyK$É?žT¼¢D—D—D0˜c0Ç`8:;:;:ë;Uî†] »Bï½ô~Á‚/_€¤“I'“Nê;�D"‘HôE*^QLó˜æ1ÍÁå;—ï\¾³efËÌ–é;Õª}²öÉÚ'¡ŠeË*–p°üÁò˃è%z‰^úN'‘HÞo¥ÊR%@Þ´¼i¬a�¾3I¤à/*¡*¸v?ì~T­YµfÕš %%{›Ãÿþ yyyèãÒÇ¥� Dˆ! raäÂÈ…úN'‘HÞo‘7"o|7ø»ÁÚ;Ú;úÎ$‘ €¿¨`iÁÒ‚¥�z8õpêaðí9Ús´¾Sýo444Ðì`³ƒÍÂþšûkî¯ ¥¥¥úN'‘HÞO†‘†‘–,;ðŸé;“D*þ¢§¹OsŸæ‚X%V‰UP1¼bxÅp}§úãºìí²·Ë^Ȱΰΰ†Ÿ–ý´ì§wðÑÅ{C À!qÈ%—\}‡’HÞŸ^>½z,è±@‘ª�Ö,Ñ;©ø‹bæÆÌ�™ jµƒÌlÍlÍlõ�ê�³Ž·Ž·Ž‡.‰]»$Â?xüàj™Z¦þ[,/ö'ýòœµ,kYÖ2Èú$듬O€<òÈ{ó‡�5�5�5…õ Ö/X¿B¢C¢C¢!gÎþœý�-Ë–eË@ÓGÓGÓRî¦ÜM¹ ©—R/¥^‘%²D–¾Q"ù«Æ cÕ@Õ@Ð@ß™$RðÅ�;<<<<<<@ö‰ìÙ'úNõç5MošÞ4LƒMƒMƒ!È$È$ÈDߩހ4ÒHƒýÁûƒ÷þÚûjï« |Ï÷|ÿ'ö³–µ¬ííí �tÒóÒ¥=J{À¶Ôm©ÛRÁòk˯-¿»svçìÎÁž–{Zîi >:ðÑ�� ô\é¹Òs°?räþH˜?;~v<”Î/�_:„¿ðþ »§»§»§ïF•H$gRð'å‡ä‡ä‡ÀÓ½O÷>Ý UVXe ¾SýuÆÎÆÎÆÎÐ÷iß§}ŸBð§ÁŸ ‰÷ï%¾Í˜Ãæ0°„%,ù/Û½\Ÿ{8ì`+øõžÜàÆÿñs…R=Œ{÷0†^“zMê5 ðÆoÊnÉË·|ËïQS£¦FM…C·Ý:t pÆg@ƒÍn_|¤øHñ¸ïwßï¾x|îñ¹Ççà;Ãw†ï è!ï!ï!‡îÝ=º{€ñ ãÆ/ b¿Šý*öƒ‚K— .�¦¹¦¹¦9üpþ‡ó?œ‡û“ïO¾?ùÿ8Ï$’HÖ±Žu@>ùäÿ¦ÝÂ#ì-^W‰DòÎ’–þ“²eÊTö‡Ù9Þ9Þ9pÅW}§ûëjM¯5½Öt¨ººêꪫá‡Þ?ôþ¡7LΘœ19H%•7ðÌ.jKÔ–¨-<8xpð`�È äPDZŽcGhò¬É³&ÏàŘc^Œ�OO<=ñ à à à Ç8Ç8ÇŠŠŠ!üVø­ð[ÀzÖ³ÌsÍsÍs¡jXÕ°ªa»:vuìjHß’¾%} Î œ8 ¶ïÛ¾oû>ðœä9És�G¶G¶G64Ðd@“°1mcÚÆ4x2ëɬ'³ÀaˆÃ‡!Ð4 i@S�_–_–_í!í!í!¸9ðæÀ›!þLü™ø3pjë©­§¶‚õbëÅÖ‹!Ì+Ì+Ì 2FeŒÊ™ÈD@ÖJÖJÖ d¥²RY)Üm|·ñÝÆ°êÒªK«.AËo[~Ûò[°üÁòË€Œ`ÙÙÙAqûâöÅí¡b�Š=*ö€ÆA�ƒÁ·U¾­òm0¬iXÓ°&˜ô7éoÒêÖ®[»nmˆsˆsˆs€¼ªyUóªÂíí-È d²}¿K%_OƒžÄŸ�? ФK“.òfriµR½‘îüI�ýû?ö³;fwÌî€Ã‡ô�êÕ)  è­ì­ì­„ïïoˆôŒôŒô|sÇݺqëÆ­¡`fÁÌ‚™Ðõ^×{]ï�õë)ÖS@»X»X»6�Þ4zÓhH+L+L+„~súÍé7üÛú·õo Ê…Ê…Ê…�»=w{îv;v.ìT_W}]õuPηœo9_0ô1ô1ô�K/]¼tlNÙœ²9w«Ý­v·x®ð\á¹ÚVl[±mEø®ùwÍ¿k òy‚;,vX ž½<{yö‚úíë·¯ßä]ä]ä]~Óž– K…%T?RýHõ#à sÐ9è ±wcïÆÞà3Óg¦ÏL0ð0ð0ð€+í¯´¿ÒtÁº`]0`‹-¶ މc┿PþBù `2ÍdšÉ4h¼¾ñúÆëÁÁÄÁÄÁÖëÖëÖë@µMµMµ ºEt‹èû£÷Gï�†§vOížÚAήœ]9»àV—[]nuߎ¾};‚±»±»±;ZZZ�Ñ7Fß}8à€ƒ¾ß�’¿¿Ä+‰W.…^ Ð%ë’õ�I"Ýø“îgÜϸŸ'UœTq¨òUùª|}§z}*L®0¹ÂdhæÞ̽™;ìÍÙ›³7Ú,´Yh™™™¯ïx•¾­ôm¥oáè•£WŽ^ëÖ¬@—»üØåG(iVÒ¬¤Üì}³÷ÍÞ0!{Bö„l°¸`qÁâ4ªÙ¨f£š ìªìªì ö\Øsa8Vq¬âXê9×s®ç œà'àÞÇ÷>¾÷1ȵr­\ ÎÎΠܠܠܦ�M›>ïÞ+¼W€Aƒ:uàiå§•ŸV£F+ŒV€Q®Q®Q.w6îlÜùÿ8±@ £Ï�>7ú”6J¥ ˜M2›d6©l3Æ €OŸú>ú>ú> f‹Ùb6hJ4%šˆ÷�÷�÷S7S7S7¨<­ò´ÊÓ@Ö_Ö_ÖrBrBrB ¨{Q÷¢î€/¾¼¤ Ô‹zQ/‚á¡á¡á!hNhNh~¶“~·~·~7èóõùú|Ð × × }Ž>GŸzk½µÞŒ®FW£+•F¥Q ™3f>F0‚PMYMYM 6Ø|`ó4^ÛxmãµÐÆØÆØÆ®½\{¹ö�—ÎKçº"]‘®pÁà‡8§RN¥œJ�ƒ�>:øÄ01L 3÷Ñ(‘Hþ Rð+¥†¦†¦†‚E„E„E¸ qâ6ÄÜ©þ|-η8ßâ<(w(w(wÀ‘ýGöÙÿêÚ×xj<5ž°µÞÖz[ëÁ½Ýû×½Áè°Ña£ÃÀYt�Eøðø‡Ç?<ÊÆÊÆÊÆ°©Æ¦›jÀ·nÜ ªOTŸ¨> ¨¨vìØ€¬‡Y³B‰K‰K‰ änÈÝ�»*l«°­Â6H—8.qhkkÙ¹gæž™ ‡px :?èü ót2èdÐIhÕ"ªEXí·ÚoµަM;š†å†å†å¥ý5¢FÔ@lýØú±õÁwŽïß9�\˜\˜\NNN�×"¯E^ ðªêUÕ«*Ü]~wùÝåPP£ FA ¨p¸Âá ‡!gzÎôœéУe�–=Z•¡W†^ ±§bOÅž‚Q¦Q¦Q¦ÒþmHÙ�²!N49ÑäDH«–V-­X�´i5¬}¬}¬} kjÖÔ¬©@':Ñ rå4Êi™µ3kgÖq±¸X\lî£P"‘ü)Dɯ²?þþ|Qœž5=kz–(›››™;Õ_çö“ÛOn?Åwn¼sã�¢˜d™d™dù Þ n7ˆ¢ñ}ãûÆ÷EѨ5j�ZQ�¢Q4¾dû1D Ec;c;c;Q4n7n7nÅ7ω¢Éd2™L¢hÒ˜4&�(ŠƒÅÁâ`QW‹«ÅÕ¢h:n:n:.ŠâXq¬8V Ož(�™›�%d YÐ{xï὇Ãý”û)÷S ªCT‡¨¿Á| ž1ž1ž1P>´|hùPhÚ´iÓ¦M¡}›ömÚ·µ�ÚFmò»ò»ò»Ðãh�£=ŽB½óõÎ×;‰Q‰Q‰Q ºŠ®¢+nܸ’ܓܓÜA®ׇÃöÛlƒÁ`0ÀØÈ±‘c#!ýlúÙô³p¸âኇ+š{oH$¯ZÍìšÙƒ|ùțɛ™;“D*~ÁÓÞO{?í ®V¸Zá*ØL±™bó7œèæ¯æ»Òw¥ïJh]к uì(¿£üŽò ë©ë©ëiîtÿ›ðXx,<a�°GØSúsE%E%E%pëèÖÑ­#x›¼MÞ&p™ê2Õe* GŽø’/ù„`!XÁOðüøiµ½è~Ñý¢ûAÊÑ”£)GápÜá¸Ãq�ïžïžïùùùÒò»’«æVÍk:¾øæ?—¹æÎ$‘.ü‚d‡d‡dðÞê½Õ{«¹ÓüýtÝet—Ñp-àZÀµ¸°öÂÚ káMÞäMs‡ûo*R‘Š ôz=€cãˆb�Xœâ§øÏÅJ(¡УG˜0aЀ@yÊS¬*ZU´ª^ ^ ^ Pkz­éµ¦CpApAp¸îsÝçºï7§–H$’ßLø à à à cBÆ„Œ àwÉï’ß%s§úûqºïtßé>t¿Ýýv÷Û°çæž›{nB�²@Y 4wº_f½Âz…õ ˆñŒñŒñ„äJÉ•’+�ºžºžºL+˜V0­t{›�6;mv‚°SØ)ì„g¹ÏrŸåBŽ,G–#m’6I›�F£Ñ@SUSUSäTÍ©šS   Ài™Ó2§eàpÏážÃ=sï‰DRHÀÿ“ãžãžãEˆ ¿¹~sý¤¡ªß­ù¶æÛšo‡3fÀÁo~sðs§úeﺽëö®8éü¥ó—pëØ­c·ŽAÓˆ¦M# Ü¼róÊÍõxõxõx¨Ð¢B‹ -à£-mùh ÄÆÄÆÄÆ@ARARAô¸ÓãN�;`J0%˜ ‡U«VÐrCË -7Àå›—o^¾ ·çÜžs{ä+ó•ù¯q�$‘ü>Ùõ³ë<ýp4€8KœeîLi5Àÿ'꣨�¢>ÅÔ¨?P‹bþ§ùŸæjîTwÞYxg¡(òä?È_§$NIœbîT‰ä¯q©Â¥ ¢(Š3GÍ%Š¢¨ß¨ßhîLiàÿÉø:ã댯Áþ¡ýCû‡`›o›o›oîT!÷Cî‡Ü‡î5Ük¸CøúðõáëA¼ ^/˜;�D"ùsååt[Úm)€ü¶ü¶¹3I¤Å€þŸuOÖ=Y÷´ñÚxm<Œj?ªý¨öæNõÏ‘XœXœX 3¾ŸñýŒïaÜúqëÇ­‡�ë!×C®›;�D"‘”ÒÀL·L·L· Õ*Õ*Õ |ßñ}Ç÷s§úçñUú*}•ÐzPëA­ÁŽG;íxº¡º¡º2¸Ì²D"‘˜‹Tü@¿W¿W¿²]²]²]Àk¹×r¯åæNõÏÕ©o§¾�úB~×ü®ù]áüÜósÏK7[J$É_F*~�›”›”›š0M˜& *4©Ð¤Bs§úçrÞí¼Ûy7t�ìÙ=öøïñßãùŠ|E¾4;…DòcúÒô%€>N@QæÎ$‘þÔþ iPÒ ¤A`ãdãdãnsÜæ¸ÍÖ±ŽuæN÷ÏÕ¼Mó6ÍÛÀiñ´xZ„C^‡¼yÁ@2ÐÜá$É+r§ò�Ê×][0"jD€ü²ü²¹³•]ÒÀÒê¤ÕI«î­Ü[¹·EEEs§úç³^j½Ôz)ôóèçÑÏÎÎÎ ñlâÙijæN'‘H^ ›6\º4`3›Í�I"?xþéóOŸ î5Ýkº×!TBÍ�ªì¨½¾öúÚ롆¼†¼†vÕÙUgW0L“âtqº8l½³õÎÖ; ^¯^¯^oîÔ‰äß©�¨�<Ž| p¿ÒýJú#ú#Á™Á™‡=pß÷¾/@úgéŸp©ðÿË”ùK¦K¦K¦K�ê”ê”ê�>hôA£Ì�ª Š#Ž8x[ö¶ìmÌHž‘<#æºÏuŸë{Ûîm»·-�)S<ZšZšZšÀg˜Ï0Ÿaæ/‘H^(nVÜ `Ò²IË"s"säå(¢€B „îBw€ "Þžõ¶4Cà_¦Ì�¨ƒ€Û·þË¡êêê7#nFÜ s§—H$/WK]K ’’ð²ß[ݳºж^ÛzÖ“¬'™;sÙSæïÈØ’±%c ععع€ýöoØ¿aîTe‡ì;Ùw²ï =íi¸½­ÞVo «V9¬‚)G§�rôwôwôwà ÷AïƒÞµ0jaÔB° ¶ ¶ ý—ú/õ_‚éˆéˆéˆÓÄiâ4@�5˜,M–&K“Åd1°ÄK��•�•�á°pX8 ä“O>�„GÂ#�5’5’5Y¾,_–r'¹“Ü ^ /…Èmä6r�+åJ¹òÅüfòË`!·�[ÈÁ"Ã"Ã",>°øÀân 7…›€ ™T†K^¦^¦^â^q/€´ú”••Á.Ü.Ü.”ß)¿S~à˜ã˜ã˜ŽÏŸ;>'£“ÑÉ.^.^.^àô™ÓgNŸ�¥µ¥µ¥5(J%ŠPLTLTLr�ƒæ>J$¯±‘Œ0 0 �}/û@¶TöÒÇjó?Ïÿà›sßœð\á¹ WÝ^uäEò¢{ÁÏùŸJ?•••r(ä@û í+xVóü·»þSv§ìX&,ºEt‹}?ô¥€æKÍ—çúŸë LT&4y»ÉÛòy‚¹wõë¯Ì*µJ­RƒÊ 2¨ à¶Ëm—Û.s§2ƒYÌb”$•$•$A¶W¶W¶d·Ìn™Ý²Ä,1K„TMª&UÏeÏeÏePø´ðiáS(©SR§¤¨�j£ÚB€ €…�…�… (]”.J°³³åyåyåyPWW‡rËÊ-+· Á1Ø1Ø1ìFÚ�´ qqq`QÛ¢¶EmP¤+Òé¼ø36t¶:[�-8�r:åt dMdMdM@^S^S^³ôüOßôd²�õ’õ’õzÑ‹^`’™d&˜››å(G9+‹•ÅÊ`ÔµF-˜œLN&'0\1\1\c#c#c#0ô5ô5ôC¬!Ö †­†­†­ ½¡½¡½%‡K—†‚'O ž@Á€‚ XY¬,VBöÑì£ÙG!¾y|óøæP\\\ºõuôuôu%J”`÷/»Ùý ”¢RTŠàÐÍ¡›C7ðœè9Ñs"x½åõ–×[à†n€›£›£›#¸Íu›ë6¬—Y/³^T¤"Í}Jþ:OÖ?Y°óà΃×w\P�z/Ý޲в a§†�ʯ-¿@ö­ìÛ—¾ÀG€®]»vèP©C%ù7òoBo…Þ°heÑ €K\¨è^Ñ`ªvªÀ~“ý&6°á¥ï³œå} úä?Ì`ªoª GþÒ—ÅŨ>U} ô(è€åBË…æþlþz‚øsù«eÍ<šy&§LN™œ³Sf§ÌNïÙÞ³½g›;ݧÓét:Ì)˜S0r;ævÌíq¾q¾q¾ççç©…©…©…�{<÷xîq0 `›b›b›öÍì›Ù7ƒòKÊ/)¿Êo(¿¡üp q q çsÎçœÏ�s[ç¶ÎmÁÙÊÙÊÙ ”ÙÊle6țɛɛ�à(8 ŽÀ¦0ÅÜ{ç5¤C‡Îp†—ŽLè·è·è·@QvQvQ6äåæåæåBÞ„¼ y ¯^^½¼z�»5wkîVH‹I‹I‹�,§,§,'(®]\»¸6¨ë¨ë¨ë€eË&–MÀí¶Ûm·Ûà£òQù¨ `wÀî€ÝàëãëãëÎöÎöÎöàøØñ±ãc�Ë‹åÅæÞI’ÿ¤R¨™V™VîÝ;Ø}o÷ý˶O_‘¾àq½Çõj6¬ÙÀ]î.ÿ5ï÷ÚùqfÁÛ¼x|¸9Í~éÒÚ¡7½ pó½›ïŒx6â€ç4ÏiæîÊ_¯ÌñOãŸÆ?…yÌû`Þ0ÿÊü+󯀛ÆMã¦1wºÿ⇙óô¹ú\}.äœÎ9�sbâbâbâ æTÌ©˜Sð´ÒÓJO+AþäüÉù“ùé­ë)×S®§ âÁŠ+„Š[+n­¸|×ø®ñ]<:xt›t›t›t°jnÕܪ9(ÒiŠ4Ào¼Í½$¿h›Øúæúæúæ }¦}¦}ªªª�f“f“fIg’Î$��ÄÆ‰�C²²²?ä7ÍošßäÃåÃåÃÁõ#×�\?‚Ày�óçAÐ¥ KA— ðaàÃÀ‡à´Êi•Ó*�?�?�?0wçË¢ÓOO?8¼ùðf€1ãÇŒ¨äRÉå4û�eìiì  m¯m`}Þú<¼x ùeÛ? yP¸¢p@íwj¿/Æ&ÍÝ—?®ÌÒ¤?H‡U™«2WeÂüÕóWÏ_ Žk×8®1wºRùÝó»çw‡g Ÿ-|¶ôyÐçAx4ùÑäG“!Lþ˜ü1`?ß~¾ý|ðËñËñË�ê7«ß¬~*~Vñ³ŠŸ�ëb×Å®‹Áñ�ãÇ ».».»nîÞI^†-†-†-�••9á9á9ággg�Ë=.÷¸$®O\Ÿ¸4Aš M¸·poáުϭ>·ú\¨î\ݹº3øò?ä”ã•ã•ãÍÝ»¿¥-lJWÍû…Er —.ÐÆhcÜÂÝ„L!ÓÜ]ø'¸¼üòr€#ïyà›l|EßÀY³Ì7ÎÞ8{ã,ìè´£ÓŽN0ïü¼óó΃mÛ¶ þ ‰$’ý úô‡è6Ñm¢ÛÀ•5WÖ\YOÝžº=uÅÅÅð/ð/ð/€�¸�¸�8ºt+è”Ï,ŸY>ä£ä£ä£p0÷^–ücüðT„~Œ~Œ~ ¤,OYž²žÄ=‰{÷zßë}¯7$ÖL¬™X„^B/¡Ô8^ãx�ãÐtWÓ]Mw�ÿ}ÿûþ÷AYEYEYÅÜ�zeîÈܰ§ÞžzÍC›‡TO©žbîleÒO…i“µÉББò(y”¹£ýqe¶8£;£;£ƒ N,8±æŽ�;vîX°PZ(-”Þûšô&½I‰S§$N�3ò3ò3r¸UÿVý[õA$’A-«ZVµ¬ ©eS˦–àßÕ¿«W°™b3Åf ½…ÞBosïE‰äÓMÓMÓM(™Q2£d�»4wiîRpÚä´ÉiXT¶¨lQèK_ú¾º÷1í4í4í„ÇÅ�‹Ã~ÇýŽû!6*6*6 ãããa¨õPë¡ÖÜ;¸wpoPÞWÞWÞªP…*À]îr×Ü{M"y9YCYCYC°?nÜþ8Ô§>õ�úsëÏ­?ò*çUΫ QU¢ªDU�S§NÀ©¾§úžê !C:†t„ÎÓ:Oë< *eWÊ®” t§;ÝÍÝ»¿Ru�êÕÕÕÕ|Žtâÿ�ùÈ|ÒÆ¥�ˆNŠNøÐãCùsùssgüOev`eñÊâ•Å ¨¯¨¯¨ïG¿ý~ô«k?ùJò•ä+°³æÎš;kƒº>º> �«�«� Ø`ƒ�¹ÃýŒ'žx‚f‘f‘f”¼[ònÉ» mªmªm „Nø¾L^]^]^‚݃݃Ýa쌱3ÆÎ€É™“3'gBbdbdb$L1}ÄôpG¼#Þù[Mɽœ{`éÂ¥ âóãó{+?.�­9®9®9†u†u†u¯.¥q¡q¡q!Ü n7/‹—ÅË “éd:h“´IÚ$ Œ0ÂþK;3Œ3Œ3Àà`p08�xÄ£W¿Wu™ºL]&œ»îþ¹ûpìÆ±Çn€ÁÖ`k°}7}7}7SÄ1ôžzO½'heZ™Vâ q†øJW•]•]PvUv^ÓÿOÄ2Æ8Æ8Æ8FgXͰša%ЇòåÊÿýí½8EqKì–Ø-±¢øNÊ;)龜â9å9å9¥(êô ús÷ºÔ¹£çŽž;*ŠŸ7ú¼Ñç�DQí®vW»›;•äÿÓŽÓŽÓŽŽå÷–ß[^‡ì²sÈNQÌœ�9!s‚¹Ó•ŠËŠËŠËÅù æ7˜ß@W8­pZá$Šs®Î¹:çª(^¯ˆW~G»êXu¬:V÷<ÚóhÏ#Q(Š¢x¼õñÖÇ[‹¢é]Ó»¦wÍÝûßâÉì'³EQ74ÝÐTE±È£Èã··’Ó!§CNQ:>t|¨(n¸´áÒ†K¯.å~q¿¸_ť喖[ZN‹N�(:!ŠÛ4Û4Û4¢8¼hxÑð"QÌÿWþ¿òÿõËíì3î3î3ŠâÒw—¾»ô]Q4Øì v¯~¯õ9êsÔG§ë¦ë¦ëDqÿÐýC÷Å+=¯ô¼ÒS§_�~uúUQÌmšÛ4·©(žíq¶ÇÙ¢8àÒ€K.‰blNlNlΫÏõËÔŸª?EQT¥ªRÿÊ÷}¹27` 5…šBA³Z³Z³ìªÚUµ«úûÛ;æ}Ìû˜7\­zµêÕª0}êô©Ó§BË¢–E-‹@á«ðUøš»×¥ªÜ©r§ÊxkÌ[cÞ–³,gY΂‡3fÀ ý ý�಺b¦˜)f•®Wº^é Ïv?Ûýl·¹Sý2Ë/-¿´ü÷î Ü 5j&ÔÝÝÝ€W¸_œEgÑJn•Ü*¹¦ë¦ë¦ßðx¨æºæºæú‹ÙWšå}”÷QT_R}Iõ%°²áʆ+‚æ ̶͚߰µ¿µ¿µ?t¯Ú½j÷ª0:ptàè@Ø%ß%ß%‡ë®¸þ ÷߯Š];€÷z¿×@™¡Ìøí­¸v9ìr)ŠE ¤�N�>úÕ¥ ù äƒ� ´Wh¯Ð^ l«l«l gΜ…xM¼&^†w ïÞ…;º;º;:¸¿äþ’ûK~ÖŽ"†ˆ:4thèP�͓͓Í{õ{õÚÅk¯]ûÛö·íoC—ð.á]¡r§Ê�*w‚NC; í4ì·Ùo³ßÁ¾Á¾Á¾�z'õNêP_U_U_}õ¹þKâã׎,ê·¨€!Úð /=ÿVeî&@SgSgSgЖӖӖ›Ý6»m~lj ¹yróäæp¢ß‰~'úÁÈé#§�œþþþ¿?ßC÷‡îÝáü§ç?=ÿ)4¬Û°núPYýeõ—�v±v±v1XºZºZºBü¤øIñ“àVŸ[}nõýýý°:guÎê8=szæô œª8UqªòŠòŠòŠóȧ1‚˧.Ÿº| K{-íµ´X °`5k;Öv¬ +V¬„ËŸ_þüòç�^+½Vz-(—P.¡\´¨Ó¢N‹:`‘`‘`‘ðëûùTþTþT·Êß*«<ð Ÿð 4nÛ¸mã¶�q%ãJƸ»õîÖ»[_Ìú>x´ôhéÑÎÌ=3÷Ì\Ì Ì Ì„r­Ëµ.×.Ö¿Xÿb}ÐËô2½ j=«õ¬Ö3°zßê}«÷aÞ¦y›æm‚æš_h~ÞúÎÐw†‚ÝWv_Ù}çûŸï¾?ª Õ…jjÔ.¨Ô¨R£J�*p¢Ï‰>'ú€fšfšfØ{Ù{Ù{Az`z`z TЍQ)T§T§T§ ×"×"×Úßh£ý (׸\ãr�ý~’} û@ö‘B¤YºX‘q•q•q\µ¾j}ÕÒ†¥ K–�-;[v†¦ò¦ò¦r(÷´ÜÓrOAã¢qѸÀÅ‚‹ '3'3'òæ7Ìo>×|®ù\ƒv}Úõi×çׯQ40h`Ð@~šhêGî)î)î)P (P(Ààdp28ýþÿ.ê?­ÿ´þS4{ÐìA³!Ü&Ü&ܪž©z¦êpjíÔÚ©õïoÿ/0Žq¯°µÖ|ˆ‹�‹�‹…ƒ£Ž:8 4O4O4Oà_£ÿ5ú_£!arÂä„É�žž�>éôI§O ò@ä�È�ê�ê�ê¿éøMÇo mLÚ˜´1�Ú<µyjs¨Ú«j¯ª½@–(K”%‚¼‡¼‡¼¤Nœ:ô[ÐoA?ðïâßÅ¿ Ø6·mnÛ2keÖʬiiiàÜȹ‘s#8»í춳۠ܦr›Êm‚’%-JZ€¥‡¥‡¥´÷oïßÞ,ß´|Óò¿¬ò™¶-m[Ú6xxÿáý‡÷Áv·ínÛÝ9'rNäP4S4S4ƒè®Ñ]£»Be¿Ê~•ý@v^v^v„d!YHá�ð@xœä$'áòÒËK//…¤öIí“Úƒ‹ÜEî"‡–1-cZÆ€uœuœõš¨Ò¹Jçžå<Ë0ºÝf9—¹±³ØYì švšvšv`;ÝvºíôßÞÎù›çož¿ B€ @uÿêþÕÿÀ‰ÿG¶cmÇÚŽ…2d@š2M™¦„ŸŸøüöç·?¿ 1bă 0( Ⴤ>ÕBÕBÕBX1gÅœs@õ‘ê#ÕGPdQdQdÆùÆùÆù°Æu�ëWЌՌՌµ�ÚNmç<Îyœƒò5Ê×(_ŽN::éè$8p0à`@é¼ûZíkµ¯œìw²ßÉ~¿¾º÷tïéÞƒùMç7�ßÔÅêbu1¸+Ý•îJ(Ì-Ì-ÌÅÅÅø¦ø›âoŠ!ÿPþ¡üC ˆb<ÞñxÇã`Ùβ�e;XsyÍå5—áшG#�? ? ? È»›w7ï.Ø~iû¥í—Püañ‡Å‚ïtßé¾ÓK×$Ø8jã¨�£àQñ£âGÅP)¼Rx¥pX±jŪ« naܸ…p»ÓíN·;ÁÅöÛ_lU«8Vq„ËC.¹<N«O«O«!x@ð€àp¹á冗Bx¥ðJá•þøñ!ë!ë!ëGÃ�† ‡CÓM?4ª»Vw­î y{óöæí…Å9‹s瀺¶º¶º6VVVÁ�jª¨U—W]^u9ÜØuc×�]�{#÷Fî °p·p·ø ËbËòdy²<�=‘=‘ýìf¶T§T§T'¨ÒµJ×*]Áº­u[ë¶¼ÿM¾nòu“¯Áz�õë5p{Üíq·_å‰õï"ðÅ*|.=]zºô„ê ª7¨ÞÒ–§-O[Ë–, €¬ŠY³*¦›lZÚÖÚÖÚÖ ¤¤lx°áh»k»k»CÉÜ’¹%sa]þºüuùPò¤äIÉ“ÒÕ+ÅÏÅÏÅÏA™¬LV&Cñ½â{Å÷À{©÷Rï¥à±Óc§ÇN(üªð«Â¯`ÝŽu;ÖíÓÓÓØ3lϰ=à ý«ô¯Ò¿¿[~·ünÁ†FmhwòîäÝÉûßÝwúÊé+§¯À9Á9Á9< x/÷^î½777aý¼õóÖσôyéóÒç�ìˆìˆìHi;²g²g²gp¾õùÖç[ÃŽ¯w|½ãkÊ Ê Ê‚“O^t9€U±•§Ø.s€~‚~‚~èCõ¡úP°­i[Ó¶æoh Õ¨q»âvÅí‚···W—¯Ò”JS*M�6�Û4nÓ¢¦EM‹šI““&'M†Ó‡O>}ΩΩΩ {böÄì‰Plý±õÇB¥}•öUÚ.3]fºÌ„6OÛ3}fŸ§>O}žÂ§ã?ÿéxر)bSXæ[æ[æCë¹­ç¶ž —¶^Úzi+\m~µùÕæPË£–G-�ÒvGî¹gähSЦ M,µlÔ²Q0¯É¼&óš€ÎZg­³¡³ÐYèÌ‹ÅÂä .—‹Ë¡duÉê’ÕÝ2ºetK¸ºùêæ«›!”PB�àÁ ‚€é3Óg¦Ï€‹\äç'Ì÷ß�(d�@¼‚ã;¾ã;PÇ©ãÔq`YͲšåÏ–UU„(B! n·‹ÛA_S_S_ÚÎk;¯í<ȱϱϱ‡oR¿Iý&µô’B«Þ­z·úKØØØÂž•{VîY ¡ÏBŸ…>ƒzMê5©×äôûGïò.ïBq§âNÅ�À¾�};ûv¯°ýWFÕIÕ `Iì’X€§¶Om_aóPâ>qŸø³‰f¬fZÍ´š ¦tSº)½tÙn¶³�í€?þøSz¼þQ&L˜ø�¿ÿáÇ嵟óœçüçSN8á²Éþ%û<»úì곫°)|Sø¦pذkî »àÒ—Þ¸ôó{I~\æ{®8WœûÛã ¡B¨ ªzªzªz�¶1mcÚF8ïrÞå¼ x=ôzèõÚ^m{µí+¹WàÅßgØÓvO[€;^w¼^E»¿O™+УУУøé´3Ù™ìL¿½�Fë­o´¢â£â£â¡øtñéâÓ¯.gí:µë郞 c�1¢§GO�ž½“{'÷N†Ì™2@VRVRV”ë]®w¹Þ öûŠ}A¬&V«7¸Á�Ÿ5\ôÃêY�éLgà'8¼É›¼ êêêêê꥛W:Pé@¥PqDÅG@ï½Oô>ÍÿhþGó¡•±•±•ñ×÷K÷H÷H÷²dÈÓ†L2mtVuVuVÁÕÉW'_� \æ2—¡ùèæ£›�†âuÅëŠ×AÄ•ˆ+W xQð¢àE¥íÆ×�¯_†›†›†›`ä[#ßùD$E$E$�:O�§Î+]¾WS_S_Sä:¹N®ƒJ•*@µäjÉÕ’¡Oã>�û4†1-Æ´Ó*+++++ÁØÀØÀØÄJb%ñgCúâcñ±ø¸tùàŸ<æ1�öyüV?~cùáó® ×…ë¨ Tª íLÚ™´3¥›§uNëœÖìÚ/´_Î=�{:÷SkSkSk¨™S3§fÔ\QsEÍð¡ï‡¾úBÝNu;ÕíôÛãô}±ëw ß%|—>®>®>®Ðp}Ãõ ׃zŠzŠz 0šÑ¼‚›ÕÒ«¤WI¯)Å)Å)ÅPgf�™ufþñv_=‹zõª7«Þ Àf–ͬWØüSžò¨E-j•þ8ªZTµ¨jà1Ãc†Ç ðŠðŠðŠ]º.]—Æ)Æ)Æ)@9䀨Xl,6qˆC”þ}hLcƒ.†‹áü´ÙOÛÿpB757575/} ô'Z´hAl$6»ÙÍn`#ÙbG±£ØñgÛÿðsãXãXãXÙ²!dÌí<·óÜÎ0?|~øüpè>¼ûðîÃK_öâ1 2•ùùw?öã=Þ㽟=î÷C® IÓÓÓð[æ·ÌoTH¯�^!z ê1¨Ç øpÿ‡û?ÜaýÃú‡½’y(„ï„ïÚ?jÿ öíÚ·_áqñ•¹›K:”t(éòuòuòu`ý±õÇÖÿövîm¸·á^8·åÜ–s[`›Ï6Ÿm>ðžë{®ï¹‚"G‘£Èùý9m»Ûv·í�;v ÛY¶³lgA…7+¼YáMèb×Å®‹øMò›ä7‰Ÿ¾$WL®˜\L‡M‡M‡!®{\÷¸î|%øJðx0÷ÁÜsAqFqFq¢+GWŽ® 6Ø` œïü{ç߃Ó×O_?}úTëS­O5øÆæ›ol`yÇå—wŸ!>C|†ÀçÞ8÷Æ9ðJðJðJøßýµ¢VÔÂù¦ç›žo wÂï„ß ‡çCžy>Þ^øö·òÓ7׆® ]B³øfñÍâÁ¥·Ko—Þ`·ßn¿ÝþÒvï¿wüÞq¸:æê˜«c ¤wIï’ÞÐob¿‰ý&‚k×&®M Á”SL�½ù{ó÷æ—.f3¬`XÁ°Ø?hÿ ýƒ Ï.Ï.Ï|³|³|³ ¶}mûÚö�g�g�g ªªªïï﹇sç­­ÖVk ñAñAñA�””úýúýúýP0³`fÁLpLpLpü/ûK?T?T?¢/G_޾ ý,úYôƒ˜ƒ1cBŸV}Zõi;ê쨳£¬j¸ªáª†�3*gTÎ(–6,mXxŒðá1îõ½×÷^_8_ó|Íó5!ncÜÆ¸� k¡k¡k~çýÎû�‡÷ƒß~?”J¥ÿST»¨vQíàÈ£#�Ž<‚Ê«*¯ª¼ N §„SxuõêêÕÆÕW{\íÒ¡Þߪ¤MI›’6°©å¦–›ZBõ°êaÕà heÐÊ •ÀR–ò[.Eýé,Ã,Ãú–ô- u^]ë!³Cf‡Ì†;µïÔ¾S6^ØxaãH»�v!í =tôÐѸ:puàjN N N�m¶=Øö”••ÁÞÏÞÏÞâ¯Ç_�¿Ñë£×G¯ÙSÙSÙS¸ÓáN‡; ý\ú¹ôs Ï•çÊs!îhÜѸ£Ð8¦qLã8õñ©�O} åœÊ9•s‚TÿTÿTPÌVÌV̆³ûÎî;» 5 5 5 sræäÌÉ›››¦`S°)2¯f^ͼ &k“µÉ,4‹—¬Îú¼ñóÆÏCþ¢üEù‹À0Â0Â0&LO§?�þt:(†+†+†CT—¨.Q]ÀuªëTש`1Àb€ÅˆéÓ'¦tŠéÓ)6žØxbã X^ny¹ååÀg£ÏFŸ�ÐhQ£E��o´o´ï»kÿÅH µ©ý…ÿK™› ðÚ…k®]€ù;òwäÃ’°%aKÂ@a¡°PXüööRû¥öKíó´ó´ó´¼5xkðV¼cðŽÁ;Àþ=û÷ìßûýy >2|âDq¢8,ü,ü,ü@Ÿ¨OÔ'‚p_¸/ÜE±¢XQ %ãKÆ—Œ½“ÞIï¶É¶É¶É`©²TYª $£$£$tqº8]X7±nbݤô¦™¢õEë‹ÖƒÕU««VWÁî„Ý » Þ©Þ©ÞY:ô¬ÈVd+²AV]V]V®G]�º :tADágG•è%z‰^PîT¹SåNAõ‘ÕGV ÄC Èäò°¯h_ѾbéÍF?Î1¿û»Ýßíþ´nкAk¨|§ò�ÊwJÛ×ÌÔÌÔÌ•µÊZe ²õ²õ²õ`/Ú‹ö"Èãäqò8ÐVÑVÑV�âÁŃ‹ƒr�r�rX}`õ�ÕP¼¯x_ñ>Ð�Ó�Ó�‹ví,Ú�uEëŠÖA=F=F=¦tÈÑf¾Í|›ù ¹¬¹¬¹ â)ñ”xêÅ÷=›Y )ÖkŠÁxÂxÂx¢öGí�ÚYÓ²¦eM¡›ÐMèö³ýôÃ7&ûnöÝì»AHnHnH.X]³ºfu ¬tV:+Ø8Ø8Ø8€f®f®f.¨º«º«ºƒ"@ ûûûª Õ„j°6}múÚt000€�·Þx î~¸ûán?cüŒñ3à³ ŸMøl¨ê¨ê¨ê”N<ó“,²ÈY‰¬DVÁí‚Û·÷î;Üw€±¯±¯±/°šÕ¬…�ÂGáΓœ'9OÁ^°ìýñŸ5(kPÖ X5tÕÐUCA§Óét:ø$ü“ðOÂÁa­ÃZ‡µ¯ìÏÃ߆a§a§a'¨BT!ª0¶3¶3¶‹Š-*‚ò†ò†ò�DI ŠWÅ«âA›ªMÕ¦‚â ÅŠ7ÀtÚtÚt¬åÖrk9è;ë;ë;ƒÞAï w«YV³¬f�¸R\)®½‹ÞEïÖßYgýÈÒdi²4(ªYT³¨&X‡Y‡Y‡�x]¼.^CSCSCS�»È]ä.`t6:�Á¢‚E‹ `ñ¦Å›o‚ê‚ê‚êX´²heÑ ìfØÍ°›Üç>÷_ÒÿO Ÿ>�âÅ#ŠG”åÛæÚæÚæÂ‹ùW@«ÕjµZ°¬bYŲ ó„yÂ<ÐÍÐÍÐÍË>–},û€­ÂVa«M?M?M?PTT¹£ÜQî¶wmïÚÞ‹mÛ,¶™ûÓuÊ\pfÑ™EgÁÉïO~ò{˜¯Ÿ¯Ÿ¯Ù=Ù=Ù½ßßnò…ä É`徕ûVîí¿´ÿÒþ Þëô^§÷:Aõ¼êyÕó@ð<„_ñÍêïÂØÄØÄØ’|’|’|@›¢MѦәÎÏŸ®øášÝ9»svçÀë[¯o½¾y_y_ùKÖ^ØÞd{“íM@ÛWÛWÛ”¹Ê\e.ô°éaÓÃd“d“d“ÌÝû_OüJüJü RW¤®H]EQEQEQ œÎ ç~¶ár–³¼ô„_áD…N”Þ;ñ{ÍÚ=k÷¬Ý k¥k¥k]žuyÖå<øâÁ¾€‡ýö{ØFÍ5kÔ,Ðn×n×n1MLÓ~ÖP %”€pA¸ \“‡ÉÃN+œV8­øãûéÇâÆä“oL†o;øÛÁPéJ¥+•®ÀûÞŸðþp^å¼Êy•™>L‰äW3)MJ“£É@‘ªx…7ƒþQe®8rñÈÅ#áFÂ�„ 0k³æ‚ðDx"¼‚9¹U_©¾R}{Çì³w œÜ~rûÉíP§C�u:@wßî¾Ý}¡¢[E·Šn <ž OͽW^?×]t}ä~šûiî§ÐÌÐÌÐÌ5j:ü–§6$äìÌÙ™³îV¸[án0­3­3­Ë©–S-§BÍG5Õ|.Ý]º»ü…‹ï‡‡‡@LŘŠ1!üãð�Ã?†¸Ëq—ã.CO‡ž= ÝúvëÛ­‹ï,¾³øÎÜ{ó�0¤RöïÚ¿ ÀgªÏT€FªF*sg“¼:ª-ª-åå!ï…¼Ð\Ó\óGÚ}µÊ\°/x_ð¾`ˆºu?ê>LO™ž2=Á_xÏñÿH\ .@üÖø­ñ[aw�Ý5v×€‡Š‡Š‡ чèCôжQÛFmAP“ &AMÀ¢±Ec‹ß0QŒDòw¢}Sû¦öM¸»ïî¾»ûà¤ËI—“.ð,ìYس0hÞ8¼q8tóîæÝÍÊ·.ߺ|kJïbÿûû¡'§ŸœW9®2À°”a)ò‡ò‡æŽ(ùã2�2�ŽZµ«V ÜùrçÍ�­T™+v^Úyiç%Hl›Ø6±-|²ù“ÍŸlÞæmÞþóÞ×xÁxÁxž5zÖèY#8µåÔ–S[àîÔ»SïN×q®ã\ÇAÓ M/4½µ»×î^»;xÇ{Ç{ǃl¾l¾l¾¹÷žDòëzzzAüàøÁñƒávÞí¼ÛypÝæºÍuÐL×L×L‡Æo4~£ñz?ô~è}ðiàÓÀ§«„UÂ?zˆ_œ NÐE뢬ܭ^LÀ$-ÎõÏ âňNº°‡=8à`îh¥Ê\°¥ú–ê[ªCÖ̬™Y3a|¯ñ½Æ÷2C�n~Ëú$듬OàFñ�âÅp=ázÂõÈpÍpÍpÏÙž³=gC½.õºÔë57ÕÜTs”ïV¾[ùn`gmgmgmî½*)s6³™ÍP´´hiÑRHÍNÍN͆»–w-ïZBäìÈÙ‘³!§^N½œzàìì M*4©Ð¤ÔßUWý]àø/Ç9þËÜ�y�eMÌš ^ ^à•ï• pQ¸˜;[YT¸¿p?À“ož|PuQÕEÊ*Ê*æÎöÛ•¹`ý¦õ›ÖoM”&J£–ŽZ:ê5z|Èl6CF—Œ.] âVÄ­ˆ[p÷‹»_ÜýÒ+¤WH¯¶ŸÚ~jû)lذ‚š5 jAõ‚êÕƒòËo,¿,ß±|Çò�²ð�Jò*™všvšv‚öíÚ %<%<%ž|ýäë'_ÓOj<© ‰ ‰ ‰`ØdØdؾn¾n¾nP{DíµG@]»ºvuíÀu¨ëPס ÷’{ÉÍ8ñÉßÏÕçWŸìX´cÀ(×Q®U>­ò©¹³•EG3�f\x÷»’'$¸ßsÿ7‘›K™+VèVèVèÀâ‹O,>�÷—¾¿ôýרø%¦ý¦ý¦ý�]=»zvuHHH€ûïW¼_b'ÅNŠ�9×r®å\›$›$›$(ߤ|“òM à«€¯¾‚Š+N¬8Êo(¿¡üðððððð›{6÷lþ†°ä7ºÃî@ñÔâ©ÅS!ãbÆÅŒ‹�Q7£nF]HpKpKpƒ¸�¸�¸x>àù€çÀ�kÈ5ä‚Ç2�eË ð|àùÀóPsWÍ]5w�ïw¾ßù~΂³à,ðÓc€’?ÊxÙx Ã.ÃÀ¹ƒsÛ4Û´—m¯©®y1‘×<æXw±îbî>¼Î^L9×s®8õrê`áoñÒ{Š+W²…l;•ÝßøæÍ2W,þtñ§‹?�‡ÆC—\:ðoPü¢Ëû‹ýÅþ�óQÎG9Aü—ñ_Æ Ž Ž Ž[+¶Vl-x^çy�çu dTɨ’Q h¤h¤hT:QŽÇu�ë×Ák¿×~¯ýà'÷“ûÉÁµ®k]׺`sÆæŒÍ°�l;Ùvriá ß+ß+ß Øa‡�¹wÊ?XD€>H¤µ\-WËA=G=G=T‡T‡T‡àyäóÈç‘�x6ñlâYH�M�M�…ço?ûùÛ�÷}Þ÷y߃8Oœ'Îûö=ì{€g¬g¬g,Ô¨PüÞö{Ûïm¨Ô©R§J�ÀÑÊÑÊÑ ˆ%–Xsï É:›~6à芣+F,±À_í¯þ#íþS� <p¸ÑáFò'äøö9lîl¾2WÌ­2·ÊÜ*´(hQÐ"èÙ¥g—že BˆÄ Qj”%¨>T}¨úR¥4JiIÑIÑIÑ�œœ éƒÓ§†¬>Y}²ú€îMÝ›º7Af-³–Y—.*bßÚ¾µ}kp÷s÷s÷×O\?qý>wøÜáspôwôwô§IN“œ&�ó]ç»ÎwÁÉÑÉÑɬ.X]°º2­L+Ó‚ÌOæ'ó+�H¦”)eJ† Ã…á  ABЉNüŽ©kÿ4KXŠŇ`úØô±éc0å™òLy`J5¥šRÁoŠ7Ńé–é–é¨>V}¬úòšå5Ëkùóòçåσ‚zõ êAÁÞ‚½{¡À©À©À rss!ëDÖ‰¬PÒ¹¤sIg0:�Ž Îg‰³Àú´õiëÓàñ±Çǃ§§§§§'xúxúxú€oC߆¾ Ás›ç6Ïm¥¨XeYeYeQ:E´äo¦äƒ’¢ý£ýáÅ$×.=\z¼lûçªç*€‹½/ö¨s¬Î1€ÊÆÊ/Ÿâ;žxñ²x@ø^ø€Ã¼Úæmnˆ«Å#I/Ö0@˜"Lyéöá„\lr± @f§ÌN,:XØÜ°¹ñ²—¥%§%èëx·ðn Ÿ!ŸñJûóZ*3S›f›f›fƒz±z±zqéjRtùé.Í4¡‹ÐEè6Ø`ØÄØÄØÄ€+®¸!„òóD¨³ÕÙêl(lPØ °Ÿ)>S|ŠfÍ*šY1Y1Y1�Z/µ^j=Èž7P®T®T®/w/w/whP®A¹åÀm©ÛR·¥ ¼§¼§¼ÊÏ”Ÿ)?‡.]º€Õ`«ÁVƒ�¡ eèKŒF4âL0$yݼXÝêQïWmoL4&¤·Ooà³Ëgðÿ¦Ö/¥uѺ@é= òyòyýmúÛÈÔ²—Ž4$%<�| P'³N&€«Ÿ«ß˶ÏÊÏÊØQ´£ x~ð|€7‡¼9@ð<ÿíŸó9@Î…œ ú} €PK¨ÅáåãåÀÎPæ”™CKCKCKø´ý§í?mNv8Ùá$´<Ûòl˳æN÷¢G�˜À&”.’c¬i¬i¬ %·Jn•Ü‚¢”¢”¢(9Yr²ä$¨�«�«�ƒzƒzƒz¨Ž«Ž«ŽƒÚBm¡¶Ý1Ý1Ý1ÐÓÓmymymyPŸPŸPŸÍZÍZÍZ0l3l3l½^¯×ë!kFÖŒ¬pÁpÁpÁ-Z8´pÛ�¶;mw‚X]¬.Vù—ò/å_‚E‰E‰E �J*© è¦è¦è-&ZL   °ncÝÆº ØÌ´™i3,çZεœ –C-‡Z«T«T«T°icÓÆ¦ ؄ڄڄ‚mÛ6¶mÀ¦³Mg›Î`;ÅvŠípXæ°ÌaØZÛZÛZ—Ž´ÁB° Œ`¯`9a‰äÜáÅÔÚ:^¬îÙ˜—ÎGbØkØ pµÓÕNbU±*À¿Âÿ «#{éš;²vd¬m¼¶1À†¤ I•õ•õ/Û¾ðXá1€ë箟ðîìÝ ÚÇÕ>à·þí?®nøããw¶¼X}ñÅ*„’—*3€®‡®‡®L´˜h1ÑzÓû›Þß@S›¦6MmÌ�NòÊü¸,© ˆôŽôŽô†uÖXw.Z¸há"PUU-]œHØ%ìv��%d Y?k¯?ýéÿ³%Éïð°ÕÃV‘]#»ô]Õw€ü‰üÌÀ*ù}ÊÌ%1YL“Ax,<ƒ|‰|‰| 0•©L5w:É+óÉÿGñµãkÇ×�P�P�P°/°/°/(ýý�Ë”Ó�t0wx‰äŸ*xrðd€À�?�o”o4w&‰ÌÜþ*¦1¦1¦1`¼a¼a¼²²2é&§¼··7ðòôòôòüãíI$’ßCÞNÞÀò±åcšÑÌÜ™$e¦OŠ'Å“ ,– Ë@¶D¶D¶ÄÜ©$¶Œqã2Æ�W]¯º^uÍ�F"‘H^e§Ø#î÷€i­i­i-ÈöËöËö›;•äÏ¢ª¨ª¨ª¹Ñ¹Ñ¹ÑP±uÅÖ[›;•D"‘¼>ÊL`šhšhšÌb³@6G6G6ÇÜ©$–ÌØÌØÌXÐêõ�à¥öR{I¡H$f’´*iÀ…öÚ˜"M‘æÎ$)3€øT|*>å§ELdÏdÏdÏÌ�JògÉ�=:{4Øî¶Ým»lFØŒ°‘£“HÌ$黤ïÎ;? ÀtÏ$M=nveæ)ÓÓÓ0µ0µ0µy]y]y] �B Í�NòªeÞμ�yŽ GXhý¡õ‡ÀZÖ²ÖÜé$’²¦ö°ÚÃÞ x@¡T(Ì`sg+»ÊL Æ‹ñb<‡„CÂ!�õ—õ—IÏuÿc%´Lh™Ð¼ßò~Ëû-�·’·’·2w*‰¤¬RQùù¿’×AÙ¹0[œ-Σ§ÑÓè B+¡• �þqŒÑÆhc4¤_L¿˜~¼y7ò–¦º•H$’ÿPv €t1]L/]ýŒ (øÃÍJ^3úÙúÙúÙ�ß5¿k~Wð˜è1Ñc¢¹SI$Éë§Ì‚L� 2À ,Ì�Fòg)ÙP²¡d¨¬UÖ*k('/'/'7w*‰¤¬ÓtÔtȽœ{�®ý¿ÊL€øÃb8àXc�µ¹CI^µôö/V5S8(àÞ˽—{/s§’HʺÛooXýñê� ïÞ1w&I™)Ä(1JŒE_E_E_�È dÒ%€œÔoS¿Mýœ:;uvê 6J¥�ÒÜ©$’²Î³™g3€ºWê^��“�3w&I™)xÆ3ž�üˆüˆüȾ’}%ûÊÜ¡þ:†C�¡ÒW¤¯H_ùkó׿ÿ‡Ë¨•Q+£¸ãŽ; Ôêuþp³‰äñêÿà-«·¬d³e³Í�IRv €©Q£¦tÝú¿Ø­Ž·:ÞêW¢¯D_‰B %ôÏßsžç<ÏyÂÖ°8ÝòtËÓ-áöíÛ·o߆k“®Mº6 TóUóUóáÔ¤S“NM‚ýWö_Ù à à Ãÿúýõ[¥�L™><çxÎñ”fz”H$’_Tö 3Kn›Ü6¹-$$'$'$ƒ¸Z\-®þõ¯×¨4*� Òj¥ÕJ«´¢ÿåqFÝÝÝ_¾(|4šÑhF£ÐzZëi­§Aâ–Ä-‰[ ¡mBÛ„¶`3Ëf–Í,Èl“Ù&³ |»üÛåß.Ý{º÷tïANýœú9õ!_ÌóEsïÍRÚ.Ú.Ú.��� ~?ƒŸÁÜ©$‰äõUf&úõ¨G=oŠ7Å›�Þ%½KzÐ××—î.Ý]ºƒC¬C¬C,0�ỹÜ~¹ýrûAÑÇE} âNq§¸\÷¸îqÝ%”|PòÈÈÈ€©�©�©ض·moÛšÞjz«é-0›ŠMÅ JV%«’!§CN‡œ //ÆcŽ1\Žºu9 Ê}Ê}Ê}püäñ“ÇO­ž·zÞê c¢ÇD�‰·ûn÷ÝîƒPK¨%ÔÚІ6�³4giÎRˆ;w.ªªªª‚õiëÓÖ§¡™¾™¾™Lz“Þ¤A#h ¸Ä¸Ä¸Ä€¬ž¬ž¬Á*ù*ù*9ÔíU·WÝ^V-¬ZX5°Üj¹Õr+d®Í\›¹Ô>jµ¸œq9ãrì‚í‚í‚áùÏßxþXܶ¸mqLßš¾5} ö5íkÚ׃ڠ6¨Áeˆ2D�‹¯‹¯‹/0ŸùÌÿå�³Ø±Ø±ØTsTsTsÀ-×-×-×Ü™D"yÁ„éÅ¿wMwv ; 4w¶²«ì?Üý/;/;/;‡ìÙ²ƒ [.l¹°|‹}‹}‹Ák¦×L¯™Ð³jϪ=«BäÕÈ«‘WaOážÂ=…P9¾r|åxH´M´M´…:ß×ù¾Î÷‘‘‘ Éß$“ü Ô^ox½á¼"xEð HØ�°;a7\¼|ñòÅËðÉŒOf|2Æí·oÜ>hóe›/Û| •,*YT‚Üþ¹ýsûÈ3#ÎŒ8g£ÏFŸ�†˜1-bZÀ“EO=Y.^.^.^ _,_,_ ¦¶¦¶¦¶�è’è’è9-rZä´€¨žQ=£zBí�Ú!µCàÔÑSGO…k+¯­¼¶6MÙ4eÓ…D!„]Â.a¤^M½šzŽß;~ïø=PÔWÔWÔ‡úƒêª?ââââââàDË-O´„òÃË/?²S³S³SaxÎðœá9ðUׯº~Õr–ç,ÏY!Y!Y!YP{oí½µ÷Âãk�¯=¾ÉÆdc²fœ9pæ@P ø¯k±¶X[¬±™ØLlŽFG££H%•TstIY÷´ÞÓzF<Ðmn·¹²8Yœ¹³•]e§°ÄK—‰ËÄe€-¶ØÂ…E]XÚ/µ_j¿„> û4ìÓ …B¡ÃdÃdÃdØ8uãÔ�S¡î³ºÏê>ƒÁ÷ß|RÆ¥ŒKúúú� OÐ'è!sbæÄ̉0ðÐÀC�E‹€E,bq=âzÄÊ)?¤ü°i5Òj$4ŒiÓ0Ñø‹Æ_À`§ÁNƒ�àñ'�?yü T¾RùJå+ h¥h¥hÍŠš5+úÏîÊ&É&É&AH¯�^!½Àk‡×¯•³*gU΂gÍž5{Ö N}pêƒS€h#Úˆ6@ $€8H$¿H¿H¿H(÷¼ÜórÏ!´ehËЖPa~…ùæÃg ?[øÙBèà×Á¯ƒtÜypçÁ0(zPô hx|âñ‰Ç' üíò·Ë߆¯¯/xgí;kßY âuñºx*¨t ÒÐxj<5ž o(o(oø¿?Þì³?Ìþ,¶[l·Ø¡¡Á½‰ä×(²*²H½Ÿz@t�Í�IRv €BÃÃÃ0F#ŒÐË£—G/X¼rñÊÅ+aäᑇG†¾î}ÝûºCûík´¯)>)>)>Ð¥S—N]:•6ë½Ä{‰÷’Òÿozjzjz 6�mÛ4§·œÞrz‹#`&~º=]Ø$l6ËYÎr~™/‰—ÄK`]Ùº²ue°‰·‰·‰‡,ë,ë,k�µ“µ“µqš8Mœö+úýãÄGÇ9Îqà׸Ìe.s)�!Œ0€ÛÜæöÿnG<$�±‘±‘±$^L¼˜xnl¼±ñÆF(Ì,Ì,Ì!LÂ@þ©üSù§ 4š ÍÀömÛ·mßÇ›Ž7o–¾�S7§nNÝ~ûÇ›à™à™à åüËù—óÛDÛDÛD³q‰ä'5ËÕ,Pybå‰r¹\š ËìÊL \® WAØ*l¶‚ñ{ã÷Æï!0(0(06 Ù4dÓ¿~+ü,‹^½,ÞØüÆæ76ƒò]å»Êw¡PW¨+Ôý—7úa¤�v´£ÝK~ÿã w%+YIéój=éIO&„ `êdêdêÚ m†6ìOÙŸ²?™2d³˜Å@ozÓû¿äÑ¡CÂa€0ˆ'žø—ìŸÕÂja5Ѓô ´`YÆ2–Dìb»€L2Éa†0C˜Îí�Û;·‡†£Žj8 Âv†í Û ={&öLûÇö�íÃ-ñ–xKs˜Ãÿ™C¢ ц€©’©’©Øl·Ùn³�ŸFl~IúÝô»éw¡¼oyßò¾f9Ä$É/²ÚoµÀ «?XÂ’?Мä•(3OÈ>•}*û„ B¡ˆÞ¢·è ûî컳ï\œqqÆÅ «)«)« UrªäTÉå)å)å)èZܵ¸k1\H¹�r!ÎÆŸ�?‘±‘±‘±�ù óAæÈ>™}2û$dŸÊ>•} c c cÀÔÞÔÞÔR3R3R3 Cþ†ü �Y1³bfEÐûëýõþÝ1ºctG88÷à܃sÁù ç/œ¿€zwëÝ­wœ>rúÈé#ˆ½{7ö.Ü(¾Q|£ŒmŒmŒm~ÖáCâS}J¥ƒÒ&.˜¸`âðxÓãM�7!ìNØ�°;à8Òq¤ãHÐkô½xÎsžÿ¬¿�yÌclÁÆå�Ë—ž.ž.ž. Þ©Þ©Þ U×V][u-Œ >*Œ;�;�;¡ÚØjc«�…Q_ŽúrÔ—`3Ãf†Í ˜æ>Í}š;ÄLˆ™3 û û û` ï@ß�¾q-âZÄ5(*)*)*«3Vg¬Î€ÖVk«µ…ö¾í}Ûû‚&\® Ãdž� —Ænº§éž¦{ ¤CI‡’ ?*?*?úË«f™f™fä¨sÔ9jð™ã3ÇGzþ_"‘Hþ'Aü�¹ƒüÙ ?)ü¤ð˜ºcꎩ;`¸ípÛá¶P3ºftÍhóå*©WR¯¤ô|»çÛ=߆ñúñúñzh3µÍÔ6Sͽ×^)}Sú¦ô…ëg¬Ÿ±æ?šÿhþ#ðhèÑÐãWÜ<(‘Hþ 9696™þ™þÁ‡ ›;[ÙUf.k…µÂZ0ùš|M¾`R˜¦×`ü#Ù6Ù6Ù*XU°ª`i Ò¤5ÃJÃJÃJs§{ýe É’5lŽØ±9vvvÒÉkæqÓÇMv­ÞµÀèl”ž0»²SÌæs@^,/–ƒé¤é¤é¤¹SAÐÌ ™A3aý±õÇÖƒ�]vØ!ŠEˆ¹Ó½þ²’³’³’Á¾»}wûî`=Ýzºõts§’H$ÿ®Jd•H€. º4�—7w&Ékðø¯ñã„6¦|S¾)L‘¦HS$à…^fÌÕZh-´ZÓšÖæÞK?I±I±I±àõÔë©×SP\W\W\7w*‰DòïÊå”Ë(G¹?ØÁsg’”�`¼0^ò•ò•ò• ˆâë0T<žñŒ‡øòñåãËCž6O›§…ZGj©u×××ÌòõcJ6%›’!õZêµÔkr7änÈ]à(G9úG[—H$’¾²s X‚Á´ß´ß´ŒaÆ0c˜¹SAôèèÑÑ£á›YßÌúf\­}µöÕÚ B…êW¼>{xöðìáðU÷¯ºÕ¶lØ`î^ýùô³õ³õ³!÷«Ü¯r¿�b�b�bs§’H$’¿�2SȲdY²,�EÉ¢dQ`zßô¾é}s§‚kS®M¹6Ô½Ô½Ô½`°Ã`‡Á ¡¡ñ¿_ï¶Îm�Û:(¹Sr§äÜly³åÍ–æîÕŸïÇÇ.K• *Ï=ž{<ÿãíJ$’?ƒ©ÈT/æb †sg’”�@&“Éd¥7×éºéºé~Ç”³¯Šj¹j¹j9<^ðxÁã�\�\�\i)i)i) †‹áb8<òäÿÈ.'\N¸œÃ"†E u#u#u£Òö¬|¬|¬|@vEvEv¥ôç)ÇSާ‡++®¬¸²"zEôŠè%'JN”œ(Ý.Gž#Ï‘ÃõÐë¡×Cá¦ú¦ú¦ŠÅŠâ×ðBQZ½´ziõ@¶V¶V¶Êm)·¥Üs§’H$/ùYägkÚ¯i`üØø±¹3IÊN� K�%€¥`)X  ]£]£]c¾<†Q†Q†Q ËÔeê2AwCwCwÔ#Ô#Ô#@»N»N»Ž·:Þêx+È��;!wl<·ñÜÆsÞ&¼Mx›ÿlWh%´ZA®³ùÌb®Å\‹¹‘§#OGž†ô+éWÒ¯@Á„‚ `±j±j± †> } gcÎÆœ��µóÖÎ[;ŒþF£¿ùö×ÿ—23efÊLp~Ëù-ç·À.Ó.Ó.ÓÜ©$ÉËY¾kù.€Ã ‡ALd¢¹3IÊN/‹—Ń¥h)ZŠ Ù¦Ù¦Ùf¾<2™ƒ |}}Áw†ï ß’’’ÖyÖyÖyÐçAŸ}@Ç®»vì •ÄJb%îº;èî —4¼”¥,ÕÕÕxØôaÓ‡M\p�®[»níºìììáa«‡­¶‚{ìy°º ì2°Ë@hÚ,´Y(œªwªÞ©zP¸¡pCáóí¯ÿ/mSÚ¦´Mà~Ãý†û : �„N¼]‰Dòg¨>½út€¾}-äNr'sg’¼†ƒ»aª0U˜ ––– ½®½®½Néâ7æ’K.¹ Öë‹õKœ¼5ykòVØ•¾+}W:8Ìt˜é0noº½éö&ð™à3Ág?Íùÿ#qŽ8Gœž=7zn„ ·&Üšp v÷ÛÝow?84þh>ûø,¼ÿìýgï?ƒF_4ú¢Ñ &‰IbÒÏÚ±Ç{n7„ m¨m¨mu—Ô]Rw l~¸ùáæ‡àpÉá’Ã%8øÖÁ·¾N{�ö:í… ©R+¤B¯£½Žö: ãú�ë?®?|‘ôEÒI ŒTF*_ƒ¿ÚEí¢v�ô–é-Ó[‚ŒŒ¿t3‘D"‘üfefàG?®Ö«}¤}¤}Ô¤&5ÿú%gKΖœ…¤Ô¤Ô¤TH•§ÊSå�””¾u|ëøÖ�óÏÏ??ÿŽÜÍÁ&Î&Î&âóâóâó€ŠT¤"ÈkÉkÉk_ó5_ƒ»µ»µ»5¸wvïìÞ… ÌX6FM4°Ä‰ÿX¸ pA 8Ÿp>á|â7/‘Hþ)ò9@B«„VM¶7Ù +'+gîleW™+6ÜÙpgÃPŪbU±0º×è^£{™;•ä×:~,üX8\8záè…£0ï£yÍûdõeõeõÿxû‰äÏpuÉÕ%çMçM“ZLj h h`îleWÙ»cc…Ó §NzÑ ©øÛH(J(J(o…·Â[!�ø%’¿‡;jìð¾í}@ž#Ï1w&IÙ» ðŒÕ«3 ›®›®›¬f5«Í�Jòk¥mNÛœ¶¼W{¯ö–>7‰äoÂ!Â! ¢©¢ @p¤å€Í®ìvVvVv  Ó†iÃ@ôýD?s§’ü/Å·Šo߂̭™[3·B@ý€úÒ7‰D"ùÝÊ\`}Ðú õA0  Ök‰µÌ�Jò¿d,ÎXœ±ŒÇ�Ç�ǡ¢ ‹*˜áæM‰D"ù§(s€åW–_Y~º]‰®¨K]êš;•äI·K·K·û¡öC퇂]»vÒcÉßDÉÆ’�Ï«<1ÿJ-¤/^fWæ «`«`«`ÐöÒöÒöÑWô}Í�Jò¿Ä5Œk×¼›x7ñnV:+�•ÎÜ©$ɯsÐýA›‡n `8f8fîL’2WX°`=ô½F¯±®XW”FÌï‡üM-M-M-/¼ðÓÓӈ߿+~T^QyEåæ+‘H~›òóËϨV' @vPvÐÜ™$eî1@«»Vw­î‚Þ]ï®wSSSs§’ŸŸŸÂ¦üMù›ò!õpêáÔÔ””1-bZÄ´€FµÕnTŒ��AÞYÞYÞÙÜé%É %ÕKªDΊœ Z¨Z +’Èä gΟ9 :ˆ>>•*àƒ�¹ûòÏWæ ëëÖ×­¯ƒÉßäoò­�ÖGëS:E°ÄOŸ§ÏÓUÓUÓUà!y¶ù¶ù¶ù ¼¦¼¦¼®]ºßS¾§|O�çUÏ«žW¡ü½ò÷ÊßÏ‘ž#=G‚ínÛݶ»�†4¤¡¹? ‰äÏ"îwX~gù€ÍE›‹/Û>'>'`e••Uü ~€þ–ý-äZ¹öß^PH!À¡§‡žÄô�éP;°v Àã �7|øö‡oÈÏËÏÄëãõkŽ®9 öiا-µxé½>ªîªî»–îZ `ÿ™ýg].w¹  x¦xfî}ýú+s÷-„B °Üe¹Ër¨+©+©+™;ÕŸOÌsÅ\(®Z\µ¸*dÔȨ‘Q¢NF�Œ: Ñ!Ñ!Ñ!�Ú.µ]j;ЯүүåUåUåUp™á2Ãeø¤ù¤ù¤Aµ¡Õ†V N›œ69m'''pNvNvNå`å`å`°ªmUÛª6]„.Bv »…Ý@?úѨHE*‚ÐUè*tñ�xH<yyy`gogogò&ò&ò& n7ŠAWOWOWŠ7(nyyyPм yAsÈ�7 o<{ö< b¾�ù6æ[¸Ztµèj”Ü,¹YräoÊß”¿ ž O…§ªÖ¬Z³jM¨q¹Æå—Á3Ë3Ë3 î:Üu¸ BO¡§ÐÓÜŸ¦Dò{E�‰°¡Ó†N}?èûÀ¼ñÒííÙ/x;àíÇZ޵ä'ä'^ú:µíÔ@|(>0T0ThTÔèÅŒ€½ä½~þ²JC* ˜Ÿ9?@øHøè¿õC1Q1 ’g%OC-ËŅÒIÿo¯»r3  £  Ù¡f‡lÚ”Á¿Ì�üh¥×J¯•^`1Ñb¢ÅD>vøØáÿ„çPW°‚PìPìPìj=¨õ D" xòÍ“ož|†C„!<¿õüÖó[¨Ú¢j‹ª- JA•‚*àý¹÷çÞŸƒr�r�rX9X9X9€pG¸#Ü1w';qž8OœÚrÚrÚrPbWbWb©bª˜*BÌØ˜±1c!ºFt�è�‘‘2™‹Ì[¶ l R¤6H…šÖü°æ‡àpÃá†Ã ` X`î^JÊžœé9Ó­|´ ú‚ê \†¹ {ÙöyEyE¹ýrûTØTa€µ»µ»¹ûòW¸PéB%€ˆüˆ|€m´(^>ÜÜÙþze¶ø®ïw}¿ë ÏO>?ùü$ŒÏŸ3>ÇÜ©~;S?S?S?ˆõ�õ�õ‡‹\üàâpË÷–ï-_Pø)ü~P}EõÕW@á ‡6 ¾ù~äû¸|ïò½Ë÷ Üî ÷ÌÝó�‰ÇÄc�ÿMþ7ùß@âèÄщ£!"'"'"¢ÞŒz3êMÐ^Ó^Ó^ƒº·êÞª{ š5jUTYPeȯɯɯ™»7’¾ÓgNŸ¸øùÅÏÞ�|? BA…sg{�‰ßŠßï ï`Äø²ínö¸Ù ýNú€Öï·~@9Y9ÙÜ}øãÊlpÄûˆ÷o¸1âÆˆ#`f§™�fvYMYMYMs§ûe†Ñ†Ñ†Ñð¨Õ£V�ZÁÁ÷¾ð}ˆ�;?v>TVuXÕaвzËê-«CÍ5Ô\6ímÚÛ´dÈÊÞ­Ÿ¯Žæ‡{œF?Œ~ Æ_a<c=ìuÛë¶× ®·¼ÞòzKèÛ!¶C,t íÚ%¬ ­ ­ Í�Vòúˆ_¿àéŧÞøä�OìkÚ¿Æ#“ƒ£Á`·çnO¿¿€Fg� ¯áM†e¶¸wõÞÕ{Waì ³6Ì‚yOç=�÷ìãìãì͸*UþìüÙù³a]Áº‚u»(vQì"viØ¥a— žXO¬'‚ÐRh)´4÷^”üOKX¸¿éþ¦û›`�n�n�< = = áà Nøp¸Mp›à&ÍG!‘üM//œxr @æ´ÌiÏ< Û&ÛfîŒÿ©Ì^ ¶­Ek — — —Á`c°1ؘ/OþðüáùÃañòÅË/‡â�Å‹7œªsªÎ© õ[ÔoQ¿…tâÿ­L L L @;A;A;Ä‹âEñâo÷WÇ8ÆA­µÔz³·ÏÞ>{;ȪʪʪÂÛ¶ l!Û!Û!ÛÁÜ{KòçË¿‘@÷¦îMsgù0a†þ†þ†þ ‹ÐEè"€Hø+ƒÈ›Ë›´¿Üþ2@ÿ¯û ¯ë‰ÿGe¶° ³ ³ CCCóº9º9º9°®ýºöëÚƒm;Ûv¶í`⬉³&Î÷'îOÜŸüïvŒ#�#�#!:(:(:îÕºWë^-0ùš|M¯àÚa±g±g±'DµŠjÕ 4�5�5�!MŸ¦OÓõÍ×6_Û ù±ù±ù±¿ÜNÑÝ¢»Ew!ªNT�¨: }¤}¤ýõÑ~¬ýXû1쪼«ò®Ê°ø»Åß-þâ†Ç �»<ìò° Õ.ª]Tr«æVÍ­ ×ß½þîõw!}Wú®ô]¯>—K}—ú.õaìÙ±gÇž/¥—ÒK «¬Z°j¨k¨k¨k¼ú÷•˜[Êê”ÕŸWû¼@ÜŒ¸¿½UgUgUgˆÐDh"4�Ð2¡eBËW—2mHÚ�´!ðÔö©íS[Ðí×í×í‡'›Ÿl~²n�¸=âöÐ_Ô_Ôÿ—B:Í6Í6ÍžZ>µ|jùâʸø'Ü4—1>c|ÆxX³wÍÞ5{aýùõçן‡Ìa™Ã2‡ÁÃj«=¬Z£Ö¨5BâÑÄ£‰Gáúþëû¯ï‡’+%WJ®¼ÊD‚�à ¸¯¸ÿêûûªý_{÷Eµ÷qü3»Én’MϦ��JB º€éU�^A¥ ˆ‘"ˆå"E¥H“* Ò!ô"Uz/¡†$„@éÙlʶìîó‡záQ¹Š{¹9ïx½6“9¿sfÂ~wgæœRbbbÀüŠùó+`}|úøô�@C !ЎÇ9Ö²–µpÆýŒûwX¼2xe0’ I†$]º(tL¸?áþ„ûàââ&“ƒÉŒ?4~ú$}’>éçÈ ›�Žt¤ã_�ÔüÔüÔ|ÈÛ�·;o7× ®\‚ׯ ^ã_ÿúø×!âZĵˆkà³Âg…Ï poäÞȽX:X:X:<ÜŸ5Ök�}]}]}]0¬1¬1¬bˆ!æïŸÎ;ìü1¼ñà�o<€Ã£�:< |pðÁÁçp" ÏI`¯À^­Þoõ>€½ÙÞüä{qºítÛé6¨•j¥Z Æ·�oßccc0l4l4l^åU^ÓVÓVÓV0Õ7Õ7Õk�µÀZ¦ö¦ö¦ö`zÅôŠé å(-Ç·ßr< ,;°ìÀ²àÐÛ¡·Coñ ñ ñÉ_ò—üÁ¼Ë¼Ë¼ ÖE¬‹X¿=øíÁoÁºÎºÎºZ�i5¦Õ˜Ÿg%x$GÉQrc}c}c}0Ž7Ž7޽J¯Ò«ÀTh*4>ùxĈ?#Œ0oÞ,¼ÔªZ«j­ª0¦`LÁ˜pè6Ðm '''�ýDû‰öùùýGîÒ7¯4¯4¯|¸Jl‰ªDU¢J(¡äiœ§sOçL•O•”|QòÅS<ÍžP©› øWNr'¹“':Ntœ9Ós¦çL~íŸ3œ3œ3€ª¢ª¢ª"DÞˆ¼yã)ìxÛØY5³jfÕ„­Ã·ß:¿úþj(Û¶lÛ²m¡ZrµäjÉ0Û~¶ýl{Ñ}D÷ÝÁþ{ûïí¿‡/{ÙûËÞ0j¨ £&€}Sû¦öMáË_ŽørŒœ6rÚÈiPij¥©•¦‚”)eJ™P8¡pBáصo×¾]û þõø×ã_‡ R©‚5ðö�·AsSsSs¢VF­ŒZ 'Ê�(w¢ômÞ·yßæP‡:ÔùÝ/h]к 5\�]�]�ARó¤æIÍaOù=å÷”‡¨³Qg£ÎÂìe³—Í^¯¾Zøj!´£íÙ�4@ k¸5Üvlرa$WJ®”\ Œ¹Æ\c.¼2õ•©¯L…F4¢Ñ?8l“#&GLßßß8ÕàTƒS  �èô|NIáb�e�e�·Žß:~ë8¬ö\í¹Ún¿~ûõÛ¯CÓð¦áMÃ!ghÎМ¡°ÑþEûÁ¿öükÏ¿öÀùù9Ú|hó¡Í0¹ýäö“ÛÃ�óÎ8‡:ê|¨3|üeð—Á ¹In’ÛÃS¥4JiKG,±tD6‰lÙ###àÆ¿nüëÆ¿àH¥#•ŽT‚¡aCƆÁŒÈ‘3"!*"*"*¨Le*CjßÔ¾©}a´Çh�Ñà½Ä{‰÷’Ç÷?ùXò±äcÿjü«ñ¯‚b¥b¥b%¿|üòñË`-¶[‹aÙÌe3—Í„OZÒú“ÖàÔØ©±Sc ‘DA:#�‘΀f¯f¯f/¬¼¾òúÊë`lglglÆÎÆÎÆÎðF·7º½Ñ ‚cƒcƒcÿÉ‘«1»ÆlS¦)À2Ë2ËvçQ©ý@~J~J~ T%ªU ä•É+“WæùµMsMsMÓ"¦EL»•v+íV>…7§9ÍÁÇÕÇÕǺé»é»é¡÷ë½_ïý:lß¼}óöÍ�ýSöOÙ?AvAvAvhWiWiWAÄ•ˆ+W ó­Ì·2ß‚üåùËó—C¹oÊ}SîÈè™Ñ3£'hÛhÛhÛ<ü²¶µ¶µ¶·¦nMÝšB°1Øl„Èj‘Õ"«AÓM{4íå_.ÿrù—!Ý;Ý;ÝÌÞfo³7Øo±ßb¿J®—\/¹½Jz•ô*�<Àí펿ð¸œË—=.{ æÑšGk…°„°„°xuÁ« ^]ëT¬S±èÒtiº4Ȩ‘Q#£ÆœGäGäGàÚ›×Þ¼ö&l Û¶1 úå÷Ëï—u^©óJ�W`ñ«‹_]ü*ýy}�#s”9Ê¡Â>¨ð\7\7\7üýý ÿÛ¤áÒpi8TŒ®]1úéw¤ßh°ªÁª«`‰y‰y‰8 p·­·­·­': � � �„¤±Ic“Æ‚,[–-ˆ�…! CB¢O¢O¢˜f˜f˜fmiK[°¦XS¬)Þxã 4Éh’Ñ$ªÖ¬Z³jMrrr€„c ÇŽ�çÏ9žs@§‰ÓÄ�sÿæþÍ¡ŸK?—~.psí͵7×Â…‚  þ¼ÿ¡ C†6„ò£Ë�.?ê(ê(ê( zbôÄ艱0baÄB¸~7ün8kŠ5Å�6H¤G¦ü•©d*™ ¶þkë¿¶þ îÔ¼SóNM9e䔑SÀxÁxÁxÖÝYwgÝ�§qä¼ý½ýÚUoW@á¯ð·ÝyTjÀ¯\2]2]2¡à�‚7 žã„ ; vì×®\üóýýÛ/SÕIAR�²BY¡¬‚{÷ î îÉîÉîÉ�ŸŸ²YŒ,¤[Ò-éH“¤IÒ$�õ“õ“õéªtUº ²Ñ²Ñ²Ñ {Sö¦ìM~¾ru‰Ÿ×þÒ @Z!­�V€4Eš"MY†,C–ÒYé¬tdkdkdk.ª#k(k(kR ©…Ôd!²YH“¥ÉÒdpþÒùKç/Þ§«« K..¹¸ä"Ìí4·ÓÜNðCÇ:þЬQÖ(kȇɇɇ�4L& yyy 3�é ÒHi¤4$wÉ]rÿý0JIR’”i÷Òî¥Ýƒ´OÓ>MûŽ•9VæX¸9ÿæü›óAÓAÓAÓJz—ô.ù—n~Ë-Û-Û- Ë–-, ¼Ë»¼ûlÏEáY0757¸5ëÖ,€â¦ÅMŸâî]^tG– K�%<|¹ú¬ê³ªÏ‚¼áyÃó†CVë¬ÖY­A~F~F~¤•ÒJi%ÈNÈNÈN€Ô^j/µ–°„% í“öIû@ê u�:<¼´ˆ#F �B .ª&U’*I•@~@~@~àa²]²]²] 5‘šHM@j.5—š?ü»—w’w’wçƒÎ�‚Ýq»ãvÇÁ8Ì8Ì8 §&NMœ s?œûáÜaN¯9½æô‚éÒ¤?ÒÎ"Ù"Ù"�5�5�5xøº´MÚ&m{ØÞ¯ý¦ˆ" êR–”%eÁ�n|pãÈLÎLÎL†½.{]öº@vvvvv6dÏÏžŸ=ÿ©¹C8S÷L]€øyñóžâyñ„DøÑåG—AÛBÛBûËqÚì´Ùi3Î)œS8ç4@À8Æ1ŒõŒõŒõ ävÉí’ÛàÒÒ¥¥KKà~à@�ÿžy�@ äß×1aÂÄÏŽF€TEª"UyøºTN*'•ãß_éဠ‘†HC–eµX-V Pžò”ªP…*€=öØMiÊ£ÿQºãŽûÃÕíœíœíœÁ?Ø?Ø?Êö(Û£lðK÷K÷KdMƒl²É©µÔZj 8ãŒó#ûýõ£KðȨQ£~8räÈ—•.+]VBX·°naÝ Uv«ìVÙ0#jFÔŒ(p6:��ÿü°î*ÜU¸ œÞszÏé=`‹Xô ÎáÓ�Ñ�XrhÉ!€Ä’ħr ùvØaÇÿó_Ž,Y8ñŠxE<8h4à3>ã3NnÅŠ¨Nuªn¸áÆ¿Ï{©¡ÔPjxá…ÿ~ÜŽú¿,øëö¿þýv¡ ]©ï×í£‰&ðÀ ,e) Ô¦6µÙ¾1�i Üà7Ài Ó@§�PöÕ²¯–}Ê.(» ìðœä9ÉsÒ#¿÷KRK©¥Ôò‘×ý,Š(¢ø÷=ÿþì׺ùÀdßо¡}CðªáUëD„E„E„Áàƒ #rFäŒx*kÅXMVÀá�‡$¼�ðöSäù��ÂÓ¦¼©¼ Ю^»z>}žâM�ö}íûÚ÷…¢ÊE•‹*ÃÀ�aÿàýƒ÷†¨ÝQ»£vCùºåë–¯ Fo£·Ñî̽3÷Î\Ðh4`|Ëø–ñ-(ªVT­¨hkhkhk€®’®’®h 5…šBÐŽÓŽÓŽÝ@Ý@Ý@(’É‹ä`_ξœ}9Hž04îw�;äœÿqþÇ`¨n¨n¨ùÕò«åWƒº?Ôý¡î +£+£+lb›À'Ù'Ù'Ônj7µÛÓ8rÒOÒOݼ»yÔßZëóN©� øWG_;úÚÑ× Ö7Ö7Ö¦wšÞiz'°kcׯ®Í³oã¢�‹6.‚«�®vºÚ b,1– ¨|U¾*_[�Žð¬éêꬹ³æÎš þeýËú—…>3úÌè3¨D%*ÙºJAþ•úK^#½Fz�„¢�¢�¢ÐéŠtÿànî'Õ¶¤mIÛàc>æcø®Üwå¾+†&†&†&¶áY1éL:“~8÷ùÎ�æ¶æ¶æ6tÐq@Lj7þÿ]Ó™`TU–æ–æ¶.IxvŠºu(*SôŸ2û«J}pŽwŽwŽóióióiЩt*�êùµï4ÄiˆÓTkP­Aµ qKâ–Ä-0gᜅsBÁ·ß|këQž–â ÅŠ'À¢r‹Ê-*/]¼tñ 9·¤[Ò- ø†oøÆÖ£&<©Ûñ·ãoÇÃg²ÏdŸÉàέ;·îÜ‚1•ÇTS¿ ü*ð+[W)<{r“ÜP5¦j €®†®€y‘Y<íñ?Dî'÷ˆ¾} öKµ_²uM¿'€›ÂMávj;µ�t7t7tOcF¾¿Éo‘ß"¿E0.|\ø¸p¨âUÅ«ŠüËù_Îÿr†3VÌX1r·æn͵áݣ¦‰ÕÄjbaÍŽ5;Öì€O?ýôÓO?…‡‡˜¸i⦉› pEàŠÀ¶®Vxþj_¨} ûáî‡äSäSl]“ðô¸Ut«Тf‹šðóe¶®é÷D0)L ÈÎËÎË΃î–î–î–­«UwUwUw跢ߊ~+ Æ!Æ!Æ®Ÿ¼~òúI›46ill*ÞT¼©òÆç�ÏÏ¿§ž“8âˆmOmOmOغ=t{(ŒÝ0vÃØ pnƹçfÀ{9ïå¼—ï^}÷ê»WÁµ¯k_Wqwiöó¼°‚ŸàÏÏÉÿNò¸äqgÎ$ÀÏëóÙºôÒì�Û7€MÇ7Ș7ÐÖ5ý}¥v-€_)’IŠ$PtStStƒ¢~EýŠúÙºª‡$�¤‘4P•ªT>U}ªúTg<Îxœñ€í—·_Þ~önÜ»qïF¨ëQ×£®DŒ>}ÊÍ,7³ÜL°Ûn·Ýn»­{óâ3eþÊü$7Hn�ÜŽ÷:Þëx/8"þD<8�p:átºevËì–ùpÞ§žN=�zÚºzáÅ“?'ÀÆÓO¸Öw­P±cÅŽ¶®­4ºÒçJ€ÛSoOh6¶ÙX[×ô÷•úðë"7¿>÷ž«ÊUå>Ç›Ÿ”C‘C‘CÑÃÅgê�­w¶ÞYˆsŠsŠs‚Cñ‡âÅÃôÄé‰ÓAí¡öP{@­:µêÔªµSk§ÖN?o?o?opòsòsò~äG~´uïþ |Îç|º£º£º£�á•á•á營~~8œ¿qþÆù�^7½nz]ˆèÑ=¢;ô[ßo}¿õP£{�î5ºƒƒƒƒƒƒƒ­;#¼øªß¯~ ‚K»Æv�ÿÓöù­ò[è4: €ºšº€Ýb»ç¸Úé‹ãç§¿ mTÚ(€ÀÄÀDÇ9Žÿ†ÖB š½×ì=€=Zô�^–^¶uþ¾R?À¯f}6ë³YŸ�ë@×�®¡¿oßþ/àsø–8Kœ%²œ³œ³œáÂÌ 3/Ì„³ûÏî?»R‡¥KŽï:¾ëø.”K)—R.*¹Vr­ä ោþ øÕñ«ãW”¾J_¥/È^‘½"{P¡â¿8 =Ö/SƒZb-±–X0~jüÔø)d4Ìh˜Ñ§$NIœ7Þ\xs!$êõ‰z(º\t¹è2”ñ,ãYÆj{Õöªíµ«Õ®V»ø.õ]ê»deebù^ÁæŸ:| `Ó‚M †·Þ  üëå_ÿÃ_˜Ílk k ©²TÙÖ}øG~yÌÒÒÐÒ@–,KøÿËþ>´ûÌî3{ûïíc�±\ ¸fë®<{"ü⻽ßíýn/h&j&j&¨3£ÎŒ:c몞Ë`Ë`Ë`ÈZŸµ>k=¤ÌO™Ÿ2®œ¹ræÊHè�Ð!¡äÎÏ�Ÿ;yŠÁ}À§•O+ŸV o)o)oùO;!ÏŠáÃ;™Ç3�xMðšàôºÓ€{Ÿßû`?/’ר»±7@ÍA5ýaƒ `:h: ÿXþ1€ì ÙÓ]Lm8ÃŒ½�?/²õË…Jñó�PBÿßö£ °)hS@º}º=@¿%ý–¨.¨þð1Km[m[€’µ%k˜|M¾&_°Ýþuû×AY ,P€Ë&—M.›.&RsÍý5÷CàÔÀ©�S!haР…à1ÇcŽÇ�U’U’U²È"ËÖGMž”r±r1ðËZ^N•¬J6@iVšÿÓöúú ®,¸ —‡ ýhèGòÉòÉô{—ú\êpüÊñ+¯9½æPöxÙã´ýƒw¼° Â‚ Q‰Q‰�·wÞ ½'½÷ÿ~!‰$?³Ÿ@ÝHÝÀ~Ÿý¾ÿÔ×]®»þÿ ¸>åCò_L€_¸×r¯å^ V¬(X–.–.–.WƒûŸõë²¢&™If‚‹ã/Ž¿8âNÆ�Œ; Ÿ…~úY(¼Tþ¥ò/•óÛæ·Íoƒ!Ç�cÈckckck0Š E�Û/·_n?È Ê Ê ‚ÂÖ…­ [Cq¿â~Åý@¿@¿@¿Jn•Ü*¹æíæíæí`þÑü£ùG�ÛËíåö Ÿ!Ÿ!ŸvûìöÙíe%e%e%pÊuÊuÊç=Î{œ÷€Ç;ïx¼žöžöžö ,¯,¯,Š E�"èa‘'Êå‰<\Åì>÷¹ÿÈ8´§=ím}0áyó\æ¹  #ÿÒöУУm7·Ý `J0%ÈîÈîü§ß³7Ù›8Á éséóÿ´½ûP÷¡Ý¢ºEx;{;ÃÏ ÿá/la À˼À—äŸ;q à—{_î}¹7,¨¹ æ‚šðÍžoö|³?*~T”‚›ãŽn=ºõèVX¹ rA$ n?¸ýàö}#úF´ çEAž�R?À¯¼ü¼ü¼ü äZɵ’k =¯=¯=o몞½SêSêSjøvË·[¾Ýoû¿íÿ¶?D‰>}ÄÖÕ ‚ ÏŠ¿poíÞÚ½5C 1�'Ï“çý÷~Ïù=ç÷ÀœŸæü4ç'ès®Ï¹>ç éõ¦×›^¼ñÆÛÖU ‚ ÏŠ¿PlSlSlG‹£ÅÑš*š*š*¶®êé»Üår—Ë]`ÖüYóg͇ž=#zF@«f­šµjÔ¦6µm]¥ ‚ð¬‰ð ùUùUùUpÎrÎrÎMš&M“f몞žGn¹qf¤ÎH�‘ �:têЩ´Kk—Ö. ˜Å,fÙºJAáyà¿Näâlv6;›Aó“æ'ÍO¶®êŸ»»ã;`Æç3>Ÿñ9´¼ÙòfË›ÐiI§%�–€,T*+Ï» ‚ ÿŸ¿���÷Ñî£ÝGCÞñ¼ãyÇÿñnm&Ý%Ý%ݦ{ún¨µ¦ÖšZk û©î§ºŸé”tJ:eë*A[à7|—û.÷]™�3g6zÓ›Þ¶®ê¯Ë+ŸW>¯<̰›a7š5 jýÜû¹÷sûJö•ì+ÙºJAÁÖDø õõõÈ?’$ÿ˜N™N™^€OÊEó‹æ͇Y/ÏzyÖËà¸Êq•ã*zf虡gÀÁÎÁÎALû$‚ üB€ßp‰u‰u‰C5C5C50ƒŒOcûgÄf3„Á¼éó¦Ï›:‹Î¢³À¨ £.Œºª©ª©ª©¶®RAøo#Ào8ëü­ó·`eeÆ{Æ{Æ{¶®ê÷LMMañžÅ{ïyx³ß>ø|àîÝ'ºO´u•‚ Â+ñ¥ðo¸^s½æz LɦdS2è.é.é.�xغ8Àz×z×zV½úëÕ_C\J\J\ Ll7±ÝÄvà³Øg±�X÷[Aø"ü†Û}·ûn÷A™®LW¦C–>KŸ¥•¿Ê_e»º¬C¬C¬C 6!6!6~ þ)ø§`»}ìö±Û!P¨TÛzôA„…¿á4Ûi¶Ólpí2Úe4<0<0<0@QDÙ°®}íöµÛ×bÝbÝbÝà}ãûÆ÷�P^]^]^¼ñ ‚ OHÜðžË=—{.‡ì·³ßÎ~Ûvuœ¬~²úÉê°2ceÆÊ ˜20e` ÔhZ£i�¦¶%AáE%¾x õRõRõRÈVd+²Ï¿ý+þWü¯øÃ‚á †/½›ônÒ» 4 lØ0ÐÖ£#‚ ¼èDx ïºÞu½ëÂóóóók7aÂþ„ýðµõkë×Vèð~‡÷;¼­•­•­•¶Aá…¸ðe>,óa™!onÞܼ¹ Oÿžþ½g×ÞÝ#w�Ü=Ó¦M›6m4oÞ8:]ît¹Óe[�† ‚ð¿F€Çð>â}ÄûèƒôAú ((SP¦ ÌÓoçþ¼ûóîσ©û§îŸºj­=´öPx#ö�Ø7bA^W^W^×Ö£!‚ ü¯à1œv9írÚò�ò�ò�PðrÁË/?½ýg¼�ñvÆÛ0¥Æ”Sj@Å£�V< ý×ö_Û-Ø«íÕöâî~Aᑬ¿°u!ÿm4r�\#‡±²±²±2h©n©n©åååÈÑçèsôÐá«_uø Ü/¹_r¿E9E9E9À4¦1 TÓUÓUÓî7·anÃ܆0Y?Y?Y¾|7øn€á>Ã}†û€£ÊQåhÃùA„ÒA€_ܺ~ëú­ë°gž {&À%÷Kî—Üa_¥}•öUK-K-K-(t-t-t…J©•R+¥Â¦ðMá›Â! J@•€*°jϪ=«öÀŽ“;Nî8 Ó‹¦M/7½›ÞMS›Om>µ9¨^V½¬zFùŽòå *‹Ê¢²ØzA„ÒB<ð‹ÔC©‡RÁ”ÎS:Oé éo¦¿™þæã·X° `xtòèäÑ Š,>;‡í¶s¬KZ—´. ´ µ µ ¡úçÕ?¯þ98¼éð¦Ã›ðžã{Žï9Š7~AÁ6Ä=¿xEþŠü9¼±è�Eo,úóí}Ûù¶ómNV'«“®~ýóëŸÃ¡)‡¦šòp»ÝºÝºÝ:Xzýéõ§¡~›úmê·WgWgWg[÷ZA(­Dø…|�|�|¼Óé�Nït‚jöÕì«ÙÿÁ†§8Å)ðÏðÏðÏxøòõõ5dÆgÆgÆ?²ýHF2’’’`䀑F€­Ÿlýdë'`ɵäZrmÝ{A¡´à7*Œª0ªÂ(8fà˜�cÀAí vxän|•·Ê[å a«ÃV‡­†ûƒîº?~<òã‘�€u¢u¢õ�–áíE/zAÞŠ¼y+ Ñ-Ñ-Ñ ,Í-Í-ÍmÝkA¡´à1zDöˆì M¶4ÙÒdËÃ׎9s8�%�%�%plî±¹ÇæÂå¶—Û^nûÈÜpà \ǸŽqo´{£Ýí`ãW¿Úø¼÷ò{/¿÷2Ø]°»`wÁÖ½AJqàcxõôêéÕF„�g÷ŸÝv?(++ƒç<Ïyžó`ÎÔ9SçLãwÆïŒß�£³£³£3¼¼úåÕ/¯†a]‡uÖš7-nZ .¸àbëÎ ‚ ¥ž¢ÉŠ&+š¬€v[Ûmm·Ž=rôÈQ¸´ôÒÒKKád¥“•NV‚jUªU©V¥J”݆uÖm¨‹ÕÅêb[÷BAþ?1ÀŸ¸YöfÙ›ea𗃿ü%œò;åwÊB7‡nÝ MÓš¦5Mƒ÷»¾ßõý®Ö7¬oX_À„ “­«A„?&îxœªT¥*¬²~Èú!pøõï~ôMõMõMávÉí’Û%ÐîT»SíNAØëa¯‡½ŽxãA^"<Îæ0ìííÿc;/;/;/�GË£åѶ.VAžŒ¸àqÓ˜ÆÐã\�s=ÎÁ¥J—*]ªÇ Ç Ç Ð§_Ÿ~}úÁKá/…¿nëbAáɈ{þ¢sŽçÏ9¢7½¹èMø‚/øP/R/Rÿ…™AΈøà/rôsôsôUeUeUePtUtUtµuU‚ ‚ð÷ˆðYÏYÏYÏ�Õ`5X @9äe)KY[W'‚ OFÜ(‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ð¢ËXÆBÊî”Ý)»á²ù²ù²Jv”ì(ÙaëâA„…/˜[Ën-¨¥p÷.KIDAT»µ –6_Ú|is8’}$ûH6ÄoŽß¿ôXÐcAÈNÈNÈN€8Ç8Ç8Gø´þ§õ?­·æßšk¾­{!‚ ØšOJŽ9 !!=ÿæ�·8Þâx Ð×Ô×Ôׄ·Ö¾µö­µàæêæêæ N“œ&9M;;; ‚•OT>Qîº?èþ (Ž,Ž,Ž„ëæëæëfÀGm=¸‚ Âó"À_$5‘šHMÀ¼Ä¼Ä¼®æ^ͽš w]Üuq\u¼êxÕδ9ÓæL(2™ŠL_Ÿ¢OѧÀ•”+)WRàtáéÂÓ…�¸>q}âz°¼fyÍòÚãÛ×uÑuÑu�›UoV½YR‡¦M K2–d,û(û(û(ˆÔFj#µ �“ÎIçÀÑßÑßÑì7Ùo²ßæææ°î•u¯¬{æ š7hÞ Hú*髤¯Àêmõ¶zÃý1÷Çܧ矞z>\Ñ\Ñ\Ñ€±ØXl,†{Y÷²îeÁ§ Nœ áÄ>„ĉ€5Äb ±õQAÇÎÖ¼0üðÃdQ²(Y¬ë°®Ãº�ÿnþ»ùïB»þvýí`Ùée§—�†&G›mrÞÔ¾©}S +]Vº¬tívívív(ÿVù·Ê¿ë—­_¶~¼zêÕS¯ž‚&4¡É4oüÔø©ñSÐ-Ô-Ô-ÝÝÝÈ?�:ÿ4”l)ÙR²>lðaƒÀ' ?YøÉB¨·¾Þúzë�V´¢X�Z�Z�Âõ¸ëq×ãà¾Ó}§ûNPì[ì[ì ·¿¿ýýíïa^�y=æõ€Zµ2jeÀ%å%å%%ÔïX¿cýŽ n¦n¦n1>1>1>зRßJ}+�Ê_å¯ò‡À�€%J[;AáwÄ7‘u�u�u (¿S~§üÔáêpu8¸Ww¯î^4*hTQŸF}õ)ĵ‹k×2ó2ó2ó`ÇÑGw…V Z5hÕ:Duˆê‘ŠHE¤Öç­Ï[ŸÖýÖýÖý¿oß­Š[·*20d`È@ ƒšN5�j:APvPvP68f8f8f€u¶u¶u6ÿþjßú™õ3ëgà´Êi•Ó*È È È‚°ýaûÃöCÕŒªU3à¨óQç£ÎPP¥ JAèáÐá‡Tz§Ò;•Þ��Ñ;£wFƒ_ ¿~-ÀñÇwß�–A-ƒZA©‡ÔCEEE[5AáqDxRf̘=zôÀ*V±êá�¥FR#©XNZNZN‚>SŸ©Ï„bm±¶X NÝ�º;u¸½ûf÷Íî›!¯R^¥¼J`mkmkmûÚÏ!‡°Ö²Ö²ÖúýÈ'Ÿ| ?ýéÿðå¼y-òZ@rTrTr,�[·<î�¿7þÞx¨P! BA ''ö~ö~ö~àPÑ¡¢CE�VJ+¥•¶>X‚ ÂãˆKOJ† àŠ+®Àְ摟{à�H ¥†RCp<ïxÞñ<8rä< îÜ/¸øã�?dk³µÙZðŽõŽõŽY5Y5YµÿÐþ¯û_*-•–½èE/À€H½¤^R/`£RH!H]¥®RW�"¥H)èNwºƒ¹›¹›¹ÛÃÝ{FyFyFAØõ°ëaסO`ŸÀ>� ¸¡¸¡¸ñ°½Dy¢Á}‚û€©�©�© ¤*R© p›ï6ßm>¨T*x`|`|`÷D÷D÷DP;©�ÔN�T1©bREpüÆñÇo "!"!"²eÊ÷Çß<(UJ•R¾�|;ùvÃ%Ã%Ã%¸¿âþŠû+Àÿ�ÿ!ÿCPFWFWFgë£%‚ üþ¢«9Ws®æÀÓÓ|–õYÖgYàZÕµªkU[W'‚ OF\xR,Xl]„ ‚ ü3"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"üER{©½Ô$³d–Ì@ÊPÆÖU ‚ Âß#Öø�U�ª@óZÏk=¯5ÄÿQüG�Ÿ–Ÿ–ŸñÚxm¼²·foÍÞ vkìÖØ­�–mZ¶iÙzlë±­Ç6��‘�‘�±uoAá�‰ðNŸ9}æô$:$:$:ÀòZËk-tÕ½*T¡ \ç:×y[y[y[hx¶áÙ†gÅ¿ ‚ðb—~C>Z>Z>:èp Ãp~ßù}ç÷¿}ùäòÉå“¡QÝFuÕµuõ‚ ‚ð׈µã�é�é� Ú»¶wmï çõçõçõ¿ß®ßõ~×û]‡¥­—¶^Úd)²YŠ­«A„ÿL|𾡾¡¾¡Ð|UóUÍWýþ犗/)^‚ví"ÚEˆ7~AáÅ"ÀcÈRe©²ThòZ“ך¼^2/™×#£UqzÅé§Cí-µ·ÔÞbëjAáɈð'êΩ;§î¨Ð¥B— ]¾Þhr£É�&CзAß}kë*AáɈ§~µ‘�lëyëyëy°ÚYí¬và¶Çm�ÛhÖºYëf­áZĵˆkЬQ³FÍ�ì#ÙG²�À²Ï²Ï²$wÉ]rI-©%5J(¡¶îœ ‚ üÿ3Àl ¶ƒ6H¤ ‚¼¢¼¢¼"Ð&i“´IP[[ š“š“š“�œœ ùó+æW�‹ÎEçFÉ(%(YR²¤d ð Ÿð Ül}³õÍÖ`Îþœý9Ø_e•ýUàÂù ç/œÙW²¯d_�}Š}Š} (f+f+fƒj¸j¸j8¸[Ü-îP‡«ÃÕáà–ê–ê– ÎùÎùÎùàVÝ­º[uð\ã¹Æs 8}äô‘ÓGÀP†2ÔÖ£+‚ ü¯ù¯ À°Ì°Ì° òßÏ?ÿ}xÐâA‹- áX±„c�ŸŸAAA ™©™©™ $“L2(¿S~§üì?·ÿÜþsPUTUTUÏž <€K´K´K48UqªâTÊ;”w(Š]Š]Š] /‘—ÈKÀàcð1ø@VxVxV8 0XÌbƒ¹•¹•¹C�¡ÆPÐètPt£èFÑ ÐžÑžÑž�Ü͹›s7ƒ~´~´~4kkk€a²a²a2(ª*ª*ª‚G�:uÀÿ´ÿiÿÓá–pK¸¼»zwõîú0HȳåÙòl[-AáEaó`íkíkí š›š›š›pÝåºËu¸žw=ïzÜê«ÿ­þ ¦¦vövövöà÷™ßg~ŸAЦ MA›  s@ç€Îäää ÑÑÑ ôQú(}@aQXP¬T¬T¬Ù@Ù@Ù@À<þB¡é¤“œá g€–´¤%à€á÷äG~óóó0Œ`TUFèVéVéVAæ¥ÌK™—àÞü{óï͇Ôz©õRëÁ]Ã]Ã]dgegeg�ì{Ù÷²ïÁ;Ø;Ø;*&TL¨˜‘ªHU¤ "ÖD¬‰XNó�æ;ÍV³šÕ¶:Ê‚ ›ç\pÁ2»evËì—¢.E]Š‚3µÏÔ>Sî�¼7òÞHpã4Æi „�>ªfWÍ®š AÊ e�¼Çz�õûð«udÈJíŒÖ¥Ö¥Ö¥�¿6mþZÈX”±(c$•K*—T®.¹ºäêH™–2-eHU¥ªRU_¾4|)ÔÛToS½MÙ6²md[pñsñsñ³u¯A[yfÀXÝXÝXnn»¹íæ6ø1óÇÌ3áfß›}oö­‡ÖC u:ÖéX§#TWUWUWAèêÐÕ¡«Á~‹ýû-@MjRÓÖÃô˜ÊT¦BQrQrQ2Ül{³íͶpAvAvA—†^zi(XG[G[GC­ µ*ÔªÍï7¿ßü>Nœ8dI²$Y’­;#‚ #ûŒì3^Þóòž—÷€ìCÙ‡²m]´ ‚ðwýå é¨é¨ésÍ4wdÈ8�qÞÕ¿«WUõUõUõüû±8áÅV2¢dDÉØ×{_ï}½aÍ»kÞ]ó.´Ò·Ò·ÒC÷sÝÏu?ö*{•½ÊÖÕ ‚ OêO@þ[ùoå¿ÓÚLk3­ 8ìuØë°†í¶gØðLóLóL³u7^<æ¹æ¹æ¹�äšäšä ÖvÖvÖvPa]…uÖCÂ[W QDÜŠ¾}+fš9hæ ¨=¸öàÚƒ¡_r¿ä~É ’Ƀl]¬ ‚ðW=öºk‰µÄ ‹‡/¾x8¨T*•JD}õAÔ“¿ñgÎÉœ“9¾¼þåõ/¯ÃÁï~ðû§×‘ý1ûcöÇÀ–k[®m¹E�‹:u†�»6îÚ¸ ¾™üÍäo&ƒ¡¦¡¦á?‚ ³õØpdú‘éG¦CæñÌã™Çah­¡µ†Ö§÷œÞszïÉR_Q_Q_�„š 5j•cWŽ]9öô:b?Å~ŠýPvRvRvÕfÕfÕfp˜î0Ýa:ìÛ°oþ `ºmºmº wÛÞm{·-<¨õ ÖƒZ÷£˜¯˜¯˜Š­Š­Š­<³Ç÷®Ù»fïð›à7ÁoôêÑ«G¯ Ë”eÊ2Ÿ^;ª}ª}ª} tR:)�`ßÔ}S÷M…’Å%‹KþÆ¥š² eÊ&ÀÐC; í{çì�³w¤´Ki—Òîé�“ ‚ðlü.EEEÁΑ;Gî ¯^3¼fw?w?÷0qŒl‘l‘lØÏµŸk?2×f®Í\ —k\®q¹Ä9Æ9Æ9‚ÞSï©÷„c‚1ÁW†_~e8WWWÀ­š·jÞª Wf_™}e6ïïï@À[o¼A#‚F�xØ®Óm§ÛN·A¶X¶X¶²ò³ò³òazÎôœé9°}ÝöuÛ×Aβœe9Ë  f@Í€š|0ø`ðAÈKÍKÍK…³ýÏö?Ûnt¸ÑáF8·îܺsëàÖ«·^½õ*àƒ>>¹“s'çN†[n ¸5RÝRÝRÝ ½Wz¯ô^pîö¹ÛçnÃåj—«]®úKúKúK�ì`ÛØ†E†E†Ep-æZ̵¸ãvÇ페n˜n˜n@Âü„ù óáR—K].u�ÔZ©µRk�ì�ì�ìЋ^ôúûÇ3r\ä¸ÈqP½yõæÕ›Ãö˜í1ÛcžîÉ)‚ <;¿ ñoÆ¿ÿ&˜BM¡¦PˆêÕ#ªÇSlñ{¾ç{(Š+Š+Šƒ¬È¬È¬HX•°*aU¬l¿²ýÊöpLwLwL‚'Oý!ý!ý!8QåD•U`‚Ç  wÐ;èàXçc��u†ñ•ÇW_ô)ú} °œå,jQ‹ZÎEÅEÅEhFjFjF‚Áßàoð‡£ÙG³�fÃGE|Ù²d€± Æ6ÛŽ}wì»cßÁ­n}p똰yÂæ ›ávÈí�Û!Þ}ÝÝÝÐÿ ÿAÿHR�ù³ógçφVTXQæ†Í ›–K‰¥Ž.;ºìè2ØSeO•=UÀzÕzÕz6ÝÜtsÓMHšŸ4?i>üXþÇò?–‡tXÐîW¼_ñ~EÈß�¿;7�C9€+Oaú§Æ>�}ûÀµ©×¦^› y²«™*˜*˜*€] »v5žA‹w¹Ë]`6³™ýðeŸ²>e}ÊBQbQbQ"èVèVèV€tN:'�œp‰þÉU�X7[7[73™ÉÌÿ°½9rà*W¹ lg;ÛAê#õ‘ú7¹ÉM�ý ûAö?üüñóðáâ¸b¤)F‚1;bv<ò¹õ¤õ¤õ$X[Z[Z[>|½jZÕ´ªi@_úÒv¶ÙÙfgú:èë ¯¡xUñªâU°Ç´Ç´ÇÞ ¼x7•§ÊSå ¹s'æNïsÞç¼Ï=Ò�_îæÚ¤0)L Yª,U– ¦Ž¦Ž¦ŽO¿Aáéú]ðOóOóOƒœWr^Éy̳ͳͳÿήà /¼x¸šÞ/’“““““ÁËÎËÎËÜ�îFw#”L+™V2 ¬/Y_²¾(Q¢ééé �@3fÌÀ V°ˆ ‚ˆG^_ÈBõ¨G=°î¶î¶îK}K}KýGêû%`H+¥•ÒÊGöß�ntÆ0†1<œ"w0ƒ £Åh1B�{uîÕ¹ÍúhÖG³`‚ÿÿ þмGó͹”"Õ–jKµAZ/­—Ö?|Ýãs�Ï=>‡º“êNª; ÖÎ_;í|¨Õ³VÏZ=¡f»šíj¶ƒXßXßX_®\/¸(†*†*†‚K+—V.­ ¯A^ƒ¼�ôë—U ¥yÒ$}”$—$—$ƒóç1Îc ´Fh�ÐÀ|Á�4(iPÒ Ð[ô½||| 8¦8¦8›6 l¹³sgçΆüåùËó—C™ì2Ùe²A§Ð)t ÐLÑLÑL�à’à’à0Þ4Þ4Þ„Ô¥©KS—B™OÊ|Ræ0X ƒòÝòÝòÝÀ5È5È5´=µ=µ=A½T½T½\’\’\’ yJò”ä)à=Ù{²÷d”¥@ ¤ R©Âïû_P¡ BAH I I »ùvóíæCXrXrX2¨š«š«šƒ©±©±©1d~�ùuæ×°4`iÀRÐËô2½ òìóìóì¡Ìƒ2Ê<Ö²–µ`Z`Z`ZIõ“ê'Õãaãaãa°¯j_Õ¾*KŒ%ÆKKK—a.Ã\†=ùqÌ=Ÿ{>÷š|4.^¼xñâE�Ê e…ðŠêÕ+*hZ¡i…¦@=P=P=ÐÖ�Ažµ§~Ë:É:É: rëäÖÉ­çcÎÇœ��£�n<ºÒÇ¥�Kµ†0„!¶îœ ‚ð¼<óð8æqæqæq�~:ýtúi¸™q3ãf\¨s¡Î…:�Ò)¥SJ'(ÙT²©døûûCðÜà¹Ás!bqÄâˆÅà7ÅoŠßðlíÙÚ³õÙôìÚ´;hëá}yä‘úïôß鿃¼Ny�ò:Aκœu9ë Mž&O“CÂO ?%ü÷‚ïß †¼Ì¼Ì¼Lpvvvvv†ð¯Ã¿ÿjׯ]¿v}(7´ÜÐrCÁ³¶gmÏÚ 5�H þy¹‚ ‹Ífà±:әΠWéUz¤ø¤ø¤ø@âáÄɇ!iBÒ„¤ po꽩÷¦BÁÉ‚“'¡d{Éö’íà|Öù¬óYPWWWWW¯ê^Õ½ªƒÇh�Ñ£ÁsˆçÏ! ÎRg©³Àm„Û· ,T* A¾\¾\¾äÊ?”R#©‘Ôd'e'e'A:/�—΃eŒeŒe X/[/[/ƒ¥¡¥¡¥!˜˜˜@‰¥ÄRbÝÝÝÐ8iœ4N�}*ûTö)ÈUä*r ±j¬+dÇdÇdÇ@NpNpN0è_Ó¿¦ ”””À½Ž{÷:º#tGès s sƒˆmÛ"¶A™žez–é vƒìÙ ºÐ….¶>˜‚ «ÿ¾ðg>á>C+C+C+(ò*ò*ò‚‚áà †Cª*U•ª‚´Vi­ÒZAöÛÙog¿ o�·Æ4w5w5w¡èZѵ¢k`hlhlh ÖUÖUÖU ##’BRH �&I“¤I`èaèaèÚ•Ú•Ú•àµÉk“×&�]‘]‘]Ë6Ë6Ë6°.³.³.ËËË��“�“�Ç•Ž+W‚sŒsŒs ¸¹¹�Ç1�cÇÀ»�wï>h 4ÁÏËÏËÏ œ—9/s^ª»ª»ª»`7Þn¼ÝxÀgœm}0A„Õ‹þ!k'k'k'Ð÷Õ÷Õ÷ÃÃÃ0L4L4LS9S9S90�2�2�i·´[Ú ×¢®E]‹‚u××]_wÞ_òþ’÷—€ëb×Å®‹AVAVAVìß°Ãþ PtPtPtåååPÎVÎVÎåDåDåD –Xbm=‚ BiUêÀßu­úµêתÒo–|³äø´Â§>­®¾®¾®¾¶®NAžŒ˜¼÷/²°°«Áj°€L2É|ñEAá#ûç»AáE#€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$Àoe“M6�Fi_–¤0) ¤÷¤÷¤÷*T�ü^ $zôèmÝ AAøÏ$ë/l]È‹b»b»b;Øí»Ûw·/dh3´Z¸ï~ßý¾;œH=‘z"ÚMh7¡ÝPöQöQö�ª?Tý¡ê-EKÑÈ&É&É&Ùº7‚ ‚ðÇDø c?c?c?è?¨ÿ þƒà‡ú?Ôÿ¡>°—½ì¶³�íÀ+¼Â+ ;&;&;³[În9»% k;¬í°¶¶î… ‚ ügâÀo(–+–+–CK]K]K8;;­hE+`.s™ t£Ý ¨jPÕ ªÐplñ ÇÚºzAAøkDxŒhÏhÏhOjÔ,¨Ùã·«q§Æ�w rbåÄʉ¶®ZAþ#`nÀÜ€¹ÐüBó Í/üþçvÕìªÙUƒW­¯Z_µ‚¢XQ¬(¶uÕ‚ ‚ð׈ðŠÅŠÅŠÅÐħ‰OP�Q�Q�yøó ø ø xh0£ÁŒ3l]­ ‚ <þDƒ 4hC#†F }øzÃà 7< ¡ýBû…ö³u•‚ ‚ðdìl]À»2õËÔ/Sš:6ulê   Ð*¿U~«|PÎWÎWηu•‚ ‚ðdž{¸k¼k¼k„ý¡ûC÷‡‚1ŘbL©—ÔKêeëáx„„„²Ã²Ã²Ã ¹¤¹¤¹v'ìNØ�€[Ëo-¿µ-^´xÑb°JVÉ*Ùºèß³¬´¬´¬¯W½^õzÚèÚèÚèÀå„Ë —¶®NA°•ç>Àކ;îhßzëý­7´­Þ¶zÛê`ýÎú�õ;[Çø‰Ÿø Š¿(þ¢ø H�I�I��àQÁ£‚G�Ü,7ËÍÀu®sÝÖÅ>ÂwÜA_[_[_t8Ðá@ø¦Á7 ¾iáêpu¸ÚÖE ‚ ¶òÜ¿°¼ayÃòTÝUuWÕ]0dÒ�IC&“˜ÄñÌy–w-ïZÞS¡©ÐTJ‹Ò¢´»ØÅ.[W÷xEYEYEYpåê•«W®‚5ÝšnMÔ¨@¡Ô÷üE²Z²Z²Z D‰`';ÙiëªAáïO‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B"‚ B)$€ ‚ ”B/l°¦ZS­©�¹8sqæb¸àuÁë‚äÏÈŸ‘?t t t àfÓ›Mo6ÃjÃjÃj[Wýä4ÿÒüKó/¸}1úb4¤I?’~ÄÖU ‚ /º60ŠQŒ�QcÔáÃ}îûp\èp¡Ã…�>+}Vú,˜7vÞØyc!gLΘœ1¶.úÉŽŽŽÁK¿XúÅRØþýöï·oëªA„Ý ¬·¬·¬·À´Î´Î´bbbÀQã¨qÔ€ù˜ù˜ùM š4 >vøØácðYí³Úç‘o̘?0�AgÐ�ù{ó÷æï=zô�´WÆZÆZŒc�c�cÁènt7ºƒåˆåˆå‘Oâ–ÖÖÃ`ô3úýÀ4Õ4Õ4˜Â¦€e‡e‡e˜CÍ¡æP°ô±ô±ô�K‰¥Ä¬`+€�ù˜�Á4×4×4ÔoªßT¿ î¹î¹î¹`~Ãü†ù [AáE÷ÂÌhz×ô®é]زyËæ-›!¹qrãäÆàºÔu©ëRÈÞœ½9{3H_J_J_BbNbNb|=çë9_Ï�Á!ƒC‡€z”z”z¬,\Y¸²”½”½”½@}B}B}zÕéU§W0Ž3Ž3Žƒ�u6ÖÙX´•´•´• xLñ˜â1öZØka¯A�¼y=ò`}ùõå×—‡Ô¦©MS›BþæüÍù›áå/·x¹„î ݺ¾nøuïBÍ÷k¾_ó}°¬¶¬¶¬†n»Mì6âfÄ͈›gLgLgLàÝØ»±wc¸�q;ãvÔñ¬ãYÇÓÖGCAxѽ0ßœ>qúÄé°±pcáÆBè5¥×”^S wãÞ�{7õ~õ~õ~°N·N·N‡PïPïPo¸Ÿr?å~ ä‡ç‡ç‡Ã�âÅŠ!nGÜŽ¸Ðç‹>_ôùêm­·µÞV�o—o—o‡Í 67ØÜ.Lº0éÂ$èÿzÿ×û¿}ä}ä}äà¶Ìm™Û²‡õï Þ¼_|eð¨1²ÆÈ#aÅÇ+>^ñ1¨·ª·ª·BÊK)/¥¼Î&g“³ Z,m±´ÅRH›š65m*Ì�›7?Z·*nU ýÇõׄº†º†º‚¥ÐRh)´õÑA^t/L¸ÞçzŸë}À#Ä#Ä#Êf—Í.› öÉöÉöÉ µ”ZJ-�<àÈ_’¿$ dñ²xYÌ�6wÚÜiP©C¥•:Àøã;Œï cÆ&Œå<å<å<(©]R»¤ö#uô–zK½Áî»wìÞ�k×®ÀäÚ“kO® ªxU¼*¼'zOôž,e)KÖñïeƒÏr–³�ì7NŠ“â€A b°ˆE,zdœqƨD%*Ùúh‚ /º&T-ªZTµ4:�N£ƒKÕ.U»T ²‹²‹²‹ÀpËpËp Š»w+î…µ kÖý6ý6ý6(îZܵ¸+¹väÚ‘k�¹ sAæh’Ý$»I6¸^s½æz LËMËMˡѵF×]ƒëšëšë¸1ãÆŒ3 Ë1Ë1Ëô3õ3õ3!ÿëü¯ó¿†¼!yCò†@ðõàëÁ×A}X}X}Œ)Æc ô)èSÐ 2ƒÌ ƒÂe…Ë ¹„Ò$¤IHpÀàÔW§¾:õä\ιœstMuMuMAwNwNwÎÖGCAxѽ07Ö)©SR§ú¥ôKé—Ç'Ÿp|” .\&Ýjt«Ñ-P,V,V,†äÓɧ“OC½µõÖÖ[ ¦–¦–¦–à<Ðy ó@8×õ\×s]A'‹“ÅÁЃC=Ök„Âß 'ü�í’í’í‚ïxçÀ;àeõ²zY¡rDåˆÊPe]•uUÖA×Ϻ~Öõ38xþàùƒçÁéªÓU§«Ð4¦iLÓHé•Ò+¥Ô�­[?JÚ”´)if…YaV@Ⱥ�u!ë`”ý(ûQöpöÒÙKg/�¦¢¦¢¦"T{©ÚKÕ^¿Ù~³ýfƒ¡º¡º¡:(£”QÊ([AáE#Yñ¼ܶ`Û‚m à䮓»Nî‚)Û§lŸ²ÝÖÃð¿«(«(«( †^zuèUøÈû#ï�¼!¢JD•ˆ*¶®NA°•æ€ ‚ O�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P ‰ ‚ ¥�‚ ‚P =ÿGq@EÙºû¥€ 2 �4Ò€d’I¶uQ‚ ‚­=÷©€´Z-\Œ¹s1Æ{xìa Íhfëáø¢B… ' ' ' oTÞ¨¼Q`ï`ï`ï´§=ím]¤ ‚`+Ï}*àœ-9[r¶Àå —'\žú]ú]ú] u•ºJ]m=ÿC¬X±‚µ³µ³µ3xä{ä{äC�5vÔØW®:\µu‘‚ ‚­<÷ ‚ ‚퉛A¡ú?aî #˰.zTXtcreate-datexÚ320°Ô50Õ54 14·2°´26Ò60²20Aë4¼yð.zTXtmodify-datexÚ320°Ô50Õ54 14·2°´26Ò60²20AëV„ŽIEND®B`‚rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_maxopenfiles.rst0000644000000000000000000000013215216464435027277 xustar0030 mtime=1782212893.972265311 30 atime=1787067671.721438635 30 ctime=1787067791.142664453 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_maxopenfiles.rst0000664000175000017500000000257015216464435026747 0ustar00rgerrger$MaxOpenFiles ------------- **Available Since:** 4.3.0 **Type:** global configuration parameter **Status:** deprecated legacy directive. Use ``global(maxOpenFiles="...")`` in new configurations. **Default:** *operating system default* **Description:** Set the maximum number of files that the rsyslog process can have open at any given time. Note that this includes open tcp sockets, so this setting is the upper limit for the number of open TCP connections as well. If you expect a large number of concurrent connections, it is suggested that the number is set to the max number connected plus 1000. Please note that each dynafile also requires up to 100 open file handles. The setting is similar to running "ulimit -n number-of-files". For new configurations, use the RainerScript global parameter instead: .. code-block:: none global(maxOpenFiles="2000") The YAML equivalent is: .. code-block:: yaml global: maxOpenFiles: 2000 Please note that depending on permissions and operating system configuration, the setrlimit() request issued by rsyslog may fail, in which case the previous limit is kept in effect. Rsyslog will emit a warning message in this case. **Sample:** ``$MaxOpenFiles 2000`` **Bugs:** For some reason, this settings seems not to work on all platforms. If you experience problems, please let us know so that we can (hopefully) narrow down the issue. rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_mainmsgqueuesize.rst0000644000000000000000000000013215132411300030154 xustar0030 mtime=1768559296.174884185 30 atime=1787067671.689438039 30 ctime=1787067791.140664416 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_mainmsgqueuesize.rst0000666000175000017500000000306515132411300027626 0ustar00rgerrger$MainMsgQueueSize ----------------- **Type:** global configuration parameter **Default:** 50000 (v8.30.0) - may change **Description:** This allows to specify the maximum size of the message queue. This parameter is only available when rsyslogd has been compiled with multithreading support. In this mode, receiver and output modules are de-coupled via an in-memory queue. This queue buffers messages when the output modules are not capable to process them as fast as they are received. Once the queue size is exhausted, messages will be dropped. The slower the output (e.g. MariaDB/MySQL), the larger the queue should be. Buffer space for the actual queue entries is allocated on an as-needed basis. Please keep in mind that a very large queue may exhaust available system memory and swap space. Keep this in mind when configuring the max size. The actual size of a message depends largely on its content and the originator. As a rule of thumb, typically messages should not take up more then roughly 1k (this is the memory structure, not what you see in a network dump!). For typical linux messages, 512 bytes should be a good bet. Please also note that there is a minimal amount of memory taken for each queue entry, no matter if it is used or not. This is one pointer value, so on 32bit systems, it should typically be 4 bytes and on 64bit systems it should typically be 8 bytes. For example, the default queue size of 10,000 entries needs roughly 40k fixed overhead on a 32 bit system. **Sample:** ``$MainMsgQueueSize 100000 # 100,000 may be a value to handle burst traffic`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_moddir.rst0000644000000000000000000000013215132411300026037 xustar0030 mtime=1768559296.174884185 30 atime=1787067671.740438989 30 ctime=1787067791.144664491 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_moddir.rst0000666000175000017500000000106615132411300025510 0ustar00rgerrger$ModDir ------- **Type:** global configuration parameter **Default:** system default for user libraries, e.g. /usr/local/lib/rsyslog/ **Description:** Provides the default directory in which loadable modules reside. This may be used to specify an alternate location that is not based on the system default. If the system default is used, there is no need to specify this parameter. Please note that it is vitally important to end the path name with a slash, else module loads will fail. **Sample:** ``$ModDir /usr/rsyslog/libs/  # note the trailing slash!`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_includeconfig.rst0000644000000000000000000000013215132411300027372 xustar0030 mtime=1768559296.174884185 30 atime=1787067672.332450025 30 ctime=1787067791.138664379 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_includeconfig.rst0000666000175000017500000000563315132411300027047 0ustar00rgerrger$IncludeConfig -------------- .. warning:: This legacy directive has been superseded by the rsyslog :doc:`include() <../../../rainerscript/include>` configuration object. While it is save to use the legacy statement, we highly recommend to use it's modern counterpart. Among others, the `include()` object provides enhanced functionality. **Type:** global configuration parameter **Default:** **Description:** This parameter allows to include other files into the main configuration file. As soon as an IncludeConfig parameter is found, the contents of the new file is processed. IncludeConfigs can be nested. Please note that from a logical point of view the files are merged. Thus, if the include modifies some parameters (e.g. $DynaFileCacheSize), these new parameters are in place for the "calling" configuration file when the include is completed. To avoid any side effects, do a $ResetConfigVariables after the $IncludeConfig. It may also be a good idea to do a $ResetConfigVariables right at the start of the include, so that the module knows exactly what it does. Of course, one might specifically NOT do this to inherit parameters from the main file. As always, use it as it best fits... Note: if multiple files are included, they are processed in ascending sort order of the file name. We use the "glob()" C library function for obtaining the sorted list. On most platforms, especially Linux, this means the sort order is the same as for bash. If all regular files in the /etc/rsyslog.d directory are included, then files starting with "." are ignored - so you can use them to place comments into the dir (e.g. "/etc/rsyslog.d/.mycomment" will be ignored). `Michael Biebl had the idea to this functionality `_. Let me quote him: Say you can add an option ``$IncludeConfig /etc/rsyslog.d/`` (which probably would make a good default) to ``/etc/rsyslog.conf``, which would then merge and include all ``*.conf`` files in ``/etc/rsyslog.d/``. This way, a distribution can modify its packages easily to drop a simple config file into this directory upon installation. As an example, the network-manager package could install a simple config file ``/etc/rsyslog.d/network-manager.conf`` which would contain. ``:programname, contains, "NetworkManager" -/var/log/NetworkManager.log`` Upon uninstallation, the file could be easily removed again. This approach would be much cleaner and less error prone, than having to munge around with the ``/etc/rsyslog.conf`` file directly. **Sample:** ``$IncludeConfig /etc/some-included-file.conf`` Directories can also be included. To do so, the name must end on a slash: ``$IncludeConfig /etc/rsyslog.d/`` **And finally, only specific files matching a wildcard my be included from a directory:** ``$IncludeConfig /etc/rsyslog.d/*.conf`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_debugprintcfsyslinehandl0000644000000000000000000000013215132411300031044 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.232448161 30 ctime=1787067791.127664174 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_debugprintcfsyslinehandlerlist.rst0000666000175000017500000000052415132411300032545 0ustar00rgerrger$DebugPrintCFSyslineHandlerList ------------------------------- **Type:** global configuration parameter **Default:** on **Description:** Specifies whether or not the configuration file sysline handler list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled. rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_generateconfiggraph.rst0000644000000000000000000000013115171370365030604 xustar0029 mtime=1776677109.10790793 30 atime=1787067672.312449653 30 ctime=1787067791.136664341 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_generateconfiggraph.rst0000664000175000017500000001713715171370365030262 0ustar00rgerrger.. _rsconf1_generateconfiggraph: .. meta:: :description: Legacy rsyslog global parameter $GenerateConfigGraph for generating configuration graph data. :keywords: rsyslog, global option, GenerateConfigGraph, Graphviz, configuration graph .. summary-start ``$GenerateConfigGraph`` is a legacy global parameter that can emit Graphviz dot data for visualizing rsyslog configuration flow. It is currently disabled. .. summary-end $GenerateConfigGraph -------------------- **Type:** global configuration parameter **Default:** **Available Since:** 4.3.1 **CURRENTLY NOT AVAILABLE** **Description:** **This parameter is currently not supported. We had to disable it when we improved the rule engine. It is considerable effort to re-enable it. On the other hand, we are about to add a new config system, which will make yet another config graph method necessary. As such we have decided to currently disable this functionality and re-introduce it when the new config system has been instantiated.** This parameter permits to create (hopefully) good-looking visualizations of rsyslogd's configuration. It does not affect rsyslog operation. If the parameter is specified multiple times, all but the last are ignored. If it is specified, a graph is created. This happens both during a regular startup as well a config check run. It is recommended to include this parameter only for documentation purposes and remove it from a production configuration. The graph is not drawn by rsyslog itself. Instead, it uses the great open source tool `Graphviz `_ to do the actual drawing. This has at least two advantages: - the graph drawing support code in rsyslog is extremely slim and without overhead - the user may change or further annotate the generated file, thus potentially improving his documentation The drawback, of course, is that you need to run Graphviz once you have generated the control file with rsyslog. Fortunately, the process to do so is rather easy: #. add "$GenerateConfigGraph /path/to/file.dot" to rsyslog.conf (from now on, I will call the file just file.dot). Optionally, add "$ActionName" statement **in front of** those actions that you like to use friendly names with. If you do this, keep the names short. #. run rsyslog at least once (either in regular or configuration check mode) #. remember to remove the $GenerateConfigGraph parameter when you no longer need it (or comment it out) #. change your working directory to where you place the dot file #. if you would like to edit the rsyslog-generated file, now is the time to do so #. do "dot -Tpng file.dot > file.png" #. remember that you can use "convert -resize 50% file.png resized.png" if dot's output is too large (likely) or too small. Resizing can be especially useful if you intend to get a rough overview over your configuration. After completing these steps, you should have a nice graph of your configuration. Details are missing, but that is exactly the point. At the start of the graph is always (at least in this version, could be improved) a node called "inputs" in a triple hexagon shape. This represents all inputs active in the system (assuming you have defined some, what the current version does not check). Next comes the main queue. It is given in a hexagon shape. That shape indicates that a queue is present and used to de-couple the inbound from the outbound part of the graph. In technical terms, here is a threading boundary. Action with "real" queues (other than in direct mode) also utilize this shape. For actions, notice that a "hexagon action" creates a deep copy of the message. As such, a "discard hexagon action" actually does nothing, because it duplicates the message and then discards **the duplicate**. At the end of the diagram, you always see a "discard" action. This indicates that rsyslog discards messages which have been run through all available rules. Edges are labeled with information about when they are taken. For filters, the type of filter, but not any specifics, are given. It is also indicated if no filter is applied in the configuration file (by using a "\*.\*" selector). Edges without labels are unconditionally taken. The actions themselves are labeled with the name of the output module that handles them. If provided, the name given via "ActionName" is used instead. No further details are provided. If there is anything in red, this should draw your attention. In this case, rsyslogd has detected something that does not look quite right. A typical example is a discard action which is followed by some other actions in an action unit. Even though something may be red, it can be valid - rsyslogd's graph generator does not yet check each and every specialty, so the configuration may just cover a very uncommon case. Now let's look at some examples. The graph below was generated on a fairly standard Fedora rsyslog.conf file. It had only the usually commented-out last forwarding action activated: .. figure:: rsyslog_confgraph_std.png :align: center :alt: rsyslog configuration graph for a default fedora rsyslog.conf rsyslog configuration graph for a default fedora rsyslog.conf This is the typical structure for a simple rsyslog configuration. There are a couple of actions, each guarded by a filter. Messages run from top to bottom and control branches whenever a filter evaluates to true. As there is no discard action, all messages will run through all filters and discarded in the system default discard action right after all configured actions. A more complex example can be seen in the next graph. This is a configuration I created for testing the graph-creation features, so it contains a little bit of everything. However, real-world configurations can look quite complex, too (and I wouldn't say this one is very complex): .. figure:: rsyslog_confgraph_complex.png :align: center :alt: Here, we have a user-defined discard action. You can immediately see this because processing branches after the first "builtin-file" action. Those messages where the filter evaluates to true for will never run through the left-hand action branch. However, there is also a configuration error present: there are two more actions (now shown red) after the discard action. As the message is discarded, these will never be executed. Note that the discard branch contains no further filters. This is because these actions are all part of the same action unit, which is guarded only by an entry filter. The same is present a bit further down at the node labeled "write\_system\_log\_2". This note has one more special feature, that is label was set via "ActionName", thus is does not have standard form (the same happened to the node named "Forward" right at the top of the diagram. Inside this diagram, the "Forward" node is executed asynchronously on its own queue. All others are executed synchronously. Configuration graphs are useful for documenting a setup, but are also a great :doc:`troubleshooting ` resource. It is important to remember that **these graphs are generated from rsyslogd's in-memory action processing structures**. You can not get closer to understanding on how rsyslog interpreted its configuration files. So if the graph does not look what you intended to do, there is probably something wrong in rsyslog.conf. If something is not working as expected, but you do not spot the error immediately, I recommend to generate a graph and zoom it so that you see all of it in one great picture. You may not be able to read anything, but the structure should look good to you and so you can zoom into those areas that draw your attention. **Sample:** ``$DirOwner /path/to/graphfile-file.dot`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_failonchownfailure.rst0000644000000000000000000000013215132411300030440 xustar0030 mtime=1768559296.174884185 30 atime=1787067672.293449298 30 ctime=1787067791.134664304 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_failonchownfailure.rst0000666000175000017500000000117115132411300030106 0ustar00rgerrger$FailOnChownFailure ------------------- **Type:** global configuration parameter **Default:** on **Description:** This option modifies behaviour of dynaFile creation. If different owners or groups are specified for new files or directories and rsyslogd fails to set these new owners or groups, it will log an error and NOT write to the file in question if that option is set to "on". If it is set to "off", the error will be ignored and processing continues. Keep in mind, that the files in this case may be (in)accessible by people who should not have permission. The default is "on". **Sample:** ``$FailOnChownFailure off`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_umask.rst0000644000000000000000000000013215132411300025701 xustar0030 mtime=1768559296.174884185 30 atime=1787067671.869441394 30 ctime=1787067791.151664621 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_umask.rst0000666000175000017500000000107115132411300025346 0ustar00rgerrger$UMASK ------ **Type:** global configuration parameter **Default:** **Description:** The $umask parameter allows to specify the rsyslogd processes' umask. If not specified, the system-provided default is used. The value given must always be a 4-digit octal number, with the initial digit being zero. If $umask is specified multiple times in the configuration file, results may be somewhat unpredictable. It is recommended to specify it only once. **Sample:** ``$umask 0000`` This sample removes all restrictions. [`rsyslog site `_\ ] rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsyslog_confgraph_std.png0000644000000000000000000000013215132411300027505 xustar0030 mtime=1768559296.175884201 30 atime=1787067730.693537881 30 ctime=1787067791.156664714 rsyslog-8.2608.0/doc/source/configuration/global/options/rsyslog_confgraph_std.png0000666000175000017500000050751415132411300027167 0ustar00rgerrger‰PNG  IHDRØM`TRMbKGDÿÿÿ ½§“ pHYsHHFÉk> vpAgØM©aºß€IDATxÚìÝe|Tgþÿÿ×™‰‡8„  Ü)®A*hq+EZ(RJ‹ $!¸»O  NÜ]'3™9ÿßí»ým·$ t¯ç�>2r�÷çšÙýpΜsIþAá¢ÐwAAø+ ôàÏÒfh3´}$úHôH²H²H²´hÑ ŸD;öÇ0�k:×t.T;VíXµc`>ß|¾ù|}‡AøtHû!ÄäÉ;’w@ O O ÜRÝRÝR�uKë–Ö-AYFYFYˆ&šh}§ý0€�é•é•é¶6¶6¶6à³Íg›Ï6hÚ0´a(HG¥£ÒQ}‡Aøx}t{`ùr¾œ/Ã…Œ 2àð³ÃÏ?'S'S'S˜?jþ¨ù£ ò«Ê¯*¿©¾T_ª`ðñUóŽßö[Ò’–�};ûvöm8›r6ål lh±¡Å†PW[W[W ž-=[z¶„Š×+^¯x]ßáA>>zßÓuÓuÓuƒðÀðÀð@Ø“º'uO*¨z¨z¨zÀàƒ >Íã›Ç7�emememÈ:›u6ë,¨BT!ª µ¨(Q¢Ô÷´þ�xÄ#PnUnUnë†Ö ­‚á5Ãk†× ftÌè˜Ñ°7aoÂÞxÒõI×']¡‡}ûöÐãz�ë=®ƒù:óuæëô]Œ ‚þé­�%|“ðMÂ7àoæoæoaê0u˜:»tvéì½B{…ö «5Vk¬Ö@î÷¹ßç~Ç:þÓñŸàøÇ8þƒ2I™¤LÞð†7úžÖß“÷È{ä=�™™ µ†ÖZk(xó:æu ªUªV©Z%ЮҮҮ‚{Mï5½×ü‚ü‚ü‚@§Ð)t ðêãÕÇ«4îѸGã 4T* õ]� ‡÷ÁXžUžUžœ¾wúÞé{p|îñ¹ÇçBõEÕU_^ ¼x5§_œ~qú4>�ÜtgÐ�AàŸàŸàŸFõ�êÕ‡þ÷úßë*W ® R²”,% $� ïiý7ÝNj'µƒŸŸ8·ñÜÆs!Ä-Ä-Ä ÚÍn7»Ýlð¨íQÛ£6ØÔ³©gSòZçµÎk §{œîqº/}¼ôñÒP}xõáÕ‡ƒW¯2^eÀ©ŠS§*À]îrWßÕ ‚ ”¼k`Z7­›Ö îͼ7óÞLð{ì÷Øï1ènênên‚WM¯š^5¡I@“€& X£X£Xoν9÷æø%ø%ø%À«¯z¼ê›<6yl‚ÎU:Wé\LϘž1=ê)ê)ê)PdXdXdXb‰% !!é{z�rÈ©ªTUª &~&~&~ÀŽp"œ"œ"œ`—ÿ.ÿ]þ�á›á›á ƒ|ù ò�ÖÓZOk= ŒŒŒ aQ¢„EàŸèŸèŸaUª„U�Îc;�í<z}Óë›^߀Õz«õVëõ]¼ BÉ)ös æ@ÌØ{zïé½§á‰ú‰ú‰ztëÑ­G7è¡ì¡ì¡ó�æÍBÖ’¬%YKàpÃà 7„ S/L½0�kt®Ñ9ðÜí¹Ûs7”›SnN¹9 öV{«½áòˆË#.�€Î'œO8ƒÖZk­µÅ0Å0Å0 ƒ 2ô=½À@2 GŽ(õFÔQo Œ;0ʆ” )…ý ûöƒK.¸tŒ?0þÀx°ïkß×¾/øæùæùæA M M èŽêŽêŽBøìðÙá³aOìžØ=± š¦š¦šC"†D ‰€fAÍ‚š�AoƒÞ½õ=‚ Åç½X¶K¶K¶ œÜwrßÉ}pÚé´Ói'¨;¢îˆº#À3Ã3Ã3ãíÙt[�­Æ®½~ôúQ\¸$p XT°¨`Q¼½¼½¼½ Ž_¿:~ Õ•êJuáIŸ'}žô¿r~åüÊAÚ£´Gi� Gx�ðáàø£ã�Ž?‚,ËÁ@yäé{zA'�“ÆAÁØ‚±cáüŠó+ί€(ß(ß(_ès²ÏÉ>'¡“q'ãNÆ`º×t¯é^H[š¶4m)hy å�–píѵG×AË!-‡´ýüúùõóƒ2“ÊL*3 ò3ò3ò3àÂý ÷/܇Ç:|œv;ívÚ ^s¼æxÍ�jÓ«M¯6]ß³"‚ðþþëVäTäTäw¤;Ò ö¦ìMÙ›†§ OžŸ“>'}NBÔ†) S@ò—ü%xÑáE‡`·Çn�Ýgggý#úGô�€Ïæ~6÷³¹`\ʸ”q)H^œ¼8y1EEEÂÍ 7+Ü¬íÆ·ßn<ôKí—Ú/ljÛÔ¶©­ïiü󊲋²‹²áÖü[óo͇½5÷ÖÜ[L™62m>v>v>và¶Óm§ÛNPTWTWT‡g?=ûéÙOàׯ…_ ˆ¯_;¾6 è< ó€ÎЮ[»níº�I˜I˜I$¯O^Ÿ¼>|wÜYpg´¿ÓþNû;àÑÉ£“G'°±´±´±Ô÷¬‚ ü÷þsË'Ÿ|xãþÆý�;ø�öí7^µÕþU{ðØæ±ÍctÑqDÇ`Þȼ‘y#Hß—¾/}¼zðêÁ«p5æjÌÕhÞ¸yãæ�a`äÀÈ�‘Pú×Ò¿–þ ­ ­ ­áü¨ó£Î�‚ƒyóæ�ã ÇŽ/À»œw9ïrP-§ZNµœ¿Ï…¾969696p4òhäÑH8[ál…³ Þâz‹ë-†!“†L2 ”J%¨sÕ¹ê\¸öÓµŸ®ýGŽ›X›X›Xð)ïSÞ§<Ôq®ã\Çtststs ¢aDȆ°Ûy·óngHß“¾'} 9xäà‘Ð&¯M^›<0ˆ4ˆ4ˆÔ÷¬‚ ügØÀ²|³|³|áȰ#ÃŽ ƒ ‡/¾pù5òkäUUUP¾ |Aù(lZØ´°)\wuÜÕq°?uêþT(Ó·Lß2}Á;Ù;Ù;j}[ëÛZß‚&‡Éaþ*üUø+ØÛoo¿½ý W�«ÎUƒçÏž; Eë­[´Ã†/ _è{ºJP@Ôâ¨ÅQ‹aŸjŸjŸ ž={öìÙ3è9¥ç”žS óúÎë;¯ ,°Òw¤ïHßÇ"ŽE‹€‹ .@ãv�Û5nG 1pØgÙgÙg�ê¹ê¹ê9\peÀ•p`Í�5Ö€}œ}œ}x—ñ.ã]j\­qµÆU�VH+¤úžA„ßû]{Úãi�§=`­f­f­¬V +ø÷î;êdÔɨ“ò0y˜< "R#R#Ra�ãÇ=Ž�–•–•–ƒÆ;h,´ nÜ6    ±Jb•Ä*à?Ïžÿ<¸÷üÞó{ϡӨN£:�‚>ûtìÓ,£,£,£ô==ú£[­[­[ !‘!‘!‘à·Ìo™ß2à7¸>J¥�~Ö𳆟������¼Ò¼Ò¼ÒÀÍÍ D}õmÔ·à‘ï‘ï‘�›tnÒ¹ ˜xšxšxBÚ„´ iàÀóÏ<‡‹©S/¦B¯f½šõjÞí¼Ûy·ãŸ'£‚ |4ä±ëÑ®G»Éò¤Ó“NO:-Ë*{•½Êþíó)›S6§l–åMõ7ÕßT_–}†û ÷.Ë[}¶úlõ‘å4‡4‡4‡·¯Ï_ž¿<¹,ìu°×Á^²<Ü~¸ýp{Y^’±$cI†,¿qxãðÆA–åãòqù¸,ü�œ.9]rºÈr`d`d`¤,›0l° ²ümæ·™ßfÊrÔ�¨!QCÞ¾^=U=U=U–ƒs‚s‚sdù+ƒ¯ ¾2�å)¦\˜rA–Ã,Ã,Ã,eY·U·U·õíûdÙg©ÏRŸ¥²¬Y®Y®Y®ïêA~ïw«*R)ŠpjáÔ©'''Âëô×é¯ÓaYÀ²€ePñvÅÛoÃüÖó[Ïo ... ­©­©­ ¡“C'‡N†½{#öF€æ„æ„æŒ]4vÑØEÐØ¿±c0ˆ3ˆ3ˆÓwÿø•:]êt©Óow„š57jnð�ç7žßxB×]Ot==#zFôŒ€V¥Z•jU êfÕͪ›'Æ�wb,ß¶|Ûòm0Àg€Ï4jШA£ ò¶ÊÛ*oË!–C,‡€üD~"?Ñwõ‚ ¿÷ûåoKSšÒüó7F3šÑðÚäµÉk0žb<Åx Ìy:ç霧`|Ûø¶ñmˆ+W.®ì5Øk°×?2~d ݃»w†ó{Ìï1J-/µ¼Ôr}—ý髸]Åï*~_ÿúõ¯_ÿ ásÃç†Ï…=i{Òö¤Áµ]×v]Û^^^ÐôZÓkM¯�ׯ^¿zý ÚåÚåÚåƒÄ @ž(O”'W¹ÊUÀ 3Ìô]­ Âïýù;h�a cÀÔÝÔÝÔŒë×3®s3æfÌ…é™Ó3§gBA@A@A,«³¬Î²:à9Ás‚çѸJŠb„b„b4ˆoß –¬Z²jÉ*è2­Ë´.Ó`ƒÕ« VpºÛén§»½}Ÿ]¡]¡]!˜&˜&˜~„Ko ‚ ü'¾�bˆ!à‡~oε̵̵e'e'e'ø¢â¿¨}+úVôV²’•ú.ó‡Ù$³If“ wLï˜Þ1ÐúrëË­/ÃËu/×½|g{y¨1¿Ý®Eš!Í�fè;� BñyÿfŠ)¦ �•ÇÊc�­lek þÇ¢¿ŠZŠZŠZ@5ªQíƒÍ×JsMsMs…WÚWÚWZ}§Aøû{ÿö�èVêVêVBÅ‹/V¼...�¥ÎRg©áÞ…{î]€g5ŸÕ|Vž„= {/F¾ùb$iŠ4EˆÈŽÈŽÈ†»Çî»{ Âë…× ¯Ož8=ŸL“FK£¥ÑpÍæšÍ5˜ygæ�™w 9'9'9f½˜õbÖ ¸Xt±èbDXEXEXÁ¼àyÁó‚áõW¯¿zýì´ÐþAðí o};bVŬŠY?õø©ÇO=à¤æ¤æ¤¢ì£ì£ìaòˆÉ#&�€˜±1ccÆBô„è Ñ`Ò¯“~�ô+¼>ðúÀëÖ3¬gXOHè™Ð3¡'äÌÌ™™3`kí ·6„ˆyó"æÁ�²7ÊÞ( ÚëÚëÚëúž]A„OϧÓÀì$;Éœg:Ïtž º]Œ.l�l�l�ÀÜÊÜÊÜ *_®|¹òeðôöôöô†Âv…í ÛA\µ¸jqÕ ü¤ò“ÊO‚²ÃÊ+; zvíÙµgWhy·åÝ–wáHБ #APþ|ùóåσòŠòŠò HI#iÀ¹–s-çZ ´SÚ)íÀú¾õ}ëûP>±|bùD¨Ý¾vûÚíÁ¥¹Ks—æðøèã£��Bj�Ô©5 åg-?kùt½ÖõZ×k Ü­Ü­Ü­ïÙAøô|2 ìÿQ�A@A�´QÚ(mŒ1Æä9òyÿ\DP^"/‘—¼Ʋ–e-ËZ�=({Pö Ð¥éÒti 9IN’o¯�“‘‘ÿÍöŸñŒgÀXÆ2öíÓÃÎ ;7ìX*,– ˜8wâ܉saçð�ÃwÍ8Í8Í8}O¢ §çÓk`:tè@Ú-í–vóö$<ði�´@Zd“M6ÿ¼›-la  D‰¤ËÒeéòÛaÓv¥íJÛv ;…�”:¥N©ÝrÝrÝr�—ËËååü³‘Ic¥±ÒX +]é ò4yš< tñºx]üÛqÍüÌüÌü`íÒµK×.…/†1ü‹á°gÕžU{VAÚ—i_¦}©ïIAøô|2 LÓ@Ó@Ó^5}ÕôUSÈ,È,È,€�¹!sCæBÆ÷ßg|ñÓã§ÇO‡¸ï⾋û2ªeT˨‰þ‰þ‰þ ]©]©] ÑnÑnÑnptÌÑ1GÇ@X�°:au`Àƒ<ëÞÖ½­{ƒÃD‡‰áŒíÛ3¶p¿êýª÷«BÁ¸‚qã 55555*=®ô¸Òc¸Ux«ðV!Üv¼íxÛN];uíÔµ··¡yóå›/ß| Íž6{Úì)”Xj`)±H® ÂÍàý‡ø@þ±‡ÕjS«M­6Aíŵ×^ Ö®Ö®Ö®°ê—U¿¬úÊt+Ó­L70?e~Êü¬N\�¸:*ØW°¯`GYtd˜‡š‡š‡‚c3ÇfŽÍà‹å_,ÿb9TTuPÕA ŒRF)£àÛ£ßýö(¤,MYš²,Í-Í-Ía½ëz×õ®à´×i¯Ó^¨~»úíê·¡Åüó[̇2eË”-Sz{ööìí C†$ i¸4\^¼*xU€R—J]*uIß“+‚ðéyÿ¦E‹hLcI$‘TüA .0\. \¸,xç‰QŒbÔ;ÿËoTMhB€Ýìf7¨´*­J fãÍÆ›�‡Úwkß­}ŒF�2\âï4”JT¢Ò;ÿý�½ìeïÛ?›ÑŒfKXÂ;¿±9|çð�ÃwÅ?/‚ ÿ«Þÿâ?–GW—R—R—‚¢šE5‹j껬ßS-U-U-«t«t«tpYã²Æe $/L^˜¼PßéJ޶½¶½¶=ȇåÃòa}§A(>¾�%“Lòï—$2+mVÚ¬4ä�Ê•7 6glÎØœ±cÆ&3™Éú.Læ™Ì3™£ÊŒ*3ª Ìq�ã:Ç*~YñËŠ£“(òÉÿ%ÿ8ê|Ôù¨3\êw©ß¥~PeW•]Uv½}�Ô^j/µÊSžòúN-‚ðßûÓ‡¥,)KÊ‚üÐüÐüP(t/t/t»P»P»PX×g]Ÿu}`oøÞð½á07enÊÜè¶¶ÛÚnk¡{n÷Üî¹`Yʲ”e)}—ý÷¡UiUZ„ç…ç…ç�_ˆ_ˆ_¨Ö©Ö©ÖÁ$·In“Ü Y|³øfÑ&£MFPŸPŸPŸÐw‚ ÿ½ßï�ývúy[ÚÒöíÕ;TîP¹ì)ØS°–?[þlù3x9õåÔ—S¡‚cÇ Ž0uÖÔYSgÁ„fšMh·WÝ^u{Ìí2·ËÜ.pËî–Ý-;ÐÓÓÓwùŸ®øöñíãÛÃÚçkŸ¯}?øáÀ Ñ–F[m�Ö+¬WXCKç–Î-�!¿k~×ü®àwÌï˜ß18®>®>®†ºuê¼W:.—Žóöòƒ (Ðwµ‚ ¿÷»=0ù˜|L>ñã/Æ_„B‹B‹B ¨r¾Êù*ça•¼J^%CÐù óAçaqÅÅW„¶§Ûžn{<®y\ó¸îµÝk»×†šOk>­ùÎ^:{éì%øyøÏÃö_Øa? y>äù�çP¥z•êUªë{:>^9?åü”óœÉ<“y&N†œ 95kÖ„%C— ]2œp (šV4­h\kr­Éµ&°/s_æ¾L0ÝlºÙt3ÌX;c팵àVË­–[- ‹,² æaÌØ‡�7%oJÞ�¢¥h)q[A>:’ü¿=ð¼ÆóÏkÀÇ~8öÃ1(5¹ÔäR“Á÷’ï%ßKP§c�Žu:‚¤•´’žä=É{’{Nì9±ç¤nKÝ–º å Ê”­O´>Ñú_7¾n|%6Jlþ7ýoúß„{a÷Âî…A'ÛN¶�lßÞÇʪƒU«úžý)ºUt«èÜ5¾k|×ü~ôûÑïG�¶KÛ¥íàÝл¡wCpŸç>Ï}(2Š xÕùUçW�a�õë=Ö5:jtÔhðèëÑ×£/tvèìÐÙLZ™´2i©_¤~‘ú¼qðÆÁp©Ê¥*—ª@¯ç½ž÷z^›¼6ymÚÑŽvúžA„·~×À(¢ˆ"ÈZ“µ&k ùõȯG~…ó�Ïw>ß=mô´ÑSð<äyÈó”3+gVÎ ÔžjOµ'\¹~åú•ëèèèeUeUeUà#ùH>ÔUsTÍQ Û¢Û¢Û[>lù°%ìþv÷·»¿…¼‰yó&Âàƒ{ î­¼ZyµòeŽ2G™£ïé*yQQQQQQ°¯Û¾nûºÁÓõO×?]½æ÷šßk>tÖeX—aPêóRŸ—ú2eÊ<‡·Þzx+\Ì»˜w1š\kr­É5ÔjP«A­ ìå²—Ë^uCuCuC¸})úR4UªTìÏÙŸ³?>±>±>±Pc@�5€ôTz*=Õ÷¬‚ üÞïØ¿úŒÏø ^�}=öõXØÛxoã½�áµÙk³×fÐghŸ¡}†BGÏŽž=Á|”ù(óQ�ŸŸG~<òã‘áê�«®€æ¦ÍM››B¿Ký.õ»e­ËZ—µ†‚)S ¦ÀÅ¡‡^ ‡lٲǖŽ-[‚W¯&^M šO5Ÿj> õ•úJ}õ=}ï/û|öùìóp¼èxÑñ"8ÓüLó3ÍÁm“Û&·M0hè ¡ƒ†BÅ +T¬êöêöêöpm˵-×¶@à…À �Àº�uë>à�ä�ä�u²ëd×É$$$xÜïq¿ÇýÀÏÒÏÒÏòí %ƒ: ê4¨´ZÛjm«µ`kk«ïYAøäÿRQlQlQ¬,_K¼–x-Q–Çý8îÇq?Êòän“»Mî&Ë¡¡¡²\´±hcÑFY–5²FÖÈòs÷çîÏÝeù›Eß,úf‘,�²e3ÊF–Oxžð<á)˪ ª ª o·“<6ylòXYþÑøGã�eÙgžÏ<Ÿy²¼õþÖû[ïËrúÜô¹éseY~&?“Ÿý·Uè�f™f™f™,›››Ëò—ª/U_ªdyʦ)›¦l’å°úaõÃê˲N¡S責ë¢ë¢ë"ËO­žZ=µ’åyCæ ™7D–G¥�J•&˧ž:xê ,«²TYª¬·ÛIÚ˜´1i£,opÛà¶ÁM–}'úNô�(ËÛ_o½ýµ,gxgxgxë{6Aþºÿ¼öä¸å¸å¸Á ûö'ìáT×S]Ou…º&uMêšÀànƒ» î+W¬\±2¨?W®þnæÝÌ»™þWü¯ø_‹Ö­-Zƒ�›�›�Ôu¬ëX×ñío>Oz=éõ¤ì¹°çž �’’�Ûun×¹8=vzìô˜·Kfd�A†¾ÿy¬g=ë!ïQÞ£¼Gp¹Üår—ËAtXtXtôùºÏ×}¾†Nq�â:Å�Y³*fU ½Zzµôj´3hgÐNÞ¼)x´êÓªO«>Ðÿûþß÷ÿJß.}»ômPÝUÝUÝ…sÎ 87 =4ôÐPpŠpŠpŠŸÞ>½}zCÕŸ«þ\õg ˜`‚õ=9‚ Ý{7°mmmþ+ýWú¯„'Ûžl{² zØõ°ëaÝFvÙm$”\jp©Á�é�é�é G=xô \¹r!­n´ºÑjÔlP³AÍ Ü—å¾,÷%j µ…Z¸|þòùËçáøÍã7�ßùKùKùK� ¥B©È#�<}O/HÝ¥îRwP›«ÍÕæPçZ�ku®ÁÀï~?ð{°_b¿Ä~ úúúÃ%‡K—à`·ƒÝvû{ö÷ìï�÷Nï�Þ;¡ÆÀk ]]]x y y ¿»~wýî‚j´j´j4x¦{¦{¦C³kÍ®5»†m Û¶Ñ÷l‚ Ÿbo`¿ÑÙêlu¶p÷ÉÝ'wŸ€ß×~_û} :¥N©S‚ׯ^ ñîÆ»ïåååxù&òM$ø�ðá7^%¾J|•}¾ëó]Ÿï óäΓ;O³f/Ì^€®¿®¿®?èŒuÆ:cþù›Ï?ÿ«o*T¨€}ìc|eð•ÁW �–GË£áÉó'ÏŸ<‡Ý»=v{@º:]�®†Á#�<Z[¶¶lm †[ ·n…øïã¿�ÿü+ûWö¯ ÷î'ÜO€Îã;�ï<zô.è]–V–V–Vú.^¡ä”XûWyÊ6…R¥F©Q¾ý-Ê+Á+Á+ª�­6¶ÚXЕҕҕ‚Ð_C ýöÕØWc_ ÐuÖuÖu†!…C ‡‚»³»³»3l2Ød°IßÅ ‚ |x¾�ý ¹—ÜKîáQáQáQ°G³G³GùWò¯ä_�!†<òš}ÞìófŸƒáÆ óeæËÌ—�['·Nn�\$É0ÄC}Oë¿©ó+œüv(Ðn˜Ý0»a`PÛ ¶AmˆiÓ.¦ìMÞ›¼7ž|ÿäû'ßCÏ�=7öÜ=.õ¸Ôã˜å›å›åë»AýÓ{ûWªT?¨~€sºsºs:8TïP½CõÀiŽÓ§9àíãíã핃*UF2’‘¼ý­é¯R£FÍ?ï/&Í”fJ3Av—ÝewÞ® øW[3À #éymóÚæµ…a'ÂN„ÁiŸÓ>§} îgu?«û úö9H’ƒàõϯ~ý3$4Jh”Ф Òéo÷ þ"¥¯ÒWé ¡UC«†V…«G®¹z¾êûU߯ú‚aªaªa*ÿ¼®ë/×±GÞ#ïÓoL¿1ýj«æ.0³4³4³Ô÷, ‚ |:>™ö¡\9xåà•ƒpäË#_ùVÎ^9{ål0œl8Ùp²¾Ó ‚ ¿ùówdþ_ñ�“@dKÙR¶D¬X!‚ð‘ LAø$‰&‚ |’DA>I¢� ‚ Ÿ$ÑÀA„O’h`‚ Â'I40Aá“$˜ ‚ðI LAø$‰&‚ |’DA>I¢� ‚ Ÿ$ÑÀA„O’h`‚ Â'I40Aá“$˜ ‚ðI LAø$‰ö¯ddd µ¨˜c޹¾C ‚ ÿê¶�É;å�òNÐ\Ñ\Ñ\:Ò‘ŽPÔ¨¨QQ#ÐþªýUû+h 5†C(šT4©hh3µ™ÚLà9Ïy®ï*Aþwè;€¾$/N^œ¼6_Þ|yóeÈpÎpÎp†ØV±­b[Á«v¯Ú½j3¶ÍØ6cHW¥«ÒUèß³Ïþ=¡Ýµv×Ú]Ów‚ ÿ»þg˜q9ãrÆåàæÓ›Oo>…3ÛÎl;³í�ì`;àþŽû;îïÛ­¶[m·Bï¼Þy½óô�^AøŸ=„h}Ýúºõuèx¿ãýŽ÷Á`§ÁNƒ�üú:k묭³šÔnR»Im}§AþgØo:=èô Ó(ãPÆ¡ŒÃ¿yÁ ^ð:¯ê¼ªó*°ÚcµÇj�¾S ‚ ÿó ¬Úžj{ªí�‰-[$þþùÒ.¥]J»Àgc?ûÙX}§A~ó?ßÀÌesÙ\†Îë:¯ë¼”ç•ç•çß>ß$µIj“T¨iXÓ°¦¡¾Ó ‚ ¿ùŸo`¿iMkZ•ëU®W¹HÁR° ퟶÚþ)X½±zcõFß)A„ß||g!†FdwÌî˜Ý jÔ.¨ T§:Õ ©·÷�q-Y4²h5ZÔhQ£d¸d¸d¸@ýÐú¡õC!¥JJ•”* «£«£«S9^ò’— ¼­¼­¼ ¶:[�­*…J¡ú Ÿ€ Â'á£k`)ÇRŽ¥ƒÅ‰‹'Bæ¢ÌE™‹À¨ºQu£ê@8á„ãc‰%¤)AJ€Ì¯2¿Êü ÌGš�4 »æíš·kŽ4i8ØÃJâ$3Ì0ƒBÏBÏBO–5,kXt¢�>ÌÔ ‚ |R>žv�ƒ„®\¸‚ÅY‹³gaÆôÓgLÅNÅNÅNÀ;ìŠó¿í龎}ûRT)ªÔ¯^¿zýê ß”oÊ7KpûñŠxE<„¾ }ú–,X F7Ý`4”ÞZzké­%ý!‚ |:>šö¼Âó Ï+ÀÍ/n~qó ˜½iö¦Ù›ÀÑÊÑÊÑ ˜ÈD&–|Žr.å\ʹ€|T>*E”"Jõ&`s˜]Ët-Óµ Ü.u»ÔíRpÄùˆógÅ(F}€‚ Ÿ ½ŸÄQXXþ³ýgûφ¦Õ›VoZ\»6vmüáóH/¤Ò‹ظþ…aŠaŠa ©6¤Ú�jpuðÕÁWÃëÏ^öú³ŸGác¥÷Ò9¤sHgxsøÍá7‡¡ÿ•þWú_ 0øxö?¼ÚšÚšÚhhÖЬ¡4 hдaÚ0m˜¾Ó ‚ èŸÞX�s�s�3¦¦¦AzаO´O´O|ßÑÿ\pÁ´Ðv@[x¶üÙògË!l^ؼ°yú'‚ zk`çÊ�+w®h›h›h›@Wî†]Ņ¿SáE…^@×Q]GuûÚïk¿¯=XXXë;� ‚þ|ð–:$uHê8w4îh Ø?`ÿ€ýPÊ´”i)S}OÇÇ«{N÷œî9�?8pþ`¸<÷òÜËsõ�JA>x;ÔàPƒC À¡¬CY‡²Ð|uóÕÍWë{>~–‡,Y‚�ãŽ8=<ôðPH™þ2ý¥¾Ó ‚ |x¬�½*ûªì«²\)¸Rp%¼rðÊÁ+Áð”á)ÃSúž†OGëá­‡·v‡íÛ†£ë�®?º^ß©A>¼o`ò7ò7ò7Ð: u@kp¿â~Åý Ô´®i]ÓZßåz ûö5ì ƒ/¾8ø"\ºuéÖ¥[åååðþã ‚ |*J¼�…Œ 2^®y¹æå0`À€@r—Ü%w}—ÿéªkQ×¢®¸Ýu»ëvúô è º}º}º}úN'‚PòJ¬�¬+XW°üíýíýí¡kó®Í»6‡Ï>sä¾7i«´UÚ Ï <7ð<^ðxÁã>9|rød}§A(y%ÖÀ.V»Xíb5P=T=T=„.»lì²Qßåþý8vpìàØ:õéÔ§SðÿÖÿ[ÿoA½@½@½@ßéAJN±7°Ôë©×S¯Ãá7‡ß~Ï <3ð Xõ³êgÕOßåþ}õüµç¯=…ìjÙÕ²«Áåê—«_®®ïT‚ %§ØØÑ”£)GS ¬AYƒ²ÐrRËI-'é»Ì¿?kWkWkWè7°ßÀ~á@…T€ÌÙ‡3ë;� Bñ+¶éééWw_Ý}u7 Y>dù�å`dndnd®ï2‹OL@L@L\²¾d}É4¶[�­¾S½ÕÚ·µok_°*´*´*„㳎Ï:>Kß©AŠß{70mž6O›þÇý�û‡úŠúŠú ¨X'°N ¾Ë+~ q q qp3ífÚÍ4P¿V¿V¿Öwª·L¾3ùÎä;òtÈÓ!Oá¼ò¼ò¼¢/G_޾¬ït‚ Åç½×{¿?øþàûƒáé�§7žÞ€¥qKã–Æ&˜`RrÁå>r¹dæfæfæBQÅ¢ŠEAº"]‘®@Q¿¢~EýÀÔÂÔÂÔÔ½Õ½Õ½Aw@w@wì:Øu°ë :t„½…{ ÷B†}†}†=È5är °*²*²*³Rf¥ÌJ�k×®  RL¥˜J1`ð•ÁW_Aª2U™ªÉH2’Œ@;K;K; OOOÀîšÝ5»k m‘¶H[JþƒuËsËs˃Z7kݬu‚ S6LÙ0ep€(ù‚ %å/ï�©*…JþøãtnÙ¹eç–PѤ¢IÅl\¿Ñ�Ð�Ð�€ÍêÍêÍj˜7#nF\>sùÌå30£âŒŠ3*Â÷?}ÿÓ÷?Á•AW]s¯Î½:÷*/s¼Ìñ2oÇ nÜ*¸lOÞž¼=¶µÚÖj[+Xýfõ›Õo wTî¨ÜQpoý½õ÷ÖÃØScO�=OW<]ñtÌ˘—1/Ö_{|íq8»ïì¾³û`jé §6„û ÷î'|€Oôsss`ÐóAÏ=‡É’$ßüôà§—C¡¤üåvÅéŠÓ'Èm–Û,·ôxÔãQ�G.¸²HY¤,›4›4›40ñ1ñ1ñ�5ÔP6 liÏÒž¥=ƒ¯¼ð ê™×3¯gK],u±ÔÛñ\ʹ”s)_¨¿P¡Ÿi>Ó|¦Áµñׯ_IÛ’¶%mƒN5œj8AnRnRn˜[›[›[ƒi¨i¨i(ØEØEØE€ÏŸ5>kÀ,Å,Å,nD߈¾ýáæç7ÎîÎîÎîоlû²í˾¡û†î j'µ“ÚéÃçA(.ÿuËØ’±%c <|ððÁÃ0à쀳΂Õk«×Vúø-È#Œ€ît§ûÛ‡�ó�ó�óA÷T÷T÷ô�—ÇÅÅ‚&C“¡É]]]]]]Hž�<;y6thСAp(òPä¡HÈ}‘û"÷è u†:C :Õ©Œb£@j#µ‘Ú¥)Mi •¨ôv{†³ gÎõBõBõB=ÌÏ?ôJé•Ò+Ò<Ò<Ò< xNðœà9úË#‚ð¾þëvÌÿ˜ÿ1°a;Âv´yÐæA›z¬ÀSLAZ)­”V¾ó¸9昃$IAï�‡¶mÚƒË.?¸üágÔͨ›QÂV„­[áuÂë„×�ûµï×¾_R?Oý<õsx²õÉÖ'[á•î•î•ÔŸ©?S�Ò¥=JƒW^]xuáí¸ªªªð¸Æã�kÀ½Ú÷jß« iõÓê§Õ‡‚«W ®Â}é¾t_‚„Í ›6CÞ‘¼#yG lSئ°M�P7¡nBÝ·ãf÷Ìî™ÝîܸámÂÛ„·�Üé¹Ós§øùS�V�V�†}Áû‚÷Cç©�§vž*®ÿáÓó§Oâ¨V)¬R|¶ú³ÕŸ­ÿ:þuüë€ÆFc£±)ù ©©©°ªþªú«êíò·Êß*1‹bÅ,‚YÊYÊYJéÒ?¤?ÚÚÚÃ~ôà �MeSÙöåïËß—?¬úaÕ« (¹(¹(vßÝ}w÷]84ïмCó Ä7Ä7ÄV?^ýxõcHÙž²=e;¬>²úÈê#äää ºµºµºµ°ªÒªJ«*Á�èÑ¢AU]U]UÖ­_·~Ýzö ö ö„ÓŸŸþüôç°¹psáæBÐ|£ùFó͇ûÀ/ ½4ôÒPȘ70o tÖ}X÷anû‚ Åå¿> ±×à^ƒ{ †ô_ÓMÿ®Ö»Zïj½’z½ãõŽ×;BÔ’¨%QK`¸ûp÷áîÐåE—]^€‰‡‰‡‰�1c<*XW°®` E›Š6mããÆÇ��ƒc/Ç^޽@÷B÷B÷2¾Ïø>ã{8ºþèú£ë¡“¦“¦“ú§õOëŸ÷OÞ?yÿ$¤jSµ©Z°c?Æ~ µ*jUÔ ,.[\¶¸ e~,óc™Aö•}e_x1åÅ”SàÖ²[Ën-ƒ�³Î8 :¹wrïägœpv¤·Lo™Þ²äç/½azÃô†pèÉ¡'‡žÀ€“N8 VQVQVQ%¿}A„âö_70›16clÆ@?�~ý< ¨sPç Î�U%«JV•’ št*éTÒ)°ìeÙ˲˜29dr8ÍiNÿÛÊ(@ª%Õ’jý›ç{Ñ‹^ >©>©> ‰Q‰Q‰QpvýÙõg×CA•´•´•´`^ϼžy=�»ÉÝän Õ�jH5~?¬ôBz!½€\ó\ó\sˆ�Ž�Ž�†ýÛ÷oß¿®¬º²êÊ*¨®®®®®Ã†3 g”ܼýæX™ceŽ•»Ãv‡íCëå­—·^^òÛA()ùŽÌm£ÚFµ�‚ó·Îß: NÔ9QçDð ¯jó­Í·6ßBΚœ59k@3R3R3¤¾R_©ï;/, €�&J¥‰ í£í£íóÎóÿX½žÎt¦3v7ìnØì÷Úïµß �,;Yv²„f«›­n¶ä$9IN©«ÔUê Ú¯´_i¿­‡ÖCëñθ•©Le` [Øæ™æ™æ™àð™ÃgŸAßúþÐ÷¨¸§âžŠ{€>ô¡p—»Ü-±Ï—ÈÐÈÐÈP¸”|)ùR2L93åÌ”3`TÖ¨¬QÙ’Û® BIûË2›èLt&:Ì`g¯Ÿ½~ö:ĪbU±ªâÚ¢v‹Ú-jƒuMëšÖ5a냭¶>€+W®@îóÜç¹ÏA¶—íe{¨ZXµ°j!¤¤¤À…o/|{á[ˆ7p½àzÁõȈΈΈ†”ý)ûSöƒc®c®c.¸'»'»'ÃÞW{_í}§¥ÓÒi žô}Ò÷I_Ðyêr¹¼Ð¼Ð¼Ð@Ñ¡¢CE‡ÀÚÝÚÝÚ;6vl Í š4‡í_´ÑÌvší4Û ê®ê®ê®`œaœaœÕæV›[m.äúäúäúÀ롯‡¾ ŠúŠúŠúPºZéj¥«�ÃQ‡£GA —Â¥ðâ›§°uaëÂÖÁº_Öý²îXüãâÿ•ÚUjW©]ñmGA_Þ»�ý&Ò1Ò1Ò6YØda˜2-dZÔ‰®]'ºä È�Ì�Ì�„�‘#FÂXÝXÝXôíзCßn"?ªiªiªi0¿ÓüNó;A½Iõ&Õ›>O}žú<}ÿñA>Ŷ¢sŒsŒs ´ñmãÛÆöÍÙ7gßPç©óÔy%�<žxâ!~hüÐø¡ÐxYãe�—�é5Ók¦×@— KÐ%|À™üHïÞ¼²Œ³Œ³Œ¡çŠž+z®Ðw*A„âWl{`¿I½žz=õ:Ì›6; ¼²½²½²¡ýœösÚÏÑw¹_™O3Ÿf>…Ùɳ“g'Cߘ¾1}c ³wgïÎÞúN'‚PüŠ}5úÒ-K·,Ý<*{Tö¨ û»ìﲿ dÌ:˜uPßåþ}q|Äñ`ùÒò¥åKh÷¼ÝóvÏõ�J¡ä”ØíT:¼ìð²ÃK0©kRפ.œfü™ñú.÷ï'æbÌŘ‹pîȹ#çŽÀàÙƒgž F‹Œ-Òw:A„’Sb Ìt’é$ÓI08ipÒà$8}óôÍÓ7!þBü…ø ï?þÿ:y´Á;‚wï€4�4�4è=±÷ÄÞõ�JáÃû` ì7}Ãú†õ ƒøäøäød¸9ýæô›z¸/Ö§&»ovßì¾°ÿÇý?îÿ^'-NZœ´333h·¬Ý²vËô�JA>xûM§ÄN‰�AyGyGyNkNkNkô=Ÿ8—8—88½íô¶ÓÛ`È¥!—†\ÓLÓLÓL}§Aн50ÓHÓHÓHd7Èn�œà'€¤rIå’Êé{Z>/xÁ ºt%è Ô˜ScN�9Ð`iƒ¥ –ê;œ ‚þé­�ý¦ñÙÆgŸ…Ê•=*{À�¶Úh QD‘¾ÓéÏcãÇÆ��á^ö½ì{ÙàyÏóžç=P6P6P6Ðw:AýÓ{3d0È` þv𷃿…ÛÏo?¿ýž†< y¢ïtž:^¯Ž‡}åö•ÛWÚ¶1lcU.T¹PE\.‚ðOùŽÌÅ­z\õ¸êqÐ|vóÙÍgîô]é»Òáˬ/³¾ÌÅnÅnÅn� ¥B©ØÌf6ƒÜ_î/÷,±ÄRßUüuŠ[Š[Š[pçì�³wÎÂõ×;\ï¾G}�úÕw:A„�O±¯Fÿ¾R§,NY ‹g/ž½x6d.È\�¹Œ–-5Z QFQFQF ,¥,¥,Žsç8Î9]N—Ó >Å“A,°À m m m  uAë‚ÖÐ5¸kp×`3i̤1“ôRáãñÑì�ý¦L¯2½Êô‚eå–•[V Ú´)hšíšíší°ø³ÅŸ-þ :†w ï¢:Duˆm‘¶H[èСÓwAa„�ÁTƒ©S!Ù0Ù0ÙV­ZM7Üd0¸Ù»Ù»Ùë;¬ ‚þ}t{`ä列#^Ž€9+rVäÀ·Ï¾}öí3(ó°ÌÃ2õ�®äøûûCèÞн¡{ai»¥í–¶sOsOsO}§AнŸÄñg…L ™2*zVô¬è ¥¿+ý]éïô�ªäõŽïß;tttàXà±Àc�úN%‚ }+¼^x½ð:Ü�wþÝùмróÊÍ+ƒÔEê"uÑwº’gáiáiá î»:ì*œÌ:™u2 ^¶}Ùöe[}§AП�¾�Å+âñ HÛ’¶%m Ô™Zgj�©úNõá5Hn�Ü šÕjV«Y-ØiºÓt§)hkkë;� ‡÷Ñ�Äñ¯îô»ÓïN?plãØÆ± T®\!Xß©><©�ÔFjž•<+yV‚9�æ<šóÎYŸ³>g ÝéNw}‡Aø€>Ú=°¢íEÛ‹¶Ch@h@h4 hÐ$€O÷,Ãbbçlçlç Þ‡½{†ý�÷?Þÿâ7ÆoŒß¨ït‚ ÎGÛÀ¢\¢\¢\ U‘ªHU@£-�¶4Ú¢ïT�–g[žmyj쩱§ÆØÝqwÇÝAû�öí7úN'‚Pò>Úö ñƒÆƒƒµƒµƒ5”�QvFÙúNõñPF+£•Ñà;Ôw¨ïPˆð‹ð‹ðƒÃn »1LßéAJÞG×ÀdgÙYv†{-×74nh Ê e†2Cßé>>ÆTSa PPPÃÞž{{îí æææúN'‚Pr>º–² eAʈ¿)þÔÏ­Ÿ[?Wß©>~�gvžÙy&ØÙÛÙÛÙC@¹€rå@N’“ä$}§A(~]{4æÑ˜GcÀÂÜÂÜÂ*•«T®’¸?Øddkdkd ò‡eˆë6×m®ÛÀCÕCÕC•¾Ó ‚ ¿�®�Ýë{¯ï½¾PϤžI=0,oXÞ°¼¾S}:\Â\Â\ S¥N•:U‚]a»Âv…Aþ²üeùËô�N¡ø|4 ,»Uv«ìVðbË‹-/¶@ƒ² Ê6(«ïTŸ®¾UûVí[ œ œ œáôîÓ»OïÖw*A„âóÑ4°Ø³±gcÏ‚®HW¤+§N;œvè;Õ§ËbµÅj‹ÕàææGƒŽ ‚Ø1±cbÇè;� Âûûhؽ {A÷‚Àék§¯�¾Ûζ�m;ë;Õ§¯é‘¦Gš�:SêL©3öœÙsfÏÐ×××wºð†7¼�x£x£x#x´ðÑÂG AóLóLóLßáA(Nzo`²•l%[ÁãW�_=~õÜê¹ÕsÓwª¿é°tX: ^?zýèõ#<ûtìÓ±p³ÉÍ&7›è;ÝÓ&k“µÉ°?dÈþ¸þàúƒëþóû"7DnˆÜ[[[p®è\ѹ"xáýÂû…7lqÛâ¶Å RÜRÜRÜàIÖ“¬'Y°|ÓòMË7A„y„y„¸ü@> zo` .$\€ä_’Iþê}]ïëz_ë;Õß�ƒ‹ƒ‹ƒ ô‹êÕ/ üø5ðkðöŽ×ÉAr�@a¬0Vƒâ”â”âÔ~ß­a·†Ýéiéiéi0²ËÈ.#»€U€U€UH›¤MÒ&P( P±cÅŽ;ÂõÀë�×!2/2/2 ›6+lO?=üô0È­äVr+}ÏŠ ïÒ{‹TGª#Õ`îeîeîe–]Xv¡¾Sý}užÜyrçÉ`9Ør°å`8´êЪC«Šoü¤WI¯’^Á�¤;Iw’à�æ�æ�îMº7éÞ$H�H�H�Õ8Õ8Õ8?~>ü<¼6mþÚžÞ}z÷é]ÈË˃ÚÍk7¯ÝÊm)·¥Üà'8ñû톆†Á³ègÑÏ¢!Þ4Þ4ÞR¦.L]ÆÞÆÞÆÞànånån±±±`öÊì•Ù+0\`¸ÀpÈõäzr=8’{$÷H.¬K[—¶. ^õyÕçUÐíÕíÕí…äìäìäl¸w7în<~þøùãç ž¢ž¢ž‰{÷$î�ð±ácÃÇÂã7ÆoŒáµëk××®�—�—�—ý#úGô‡¼©ySóþï² ïCï«Ñ?hò Éƒ&àèèfKÌ–˜-Ñwª¿/“Ú&µMjðýÃöÛ+~XñÊ yQó¢æEàjàjàúߊè‡Ñ£„ .L¸ãÚŽk;®-¤Y§Y§YÃ�Ï|~àsßl|³ñÍ`õ¼ÕóVÏ«ÙV³­fC�Úujש �g4žÑx+}Àë¯o¼¾�RF¥ŒJ�{s÷æîÍauÁê‚Õ0íõ´×Ó^ƒnˆ#è‚ðçèmL;M;M; ^Ž}9öåXpmâÚÄõ#þMæï¦V“ZMj5�Ö­-Z[À®Ò»Jï* êºêºêº}Üò¥Ê—*_ JÝ+u¯Ô=hÚ<´y(øøøÀý÷gÜŸ)]Sº¦t…2FeŒÊ�Sm§ÚNµaTæ¨ÌQ™Ð°~Ãú ëCùíå·—ßZ�V§Õ4h~¿]K+K+K+¨6¢Úˆj#Ày¹órçåÐäç&?7ùœª;UwªæVæVæV {¢{¢{Xa…°…-l³ñfãÍÆƒ£»£»£;T¾Wù^å{àÞÕ½«{W¸í}Ûû¶7$š%š%š�÷(ïQÞ£ þòúËë/‡£§Žž:z Êî-»·ì^0јhL4Ð~jû©í§‚×~¯ý^û¡F�=jô€UVTYQjF׌®­ïo… |Zô¶–¼4yiòRÈÈÊÈÊÈ×××}OÇÿžþÕúWë_ f_™}eö8çvÎíœô =þÊ€†br€ Ž8âÆÆÆ µ—ÚKí!¯z^õ¼ê yJž’'M4šh4ŒbŒbŒb€‘Œd$PŸúÔºÒ•®bû9ä�rc¹±Üøíßÿµ<òȼñÆÈ$“LHš>4}(DíŽÚµv”ßQ~GyH M M —Þ.½]zƒ4T* ÅÏŠŸ?ƒ±™±™±˜šš¾ÝL*Páƒ~â‚ð÷¡·=°§·žÞzz ,“,“,“ ü‹ò/Ê¿Ð÷tüï±�n;Ýv:x·ðnáÝ‚²‚²‚² !%!%!å/ ¨B… ¤åÒri9à�?þPàZàZà òxy¼<¬v[í¶Ú ru¹º\˜Ï|æÿ›ñÌ1ǤƒÒAéàÛ¿ÿP)JQ ¤KÒ%éÒÛ¿ÿ¹çÖ�~ôi�´@ZÀÛ×›Þôf3›ÙÀcó´—µ—µ—ßo}Íúšõ5pŠpŠpŠŸ5>k|ÖÀ<£yFóŒ`¡z¡z¡”½”½”½@-�–FíhG»·ãh5‰šDˆ ˆ ˆ µ³ÚYí¬ïoƒ |ZôÖÀžÕyVçY¨’_%¿J>|mðµ�8ûPoZµjUGVYuäÛÅ€¹Ë]îþùq¤5Òi äææÂÕ «AWƒ`oÀÞ€½ТN‹:-ê@éñ¥Ç—I]’º$u�››(XW°®`äÌ;˜w¢F7ŒnI–I–I–�ä“ä“äóûíª®©®©®AÔ¦¨MQ› ! ! !¢²¢²¢²à�î�î�2r2r2ràå×_>„gžxv2keÖʬo6¾Ùøf#ص´ki×¢.F]Œº'{�ìu²¸çþ�ûw`»Ûv·ínØ5w×Ü]sá|ãó�Ï7†(¯(¯(/ˆ­[)¶d5ÎjœÕÞL|3ñÍÄ·y£ý¢ý¢ý`FíµgÔ†'Wž\yrEßßAø´|ðCˆêêêêêêðòØËc/�A�°a=€f4£™¾§ã—A7ƒnÝÀ÷˜ï1ßc° ý‚ö ÚChdhdh$¸7roäÞèO B!`ÐÒ ¥AK(Ó¼Ló2Í¡Éá&‡›ç Μ7€¡‹¡‹¡ Lo1½Åô l¡l¡lŠE„"¸ÈE.Â�µCÖYûöì>Óf¦ÍLÿÍ÷D:!��N€—“—“—¨¶¨¶¨¶@©�R!¥B@g¡³ÐYÀjõjõj5X&X&X&€Õ6«mVÛ`µÕj«ÕV`Ýʺ•u+°ß`¿Á~8Y9Y9Y�qsãæÆÍÁ©©SS§¦0û‹Ù_ÌþbbbÀ8Ü8Ü8̶šm5Û ÎÎΰ1scæÆLpØá°ÃaÇÛ¼R*¤TH�¹Ïç>Ÿûœ~púÁéà*W¹ªïoƒ |$ù>ÔS’S’S’aÎ…9æ\€™»fîš¹ ª�ªvªÚŸ¸ÎGø0ÍÍÍáúºë뮯ƒå7–ßX~Ì·›o7ßþÇï{1àÅ€`Dþˆüù°ñÕÆW_AýgõŸÕ+a‚PŒ>ø!ĸ~qýâú�AUƒªU¡ÜþrûËí×÷4ÿª»Awƒî ûÈ>²œX{b퉵ÿù}­3Zg´†Vþ­ü[ùCºoºoº/p’“œÔwU‚ ü�|ð=0¿8¿8¿8ˆêÕ'ªÌ �:'TßÓ ü‘�=!{BöÀÆol¼‹k/®½¸68�sç4NßéAø_öÁ÷À^õÕÿU¨6­Ú´jÓô]¾ðŸ4²idÓÈê-¨· ÞØë·×o¯è¶é¶é¶é;� ÿË>XË}œû8÷1$''ƒki×Ò®¥õ]¾ðŸ(z(z(zÀ�óCÎ9Ï×>_û|-ÜÚ}k÷-q1Aôèƒ5°ä²Ée“Ë‚v¹v¹v9”[~lù±ú._ø³¼¼¼Áã…Ç �°gÏž={ö@ÖÙ¬³Ygõ�N„ÿE¬�%=OzžôÌîšÝ5» ¥:”êPªƒ¾Ëþ[�7uÞÔy˜w2ïdÞ ŽL;2íÈ<üúî뻯ïB¨*…Jï?ž Ÿ®vØ«:¯ê¼ª���`jbjbj¢ïò…ÿ–é Ó¦7Àׯׯ×V�X=bõh‘Ü"¹E2T+[­lµ²Å¿Ýì¸ì¸ì8Xï²Þe½ h¶h¶h¶€l*›Ê¦¿)~Sü&°ûÖî[»oAí«öUû‚ò„ò„ò¤5Kk–Ö :„wïñ1ñ1ñ1‘‘‘Ou<ÕñX6·lnÙB#B#B# ¶clÇØŽ`·Ën—Ý.h>¢ùˆæ#Àð©áSçúþ4á[‰ï�ÉOå§òSˆìÙ-²T ­ZEœuøÉ«{³îͺ7¡Y“fMš5�=Wö\ÙsŠF�.]üÛ3o<Þx<¤OHŸ�>̾1ûÆì(]6ºl4\rpÉÁ%°oʾ)û¦¼½mK‹„ /`�Ç:�u�´;iwÒn(ZT´¨hüÐç‡>?ô�äËÉ—“/CðÐà¡ÁCagÁ΂�Pz}éõ¥×CÐë ×A¯áäÖ“[OnÕ÷ì ‚ �--ZZ´’'$OHžŽ®Ž®Ž®ú.[x_’«ä*¹Â vƒÚ j±Ýc»Çv‡«/¯¾¼ú²ø·g|Èø�ñ!°¶¶¶¶¶† ³+Ì®0œÊ8•q*VùVùVùPí«j_Uû ì°wÀ^h~¤ù‘æGÀ ·AoƒÞ Ø¡Ø¡ØeÒˤ—IÃ9†s ç€âÅ7Šoà|öùìóÙPʱ”c)G¨7±ÞÄzÁ2Ð2Ð2®ýtí§k?é{öA€ÐÀ2¿Ïü>ó{È¿“'ÿTÈ©�Sᯬ.|”Ê”+S®L9�3 g@ø›û›û›Cú±ôcéÇJ`ƒ¹ä’ Üã÷Þy¼ h¨Q£~û°²PY¨,*S™Êï¼N‹í;ïoMkZCΜœ99s Ê)Ê)Ê Ž-9¶äذq³q³qƒ–u[Ömù·›¡ø”øo`qÚ8mœŒ®]5º eüÊø•ñ’I&Yßå Å¥ýÕöWÛ_…àÍÁ›ƒ7CÐà ÁAƒalÒØ¤±IÀhFS ‡åqò8y¨=Ôj�wžˆ$’Hà2—¹ t¤#Ar“Ü$7Ð%ë’uÉ õÖzk½y»æàu®sdoÙ[ö†Jo*½©ôLMMÁ«®W]¯º ¬¬¬ïYá]%¾–°'aO°j;Ôv(ö4ìiØSße ÅÍx�ñ ãAàkékék ÁñÁñÁñð$íIÚ“´âÛNà o4¼w÷ßÝw?ì[¾où¾å�¹4siæRˆ_¿ ~äZåZåZ�Ía›Ã6‡¡ÁÄL„ƒùóæÃuƒë× Àè+£¯Œ¾‚¤ä¤ä¤dèëÒ×¥¯ p‹[Ü‚ ÷6ÜÛp®<¸òàJˆù%æ—˜_ô=Û‚ —°m³¶ÍÚ6K–ØùÃÎv–ôÖ½{"?‘ŸÈòV«­V[­dyÖ¡Y‡f’å … 7¼ÿð… +V”åøÎñ�ã;ËrÒÓ¤§IOe9©]R»¤v²œ|>ù|òyY.r/r/rû¾œ£9GsŽÊrBï„Þ ½e9->->-^–ãããd9o]Þº¼u²,‡È!rˆ,g'e'e'Érü¸øqñãd9Å0Å0ÅP–U›T›T›ô=É‚ Ȳ,—ØZˆòLy¦<Y|dñ¨?¡þ„ú Ï¸>ãúˆ5ôþö2m3m3maö¸Ùãf�ƒ^1½bzÅ@÷Ýwtß¡ït‚ ü”Ø!Ä‚¯ ¾.øÒg§ÏNŸ åÃˇ—×w¹Â‡b�n�n�ž¾ž¾ž¾dddɮɮÉâ,TAŠA‰50•©ÊTeúö––6–6–6ú.WøÐZ¶4liNkœÖ8­ÿÒþ¥ýKƒ|V>+‹%¨Ax%×Àf¨f¨f€¦HS¤)Ëo-¿µüVßå šaeÃʆ•Á÷¹ïsßç:!tBè¸_é~¥û•ô�N„OY‰5°´riåÒÊ�áqÃã†ÇÁj¦ÕL«™ú.WЗ*5ªÔ¨RºœîrºËiسpÏÂ= ¡à—‚_ ÄY}‚ ü%ÖÀâÚÆµ�k V:+�•ÌW›¯6_­ïr}ë=µ÷ÔÞSA�­ÎVgÃ)×S®§Äob‚ ü%ÖÀR"R"R"Àv¡íBÛ…ú.SøXXÔ±¨cQ¼5Þo ½tôÒÑK›››«ït‚ |JJ¬�e}›õmÖ·`ígígí§ï2…�Mã=�÷4Þ5[×l]³5ì¼wðÞÁ k¤k¤kôöuš¯5_k¾ÍaÍaÍa}§ácRb ,;/;/;,{[ö¶ì­ï2…��Ò^i¯´ï Þ¼/@D§ˆN� äiÈÓ�§ð¼ÓóNÏ;Á7+¿YùÍJ8wçÜ�swô�Z„�IÉ50ŸlŸl°îcÝǺ�¾Ë>V—U\Vq4íÝ´wÓÞ0Cž!Ï�¡oï¾½ûö†ÕmV·YÝnþxóÇ›?�xÄ#}§ácPì‹ùÎ,œY8òjåÕÊ«v¦v¦v¦ú.SøØdÖϬŸYúô9è;3wfîÌ„;[îl¹³t>:�ÏÛ×Gl�رtýuýuýAñLñLñLßU‚ OÅÞÀòMóMóM¡ µ µ lÛ.¶]¬ï2…�ÍÝcw�Ý= k,¬±°ÄÄÄüñëc²b²b² 73737,±ÄRßE‚ WÅ~QuYuYuä±òXy,˜ššê»LácÓz}ëõ­×ÃÒuK×-]N³œf9Íúã×gdd@ìúØõ±ëõ�^„�A±70õ<õ<õuFêŒÔííí ïô‚ | Šý¢¦›¦›¦HÁR° J­R«Ô¾ÿ¸Âß“tGº#Ý�nt£`9×r®å\ø:öëØ¯c!¤yHó�æ�1 c@ƈ¹s%抾S ‚ð1(þ=° u�:”fJ3¥43hfÐLße ŸŠ–ËZ.k¹ ¶­Ù¶fÛèÚ·kß®}ß>ÿ¦Ö›Zoj�.]—®K×wZAô©ø÷À5‰šDP^T^T^¥¤””’¾Ë>5u¿¯û}Ýïa홵gÖžîp‡;pS}S}S Ûù€9æg[ÈBBöôìéÙÓÁ°·aoÃÞ`zÁô‚é…?~[QÓ¢¦EMá¢ýEû‹öÓ&¦MLè¿¶ÿÚþk�#áX|cñ�Å7Pا°OaÈÍÉÍÉÍ«V¬€qeãÊÆ•‹}ö>¯xÅ+(°/°/°‡WC^ y5n*o*o*á‘î‘î‘ ó ó ó œU9«rVP«\­rµÊAWË®–]-Á9Ô9Ô9,]-]-]AyRyRyø‚/ø¨Nuªÿ›í§’Jê¨Ó +¬@yHyHy,°À°pµpµxwý[ÜâÖ;§“N:ȵåÚrmP�T�T�„8ÿ8ÿ8x}âõ‰×'à‰Ç�'°sÇÎ;w@á¾Â}…ûÀÙÅÙÅÙšîiº§ép«íVÛ­6Ø^²½d{ ¤õÒzI\N ü�+þ&!!ñÏFVRŠŒ‹Œ‹ŒacÔÆ¨�QPý^õ{ÕïÁ0àÿñ¾;ë﬿³Î.:»èì"貸Ëâ.‹!²Vd­ÈZ°}áö…ÛÂ4Ãi†Ó !G‘£ÈQÀ¼»óîλ “÷NÞ;y/´ kÖ6 äŸåŸåŸAò�<$À{ìK®n}K9�r:å4\�~uúÕépmÁµ×@ÞÕ¼«yWÁuŽë×90Èu�ë WpµvµvµëëëP~¡üBù…¾«øl±Å¤)AJSL1ªQ�j@µ•ÕVV[ �¢:EuŠ‚üÑù£óGCìîØÝ±»áΚ;kî¬�ã뎯;¾îíbÇnQnQnQðY�Ïj|VjŒ¯1¾ÆxPNPNPNÐwÑ‚ðaû@”]”]”]À{„÷ï`6ÇlŽÙœÿü¾§ÇŸz Û¶)lv8Øá ¨}Õ¾j_¿cüŽñ;À>Õ>Õ>Ê+¬ü1�ãåx9T«U«U«!ö§ØŸb‚Û«n¯º½ úNï;½ïtPd+²Ùúž�â¿,~Yü28åuÊë”ÜpsÀÍP¦S™Ne:A÷öÝÛwo Ë5,×°ØÍ´›i÷ïn\Ú–¶´Õw5ÉIr’œÀüœù9ósPƒÔj¬ª±ªÆ*è:Ðu +¼|ø".Õ¿TÿR}øþî÷w¿¿ C*†T �Þô¦7à¶ßm¿Û~0h0Ð` ¾«„’Uü ì·C†¿ýW‰åÛ§ÃN„�;�[\#\#\#@Ú'í“öAÃ{ ï5¼Gr�äÉ…ÞF½�z�“‘“‘“QÉ}!~;{ïÄ�wNÜ�“—N^:y œK;—v. ㎌;2îÔ›_o~½ù ´SÚ)í€gþùx˜¿xþâù‹áZêµÔk©ðåø/Ç9æ˜{`îhðYƒÏ|ÊëÊëÊë%—GøÍhF3(ß |ƒò `؆a†m€å¶Ëm—ÛB©ª¥ª–ª ú,è³ +:Vt¬ŠÆ�)£ïð‚P¼Š}쟇.æ1�y ›®›®›´¤%-Á¤¬IY“²`ÔÞ¨½Q{°›l7Ùn2ØÏ·Ÿo?²7foÌÞ‰ªDU¢ Ì0ÿÁü¨TX©°R!´)Û¦l›²@QD½½G:%�’NñvÏï_�å,g¡”{)÷Rî`žažaž6Wl®Ø\�"Ÿ"Ÿ"0ô5ô5ôÉN²“ìx{²@$‘D‚ÒPi¨4SoSoSo0÷5÷5÷«WV¯¬^Á#ßG¾�|!{aöÂì… î î îŠÑŠÑŠÑðøÑãG��AˆAˆA˜+Ìæ p³p³p³€ê¹Õs«çòÏ“^fÏ�=wö\�NH'¤Åÿ¸juÕêªl¯¸½âöŠÐfi›¥m– äAɃ’¡Ô²RËJ-+þí ÅËÁÊÁÊÁ &™xdâ¸sûÎí;·aÛ©m§¶�‚7Ÿ¿ùüÍç0Êy”ó(g0�4�4�ÔwjAx?žf´Öh­ÑZЖ֖֖í1í1í±ÿßÿïäŽbˆ’I&˜À&8À�Óåt9�þú-?’Éÿî>Pyä‘÷_,¢ˆ"�oÊ7å›oÿþ¯bˆ!Ї>¼s¿³¢QE£ŠF�ÊWå«ò…˜Í1›c6ƒã:ÇuŽëàËA_úr¸¸¸±Ä r²œ,'¿3¾7ÞxƒôPz(=*Q‰JÅ÷9]ȸ�q!¶]ÚviÛ%¹o侑û`ä‚‘ F.€R«J­*µªø¶÷wWÔ»¨wQoHÉNÉNɆ‚°‚°‚°ŸCJ–’¥dhú éƒ¦`ñÄÅO„ËËKX?rýÈõ#!Xþ°üaúž5Ax?ÅÞÀ wî2ܺٺٺ٠Uj•Úw~ûmÏB¶—íe{дѴѴ�ÈÆ‘�#ƒI{“ö&í¡|\ù¸òqPô¦èMÑ(’Ф¢³¢‡¶�¶�¶ÁÛëtt¯u¯u¯ÿ8Ÿ¶ª¶ª¶*hëhëh뀮…®…®ÅÛqt¿è~ÑýEaEaEa =¡=¡=ºãºãºãP”\”\” ŠpE¸"²ëe×Ë®ªªªàlèlèl6Y6Y6YÐØ³±gcOð8èqÐã tPwPwPƒÜZn-·ÝçºÏuŸƒvšvšvÚÛœé“Ò'¥O‚€J•*ABvBvB1œÞ.¼]x;Ø×c_�}=`üÅñÇ_„6õÚÔkS�ÿøy¥¼R^ ©©©p ú@ô�hÈZ™µ2kåûç+T8¨p\èr¡Ë….�0>a|ÂxHNLNLN„Cç�;t-~´øÑâÿbœê Õªÿù–î¶î¶î6Ÿw|Þñy°ñÔÆSOÁÍy7çÝœ÷ö¬×g­žµzÖ r¦åLË™gÊž){¦,\[rmɵ%Àw|ÇwÅŸ¯Ü�rÊ€9š9š9È•9*søEøEøEkXÚâß® |ÅßÀ:v2ìºB]¡®´–ZKí;7n’¥@)r.å\ʹ‡S§N�SƧŒOÃØØ±±ccÁ,Ñ,Ñ,”·”·”· UþªüU�=5{jöTHž><}8díÊÚ•µ W®2\ÑÍ¢›Eÿ›µ³Ìþ1ûGÈ|™ù2ó%(Ö+Ö+ÖÃÓ«O¯>½ &&&`ÓÕ¦«MWˆ;6v,Ü«p¯Â½ `wßî¾Ý}ˆó‹ó‹óƒÚMj7©ÝL‡™3ûÆì³o ¸·roåÞ :ûuöëì[o}¼õ1켸óâ΋ðHóHóHÑý£ûG÷û#öGì�@dFdFdÆÛ¼yyypçü�ówÎCÖì¬ÙY³ÿúç’“œ“œ“ ûúíë·¯ôOíŸÚ?Ok<­ñ´??Ž4Sš)ÍõõõXWm]µuÕ Ñ!Ñ!±V‰/V8¬pÜycä�‘�|/ù^ò=(ÕªT«R­àpÙÃe—…sÎu8×áíû’'=Nz ÚmÚmÚmPøKá/…¿¼3N|r|rüûçûWã2ÆeŒƒ « « +èêØÕ±«#ÔM®›\7Bë‡Ö­¯¼Zðj˜ÅšÅšÅBh^h^hø-õ[ê·ävr;¹]ñçû�Í~›ý6ûák§¯�¾v‚' Ož$@èôÐé¡ÓKn»‚P¢äbÓ?¦LY0*`T€,'ÔI¨“Pç�ç¯Æ\�¹*Ëí/´¿Ðþ‚,?þåñ/�‘eíxíxíxY–—ÈKä%²¬» » » Ëšušušu²¬ùNó�æ;YÖit�F–u»u»u»ßy~ŒfŒfŒ,k³´YÚ¬ßçÒ%èt ²¬Y¢Y¢Y"Ëššš²¬í¥í¥í%ËZs­¹Ö\–5ã4ã4ãdYsZsZsZ–‹Ö­-Z+Ëšešeše²¬‘5²F–eÙ[ö–½eY³_³_³_–Õ�Õ�Õ�eYþUþUþU–u—u—u—e¹ðháÑ£²\˜P˜P˜ ËZW­«ÖU–µe´e´edY3J3J3J–‹–-+Z&Ëÿ·Ô’,Ëkä5òYÖ~©ýRû¥,˾²¯ìû×?—ã]�w=ÞU–çËóåù²,ª U…ª÷øœ#c"c"e¹íçm?oû¹,ßüîæw7¿“å$Ï$Ï$OYέ”[)·ÒÛÏ'énÒݤ»²œg�g�g Ëêîêîê´1icÒFYγȳȳ�euCuCuCYNP$(²œs!çBÎ…·Û�à1Ác‚‡,ÿP÷‡º?Ô•åˆÐˆÐˆPYž:yêä©“eùåæ—›_n–å‚9s æÈrBÇ„Ž e9gSΦœM²œ¥ËÒeéd9i[Ò¶¤m²œú:õuêkYNh—Ð.¡�,«f¨f¨fü‰ x#¿‘ßÈò“sOÎ=9'˭ǵ×zœ,ßPßPßPËr¡w¡w¡·,'ÝOºŸt_–3L2L2LÞ¾ý'·ŸÜ~r“å/’¾Hú"I–u:�N§“eí×Ú¯µ_Ërʃ”)d9aiÂÒ„¥²ü+›¼×ÿ4ÿNkOkOkeyŽjŽjŽJ–U¨PûÿBÉ*ö“8L¢M¢M¢A.-—–KƒÚUíª~gÅ‚ÿû?>ÈŸ=>{Ã* «0¬\=õüÕóàbïbïb_îýrï—{A£ˆQÄü¾~MYMYMYx6çÙœgs ¥GJ�”p»Ãí·;€ýJû•ö+a§ûN÷�î )­)­) ËYÎòw籡ÔPjøö‹pªõ©Ö§ZCÈÍ�›!7Áì;³ï̾Ãë†× ¯Ãçû?ßÿùþ÷_š­±Ec‹ÆpøÄá‡O@dÝȺ‘uß^‡&Ÿ‚b?„hÞü‡y0yhòÐä!¤Ù¥Ù¥Ù½}ÞùWç_�…�k7®Ý¸jv¬Ù±fG �@Ä�›‹]n‹Ü¹- Ù:Ù:Ùª}[íÛjß¾ÿ¸òy�¼ÌÊš•5+ �\:¹tr�qQã¢ÆE�ÖEë¢u�à†Á ƒ‚ÅQ‹£G!kNÖœ¬9`·Çn�ݰ4·4·4‡¬IY“²&½]*Ér’å$ËI�=0{`ö»äþãìSÃã†Ç �C�‹5.Ö¸]+ºVt…nÉÝ’»%CåÈÊ‘•#ÁbœÅ8‹q�W'¯N^(ߥ|—ò]àÿöt KR—¤.IÐcL�1=ÆÀ¹»çîž» yîyîyî\¿¡™¡™¡¸�rå> f9Ìr˜ÝßtÓý TiQ¥E•P¾jùªå«¾]-ÿwþqvkÆÖŒ­[aÇÐCw …Nu;ÕíTFÚ�´is.æ\Ì�ç'ŸŸ|~òý??Û<Û<Û<(íWÚ¯´<ýlô³ÑÅúÕ„Wì{`¦ L˜.‹¦M-šBRaRaRáÛçË_,±üE(OyÊ¿ûƪT¥ª¾§ãï'Iþ’ü% Ê�r ˜—3/g^®þm3—\rA^!¯�W¼}ØÙÆÙÆÙ^­µþÕzÐÕÒÕÒÕi‰´DZ,f1‹gœqæ3ŸùïŒÿG�ÿQŽ“œä$�Fi¿GZ -�ðö¬Óa cH›¥ÍÒf0É1É1É�¢~EýŠúAÑ¡¢CE‡`ûôíÓ·O‡×–¯-_[‚�¯�¯�/ŒR�R�Rƒ²­²­²-È7äò �íd;ù�°a‚ &À·|Ë¿ù‡ƒ4Eš"M�‚؂؂Xˆ Š Š ‚àGÁ�‚ADDDDD(âqŠ8йéÜtnÀ@R +m˜U4«hVòfåÍÊ›Ld"‹áû!@‰­Vh}ÇúŽõH—>.}\É"W—«ËÕ¡hBÑ„¢ üóÂãÿug,ÎXœE{E{E{È Ë Ë,ŽÓ»µhÑ‚TGª#Õiˆ4Dòöé Ï Ï O(ûSÙŸÊþR;©�Ôþï·ÃwÆqÀ�ÆJc¥±ï<^™ÊTi¡´PZøÎãN8áÌf6³:t¼m\4h~?Îo‹?ÿÖÀ¤EÒ"ioå?Þ'…IaR(f*f*fBË-_´|½÷Ü{0ô¼ÖóZÏk`çjçjç ²¿ì/ûƒ4Iš$M©«ÔUêúÎöÿqˆ´RZ)½{–æo�í‡Â•9ÊeXZZB³sÍÎ5;ýgöŸÙ&l3Þf¼ÍêéêéêéŠïû‘íŸíŸí6ö6ö6ã5<…¿§[ ÑZe­²VAÆíŒÛ·K®€¼Íy›ó6ÃÁI'œ‰#G$Ž€1wÇÜs¬±Æúÿñþ‚M› 6Ák¿×~¯ýÀd…É “Pµ°jaÕB #éXrùKÚogs::8:8:À“éO¦?™®¸âúãô1ècÐŒ?6~ Ï;>ïø¼#$žH<‘xâ+ÄWˆ¯_ ûbØÃàôÝÓwOß…O_<}ñ^•zUêU)È–=,{dgfgfgBÖã¬ÇY�!swæîÌÝ�â�â�âiª4Uš ²öeíËÚ)S¦ EiEiEiÈ9“s&ç Üx~ãù�çÐ`yƒå –CfÕ̪™Uß ˆ‘b¤ ršæ4Íi ƒ2e ‚´‰iÓ&BŽiŽiŽ)älÈÙ�³j”®QºFéw wÁþ¹øàÓ¡O‡> Ùó‡g‡ø¾ñ}ãû‚ÓC§‡N!åjÊÕ”«�a–a–a)Q)Q)Q�fœfœf >>> ¥¥-¯´¼Òò „ô éÒ lÆÙŒ³V­.Z]ëÉÖ“­'¿ÿ÷"~züôøé�á‘á‘á5Õ5Õ5Õzü¢ Â_Pb{`¶ƒlÙ‚Œ]»2v•\ן\rý Üky¯å½–Щ¨SQ§"0Š1Š1ŠùÏï×uÐuÐu€}Îûœ÷9ÃÚÆk¯m rM¹¦\³är(Ò&i“´ :ôëЯC?¸v+ìVä:ç:ç:ÿõqíºØu±ës2çdÎÉE5E5E5Èê›Õ7«/Œ_2~Éø%Po]½uõÖ�o¦o¦o&txÖáY‡gw%îJÜègÞϼŸ9´1mcÚÆ²~Ìú1ëGè�Ù;³w&4?ÖüXóc�Þ ½Azè3¿Ïü>ó¡™w3ïfÞPE®"W‘azé饧—†‚;w î@Ö¥¬KY— �qã>ÆÐÔµ©kSW°[g·ÎnŒÝ2vËØ- Û¥Û¥ÛeÊ8”�±‹Ç.»”””þ¸~¹�Ü@n_|ið%Œÿzü×ã¿Ó$Ó$Ó$È�3:g4¸OwŸî>úìw°ßAȨ’Q%£ ¸Ww¯î^úMê7©ß¤·K¯Mj?©ý¤öPKUKUKщщщ�Ú.µ]j;Ðh ´ÅðÏÎààààà`¨lRÙ¤² TÜ[qoŽô«)ﯤNo¼zéꥫ—dyòáɇ'–e�J£Ò¼ÇiÛä'ߟ|ò•å/V|±â‹²\QQ!ËòOòOòO²¬µÒZi­d¹Ð¥Ð¥ÐE–5¿j~Õü*Ër˜&‡½3οžÖœ¡ËÐeȲîªîªîª,ÆÆÆÊ²ú¸ú¸ú¸,ËÝänr·w‚Œ—ÇËãeY=T=T=T–Õ/Ô/Ô/dùÿV)©Yþó _¾.|-ËK~^òó’Ÿey{Íí5·×”e­©ÖTkªït‡ò8çqÎãYþ2ì˰/ÃdùE»í^´Ów*AøkJlÌq‚ãÇ �;"wDîÈ É É )¾ñSÂRÂR ìǰÃ~„Çö�íÛù�çvžÛ m Ú´…-…[ ·Â�Ñ?Fÿ óûÏï?¿?„Ì ™òon¿"�—ÆKãA³X³X³vWÝ]uwUXÓeM—5]`íÓµO×>…—e_–}Yöí’W§*žªxª"¬Ù±fÇš°Ú~µýj{¸ètÑé¢0‹YÌ*©ÙþÏŒ*U6ª CÏ =7ôÜ©r§Ê�*plÛ±mǶ�ü¹ü¹ü¹þò %ëu�×=^÷€õáëÃׇCWÛ®¶]m¡Ú¥j—ª]Òw:AøkJ¬�Y8Y8Y8�b…b…b¤—M/›^¶øÆ/Ó Lƒ2  ^£z�ê5‚š«k®®¹:ê|¨ó!0´5´5´…Z÷kݯu&ÔœPsBM°c;Æv ”(Pú÷ãJ*I%© miÚÒ´¥°­Ò¶JÛ*A³a͆5» ì6°X7¶nlÝÞ¼~óúÍkØ.o—·ËЯ{¿îýºC¿6~müàg�Ÿ=~ö€ŒE‹2•Ôlÿy•öWÚ_i?Lè9¡ç„žptÎÑ9Gç€ß¿'~O@µPµPµPß)…â~ ü@øX&/“—ÉÐât‹Ó-NC÷WÝ_u¥ït‚ð~J¬�™'›'›'ƒÙV³­f[!Å9Å9Źø·£4Sš)Í@qIqIq ó ó óAΕså\0ºntÝè:œ;|îð¹Ãy-òZä5Èš?4èïÇ“GË£åÑ`1Áb‚ŨgYϲž%|þûóߟ‡sŽçÏ9‚Q´Q´Q4$VM¬šXbÎÆœ�9 á‡Ã‡†§¥Ÿ–~ZÒãÒãÒã Ð¡Ð¡°–Z*.µ¾¨õE­/`æú™ëg®‡[7nݸu–÷^Þ{yoˆ;*v”¾S ÿ-•›ÊMåñññð�ãwŽß9B¯î½º÷êÞ¥½K{—ƒöí Úë;­ ¼Ÿk`&wLî˜Ü� �+<®ð^}=ôõÐ÷÷wþ±†ÔDj"5¢‰&.Æ\Œ¹›R6¥lJ�²Ên(»¬›Z7µnÊï—ðøíÆ›ÿ¸^Çl·Ùn³Ý0wùÜås—ÃÄ_'þ:ñW8´ÿÐþCûaûšík¶¯ƒG� �É“&# \ûrí˵‡Æ]wiÜÖ8®q\ãvËí–Û-ÿk%–¤ê½ª÷ªÞ I‹¤Eؽ´{i÷¾9ôÍ¡oA@n@n@.dFeFeFé;­ð¯Š‹‹áî7w¿¹û Ì3œg8Ï®7¼ÞðzC˜ªšªšª�ñã=ƃr’r’r’¾S Bñ(±ö›Ê-+·¬ÜÞX¿±~c òQù¨|´øÆÏÛ”·)oäÕÏ«ŸW455!9<9<9TÓUÓUÓ¡²yeóÊæ`}ÝúºõuP©ŒTF IÓ¤iÒ EþŠüP0°``Á@ˆ_¿,~œis¦Í™6àfìfìf õ:ÕëT¯äùçùçùƒã÷Žß;~7UÜTq¨vªvªv‚ã\ǹŽs¡êøªã«ŽÃxÃxÃXL¶¸ØÙÙÁÿÇÞ}ÆEqõÿÿí.méAQ±bWì½+ÖØc‰=šØ5ö‚hì½D±‹{/ØÁŠ"¢ ]štvþ7þ——y\ùæ—¢fEÏóÎu ³gÞsfãÇ3sæÌXó±æcÍaTÕQUGU… › › ˜b=ÅzŠ5‰?$ÒΧ�O;O‰Ì ¤)èRÐ¥  „x†x†xÂü¸ùqóã`MÏ5=×ô„Çj«q ¶_Ø~a{¨æUÍ«š—¦S §ñé X§*NU qLâ˜Ä1PXXøáí¾�{÷6 U†*C¸Ú¹Ú¹ÚÁË[/o½¼ÍÍÍPpýÁõÇ3gÀ¢¥EK‹–PSYSYS ±õbëÅÖ“Û&·MnC…ï*|Wá;ÈÍÍ…â>Å}ŠûÀ¯üʯ€‹‡‹‡‹ |=ðõÀ×Pêh©£¥ŽÂ‡ àYŸg}žõ�SŧŠOC¨M¨M¨ ¿)~SüæÓŸÐ%o!o!oµ®ÔºRë ÌOœŸ8?úLï3½Ït¸mwÛî¶L>?ùüäó°Qg£ÎFxzïé½§÷ ¨JQ•¢*üw$,ü3Òyé¼t’’’àx¯ã½Ž÷‚Mg4�Ñ6ÆnŒÝ ŽÞŽÞŽÞ°Øv±íb[è›Ù7³o&m3Úf´MÓG!Ÿ–ìÝtÄOµƒtuº:] “¤IÒ$ ¦î™ºgêpà2ÀåS\R>©‚Ê• *Ó½Oö>Ù ‰‰‰–––Æ1Æ1Æ1PíVµ[ÕnAõÔê©ÕSÁ¡—C/‡^`œoœoœÏû•4¾r…s çÎ�øñ3âg@øÂð…á !¨(¨(¨b~�ù5æW°PY¨,Tà5ÅkŠ×¨ý öƒÚÀ²ºeuËêÀ†0DÓG#ÿ®O^ÀÞ½0rú¨é£¦�¯e^˼–A»í´{ éÃ>X3šÑ R—§.O]û?ìÿ°?Ïž<^U}UõUÕ÷…Ïn“Ý&»MPõÛªßVýÊg–Ï,Ÿ ¶ƒlÙƒ €Þ-½[z·@6P6PV’Þ¼ŸýìÕcÕcÕcÈÕÎÕÎÕ†ôé#ÒG@¤A¤A¤D´ˆhÑ"ÎEœ‹8Ù›³7go‹9s,æ@u·ênÕݠ曚oj¾�²áeȃ–�–�Ö¬B/_’O^ÀÞÙqzÇé§!%(%(%&Í™4gÒM¾ð©H�R ÷jÜ«q¯,9¸äà’ƒ`mgmgm¥F–Yj$Ä­Š[·êýb¿ú�ôé7Ë–+,W@ÿ2þeüÁª¯U_«¾`VÙ¬²Ye0Ë5Ë5˳ fÌ*€aŠaŠa h'j'j'‚¼ƒ¼ƒ¼EQ ** ¬cë@VSVSV¤Òip˜Ã©‹ÔEêòîÿ÷—�ß=W˜i”i”ii�Ò¥5‚ôé=Ò{@ª{ª{ª;Ä[Å[Å[A|a|a|!dffBш¢E#Àô€éÓà4Úi´Óhðˆðˆðˆ×ú®õ]냙£™£™#èŒÐ¡#žË„ÿ§­€ÇÇÇö³ÛÎn; K£–F-�£…F �jº„�¥8­8­8 .¥\J¹”ûê쫳¯4hß }ƒöÐûlﳽςá#ÃG†� ëMÖ›¬7�<\Ô®¨]Q»÷…¬¨|Qù¢òP¨S¨S¨ÉÉÉ ]“®I×3Ì0]¥®RW FIFIFI`|ÕøªñU(5«Ô¬R³ ìº²ëÊ®ëÖ ¬€Í›56kÀ|…ù 󠤤¤é³%%Û¿VÀÞ¤¿I“Sƒ§O †‰¯'¾žø*®8¸â`Mwƒð¡2êfÔͨ ;oí¼µóÜ÷¿ï߆d É’�š7jÞ¨9ÈœdN2§¿Ñð.É©“ÔIê$PVV†BY¡¬P™d’ d-ËZ–µ rwåîÊÝyµójçÕ†ÂÇ…� Cñ÷ÅßE‹.])H ’‚@«�V­6 øNñ�â;Ð:£uFëÌûK˜úåôËé—ÃN†� ;�ñVã­Æ[A¿²~eýÊ ¸¦¸¦¸ббሄÄ'ÿ¯Iø Ø; Ë/,¿°<”Y^fy™å0°ãÀŽ;jº„*|Xø°ða°®õºÖëZƒádÃɆ“aä©‘§Fž{w{wû/`QdA>?Ÿ|ýÿªù¤æ“šOà‘Ç#�GPÔ°¨aQCMwƒðW©Ú¨Ú¨ÚÀ‰k'®�¸ ¬X/°ÏÑž£=GÃÌæ3›Ïl. — ŸÞ'{Ø©¶µÚÖj[á@ê�Ô©mmmòþ5KÂç)mAÚ‚´°õ›­ßlýÂ+†W ¯cÖŒY3f Ô~Zûií§ ³�YÈ,>|‚ æ_�Ù¶9ls\ë¹Ös­7šÝhv£™¦»Aø#�Ž?:þè8Ì\5sÕÌU�k’k’k .0„:þuüëø‹Â%¿ï_/`²‹²‹²‹Ðlh³¡Í†Â�wzÜéÙ]³»fwÕtw…“ 'N†#�Ž<:ò|ƒ|ƒ|ƒÀËÇËÇ˦EM‹š¥ôJé•ÒÓtZA¾fÿz{§Zåj•«Umkmkmk42h¤¦»ãë•j”j”jËm–Û,·�3‡Ï>s&ÞœxsâMè}³÷ÍÞ7Aw‚îÝ šN+‚ �YˆÿëÈË#/�¼„;ßßùþÎ÷0oƼóf€n-ÝZºµ4Ý=_¾GO=yôäýªývÁvÁvÁ0lô°ÑÃFƒ­ÒVi«ÔtQr€IDATJA„ßÓØì�Æa�ÇA†*C•¡‚ûA÷ƒîi:Õ—Kõ­ê[Õ·ð«Ã¯¿:€ï[ß·¾o¡Ib“Ä&‰0Y9Y9Y) — Ÿ?�0‹¶m-ÚB“½Mö6Ù Ç Ž7Õ0Õ0Õ0M§ûr¤LO™ž2–ç/Ï_ž§#NGœŽ€ &<˜ðz÷îÝ»woЭ;Zw´¦Ó ‚ ü¹}ýi5¹ÕäV“áÒ½K÷.݃»Éw“ï&C}êS_ÓáJ¢ ‚‚е¡kC×Â:õ:õ:5ØV·­n[–]XvaY°N´N´NÔtXA„¿Oã#°w,6Yl²Øí·Ün0Ê;”w(ò&åMÊ›¤ét%GáºÂu…ëàH…#ŽTWWWh2¦É˜&c`J÷)ݧt…K„’ï³)`ï´jѪE« §§—*_ª|©²¦S}þÒrÓrÓráç�?ïüy'œ68mpÚ¾ü>ðû@èõ°×Ã^AÏIÏIïï¬E(‚ð™Òø,Ä?ð&àMÀØeºËt—),y¸äá’‡`UÓª¦UMM§û|�}:ß^|{ñm¨[¿nýºõaÚˆi#¦�…K„/ßg;{'*,*,* ævŸÛ}nwø!뇬² jlÕØª±šN÷ïy[æm™·e`Ç­·vÜ‚ûÖ÷­ï[È #6ŒØuúÔéS§Èle¶2[M§Aøô>›YˆÄÙÝÙÝÙZ÷lݳuOØa´Ãh‡,(µ Ô‚R`�`�`� é”ŸN´y´y´9¬®µºÖêZ [A·‚n˜»c;Àa‚ñ2† _¡ÏöâÿêbÖŬ‹È&Ê&Ê&‘ô#éGÒ�8âˆÓtº�GýVýVý¼¼¼aî½¹÷æÞ÷¾î}ÝûÂÌ£3�Î< =z:ôÔtZAÍùì/!þ¯Ð�¡C7‚O°O°O0L}0õÁÔP)¸Rp¥`M§ûçråÊ{=÷zîõ„k+®­¸¶6Ø|`shfÝ̺™5ÈÈÈh:­ ‚數öŽß ¿~7 Ä:Ä:ÄæGÎ�œ ÆíŒÛ·Ótº¿.þAüƒø°nÒºIë&AöÌì™Ù3a¬j¬j¬ \Z¸´pi¡é”‚ ŸŸs ñy�óç=tOëžÖ= û}÷ûî÷îsŸûšN÷ÿЕ®t…û£ï�¾?~ ù)ä§°t±t±t�y÷æÝ›wO.A„?Sb ˜þ=ý{ú÷`„Ó§NpSvSvS�[·n}¿�º…º…ºDߊ¾} â â 4pϬȧȧÈŽ?8þàøXÖkY¯e½ ýÙögÛŸ…±÷ÇÞ{L&˜L0“2AþT‰-`ï8wvîìܼͼͼÍ`[Ÿm}¶õ�$¿$¿$?8QùDå•¡|ÿøþñ¢ Q…¨>ÂŽSH!xË[ÞþñfÙ²d€uÃ× _7ŽY³:f6MØ4atmÔµQ×F ¨¨õ?ß&‚ðw}öÓèÿª6oÛ¼móžÉžÉžÉàÇm?nûq\o{½íõ¶ðªÇ«¯zÀÑ*G«­õëÖ ™R¦”ý�׆¼à/ `XÀ°€a`4ÝhºÑt¨Ù¼fóšÍßoããã k\ûãÚAæ-ó–yÃìC³Í>šî5A„’«Ä�ÀÞ)¬YX³°&äý˜÷cÞ�pl걩Ǧ«i¯¦½šö~»óYç³ÎgÁË»/ï¾¼û÷÷)�”GÊaR¹Iå&•ƒií§µŸÖâ†Ç �Áƒ?„¹§çžž{Ê(Ë(Ë(aÖôYÓgM…Kác)ñ#°Ì˜Ì˜ÌXðhÁ£�`ÍÆ5×l„‚jÕ ªý~û§5žÖxZ®W»^íz5p‰¿²¶m~­üZùµ`õÑÕGW…ÇÇGPìSìSìƒ±ÍÆ6Û " " "¡g|ÏøžñÐöVÛ[mo�Ö@­�Z5Ý[‚ _Ž;�þ�¬ºYu³êÂR—¥.K]`gØÎ°�að:÷uîë\�žIϤg¿ÿ\ÇÑGw ûÇï¿<è»ê»ê»þñ~ü ý ý ax“áM†7�ŒS§2N½ÿ½¢²¢²¢2Ì0›a6à fçÎÎ�� ò`y°¼?Ÿ&‚ð¹*ñì�bŸbŸbv v vƒ�ê�ê�j8þíño� iiiï··¹nsÝæ:´:huÐ ¼Ü¼Ü¼Ü~ßnTŨŠQ¡OnŸÜ>¹p÷ÕÝWw_ýqøEûí_´¡azÃô†éšîA„/ÏsL1E1E1êt©Ó¥NXÿëú_×ÿ ¿Ìþeö/³¡õ¶ÖÛZo]]]Hj”Ô(©œÙuf×™]PìWìWì÷¾½ççgX¹på• !¸mpÛà¶ÿÇŽ;Ð� {){){ i>i>i>peWö‚º�º�º=X-‚PR|1#°?óæÛ7ß¾ùŽÆ�= ë|Öù¬ó�¬ëY׳®Ãj¯Õ^«½ R¹Jå*•ƒ›wnÞ¹yFUUaTÈtÈtÈt­}Zû´ö�ýû=ö{ âÈŠ#+Ž„VÏZ=kõ ê-©·¤Þp®â\Ź ˜×4¯i^ðÁM÷‚ —ã«)`ÿëJõ+Õ¯T‡ž{nì¹²«eWË®å÷•ßW~ä×ɯ“_òòòòòòÀk‘×"¯EàµÎk�×:¨ëV×­®¸é¹é¹é�n¢n¢n¢¦�JáëQâg!þS©¹©¹©¹�Ù/³_f?PEª"U‘ðˆG<ºUíVµ[UX¤X¤X¤‡E‹�ÒFi£´2È CÓG!‚ðõúbî�ý]fþfþfþ`àhàhàøþçZw´îhÝ�fß7û¾Ù÷àââÊÖÊÖÊÖšN-‚ ¼óÕ^B̘˜11c" ^2xÉà%�Ý&»Mv¨b]źŠ5( ”ÊøFç�otÀý€û÷šN-‚ ¼óÕŽÀ²Êg•Ï*fÍš„õ³×Ï^?–<^òxÉc¨x«â­Š·Àg¤ÏHŸ‘v=ìzØuM§AÞùj X4ÑDF­ŒZµ‚2eÊ8€öí'ÚO w½Þõz׃– Z6hÙ|�û÷=a§ÂN…�úàÝ ‚ è«-`'?œüp2T˜PaB…  tR:)³¦”ü¨ü¨ü(ômÔ·QßFТ\‹r-Ê�ÏbŸÅ>‹!Ì4Ì4ÌTÓG!‚ðõúêf!ªÂUáªpˆÜ¹5r+tÕîªÝUû�·—Êe�Ð+¨WP¯ ÀC aIÅ%—T„)=§ôœÒ*¬x°âAM� Â×ã«�%H R‚Ùƒ³g† îÜ+¸ÿùçµµµ¡wbïÄÞ‰Ð&²Md›Hðuõuõu…'ùOòŸäkúèA¾_]‹Ø±3b'˜ì7Ùo²¬zXõ°êñ×?/Ÿ$Ÿ$Ÿ½�{;÷v†Öµ[×n]–®^ºzéjx"{"{"ÓôQ ‚ |ù¾ºù"òEä pÄG@ñXñXñøï·#ó”yÊ<¡ç=èù´íÖ¶[Ûn°tÜÒqKÇAè ÐA¡ƒ4}´‚ _®¯¦€–/,_X"NEœŠ8•ZUjU©Õ‡·+�”GÊ#¡gxÏðžáЮ_»~íúÁòÃË/? �µk=þêî4 ‚ |z_MËìžÙ=³;d˜d˜d˜@Y“²&eM>^ûòöòöòöгJÏ*=«@{‹öí-À×É×É× ,x°àÁM÷‚ —ã«)`±Gc�Æí¦ÚMµ›B©*¥ª”ªòñ÷#Ó•éÊt¡Û‘nGº�.9]rºäÀò:Ëë,¯÷ÊÞ+{¯¬¦{C¡äûj XèýÐû¡÷Á!Ú!Ú! ‚ ‚ ‚>Ýþä5ä5ä5 ký®õ»Öï�Þ½Â*—U.«\à®ê®ê®JÓ½"‚Pr}5,R+R+R \—¸.q]òïíWvHvHv:ÇwŽï=L{˜ö0…Uþ«üWùÃ�²wÊÞ#2A„¿í‹/`™w2ïdÞ�ĨĨÄ(p_ã¾Æ}�æò´ïÒ¾Kû.Ðw]ßu}×Ášåk–¯Y·Þzx롦{K¡äøâ XRNRNRHk¤5Ò°™i3Óf¦æòÈúËúËúCÛÓmO·= ýýúûõ÷ƒ vì6ØÁ ×®7\�-la‹¦{OáóõÅOðŽOŒOŒOãõÆë�׃Q£:Fu€*TáLâø«d&2™ ´>Þúxëã è¢è¢è=6zlô€â]Å»ŠwAcÓ`æéÞAø||ñìù€çžGCGCGCÐí¯Û_·¿¦Sý^ ÇŽ-A®”+åJØúùh(r(r(r€›ÓnN»9 ’z$õHúkh ‚ðñ}±—&L<EQEQEQ`ßß¾¿ýgxéðÏ4¼ÐðBà ?"?"?민þ1‡‡‡C»Jí*µ«¤é”,§ANƒœp¡å…–Z‚l�l�l ÈëÉëÉë�iOÓž¦=¡nHÝ�º!p¿ÒýJ÷+A²k²k²+˜&›&›&ƒ�����è=×{®÷Ò¦¤MI›¹ž¹ž¹ž`‚ ¿]X¥x`ñÀâ�ð¸ÖãZ�kÁ«v¯Ú½jAÊ e�LΛœ79Yí³Úgµ‡"�"�"pÅW@qVqVqär¹\.‡ýôÐx/ð^à =¿íùmÏo¡›N7�n:€=öØÃí·wÜÞùãòÇå�ƒÊÝ+w¯ÜlJÙ”²)—[_n}¹5XT·¨nQ gÎ*œ�*U4‚—ý^ö{ÙtGëŽÖ Õ7Wß\}³¦Ï¢ |ž¾ØXLý˜ú1õÁøµñkã×`lmlml­éTÿ\ýªõ«Ö¯ cÓÆ¦�Mƒý!ûCö‡À‰€'@Z*-•–j:åïéøèøèøÀÑ€£G Ð(Ð(ЬkYײ®;ƒwï †«+®®¸º:%tJè‹®.ººè*Ä�ˆ;wòòò!oHÞ�¼!°üþòûËïCâ‰Ä‰'~¿_y˜F¿ýbô ”?UþTùS`˜m˜m˜ Õ,ªYTƒ×ç_Ÿ}°Æk ›l²� `X”³(gQŒ®]1ºåmÊÛ”·ÕzÕzÕz¸p%à ̰ža=ÃaU“UMV5�äœäœä0{köÖì-ØO¶Ÿl?z÷(îQ êyêyêyàÖÇ­�[�M‘M‘MÑôÙ„ÏÛ—7K"‰$x¹ûåî—»Á)Å)Å)…ßÌGÿ2ÔjR«I­&0áÜ„sÎÁ¯í~m÷k;8|òðÉÃ'Aº+Ý•îj:åo$’H"H;¤ÒŽ÷?Ö9§sNçäiåiåiñßk�²YŠ,d¡²PY(ȶȶȶ-hA‹¿±_]tÑ}?B•NJ'¥“ÿ ¿ œpÂùoá,[<¶x,dêeêeêÁ�mw¶ÝÙ× ¯^7„fk›­m¶JýRê—R¿€z¶z¶z6ÿá½#Ï‘çÈs@§P§P§´çkÏמ¯é“&Ÿ·/n–·,oYÞ2HÙ˜²1e#47hnÐÜ€ÿþú¥©áTé†L²šd5É ~¶úÙêg+P…«ÂUáÐû»Þßõþä!òyˆƒša†È6Ë6Ë6£Å(HT&*•à<ÆyŒó`4£ ¸à‚ �A¿iç]!¹Ï}îÿf»ÿLÿ9rä@(¡„å(G9À 7Ü€"Š(.r‘‹@_úÒ÷7??ÍiNƒ,C–!Ë€¢ÊE•‹*CÑÖ¢­E[A/Q/Q/ìÛÛ··oõºÖëZ¯+xyxyxyü>Žºžºžº`‡vü· K—¤KÒ%+++�t�t�tpùÆå—o4xÞá3öÅ°Ü Ü Ü È«“W'¯˜/2_d¾HÓ©>=�³g=ÎÂdÏÉž“=aiÚÒ´¥i j©j©j ßLúfÒ7“@ËWËWË÷ßϧ¶WÛ«í!Ø-Ø-Ø 6uÚÔiS'P®W®W®‡Ž3;Îì8®\¾rùÊe(œP8¡pD]�ºuªT)¨ROÚŸ(IC\‡¸q•¤­ ·6ÜÚP’T‹U‹U‹ÿý,}Xú0I*(SP¦ Œ$¥4NiœÒX’/$^H¼ IY‹³g-–¤”—)/S^JR’Y’Y’™$å7Ëo–ßL’2]2]2]$)Î<Î<Î\’òòóòóò%©xuñêâÕ’”â•â•â%I Íš'4—¤ô�éÓ7JR~F~F~†$%mHÚ�´A’’/&_L¾(IEu‹êÕ•$é�ôFz#Io¿yûÍÛo$)»Vv­ìZšþ ÂçMöîÿhº�~,vvvp<øxðñ`ð½à{Á÷(((h:Ý¿/Ú*Ú*Ú –X-±ZbÕMª›T7�!C<†x€Îf�Í:ŸpšvÁÜ‚¹saXô°èaÑ`_`_`_súÎé;§/hwÔî¨ÝQÓ½$BIôÅMâˆ9s<æ8Øv³ífÛíë-\ï¼›Ä2Ãi†Ó 'xÐãA�=`ãš�k6®�‚ví Ú}ºýç7Èo�ß:[u¶êlõÂê…Õ ƒe�²@©éÞ¡$ûâF`¾Ñ¾Ñ¾ÑïW�°gÀž{4�êóñ:õuêëTX¼hñ¢Å‹Ày±óbçÅ0R=R=R J=¥žROÓ)AþÜ—3ÛÊV¶Â›ð7áoÂÁ6Æ6Æ6FÓ¡>?e,ÊX”±€Y>³|fù@̺˜u1ë`õÆÕWo„l—l—lM§Aøs_LËz–õ,ëdèfèfèB™oÊ|SFL?þC¶Z¶Z¶Z0£þŒú3êCÊÞ”½){áçr?—û¹dŽÍ›9VÓ)AþØSÀÞMƒVQQó±æcÍÅ_ÀʪŽU«:0}ðôÁÓC¾q¾q¾1ø–ñ-ã[Ò;¤wHï é”LµVµVµÂN„�; &LÐt*Aþ Š9ÿ¡é *¶{l÷Øîr'äNÈhݯu¿Öý@¯´^i½ÒšN÷ùSÖRÖRÖO{O{O{Ž Ž Ž�ËêËêËj¨V%¬J60l`Ø@Óiß»uáÖ…[`¥ÁJƒ•ààêàêà 9ksÖæ¬…$u’:I YM²šd5�7foÌÞ˜AŒqŒqŒ1p�ƒyœ�V:­tZiº7áëòÅŒÀþÿç‡@ÏGÏGÏ”k”k”k4�ªä1©gRϤüpù‡Ë?\ó¦æMÍ›Â"ÃE†‹ !îNÜ�¸ÏhMÉèžÑ=£{³ÉÏ&?› ÁÁÁpÝûº÷uo•4*iT\º~éú¥ëp­ôµÒ×Jƒ�¿�¿�?ªp¨Â¡  ^¡^¡^K–:,u€Ã1‡cÇ@~ùüòùåaÕêU«W­†ë½®÷ºÞ ÎŽ8;âìØX°±`c¨f©f©fiº7áëòŰävÉí’Û�éjÓÕ¦«A÷‚îÝ šNUrœ58kpÆY޳g N“�&;M†Eg�Ytb•±ÊØÏ`¼ã$ÇIŽ“À¶œm9ÛrШJ£*�ª€Û~·ýnûAÙUÙUÙº^ïz½ëuèÿ ÿƒþÀÊÍÊÍÊ Š5,jFFF`µÎj�Õ:�úKý¥þ11bbÄD\¸0p!ô˜Úcj�©ÐÒ³¥gKO8ï}Þû¼7¤5Hk�ö�LákðŰ„ý ûöƒUªUªU*GqšNUòé7Óo¦ß Fº�té[=¶zl…ù æ/˜¿"ã"ã"5ÙÏÿYQ. —†ó~±ÝRH­“Z'µN‚îlÝÙº³AwªîTÝ© Û-Û-Û 27™›Ìí÷ÍÊ"d²È6È6È6€ø˜ø˜øðßî¿Ý;\]zuéÕ¥P¾°|aùBО¬=Y{²ûA¾B%¿€yã�7dÚeÚeÚ�y‚y‚y‚¦C}ytƒuƒuƒá[ûoí¿µ‡º}êö©ÛîY¸gá;v&쌂)Q¢u¼:^ÒTiª4ÐB -�Í–Í–ÍqÄñ7ŸûÏâÂÅ]Š»wùÍÏ�p ¸Ìe.ƒÁZƒµk¡t­ÒµJׂ®Wº^éz&XO°ž` k;¯í¼¶3˜4?h~PsçG¾F%¾€ï)ÞS¼²zeõÊêf§ÍN›�Ötª/—ömíÛÚ·a€åË–в~Ëú-ëÃ’K,Y�?<þðø¿—Ç|œù8óqP�[�[� þßùçÿ²²²ÐzEë­W€r¼r¼r?%¾€åÏÊŸ•? ”NJ'¥“¦Óÿ”I I I Lš?iþ¤ùPêI©'¥žÀüqóÇÍQQQšN)Âç¤Ä°Ü�¹s‚þxýñúã5�FøPå Ê”‡±WÇ^{ªU+ªV‹üù/ò‡Ç»ï~¼[Ó)Aø”Ø&J�R ä7Ëo–ß 6l4بéTÂÇ¢ã¡ã¡ãCN99ä$´ßz|ëñ°4kiÖÒ,¸½óöÎÛ;ÿ9u'u'u'ˆÙ³5f+¨§«§«§kúhAøJlSÏUÏUÏ…¼“y'óN‚þ>ý}úû4�JøØáŠpE8xö>ì}úMî7¹ßdX·mݶuÛà‚Ñ£ F ÎTgª3áØ�cCŽ �ËG,±Bå¡òÐû-áÿ¥Ä.%U¼¨xQñ"(´)´)´½êzÕõªk:•ð©È§É§É§AkûÖö­íÁø‘ñ#ãG°©Í¦6›ÚÀ­ Z´àȽ#÷ŽÜƒ¨gQÏ¢ž�g+ÏVž­ ÒóJÏ+=EyEyEyM� C‰ý·©z°z°z0¨Pÿ þ´»jwÕîªéTÂ'×�~ôƒzKë-­·jÔ¨«ë¬®³ºDÅFÅFžßÜÿGÿý„HËHËHKM‡ác*±#0õIõIõI(Ö.Ö.ÖY5Y5Y5M§>5õeõeõe8¦wL¾²úÊê+PPTPTP<á OÞo$H„ŸÖÿ´þ§õÀLf2SÓG#‡(±#°woâÅSL�l²ÉÖt(áSË�? \”_”_”CbÛ͉m]tÑýýöjµ�Úü×ú¯õ_ ‘#;FvÔôQ‚ð1”Üö2=™žLÐFmM§>5} } } XtzÑéE§á€ýûöЫn¯º½ê‚y5ójæÕ~ÿ¹§¥ž–zZ ŽÚµ?jÿvôš×¼©·Ô[ê EéEéEé ª¬ª¬ª yyyðæÅ›o^@ìϱ?Çþ /޽8öâD–‰,YÂÖ…­ [Ï®<»òì D]ˆºu^j½Ôz©ñ·ãoÇ߆Ìþ™ý3ûCA@A@A¨ªªBqfqfq&P™ÊTÖtï Âç¥Ä¾Ð2÷bîÅÜ‹0ãÐŒC3Aߎ};öíµÚ×j_«½¦Ó ÿ¶ìýÙû³÷C�‹}‰1‰1‰1ðvÊÛ)o§@VtVtV4äÊre¹2(´+´+´¼ñÆÈ"‹,À;ì€bˆ<ðÀ¸Ï}îóþŠÁ;餓è£�>È‹åÅòbÐóÖóÖóÃlÃlÃl0Úk´×h/˜Î6�m:ì]ì]ì]ÀÖÍÖÍÖ Ì™?2–�-[6ã3þ8Á Nhúì§Qbï�½û²|¹|¹|9Ȼɻɻíi�(`_ê†U «BƒÝ v7Ø öëí×Û¯‡ÒZ¥µJkÁ�ꪨ/´^h½Ð‚±ÇvÛ<¬=¬=¬AÿŠþý+`=Âz„õ°¹lsÙæ2”ëR®K¹.`ºÑt£éF0ziôÒè% 1b0 œ œ œ@YQYQY´µµµµµAî#÷‘û€v�v�vH¥‡ÒCP«ŒUÆP|¦øLñ(,_X¾°<älÈÙ�³rÜrÜrÜ G7G7G2å™òL9d´Éh“ÑÒ¶¦mMÛ A5ƒjÕ„Œ�Œ�Œ(XW°®`ÈwËwËwƒÍ› 6Àq‰ãÇ%PiS¥M•6�“¾“¾“>˜Œ5k2´¿ÓþNû;MŸ=AøgJîÌ:×:×f\™qeÆè÷S¿Ÿúý5×<\óð'ØáÎpÔgÔgÔg@¾Y¾Y¾È'Ÿü?þ˜êŽêŽêÜÝwwßÝ} ¤¤�|ù6òå¿—†ä¯å¯å¯¡Ø¹Ø¹Ø¸Ãî€ÂHa¤0¶²•­šîõÏÀ#ñ²Ûe·Ën¡ÏCŸ‡>‡�¨�¨�(ˆ°‹°‹°ƒ¼qyãòÆ�õë Ö ÜÒrKË-���xÓóMÏ7=Áû†÷ ï`¹ÏrŸå>еѵѵRH!EÓûÇÔUÔUÔU ¯K^—¼.�Û8·qncHœ28e0<7ynòÜ^ôÑÿExÙêe«—­ p{áöÂí`¹Ýr»åv¨š[5·j.ÔPÔPÔP@Ùne»•íZ´hÐôQ Âÿ[É�bˆ!¨—«—«—ƒz«z«úþÿ¶èmÑÛ"XõdÕ“UO cxÇðŽáP�jTû|îbÅ‹/V„Àš�5k‚Çx�ñã!°N`�À:puöÕÙWgÃÈ´‘i#Ó 87878~ðûƒßì³vÌÚöØóWnÝ|i ‚ ‚ ‚àyÄóˆçpmеA×ÁãÍ�7?Þ Ú´h?€J­*µªÔ ú\és¥Ï(;¥ì”²SÀÚÚÚÚÚäyòþþttt ÑÀF [-[-Û¿Ð{7,oXÞ°k;k;k;èök·_»ý ñzñzñzÐÀª�U+0Œ4Œ4Œ„òß—ÿ¾ü÷¡ŽPG¨!Ož'Ï“Ã+ãWƯŒ!¥GJ�”à)yJž%nÜüçrÛç¶ÏmA)A)A)pºÑéF§AšYšYšT©U¥V•Z0¢Æˆ#j€ûF÷�îA/P/P/�ßOvÈ#�¼ßïGa£°QØ·¹ÍWðFheeepnãÜÆ¹ 8ãŒ3Ð&°M`›@H}šú4õ)Ü-w·ÜÝrp­ÒµJ×*Áñ�ÿxüG¨Z½jõªÕ¡C×];t§&NMœš€|¼|¼\¬A*hH‰-`ŠåŠåŠå ÐRh)´ ¨EQ‹¢¿ß.x\ð¸àqð|Úóiϧ�ù6ómæÛ PU¨*TA}y}y}9/(^P¼nÄ܈¹vÎvÎvÎ�_5¿j~Up¶u¶u¶…,ï,ï,oHÕKÕKÕ[l±ý?ò% K–0 ž¾zúêé+H~•ü*ùÝy,zRô¤è %%%ÂÁJ+¬ .\€.-\Z¸@ãù�ç7žC-†Z YUYUYU`Ø éocÉ%ó“ùÉüÀK,�¶´¥-Ф…I x!{!{!ƒ“ß�üîäw0Ïožß Ê$”I(“¥~-õk©_¡øjñÕâ« ]N»œv9@t€rÈi‚4Aš 4SgSgSg(#/#/#kkkXµxÕâU‹ÁÐÞÐÞЪt¬Ò±JG8Wñ\Åsáæò›Ëo.‡×:\ëp ̬̬̬  mhÞ7¼oxÈ ƒ ¨Q¿FýõAé«ôUú�iLã�pÂüñÇîøÞñ½ã ›gmžµy¸rä>–è.Ñ]¢ ÖßXcý <´4BöZöZöúý¥Ç).S\¦¸ÀÝÜ»¹wsa[ùmå·•‡Ðæ¡ÍC›Ãws¿›ûÝ\°\i¹Òr¥¦Ó _ª;“-�-�-½yzóôæAnhnhnèÿµ!2dÀv°XÃÖ€¶¹¶¹¶9¹¹¹BñáâÃŇ�Ÿù™ŸAöTöTöôÿh/Š(¢þFÐç<ç9H£¤QÒ¨8àwÏÝã÷Þÿ8{zöôìéðªì«²¯Ê‰ù'柘fUͪšU…•TnP¤³ÒYé,ÈRd)²�…ÊBe¡ïg9*ìö {PVPVPV¶±�máDEI$\üá‵G×]{¼u¼u¼uàûu߯û~XÇ[Ç[Ç„ý ÿ Y¤,R µãkÇ׎‡E1‹bÅ€Ì^f/³‡Å]wYܽ½½4�VøR•ØöŽÞE½‹z!¯Q^£¼FÿÇÐŒf4:Ò‘Ž�8!qBâ0ïiÞÓ¼'888ßò-ß!„ò´÷Ÿ‘ W¹ÊÕ¿ð-oyËï' (P àý®/yÉKÞ¯(L0Á@i¤�4N'�ƒÂË…— /¿oÆ>Ä>Ä>:t<}›÷mÞ·9ü0ï‡y?̃V¬:X�ÚNm§¶ à7Çñoö¾Ùûf/ÜÝuw×Ý]P°¨`QÁG˜ ssþÍù7çÃÞS{Oí=c‡Ž:v(´Õn«ÝV´zkõÖêýI¾_´Ô°Ô°Ô0x¤ýHû‘6äXçXçXk.�ÅD‹‰a⡉‡&çVέœ[ÁÊ•…+ !}~úüôùšî5áKSâ ˜A˜A˜Ad9e9e9ýþ÷²‡²‡²‡�8.q\â8ؽe÷–Ý[à’ö%íKÚ0Ävˆí[ÈÊÊÊÊÊ‚‚܂܂\ˆ’¢¤( Šò‹ò‹ò!v]ìºØu�nœnœn q—ã.Ç]†ô„ô„ô„ßï7±tbéÄÒ�:5ujêTx•÷*ïU¼®ðºÂë ïלU§«ÓÕéð¨Û£n�ºÁã±�Ç> Ò=éžtž[>·|n UÎT9Så Ÿ>|Î:wèÜ!èæ×ͯ›H �°æÞš{kîÁ‘_ŽüräˆÝ»=v;¼jþªù«æPhPhPhQ�¢:EuzŸ7ì›°o¾�õÚëµ×kCúé?¤ÿðÏÏK©„S §`¯Ç^�½0hö ÙƒfCíÓµO×>ÍûPü‰¢E#ŠFÀ©A§�k¦¬™²f ä;ä;ä;|ø÷'1(1(16ר\cs H©šR5¥*<Í|šù4­_´~Ñz333ø íl6Øloÿæþ‡çû_Ï3žg<‡­µ¶ÖÚZ N‡ž= á+ÃW†¯„Þ;¼wxCD�ˆ= ®g\ϸž°Ü¹ÿr¸RõJÕ+U?~®wÞÍvâ4Äiˆ˜l1Ùb²öߨcÿ �.H¤ ŸnÿÂ×¥ÄÞ{ǨžQ=£z�Ö,­YZ3 /}é `@ �€E¢E¢E"´°laÙÂLCLCLCÀ,Ó,Ó,T›U›U›a»ïvßí¾ c£c£cŠ5Š5Š5`½ÏzŸõ>Xæ¿Ì™?È�Ê�Ê�‚ÑX£±Fc�CâÐû\æ ̘7€Ÿoþ|óç› +'+'+&Ú&Ú&ÚPïf½›õnÂþiû§íŸz~z~z~ o(o(oû.í»´ïèÒ?¤t÷ëî×Ýmë´­Ó¶èÍ×›¯7̜͜͜az¯é½¦÷‚ìyÙó²ç�öíÚ;ÀHf$3’A'·Nn�Ü ¥aKÖ†`¬k¬kü›Åoë,©³¤Î’÷³ÐMv™ì2Ù e(Cÿúù�"¤)Žõ=Ö÷X_¨Ö°ZÃj Á«¯W_¯¾ÿüjmÒÚ¤µ '''àLÚ™´3i0`ç€�v‚zè}À÷çÝ,<ùpùpùp�ÿ,ÿYþ3”iQ¦E™pÓà¦ÁM¨žS=§z”«[®n¹º=5zjôT¨°£ÂŽ ;@VFVFVä ä ä @vEvEv¨Nu>â{ê¢fGÍŽš ¼x=ð‚eO—=]öô[ë·Öo �®=ºöèÈbd1²°íoÛß¶?„;‡;‡;ƒlŒlŒlÌoé~2zázázá0$xHð�`Xä½È{‘7„……�GK�–-?aáë •pÇ“�'O–¤ŸÆþ4ö§±’TœSœSœóþ÷‡»î~¸»$5:Ùèd£“’ôbô‹Ñ/Fk:õ—+þQü£øG’ôݵï®}wM’^¬x±âÅŠo÷êÁ«¯”¤¦‘M#›FJRà/�¿þ"I!ãBÆ…Œ“¤”ê)ÕSªKRúŠôé+$)¤QH£�F’”¾!}CúIJ½‘z#õ†$…„„HRúŽôé;$)-&-&-F’îﺿëþ.IÊPf(3”’¤2S™©Ì$©óåΗ;_–¤S§e|ÊxIz { { “¤Ôn©ÝR»IRøàðÁáƒ%éa݇uÖ•¤§'Ÿž|zR’‚‚‚$);;;;;ûÏ�¿¸Bq…â ’´o侑ûFJR£Š�*6ª(IwºûÓÝŸ$)mlÚØ´±’ôðÎÃ;ïHR‚i‚i‚éûÏ�m3¶ÍØ6’ô³êgÕϪ÷?ÏlŸÙ>³½$Ýßÿýý’ô ÑƒFIRÖ�Y?fýøñ¾~~~’´üÅòË_H’tGº#Ýùxí _§ Ñø¼ñyãó�37gnÎ\�l$ɤªRU©*”ö.í]Ú†µÖfXP«ÕjµZÓ©¿\a¡a¡a¡`àbàbàeee¡áÿŒdT?¨~Pý)�R:¥t‚ ºAuƒêÂüÐù¡óCá¹ës×ç®0U6U6UA5‚jÕ€¿¿?˜>9|r85 jÔrúæôÍé “fNš9i&Ü9vçØ�c ?.?.?¸à‚ ¨ªªBè÷¡ß‡~/;¿ìü²3¤ë¥ë¥ëAFãŒÆ�áÇ£?ýñ(ÜÝywçÝ�pÈó�ç!Oð1ö1ö1†D§D§D'X×k]¯u½à@Ë-ü…‘H‘u‘u‘5¼õ{ë÷Öò ó ó !emÊÚ”µ�žž>M}šú4¹¿Üÿÿø¯[–+Ë•åB~�üù5`ÕêU«W­†ë½®÷ºÞ ÎŽ8;âìØX°±`c¨f©f©f}øé«²³ÊÎ*;!ânÄ݈»�1ÿbþÅ�úÕ¾B%¾€™™™ANéœÒ9¥ß¿öâݽ¯º½ëö®Ûú+ú+ú+Ày½ózçõšNýåJjžÔ<©9˜_4¿h~äcåcåc?BÓ˜Ä$0Ùa²Ãd4®Ð¸Bã 0°ÝÀvÛAæšÌ5™kàù¥ç—ž_£F7Œn€ú¶ú¶ú6Ø�±c7 7n2Üê£ê£ê£Pz}éõ¥×ƒÁƒ@ýTýTý0Á` [ØúcôÇè�{O{O{Op p p Ïöží=ÛCÙUeW•]ÁÁÁ ]I»’v%°ªaUê˜H&’‰M+6­Ø´"xºyºyºAÈ–�-![@ª)Õ”jB¡e¡e¡%T/¨^PýýŸu®ê\Õ¹ ºTèR¡ ØêÙêÙêAÏž <¡ô¹ÒçJŸ / / /(J*J*Jú}7*¦+¦+¦CÄðˆáÃ!paàÂÀ…Ðcj�©=¦BKÏ–ž-=á¼÷yïóÞ�Ö ­AZƒ?}ÖK¬—X/ÕyÕyÕyx»òíÊ·+ÿ½ï¥ðe*ñÌ\Û\Û\TÕUÕUÕ!»OvŸì>šNõõÒ¡3Bg¨bU±ªØ�Øð»µ W³šÕ 9H’(M”&J0Zj´Ôh)¤4Ki–Ò Å(F8à¨Qó1FÞÿyN�oø†o€\rÉýl¯B… ¤ÝÒni÷o'P(é�ô@zo¾}øö!,”/”/”ä6“ÚLjóþϹ>¹>¹> —…ËÂAj&5“šxÀƒ¿_!‹�E@¶A¶A¶ÄÇÄÇÄÇ€ÿvÿíþÛáêÒ«K¯.…ò…å Ë‚ödíÉÚ“?¼Û õ õ õøïbÌÚÞÚÞÚÞá|_µ?‰Ã|²ùdóÉ Û%Û%ÛoŒß¿1 ,°ø˜;úÏ_ w‚ïß †ûÃî»? :$vHì�eâÊÄ•‰ûã�«‡©‡©‡AfÛ̶™mAÝMÝMÝ Ì§šO5Ÿ ²%²%²%šîÍç|ÆùŒó¸2øÊà+ƒ!;+;+; � � �> áw�C´£í@vOvOv²2²2²2 ³bfÅÌŠà˜æ˜æ˜ן_~ýùû72ã…^¼Ÿ½P‡:Ôò�‡@7ºÑ dMdMdM€ZÔ¢ЉNtJSšÒüwúhq@q@qAü·P½kGq´ÐB dGdGdG€ïøŽï#Œ0â¿ï3lmØÚ°5Œ¾0úÂè P¼µxkñVPd*2™ ?EŠþ�Ò¥t)d'd'd'xÿ¾±wÜqÇýýä†0„!€n¸G8Â0Xk°Ö`-”n^ºyéæÐueו]WB™Ýev—Ù t¦3�ùãÇIþ¦—Ç_yLϘž1=FîFîFîŸøË(|ñJüL·žn=Ýz`˜j˜j˜ o6¿ÙüfóÇßÏ+›W6¯l`÷O»Úý”6(mPÚà7o„þ…£ GŽ‚#‘G"�DÂ÷ß;|ïÙnÙnÙnšîÅ�Çe¥ËJ—• ;Tw¨îP=z>ôü‡·kèoèoèz]ôºèu�‹o.¾¹øö Û7lß0prsrsrƒ&Û o2\o»Þv½ ×ú^ë{­/ÜÞu{×í]�SœSœS )³Sf§Ì†ÈüÈüÈü÷�GD>Ž|ù‡? 3*fT„èµÑk£×‚E‹ àUô«èWÑp2âdÄÉþ,üd,ÊX”±Â&†M ›/ú¼èó¢¤Ú§Ú§ÚÛWo^½yñÉñÉñÉ�Ö5­kZWÈš=4{(XZZB©”R)¥RÞÿùÝ[ÞÍBLÍIÍIÍ�ˆ;"v@âÓħ‰O!©QR£¤FÑU£«FW…»»;xuãÕ�W7Àê†Õ «àYƳŒgص7joœ•�•�•ÁÓ®O»>í ê^ê^ê^ÿü¼©oªoªoBàÁÀƒ�ÁsºçtÏé U]«ºÖGœ�)|�JüL!SÈ20n6Ül8¤4Ji”ÒèÃÛý_qÝãºÇu‡8eœ2N ^k¼Öx­ÓlÓlÓì?ÿ¼^u½êzÕÁu±ëb×Åðkܯq¿Æ�º·º·ú z�×ð;Ãï ¿ƒÖZ?hýNt?ÑýDw¨4³ÒÌJ3Áh�Ñ£¿ÝJW*]©töYØgaÈß“¿'”Ó.§]NœÌœÌœÌÀ8ß8ß8~œÿãüçë)¯¦¼š&Î&Î&ÎàcçcçcVVV 7Ao‚ÞðÝî»Ýw;�É6“m&ÛÀ×Ä×Ä×Lš64m6klÖØ¬�².e]ʺ€Ž½Ž½Ž=˜_0¿`~|[ù¶òm*•� TUUAò–¼%oÐñÔñÔñ„Þ^½½z{AáëÂ×…¯A'F'F'æ��ÿÝ%Ó†ãŽk8Ü—»/w_¶Ö¶Ö¶Ö ©© S6OÙô|ׯ_m<,5_j¾ÔöÖÛ[oo=ˆ>}*úܸyãæ�› {${${�”�”�”à‘é‘é‘ /·¾Üúr+\|qðÅÁP¸±pcáFðxåñÊã4¬Ý°vÃÚ ó–yË4x�A5V5V5|Í|Í|Í@é¤tR:Á¨”Q)£R@w²îdÝ�poEøöûØïa¯ÿ^ÿ½þ¾;|wønÒlH³!Í á�†¹¹Ü\n®éЗê‹)`V?YýdõèÄéÄéÄÁëí¯·¿Þþñ^+Uœ_œ_œÅ7‹oßõ@õ@õ@ˆë×?®?<Ÿþ|úóé°0paàÂ@xdøÈð‘!\ɼ’y%ó7Ÿÿµø×â_¡X§X§XòÝóÝóÝáÞø{ãï�‡žÚ=µ{jƒúºúºú:œv:ítÚ ”ÚJm¥68?s~æü ÊŒ,3²ÌHh;»íì¶³�>ô¡p‘‹|Æ+ï5Þk¼F¦ŒL™ÕfU›Um컸ï⾋p¹Éå&—›@×f]›umunÖ¹Yç&èèèh:ýWè?Ïm%æ$æ$æÀ™ŸÎütæ'˜0!`T¶®l]Ù”ZPjA)(}¬ô±ÒÇ}ôÑ×txáK÷Å0e²2Y™ v‰v‰v‰nnnžxâùíªÊ©Ê©ÊÁ«€W¯ÀÌÍÌÍÌ G=Žz.J¥‹\op½ÁuØ›±7coèVÒ­¤[ œú8õqê/Ÿ¿|þò9¼>öúØëc`õÌê™Õ3xµûÕîW»áÅÅ_\„g<ã�ý2ûeöK. —†K`¾Ç|�ù3o̼1óàœû9÷sî[+¶Vl-(S.¦\ 4¼ÓðNÃ; _G¿Ž~MŸ•?¦°RX)¬ áІ+®€ªMª6©Ú.¼¼ðòÂKØûlï³½ÏàÈè#£�Œ†–ò–ò–rð¼èyÑó"Øt±ébÓ…÷¯«> Õ<Õ<Õ<ˆ¬Y1²"¸¸¸Ã]ƒ»w  Œ{÷2î0A5A5A±±± Ø¥Ø¥Ø¥éôÂ׿‹™…øÎÞ ½A{ƒàʼn'^œ€™ógΟù!ï!šÅ,fAÑø¢ñEãyÿ íî})Ú*Ú*Ú¾‘�)S4ä¶r[¹-È–Ê–Ê–‚¬’¬’¬H~’ŸäR©¿Ôäáòpy8�GyP”X”X”² Y�,´×i¯Ó^üÀüÀßãU4¥hJÑPgª3Õ™ïï1h=Óz¦õ ØË^öjúlüsY=³zfõ„^7¼nxÁår—Ë].éÓÓ§§O·ónçÝÎCƒ &4˜î·Üo¹ß]]]�?“?“?ÓôQ|¾ ¶l)ØI[“¶&m…à3Ág‚ÏÀ�¦wšÞi o:½éô¦¸»º»º»Bë«­¯¶¾ •b*ÅTŠùù¹x-Š a_\»Ÿv?í~l ݺ)|køÖð­F†F†F†šN'üS“ &L‚}_ô}Ñn˜Ý0»a¡cCÇ†Ž…ü¼ü¼ü<(;µìÔ²S¡òÞÊ{+ï…ò+˯,¿; v zkôÖè­yiyiyiMÕ'0›Ù̆â³Åg‹ÏBzÿôþéý!¢ADƒˆðlƳÏfÀÓ†O>m?güœñ3ØFÛFÛFC�6uÚÔiµ}jûÔöKÉR²”@ÞHÞHþ ž¯„ñÅ\B|ÇáŠÃ‡+PÔ¢¨EQ ˆ;w,îTø¦Â7¾Ñt:áŸÒõÕõÕõýïJIÿýß¼„¼„¼xµåÕ–W[àb…‹.V€e–UXV¦:Lu˜ F›Œ6m«�V;­v‚CŒCŒC 85vjìÔ¬²­²­²Áì®Ù]³»`|Ïøžñ=0hoÐÞ =hMך®5]>‡9Ì�|e¾2_ Y#²Fd�€Ì ™27@z•ô*éU ~vüìøÙµ.j]Ô:ˆ7Ž7Ž7†ÌüÌüÌ|0ìaØÃ°8>v|ìøÚe´Ëh—åë–¯[¾.”ò/å_Êä7å7å75}¶á¯ùâ ˜I®I®I.XW±®b]¢jGÕŽª- Ø—J¯—^/½^�½8{qöbx4õÑÔGS¡sBç„Î Ð{zïé½§Cf½Ìz™õàÅ…^\€èmÑÛ¢·Áy÷óîçÝ!g`ÎÀœ�P0±`bÁD`2“™ †K —.ãdãdãä÷“P ¦L3˜ú½ô{é÷=¥žRO ÚeµËj—}?ûN;Y;Y;Ô Ô Ô  È¬È¬È ŠŸ?-~ …g Ïž�¼syçòÎAnanan!dß;›}2õ3õ3õ!ëfÖͬ›�¿8qþbÐ2Ö2Ö2ÝRº¥tK�¹‡¹‡¹899AÍ€š5À©†S §P*¹Tr©äß\’þ‘ù(E)Jiú, Â?óÅ0­þZýµúCńРà¾î}ÝûºÐ¾SûNí;Ç9ÎqM§>TþìüÙù³á`áÁƒ…p¾íù¶çÛBÏ�ž!=C Ý«v¯Ú½­öZíµÚƒ]„]„]T¤"á¿‹Õª´UÚ*mÈóÈóÈó€\÷\÷\wÈj›Õ6«-$E'E'ECò”ä)ÉS ëLÖ™¬3�™™ ɇ’%‚üSù§òO�J¦’©dïß¦š¡š¡š2{™½Ì´iÒò‹ò‹ò‹ {]÷ºîuP.T.T.ý6úmôÛ€ƒ“ƒ“ƒ˜¾1}cúl´l´l´Àê±Õc«Ç Rÿ¤þIП¥?KèµÑk£×æ7Ï[�à'~Óas™Ë\MŸ5Aø¸¾¸{`ï„:V­*ZUËdËdËdï׸J¦ØÞ±½c{æc›Žm:oß&¾M„‘º#uGê‚û0÷aîÀ]ìBÌŠ„/Ú7{Ç¥›K7—n c¡c¡c¡¡¡Ѐ|„÷ó ÿõ õ õ ¸iuÓê¦lÓߦ¿MªëV×­® “zLê1©˜œ79orQ¸á+òÅ,%õ¿Þ]Rq_å¾Ê}Üó¿çÏ_Ó©„¿*g\θœq°µÆÖ[kÀ–¡[†n }ë÷­ß·>Œ)S8¦ð7…K„¯Î;{§Aà 4„õÖWX_ÒRÒRÒRÀÜÊÜÊÜJÓé„ÿµ!jCÔØØ|có�ÍAÝHÝHÝ~2ÿÉü'sp)t)t)†2”¡šN+‚&}±#°wÜ»»wwï† ;v„»Ãï¿;\Ó©„wÔUÕUÕUáÒ•KW.]�y[æm™·œ£œ£œ£`î�sœûão — Â|±“8þ×áÇ> w3ïfÞÍ„òòrФ5Hk�¦Ó}}²u²u²u`—å.Ë]–ømà·�ßÂ`ËÁ–ƒ-Ák©×R¯¥ �“ÇÉã4�V„ÏÑ?{§ÑÁF„”Ê)•S*ÃÓÃO?=¬éT_‘x≇§_œ~qf�œ=röHˆ^½6z-̽7÷ÞÜ{Ðd|“ñMÆ‹Â%ŸûjF`ïlÕÙª³U’÷%ïKÞÓ”Ó”Ó” k'k'k§ét_µ£ÚQíWV^Yye%ø ÷î7êï©¿§þè—Ý/»_6t5èjÐUÓiA(I¾šØ;mšµiÖ¦D}õ}Ô÷~<üx¸x°ù£Ë~˜ý0û!l|ºñ鯧à7Ùo²ßdtiÐ¥A—`ØŽa;†í…K„î«+`eΖ9[æ,Ôt¯é^Ó~õë¨_G�ÚAí vÐtº’ïEâ‹Ä‰0·÷ÜÞs{CtNtNtÌ5šk4ךz4õhêò=ò=ò=šN+BIöÕ°w:ßí|·ó]ß¾%| œ*@  €£“ŽN:: Ž+å)OA=B=B=âýŸÿmRy©¼T®´»ÒîJ;XÐsAÏ=¡^µzÕêUƒÉ''Ÿœ|¬­¬­¬Å‹=A(�Ä=°¿)Ú%Ú%ÚædÏÉž“ý~ʼn†Q £FÁÙÒgKŸ- Ï]Ÿ»>w…Ñ]FwÝ>}¾üuùëò×Á^ݽº{uá갫îƒÁwß|k5Öj¬²j²j²jšîMA„N°èìö³ÛÏn‡êêj¨´¿ÒþJûÁ§†O Ÿ 7NoœÞ88e|Êø”1¸»»ÿýý×/®_\âÂãÂã¡T¹RåJ•í»Úwµï¾ß.å\ʹ”s°.e]ʺH­•Z+µŒ[ö&ëMÖ›¬ÿóýdšfšfšÂpõpõp5Ì:˜u0 š,j²¨É"ÔeP—A]àÊÆ+¯l„–�Z6jÙ¼+{Wö® ºt+èVÐto ‚ |:bö7÷ îÜü¬ý¬ý¬áí³·ÏÞ>ûãí ü)ð'nÜ.ø/¼ñYr’œ$'ð[â·Äo œp<áxÂñýï¦L˜‹’%-J‚þ ýú'À7ÅßS, — _QÀþ&¯�^½6ÂîàÝÁ»ƒ¡gïž½{öÃQ†£ Gý~ûôRé¥ÒKÁ±ÎÇ:ë êêêêêêÜ~ðˆàÁ#`õžÕ{Vï�¼Çy�óÿ~»ÏÏOˆ¬Y)²Hý¥þRM÷Ž ¿G\Bü@YÖYÖYÖpÆçŒÏØ Ú Ú ‚[¥n•ºU ;v*ì¢+DWˆ†cáÇÂ�…CùÖå[—ÿÍêíé]Ò»¤w�aúÃô‡éÃá}‡÷Þ÷çûw¬ëX×±.øò?ä<í<í<í4Ý+‚ Ÿž�} £d£d£dè9¸çàžƒá@饔ßJ¾•|+A¥âJÅ•Š!jJÔ”¨)pæí™·gÞB¾W¾W¾HAR�~süæøÍ�«N¬:ñÛ¤Ѐ ¬¬ e—=\ö0ôµêkÕ× ~0ûÁì3°f9Ìr˜¦{Cáß#F`Ÿˆú¾ú¾ú>D5‰jÕæ.ž»xîb¸Üár‡Ë ™W3¯f^àäçäçä»ûìî³»¼Ö­ÿZÜn 7ÔVkX­aÐÄ·‰o_¨¿§þžú{ Ì·e¾-ó-())Æó¦é ‚ ”T_ý -?yuyuyupÔqÔqÔ+m+m+mH(›P6¡,ìa{®r•«ÐíD·ÝNÀ i…´B�uë<Ö�à ‡7@;Q;Q;ñ7;xÉK^jú(A4G°OLå¥òRyAÒˤ—I/ÿ{Ë–',OÀŒ3f̘5ä5ä5äÀv¶³]ÓéA>_¢€}bú‡õë†öí=Ú{Àí Ú´A�5PwPÝAuAŽ,G–#ÓtZA„’C°‰e¼e¼e A„χ(`ŸXöÁìƒÙ!òräåÈË0hñ Åƒÿ~»&×›\orýý*ñ[oy¼å1`ˆ!†ÐŒf4ÓôÁ‚ |FDûÄ’�’�’� `@Á€‚à°ÏaŸÃÿõ€r ZÐG4Žh2?™ŸÌ¶æoÍßšÒPi¨4š§4OižãÇ4}t‚ š#dþÄBû…ö í6æ6æ6æ`“e“e“õÿøÀHF2¼n{Ýöº Cï ½3ôürû—ۿ܆‹µ/Ö¾X†húèA4G°OìÙ¾gûží;;;�5’5’5úëŸ÷zåõÊ댨0¢Âˆ °c׎];vÁEÙEÙE1kQ„¯˜(`ŸHÞ¬¼Yy³à•í+ÛW¶P)§RN¥œÐ�+®¸B£o}ÓèøNñ�â;øÝ÷»ïw.Ô¸PãB À 7Ü4}Ô‚ ÿqìIP%¨T�ÿmþ·ùß‚Óc§ÇN�? Ánt£4ìÖ°[Ãnï¼!{Cö†lP_V_V_†Öú­õ[ë¹ä’«é^AøtDûD^ïy½çõ0®`\Á¸¯0^a¼âãµßPÝPÝP 2=™žL6ÜÝpwÃ]PTT„¶´¥í‡ïFá³% Ø'ò¤î“ºOê‚ójçÕΫA¯”^)½RqräÈ¡Á³Ï<…�Â@a럯¾þ9¯(^Q¼Úkµ×j¯²±²±²±šîA„�G°�¬ø—â_Š�U_T}QZÎl9³åL`ÛØö vX‘ŠT„ºëV¬[î w…;¬NY�²:Š·o+Þ�jvªÙ©&ÈBd!²M÷’ ‡“8>²Œ)S2¦@ZVZVZ¸Ìs™ç2ïßÛ­°ZaµÂàûÙßÏþ~6z}èõ¡×p´ÅÑG[[ÙÊVM÷’ ‡ì#‹Úµ+jè9è9è9€Ýv»ívXU¾æØšckŽ…‰ý'öŸØŽ8vàØ8dyÈò�%¨3Õ™êLM÷– Â?' ØGö2çeÎ˰=n{Üö8èŒÒ¥3JsyªW7®n +N¬8±"79nrÜüòÿÉÿ'P;©�ÔNšî5A„¿O°�,ê^Ô½¨{àÜй¡sC�YÈ,dšNUNW9]å4LöŸì?ÙN[ž¶õ õ õ ;v"ìL(˜P0AÓ½!ŸQÀ>’Ȇ‘ #‚m¡m¡m!(C”!Êô¼•kškškÌ3cÌŒ1pkÿ­ý·öÃŽ ;6ìØE½ŠzõÒtÊ?÷öèÛ£o�Bð¡àCÁ‡àQÕGUU…�Ø�Ø�Xˆw‹w‹wƒbýbýb}kÖ,¬<7|nøÜž=7znIû’ö%íûÎö�í;ƒë×3®g@ÝXÝXÝø÷ûU»«ÝÕîaaaq¯â^Ž‚„ s™Ë\¨1¤Æ�CÀð¶ámÃÛ è£è£èz¾z¾z¾ [.[.[�I�I�I°(iQÒ¢$xèñÐ㡨ö¨ö¨öÀÛ�·!oCàÁ�€‡M6}زó³ó³ó!sCæ†Ì ð ôƒÒJCôóèçÑÏ!üRø¥ðK�ëžëžëÏç>Ÿû|.¤.H]�º@ÓgOþQÀ>’eŒ2F öæöæöæšNóÏ9ç9ç9çÁ´¶ÓÚNk �¯_¾†mS·MÝ6TÎ*g•³¦Sþ±œu9ërÖÁäÜɹ“sá|™óeΗ�Ç� À"íEÚ‹´áuù×å_—‡K,9°¦&LM˜š÷î܇Gç�tnºÝt»é“'Ož=ôЪP…*Ý3ºgtOxöý³ïŸ}éËÒ—¥/ƒ )CÊ�`uøêðÕáp½×õ^×{ÁÙ‘gGž ›šmj¶©¤=I{’ö~XøÃ®‚]» à²õeëËÖ= z@ôX¸"pE Üè}£÷�Þš>{‚ð÷ˆö�Š=(zñÕã«ÇW§|§|§|M§úpåš•kV®Ìè=£÷ŒÞâââ [o}¼õ1¨Ú«Ú«Úk:åïYæYæYæ�±¥±¥±%xœö8íqÎ8sàLÈŽÌŽÌŽ„û•îWº_ ÊÜ,s³ÌM°l1Øb0 ˜=`ö€ÙÐxMã5�×€ƒÂAá é�ô@zÀûk¬ÿCçªÎU�«P¡E…Z€­ž­ž­4ðlàÙÀJŸ+}®ô9°ð²ð²ð‚¢¤¢¤¢¤ß4�H"‰ å§å§åŽ“'9NÛš¶5mkBÃå —7\ñR¼/ÁíK·/ݾ=¦ö˜Úc*´¬Ú²j˪pnɹ%ç–€öí=Ú{À(Æ(Æ(ª)ª)ª)àÛ*ßVù¶ ¸´uiëÒ~2øÉà'h.5—šKš>{‚ð÷ˆö�RcScScám©·¥Þ–§'NOœžh:ÕÇã¸Ýq»ãv˜ywæÝ™wáQÑ£¢GE°qÊÆ)§@þµükù×4�ò7´ÐB $�@�VJ+¥• [/[/[zõê „ y†/ó“ùÉü~óówïsÛÌf6:è êxu¼:¤SÒ)él3Øf° J×*]«t-èz¥ë•®W`‚õë Ö°¶óÚÎk;ƒÅ^‹½{Aò�<$�}+ûVöío+L¦ƒ„¹ sæBŽ,G–#^�*”0¢€} Ô-©[R·€þcýÇú�A?O?O?OÓ©>;?;?;?˜Ùfÿ™ýáå�/|ù#¬Ù¿fÿšý�Û<·yns üžïùTÇTÇTÇ ¸(¸(¸üŽùó;¶»lwÙî‚êªo¨¾b�ý5öWHê�Ô!©¼ùþÍ÷o¾‡¢îEÝ‹ºCT­¨ZQµ =.=.=^uxÕáU‡ßïV½\½\½¢öEí‹Ú©9©9©9±#bGÄH|šø4ñ)$5Jj”Ôbbb ºjtÕèª�b—b—b¯u_ë¾Ö­0­0­0(Ü\¸¹p3ø—ñ/ã_,]-]-]¡ÖúZëk­‡½Q{£öFÁY�³:gu Ì5Ì5Ìâ—Ç/�_Ë2–e,ƒh÷h÷hw�žHO¤'ðöÉÛ'oŸÀlïÙÞ³½á⨋£.jpÅAø'dÒh:HIµkö®Ù»fCâÜʼnsa“˜¤éPÿ¢”Ù)³SfÃ’¶KÚ.i æ6æ6æ60Öj¬ÕX+064646ü÷ò¨æªæªæB7©›ÔM‚væíÌÛ™Cƒý ö7Ø¥¢KE—Šs…¹Â\áU«„W�¼¶ymóÚBùÄò‰åAyUyUy¢_E¿Š~i÷Óî§ÝÇŽ'O€M#›F6�øï´úbÿbÿbxqþÅùç!µkj×Ô®`ß¾…} п¥KÿDûDûDû€Öh­ÑZ£ÁÚÀÚÀÚ.%\J¸Ú«´Wi¯‚²ºeuËê«‘¯F¾ — .\†J¶•l+ÙBáãÂÇ…�!J¥ˆR€ÜSî)÷«V¬€RW©«Ô…H‹H‹H 0©hRѤ"¸¨]Ô.j�Ì%sÉ"ëDÖ‰¬–»-w[î‹»w-îjú[%�(`ÿÔT¦2W_\}qupzáôÂéôžÖ{Zïiš÷ï{w/Ðç’Ï%ŸK _^¿¼~y˜Ð{Bï ½Á$Æ$Æ$æÓçÈZ—µ.kôLí™Ú3†­¶nØ:è–Ô-©[Ò‡·/ÂçC\Bü‡ŠæÍ+šoº¾éú¦+غٺٺi:•æXØ[Ø[ØÃ´-Ó¶LÛ…5 kÖ€e²e²e2HOOÿô9R†¥ KµªÕªV«¨.ª.ª.‚J©Rª”ܼ Ÿ1û‡²ÏfŸÍ> t&èLÐ�³Ìþ1Ü:¹urë¤étš—y"óDæ Xa¸Âp…!äääÀ�?þVã¬ÆY�ÓtJAJ21û‡RV¦¬LYùþ¦¸�³�³Ígü€ï¿Í¤£IG“Žð£ÿ�þ?úƒ¡‘¡‘¡,™²dÊ’)�8+qVâ,M§¡$ìJ¶J¶J¶}S}S}S0H0H0HÐtªÏ�ázÃõ†ëaÂØ c'Œ›<›<›r|äxPä)òy°Ôn©ÝR;HX•°*a•¦{C>¢€ýMÅÅÅPؤ°Ia0ò4ò4òÔtª’OÑJÑJÑ z¬è±¢Ç èªìªìªßæ¾Í}›CPHPH�߯önµz£££p�ì:Ùu28 sæ0 ­ ­ ­ ¡}Cû†öàÝÖ»­w[°k?Ö~,`…V ¯¯–-'ZNùeùeùeHÏKÏKσ«1Wc®Æ@å•T•ªUªV©D‡D‡D‡ÀËZ/k½¬¥é³%ŸQÀþ¦÷÷wPÙ©ìTvbï�M>Z>Z>ºhwÑî¢ ýœú9õs‚Uú«ôWéÃ�§7žÞx \àþÍ`È‘á„$�@�O>ùÀas¸ÈE.¾ÿ˜¬XV,+Ù7²odßüíV¦2•¡xLñ˜â1�©—©—©w¶ÝÙvg\7¼nxÝš­m¶¶ÙZ(µ«Ô®R»4w~ás¢¥é%MA©‚R¥ ¸mqÛâ¶`tÎèœÑ9`4£­ét_YCYCYCh«n«n«GGGØpcÃ� 7 ÿjþÕü«Ð|Kó-Í·€ì ì ìà'̳H¶H¶ŠlŠlŠl H¯H¯H¤Òip“›ÜJSšÒ@E*RäMäMäM Ð Ð Ðà7 ªP¡©µÔZj z]õºêu{¹½Ü^õºÖëZ¯+xyxyxyü£È‚ðÅìoJS¥©ÒT ³Jg•Î*0ú>ú>šNõõhèÑУ¡(g(g(gÀêú«ë¯®¹urëäÖ�«z¬ê± ÍÍÍ>Þ~�ƒŒƒŒƒ`yøòðåá�ã’ã’ã:gtÎèœ�VsZÍi5ôËè—Ñ/ä�CxšxšxšÀŠû+Òjiµ´š×h^£y �ÎJg¥³`¬e¬e¬,;Xv°„úùõóëçCÑ¥¢KE—@/X/X/t[é¶Òm¥é³ Ÿ±âß´¿ùþæû›CÔѨ£QGa†Ñ £FšNõõ ݺ3t'¬hµ¢ÕŠVP¯¸^q½b0ÀüóAg“Î&�MšN)§ &qüMYR–”%�ñBã…Æ 5�F¨<°òÀÊaºùtóéæ<7xnð\Øxgã��w ÿçüŸóÖtJA>QÀþ¦ìÄìÄìD0n8Üp¸¦Óï8ë:ë:ë¬K³.ͺQƒ¢E ‚•æ+ÍWšCŽwŽwŽ·¦S ‚ð1‰ö7euÏêžÕŒ¾5úÖè[M§þ—Ý »v/`†Ï Ÿ>�¶4miÚRX:éü¥ó!ã—Œ_2~ÑtJA>QÀþ¦œ9 r€ñã;Æw4�Fø#Ö Ö Ö 0=~züôx�ºH]¤.°¸ìⲋË›ùoæ¿™¯é”‚ |QÀþ¢‚9s æ@îœÜ9¹sÀô•é+ÓWšN%üÓ Ó Ó ˜¼vòÚÉkÁÄËÄËÄ ækÏמ¯ ¯[¼nñº…¦S ‚ðOˆöåææBþùüóùçÁ¼²yeóÊšN%üU†- [¶„‰nÝ&º�K°K°K0Ìo8¿áü†ðlí³µÏÖj:¥ ‡(`Q¡ºP]¨†b—b—bÐë ×A¯ƒ¦S —^”^”^Œ|3òÍÈ7ÐÀ®�];XÒyIç%�á^å{•B‰ Ø_¤š­š­š òúòúòú Ø¥Ø¥kÒ•XZZZÐïT¿SýNA×>]ûtíË}—û.÷…kf×Ì®™ç9ÏyM§áÿ" Ø_¤Z­Z­Z ²lY¶,ä×ä×ä×4�JøPò£ò£ò£Ð©~§ú�êÃÐÈ¡‘C#aSò¦äMÉp2ádÂÉ�¼%oéÿ˜†/EKÑR4-(ZP´àÿcï>㢸úÿÿ¿v—¥,½#UQ,ØÐ¨ÄÞ»±ÆÞK¬±÷Ø±×Ø5*–Ø+ö.bˆˆôÞX¶ÌÿÆ/^ø¿’\ßÍ¢™ç.³gÞgÎÊÇ™=sFß½‰þ]Ä¥¤þ u/u/u/�yɼd^ K�%Èô�Jô±H–H–H–@C¡¡ÐP O O OX=kõ¬Õ³ ç]λœwÐeX—a]†�,W–+Ë…ÃA‡ƒAz�ô:éu`È»!<ðÀCß½‰¾lbûƒÔNj'µH…D²Å²Å²Å@#ñ×Üé™ ¨U=ªzL5�j:Õ–ÍZ6kÙ,ÈÍÌÍÌÍ« « « ˜Ð|Bó ÍÁæ;›ïl¾ƒ5[ÔlQܓܓܓôÝ‘èË&^BüƒÔ~j?µÈÌdf23�©d*™Jß©DŸš�ÒGé£,º1:¨^P½ z0lȰ!Æ@ôÁèƒÑ!Ô6Ô6ÔŽ8 ïÔ"Ñ¿ƒXÀþ ÝÝÝ0(cPÆ  HÕRµT­ïT¢OM·E·E·Bk†Ö ­ Ï»=ïö¼¤ÏNŸ�>»h;mememeض'lOÄçÆçÆçê;½Hôe ؤm¡m¡mšPM¨&˜ÉLfê;•èS»?ãþŒû3`lðØà±Á™™™ýûÛ?Nœþ8N™�2;e¦ïô"Ñ—M,`ÔqŽs˜Ìd&2dÈôJô©y¾ñ|ãùfdÎÈœ‘ �ß4~Óø ˜M6›l6ù×Û«¶«¶«¶Ãî ÝA»ƒ ylòØä±úî…Hôe'qüQräÈõBôO³7³7³7ƒ `бtÇÒKÃ9«sVç¬`gß�}wö…³³3È^—½.{Ü»xï⽋p&òLä™HèK_úùÊ|e¾òÛç·ÏoÊÕÊÕÊÕ�æšæšæ I“.&]„ô2éeÒË€²¹²¹²9(¯)¯)¯AþìüÙù³AõXõXõ´åµåµåAÓYÓYÓt+t+t+@6N6N6dQ²(YH $0i4Òh$˜ú˜ú˜ú€¢¾¢¾¢>˜M1›b6ìØ °Nw�î:Ý«®V]­º‚â±â±â1(âqŠ80\`¸Àp0†1ŒÑ÷(‰þ­Ä&ý V‚•`%@7ºÑ h¡m¡m¡…óþçýÏûÃ:å:å:%„x‡x‡xÃêàÕÁ«ƒ!ªDT‰¨�¹>!OÈò ªyTó¨æpþüùóçÏÃZj=¨Š×Š×Š×àçç_uÿªûWÝÁ5Ë5Ë5 L‚L‚L‚;ì°ÓwoŠ!p€œ93rf@¤E¤E¤ÜšvkÚ­iðxÊã)�§€AmƒÚµák߯}¿ö…FM5iÔv;ìvØ�¸²‰è7‰g`�ü¦ü¦ü&‚�`º]€.¸ÈE>â5~YsYsYsèÙ¿gÿžýA1M1M1íÿ~ßË“/O¾< ªzªzªzÐèH£#�Ž@aïÂÞ…½a䎑;FîÇTÇTÇT(T"¨DñB¼K –,…Ø ±b7À�%w–ÜYßLüfâ7Aš-Í–fÿß9Š;a‹°EØoZ¿iý¦5›{lî±¹ð|Êó)ϧ@¹§åž–{ ÃŒ† 3‰�ÄG&Ö&Ö&ÖÀYÎrVß½øŒ$“L2˜cŽ9P™ÊT*·®ÜºrkÈú1ëǬáÉ�O~|ò#œ›rnʹ)pÁë‚×/¨mXÛ°¶!´³lgÙÎ’’’øtW@DŸ±€ýA5 jÔÝcÝcÝcÐÎÕÎÕÎ-úù£S�N=:G‚Ž /S/S/SÈIÈIÈI???({µìÕ²W!Ð2Ð2ÐÁA!X‚¡²Me›Ê6ð äƒ’J‚ñCã‡Æ¡[›nmºµNr’“EûM[›¶6m-<øéÁO~‚‹^,z±.Ý»tïÒ=pmîÚܵ9YYY@»ýíö·ÛÞ7½ozß®r•«P0¥`JÁØÖs[Ïm=áÆ¬³nÌ˲–e-ËBÝNu;Õí7ûÞì{³/¼<ðòÀË Ï’gɳ ÕƒVZ=€„€„€„8owÞî¼” +V. ${%{%{¡ÚÃj«=„ã¹Çs�çB;Ãv†í ÁÃÐÃÐÃðÓ�_VtVtV4ô?èЂ˗ . ÕFW]m4Ì|4óÑÌGàÙÛ³·go�ܕܕÜÕ÷§î f�=ö`9×r®å\¨G=êu²ëd×Ɇç¾Ï}ŸûÂѦG›m SB§„N …û:ìë°šo~¼ùq0:jtÔ訾;#Òñ>°?HþXþXþsÁ\0Ý"Ý"Ý¢¢Ÿ¿Ÿ=v¥Í•6WÚ@ÙgeŸ•}FUUa¬þfõ7«¿�œ9'rN@ئ°Ma›àžîžîžÜòÝòÝòÁ¼¾y}óú�á�á�á W¯„_ a’0I˜ôë\¶'lOØžÏÛž·=oƒ»›»›»øíòÛå· \Ž»w9ÁîÁîÁîõ4êiÔS�,—,—,v°ƒ Ø­Ø­Ø V›­6[m'''¨ñ¸Æã�!t`èÀÐ�èèè�65ÚÔh(G(G(GÀæK›/m¾k,ÖX¬�cã��?64å4å4åÀæ¢ÍE›‹ Þ¬Þ¬Þ 9—s.ç\ÍrÍrÍòO7n¡¹¡¹¡¹0£úŒê3ªC„i„i„)L}8õáÔ‡0æî˜»cîB©¥f”š‰‡D¼T¥7Pyl展Ç Ïž3`œgœgœ\àôýéýƒ ƒ ƒ øš¯ù¨0 Â€  pkàÖÀ­0gÌœ1sÆÀ˜�cvŽÙ åû”ïS¾�¾S‹þ)âØ$¿*¿*¿ Âa‰°tctctÞÀ)EŠˆ!†þsíÿýôds˜Ã ¤ éB:`‚ & <ž Ï~c‡J”(ÿD@ 4 Ün ·Šþþç;úË ÛíiOûš¨¨½ zô†˜�1c6‚Ûj·Õn«á»®ßuý®+”3(gPˆ%–X’…d!ùƒö{Ò“ž •„JBwÜqÿxãtÅæŠÍŒŒŒ†!M†4ÒºÇu�ë÷Aáý)ÊÎÊÎÊÎ�Ú;µwjoÐÝÒÝÒÝúçsXo³Þf½ FžyräIhÜ$¸I0,k±¬Å²ðòöËÛ/oëûh‰þ)bûƒä-å-å-Aç¬sÖ9ƒF«Ñj´lðË™…à(8 Ž ®§®§®Q5¢jDÕã†Æ �B‰¸q%â@óVóVó4�D#ùõþ´UµUµUAÛOÛOÛt‘ºH]äïçÓ–Ö–Ö–mEmEmEÐÕÑÕÑÕ)jG·Y·Y·4�4�4�@{J{J{ t'u'u'A“¬IÖ$ƒô‰ô‰ô dûfûfûBAÿ‚þý¡¤¼¤¼¤¬³¬³¬³ F·ÝjtƒG:ép6*lTB]¡®PtCuCuCA;A;A;¡(gú˜ô1éc`¿û~÷ýî�����ð&‡¼ªÿªþ«ú°÷Û½ßîý†ÝvkØ-ð·õ·õ·å?—Jÿ/ù!ù!ù!pa÷…ÝvCÈè�Ñ!£�e,cÙßϳ?fÌ~¸2ôÊÐ+C!¿j~ÕüªÚ"´Eh 8|8øp0d-ÏZžµü´cuÅꊨmÔ6j›¿Ÿï¿¥®O]Ÿº6ÿ¼ùçÍ?Ãææ››onQý¢úEõƒ‹ò‹ò‹rÈ–dK²%U5ªjTU8dwÈî�Äî�Ý»ÿãç2¨cPÇ t^ÛymçµÐú‡Ö?´þ6FlŒØiÇÒŽ¥ûøû/bûƒLº™t3é†c ÇŽ…œ–9-sZý\r@r@rr®ä\ɹÇRŽ¥K�3FgŒÎÁ�Ø!±CbA‘¨HT$‚ì¶ì¶ì6ä-É[’·²Çg�ÏéýÒû¥÷ƒ¬�Y;³v‚|‰|‰| D׊®]ë×¹Þ/]”‘‘Ò5Ò5Ò5ð2øeðË`333ëÖ-¬[@ì�Ø!±Cà¡ËC—‡.`ûØö±Ö6ºê€IDATícˆÛ·'nT¨Y¡f…š`Òפ¯I_Ø;xïགྷÁïk¿¯ý¾†f{šíi¶¶>ßú|ës¼x9ð2ÂsßâââàöÃÛo?íííÐj 5…°Êv•í*[Hì‘Ø#±¨Ö©Ö©ÖAêýÔû©÷Ýέ´[i·Ò 0²0²0ò¯çú=!>!>!>ííí }êö©Û§.hçkçkçÃõC×]?¹‡sçãŠÆ�+ÂË-–[,áÙºgëž­ûø¹Þ“øH|$>Ð~Yûeí—�guÏêžÕáØ¡c‡ŽBœ~ÿ…¿ûƒŒ¯_7¾ƾƾƾ�¾3}gú΢Ÿ m…¶B[°P[¨-ÔÐaP‡AA¹Yåf•›RG©£Ô„:B¡,]¸táÒ…€5ê�¹�}ìƒIÕ&U›T XÃÖ€t™t™ô7ÎÌ;™w2ï“3&gLΖ°„% u•ºJ]�Ë\æ2üÔï§~?õrÈ!$i’4Il™¿eþ–ù@G:Ò zô2è~ü:øu(šv.ß.ß.ß}<ûxöñu¶:[� Xb‰%øøøi¤‘µÚÕjW«H*I*I*í×­¥[K·–°tÕÒUKW�4Wš+ý�y8þáø‡ã!ënÖݬ»Ðìq³ÇÍ-hA‹?ßž$\. ›®6]mºBD…ˆ  ùPò¡äC@Yd�-¶Øªªª�×8¯q^c°îiÝÓº'ä·Ëo—ß ºt-è Ö­'ZOŸé>Ó}¦ƒû÷ î@qGqGq: ÃöÛ?l?Øœµ9ks¤]¤]¤]ÀÄÓÄÓÄ“¢õ‹‚6m Ú@fffff&Èíävr;°nmÝÚº5HKKÿùq303030ƒo„o„oX¨X¨X¨€f‘Í"›E­C ú¢?ešû4÷iî‚Ô<¨yPó¢×oî¼¹óæNA¨nQÝ¢º… œÙxfã™�úNû‹¢…hAXn¸Üp¹¡ ì|¸óá·¯ù Á‚7 B«Ñ­F·-{—ï]¾w¹ ̨0£ÂŒ ‚°¹psáæBA¸dxÉð’¡ ´yÒæI›'‚Ñ%¢KDA¸ríʵ+סÍö6ÛÛl„ˆ#~ŒøQ®¾½úöê[Ah³¡Í†6!2/2/2Oâ[Ä·ˆo!�4�4�4‚p3èfÐÍ AèT§S�Nu¡ûµî׺_„{y÷òîå Âe£ËF—�¡íú¶ëÛ®„ÇO?yüD†úõê/Ó §N7„]cw�Ý5Vú<íó´ÏSAxØúa뇭ÿïþ§nIÝ’ºE†×^gxAh°¦Ášká\À¹€s‚êêê.í#ÛG¶�„«õ®Ö»ZOþß%cAh?³ýÌö3áló Ï6„ÜŹ‹s Â’óKÎ/9/Ë.o¸¼¡ LÉœ’9%S.{ùÛËß~„�K„A˜Ûrn˹-ápÈá�Ã!Ÿè3(Ò;ñâŸdùÎò�å;ȼ›y7óƒû„Jn/¹½ävX»ríʵ+Á§‰OŸ&Àp@ß©¿<ïç¨Äwˆïß<ªyTó¨öw0šÑŒ÷î+ÜWÀ·ã¾÷í8ès½Ïõ>×áôºÓëN¯uuuÈ?“&ÿ èÒuéºt(ûºì벯A¥ŒRF�î˜î˜îx_ò¾ä} ”‰ÊDe"hÚjÚjÚòŸI3ïo,wé0Òa$¸åºåºåBÍù5çל_t?a™Ëe.—¹ ¹I¹I¹I`jejej&÷Mî›ÜÛ0Û0Û0赢׊^+@‘¢HQ¤ÀÍè›Ñ7£ÿïîÛ²d;*V*¬T>?ûüìó34íÓ´OÓ>PÖ»¬wYoþ³Ì~~z~z~:0�� ,jGæ!ó�y@Èó�ç!Ï!Ô:Ô:ÔF.¹däðµôµôµ„Ýßïþ~÷÷ }ª}ª}ú7ÆÍ 'œÀÍÃÍÃÍÞÖ~[ûmí�ûÙâ%Ä?ÉZ°¬ÈÐeè2tE¯—¸\âr‰Ë¬÷^iJSZß©¿@íhG;Ð\×\×\ùkùkùë�ØþûE›3È ;ÁN°·l·l·l�.”.”.„„2 eÊ€ô¼ô¼ô<Є&4¡è¶‡÷¿Ð 0Àà¼þË¥ä_ùå’¬ð@x <øàõ÷ÛÿÒŽ¤®¤®¤.EKZý×ìNùùùÐ\Ð\Ð\€¸q âÀ–[vlÙš]š]š]à™é™é™ —\>pyÑ~„SÂ)áÔùßï¿ h@Ñ¥Âÿê‡dƒdƒdÄ=‰{÷b~Œù1æGؾ?|8¼®ýºöëÚ`pÉà’Á%N'„øäßÊ¿• êêêüg�KÑ—E<û“¬Ï[Ÿ·>¦¦¦ŸpG]éJWx:þéø§ãál©³¥Î–‚÷÷‚?0í\Ø'ìö�æ’æ’æèÖéÖéÖñû¿(?3ÒkÒkÒk`9Îrœå8H­šZ5µêGÜÁ/…å}a�¼–¼–¼†¬Y-²Zoxð6´6´6üàøþr»$H@ò�äÉ7€~øùä“’Á’Á’Á­.ÿþõ~’~’~@}êS¿èõ÷…ì? )¤ðƒvÞW\qÉlÉlÉì¶¿ÿ_ž$nãeãeãmBÚ„´ �vß¶û¶Ý·àééÿád E…èýßÿs ü>ÿ`3˜¢÷~i�0“& L€³©³©³)4»ÓìN³;0:rtäèHXb±Äb‰\7¸npýï_êŒÔ©3À~•ý*ûUñs!*VÄö'9å9å9åAú�ôé7@3V3Vó ž¸Ú(´Qh#øyÚÏÓ~žÉÉÉP (P(þï÷gdededÁ²øeñËâaÕ•UWV]|ðÁGßGñï“ZH-¤Påx•ãUŽÃ“QOF=:s�¹Îüï·¯(£(£(y5òjäÕ€'러²N\=qõÄU(³üÍò7¡Z‡jªuÅAÅAÅAxpøÁá‡áݽw÷Þ݃¼cyÇòŽAFéŒÒ¥!Ñ$Ñ$ÑrvåìÊÙñ¹ñ¹ñ¹�x,ñXâ1ÈuÌuÌu„d§d§d'°²²‚g+ž­x¶^¹¼ryå‰Ù‰Ù‰Ù�+Ë•åÊàí¼·óÞ΃ôZéµÒkAÆáŒÃ‡!ïyÞó¼ç�Ù#³Gf�¢Ÿ¹¹¹‚_/¿^~½ f™šej–�rGË-w´g´g´g ¥rJå”ÊEÓÒSߤ¾I}ÉÇ’�%ƒœr~Èù—$.I\ §N%œ‚Üæ¹Ís›CÂÝ„» w¡rÕÊU+Wã—Æ/�_Âýˆû÷# épÒá¤Ã ^«^«^ ô¢½þú¸e¯È^‘½Þ¼)xSÕ:VëX­£¾?­¢OE6ûúò¹ÐöÕöÕö…K}.õ¹ÔêZ×µ®k O…§â#>†äÜžs{Îí�wïÞ9ÀØÁc� ¦¥LK™–IUIUÉÿ8ã0ñ3ñ3ñƒ'矜rÂaŠ0´žÖzZëi q•¸J\õ}4ÿ>'''8—y.ó\&¸]p»àv':Ntœø×Ûu´q´q´»4»4»4ȪšU5«*Xݵºku:ÇtŽé޾޾޾à•ì•ì• yGóŽæS#S#S#(X>°| xôðèáÑt�º@] ”TrPÉAà4Âi„Ó0èlÐÙ 3”t+éVÒ \K¸–p-5 kÖ0ƒ3g ΀QG£ŽFÁø‰ñã'P²qÉÆ%ƒÍQ›£6GÁå;—ï\¾ï5Þk¼×-á¥T*¡Ìˆ2#ÊŒ7[7[7[0(cPƠ̯ûŸ<ÿxþq(´-´-´…R?”ú¡ÔàtÂé„Ó (|Qø¢ð8ìqØã°\×»®w]† C…¡JD•ˆ*îÇÜ�¹ßž¾=}{B¹fåš•kIý“ú'õ•¿Ê_åæß˜cþ X ³f5Œ¢K«ÒE‡‹ í«´¯Ò¾‚ŽÞ½;zƒ�•�•�•¾?­¢�Nß³H>7É’;$w„Á©ƒS§ ›ko®½¹öñÚÏŠÊŠÊŠ„ñgÇŸVZ6nÙ¸ecA¸½èö¢Û‹¡°aÿÂþ‚r6älÈYA8";";"„ãÁǃ� Bª*U•ª*joCå •7T„ïäßÉ¿“ ‚®µ®µ®µ „M›6YŽŒ:2êÈ(Ar r r„Ôá©ÃS‡½?æLÌ™˜3‚p¢Á‰'‰'vœØ! ïÞ%¼Ó÷h9YòdÉ“%a¬0V+BêÓÔ§©Oõ�JôOyÕóUÏW=aXûa퇵„'Ûžl{²Mß©DŸšx ñO2 0 0 £¦FM�šBÆÕŒ«W?^ûFFFFFF`~Ìü˜ù10õ2õ2õ[k[k[kЩt*� žÛ<·yn%&•˜Tb\;~íøµãØ8°q`ã_·+ÑJ´-¤ÏIŸ“>æäÌÉ™“jgµ³ÚTUU!ýEú‹ô�1(cPÆ Xš¾4}i:888CRrRrR2¬H_‘¾"ò_å¿Ê¥ïQ�f=šõhÖÜϸŸq?+\W¸®p…ôUé«ÒWé;�èSy³öÍÚ7kaÕËU/W½„&‹š,j²|ûûö÷í¯ït¢OM,`’ÂBa¡°›¯l¾²ù â6ÆmŒÛøñÚ7r2r2rÇ'ŽOŸ€}iûÒö¥¡t‡ÒJwÃ݆» wC›+m®´¹å•[Tn8Žuë8"²"²"²~£á’”¤$è2u™ºLH‘¥ÈRd6?l~Ø|ð}âûÄ÷ xÅzÅzÅBÄðˆáÃáEÔ‹¨QPõBÕ U/@Ù¦e›–m ÷,ïYÞ³„L£L£L#}� ÈÈÈÀ …ƒZööö0×®ÿ\xÛÿmÿ·ý�Ç<æ±¾ÓŠþ*á¼p^8÷4÷4÷4°àÞ‚{ îAí„Ú µ ]Z»´vi?¢ÏƒXÀþ$©‹ÔEêî~î~î~ù4òiäß¹oå÷ü2›Kè+ôú‚ÄAâ q€ðÜðÜð\X[{míµµápàáÀÃ�ðÜü¹ùss�ØKì%ö¿nNÈr…\°�±�±��yÊyÊyJH™>2}$ wî8ÜÎm;·íÜ6ÐÔÒÔÒÔ‚tEº"]—Z_j}©5¼ {ö2 Zg¶Îl� ¦·Mo›£ÅS͂͂͂atÜè¸ÑqPa`…�Â쓳OÎ> §ìOÙŸ²‡B]¡®P÷÷÷'úgäLÈ™�3vXí°ÚakTkTkTÐ)­SZ§4èiÙÓ²§%Èýåþr}§ýSÄûÀþ"×ó®ç]ÏÕÉW&_™ ÚÚÚ s�9È>ÂÞOS¾Îu®�èD'¸1áÆ„ zFôŒèP7 n@](ÜR¸¥p <íñ´ÇÓ¿ÑNYÊR”ϔϔÏÀä‘É#“G°2heÐÊ ˜è8Ñq¢#\éu¥×•^ÐPÿAý�KC—†. ¡y¹æåš—ƒ’-J¶(ùáMU©ÊÇœ¾þ‘˜8š8š8ÂÀý÷Üåg–ŸY~&잺{êî©’’’ ÝFwÝm4TÔUÔUÔ�Aƒ6mô�^T0£`FÁ ¸izÓô¦)’’’€Ù(³Qf£`Ú–i[¦mŸ“>'}Nþýý‰>Obû‹JV+Y­d5HKHKHKe}e}e}°³³ûëíæ®É]“»¢5Ñšh ¤UL«˜VÞX¾±|c †W^a8ûûûÀžˆ={" Þ2Þ2Þ²hí·oß¾}ûâÎÅ�‹;ٱٱٱð¦Õ›VoZÁ¡¡‡† wûÝíw·H¼%ÞohÞµy׿]¡´giÏҞкc뎭;ÂöRÛKm/eú”éS¦xyyAõ�ÕwVß ²u²u²O¸hë_%õ‘úH}Àÿ�ÿ!ÿCEÏ“:îuÜ븬ºµêÖª[à±Ôc©ÇRhÛ°mö ¡Â~¨ð˜Ô6©m"®äðéÜç>÷!;3;3;î~÷û»ßÃiËÓ–§-AÙWÙWÙÚ×o_¿}}h¤n¤n¤.Z“Tôï&y?›CßA>7y²`úÒô¥éKÈMÌMÌM�ŸÎOç%-JZ”„¼ô¼ô¼tPe«²UÙ`hh6'lNØœÉ*É*É*PPP€tïtïto „B@¡P( 0¿n~Ýü:�@ ú•?Ál Ñ.Ñ.ÑÎU?Wý\u¸QòFÉ%AqHqHqꬨ³¢Î ¨]ºvéÚ¥ÁÙÅÙÅÙd–2KÙ_XíþßN=\=\="�#�#�!¤KH—�.pÖýY÷g��£�£�#4éߤ“þP?¢~Dý°b5Äjˆ¾Ó‹Š±€ýEï'CÌ2kȬ!à7Èo�ß h߬}³öÍô�NôW¥G§G§GãèGÑ�¢áZ™ke®•�øÛñ·ãoƒÃp‡áẮº®ºÊï*¿«ü.p5s5s5óXóXóX 3�é¬ïÞüó„GÂ#á¤oOßž¾¢GF�Œ OK>-ù´$<¹üäò“Ë�Û-·[n7ðR{©½ÔPKý-õ·@ÅòËW,¦UM«šÃKÓ¢âE,`Ónùnùn9ÄnˆÝ»¦ š2hÊ }§},ººº�8#qFâ x4ûÑìG³á±ú±ú±^½xõâÕ PURURU‚Êû+ﯼJÕ,U³TMðŽôŽôŽç¹Îs�ç‚éPÓ¡¦CÁ¤¡IC“†`ÐÌ ™A3ŠÖ0,nö°‡=Pؼ°yasÈï“ß'¿äÏ=ž{Þ­y·æÝ—…ËÂeðöÛ·ß¾ý’Ü’Ü’Ü@¾X¾X¾Jî+¹¯ä>¨þ¬ú³êÏÀw¿ï~ßý`ÝØº±uc�($ ÉXaF$ú�øØßäó�Ïw>ßÁ�¾7úÞè 9«sVç¬ó1æcÌÇè;�èï’úKý¥þà|ÅùŠópÆgÀ#ß#ß#·^Üzqkp—¸KÜ%à9Âs„çx{úíé·§!d`ÈÀ��PèPèP膡†¡†¡`>×|®ù\(áRÂ¥„ Ø]³»fw ¬úXõ±êVVV`ÖØ¬±YcPLQLQLÓ¦L€Ñ$£IF“À Ý Ý  ž<1x2 ™…Ì4 šMhohoho€ÚWí«ö…££#P¾Q¾Q¾�¼½y{óöB®*W•«‚Œ2@FvFvF6¤¸§¸§¸Câ™Ä3‰g ¯t^é¼ÒPx¡ðBá0íaÚô¸mqÛⶪª«ª«ª¡â©Š§*žÇšŽ5k‚™`&˜ ¹+¹+¹û·‡E$Ä3°¿-ù›äo’¿�©¥§–žZ¦O5žj ^ó½æ{Í×w:ÑÇ¢.P¨ àÌÍ37ÏÜ„C•U>Tšæ7Íoš�çvžÛy.˜l6Ùl²xÈCB~Ïüžù=!¥]J»”v�>>}|úxHY—².eDï‰Þ½§h²NŽ"G‘£€œ…9 sB¾{¾{¾;h»k»k»S´¨o(¡„¨@à OxT¦2•ùÏ"ºÿY•>�tÒ ,°Æ2–± —Ê¥r)(f(f(f€yœyœy˜/6_l¾ìÙ7²oîîî`§´SÚ)Á&Â&Â&ìîÛÝ·»_ôªHôO ØßµšÕ¬†üðÿÁ*DWˆ® Ý:vëØM\Dô³—ê�ê�ê ÛØÆ6 <2<2<†xñâ 5·×Ü^s;ð_ñÕߨQ€N«Óê´ ;­;­;]4ù¦ðJá•Â+ \¯\¯\ªªª é é éšMŠ&´5µ5µ5Á   dÃdÃdÃ@~N~N~ŒË—3.ŠaŠaŠa Ï“çÉó@z@z@z¤½¥½¥½AzCzCzƒ¢UåE¢bH,`É‹#G,àÁÜsÌ…ùòùòùr�Œ�Œ�ŒÐw:Ѷ“�ì„ÐÑ¡£CGÃúë¬N—�.;]†¡—‡^zœlœlœlôV$úwWâøHª9Usªæ �%<‚„ó çÎë;•è�R%©’TIpðÎÁ;ïÀ’’KJ.) C†4 �É{&G,\"Qq"NâøHœ~túÑéG°î`ÝÁº<Ëy–ó,§èKQñ”�� ›;n#ĥǥǥÃxÏñžã=¡Êü*ó«Ì§è»&‘HTlˆg`‰qsãæÆÍá«…_-üj!?~ü„ªBUA¼Ÿ¥øøåFï{ïî½»÷f �1tÆP�?”?”?„ùç_œª\ªr©Ê% 6µW≊%±€}duRë¤ÖI…„A ƒAÔØ¨±QŸà‰Í¢?§ ]A»‚v°·ÃÞ{;ÀšŸÖü´æ'h=¹õäÖ“a܃qÆ=»Rv¥ìJé;­H$ú#ÄI™�.¤ é0/w^î¼\(ù]ÉïJ~}Nõ9Õ甾Óýû$&&†“Nn8 )¦)¦)¦0²õÈÖ#[Cù˜ò1åc€” „¾ÓŠD¢?C<ûÈ$6‰ 4Ó4Ó4ÓÀ ¿~7ü «vVí,ñRÔ?æ�áÆ0#aFÂŒPÔSÔSÔƒ¹�ç>žûÊkÊkÊk —Hô Ø'Råa•‡U‚Ùf³Íf›áºåuËëâ⯟LÁë‚ׯáç3?Ÿùù ¬vZí´Ú ÚviÛ¥mg0Î`œØM¶›l7YßiE"ÑÇ °Oĸ³qgãÎÐìM³7ÍÞÀ¯ ^¼@­ŒVFë;Ý—#Ñ'Ñ'ÑÇ.Ž] ×\pýLršä4É Úßm·ý]�[É­äVúN+‰>&ñ;°O,·^n½Üz0õÖÔ[SoA»¼vyíò ©¼©¼©\ßé>Cu¨CxPõAÕUacÜÆ¸�qàÕÕ««WWÔqPÇAÁÖØÖØÖXßaE"ѧ$ž�}bïqÿþRVPFPFP(»(»(»è;ÝçCµVµVµö.Ü»pïBX¼*xU0´Žk×:Æõ×g\±p‰Dÿ&bû‡Ô «V/ äžrO¹'\êt©Ó¥NúNUü%&&Ââš‹k.® ×O^?yý$LNŸœ>9:Üëp¯Ã=�kä¹FßiE"Ñ?I¼„ø „�v4ÚÑn_¸}áv°ÿÁþûô�®øxRþIù'åa}çõ�×w†’‡J*y†*‡*‡*Áæ�Í;›wúN)‰ôI,`ÿ°÷�åX8qáÄ…Áþ�ýûð�ì;Ùw2à:×¹®ï”z8.‹Ô‹Ô‹àTÄ©ˆSpx÷á݇wCÛ¨¶Qm£ Ãè£;ŒÃ† è;­H$*ÄKˆÿ0¹±ÜXn =z÷èÝ£7Ü6¼mxÛžõyÖçY}§ûçe”Ë(—QVy®ò\å 'Çœsr Œ 86º.躠ë±p‰D¢_ ˜žxÕôªéU—o\¾qyØá³Ãg‡äõÌë™×Sßé>½p‡p‡p˜<3xf0äÌÊ™•3 æªçªçª¡Z·jݪu~äG~ÔwZ‘HT‰LÏ:ÖêX«c-ÐÍÑÍÑÍ�£m޶9ÚFß©>>]]]8wáÜ…s`�|�|�ü´~Z?-Lõ™ê3Õœ«9Ws®¦ï´"‘ès 0=3ëcÖǬô¯×¿^ÿzpvïÙ½g÷³ÖÏZ?k­ït_Î�œ!9C`À 6 €½·öÞÚ{ [¶l ýÖõ[×o˜59jrTßiE"ÑçDœÄQÌìi¾§ùžæpKqKqKóÎ;8ï XXXFOo‹©S%¦ ¬Y³fÍš5 |-|-| £‚F� �öí=Úë;¥H$úœ‰g`ÅL§E�uZ6‚�`#À“&;L@»R»R»Rßé~Ÿ°SØ)ì„»îv¸Ûf©f©f© ¤¬¤¬¤ f¥ÍJ›•&.‘Hôñˆ¬˜1®j\Õ¸* ]=tõÐÕðìೃÏÂÉC'�¯z¢z¢z"2=dzÈV÷]Ýwu_èø¤ã“ŽO`Ø�a†s{s{s{}]‘Hô%ùŒ.Jý»¸x¸x¸xÀðñÃǫϯ>¿ú<äíÏÛŸ·‚N�: ç�t~س;fw ÚÑŽvc¿‚¯à+ø{ØÃ�T’T’TúõvY9Y9Y9°%~Kü–xß¾%| Lz>éù¤çPÙ²²eeK`5«Y­ï£)‰¾H‚¨XS•Q•Q•„iã¦�›6Nl m m AZ_Z_Zÿýw—‚ð}íïk_[„ !Húëû;·ÿÜþsûa›í6Ûm¶‚ qÔ8j‹~þ¦Ö›Zoj ÂØúcë�­/Ór§åNË„¸ä¸ä¸d}-‘Hôo"ž�Sk2Öd¬�5;×ì\³¶æoÍßšé†é†é†¿ÞþΚ;kî¬�ø×ñ¯ã_ƒ3Î8ÿ‰ýň;æ�™?fþxð*àU8ÉœdN2°úÖê[«oaÓŽM;6í€Z!µBj…@Ÿð>á}ÂAQUQUQUßGM$ý›ˆ¬˜zëôÖé­• *T’í’í’í~ûб¡cCÇÂË/¼\ðÇ ˜ÚTmª6… U6TÙPnÕ¹UçVÐäiò4yð}Ÿïû|ß*lª°©Â&æ>Ì}˜;4^ÖxYãe «*«* —H$ÒqG1UíUµWÕ^A G G ô;ÕïT¿S`ñÜâ¹Åó_oŸÛ5·knW¸Úêj««­€0Âû¿÷sÁå‚ËØ2iˤ-“Š ×{á;Ãw†ïM²&Y“ 5_Ô|QóÈËËëû(‰D¢3ñ>°Ï„ò¾ò¾ò>:rèÈ¡#°´ÅÒK[À‹ò/Ê¿(‚½`/ØÃ×w¾¾óõ8Yp²àdXÖ³¬gYï×íŚĚĚ@Ïn=»õìÁ�Á�Á�€ @@àƒO…aGÃŽ†á‡Ê?Tþ¡2Li<¥ñ”Æ ó—ùËô0ûQ$‰Ä3°Ï„©Ÿ©Ÿ©ôéÙ§gŸž°oÕ¾UûVAï½Oô>Æ!Æ!Æ!O<ðtÀ¯ÛQ¯V¯V¯†uo×½]÷näÜȹ‘óÁï W=êQäÏäÏäÏÀs¥çJÏ•�cšcšc ʡʡʡú>*"‘èßL<ûÌe¿Ì~™ý… = Ëî.»»ì.´Übp‹Áðµ××^_{�u'ëNÖ� ¡uBë„Ö0F;F;F[t?™…ÎBg¡ƒR5KÕ,UjUªU©V%h:§éœ¦sÀ÷²ïeßËà^ʽ”{)0¬kX×°®¾{/‰þÍÄö…9—w.ï\ i5¤Õ�VÛ&¶Ml0?n~Üü8˜Ž6m:T*4×4×4×€¿‡¿‡¿T7©nRÝJ4,ѰDC�äKò%ùúî•H$ýš8 ñ csÁæ‚ÍÈz•õ*ëè®é®é®AYd5,kXÖ°„-�·tÞÒܲܲܲ@ÖPÖPÖðƒ†òÉG,\"‘¨¿ûÂ8>u|êø|žû<÷ù`¶¢ÁvƒíÛ¡Êé*§«œ†.%\J¸€lŒlŒlŒ¾S‹D"ÑŸ'^BüBMQNQNQ›5oÖ¼Y ìØ7°‡ø¬ø¬ø,(ÿ¶üÛòoáÛ»ßÞýö.ÈîÊîÊîê;µH$ýqâ%Ä/LV^V^Vd¤e¤e¤ÁôeÓ—M_UÒª¤UIƒ°Ä°Ä°DXì´Øi±è�  gDψž õ’zI½ôÝ ‘H$ú¿‰—¿01ãbÆÅŒÝ6Ý6Ý6ðøÉã'�ŸŠ~îãäãäãS¯O½>õ:\­rµÊÕ*°§öžÚ{jƒN¡Sèúî…H$ýßÄö…yáôÂé…¸Îr�å: ¬V[­¶ú�ÕàËÖ-[·l]˜ünò»ÉïàòôËÓ/O‡]Ñ»¢wEƒF¥QiTúî�H$ý>±€}!„jB5¡„Ú‡Ú‡ÚC¥¯*}Ué+�\‘\‘\ùý÷ygzgzgÂÔ–S[Nm ׯ9^s„Ÿ}öýÙtmtmtmôÝ;‘H$ú5±€}!r´9Ú-$nLܘ¸Ê-w´ÜÑ?þ~ï²Þe½ËÂÔSgL�Á²`Y° v™ï2ßeÚ Ú Ú úî¥H$'q|!"*GTލ 2_™¯Ì*"‘èß@,`Ÿ¹P!TÀù¦óMç›`sÔæ¨ÍŸ˜}øWyºyºyºÁÌ­3·ÎÜ O–?Yþd9l¹¶åÚ–kPX¹°rae}‘Hô% Øg.Ü8Ü8ܼS¼S¼Sþùý»Ÿq?ã~¦ùOóŸæO+<­ð´lÊÝ”»)TKUKUâwd"‘èóýL)7*7*7Â� <`pçÁ�w†jÊjÊjJýåŠ}û.ö„„„CÙ¡e‡– à † 3£p£p£p}=‘Hô%ÏÀ>S‰åË'–õnõnõnp=ïzÞµ|÷äêáêáê3OÍ<5óDŒ�1Ö=Y÷dÝÈŸ–?-š¾SŠD¢/�XÀ>Sñëâ×ů³5fkÌրŋô�ªH‰U%V•XÓ¦'LO€¨fQÍ¢šÁZùZùZ9ä=È{�÷@ß)?švšvšv�’�’�’ ù�òå?Òw*‘èŸ!^BüLmi¶¥Ù–f�ç“ç“çcV�Y=fõßo÷SIê™Ô3©'l ذ œÍœÍœÍ`Ô¸QãF�Å Å Å }§ÔŸ˜ý1ûcöCÄЈ¡Cáké×Ò¯¥ O—§ËÓ½½îŽîŽîœ�œ�œ�À£·�Þ>z õwÖßY'˜57knÖ,X°<εœk9ׂ›;oî¼¹LG™Ž2_›|mòµ 0� |‚Û/D¢OI<ûÌèöêöêö»‹ï.¾»¥·—Þ^z»¾Sýß÷8îqÜ3^Ìx1ã$ÏLž™<VkWkWk!·fnÍÜšúN©? q q qp+íVÚ­4(Œ,Œ,Œüýí3FdŒÈ‡,Y²„n-ÜZ¸A¥äJÉ•’á~•ûUîW�7³ÞÌz3 ±ŠXE,ÜWÞWÞWžu{ÖíYÂáˆpR¤H=ùËó—ç/×÷щþÙì_è;ˆè�É�Ï�Ï�‡#­�´>ÒšölÚ³iOp,ãXƱŒ¾ÓýßL]L]L]À¯�_¿6pÞã¼ÇyxìôØé±T}SõMÕ7`TǨŽQ1^¢J[F[F[Ò6¤mHÛÊgÊgÊg�••Z¹V®•ƒ‘‘‘‘‘d×ή�]ònæÝÌ» ªëªëªë .«.«. vvvP1¤bH۰µ°µ°©­ÔVjûÁŽ£ˆ" ÞU{Wí]5سsÏÎ=;¡é€¦šÏÏÏ(Õ¨T£R� dã’�K6ÅcÅcÅcxqüÅñÇ!yxòðäáà×À¯�_X±cÅŽ;À*Ï*Ï*œcœcœc€B )„´ì´ì´lÈÞš½5{+Ȼɻɻn¸ái1i1i1 m«m«m Ê0e˜2 d­d­d­ ïQÞ£¼G ™­™­™ †m Û¶Õ÷(Š>wâØg&> > >´´´Àý¶ûm÷ÛúNõçÙæÙæÙæÁÔ˜©1Sc »tvéìÒ°Òv¥íJ[ÈVe«²‹ñóÈò\ó\ó\arÕÉU'W…€Ô€Ô€T8^ëx­ãµ`^Çyçu„ÈÓ‘§#OCУ GA�`À¤“L‚=göœÙs‚š5j÷ï9Þs„Áƒ @ôŠèÑ¿qIUí vP;À«m¯¶½Ú)µSj§Ô†;�î4ºÓb‡Ç�ëüÖù­óƒ%VK¬–X}ÐÀ/kYâ…^ð¢ï‹¾/úÂÉi'§�œwãïÆß�‡ÔQ©£RGÁÙð³ágÃaí­µ·ÖÞ‚�Ëv.Û¹ 64ØÐ`CHNN†)¹Sr§äÂü“óOÎ? �Õ«VƒgUžUyVÖX¯±^c Ûb·Ån‹Õ÷艾bûÌD]ˆºu¬æ[Í·šæïÌß™¿Ówª¿Î6Ø6Ø6¦†N � £ FŒ†eW”]Q2gfÎÌ,†«Þ›_1¿b~Ìž™=3{ =z,„¡~Cý†ú�AuƒêÕáäð“ÃOÏ!žC<‡@nfnfn&´nѺEëдuÓÖM[ƒw†w†w(•‰ÊDP·U·UÿÆŠ\!WÈà7Ðo ß@pžâ<Åy ´zÛêm«·PªN©:¥ê@‰Ò%J—( ­2Ze´ú �DIÉuÉuÉu(³¹Ìæ2›Á±—c/Ç^Ð*¡UB«09`rÀälwÝîºÝšVjZ©i%`;Àv€-\н{)Òf¦ÍL› æ¹æ¹æ¹`>Ç|ŽùèSªO©>¥ Ô�RCJ �Ž ;6ìØZÚ´´ii£ïÑ})Äö™‰~ý0ú!¸Tv©ìRd�²@Y ¾Sý}Ö¬X€I‡'žtÔ¥Ô¥Ô¥`Ù¾eû–íƒôuéëÒ×é;åopÅW 4¥)]ô²ý<ûyöó vyìòØå€5ÖXƒ±‹±‹± Ø\¶¹lsìWد°_$H2��@Ðàì× @¸)Ün‚.„ Þ_gŒ1ÆÀB²ð´#C†¬¨ÚÒ–¶�¿9sþfˆjÕ4ª)\7½nzÝŽ… ;Ò]Ò]Ò] ë ë ëÒ�Ò�Ò�`®1טkÀ¶¡mCÛ†`5Âj„Õð‰ò‰ò‰¯]^»¼vé{ÐD_ ±€}&tststs jvÔì¨Ùàååååå¥ïTŸUS«¦VMa’÷$ïIÞ ; ; ;K:,é°¤CÑÿø‹ O<ñÉÉÉ‚¢—•YÊ,e˜w4ïhÞˆ%–Ø¢íÿS`Þûå»&É`É`É`�4”4”4üû}¿ýÉÉ�´�´�´øàç&˜`’ŒŒżþ~¿ó˜Ç¼¢íÈ"‹,à1�y ²TYª,¬X°:µ.ÔºPëtšÜir§Éð“ÑOF?�¯ÎWç«ÍuÍuÍõú÷ßq+V*¬êÓêÓêÓú4Ñ—B,`Ÿ‰¼ yò.@zDzDz¸8¹8¹8é;Õ§c¹Ñr£åF˜>!|B8˜‡˜‡˜‡ÀBåBåB%$¾H|‘øBß)AÈ2„ ˆO�O�O‡Ûn·Ýn»A|Óø¦ñM¡ñƒÆ?€”);Rv@ö­ì[Ù· mpÚà´ÁÀ[Þò’F%�J9Ãs†ç ‡¤×I¯“^ÿƳÉ&’×%¯K^Ù}²ûd÷�øëñ×㯃*Tª …”à”à”`ÈX“±&c ¤tNéœÒҌҌҌ #1#1# b b b@zIzIz n\¿qýÆuооо€¯G=úëÑp¯Ì½2÷Ê@t@t@t({+{+{CÞ¨¼Qy£ kPÖ ¬A�™™ G�£Æ´�´�´�`�ׯ5^°Ýk»×ö/ð?^"ý ØgBi 4P€*V«ŠÛ.¶]l»è;Õ§gÞͼ›y7;sì̱3Á!Ð!Ð!n_¸}ávˆÿ&þ›øoô—OX.,–C–a–a–!¤¹¤¹¤¹ÀÀÕW\ _}eô•”�•�•�Á�ÇCy Be¡²P´…ÚBm!ÈnÈnÈnÀHF20ÝhºÑt#èrt9ºœöWU¨*Tƒï ¾3øFŽ9väX0I2I2I‚œA9ƒr�ßD¿‰~¡ã‘ŽG:�ŒR¥2J�Ÿ·Ÿ·Ÿ7tTwTwTƒiÓ ¦`¦ÿLÿ™þ`´Êh•Ñ*¼/Á Æ 3hÌ (¯,¯,¯„èÄèÄèDH]žº'}NÂüˆùó#àmüÛø·ñŸ>GjTjTj$$$A¶<[ž-‡Ì”Ì”L=<@$ú7 Øg"V«ŒU‚³«³«³«¾ÓèŸq[ã¶ÆmapÅÁW„ªÙU³«fC€K€K€ D\ޏqùÓíßöŠíÛ+°|ÿòýË÷ÃŒF3Íh–––ú>:"Ñ¿ƒx ñ3ñìfý0 ª¯®¾ºújhŸÙ>³}¦¾Sê5ê5ê5°{õîÕ»WCHlHlH,L¾6ùÚäkà]Ë»–w-}§‰D“xVÌåÇæÇæÇBššš?¸îsÝçºOß©Šùhùhùh轪÷ªÞ« á½†÷Þƒ€'NÀ³¶ÏÚ>—.‰¾(b+æ2…L!SÕFÕFÕFpúÉé'§Ÿô�ªø2hkÐÖ -tÏîžÝ=Z´ h‹V.Z¹h%<ÜúpëíúN)‰>±€sYõ³êgÕyyyP\R\R\ÒwªâOöµìkÙ×Ð¥C—]:@×9]çt�+®¬¸²â Ü©v§Ú�júNùûÔkÕkÕk!,(,(,TcUcUcõ�J$*^ ô@ô¿eäfäfä‚QI£’F%ÁÄÄÄÄÄDß©>’c’c’cÐ.¨]P» 0,iXÒ°$¬‰Y³&†¨†¨†¨ ~ÇúëwNqŠSúN ·³ngÝ΂͹›s7çÂÈ#ŒlV#­FZ�M M M 0b<Äxhçkçk烲¾²¾²>8]pºàt,JX”°(áqáqáqà´ÁiƒÓ(Z"´D(d·Én“Ý"{GöŽì ’u’u’uPú«Ò_•þ Ì–š-5[ªï£!ý6ñ ¬˜KðMðMðÛ8Û8Û80®n\ݸº¾S}†~Y㯅Y ³f0èü óƒÎÃ&õ&õ&5\p½àzÁÇ8Æé;,¼íú¶ëÛ®ðrÒËI/'AæýÌû™÷ázçë�¯w†áIÓ†'Á¥ë—®_ºÁÎÁÎÁΰøà⃋¡r‡Ê*º•º•º•°Ä}‰ûw8}8úp4xxxÃê5«×¬^×»]ïv½œzvèÙ¡°QµQµQê™ê™êâ´t—Hôñ ¬˜‹?$þ8žu<ëx8Á Nè;Õgì—µúÎk8¯á<0ò2ò2ò‚õË×/_¿TÙªlU6´n׺]ëv 9!9!ÑÃñ.9±äÄ’Á©”S)§RP×·®o]_x°ïÁ¾ûÀ$À$À$¾9ñ͉oN€E¢E¢E"<)û¤ì“² ùZóµæk0¿j~Õü*Ø·´oiß„ÞBo¡7¼®øºâëŠp{Áí·ÀOö?ÙÿdñýãûÇ÷‡)nSܦ¸Aï¼Þy½óÀGõ=v"ÑÏÀŠ)!SÈ2!klÖØ¬±`Sݦº�xæõñ˜cŽ9ÔI¬“X'ƼójÌ+8`|Àø€1ÖÖÖ�¶±¶±¶±ò½_%~ˆ0D¼â¯€RHƒ“' N‚Ñ,£YF³ÀhŠÑ£) Ù-Ù-Ù ’²’²’²¿nVòZòZòrMsMsM!>:>:>n;¸íà6¸¶äÚ’kKÀ»Ð»Ð»ä“ä“ä“ôá|$O$O$Oô="ÑÿŸXÀŠ©ðá ÂÀÒà¥ÁKƒa«X˜ž3=gzNßéþ}âÛÆ·�o Kl—Ø.±‡gÏžÁèÖ£[�n fsÌæ˜‰gÈ"Ñ?J¼„XL½Ÿ¼aÔ¨…Q 0¬bXŰоSý{999ÁŒ3VÌXÙÆÙÆÙÆ°¸â⊋+BFFFFF†¾SŠDÿ.b+¦r7çnÎÝ ŠŠŠŠŠŠ } } } ïT";;;˜²vÊÚ)kA$ ’A€ �t=ézÒu}§‰þÄVLåÎÊ�•; ÷÷÷@zGzGzGß©DïYU±ªbU&:NtœèvžvžvžÐ6 m@[ˆ½{+öŸœµ(ý ‰¬˜Ê™š35g*())�ä†ä†ä†¾S‰þ›éRÓ¥¦KaLȘ�1!PúVé[¥oÁ<ßy¾ó|áÍ„7ÞLÐwJ‘èË$°b*'/'/'L/˜^0½øâ‹¯¾S‰~�q%ãJÆ•`ضaÛ†mƒškk®­¹š4 h ¡þ¡þ¡þúN)}YÄVLe�Ì:™ulVÚ¬´Y©ï4¢?Êp©áRåЯy¿æýšC3—f.Í\`©ßR¿¥~pûêí«·¯‘D©ï´"ÑçM\ ±˜Ñèt�“˜“˜“Ç,ŽYÓw*ÑŸ%«"«"«]{uíÕµX>´|hùÖ|·æ»5ßAŽ,G–#ƒ&IM’š$�ÄQâ(‰þñ ¬˜ÑÖÖ†üù#òG€évÓí¦Ûõ�JôW½_›°EA‹‚0bÿˆý#öC`f`f`&}{ôíÑ· “éd:™¾ÓŠDŸñ ¬˜Ñ�Ö�Ö�mmm0\a¸Âp0‹YÌÒw:Ñ_öË%CüñÌ¿1ÿÆüX‘³"gEd¯Ì^™½zÌè1£Ç 0œo8ßp¾¾C‹DÅ›xVÌhM´&ZЖՖՖù;ù;ù;}§}l¾G}�ú…é˧/Ÿ¾n¼9ðæ@Øà³Ágƒä)ó”yÊ¢íu{u{u{áqîãÜǹ�––¦ï^ˆDú%°bF[_[_[„GÂ#áÈ[Ë[Ë[ë;•èS)S¹Lå2•á‡9?Ìùa¼Ûÿnÿ»ý°bÿŠý+öCÆÝŒ»wá䔓SNN�î»Oì>ŽÆ�;§ïô"‘~‰¬˜ÑÖÐÖÐÖÝAÝAÝA�ߕߕßÕw*ѧæºÄu‰ë˜1kƬ³ PS¨)ÔÀ�6CÚ ißOý~ê÷Sá寗_n„ý�÷?ÞÿÒeé²tñ»3Ñ¿”øX1£Û¯Û¯ÛÚÚÚ ó“ùÉüô�JôOyÿàRŸpŸpŸpX“´&iMdI³¤YüwóvÍÛ5oׄóuÏ×=_¾å[¾Õwx‘è&ž�7ÛÙÎv …B¡$Í%Í%ÍõJô© éBº�'†�vbLWOWOWÿºp½§¬¯¬¯¬»Zîj¹«%d(2 }÷B$úg‰¬¸Ñ A’m’m’m@/zÑKß¡DŸšn§n§n'(Q¢,ÖX¬±Xò£ò£ò£¿ÿ¾kU®U¹V®É¯É¯ÉõÝ ‘èŸ%°bF¸*\®‚Á,ƒY³@– K�%è;•èS“}/û^ö=tëÛ­o·¾dddK‡/¾t8ÔRÔRÔR€|–|–üƒÛ)”-”-”-`gË�-w¶åAåAåÁߨASšÒ´IÚ$m¨Tÿ¨þ²³²³²³ æ^̽˜{ >„Mo4½Ñ®:^u¼ê—ë]®w¹œ[yn幕p.í\Ú¹4¸\úréË¥áŠpE¸"À�.7ºÜè%%%–––1«bVŬ‚lu¶:[ êñêñêñ �ÖFk£¯…Šþñ;°â&—\rAò\ò\òXÌbë;”èŸ"­-­-­ n7Ün¸Ý€1îcÜǸC—e]–uYg–œYrf ìŠÜ¹+î÷ºßë~/¸:þêø«ãaŸÍ>›}6àó•ÏW>_AdPdPdÄÕ�«W2å™òL9ä´Ìi™Ó B B B�ô HÒ$i’40laØÂ°Î4œi8ä«å«å«AÒQÒQÒ ¦L1˜lf3›Aó£æGÍ� 4 A“£ÉÑ䀪¡ª¡ª!¨¬TV*+`ã`€€y¢y¢y"X›Y›Y›�ó2çeÎËÀã¶Çm�Û`ßɾ“}'p(áP¡X÷³îgÝ$Q’(I”¾GM¤/b+n$H�yä‘RH¡¾C‰ôE3Q3Q3Ld&2T¹UåV•[�9}äô‘Ó`gg]úué×¥Ôp¬áXÃÌFš�4 Œd$#õý)üüò%ž´­´­´-xà�àáìáìá b:Ätˆ�»w=îzÀÉè“Ñ'£áŒùó3æÐq_Ç}÷A£�4†y†y†yúî”迉Óè‹™¡ÌPfR¤HõRõRõÒ_oÛ=¶{lwØì¾Ù}³;XU¶ªlU^›¿6m«=W{®öm)m)m)Xo¼Þx½1\9åü•ó����‡Æެ=²öÈZ8äü‘óG~?Ÿ¢µ¢µ¢5˜º™º™º�e´e´e4X×±®c]T¦*S•),´üÑòG�””Ò«Ò«Ò«ÀqŽsŒF�4 é#ÓG¦�ÅÅŰ.g]κ_¾|óóóÁn�Ý»5p(ìPØ¡0¸ÐöBÛ m!±bÿÄþp-àZÀ5ˆ»w-î$´Mh›Ð¢–E-‹Z§gŸž}z6ä–Î-�[úÓ�ßÛ•oW¾] ó"çE΋„£ÍŽ6;Ú ºFw�î ¬X/°††nl¸̬̬̬ôú‘ûwéNwºƒé-Ó[¦· á¾†ûîƒN œ8A·VÝZukÇŽ€y?ÌûaÞðÎú�õ;k}‡ý7±€32™‰Ìd�d�d�@�£ÎQçüz;›¥6Km–]¢«t¯Ò½J÷ ™E3‹fp¯ÿ½þ÷úƒv¹v¹v9X̶˜m1ªäWɯ’ÝvkØ­!x®ò\å¹ Ì«›W7¯ô§?ý?ŸeË–Àf¸Íp›áàšàšàš%Ž–8Zâ(ذ;`wäƒåƒåƒ�~ô£ÿ¹CW+ŒÆ‚éKÓ—¦/ÁÊÚÊÚÊ\¥®RW)8,vXì°.z]ôºèfnfnfnà;Úw´ïh°Øn±Ýb;ÜX~cù�å`;ÕvªíT°v°v°v€´ ÐôQÓGMA­¦µšÖj ‹Ï,>³ø 8ìtØé°ó#ØÖ°n¹qäÆ˜›:7un*”ø±Ä�%~„Eg�]t«««Á(Á(ÁH¼¯¯Ø1¾l|Ùø24~ÖøYãg°°âŠ +‚ãÇ-Ž[`–Å,‹Ypë»[ßÝúNßiE˜‘-’-’-ÙvÙvÙvPy©¼T¿õÝ×ûÙ‰;ØÁàG~äG�ÛÈmä6 )£)£)ÚÃÚÃÚÃügÖ˜ä…ä…äÅo´÷†7¼ùAà '„áÂpaøßèp9äyÈâ—s§åNË�ï<Þy¼ó€ yAó‚æ�ueëÊÖ•Á¿¢EÿŠ œÎ gA’"I‘¤€ä™ä™äYÑ,G™›ÌMæ&åLÊ™”~â'>â쳋Y³.fÁ¦¹›ænš ½ {ö2„ïâ¿‹ÿ.¬šX5±jòñö÷Å3ÁДҔҔ 1ÄðŸ�aõ³ÕÏV?Ãð^Ã{ ï½Ü{¹÷r‡ 7 Ü0.m¹´åÒ`=ëY¯ïƒöï%°bF" ‘…€"V«ˆ…ܺ¹usëþƆЈF4ÚÒ–¶�86qlâX°éjÓÕ¦+˜–6-mZÈ@òŸûx~%“L2�k\ãÚúËý>Üâ·>ìÀ/7=â�€(¢ˆ¢hõ}îsH'�tF £…ÑPx¹ðráå¢fܸ=p{%”á¼ ¤=I{’öDtKtKtK¡ jAÕ‚ª‚�‘‘!ÉË’—%/u'u'u§_ïWÕYÕYÕY''NNœ,I›’6%m„‚Š * BÖ¢¬EY‹!A’ I�BÆ®Œ]»!«AVƒ¬‚�P;¡vBmAȺŸu?ë¾ L(˜P0Aâ�â�â�!}Iú’ô%‚ ¬Ök!;););IâGÄ�ˆ!)¦)¦)¦‚P`V`V`&™Õ3«gV„„ú õê ‚²£²£²ãy©© BúÞô½é{A»E»E»å¯�Ëî»kì®!Ë}–û,÷m²6Y›ü×Û»ÖçZŸk}¡U­VµZÕ„”À”À”@A(|Sø¦ð� èêê ‚N®“ëä‚ ~§~§~'º]‚.A´´´A¡ŽPG‚à,8 ΂ š§š§š'ÿoÅAPWW„ÂI…“ ' Bû€öíá¬ê¬ê¬Jžõ~ÖûYoAX¼.x]° Ì)˜S0GT.*•‹ $ÏNž�<[ A³P³P³P4F#�‘ ‚ÚGí£öa«°UØúÇ�Õ°+aW¡­¢­¢­BR"R"R"AÓMÓMÓM’ã’ã’ã!ÿZþµükEïÕbT‹Q-a…z…z…úƒG #…‘‚Pا°OaA(|]øºðµ Ï„g³¿>^ïiŽiŽiŽ Â’‰K&.™({t{t{t¿]ÑŸ#°bê`…ƒV„& L˜‚PB(!”(úùáN‡;î$uOÖ=Y÷¤ DŽˆ9Bß©¿\YÙYÙYÙ‚0jѨE£ ÂÃõ×?\ÿ÷Û 6 6 6„¯¤_I¿’ ÂÖ[l  ¿[øÝÂï!ðzàõÀë‚Z;´vhmARyHå!•á®ù]󻿂ð2åeÊËAÜgpŸÁ}ánù»åï–„ðváíÂÛ Â�SCN 9%w}ïúÞõ„ÿwæ- ;v0„£YG³Žf ÂTË©–S-¡Á•W\„3ýÎô;ÓOžZ?µ~j-Cg �1t† ÜH¹‘r#E~œóãœçÂDˉ–-aoúÞô½é‚ðýØïÇ~?Vn.¹¹äæ’ÿ»ÿÊjÊjÊj‚°¤ó’ÎK: B…›nV¸);.︼㲠¼ZõjÕ«U‚0¾Ïø>ãûÂÁOm|2ëgÖϬÿÏ>ÿ­Ä3°bʶ»mwÛî ¡¡¹crÇäŽÑwª/³ ³ ³ (¼Ux«ð¨Ž©Ž©Ž}ÄØ`ƒ Ð�ntm”6Jê ê ê `ºÈt‘é"Šfuºà‚  E‹öƒ÷»âŠë¯;âˆ#E«æþòÀTpÀðÄOþ3KT2E2E20ÆcŠf»þw;¿ÜÆ!©*©*©úA?Þ/^øË¬WI/I/I/0Ûn¶Ýl;˜»˜»˜»ý]ÒYÒYÒH!… :Õ©˜cŽù‡€f ©$©$©ôÁ릘bZô§d“d“d÷7îoÜœ:5tj5š×h^£9¬p[á¶Â lll?ÂlT­Z«ÖªAUKUKU L÷›î7Ýÿ?¢ÿI<+¦ìÙ²;’Ÿ%?K~†ä‚ä‚ä‚¢ÅL?¶œøœøœx8×â\‹s-@»_»_»º„t éÒÁÒÁÒÁ¿ÿ~ÕJÕJÕJÈê‘Õ#«˜F™F™F�éW¦_™~¥ï£ù÷9”v(íPdwewew!~^ü¼øy`‰%–£]i_i_i_Ð Ô Ô „”ý)ûSöC˜O˜O˜¨ìTv*;ðïâßÅ¿ \9tåЕCs:ætÌiHÒ…t - - -¡ KA—‚. ì¯ì¯ì_4û4Ç%Ç%Çræ.Ì]ª^ª^ª^�³2geÎJ0ìiØÓ°'$ýœôsÒÏ[/¶^l=0µ6µ6µU–*K•Yª,U– ”�”�”� ¿C~‡ü �¢�¢�ù…ù…ù…�——òòòÐö~ÛûmïÿþqP( ”�Ÿ�Ÿ�Ÿ9Ïržå<EYEYEYÈ?’$ÿäææBáС…C¡ DA‰‚�s&çLÎpJvJvJ×'®O\Ÿ@A`A`A ”Ÿ^~zùé`<Òx¤ñH�?�?�?øÃÃô»Þ®z»êí*�è$:‰Ü]Ü]Ü]þá翘lö/ôDôÿ'Í�fH3àú¡ë‡®·Ü~pûšŸÉ×&_›| ïÖ½[÷nÄ¿ˆÿªÕ«V¯Z½¿Þ®ñVã­Æ[Aâ&q“¸AÜœ¸9qs ~Cü†ø Ðái‡§ž‚ï#ßG¾�ÀÖÓÖÓÖÞv}ÛõmW(Œ+Œ+ŒÃ\Ã\Ã\p¯ì^Ù½2¨»«»«»CöÔì©ÙSÁ6Æ6Æ6hG;Ú�ò¶ò¶ò68Lq˜â0ª©r¤ÊÈx“ñ&ã d·Ën—Ýd9²Y(=”J0ó1ó1óm-m-m-°ö·ö·ö‡’%3Jf@|J|J| ˜‡˜‡˜‡@yûòöåíÁ¤¯I_“¾¿î¿Zª–ª¥ð|ÿóýÏ÷ƒt“t“t8»8»8»€Ö^k¯µ‡÷÷w°jgÕΪ(º*º*ºBfnfnf.XÞ²¼ey ªyUóªæ>+}Vú¬„Gûí{´¢�£�£�Aç¯ó×ùƒÓ-§[N·@ÚZÚZÚú¯�ßá¨ÃQ‡£ÀaµÃj‡ÕPwtÝÑu?Á¿OÑo“¼ŸÍ¡ï ¢ÿòË%“cŒY0¼ky×ò®]ÚviÛ¥íÇßݤZ“jMª.U\ª¸T�1Çl³‘¢:þóà¦ÿm´ÏhŸÑ>àÙų‹g;wìܱsõ}0?žØÞ±½c{Ãâ ‹+,®ƒÜ¹r‡Ê=*÷¨ÜCßéDÿ”ÇÝwÜ~jÿSûŸÚä*“ªLªnåÜʹ•Ówºñbq•K.¹P¢G‰%z@\ݸºquÿ~³ÿííÏo~û3ßø|ãs˜²zÊê)«ÁãŽÇ�;úË'ú´";GvŽì ¶lزa t|ÛñmÇ·báÒqG1Wªq©Æ¥CìæØÍ±›¡°Ra¥ÂJ¿Ý÷\¾uùÖå[p±u±u±…r�Êu*× *\©p¥ÂP/T/T/«êVÕ­ªCû™íg¶Ÿ ·NÞ:yë$œ|zðéßønL–"K‘¥À‹ƒ/¾8›í6Ûm¶ƒºu3êf-¥+Ðè àÑ­G·Ý‚Àümj´©Ñ&PNVNVN†Í�6?Úü„,!KÈúóýüØš¯n¾ºùj¨=«ö¬Ú³`AÇt„°a=ÂÄ3±/ÎûÇ-t_è¾Ð¾nóu›¯Û@ÓvMÛ5m÷÷Ûý5b+æœ��!§TN©œR�Û6·mîG¼„h(5”JÁÄÝÄÝÄ,žZ<µx ŠMŠMŠM`vÄìˆÙ(P. \¤õMë›Ö Ó Ó Ó M“¦IÓüº]¡‰ÐDh¦;Lw˜îµ�ÚFm{ºïé¾§;(… À*Ö*Ö*žî}º÷é^Èî—Ý/»Î+œW8¤>R©<¿òüÊó+ m«m«ý—Pÿ,YuYuYuèy±çÅž¡ÉŒ&3šÌ€Åï¿[üN<9ðä@P»¨]Ôâ—úŸ�½…{ ÷BP½ zAõ`Ñ•EW]�æáÍÛ‡C÷mÝ·ußÒXi¬4Vßiÿ½ÄVÌÙϲŸe? ´Ý´Ý´Ý m~Úü´ùŸ`G¿,Î+Üî ÷Š^>fpÌà˜l^»yíæµ���ÊÊÊÊÊÊ •„JBÝœn„n„nx¹z¹z¹Âò]Ëw-ßæ/Í_š¿„q­Æµ× n5¾ÕøVcà;¾ã;(è]л 7ÄlŒÙ³ÜV»­v[ úë:¬+ȼeÞ2o}�JÙIÙIÙIè:´ëЮCaظaã†�ƒ1'bNÄÀ¼Šó*Ϋ¯:¿êüª3ü¿% ô�Zôß„‰ÂDa"„÷ ïÞæ�˜?bþ:t<è8ŒP�P�PA§ñ�Æwe Ê”Õwj‘XÀŠ9kkk°´´,úEø±iûhûhû€æ æ æ`Ñë·›Ýnv»Xö·ìoÙZh= õpIrIrIu7u7õ‹¿jwjwjw‚®¬®¬®,D]Žºu   Â`üüñóÇχ²²2x{ííµ·× Ô�R7JÝë(ë(ë(¨Ñ­F·Ý Ãá‡;†&]›tmÒ$[%[%[õ=*¿a-kY µ:ÕêT«‚sEçŠÎaA·Ýtƒ5ÖTXS"êDÔ‰¨B¡�ÐGßáÿ}„ýÂ~a?¼Ž|ù:V¹¯r_åóïÏ¿?ÿ>8ïtÞé¼nZ¸iá&øjèWC¿ ’†’†’†úN/zOœÄQÌIªIªIªA)I)I) ¼²}eûÊÚІ6¡ý¸cqÇâŽ�¤¼¤¼¤/}HëHëHë@‰%”8>Ó|¦ùLŸ®>]}º‚‡ÒCé¡óëæ×ͯå(‡xŸÖGüì3aØÏ°Ÿa?¨V!¬B<ðhÀ£Ðìi³§Íž¾øò1VG º9º9º9ððÛ‡ß>üŽ\j<Ä]Š»w B… =×^;xí Ž-[8 A'�“Æ�‰�‰�‰¿0~aüL²L²L²Àd²Éd“É`˜c˜c˜ÒÒÒ _(_(_$’H"¨G©G©G�nŠnŠn +yý½ï:½ñÆ[×iáà îûȘڛڛڃk®k®k.<Ùõdד]ºN%üQO�§Æ.”¾PúBi˜µqÖÆYÁ=É=É= |oúÞô½ ®—]/»^F.Aø¢€}lÊP†2PóLÍ35ÏÀ«'VO¬ ¿m~Ûü¿ãÆ0áõÓ¶—. \ ;µ;µ;µ0hí µƒÖ mƒ¶ Ú¦M'šNÔuZAø°‰ö‘ªx³âÍŠ7!«DV‰¬19brÄd]§~ܹ͋/ra¦v¦v¦âªÆU�« ¾õ|ëùÖƒ{ìi°ä•ä•ä•t�V>¢€}¤   ¡B§ �*t‚+ŽW¯8ê:•ð“Âö…í ÛÃiÙiÙiøëûëûëCU¿ª~Uý`æÐ™Cg…’;Kî,¹S×iáã$ ØG®‘º‘º‘Û>¶}l iYiYiYºNõùJÏMÏMÏ…ƒV Z1ö±�}Àðkï ¿ßœùæÌ7gÀh§ÑN#Q¸á/ì#WÁº‚uk0v4v4v„ kAׂ®é:Õgd˜a¥ÃJ‡•†Yþ³ügùCÚ›´7ioÀo‚ß¿ àÕÔ«©WS�í’í’‰‹náo! ØGÎ(Î(Î(švoÚ½iw8Ûüló³Í¡àxÁñ‚ãºN÷éÒ|¡ùBóœìu²×É^àWÒ¯¤_I¨6¦Ú˜jc`švšvšŠ/,¾°øB]§„O“(`ŸˆŸžtœ™™ �–=Zöh™®S}z2:dtÈè+»¯ì¾²;|pðÁÁ0üÈð#Ã�@MM Ž1c8F×iáÓ& Ø'ÂâˆÅ‹#ÐpNÃ9 çÀ‰œ9'r@=\=\=\×é>~aeÂÊ„•�µfÔšQ ’Ú&µMj ~UüªøU�º–u-ëZ‚ÜAî wÐuZAø<ˆö‰i®ß\¿¹>$tIè’Ðî�¼?òþH]§úøN)œR8N7:Ýèt#˜“;'wN.ÔȪ‘U# ¦/Ÿ¾|úrpötötöÔuZAø<‰¥¤>Qzèy 'Ü[|oñ½Åð½Á÷߀¡µ¡µ¡µ®Ó}¸2r2r2r`Ó°MÃ6 ƒgûŸí¶™ 2dubëÄÖ‰™¾L_&V�G`Ÿ¨fvÍìšÙAvbvbv"\×\×\×è:Õ‡ë•ù+óWæà[×·®o]H�4 iÌž;{îì¹à•è•è•( — |HÄØ'î© §.œ‚6lØ€ÿ*þUÀÚÈÚÈÚH×étG»A»A»®ø]ñ»â[B·„n … "D@Ïo{~Ûó[0º`tÁè‚®Ó ‚ðKÄØ'®¡¼¡¼¡ìºÙu³ë‡»îv¸›®SéNNxNxN8l˜¼aò†É°eÄ–[FÀ€J (ý�ô?Òÿˆ(\‚ð1'C>qŠ–Š–Š–Ð£s�Î=:ÃüÕóWÏ_ u4u4u4PQ¯¢^E=]§üçEGEGEGAà÷�ß~êÒêÒêÒàìì ®É®É®ÉºN)Â!N!~f¶ylóØæOz<éñ¤|¿áû ßo“h“h“h]§ûûH¥¥ÒRi¸½øöâÛ‹aýÛõo׿…êÛªo«¾ úë{¬ï10s1s1sÑuZAþ q ñ3Ó©q§Æ�ƒ¦…¦…¦q?â~Ä]שþ>ªU„*v¦ìLÙ™«�W;¯v†.Ý»tïÒ†W^exQ¸áS ŽÀ>SÁÁÁ°Ðw¡ïB_[ll±±Å êĪ«~„Ï¡Šß¿1~#¬ë´®ÓºN�´,iYÒ2qmĵ× |ÓòMË7¦1�iºN+ÂßA�}¦*YT²¨dí\Ú¹´s�µ¯Ö¾Zû ’&L¨ët¿_ðžà=Á{`fÇ™gvƒ7 nÀ÷¦ß›~o å/—¿\þ2¢p Â'H°Ï\{Ûö¶ímÁÙÈÙÈÙÖ-]·tÝRP]Q]Q])Ú.竜¯r¾‚Èï"¿‹ü¤×Òkéõ¿ŸWÛNÛNÛÎ69Ûäl˜ï3ßg¾4éÚ¤k“®0¶á؆c‚õë Öt=»‚ ü“Ä)D€DãDãDcðÅ_À;Æ;Æ;ên«»­î6˜—8/q^"¤E¤E¤EÀÏž;¨ ®�®�®�pì豣ǎBÅ-·TÜòÇû‘NH'¤ððäÓOBéÄÒ‰¥Áú õAëƒEÛÅIqRœ«üVù­òƒÜ!¹Cr‡Àhåhåh%”¶,mYÚR׳&‚.ˆûÀ²B³B³BášÞ5½kzððÕÃW_A‚C‚CÂ{««G5ŽjÕî™Ý3»g©HÅ?Ñ_ÈÐ�¡!CaXæ°Ìa™Ð®V»ZíjÁäèÉÑ“£!dfÈÌ�™°ªóªÎ«:ƒGY�²eaRú¤ôIé`îaîaî¡ëYA—DûÌiêkêkêÃJŸ•>+}`nÔܨ¹Q�»;wwîîŸo_hYhYh ×ê]«w­tŸÑ}F÷`xÛð¶áíÿÝ_ÎÙœ³9gañÛÅo¿… E�"HQ�£:Gu†Â�… 7Bd§ÈN‘� mÿ¶ýÛö‡ö!íCÚ‡€�­�­�­®gM„�¸ˆã3§w]ïºÞuhw¦Ý™vg kÓ®M»6óåæËÍ—ÿúû®÷¼ÞózOˆ Œ Œ üÍd&3aŸjŸjŸ ö¯Þ¿zÿê¢' Ož0V´ZÑjE+h–Ð,¡YtIì’Ø%Q.A~N0€Ê÷*ß«|Vy­òZåË�/?¾ü8”Ï*ŸU> H �„¢íãGÄ�ˆwæß™gþÿn?84848–¸.q]â Ùßf›ýíÏ·Ëh�Ñ £œ¨z¢ê‰ª�‘‘¡ëÙáC$ ˜ð_LÜLÜLÜà›/¿ùò›/aßè}£÷�†¾ }ú&€IžIžIähs´9Z¸<óòÌË3A¦ Ó„ý¼½¬‰Y³&BÀ©€S§ xuðêàÕ¿Þ¿T Hp.æ\̹8z:ôt¨®gE„‘øLøE²á²á²áP‰JTV[ulÕ1¨Ÿ]?»~6,*¹¨ä¢’p3ófæÍLxzüéñ§Ç¡Dƒ J4Ó¯L¿2ý ö­Ý·vßZØÿxÿãý��2”¡ ÈË˃E/‹^½Àm‹Û·-Ðø~ãû�ïCÝõu××]5û×ì_³¿®gC„‘¸Œ^øC¤:R©<­ù´æÓš0}ÛômÓ·AÌ×1_Ç| ªªªªªªPµwÕÞU{CPfPfPfÑ"«ûW÷¯îuNÖ9Yç$4Ød`“�P™ÊT¬¯Y_³¾ú_ë­ÿµ®G+‡L0á/™o7ßn¾LIž’<åýÇ‘a„ô¸Øãb�‹0Âx„ñc(;°ìÀ²Áf†Í › k/k/k¯ëQ‚ð1§…¿D¯·^o½ÞÀ.pxÆ3ž�áK׆/¡›g7ÏnžP7¾n|Ýx ˆ ‚t�Z„O�¸ˆCøKZUmUµUU¨\¹råÊ•¡J|•ø*ñðe— _&À›Ão¿9 ©Î©Î©ÎºN+§D0á/ю׎׎‡š7jÞ¨yŒ90æÀXZii¥¥• {Möšì5à«ï«ï«á�Ã;‡wÖujA>¢€ Éó.Ï»<稜•ZVj”¹Zæj™«à tP:(alÆØŒ±ðEþù_äÃl‹Ù³-àvøíðÛáˆÇœ‚ð§‰&ü)šÉšÉšÉð¼ÒóJÏ+A•×U^Wy ÄKlÑv†G �…~}ûõí×z”ïQ¾Gy¼x7ð.´=h{Ð Ÿ>)|¢ëQ ‚ð1LøSÒ§§OOŸñYñYñYP¶MÙ6eÛüúöòòòÐrBË -'Àøžã{Žï g®ž¹zæ*¬2Ye²Ê²»ewËî¦ëÑ ‚ð1LøS"‹E‹,ú}ôûè÷�~%üJøýþ÷W•ªJU%ðµóµóµƒØZ±µbkÁ·9nsÜ ®~\ý¸úº¥ 2QÀ„?å鸧㞎ƒR­Jµ*Õ Lw›î6ÝýÇÛq^ï¼Þy=̬3³ÎÌ:`×Ë®—]/˜yaæ…™àY¹gåž•ÓõhAø‰&ü1Ž8â/í_Ú¿´‡òžå=Ë{þõfMO™ž2=£¬GY�²†¦‰M›&ÂB§…N �à\á¹Âs… yJžÒßП ?QÀ„?$qXâ°Äa������•*Wª\©òß×¾�ƒ�ƒ�tµèjÑÕ†žzvèYØÑfG›m`{ÿíý·÷UUU]φ º$Vâþ�w‡ÞzwóóóÀÎÂÎÂÎâïïGf.3—™ƒ7Þx¶Ûl·Ùnƒ¥Ï–>[ú âœãœãœa˜á0Ãa†`žožož¯ëÙáß$ŽÀ„?$dtÈè�ÑàRÙ¥²Ke055ÿwâáàáàá¾Ë}—û.‡¬åY˳–ƒŸ­Ÿ­Ÿ-ÄÖŒ­[S׳#¿I0áwÑækóµùðb‹ /&@…-¶TØ `þ½ŽÇ�;‡)½¦ôšÒ ŠŸ-~¶øY˜é<Óy¦3oÞ¼H!…]Ïš ÿ$QÀ„ß%»cvÇìŽ���eg”�Qv†îò˜ô7éoÒF4ÑxDchêØÔ±©#,Ø´`Ó‚Mp¹Ûån—»÷¸Ç=]Ïž ÿQÀ„ßåõæ×›_o½êzÕõªCiEiEi…®S�~‚~‚~|mòµÉ×&0 Ø€bŠÁ–Ü-¹[ra÷ÛÝow¿u¸:\®ë´‚ ü�ÄEÂï~0ü`øA(v¬Ø±bÇÀð€áúNUD¶X¶X¶шF€]ª]ª]*,«µ¬Ö²Z�P˜P˜P³fÌÓdÓdÓä¿Ú« º$ŽÀ„ß¶ˆE,‚—™/3_f‚G„G„GÈ:È:È:è:ܯ«h]Ѻ¢5Ìž2{Êì)ó(æQÌ#ðññ�„ .è:¥ …(`ÂoÊj’Õ$« ¼3zgôÎÊ +3¬Ì0]§úýœ8 p3;Íì4³X³:fu fÕ™UgV«V1¬¢®S~º´Ó´Ó´Ó ¢~DýˆúðrçË�/w¨@]§>v¢€ ¿)íTÚ©´S�ß6¿m~[pÚì´Ùi³®Sýqæ—Í/›_†oC¿ ý6¼OxŸð>sœç8Ïq†›¯n¾ºù ˜Ìd&ë:í‡'çtÎéœÓ°qÁÆÀKõKõKõÿ~_PdPdP$l9¶åØ–cpµ×Õ^W{Á“åO–?Y[·n „¬ñYã³ÆÃ�=7öÜØó6ÌÛ0o$VL¬˜(þÀ~…øLøMá3Âg„ÏË Ë Ë °Ûa·Ãn‡®SýyÐkx¯á½†ƒãsÇçŽÏaÍ¥5—Ö\‚ĵ‰k×Bû‚öí @o‰Þ½%ºN­{²/e_ʾy”¨ú *ĵ�k×2ßf¾Í| O}*ú@YeYeY%œØub׉]`jhjhj=ôlгØDÚDÚDÂ9Å9Å9”hU¢U‰V`\̸˜q1ørý—ë¿\mV·YÝf5Ô^V{Yíeà¿Ù³ÿf°«jWÕ®ª®÷žð¿ˆSˆÂ/J—0.a`Ž9æ`?Å~Šý`ó˜§ëtÿ¨HE*÷šÞkz¯)l4ßh¾Ñn^¸yáfplíØÚ±µ®w¢ðkdÒ�tDø0HÛ¥íÒvø¾Í÷m¾o•vTÚQitÝytçѺN÷áyiþÒü¥9,­»´îÒºàÖÞ­½[{\rpÉÁ%Á¼�yó6ºËwíܵs×ÎÁÌœ™93s`î˹/ç¾Ëa–Ã,‡�û2÷eîË ÿZþµükv.ì\Ø9°lkÙÖ²-¸GºGºGBVͬšY5!üføÍð› ßW¿¯~_(S®L¹2åÀ¨³Qg£÷.òÉÚŸµ?›(|`€IDATk?¼<øòà˃ ×L¯™^3(}½ôõÒ×!óPæ¡ÌCkkkvÁvÁvÁ ¿N�þ:ˆ“ÇÉãäàääÆý�û÷‡W^=xõìííÁu�ë:×uÕ1ªcTGHªšT5©*—2.e\ œ;7vn ©õSë§Ö‡Ä…‰ ‚kE׊®‹–Ëè˜Ñ1£#ÄzÄzÄz€û÷î;@ñNñNñN—Ÿ0á·ˆ&üµ«ÚUí ck�­=¶6ôôíéÛÓêxÔñ¨ã¡ët®„ 'NÀ²:Ëê,«šsšsšs0öØØcc��ãÇ=Ž{þý\gžxf ,_¾8vìß±Ç~p°u°u°Õõ¬ Â_#¾þKÊΔ�);!÷\î¹ÜsP®„] ;]§úð9´uhëЦ¶žÚzjkpˆtˆtˆ„YÁ³‚gCغ°uaëþ½<’™d&™Aahaha(Ô:[ël­³�°)aSÂ&]Ï– ü=Ęð_î·ºßê~+ØÜds“ÍM`éú¥ë—®ƒ0ƒ0ƒ0]§ûx¨ ÔjØ»j諾«à⃋.>€ÁÏ?ü¼{ö: ²R²R²RºN+'q‡ð_âÄ-ˆ[6 lØ4ý«úWõ¯ê:ÕÇÇ@a 0P@ï=½÷ôÞö•í+ÛW†Õn«ÝV»ABÙ„² e¡}³öÍÚ7½“z'õNê:µ |\Ä)Dá¿$M8špl5¶[ È¿�!÷Ãüyw¹Ë]hQºEé¥a¬|¬|¬Žzõ:êÎo8¿á<ä_È¿�/ï"ˆ(`ÒHi¤4b¾Œù2æKpYï²Þe½®S}B¦1�iP}_õ}Õ÷�¯‰¯‰¯ '''C€Q€Q€¤œO9Ÿr^×aÿ7uououoH4L4L4)QJ”u�JøÜˆ&�ç˜ç˜ç©‡S§§H§H§È¿Þ®ðËJ�*uªÔ)˜m5Ûj¶¨ÝÔnj7ðÃ? ò`äÁȃºNù òÉ'®Î½:÷ê\”Êe�\>¹|ryHž•<+y¤ïHß‘¾Ò§5Nk i¾i¾i¾�¸:quâjPÅ©âTq�W�W�W‰Þ‰Þ‰Þ ŠQŨbÞëîÇÇøÄ׋¯_R:¦tLéÚõÚõZñÖgO0€¼½y{óö‚J¦’©d`µÀj�Õ]§úôYk¬5Ö˜¨�¨�¨…².e]ʺÀ÷[¿ßúýVx¦|¦|¦ÔuÊ"¾¾¾pÖó¬çYO¸þîú»ëïà~Àý€û°ìÀ²ËÀ¸þãú�ë;üvøíðƒ=–{,÷XÂÐ=C÷ Ýw†ß~g8¼+÷®Ü»r08fpÌà¸c}ÇúŽ5äTÊ©”S V~»òÛ•ßÂ.ƒ]» `kÀÖ€­põÒÕKW/éz6]L Û'Û'Û4k5k5kÁò¢åEË‹ºNõù0q2q2q‚Á?üZk[k[kaÁ•W\�K/m¼´´»µ»µ:\ÿ§FÜJº•t+ åÚ”kS® ´êת_«~P<¥xJñ(ô/ô/ô‡î »7ìÞ:”ëP®C9ÐŽÔŽÔŽ„¼×y¯ó^ƒëy×ó®ç�’”¤$Â�:7êܨϬžY=³‚‘ G.¹ªXT±¨b;Æì³c hžjžjžêzï º"®BH�¤ ŒË—7.M-šZ4RH!E×é>úÝõ»ëw‡Î~�ý:û�Ý\»¹vsa½v½v½Ö$¬IX]îv¹Ûå.(j+j+jë ¨5j�NJ'¥÷¯žü±™\3¹fr l¢m¢m¢¡°{a÷Âî€>øCÊP ‡r€F4¢È äòˆ=(zD¯Œ^½ö¾ÜûrïKxåõÊë•è_Ô¿¨¤cÒ1阮÷š +¢€ Ä¿‹ÿ,<,<,<Àà¼Áyƒ�àb‚OV!„@аinÓܦ9,¿·üÞò{�Ø+±Wb/˜30g`˜è›è›ü›¿Í�DI€=öØS´z¼n¸½÷ÿ`à€8∮q�k€'žxw¸Ã0Zj´Ôh)89;9;9Có»Íï6¿ ­Z9´r…¹Â\aú×õ¯ë_ç?…Sø¼ˆSˆÉ>É>É>`ll¬ë4ÂÿUñ\ÅsÏÁÌ»3ïμ 1110/}^ú¼tH I I ù÷òXšXšXš@”G”G”ÜwÿÝýw�Ð7¡oB_H;’v$íd}�õuÖ× ÷½Þ÷z߃ÝC»‡váɘ'cžŒ�W%^•xUrn8¨:¨:¨:À»gïž½{Ù³;fwä?WE Ÿ'±””À÷)îSÜ¡Á“O<�V&­LZ™è:•𿨦¨¦¨¦ÀŽù;æï˜×'^Ÿx}" ÷î9Üj}Uë«Z_é:¥ ü3ÄØg.÷Vî­Ü[�q%ãJÆp*çTΩœ®S ¿—ržržrôµìkÙ׺œír¶ËYX¾wùÞå{áäù“çOžíJíJíJ]§„¿—(`Ÿ¹Ü†¹ s‚ª�ª�ªXí·Úoµ_ש„?J/M/M/ ÚvmÛµmWø–oùØ{pïÁ½a뀭¶€ü°ü°|±(³ð‰ì3—{9÷rîe�ϓϓÏeoeoeo]§þ´©Le*Ô:Pë@­0£ÒŒJ3*APà†A aYÚ²´ei�i�i�i­ë°‚ð׈ö™Ë›Ÿ7?o>è—Ð/¡_CCCu�Jø»”Yfd™‘0+bVĬÈ®˜]1»"ø}ï÷½ß÷ççç¤ë”‚ðçˆö™Ë�•;+wè¿Ô©ÿ½½â²äOŽCŠCŠC LY?eý”õà\×¹®s]˜ydæ‘™Gà…û ÷îºN)Œ(`Ÿ¹¼õyëóÖƒ~ˆ~ˆ~´7hoÐ^ש„ŠÉX“±&ca#4²ldÙÈü/ú_ô¿×__|}±®S Âï# Øg.#5#5#ŒÇ�5 ŠXE¬"Vש„š¢º¢º¢:ôÔcP�AðMËoZ~ÓÖ×]_w}]8v0ì`h–k–k–ë:­ ü2±”Ôg.£CF‡Œ`fofofòhy´ò|ä©ëQŸ:QÀ>sê+ê+ê+`¸Úpµáj]§>4Vï¬ÞY½ƒ Ö¬'XƒÇr�åËÁ7Ý7Ý77~Üøqc™2#dŒrå2ÊfŒ›1nÆ8Èè”Ñ)£“®G!|ªÄZˆŸ«…,d!Ì9ÿåü—PŠR”ºmè¶¡Û]‡>T…Ñ…Ñ…Ñpb艡'†Â £F'Œ â@Ä�ˆpYvYvY¦æ¦æ¦æ°úÞê{«ïAo�Þ½=t�^øÔˆ#°Ï””+åJ¹P° `AÁPÎRÎRÎÒu*áC÷Ó ïõêÔ€”�);Sv•²WÊ^)[´]vfvfv&¬‘­‘­‘AÌÁ˜ƒ1âµð7ì3%Õ–jKµAm¢6Q›€B®�+ħAørœrœrœÀ¿›7ÿnpÚþ´ýi{�^I¯¤W?ß>heÐÊ •°½áö†Û‚ôVz+½Õõ(„O…ø'ësL0Á U�*H@6S6S6Sס„]ê€Ô© )-)-) L:˜t0éT¡ U~¾}áªÂU…«`k™­e¶–�çkž¯y¾F×£>¢€}®~zÔ»#Ž8*T¨tJøÐ•ð+áWÂV[®¶\m Ǧ›zl*Ll9±åÄ–ðÅ‘/Ž|q”K•K•K‹Þ–––\6¸lp�–…- [þ �~|’gáÆÂ�…!ohÞм¡�u$ëHÖȬ˜Y1³"dxexexAŠ&E“¢�”{)÷RîAÚƒ´i Ó#Ó#Ó2wdîÈÜ999999P +�È@š)Í”Äxq#³ ˜éSÓ§¦OÁo¼ïeÞ˼—ÁèÚ£k�® —×]^wyu=êzÔ®ø^ñ½â »£vG펂Fé�Ò¥ƒ×¯7^o yPò äAïïï éWÒ¯¤_�¬ˆ¬ˆ¬Èl›Ù6³-dggC^í¼Úyµ!dþÈü‘ ~¬~¬~ êPu¨: ã ã ãARKjI Ò é…ô �+<d’I&ÈÃåáòpÐËÖËÖË"‰$ô ô ô @á¬pV8ƒÁaƒÃ‡Á`©ÁRƒ¥`8Ýpºát016161³†f Í‚ù—æ_š æéæéæé`wÆîŒÝ°�³�³�ãçÆÏ�ŸƒávÃí†ÛÁp‚áà  ðPx(<€ºÔ¥®®÷îÇC0Aþ¸ÉLf2h¶h¶h¶@úÜô¹és!9 9 9lSlSlS ®²®²®T�T�T� ( ( (æfÍÍš›•FW]i4(·+·+·ƒ©ÒTiª³f Ì€™«™«™+˜ß3¿g~ì«ØW±¯F«ŒV­£¡FC�†‚É“&Àx ñ@ã� l¬l¬l úçôÏéŸÙ,Ù,Ù,P¶U¶U¶Y†,C–êZêZêZPX¥°JaÐ~§ýNût+èVÐ òç7Îo ÙAÙAÙA�û ÷AîÈŸ�?;6äææBÖɬ“Y'!¢mDÛˆ¶�Õ «AVÈŸ=>{<äſſłžBO¡§Å"Å"Å"0Ùe²Ëd8=vzìôœG8�pŽwï:Þ—ª.U]ª‚C?‡~ýÀ ¤AIƒ’ ë*ë*ëªë�î‰Ëè?SÚm€6fîž¹{ænðªèUÑ«"´ÙÖf[›mºN÷ss æÌ�pûpûp{0ébÒŤ ¸X»X»ˆçZýýs˜Ã�}#ûFö x7îݸwã Â3Â3ÂB‹‡-±oc߯¾…ô€ô€ô0hhÐР!Øì¶Ùm³ì§ØO±Ÿ¥]J»”v‡Þ½zƒ¾§¾§¾'Ø>´}hû,õ,õ,õÀä€É“ {&{&{¦ëIø rÈ!TSUSUS!siæÒÌ¥�u#ëFÖ Èœ58k0¤ôOéŸÒÞ6{Ûìm3ˆSÄ)â�"K‘¥È knÖܬ¹ \§\§\aaaàÖÙ­³[g(W±\År¡¸qÿâþ`kgkgkrg¹³ÜYדðÏì3¥]­]­] 3]fºÌt¯-^[¼¶@›m´9ðÏõ/þ^ü=8æsÌç˜tºÑéF§`[Ͷšmµ_ß‘à#ÁG‚áqùÇå—‡Š�+>®ø:,tX©KS—¦.…fç›�ovÎ[�·:oÑÑÑ0hÉ %ƒ–€a”a”a”®gÿᾯ¾¯¾©sRç¤Î�góŸÍ6ny¸åáˆL‰L‰LÍÍͰëb×Å® ¸wuïêÞJ½-õ¶Ô[(5®Ô¸RãÀq€ãÇ ðSø)ü@n!·�[Î8óüƒúWI¯¥×ÒkÐlÒlÒl‚ Ï Ï OxëôÖé­DÆDÆDÆ@øÉð“á'!Ú$Ú$Úò—æ/Í_ v'ìNØ�€J•*UªT <==Á9È9È9Œ]Œ]Œ]€Ýìf·®Gû׉SˆŸ)Ù|Ù|Ù|Юÿ\ÿ9hÒ5éšô¡ßm²m²m Ÿ#Ÿ#Ÿ²Ë²Ë²Ë@5ªñ ¬0²0²0N~òû“ßC»Þíz·ë Íž7{Þì9eeeƒüªüªü*˜hL4&PÊ•r¥N?}üôqèÚ'´O(¤x¤x¤x€,T* '™“ÌI¦ë½ñÏ“¥D)’¿Nþ:ùk¸»öîÚ»káî⻋ï.†øåñËã—ƒe¤e¤e$TN¬œX9ZŒj1ªÅ((1¯Ä¼óÀ|†ù ó _O¿ž~½_èè ÷{ýi2w™»ÌôýõýõýÁl(úo jP�‚¥`)rœsœsœ!¹OrŸä>ð¼ÇóÏ{Àcé±ôX‚Ë“.Oº< ŒªU7ªUæT™Sex—ô.é]Ü[»·vo úkô×è„W‡Šö¹zÍk^ƒb©b©b)þ|3­£ÖQëa�Ç=†Ü Ü Ü П¦?M(‰ŠD(Ó£L�2= ¥tJé”Ò�ð,áYÂ30ßg¾Ï|hohoho€E–E–Ex6õlêÙôkë×Ö¯ Œe,cßëØ 'œ ®}\û¸ö>3|føLx7òÝÈw#!÷uîëÜ×P¢~‰ú%êƒÝ*»Uv«€›Üä&˜¬4Yi²ägågåg!uFêŒÔ°"cEÆŠ (çXαœ#|}ñë‹__³³fgÍÎBÄʈ•+!csÆæŒÍà˜æ˜æ˜ŽÕ«9VƒW^ x5ôîéÝÓ»R¤)E‚Í6?ØüšŠšŠšŠ�Ý;»wvop5u5u5Ù;Ù;Ù»o÷l.Ø\°B2C2C2áü„óÎO€°.a]º€Íi›Ó6§¡®y]óºæPÅ·Šo_(^»xíâµA±I±I±é½å A7d¾2_™/˜bŠ)`:Èt�é ¢uZm}´õQHY�² e¼J{•ö* n”¸QâF XÜ~qûÅíÁ¢‡E‹ÐxVãY�g�—“—“—Xõ°êaÕ0à 3]�ö׉ö™úé;Å*Å*Å*(Ø_°¿`ÿ/l" ‘…ÀÞ¥{—î] ÁÁÁÐ÷pßÃ}ÃÙ}g÷�ÝMMšš45�bÎÅœ‹9ÃhÕhÕhôø¾Ç÷=¾“/L¾0ùê”®SºNi˜0vÂØ caÂÑ G'…æ4çýEÎ¥Ò ideeeeeAþàüÁùƒ!Å-Å-Å rnäÜȹ7ÜpcìËÙ—³/öžÝ{vïY�]—]—]ÙAÙAÙAÈÞš½5{+Í š4l6Ùl²Ù¹!¹!¹!p»æíš·kÂåg—Ÿ]~•“*'UN‚m“¶MÚ6 Fžy~äyØ÷zßë}¯áIÜ“¸'qÐòtËÓ-Oƒ[·:nu ¶Ul«ØVðè»Gß=úü­ü­ü­ÀC ÿÁý©>¬>¬> ÷/Ý¿tÿM?š~4’œ“œ“œ¡Ö”ZSjM�‰u&Ö™X§¨°ê�Ñ£?FןFáï&ë ë ë¶l;Øv[l±¼&yMòšÉS“§&O…»ýïö¿ÛÎW<_ñ|E8²ñÈÆ#¡QT£¨FQвl˲-Ë‚õ7ÖßX£ëQýœ(`Ÿ«ÏE(  P=S=S=êP‡:E›É¬eÖ2kp<ïxÞñ<$~“øMâ7жeÛ–m[BöÔì©ÙSáèú£ë�®‡YKf-™µ Ág„ÏŸà>Ü}¸ûp�=•=•=“&L€6K›¥ÍšÑŒfïõ;L6L6 ÊÔ-S·L]°ßa¿Ã~ÔlY³eÍ–àRèRèR%;—ì\²3HU¤*R € -Z´ ùH>’SlL±1`·Øn±Ýb¨¹°æÂš Áé¥ÓK§—0Ãi†Ó 'ð1ò1ò1‚î{»ïí¾.´¾ÐúBkxlõØê±8';';'CL¿˜~1ý �²�²�´Ë´Ë´Ë@¨TBó˜æ1ÍcÀÐÏÐÏИÈD&þ�ûï)Oy ¯ê¼ªóªl¼ýñöÇãããÍ-š[4·€&‡šjrìVÚ­´[ Ìf6³uýátf XPTÐÚœnsºÍih|³ñÍÆ7áIæ“Ì'™p8öpìáX¸òìʳ+Ïà˯¿üú˯¡É‰&'šœƒ.] ºèz0¢€}öL#M#M#!»mvÛì¶¿±a>ùäƒä'ùIï=Ðм‚yó �Ù5³kfWÐ*µJ­äÛåÛåÛAi¬4Vƒ‘ÊHe¤õXõXõX  h@ÑÉý_c€À¶°¤ÒiÄŸ¨ àÇ8Ò)FÞFÞFÞPÇ»Žwo¨&«&«&ƒ[Ån»U ödìÉØ“A3ƒfÍ„UTPœÝ�Ý�Ýu—[¬Äñ™³hnÑÜ¢9d�Î�5ú76üñd»ìŠìŠìJÑË)ÛR¶¥l…�ÂFòòò ((4¢�ÞkG�5ЉNt*º?çWýtDÕ“žôY€,@ðÞÏ<Ò’m—m—mÊSžòEýÈ~�ý û�ÿÜ *¥H)R HÝ¥îRw�u‘u‘uûVö­ì[Am‡Úµ`@ð€àÁ°rÁÊ+@ã ÆA�ƒ Ð³Ð³Ð˜Ï|æFaT'ãpÆáŒÃ��’�’�Âßvî0çE΋œ°*jUÔª(¸htÑ袌i>¦ù˜æ0¤Ù�fCš�}Oûžö=O<Ïãþ$¥¤””øÄúÄúÄ‚˜˜˜L1™b2æt›ÓmN7ý>ôûÐïu—S°ÏœåsËç–Ï!Ë8Ë8Ë4Í5Í5¿ôÄݾô¥/D©¢TQ*86èØ cƒà‘×#¯G^ÐŨ‹Q#HèšÐ5¡+dǪ̂™QÞ,}³ôÍ{K ½éò¦Ë›.�v5íjÚUˆ°‹°‹°ƒÂR…¥ K½×ßK^ò¢¾�ú6ê[HmžÚ<µ9¼,ý²ôËÒ�q"ãDÆ ?~ ü¤uNëœÖB÷„î Ýó#æĠtÓtÓtӢ列69mrÚ§+ž®xº"„Î �::Ïë<¯ó<¸×á^‡{àÐéC§�†Ûãn�»=ÒâÓâÓâ!vJì”Ø)�Ð6¡mB[HR'©“ÔE±�ô<ÒóHO˜Ÿ9?s~&ä�Ê•?êÏ@*�`�ׯ5^�”‘”‘”³{Ïî=»7T;^íxµãÀ5®qí7zË[Þ»ïÞ}÷î;8pðÀÁ!fcÌÆ˜�ýs¤MÐ&hà–ö–ö–Âê…Õ «Yã³Æg�‡³ögíÏÚà ¿~7ü€øßí„^½zá¯çþ›6 lÀ· ß&|›�¾hôE£/`É•%W–\�ðAáƒÂýû¹DûÌ™=5{jöò4yš< Ì,˜YðKk¾EA˜D›D›DC‰:%ꔨC/½8ô"4ÎlœÙ8\. ¬ê½ª÷ªÞPþiù§åŸùX¦Y¦Y¦Á"“E&‹L ñ„ÆOÚÓžöïûÿW?Y<·xnñ-Y´dÑhú¢é‹¦/@î#÷‘û@½‘õFÖ K.,¹°äØWµ¯j_¼ûx÷ñî‹g.ž¹x&8z8z8zÀtõtõt5tÒýI÷'EWE¶ªÕªV«Z0âØˆc#ŽAÉ�’!%CÀv·ínÛÝ ¦¦ݔݔݔ0õØÔcS��Qk£ÖF­‹b·xÞây‹ç0âüˆó#ÎÝ€úg›tlÒ±I�““ïL¼3ñØ7·onßü4d‚ &`°Ü`¹ÁrXŸ´>i}Ÿ >|ê¯ޤrR9©+|Vø,0Ž1Ž1Ž�û9÷sîçÀÎÀ��;A:$’Aò¾ä}Éû /3/3/¤ÇÒcéqQ;?=gLø0è�ׯ?¾ªÿUý¯êƒOœOœOlx·á݆w�¹9ssææ/�¸‘ù3÷,õYê³TXûÍÚoÖ~þ.þ.þ.`hhX´Ý’'Kž,yϦ=›öl¬ Z´.   t=ŠOOŒŒŒ?Ìo7¿Ýüv0òû‘ß�üÊí/·¿Üþ?ß®º»º»º;t1èbÐÅzF÷Œî >Õ|ªùTEMEMEM0×3×3׃´‘i#ÓF‚þ)ýSú§Àôžé=Ó{�f”f”fŠêŠêŠê`ff)!)!)!`0ß`¾Á|°Ì³Ì³ÌƒµµÖÖZ[ žö|ÚóiO˜i;Óv¦-,Û¶lÛ²mСA‡@�Ó5N×8 ékÓצ¯ƒo ¾5ø Ú´1hÙÓ³§gOýþúýõû]=k¦5ÓšiÁ$É$É$é×ǯ=¨=¨=i}Òú¤õýkú×ô¯ý¸Ìæ s°èdÑÉ¢ä?ΜÿÒ¦Lòîòîòî`UÛª¶UmÈ]œ»8w1hÌ4f3�7�7�7bˆ! Ïž/<ô§?ýA›¤MÒ&8ÀPöPöPöÕÕÕ�w”w”w›d›d›ä÷®¦]”½({dÎ:œu *T6¨ V£¬FY�y%y%y%Èk˜×0¯!dxgxgxƒ¶¦¶¦¶&$D%D%DA©»¥î–º V»¬vYíú Ÿ§fêfêf0¯Ü¼róÊA¥Á•W �*wªÜ©ò?ÿ{".âøÌ™ššBá‰Â…'  ~Aý‚úE?ÏŸ“?'X ±b1Ê” (‰—/'^†â§¸®ñ ºsãÎ�;7ÀÉÆÉÆÉ<êxÔñ¨ó×Û¥íh…Í ›6‡çWŸ_}~²Kd—È.ÏŸ;>w„Îz�õ:ëÁ¹¬sYç² àuÁë‚×0ÍlšÙ43Xæ¶Ìm™hC´!Ú˜¾gúžé{`eç•�Wv�¥ÆRc þøã`�5Ö€;î¸CH‡�!àÄÅO\„báÅ‹…ƒS¨S¨S(l´Ûh·Ñ435353¡}óöÍÛ7‡Y»gížµzOï=½÷t?~>ü<ä™ç™ç™Ãt×é®Ó]Á$Â$Â$âçÃ/|Zø´ð),¸|àò�Pø¤ðIá“_—Z«Öªaúùéç§Ÿ‡åK—/]¾dËdËdË€¬`´¯Ò¾Jû*ðè꣫�®Âþkû¯í¿ÍTÍTÍT ï¬ï¬ï ÷�ß?~ÿ8Ø.³]f» *¬ª°ªÂ*8êqÔã¨Ô?Xÿ`ýƒ`ÕÛª·Uo¸Øïb¿‹ý`Lç1�Çtggg02`$8w*îT ‡- }´}´}´ \¤\¤\�oß¾###ˆ˜1;b6˜_4¿h~f™Ì2™eò×?NŠóŠóŠóÐxwãÝ�wÃá…‡^íbÚÅ´‹ÅeÅeÅåî÷D°ÏœùjóÕæ«A3T3T3rÆçŒÏvØaGѪÛ?^\Wôƒr”£œ®Ó‚–±ŒeðÚÿµÿkpÝçºÏuÈüeþ2ÿ¿¡ýø�@©ˆTD‚—£—£—#´¬Õ²VËZ°Îs�ç:O8Xì`±ƒÅÀ%Û%Û%BóBóBóÀÄÄÄÄÄŠ—+^®x9xâýÄû‰71>b|œË9—s.OZ?iýä½S«ÄO|Ñýye~(óC™À¡—C/‡^ÐJj%µ’ drÉä’ÉàTΩœS9xz÷éݧwÁiµÓj§ÕP�X�X�µZ×j]«5x×ö®í]† qãÆ üO�üƒÙ³ fµÿ$ûIö“l0Ùh²ÑdcѸžnºýévȈ̈̈„7OÜ;úì€; î,¸³ hÅ”®5\k¸ÂõÀë�×a]Úº´ui`ŸjŸjŸ VfVfVfp§þ�úwêCÐwAß};Ïí<·ó\Ñ�ì^x}à5Èýä~r¿ßù™ù\‹»w-¡¡¡�f‘f‘föØcÿþºˆïÀ>s»,vYì*:‹3�3�3ÕuªÏØ�·+Ⱦ’}%û dKeKeKÿz³¿ÖYd‘UôrYã²Æe�!zTô¨èQ òSù©ü@–,K–%¿÷þŸ®®œÇ<æýŽ×ÿ/=ôÐé–tKºÒKé¥ôòçíÈæÉæÉæú裴¡ mK,±åååÐÞÖÞÖÞ©²TYª §¼OyŸò†iIÓ’¦%Áô—Ó_NYtºÞk½×z¯�Å,fñ/äßË^ö‚•‡•‡•ttíèÚÑV˜¬0Ya‹º.꺨+$�H‘4dkekekÁÐÙÐÙЬ/Y_²¾6ñ6ñ6ñ s–9ËœùÙš�ŠŠŠ Ù¥Ù¥yïTžþ!ýCú‡ŠþéÌG푵GÖ “§Nž:y*l ܸ%rå4Êivì*ØUÃ�† 7Bh‹Ð¡- n]ܺ¸u`;Ðv í@�?“?“ÿ�‹%›cŽ9ðŒg<iŒ4Fó|nÿQÀ>sЇЇЇ`5ÆjŒÕˆsŒsŒsü;ìJWºÂÓqOÇ=g\ϸžq…|—|—|—ÿývi�´GÚ… /^m 6PHÑåù»Sâfçfçfá½Â{…÷É_ò—þŽ#°o; %(T¦2ï}W‘T3©fRM°�l;Ùv2(ª)ª)ª�d.™Kæïµ£D‰d£d£dï_eùãm²²²ï½þSaðÿ¢íÈ ƒ —\r¡�…²…²…ü§àÉÉÉ>øàÞëõÓ›Rk©µÔª„W ¯Žu8Öá´/Ó¾Lû2PÊ­”[)7жҶҶ:Ò‘Ž?×OóóÓ’aßìÿfÿ7ûaõãÕ�W?†¨²Qe£ÊÂf‡Í›@^(/”¥)Mi~~ûÄ�¯ÿ´ÔüxÛ‡l‹l‹lË{¯ÿ´èá�ß¡/7^n¼¦ Ÿ6|Úp˜ûrî˹/áì˳/Ͼ„3¯Î¼:ó ʾ.ûºìkðöòöòö‚;Oî<¹óÌG˜�0FO=a4ÈûÈûÈûü}Ûˆk×"®�E‹&MÀ:Ð:Ð:ð¯·û¿ˆ&à˜å˜å˜q;ãvÆíüçúyÖøYãg�a×Ô]SwM…Ä´Ä´Ä4È7Î7Î7þßïOËHËHË€€Ø€Ø€XXvyÙåe—)ºÿëáää±>±>±>êêêñ×Û•!C˜Ž5k:¢:EuŠê­Z?´†{Þ÷¼ïyC»�v!íB tréäÒÉ�h”h”h!=Cz†ô„äëÉד¯C¶u¶u¶5dšfšfšB2É$i+ÒV¤­€¤.I]’º@Š2E™¢,º!?:?:?äååáVâ­Ä[‰�X*±Tb)HÞ’¼%y ¤öJí•Ú Þ$¼Ix“Ùòly¶R=S=S=!…R€¬}Yû²öAºuºuº5�/_<j ¨5 Ö¨%«%«%‹\‹\‹\°³³ƒÄ�‰7þ|\9[s¶æl…¸ùqóãæÃ6«mVÛ¬ =(=(=œf;Ívš v—í.Û]†äzÉõ’ëAæíÌÛ™·!ådÊÉ”“ öP{¨=ŠnçH1M1M1…¬SY§²NAº{º{º;¤X¦X¦X¾÷ºEºEº¤oOßž¾BŒCŒCŒaßê}«÷­Í!Í!Í!(1©Ä¤“À*È*È*¢ƒ£ƒ£ƒáeÍ—5_Ö«ÇV�­ƒ¡ÚPm¨†(³(³(3Èo“ß&¿Í_ÿ<|[ðmÁ·pÉ÷’ï%_¨S?¦~ (N+N+Nÿó¿'â;0(Z÷vþíüÛù@zÐãïïçQØ£°Ga�šš __þúò×—Áà¡ÁCƒ‡ÿûýÖC¬‡X³Ef‹ÌÁ³2ÏÊ<+Òxi¼4¾èè��³ÚYí¬†&ÞM¼›xÆÃo8 SSS`£¶QÛü‰#N}'}'}'×~\ûqí!öëØ¯c¿†w>ï|Þù@Wó®æ]Í¡Ft�èÑ�s=çzÎu�ÇÉãäqÛ ¶Al¨µ¸ÖâZ‹¡êȪ#«Ž„Ì¡™C3‡B m m -xÄxÄxÄ@Úõ´ëi×ÁÓÊÓÊÓ <Ôj5˜T4©hRfØÎ°�a qã:Æu„”Ã)‡SƒçQÏ£žG¡ÜörÛËmi�´@Z#-GZŽ´ó�æÍ7‚|¾|¾|>Œ 0*,ÆXŒ±ó¿ç¡IÏ&=›ô=¹ž\Oþ ãZRuIÕ%`lblbl_û¢ØÅ 2/2/2Z,j±¨Å"¨s Î�: ¬dXɰ’0¸éঃ›¾øâ ùyùyùyСb‡Š*‚I¢I¢I"dnËÜ–¹ :Œê0ªÃ¨¢¥Õþóz»í:´óýæûÍ÷ƒƒƒƒƒƒ¸¬pYá²¢;FwŒîåååàõÔë©×Sˆ;w&î hhh@Ú½´{i÷@-‹–EúFë­k£/�¾4úRÑÙ?JûTûTûö§íOÛŸ¹ rä6€&·›Ünrû_üE‘A’¤à#ÁG‚�HÒ�GC y$I™W2¯d^ùûÚÏx›ñ6ã­$�;3î̸3’ÔªI«&­šHÒ�ùwæß™/Iý úô“¤gnœ¹qF’éÒ;¤'IG¯½vôš$%«’Uɪ¢öÖ|±æ‹5_HÒ0Å0Å0…$iÛhÛhÛHÒ‹I/&½˜$I‡Fuh”$/~¼øñâ’”<}Z’Ž5:ÖèX#I:¶åØ–c[$).2.2.R×{£ˆª‹ª‹ª‹$-6[l¶ØL’&YL²˜d!I ­Z'´Öu:áC³7hoÐÞ Iä>È}�»$©ej™Z&IécÓǦ�•¤îí»·ïÞ^’¹r9äòÇÛ/¼[x·ð®$í:¾ëø®ã’ôÿW¬‘¤ðá5Âküûã§ èɹ�‹Æ’%=Jzô÷µ¯T*•J%˜1;bvLÜMÜMÜÁÆÊÆÊÆ ´*­J«‚çÖÏ­Ÿ[C±‰Å&›W�^=zõ(lm²µÉÖ&?oW¦‘idH��:;u6ÌΚ�5; ÔNj'µ¨.¨.¨.@jHjHj¤ L˜6¥.J]” ùNùNùN��˜�˜�KR—¤.I…¼°¼°¼0]ï0Øo°ß`? ÑÑÑ‚cÇ:Žu`ÖÙYgg�…‡Ë.{¸ ´©ÚTmª®Ó ºVsLÍ15Ç€‹ÒE预5«Ö¬Z³ ¶¤mIÛ’­Ûµn׺4kܬq³Æ¿¿Ý$£$£$#XvfÙ™egàZÿký¯õ‡ ò ò rp½ïzßõþ¿?^QÀL¯›^7½^tŠ#®k\׸®_ûJG¥£Òž84½ÙôfÓ›°´ûÒîK»Ã~ðÃH\ž¸²ùÈæ#Áúµõkë׺Nÿs¢€ ÿÅÃÁÃÁÃŽ�?>þøxÈLÉLÉLËF–�,ýùv³Wd¯È^Q…Q…Q…�R)¥RJ%···€ŠÃ+¯8®•¿VþZyØùzçë�¯!Ö"Ö"Ö¤õÒzi=¼yóæÍ›7ðî컳ïÎBfLfLf „·oÞ 90äÀ¸×÷^ß{}AVVVVVZtmѵEWp+íVÚ­4´éÔ¦S›N°Ùu³ëfW(Ó§LŸ2} ìñ²ÇˇÛjl«± ôõõþ…ûYþ*EgEgEg¨­©­©­ÏÁžƒ=Cp»àvÁíàÜÝswÏÝ…€Ý»vƒÕs«çVÏÁk§×N¯�à™æ™æ™kÖ:¬e°2X¬ëQ –ÖKë¥õ‚´i'ÒN@XzXzX:\/~½øõâðòÕËW/_�õ$ëIÖ“ ™u3ëfÖPov½Ùõfƒyˆyˆyˆ®Gñ¿‰Å|…ÿ’¿8qþb[bl‰±% ß ~ƒú ‚š53jfüùv5U4U4U õnêÝÔ» yªyªy ‡-[e[e[e[HuHuHu­‡ÖCëzwõîêÝúЇ>`jj ÙñÙñÙñ õÔzj=Á¼”y)óR�›š›š› ªLU¦* ¶l5Ø ÖǬ�Y+ZËNÝ_Ý_ÝR˦–M- Üà7ÀØØØØØÌ®›]7»ÄGœ®÷Ê_§¦¦)·Sn§Ü† †A ƒÂíã·�ß>ñ[ã·ÆoË+–W,¯@eŸÊ>•} ÂŠ +*¬÷Eî‹Ü�¹Â\a®¹‰ÜDnÂ{OîþUMhBP½Q½Q½�¨�¨�¨s s s�'š'š'ˆªU3ª&({*{*{ÂÉ_$‘ õ]ë»Öw…’¶%mKÚ‚Ò[é­ôþë±þm¢€ ÿíÇçF-Ì]˜»0ìÇÛ�·}Oõ=Õ÷oxì†ðaÑÖÖ†x§x§x'»v/ì< yò0"ËG–�,ÿÿr~pØè°Ña#”QzDéPv`Ù�e‚ãÇŽÀ~»ývûí`cc23™™ÌL×£üø¨®¨®¨®@rùäòÉå!qkâÖÄ­ð6÷mîÛ\xú*ôU(ÄÈcä1rP Q Q ‡Í›6C妕›Vn •ÛUnW¹”t-éZÒŒRŒRŒRt=º¿�(`Â/ºd~Éü’9Ï8žq<æ½™÷fÞ0t5t5tÕu:á÷ãÒGªQªQªQ}>ú|ôy‹ ‹ ‹ƒ×o^¿yý¢ZDµˆj¹!¹!¹! 2V«ŒAùZùZùÊ”5(k.�\¹4‚K\,qlllÁØÞØÞØ”«”«”«@¢ Q†€¢PQ¨(y7y7y7þ³”Ô‡NŠ�"¤(Ô/Ô/Ô‡‚‹ .‚ê[Õ·ªo!ÿ«ü¯ò¿‚Ôj©ÕR«At»èvÑí vQì¢ØE;+vVì,HÔOÔOÔ‡ü ü ü ¢5í«ÙW³¯îjwµ»ÊhËhËh¡L“2MÊ4óûæ÷Íïƒ,S–)ËÔõlüóD~QÌ×1_Ç| 3‡Í6søv÷íîÛ\â\â\>�SjÂßC½Q½Q½Õ|TóQMˆ ˆ ˆ½‘z#õF‚W°W°W0dxdxdx@’w’w’7ä¾Ë}—ûôõõA±_±_±¿è¹_&sMæšÌ+7+7+7°lnÙܲ9˜62mdÚ ×®3\†; wîåPåPåP0ìjØÕ°+è?×®ÿôë=Ö{ 2­L+Ó‚¾©¾©¾)È¿‘#ÿ Ož,< Ú¶Ú¶Ú¶ Ù¯Ù¯Ù… .õ#õ#õ#È7Í7Í7…üêùÕó«ƒj§j§j'ädçdçdC¦C¦C¦¤J=”z2ÏgžÏ<*;•�ÊÔêu¨Õ‰êDÐ?®\ÿ8XXX€ã5ÇkŽ×Àé¡ÓC§‡àÒߥ¿K(ѳDÏ=Á\e®2W�q q q ÈÊÊêzï랸ˆCøEN›�6;m»p»p»px¸îẇëÀ~Çš»Â'N3L3L3 ®ª®ª®ª`çÐ�Cw…ÆsÏi<z¶ëÙ®g;035353ÞñŽw  W…«Â!ëHÖ‘¬#�––™i™i™i�ížížíéÁéÁéÁ�ìžìžìi9i9i9�Ð+¡WB/P=R=R=‚‚ì‚ì‚lP»©ÝÔnP`\`\` …ß~[ø-üÿZ@ÒJZI …« W®â?kŽÉÊÊ‚ž§ž§ž'ÈËË]¼£¸¦¸¦¸å Ê”ƒÃ‡ ƒ�³�³�3Ž1c8Ìš4?½*zUô«‰V­&‚Y9³rfåÀü•ù+óW`æjæjæ fififi`²Éd“ɦ÷VÝïF7º½7ÑxÀ]ïí—8~Ó®r»Êí*¯6¼Úðj̪7«Þ¬zºN%èJÚδ�i;a«ÓV§­Nð¤ÿ“þOúC¿ýô[õlêÙÔ³yyy“¿Þßä‘GОö´é±ôXz ÚmŒ6$•¤’T ¥KéR:0Œa ÉWò•|�PB †2”¡ …IaRÈË˵+k#k#kì`;@vSvSvd®2W™+Èd2�9ÊeŽ +%+%+…x²«Žˆ&ü¦°#aGÂŽÀ­ ·.Ü þ{ý÷úï]§þqÏyÎsx|ûñíǷᇖ?´ü¡%Xß±¾c}†d É’%”Pb€®Ã Ÿq QøM...`–a–a–Á‚'O‡åË–ë:�ðOÉ~žý<û9z}èõ¡×pÁú‚õkh{¢í‰¶' ]»víÚµ#g#g#ç¿ÞŸ ü¢€ ¿É¨¼Qy£òàçç—3/g^Î…�ÂGrµ\-ÿ$)ðªõ«Ö¯Zúªëª®« … >€)ò)ò)r(ºüéòÿÂsžá÷§…ß%þIü“ø'0Íušë4W÷rÜËq/¡B� 5*ÔÐu:áÏRª U…pjÇ©§vÀ¡æ‡šj sæ6Ì…®Å»ïZÌ Í Í ÿz‚ðw‹ù ¿‹ãŽ_8~UÎU9Wå\è|¡ó…κN%üYúúúà'ó“ùÉàœÇ9�s0úøèã£�Ã0Q¸„›(`ÂÒ"¼Ex‹pxäøÈñ‘#DGDGD‹UÎ?xùùùpdü‘ñGƃo”o”o{TìQ±Gàoäoäo5‡ÔRsÈÜeî2w]§„ß&N! ˆTYª,U†…F ��Ér“å&Ëa¤×H¯‘^ºN'ü_o*¿©ü¦2lðÞà½ÁRV§¬NY ýçöŸÛ.x>ô|èùä‡å‡å‡u�Vþq&ü!²g²g²gÐ9½szçtx°àÁ‚ àuðëà×bõr�Ëo˜ß0¿!{xìá±à{Â÷„ï (žW<¯xøó/æ_ jͨ5£Ö Q¸„�›8þo¼ñ†•6+mVÚ@nznzn:L|2ñÉÄ' Ë�eÈþÂêõÂQ3¢fDMØÐgCŸ } ­lZÙ´²Ðzÿéý§ƒçIÏ“ž'‹ *ŸQÀ„¿ä]Ü»¸wq0ãÅŒ3^ÀàÀÁ�ƒ¡ÎÁ:ëÔuºO—ÊYå¬r†“-N¶8ÙŽ1>b ^Ö^Ö^ÖÐýP÷CÝ�e°e°¥82>Qâ¢ð—8s.æ\ :Øu°ë`;Êì(³£ dZgZgZë:ݧçuõ×Õ_W‡Ù›foš½ ._4¾h £º�ê>ª; �=4Z.áó ŽÀ„¿EÞÆ¼�yaVÏY=gõ„ §+œ®pú~Ù÷˾_ê:ÝÇ+·OnŸÜ>pJ}J}J Çškz¬)Ô5­kZ׺÷îÞ»{o°(°(°(ÐuZAøw‰#0áoa4Àh€Ñè;©ï¤¾“àbÚÅ´‹iEkè LèÁЃ¡Á·¹osßæp%üJø•pøöÄ·'¾=ƒÌ`Dá>oâLøGì�°wÂÞ p#ýFú�tðëç×ϯXÖµ¬kYW×é>¸¶íÚ¶kÛ åš–kZ®�öaíÃÚ‡�éÓ¦ t�V>l¢€ ÿŠkϯ=¿ö6mÚÓ#§GN�„²³ÊÎ*;K×éþ9’™d&™Áý^÷{Ýï[/n½¸õ"˜®5]kºúõé×§_ðˆñˆñˆÑuZAø¸ˆSˆÂ¿¢þªú«ê¯‚†¦ MšÂêÅ«¯^ i}Òú¤õÑuº¿_ªSªSªÎœ8VíYµgÕð ö ö .Z‹P.AøóĘð¯Ê+Ì+Ì+„LX0÷÷÷`‚4Aš �Á-ƒ[·t�ò�“ÚIí¤vpûÍí7·ßÀ–‡[ny/^8¼€þÊþÊþJ(]®t¹Òåt�V> âLøWéééÃÈÓ#O�< qµãjÇÕ†Cv Ù1´]´]´]t�ò÷KJIJIJ�•²•²•2XŸ²>e} t°ï`ßÁ¦[M·šn% — üĘ S¯l_Ù¾²¿Ç~�ýC¯ò½Ê÷*ͳšg5Ï‚ŒÍ›36éb§Š�*�Ì™52ƒbÞż‹yÿûy544à®ù]󻿰Åm‹Û7(ö}±ï‹}Ê (7 ¸Lq™â2E׳+Ÿ6}]>oe’Ë$—I†!‡‡rÖç¯Ï_Ÿ÷ î܇#Ž<8ò¶ïÚ¾kû.XUlU±UÅ ûóîÏ»?ÿëýçNÎ�œ;iŠ4E(Ö)Ö)Öý|»ÔZ©µRkÁŽ´i;ÒàÁÎ;섯Œ¾2úÊš%5Kj–Ê­Ê­Ê­ºžUAø<ˆSˆÂÁûKï/½¿„Æ /l¼ÆÚŒµkk®¯¹¾æ:¤¦¥¦¥¦Áñ‘ÇG ¹ssçæÎýóý¥ÞK½—zÆ^{uìU8=ðôÀÓ‹~®§§·Rn¥ÜJ�)w§Ü�rRÓSÓSÓaö™ÙgfŸ�¶Nm�Ú:�ò”ò”ò”®gQ>/¢€ º5‰IL‚Ç/¿|üv Ý5t×PxtóÑÍG7¡àiÁÓ‚§E›_~vùÙågõÇ»“^I¯¤W°óôÎÓ;Oæ[›nmºóäóäóäpÏúžõ=kXm´Úhµ¬[³nͺ5Ð6·mnÛ\˜zzêé©§¡ÔÌR3KÍÔõä ÂçM0A§&6LlS\¦¸Lq�³›În:» èMozÿÂö$€cúÇô�ý‰à÷Ÿß~ÿ9¬HX‘°"Ôrµ\-‡{·ïݾwzwêÝ©w'ˆ­[-¶ø=ñ{â÷Ú™´3igžžžºž5A@0AÇ,šY4³hSÆM7eô(èQУ,š[4·hþóíµIÚ$mœ‰?&¢ó£ó£óÿw?éëÒ×¥¯ƒ…Å[X ^¯y½æõš÷Ú¥¥‘ñ‘ñ‘ñ`™m™m™ Î;œw8ïÐõ, ‚ðKDtJ©P*” hØ °A ¬�X±>6uØÔaSh:¡é„¦Àð�áÃEï{òüÉó'Ïáæ”›SnþÆÕ~’L’I2ع-r[$œ°8aqÂâ×·W�T�T�„ÅM7]Ü.&_L¾˜¬ëYá—ˆ&|PŒW¯4^ �’;%wJ†]÷vÝÛuöì ØU:VéX¥#„„„Á�N8ª/T_¨¾rÉ%·¨½ ¯‚¾ ú VD®ˆ\ ùåóË痯ÙÌd&xxxA¥E•UZM´M´M´ ‹—ÅËâu=+‚ üq˜ðQ�&I“¤I¾%|KøØðfÛ oàü€ó΀fÉÍ’›%ƒ2@  �@�@�@Øã¹Çs�'r|Èñ!`élélé ®–®–®–PûXícµ�AórÍË5/U:UéT¥T|PñA`ÐÄ ‰A]�^„_" ˜ðQÒ¶Ô¶Ô¶„Ùýf÷›ÝæT˜SaN�¥@)äÕåÕåÕÁm›Û6·mÐ)£SF§ ¨gSϦž Ôð«áWÃ&9Lr˜²[²[²�p +Aøœ‰™…�’|²|²|2hêjêjê‚ö¦ö¦ö&°Žu¬i”4Jc—�]>v9 ©1¤Æ�¿ÐÐ-n! — |”Äw`ÂÇ©�hÞ¹Þ¹Þ¹`—c—c—²m²m²mPΰœa9C(Y«d­’µtV„‚(`ÂGÍÍØÍØÍ|,|,|,`íÓµO×>…m´YÐgÎ8œ—v]Úui°šÕ¬ÖujAþâ¢ðQ{sûÍí7·¡äW%¿*ùôSõSõS�bšbšb˜º˜º˜ºÀ†bŠm(VtU¡ÏpŸá>Ãu�^„¿B0áãôãwW�ª?ªþ¨:TôªèUÑ GGG‹6k4®Ñ¸Fã@)‹”EÂÆÔ�©SAj%µ’ZAc³Æf�Í€}ìcŸ®%Â!N! ¥¼y;òv@dÅÈŠ‘¡Âº ë*üÂ*òLcÓ á hø ,X8°6½ÛônÓ;¸˜v1íb0‘‰LÔõ¨Aø#ĘðQŠ10b ¶(lQØÊ—5.kü¿ß×`VƒY f7¸Á ø!ð‡À�RH�&4AÜö%q&|”Â…- [Å.»\ì2˜w1ïbþ{žä\�jTƒF ŒÁ�*Cª ©[ÙÊVàBÍ 5/ÔjS›Úº¥ ¿E� —þô§?¼P½P½PAyÊS��“�“�ûí d ¡þÀúëYIYIYIXk¶Öl­HR�TÍZ6kÙ¬%p†3œÑõàAxŸ(`ÂG%³}fûÌöííí­µnÔº°Œe,ûóíÖ{QïE½ÀqŽsÖ´YÓfM�¶J[¥­Ðœæ4ÿóÍ ‚ðLø¨$)’I PßSßSßçE΋œý cŒ1Ô³¨gQÏd×e×e×a]üºøuñ ÉÕäjr¡elËØ–± s—¹ËÜu=‚ðyLø¨<_÷|Ýóuàêê vgìÎØý�§öZÒ’–à�7Þ€^O½žz=a•z•z•4]4]4] Í‚6 Ú,Ù$Ù$Ù$]ÏŠ |žD>*¡OBŸ„>÷†î Ý‚ÌUæ*sýçú«“Z'µN*ÈÈÈÀŠ +*¬¨ZS­©ÖÚkÚkÚk=ôÐÓõìÂçE\…(|rMsMsMáí±·ÇÞƒÊM*7©ü/^ï^kR­Iµ&Áw�¿kü]c8¸åà–ƒ[àð­Ã·ß©‚TAª ëY„Ï‹(`ÂG!¶olߨ¾ *§*§*¥ŒJ•2ú÷sÔ¸SãN�;0&kLÖ˜,8TóPÍC5áàñƒÇíZíZíZ]Ï– |D> ±ûb÷Åî + + +0h>Ð| îòT ¬X-Æ¿ÿfü8võØÕcWá@â�ĉ ½�^H/t=k‚ðiLø(¼Hz‘ô" JW(]¡tPf*3•™ºN_”ÿ¢üåaâʉ+'®„Ó×N_;} öxìñØãÚéÚéÚéºN)Ÿ&QÀ„š¶’¶’¶¼¹÷æÞ›{àvÏížÛ=]§ú¹J�*=ªô&dMÈš�g½Îz�õ‚]Íw5ßÕ4_j¾Ô|©ë”¿Âö…í ÛCRfRfR&ä=Ê{”÷Hש]Lø e7ÎnœÝR|S|S|Áu¼ëx×ñºNõë*Ü­p·Â]˜\ir¥É•àb»‹í.¶ƒ�SwNÝ9´M´M´b±E¢÷Fï�Þ —-/[^¶µµÚZmýëÛkïjïjï‰é'¦Ÿ˜«N¯:½ê4Üž~{úíépoŽ÷V@X½°zaõ k|Öø¬ñpÖþ¬ýY{¸áwÃï†@º½ðwLø E­�Zµär¹\.‡SJL)1Eשþ·rËm,·¦œ›rnÊ9¸Ö÷Zßk}a[ñmÅ·�«ÆUó^þÿ¡‹{÷.îÜN¹�r; " " "~}û´i#ÒFÀ‹, e‰–%Z–€Ê‰•+'Âýª÷«Þ¯ á³Âg…Ïãã㸟s?ç~ì ܸ3¤CÒ!é$ïKÞ—¼òç-Î[¬ëÙþ,=ßé:ˆ ü’ œ œ H9›r6å,4ÏnžÝ<dÍdÍdÍt�î³)nSܦ8T8\áp…ðÓu§ëNWH>˜|0ù TލQ9ôlõlõlu�ö×iÊhÊhÊ@Êš”5)k '8'8'²Þf½Íz …F¡Q€R©T*•�é•é•é¹·roåÞÕuÕuÕuP{¨=Ô`«o«o«•nTºQé˜Û˜Û˜Û€ÜFn#·y¯ã·¼å-DV�¬YvnÛ¹mç6hÖ¿Yÿfý¡ô�Ò7Jßׯ®�]C©&¥š”jÆ��?†�£!GCŽBâðÄá‰ÃÁ³‘g#ÏF°dË’-K¶€e®e®e.8E;E;EP)™)™)™�¹!sCæP|­øZñ5P‚”€”è”è”hдӴӴƒœ9/r^€^k½Öz­!÷Qî£ÜGPè[è[è í Ú´Óõ^üôˆ#0კ™™λœw9ï*º¡øcã~Áý‚û˜f;Ívš-ܹsçÎ�;°Å{‹÷o(ü²ðËÂø;²Üâ¹Ås‹Ã¤j“ªMªþÉþÉþÉp´ÎÑ:Gë€_'¿N~� âTÄ©ˆSpüÑñGÇAÿ‰ý'öŸ;Oï<½ó4oq¼Åñäääƒòåʇ¨%QK¢–ü¼_µ½Ú^ma›Â6…m‚$¯$¯$/¸Ûønã»�!fxÌð˜áèèè -Z.´|¯k¬±ÜqÇB¾ ù&ä81õÄÔSá^ì½Ø{±�<*yTò(8óòÌË3/aÕíU·W݆mÛ¶ÀšFk­i‰×¯%^ƒÉÙ“³'gÜsNÌ9[«o­¾µ:W ®\VX­°Za›b6ÅlŠÑõÞût‰&|�ÔNj'µ¼þfø›áPÖ³¬gYO]§úë\§¸Nq�Óƒ§O†ûîO¸?6TÙPeC(ˆ*ˆ*ˆÒuÊŸ3»lvÙì2˜››CÉy%畜C<‡xñýú5ôkÀ‰á'†Ÿ¥—\z0d§g§g§C›–mZ¶i ÍÚ4kÓ¬ ”M+›V6 râsâsâAÝNÝNý G( c…±Â<xðN“�&;M†ÖoZ¿iý\ëºÖu­ ÅÜŠ¹sƒ´Öi­ÓZ¿×@<ñÄ­mYæ‡2?”ùz9ôrè­ãZǵŽ£}FûŒöÁæâ›‹o.Í*7«Ü¬2ô·éoÓß.Æ\Œ¹)3Rf¤Ì³l³l³l0›m6Ûl6ôqíãÚÇ\»v �|:ùtò�VÖ­¬[YÿÞYþ(QÀ„Rvfvfv&dNÉœ’9œòœòœòt�êïSjT©Q¥FÁ´éÓ¦O›�º?êþ¨;¬sZç´Î TsTsTst�ò§8Å7Üp+zÙÎÏÎÏÎbÇ,ŽY Xa…:::ƒõ%ëKÖ—Àn‰Ý»% C† `4¢�~£_}ôÑé–tKºÒKé¥ôò½Ÿbˆ!0�yÌû�v~\òë§vhG;ÚAÞy?äýo›½mö¶\7¹nrÝ޼8òâÈ �o—o—omGmGmG���³B³B³B°ñ±ñ±ñË–#,G@ù·åß– îÛÝ·»o×õNût‰&|�2jdÔȨšëšëšë`7Ûn¶Ýl]§úû¹¨]Ô.j˜1ÆüóáEÔ‹¨Q°ºçêž«{B¾_¾_¾Ÿ®S¾§4¥) ²¹²¹²¹E/çdädäd€Y'³Nf�€bˆ)Úþ?æ'?~×$$$2™�Ìç7úýiûoeßʾYKYKYË÷~n„F [ [ {ÿóOýúá‡_Ñvd�Að˜Ç<½d½d½d°Üg¹ÏrÔ9_ç|�óÐyRçI�'ÁFåFåF%TÑVÑVÑBáõÂë…×ßßÿ�[¹ rAePŸRŸRŸÒõNût‰&|�ÞöyÛçm0ïoÞß¼?XŸ´>i}Rשþ9Å·ßR| Ì;sì̱ðöÅÛo_Àʨ•Q+£ Ç/Ç/ç(dRš”&¥Aljljl*Ü)q§Ä�Û,¶Yl3hò Éƒ& iKÒ–¤-�y;óvæmH”2(eð†7¼�„Q £FAÖð¬áYÃ!áU«„W¿Ða&™dBb`b`b döÉì“Ùb¯Ç^�½ªgªgªg�t-éZÒ5H[‘¶"m$uIê’ÔR”)Ê%¤Å§Å§ÅC~t~t~4È/Ê/Ê/ÂÍë7¯ß¼šMˆ&ê�®7ºÞh*T&¨ DùGùGùCNïœÞ9½!wTî¨ÜQ�10c`Æ@HŠHŠHŠ€B‡B‡BÐtÖtÖt†î+ÜW¸Ãf÷Íî›Åcwþ1¢€ ¤È;‘w"ï€ã ÇŽ3@/\/\/\שþyŽG�8�io§½�öbÝbÝbÝ`ùÒåK—/…¬à¬à¬`Ýå“K‹¥Å�a�a�a)Î)Î)Î0`ù€å–Cmemem%Ó+¦WL?üxðc�¾�¾�¾M�¦@Sz7õnêÝ„‘Œd$`²Öd­ÉZÐfi³´YïõWMª&UýaúÃô‡ÁÈïF~7ò;0J0J0J€¬�Y³‚çÏ ž Ó¡N‡:‚4×4×4Wð,ëYÖ³,tRwRwRƒIE“Š&a†÷ ïÞ \¦\¦\’»ä.¹Ã·¿øí@¨�S!§BDÅGÅGÅCòâäÅÉ‹!w}îúÜõÐau‡ÕVCÝGuÕ}ªÑªÑªÑ wWï®Þ]ðV{«½Õà™î™î™®ËOÔ§M&ýH×Aá}þÇü�ùƒ’õKÖ/YzZõ´êi¥ëTÿ¾äùÉó“ç ,hf;Ìv˜í€1寔SÌG›�6ýïå‘>"}D:¸5rkäÖÆ>ûxìc]Ï’ð¹G`Â¥àhÁÑ‚£ß&¾M|(=½ôôÒŸñZ‚¶“m'ÛN†©ë§®ŸºT7U7U7!`RÀ¤€I�z*õTê¿ðKòÛä·ÉoA?A?A?2™ŠL¤'¥'¥'éz–„Ï•(`Â%µZjµÔj�;0w`î@(áQ£„‡®SéžÕf«ÍV›aRì¤ØI±À NpÚ.´]h ÉË’—%/ûçú·¹lsÙæ2,Þ»xïâ½0½ñôÆÓƒE¾E¾E¾®gGø\‰SˆÂ%ôBè…Ð °¡ûæá—ˆ&|PâÅ-Š[6n6n6n`4Ûh¶Ñ'xÿ×ßÅ$Õ$Õ$FÍ5gÔ(ݯt¿Òý`îws¿›û¼=ðöÀÛºN)ÿ QÀ„J´o´o´/8UrªäT ¸ÊU®ê:ՇϨšQ5£j0T9T9T _¬þbõ«anôÜè¹Ñ~(üPø!]§üu1¥cJÇ”†X)VŠ_h¿“(`ÂAûLûLû RüSüSüÁa Ã@‡�ºNõñQ.V.V.†óÌ0¼c¼c¼c`›æn‚_½øêÅWºNY$µ_j¿Ô~PPPÇ7ßp|¼ûvìÛ±ðxçã��w›ø7ñoâ!´qhãÐÆðÂð…á Cxžø<ñy"<-xZð^ç¿Î�ÏÛ>oû¼-hii�¦�¦�¦¼*õªÔ«RpÿòýË÷/C̸˜q1ã€RHÑõl”(`ÂAƒ �þ"ýEú °kn×Ü®¹®S}¼SSS¡÷½èý4kÚ¬i³¦à¿Ç�ÿx2ýÉô'Àí Ùò‡eƒûñ÷ãïÇCòƒäÉ !*!*! Æ}=îëq_Ãv¶³¸\örÙËeáX¥c•ŽU‚©¡SC§†Bn±Üb¹Åà¶Åm‹Û0ù›ÉßLþrïçÞϽçöžÛ{n/¬¶þÙúgð¢ä‹’/J‚! †,áááy8¿L0áƒ�ŸŸŸŸŸy'óNæ�¹�ÜF|:ÿ2½,½,½,øú˯¿üúKørß—û¾Ü���pÿÎý;÷ïè._±1ÅÆ¶¯l_Ù¾ÏKž—ÇŽ'O€ÂQá¨p„SÏN=;õ 2·gnÏܹ9¹9¹9�=={zötè”×)¯SœÛnÿ¹ý`|Úø´ñip¨îPÝ¡:T_y|åñ`Ž9æºÞ7Âï&Vâ>ûò÷åïˇ׷^ßz} ¦N˜:aêàx ëtŸ�{÷ î@`½Àz�õ õÁÖ[„Î;oì¼ô}õ}õ}ÿþ~c«ÇV�­‘í"ÛE¶‹‰-&BÎ…œ 9Àb�Å:‹uàžãžãž\ç:×áÕ½W÷^݃�d´Éh“ÑlŽÛ·9®ëTÂOÜW»¯v_ S{Oí=µ7¼T¿T¿TÃòfË›-o9!9!9!ºN)|®DtJí¡öP{]4`zÀô€©X»ïƒã²Îe�Ë:˜6pÚÀi!qVâ¬ÄY0/`^À<È È È ÐuJás# ˜ Sê8uœ: K–*,F©F©F©ºN%ü‡Î�:ôóÓÎO;ê¯Õ_«¿†ysæÍ™7’ã’ã’ãt�Rø\ˆ&è”:X¬ÍlÍlÍl0niÜÒX\ðÁ³2·2·2‡Iç'�ŸtLÕÿ�½»Ž�âÚÿ?þš•lˆ{ �  @Ð Á‚•Bp-R¼Å¡ÅÝݵ¸C!h±âî,ƒ$„¸ëJvw~ünox|ÛÞÛ[Ú.-óü§²³ç¼gNàÓ™9sƪЪæ‡Î� ñÎñÎñΦN)ù§“ ˜Ä¤ Õ…êB5èëèëèë€y„y„y„©SI~+ëÕÖ«­WØ c.Œ¹¥ÍK›—6‡yyóòæåAdzdz¤´H®äO"0‰Iéêê‚ñ+ãWƯ@uNuNuÎÔ©$ÿ«bÅŠÀðχ>üs¨íXÛ±¶#,踠ゎðäõ“×O^›:¥äŸF*`“ÒÓÓ1ELS@™ªLU¦š:•ä÷Ræ)ó”yðåÍ/o~yÚÆµ�kË-´|ܬv³ÚÍj¦N)ù§�–’’˜T¾&_“¯¥ƒÒAéÊfÊfÊf¦N%ùPŠ2Š2Š2ÐñPÇC�m¬m¬m,lpÛà¶Á r—æ.Í] Ÿó9ŸÂxa¼0þ½´hÑ›ÙÌfàk¾æk@… •©÷Nò±�ÎÀ$&¥>¥>¥>ÊËÊËÊË l¢l¢lbêT’?ŠPK¨%Ô‚f�›unÖF¹Žrå û‚öí ‚ƒC=8ôôôо÷¦ñ›ÆoC°_°_°vvv›zo$©€ILªÀ¥À¥À”k”k”k@¹M¹M¹ÍÔ©$–:åꔫS&/›¼lò28÷âÜ‹s/`—j—j— Âç„Ï ŸcüÇø�ñ‡©¾S}§ú«S¯N½:eêô’��TÀ$&Up³àfÁMPŽPŽPŽùcùcùcS§’üÙ*m¯´½Òv˜)ÎgŠp{ÑíE·A·õÝÖw[§lNÙœ²�×Ï_?ýµ;ÔîP;0Œ¦N/ùXHLbR††† ª£ª£ªcê4’¿š|…|…|¤´Li™Òž¥xùàex­{­{­3ujÉÇB*`“ÒŸÖŸÖŸÁUp\M�FòWI­�Z!µ Ïž3<N?=üôð_ß>R©‹ÔAðñàãÁÇ�óœç¼©÷BbjR“˜”Á×àkðQ+jE­©ÓHþ*²$Y’, 84phàÕ}«ûV÷³³³_¸Dh8l8l8 ‡úê¨?¼®üºòëÊ¦Þ ‰©IÔ1ûcöÇìá±ì±ì± æ¦ÏMŸ+­ÜðÉ0 Œ�Ð!¡CB8zâ艣'àÀ¶ÛlƒGß<úæÑ7 Óëô:=È^Ê^Ê^ÂÒKO,=c&Ž™8f"p�{Üã ã ã зַַ†üãùÇó�Cz‰ôé% 3)3)3 ò<ó<ó<‹Þܬ¯¯š8Mœ& ¥ ¥ ¥Àð¹ásÃç ß£ß£ßò¡ò¡ò¡ Ÿ(Ÿ(Ÿòûòûòû ŠUŪb¡X�b=Šõ‹,€eoËÞ–½Áþ û/쿇³g΂ÍF›�6A1D1D1ä{ä{ä{€ L`‚©GåïCzL"‘˜ŒÌBf!³€’çKž/yF}6ê³QŸA7Y7Y7œés¦Ï™>°m¶ Û&ÀƒÒ˜Ä¤ŽÙ³9f���07cnÆ\i5úO޾—¾—¾d$e$e$AT‹¨Q-à™ö™ö™î¹Üs¹ç/Z¼hñ¢¤†¤†¤†@ÕµU×V] í·kÜ®1¸utëèÖ\·ºnuÝ Ž.Ž.Ž.à�ï�ï�æ5Ìk˜×ÙVÙVÙV† Äa   <ä!o¼ñþ Á3È èAz€ñ ñ ñ ˆ;ÄâçˆsÄ9 “ëä:9d~–ùYæg�~>ý|úyHMM…ä†É “BÜWq_Å}I“& õ>õ>õ>0Ÿk>×|.”Õ•Õ•ÕA¥•T:¾å}Ëû–/*äf1f1f1€vØ™zTÿ|R“˜Ô±æÇšk�C‡<ùó/!ŠÝÅîbw׋ëÅõ +&+&+Xb‰å¯ïMÚ›´7ið²ÛËn/»AÝúuë×­Ž_9~åø•…ÊBe0f³ŒY`Â=Ã=Ã=!="="=æ;Ìw˜ÕU;Tíø;ø;ø;@¹%å–”[²U²U²U¦Þ»?žt QbRfWÌ®˜]ý!ý!ý¡?¿¿œpþÁÒJ¤•H+· Ü6pÈúÈúÈúü|ûd—d—dØ2aË„-À³ƒgÏðnó»Íï6æƛoj mj¶©Ù¦&8à€°²áʆ+BÀÒ€¥K¡ ]èbêƒm?Ý[z~ýùõç×áâš‹k.®�×Ç^{} Ї)µ×Ô^S{ Tù¼ÊçU>÷ ÷ ÷ P©T*• ØÅ.výB�iLcSïåG¨(T*‚Åj‹Õ«Á ,×¾®}]ûB-jQ‹¢7™'žN<�x^]zuéÕ%¸ïßÿ¾?\riÈ¥!àjájájMRš¤4Iÿïý¿÷ÿl¿±ýÆöSï퇓 ˜Ä¤Š½)ö¦Ø(\Q¸¢pˆmŶb[”‚RPþñýUH®�\! Ê”+(BW¡«Ðõ×·�QǨcÔu;êvÔm§§§Ë8Ë8Ë8ÈrÍrÍr׃®]BqYqYqèŠëŠëŠCܨ¸Qq£@;C;C;îl¿³ýÎv¨�^;½v:X¨-ÔjS�ÂG“®IפíÁ·ß §óNç�΃¼è¼è¼h¨W¢^‰z%à‹“_œüâ$”þ¢ô¥¿¹›ÜMîfêôò+ò+ò+P’’”Jî(¹£äh>³ùÌæ3!)4)4)n©n©n©àDÿýOô‡#£ŽŒ:2 šn~¸ùahnhnhnÛî¶Ým»›z¯þwÒ4z‰IYlµØj±tƒuƒuƒ¡ð^á½Â{EŸ§lLÙ˜²‚͂͂Íàô±ÓÇNƒjüPã‡ðÔñ©ãSGÐ=Ô=Ô=„‹õ.Ö»X.Æ]Œ»Wî†] ƒðÇá�ÃCn‰Ü¹% MHÒÐ;é�ôN?Ï¥ ÐèàÉã'�Ÿ<†³³3¸¯¸¯¸¯€ô‚ô‚ôȽ‘{#÷¤ËÒeéïým’u—u—uÚÓžöp~äù‘çGÂb§ÅN‹�àêü«ó¯ÎMSMSMSˆŸ?+~œlr²ÉÉ&prßÉ}'÷AòÑä£ÉG!I—¤KÒÁ‘ä#ÉG’á®Å]‹»pµÌÕ2WË@ú“ô'éOà’Ï%ŸK>ð¦ÿ›þoúÿùã'ÎgŠ3!dbÈÄ�‰0-jZÔ´(84õÐÔCS!P¨TÀâ”Å)‹S ÿÚþkû¯…rÃË /7\*\4¡ŒPF(%‚J•‚.~]üºøÁ¢¾‹ú.ê _,úbÑ‹àö·¿¸ýLÚ>iû¤íp¥ç•žWz‚þ¸þ¸þ¸©÷â·“ ˜Ä¤,C-C-C¡p@á€ÂP¸ªpU᪢ÏWWWa«b«b«âßÅ¿‹VϬžY=ƒ•ÕVV[Y ^¿}ýöõ[xxëá­‡·`mÎÚœµ9�>-}Zú4HÓÄ4Þõz×ë]/Xm¾Ú|µ9\-¸Zpõç¹Z…V¡Û™¶3mg‚¹§¹§¹'8Ÿp>á|¬š[5·jG¾9òÍ‘oàüÑóGÏ}¯ 4 o"o"oƒ�ÁòªæUÍ« Åwß]|7d•Î*�U–î_ºé~иiÜ4n�œœœœœ +¾_ñýŠï¡0ª0ª0 6”ÛPnC9¸rþÊù+ç!¥_J¿”~�¶?mÚ~8_ü|ñóÅ!òzäõÈëÞ¸åžÉ=“{¶Ùo³ßf«î®º»ê.Ô˜Wc^�y°(tQè¢PhwªÝ©v§À{ì–²”¥¦þ­û„¸à‚ Xt³èfÑ _i|¥ñ˜·wÞÞy{¡Ý÷í¾o÷=ìÛ¸oã¾�°Ìj™Õ2+HÚœ´9i³©ÃÿwR“˜”E€E€Ev*ìTØ ý ý ýŠ>·Ž·Ž·Ž˽–{-÷‚G+�V­ ¹¾¹¾¹äoäoäoàÙ�gwžÝ'œpJØ–°-a ëw¬ß±>Ô¯Y¿fýšà´Åi‹Ó�u”u”u¡�ÐFhóó\²G²G²Gà¦vS»©Án«ÝV»­àSϧžO=°=c{Æö Ø4³ifÓ èOÞ?ãÉ"‹,�}!ûBö899�ÝY»³vg¡ÂË /+¼„w5ÞÕxWBû†ö í Õ/T¿Pý”oZ¾iù¦péý¥÷—‚ØIì$vë‰Ö­'B5u5u55t›ÕmV·Yà]Ï»žw=˜m6Ûl¶4ŸÐ|Bó?áy¢äÞɽ“{ n,¸á[÷†o…é›§ož¾zžìy²çI°ëm×Û®·©»$¿¦Øž(ö´rlåØÊ.\ÆZÆZÆZ0ëóYŸÏúÂÎ…� ûˆ_0+0‰I©VªVªV‚ñ¢ñ¢ñ"†††¿·�9rà Oxœæ4§‹>VÌRÌRÌÍ1Í1Í1– K…¥ ˜ f‚…ŽBÇ÷ÚË$“Ìÿ!  2‡‰ÃÄa@DüþýCÄ1ø–où´�Ú@m dXdXdXÀ¥ KA—‚ ìUØ«°W”””W-®Z\žò”§ ¼^ /ß‹ÙAÖAÖÌ/š_4¿òÁòÁòÁÜ8%K–< œXpbÁ pîãÜǹÌè6£ÛŒnàUÞ«¼Wù?®¿OF1ŠQ ôåôåôå3Ì0ûëc¸®:Øö´íiÛD ÑB´ñˆGEÝj 5…x\þqùÇå!ñbâÅÄ‹>>Ï ž<‡ O7<Ýð¼Ëy—ó.#FŽ9b$Xϰža=ã¿·cìgìgìo¾yøæ!„Ž: Ó Ó Ó><§zƒzƒz„e†e†e‚¦›¦›¦¤f¦f¦fÂãÝ�w?Þ Y‹²e-ú íD†E†E‚¶¢¶¢¶â‡çû¿ô§ô§ô§àäô“ÓON‡%�–4ZÒÂtaº0DÝŠºu rå Ê9›s6çl†'�ž4zÒË$–I,óÇç2a6Âl|ñú‹×_¼†vªvªv*X¿yýæõ›!©JR•¤*|¿¿—TÀ$&¥LU¦*SA1C1C1ÔMÕMÕMßÛ`‹Xºµºµºµpiÿ¥ý—öÃÆÚko¬ Õ�ª;Uw‚ªNU�ª:A|ëøÖñ­!{{ööìí� HP$(@;[;[;Â߆¿  :G�£Î"ÆFŒ�ûó\ú®ú®ú®þMø7á߀ú ú ú SdZ™V¦…sÌ0Ì.˜]0»ðÛÛš Í…æpçÛ;ßÞù&��4vÒXÈ�È�Èÿ€3ÚŸ$NMœš8Ö·Yßf}H©–R-¥älÏÙž³&VžXybe¸_ÿ~ýûõ‹¾§î®î®îþ í4Yßd}HÙ›²7eï‡çû¿^�}=öõXø¡á hÍÆ4Ól (.(.(.À†‡nxaaaPX¢°Da X2uÉÔ%SápÂá„à |®�W¡ŠPÚNh;¡í¨ìXÙ±²#ëƒõÁz064646üóúÿÍD‰Ä„²m²m²mDqx‹á-†·ÅgvÏìžÙ}®ë©ë©ë)Šíš´kÒ®‰(Xx`á�…¢˜:'uNêQTOSOSOE£³ÑÙè,ŠimÓÚ¦µŤ½I{“öŠ¢¶�¶�¶�(VVV‹b†K†K†‹(&6Il’ØDó6çmÎÛ,ŠbŠ˜"¦õklilil)Š¢˜°?aÂ~Q̹Ÿs?ç¾(ªû¨û¨ûˆbRfRfR¦(þÿèD1÷uîëÜ×¢˜¼0yaòBQL L L Em¤6R)Ši÷Òî¥ÝÅ„û ÷î‹bá±Âc…ÇDQwVwVwV“&-LZ(ŠIm’Ú$µÅœM9›r6‰¢ÚWí«öÅĉˆbúÓô§éOEѸڸڸZ�+Œ+Œ+D1saæÂÌ…¢¨~¡~¡~ñûÇ%µIj“Ô&¢8Âi„Ó'Q Õ„jB5>Þ×ú\ës­�(¶®Ûºn뺢˜º+uWê.QÔ½Ö½Ö½EãcãcãcQ4*�J£R c c cEјhL4&Š¢aƒaƒaƒ(þÿI-¢(º‰n¢›(jçjçjçŠbʸ”q)ãD±pXá°Âa¢¨› › › Ší´_Ð~�(žÕžÕžÕŠâ‹/_|ùâKQ\}ýõõ×EQ3[3[3[µîZw­»(¦ÌJ™•2Ku�F§EýBýBýBQÔ«ô*½Ju t t D±°baÅŠ¢(n·Š[ûq¸òêÊ«+¯D±­E[‹¶¢˜••%ŠúîúîúŸŸ/ŠêkêkêkEßùùÈÏG~.Š+ W®(|¯Áâq„(êúèúèúˆ¢.R©‹Eñ…øBü€ßƒÿ>¼N}�úZGdŒÈ‘!ŠÏw=ßõ|ׇ·û¡¤çÀ$&¥ V+ƒA±]±]± ‹>Ïœ58k0ä�ÏŸ7´3µ3µ3ÁéŠÓ§+@s™Ë\pÄÇ÷;èE/zýÑ~”ý(ûQÿ=—pV8+œ}oöÜÿõ¯kÍ1Çüú±šd5Éj0‰IL*úùÏòùã�Ñ][º¶tmù ý}Í×| Å)Nñ÷î‡ïMzù£Vzx÷á݇wÁæ�Í›P>¿|~ù|@… ÕïoW8"Ž@º:]�®†ã¾Ç}�ûBêÝÔ»©wÁ­§[O·žP£V�Z5jÁÚvkÛ­mƒÞ z3è Ø¼±ycó–�]>vùXøÊî+»¯ìÀî�Ý»°lð²ÁËàɃ&š 5î׸_ã>6‚�`êáêáêá°ïľûNÀ�wÜå¢ËE—‹÷÷÷X¯_¯_¯‡>¹}rûäÂcÝcÝc¼5kþÖj ©1¤Æ¸—z/õ^*tËè–Ñ-êQ�zÿaÿ jÔ,¨ Ê=(÷ ¼¹øæâ›‹púíé·§ßB½zõêÕ«›'ož¼y2ÔíR·KÝ.?^øLøLø ¸Ìe.Ù’gJž) Ï&<›ðlò y†<¨+Ôê ÐtRÓIM'ñï+ÿ+§rNåœÊAåî•»Wî7ÇÞ{s,T¦2¦|)€t QbRªöªöªö`uÓê¦ÕMÈž1<ã½÷BFFFÀ€ 8¥íKÛ—¶};};};S§ÿç ¯^5¼*”M,›X6är¹Ã‡·+v»ˆ]ÀQî(w”CÇÄŽ‰¡ç’žKz.�“º“º“:ˆoß"¾$OLž˜<Òf§ÍN› ž{=÷zî…$ß$ß$_Hû:íë´¯¡lç²�Ëv†Ä°Ä°Ä0Hë›Ö7­/ÉB²� â,q–8 ¬{[÷¶î ¥«–®Zº*ø ñâ3šššÀ{½÷zïõ�à‘à‘àQ´¯2P¨ „le¶2[ ]övÙÛe/¸ôvéíÒŽ|vä³#ŸËXƲ_ß‹G�,AÍ…5Ö\g=Îzœ… À À @ðí3Úg4hNhNhNÀ[ÞòöÚ‘5‘5‘5�ØÒ±¥cKÃvq»¸]„N­;µîÔík´¯Ñ>ØÔaS‡M svæìÌÙ>~^Ó½¦{M‡èMÑ›¢7�a¢a¢aâŸñøÛHLbR?Ý[q©íRÛ¥6$4NhœðÞÒ@nƒÜ¹ ‚^e{•íU'5NjœŠ4Eš"ÍÔéÿ¹ FŒ. –÷-ï[ÞÿÎ%—\f3„ P+Ô 5xXyXyX�ëv×í®Û!lGØŽ° ?&?&?V´2‹¬™¬™¬Èòeù²ü¢96²ê²ê²ê Ë’eɲ@� rAd“M6 F�„§ÂSá)ÈæÉæÉæ�ìºìºì:(æ(æ(æ€|“|“|Èâdq²8�-—-—-™ dÈBe¡²PPŒTŒTŒû>ö}ìû@Áð‚áÃ!ß5ß5ßöoÝ¿uÿVØê·Õo«_ÑŸ +V*¬ …ƒÂd2™L&³âfÅÍÞ;µ–Õ•Õ•Õ¡•ÐJhõóÃ(û^ö½ì{H*–T,©Ä��;wžþðô‡§?@˜S˜S˜dÄgÄgăÖMë¦ý·ð´ð´ðÍ(Í(ͨ¢5EME*`’�‚S}§úNõ!½szçôÎü{ºøŸ%ýUú«ôWðLùLùL ù.ù.ù.¦> [ÁV° kUÖª¬UB?-Ù�îtCŒ!Æ…ã ÇŽËE–‹,1ĸãŽ;`À€á½ïÿ´–ÒO?wÅWÀO<)š…ú¯zšÍŠ%J& “„I] ¡�UJ¡ºP]¨þÞ~ütIu Bo¡·Ð¬vXí°ÚÖîÖîÖîEº]„.@*©¤5©IMÀk¬ßk× +¬Š&SüÛO‹Nÿë¿Â&a“° Ìû›÷7ïÅ›oR¼ ø·ôoéßV”ZQjE)p\à¸ÀqÁ‡[v¿ì~ÙýÀê�Õ« «)«)3áâÉÒ=0ÉGÁ©¯S_§¾E³ü ŽGƒcÑc`”¬ˆ¬ˆ¬Øê¿Õ«?óŒyÆ<è¤î¤î¤†ò”ç?=Îôÿ'�À¹‚sç Î#Î#ξZñÕŠ¯V€ù[ó·æosœ�Vÿ*þUüáx‹ã-Ž·m€6@ªÛªÛªÛ¿¿]Y_Y_Y_044„ÔàÔàÔ`xUñUÅWAë¤uÒ:Aý®õ»Öï W_9|å0Äý÷cÜ��!fˆ"èlu¶:[ÐtÕtÕt…üþùýóûƒ¶@[ -€\÷\÷\wÈ[˜·0o!h{k{k{CîÊÜ•¹+Á¬—Y/³^�ü}ò÷ÉßûFï½k–ö–ö–ö ÍÖfk³![›­ÍÖB~çüÎù�AÝAÝAÝ “ “ “@­SëÔ:PÇ«ãÕñ ôWú+ý¡íöÛ>üõã�¯ÈWä+@�¨NT'Bî‹Ü¹/À¢¼Ey‹ò >ª>ª> y»òvåí*ZjMSBSBS¢h%”â)ÅSЧ@ɧ%Ÿ–| š]š]š]à;ÕwªïT0a>Â|())ýæaú¹PB …—?¼üáåPñfÅ›o‚,^/‹7Ñ/) Ÿõ/¦‹ ‘@Þá¼Ãy‡á¦æ¦æ¦> ø,à³PÌTÌTÌüãú :"t-~´øÑâ0®æ¸šãjBIyIyI9Èmä6r›_ÿ¾²©²©²)D_޾}ö]ÝwußUè0¾ÃøãÁÜÏÜÏÜï7Çùh94uhêЮE^‹¼ ö{ì÷Øï�RÅK/Uü÷·k¾Õ|«ùVJ ¥„R?;~vülHØ�°!atxÖáY‡gàââŽeË:–…ènÑÝ¢»�.^¯‹³<³<³<ð¨êQÕ£*ö(ìQØr&çLΙ ŽqŽqŽq@;ÚÑòïæßÍ¿ .“\&¹L‚jG«­v2_g¾Î| 9írÚå´y®}ûômènÓݦ» Ø×µ¯k_ׄ¿¨¦ž)‘ˆ¢(&ßK¾—|OVX}`uQŒ¯_'¾Î×¾¡‚¡‚¡‚(îºèþ¡¢ØÐ·¡oC_Q|àøÀñ�£(ê¾Ò}¥ûJã£ã£ã£EñAÞƒ¼y¢øhΣ9�æˆbfFfFfFQ{׺\ër­‹(Í š4K³weïÊÞ%Š999999¢ø8ûqöãlQ|äôÈé‘“(¦OLŸ˜>±èûê[ê[ê[¢øÂç…Ï Q|äûÈ÷‘¯(¦îNÝ�ºÛÔ£QäŠß¿+~¢øí™oÏ|{F“£’£’£L�JòWÉÎÎÅ9žs<çxŠânïÝÞ»½M�ªˆt QòQ°«mWÛ®6˜{™{™{Á»­ï¶¾Û n¸ñG,V®wÑ»è] gwÎîœÝ ®¤®¤®)))`ˆ6D¢áüŒó3ÎÏÙEÙEÙEˆ²�²�²y;y;y;˜7#nF0“™ÌŽp„#`L7¦Óá»ñß�ÿn<< (^®x¹âå ÷xîñÜãаIÃ& ›Àžˆ={" yZò´äiàïïÁ‹‚/‚I²I²I2°ïeß˾ׇîýï×(¬QX£0Í Í Í„UçV�[uÆu×q\Gp(áP¡ć÷#ù¸h7h7h7À¶ÛlkšéšéšéÐѦ£MG›oÿ�"Mâ�|”ã•ã•ãÁù¥óKç—ðÎæ�Í»?ð/ŠÙ5³kf× Bó Í+4‡âæÅÍ‹›Cƒ· Þ6x æÌ/˜_€Ï~Öð³†Ð³AÏ=­ ÷°ðaáÃBP[«­ÕÖ L¦ S‹ÚÿÿàBˆWˆWˆWÑšŽA“‚&M‚:)uRê¤@FDFDFœXsb͉5Т°Ea‹BèœÞ9½s:<]õtÕÓUµ"jEÔ S�JÑ,Ѿ-ú¶èÛ¬úXõ±êó×Í_7¼{øîệÞ�äã�="{DöX9`倕 zYô²èe0²pdáÈB°êhÕѪã‡÷óG‘ ˜ä£ðÓ"¼Û1¶cìŸñå_³BĦbS±)…‡ÂCÈ’?$œmv¶ÙÙf°adžvÀ™ïÎ|wæ;0d2 ™ÀZÖ²–Ïbû‰bˆbˆbŒüvä·#¿…hM´&ZCË -7´œ{q«§«§«I±I±I±p~Íù5ç×Àasð0x< `égégùÝK³r²r²r‚oªSý›êàiãiãi3÷ÌUiýå€IDATÜ3s\mqµÅÕ ¢¢b괒߬u¨Ïj=«õ¬L[3mÍ´5 ~¤~¤~“ëM®7¹T|PñA¦ûsÒ%DÉGÅk­×Z¯µp´ÂÑ G+€æ¦æ¦æ&˜70o`Þàèà_Ó­…“ÂIá$È�åÎrgx±êŪ«`ÿàýƒ÷†}†}†}ݺ)t„ههÙSôdék^ó„ÍÂfa3×××�‡»‡»‡;l»}ìö±°6mþÚ|صe×–][ v`íÀÚ�àÚõ‡khaÓ¦… Ô]ZwiÝ¥ &‹Éb2B�P`êÑø9‹H‹H‹HRcH�!5à²þ²þ²v[í¶Úm7ÎÜ8sã ô¼ØóbÏ‹PnB¹ å&€`Œ‚ÑÔé%?-å’x5ñjâU8²ëÈ®#»àþøûãï�‡Vlµ:FtŒèæ«ÌW™¯2uè_'0ÉGÅí”Û)·S�;/w^î<ÈõÌõÌõó«æWͯþþv�Ë�Ë�Ëáõþ×û_ï‡ôé5Òk@D»ˆvíŠf‘Y¶:lu®j¯j¯j!óYæ³Ìg «¬«¬« ñYñYñY='zNôÈj™Õ2«%ÄLŠ™3 ~¼ðã…/€÷7Þßx9>9>9>P·kÝ®u»‚S-§ZNµ ¨kP× ®práÉ…'BZBZBZ·+nWܪ<¯ò¼ÊsPuRuRu2õ¨üœì±ì±ì14�mÛ<ªøTñ©âk¬y°&̉›7'ªÝ¬v³ÚMÚ´;h7x•ñ*ãUd�d�d�L½Ÿ€=’08apÂ`8ûòì˳/áºáºáºÊ9—s.ç 3JÏ(=£4x{{óó·+|¤„Ÿfs˜:ˆDPP¡ BA·lܲqË`@ì€Ø±Pkx­áµ†ÿþv ‡ ‡ ‡àÍù7çßœ‡ôŽéÓ;‚G7�nÝÀåk—¯]¾†7Îoœß8Cþ½ü{ù÷ÀÂha´0‚z¬z¬z,”,Y²dÉ’�U�U�U·2neÜ‚2—Ê\*s ò®ç]Ï»ÁÁÁ ¦¦žÇ=�{+o+o+oÐxj<5ž98rpä`ÐÓÓ»ZvµìjA©K¥.•ºŠ—Š—Š—¿¿ÿj¢¿è/úCäÊÈ•‘+áÇÙ?Îþq6< xð,<î{Ü÷¸�_~ø5øùúùúù‚Ç#G€)LaŠ©÷âïë§•@^Ž}9öåX¸t5èj¼zùêå«—Pfq™ÅeCÛFmµmU ªT)ÅFÅFÅFS§ÿßILòQZd¹Èr‘%_Q|EñÐop¿ÁýþÀ4Jþ"ÿZ1"~füÌø™p½Ìõ2×ËÀ�¦wšÞi šKšKšKà£÷Ñûè¡nߺ}ëöŸhŸhŸh°³¶³¶³3;3;3;SïŒééãõñúxÈmŸÛ>·=¼Ùõf×›]p·ÔÝRwKÁËô—é/ÓÁØÂØÂØjøÖð­á �óç7ί¯¯�ݑݑÝ1õÞ|8é¢ä£ä;Ðw ï@¸SâN‰;%@ Å@® W…«¦N'ùÍòÉ'¿h%¨©=R{¤Bûí_´ѾѾѾp×å®Ë]8x4ðh €Õ«V# òóÊÏ+?‡r5ËÕ,WÊ>)û¤ìp w w ÅIÅIÅI�¥ËÒeé@*PÁÔ;ÿä‘GˆKÄ%âÐ7×7×7‡Œ#G2Ž@t‹èÑ- ºrtåèÊ& “…É ¥iJÓ”¦ 7È r”Ï-Ÿ[>ú}Õï«~_AùoÊSþ°yeóÊæ°žõ˜pÍÂ?‹t&ù(Å ˆ3æ´šÓjN+˜×n^»yíÀMå¦rû€×yH>niÑiÑiѰªÎª:«êÀ«V¬ ð@à�À�®LW¦+!;<;<;T^*/•8vsìæØ œ�ÎFg#xÌò˜å1 œO:Ÿt> V3­fZÍ+K+K+K(vªØ©b§@¨ T‚ʨ2ªŒ 4Wš+ÍAî(w”;‚l´l´l4°Ÿýì¶±�m n7Š‹Þ(]ت°Ua+йëÜuî 5j�Z#¨OªOªOB~Ÿü>ù} Ï<Ï<ÏÒ§/N_ o÷¿Ýÿv?$ïNÞ�¼2¾Îø:ãë÷.a÷¶èmÑÜ´nZ7-TJ¬”X)¼Ö{­÷Z%•j·:Üêp«ìµÿÕþW°Î|œ ¾øâkêp’_eèeèeèÅ‹âEö6ØÛ`ohôºÑëF¯¡×Â^ {-‹5,j˜:­äïJº„(ù[¸æwÍïšVVVÁbíbíb-X<³xfñÌÔé$?É–g˳å°c÷ŽÝ;vó‘ÏF> j¨= 6ܸpd² Y†©ÓJþî¤Kˆ’¿¿4¿4¿4ÐVÒVÒV‚p‹p‹p S§’0‹YÌ‚ð’á%ÃK´sÓÎM;iáiáiá0·îܺsëBƒ³ Î68+.ÉK*`’¿ûûûðûÚïk¿¯áJ•„+ ¦Nõé2Äb ±pºòéʧ+ÃÜ7sßÌ}µÎÖ:[ë,LµŸj?ÕÜtÿÑýGS§•üSILò·Òâz‹ë-®Ã‹¯^|õâ+ˆ·�·�·7uªOGæúÌõ™ëa퓵OÖ>�£ùGó�æÃ°Eà [}žõyÖçû¶Ø·Å¾5uZÉ?�4‰Cò·âeçeçe¥›—n^º9\ztéÑ¥GЇ>ô1u¸°°Ça�ÃÃúòë˯/6É6É6É0wèÜ¡s‡‚[�[�ÛGøúÉ?›t&ù[‘‘‘�Vç[�ounM¼5ñÖDȪ‘U#KšÍö‡1Œ1Œ1Œ�³ÂYá¬ó‡Ì2Ô´©iSÓ¦®˜ºbê ©pILK:“ü-UϪžU= ìËÚ—µ/ v^Øya't¥+]Mîo,«]V»¬v°cÊŽ);¦À ^ðºl財ˠ^B½„z < �L�Vò©“ÎÀ$KÊ)Ê)Ê)ÐqLÇ1ÇÀ…úê_¨_ô¢JÉoI$‘¾6|møZ˜63lf¤&§&§&ÜÝsvÏÙ ²Y€ „’BI¡¤©CK$ÿŸTÀ$k5êÖ¨[£.¸Vq­âZ~Ü÷ã¾÷™:ÕÇϰааÎêÏêÏêažfžfžª÷¯Þ¿z˜ñÍŒof|îiîiîi¦N+‘ü2©€IþÖ”£”£”£ Ëø.㻌‡ËV—­.[ÁÛÀ·�oM�îã““—“—“Zmhµ¡_ ¾|†nºmè6ècÕǪ�˜G›G›G›:­DòŸI÷À$ÿUü«øWñ‡*û«ì¯²‚c‚c‚c`\»qíÆµá„pB8aꔦ k]Öº¬uå~å~å~˜ódΓ9O TX©°Ra¦N)‘üo¤¥¤$ÿ(ñ ãÆ/„éÆéÆéFºh袡‹À?×?×?×ÔéþB (àÚêk«¯­†íQÛ£¶GA½üzùõò¡w`ïÀÞ�`ÕÓª§UOS‡•H~©€Iþ‘Ž>;úìè3¸ìzÙõ²+Ìo2¿Éü&`ûÒö¥íKS§ûó *T0ô<Ðó@O¸VöZÙkeáËU_®úr4 jÔ4dŸÉ>“}fê´ɇ‘î�Iþ‘Z�lu²ÕI°Â + ¸pÿàþ@Aü_Çïïïókͯ5¿<™ödÚ“i0½âôŠÓ+BóÕÍW7_-.É?‹TÀ$ÿHŦ›Zl* \>pùÀåpsãÍ�77ÂÃ!‡<bêt€€‡m¶}Øfœ™qfÆp¼êxÕñ*Ìi0§Áœà¥ñÒxiLV"ùsHLò�æ½Ä{‰÷èгCÏ=akÍ­5·Ö„Ôõ©ëS×›:ÝÿNWUWUWô;Ðï@?XýzõëÕ¯¡½s{çöÎ0ê£î‚Ý»%vKL�V"ùsI÷À$Ÿ„¼¼Â.Òòû’O�(‘|Âv^ÜyqçEQ¬Ø¤b“ŠMDÑÒÎÒÎÒî§Kê¢Øù]çw�߉¢.I—¤KúýýÄjcµ±ZQüÁ민DQk§µÓÚ}®Þ«Þ«Þ+Š{ö$ìIÅÞ½{÷îÝ[/n½¸õâVQ4è :ƒÎÔGK"ù¸Hg`’OŠAcÐ4pyÑåE—ÁÎY;gíœá�Â…?‚ü¬ü¬ü¬¢íŸ¯z¾êù*xÓåM—7]~Gþƒ?l4Ûh¶Ñ ¾ÞûõÞ¯÷™îgºŸé™U2«dV�e6Ël–ÙÀ­·zÜêSÚOi?¥=4Øl`³� SÊ”2¥©�žDòq‘ ˜ä“¿*~Uü*X¸`á‚… àj—«]®vcŽ1ǘóóíc41š Ü ¼x/ðïïBÞ…¼ y°]³]³])uSê¦Ô…i‹¦-š¶F6ÙpdCr…\!f—Ÿ]~vy¨Ø¥b—Š¿£`J$Ÿ©€I>)%{–ìY²',,\X¸°ºýÐí‡n?€EK‹–-¾½n�n�nܸpãÂ�  õÑúh}þ{?q;âvÄ퀅UV]X’‹%K~ï^Ú ûö/ì!ì밯þ†~…ý û‚Ë&—M.›L}”$’¿©€I>)2™‡Ìj©k©k©aóÍÍ77ß„E3ÍX4ʩʩʩ~þ½ëý®÷»Þ’û%÷Kî÷ëíë¢tQº(ø®Áw ¾k·úßê«ÿ¯oÿ¢ÿ‹þ/úÃfÕfÕfè†ë†ë†›ú(I$¦¾ '‘| ^/ƒ—(Þ»xï⽋¢Øåz—ë]®‹¢ª“ª“ª“(ZDXDXDˆbp\p\pܯ·sÊþ”ý){Qt®ç\Ϲ^Ñd�_û¯�ÜFn#Åé-Ò[¤‹bTí¨ÚQµM}4$’¿éu* ‹”EÊ"¡6µ© luØê°ÕvµÞÕzWkX¡_¡_¡‡³Ég“Ï&ƒïQߣ¾GA~E~E~dÝeÝeÝaÑùEç�‡TÿTÿT�O’O’O›m~´ù|Úù´óiM.5¹Ôä 8pj-­µ´ÖRp½çzÏõž©�†Dò÷ ­Ä!‘üÆPc¨1®Í¾6ûÚlzüéñ§áݬw³ÞÍ333p¾á|ÃùÄœ�9sªÏ«>¯ú<¨û îƒº YR³¤fIPE^E^Ev_Û}m÷5(š*š*ššz/%’¿'é L"ùd•d•d• rJå”Ê) -§-§-É’'$O(ÚNh$4ÁÖ�[7nÝ�mÛ¶{{{ †bL½7É?‹4‰C"ù ÌÒÍÒÍÒÁ]ç®s×ýüsß§¾O}ŸB§N œÀÞho´7".‰äO$0‰ä7°}nûÜö9tÞÚykç­à·Ëo—ß.èû¤ï“¾O j­ªµªÖ‚+AW‚®�qµqµqµ©SK$ÿlR“H~‹:Ô¡¤K-–Z Æ 3lÌ0ؾûþíû¡çþ�ûw†³¯Ï¾>û¾Ÿôý¤ï'�ÑÛèmô6ux‰äŸIº&‘üÙ Ù Ù E«Ø·±lcÙÆd‹d‹d‹þ½/Ml4±,j¿¨ý¢ö`ìlìlì ½Êö*Û«,È£åÑòhSï�DòÏ ��I$¿Á»ë﮿»â#ñ‘øJµ.ÕºTëŸoWþzùëå¯Ãäk“¯M¾Wî]¹wåì[¹o徕`œeœeœe꽑Hþ¤&‘ü!Ž!Ž!ŽàÑã‡G°ßa¿Ã~ǯoï“è“è““§Ož>y:\³¾f}Íö^Þ{yïe0¼1¼1¼1õ^I$oR“Hþ“<à„- [¶*­®´ºÒÿ09ÃÇÖÇÖÇ&M šW�¯:_u†={2öd€þ„þ„þ„©wR"ù{’ ˜Dò¤Y§Y§YCÒñ¤ãIÇ¡r½Êõ*×ûßÛñÖxk¼50¹ë䮓»Âõ×\{îm¸·!’ ɆdSï­Dò÷"0‰ä?ˆOˆOˆOù!ù!ù!p}áúÂõÅïoÏû ï/¼¿€)›§lž²n†Ü ¹{÷î CCCSïµDò÷ 0‰ä?¯^5¼*¸‡¸‡¸‡€ME›Š6?¼]¯¯¯˜´rÒÊI+á†Ý »v°óó�Ÿïüô‚^Ð ¦Þ{‰äã&M£—H~�xN<'žƒW‡^zu|�ùó=Bº�.¤ÿqýx�ô:éu¦¼žòzÊkXØea—…]@4ÍEs跬߲~Ë@1N1N1ÎÔGE"ù¸Hg`É/( „ê'ÔO¨>Ž>Ž>Ž^žžžžžž0íå´—Ó^ƒÚj?¨ ÛvoÛ½m7Ö)¬SXÇÔGE"ù¸HL"ùÑ;¢wDïq´8Z å–;XîàŸßomm-L)>¥ø”âðØõ±ëcWØRuKÕ-UA×Z×Z×úÃû‘Hþ ¤&‘ü‚ȶ‘m#ÛBñ‚âÅ Àª�U«>]ÿ¥ƒK—†©g¦ž™zž>+|V›£7GoŽ]G]G]GS%‰Ä´¤&‘ü‚ˆÒ¥#Jƒ÷Nï�Þ;Ax&<žýõ9< L7Ÿn>ÝÂ"Ã"Ã"aô Ó6LÍ<Í<Í×|×|×|S§ú¹3JÌ(1¦1ý‹é_À;Ïwžï¶úØjH¾ž|=ù:ÄFÄFÄF@a¥ÂJ…• jPÔ ¨A:-tZè40L3L3L3õÞÿóIL"yOÄ܈¹s¡Ô¡R‡JÕDÕDÕDS§úu.'\N¸œ€©-§¶œÚ%6JlkV­YµfäÅåÅåÅ™:¥é$NMœš8Ö7Yßd}HÙ›²7eï¯ooüÑø£ñGØýl÷³ÝÏÀ5×5×5üT~*?\¸p!ï>¼ûðn0¾6¾6¾†[]ou½Õ&Mž4yÒdÈ7Ï7Ï7½›ÞMïºAºAºA¦>ÿµúä­È[‘·ÂÔ)ƒ…,daÑ¥;ýhýhýhÐ�Ð�Ð�ƒ¿Áßà_´¹ÑÅèbtCˆ!ÄÆÒÆÒÆÒ`H4$¡dÓ’MK6…½gôžÑJl/±½Äö_è7Ž8â@7W7W7Â߆¿  ö)ö)ö)àÝÈ»‘w#h×®]»ví`àù�çž•F¥Qi ìÁ²Ëq›¸M܆††ììì·ÖÞZ{kíÏ»5L6L6LÝxÝxÝxˆÄÀT¦2 rƒÜ ãyãyãy08œ N ö{Š=A<"�€1ÖkŒÒH#ÍÔƒø×‘Vâ�H€¼[y·ònAâ›Ä7‰o ýÕöWÛ_5uªÿ�³“³“³L¹6åÚ”k°äØ’cKŽÁÊw+ß­|£�¿=¬Y²"²›e7Ënfê”?§V+‚AµEµEµtɺd]2ôËì—Ù/lWÚ®´] Û÷oß¿}?¸ßu¿ë~^Žx9âå(m^Ú¼´9Ô‹­[/<�=�=�!a{Âö„í�Ö7­oZߟ÷+< ¡jvÕìªÙE…¦Ùºfëš­ƒ*ùUò«äC‰üù%ò!tvèìÐÙ ÷Ð{è=€zÔ£ˆÖ¢µh ¥�–>Zú(8Tt¨èPšUnV¹YeðîéÝÓ»'lqÜâ¸Å,&XL°˜Cï½;ô.Üñ¹ãsÇÛ>¶}l VVVðúÄë¯O@Ó+M¯4½¥^•zUê”’•’•’Amm-ÈÊÊþ‚î?Ò˜D¤–L-™Z,[ ¶ VXaeêPûåöËí—ÃÄL\Kß-}·ô,ûvٷ˾…±cÆ€Ým»Ûv·M�¶ˆ¼­¼­¼-È/É/É/�™£™£™#x{{{{{íŒ[·2À¸Ö¸Ö¸Š/v¼Øqðpõpõp///(´)´)´ÙjÙjÙjGá—–+MiJƒ¼¢¼¢¼"ÈRe©²TPÌQÌQ¼7 U~J~J~ doeoeo�žô¤'N8á@&™d‚¬¤¬¤¬$ÈnÉnÉn�bšbšbˆŽ¢£è/_$¾HE{E{E{¸±ýÆöÛ!O�§ÎSCš,M–&ÅeÅeÅepðtðtðïmÞÛ¼·�P\(.‡2”¡ PƒÔ(G9Ê™zôþ:Ò˜D¼±}cûÆÜî¸Ýq»£-F[ü�î�ý7öSì§ØO�‰§&žšx d2™,^¾xùâå�V-­ZZ5S§|�9rª Õ„÷réŽêŽêŽ‚r°r°r0÷…ûÂ}àw¸DIä{툈ˆ€+®¸žxâùú5bÄ” %€ò”§ü/lç‡~€%–X¾÷½JT¢ B… ¨K]ê_ð_ðŒRF)£Àá�Ã!‡CPêi©§¥žÂÔJS+M­­ýZûµö½­ÞVo ç8Ç�B )|/G3šÑ Ä(1JŒ2õ ýõ¤&ù´me+[!6/6/6<ö{ì÷ØoêPÛ½¶{m÷Âønã»�ï* •… ù/ò_äÉ’$?0uJþ}FT°¾`}ÁzHtNtNt†§Ýžv{Ú ê¦ÕM«›ú[ú[ú[ ‰×Äkâ!o^Þ¼¼÷V&É_™¿2%hiiAÞ ¼Ay¿4ð_Ï}¬,XY°454545 §tNéœÒïµw2ÿdþIÐè4:�r×ç®Ï]ùB¾�/€Æ_ã¯ñõVõVõV�ϖϖφ7¯Þ¼zó òÆå�ËþËý—û/‡ìçÙϳŸƒSG§ŽNÁk¤×H¯‘`û•íW¶_AAnAnA.888‚ÎKç¥ó*ÊsnÒ¹Iç&ÁÅÅèÎéÎéΙzðþ:R“|Òôõõ!µWj¯Ô^à–ã–ã–cêT>«0«0«0øVøVøV§µNk�Ö¢΋:/ê I7“n&Ý4aÀa c¼K}—ú.ÎÖ8[ãl (·©Ü¦r›àKÅ—Š/�mžmžm�Ž6:Úè(äÌÏ™Ÿ3Ä@1P „8×8×8Wðì?Ø0®®®ƒf‚f‚fÂ{ýEE$˜'˜'˜C-óZæµÌAg­³ÖYCR÷¤îIÝA}D}D}ê¬w°ÞAxÓéM§7�@ã¨qÔ8B@§€N� «BV…¬ Ðoa¿…ýBªsªsª3D*#•‘Jä6Èm�”Ú]jw©ÝpÜý¸ûqw¸©¼©¼©„Ä«‰W¯‚ýEû‹ö¡ü�òÊ€´-i[Ò¶Å6¿`~ÁüXÞ¶¼my„·Â[á­ Çí/&ˆÿbê ‰)dïÍÞ›½ÆÖl=˜4`Ò€IÀëš×5¯k¦N÷×)))��7VÜX¢»Ew‹î'N„RcJ�)5æ¯Ë³±æÆšk³7ÏÞ<{럭¶þYÑl?‰¤30É'.¾X|±øb ‹�EÈ" DŸ}Jü…«Î,,ª[T·¨Ãn»=ì6øøùøùøÁü”ù)óS æ`ÌÁ˜¿`v›®º®º®:$¸'¸'¸Cf�Ì™5 þËø/ã¿4õQ’|l¤&ù¤%,NXœ°ìûÛ÷·ïæ:s�¹ÎÔ©LǼ©ySó¦ðu·¯»}Ý ª}Uí«j_Á‚“ N.8 Ñu£ëF×ýóúW Q Q �ѧGŸ}Vy®ò\å Îûœ÷9ï3õÑ‘|l¤Kˆ’OÚÞ‹{/šDM¢Æ·ßf|S§úx¶+lWØö4ÞÓxOc¸%»%»%ƒ‰ &€ÏTŸ©>SM�Rò©’ ˜ä“¶$vIì’XpÿÌý3÷Ï Wx¯ð^á¦NõñÑWÒWÒW‚ý®û]÷»Â¥Ç—_z ãÕãÕãÕPI[I[Ikê”’O�t QòIÒõ×õ×õ‡”)=Rz@©7¥Þ”zcêT/E¨"T =�õ<Öó´ kÖ* ;,vXìOn?¹ýä#zZòi� ˜ä“¤öQû¨}@Ý]Ý]ÝìŸÙ?³7Á—ÿnä¶r[¹-tëÔ­S·NÐéÇN?vú–•XVbY ¸·ñÞÆ{M�ò?Å(FAÚÁ´ƒiA½\½\½ÜÔ¡$¿—TÀ$Ÿ$õbõbõbÐúj}µ¾`gcgcgcêTÂmá¶pÚ§¶OmŸ ½Žô:Òë¬ö]í»Únô¿ÑÿFS§ü¹änÉÝ’»Á²ÝËv/Û ObŸÄ>‰…ìÙ3²g@Úå´Ëi—!»0»0»2ÎdœÉ8©ù©ù©ù�ý6ûmö[0l0l0l€´�i;ÓvBö‘ì#ÙGŠú1Ž1Ž1Ž�´çiÏÓžCÒü¤ùIóAª Õ„šú(üsHk!J>Ié!é!é! /�È Àî¼Ýy»ó@úóþÃû±>>>ƒVZ]huT�U�U�aãº�ë6®Ý4Ý4Ý4h¶²ÙÊf+�|ò1á B_ö{Ùïe?8uôÔÑSGÁ-Ð-Ð-BBBa›z›z›>?ÿùùÏσñsãçÆÏ!®G\�¸`^`^`^S¾˜òÅ”/ŠfIÃü•óWÎ_ gJŸ)}¦4<¸óà΃;`±Ìb™Å2PÞRÞRÞ‚Á‡|,,-,->·ü]Hg`’ORÂí„Û ·ÁvŽíÛ9`}ßú¾õ}S§ú[ÊR–BÓÔ¦©MSahÈÐ�¡!°£øŽâ;ŠÃé6§ÛœnÆ�Æ�Æ�¦‹é½É{“÷&p r r ‚VlµÒÒÒ ×1×1×ê´¨Ó¢N èß7¾o<”Pf@™�Ñ9£sFg°ìmÙÛ²7”ì_²Éþ�å•å•å™ã3Çgއ�}vöÙÙZTiQ¥Eà8Àq€#\νœ{9"~Œø1âGSÚߟt&ù$¥¥¥¥¥¥�½Ü^n/6°� ¦NõÏÑ`QƒE �ª¹ª¹ª9¬)XS°¦4Ý5Ý5ݡ㚎k:®Ù(Ù(Ù¨¿0˜ o‹·ÅÛÀ.v± ˆ'žx0Ûn¶Ýl;Økì5ö°�´�´�e{e{e{à W¸ò^{æ˜c‚NÐ :PïRïRÃ1‡cÃ�7^Üx¯^½zõêÈâeñ²x0V5V5VºÒ•®¦­¿/é LòIÊxžñ<ã98¤9¤9|Bo°ý«ù_ô¿èÆÅ�‹'Ïž<{ò,°<`yÀ ?~0üð€l²ÉÔ¨QS´j½n¸öØcÿÞ÷þµØ/è@‡÷~þÓªó-iIK�çÈsä9`wÐî ÝA¨{¡î…º óÄÎ;O„mªmªm*ð3úýŒ¦›©€I>I×2®e\‡�;vš:Í?_ÕØª±UcaÂæ ›'l†Ëf—Í.›ÁŽå;–ïX:�¿ÎÿÃûùoTíTíTí@6\6\6nõ¼ÕóVOˆH‹H‹Hƒ¼iyÓò¦AJFJFJFÑ÷\WÁU€”m)ÛR¶ÁË^/{½ìi7Òn¤Ý€ÜÔÜÔÜT0?b~ÄüÔZÿiý§ðÀû�÷ox»àí‚· /$/$/ø†oøÆÔ£ò÷'0É'ÅXËXËX 2Ã2Ã2ÃÀe„Ë—¦Nõéð=ã{Æ÷ LÙ4eÓ”MðpöÃÙgÆcŽm8šo4ßh¾ùóúwhåÐÊ¡L·™n3ÝTN*'•uF�Q#»�ì>²;XU³ªfU­è{Íz5ëÕ¬ô•õ•õ•AB£„F � öòÚËk/‡n‡»îv”ÊeŒ4:|ó}ó}óámÒÛ¤·I�˜˜…Aa�nà|0i%É'%§^N½œz0nܸqãÆÁØÃc�= å÷—ß_þü°�Uü¤øIñ“`IÅ%—T„K ,1FºŒté– – – ¦N)ùXIg`’OJ~©üRù¥À`o°7؃µ¿µ¿õ_péJòËܹ/r_S/M½4õd|Ÿñ}Æ÷°dÚ’iK¦AÖð¬áYÃM�Rò±’ ˜ä“¢NV'«“Aa«°UØ‚²Ž²Ž²Ž©SI\v»ìvÙ SN98å ˆb„ mÚ,´�´Ni�Ò:™:¥äc#0É'E]L]L] ³³³Ai¦4Sš™:•ä'v‡íÛ† _OøzÂ×`wÎîœÝ9˜;k³ þtüéøÓ¦N)ùXH÷À$Ÿ”<à°'{Oöžì¢ÿ÷,KÁÔé$ÿ—ºP]¨.„Mi›Ò6¥Ax±ðbáÅ`Ü™qgÆ�Ïž=<{˜:¥ÄT¤30É'E­R«Ô*0«bVŬ ˜¹˜¹˜¹˜:•ä×SSSÂðIÃ' Ÿ5ŽÔ8Rã,4_h¾Ð^.y¹äåS§”˜ŠTÀ$Ÿ”Ì´Ì´Ì4°ziõÒê%(&+&+&›:•ä¿QîRîRî‚þíû·ïßš››aщE'�€ÝtÐÝÔ)%5©€I>)Yû²öeí›{6÷lî�0F#Œ1u*Éo¥pR8)œ {Íî5»×„î†î†îX­_­_­‡Ëõ/׿\ßÔ)%©€I>)ù#óGæ�‹Ý»-v›:�ä÷’—‘—‘—� ‹ ‹ ÜppÃÁ a»ùvóíæpüÜñsÇÏ�ñ€ñ€ñ€©ÓJþ,Ò³à’OŠN¥SéT`;Ìv˜í0S§‘|°K\â4¤! «-V[¬¶ÀÊY+g­œ9êu޾¸ñÅ�/n€r½r½r½©CKþ(Ò˜äÓðŒg<íeíeíeP-Q-QI7ÿÿqª‡V­ Ó¦9Ls€ž7¤NH��:ðãÍoþxó7w#ù‹IÓè%Ÿ†§<å)ÈŽËŽËŽƒ¢²¢²¢²©CIþ*­=Z{´ö€rËM,7v;Øí`78üåá/ M#šF4CCCÐ6Ð6Ð6€=—÷\ÞsÚµlײ]Kp>ç|ÎùÜïOœ N'€F¡Qh Ñh4 h#´ÚÐöÑöÑöý�úõ?‚q±q±q1€XW¬+Ö¹^®—ëA¶A¶A¶äUäUäUÀ,Ñ,Ñ,T¥U¥U¥AÕBÕBÕŠeË*–ŠŠŠ¦>ê>©€I> 餓‚“à$8�ì°ì°ì0Ð�~ô3u8ÉŸM1_1_1*S™Ê@%c%c%#ô~Ûûmï·pää‘“GNÂÁ7ß|a¶a¶a¶ð üƒòÊÃý~è÷C?h;½íô¶Ó!¾Z|µøjÛ)¶Sl'HYž²¡ö±ÏÔ{û¿“——Gq«:Vu¬ Þxã 4Jm”Ú(µh ÉÌ Ì Ì ?~0ü ‚NÐ :0ûÒìK³/AÛRÛRû kÞ%¿N~�üb­b­b­ÀÜÁÜÁÜôãôãôã Ì�2CÊ ‹uë,ÖAxÇðŽáÁº½u{ëö »®»®»Î!Î!Î!P©n¥º•ꂪ„ª„ªE³‚"¨¨_mˆ6DáïÂß…¿ƒ„* Uª@Ú¬´Yi³À6ß6ß6jm­µµÖVP¼S¼S¼‹4‹4‹4PQQÑOôýà¸ñ¸ñ¸®¤_I¿’cÛ�m?¶=”û¾Ü÷徇´6imÒÚ@\n\n\.˜ç›ç›çƒ÷Fï�Þ!£FF�Œ�|=ùzòu°Ùe³ËfˆeŲbYp½âzÅõ ¼ñvÄÛàQÆ£ŒG°\n¹ÜrùŸ?žqßÅ}÷Zzhé¡¥ðìÖ³[Ïn�_¼_¼_.5]jºÔ„Î5;×ì\ZvoÙ½ew8Ÿw>ï|lé¾¥û–îpµíÕ¶WÛB¿½ýööÛ n­ÜZ¹µúßû“ ˜äÓ0„! ³$³$³$Ð5Ô5Ô5ñˆGE›•°*aU ¬[=¶z õ,ëYÖ³{£½ÑÞ}'ô�Ðw¤Z¤Z¤Z€ó]ç»Îw¡D¥•JT‚�Y³f�¢š¢š¢<ÜþpûÃí�bL1¦�B )üy<[[[ðjãÕÆ« ,(XP°j×­]·v]ÐwÖwÖwK[K[K[0¾4¾4¾šÒ”¦üûÿŒ-vYì²Ø¥Ž—:^ê8¤=N{œöjÕ ª‡{îu¸$=Iz’ôæœ?pþ@8juÔꨜ¨y¢æ‰š0?u~êüT0?n~Üü84Ûdl“±àÝÈ»‘w#‚„ !=^ôxÑcpŽpŽpŽøã‡-½gzÏôžð�æ;Íwˆ/_*¾ × × ×AÍàšÁ5ƒAž"O‘K³J?:VÁVÁVÁÐép§Ã�Cý�ú!õC`×½]÷v݃éªéªé*¢¢¢ÿ þü/­hÅo(hR“|RÌôfz3=hvjvjvþÂJ”(A ƒÅ` ¥(*µJ­RƒÐDh"4�|Ÿ|Ÿ|º Ý…î`6Êl”Ù(0‹3‹3‹0€ü{òŸó9Ÿÿ†€¹ä’ ¢¿è/úýù–O>ùÍŽË"‹,Èè“Ñ'£Äî‰Ý»v–ØYbg Hz˜ô0é!x·ónçÝ„>B¡È6É6É6�ÊBe¡²s­¹Ö\[Ô�;î¸ÿ 㔨KÔ%ê`iìÒØ¥±àéé ólçÙγ§ÕN«�VW¹ÊÕ?!€ä�Õ….t×.®]\»À˜ycæ�™ç¯�¿vþ¬�¾vúÚéÐwtßÑ}GC³‰Í&6›È¿_ƒôk¤&ù¤XNµœj9²ÏdŸÉ>ÃÏŸÓ AÂa�°8À€º‚º‚ºˆóÅùâ|°ýÒöKÛ/Aì-ö{3˜ÁŒ_êK,A8*Ž�éLçÿð_7„+Âá ÐŒf4£èÌí_÷n„@!PüñÇhG;Ún¸á„J(®®®5owÓî¦ÝM(ýªô«Ò¯ ÷W½¿êý˜77onÞ¼è^á»ã; a�0$�À¢v “ “ “ åZʵ”kà<Ñy¢óD0‹1‹1‹ùýã“Õ1«cVGXéºÒu¥+xùyùyùÁÀ–[l ªªªÿ¡�éLg:ä¹ç¹ç¹ƒ:^¯Ž‡­[¶‚Ä^޽{~lûcÛÛB­eµ–ÕZ{ö8ì�ÝSwOÝ=.ú_ô¿è±=c{Æö„wï<Þy@¶¶¶?D�Š=ª(ïÛ}o÷½Ý*M¨4¡¼¼öòÚËk¿\ÄAâ qìóÞç½ÏG;Žv Ö X3`Ío(\?µÓXl,6†G=õxÔ£è’nìg±ŸÅ~öá¿?Ù²7do€9/缜óžÄ<‰yéŽéŽéŽ0qöÄÙgÃ�öÚhÿ^®ãâqñø{ílÉÞ’½å½v¶=ÙödÛ‡çû¿òÆæ�Í [\·¸nqëÖ¬;€ìºìºì:¬{°îÁºpúóÓŸŸþ < < <`õ¦Õ›Vo‚Å“O^<Ä’bI±äŸï'uÏÖ=[÷,ôßÒKÿ-ðýÐï‡~?’;$wHîðëß“ÎÀ$Ÿ‡ë×®CNxNxN8–/,_XþßWáxŠúŠúŠúà\Ϲžs=¨ýCíjÿeÖ–Y[f-(½•ÞJo0>`|Èäò�½’½’½.s™ËÐce�•=V‚nŒnŒn «[¬n±º?ÏõÓ =K÷,ݳ4h¶h¶h¶€Õ«VÀhm´6ZÃRÝRÝRØ$Ú$Ú$‚í6Ûm¶Û`©íRÛ¥¶`×À®�]p]ëºÖu-”¶-m[ÚTõTõTõ t�ÒuJ×�ÉC&™<âããAõTõTõ,¶ZlµØ e¬ËX—±†uYë²Öe�ÛN·�n;‹òº§º§º§ÂÔˆ©S# ôªÒ«J¯®s�ëÿû¸<ïû¼ïó¾Y7²nd]˜,L& `®0W˜ÿÿJ Í…æBsð¼éyÓófÑtï … ÿ€×æXå[å[åðíöÛ®é®é®é`½Çz�õ°¾b}Åú äîÊÝ•» rmrmrmàÔÖS[Om…6Û l3¬­­ßk§½k{×öžïÿÊé•Ó+§„V­Z>ølà3¨Ð£B� =Àn¿Ý~»ý`ñÒâ¥ÅK°o3Þf<¸Wp¯à^žÖZÿi} ‚"€ TàO|ýPãìÆÙ�³!,),), Žu:ÖéX'¬¬¬A%¨Õ{ã-­Ä!ù”<üâ῀ݛwoÞ½¦,LY˜–^–^–^Ù%²Kdè_п ¬{½îõº×P-¼ZxµpS§ÿú�ø–—X^by pqrqrq‚/=¿ôüÒó÷7�Ow>Ýù4|YòË’_–ewewewpÒ:i�´P{zíéµ§C°K°K° Ô¬P³BÍ Pip¥Á•î¨]Q»¢ ÖÕZWk]…ÊÛ*o«¼ öXï±Þc Õ—V_Z})<xF 5dÔ(û¤ì“²OÀ%Ç%Ç%Öõ^×{]o}oô½Ñ÷ vÍÚ5kׄ­O´>Ѫ]¯v½Úu0Œ6Œ6Œ†{Þ÷¼ïyCåU•WU^["¶Dl�€ZµjAÀÌ€™3}ÿ Õ…êB5œ<x:&�ž¼]q�¸GÜæ�æ�æ�P«x­âµŠC‹àÁ-‚á”Ý)»Svp/î^ܽ8ˆŒ�Œ�Œ…ÇçŸ|œ;9wrîîîîE?wjîÔÜ©9¼ {ö* =züÞó|$“L2(Œ £Â.*•‹ ,'YN²œuÆÕWg”ª\ªr©ÊðÒõ¥ëKWxñ,âY0šÑŒ†«W®^¹zªU ª÷î;܇�û6îÛ¸ vì,Øùëû¯ÌPf(3 |¯ò½Ê÷Ç·ŽoßBCC”Xv`Ù��aÈ0dàJÄ•ˆ+¿0‹T8$AÁþ‚ýûa•Û*·Un`©·Ô[ê¡Îà:ƒë †ïÒ¾Kû. bvÄìˆÙñáãW¦R™Je*-2üêÇW?¾ú…¿Ò%DÉ'Ŧ†M ›PèTèTèÚÚÚÀf6³j�®=ºöh¨MmjLcÓL�úŸ+')')' ..\ Î6Î6Î6@ÃÿzþKö@ö@öì½ì½ì½ lfÙ̲™àWʯ”_)xÐñAÇAi§´SÚ�PB(!”dÈ��yˆyˆys„9œ¢æÍ˜0?ÂIá¤pò½~šä+ø ¾`ooæçÌÏ™ŸÇQŽ£G�2R©ŒóVæ­Ì[�ÌUæ*sóóó0;cvÆì 8%9%9%�wCï†Þ áhúÑô£é ë§ë§ë‘‰‘‰‘‰�éœéœé rw¹»Üªíª¶«Ú.°ibÓĦ ¨TªpT8* Û.Û.ÛÅ*«\¬2g„3™ŸFáœpN8Ùw³ïfß…ßß_ht¸ÑáF‡A—¥ËÒeA²e²e²eÑãe)KÙ>Yœ,N*:T„dÏdÏä_8#—ÎÀ$Ÿkkk¢„(! r|r|r|L�êÓ¥l¡l¡ld’I&èªèªèªü ÿ«Gq@i¤½÷ùYÎr„GÂ#á>‚�àÂ@a 0ðÜA‘¢çšpÀá7|ï_gr?{n0€€2”¡ „Ž :îXݱºcwóïæß͇Ü5¹kr×€ ô‚Ä—âKñ%ˆñb¼ÿ?ä·Ç{0î0î0î€Â… @êW©_¥~YU³ªfU…¡[†nº¼*zUôªøÇ¾Ÿ.…***þüs©€I>)V§¬NY�ëëëH(�P:¡ôŸØa7ºÑ ž�}6öÙX8[îl¹³å@ã¡ñÐü†éÈâñ€xô—ô—ô—À¸Þ¸Þ¸ž_} úïÆÚÝÚÝÚl£m£m£!Ö>Ö>ÖþhØ 'œ@/Žǃ.V«‹…ì©ÙS³§Bx�ðá= Î :ƒê Õ-Õ-Õ-È)•S*§TQ3ÆóÆóÆó`È5äÞ{Ï0ß0ß0ô…úBý{ã`ØoØoØzµ^­Wƒ ä‚ <*x9Ws®æ\f2“™`6‚AUUô¾z_½/ÊÊÊ€a²a²a2ÆÆÆýœw¼ãôÜ×s_Ï}0Y3Y3YãóÆç�Ï·Ý~tû ÅB±PcscscsÐ'êõï=F`¨c¨c¨†á†á†áïý|€a€aèsõ¹ú\°Xm±Úb5x~ëù­ç·PòeÉ—%_B«™­f¶š ]ûwíßµ?8_t¾è|ñÇ/osÞæ¼Í�Ú/µ_j?ðtótótûùvÒ%DÉ'E®�+ä p6:���P˜P˜ð'‚çMŸ7}Þ¾ïú}×ﻂïvßí¾ÛAãªqÕ¸‚9æ˜ÿ‡ïgfgfgfÃæÂÍ…› ÁìŠÙ³+0f嘕cVò·_*I±F±F±jÝ©u§Ö¸ëw×ï®4Èh�Ñ d2Ùo9cù?l‡Úµ -ª´¨Ò¢ \©q¥Æ• ¾߈o ž[=·znвIË&-›€} ûö-à‡ ?LøapdÀ‘`ñ�Åwß�"Y‘¬H†°a'ÂN€b½b½b=$$$BH«�V!­À,Û,Û,òOåŸÊ?¶¶¶Pù|åó•ÏÃþ×û_ï MtMtMt ,¥,¥,Y¯²^e½‚n/Ü^¸�Ë—-.[ îTÜ©¸S�<(yPò p©âRÅ¥ ¤ Mš2ì°Ãîößxßxßx"JG”Ž( λœw9ï‚°+aW®€ýfûÍö›!Û�mÈ6€Y5³jfÕàѨG£�‚¼]y»òv�Ù³;fw Ç7Ç7ÇF6ÙtdS8[ýlõ³Õ!Î?Î?Îʽ-÷¶Ü[hp¯Á½÷À¢ŽE‹:ÿã ½çy‡çžw(z]�×>¯}^¿°ú¿4 QòIÚº#tG(d¶Íl›ÙƼófÌ›?¾ŸÝßîþv÷·ð°ËÃ.»ÀRË¥–K-Áì±Ùc³Ç þ{;ë—®_º~)<Ïxžñ<6´ßÐ~C{ê u…ºÿýû»ÔôÔôÔt˜Ÿ2?e~ ô,Þ³xÏâPÛ¾¶}í8#»Š]Å® OÕ§êSA\".—€òšòšòã…ñÂxà{¾ç{ЫÿVÿ-ˆcűâX† C…¡ ¬Ök@8/œ΃±ž±ž±`ƒ 6 x ž‚'ˆ9bŽ˜X`�ÈÈÈ€ÑÒhi´ÃÃÃ�[É­äV F‹Ñb4I$‘ÀMnrÅ(FݯŠWÅ« zŠž¢'ÈgÈgÈg€ Ô‚úv<„BÀpÖpÖpÄsâ9ñÿ¾t*w–;Ë�Á°Ô°Ô°'œð¢K©be±²X¸Æ5®�|¹|¹|9©Bª� úáúáúá`Ì6f³Aæ+ó•ù‚"L¦+:žÿ«Üâ¹Ås‹Ã‚С B¡é䦓›N†›[ln±ùçÛKLòI:Wx®ð\!\®u¹ÖåZ°8|qøâpþ}þCåĿĿÄœ°9asÂàåÒ—K_.…™-f¶˜Ùj„ׯ÷»ßï~¿;¤¥¥�üŠüŠü Ô¯S¿Ný:àhæhæhV4­ùÙËg/Ÿ½„õŸ­ÿlýg^9¼rxexUðªàU(�)�)�A½võÚÕkŽë×;®‡wgß�}wB‡,Y ô£ýÀ¿‰ÿ&PÜ£¸Gñ?`……uiÙ¥e—–ÁÁ¡‡ “4“4“4PÖ±¬cYGS§“üYt1º] ¬³]g»Î´Z­Œ;=îô¸Ó l­l­lýóïI÷À$Ÿ¤r�Ê5*×2–g,ÏXo3Þf¼ýãÚW©T*• ¬°þÁú‡¢çÌíííÁ¨5j�Zuuu€JL(1®¿vüÚqØÕlW³]Í~Þ®` ‚2fgÌΘ ³sgçÎÎ…B·B·B7Ð^Ô^Ô^„Œ—/3^Bæ ÌA™ƒ`iÆÒŒ¥ qÓ¸iÜ 9%9%9Vd¬ÈX‘êpu¸ú#xέI…&šT€FŸ5ú¬Ñg°´êÒªK«BĸˆqãL�NòGËóÅ|Öe®Ë\— ïn¼»ñî|%|%|%üzáú‰TÀ$Ÿ$‡ž=z½x25;5;5û�k_U\U\U\Ÿº>u} ΞΞΞàÙÁ³ƒg0Ûk¶×l/´¹ÒæJ›+PaQ…E�뷮ߺ~ QÙQÙQ¿”ç_³ÏŒYÆ,c¤ÊSå©rx5ïÕ¼WóÀï©ßS¿§àõÎë�×;ˆ5,j¼Œyó2ª_¨~¡ú(ߢ|‹ò-à�íÛ¶�¥ÊRe©þ§]üSÈÚÈÚÈÚÀ5¾¨ñE hСA‡`þèù£ç�†‹/¼x c c cL�Vò?û× CZLz^¼„y �\:¹tri˜à:Áu‚+8�ŒNÆÿÞœTÀ$Ÿ$«#VG¬Ž€Õz«õVë!ù`òÁäƒÞîÏP@ˆ}žb_\Á"ò"ò"ò`]½uõÖÕƒ#»Žì:² B­C­C­ApœçŸ7'æ‰yb8Æ9Æ9ÆÁÜü¹ùsó!cDƈŒ0Ìu˜ë0W8·ýÜösÛA_W_W_2,2,2,àRÐ¥ KAö*ìUØ+Ê Ê ÊË»–w-ïšzTŠÈ×Ê×Ê׺/t_è ÿØþcû�…}ÝöuÛ× –——áÝðwÃß ÿðþ$.õõõ8¾âøŠã+`FÞŒ¼yà~Îýœû9˜vfÚ™ig x�âuŠÿ“?¤Yˆ’O’êªêªê*”1/c^ÆÂ‡-[ �hĺ¸=zà7¸Á¿W£¿5îÖ¸[ãàí´·ÓÞNƒ 4\Ðt[t[t[àYÏg=Ÿõü…vÊSžò�ÿ"ÿEþ (R,¤X¬<¹òäÊ“0Þu¼ëxW¸ÒûJï+½¡ÿ þƒú÷&îMÜ›@Ë -+´¬ðÞ‹R�êT7õ¨üœl³l³lsÑbø>3}fúÌ„}6ûlöÙÀ´ÓJL+�›7n†–9-sZæ@‰q%Æ•�.9šL¾6_›¯…G£�~4Ž�;6îØ8Ðêõ�0¸õàÖƒ[C�îuº×éòBy¡üwÌ– ˜ä“æ]Ö»¬wY¸vâÚ‰k'À¸Ü¸Ü¸doeoepO,oMÞš¼5ðVÿVÿVé•Ó+§W†×¶¯m_ÛB¥a•†U×+^¯x½"ì‹Úµ/ lllAÜ"n·@ttttt4ÄŸ‹?rÞå¼Ëy¯[¿nýº5|xðáÁp¿ßý~÷ûÍ"kÙ­e·–ÝÀ³¬gYϲÔ)¨SP'ØQnG¹åÀ»�wï>àsÒç¤ÏI¨¹»æîš»A¾^¾^¾ÞÔ£òëÜf»Ív› c£ÇF��†gKŸ-}¶Žzõ8êSºOé>¥;ø�ôé?š?mþ´ùS(£)£)£³ûf÷Íî›z/þ9DÑGô�´�´�´¸{ðîÁ»á¢ÏEŸ‹> ™­™­™ -¶|Øò!|öåg_~ö%Xu²êdÕ‰~žQš…(ù¤EÄFÄFÄÂ’Ô%©KRaÙüeó—Í»cvÇìŽýþv ~?ƒdÜ˸—q Ï Ï ÏÀö˜í1Ûc j£j£j®®®`,o,o,ò{ò{ò{@úÐ,Ã,Ã,à /)/)/ ŒµŒµŒµÀ¦ŒM›2P�Q�Q�ÚmŽ6Ìv™í2Û'N8œa•°JX… € Ÿ Ÿ þ=]Û¬oXß°¾$’ȼ/ËTôöz{½=„ÉÃäar8ãÆÿŒ?„9„9„9€Ó\§¹Ns¡nnÝܺ¹PcK�-5¶@É»%ï–¼ ò‡ò‡ò‡¦Þ‹�—øT|*>…lßlßl_xžó<çyÜK¾—|/^¹¿rå÷î9܃f«›­n¶Îœ 8 6OlžØ<ªP…?b¥•‘ ˜ä“¦é¨é¨éc¼Çx�ñ†~÷úÝëwj_«}­ö¼ßJbZb’˜$&A’U’U’<þúñ×�¿†{.÷\î¹@¢6Q›¨Ç Ç Ç ð}àûÀ÷øÚûÚûÚƒÛI·“n'ÁÙÅÙÅÙ” ¥Bù¾^%öûˆ} kYÖ²¬e�ŸŸ‘s#çFÎ…çžWx^Þ|;ðí@(¶àÿµwßqQœûÿ÷_³ôÞDQ,¢bW,ˆ± *öØ5Å�5–£X5–Ø»Æ$"{,ØìX±aAE‘.mwç÷Ç9çkîûäää$Ñý<ÿÉ#ËìÌ{fз×ìì53-fBõSÕOU? ,X6°Ï™ž3=g‚i�i�iÐëÏ-&0;ivÒì$pþÐùCçaÀÁü S∢E¿K¿K¿ žo}¾õùV8çwÎïœ,߸|ãò��³3ggÎNðìéÙÓ³'XyXyXy@MM ”™\fr™Éà1ÇcŽÇp­àZÁµX[[ƒ™•™•™˜Í7›o6Œû÷3îÇÿÍ2ÿÚd“M6èêêBÁ¡‚C‡ ¿r~åüÊ�×;¯w^ox1ôÅÐCá~Ìý˜û1�´;iwÒnHì‘Ø#±¤lMÙš²4m5m5mÁe±Ëb—ÅPåý*ïWyª�«6®Ú8¨x³âÍŠ7ÁôŠéÓ+†;Ÿoñ¿)„øãj}^ëóZŸCÔð¨áQá MA›‚6¯foM{M{M{ДӔӔƒ«Ý¯v¿ÚÜ�¹s?ƒŽ :6踸¹¸¹¸ÁÝUwWÝ]·kÞ®y»&\Ÿv}ÚõipLsLsL¹Õr«åV“G&�L�É“+&WÀ"Û"Û"<<<Àv™í2Ûe`µÇj�Õ°xfñÌâ˜Ú›Ú›ÚƒÑ-£[F·À8×8×8”éÊte:hÇjÇjÇ‚î¬î¬î,h«j«j«BÞÇyç} 9Ór¦åLƒì9Ùs²ç@Zí´Úiµ!ëó¬Ï³>‡Âó…ç ÏCapapa0hÒ5éštpXì°Øa1¸>v}ìúü–ø-ñ[^½*zUçkÎל¯�mŠmŠm •3*gTˆ$’HCŸÅWd&poÖ½Y÷fÁÔ^S{Mí3ŽÌ82ã¸õwëïÖßÐéÄ_¥nP7¨àbé‹¥/–†{VìY±Ê+;¬ì0üÉàOÎûœ÷9ïûïëËÿ$ÿ“üO ­fZÍ´š�q4ãhÆQÈ•5*kd6Êl”ÙRn§ÜN¹ é‡Ò¥‚—Ë^.{¹ ò+åWʯôê èúJúJúJ ›¨›¨›j}µ¾ZŒ50jU£jT0þÑøGãÁ´‚iÓ `¾Ö|­ùZ°u¶u¶u†_”ø¢ÄàØÙ±³cg°™h3Ñf"س9fs rrrÀf„Í› ¬UÖ*k }vþ<)0!mWmWmW˜0l° àÕäV“[M† ãAǃŽ:�ø³òÃòÃòÃ`ë½­÷¶ÞƒÝ;wïܽº¸uqëâíN·;Ýî4˜Z›Z›Z¿�@:t耮t¥+¨eÔ2j`-kY êPu¨:”ÿ›Ë�õ¬g=(Ý•îJw`;ØÊmå¶r›W�WyGI� ñ+ë:¬ë°®<1}búÄB#C#C‹Ð%ñÇ$ßI¾“|–G.�\ φ<òl Ý0tÃÐ àkçkçkô§?2Â.¶d&!~¥^Ÿz}êõ�»ï^¼{^´xÑâE‹¿¾^ñšYa…Ä–Š-[ ¾šýÕì¯fƒuOëžÖ=aÚÓiO§=ß‘¾#}G"Åõ–�›8„ø•òÊ?(ÿÌʘ•1+W7]ÝtuÓk˜¡Cü-röäìÉÙ›³7goΆCî‡Ü¹CÏÔž©=S!(=(=(Œk×4®iè´âï�!~Åê3«Ï¬>ƒúÞõ½ë{ÃñºÇë¯ ”§<å �NüKRǤŽIaºÑt£éFpA½ ^Pabã‰�'6†à-Á[‚·Hq½í¤À„ø �ë5®×¸ܳ¿gÏ�ytæ‘LAd0ª§ê©z‰'VœX“ &L*×d×d×d˜ÚrjË©-Áûg_Ǥ̢H’â7TØ^a{…íP:¼txép8–v,íXš¡S½{^Ny9ååXo±Þb½¬µrÔÊQÐ=³{f÷LþÓðŸ†ÿö‡íÛ6tZñ¦É]ˆBüŽSާO9†å–oXþjÎDÛa¶Ãlå1¯MÒò¤åIËaIó%Í—4‡œ9'rNÀðà ^ǼŽyãÕ4õâ�$#0!~G­¡µ†Ö -6Zl„“gOž=yÖЩÞ>ú÷ôïé߃“'Ož•}*û:¥(îä¢B½ïê}Wï;ðŠðŠðŠ€ˆÃ‡#ƒÚGí£ö1tº7O}¬>VÃ…é¦_˜“Œ&M2›$›$›$˜ÒjJ«)­¤¸ÄßKæBâO0Zh´Ðh!ôZ×k]¯u0I�¤NRá|ÓóMÏ7…ºÔ¥®¡C¾…ß~[ø-l·ßn¿Ývü¼ãç?Cµ‹ÚE…vì:Ø�ñtãéÆÓ �V¼m¤À„ø <x ðÌ;˜w0‡ï~?ðû�P©t¥Ò•Jƒ����Ý[8âxqüÅñÇaÕ‘UGV�„s çÎÁ¸ªãªŽ« 5úÕèW£(Їâaè´âm%—…øOž<lVج°Y§#NGœuŸºOýOø-òþù ÆëÑ×£¯GÃWÚ¯´_i!Ï:Ï:Ϧ÷žÞ{zo¨y¸æáš‡¥¸Ä›!&ÄßÀ<Ô<Ô<n¸mà6ˆŠŠ‚Ó1§cNÇ:ÝŸ§-Ôj aϳ=Ïö<ƒ™“gNž9æ6Ìm˜ ŸÇÿy<”œ_r~Éù†N+Þ5r¢¯Á®Ê»*ïª ;ê憎£>L¯5½ÖôZàò©Ë§.Ÿ:Ý—Ó=§{NwXWg]�uuàü'ç?9ÿ Þ7xßà}ÐpFà gqÄgè´â]%#0!^ƒ6óÛÌo3¼«zWõ® Ëï.¿»ü.äMÌ›˜7ñÕrú5ú5ú5�á�á�áúúú†Ë�ä’ä’äÓL0mœô!x÷8îqÜÐGUˆÿUñÚÝYpgÁ�ªÚǪ�U+UíŸÐ?¡‚ª:å9å9婪} } } ª�>}4ú¯oïéʧ+Ÿ®TÕôÓ?Lÿðß^¸¶pmáZUÝn¹Ýr»¥ªöÞ{xï᪺­ö¶ÚÛj«jaýÂú…õ }Ô„ø}r½o@FçŒÎ�áî™»gîž�˜Š1c*¾ú¹²FY£¬�Ã9‡sç@SšÒôOl'ûdöÉì“0ùÀä“€S§&NM`²ûd÷Éî�çœçœç kç¬�³v\¾|ùòåË0¶ÚØjc«Aí2µËÔ.Üâ· }Ô„ø}R`B¼F{nï¹½ç6ŒŽ9:no¼½ñöÆ_N QCÔˆ9s:æ4¼˜ýbö‹Ùàø™ãgŽŸýñím®¾¹úæêðCä‘?D‚i7Ón¦ÝÀµ¿k×þ�øKâ/‰¿€rJ9¥œ‚©–S-§ZBéÜÒ¹¥ev}QÌÈg`B¼FîMÝ›º7…jÞÕ¼«yƒ¹§¹§¹ç^þâø‹ã/އ;SîL¹3å�oç걫ǮƒyÎóœç9CŽš£æ¨�Ö=­{Zw˜¸h⢉‹€–´¤%|eú•éW¦PºQéF¥ú( ñçH� ñU\ýqõǰ¦ÒšJk*ÁœþsúÏéžnžnžn@_úÒ÷Õò©šTMªN}"ú@d»Èv‘íþ{Ž=µöÔÚS V}³ê›U߀zR=©ž4ôÑâÏ‘/2 a@/.½¸ôâlÈÝ�»!¾ûỾû´hÑ[¿ßúýÖï¡Þ¸zãê�Â# ®|så›+ß@¯f½šõj×\kp­P‹ZÔå=å=å=°ïfß;Ôþ´ö§µ?…zaõÂê…Að–à-Á[ ñÃÆ?eŸ²Oy¦¼ï)0!Šýcýcýc8{ûìí³·aòËÉ/'¿­§ÖSë –K-—Z.…Ê%*—¨\sþÎyة۩۩7?7?7?¨Ü³rÏÊ=¡åÔ–S[N???ðjëÕÖ«-”¨S¢N‰:Àsžó.Q Q”I� Qí<»óìγнy÷æÝ›C~v~v~ö«Ÿû6÷mîÛBlBlBl qXã°ÆaPŦŠM°t°t°tqÄÑÐ{#Äë!Ÿ� QåççƒÖAë uø÷ŸwÛqlDZ02dþÈ|¨[³nͺ5Á²¢eEËŠHq‰w‚˜EPƒ¶ Ú6h ÁæÁæÁæ`mfmfm~Ýýºûu‡N3;Íì4”½Ê^e¯¡Ó ar Qˆ"ìnƒ» î6€/}ñè‹G0lÛ°möA“ºMê6yù,Äï�˜E˜ã#ÇGŽ� Tb©ÄR‰PrHÉ!%‡:•EƒL%%DQ–DI€=ö؃úP}¨>4t(!Š� !„(–¤À„BKR`B!Š%)0!„Å’˜BˆbI L!D±$&„¢X’BQ,I� !„(–¤À„BKR`B!Š%)0!„Å’˜â¿ÊéšÓ5§+<ÿàùÏ?}Œ>FcèTâ]'&„ø�ž/}¾ôùRX¹q寕aeÐÊ •ApÿÃûÞÿš49h™J¦’©ÀýZ÷kݯ‘%"KD–€¤ˆ¤ˆ¤Cï…x[I� Q”™bŠ)Ѓô¥¢RQ©øæ6Âç„Ï HôJôJô‚~Mú5é×tÓuÓuÓ!:2:2:²·doÉÞæÕÌ«™WƒUv«ìVÙÁÕ«W¯^½ z�^§×AŠyŠyŠ9¨)jŠšbèƒ+Š;)0!Š05D QC ¿0¿0¿Ò´iÚ4-¤¹§¹§¹ÃÓµO×>] Ú$m’6éWïë¥öR{Á‹á/†¿É?%ÿ”üdÚeÚeÚ³™ÍìßÙp*Pî6¿ÛünsH»™v3í&Xõ·êoÕÜZºµtk C’‡$I§ Nœ6€Sk§ÖN­ÁâK‹/-¾¬°Â Ž~üóãŸÃâ¤ÅI‹“àE³Í^45CÍP3 /$/$/žø?ñâ©]S»¦výÏúŸõ?CNãœÆ9�áùˆç#ž�€Œ;w2î@†e†e†¥â»Jh)D¦6P¨ à†Õ «V°Üd¹ÉrèгCÏ=a÷äÝ“wO†N[:mé´Úïn¿»ýn8´ÿÐþCûáôÕÓWO_ç^νœ{ÁÃ�~ôð#è–Õ-«[T§:Õc»©_¤~‘ú$¬KX—°¬|°òÁJ8t6èl¸Õt«éV&�xtâQø4üÓðOáI\“¸&qÀ,f1 , , ,áè÷G¿?ú=œ™wfÞ™yÐtÓýM÷C�¤I5’`ýÎõ;×ï�¯ÆWã Ï·>ßú|+´2jeÔÊLÊ›”7)ÓkL¯1½´ù Ím>“q&ãLÆA?m?m?íÿõ¥xGÈLˆ"Ìx€ñã`Z`Z`ZV«¬VY­‚.Í»4ïÒªgTϨž‡ô‡ô‡ô�ö<íyÚsX³qÍÆ5!`KÀ–€-0øèࣃ�‚{÷.î]`m‡µÖvµ–ZK­õïÛuä4Èiøøø€ÏFŸ�>!°_`¿À~àíåíåíô§?ý!÷Eî‹Ü@!„a„Ö¥¬KY—‚Š=*z@å#•�T>-J·(Ý¢4œÎ=�{:.ï½¼÷ò^>{øìá³ÁWï«÷ÕÃOüÄO€{¨{¨{(dwËî–Ý üŽùó;ïŸ}ÿìûgÁ,Ü,Ü,ÜÐgK¼i2¢S³Õl5ø†oøèD':½ú¹™ÎLg¦ƒÂ‹… /BNlNlN,< ~ü,œuÎ:gÝ«åË4)Ó¤LØ¿`ÿ‚ý @¦ Ó†� &˜üV€B )u·º[Ý ¼ä%/_½Î{¼Ç{€N8ýêõÿ´žêuÇ«—òø“ÇŸÀCŸ‡>} âVÄ­ˆ[p»á톷‚ÑÇF} j¬«Æ‚éÓ¦ À!Ï!Ï!JÞ.y»ämCŸ%a(R`BaŠ»â®¸I$‘<à~µ€-¶ØËXÆ20Yf²Ìd˜©fª™ @[ÚÒ^6yÙäe°ìmÙÛ²7hzhzhzéHÇß`‰%– ,S–)Ë€¡ e( E‹hF3š~øá\á W€ Ÿ|ò�g<ãP’’”ó9æsÌç€[„[„[´:Ýêt«ÓЦT›RmJ�©�©�© dÏ<žypà 7 �4Ò }v„¡I� Q„éRu©ºTÈOÏOÏO‡ŒÑ£3FCNPNPN¼(xQð¢ÒÒÒÀ<Ó<Ó<Þûñ½ßûŽ®=ºöèZ(H)H)H�3ËÎ,;³ ‚{÷îF�ü�íîÕíÕí…g5žÕxVR·§nOÝÏ[=oõ¼l/Ø^°²:guÎê OZ�òIÊ')Ÿ€^xú$ ƒ‘¢ÓÓÓç»Îw�ïBcMcMc äŽÉ“;êÞ¯{¿î}ðYí³Úg5hFkFkFÃ�CV Y§W�^uz<:òèÈ£#Ð1µcjÇT¨—V/­ÞïŒ`ò®å]Ë»u<ëxÖñ„Jã*�«4^†¿ ÚmŒ6B·œ9®k]׺®…¬ÛY·³nCHÃ�†! ¡Lb™Ä2‰PáE…^€q3ãfÆÍ µnjÝÔºð^ü{ñïÅÃØic§��7:Þèx£#$Å'Å'ŃåRË¥–KÁl‹Ù³-0<`xÀð°®i]Óº&K,±@ÐÀÐgK¼iŠúO†"„øwénénénÖ"¬EX j?Ô~¨=x/ò^ä½ÈÐé„0,� Q”%“L2¨;Õ�êNPªÕ‡†%DÑ ·Ñ !„(–¤À„BKR`B!Š%)0!„Å’˜BˆbI L!D±$&DQV—ºÔe¿²_ÙÊÊʆ%DÑ _d¢Ð�Ó�Ó�ƒ O4<Ñâ#â#â# ÷@î�ܰËg—Ï.hêÒÔ¥© ¸”r)åR \r\r\r^Í!h1ÅbŠÅCï�o†|‘Yˆ"À¨®Q]£ºŸ¿ÿùûŸ¿ÿïËáG~õÿ}ô]Ðw´)hSЦÀÐ{!Ä›%—…(BšÇ7�oî×ݯ»_ÿÏËY&X&X&@[ç¶Îm�ÁôkÓ¯M¿6tz!Þ,)0!Š�j›ªmª¶ ª{V÷¬îùŸ—óÐxh<4à?Íšÿ4C§Â0¤À„(B,ü,ü,ü �Y;³vf )¥)¥)õïË 8\¾rùÊå+C§Â0¤À„(‚ü/ú_ô¿eÒˤ—IõºmÛ2¶e Å…Z\“Þ&½Mz:­†!&DäyÊó”ç)ðKóKóûÕs»*UªT©R%¨¬þ±úÇ �RÃ’¢²j1Ôb(Õ ªT,nXܰ¸Í{7ïݼ7¸,tYè²ÐÐ)…0,¹�^¼Ó –,/XéëÒ×¥¯ÝFÝFÝFP¼oÅÛp¹”ï•ï•ïÁKñR¼°=`{Àöøn÷Ý=}öôÙSÐëŒuüS¬¦«éj:(÷•ûÊ}°5²5²5KKKÃåïù"³x'¥…¥…¥…ÁÊK+/­¼ç9ÏyÀögÛŸm¥¥ÒRiiÀ€-hA ÐÓÓƒ„Œ„Œ„ (ó¨Ì£2�À*Û*Û*ÔÚjmµ¶s6£Í {oöÞì½à6Ûm¶Ûlyo佑÷ÀãC�=>4`>ñV“ï”ÛŸÞþôö§°8iqÒâ$°³³ƒW{\íqìŽÛ·;ê|u¾:ßp93ÅL1u–:K�º º º  9¡9¡9š2š2š2 ¦ª©jªsöQú(} ¯N^�¼:°ÏrŸå>K8ßí|·óÝ`°Å`‹ÁàwÖï¬ßYP•@%ÐpyÅÛE L¼Ý4hÐ@ôýèûÑ÷aõ•ÕWV_�€>øú ë3¬Ï00Ÿf>Í\¾Oõ—éoêoêoÂÞU{Wí]áÚpm¸:^ëx­ã5è|¥ó•ÎWÀø‰ñã'†N+Š;)0ñV*èSЧ Dê#õ‘zؽ~÷úÝëa€Í›6мEóÍ[€f¯f¯f¯¡Ó¾…ºÐ….p©Î¥:—êÀ¢v‹Ú-jUêU©W¥ Ú3hÏ =`ÛÒ¶¥­!/ÕŠbM L¼UÒž¦=M{ +ú®è»¢/<°`ÿÀFTQuDU¨V%¬J˜¡S¾{ž”zRêI)Xxáý…÷!GþŽü0"`DÀˆ(çVέœ›¡SŠâFn£o…„ À¤ÜI¹“r!o\Þ¸¼q0µòÔÊS+KqšËS—§.OáËœ/s¾ÌÏ=ž{<÷@Ø‚°a àtÞé¼ÓyÀD&2ÑÐiEq!&ЧÃæ0Dߊ¾} ¦®˜ºbê ¨ñ²ÆË/aB‰ %&”çiÎӜ峭"ê„U «0¸ÞàzƒëA÷øîñÝãaQü¢øEñÙ6²md[Ð6Ñ6Ñ61tZQÔÉ%DQ¬4/h^Ð"Í#Í#Í!Ê(Ê(Êúº÷uïë-Æ´Ób h*i*i*:­ø£â"â"â"`i…¥–Vï Þ¼7À ƒf šv¶v¶v¶†N)Š)0Q,¼¨ó¢Î‹:°Òh¥ÑJ#¸Ÿx?ñ~"ŒL™<2ª(U”*Š¡SŠ¿*ygòÎä�°èࢃ‹B~åüÊù•aä�‘F�mÛ<¶:¥(*¤ÀD‘–�™�™� �:-t»L»L»Lž9^¯�‡ScN�95VUXUaUèÐ5 +ôrëåÖË ,½-½- 8Õ“x3´_j¿Ô~ QIQIQIþQøGáAç ÎA�ƒ Cûí;´“M&›L6:­xÓä&Q$„„„BxÙð²áeayàòÀå�Ð÷eß—}_€«®¸ú¿—.I—¤K‚Ôå©ËS—CFDFDF�H"‰=wþÓü§ùO!£RF¥ŒJ Öëƒ!Ë1Ë1Ëž�y6æÙйéÜtn`= .V«‹ÿþã¬õÓúiý`‡ýöw€5ýÖô[Ó²Kd—È.ñ÷mG]«®U×B–]–]–<›þlú³é sÕ¹ê\ÿøzŒgÏ0žÁ“‚'O‚Ϧ~6õ³©°ÏkŸ×>/X¸táÒ…K!#$#$#äï?^¢h“•v'íNÚ˜;eSàÄÞ{Oì…СB@à²Àe�Ë@3B3B3â_AXAXA,2_d¾Èf}4ë£Y�ꮺ«î=ÿß3¾g|aÆøãgŒ‡Ì#™G2�Àé§œ!—C.‡\†txÐáÕûÔêuÇo¬§ÂŒ 3*@ÎÙœ³9gÿþã}fá™…gÂ~í~í~-¸—t/é^Ô 5CÍøû¶£‹ÐEè" öTì©ØSbbbZ?hý õŸXaE*Rªï¯¾¿ú~˜òdÊ“)O õËÔ/S¿„)e§”�R��eŠòw†˜0ˆÛ· nÀ”ÊS*O© y»òvåí‚°ZaµÂjAU‡ªUsÌ1ÿóÛ±Xm±Úb5¸Ìq™ã2Òf§ÍN› $�@Â_ßß¾;|wÀÇ1Ç|vSí¦ÚMŸ…> }B¶¶¶?è6ë6ë6C\N\N\xxàá�‡¿±žú×ÿ¸>X¬³Xg±îï?î7~¹ñË�_ ? ? ?Zº¶tmé 6¡6¡6¡ßvŒ£Œ£Œ£À'Ã'Ã'²s²s²s °[a·Ân}ýnÉnÉnÉðE—/º|Ñ*Ý­t·Ò]˜ÒpJÃ) áôúÓëO¯õ¤zR=ù÷GQ4È¿UÄ›a‚ &pb艡'†ÂêS«O­>þý7úo„¾sûÎí;ÌO™Ÿ2?õ¶¿’•¬„ij‰gϦ3›Îl:©�R;¥v‚Æol¼ K–*,‡\¹r…? øaÀpÿôýÓ÷OÃá9‡çž |0ð$êu‰:8ÒöHÛ#maàûßø>(w•»Ê]P¾R¾R¾‚çêsõ¹ +rWä®È­›ÖMëŽ�;;víxíxíx8Þæx›ãm Kr—ä.ɰ7joÔÞ(°l`ÙÀ²X¤X¤X¤@JÓ”¦)M¡Ïç}>ïó98Ïržå<ë?ï~êâÔÅ©‹áüšókί�ëw¯ß½~ö�Ú7jß(Hi—Ò.¥<¶lÿØúÙõ³ëg.?¹üäòd/Ê^”½l l l êlÔÙ¨³�ã�ã�ã ­j´ªÑªÄ.Š]»·%nKÜyëòÖå­ƒÜŹ‹sƒ²JY¥¬ÚÒ–¶ý´ZZZÂÇi§}œeû”íS¶, ]º(:ÖìX³cMèìÙÙ³³'ß1¾c|çµü† �˜x­   !bTĨˆQ°|Èò!ˇ@ŸÑ}F÷ çœ?pþk,®™Ë\æB©ÐR¡¥B¡eAË‚–P.¡\B¹˜_k~­ùµ oÞþ¼ý5(jPÔ È Í Í ç›Î7�oBÔûQïG½™ïg¾Ÿù>8�q:ãtö¬Ý³vÏZH;œv8í0( •†JCÀ_|Á>À>À>,Z[´¶h ^½z„ªÚªÚªZp¼ìxÙñ2ì¾·ûÞî{ ]¢]¢]ñÞñÞñÞðôîÓ»OïBóöÍÛ7oç¬ÏYŸ³†}£÷�Þ7ú¿ï¾ÓN§�N;¡|lùØò±P6¡lBÙhdÝȺ‘5”¢¥€SõOÕ?U̘50k±Æ±Æ±Æ0¹Ëä.“»€®‰®‰® dµËj—Õì¶ÚmµÛ 'Çž{r,lž²yÊæ)Ðüûæß7ÿ~ ø)à'0Ûg¶Ïl°Œe,ûûO¯¦»¦»¦;ÁøqãÇ�ûîo¸¿!,I^’¼$²\³\³þ‡ÏàDÑ&&^«ï›|ßäû&°î溛ën„À �!°o`ßÀ¾ ‰ÑÄhbÞ@�<à˜›››››ƒs¸s¸s84}ÖôYÓg�cžcžcÇ>ûp,˜¬0Ya²”!ÊeX¶·loÙŒ–-7ZJO¥§Ò,M,M,MÀh¥ÑJ£• Ä*±J,�N:é F©Qj˜†˜†˜†€yŽyŽyØÆØÆØÆ€Å.‹]»^=Ò¨·Qo£Þ`²Ñd£ÉF0ûÀì³À²Ÿe?Ë~à’å’å’ŽÕ«;V‡Ô§©OSŸBNÙœ²9e!ºTt©èRpT{T{T q�ãÇ=ö³Ÿý`Ýź‹u°ê`ÕÁª8$:$:$BÀ�?üŽ8€ ¦L/˜BÂÓ„§ O!6?6?6Î|uæ«3_½º£ú¨ê£ª�‚“%N–8Y*XT°¨`ž›=7{n†§Kœ.q4-5-5-AMPÔ¿áÒíô ¿ð Ô¸^ãz�ë0Íxšñ4c8ûÃÙÎþ3šùÓÌŸ ÿhþÑü£oà÷N¼VR`⵪r£Ê�*7ÀÙÄÙÄÙΖ;[îl9È�Ê�Ê�zƒAtèÐ�zS½©Þ^ò’— „)aJEQÀ°àWÏ­ªMmj¿zÿŸ¦¢¢N8áÄ¿„V@ ¦¨)jʯ^·Ã;ÐÔÕÔÕÔ…Ì™ 2@lNlNlÄXÇXÇXõqׯ]÷«÷iÑ¢5F�Qc@�£ÎQç€u„u„uÔÓÔÓÔÓÀ¶1ÛÆlÚÚÚÐâP‹C-Á–1[ÆlÚ®Ú®Ú®àºÞu½ëzÈ;šw4ï(˜~jú©é§oð¼þ§Ó=V7V7.] ºª“ê¤:AÝÎu;×í Æ Æ Æ¯³HÅ!&^«Æ7ßl|ÂÆ„� qš8Mœf˜u`Öxô,èYÐòÏ¿¸uKuKuK¡°baÅŠ78npÜ`°úÜês«Ï¡rïʽ+÷mEmEmEÈ>™}2û$hMµ¦ZSПџџ�—ÎK纇º‡º‡ ©© ÚTmª6tñºx]<è'ê'ê'‚ö;íwÚï@IT•DH/H/H/íííÐÒÒý—ú/õ_Ba‰Â…%@×O×O×tÓuÓuÓ_íŽn­n­n-|[ðmÁ·àÚŵ‹kŸ=>{|6„æ…æ…æAŸ�}6öÙø«÷UÔUÔU��ÎGçúžúžúž¯~°0`aÀB¸ÔúRëK­¡TéR¥K•†ví<Úy@t¥èJÑ•À#Î#Î#îÕû¼2¼2¼2àîî»»ïî†ìèìèìh(¬_X¿°>èGëGëGƒ¾·¾·¾÷ë;Íÿº{så‚• V.€ˆÖ­#ZèÐQ¡£BáýÉïO~2……Ém÷Åž˜x#*úWô¯èSÏO=?õü«HN*œT8©®—º^êúkœQ£ÖàZƒk †RcK�-5ÖõX×c]ˆ‰�‰�‰‡¡öCí‡ÚCµÈj‘Õ"¡Ýêv«Û­†½ãöŽÛ;bkÇÖŽ­ åj–«Y®&¤D¥D¥DÁõ×\o.ö.ö.öpc×�]7vÁµY×f]›®©®©®©p¯Þ½z÷êA³´fiÍÒà‘ý#ûGö°sèΡ;‡B|ƒøñ Àõ‚ë× pfæ™™gf§8Å)Еԕԕ„‡~ýú�É“+&W@¯Óëô:ÈÝ•»+w×ÞÿÌ%™K2—@ú�ô;éw@3D3D3nM¸5áÖ„WËyú{ú{úCö~õÚÖk[¯-TY_e}•õðÁóžðªÝ¬v³ÚÍWï뺴ëÒ®K¡â¶ŠÛ*nƒUÝWu_ÕŽO8>áøðèêÑÕ£+¤¾L}™úòï?¿É“&„é3Òg¤CBû„ö íaÊà)ƒ§ †ú§êŸª ÃƼ¾ß3ñfÉL æÌ)˜[6mÙ´eìn¹»åî–п^ÿzýëA‹¹-涘û7~Fv‹[ÜÝÝÝÐ=Ó=Ó=MŠ&E“Æ=�{÷ZÓšÖ ¶P[¨- pKá–Â-  Õ„jB�où–oA¤ Ò�ZN-§–ÕNµSí@Y©¬TVÁ ª�ê£ú€RZ)­”£‹F�.Ba•Â*…U€‘Œd$húhúhú€Z^-¯–ö²—½€'žx‚rH9¤åŽrG¹ú�ú�ú� ÌSæ)óÀ¨¶Qm£ÚÀ6¶ñsªOÔ'êЭ֭֭6³™Í ñ×øküA3O3O30à 3P¿S¿S¿ÅIqRœ€¾ô¥/¨…j¡ZJ´­DÍiNóWÛÑoÕoÕomœ6NJ?¥ŸÒ ÅB±Í4Í4Í4Ð,Ò,Ò,âÿîNýŸµ£íàRâ¥ÄK‰°8iqÒâ$ð¹ásÃç|Té£JU› › ›¿ñûm¢h‘†õ¯ÛëŸ|b0¬Z¸j᪅ÐäÇ&?6ùú®ì»²ïJ0?i~Ò\¾ÏóÎÓGê#õ‘°·ÛÞn{»AxXxXxtÒqHÇ!ÐÙ¿³g0¾m|Ûø¶¡ÓŠ×M.! Ã*¤�Bð_â¿Ä LÜ?qÿÄýpåÁ•WÀ×�_~øê6rñnÊ>”}(û¬X±bÅŠ°%zKô–h3"fD t�ïß5^Šë]##0Q$¥]H»�v–Ç.�] ‰y‰y‰y0gè´¢¸‘oµ„ À‚: ê,¨N~N~N~0ìΰ;Ãî€óTç©ÎS �òí““š“š“ >Þðñ†�áô¡Ó‡N‚¡“†N: üîùÝó»,d! �VWR`â��——+­´b<ðyàóÀFôÑkD/¨Ò¶JÛ*ÃßuO‚Ÿ? ~õÙVÞò¼åyËa„÷ïÞP®Q¹Få:¥x[H�‰wJAï‚Þ½!Ò$Ò$Òö˜í1ÛcõºÕëV¯¸Vq­âZXÃÖ2è?£Â 1ŒÎ�7:ú]ú]ú] :ªŽª#`�=ö†‹©ÌVf+³!½qzãôÆpªÑ©F§�o¢o¢o" ê9¨ç ž`hhhÀã)ÞJR`â�¤¦©ijÄtŠéÓ ]8táÐPü?ÅøœÏùÜpùþõ ͼ¨¼¨¼(8÷à܃s êùªç«ž‡=z€zK½¥Þ2à�Ì'Ÿ|е׵׵‡Z k5¬ÕÚÌj3«Í,0ñ7ñ7ñ7`>ñV“¢K7M7M7…Éõ&×›\†F� •5•5•eñŽ“?Beÿœì˜«\å*�M6Ù†%DÑ &„¢X’BQ,I� !„(–¤À„BKR`B!Š%)0!„Å’˜BˆbI L!D±$&„¢X’BQ,I� !„(–¤À„BKR`B!Š%)0!„Å’˜BˆbI L!D±$&„¢X’BQ,I� QP@ð„'<ùÕë¶Øb „J((” J…_ý<•TR�l²É6ôNñf)ê?:ˆï2ÝVÝVÝV8^öxÙãe!^¯‰×@ntntn4üâó‹Ï/>Ð* U@+p‰s‰s‰×P×P×PJ J J‹X‹X‹XCï�o†±¡!À¨‹Q£.paÒ…I&ÁøöãÛ�oŒcã@�§ÎSçÁ±Ç:ëj¾š¯æÃ·nÜ ¸spçàÎ†Þ !Þ,¹„(DÒdl“±MÆBi]i]i¨ZU«j�‘Œdä«â²L°L°L€ÀÎ��;ƒÉb“Å&‹ �^ˆ7K Lˆ"Ä7Ç7Ç7jt®Ñ¹ÆïŒ¨<==Áÿ‘ÿ#ÿG†N-„aH� Q„X¸Y¸Y¸Að‰àÁ'@³Z³Z³úß—kÕ©U§V�Àe¤ËH—‘†N-„aÈg`BAþþþàþÜý¹ûsH$‘DÀ¦ƒM›Ð,¾Y|³x0ifÒ̤™¡Ó a2¢òœé9Ós&42idÒÈäÕëÞÞÞàwÙï²ßeC§°¤À„(‚,ú[ô·èAÎAÎAÎ`1Öb¬ÅXhQ­EµÕÀe‰Ë—%†N)„aÉ%DñNÈðÈðÈð€}¹ûr÷åBú²ôeéË@©ªTUª:Ý¿S¼/Å x8àá0‰1‰1‰�ôGé�ÒÁêÖ«[¯n úúú†NûÖ°†5`ºÅt‹éhY¿eý–õÁ}“û&÷M†'ÞR`â�ðhÝ£u�ÖÁú õAëƒ 0#0#0Lt&:�¡Óý;ÅAqPÀ±“c'ÇN®Y®Y®Y�ç›ç›ç ªNÕ©E1ÿ4eš2 vœÜqrÇI(IIJî¸ãnèpâ­!&Þ ê�ê�ê�àfïfïfÃúë;¬/˜™š™š™:ÝoÈ ƒ  ,e) ù�ó;çw“)&SL¦€ÆYã¬q6tÈÿîaðÃà‡Á wÓ»éÝ �F¼m¤À„(Êþyû¡f˜:‹EŒÜÄ!„¢X’BQ,I� !„(–¤À„BKR`B!Š%)0!„Å’ÜF/ÄŸ�ñ2ãeÆK¸·ñÞÆ{¡ÔõR×K]‡’÷JÞ+yž$*ù¨ä#°œ`9Ár´ø¢Å-¾µªZU­ ;vì ÇŽ={@l`l`l ØL¶™l3Ä ú¬ñ2âw<œûpîù°hõ¢Õ‹VC³…Í6[› l2° xŽðá9tn:7�”˜TbR‰I�w&ïLÞx´ÿÑþGûáæ“›On>�mÍ·5ßÖ: é4¤ÓhݸuãÖ�Á<Í<Í< ÎÍ?7ÿÜ|Ï Ï ÏƒnG»ívG Ž›<6ylý9ý9ý9°ýÖö[Ûo¡OÓ>Mû4…®^]½ºzÁÏ7~¾ñó È·Ë·Ë·ƒ¼%yKò–@ÚgiŸ¥}­ÂZ…µ ˜;~îø¹ãÁã¢ÇE�‹ðÑ{½÷Ñ{P¿Lý2õË€:K�¥Î4häo QTÈLˆß‘˜˜¹Ú\m®¼ïzßõ¾ Ê`e°2ŒÚµ1jêõ‚záÕûŒ‚�‚�‚�'<á ¸}äö‘ÛGàïï“FN9i$tý°ë‡]?O/O/O/¸p-àZØœ°9asÊ\*s©Ì%Pæ)ó”yÐκ�u;kÐØhl46`ddWï†_ ‡g—ž]zv ²eÊ>:K�¥ÎŒs�s�s¡äÇ%?.ù1TWi\¥q�ü^ò{ÉïÁýÏîvÿ3ðíæÛÍ·Û«ý0Ž0Ž0Ž5YMV“�—¼ä¥¡ÏŠÿ &ÄïP•p%xÄ#ý꿃Ì`þï3$¥ŠRE©Üâ·k¬±}w}w}wp=èzÐõ Ìm:·éܦp&òLä™H˜gþ�ùwÀê¸Õq«ã`fmfmf º†º†º† vP;¨@é¦tSº� &˜éýÒû¥÷ƒI3'Íœ4‚&Mš¥•ÒJiŒ#ÅH,±ÄH!…`/{Ù Ìcó€þô§?Pžò”µ´ZZ-ý«`„F TSª)Õ€óœç¼¡ÏŠÿ „øe¼Êx•ñ›26elÊ@Ìј£1G!­nZÝ´º�û ÷AîÈ-›[6·,h;h;h;@îšÜ5¹k wOîžÜ=pÝ÷ºïu_8¿àü‚ó À®ÿ\ÿ¹à±Çc�ÇÈy–ó,çÔ™Zgj�©�Û7·on_ˆ™3/f¤ J”22ÇgŽÏ¹³rgå΂¤óIç“΃[†[†[¸•v+íVôQú(}dùfùfùBn\n\ndΜ=XÅ*V�]»v Òו¾®ô5œjxªá©†�¾(}Qú"Ⱦœ}9û2ä©yjž Ú/µ_j¿4ôYâ¤À„øîUÜ«¸W�±¡cCdžÂ��;!wBàÀª«¬ŸDŸDŸD(½¡ô†Ò ¡NB�„:P©S¥N•:�C�C�C¨ËÕåêrxÒþIû'íaçÕ�Ww^…6ÛZú¨?Ðò-1aÆ„f@·&nMܠ݀vÚ 0t*ñ¶�˜BˆbI L!D±$&„¢X’BQ,I� !„(–¤À„BKR`B!Š%)0!„Å’˜x7Üæ6·A}ª>UŸ"³ª¿)Ùd“ \æ2— F¼md2_ñN0©lRÙ¤2¤LJ™”2 ¾èðE‡/:€I“>&} �î-4Ÿù̇K/U¼T7n ÜdèPâm#&Þ î�ܹ7‚Ðs¡çBÏAÆ�?füJ¶’­d:ÝÛGµV­Ukh×*®UÔ̬™Y3ÓЩÄÛFæBBQ,ɧB!Š¥ÿ;¹uîe+‰ô.zTXtcreate-datexÚ320°Ô50Õ54 14µ2µ´22×60²20B# ðc}.zTXtmodify-datexÚ320°Ô50Õ54 14µ25°26Ñ60²20A¼õä‡IEND®B`‚rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_abortonuncleanconfig.rst0000644000000000000000000000013015171370365031001 xustar0029 mtime=1776677109.10790793 29 atime=1787067672.21144777 30 ctime=1787067791.125664136 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_abortonuncleanconfig.rst0000664000175000017500000000302015171370365030442 0ustar00rgerrger:doc:`rsyslog.conf configuration parameter ` $AbortOnUncleanConfig ---------------------- **Type:** global configuration parameter **Parameter Values:** boolean (on/off, yes/no) **Available since:** 5.3.1+ **Default:** off **Description:** This parameter permits to prevent rsyslog from running when the configuration file is not clean. "Not Clean" means there are errors or some other annoyances that rsyslogd reports on startup. This is a user-requested feature to have a strict startup mode. Note that with the current code base it is not always possible to differentiate between a real error and a warning-like condition. As such, the startup will also prevented if warnings are present. I consider this a good thing in being "strict", but I admit there also currently is no other way of doing it. It is recommended to use the new config style. The equivalent of this parameter in the new style is ``global(abortOnUncleanConfig="")``. **Caveats:** Note that the consequences of a failed rsyslogd startup can be much more serious than a startup with only partial configuration. For example, log data may be lost or systems that depend on the log server in question will not be able to send logs, what in the ultimate result could result in a system hang on those systems. Also, the local system may hang when the local log socket has become full and is not read. There exist many such scenarios. As such, it is strongly recommended not to turn on this parameter. [`rsyslog site `_\ ] rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_debugprinttemplatelist.r0000644000000000000000000000013215132411300031005 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.278449019 30 ctime=1787067791.131664248 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_debugprinttemplatelist.rst0000666000175000017500000000045215132411300031023 0ustar00rgerrger$DebugPrintTemplateList ----------------------- **Type:** global configuration parameter **Default:** on **Description:** Specifies whether or not the template list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled.. rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_modload.rst0000644000000000000000000000013215132411300026200 xustar0030 mtime=1768559296.174884185 30 atime=1787067671.753439232 30 ctime=1787067791.147664546 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_modload.rst0000666000175000017500000000156015132411300025650 0ustar00rgerrger$ModLoad -------- **Type:** global configuration parameter **Default:** **Description:** Dynamically loads a plug-in into rsyslog's address space and activates it. The plug-in must obey the rsyslog module API. Currently, only MariaDB/ MySQL and Postgres output modules are available as a plugins, but users may create their own. A plug-in must be loaded BEFORE any configuration file lines that reference it. Modules must be present in the system default destination for rsyslog modules. You can also set the directory via the `$ModDir `_ parameter. If a full path name is specified, the module is loaded from that path. The default module directory is ignored in that case. **Sample:** .. code-block:: none $ModLoad ommysql # load MariaDB/MySQL functionality $ModLoad /rsyslog/modules/ompgsql.so # load the postgres module via absolute path rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_resetconfigvariables.rst0000644000000000000000000000013215132411300030762 xustar0030 mtime=1768559296.174884185 30 atime=1787067671.779439716 30 ctime=1787067791.149664584 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_resetconfigvariables.rst0000666000175000017500000000066315132411300030435 0ustar00rgerrger$ResetConfigVariables --------------------- **Type:** global configuration parameter **Default:** **Description:** Resets all configuration variables to their default value. Any settings made will not be applied to configuration lines following the $ResetConfigVariables. This is a good method to make sure no side-effects exists from previous parameters. This parameter has no parameters. **Sample:** ``$ResetConfigVariables`` rsyslog-8.2608.0/doc/source/configuration/global/options/PaxHeaders/rsconf1_debugprintmodulelist.rst0000644000000000000000000000013215132411300031026 xustar0030 mtime=1768559296.173884169 30 atime=1787067672.256448609 30 ctime=1787067791.129664211 rsyslog-8.2608.0/doc/source/configuration/global/options/rsconf1_debugprintmodulelist.rst0000666000175000017500000000044315132411300030475 0ustar00rgerrger$DebugPrintModuleList --------------------- **Type:** global configuration parameter **Default:** on **Description:** Specifies whether or not the module list should be written to the debug log. Possible values: on/off. Default is on. Does not affect operation if debugging is disabled. rsyslog-8.2608.0/doc/source/configuration/global/PaxHeaders/index.rst0000644000000000000000000000013115171370365022563 xustar0029 mtime=1776677109.10790793 30 atime=1787067672.184447266 30 ctime=1787067791.123664099 rsyslog-8.2608.0/doc/source/configuration/global/index.rst0000664000175000017500000002157615171370365022243 0ustar00rgerrgerLegacy Global Configuration Statements ====================================== Global configuration statements, as their name implies, usually affect some global features. However, some also affect main queues, which are "global" to a ruleset. True Global Directives ---------------------- .. toctree:: :glob: options/rsconf1_abortonuncleanconfig options/rsconf1_debugprintcfsyslinehandlerlist options/rsconf1_debugprintmodulelist options/rsconf1_debugprinttemplatelist options/rsconf1_failonchownfailure options/rsconf1_generateconfiggraph options/rsconf1_includeconfig options/rsconf1_mainmsgqueuesize options/rsconf1_maxopenfiles options/rsconf1_moddir options/rsconf1_modload options/rsconf1_umask options/rsconf1_resetconfigvariables - **$MaxMessageSize** , default 8k - allows to specify maximum supported message size (both for sending and receiving). The default should be sufficient for almost all cases. Do not set this below 1k, as it would cause interoperability problems with other syslog implementations. **Important:** In order for this directive to work correctly, it **must** be placed right at the top of ``rsyslog.conf`` (before any input is defined). Change the setting to e.g. 32768 if you would like to support large message sizes for IHE (32k is the current maximum needed for IHE). I was initially tempted to set the default to 32k, but there is a some memory footprint with the current implementation in rsyslog. If you intend to receive Windows Event Log data (e.g. via `EventReporter `_), you might want to increase this number to an even higher value, as event log messages can be very lengthy ("$MaxMessageSize 64k" is not a bad idea). Note: testing showed that 4k seems to be the typical maximum for **UDP** based syslog. This is an IP stack restriction. Not always ... but very often. If you go beyond that value, be sure to test that rsyslogd actually does what you think it should do ;) It is highly suggested to use a TCP based transport instead of UDP (plain TCP syslog, RELP). This resolves the UDP stack size restrictions. Note that 2k, is the smallest size that must be supported in order to be compliant to the upcoming new syslog RFC series. - **$LocalHostName** [name] - this directive permits to overwrite the system hostname with the one specified in the directive. If the directive is given multiple times, all but the last one will be ignored. Please note that startup error messages may be issued with the real hostname. This is by design and not a bug (but one may argue if the design should be changed ;)). Available since 4.7.4+, 5.7.3+, 6.1.3+. - **$LogRSyslogStatusMessages** [**on**/off] - If set to on (the default), rsyslog emits message on startup and shutdown as well as when it is HUPed. This information might be needed by some log analyzers. If set to off, no such status messages are logged, what may be useful for other scenarios. [available since 4.7.0 and 5.3.0] - **$DefaultRuleset** [name] - changes the default ruleset for unbound inputs to the provided *name* (the default ruleset is named "RSYSLOG\_DefaultRuleset"). It is advised to also read our paper on :doc:`using multiple rule sets in rsyslog <../../concepts/multi_ruleset>`. - **$DefaultNetstreamDriver** , the default :doc:`network stream driver <../../concepts/netstrm_drvr>` to use. Defaults to ptcp. - **$DefaultNetstreamDriverCAFile** - **$DefaultNetstreamDriverCertFile** - **$DefaultNetstreamDriverKeyFile** - **$NetstreamDriverCaExtraFiles** - This directive allows to configure multiple additional extra CA files. This is intended for SSL certificate chains to work appropriately, as the different CA files in the chain need to be specified. It must be remarked that this directive only works with the OpenSSL driver. - **$RepeatedMsgContainsOriginalMsg** [on/**off**] - "last message repeated n times" messages, if generated, have a different format that contains the message that is being repeated. Note that only the first "n" characters are included, with n to be at least 80 characters, most probably more (this may change from version to version, thus no specific limit is given). The bottom line is that n is large enough to get a good idea which message was repeated but it is not necessarily large enough for the whole message. (Introduced with 4.1.5). Once set, it affects all following actions. - **$OptimizeForUniprocessor** - This directive is no longer supported. While present in versions prior to 8.32.0, the directive had no effect for many years. Attempts to use the directive now results in a warning. - **$PreserveFQDN** [on/**off**) - if set to off (legacy default to remain compatible to sysklogd), the domain part from a name that is within the same domain as the receiving system is stripped. If set to on, full names are always used. Reverse lookup results are cached; see :ref:`reverse_dns_cache` for controlling cache refresh. - **$WorkDirectory** (directory for spool and other work files. Do **not** use trailing slashes) - :doc:`$PrivDropToGroup ` - :doc:`$PrivDropToGroupID ` - :doc:`$PrivDropToUser ` - :doc:`$PrivDropToUserID ` - **$Sleep** - puts the rsyslog main thread to sleep for the specified number of seconds immediately when the directive is encountered. You should have a good reason for using this directive! - **$LocalHostIPIF** - (available since 5.9.6) - if provided, the IP of the specified interface (e.g. "eth0") shall be used as fromhost-ip for local-originating messages. If this directive is not given OR the interface cannot be found (or has no IP address), the default of "127.0.0.1" is used. Note that this directive can be given only once. Trying to reset will result in an error message and the new value will be ignored. Please note that modules must have support for obtaining the local IP address set via this directive. While this is the case for rsyslog-provided modules, it may not always be the case for contributed plugins. **Important:** This directive shall be placed **right at the top of rsyslog.conf**. Otherwise, if error messages are triggered before this directive is processed, rsyslog will fix the local host IP to "127.0.0.1", what than can not be reset. - **$ErrorMessagesToStderr** [**on**\ \|off] - direct rsyslogd error message to stderr (in addition to other targets) - **$SpaceLFOnReceive** [on/**off**] - instructs rsyslogd to replace LF with spaces during message reception (sysklogd compatibility aid). This is applied at the beginning of the parser stage and cannot be overridden (neither at the input nor parser level). Consequently, it affects all inputs and parsers. main queue specific Directives ------------------------------ Note that these directives modify ruleset main message queues. This includes the default ruleset's main message queue, the one that is always present. To do this, specify directives outside of a ruleset definition. To understand queue parameters, read :doc:`queues in rsyslog <../../concepts/queues>`. - **$MainMsgQueueCheckpointInterval** - **$MainMsgQueueDequeueBatchSize** [default 32] - **$MainMsgQueueDequeueSlowdown** [number is timeout in *micro*\ seconds (1000000us is 1sec!), default 0 (no delay). Simple rate-limiting!] - **$MainMsgQueueDiscardMark** [default 98% of queue size] - **$MainMsgQueueDiscardSeverity** [either a textual or numerical severity! default 4 (warning)] - **$MainMsgQueueFileName** - **$MainMsgQueueHighWaterMark** [default 90% of queue size] - **$MainMsgQueueImmediateShutdown** [on/**off**] - **$MainMsgQueueLowWaterMark** [default 70% of queue size] - **$MainMsgQueueMaxFileSize** , default 1m - **$MainMsgQueueTimeoutActionCompletion** [number is timeout in ms (1000ms is 1sec!), default 1000, 0 means immediate!] - **$MainMsgQueueTimeoutEnqueue** [number is timeout in ms (1000ms is 1sec!), default 2000, 0 means discard immediately] - **$MainMsgQueueTimeoutShutdown** [number is timeout in ms (1000ms is 1sec!), default 0 (indefinite)] - **$MainMsgQueueWorkerTimeoutThreadShutdown** [number is timeout in ms (1000ms is 1sec!), default 60000 (1 minute)] - **$MainMsgQueueType** [**FixedArray**/LinkedList/Direct/Disk] - **$MainMsgQueueSaveOnShutdown**  [on/**off**] - **$MainMsgQueueWorkerThreads** , num worker threads, default 2, recommended 1 - **$MainMsgQueueWorkerThreadMinumumMessages** , default queue size/number of workers rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/converting_to_new_format.rst0000644000000000000000000000013115171370365025315 xustar0029 mtime=1776677109.10790793 30 atime=1787067672.022444246 30 ctime=1787067791.107663801 rsyslog-8.2608.0/doc/source/configuration/converting_to_new_format.rst0000664000175000017500000001740515171370365024771 0ustar00rgerrgerConverting older formats to |FmtAdvancedName| ============================================= First of all, converting of older formats is not strictly necessary. All formats can be mixed and matched and play well together. There are still a number of reasons to convert older formats: * existing simple constructs need to be enhanced and become more complex * aid future extensions * ensure no side-effects accidentally occur * unify rsyslog.conf language For broader migrations, rsyslog can also translate supported configurations directly between canonical RainerScript and YAML. See :doc:`../tutorials/config_format_translation` for the built-in translation workflow. The built-in translator currently recognizes a limited subset of traditional selector/action syntax for structured YAML output. Common file actions (``/var/log/...`` and ``-/var/log/...``) and ``:omusrmsg:...`` are covered, but broader legacy syntax still requires review and may fall back to warnings or raw script output. Do not overdo conversion ~~~~~~~~~~~~~~~~~~~~~~~~ Note: simple facility and severity based filters which trigger writing to files can actually be very well expressed in |FmtBasicName|. So if you have something like:: mail.info /var/log/maillog We suggest you leave it as-is without conversion. Equally, in our opinion it is also fine to add new rules like the above. If you still want to convert, the line may look as follows (completely in new format):: if prifilt("mail.info") then { action(type="omfile" file="/var/log/maillog") } More compact, this can also be written like:: if prifilt("mail.info") then action(type="omfile" file="/var/log/maillog") The older-selector-style filter is well-known, so this may also write it as:: mail.info action(type="omfile" file="/var/log/maillog") There are ample additional possibilities. We suggest to keep things consistent. Converting Module Load ~~~~~~~~~~~~~~~~~~~~~~ This is very straight-forward. In |FmtObsoleteName| format we use:: $ModLoad module-name This is very simply converted to:: module(load="module-name") Sometimes modules provide global settings. In |FmtObsoleteName| format these are given in individual lines **after** the \$ModLoad. In |FmtAdvancedName| format they are given inside the module object. This makes it much clearer which module they belong to and that they actually are global parameters (in contrast to per-action or per-listener parameters). A typical example is `imtcp`:: $ModLoad imtcp $InputTCPMaxSession 500 This is converted to:: module(load="imtcp" maxSessions="500") Note: in |FmtObsoleteName| format it is possible to provide global parameters more than once. In this case it is unclear which one actually applies. For example:: $ModLoad imtcp $InputTCPMaxSession 500 ... *.* /var/log/messages ... $InputTCPMaxSession 200 This is especially problematic if module-global parameters are used multiple times in include files. In |FmtAdvancedName| format this is no longer possible. Module-global parameters can only be applied once when the module is loaded. Any attempt to change them afterwards results in an error message and will be ignored. The error messages will help you find and fix multiple settings. Let us assume "200" is the setting actually intended in above config snippet. So it would be converted to:: module(load="imtcp" maxSessions="200") ... *.* /var/log/messages ... Converting Actions ~~~~~~~~~~~~~~~~~~ In general, you have lines like:: filter action where *filter* is any of the filters and *action* is ... the action to be carried out. As could be seen above, the filter does **not** necessarily need to be changed in order to convert the action. All filters also work with all config formats. It often is best to keep existing filters, at least while working on the conversion (do not change too many things at once). The following table lists traditional action syntax and how it can be converted to new-style ``action()`` objects. The link will bring you to detail documentation. In these detail documentations all parameters are given. It is also specified which |FmtObsoleteName| directives map to |FmtAdvancedName| properties. This table is not conclusive but covers the most commonly used actions. .. csv-table:: :header: "|FmtBasicName|", "|FmtAdvancedName|" :widths: auto :class: parameter-table "file path (`/var/log/...`)", "action(type="":doc:`omfile `"" file=""/var/log.../"" ...)" "UDP forwarding (`@remote`)", "action(type="":doc:`omfwd `"" target=""remote"" protocol=""udp"" ...)" "TCP forwarding (`@@remote`)", "action(type="":doc:`omfwd `"" target=""remote"" protocol=""tcp"" ...)" "user notify (``:omusrmsg:user``)", "action(type="":doc:`omusrmsg `"" users=""user"" ...)" "module name (``:omxxx:..``)", "action(type="":doc:`omxxx `"" ...)" Some concrete examples:: OLD: :hostname, contains, "remote-sender" @@central NEW: :hostname, contains, "remote-sender" action(type="omfwd" target="central" protocol="tcp") OLD: if $msg contains "error" then @central NEW: if $msg contains "error" then action(type="omfwd" target="central" protocol="udp") OLD: *.emerg :omusrmsg:* NEW: *.emerg action(type="omusrmsg" users="*") **NOTE:** Some actions do not have a |FmtBasicName| format configuration line. They may only be called via the ``action()`` syntax. Similarly, some very few actions, mostly contributed, do not support ``action()`` syntax and thus can only be configured via |FmtBasicName| and |FmtObsoleteName|. See module doc for details. Action with Multiple Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In many cases, actions have additional parameters, which also need to be converted. In |FmtObsoleteName| format the action parameters are given before the actual action call. To convert such constructs, you need to map all |FmtObsoleteName| parameters to |FmtAdvancedName| ones. To look these up, you need to turn to three different documentation pages: * the :doc:`action object ` itself * the :doc:`output module ` that is called in the action (e.g. omfwd) * the :doc:`queue documentation <../rainerscript/queue_parameters>` (if an action queue is used) To find the parameter in question, you can other do an on-page search via the browser on these pages. Often it is very convenient to just use the `rsyslog doc search engine `_: Type the |FmtObsoleteName| format statement into the search box. Most often, one of the first search results is the matching object description doc page. Converting Action Chains ~~~~~~~~~~~~~~~~~~~~~~~~ Actions can be chained via the ampersand character ('``&``'). In |FmtAdvancedName| format this has been replaced by blocks. For example:: *.error /var/log/errorlog & @remote becomes:: *.error { action(type="omfile" file="/var/log/errorlog") action(type="omfwd" target="remote" protocol="udp") } The latter is much easier to understand and less error-prone when extended. A common construct is to send messages to a remote host based on some message content and then not further process it. This involves the ``stop`` statement (or it's very old-time equivalent tilde ('``~``'). It may be specified as such:: :msg, contains, "error" @remote & ~ which is equivalent to:: :msg, contains, "error" @remote & stop This format is often found in more modern distro's rsyslog.conf. It again is fully equivalent to:: :msg, contains, "error" { action(type="omfwd" target="remote" protocol="udp") stop } And, just to prove the point, this is also exactly the same like:: if $msg contains "error" then { action(type="omfwd" target="remote" protocol="udp") stop } rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/sysklogd_format.rst0000644000000000000000000000013215132411300023402 xustar0030 mtime=1768559296.183884327 30 atime=1787067673.020462851 30 ctime=1787067791.531671702 rsyslog-8.2608.0/doc/source/configuration/sysklogd_format.rst0000666000175000017500000002755715132411300023070 0ustar00rgerrger *************** sysklogd format *************** This is the format in use since the beginning of syslogging. It still is an excellent choice to do very simple things. For more advanced things, use the |FmtAdvancedName| format. DESCRIPTION =========== The syslog.conf file is the main configuration file for :manpage:`syslogd(8)` which logs system messages on \*nix systems. This file specifies rules for logging. For special features see the sysklogd(8) manpage. Every rule consists of two fields, a selector field and an action field. These two fields are separated by one or more spaces or tabs. The selector field specifies a pattern of facilities and priorities belonging to the specified action. Lines starting with a hash mark ("#") and empty lines are ignored. This variant of syslogd is able to understand a slightly extended syntax compared to the original BSD syslogd. One rule may be divided into several lines if the leading line is terminated with a backslash ("\\"). SELECTORS ========= The selector field consists of two parts, a facility and a priority, separated by a period ("."). Both parts are case insensitive and can also be specified as decimal numbers corresponding to the definitions in ``/usr/include/syslog.h``. It is safer to use symbolic names rather than decimal numbers. Both facilities and priorities are described in :manpage:`syslog(3)`. The names mentioned below correspond to the similar ``LOG_`` values in ``/usr/include/syslog.h``. The facility is one of the following keywords: auth, authpriv, cron, daemon, ftp, kern, lpr, mail, mark, news, security (same as auth), syslog, user, uucp and local0 through local7. The keyword security is deprecated and mark is only for internal use and therefore should not be used in applications. The facility specifies the subsystem that produced the message, e.g. all mail programs log with the mail facility (LOG_MAIL) if they log using syslog. In most cases anyone can log to any facility, so we rely on convention for the correct facility to be chosen. However, generally only the kernel can log to the "kern" facility. This is because the implementation of ``openlog()`` and ``syslog()`` in glibc does not allow logging to the "kern" facility. Klogd circumvents this restriction when logging to syslogd by reimplementing those functions itself. The priority is one of the following keywords, in ascending order: debug, info, notice, warning, warn (same as warning), err, error (same as err), crit, alert, emerg, panic (same as emerg). The keywords warn, error and panic are deprecated and should not be used anymore. The priority defines the severity of the message. The behavior of the original BSD syslogd is that all messages of the specified priority and higher are logged according to the given action. This :manpage:`syslogd(8)` behaves the same, but has some extensions. In addition to the above mentioned names the :manpage:`syslogd(8)` understands the following extensions: An asterisk ("\*") stands for all facilities or all priorities, depending on where it is used (before or after the period). The keyword none stands for no priority of the given facility. Multiple facilities may be specified for a single priority pattern in one statement using the comma (",") operator to separate the facilities. You may specify as many facilities as you want. Please note that only the facility part from such a statement is taken, a priority part would be ignored. Multiple selectors may be specified for a single action using the semicolon (";") separator. Selectors are processed from left to right, with each selector being able to overwrite preceding ones. Using this behavior you are able to exclude some priorities from the pattern. This :manpage:`syslogd(8)` has a syntax extension to the original BSD source, which makes its use more intuitive. You may precede every priority with an equation sign ("=") to specify that syslogd should only refer to this single priority and not this priority and all higher priorities. You may also precede the priority with an exclamation mark ("!") if you want syslogd to ignore this priority and all higher priorities. You may even use both, the exclamation mark and the equation sign if you want syslogd to ignore only this single priority. If you use both extensions then the exclamation mark must occur before the equation sign, just use it intuitively. ACTIONS ======= The action field of a rule describes the abstract term "logfile". A "logfile" need not to be a real file, btw. The :manpage:`syslogd(8)` provides the following actions. Regular File ------------ Typically messages are logged to real files. The filename is specified with an absolute pathname. It may be specified as a file name relative to rsyslog's working directory if the filename starts with "." or "..". However, this is dangerous and should be avoided. Named Pipes ----------- This version of :manpage:`syslogd(8)` has support for logging output to named pipes (fifos). A fifo or named pipe can be used as a destination for log messages by prepending a pipe symbol ("|") to the name of the file. This is handy for debugging. Note that the fifo must be created with the :manpage:`mkfifo(1)` command before :manpage:`syslogd(8)` is started. Terminal and Console -------------------- If the file you specified is a tty, special tty-handling is done, same with ``/dev/console``. Remote Machine -------------- This :manpage:`syslogd(8)` provides full remote logging, i.e. is able to send messages to a remote host running :manpage:`syslogd(8)` and to receive messages from remote hosts. The remote host won't forward the message again, it will just log them locally. To forward messages to another host, prepend the hostname with the at sign ("@"). Using this feature you are able to collect all syslog messages on a central host, if all other machines log remotely to that one. This reduces administration needs. Using a named pipe log method, messages from remote hosts can be sent to a log program. By reading log messages line by line such a program is able to sort log messages by host name or program name on the central log host. This way it is possible to split the log into separate files. List of Users ------------- Usually critical messages are also directed to "root" on that machine. You can specify a list of users that ought to receive the log message on the terminal by writing their usernames. You may specify more than one user by separating the usernames with commas (","). If they're logged in they will receive the log messages. Everyone logged on ------------------ Emergency messages often go to all users currently online to notify them that something strange is happening with the system. To specify this wall(1)-feature use an asterisk ("*"). EXAMPLES ======== Here are some examples, partially taken from a real existing site and configuration. Hopefully they answer all questions about configuring this :manpage:`syslogd(8)`. If not, don't hesitate to contact the mailing list. :: # Store critical stuff in critical # *.=crit;kern.none /var/adm/critical This will store all messages of priority crit in the file ``/var/adm/critical``, with the exception of any kernel messages. :: # Kernel messages are stored in the kernel file, # critical messages and higher ones also go # to another host and to the console # kern.* /var/adm/kernel kern.crit @finlandia kern.crit /dev/console kern.info;kern.!err /var/adm/kernel-info The first rule directs any message that has the kernel facility to the file ``/var/adm/kernel``. (But recall that only the kernel itself can log to this facility.) The second statement directs all kernel messages of priority crit and higher to the remote host finlandia. This is useful, because if the host crashes and the disks get irreparable errors you might not be able to read the stored messages. If they're on a remote host, too, you still can try to find out the reason for the crash. The third rule directs kernel messages of priority crit and higher to the actual console, so the person who works on the machine will get them, too. The fourth line tells the syslogd to save all kernel messages that come with priorities from info up to warning in the file ``/var/adm/kernel-info``. This is an example of the 2nd selector overwriting part of the first one. The first selector selects kernel messages of priority info and higher. The second selector filters out kernel messages of priority error and higher. This leaves just priorities info, notice and warning to get logged. :: # The tcp wrapper logs with mail.info, we display # all the connections on tty12 # mail.=info /dev/tty12 This directs all messages that use ``mail.info`` (in source ``LOG_MAIL | LOG_INFO``) to ``/dev/tty12``, the 12th console. For example the tcpwrapper :manpage:`tcpd(8)` uses this as its default. :: # Write all mail related logs to a file # mail.*;mail.!=info /var/adm/mail This pattern matches all messages that come with the mail facility, except for the info priority. These will be stored in the file ``/var/adm/mail``. :: # Log all mail.info and news.info messages to info # mail,news.=info /var/adm/info This will extract all messages that come either with mail.info or with news.info and store them in the file ``/var/adm/info``. :: # Log info and notice messages to messages file # *.=info;*.=notice;\ mail.none /var/log/messages This lets the syslogd log all messages that come with either the info or the notice priority into the file ``/var/log/messages``, except for all messages that use the mail facility. :: # Log info messages to messages file # *.=info;\ mail,news.none /var/log/messages This statement causes the syslogd to log all messages that come with the info priority to the file ``/var/log/messages``. But any message coming either with the mail or the news facility will not be stored. :: # Emergency messages will be displayed using wall # *.=emerg * This rule tells the syslogd to write all emergency messages to all currently logged in users. This is the wall action. :: # Messages of the priority alert will be directed # to the operator # *.alert root,joey This rule directs all messages of priority alert or higher to the terminals of the operator, i.e. of the users "root" and "joey" if they're logged in. :: *.* @finlandia This rule would redirect all messages to a remote host called finlandia. This is useful especially in a cluster of machines where all syslog messages will be stored on only one machine. CONFIGURATION FILE SYNTAX DIFFERENCES ===================================== Syslogd uses a slightly different syntax for its configuration file than the original BSD sources. Originally all messages of a specific priority and above were forwarded to the log file. The modifiers "=", "!" and "-" were added to make the syslogd more flexible and to use it in a more intuitive manner. The original BSD syslogd doesn't understand spaces as separators between the selector and the action field. BUGS ==== The effects of multiple selectors are sometimes not intuitive. For example "mail.crit,\*.err" will select "mail" facility messages at the level of "err" or higher, not at the level of "crit" or higher. Also, if you specify a selector with an exclamation mark in it which is not preceded by a corresponding selector without an exclamation mark, nothing will be logged. Intuitively, the selector "ftp.!alert" on its own will select all ftp messages with priorities less than alert. In fact it selects nothing. Similarly "ftp.!=alert" might reasonably be expected to select all ftp messages other than those with priority alert, but again it selects nothing. It seems the selectors with exclamation marks in them should only be used as "filters" following selectors without exclamation marks. Finally, using a backslash to divide a line into two doesn't work if the backslash is used immediately after the end of the selector, without intermediate whitespace. rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/property_replacer.rst0000644000000000000000000000013215241075234023751 xustar0030 mtime=1787067036.578577789 30 atime=1787067036.722580485 30 ctime=1787067791.517671441 rsyslog-8.2608.0/doc/source/configuration/property_replacer.rst0000664000175000017500000003704115241075234023422 0ustar00rgerrgerThe Property Replacer ===================== **The property replacer is a core component in rsyslogd's** `string template system `_. A syslog message has a number of well-defined properties. Each of these properties can be accessed **and** manipulated by the property replacer. With it, it is easy to use only part of a property value or manipulate the value, e.g. by converting all characters to lower case. Accessing Properties -------------------- Syslog message properties are used inside templates. They are accessed by putting them between percent signs. Properties can be modified by the property replacer. The full syntax is as follows: :: %property:fromChar:toChar:options% Available Properties ^^^^^^^^^^^^^^^^^^^^ The property replacer can use all :doc:`rsyslog properties `. Character Positions ^^^^^^^^^^^^^^^^^^^^ **FromChar** and **toChar** are used to build substrings. They specify the offset within the string that should be copied. Offset counting starts at 1, so if you need to obtain the first 2 characters of the message text, you can use this syntax: "%msg:1:2%". If you do not wish to specify from and to, but you want to specify options, you still need to include the colons. For example, if you would like to convert the full message text to lower case, use "%msg:::lowercase%". If you would like to extract from a position until the end of the string, you can place a dollar-sign ("$") in toChar (e.g. %msg:10:$%, which will extract from position 10 to the end of the string). There is also support for **regular expressions**. To use them, you need to place a "R" into FromChar. This tells rsyslog that a regular expression instead of position-based extraction is desired. The actual regular expression must then be provided in toChar. The regular expression **must** be followed by the string "--end". It denotes the end of the regular expression and will not become part of it. If you are using regular expressions, the property replacer will return the part of the property text that matches the regular expression. An example for a property replacer sequence with a regular expression is: "%msg:R:.\*Sev:. \\(.\*\\) \\[.\*--end%" It is possible to specify some parameters after the "R". These are comma-separated. They are: R,,,<:doc:`nomatch `\ >, regexp-type is either "BRE" for Posix basic regular expressions or "ERE" for extended ones. The string must be given in upper case. The default is "BRE" to be consistent with earlier versions of rsyslog that did not support ERE. The submatch identifies the submatch to be used with the result. A single digit is supported. Match 0 is the full match, while 1 to 9 are the actual submatches. The match-number identifies which match to use, if the expression occurs more than once inside the string. Please note that the first match is number 0, the second 1 and so on. Up to 10 matches (up to number 9) are supported. Please note that it would be more natural to have the match-number in front of submatch, but this would break backward-compatibility. So the match-number must be specified after "nomatch". :doc:`nomatch ` specifies what should be used in case no match is found. The following is a sample of an ERE expression that takes the first submatch from the message string and replaces the expression with the full field if no match is found: :: %msg:R,ERE,1,FIELD:for (vlan[0-9]\*):--end% and this takes the first submatch of the second match of said expression: :: %msg:R,ERE,1,FIELD,1:for (vlan[0-9]\*):--end% **Please note: there is also a** `rsyslog regular expression checker/generator `_ **online tool available.** With that tool, you can check your regular expressions and also generate a valid property replacer sequence. Usage of this tool is recommended. Depending on the version offered, the tool may not cover all subtleties that can be done with the property replacer. It concentrates on the most often used cases. So it is still useful to hand-craft expressions for demanding environments. **Also, extraction can be done based on so-called "fields"**. To do so, place a "F" into FromChar. A field in its current definition is anything that is delimited by a delimiter character. The delimiter by default is TAB (US-ASCII value 9). However, if can be changed to any other US-ASCII character by specifying a comma and the **decimal** US-ASCII value of the delimiter immediately after the "F". For example, to use comma (",") as a delimiter, use this field specifier: "F,44".  If your syslog data is delimited, this is a quicker way to extract than via regular expressions (actually, a *much* quicker way). Field counting starts at 1. Field zero is accepted, but will always lead to a "field not found" error. The same happens if a field number higher than the number of fields in the property is requested. The field number must be placed in the "ToChar" parameter. An example where the 3rd field (delimited by TAB) from the msg property is extracted is as follows: "%msg:F:3%". The same example with semicolon as delimiter is "%msg:F,59:3%". The use of fields does not permit to select substrings, what is rather unfortunate. To solve this issue, starting with 6.3.9, fromPos and toPos can be specified for strings as well. However, the syntax is quite ugly, but it was the only way to integrate this functionality into the already-existing system. To do so, use ",fromPos" and ",toPos" during field extraction. Let's assume you want to extract the substring from position 5 to 9 in the previous example. Then, the syntax is as follows: "%msg:F,59,5:3,9%". As you can see, "F,59" means field-mode, with semicolon delimiter and ",5" means starting at position 5. Then "3,9" means field 3 and string extraction to position 9. Please note that the special characters "F" and "R" are case-sensitive. Only upper case works, lower case will return an error. There are no white spaces permitted inside the sequence (that will lead to error messages and will NOT provide the intended result). Each occurrence of the field delimiter starts a new field. However, if you add a plus sign ("+") after the field delimiter, multiple delimiters, one immediately after the others, are treated as separate fields. This can be useful in cases where the syslog message contains such sequences. A frequent case may be with code that is written as follows: ```` :: int n, m; ... syslog(LOG_ERR, "%d test %6d", n, m); This will result into things like this in syslog messages: "1 test      2", "1 test     23", "1 test  234567" As you can see, the fields are delimited by space characters, but their exact number is unknown. They can properly be extracted as follows: :: "%msg:F,32:2%" to "%msg:F,32+:2%". This feature was suggested by Zhuang Yuyao and implemented by him. It is modeled after perl compatible regular expressions. Property Options ^^^^^^^^^^^^^^^^ **Property options** are case-insensitive. Currently, the following options are defined: **uppercase** convert property to uppercase only **lowercase** convert property text to lowercase only **fixed-width** changes behaviour of toChar so that it pads the source string with spaces up to the value of toChar if the source string is shorter. *This feature was introduced in rsyslog 8.13.0* **json** encode the value so that it can be used inside a JSON field. This means that several characters (according to the JSON spec) are being escaped, for example US-ASCII LF is replaced by "\\n". The json option cannot be used together with either jsonf or csv options. **jsonf**\[:outname\] (available in 6.3.9+) This signifies that the property should be expressed as a JSON field. That means not only the property is written, but rather a complete JSON field in the format ``"fieldname"="value"`` where "fieldname" is given in the *outname* property (or the property name if none was assigned) and value is the end result of property replacer operation. Note that value supports all property replacer options, like substrings, case conversion and the like. Values are properly JSON-escaped, however field names are (currently) not, so it is expected that proper field names are configured. The jsonf option cannot be used together with either json or csv options. For more information you can read `this article from Rainer's blog `_. **csv** formats the resulting field (after all modifications) in CSV format as specified in `RFC 4180 `_. Rsyslog will always use double quotes. Note that in order to have full CSV-formatted text, you need to define a proper template. An example is this one: $template csvline,"%syslogtag:::csv%,%msg:::csv%" Most importantly, you need to provide the commas between the fields inside the template. *This feature was introduced in rsyslog 4.1.6.* **drop-last-lf** The last LF in the message (if any), is dropped. Especially useful for PIX. **date-utc** convert data to UTC prior to outputting it (available since 8.18.0) **date-mysql** format as MariaDB/MySQL date **date-rfc3164** format as RFC 3164 date **date-rfc3164-buggyday** similar to date-rfc3164, but emulates a common coding error: RFC 3164 demands that a space is written for single-digit days. With this option, a zero is written instead. This format seems to be used by syslog-ng and the date-rfc3164-buggyday option can be used in migration scenarios where otherwise lots of scripts would need to be adjusted. It is recommended *not* to use this option when forwarding to remote hosts - they may treat the date as invalid (especially when parsing strictly according to RFC 3164). *This feature was introduced in rsyslog 4.6.2 and v4 versions above and 5.5.3 and all versions above.* **date-rfc3339** format as RFC 3339 date **date-unixtimestamp** Format as a unix timestamp (seconds since epoch) **date-year** just the year part (4-digit) of a timestamp **date-month** just the month part (2-digit) of a timestamp **date-day** just the day part (2-digit) of a timestamp **date-hour** just the hour part (2-digit, 24-hour clock) of a timestamp **date-minute** just the minute part (2-digit) of a timestamp **date-second** just the second part (2-digit) of a timestamp **date-subseconds** just the subseconds of a timestamp (always 0 for a low precision timestamp) **date-tzoffshour** just the timezone offset hour part (2-digit) of a timestamp **date-tzoffsmin** just the timezone offset minute part (2-digit) of a timestamp. Note that this is usually 0, but there are some time zones that have offsets which are not hourly-granular. If so, this is the minute offset. **date-tzoffsdirection** just the timezone offset direction part of a timestamp. This specifies if the offsets needs to be added ("+") or subtracted ("-") to the timestamp in order to get UTC. **date-ordinal** returns the ordinal for the given day, e.g. it is 2 for January, 2nd **date-iso-week** and **date-iso-week-year** return the ISO week number and week-numbering year, which should be used together. See `ISO week date `_ for more details **date-week** returns the week number **date-wday** just the weekday number of the timestamp. This is a single digit, with 0=Sunday, 1=Monday, ..., 6=Saturday. **date-wdayname** just the abbreviated english name of the weekday (e.g. "Mon", "Sat") of the timestamp. **escape-cc** replace control characters (ASCII value 127 and values less then 32) with an escape sequence. The sequence is "#" where charval is the 3-digit decimal value of the control character. For example, a tabulator would be replaced by "#009". Note: using this option requires that :doc:`$EscapeControlCharactersOnReceive ` is set to off. **space-cc** replace control characters by spaces Note: using this option requires that :doc:`$EscapeControlCharactersOnReceive ` is set to off. **drop-cc** drop control characters - the resulting string will neither contain control characters, escape sequences nor any other replacement character like space. Note: using this option requires that :doc:`$EscapeControlCharactersOnReceive ` is set to off. **compressspace** compresses multiple spaces (US-ASCII SP character) inside the string to a single one. This compression happens at a very late stage in processing. Most importantly, it happens after substring extraction, so the **FromChar** and **ToChar** positions are **NOT** affected by this option. (available since v8.18.0) **sp-if-no-1st-sp** This option looks scary and should probably not be used by a user. For any field given, it returns either a single space character or no character at all. Field content is never returned. A space is returned if (and only if) the first character of the field's content is NOT a space. This option is kind of a hack to solve a problem rooted in RFC 3164: 3164 specifies no delimiter between the syslog tag sequence and the actual message text. Almost all implementation in fact delimit the two by a space. As of RFC 3164, this space is part of the message text itself. This leads to a problem when building the message (e.g. when writing to disk or forwarding). Should a delimiting space be included if the message does not start with one? If not, the tag is immediately followed by another non-space character, which can lead some log parsers to misinterpret what is the tag and what the message. The problem finally surfaced when the klog module was restructured and the tag correctly written. It exists with other message sources, too. The solution was the introduction of this special property replacer option. Now, the default template can contain a conditional space, which exists only if the message does not start with one. While this does not solve all issues, it should work good enough in the far majority of all cases. If you read this text and have no idea of what it is talking about - relax: this is a good indication you will never need this option. Simply forget about it ;) **secpath-drop** Drops slashes inside the field (e.g. "a/b" becomes "ab") and makes empty, "." and ".." path components non-special. Useful for secure pathname generation with dynafiles, but may create name collisions because separators are removed. **secpath-replace** Replaces slashes inside the field by an underscore (e.g. "a/b" becomes "a\_b") and makes empty, "." and ".." path components non-special. This is usually preferred for dynafile path components because it keeps a visible separator while preventing path traversal. To use multiple options, simply place them one after each other with a comma delimiting them. For example "escape-cc,sp-if-no-1st-sp". If you use conflicting options together, the last one will override the previous one. For example, using "escape-cc,drop-cc" will use drop-cc and "drop-cc,escape-cc" will use escape-cc mode. Further Links ------------- - Article on ":doc:`Recording the Priority of Syslog Messages <../tutorials/recording_pri>`" (describes use of templates to record severity and facility of a message) - :doc:`Configuration file syntax `, this is where you actually use the property replacer. .. toctree:: :maxdepth: 2 nomatch rsyslog-8.2608.0/doc/source/configuration/PaxHeaders/modules0000644000000000000000000000013015241076617021055 xustar0029 mtime=1787067791.50367118 30 atime=1787067808.813993741 29 ctime=1787067791.50367118 rsyslog-8.2608.0/doc/source/configuration/modules/0000775000175000017500000000000015241076617020600 5ustar00rgerrgerrsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/mmjsontransform.rst0000644000000000000000000000013115216464435025125 xustar0030 mtime=1782212893.974265343 30 atime=1787067672.493453027 29 ctime=1787067791.29166723 rsyslog-8.2608.0/doc/source/configuration/modules/mmjsontransform.rst0000664000175000017500000001616415216464435024602 0ustar00rgerrger.. _ref-mmjsontransform: ******************************************** mmjsontransform: JSON Dotted Key Transformer ******************************************** ==================== ========================================================================== **Module Name:** **mmjsontransform** **Author:** `rsyslog project `_ **Available since:** 8.2410.0 ==================== ========================================================================== .. note:: ``mmjsontransform`` is a **fresh** module. Parameter names and behavior may still change as real-world feedback arrives, so expect possible breaking adjustments in upcoming releases. Purpose ======= ``mmjsontransform`` restructures JSON properties whose names contain dotted segments. The action reads a JSON object from the configured input property and stores the transformed tree under a dedicated output property. By default, the module expands dotted keys into nested containers (``unflatten`` mode) so pipelines that consume ``option.jsonfTree`` data can normalize payloads inline. When ``mode="flatten"`` is selected, the action collapses nested objects back into dotted keys. Failure conditions ================== ``mmjsontransform`` aborts the action when any of the following occur: * The input property does not resolve to a JSON object. * The output property already exists on the message. * Rewriting a key would overwrite an existing incompatible value (for example, ``{"a": 1}`` combined with ``{"a.b": 2}``). Notable Features ================ - :ref:`mmjsontransform-modes` — bidirectional conversion between dotted keys and nested containers. - :ref:`mmjsontransform-conflict-handling` — detailed conflict reporting to locate incompatible payloads quickly. - :ref:`mmjsontransform-policy` — optional YAML policy-based mode selection, key renaming, and field dropping before processing. - watched policy reloads — optional automatic policy refresh with debounce when ``policyWatch`` is enabled. Configuration Parameters ======================== .. note:: Parameter names are case-insensitive; camelCase is recommended for readability. Action Parameters ----------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-mmjsontransform-input` - .. include:: ../../reference/parameters/mmjsontransform-input.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-mmjsontransform-output` - .. include:: ../../reference/parameters/mmjsontransform-output.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-mmjsontransform-mode` - .. include:: ../../reference/parameters/mmjsontransform-mode.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-mmjsontransform-policy` - .. include:: ../../reference/parameters/mmjsontransform-policy.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-mmjsontransform-policywatch` - .. include:: ../../reference/parameters/mmjsontransform-policywatch.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-mmjsontransform-policywatchdebounce` - .. include:: ../../reference/parameters/mmjsontransform-policywatchdebounce.rst :start-after: .. summary-start :end-before: .. summary-end .. _mmjsontransform-modes: Transformation modes ==================== ``mmjsontransform`` supports two modes controlled by the :ref:`mode ` parameter or, when configured, by the reloadable :ref:`policy ` file. Both modes rewrite the entire input object before assigning it to the configured output property. .. _mmjsontransform-mode-unflatten: Unflatten dotted keys --------------------- ``mode="unflatten"`` (the default) expands dotted keys into nested containers. For example ``{"a.b": 1, "a.c": 2}`` becomes ``{"a": {"b": 1, "c": 2}}``. When the module encounters a dotted path that points to an existing non-object value, it stops processing, leaves the output unset, and reports the conflicting path. .. _mmjsontransform-mode-flatten: Flatten nested containers ------------------------- ``mode="flatten"`` performs the reverse operation. Nested objects become dotted key paths (``{"nested": {"value": 1}}`` is rewritten to ``{"nested.value": 1}``), while arrays are preserved with their elements recursively flattened. If flattening would overwrite an existing scalar with a different value, the action fails and reports the mismatch. .. _mmjsontransform-policy-reload: Policy reloads ============== When :ref:`policy ` is configured, ``mmjsontransform`` loads the YAML file during startup and reloads it on ``HUP``. When :ref:`policyWatch ` is enabled, rsyslog also watches the file for changes and reloads it after the configured :ref:`policyWatchDebounce ` quiet period when watch support is available. If watched reloads are unavailable in the current build or runtime environment, rsyslog logs a warning and continues with ``HUP``-only reload behavior. Invalid updates are rejected and the previous in-memory policy remains active. .. _mmjsontransform-conflict-handling: Conflict handling ================= The module tracks the full dotted path responsible for a hierarchy conflict and logs a user-facing error when a mismatch occurs. Review the reported path to identify which input property must be renamed or preprocessed before retrying the transformation. Examples ======== Normalize and persist dotted JSON --------------------------------- The following snippet receives JSON payloads, normalizes dotted keys into nested objects, and writes both the structured tree and a flattened representation to ``/tmp/out.json``:: module(load="mmjsontransform") module(load="imtcp") input(type="imtcp" port="10514" ruleset="process-json") ruleset(name="process-json") { action(type="mmjsontransform" input="$!raw" output="$!normalized") action(type="mmjsontransform" mode="flatten" input="$!normalized" output="$!normalized_flat") action(type="omfile" file="/tmp/out.json" template="json-template") } template(name="json-template" type="string" string="%$!normalized%\n%$!normalized_flat%\n") Troubleshooting =============== When a hierarchy conflict occurs (for example, ``mode="unflatten"`` sees ``"a": "value"`` and ``"a.b": 1``), ``mmjsontransform`` logs an error that includes the conflicting path. Inspect the reported path to determine which input property needs to be renamed or moved before retrying the transformation. .. toctree:: :hidden: ../../reference/parameters/mmjsontransform-input ../../reference/parameters/mmjsontransform-output ../../reference/parameters/mmjsontransform-mode ../../reference/parameters/mmjsontransform-policy ../../reference/parameters/mmjsontransform-policywatch ../../reference/parameters/mmjsontransform-policywatchdebounce rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/idx_parser.rst0000644000000000000000000000013215132411300024003 xustar0030 mtime=1768559296.176884216 30 atime=1787067672.271448888 30 ctime=1787067791.198665497 rsyslog-8.2608.0/doc/source/configuration/modules/idx_parser.rst0000666000175000017500000000064215132411300023453 0ustar00rgerrgerParser Modules -------------- Parser modules are used to parse message content, once the message has been received. They can be used to process custom message formats or invalidly formatted messages. For details, please see the :doc:`rsyslog message parser documentation <../../concepts/messageparser>`. The current modules are currently provided as part of rsyslog: .. toctree:: :glob: :maxdepth: 1 pm* rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/omgssapi.rst0000644000000000000000000000013115216464435023510 xustar0029 mtime=1782212893.97526536 30 atime=1787067672.846459608 30 ctime=1787067791.426669746 rsyslog-8.2608.0/doc/source/configuration/modules/omgssapi.rst0000664000175000017500000000766515216464435023173 0ustar00rgerrger************************************* omgssapi: GSSAPI Syslog Output Module ************************************* Purpose ======= What is it good for ------------------- - Client-server authentication - Log messages encryption Requirements ------------ - Kerberos infrastructure - rsyslog, rsyslog-gssapi Configuration ============= Let's assume there are 3 machines in Kerberos Realm: - The first is running KDC (Kerberos Authentication Service and Key Distribution Center), - The second is a client sending its logs to the server, - The third is receiver, gathering all logs. 1. KDC: - Kerberos database must be properly set-up on KDC machine first. Use kadmin/kadmin.local to do that. Two principals need to be added in our case: #. sender@REALM.ORG - client must have ticket for principal sender - REALM.ORG is Kerberos Realm #. host/receiver.mydomain.com@REALM.ORG - service principal - Use ktadd to export service principal and transfer it to /etc/krb5.keytab on receiver #. CLIENT: - set-up rsyslog, in ``/etc/rsyslog.conf``: - ``$ModLoad omgssapi`` - load output GSS module - ``$GSSForwardServiceName otherThanHost`` - set the name of service principal, "host" is the default one - ``*.* :omgssapi:receiver.mydomain.com`` - action line, forward logs to receiver - ``kinit root`` - get the TGT ticket - ``service rsyslog start`` #. SERVER: - set-up rsyslog, in /etc/rsyslog.conf: - ``$ModLoad imgssapi`` - load input GSS module - ``$InputGSSServerServiceName otherThanHost`` - set the name of service principal, "host" is the default one - ``$InputGSSServerPermitPlainTCP on`` - accept GSS and TCP connections (not authenticated senders), off by default - ``$InputGSSServerRun 514`` - run server on port - ``service rsyslog start`` The picture demonstrate how things work. .. figure:: gssapi.png :align: center :alt: rsyslog gssapi support rsyslog GSSAPI support Configuration Parameters ======================== .. note:: Parameter names are case-insensitive; camelCase is recommended for readability. Module Parameters ----------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-omgssapi-gssforwardservicename` - .. include:: ../../reference/parameters/omgssapi-gssforwardservicename.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omgssapi-gssmode` - .. include:: ../../reference/parameters/omgssapi-gssmode.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omgssapi-gsstokeniotimeout` - .. include:: ../../reference/parameters/omgssapi-gsstokeniotimeout.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omgssapi-actiongssforwarddefaulttemplate` - .. include:: ../../reference/parameters/omgssapi-actiongssforwarddefaulttemplate.rst :start-after: .. summary-start :end-before: .. summary-end Action Parameters ----------------- The ``omgssapi`` action is configured via module parameters. In modern ``action()`` syntax, it takes a ``target`` parameter and can optionally have a ``template`` assigned. Legacy ``:omgssapi:`` syntax is also supported and includes options for compression and TCP framing. These are specified in parentheses after the selector, for example ``:omgssapi:(z5,o)hostname``. - **z[0-9]**: Enables zlib compression. The optional digit specifies the compression level (0-9). Defaults to 9 if no digit is given. - **o**: Enables octet-counted TCP framing. .. toctree:: :hidden: ../../reference/parameters/omgssapi-gssforwardservicename ../../reference/parameters/omgssapi-gssmode ../../reference/parameters/omgssapi-gsstokeniotimeout ../../reference/parameters/omgssapi-actiongssforwarddefaulttemplate rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/omsnmp.rst0000644000000000000000000000013215145046112023165 xustar0030 mtime=1771326538.930012509 30 atime=1787067671.701438262 30 ctime=1787067791.470670566 rsyslog-8.2608.0/doc/source/configuration/modules/omsnmp.rst0000664000175000017500000000772515145046112022644 0ustar00rgerrger******************************* omsnmp: SNMP Trap Output Module ******************************* =========================== =========================================================================== **Module Name:**  **omsnmp** **Author:** Andre Lorbach =========================== =========================================================================== Purpose ======= Provides the ability to send syslog messages as an SNMPv1 & v2c traps. By default, SNMPv2c is preferred. The syslog message is wrapped into a OCTED STRING variable. This module uses the `NET-SNMP `_ library. In order to compile this module, you will need to have the `NET-SNMP `_ developer (headers) package installed. Configuration Parameters ======================== .. note:: Parameter names are case-insensitive; camelCase is recommended for readability. Module Parameters ----------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-omsnmp-server` - .. include:: ../../reference/parameters/omsnmp-server.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-port` - .. include:: ../../reference/parameters/omsnmp-port.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-transport` - .. include:: ../../reference/parameters/omsnmp-transport.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-version` - .. include:: ../../reference/parameters/omsnmp-version.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-community` - .. include:: ../../reference/parameters/omsnmp-community.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-trapoid` - .. include:: ../../reference/parameters/omsnmp-trapoid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-messageoid` - .. include:: ../../reference/parameters/omsnmp-messageoid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-enterpriseoid` - .. include:: ../../reference/parameters/omsnmp-enterpriseoid.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-specifictype` - .. include:: ../../reference/parameters/omsnmp-specifictype.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-snmpv1dynsource` - .. include:: ../../reference/parameters/omsnmp-snmpv1dynsource.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omsnmp-traptype` - .. include:: ../../reference/parameters/omsnmp-traptype.rst :start-after: .. summary-start :end-before: .. summary-end .. toctree:: :hidden: ../../reference/parameters/omsnmp-server ../../reference/parameters/omsnmp-port ../../reference/parameters/omsnmp-transport ../../reference/parameters/omsnmp-version ../../reference/parameters/omsnmp-community ../../reference/parameters/omsnmp-trapoid ../../reference/parameters/omsnmp-messageoid ../../reference/parameters/omsnmp-enterpriseoid ../../reference/parameters/omsnmp-specifictype ../../reference/parameters/omsnmp-snmpv1dynsource ../../reference/parameters/omsnmp-traptype Caveats/Known Bugs ================== - In order to decode the custom OIDs, you will need to have the adiscon mibs installed. Examples ======== Sending messages as snmp traps ------------------------------ The following commands send every message as a snmp trap. .. code-block:: none module(load="omsnmp") action(type="omsnmp" server="localhost" port="162" transport="udp" version="1" community="public") rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/ompipe.rst0000644000000000000000000000013215132411300023134 xustar0030 mtime=1768559296.181884295 30 atime=1787067673.926479741 30 ctime=1787067791.457670323 rsyslog-8.2608.0/doc/source/configuration/modules/ompipe.rst0000666000175000017500000000331615132411300022605 0ustar00rgerrgerompipe: Pipe Output Module ========================== **Module Name:    ompipe** **Author:**\ Rainer Gerhards **Description**: The ompipe plug-in provides the core functionality for logging output to named pipes (fifos). It is a built-in module that does not need to be loaded. **Global Configuration Parameters:** Note: parameter names are case-insensitive. - Template: [templateName] sets a new default template for file actions. **Action specific Configuration Parameters:** Note: parameter names are case-insensitive. - Pipe: string a fifo or named pipe can be used as a destination for log messages. - tryResumeReopen: Sometimes we need to reopen a pipe after an ompipe action gets suspended. Sending a HUP signal does the job but requires an interaction with rsyslog. When set to "on" and a resume action fails, the file descriptor is closed, causing a new open in the next resume. Default: "off" to preserve existing behavior before introduction of this option. **Caveats/Known Bugs:** None **Sample:** The following command sends all syslog messages to a pipe named "NameofPipe". ::     Module (path="builtin:ompipe")     *.* action(type="ompipe" Pipe="NameofPipe") **Legacy Configuration Parameters:** rsyslog has support for logging output to named pipes (fifos). A fifo or named pipe can be used as a destination for log messages by prepending a pipe symbol ("|") to the name of the file. This is handy for debugging. Note that the fifo must be created with the mkfifo(1) command before rsyslogd is started. **Legacy Sample:** The following command sends all syslog messages to a pipe named /var/log/pipe. ::     $ModLoad ompipe     *.* |/var/log/pipe rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/impstats.rst0000644000000000000000000000013215216464435023533 xustar0030 mtime=1782212893.973265327 30 atime=1787067673.421470327 30 ctime=1787067791.248666429 rsyslog-8.2608.0/doc/source/configuration/modules/impstats.rst0000664000175000017500000004026115216464435023202 0ustar00rgerrger*********************************************************** impstats: Generate Periodic Statistics of Internal Counters *********************************************************** =========================== =========================================================================== **Module Name:**  **impstats** **Author:** `Rainer Gerhards `_ =========================== =========================================================================== Purpose ======= This module provides periodic output of rsyslog internal counters. The set of available counters will be output as a set of syslog messages. This output is periodic, with the interval being configurable (default is 5 minutes). Be sure that your configuration records the counter messages (default is syslog.=info). Besides logging to the regular syslog stream, the module can also be configured to write statistics data into a (local) file. When logging to the regular syslog stream, impstats records are emitted just like regular log messages. As such, counters increase when processing these messages. This must be taken into consideration when testing and troubleshooting. Note that loading this module has some impact on rsyslog performance. Depending on settings, this impact may be noticeable for high-load environments, but in general the overhead is pretty light. **Note that there is a** `rsyslog statistics online analyzer `_ **available.** It can be given a impstats-generated file and will return problems it detects. Note that the analyzer cannot replace a human in getting things right, but it is expected to be a good aid in starting to understand and gain information from the pstats logs. The rsyslog website has an overview of available `rsyslog statistic counters `_. When browsing this page, please be sure to take note of which rsyslog version is required to provide a specific counter. Counters are continuously being added, and older versions do not support everything. Notable Features ================ - :ref:`impstats-statistic-counter` - :ref:`impstats-push-mode` Choose Your Mode ================ impstats supports three common operating modes: - Local emission only (syslog and/or file) - Push mode only (Remote Write endpoint) - Local emission and push mode together Use this page for module reference and parameters. For task-oriented workflows and troubleshooting, use: - :doc:`../../tutorials/impstats_push_victoriametrics` - :doc:`../../faq/impstats-push-mode` .. _impstats-push-mode: Push Mode (VictoriaMetrics / Prometheus Remote Write) ===================================================== impstats can push counters directly to VictoriaMetrics (and other Prometheus Remote Write compatible backends) on every impstats interval. This is enabled by setting :ref:`param-impstats-push-url` to a Remote Write endpoint such as ``http://localhost:8428/api/v1/write``. When push mode is enabled, impstats reads internal counters directly from stats objects and sends them as Prometheus Remote Write payloads (``application/x-protobuf`` with ``snappy`` compression) over HTTP. Push mode is independent of local emission format and destination. You can still use syslog/file output and any supported ``format`` for local records while push mode runs in parallel. Key notes: - Push mode is available only in builds configured with ``--enable-impstats-push``. - Project-provided rsyslog packages are built with impstats push support. For package library locations, see |RsyslogPackageDownloads|_ on rsyslog.com. - TLS options (``push.tls.*``) apply only when ``push.url`` uses ``https://``. - ``push.tls.certfile`` and ``push.tls.keyfile`` must be configured together. - Optional batch controls (``push.batch.maxBytes`` and ``push.batch.maxSeries``) split large Remote Write payloads. - For naming, labels, retries, and limitations details, see :doc:`../../faq/impstats-push-mode` and :doc:`../../tutorials/impstats_push_victoriametrics`. Configuration Parameters ======================== The configuration parameters are grouped below by use case. .. note:: Parameter names are case-insensitive, but punctuation such as dots is significant. Use the parameter names exactly as shown. .. note:: This module supports module parameters, only. Core Module Parameters (Local Emission) --------------------------------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-impstats-interval` - .. include:: ../../reference/parameters/impstats-interval.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-facility` - .. include:: ../../reference/parameters/impstats-facility.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-severity` - .. include:: ../../reference/parameters/impstats-severity.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-resetcounters` - .. include:: ../../reference/parameters/impstats-resetcounters.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-format` - .. include:: ../../reference/parameters/impstats-format.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-log-syslog` - .. include:: ../../reference/parameters/impstats-log-syslog.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-log-file` - .. include:: ../../reference/parameters/impstats-log-file.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-log-file-overwrite` - .. include:: ../../reference/parameters/impstats-log-file-overwrite.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-ruleset` - .. include:: ../../reference/parameters/impstats-ruleset.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-bracketing` - .. include:: ../../reference/parameters/impstats-bracketing.rst :start-after: .. summary-start :end-before: .. summary-end Push Mode Parameters (Remote Write) ----------------------------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-impstats-push-url` - .. include:: ../../reference/parameters/impstats-push-url.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-labels` - .. include:: ../../reference/parameters/impstats-push-labels.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-timeout-ms` - .. include:: ../../reference/parameters/impstats-push-timeout-ms.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-label-instance` - .. include:: ../../reference/parameters/impstats-push-label-instance.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-label-job` - .. include:: ../../reference/parameters/impstats-push-label-job.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-label-origin` - .. include:: ../../reference/parameters/impstats-push-label-origin.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-label-name` - .. include:: ../../reference/parameters/impstats-push-label-name.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-batch-maxbytes` - .. include:: ../../reference/parameters/impstats-push-batch-maxbytes.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-batch-maxseries` - .. include:: ../../reference/parameters/impstats-push-batch-maxseries.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-tls-cafile` - .. include:: ../../reference/parameters/impstats-push-tls-cafile.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-tls-certfile` - .. include:: ../../reference/parameters/impstats-push-tls-certfile.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-tls-keyfile` - .. include:: ../../reference/parameters/impstats-push-tls-keyfile.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-impstats-push-tls-insecureskipverify` - .. include:: ../../reference/parameters/impstats-push-tls-insecureskipverify.rst :start-after: .. summary-start :end-before: .. summary-end .. _impstats-statistic-counter: Statistic Counter ================= The impstats plugin gathers some internal :doc:`statistics <../rsyslog_statistic_counter>`. They have different names depending on the actual statistics. Obviously, they do not relate to the plugin itself but rather to a broader object – most notably the rsyslog process itself. The "resource-usage" counter maintains process statistics. They base on the getrusage() system call. The counters are named like getrusage returned data members. So for details, looking them up in "man getrusage" is highly recommended, especially as value may be different depending on the platform. A getrusage() call is done immediately before the counter is emitted. The following individual counters are maintained: - ``utime`` - this is the user time in microseconds (thus the timeval structure combined) - ``stime`` - again, time given in microseconds - ``maxrss`` - ``minflt`` - ``majflt`` - ``inblock`` - ``outblock`` - ``nvcsw`` - ``nivcsw`` - ``openfiles`` - number of file handles used by rsyslog; includes actual files, sockets and others Format ------ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "word", "legacy", "no", "none" .. versionadded:: 8.16.0 Specifies the format of emitted stats messages. The default of "legacy" is compatible with pre v6-rsyslog. The other options provide support for structured formats (note the "cee" is actually "project lumberjack" logging). The json-elasticsearch format supports the broken ElasticSearch JSON implementation. ES 2.0 no longer supports valid JSON and disallows dots inside names. The "json-elasticsearch" format option replaces those dots by the bang ("!") character. So "discarded.full" becomes "discarded!full". The zabbix format supports arrayed-JSON objects with a single JSON object per pstats emission to disk or syslog. This format should be compatible with most JSON parsers from other monitoring products. log.file is highly recommended as log.syslog may encounter message truncation problems if the emission is large. If you must use log.syslog, it's recommended to monitor pstats for truncation and increase $MaxMessageSize at the top of your main rsyslog configuration file. Options: json/json-elasticsearch/cee/legacy/prometheus/zabbix Caveats/Known Bugs ================== - This module MUST be loaded right at the top of rsyslog.conf, otherwise stats may not get turned on in all places. - When using the format "zabbix", it is not recommended to use log.syslog="on". This can cause message truncation in stats. Examples ======== Load module, send stats data to syslog stream --------------------------------------------- This activates the module and records messages to /var/log/rsyslog-stats in 10 minute intervals: .. code-block:: rsyslog module(load="impstats" interval="600" severity="7") # to actually gather the data: syslog.=debug /var/log/rsyslog-stats Load module, format the output to Zabbix, and output to a local file -------------------------------------------------------------------- .. code-block:: rsyslog module(load="impstats" interval="60" severity="7" format="zabbix" log.syslog="off" log.file="/var/log/stats.log") Load module, send stats data to local file ------------------------------------------ Here, the default interval of 5 minutes is used. However, this time, stats data is NOT emitted to the syslog stream but to a local file instead. .. code-block:: rsyslog module(load="impstats" interval="600" severity="7" log.syslog="off" # need to turn log stream logging off! log.file="/path/to/local/stats.log") Load module, send stats data to local file and syslog stream ------------------------------------------------------------ Here we log to both the regular syslog log stream as well as a file. Within the log stream, we forward the data records to another server: .. code-block:: rsyslog module(load="impstats" interval="600" severity="7" log.file="/path/to/local/stats.log") syslog.=debug @central.example.net Load module with Remote Write push mode (VictoriaMetrics) --------------------------------------------------------- This keeps local output and additionally pushes the same interval counters to VictoriaMetrics using Prometheus Remote Write: .. code-block:: rsyslog module(load="impstats" interval="30" format="json" log.file="/var/log/rsyslog-stats.log" push.url="http://localhost:8428/api/v1/write" push.labels=["env=prod", "cluster=edge"] push.label.origin="on" push.label.name="on") Explanation of output ===================== Example output for illustration:: Sep 17 11:43:49 localhost rsyslogd-pstats: imuxsock: submitted=16 Sep 17 11:43:49 localhost rsyslogd-pstats: main Q: size=1 enqueued=2403 size.enqueued=614168 full=0 maxqsize=2 Explanation: All objects are shown in the results with a separate counter, one object per line. Line 1: shows details for - ``imuxsock``, an object - ``submitted=16``, a counter showing that 16 messages were received by the imuxsock object. Line 2: shows details for the main queue: - ``main Q``, an object - ``size``, messages in the queue - ``enqueued``, all received messages thus far - ``size.enqueued``, cumulative byte volume of all received messages thus far (counted on arrival, before discard/flow-control checks) - ``full``, how often was the queue was full - ``maxqsize``, the maximum amount of messages that have passed through the queue since rsyslog was started See Also ======== - `rsyslog statistics counter `_ - `impstats delayed or lost `_ - cause and cure - :doc:`../../tutorials/impstats_push_victoriametrics` .. toctree:: :hidden: ../../reference/parameters/impstats-interval ../../reference/parameters/impstats-facility ../../reference/parameters/impstats-severity ../../reference/parameters/impstats-resetcounters ../../reference/parameters/impstats-format ../../reference/parameters/impstats-log-syslog ../../reference/parameters/impstats-log-file ../../reference/parameters/impstats-log-file-overwrite ../../reference/parameters/impstats-ruleset ../../reference/parameters/impstats-bracketing ../../reference/parameters/impstats-push-url ../../reference/parameters/impstats-push-labels ../../reference/parameters/impstats-push-timeout-ms ../../reference/parameters/impstats-push-label-instance ../../reference/parameters/impstats-push-label-job ../../reference/parameters/impstats-push-label-origin ../../reference/parameters/impstats-push-label-name ../../reference/parameters/impstats-push-batch-maxbytes ../../reference/parameters/impstats-push-batch-maxseries ../../reference/parameters/impstats-push-tls-cafile ../../reference/parameters/impstats-push-tls-certfile ../../reference/parameters/impstats-push-tls-keyfile ../../reference/parameters/impstats-push-tls-insecureskipverify rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/omhttpfs.rst0000644000000000000000000000013115132411300023506 xustar0029 mtime=1768559296.18088428 30 atime=1787067673.365469283 30 ctime=1787067791.435669913 rsyslog-8.2608.0/doc/source/configuration/modules/omhttpfs.rst0000666000175000017500000000600415132411300023155 0ustar00rgerrger************************************* omhttpfs: Hadoop HTTPFS Output Module ************************************* =========================== =========================================================================== **Module Name:** **omhttpfs** **Available Since:** **8.10.0** **Author:** `sskaje `_ =========================== =========================================================================== Purpose ======= This module is an alternative to omhdfs via `Hadoop HDFS over HTTP `_. Dependencies ============ * libcurl Configuration Parameters ======================== .. note:: Parameter names are case-insensitive. Action Parameters ----------------- Host ^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "word", "127.0.0.1", "no", "none" HttpFS server host. Port ^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "integer", "14000", "no", "none" HttpFS server port. User ^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "word", "hdfs", "no", "none" HttpFS auth user. https ^^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "binary", "off", "no", "none" Turn on if your HttpFS runs on HTTPS. File ^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "word", "none", "yes", "none" File to write, or a template name. isDynFile ^^^^^^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "binary", "off", "no", "none" Turn this on if your **file** is a template name. See examples below. Template ^^^^^^^^ .. csv-table:: :header: "type", "default", "mandatory", "|FmtObsoleteName| directive" :widths: auto :class: parameter-table "word", "RSYSLOG_FileFormat", "no", "none" Format your message when writing to **file**. Default: *RSYSLOG_FileFormat* Configure ========= .. code-block:: none ./configure --enable-omhttpfs Examples ======== Example 1 --------- .. code-block:: none module(load="omhttpfs") template(name="hdfs_tmp_file" type="string" string="/tmp/%$YEAR%/test.log") template(name="hdfs_tmp_filecontent" type="string" string="%$YEAR%-%$MONTH%-%$DAY% %MSG% ==\n") local4.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on") local5.* action(type="omhttpfs" host="10.1.1.161" port="14000" https="off" file="hdfs_tmp_file" isDynFile="on" template="hdfs_tmp_filecontent") rsyslog-8.2608.0/doc/source/configuration/modules/PaxHeaders/omrelp.rst0000644000000000000000000000013115216464435023164 xustar0030 mtime=1782212893.976265376 29 atime=1787067674.04548196 30 ctime=1787067791.464670454 rsyslog-8.2608.0/doc/source/configuration/modules/omrelp.rst0000664000175000017500000001745515216464435022645 0ustar00rgerrger************************** omrelp: RELP Output Module ************************** =========================== =========================================================================== **Module Name:**  **omrelp** **Author:** `Rainer Gerhards `_ =========================== =========================================================================== Purpose ======= This module supports sending syslog messages over the reliable RELP protocol. For RELP's advantages over plain tcp syslog, please see the documentation for :doc:`imrelp ` (the server counterpart).  Setup Please note that `librelp `__ is required for imrelp (it provides the core relp protocol implementation). Configuration Parameters ======================== .. note:: Parameter names are case-insensitive; camelCase is recommended for readability. Module Parameters ----------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-omrelp-tls-tlslib` - .. include:: ../../reference/parameters/omrelp-tls-tlslib.rst :start-after: .. summary-start :end-before: .. summary-end Action Parameters ----------------- .. list-table:: :widths: 30 70 :header-rows: 1 * - Parameter - Summary * - :ref:`param-omrelp-target` - .. include:: ../../reference/parameters/omrelp-target.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-port` - .. include:: ../../reference/parameters/omrelp-port.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-template` - .. include:: ../../reference/parameters/omrelp-template.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-timeout` - .. include:: ../../reference/parameters/omrelp-timeout.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-conn-timeout` - .. include:: ../../reference/parameters/omrelp-conn-timeout.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-rebindinterval` - .. include:: ../../reference/parameters/omrelp-rebindinterval.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-keepalive` - .. include:: ../../reference/parameters/omrelp-keepalive.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-keepalive-probes` - .. include:: ../../reference/parameters/omrelp-keepalive-probes.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-keepalive-interval` - .. include:: ../../reference/parameters/omrelp-keepalive-interval.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-keepalive-time` - .. include:: ../../reference/parameters/omrelp-keepalive-time.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-windowsize` - .. include:: ../../reference/parameters/omrelp-windowsize.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls` - .. include:: ../../reference/parameters/omrelp-tls.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-compression` - .. include:: ../../reference/parameters/omrelp-tls-compression.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-permittedpeer` - .. include:: ../../reference/parameters/omrelp-tls-permittedpeer.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-authmode` - .. include:: ../../reference/parameters/omrelp-tls-authmode.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-cacert` - .. include:: ../../reference/parameters/omrelp-tls-cacert.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-mycert` - .. include:: ../../reference/parameters/omrelp-tls-mycert.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-myprivkey` - .. include:: ../../reference/parameters/omrelp-tls-myprivkey.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-prioritystring` - .. include:: ../../reference/parameters/omrelp-tls-prioritystring.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-tlscfgcmd` - .. include:: ../../reference/parameters/omrelp-tls-tlscfgcmd.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-tls-permanentfailuredisablesaction` - .. include:: ../../reference/parameters/omrelp-tls-permanentfailuredisablesaction.rst :start-after: .. summary-start :end-before: .. summary-end * - :ref:`param-omrelp-localclientip` - .. include:: ../../reference/parameters/omrelp-localclientip.rst :start-after: .. summary-start :end-before: .. summary-end .. toctree:: :hidden: ../../reference/parameters/omrelp-tls-tlslib ../../reference/parameters/omrelp-target ../../reference/parameters/omrelp-port ../../reference/parameters/omrelp-template ../../reference/parameters/omrelp-timeout ../../reference/parameters/omrelp-conn-timeout ../../reference/parameters/omrelp-rebindinterval ../../reference/parameters/omrelp-keepalive ../../reference/parameters/omrelp-keepalive-probes ../../reference/parameters/omrelp-keepalive-interval ../../reference/parameters/omrelp-keepalive-time ../../reference/parameters/omrelp-windowsize ../../reference/parameters/omrelp-tls ../../reference/parameters/omrelp-tls-compression ../../reference/parameters/omrelp-tls-permittedpeer ../../reference/parameters/omrelp-tls-authmode ../../reference/parameters/omrelp-tls-cacert ../../reference/parameters/omrelp-tls-mycert ../../reference/parameters/omrelp-tls-myprivkey ../../reference/parameters/omrelp-tls-prioritystring ../../reference/parameters/omrelp-tls-tlscfgcmd ../../reference/parameters/omrelp-tls-permanentfailuredisablesaction ../../reference/parameters/omrelp-localclientip Examples ======== Sending msgs with omrelp ------------------------ The following sample sends all messages to the central server "centralserv" at port 2514 (note that the server must run imrelp on port 2514). .. code-block:: none module(load="omrelp") action(type="omrelp" target="centralserv" port="2514") Sending msgs with omrelp via TLS ------------------------------------ This is the same as the previous example but uses TLS (via OpenSSL) for operations. Certificate files must exist at configured locations. Note that authmode "certvalid" is not very strong - you may want to use a different one for actual deployments. For details, see parameter descriptions. .. code-block:: none module(load="omrelp" tls.tlslib="openssl") action(type="omrelp" target="centralserv" port="2514" tls="on" tls.cacert="tls-certs/ca.pem" tls.mycert="tls-certs/cert.pem" tls.myprivkey="tls-certs/key.pem" tls.authmode="certvalid" tls.permittedpeer="rsyslog") |FmtObsoleteName| directives ============================ This module uses old-style action configuration to keep consistent with the forwarding rule. So far, no additional configuration directives can be specified. To send a message via RELP, use .. code-block:: none *.*  :omrelp::;